Home | History | Annotate | Line # | Download | only in ddd
      1 #include <sys/poll.h>
      2 #include <openssl/ssl.h>
      3 
      4 /*
      5  * Demo 5: Client  Client Uses Memory BIO  Nonblocking
      6  * =====================================================
      7  *
      8  * This is an example of (part of) an application which uses libssl in an
      9  * asynchronous, nonblocking fashion. The application passes memory BIOs to
     10  * OpenSSL, meaning that it controls both when data is read/written from an SSL
     11  * object on the decrypted side but also when encrypted data from the network is
     12  * shunted to/from OpenSSL. In this way OpenSSL is used as a pure state machine
     13  * which does not make its own network I/O calls. OpenSSL never sees or creates
     14  * any file descriptor for a network socket. The functions below show all
     15  * interactions with libssl the application makes, and would hypothetically be
     16  * linked into a larger application.
     17  */
     18 typedef struct app_conn_st {
     19     SSL *ssl;
     20     BIO *ssl_bio, *net_bio;
     21     int rx_need_tx, tx_need_rx;
     22 } APP_CONN;
     23 
     24 /*
     25  * The application is initializing and wants an SSL_CTX which it will use for
     26  * some number of outgoing connections, which it creates in subsequent calls to
     27  * new_conn. The application may also call this function multiple times to
     28  * create multiple SSL_CTX.
     29  */
     30 SSL_CTX *create_ssl_ctx(void)
     31 {
     32     SSL_CTX *ctx;
     33 
     34 #ifdef USE_QUIC
     35     ctx = SSL_CTX_new(OSSL_QUIC_client_method());
     36 #else
     37     ctx = SSL_CTX_new(TLS_client_method());
     38 #endif
     39     if (ctx == NULL)
     40         return NULL;
     41 
     42     /* Enable trust chain verification. */
     43     SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
     44 
     45     /* Load default root CA store. */
     46     if (SSL_CTX_set_default_verify_paths(ctx) == 0) {
     47         SSL_CTX_free(ctx);
     48         return NULL;
     49     }
     50 
     51     return ctx;
     52 }
     53 
     54 /*
     55  * The application wants to create a new outgoing connection using a given
     56  * SSL_CTX.
     57  *
     58  * hostname is a string like "openssl.org" used for certificate validation.
     59  */
     60 APP_CONN *new_conn(SSL_CTX *ctx, const char *bare_hostname)
     61 {
     62     BIO *ssl_bio, *internal_bio, *net_bio;
     63     APP_CONN *conn;
     64     SSL *ssl;
     65 #ifdef USE_QUIC
     66     static const unsigned char alpn[] = { 5, 'd', 'u', 'm', 'm', 'y' };
     67 #endif
     68 
     69     conn = calloc(1, sizeof(APP_CONN));
     70     if (conn == NULL)
     71         return NULL;
     72 
     73     ssl = conn->ssl = SSL_new(ctx);
     74     if (ssl == NULL) {
     75         free(conn);
     76         return NULL;
     77     }
     78 
     79     SSL_set_connect_state(ssl); /* cannot fail */
     80 
     81 #ifdef USE_QUIC
     82     if (BIO_new_bio_dgram_pair(&internal_bio, 0, &net_bio, 0) <= 0) {
     83 #else
     84     if (BIO_new_bio_pair(&internal_bio, 0, &net_bio, 0) <= 0) {
     85 #endif
     86         SSL_free(ssl);
     87         free(conn);
     88         return NULL;
     89     }
     90 
     91     SSL_set_bio(ssl, internal_bio, internal_bio);
     92 
     93     if (SSL_set1_host(ssl, bare_hostname) <= 0) {
     94         SSL_free(ssl);
     95         free(conn);
     96         return NULL;
     97     }
     98 
     99     if (SSL_set_tlsext_host_name(ssl, bare_hostname) <= 0) {
    100         SSL_free(ssl);
    101         free(conn);
    102         return NULL;
    103     }
    104 
    105     ssl_bio = BIO_new(BIO_f_ssl());
    106     if (ssl_bio == NULL) {
    107         SSL_free(ssl);
    108         free(conn);
    109         return NULL;
    110     }
    111 
    112     if (BIO_set_ssl(ssl_bio, ssl, BIO_CLOSE) <= 0) {
    113         SSL_free(ssl);
    114         BIO_free(ssl_bio);
    115         return NULL;
    116     }
    117 
    118 #ifdef USE_QUIC
    119     /* Configure ALPN, which is required for QUIC. */
    120     if (SSL_set_alpn_protos(ssl, alpn, sizeof(alpn))) {
    121         /* Note: SSL_set_alpn_protos returns 1 for failure. */
    122         SSL_free(ssl);
    123         BIO_free(ssl_bio);
    124         return NULL;
    125     }
    126 #endif
    127 
    128     conn->ssl_bio = ssl_bio;
    129     conn->net_bio = net_bio;
    130     return conn;
    131 }
    132 
    133 /*
    134  * Non-blocking transmission.
    135  *
    136  * Returns -1 on error. Returns -2 if the function would block (corresponds to
    137  * EWOULDBLOCK).
    138  */
    139 int tx(APP_CONN *conn, const void *buf, int buf_len)
    140 {
    141     int rc, l;
    142 
    143     l = BIO_write(conn->ssl_bio, buf, buf_len);
    144     if (l <= 0) {
    145         rc = SSL_get_error(conn->ssl, l);
    146         switch (rc) {
    147         case SSL_ERROR_WANT_READ:
    148             conn->tx_need_rx = 1;
    149         case SSL_ERROR_WANT_CONNECT:
    150         case SSL_ERROR_WANT_WRITE:
    151             return -2;
    152         default:
    153             return -1;
    154         }
    155     } else {
    156         conn->tx_need_rx = 0;
    157     }
    158 
    159     return l;
    160 }
    161 
    162 /*
    163  * Non-blocking reception.
    164  *
    165  * Returns -1 on error. Returns -2 if the function would block (corresponds to
    166  * EWOULDBLOCK).
    167  */
    168 int rx(APP_CONN *conn, void *buf, int buf_len)
    169 {
    170     int rc, l;
    171 
    172     l = BIO_read(conn->ssl_bio, buf, buf_len);
    173     if (l <= 0) {
    174         rc = SSL_get_error(conn->ssl, l);
    175         switch (rc) {
    176         case SSL_ERROR_WANT_WRITE:
    177             conn->rx_need_tx = 1;
    178         case SSL_ERROR_WANT_READ:
    179             return -2;
    180         default:
    181             return -1;
    182         }
    183     } else {
    184         conn->rx_need_tx = 0;
    185     }
    186 
    187     return l;
    188 }
    189 
    190 /*
    191  * Called to get data which has been enqueued for transmission to the network
    192  * by OpenSSL. For QUIC, this always outputs a single datagram.
    193  *
    194  * IMPORTANT (QUIC): If buf_len is inadequate to hold the datagram, it is truncated
    195  * (similar to read(2)). A buffer size of at least 1472 must be used by default
    196  * to guarantee this does not occur.
    197  */
    198 int read_net_tx(APP_CONN *conn, void *buf, int buf_len)
    199 {
    200     return BIO_read(conn->net_bio, buf, buf_len);
    201 }
    202 
    203 /*
    204  * Called to feed data which has been received from the network to OpenSSL.
    205  *
    206  * QUIC: buf must contain the entirety of a single datagram. It will be consumed
    207  * entirely (return value == buf_len) or not at all.
    208  */
    209 int write_net_rx(APP_CONN *conn, const void *buf, int buf_len)
    210 {
    211     return BIO_write(conn->net_bio, buf, buf_len);
    212 }
    213 
    214 /*
    215  * Determine how much data can be written to the network RX BIO.
    216  */
    217 size_t net_rx_space(APP_CONN *conn)
    218 {
    219     return BIO_ctrl_get_write_guarantee(conn->net_bio);
    220 }
    221 
    222 /*
    223  * Determine how much data is currently queued for transmission in the network
    224  * TX BIO.
    225  */
    226 size_t net_tx_avail(APP_CONN *conn)
    227 {
    228     return BIO_ctrl_pending(conn->net_bio);
    229 }
    230 
    231 /*
    232  * These functions returns zero or more of:
    233  *
    234  *   POLLIN:    The SSL state machine is interested in socket readability events.
    235  *
    236  *   POLLOUT:   The SSL state machine is interested in socket writeability events.
    237  *
    238  *   POLLERR:   The SSL state machine is interested in socket error events.
    239  *
    240  * get_conn_pending_tx returns events which may cause SSL_write to make
    241  * progress and get_conn_pending_rx returns events which may cause SSL_read
    242  * to make progress.
    243  */
    244 int get_conn_pending_tx(APP_CONN *conn)
    245 {
    246 #ifdef USE_QUIC
    247     return (SSL_net_read_desired(conn->ssl) ? POLLIN : 0)
    248         | (SSL_net_write_desired(conn->ssl) ? POLLOUT : 0)
    249         | POLLERR;
    250 #else
    251     return (conn->tx_need_rx ? POLLIN : 0) | POLLOUT | POLLERR;
    252 #endif
    253 }
    254 
    255 int get_conn_pending_rx(APP_CONN *conn)
    256 {
    257 #ifdef USE_QUIC
    258     return get_conn_pending_tx(conn);
    259 #else
    260     return (conn->rx_need_tx ? POLLOUT : 0) | POLLIN | POLLERR;
    261 #endif
    262 }
    263 
    264 /*
    265  * The application wants to close the connection and free bookkeeping
    266  * structures.
    267  */
    268 void teardown(APP_CONN *conn)
    269 {
    270     BIO_free_all(conn->ssl_bio);
    271     BIO_free_all(conn->net_bio);
    272     free(conn);
    273 }
    274 
    275 /*
    276  * The application is shutting down and wants to free a previously
    277  * created SSL_CTX.
    278  */
    279 void teardown_ctx(SSL_CTX *ctx)
    280 {
    281     SSL_CTX_free(ctx);
    282 }
    283 
    284 /*
    285  * ============================================================================
    286  * Example driver for the above code. This is just to demonstrate that the code
    287  * works and is not intended to be representative of a real application.
    288  */
    289 #include <sys/types.h>
    290 #include <sys/socket.h>
    291 #include <sys/signal.h>
    292 #include <netdb.h>
    293 #include <unistd.h>
    294 #include <fcntl.h>
    295 #include <errno.h>
    296 
    297 static int pump(APP_CONN *conn, int fd, int events, int timeout)
    298 {
    299     int l, l2;
    300     char buf[2048]; /* QUIC: would need to be changed if < 1472 */
    301     size_t wspace;
    302     struct pollfd pfd = { 0 };
    303 
    304     pfd.fd = fd;
    305     pfd.events = (events & (POLLIN | POLLERR));
    306     if (net_rx_space(conn) == 0)
    307         pfd.events &= ~POLLIN;
    308     if (net_tx_avail(conn) > 0)
    309         pfd.events |= POLLOUT;
    310 
    311     if ((pfd.events & (POLLIN | POLLOUT)) == 0)
    312         return 1;
    313 
    314     if (poll(&pfd, 1, timeout) == 0)
    315         return -1;
    316 
    317     if (pfd.revents & POLLIN) {
    318         while ((wspace = net_rx_space(conn)) > 0) {
    319             l = read(fd, buf, wspace > sizeof(buf) ? sizeof(buf) : wspace);
    320             if (l <= 0) {
    321                 switch (errno) {
    322                 case EAGAIN:
    323                     goto stop;
    324                 default:
    325                     if (l == 0) /* EOF */
    326                         goto stop;
    327 
    328                     fprintf(stderr, "error on read: %d\n", errno);
    329                     return -1;
    330                 }
    331                 break;
    332             }
    333             l2 = write_net_rx(conn, buf, l);
    334             if (l2 < l)
    335                 fprintf(stderr, "short write %d %d\n", l2, l);
    336         }
    337     stop:;
    338     }
    339 
    340     if (pfd.revents & POLLOUT) {
    341         for (;;) {
    342             l = read_net_tx(conn, buf, sizeof(buf));
    343             if (l <= 0)
    344                 break;
    345             l2 = write(fd, buf, l);
    346             if (l2 < l)
    347                 fprintf(stderr, "short read %d %d\n", l2, l);
    348         }
    349     }
    350 
    351     return 1;
    352 }
    353 
    354 int main(int argc, char **argv)
    355 {
    356     int rc, fd = -1, res = 1;
    357     static char tx_msg[300];
    358     const char *tx_p = tx_msg;
    359     char rx_buf[2048];
    360     int l, tx_len;
    361     int timeout = 2000 /* ms */;
    362     APP_CONN *conn = NULL;
    363     struct addrinfo hints = { 0 }, *result = NULL;
    364     SSL_CTX *ctx = NULL;
    365 
    366     if (argc < 3) {
    367         fprintf(stderr, "usage: %s host port\n", argv[0]);
    368         goto fail;
    369     }
    370 
    371     tx_len = snprintf(tx_msg, sizeof(tx_msg),
    372         "GET / HTTP/1.0\r\nHost: %s\r\n\r\n",
    373         argv[1]);
    374 
    375     ctx = create_ssl_ctx();
    376     if (ctx == NULL) {
    377         fprintf(stderr, "cannot create SSL context\n");
    378         goto fail;
    379     }
    380 
    381     hints.ai_family = AF_INET;
    382     hints.ai_socktype = SOCK_STREAM;
    383     hints.ai_flags = AI_PASSIVE;
    384     rc = getaddrinfo(argv[1], argv[2], &hints, &result);
    385     if (rc < 0) {
    386         fprintf(stderr, "cannot resolve\n");
    387         goto fail;
    388     }
    389 
    390     signal(SIGPIPE, SIG_IGN);
    391 
    392 #ifdef USE_QUIC
    393     fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    394 #else
    395     fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    396 #endif
    397     if (fd < 0) {
    398         fprintf(stderr, "cannot create socket\n");
    399         goto fail;
    400     }
    401 
    402     rc = connect(fd, result->ai_addr, result->ai_addrlen);
    403     if (rc < 0) {
    404         fprintf(stderr, "cannot connect\n");
    405         goto fail;
    406     }
    407 
    408     rc = fcntl(fd, F_SETFL, O_NONBLOCK);
    409     if (rc < 0) {
    410         fprintf(stderr, "cannot make socket nonblocking\n");
    411         goto fail;
    412     }
    413 
    414     conn = new_conn(ctx, argv[1]);
    415     if (conn == NULL) {
    416         fprintf(stderr, "cannot establish connection\n");
    417         goto fail;
    418     }
    419 
    420     /* TX */
    421     while (tx_len != 0) {
    422         l = tx(conn, tx_p, tx_len);
    423         if (l > 0) {
    424             tx_p += l;
    425             tx_len -= l;
    426         } else if (l == -1) {
    427             fprintf(stderr, "tx error\n");
    428         } else if (l == -2) {
    429             if (pump(conn, fd, get_conn_pending_tx(conn), timeout) != 1) {
    430                 fprintf(stderr, "pump error\n");
    431                 goto fail;
    432             }
    433         }
    434     }
    435 
    436     /* RX */
    437     for (;;) {
    438         l = rx(conn, rx_buf, sizeof(rx_buf));
    439         if (l > 0) {
    440             fwrite(rx_buf, 1, l, stdout);
    441         } else if (l == -1) {
    442             break;
    443         } else if (l == -2) {
    444             if (pump(conn, fd, get_conn_pending_rx(conn), timeout) != 1) {
    445                 fprintf(stderr, "pump error\n");
    446                 goto fail;
    447             }
    448         }
    449     }
    450 
    451     res = 0;
    452 fail:
    453     if (conn != NULL)
    454         teardown(conn);
    455     if (ctx != NULL)
    456         teardown_ctx(ctx);
    457     if (result != NULL)
    458         freeaddrinfo(result);
    459     return res;
    460 }
    461