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  */
create_ssl_ctx(void)19 SSL_CTX *create_ssl_ctx(void)
20 {
21     SSL_CTX *ctx;
22 
23     ctx = SSL_CTX_new(TLS_client_method());
24     if (ctx == NULL)
25         return NULL;
26 
27     /* Enable trust chain verification. */
28     SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
29 
30     /* Load default root CA store. */
31     if (SSL_CTX_set_default_verify_paths(ctx) == 0) {
32         SSL_CTX_free(ctx);
33         return NULL;
34     }
35 
36     return ctx;
37 }
38 
39 /*
40  * The application wants to create a new outgoing connection using a given
41  * SSL_CTX.
42  *
43  * hostname is a string like "openssl.org:443" or "[::1]:443".
44  */
new_conn(SSL_CTX * ctx,const char * hostname)45 BIO *new_conn(SSL_CTX *ctx, const char *hostname)
46 {
47     BIO *out;
48     SSL *ssl = NULL;
49     const char *bare_hostname;
50 
51     out = BIO_new_ssl_connect(ctx);
52     if (out == NULL)
53         return NULL;
54 
55     if (BIO_get_ssl(out, &ssl) == 0) {
56         BIO_free_all(out);
57         return NULL;
58     }
59 
60     if (BIO_set_conn_hostname(out, hostname) == 0) {
61         BIO_free_all(out);
62         return NULL;
63     }
64 
65     /* Returns the parsed hostname extracted from the hostname:port string. */
66     bare_hostname = BIO_get_conn_hostname(out);
67     if (bare_hostname == NULL) {
68         BIO_free_all(out);
69         return NULL;
70     }
71 
72     /* Tell the SSL object the hostname to check certificates against. */
73     if (SSL_set1_host(ssl, bare_hostname) <= 0) {
74         BIO_free_all(out);
75         return NULL;
76     }
77 
78     return out;
79 }
80 
81 /*
82  * The application wants to send some block of data to the peer.
83  * This is a blocking call.
84  */
tx(BIO * bio,const void * buf,int buf_len)85 int tx(BIO *bio, const void *buf, int buf_len)
86 {
87     return BIO_write(bio, buf, buf_len);
88 }
89 
90 /*
91  * The application wants to receive some block of data from
92  * the peer. This is a blocking call.
93  */
rx(BIO * bio,void * buf,int buf_len)94 int rx(BIO *bio, void *buf, int buf_len)
95 {
96     return BIO_read(bio, buf, buf_len);
97 }
98 
99 /*
100  * The application wants to close the connection and free bookkeeping
101  * structures.
102  */
teardown(BIO * bio)103 void teardown(BIO *bio)
104 {
105     BIO_free_all(bio);
106 }
107 
108 /*
109  * The application is shutting down and wants to free a previously
110  * created SSL_CTX.
111  */
teardown_ctx(SSL_CTX * ctx)112 void teardown_ctx(SSL_CTX *ctx)
113 {
114     SSL_CTX_free(ctx);
115 }
116 
117 /*
118  * ============================================================================
119  * Example driver for the above code. This is just to demonstrate that the code
120  * works and is not intended to be representative of a real application.
121  */
main(int argc,char ** argv)122 int main(int argc, char **argv)
123 {
124     const char msg[] = "GET / HTTP/1.0\r\nHost: www.openssl.org\r\n\r\n";
125     SSL_CTX *ctx = NULL;
126     BIO *b = NULL;
127     char buf[2048];
128     int l, res = 1;
129 
130     ctx = create_ssl_ctx();
131     if (ctx == NULL) {
132         fprintf(stderr, "could not create context\n");
133         goto fail;
134     }
135 
136     b = new_conn(ctx, "www.openssl.org:443");
137     if (b == NULL) {
138         fprintf(stderr, "could not create conn\n");
139         goto fail;
140     }
141 
142     if (tx(b, msg, sizeof(msg)) < sizeof(msg)) {
143         fprintf(stderr, "tx error\n");
144         goto fail;
145     }
146 
147     for (;;) {
148         l = rx(b, buf, sizeof(buf));
149         if (l <= 0)
150             break;
151         fwrite(buf, 1, l, stdout);
152     }
153 
154     res = 0;
155 fail:
156     if (b != NULL)
157         teardown(b);
158     if (ctx != NULL)
159         teardown_ctx(ctx);
160     return res;
161 }
162