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