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