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