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