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