xref: /netbsd-src/crypto/external/bsd/openssl/dist/demos/bio/sconnect.c (revision b0d1725196a7921d003d2c66a14f186abda4176b)
1c7da899bSchristos /*
2*b0d17251Schristos  * Copyright 1998-2020 The OpenSSL Project Authors. All Rights Reserved.
3c7da899bSchristos  *
4*b0d17251Schristos  * Licensed under the Apache License 2.0 (the "License").  You may not use
5c7da899bSchristos  * this file except in compliance with the License.  You can obtain a copy
6c7da899bSchristos  * in the file LICENSE in the source distribution or at
7c7da899bSchristos  * https://www.openssl.org/source/license.html
8c7da899bSchristos  */
9a89c9211Schristos 
10635165faSspz /*-
11635165faSspz  * A minimal program to do SSL to a passed host and port.
12a89c9211Schristos  * It is actually using non-blocking IO but in a very simple manner
13a89c9211Schristos  * sconnect host:port - it does a 'GET / HTTP/1.0'
14a89c9211Schristos  *
15a89c9211Schristos  * cc -I../../include sconnect.c -L../.. -lssl -lcrypto
16a89c9211Schristos  */
17a89c9211Schristos #include <stdio.h>
18a89c9211Schristos #include <stdlib.h>
19a89c9211Schristos #include <unistd.h>
20c7da899bSchristos #include <string.h>
2113d40330Schristos #include <errno.h>
22a89c9211Schristos #include <openssl/err.h>
23a89c9211Schristos #include <openssl/ssl.h>
24a89c9211Schristos 
25c7da899bSchristos #define HOSTPORT "localhost:4433"
26c7da899bSchristos #define CAFILE "root.pem"
27c7da899bSchristos 
main(int argc,char * argv[])2813d40330Schristos int main(int argc, char *argv[])
29a89c9211Schristos {
30c7da899bSchristos     const char *hostport = HOSTPORT;
31c7da899bSchristos     const char *CAfile = CAFILE;
32*b0d17251Schristos     const char *hostname;
33c7da899bSchristos     char *cp;
34c7da899bSchristos     BIO *out = NULL;
35a89c9211Schristos     char buf[1024 * 10], *p;
36a89c9211Schristos     SSL_CTX *ssl_ctx = NULL;
37a89c9211Schristos     SSL *ssl;
38a89c9211Schristos     BIO *ssl_bio;
3913d40330Schristos     int i, len, off, ret = EXIT_FAILURE;
40a89c9211Schristos 
41c7da899bSchristos     if (argc > 1)
42c7da899bSchristos         hostport = argv[1];
43c7da899bSchristos     if (argc > 2)
44c7da899bSchristos         CAfile = argv[2];
45c7da899bSchristos 
46a89c9211Schristos #ifdef WATT32
47a89c9211Schristos     dbug_init();
48a89c9211Schristos     sock_init();
49a89c9211Schristos #endif
50a89c9211Schristos 
51c7da899bSchristos     ssl_ctx = SSL_CTX_new(TLS_client_method());
52a89c9211Schristos 
53c7da899bSchristos     /* Enable trust chain verification */
54c7da899bSchristos     SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL);
55c7da899bSchristos     SSL_CTX_load_verify_locations(ssl_ctx, CAfile, NULL);
56a89c9211Schristos 
57a89c9211Schristos     /* Lets make a SSL structure */
58a89c9211Schristos     ssl = SSL_new(ssl_ctx);
59a89c9211Schristos     SSL_set_connect_state(ssl);
60a89c9211Schristos 
61c7da899bSchristos 
62a89c9211Schristos     /* Use it inside an SSL BIO */
63a89c9211Schristos     ssl_bio = BIO_new(BIO_f_ssl());
64a89c9211Schristos     BIO_set_ssl(ssl_bio, ssl, BIO_CLOSE);
65a89c9211Schristos 
66a89c9211Schristos     /* Lets use a connect BIO under the SSL BIO */
67a89c9211Schristos     out = BIO_new(BIO_s_connect());
68c7da899bSchristos     BIO_set_conn_hostname(out, hostport);
69*b0d17251Schristos 
70*b0d17251Schristos     /* The BIO has parsed the host:port and even IPv6 literals in [] */
71*b0d17251Schristos     hostname = BIO_get_conn_hostname(out);
72*b0d17251Schristos     if (!hostname || SSL_set1_host(ssl, hostname) <= 0)
73*b0d17251Schristos         goto err;
74*b0d17251Schristos 
75a89c9211Schristos     BIO_set_nbio(out, 1);
76a89c9211Schristos     out = BIO_push(ssl_bio, out);
77a89c9211Schristos 
78a89c9211Schristos     p = "GET / HTTP/1.0\r\n\r\n";
79a89c9211Schristos     len = strlen(p);
80a89c9211Schristos 
81a89c9211Schristos     off = 0;
82635165faSspz     for (;;) {
83a89c9211Schristos         i = BIO_write(out, &(p[off]), len);
84635165faSspz         if (i <= 0) {
85635165faSspz             if (BIO_should_retry(out)) {
86a89c9211Schristos                 fprintf(stderr, "write DELAY\n");
87a89c9211Schristos                 sleep(1);
88a89c9211Schristos                 continue;
89635165faSspz             } else {
90a89c9211Schristos                 goto err;
91a89c9211Schristos             }
92a89c9211Schristos         }
93a89c9211Schristos         off += i;
94a89c9211Schristos         len -= i;
95635165faSspz         if (len <= 0)
96635165faSspz             break;
97a89c9211Schristos     }
98a89c9211Schristos 
99635165faSspz     for (;;) {
100a89c9211Schristos         i = BIO_read(out, buf, sizeof(buf));
101635165faSspz         if (i == 0)
102635165faSspz             break;
103635165faSspz         if (i < 0) {
104635165faSspz             if (BIO_should_retry(out)) {
105a89c9211Schristos                 fprintf(stderr, "read DELAY\n");
106a89c9211Schristos                 sleep(1);
107a89c9211Schristos                 continue;
108a89c9211Schristos             }
109a89c9211Schristos             goto err;
110a89c9211Schristos         }
111a89c9211Schristos         fwrite(buf, 1, i, stdout);
112a89c9211Schristos     }
113a89c9211Schristos 
11413d40330Schristos     ret = EXIT_SUCCESS;
115c7da899bSchristos     goto done;
116a89c9211Schristos 
117a89c9211Schristos  err:
118635165faSspz     if (ERR_peek_error() == 0) { /* system call error */
119a89c9211Schristos         fprintf(stderr, "errno=%d ", errno);
120a89c9211Schristos         perror("error");
12113d40330Schristos     } else {
122a89c9211Schristos         ERR_print_errors_fp(stderr);
12313d40330Schristos     }
124c7da899bSchristos  done:
125a89c9211Schristos     BIO_free_all(out);
126635165faSspz     SSL_CTX_free(ssl_ctx);
12713d40330Schristos     return ret;
128a89c9211Schristos }
129