1/* NOCW */
2/* demos/bio/saccept-conf.c */
3
4/*
5 * A minimal program to serve an SSL connection. It uses blocking. It uses
6 * the SSL_CONF API with a configuration file. cc -I../../include saccept.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#include <openssl/conf.h>
15
16int main(int argc, char *argv[])
17{
18    char *port = "*:4433";
19    BIO *in = NULL;
20    BIO *ssl_bio, *tmp;
21    SSL_CTX *ctx;
22    SSL_CONF_CTX *cctx = NULL;
23    CONF *conf = NULL;
24    STACK_OF(CONF_VALUE) *sect = NULL;
25    CONF_VALUE *cnf;
26    long errline = -1;
27    char buf[512];
28    int ret = 1, i;
29
30    SSL_load_error_strings();
31
32    /* Add ciphers and message digests */
33    OpenSSL_add_ssl_algorithms();
34
35    conf = NCONF_new(NULL);
36
37    if (NCONF_load(conf, "accept.cnf", &errline) <= 0) {
38        if (errline <= 0)
39            fprintf(stderr, "Error processing config file\n");
40        else
41            fprintf(stderr, "Error on line %ld\n", errline);
42        goto err;
43    }
44
45    sect = NCONF_get_section(conf, "default");
46
47    if (sect == NULL) {
48        fprintf(stderr, "Error retrieving default section\n");
49        goto err;
50    }
51
52    ctx = SSL_CTX_new(SSLv23_server_method());
53    cctx = SSL_CONF_CTX_new();
54    SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_SERVER);
55    SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CERTIFICATE);
56    SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_FILE);
57    SSL_CONF_CTX_set_ssl_ctx(cctx, ctx);
58    for (i = 0; i < sk_CONF_VALUE_num(sect); i++) {
59        int rv;
60        cnf = sk_CONF_VALUE_value(sect, i);
61        rv = SSL_CONF_cmd(cctx, cnf->name, cnf->value);
62        if (rv > 0)
63            continue;
64        if (rv != -2) {
65            fprintf(stderr, "Error processing %s = %s\n",
66                    cnf->name, cnf->value);
67            ERR_print_errors_fp(stderr);
68            goto err;
69        }
70        if (!strcmp(cnf->name, "Port")) {
71            port = cnf->value;
72        } else {
73            fprintf(stderr, "Unknown configuration option %s\n", cnf->name);
74            goto err;
75        }
76    }
77
78    if (!SSL_CONF_CTX_finish(cctx)) {
79        fprintf(stderr, "Finish error\n");
80        ERR_print_errors_fp(stderr);
81        goto err;
82    }
83
84    /* Setup server side SSL bio */
85    ssl_bio = BIO_new_ssl(ctx, 0);
86
87    if ((in = BIO_new_accept(port)) == NULL)
88        goto err;
89
90    /*
91     * This means that when a new connection is accepted on 'in', The ssl_bio
92     * will be 'duplicated' and have the new socket BIO push into it.
93     * Basically it means the SSL BIO will be automatically setup
94     */
95    BIO_set_accept_bios(in, ssl_bio);
96
97 again:
98    /*
99     * The first call will setup the accept socket, and the second will get a
100     * socket.  In this loop, the first actual accept will occur in the
101     * BIO_read() function.
102     */
103
104    if (BIO_do_accept(in) <= 0)
105        goto err;
106
107    for (;;) {
108        i = BIO_read(in, buf, 512);
109        if (i == 0) {
110            /*
111             * If we have finished, remove the underlying BIO stack so the
112             * next time we call any function for this BIO, it will attempt
113             * to do an accept
114             */
115            printf("Done\n");
116            tmp = BIO_pop(in);
117            BIO_free_all(tmp);
118            goto again;
119        }
120        if (i < 0) {
121            if (BIO_should_retry(in))
122                continue;
123            goto err;
124        }
125        fwrite(buf, 1, i, stdout);
126        fflush(stdout);
127    }
128
129    ret = 0;
130 err:
131    if (ret) {
132        ERR_print_errors_fp(stderr);
133    }
134    if (in != NULL)
135        BIO_free(in);
136    exit(ret);
137    return (!ret);
138}
139