Home | History | Annotate | Line # | Download | only in bio
      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.1.2  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     /* Use it inside an SSL BIO */
     67      1.1  christos     ssl_bio = BIO_new(BIO_f_ssl());
     68      1.1  christos     BIO_set_ssl(ssl_bio, ssl, BIO_CLOSE);
     69      1.1  christos 
     70      1.1  christos     /* Lets use a connect BIO under the SSL BIO */
     71      1.1  christos     out = BIO_new(BIO_s_connect());
     72      1.1  christos     BIO_set_conn_hostname(out, hostport);
     73      1.1  christos 
     74      1.1  christos     /* The BIO has parsed the host:port and even IPv6 literals in [] */
     75      1.1  christos     hostname = BIO_get_conn_hostname(out);
     76      1.1  christos     if (!hostname || SSL_set1_host(ssl, hostname) <= 0) {
     77      1.1  christos         BIO_free(ssl_bio);
     78      1.1  christos         goto err;
     79      1.1  christos     }
     80      1.1  christos 
     81      1.1  christos     BIO_set_nbio(out, 1);
     82      1.1  christos     out = BIO_push(ssl_bio, out);
     83      1.1  christos 
     84      1.1  christos     p = "GET / HTTP/1.0\r\n\r\n";
     85      1.1  christos     len = strlen(p);
     86      1.1  christos 
     87      1.1  christos     off = 0;
     88      1.1  christos     for (;;) {
     89      1.1  christos         i = BIO_write(out, &(p[off]), len);
     90      1.1  christos         if (i <= 0) {
     91      1.1  christos             if (BIO_should_retry(out)) {
     92      1.1  christos                 fprintf(stderr, "write DELAY\n");
     93      1.1  christos                 sleep(1);
     94      1.1  christos                 continue;
     95      1.1  christos             } else {
     96      1.1  christos                 goto err;
     97      1.1  christos             }
     98      1.1  christos         }
     99      1.1  christos         off += i;
    100      1.1  christos         len -= i;
    101      1.1  christos         if (len <= 0)
    102      1.1  christos             break;
    103      1.1  christos     }
    104      1.1  christos 
    105      1.1  christos     for (;;) {
    106      1.1  christos         i = BIO_read(out, buf, sizeof(buf));
    107      1.1  christos         if (i == 0)
    108      1.1  christos             break;
    109      1.1  christos         if (i < 0) {
    110      1.1  christos             if (BIO_should_retry(out)) {
    111      1.1  christos                 fprintf(stderr, "read DELAY\n");
    112      1.1  christos                 sleep(1);
    113      1.1  christos                 continue;
    114      1.1  christos             }
    115      1.1  christos             goto err;
    116      1.1  christos         }
    117      1.1  christos         fwrite(buf, 1, i, stdout);
    118      1.1  christos     }
    119      1.1  christos 
    120      1.1  christos     ret = EXIT_SUCCESS;
    121      1.1  christos     goto done;
    122      1.1  christos 
    123  1.1.1.2  christos err:
    124      1.1  christos     if (ERR_peek_error() == 0) { /* system call error */
    125      1.1  christos         fprintf(stderr, "errno=%d ", errno);
    126      1.1  christos         perror("error");
    127      1.1  christos     } else {
    128      1.1  christos         ERR_print_errors_fp(stderr);
    129      1.1  christos     }
    130  1.1.1.2  christos done:
    131      1.1  christos     BIO_free_all(out);
    132      1.1  christos     SSL_CTX_free(ssl_ctx);
    133      1.1  christos     return ret;
    134      1.1  christos }
    135