Home | History | Annotate | Line # | Download | only in bio
sconnect.c revision 1.1
      1  1.1  christos /*
      2  1.1  christos  * Copyright 1998-2025 The OpenSSL Project Authors. All Rights Reserved.
      3  1.1  christos  *
      4  1.1  christos  * Licensed under the Apache License 2.0 (the "License").  You may not use
      5  1.1  christos  * this file except in compliance with the License.  You can obtain a copy
      6  1.1  christos  * in the file LICENSE in the source distribution or at
      7  1.1  christos  * https://www.openssl.org/source/license.html
      8  1.1  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 <string.h>
     20  1.1  christos #include <errno.h>
     21  1.1  christos #include <openssl/err.h>
     22  1.1  christos #include <openssl/ssl.h>
     23  1.1  christos #if !defined(OPENSSL_SYS_WINDOWS)
     24  1.1  christos #include <unistd.h>
     25  1.1  christos #else
     26  1.1  christos #include <windows.h>
     27  1.1  christos # define sleep(x) Sleep(x*1000)
     28  1.1  christos #endif
     29  1.1  christos 
     30  1.1  christos #define HOSTPORT "localhost:4433"
     31  1.1  christos #define CAFILE "root.pem"
     32  1.1  christos 
     33  1.1  christos int main(int argc, char *argv[])
     34  1.1  christos {
     35  1.1  christos     const char *hostport = HOSTPORT;
     36  1.1  christos     const char *CAfile = CAFILE;
     37  1.1  christos     const char *hostname;
     38  1.1  christos     BIO *out = NULL;
     39  1.1  christos     char buf[1024 * 10], *p;
     40  1.1  christos     SSL_CTX *ssl_ctx = NULL;
     41  1.1  christos     SSL *ssl;
     42  1.1  christos     BIO *ssl_bio;
     43  1.1  christos     int i, len, off, ret = EXIT_FAILURE;
     44  1.1  christos 
     45  1.1  christos     if (argc > 1)
     46  1.1  christos         hostport = argv[1];
     47  1.1  christos     if (argc > 2)
     48  1.1  christos         CAfile = argv[2];
     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  christos     ssl_ctx = SSL_CTX_new(TLS_client_method());
     56  1.1  christos 
     57  1.1  christos     /* Enable trust chain verification */
     58  1.1  christos     SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL);
     59  1.1  christos     if (!SSL_CTX_load_verify_locations(ssl_ctx, CAfile, NULL))
     60  1.1  christos         goto err;
     61  1.1  christos 
     62  1.1  christos     /* Let's make an SSL structure */
     63  1.1  christos     ssl = SSL_new(ssl_ctx);
     64  1.1  christos     SSL_set_connect_state(ssl);
     65  1.1  christos 
     66  1.1  christos 
     67  1.1  christos     /* Use it inside an SSL BIO */
     68  1.1  christos     ssl_bio = BIO_new(BIO_f_ssl());
     69  1.1  christos     BIO_set_ssl(ssl_bio, ssl, BIO_CLOSE);
     70  1.1  christos 
     71  1.1  christos     /* Lets use a connect BIO under the SSL BIO */
     72  1.1  christos     out = BIO_new(BIO_s_connect());
     73  1.1  christos     BIO_set_conn_hostname(out, hostport);
     74  1.1  christos 
     75  1.1  christos     /* The BIO has parsed the host:port and even IPv6 literals in [] */
     76  1.1  christos     hostname = BIO_get_conn_hostname(out);
     77  1.1  christos     if (!hostname || SSL_set1_host(ssl, hostname) <= 0) {
     78  1.1  christos         BIO_free(ssl_bio);
     79  1.1  christos         goto err;
     80  1.1  christos     }
     81  1.1  christos 
     82  1.1  christos     BIO_set_nbio(out, 1);
     83  1.1  christos     out = BIO_push(ssl_bio, out);
     84  1.1  christos 
     85  1.1  christos     p = "GET / HTTP/1.0\r\n\r\n";
     86  1.1  christos     len = strlen(p);
     87  1.1  christos 
     88  1.1  christos     off = 0;
     89  1.1  christos     for (;;) {
     90  1.1  christos         i = BIO_write(out, &(p[off]), len);
     91  1.1  christos         if (i <= 0) {
     92  1.1  christos             if (BIO_should_retry(out)) {
     93  1.1  christos                 fprintf(stderr, "write DELAY\n");
     94  1.1  christos                 sleep(1);
     95  1.1  christos                 continue;
     96  1.1  christos             } else {
     97  1.1  christos                 goto err;
     98  1.1  christos             }
     99  1.1  christos         }
    100  1.1  christos         off += i;
    101  1.1  christos         len -= i;
    102  1.1  christos         if (len <= 0)
    103  1.1  christos             break;
    104  1.1  christos     }
    105  1.1  christos 
    106  1.1  christos     for (;;) {
    107  1.1  christos         i = BIO_read(out, buf, sizeof(buf));
    108  1.1  christos         if (i == 0)
    109  1.1  christos             break;
    110  1.1  christos         if (i < 0) {
    111  1.1  christos             if (BIO_should_retry(out)) {
    112  1.1  christos                 fprintf(stderr, "read DELAY\n");
    113  1.1  christos                 sleep(1);
    114  1.1  christos                 continue;
    115  1.1  christos             }
    116  1.1  christos             goto err;
    117  1.1  christos         }
    118  1.1  christos         fwrite(buf, 1, i, stdout);
    119  1.1  christos     }
    120  1.1  christos 
    121  1.1  christos     ret = EXIT_SUCCESS;
    122  1.1  christos     goto done;
    123  1.1  christos 
    124  1.1  christos  err:
    125  1.1  christos     if (ERR_peek_error() == 0) { /* system call error */
    126  1.1  christos         fprintf(stderr, "errno=%d ", errno);
    127  1.1  christos         perror("error");
    128  1.1  christos     } else {
    129  1.1  christos         ERR_print_errors_fp(stderr);
    130  1.1  christos     }
    131  1.1  christos  done:
    132  1.1  christos     BIO_free_all(out);
    133  1.1  christos     SSL_CTX_free(ssl_ctx);
    134  1.1  christos     return ret;
    135  1.1  christos }
    136