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