Home | History | Annotate | Line # | Download | only in ddd
      1      1.1  christos #include <openssl/ssl.h>
      2      1.1  christos 
      3      1.1  christos /*
      4      1.1  christos  * Demo 1: Client  Managed Connection  Blocking
      5      1.1  christos  * ==============================================
      6      1.1  christos  *
      7      1.1  christos  * This is an example of (part of) an application which uses libssl in a simple,
      8      1.1  christos  * synchronous, blocking fashion. The functions show all interactions with
      9      1.1  christos  * libssl the application makes, and would hypothetically be linked into a
     10      1.1  christos  * larger application.
     11      1.1  christos  */
     12      1.1  christos 
     13      1.1  christos /*
     14      1.1  christos  * The application is initializing and wants an SSL_CTX which it will use for
     15      1.1  christos  * some number of outgoing connections, which it creates in subsequent calls to
     16      1.1  christos  * new_conn. The application may also call this function multiple times to
     17      1.1  christos  * create multiple SSL_CTX.
     18      1.1  christos  */
     19      1.1  christos SSL_CTX *create_ssl_ctx(void)
     20      1.1  christos {
     21      1.1  christos     SSL_CTX *ctx;
     22      1.1  christos 
     23      1.1  christos #ifdef USE_QUIC
     24      1.1  christos     ctx = SSL_CTX_new(OSSL_QUIC_client_method());
     25      1.1  christos #else
     26      1.1  christos     ctx = SSL_CTX_new(TLS_client_method());
     27      1.1  christos #endif
     28      1.1  christos     if (ctx == NULL)
     29      1.1  christos         return NULL;
     30      1.1  christos 
     31      1.1  christos     /* Enable trust chain verification. */
     32      1.1  christos     SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
     33      1.1  christos 
     34      1.1  christos     /* Load default root CA store. */
     35      1.1  christos     if (SSL_CTX_set_default_verify_paths(ctx) == 0) {
     36      1.1  christos         SSL_CTX_free(ctx);
     37      1.1  christos         return NULL;
     38      1.1  christos     }
     39      1.1  christos 
     40      1.1  christos     return ctx;
     41      1.1  christos }
     42      1.1  christos 
     43      1.1  christos /*
     44      1.1  christos  * The application wants to create a new outgoing connection using a given
     45      1.1  christos  * SSL_CTX.
     46      1.1  christos  *
     47      1.1  christos  * hostname is a string like "openssl.org:443" or "[::1]:443".
     48      1.1  christos  */
     49      1.1  christos BIO *new_conn(SSL_CTX *ctx, const char *hostname)
     50      1.1  christos {
     51      1.1  christos     BIO *out;
     52      1.1  christos     SSL *ssl = NULL;
     53      1.1  christos     const char *bare_hostname;
     54      1.1  christos #ifdef USE_QUIC
     55  1.1.1.2  christos     static const unsigned char alpn[] = { 5, 'd', 'u', 'm', 'm', 'y' };
     56      1.1  christos #endif
     57      1.1  christos 
     58      1.1  christos     out = BIO_new_ssl_connect(ctx);
     59      1.1  christos     if (out == NULL)
     60      1.1  christos         return NULL;
     61      1.1  christos 
     62      1.1  christos     if (BIO_get_ssl(out, &ssl) == 0) {
     63      1.1  christos         BIO_free_all(out);
     64      1.1  christos         return NULL;
     65      1.1  christos     }
     66      1.1  christos 
     67      1.1  christos     if (BIO_set_conn_hostname(out, hostname) == 0) {
     68      1.1  christos         BIO_free_all(out);
     69      1.1  christos         return NULL;
     70      1.1  christos     }
     71      1.1  christos 
     72      1.1  christos     /* Returns the parsed hostname extracted from the hostname:port string. */
     73      1.1  christos     bare_hostname = BIO_get_conn_hostname(out);
     74      1.1  christos     if (bare_hostname == NULL) {
     75      1.1  christos         BIO_free_all(out);
     76      1.1  christos         return NULL;
     77      1.1  christos     }
     78      1.1  christos 
     79      1.1  christos     /* Tell the SSL object the hostname to check certificates against. */
     80      1.1  christos     if (SSL_set1_host(ssl, bare_hostname) <= 0) {
     81      1.1  christos         BIO_free_all(out);
     82      1.1  christos         return NULL;
     83      1.1  christos     }
     84      1.1  christos 
     85      1.1  christos #ifdef USE_QUIC
     86      1.1  christos     /* Configure ALPN, which is required for QUIC. */
     87      1.1  christos     if (SSL_set_alpn_protos(ssl, alpn, sizeof(alpn))) {
     88      1.1  christos         /* Note: SSL_set_alpn_protos returns 1 for failure. */
     89      1.1  christos         BIO_free_all(out);
     90      1.1  christos         return NULL;
     91      1.1  christos     }
     92      1.1  christos #endif
     93      1.1  christos 
     94      1.1  christos     return out;
     95      1.1  christos }
     96      1.1  christos 
     97      1.1  christos /*
     98      1.1  christos  * The application wants to send some block of data to the peer.
     99      1.1  christos  * This is a blocking call.
    100      1.1  christos  */
    101      1.1  christos int tx(BIO *bio, const void *buf, int buf_len)
    102      1.1  christos {
    103      1.1  christos     return BIO_write(bio, buf, buf_len);
    104      1.1  christos }
    105      1.1  christos 
    106      1.1  christos /*
    107      1.1  christos  * The application wants to receive some block of data from
    108      1.1  christos  * the peer. This is a blocking call.
    109      1.1  christos  */
    110      1.1  christos int rx(BIO *bio, void *buf, int buf_len)
    111      1.1  christos {
    112      1.1  christos     return BIO_read(bio, buf, buf_len);
    113      1.1  christos }
    114      1.1  christos 
    115      1.1  christos /*
    116      1.1  christos  * The application wants to close the connection and free bookkeeping
    117      1.1  christos  * structures.
    118      1.1  christos  */
    119      1.1  christos void teardown(BIO *bio)
    120      1.1  christos {
    121      1.1  christos     BIO_free_all(bio);
    122      1.1  christos }
    123      1.1  christos 
    124      1.1  christos /*
    125      1.1  christos  * The application is shutting down and wants to free a previously
    126      1.1  christos  * created SSL_CTX.
    127      1.1  christos  */
    128      1.1  christos void teardown_ctx(SSL_CTX *ctx)
    129      1.1  christos {
    130      1.1  christos     SSL_CTX_free(ctx);
    131      1.1  christos }
    132      1.1  christos 
    133      1.1  christos /*
    134      1.1  christos  * ============================================================================
    135      1.1  christos  * Example driver for the above code. This is just to demonstrate that the code
    136      1.1  christos  * works and is not intended to be representative of a real application.
    137      1.1  christos  */
    138      1.1  christos int main(int argc, char **argv)
    139      1.1  christos {
    140      1.1  christos     static char msg[384], host_port[300];
    141      1.1  christos     SSL_CTX *ctx = NULL;
    142      1.1  christos     BIO *b = NULL;
    143      1.1  christos     char buf[2048];
    144      1.1  christos     int l, mlen, res = 1;
    145      1.1  christos 
    146      1.1  christos     if (argc < 3) {
    147      1.1  christos         fprintf(stderr, "usage: %s host port\n", argv[0]);
    148      1.1  christos         goto fail;
    149      1.1  christos     }
    150      1.1  christos 
    151      1.1  christos     snprintf(host_port, sizeof(host_port), "%s:%s", argv[1], argv[2]);
    152      1.1  christos     mlen = snprintf(msg, sizeof(msg),
    153  1.1.1.2  christos         "GET / HTTP/1.0\r\nHost: %s\r\n\r\n", argv[1]);
    154      1.1  christos 
    155      1.1  christos     ctx = create_ssl_ctx();
    156      1.1  christos     if (ctx == NULL) {
    157      1.1  christos         fprintf(stderr, "could not create context\n");
    158      1.1  christos         goto fail;
    159      1.1  christos     }
    160      1.1  christos 
    161      1.1  christos     b = new_conn(ctx, host_port);
    162      1.1  christos     if (b == NULL) {
    163      1.1  christos         fprintf(stderr, "could not create connection\n");
    164      1.1  christos         goto fail;
    165      1.1  christos     }
    166      1.1  christos 
    167      1.1  christos     l = tx(b, msg, mlen);
    168      1.1  christos     if (l < mlen) {
    169      1.1  christos         fprintf(stderr, "tx error\n");
    170      1.1  christos         goto fail;
    171      1.1  christos     }
    172      1.1  christos 
    173      1.1  christos     for (;;) {
    174      1.1  christos         l = rx(b, buf, sizeof(buf));
    175      1.1  christos         if (l <= 0)
    176      1.1  christos             break;
    177      1.1  christos         fwrite(buf, 1, l, stdout);
    178      1.1  christos     }
    179      1.1  christos 
    180      1.1  christos     res = 0;
    181      1.1  christos fail:
    182      1.1  christos     if (b != NULL)
    183      1.1  christos         teardown(b);
    184      1.1  christos     if (ctx != NULL)
    185      1.1  christos         teardown_ctx(ctx);
    186      1.1  christos     return res;
    187      1.1  christos }
    188