1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 1998-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. 12e1051a39Sopenharmony_ci * It uses blocking. 13e1051a39Sopenharmony_ci * saccept host:port 14e1051a39Sopenharmony_ci * host is the interface IP to use. If any interface, use *:port 15e1051a39Sopenharmony_ci * The default it *:4433 16e1051a39Sopenharmony_ci * 17e1051a39Sopenharmony_ci * cc -I../../include saccept.c -L../.. -lssl -lcrypto -ldl 18e1051a39Sopenharmony_ci */ 19e1051a39Sopenharmony_ci 20e1051a39Sopenharmony_ci#include <stdio.h> 21e1051a39Sopenharmony_ci#include <signal.h> 22e1051a39Sopenharmony_ci#include <stdlib.h> 23e1051a39Sopenharmony_ci#include <openssl/err.h> 24e1051a39Sopenharmony_ci#include <openssl/ssl.h> 25e1051a39Sopenharmony_ci 26e1051a39Sopenharmony_ci#define CERT_FILE "server.pem" 27e1051a39Sopenharmony_ci 28e1051a39Sopenharmony_cistatic volatile int done = 0; 29e1051a39Sopenharmony_ci 30e1051a39Sopenharmony_civoid interrupt(int sig) 31e1051a39Sopenharmony_ci{ 32e1051a39Sopenharmony_ci done = 1; 33e1051a39Sopenharmony_ci} 34e1051a39Sopenharmony_ci 35e1051a39Sopenharmony_civoid sigsetup(void) 36e1051a39Sopenharmony_ci{ 37e1051a39Sopenharmony_ci struct sigaction sa; 38e1051a39Sopenharmony_ci 39e1051a39Sopenharmony_ci /* 40e1051a39Sopenharmony_ci * Catch at most once, and don't restart the accept system call. 41e1051a39Sopenharmony_ci */ 42e1051a39Sopenharmony_ci sa.sa_flags = SA_RESETHAND; 43e1051a39Sopenharmony_ci sa.sa_handler = interrupt; 44e1051a39Sopenharmony_ci sigemptyset(&sa.sa_mask); 45e1051a39Sopenharmony_ci sigaction(SIGINT, &sa, NULL); 46e1051a39Sopenharmony_ci} 47e1051a39Sopenharmony_ci 48e1051a39Sopenharmony_ciint main(int argc, char *argv[]) 49e1051a39Sopenharmony_ci{ 50e1051a39Sopenharmony_ci char *port = NULL; 51e1051a39Sopenharmony_ci BIO *in = NULL; 52e1051a39Sopenharmony_ci BIO *ssl_bio, *tmp; 53e1051a39Sopenharmony_ci SSL_CTX *ctx; 54e1051a39Sopenharmony_ci char buf[512]; 55e1051a39Sopenharmony_ci int ret = EXIT_FAILURE, i; 56e1051a39Sopenharmony_ci 57e1051a39Sopenharmony_ci if (argc <= 1) 58e1051a39Sopenharmony_ci port = "*:4433"; 59e1051a39Sopenharmony_ci else 60e1051a39Sopenharmony_ci port = argv[1]; 61e1051a39Sopenharmony_ci 62e1051a39Sopenharmony_ci ctx = SSL_CTX_new(TLS_server_method()); 63e1051a39Sopenharmony_ci if (!SSL_CTX_use_certificate_chain_file(ctx, CERT_FILE)) 64e1051a39Sopenharmony_ci goto err; 65e1051a39Sopenharmony_ci if (!SSL_CTX_use_PrivateKey_file(ctx, CERT_FILE, SSL_FILETYPE_PEM)) 66e1051a39Sopenharmony_ci goto err; 67e1051a39Sopenharmony_ci if (!SSL_CTX_check_private_key(ctx)) 68e1051a39Sopenharmony_ci goto err; 69e1051a39Sopenharmony_ci 70e1051a39Sopenharmony_ci /* Setup server side SSL bio */ 71e1051a39Sopenharmony_ci ssl_bio = BIO_new_ssl(ctx, 0); 72e1051a39Sopenharmony_ci 73e1051a39Sopenharmony_ci if ((in = BIO_new_accept(port)) == NULL) 74e1051a39Sopenharmony_ci goto err; 75e1051a39Sopenharmony_ci 76e1051a39Sopenharmony_ci /* 77e1051a39Sopenharmony_ci * This means that when a new connection is accepted on 'in', The ssl_bio 78e1051a39Sopenharmony_ci * will be 'duplicated' and have the new socket BIO push into it. 79e1051a39Sopenharmony_ci * Basically it means the SSL BIO will be automatically setup 80e1051a39Sopenharmony_ci */ 81e1051a39Sopenharmony_ci BIO_set_accept_bios(in, ssl_bio); 82e1051a39Sopenharmony_ci 83e1051a39Sopenharmony_ci /* Arrange to leave server loop on interrupt */ 84e1051a39Sopenharmony_ci sigsetup(); 85e1051a39Sopenharmony_ci 86e1051a39Sopenharmony_ci again: 87e1051a39Sopenharmony_ci /* 88e1051a39Sopenharmony_ci * The first call will setup the accept socket, and the second will get a 89e1051a39Sopenharmony_ci * socket. In this loop, the first actual accept will occur in the 90e1051a39Sopenharmony_ci * BIO_read() function. 91e1051a39Sopenharmony_ci */ 92e1051a39Sopenharmony_ci 93e1051a39Sopenharmony_ci if (BIO_do_accept(in) <= 0) 94e1051a39Sopenharmony_ci goto err; 95e1051a39Sopenharmony_ci 96e1051a39Sopenharmony_ci while (!done) { 97e1051a39Sopenharmony_ci i = BIO_read(in, buf, 512); 98e1051a39Sopenharmony_ci if (i == 0) { 99e1051a39Sopenharmony_ci /* 100e1051a39Sopenharmony_ci * If we have finished, remove the underlying BIO stack so the 101e1051a39Sopenharmony_ci * next time we call any function for this BIO, it will attempt 102e1051a39Sopenharmony_ci * to do an accept 103e1051a39Sopenharmony_ci */ 104e1051a39Sopenharmony_ci printf("Done\n"); 105e1051a39Sopenharmony_ci tmp = BIO_pop(in); 106e1051a39Sopenharmony_ci BIO_free_all(tmp); 107e1051a39Sopenharmony_ci goto again; 108e1051a39Sopenharmony_ci } 109e1051a39Sopenharmony_ci if (i < 0) 110e1051a39Sopenharmony_ci goto err; 111e1051a39Sopenharmony_ci fwrite(buf, 1, i, stdout); 112e1051a39Sopenharmony_ci fflush(stdout); 113e1051a39Sopenharmony_ci } 114e1051a39Sopenharmony_ci 115e1051a39Sopenharmony_ci ret = EXIT_SUCCESS; 116e1051a39Sopenharmony_ci err: 117e1051a39Sopenharmony_ci if (ret != EXIT_SUCCESS) 118e1051a39Sopenharmony_ci ERR_print_errors_fp(stderr); 119e1051a39Sopenharmony_ci BIO_free(in); 120e1051a39Sopenharmony_ci return ret; 121e1051a39Sopenharmony_ci} 122