1 /*
2 * Copyright (C) 2004-2012 Free Software Foundation, Inc.
3 * Copyright (C) 2001,2002 Paul Sheer
4 * Copyright (C) 2016-2018 Red Hat, Inc.
5 * Portions Copyright (C) 2002,2003 Nikos Mavrogiannopoulos
6 *
7 * This file is part of GnuTLS.
8 *
9 * GnuTLS is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * GnuTLS is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 */
22
23 /* This server is heavily modified for GnuTLS by Nikos Mavrogiannopoulos
24 * (which means it is quite unreadable)
25 */
26
27 #include <config.h>
28
29 #include "common.h"
30 #include "serv-args.h"
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <errno.h>
34 #include <sys/types.h>
35 #include <string.h>
36 #include <gnutls/gnutls.h>
37 #include <gnutls/dtls.h>
38 #include <sys/time.h>
39 #include <sys/select.h>
40 #include <fcntl.h>
41 #include <list.h>
42 #include <netdb.h>
43 #include <unistd.h>
44 #include <socket.h>
45
46 /* Gnulib portability files. */
47 #include "read-file.h"
48 #include "minmax.h"
49 #include "sockets.h"
50 #include "udp-serv.h"
51
52 /* konqueror cannot handle sending the page in multiple
53 * pieces.
54 */
55 /* global stuff */
56 static int generate = 0;
57 static int http = 0;
58 static int x509ctype;
59 static int debug = 0;
60
61 unsigned int verbose = 1;
62 static int nodb;
63 static int noticket;
64 static int earlydata;
65 int require_cert;
66 int disable_client_cert;
67
68 const char *psk_passwd = NULL;
69 const char *srp_passwd = NULL;
70 const char *srp_passwd_conf = NULL;
71 const char **x509_keyfile = NULL;
72 const char **x509_certfile = NULL;
73 unsigned x509_certfile_size = 0;
74 unsigned x509_keyfile_size = 0;
75 const char *x509_cafile = NULL;
76 const char *dh_params_file = NULL;
77 const char *x509_crlfile = NULL;
78 const char *priorities = NULL;
79 const char **rawpk_keyfile = NULL;
80 const char **rawpk_file = NULL;
81 unsigned rawpk_keyfile_size = 0;
82 unsigned rawpk_file_size = 0;
83
84 const char **ocsp_responses = NULL;
85 unsigned ocsp_responses_size = 0;
86
87 const char *sni_hostname = NULL;
88 int sni_hostname_fatal = 0;
89
90 const char **alpn_protos = NULL;
91 unsigned alpn_protos_size = 0;
92
93 gnutls_datum_t session_ticket_key;
94 gnutls_anti_replay_t anti_replay;
95 int record_max_size;
96 const char *http_data_file = NULL;
97 static void tcp_server(const char *name, int port);
98
99 /* end of globals */
100
101 /* This is a sample TCP echo server.
102 * This will behave as an http server if any argument in the
103 * command line is present
104 */
105
106 #define SMALL_READ_TEST (2147483647)
107
108 #define GERR(ret) fprintf(stderr, "Error: %s\n", safe_strerror(ret))
109
110 #define HTTP_END "</BODY></HTML>\n\n"
111
112 #define HTTP_UNIMPLEMENTED "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n<HTML><HEAD>\r\n<TITLE>501 Method Not Implemented</TITLE>\r\n</HEAD><BODY>\r\n<H1>Method Not Implemented</H1>\r\n<HR>\r\n</BODY></HTML>\r\n"
113 #define HTTP_OK "HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n"
114
115 #define HTTP_BEGIN HTTP_OK \
116 "\n" \
117 "<HTML><BODY>\n" \
118 "<CENTER><H1>This is <a href=\"http://www.gnu.org/software/gnutls\">" \
119 "GnuTLS</a></H1></CENTER>\n\n"
120
121 /* These are global */
122 gnutls_srp_server_credentials_t srp_cred = NULL;
123 gnutls_psk_server_credentials_t psk_cred = NULL;
124 #ifdef ENABLE_ANON
125 gnutls_anon_server_credentials_t dh_cred = NULL;
126 #endif
127 gnutls_certificate_credentials_t cert_cred = NULL;
128
129 const int ssl_session_cache = 2048;
130
131 static void wrap_db_init(void);
132 static void wrap_db_deinit(void);
133 static int wrap_db_store(void *dbf, gnutls_datum_t key,
134 gnutls_datum_t data);
135 static gnutls_datum_t wrap_db_fetch(void *dbf, gnutls_datum_t key);
136 static int wrap_db_delete(void *dbf, gnutls_datum_t key);
137 static int anti_replay_db_add(void *dbf, time_t exp, const gnutls_datum_t *key,
138 const gnutls_datum_t *data);
139
140 static void cmd_parser(int argc, char **argv);
141
142
143 #define HTTP_STATE_REQUEST 1
144 #define HTTP_STATE_RESPONSE 2
145 #define HTTP_STATE_CLOSING 3
146
147 LIST_TYPE_DECLARE(listener_item, char *http_request; char *http_response;
148 int request_length; int response_length;
149 int response_written; int http_state;
150 int listen_socket; int fd;
151 gnutls_session_t tls_session;
152 int handshake_ok;
153 int close_ok;
154 time_t start;
155 int earlydata_eof;
156 );
157
safe_strerror(int value)158 static const char *safe_strerror(int value)
159 {
160 const char *ret = gnutls_strerror(value);
161 if (ret == NULL)
162 ret = str_unknown;
163 return ret;
164 }
165
listener_free(listener_item * j)166 static void listener_free(listener_item * j)
167 {
168
169 free(j->http_request);
170 free(j->http_response);
171 if (j->fd >= 0) {
172 if (j->close_ok)
173 gnutls_bye(j->tls_session, GNUTLS_SHUT_WR);
174 shutdown(j->fd, 2);
175 close(j->fd);
176 gnutls_deinit(j->tls_session);
177 }
178 }
179
180
181 /* we use primes up to 1024 in this server.
182 * otherwise we should add them here.
183 */
184
185 gnutls_dh_params_t dh_params = NULL;
186 gnutls_rsa_params_t rsa_params = NULL;
187
generate_dh_primes(void)188 static int generate_dh_primes(void)
189 {
190 int prime_bits =
191 gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH,
192 GNUTLS_SEC_PARAM_MEDIUM);
193
194 if (gnutls_dh_params_init(&dh_params) < 0) {
195 fprintf(stderr, "Error in dh parameter initialization\n");
196 exit(1);
197 }
198
199 /* Generate Diffie-Hellman parameters - for use with DHE
200 * kx algorithms. These should be discarded and regenerated
201 * once a week or once a month. Depends on the
202 * security requirements.
203 */
204 printf
205 ("Generating Diffie-Hellman parameters [%d]. Please wait...\n",
206 prime_bits);
207 fflush(stdout);
208
209 if (gnutls_dh_params_generate2(dh_params, prime_bits) < 0) {
210 fprintf(stderr, "Error in prime generation\n");
211 exit(1);
212 }
213
214 return 0;
215 }
216
read_dh_params(void)217 static void read_dh_params(void)
218 {
219 char tmpdata[2048];
220 int size;
221 gnutls_datum_t params;
222 FILE *fp;
223
224 if (gnutls_dh_params_init(&dh_params) < 0) {
225 fprintf(stderr, "Error in dh parameter initialization\n");
226 exit(1);
227 }
228
229 /* read the params file
230 */
231 fp = fopen(dh_params_file, "r");
232 if (fp == NULL) {
233 fprintf(stderr, "Could not open %s\n", dh_params_file);
234 exit(1);
235 }
236
237 size = fread(tmpdata, 1, sizeof(tmpdata) - 1, fp);
238 tmpdata[size] = 0;
239 fclose(fp);
240
241 params.data = (unsigned char *) tmpdata;
242 params.size = size;
243
244 size =
245 gnutls_dh_params_import_pkcs3(dh_params, ¶ms,
246 GNUTLS_X509_FMT_PEM);
247
248 if (size < 0) {
249 fprintf(stderr, "Error parsing dh params: %s\n",
250 safe_strerror(size));
251 exit(1);
252 }
253
254 printf("Read Diffie-Hellman parameters.\n");
255 fflush(stdout);
256
257 }
258
259 static int
get_params(gnutls_session_t session,gnutls_params_type_t type,gnutls_params_st * st)260 get_params(gnutls_session_t session, gnutls_params_type_t type,
261 gnutls_params_st * st)
262 {
263
264 if (type == GNUTLS_PARAMS_DH) {
265 if (dh_params == NULL)
266 return -1;
267 st->params.dh = dh_params;
268 } else
269 return -1;
270
271 st->type = type;
272 st->deinit = 0;
273
274 return 0;
275 }
276
277 LIST_DECLARE_INIT(listener_list, listener_item, listener_free);
278
cert_verify_callback(gnutls_session_t session)279 static int cert_verify_callback(gnutls_session_t session)
280 {
281 listener_item * j = gnutls_session_get_ptr(session);
282 unsigned int size;
283 int ret;
284
285 if (gnutls_auth_get_type(session) == GNUTLS_CRD_CERTIFICATE) {
286 if (!require_cert && gnutls_certificate_get_peers(session, &size) == NULL)
287 return 0;
288
289 if (ENABLED_OPT(VERIFY_CLIENT_CERT)) {
290 if (cert_verify(session, NULL, NULL) == 0) {
291 do {
292 ret = gnutls_alert_send(session, GNUTLS_AL_FATAL, GNUTLS_A_ACCESS_DENIED);
293 } while(ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN);
294
295 j->http_state = HTTP_STATE_CLOSING;
296 return -1;
297 }
298 } else {
299 printf("- Peer's certificate was NOT verified.\n");
300 }
301 }
302 return 0;
303 }
304
305 /* callback used to verify if the host name advertised in client hello matches
306 * the one configured in server
307 */
308 static int
post_client_hello(gnutls_session_t session)309 post_client_hello(gnutls_session_t session)
310 {
311 int ret;
312 /* DNS names (only type supported) may be at most 256 byte long */
313 char *name;
314 size_t len = 256;
315 unsigned int type;
316 int i;
317
318 name = malloc(len);
319 if (name == NULL)
320 return GNUTLS_E_MEMORY_ERROR;
321
322 for (i=0; ; ) {
323 ret = gnutls_server_name_get(session, name, &len, &type, i);
324 if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER) {
325 char *new_name;
326 new_name = realloc(name, len);
327 if (new_name == NULL) {
328 ret = GNUTLS_E_MEMORY_ERROR;
329 goto end;
330 }
331 name = new_name;
332 continue; /* retry call with same index */
333 }
334
335 /* check if it is the last entry in list */
336 if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
337 break;
338 i++;
339 if (ret != GNUTLS_E_SUCCESS)
340 goto end;
341 /* unknown types need to be ignored */
342 if (type != GNUTLS_NAME_DNS)
343 continue;
344
345 if (strlen(sni_hostname) != len)
346 continue;
347 /* API guarantees that the name of type DNS will be null terminated */
348 if (!strncmp(name, sni_hostname, len)) {
349 ret = GNUTLS_E_SUCCESS;
350 goto end;
351 }
352 };
353 /* when there is no extension, we can't send the extension specific alert */
354 if (i == 0) {
355 fprintf(stderr, "Warning: client did not include SNI extension, using default host\n");
356 ret = GNUTLS_E_SUCCESS;
357 goto end;
358 }
359
360 if (sni_hostname_fatal == 1) {
361 /* abort the connection, propagate error up the stack */
362 ret = GNUTLS_E_UNRECOGNIZED_NAME;
363 goto end;
364 }
365
366 fprintf(stderr, "Warning: client provided unrecognized host name\n");
367 /* since we just want to send an alert, not abort the connection, we
368 * need to send it ourselves
369 */
370 do {
371 ret = gnutls_alert_send(session,
372 GNUTLS_AL_WARNING,
373 GNUTLS_A_UNRECOGNIZED_NAME);
374 } while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);
375
376 /* continue handshake, fall through */
377 end:
378 free(name);
379 return ret;
380 }
381
382 #define MAX_ALPN_PROTOCOLS 16
initialize_session(int dtls)383 gnutls_session_t initialize_session(int dtls)
384 {
385 gnutls_session_t session;
386 int ret;
387 unsigned i;
388 const char *err;
389 #ifdef ENABLE_ALPN
390 gnutls_datum_t alpn[MAX_ALPN_PROTOCOLS];
391 #endif
392 unsigned alpn_size;
393 unsigned flags = GNUTLS_SERVER | GNUTLS_POST_HANDSHAKE_AUTH | GNUTLS_ENABLE_RAWPK;
394
395 if (dtls)
396 flags |= GNUTLS_DATAGRAM;
397
398 if (earlydata)
399 flags |= GNUTLS_ENABLE_EARLY_DATA;
400
401 gnutls_init(&session, flags);
402
403 /* allow the use of private ciphersuites.
404 */
405 gnutls_handshake_set_private_extensions(session, 1);
406
407 gnutls_handshake_set_timeout(session,
408 GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
409
410 if (nodb == 0) {
411 gnutls_db_set_retrieve_function(session, wrap_db_fetch);
412 gnutls_db_set_remove_function(session, wrap_db_delete);
413 gnutls_db_set_store_function(session, wrap_db_store);
414 gnutls_db_set_ptr(session, NULL);
415 }
416
417 if (noticket == 0)
418 gnutls_session_ticket_enable_server(session,
419 &session_ticket_key);
420
421 if (earlydata) {
422 gnutls_anti_replay_enable(session, anti_replay);
423 if (HAVE_OPT(MAXEARLYDATA)) {
424 ret = gnutls_record_set_max_early_data_size(session, OPT_VALUE_MAXEARLYDATA);
425 if (ret < 0) {
426 fprintf(stderr, "Could not set max early data size: %s\n", gnutls_strerror(ret));
427 exit(1);
428 }
429 }
430 }
431
432 if (sni_hostname != NULL)
433 gnutls_handshake_set_post_client_hello_function(session,
434 &post_client_hello);
435
436 if (priorities == NULL) {
437 ret = gnutls_set_default_priority(session);
438 if (ret < 0) {
439 fprintf(stderr, "Could not set default policy: %s\n", gnutls_strerror(ret));
440 exit(1);
441 }
442 } else {
443 ret = gnutls_priority_set_direct(session, priorities, &err);
444 if (ret < 0) {
445 fprintf(stderr, "Syntax error at: %s\n", err);
446 exit(1);
447 }
448 }
449
450 #ifndef ENABLE_ALPN
451 if (alpn_protos_size != 0) {
452 fprintf(stderr, "ALPN is not supported\n");
453 exit(1);
454 }
455 #else
456 alpn_size = MIN(MAX_ALPN_PROTOCOLS,alpn_protos_size);
457 for (i=0;i<alpn_size;i++) {
458 alpn[i].data = (void*)alpn_protos[i];
459 alpn[i].size = strlen(alpn_protos[i]);
460 }
461
462 ret = gnutls_alpn_set_protocols(session, alpn, alpn_size, HAVE_OPT(ALPN_FATAL)?GNUTLS_ALPN_MANDATORY:0);
463 if (ret < 0) {
464 fprintf(stderr, "Error setting ALPN protocols: %s\n", gnutls_strerror(ret));
465 exit(1);
466 }
467 #endif
468
469 #ifdef ENABLE_ANON
470 gnutls_credentials_set(session, GNUTLS_CRD_ANON, dh_cred);
471 #endif
472
473 if (srp_cred != NULL)
474 gnutls_credentials_set(session, GNUTLS_CRD_SRP, srp_cred);
475
476 if (psk_cred != NULL)
477 gnutls_credentials_set(session, GNUTLS_CRD_PSK, psk_cred);
478
479 if (cert_cred != NULL) {
480 gnutls_certificate_set_verify_function(cert_cred,
481 cert_verify_callback);
482
483 gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
484 cert_cred);
485 }
486
487 if (disable_client_cert)
488 gnutls_certificate_server_set_request(session,
489 GNUTLS_CERT_IGNORE);
490 else {
491 if (require_cert)
492 gnutls_certificate_server_set_request(session,
493 GNUTLS_CERT_REQUIRE);
494 else
495 gnutls_certificate_server_set_request(session,
496 GNUTLS_CERT_REQUEST);
497 }
498
499 /* use the record size limit extension */
500 if (record_max_size > 0) {
501 if (gnutls_record_set_max_recv_size(session, record_max_size) <
502 0) {
503 fprintf(stderr,
504 "Cannot set the maximum record receive size to %d.\n",
505 record_max_size);
506 exit(1);
507 }
508 }
509
510 if (HAVE_OPT(HEARTBEAT))
511 gnutls_heartbeat_enable(session,
512 GNUTLS_HB_PEER_ALLOWED_TO_SEND);
513
514 #ifdef ENABLE_DTLS_SRTP
515 if (HAVE_OPT(SRTP_PROFILES)) {
516 ret =
517 gnutls_srtp_set_profile_direct(session,
518 OPT_ARG(SRTP_PROFILES),
519 &err);
520 if (ret == GNUTLS_E_INVALID_REQUEST)
521 fprintf(stderr, "Syntax error at: %s\n", err);
522 else if (ret != 0)
523 fprintf(stderr, "Error in profiles: %s\n",
524 gnutls_strerror(ret));
525 else fprintf(stderr,"DTLS profile set to %s\n",
526 OPT_ARG(SRTP_PROFILES));
527
528 if (ret != 0) exit(1);
529 }
530 #endif
531
532
533 return session;
534 }
535
536 #include <gnutls/x509.h>
537
538 static const char DEFAULT_DATA[] =
539 "This is the default message reported by the GnuTLS implementation. "
540 "For more information please visit "
541 "<a href=\"https://www.gnutls.org/\">https://www.gnutls.org/</a>.";
542
543 /* Creates html with the current session information.
544 */
545 #define tmp_buffer &http_buffer[strlen(http_buffer)]
546 #define tmp_buffer_size len-strlen(http_buffer)
peer_print_info(gnutls_session_t session,int * ret_length,const char * header)547 static char *peer_print_info(gnutls_session_t session, int *ret_length,
548 const char *header)
549 {
550 const char *tmp;
551 unsigned char sesid[32];
552 size_t i, sesid_size;
553 char *http_buffer, *desc;
554 gnutls_kx_algorithm_t kx_alg;
555 size_t len = 20 * 1024 + strlen(header);
556 char *crtinfo = NULL, *crtinfo_old = NULL;
557 gnutls_protocol_t version;
558 size_t ncrtinfo = 0;
559
560 if (verbose == 0) {
561 http_buffer = malloc(len);
562 if (http_buffer == NULL)
563 return NULL;
564
565 strcpy(http_buffer, HTTP_BEGIN);
566 strcpy(&http_buffer[sizeof(HTTP_BEGIN) - 1], DEFAULT_DATA);
567 strcpy(&http_buffer
568 [sizeof(HTTP_BEGIN) + sizeof(DEFAULT_DATA) - 2],
569 HTTP_END);
570 *ret_length =
571 sizeof(DEFAULT_DATA) + sizeof(HTTP_BEGIN) +
572 sizeof(HTTP_END) - 3;
573 return http_buffer;
574 }
575
576 if (gnutls_certificate_type_get2(session, GNUTLS_CTYPE_CLIENT) == GNUTLS_CRT_X509) {
577 const gnutls_datum_t *cert_list;
578 unsigned int cert_list_size = 0;
579
580 cert_list =
581 gnutls_certificate_get_peers(session, &cert_list_size);
582
583 for (i = 0; i < cert_list_size; i++) {
584 gnutls_x509_crt_t cert = NULL;
585 gnutls_datum_t info;
586
587 if (gnutls_x509_crt_init(&cert) == 0 &&
588 gnutls_x509_crt_import(cert, &cert_list[i],
589 GNUTLS_X509_FMT_DER) ==
590 0
591 && gnutls_x509_crt_print(cert,
592 GNUTLS_CRT_PRINT_FULL,
593 &info) == 0) {
594 const char *post = "</PRE><P><PRE>";
595
596 crtinfo_old = crtinfo;
597 crtinfo =
598 realloc(crtinfo,
599 ncrtinfo + info.size +
600 strlen(post) + 1);
601 if (crtinfo == NULL) {
602 free(crtinfo_old);
603 return NULL;
604 }
605 memcpy(crtinfo + ncrtinfo, info.data,
606 info.size);
607 ncrtinfo += info.size;
608 memcpy(crtinfo + ncrtinfo, post,
609 strlen(post));
610 ncrtinfo += strlen(post);
611 crtinfo[ncrtinfo] = '\0';
612 gnutls_free(info.data);
613 }
614 gnutls_x509_crt_deinit(cert);
615 }
616 }
617
618 http_buffer = malloc(len);
619 if (http_buffer == NULL) {
620 free(crtinfo);
621 return NULL;
622 }
623
624 strcpy(http_buffer, HTTP_BEGIN);
625
626 version = gnutls_protocol_get_version(session);
627
628 /* print session_id */
629 sesid_size = sizeof(sesid);
630 gnutls_session_get_id(session, sesid, &sesid_size);
631 snprintf(tmp_buffer, tmp_buffer_size, "\n<p>Session ID: <i>");
632 for (i = 0; i < sesid_size; i++)
633 snprintf(tmp_buffer, tmp_buffer_size, "%.2X", sesid[i]);
634 snprintf(tmp_buffer, tmp_buffer_size, "</i></p>\n");
635 snprintf(tmp_buffer, tmp_buffer_size,
636 "<h5>If your browser supports session resumption, then you should see the "
637 "same session ID, when you press the <b>reload</b> button.</h5>\n");
638
639 /* Here unlike print_info() we use the kx algorithm to distinguish
640 * the functions to call.
641 */
642 {
643 char dns[256];
644 size_t dns_size = sizeof(dns);
645 unsigned int type;
646
647 if (gnutls_server_name_get
648 (session, dns, &dns_size, &type, 0) == 0) {
649 snprintf(tmp_buffer, tmp_buffer_size,
650 "\n<p>Server Name: %s</p>\n", dns);
651 }
652
653 }
654
655 kx_alg = gnutls_kx_get(session);
656
657 /* print srp specific data */
658 #ifdef ENABLE_SRP
659 if (kx_alg == GNUTLS_KX_SRP) {
660 snprintf(tmp_buffer, tmp_buffer_size,
661 "<p>Connected as user '%s'.</p>\n",
662 gnutls_srp_server_get_username(session));
663 }
664 #endif
665
666 #ifdef ENABLE_PSK
667 if (kx_alg == GNUTLS_KX_PSK && gnutls_psk_server_get_username(session)) {
668 snprintf(tmp_buffer, tmp_buffer_size,
669 "<p>Connected as user '%s'.</p>\n",
670 gnutls_psk_server_get_username(session));
671 }
672 #endif
673
674
675 /* print session information */
676 strcat(http_buffer, "<P>\n");
677
678 tmp =
679 gnutls_protocol_get_name(version);
680 if (tmp == NULL)
681 tmp = str_unknown;
682 snprintf(tmp_buffer, tmp_buffer_size,
683 "<TABLE border=1><TR><TD>Protocol version:</TD><TD>%s</TD></TR>\n",
684 tmp);
685
686 desc = gnutls_session_get_desc(session);
687 if (desc) {
688 snprintf(tmp_buffer, tmp_buffer_size,
689 "<TR><TD>Description:</TD><TD>%s</TD></TR>\n",
690 desc);
691 gnutls_free(desc);
692 }
693
694 if (gnutls_auth_get_type(session) == GNUTLS_CRD_CERTIFICATE &&
695 gnutls_certificate_type_get2(session, GNUTLS_CTYPE_CLIENT) != GNUTLS_CRT_X509) {
696 tmp =
697 gnutls_certificate_type_get_name
698 (gnutls_certificate_type_get2(session, GNUTLS_CTYPE_CLIENT));
699 if (tmp == NULL)
700 tmp = str_unknown;
701 snprintf(tmp_buffer, tmp_buffer_size,
702 "<TR><TD>Certificate Type:</TD><TD>%s</TD></TR>\n",
703 tmp);
704 }
705
706 if (version < GNUTLS_TLS1_3) {
707 tmp = gnutls_kx_get_name(kx_alg);
708 if (tmp == NULL)
709 tmp = str_unknown;
710 snprintf(tmp_buffer, tmp_buffer_size,
711 "<TR><TD>Key Exchange:</TD><TD>%s</TD></TR>\n", tmp);
712
713 #ifdef ENABLE_ANON
714 if (kx_alg == GNUTLS_KX_ANON_DH) {
715 snprintf(tmp_buffer, tmp_buffer_size,
716 "<p> Connect using anonymous DH (prime of %d bits)</p>\n",
717 gnutls_dh_get_prime_bits(session));
718 }
719 #endif
720
721 #if defined(ENABLE_DHE) || defined(ENABLE_ANON)
722 if (kx_alg == GNUTLS_KX_DHE_RSA || kx_alg == GNUTLS_KX_DHE_DSS) {
723 snprintf(tmp_buffer, tmp_buffer_size,
724 "Ephemeral DH using prime of <b>%d</b> bits.<br>\n",
725 gnutls_dh_get_prime_bits(session));
726 }
727 #endif
728
729 tmp = gnutls_compression_get_name(gnutls_compression_get(session));
730 if (tmp == NULL)
731 tmp = str_unknown;
732 snprintf(tmp_buffer, tmp_buffer_size,
733 "<TR><TD>Compression</TD><TD>%s</TD></TR>\n", tmp);
734
735 tmp = gnutls_cipher_suite_get_name(kx_alg,
736 gnutls_cipher_get(session),
737 gnutls_mac_get(session));
738 if (tmp == NULL)
739 tmp = str_unknown;
740 snprintf(tmp_buffer, tmp_buffer_size,
741 "<TR><TD>Ciphersuite</TD><TD>%s</TD></TR>\n",
742 tmp);
743 }
744
745 tmp = gnutls_cipher_get_name(gnutls_cipher_get(session));
746 if (tmp == NULL)
747 tmp = str_unknown;
748 snprintf(tmp_buffer, tmp_buffer_size,
749 "<TR><TD>Cipher</TD><TD>%s</TD></TR>\n", tmp);
750
751 tmp = gnutls_mac_get_name(gnutls_mac_get(session));
752 if (tmp == NULL)
753 tmp = str_unknown;
754 snprintf(tmp_buffer, tmp_buffer_size,
755 "<TR><TD>MAC</TD><TD>%s</TD></TR>\n", tmp);
756
757 snprintf(tmp_buffer, tmp_buffer_size,
758 "</TABLE></P>\n");
759
760 if (crtinfo) {
761 snprintf(tmp_buffer, tmp_buffer_size,
762 "<hr><PRE>%s\n</PRE>\n", crtinfo);
763 free(crtinfo);
764 }
765
766 snprintf(tmp_buffer, tmp_buffer_size,
767 "<hr><P>Your HTTP header was:<PRE>%s</PRE></P>\n"
768 HTTP_END, header);
769
770 *ret_length = strlen(http_buffer);
771
772 return http_buffer;
773 }
774
peer_print_data(gnutls_session_t session,int * ret_length)775 static char *peer_print_data(gnutls_session_t session, int *ret_length)
776 {
777 gnutls_datum_t data;
778 char *http_buffer;
779 size_t len;
780 int ret;
781
782 ret = gnutls_load_file(http_data_file, &data);
783 if (ret < 0) {
784 ret = asprintf(&http_buffer,
785 "HTTP/1.0 404 Not Found\r\n"
786 "Content-type: text/html\r\n"
787 "\r\n"
788 "<HTML><HEAD><TITLE>404 Not Found</TITLE></HEAD>\n"
789 "<BODY><H1>Couldn't read %s</H1></BODY></HTML>\n\n",
790 http_data_file);
791 if (ret < 0)
792 return NULL;
793
794 *ret_length = strlen(http_buffer);
795 return http_buffer;
796 }
797
798 ret = asprintf(&http_buffer,
799 "HTTP/1.0 200 OK\r\n"
800 "Content-Type: application/octet-stream\r\n"
801 "Content-Length: %u\r\n"
802 "\r\n",
803 data.size);
804 if (ret < 0)
805 return NULL;
806 len = ret;
807 http_buffer = realloc(http_buffer, len + data.size);
808 memcpy(&http_buffer[len], data.data, data.size);
809 gnutls_free(data.data);
810 *ret_length = len + data.size;
811 return http_buffer;
812 }
813
human_addr(const struct sockaddr * sa,socklen_t salen,char * buf,size_t buflen)814 const char *human_addr(const struct sockaddr *sa, socklen_t salen,
815 char *buf, size_t buflen)
816 {
817 const char *save_buf = buf;
818 size_t l;
819
820 if (!buf || !buflen)
821 return "(error)";
822
823 *buf = 0;
824
825 switch (sa->sa_family) {
826 #if HAVE_IPV6
827 case AF_INET6:
828 snprintf(buf, buflen, "IPv6 ");
829 break;
830 #endif
831
832 case AF_INET:
833 snprintf(buf, buflen, "IPv4 ");
834 break;
835 }
836
837 l = 5;
838 buf += l;
839 buflen -= l;
840
841 if (getnameinfo(sa, salen, buf, buflen, NULL, 0, NI_NUMERICHOST) !=
842 0) {
843 return "(error)";
844 }
845
846 l = strlen(buf);
847 buf += l;
848 buflen -= l;
849
850 if (buflen < 8)
851 return save_buf;
852
853 strcat(buf, " port ");
854 buf += 6;
855 buflen -= 6;
856
857 if (getnameinfo(sa, salen, NULL, 0, buf, buflen, NI_NUMERICSERV) !=
858 0) {
859 snprintf(buf, buflen, "%s", " unknown");
860 }
861
862 return save_buf;
863 }
864
wait_for_connection(void)865 int wait_for_connection(void)
866 {
867 listener_item *j;
868 fd_set rd, wr;
869 int n, sock = -1;
870
871 FD_ZERO(&rd);
872 FD_ZERO(&wr);
873 n = 0;
874
875 lloopstart(listener_list, j) {
876 if (j->listen_socket) {
877 FD_SET(j->fd, &rd);
878 n = MAX(n, j->fd);
879 }
880 }
881 lloopend(listener_list, j);
882
883 /* waiting part */
884 n = select(n + 1, &rd, &wr, NULL, NULL);
885 if (n == -1 && errno == EINTR)
886 return -1;
887 if (n < 0) {
888 perror("select()");
889 exit(1);
890 }
891
892 /* find which one is ready */
893 lloopstart(listener_list, j) {
894 /* a new connection has arrived */
895 if (FD_ISSET(j->fd, &rd) && j->listen_socket) {
896 sock = j->fd;
897 break;
898 }
899 }
900 lloopend(listener_list, j);
901 return sock;
902 }
903
listen_socket(const char * name,int listen_port,int socktype)904 int listen_socket(const char *name, int listen_port, int socktype)
905 {
906 struct addrinfo hints, *res, *ptr;
907 char portname[6];
908 int s = -1;
909 int yes;
910 listener_item *j = NULL;
911
912 snprintf(portname, sizeof(portname), "%d", listen_port);
913 memset(&hints, 0, sizeof(hints));
914 hints.ai_socktype = socktype;
915 hints.ai_flags = AI_PASSIVE;
916
917 if ((s = getaddrinfo(NULL, portname, &hints, &res)) != 0) {
918 fprintf(stderr, "getaddrinfo() failed: %s\n",
919 gai_strerror(s));
920 return -1;
921 }
922
923 for (ptr = res; ptr != NULL; ptr = ptr->ai_next) {
924 int news;
925 #ifndef HAVE_IPV6
926 if (ptr->ai_family != AF_INET)
927 continue;
928 #endif
929
930 /* Print what we are doing. */
931 {
932 char topbuf[512];
933
934 fprintf(stderr, "%s listening on %s...",
935 name, human_addr(ptr->ai_addr,
936 ptr->ai_addrlen, topbuf,
937 sizeof(topbuf)));
938 }
939
940 if ((news = socket(ptr->ai_family, ptr->ai_socktype,
941 ptr->ai_protocol)) < 0) {
942 perror("socket() failed");
943 continue;
944 }
945 s = news; /* to not overwrite existing s from previous loops */
946 #if defined(HAVE_IPV6) && !defined(_WIN32)
947 if (ptr->ai_family == AF_INET6) {
948 yes = 1;
949 /* avoid listen on ipv6 addresses failing
950 * because already listening on ipv4 addresses: */
951 (void)setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
952 (const void *) &yes, sizeof(yes));
953 }
954 #endif
955
956 if (socktype == SOCK_STREAM) {
957 yes = 1;
958 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
959 (const void *) &yes,
960 sizeof(yes)) < 0) {
961 perror("setsockopt() failed");
962 close(s);
963 continue;
964 }
965 } else {
966 #if defined(IP_DONTFRAG)
967 yes = 1;
968 if (setsockopt(s, IPPROTO_IP, IP_DONTFRAG,
969 (const void *) &yes,
970 sizeof(yes)) < 0)
971 perror("setsockopt(IP_DF) failed");
972 #elif defined(IP_MTU_DISCOVER)
973 yes = IP_PMTUDISC_DO;
974 if (setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER,
975 (const void *) &yes,
976 sizeof(yes)) < 0)
977 perror("setsockopt(IP_DF) failed");
978 #endif
979 }
980
981 if (bind(s, ptr->ai_addr, ptr->ai_addrlen) < 0) {
982 perror("bind() failed");
983 close(s);
984 continue;
985 }
986
987 if (socktype == SOCK_STREAM) {
988 if (listen(s, 10) < 0) {
989 perror("listen() failed");
990 exit(1);
991 }
992 }
993
994 /* new list entry for the connection */
995 lappend(listener_list);
996 j = listener_list.tail;
997 j->listen_socket = 1;
998 j->fd = s;
999
1000 /* Complete earlier message. */
1001 fprintf(stderr, "done\n");
1002 }
1003
1004 fflush(stderr);
1005
1006 freeaddrinfo(res);
1007
1008 return s;
1009 }
1010
1011 /* strips \r\n from the end of the string
1012 */
strip(char * data)1013 static void strip(char *data)
1014 {
1015 int i;
1016 int len = strlen(data);
1017
1018 for (i = 0; i < len; i++) {
1019 if (data[i] == '\r' && data[i + 1] == '\n'
1020 && data[i + 2] == 0) {
1021 data[i] = '\n';
1022 data[i + 1] = 0;
1023 break;
1024 }
1025 }
1026 }
1027
1028 static unsigned
get_response(gnutls_session_t session,char * request,char ** response,int * response_length)1029 get_response(gnutls_session_t session, char *request,
1030 char **response, int *response_length)
1031 {
1032 char *p, *h;
1033
1034 if (http != 0) {
1035 if (strncmp(request, "GET ", 4))
1036 goto unimplemented;
1037
1038 if (!(h = strchr(request, '\n')))
1039 goto unimplemented;
1040
1041 *h++ = '\0';
1042 while (*h == '\r' || *h == '\n')
1043 h++;
1044
1045 if (!(p = strchr(request + 4, ' ')))
1046 goto unimplemented;
1047 *p = '\0';
1048 }
1049
1050 if (http != 0) {
1051 if (http_data_file == NULL)
1052 *response = peer_print_info(session, response_length, h);
1053 else
1054 *response = peer_print_data(session, response_length);
1055 } else {
1056 int ret;
1057 strip(request);
1058 fprintf(stderr, "received cmd: %s\n", request);
1059
1060 ret = check_command(session, request, disable_client_cert);
1061 if (ret > 0) {
1062 *response = strdup("Successfully executed command\n");
1063 if (*response == NULL) {
1064 fprintf(stderr, "Memory error\n");
1065 return 0;
1066 }
1067 *response_length = strlen(*response);
1068 return 1;
1069 } else if (ret == 0) {
1070 *response = strdup(request);
1071 if (*response == NULL) {
1072 fprintf(stderr, "Memory error\n");
1073 return 0;
1074 }
1075 *response_length = strlen(*response);
1076 } else {
1077 *response = NULL;
1078 do {
1079 ret = gnutls_alert_send_appropriate(session, ret);
1080 } while(ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);
1081 return 0;
1082 }
1083 }
1084
1085 return 1;
1086
1087 unimplemented:
1088 *response = strdup(HTTP_UNIMPLEMENTED);
1089 if (*response == NULL)
1090 return 0;
1091 *response_length = ((*response) ? strlen(*response) : 0);
1092 return 1;
1093 }
1094
1095 static void terminate(int sig) __attribute__ ((__noreturn__));
1096
terminate(int sig)1097 static void terminate(int sig)
1098 {
1099 fprintf(stderr, "Exiting via signal %d\n", sig);
1100 exit(1);
1101 }
1102
1103
check_alert(gnutls_session_t session,int ret)1104 static void check_alert(gnutls_session_t session, int ret)
1105 {
1106 if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED
1107 || ret == GNUTLS_E_FATAL_ALERT_RECEIVED) {
1108 int last_alert = gnutls_alert_get(session);
1109 if (last_alert == GNUTLS_A_NO_RENEGOTIATION &&
1110 ret == GNUTLS_E_WARNING_ALERT_RECEIVED)
1111 printf
1112 ("* Received NO_RENEGOTIATION alert. Client does not support renegotiation.\n");
1113 else
1114 printf("* Received alert '%d': %s.\n", last_alert,
1115 gnutls_alert_get_name(last_alert));
1116 }
1117 }
1118
tls_log_func(int level,const char * str)1119 static void tls_log_func(int level, const char *str)
1120 {
1121 fprintf(stderr, "|<%d>| %s", level, str);
1122 }
1123
tls_audit_log_func(gnutls_session_t session,const char * str)1124 static void tls_audit_log_func(gnutls_session_t session, const char *str)
1125 {
1126 fprintf(stderr, "|<%p>| %s", session, str);
1127 }
1128
main(int argc,char ** argv)1129 int main(int argc, char **argv)
1130 {
1131 int ret, mtu, port;
1132 char name[256];
1133 int cert_set = 0;
1134 unsigned use_static_dh_params = 0;
1135 unsigned i;
1136
1137 cmd_parser(argc, argv);
1138
1139 #ifndef _WIN32
1140 signal(SIGHUP, SIG_IGN);
1141 signal(SIGTERM, terminate);
1142 if (signal(SIGINT, terminate) == SIG_IGN)
1143 signal(SIGINT, SIG_IGN); /* e.g. background process */
1144 #endif
1145
1146 sockets_init();
1147
1148 if (nodb == 0)
1149 wrap_db_init();
1150
1151 if (HAVE_OPT(UDP))
1152 strcpy(name, "UDP ");
1153 else
1154 name[0] = 0;
1155
1156 if (http == 1) {
1157 strcat(name, "HTTP Server");
1158 } else {
1159 strcat(name, "Echo Server");
1160 }
1161
1162 gnutls_global_set_log_function(tls_log_func);
1163 gnutls_global_set_audit_log_function(tls_audit_log_func);
1164 gnutls_global_set_log_level(debug);
1165
1166 if ((ret = gnutls_global_init()) < 0) {
1167 fprintf(stderr, "global_init: %s\n", gnutls_strerror(ret));
1168 exit(1);
1169 }
1170 #ifdef ENABLE_PKCS11
1171 if (HAVE_OPT(PROVIDER)) {
1172 ret = gnutls_pkcs11_init(GNUTLS_PKCS11_FLAG_MANUAL, NULL);
1173 if (ret < 0)
1174 fprintf(stderr, "pkcs11_init: %s",
1175 gnutls_strerror(ret));
1176 else {
1177 ret =
1178 gnutls_pkcs11_add_provider(OPT_ARG(PROVIDER),
1179 NULL);
1180 if (ret < 0) {
1181 fprintf(stderr, "pkcs11_add_provider: %s",
1182 gnutls_strerror(ret));
1183 exit(1);
1184 }
1185 }
1186 }
1187 pkcs11_common(NULL);
1188 #endif
1189
1190 /* Note that servers must generate parameters for
1191 * Diffie-Hellman. See gnutls_dh_params_generate(), and
1192 * gnutls_dh_params_set().
1193 */
1194 if (generate != 0) {
1195 generate_dh_primes();
1196 } else if (dh_params_file) {
1197 read_dh_params();
1198 } else {
1199 use_static_dh_params = 1;
1200 }
1201
1202 if (gnutls_certificate_allocate_credentials(&cert_cred) < 0) {
1203 fprintf(stderr, "memory error\n");
1204 exit(1);
1205 }
1206
1207 /* X509 credentials */
1208 if (x509_cafile != NULL) {
1209 if ((ret = gnutls_certificate_set_x509_trust_file
1210 (cert_cred, x509_cafile, x509ctype)) < 0) {
1211 fprintf(stderr, "Error reading '%s'\n",
1212 x509_cafile);
1213 GERR(ret);
1214 exit(1);
1215 } else {
1216 printf("Processed %d CA certificate(s).\n", ret);
1217 }
1218 }
1219 if (x509_crlfile != NULL) {
1220 if ((ret = gnutls_certificate_set_x509_crl_file
1221 (cert_cred, x509_crlfile, x509ctype)) < 0) {
1222 fprintf(stderr, "Error reading '%s'\n",
1223 x509_crlfile);
1224 GERR(ret);
1225 exit(1);
1226 } else {
1227 printf("Processed %d CRL(s).\n", ret);
1228 }
1229 }
1230
1231 if (x509_certfile_size > 0 && x509_keyfile_size > 0) {
1232 for (i = 0; i < x509_certfile_size; i++) {
1233 ret = gnutls_certificate_set_x509_key_file
1234 (cert_cred, x509_certfile[i], x509_keyfile[i], x509ctype);
1235 if (ret < 0) {
1236 fprintf(stderr,
1237 "Error reading '%s' or '%s'\n",
1238 x509_certfile[i], x509_keyfile[i]);
1239 GERR(ret);
1240 exit(1);
1241 } else
1242 cert_set = 1;
1243 }
1244 }
1245
1246 /* Raw public-key credentials */
1247 if (rawpk_file_size > 0 && rawpk_keyfile_size > 0) {
1248 for (i = 0; i < rawpk_keyfile_size; i++) {
1249 ret = gnutls_certificate_set_rawpk_key_file(cert_cred, rawpk_file[i],
1250 rawpk_keyfile[i],
1251 x509ctype,
1252 NULL, 0, NULL, 0,
1253 0, 0);
1254 if (ret < 0) {
1255 fprintf(stderr, "Error reading '%s' or '%s'\n",
1256 rawpk_file[i], rawpk_keyfile[i]);
1257 GERR(ret);
1258 exit(1);
1259 } else {
1260 cert_set = 1;
1261 }
1262 }
1263 }
1264
1265 if (cert_set == 0) {
1266 fprintf(stderr,
1267 "Warning: no private key and certificate pairs were set.\n");
1268 }
1269
1270 #ifndef ENABLE_OCSP
1271 if (HAVE_OPT(IGNORE_OCSP_RESPONSE_ERRORS) || ocsp_responses_size != 0) {
1272 fprintf(stderr, "OCSP is not supported!\n");
1273 exit(1);
1274 }
1275 #else
1276 /* OCSP status-request TLS extension */
1277 if (HAVE_OPT(IGNORE_OCSP_RESPONSE_ERRORS))
1278 gnutls_certificate_set_flags(cert_cred, GNUTLS_CERTIFICATE_SKIP_OCSP_RESPONSE_CHECK);
1279
1280 for (i = 0; i < ocsp_responses_size; i++ ) {
1281 ret = gnutls_certificate_set_ocsp_status_request_file
1282 (cert_cred, ocsp_responses[i], 0);
1283 if (ret < 0) {
1284 fprintf(stderr,
1285 "Cannot set OCSP status request file: %s: %s\n",
1286 ocsp_responses[i],
1287 gnutls_strerror(ret));
1288 exit(1);
1289 }
1290 }
1291 #endif
1292
1293 if (use_static_dh_params) {
1294 #if defined(ENABLE_DHE) || defined(ENABLE_ANON)
1295 ret = gnutls_certificate_set_known_dh_params(cert_cred, GNUTLS_SEC_PARAM_MEDIUM);
1296 if (ret < 0) {
1297 fprintf(stderr, "Error while setting DH parameters: %s\n", gnutls_strerror(ret));
1298 exit(1);
1299 }
1300 #else
1301 fprintf(stderr, "Setting DH parameters is not supported\n");
1302 exit(1);
1303 #endif
1304 } else {
1305 gnutls_certificate_set_params_function(cert_cred, get_params);
1306 }
1307
1308 /* this is a password file (created with the included srpcrypt utility)
1309 * Read README.crypt prior to using SRP.
1310 */
1311 #ifdef ENABLE_SRP
1312 if (srp_passwd != NULL) {
1313 gnutls_srp_allocate_server_credentials(&srp_cred);
1314
1315 if ((ret =
1316 gnutls_srp_set_server_credentials_file(srp_cred,
1317 srp_passwd,
1318 srp_passwd_conf))
1319 < 0) {
1320 /* only exit is this function is not disabled
1321 */
1322 fprintf(stderr,
1323 "Error while setting SRP parameters\n");
1324 GERR(ret);
1325 }
1326 }
1327 #endif
1328
1329 /* this is a password file
1330 */
1331 #ifdef ENABLE_PSK
1332 if (psk_passwd != NULL) {
1333 gnutls_psk_allocate_server_credentials(&psk_cred);
1334
1335 if ((ret =
1336 gnutls_psk_set_server_credentials_file(psk_cred,
1337 psk_passwd)) <
1338 0) {
1339 /* only exit is this function is not disabled
1340 */
1341 fprintf(stderr,
1342 "Error while setting PSK parameters\n");
1343 GERR(ret);
1344 }
1345
1346 if (HAVE_OPT(PSKHINT)) {
1347 ret =
1348 gnutls_psk_set_server_credentials_hint
1349 (psk_cred, OPT_ARG(PSKHINT));
1350 if (ret) {
1351 fprintf(stderr,
1352 "Error setting PSK identity hint.\n");
1353 GERR(ret);
1354 }
1355 }
1356
1357 if (use_static_dh_params) {
1358 ret = gnutls_psk_set_server_known_dh_params(psk_cred, GNUTLS_SEC_PARAM_MEDIUM);
1359 if (ret < 0) {
1360 fprintf(stderr, "Error while setting DH parameters: %s\n", gnutls_strerror(ret));
1361 exit(1);
1362 }
1363 } else {
1364 gnutls_psk_set_server_params_function(psk_cred,
1365 get_params);
1366 }
1367 }
1368 #endif
1369
1370 #ifdef ENABLE_ANON
1371 gnutls_anon_allocate_server_credentials(&dh_cred);
1372
1373 if (use_static_dh_params) {
1374 ret = gnutls_anon_set_server_known_dh_params(dh_cred, GNUTLS_SEC_PARAM_MEDIUM);
1375 if (ret < 0) {
1376 fprintf(stderr, "Error while setting DH parameters: %s\n", gnutls_strerror(ret));
1377 exit(1);
1378 }
1379 } else {
1380 gnutls_anon_set_server_params_function(dh_cred, get_params);
1381 }
1382 #endif
1383
1384 if (noticket == 0)
1385 gnutls_session_ticket_key_generate(&session_ticket_key);
1386
1387 if (earlydata) {
1388 ret = gnutls_anti_replay_init(&anti_replay);
1389 if (ret < 0) {
1390 fprintf(stderr, "Error while initializing anti-replay: %s\n", gnutls_strerror(ret));
1391 exit(1);
1392 }
1393 gnutls_anti_replay_set_add_function(anti_replay, anti_replay_db_add);
1394 gnutls_anti_replay_set_ptr(anti_replay, NULL);
1395 }
1396
1397 if (HAVE_OPT(MTU))
1398 mtu = OPT_VALUE_MTU;
1399 else
1400 mtu = 1300;
1401
1402 if (HAVE_OPT(PORT))
1403 port = OPT_VALUE_PORT;
1404 else
1405 port = 5556;
1406
1407 if (HAVE_OPT(UDP))
1408 udp_server(name, port, mtu);
1409 else
1410 tcp_server(name, port);
1411
1412 return 0;
1413 }
1414
retry_handshake(listener_item * j)1415 static void retry_handshake(listener_item *j)
1416 {
1417 int r, ret;
1418
1419 r = gnutls_handshake(j->tls_session);
1420 if (r < 0 && gnutls_error_is_fatal(r) == 0) {
1421 check_alert(j->tls_session, r);
1422 /* nothing */
1423 } else if (r < 0) {
1424 j->http_state = HTTP_STATE_CLOSING;
1425 check_alert(j->tls_session, r);
1426 fprintf(stderr, "Error in handshake: %s\n", gnutls_strerror(r));
1427
1428 do {
1429 ret = gnutls_alert_send_appropriate(j->tls_session, r);
1430 } while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);
1431 j->close_ok = 0;
1432 } else if (r == 0) {
1433 if (gnutls_session_is_resumed(j->tls_session) != 0 && verbose != 0)
1434 printf("*** This is a resumed session\n");
1435
1436 if (verbose != 0) {
1437 #if 0
1438 printf("- connection from %s\n",
1439 human_addr((struct sockaddr *)
1440 &client_address,
1441 calen,
1442 topbuf,
1443 sizeof(topbuf)));
1444 #endif
1445
1446 print_info(j->tls_session, verbose, verbose);
1447
1448 if (HAVE_OPT(KEYMATEXPORT))
1449 print_key_material(j->tls_session,
1450 OPT_ARG(KEYMATEXPORT),
1451 HAVE_OPT(KEYMATEXPORTSIZE) ?
1452 OPT_VALUE_KEYMATEXPORTSIZE :
1453 20);
1454 }
1455
1456 j->close_ok = 1;
1457 j->handshake_ok = 1;
1458 }
1459 }
1460
try_rehandshake(listener_item * j)1461 static void try_rehandshake(listener_item *j)
1462 {
1463 int r, ret;
1464 fprintf(stderr, "*** Received hello message\n");
1465
1466 do {
1467 r = gnutls_handshake(j->tls_session);
1468 } while (r == GNUTLS_E_INTERRUPTED || r == GNUTLS_E_AGAIN);
1469
1470 if (r < 0) {
1471 do {
1472 ret = gnutls_alert_send_appropriate(j->tls_session, r);
1473 } while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);
1474 fprintf(stderr, "Error in rehandshake: %s\n", gnutls_strerror(r));
1475 j->http_state = HTTP_STATE_CLOSING;
1476 } else {
1477 j->close_ok = 1;
1478 j->http_state = HTTP_STATE_REQUEST;
1479 }
1480 }
1481
tcp_server(const char * name,int port)1482 static void tcp_server(const char *name, int port)
1483 {
1484 int n, s;
1485 char topbuf[512];
1486 int accept_fd;
1487 struct sockaddr_storage client_address;
1488 socklen_t calen;
1489 struct timeval tv;
1490
1491 s = listen_socket(name, port, SOCK_STREAM);
1492 if (s < 0)
1493 exit(1);
1494
1495 for (;;) {
1496 listener_item *j;
1497 fd_set rd, wr;
1498 time_t now = time(0);
1499 #ifndef _WIN32
1500 int val;
1501 #endif
1502
1503 FD_ZERO(&rd);
1504 FD_ZERO(&wr);
1505 n = 0;
1506
1507 /* flag which connections we are reading or writing to within the fd sets */
1508 lloopstart(listener_list, j) {
1509
1510 #ifndef _WIN32
1511 val = fcntl(j->fd, F_GETFL, 0);
1512 if ((val == -1)
1513 || (fcntl(j->fd, F_SETFL, val | O_NONBLOCK) <
1514 0)) {
1515 perror("fcntl()");
1516 exit(1);
1517 }
1518 #endif
1519 if (j->start != 0 && now - j->start > 30) {
1520 if (verbose != 0) {
1521 fprintf(stderr, "Scheduling inactive connection for close\n");
1522 }
1523 j->http_state = HTTP_STATE_CLOSING;
1524 }
1525
1526 if (j->listen_socket) {
1527 FD_SET(j->fd, &rd);
1528 n = MAX(n, j->fd);
1529 }
1530 if (j->http_state == HTTP_STATE_REQUEST) {
1531 FD_SET(j->fd, &rd);
1532 n = MAX(n, j->fd);
1533 }
1534 if (j->http_state == HTTP_STATE_RESPONSE) {
1535 FD_SET(j->fd, &wr);
1536 n = MAX(n, j->fd);
1537 }
1538 }
1539 lloopend(listener_list, j);
1540
1541 /* core operation */
1542 tv.tv_sec = 10;
1543 tv.tv_usec = 0;
1544 n = select(n + 1, &rd, &wr, NULL, &tv);
1545 if (n == -1 && errno == EINTR)
1546 continue;
1547 if (n < 0) {
1548 perror("select()");
1549 exit(1);
1550 }
1551
1552 /* read or write to each connection as indicated by select()'s return argument */
1553 lloopstart(listener_list, j) {
1554
1555 /* a new connection has arrived */
1556 if (FD_ISSET(j->fd, &rd) && j->listen_socket) {
1557 calen = sizeof(client_address);
1558 memset(&client_address, 0, calen);
1559 accept_fd =
1560 accept(j->fd,
1561 (struct sockaddr *)
1562 &client_address, &calen);
1563
1564 if (accept_fd < 0) {
1565 perror("accept()");
1566 } else {
1567 char timebuf[SIMPLE_CTIME_BUF_SIZE];
1568 time_t tt = time(0);
1569 char *ctt;
1570
1571 /* new list entry for the connection */
1572 lappend(listener_list);
1573 j = listener_list.tail;
1574 j->http_request =
1575 (char *) strdup("");
1576 j->http_state = HTTP_STATE_REQUEST;
1577 j->fd = accept_fd;
1578 j->start = tt;
1579
1580 j->tls_session = initialize_session(0);
1581 gnutls_session_set_ptr(j->tls_session, j);
1582 gnutls_transport_set_int
1583 (j->tls_session, accept_fd);
1584 set_read_funcs(j->tls_session);
1585 j->handshake_ok = 0;
1586 j->close_ok = 0;
1587
1588 if (verbose != 0) {
1589 ctt = simple_ctime(&tt, timebuf);
1590 ctt[strlen(ctt) - 1] = 0;
1591
1592 printf
1593 ("\n* Accepted connection from %s on %s\n",
1594 human_addr((struct
1595 sockaddr
1596 *)
1597 &client_address,
1598 calen,
1599 topbuf,
1600 sizeof
1601 (topbuf)),
1602 ctt);
1603 }
1604 }
1605 }
1606
1607 if (FD_ISSET(j->fd, &rd) && !j->listen_socket) {
1608 /* read partial GET request */
1609 char buf[16*1024];
1610 int r;
1611
1612 if (j->handshake_ok == 0) {
1613 retry_handshake(j);
1614 }
1615
1616 if (j->handshake_ok == 1) {
1617 int earlydata_read = 0;
1618 if (earlydata && !j->earlydata_eof) {
1619 r = gnutls_record_recv_early_data(j->
1620 tls_session,
1621 buf,
1622 MIN(sizeof(buf),
1623 SMALL_READ_TEST));
1624 if (r == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
1625 j->earlydata_eof = 1;
1626 }
1627 if (r == 0) {
1628 earlydata_read = 1;
1629 }
1630 }
1631 if (!earlydata_read) {
1632 r = gnutls_record_recv(j->
1633 tls_session,
1634 buf,
1635 MIN(sizeof(buf),
1636 SMALL_READ_TEST));
1637 }
1638 if (r == GNUTLS_E_INTERRUPTED || r == GNUTLS_E_AGAIN) {
1639 /* do nothing */
1640 } else if (r <= 0) {
1641 if (r == GNUTLS_E_HEARTBEAT_PING_RECEIVED) {
1642 gnutls_heartbeat_pong(j->tls_session, 0);
1643 } else if (r == GNUTLS_E_REHANDSHAKE) {
1644 try_rehandshake(j);
1645 } else {
1646 j->http_state = HTTP_STATE_CLOSING;
1647 if (r < 0) {
1648 int ret;
1649 check_alert(j->tls_session, r);
1650 fprintf(stderr,
1651 "Error while receiving data\n");
1652 do {
1653 ret = gnutls_alert_send_appropriate(j->tls_session, r);
1654 } while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);
1655 GERR(r);
1656 j->close_ok = 0;
1657 }
1658 }
1659 } else {
1660 j->http_request =
1661 realloc(j->
1662 http_request,
1663 j->
1664 request_length
1665 + r + 1);
1666 if (j->http_request !=
1667 NULL) {
1668 memcpy(j->
1669 http_request
1670 +
1671 j->
1672 request_length,
1673 buf, r);
1674 j->request_length
1675 += r;
1676 j->http_request[j->
1677 request_length]
1678 = '\0';
1679 } else {
1680 j->http_state =
1681 HTTP_STATE_CLOSING;
1682 }
1683 }
1684 /* check if we have a full HTTP header */
1685
1686 j->http_response = NULL;
1687 if (j->http_state == HTTP_STATE_REQUEST && j->http_request != NULL) {
1688 if ((http == 0
1689 && strchr(j->
1690 http_request,
1691 '\n'))
1692 || strstr(j->
1693 http_request,
1694 "\r\n\r\n")
1695 || strstr(j->
1696 http_request,
1697 "\n\n")) {
1698 if (get_response(j->
1699 tls_session,
1700 j->
1701 http_request,
1702 &j->
1703 http_response,
1704 &j->
1705 response_length)) {
1706 j->http_state =
1707 HTTP_STATE_RESPONSE;
1708 j->response_written
1709 = 0;
1710 } else {
1711 j->http_state = HTTP_STATE_CLOSING;
1712 }
1713 }
1714 }
1715 }
1716 }
1717
1718 if (FD_ISSET(j->fd, &wr)) {
1719 /* write partial response request */
1720 int r;
1721
1722 if (j->handshake_ok == 0) {
1723 retry_handshake(j);
1724 }
1725
1726 if (j->handshake_ok == 1 && j->http_response == NULL) {
1727 j->http_state = HTTP_STATE_CLOSING;
1728 } else if (j->handshake_ok == 1 && j->http_response != NULL) {
1729 r = gnutls_record_send(j->tls_session,
1730 j->http_response
1731 +
1732 j->response_written,
1733 MIN(j->response_length
1734 -
1735 j->response_written,
1736 SMALL_READ_TEST));
1737 if (r == GNUTLS_E_INTERRUPTED || r == GNUTLS_E_AGAIN) {
1738 /* do nothing */
1739 } else if (r <= 0) {
1740 j->http_state = HTTP_STATE_CLOSING;
1741 if (r < 0) {
1742 fprintf(stderr,
1743 "Error while sending data\n");
1744 GERR(r);
1745 }
1746 check_alert(j->tls_session,
1747 r);
1748 } else {
1749 j->response_written += r;
1750 /* check if we have written a complete response */
1751 if (j->response_written ==
1752 j->response_length) {
1753 if (http != 0)
1754 j->http_state = HTTP_STATE_CLOSING;
1755 else {
1756 j->http_state = HTTP_STATE_REQUEST;
1757 free(j->
1758 http_response);
1759 j->http_response = NULL;
1760 j->response_length = 0;
1761 j->request_length = 0;
1762 j->http_request[0] = 0;
1763 }
1764 }
1765 }
1766 } else {
1767 j->request_length = 0;
1768 j->http_request[0] = 0;
1769 j->http_state = HTTP_STATE_REQUEST;
1770 }
1771 }
1772 }
1773 lloopend(listener_list, j);
1774
1775 /* loop through all connections, closing those that are in error */
1776 lloopstart(listener_list, j) {
1777 if (j->http_state == HTTP_STATE_CLOSING) {
1778 ldeleteinc(listener_list, j);
1779 }
1780 }
1781 lloopend(listener_list, j);
1782 }
1783
1784
1785 gnutls_certificate_free_credentials(cert_cred);
1786
1787 #ifdef ENABLE_SRP
1788 if (srp_cred)
1789 gnutls_srp_free_server_credentials(srp_cred);
1790 #endif
1791
1792 #ifdef ENABLE_PSK
1793 if (psk_cred)
1794 gnutls_psk_free_server_credentials(psk_cred);
1795 #endif
1796
1797 #ifdef ENABLE_ANON
1798 gnutls_anon_free_server_credentials(dh_cred);
1799 #endif
1800
1801 if (noticket == 0)
1802 gnutls_free(session_ticket_key.data);
1803
1804 if (earlydata)
1805 gnutls_anti_replay_deinit(anti_replay);
1806
1807 if (nodb == 0)
1808 wrap_db_deinit();
1809 gnutls_global_deinit();
1810
1811 }
1812
cmd_parser(int argc,char ** argv)1813 static void cmd_parser(int argc, char **argv)
1814 {
1815 optionProcess(&gnutls_servOptions, argc, argv);
1816
1817 disable_client_cert = HAVE_OPT(DISABLE_CLIENT_CERT);
1818 require_cert = ENABLED_OPT(REQUIRE_CLIENT_CERT);
1819 if (HAVE_OPT(DEBUG))
1820 debug = OPT_VALUE_DEBUG;
1821
1822 if (HAVE_OPT(QUIET))
1823 verbose = 0;
1824
1825 if (HAVE_OPT(PRIORITY))
1826 priorities = OPT_ARG(PRIORITY);
1827
1828 if (HAVE_OPT(LIST)) {
1829 print_list(priorities, verbose);
1830 exit(0);
1831 }
1832
1833 nodb = HAVE_OPT(NODB);
1834 noticket = HAVE_OPT(NOTICKET);
1835 earlydata = HAVE_OPT(EARLYDATA);
1836
1837 if (HAVE_OPT(ECHO))
1838 http = 0;
1839 else
1840 http = 1;
1841
1842 record_max_size = OPT_VALUE_RECORDSIZE;
1843
1844 if (HAVE_OPT(X509FMTDER))
1845 x509ctype = GNUTLS_X509_FMT_DER;
1846 else
1847 x509ctype = GNUTLS_X509_FMT_PEM;
1848
1849 generate = HAVE_OPT(GENERATE);
1850
1851 if (HAVE_OPT(DHPARAMS))
1852 dh_params_file = OPT_ARG(DHPARAMS);
1853
1854 if (HAVE_OPT(ALPN)) {
1855 alpn_protos = STACKLST_OPT(ALPN);
1856 alpn_protos_size = STACKCT_OPT(ALPN);
1857 }
1858
1859 if (HAVE_OPT(X509KEYFILE)) {
1860 x509_keyfile = STACKLST_OPT(X509KEYFILE);
1861 x509_keyfile_size = STACKCT_OPT(X509KEYFILE);
1862 }
1863
1864 if (HAVE_OPT(X509CERTFILE)) {
1865 x509_certfile = STACKLST_OPT(X509CERTFILE);
1866 x509_certfile_size = STACKCT_OPT(X509CERTFILE);
1867 }
1868
1869 if (x509_certfile_size != x509_keyfile_size) {
1870 fprintf(stderr, "The certificate number provided (%u) doesn't match the keys (%u)\n",
1871 x509_certfile_size, x509_keyfile_size);
1872 exit(1);
1873 }
1874
1875 if (HAVE_OPT(X509CAFILE))
1876 x509_cafile = OPT_ARG(X509CAFILE);
1877 if (HAVE_OPT(X509CRLFILE))
1878 x509_crlfile = OPT_ARG(X509CRLFILE);
1879
1880 if (HAVE_OPT(RAWPKKEYFILE)) {
1881 rawpk_keyfile = STACKLST_OPT(RAWPKKEYFILE);
1882 rawpk_keyfile_size = STACKCT_OPT(RAWPKKEYFILE);
1883 }
1884
1885 if (HAVE_OPT(RAWPKFILE)) {
1886 rawpk_file = STACKLST_OPT(RAWPKFILE);
1887 rawpk_file_size = STACKCT_OPT(RAWPKFILE);
1888 }
1889
1890 if (rawpk_file_size != rawpk_keyfile_size) {
1891 fprintf(stderr, "The number of raw public-keys provided (%u) doesn't match the number of corresponding private keys (%u)\n",
1892 rawpk_file_size, rawpk_keyfile_size);
1893 exit(1);
1894 }
1895
1896 if (HAVE_OPT(SRPPASSWD))
1897 srp_passwd = OPT_ARG(SRPPASSWD);
1898 if (HAVE_OPT(SRPPASSWDCONF))
1899 srp_passwd_conf = OPT_ARG(SRPPASSWDCONF);
1900
1901 if (HAVE_OPT(PSKPASSWD))
1902 psk_passwd = OPT_ARG(PSKPASSWD);
1903
1904 if (HAVE_OPT(OCSP_RESPONSE)) {
1905 ocsp_responses = STACKLST_OPT(OCSP_RESPONSE);
1906 ocsp_responses_size = STACKCT_OPT(OCSP_RESPONSE);
1907 }
1908
1909 if (HAVE_OPT(SNI_HOSTNAME))
1910 sni_hostname = OPT_ARG(SNI_HOSTNAME);
1911
1912 if (HAVE_OPT(SNI_HOSTNAME_FATAL))
1913 sni_hostname_fatal = 1;
1914
1915 if (HAVE_OPT(HTTPDATA))
1916 http_data_file = OPT_ARG(HTTPDATA);
1917
1918 }
1919
1920 /* session resuming support */
1921
1922 #define SESSION_ID_SIZE 128
1923 #define SESSION_DATA_SIZE (16*1024)
1924
1925 typedef struct {
1926 unsigned char session_id[SESSION_ID_SIZE];
1927 unsigned int session_id_size;
1928
1929 gnutls_datum_t session_data;
1930 } CACHE;
1931
1932 static CACHE *cache_db;
1933 static int cache_db_ptr;
1934 static int cache_db_alloc;
1935
wrap_db_init(void)1936 static void wrap_db_init(void)
1937 {
1938 }
1939
wrap_db_deinit(void)1940 static void wrap_db_deinit(void)
1941 {
1942 int i;
1943
1944 for (i = 0; i < cache_db_ptr; i++)
1945 free(cache_db[i].session_data.data);
1946 free(cache_db);
1947 }
1948
1949 static int
wrap_db_store(void * dbf,gnutls_datum_t key,gnutls_datum_t data)1950 wrap_db_store(void *dbf, gnutls_datum_t key, gnutls_datum_t data)
1951 {
1952 int i;
1953 time_t now = time(0);
1954
1955 if (key.size > SESSION_ID_SIZE)
1956 return GNUTLS_E_DB_ERROR;
1957 if (data.size > SESSION_DATA_SIZE)
1958 return GNUTLS_E_DB_ERROR;
1959
1960 if (cache_db_ptr < cache_db_alloc)
1961 i = cache_db_ptr++;
1962 else {
1963 /* find empty or expired slot to store the new entry */
1964 for (i = 0; i < cache_db_ptr; i++)
1965 if (cache_db[i].session_id_size == 0 ||
1966 !(now <
1967 gnutls_db_check_entry_expire_time(&cache_db[i].
1968 session_data)))
1969 break;
1970
1971 if (i == cache_db_ptr) {
1972 /* try to allocate additional slots */
1973 if (cache_db_ptr == ssl_session_cache) {
1974 fprintf(stderr,
1975 "Error: too many sessions\n");
1976 return GNUTLS_E_DB_ERROR;
1977 }
1978 cache_db_alloc = cache_db_alloc * 2 + 1;
1979 cache_db = realloc(cache_db,
1980 cache_db_alloc * sizeof(CACHE));
1981 if (!cache_db)
1982 return GNUTLS_E_MEMORY_ERROR;
1983 memset(cache_db + cache_db_ptr, 0,
1984 (cache_db_alloc - cache_db_ptr) * sizeof(CACHE));
1985 cache_db_ptr++;
1986 }
1987 }
1988
1989 memcpy(cache_db[i].session_id, key.data, key.size);
1990 cache_db[i].session_id_size = key.size;
1991
1992 /* resize the data slot if needed */
1993 if (cache_db[i].session_data.size < data.size) {
1994 cache_db[i].session_data.data =
1995 realloc(cache_db[i].session_data.data,
1996 data.size);
1997 if (!cache_db[i].session_data.data)
1998 return GNUTLS_E_MEMORY_ERROR;
1999 }
2000 memcpy(cache_db[i].session_data.data, data.data, data.size);
2001 cache_db[i].session_data.size = data.size;
2002
2003 return 0;
2004 }
2005
wrap_db_fetch(void * dbf,gnutls_datum_t key)2006 static gnutls_datum_t wrap_db_fetch(void *dbf, gnutls_datum_t key)
2007 {
2008 gnutls_datum_t res = { NULL, 0 };
2009 time_t now = time(0);
2010 int i;
2011
2012 for (i = 0; i < cache_db_ptr; i++) {
2013 if (key.size == cache_db[i].session_id_size &&
2014 memcmp(key.data, cache_db[i].session_id,
2015 key.size) == 0 &&
2016 now < gnutls_db_check_entry_expire_time(&cache_db[i].
2017 session_data)) {
2018 res.size = cache_db[i].session_data.size;
2019
2020 res.data = malloc(res.size);
2021 if (res.data == NULL)
2022 return res;
2023
2024 memcpy(res.data, cache_db[i].session_data.data,
2025 res.size);
2026
2027 return res;
2028 }
2029 }
2030 return res;
2031 }
2032
wrap_db_delete(void * dbf,gnutls_datum_t key)2033 static int wrap_db_delete(void *dbf, gnutls_datum_t key)
2034 {
2035 int i;
2036
2037 for (i = 0; i < cache_db_ptr; i++) {
2038 if (key.size == cache_db[i].session_id_size &&
2039 memcmp(key.data, cache_db[i].session_id,
2040 key.size) == 0) {
2041
2042 cache_db[i].session_id_size = 0;
2043 free(cache_db[i].session_data.data);
2044 cache_db[i].session_data.data = NULL;
2045 cache_db[i].session_data.size = 0;
2046
2047 return 0;
2048 }
2049 }
2050
2051 return GNUTLS_E_DB_ERROR;
2052 }
2053
2054 static int
anti_replay_db_add(void * dbf,time_t exp,const gnutls_datum_t * key,const gnutls_datum_t * data)2055 anti_replay_db_add(void *dbf, time_t exp, const gnutls_datum_t *key, const gnutls_datum_t *data)
2056 {
2057 time_t now = time(0);
2058 int i;
2059
2060 for (i = 0; i < cache_db_ptr; i++) {
2061 if (key->size == cache_db[i].session_id_size &&
2062 memcmp(key->data, cache_db[i].session_id,
2063 key->size) == 0 &&
2064 now < gnutls_db_check_entry_expire_time(&cache_db[i].
2065 session_data))
2066 return GNUTLS_E_DB_ENTRY_EXISTS;
2067 }
2068
2069 return wrap_db_store(dbf, *key, *data);
2070 }
2071