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