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