1 1.1 christos /* 2 1.1.1.2 christos * Copyright 2013-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 serve an SSL connection. It uses blocking. It use the 12 1.1 christos * SSL_CONF API with the command line. cc -I../../include server-arg.c 13 1.1 christos * -L../.. -lssl -lcrypto -ldl 14 1.1 christos */ 15 1.1 christos 16 1.1 christos #include <stdio.h> 17 1.1 christos #include <string.h> 18 1.1 christos #include <signal.h> 19 1.1 christos #include <stdlib.h> 20 1.1 christos #include <openssl/err.h> 21 1.1 christos #include <openssl/ssl.h> 22 1.1 christos 23 1.1 christos int main(int argc, char *argv[]) 24 1.1 christos { 25 1.1 christos char *port = "*:4433"; 26 1.1.1.2 christos BIO *ssl_bio = NULL; 27 1.1.1.2 christos BIO *tmp; 28 1.1 christos SSL_CTX *ctx; 29 1.1 christos SSL_CONF_CTX *cctx; 30 1.1 christos char buf[512]; 31 1.1 christos BIO *in = NULL; 32 1.1 christos int ret = EXIT_FAILURE, i; 33 1.1 christos char **args = argv + 1; 34 1.1 christos int nargs = argc - 1; 35 1.1 christos 36 1.1 christos ctx = SSL_CTX_new(TLS_server_method()); 37 1.1 christos 38 1.1 christos cctx = SSL_CONF_CTX_new(); 39 1.1 christos SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_SERVER); 40 1.1 christos SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CERTIFICATE); 41 1.1 christos SSL_CONF_CTX_set_ssl_ctx(cctx, ctx); 42 1.1 christos while (*args && **args == '-') { 43 1.1 christos int rv; 44 1.1 christos /* Parse standard arguments */ 45 1.1 christos rv = SSL_CONF_cmd_argv(cctx, &nargs, &args); 46 1.1 christos if (rv == -3) { 47 1.1 christos fprintf(stderr, "Missing argument for %s\n", *args); 48 1.1 christos goto err; 49 1.1 christos } 50 1.1 christos if (rv < 0) { 51 1.1 christos fprintf(stderr, "Error in command %s\n", *args); 52 1.1 christos ERR_print_errors_fp(stderr); 53 1.1 christos goto err; 54 1.1 christos } 55 1.1 christos /* If rv > 0 we processed something so proceed to next arg */ 56 1.1 christos if (rv > 0) 57 1.1 christos continue; 58 1.1 christos /* Otherwise application specific argument processing */ 59 1.1 christos if (strcmp(*args, "-port") == 0) { 60 1.1 christos port = args[1]; 61 1.1 christos if (port == NULL) { 62 1.1 christos fprintf(stderr, "Missing -port argument\n"); 63 1.1 christos goto err; 64 1.1 christos } 65 1.1 christos args += 2; 66 1.1 christos nargs -= 2; 67 1.1 christos continue; 68 1.1 christos } else { 69 1.1 christos fprintf(stderr, "Unknown argument %s\n", *args); 70 1.1 christos goto err; 71 1.1 christos } 72 1.1 christos } 73 1.1 christos 74 1.1 christos if (!SSL_CONF_CTX_finish(cctx)) { 75 1.1 christos fprintf(stderr, "Finish error\n"); 76 1.1 christos ERR_print_errors_fp(stderr); 77 1.1 christos goto err; 78 1.1 christos } 79 1.1 christos #ifdef ITERATE_CERTS 80 1.1 christos /* 81 1.1 christos * Demo of how to iterate over all certificates in an SSL_CTX structure. 82 1.1 christos */ 83 1.1 christos { 84 1.1 christos X509 *x; 85 1.1 christos int rv; 86 1.1 christos rv = SSL_CTX_set_current_cert(ctx, SSL_CERT_SET_FIRST); 87 1.1 christos while (rv) { 88 1.1 christos X509 *x = SSL_CTX_get0_certificate(ctx); 89 1.1 christos X509_NAME_print_ex_fp(stdout, X509_get_subject_name(x), 0, 90 1.1.1.2 christos XN_FLAG_ONELINE); 91 1.1 christos printf("\n"); 92 1.1 christos rv = SSL_CTX_set_current_cert(ctx, SSL_CERT_SET_NEXT); 93 1.1 christos } 94 1.1 christos fflush(stdout); 95 1.1 christos } 96 1.1 christos #endif 97 1.1 christos /* Setup server side SSL bio */ 98 1.1 christos ssl_bio = BIO_new_ssl(ctx, 0); 99 1.1 christos 100 1.1 christos if ((in = BIO_new_accept(port)) == NULL) 101 1.1 christos goto err; 102 1.1 christos 103 1.1 christos /* 104 1.1 christos * This means that when a new connection is accepted on 'in', The ssl_bio 105 1.1 christos * will be 'duplicated' and have the new socket BIO push into it. 106 1.1 christos * Basically it means the SSL BIO will be automatically setup 107 1.1 christos */ 108 1.1 christos BIO_set_accept_bios(in, ssl_bio); 109 1.1.1.2 christos ssl_bio = NULL; 110 1.1 christos 111 1.1.1.2 christos again: 112 1.1 christos /* 113 1.1 christos * The first call will setup the accept socket, and the second will get a 114 1.1 christos * socket. In this loop, the first actual accept will occur in the 115 1.1 christos * BIO_read() function. 116 1.1 christos */ 117 1.1 christos 118 1.1 christos if (BIO_do_accept(in) <= 0) 119 1.1 christos goto err; 120 1.1 christos 121 1.1 christos for (;;) { 122 1.1 christos i = BIO_read(in, buf, 512); 123 1.1 christos if (i == 0) { 124 1.1 christos /* 125 1.1 christos * If we have finished, remove the underlying BIO stack so the 126 1.1 christos * next time we call any function for this BIO, it will attempt 127 1.1 christos * to do an accept 128 1.1 christos */ 129 1.1 christos printf("Done\n"); 130 1.1 christos tmp = BIO_pop(in); 131 1.1 christos BIO_free_all(tmp); 132 1.1 christos goto again; 133 1.1 christos } 134 1.1 christos if (i < 0) 135 1.1 christos goto err; 136 1.1 christos fwrite(buf, 1, i, stdout); 137 1.1 christos fflush(stdout); 138 1.1 christos } 139 1.1 christos 140 1.1 christos ret = EXIT_SUCCESS; 141 1.1.1.2 christos err: 142 1.1 christos if (ret != EXIT_SUCCESS) 143 1.1 christos ERR_print_errors_fp(stderr); 144 1.1 christos BIO_free(in); 145 1.1.1.2 christos BIO_free_all(ssl_bio); 146 1.1 christos return ret; 147 1.1 christos } 148