server-conf.c 3.0 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
/* NOCW */
/* demos/bio/saccept.c */

/* A minimal program to server an SSL connection.
 * It uses blocking.
 * saccept host:port
 * host is the interface IP to use.  If any interface, use *:port
 * The default it *:4433
 *
 * cc -I../../include saccept.c -L../.. -lssl -lcrypto
 */

#include <stdio.h>
#include <signal.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
#include <openssl/conf.h>

int main(int argc, char *argv[])
	{
	char *port = "*:4433";
	BIO *in=NULL;
	BIO *ssl_bio,*tmp;
	SSL_CTX *ctx;
	SSL_CONF_CTX *cctx = NULL;
	CONF *conf = NULL;
	STACK_OF(CONF_VALUE) *sect = NULL;
	CONF_VALUE *cnf;
	long errline = -1;
	char buf[512];
	int ret=1,i;

	SSL_load_error_strings();

	/* Add ciphers and message digests */
	OpenSSL_add_ssl_algorithms();

	conf = NCONF_new(NULL);

	if (NCONF_load(conf, "accept.cnf", &errline) <= 0)
		{
		if (errline <= 0)
			fprintf(stderr, "Error processing config file\n");
		else
			fprintf(stderr, "Error on line %ld\n", errline);
		goto err;
		}

	sect = NCONF_get_section(conf, "default");

	if (sect == NULL)
		{
		fprintf(stderr, "Error retrieving default section\n");
		goto err;
		}

	ctx=SSL_CTX_new(SSLv23_server_method());
	cctx = SSL_CONF_CTX_new();
	SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_SERVER);
	SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CERTIFICATE);
	SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_FILE);
	SSL_CONF_CTX_set_ssl_ctx(cctx, ctx);
	for (i = 0; i < sk_CONF_VALUE_num(sect); i++)
		{
		int rv;
		cnf = sk_CONF_VALUE_value(sect, i);
		rv = SSL_CONF_cmd(cctx, cnf->name, cnf->value);
		if (rv > 0)
			continue;
		if (rv != -2)
			{
			fprintf(stderr, "Error processing %s = %s\n",
						cnf->name, cnf->value);
			ERR_print_errors_fp(stderr);
			goto err;
			}
		if (!strcmp(cnf->name, "Port"))
			{
			port = cnf->value;
			}
		else
			{
			fprintf(stderr, "Unknown configuration option %s\n",
							cnf->name);
			goto err;
			}
		}

	if (!SSL_CONF_CTX_finish(cctx))
		{
		fprintf(stderr, "Finish error\n");
		ERR_print_errors_fp(stderr);
		goto err;
		}

	/* Setup server side SSL bio */
	ssl_bio=BIO_new_ssl(ctx,0);

	if ((in=BIO_new_accept(port)) == NULL) goto err;

	/* This means that when a new connection is acceptede on 'in',
	 * The ssl_bio will be 'dupilcated' and have the new socket
	 * BIO push into it.  Basically it means the SSL BIO will be
	 * automatically setup */
	BIO_set_accept_bios(in,ssl_bio);

again:
	/* The first call will setup the accept socket, and the second
	 * will get a socket.  In this loop, the first actual accept
	 * will occur in the BIO_read() function. */

	if (BIO_do_accept(in) <= 0) goto err;

	for (;;)
		{
		i=BIO_read(in,buf,512);
		if (i == 0)
			{
			/* If we have finished, remove the underlying
			 * BIO stack so the next time we call any function
			 * for this BIO, it will attempt to do an
			 * accept */
			printf("Done\n");
			tmp=BIO_pop(in);
			BIO_free_all(tmp);
			goto again;
			}
		if (i < 0) goto err;
		fwrite(buf,1,i,stdout);
		fflush(stdout);
		}

	ret=0;
err:
	if (ret)
		{
		ERR_print_errors_fp(stderr);
		}
	if (in != NULL) BIO_free(in);
	exit(ret);
	return(!ret);
	}