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