Path: blob/main/crypto/openssl/doc/designs/ddd/ddd-01-conn-blocking.c
34889 views
#include <openssl/ssl.h>12/*3* Demo 1: Client — Managed Connection — Blocking4* ==============================================5*6* This is an example of (part of) an application which uses libssl in a simple,7* synchronous, blocking fashion. The functions show all interactions with8* libssl the application makes, and would hypothetically be linked into a9* larger application.10*/1112/*13* The application is initializing and wants an SSL_CTX which it will use for14* some number of outgoing connections, which it creates in subsequent calls to15* new_conn. The application may also call this function multiple times to16* create multiple SSL_CTX.17*/18SSL_CTX *create_ssl_ctx(void)19{20SSL_CTX *ctx;2122#ifdef USE_QUIC23ctx = SSL_CTX_new(OSSL_QUIC_client_method());24#else25ctx = SSL_CTX_new(TLS_client_method());26#endif27if (ctx == NULL)28return NULL;2930/* Enable trust chain verification. */31SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);3233/* Load default root CA store. */34if (SSL_CTX_set_default_verify_paths(ctx) == 0) {35SSL_CTX_free(ctx);36return NULL;37}3839return ctx;40}4142/*43* The application wants to create a new outgoing connection using a given44* SSL_CTX.45*46* hostname is a string like "openssl.org:443" or "[::1]:443".47*/48BIO *new_conn(SSL_CTX *ctx, const char *hostname)49{50BIO *out;51SSL *ssl = NULL;52const char *bare_hostname;53#ifdef USE_QUIC54static const unsigned char alpn[] = {5, 'd', 'u', 'm', 'm', 'y'};55#endif5657out = BIO_new_ssl_connect(ctx);58if (out == NULL)59return NULL;6061if (BIO_get_ssl(out, &ssl) == 0) {62BIO_free_all(out);63return NULL;64}6566if (BIO_set_conn_hostname(out, hostname) == 0) {67BIO_free_all(out);68return NULL;69}7071/* Returns the parsed hostname extracted from the hostname:port string. */72bare_hostname = BIO_get_conn_hostname(out);73if (bare_hostname == NULL) {74BIO_free_all(out);75return NULL;76}7778/* Tell the SSL object the hostname to check certificates against. */79if (SSL_set1_host(ssl, bare_hostname) <= 0) {80BIO_free_all(out);81return NULL;82}8384#ifdef USE_QUIC85/* Configure ALPN, which is required for QUIC. */86if (SSL_set_alpn_protos(ssl, alpn, sizeof(alpn))) {87/* Note: SSL_set_alpn_protos returns 1 for failure. */88BIO_free_all(out);89return NULL;90}91#endif9293return out;94}9596/*97* The application wants to send some block of data to the peer.98* This is a blocking call.99*/100int tx(BIO *bio, const void *buf, int buf_len)101{102return BIO_write(bio, buf, buf_len);103}104105/*106* The application wants to receive some block of data from107* the peer. This is a blocking call.108*/109int rx(BIO *bio, void *buf, int buf_len)110{111return BIO_read(bio, buf, buf_len);112}113114/*115* The application wants to close the connection and free bookkeeping116* structures.117*/118void teardown(BIO *bio)119{120BIO_free_all(bio);121}122123/*124* The application is shutting down and wants to free a previously125* created SSL_CTX.126*/127void teardown_ctx(SSL_CTX *ctx)128{129SSL_CTX_free(ctx);130}131132/*133* ============================================================================134* Example driver for the above code. This is just to demonstrate that the code135* works and is not intended to be representative of a real application.136*/137int main(int argc, char **argv)138{139static char msg[384], host_port[300];140SSL_CTX *ctx = NULL;141BIO *b = NULL;142char buf[2048];143int l, mlen, res = 1;144145if (argc < 3) {146fprintf(stderr, "usage: %s host port\n", argv[0]);147goto fail;148}149150snprintf(host_port, sizeof(host_port), "%s:%s", argv[1], argv[2]);151mlen = snprintf(msg, sizeof(msg),152"GET / HTTP/1.0\r\nHost: %s\r\n\r\n", argv[1]);153154ctx = create_ssl_ctx();155if (ctx == NULL) {156fprintf(stderr, "could not create context\n");157goto fail;158}159160b = new_conn(ctx, host_port);161if (b == NULL) {162fprintf(stderr, "could not create connection\n");163goto fail;164}165166l = tx(b, msg, mlen);167if (l < mlen) {168fprintf(stderr, "tx error\n");169goto fail;170}171172for (;;) {173l = rx(b, buf, sizeof(buf));174if (l <= 0)175break;176fwrite(buf, 1, l, stdout);177}178179res = 0;180fail:181if (b != NULL)182teardown(b);183if (ctx != NULL)184teardown_ctx(ctx);185return res;186}187188189