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