2 * Copyright (C) 2004-2012 Free Software Foundation, Inc.
3 * Copyright (C) 2001,2002 Paul Sheer
4 * Portions Copyright (C) 2002,2003 Nikos Mavrogiannopoulos
6 * This file is part of GnuTLS.
8 * GnuTLS is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
13 * GnuTLS is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 /* This server is heavily modified for GnuTLS by Nikos Mavrogiannopoulos
23 * (which means it is quite unreadable)
29 #include "serv-args.h"
33 #include <sys/types.h>
35 #include <gnutls/gnutls.h>
36 #include <gnutls/dtls.h>
37 #include <gnutls/openpgp.h>
39 #include <sys/select.h>
46 /* Gnulib portability files. */
48 #include "version-etc.h"
49 #include "read-file.h"
54 /* konqueror cannot handle sending the page in multiple
58 static int generate
= 0;
63 unsigned int verbose
= 1;
67 int disable_client_cert
;
69 const char *psk_passwd
= NULL
;
70 const char *srp_passwd
= NULL
;
71 const char *srp_passwd_conf
= NULL
;
72 const char *pgp_keyring
= NULL
;
73 const char *pgp_keyfile
= NULL
;
74 const char *pgp_certfile
= NULL
;
75 const char *x509_keyfile
= NULL
;
76 const char *x509_certfile
= NULL
;
77 const char *x509_dsakeyfile
= NULL
;
78 const char *x509_dsacertfile
= NULL
;
79 const char *x509_ecckeyfile
= NULL
;
80 const char *x509_ecccertfile
= NULL
;
81 const char *x509_cafile
= NULL
;
82 const char *dh_params_file
= NULL
;
83 const char *x509_crlfile
= NULL
;
84 const char * priorities
= NULL
;
85 const char * status_response_ocsp
= NULL
;
87 gnutls_datum_t session_ticket_key
;
88 static void tcp_server (const char *name
, int port
);
92 /* This is a sample TCP echo server.
93 * This will behave as an http server if any argument in the
94 * command line is present
97 #define SMALL_READ_TEST (2147483647)
99 #define GERR(ret) fprintf(stdout, "Error: %s\n", safe_strerror(ret))
101 #define HTTP_END "</BODY></HTML>\n\n"
103 #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"
104 #define HTTP_OK "HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n"
106 #define HTTP_BEGIN HTTP_OK \
109 "<CENTER><H1>This is <a href=\"http://www.gnu.org/software/gnutls\">" \
110 "GnuTLS</a></H1></CENTER>\n\n"
112 /* These are global */
113 gnutls_srp_server_credentials_t srp_cred
= NULL
;
114 gnutls_psk_server_credentials_t psk_cred
= NULL
;
115 gnutls_anon_server_credentials_t dh_cred
= NULL
;
116 gnutls_certificate_credentials_t cert_cred
= NULL
;
118 const int ssl_session_cache
= 128;
120 static void wrap_db_init (void);
121 static void wrap_db_deinit (void);
122 static int wrap_db_store (void *dbf
, gnutls_datum_t key
, gnutls_datum_t data
);
123 static gnutls_datum_t
wrap_db_fetch (void *dbf
, gnutls_datum_t key
);
124 static int wrap_db_delete (void *dbf
, gnutls_datum_t key
);
126 static void cmd_parser (int argc
, char **argv
);
129 #define HTTP_STATE_REQUEST 1
130 #define HTTP_STATE_RESPONSE 2
131 #define HTTP_STATE_CLOSING 3
133 LIST_TYPE_DECLARE (listener_item
, char *http_request
;
134 char *http_response
; int request_length
;
135 int response_length
; int response_written
;
136 int http_state
; int listen_socket
;
137 int fd
; gnutls_session_t tls_session
; int handshake_ok
;);
140 safe_strerror (int value
)
142 const char *ret
= gnutls_strerror (value
);
149 listener_free (listener_item
* j
)
152 free (j
->http_request
);
153 free (j
->http_response
);
156 gnutls_bye (j
->tls_session
, GNUTLS_SHUT_WR
);
159 gnutls_deinit (j
->tls_session
);
164 /* we use primes up to 1024 in this server.
165 * otherwise we should add them here.
168 gnutls_dh_params_t dh_params
= NULL
;
169 gnutls_rsa_params_t rsa_params
= NULL
;
172 generate_dh_primes (void)
175 gnutls_sec_param_to_pk_bits (GNUTLS_PK_DH
, GNUTLS_SEC_PARAM_NORMAL
);
177 if (gnutls_dh_params_init (&dh_params
) < 0)
179 fprintf (stderr
, "Error in dh parameter initialization\n");
183 /* Generate Diffie-Hellman parameters - for use with DHE
184 * kx algorithms. These should be discarded and regenerated
185 * once a week or once a month. Depends on the
186 * security requirements.
189 ("Generating Diffie-Hellman parameters [%d]. Please wait...\n",
193 if (gnutls_dh_params_generate2 (dh_params
, prime_bits
) < 0)
195 fprintf (stderr
, "Error in prime generation\n");
203 read_dh_params (void)
207 gnutls_datum_t params
;
210 if (gnutls_dh_params_init (&dh_params
) < 0)
212 fprintf (stderr
, "Error in dh parameter initialization\n");
216 /* read the params file
218 fd
= fopen (dh_params_file
, "r");
221 fprintf (stderr
, "Could not open %s\n", dh_params_file
);
225 size
= fread (tmpdata
, 1, sizeof (tmpdata
) - 1, fd
);
229 params
.data
= (unsigned char *) tmpdata
;
233 gnutls_dh_params_import_pkcs3 (dh_params
, ¶ms
, GNUTLS_X509_FMT_PEM
);
237 fprintf (stderr
, "Error parsing dh params: %s\n", safe_strerror (size
));
241 printf ("Read Diffie-Hellman parameters.\n");
246 static char pkcs3
[] =
247 "-----BEGIN DH PARAMETERS-----\n"
248 "MIGGAoGAtkxw2jlsVCsrfLqxrN+IrF/3W8vVFvDzYbLmxi2GQv9s/PQGWP1d9i22\n"
249 "P2DprfcJknWt7KhCI1SaYseOQIIIAYP78CfyIpGScW/vS8khrw0rlQiyeCvQgF3O\n"
250 "GeGOEywcw+oQT4SmFOD7H0smJe2CNyjYpexBXQ/A0mbTF9QKm1cCAQU=\n"
251 "-----END DH PARAMETERS-----\n";
254 static_dh_params (void)
256 gnutls_datum_t params
= { (void *) pkcs3
, sizeof (pkcs3
) };
259 if (gnutls_dh_params_init (&dh_params
) < 0)
261 fprintf (stderr
, "Error in dh parameter initialization\n");
265 ret
= gnutls_dh_params_import_pkcs3 (dh_params
, ¶ms
,
266 GNUTLS_X509_FMT_PEM
);
270 fprintf (stderr
, "Error parsing dh params: %s\n", safe_strerror (ret
));
274 printf ("Set static Diffie-Hellman parameters, consider --dhparams.\n");
280 get_params (gnutls_session_t session
, gnutls_params_type_t type
,
281 gnutls_params_st
* st
)
284 if (type
== GNUTLS_PARAMS_RSA_EXPORT
)
286 if (rsa_params
== NULL
)
288 st
->params
.rsa_export
= rsa_params
;
290 else if (type
== GNUTLS_PARAMS_DH
)
292 if (dh_params
== NULL
)
294 st
->params
.dh
= dh_params
;
306 generate_rsa_params (void)
308 if (gnutls_rsa_params_init (&rsa_params
) < 0)
310 fprintf (stderr
, "Error in rsa parameter initialization\n");
314 /* Generate RSA parameters - for use with RSA-export
315 * cipher suites. These should be discarded and regenerated
316 * once a day, once every 500 transactions etc. Depends on the
317 * security requirements.
319 printf ("Generating temporary RSA parameters. Please wait...\n");
322 if (gnutls_rsa_params_generate2 (rsa_params
, 512) < 0)
324 fprintf (stderr
, "Error in rsa parameter generation\n");
331 LIST_DECLARE_INIT (listener_list
, listener_item
, listener_free
);
333 gnutls_session_t
initialize_session (int dtls
)
335 gnutls_session_t session
;
339 if (priorities
== NULL
)
340 priorities
= "NORMAL";
343 gnutls_init (&session
, GNUTLS_SERVER
| GNUTLS_DATAGRAM
);
345 gnutls_init (&session
, GNUTLS_SERVER
);
347 /* allow the use of private ciphersuites.
349 gnutls_handshake_set_private_extensions (session
, 1);
353 gnutls_db_set_retrieve_function (session
, wrap_db_fetch
);
354 gnutls_db_set_remove_function (session
, wrap_db_delete
);
355 gnutls_db_set_store_function (session
, wrap_db_store
);
356 gnutls_db_set_ptr (session
, NULL
);
358 #ifdef ENABLE_SESSION_TICKET
360 gnutls_session_ticket_enable_server (session
, &session_ticket_key
);
365 gnutls_session_ticket_enable_server (session
, &session_ticket_key
);
367 if (gnutls_priority_set_direct (session
, priorities
, &err
) < 0)
369 fprintf (stderr
, "Syntax error at: %s\n", err
);
373 gnutls_credentials_set (session
, GNUTLS_CRD_ANON
, dh_cred
);
375 if (srp_cred
!= NULL
)
376 gnutls_credentials_set (session
, GNUTLS_CRD_SRP
, srp_cred
);
378 if (psk_cred
!= NULL
)
379 gnutls_credentials_set (session
, GNUTLS_CRD_PSK
, psk_cred
);
381 if (cert_cred
!= NULL
)
382 gnutls_credentials_set (session
, GNUTLS_CRD_CERTIFICATE
, cert_cred
);
384 if (disable_client_cert
)
385 gnutls_certificate_server_set_request (session
, GNUTLS_CERT_IGNORE
);
389 gnutls_certificate_server_set_request (session
, GNUTLS_CERT_REQUIRE
);
391 gnutls_certificate_server_set_request (session
, GNUTLS_CERT_REQUEST
);
394 if (HAVE_OPT (HEARTBEAT
))
395 gnutls_heartbeat_enable(session
, GNUTLS_HB_PEER_ALLOWED_TO_SEND
);
397 #ifdef ENABLE_DTLS_SRTP
398 if (HAVE_OPT (SRTP_PROFILES
))
400 ret
= gnutls_srtp_set_profile_direct (session
, OPT_ARG(SRTP_PROFILES
), &err
);
401 if (ret
== GNUTLS_E_INVALID_REQUEST
) fprintf (stderr
, "Syntax error at: %s\n", err
);
403 fprintf(stderr
, "Error in profiles: %s\n", gnutls_strerror(ret
));
411 #include <gnutls/x509.h>
413 static const char DEFAULT_DATA
[] =
414 "This is the default message reported by the GnuTLS implementation. "
415 "For more information please visit "
416 "<a href=\"http://www.gnutls.org/\">http://www.gnutls.org/</a>.";
418 /* Creates html with the current session information.
420 #define tmp_buffer &http_buffer[strlen(http_buffer)]
421 #define tmp_buffer_size len-strlen(http_buffer)
423 peer_print_info (gnutls_session_t session
, int *ret_length
,
427 unsigned char sesid
[32];
428 size_t i
, sesid_size
;
430 gnutls_kx_algorithm_t kx_alg
;
431 size_t len
= 20 * 1024 + strlen (header
);
432 char *crtinfo
= NULL
;
437 http_buffer
= malloc (len
);
438 if (http_buffer
== NULL
)
441 strcpy (http_buffer
, HTTP_BEGIN
);
442 strcpy (&http_buffer
[sizeof (HTTP_BEGIN
) - 1], DEFAULT_DATA
);
443 strcpy (&http_buffer
[sizeof (HTTP_BEGIN
) + sizeof (DEFAULT_DATA
) - 2],
446 sizeof (DEFAULT_DATA
) + sizeof (HTTP_BEGIN
) + sizeof (HTTP_END
) - 3;
450 if (gnutls_certificate_type_get (session
) == GNUTLS_CRT_X509
)
452 const gnutls_datum_t
*cert_list
;
453 unsigned int cert_list_size
= 0;
455 cert_list
= gnutls_certificate_get_peers (session
, &cert_list_size
);
457 for (i
= 0; i
< cert_list_size
; i
++)
459 gnutls_x509_crt_t cert
;
462 if (gnutls_x509_crt_init (&cert
) == 0 &&
463 gnutls_x509_crt_import (cert
, &cert_list
[i
],
464 GNUTLS_X509_FMT_DER
) == 0 &&
465 gnutls_x509_crt_print (cert
, GNUTLS_CRT_PRINT_FULL
, &info
) == 0)
467 const char *post
= "</PRE><P><PRE>";
469 crtinfo
= realloc (crtinfo
, ncrtinfo
+ info
.size
+
473 memcpy (crtinfo
+ ncrtinfo
, info
.data
, info
.size
);
474 ncrtinfo
+= info
.size
;
475 memcpy (crtinfo
+ ncrtinfo
, post
, strlen (post
));
476 ncrtinfo
+= strlen (post
);
477 crtinfo
[ncrtinfo
] = '\0';
478 gnutls_free (info
.data
);
483 http_buffer
= malloc (len
);
484 if (http_buffer
== NULL
)
490 strcpy (http_buffer
, HTTP_BEGIN
);
492 /* print session_id */
493 sesid_size
= sizeof(sesid
);
494 gnutls_session_get_id (session
, sesid
, &sesid_size
);
495 snprintf (tmp_buffer
, tmp_buffer_size
, "\n<p>Session ID: <i>");
496 for (i
= 0; i
< sesid_size
; i
++)
497 snprintf (tmp_buffer
, tmp_buffer_size
, "%.2X", sesid
[i
]);
498 snprintf (tmp_buffer
, tmp_buffer_size
, "</i></p>\n");
499 snprintf (tmp_buffer
, tmp_buffer_size
,
500 "<h5>If your browser supports session resuming, then you should see the "
501 "same session ID, when you press the <b>reload</b> button.</h5>\n");
503 /* Here unlike print_info() we use the kx algorithm to distinguish
504 * the functions to call.
508 size_t dns_size
= sizeof (dns
);
511 if (gnutls_server_name_get (session
, dns
, &dns_size
, &type
, 0) == 0)
513 snprintf (tmp_buffer
, tmp_buffer_size
, "\n<p>Server Name: %s</p>\n",
519 kx_alg
= gnutls_kx_get (session
);
521 /* print srp specific data */
523 if (kx_alg
== GNUTLS_KX_SRP
)
525 snprintf (tmp_buffer
, tmp_buffer_size
,
526 "<p>Connected as user '%s'.</p>\n",
527 gnutls_srp_server_get_username (session
));
532 if (kx_alg
== GNUTLS_KX_PSK
)
534 snprintf (tmp_buffer
, tmp_buffer_size
,
535 "<p>Connected as user '%s'.</p>\n",
536 gnutls_psk_server_get_username (session
));
541 if (kx_alg
== GNUTLS_KX_ANON_DH
)
543 snprintf (tmp_buffer
, tmp_buffer_size
,
544 "<p> Connect using anonymous DH (prime of %d bits)</p>\n",
545 gnutls_dh_get_prime_bits (session
));
549 if (kx_alg
== GNUTLS_KX_DHE_RSA
|| kx_alg
== GNUTLS_KX_DHE_DSS
)
551 snprintf (tmp_buffer
, tmp_buffer_size
,
552 "Ephemeral DH using prime of <b>%d</b> bits.<br>\n",
553 gnutls_dh_get_prime_bits (session
));
556 /* print session information */
557 strcat (http_buffer
, "<P>\n");
559 tmp
= gnutls_protocol_get_name (gnutls_protocol_get_version (session
));
562 snprintf (tmp_buffer
, tmp_buffer_size
,
563 "<TABLE border=1><TR><TD>Protocol version:</TD><TD>%s</TD></TR>\n",
566 if (gnutls_auth_get_type (session
) == GNUTLS_CRD_CERTIFICATE
)
569 gnutls_certificate_type_get_name (gnutls_certificate_type_get
573 snprintf (tmp_buffer
, tmp_buffer_size
,
574 "<TR><TD>Certificate Type:</TD><TD>%s</TD></TR>\n", tmp
);
577 tmp
= gnutls_kx_get_name (kx_alg
);
580 snprintf (tmp_buffer
, tmp_buffer_size
,
581 "<TR><TD>Key Exchange:</TD><TD>%s</TD></TR>\n", tmp
);
583 tmp
= gnutls_compression_get_name (gnutls_compression_get (session
));
586 snprintf (tmp_buffer
, tmp_buffer_size
,
587 "<TR><TD>Compression</TD><TD>%s</TD></TR>\n", tmp
);
589 tmp
= gnutls_cipher_get_name (gnutls_cipher_get (session
));
592 snprintf (tmp_buffer
, tmp_buffer_size
,
593 "<TR><TD>Cipher</TD><TD>%s</TD></TR>\n", tmp
);
595 tmp
= gnutls_mac_get_name (gnutls_mac_get (session
));
598 snprintf (tmp_buffer
, tmp_buffer_size
, "<TR><TD>MAC</TD><TD>%s</TD></TR>\n",
601 tmp
= gnutls_cipher_suite_get_name (kx_alg
,
602 gnutls_cipher_get (session
),
603 gnutls_mac_get (session
));
606 snprintf (tmp_buffer
, tmp_buffer_size
,
607 "<TR><TD>Ciphersuite</TD><TD>%s</TD></TR></p></TABLE>\n", tmp
);
611 snprintf (tmp_buffer
, tmp_buffer_size
, "<hr><PRE>%s\n</PRE>\n",
616 snprintf (tmp_buffer
, tmp_buffer_size
,
617 "<hr><P>Your HTTP header was:<PRE>%s</PRE></P>\n" HTTP_END
,
620 *ret_length
= strlen (http_buffer
);
626 human_addr (const struct sockaddr
*sa
, socklen_t salen
,
627 char *buf
, size_t buflen
)
629 const char *save_buf
= buf
;
637 switch (sa
->sa_family
)
641 snprintf (buf
, buflen
, "IPv6 ");
646 snprintf (buf
, buflen
, "IPv4 ");
654 if (getnameinfo (sa
, salen
, buf
, buflen
, NULL
, 0, NI_NUMERICHOST
) != 0)
661 strncat (buf
, " port ", buflen
);
667 if (getnameinfo (sa
, salen
, NULL
, 0, buf
, buflen
, NI_NUMERICSERV
) != 0)
674 wait_for_connection (void)
684 lloopstart (listener_list
, j
)
686 if (j
->listen_socket
)
692 lloopend (listener_list
, j
);
695 n
= select (n
+ 1, &rd
, &wr
, NULL
, NULL
);
696 if (n
== -1 && errno
== EINTR
)
704 /* find which one is ready */
705 lloopstart (listener_list
, j
)
707 /* a new connection has arrived */
708 if (FD_ISSET (j
->fd
, &rd
) && j
->listen_socket
)
714 lloopend (listener_list
, j
);
719 listen_socket (const char *name
, int listen_port
, int socktype
)
721 struct addrinfo hints
, *res
, *ptr
;
725 listener_item
*j
= NULL
;
727 snprintf (portname
, sizeof (portname
), "%d", listen_port
);
728 memset (&hints
, 0, sizeof (hints
));
729 hints
.ai_socktype
= socktype
;
730 hints
.ai_flags
= AI_PASSIVE
736 if ((s
= getaddrinfo (NULL
, portname
, &hints
, &res
)) != 0)
738 fprintf (stderr
, "getaddrinfo() failed: %s\n", gai_strerror (s
));
742 for (ptr
= res
; ptr
!= NULL
; ptr
= ptr
->ai_next
)
745 if (ptr
->ai_family
!= AF_INET
)
749 /* Print what we are doing. */
753 fprintf (stderr
, "%s listening on %s...",
754 name
, human_addr (ptr
->ai_addr
, ptr
->ai_addrlen
,
755 topbuf
, sizeof (topbuf
)));
758 if ((s
= socket (ptr
->ai_family
, ptr
->ai_socktype
,
759 ptr
->ai_protocol
)) < 0)
761 perror ("socket() failed");
765 #if defined(HAVE_IPV6) && !defined(_WIN32)
766 if (ptr
->ai_family
== AF_INET6
)
769 /* avoid listen on ipv6 addresses failing
770 * because already listening on ipv4 addresses: */
771 setsockopt (s
, IPPROTO_IPV6
, IPV6_V6ONLY
,
772 (const void *) &yes
, sizeof (yes
));
776 if (socktype
== SOCK_STREAM
)
779 if (setsockopt (s
, SOL_SOCKET
, SO_REUSEADDR
,
780 (const void *) &yes
, sizeof (yes
)) < 0)
782 perror ("setsockopt() failed");
789 #if defined(IP_DONTFRAG)
791 if (setsockopt (s
, IPPROTO_IP
, IP_DONTFRAG
,
792 (const void *) &yes
, sizeof (yes
)) < 0)
793 perror ("setsockopt(IP_DF) failed");
794 #elif defined(IP_MTU_DISCOVER)
795 yes
= IP_PMTUDISC_DO
;
796 if (setsockopt (s
, IPPROTO_IP
, IP_MTU_DISCOVER
,
797 (const void *) &yes
, sizeof (yes
)) < 0)
798 perror ("setsockopt(IP_DF) failed");
802 if (bind (s
, ptr
->ai_addr
, ptr
->ai_addrlen
) < 0)
804 perror ("bind() failed");
809 if (socktype
== SOCK_STREAM
)
811 if (listen (s
, 10) < 0)
813 perror ("listen() failed");
818 /* new list entry for the connection */
819 lappend (listener_list
);
820 j
= listener_list
.tail
;
821 j
->listen_socket
= 1;
824 /* Complete earlier message. */
825 fprintf (stderr
, "done\n");
835 /* strips \r\n from the end of the string
841 int len
= strlen (data
);
843 for (i
= 0; i
< len
; i
++)
845 if (data
[i
] == '\r' && data
[i
+ 1] == '\n' && data
[i
+ 1] == 0)
855 get_response (gnutls_session_t session
, char *request
,
856 char **response
, int *response_length
)
862 if (strncmp (request
, "GET ", 4))
865 if (!(h
= strchr (request
, '\n')))
869 while (*h
== '\r' || *h
== '\n')
872 if (!(p
= strchr (request
+ 4, ' ')))
876 /* *response = peer_print_info(session, request+4, h, response_length); */
879 *response
= peer_print_info (session
, response_length
, h
);
884 fprintf (stderr
, "received: %s\n", request
);
885 if (check_command (session
, request
))
888 *response_length
= 0;
891 *response
= strdup (request
);
892 *response_length
= ((*response
) ? strlen (*response
) : 0);
898 *response
= strdup (HTTP_UNIMPLEMENTED
);
899 *response_length
= ((*response
) ? strlen (*response
) : 0);
902 static void terminate (int sig
) __attribute__ ((noreturn
));
907 fprintf (stderr
, "Exiting via signal %d\n", sig
);
913 check_alert (gnutls_session_t session
, int ret
)
915 if (ret
== GNUTLS_E_WARNING_ALERT_RECEIVED
916 || ret
== GNUTLS_E_FATAL_ALERT_RECEIVED
)
918 int last_alert
= gnutls_alert_get (session
);
919 if (last_alert
== GNUTLS_A_NO_RENEGOTIATION
&&
920 ret
== GNUTLS_E_WARNING_ALERT_RECEIVED
)
922 ("* Received NO_RENEGOTIATION alert. Client does not support renegotiation.\n");
924 printf ("* Received alert '%d': %s.\n", last_alert
,
925 gnutls_alert_get_name (last_alert
));
930 tls_log_func (int level
, const char *str
)
932 fprintf (stderr
, "|<%d>| %s", level
, str
);
936 tls_audit_log_func (gnutls_session_t session
, const char *str
)
938 fprintf (stderr
, "|<%p>| %s", session
, str
);
942 main (int argc
, char **argv
)
947 set_program_name (argv
[0]);
948 cmd_parser (argc
, argv
);
951 signal (SIGHUP
, SIG_IGN
);
952 signal (SIGTERM
, terminate
);
953 if (signal (SIGINT
, terminate
) == SIG_IGN
)
954 signal (SIGINT
, SIG_IGN
); /* e.g. background process */
963 strcpy (name
, "UDP ");
969 strcat (name
, "HTTP Server");
973 strcat (name
, "Echo Server");
976 gnutls_global_set_log_function (tls_log_func
);
977 gnutls_global_set_audit_log_function (tls_audit_log_func
);
978 gnutls_global_set_log_level (debug
);
980 if ((ret
= gnutls_global_init ()) < 0)
982 fprintf (stderr
, "global_init: %s\n", gnutls_strerror (ret
));
990 /* Note that servers must generate parameters for
991 * Diffie-Hellman. See gnutls_dh_params_generate(), and
992 * gnutls_dh_params_set().
996 generate_rsa_params ();
997 generate_dh_primes ();
999 else if (dh_params_file
)
1005 static_dh_params ();
1008 if (gnutls_certificate_allocate_credentials (&cert_cred
) < 0)
1010 fprintf (stderr
, "memory error\n");
1014 if (x509_cafile
!= NULL
)
1016 if ((ret
= gnutls_certificate_set_x509_trust_file
1017 (cert_cred
, x509_cafile
, x509ctype
)) < 0)
1019 fprintf (stderr
, "Error reading '%s'\n", x509_cafile
);
1025 printf ("Processed %d CA certificate(s).\n", ret
);
1028 if (x509_crlfile
!= NULL
)
1030 if ((ret
= gnutls_certificate_set_x509_crl_file
1031 (cert_cred
, x509_crlfile
, x509ctype
)) < 0)
1033 fprintf (stderr
, "Error reading '%s'\n", x509_crlfile
);
1039 printf ("Processed %d CRL(s).\n", ret
);
1043 #ifdef ENABLE_OPENPGP
1044 if (pgp_keyring
!= NULL
)
1047 gnutls_certificate_set_openpgp_keyring_file (cert_cred
, pgp_keyring
,
1048 GNUTLS_OPENPGP_FMT_BASE64
);
1051 fprintf (stderr
, "Error setting the OpenPGP keyring file\n");
1056 if (HAVE_OPT (PGPCERTFILE
))
1058 if (HAVE_OPT (PGPSUBKEY
))
1059 ret
= gnutls_certificate_set_openpgp_key_file2
1060 (cert_cred
, pgp_certfile
, pgp_keyfile
, OPT_ARG (PGPSUBKEY
),
1061 GNUTLS_OPENPGP_FMT_BASE64
);
1063 ret
= gnutls_certificate_set_openpgp_key_file
1064 (cert_cred
, pgp_certfile
, pgp_keyfile
, GNUTLS_OPENPGP_FMT_BASE64
);
1069 "Error[%d] while reading the OpenPGP key pair ('%s', '%s')\n",
1070 ret
, pgp_certfile
, pgp_keyfile
);
1076 if (x509_certfile
!= NULL
)
1077 if ((ret
= gnutls_certificate_set_x509_key_file
1078 (cert_cred
, x509_certfile
, x509_keyfile
, x509ctype
)) < 0)
1081 "Error reading '%s' or '%s'\n", x509_certfile
, x509_keyfile
);
1086 if (x509_dsacertfile
!= NULL
)
1087 if ((ret
= gnutls_certificate_set_x509_key_file
1088 (cert_cred
, x509_dsacertfile
, x509_dsakeyfile
, x509ctype
)) < 0)
1090 fprintf (stderr
, "Error reading '%s' or '%s'\n",
1091 x509_dsacertfile
, x509_dsakeyfile
);
1096 if (x509_ecccertfile
!= NULL
)
1097 if ((ret
= gnutls_certificate_set_x509_key_file
1098 (cert_cred
, x509_ecccertfile
, x509_ecckeyfile
, x509ctype
)) < 0)
1100 fprintf (stderr
, "Error reading '%s' or '%s'\n",
1101 x509_ecccertfile
, x509_ecckeyfile
);
1106 /* OCSP status-request TLS extension */
1107 if (status_response_ocsp
)
1109 if (gnutls_certificate_set_ocsp_status_request_file (cert_cred
, status_response_ocsp
, 0) < 0)
1111 fprintf (stderr
, "Cannot set OCSP status request file: %s\n", gnutls_strerror(ret
));
1116 gnutls_certificate_set_params_function (cert_cred
, get_params
);
1117 /* gnutls_certificate_set_dh_params(cert_cred, dh_params);
1118 * gnutls_certificate_set_rsa_export_params(cert_cred, rsa_params);
1121 /* this is a password file (created with the included srpcrypt utility)
1122 * Read README.crypt prior to using SRP.
1125 if (srp_passwd
!= NULL
)
1127 gnutls_srp_allocate_server_credentials (&srp_cred
);
1130 gnutls_srp_set_server_credentials_file (srp_cred
, srp_passwd
,
1131 srp_passwd_conf
)) < 0)
1133 /* only exit is this function is not disabled
1135 fprintf (stderr
, "Error while setting SRP parameters\n");
1141 /* this is a password file
1144 if (psk_passwd
!= NULL
)
1146 gnutls_psk_allocate_server_credentials (&psk_cred
);
1149 gnutls_psk_set_server_credentials_file (psk_cred
, psk_passwd
)) < 0)
1151 /* only exit is this function is not disabled
1153 fprintf (stderr
, "Error while setting PSK parameters\n");
1157 if (HAVE_OPT (PSKHINT
))
1159 ret
= gnutls_psk_set_server_credentials_hint (psk_cred
,
1163 fprintf (stderr
, "Error setting PSK identity hint.\n");
1168 gnutls_psk_set_server_params_function (psk_cred
, get_params
);
1173 gnutls_anon_allocate_server_credentials (&dh_cred
);
1174 gnutls_anon_set_server_params_function (dh_cred
, get_params
);
1176 /* gnutls_anon_set_server_dh_params(dh_cred, dh_params); */
1179 #ifdef ENABLE_SESSION_TICKET
1181 gnutls_session_ticket_key_generate (&session_ticket_key
);
1185 mtu
= OPT_VALUE_MTU
;
1189 if (HAVE_OPT (PORT
))
1190 port
= OPT_VALUE_PORT
;
1195 udp_server (name
, port
, mtu
);
1197 tcp_server (name
, port
);
1201 tcp_server (const char *name
, int port
)
1206 struct sockaddr_storage client_address
;
1209 s
= listen_socket (name
, port
, SOCK_STREAM
);
1225 /* flag which connections we are reading or writing to within the fd sets */
1226 lloopstart (listener_list
, j
)
1230 val
= fcntl (j
->fd
, F_GETFL
, 0);
1231 if ((val
== -1) || (fcntl (j
->fd
, F_SETFL
, val
| O_NONBLOCK
) < 0))
1238 if (j
->listen_socket
)
1240 FD_SET (j
->fd
, &rd
);
1243 if (j
->http_state
== HTTP_STATE_REQUEST
)
1245 FD_SET (j
->fd
, &rd
);
1248 if (j
->http_state
== HTTP_STATE_RESPONSE
)
1250 FD_SET (j
->fd
, &wr
);
1254 lloopend (listener_list
, j
);
1256 /* core operation */
1257 n
= select (n
+ 1, &rd
, &wr
, NULL
, NULL
);
1258 if (n
== -1 && errno
== EINTR
)
1262 perror ("select()");
1266 /* read or write to each connection as indicated by select()'s return argument */
1267 lloopstart (listener_list
, j
)
1270 /* a new connection has arrived */
1271 if (FD_ISSET (j
->fd
, &rd
) && j
->listen_socket
)
1273 gnutls_session_t tls_session
;
1275 tls_session
= initialize_session (0);
1277 calen
= sizeof (client_address
);
1278 memset (&client_address
, 0, calen
);
1279 accept_fd
= accept (j
->fd
, (struct sockaddr
*) &client_address
,
1284 perror ("accept()");
1291 /* new list entry for the connection */
1292 lappend (listener_list
);
1293 j
= listener_list
.tail
;
1294 j
->http_request
= (char *) strdup ("");
1295 j
->http_state
= HTTP_STATE_REQUEST
;
1298 j
->tls_session
= tls_session
;
1299 gnutls_transport_set_ptr (tls_session
,
1300 (gnutls_transport_ptr_t
)
1301 gl_fd_to_handle (accept_fd
));
1302 j
->handshake_ok
= 0;
1308 ctt
[strlen (ctt
) - 1] = 0;
1310 printf ("\n* Accepted connection from %s on %s\n",
1311 human_addr ((struct sockaddr
*)
1312 &client_address
, calen
, topbuf
,
1313 sizeof (topbuf
)), ctt
);
1318 if (FD_ISSET (j
->fd
, &rd
) && !j
->listen_socket
)
1320 /* read partial GET request */
1324 if (j
->handshake_ok
== 0)
1326 r
= gnutls_handshake (j
->tls_session
);
1327 if (r
< 0 && gnutls_error_is_fatal (r
) == 0)
1329 check_alert (j
->tls_session
, r
);
1332 else if (r
< 0 && gnutls_error_is_fatal (r
) == 1)
1334 check_alert (j
->tls_session
, r
);
1335 fprintf (stderr
, "Error in handshake\n");
1341 gnutls_alert_send_appropriate (j
->tls_session
, r
);
1343 while (ret
== GNUTLS_E_AGAIN
1344 || ret
== GNUTLS_E_INTERRUPTED
);
1345 j
->http_state
= HTTP_STATE_CLOSING
;
1349 if (gnutls_session_is_resumed (j
->tls_session
) != 0
1351 printf ("*** This is a resumed session\n");
1355 printf ("\n* Successful handshake from %s\n",
1356 human_addr ((struct sockaddr
*)
1357 &client_address
, calen
, topbuf
,
1359 print_info (j
->tls_session
, verbose
, verbose
);
1360 if (gnutls_auth_get_type (j
->tls_session
) ==
1361 GNUTLS_CRD_CERTIFICATE
)
1362 cert_verify (j
->tls_session
, NULL
);
1364 j
->handshake_ok
= 1;
1368 if (j
->handshake_ok
== 1)
1370 r
= gnutls_record_recv (j
->tls_session
, buf
,
1371 MIN (1024, SMALL_READ_TEST
));
1372 if (r
== GNUTLS_E_HEARTBEAT_PING_RECEIVED
)
1374 gnutls_heartbeat_pong(j
->tls_session
, 0);
1376 if (r
== GNUTLS_E_INTERRUPTED
|| r
== GNUTLS_E_AGAIN
)
1382 if (r
== GNUTLS_E_REHANDSHAKE
)
1384 fprintf (stderr
, "*** Received hello message\n");
1387 r
= gnutls_handshake (j
->tls_session
);
1389 while (r
== GNUTLS_E_INTERRUPTED
1390 || r
== GNUTLS_E_AGAIN
);
1396 ret
= gnutls_alert_send_appropriate
1397 (j
->tls_session
, r
);
1399 while (ret
== GNUTLS_E_AGAIN
1400 || ret
== GNUTLS_E_INTERRUPTED
);
1403 j
->http_state
= HTTP_STATE_CLOSING
;
1410 if (r
!= GNUTLS_E_UNEXPECTED_PACKET_LENGTH
)
1412 j
->http_state
= HTTP_STATE_CLOSING
;
1413 check_alert (j
->tls_session
, r
);
1415 "Error while receiving data\n");
1424 realloc (j
->http_request
, j
->request_length
+ r
+ 1);
1425 if (j
->http_request
!= NULL
)
1427 memcpy (j
->http_request
+ j
->request_length
, buf
, r
);
1428 j
->request_length
+= r
;
1429 j
->http_request
[j
->request_length
] = '\0';
1432 j
->http_state
= HTTP_STATE_CLOSING
;
1435 /* check if we have a full HTTP header */
1437 j
->http_response
= NULL
;
1438 if (j
->http_request
!= NULL
)
1440 if ((http
== 0 && strchr (j
->http_request
, '\n'))
1441 || strstr (j
->http_request
, "\r\n\r\n")
1442 || strstr (j
->http_request
, "\n\n"))
1444 get_response (j
->tls_session
, j
->http_request
,
1445 &j
->http_response
, &j
->response_length
);
1446 j
->http_state
= HTTP_STATE_RESPONSE
;
1447 j
->response_written
= 0;
1452 if (FD_ISSET (j
->fd
, &wr
))
1454 /* write partial response request */
1457 if (j
->handshake_ok
== 0)
1459 r
= gnutls_handshake (j
->tls_session
);
1460 if (r
< 0 && gnutls_error_is_fatal (r
) == 0)
1462 check_alert (j
->tls_session
, r
);
1465 else if (r
< 0 && gnutls_error_is_fatal (r
) == 1)
1469 j
->http_state
= HTTP_STATE_CLOSING
;
1470 check_alert (j
->tls_session
, r
);
1471 fprintf (stderr
, "Error in handshake\n");
1477 gnutls_alert_send_appropriate (j
->tls_session
, r
);
1479 while (ret
== GNUTLS_E_AGAIN
);
1483 if (gnutls_session_is_resumed (j
->tls_session
) != 0
1485 printf ("*** This is a resumed session\n");
1488 printf ("- connection from %s\n",
1489 human_addr ((struct sockaddr
*)
1490 &client_address
, calen
, topbuf
,
1493 print_info (j
->tls_session
, verbose
, verbose
);
1494 if (gnutls_auth_get_type (j
->tls_session
) ==
1495 GNUTLS_CRD_CERTIFICATE
)
1496 cert_verify (j
->tls_session
, NULL
);
1498 j
->handshake_ok
= 1;
1502 if (j
->handshake_ok
== 1 && j
->http_response
!= NULL
)
1504 /* FIXME if j->http_response == NULL? */
1505 r
= gnutls_record_send (j
->tls_session
,
1507 j
->response_written
,
1508 MIN (j
->response_length
-
1509 j
->response_written
,
1511 if (r
== GNUTLS_E_INTERRUPTED
|| r
== GNUTLS_E_AGAIN
)
1518 j
->http_state
= HTTP_STATE_CLOSING
;
1521 j
->http_state
= HTTP_STATE_REQUEST
;
1522 free (j
->http_response
);
1523 j
->response_length
= 0;
1524 j
->request_length
= 0;
1525 j
->http_request
[0] = 0;
1530 fprintf (stderr
, "Error while sending data\n");
1533 check_alert (j
->tls_session
, r
);
1537 j
->response_written
+= r
;
1538 /* check if we have written a complete response */
1539 if (j
->response_written
== j
->response_length
)
1542 j
->http_state
= HTTP_STATE_CLOSING
;
1545 j
->http_state
= HTTP_STATE_REQUEST
;
1546 free (j
->http_response
);
1547 j
->response_length
= 0;
1548 j
->request_length
= 0;
1549 j
->http_request
[0] = 0;
1556 j
->request_length
= 0;
1557 j
->http_request
[0] = 0;
1558 j
->http_state
= HTTP_STATE_REQUEST
;
1562 lloopend (listener_list
, j
);
1564 /* loop through all connections, closing those that are in error */
1565 lloopstart (listener_list
, j
)
1567 if (j
->http_state
== HTTP_STATE_CLOSING
)
1569 ldeleteinc (listener_list
, j
);
1572 lloopend (listener_list
, j
);
1576 gnutls_certificate_free_credentials (cert_cred
);
1580 gnutls_srp_free_server_credentials (srp_cred
);
1585 gnutls_psk_free_server_credentials (psk_cred
);
1589 gnutls_anon_free_server_credentials (dh_cred
);
1592 #ifdef ENABLE_SESSION_TICKET
1594 gnutls_free (session_ticket_key
.data
);
1599 gnutls_global_deinit ();
1604 cmd_parser (int argc
, char **argv
)
1606 optionProcess (&gnutls_servOptions
, argc
, argv
);
1608 disable_client_cert
= HAVE_OPT (DISABLE_CLIENT_CERT
);
1609 require_cert
= HAVE_OPT (REQUIRE_CLIENT_CERT
);
1610 if (HAVE_OPT (DEBUG
))
1611 debug
= OPT_VALUE_DEBUG
;
1613 if (HAVE_OPT (QUIET
))
1616 if (HAVE_OPT (PRIORITY
))
1617 priorities
= OPT_ARG (PRIORITY
);
1619 if (HAVE_OPT (LIST
))
1621 print_list (priorities
, verbose
);
1625 nodb
= HAVE_OPT (NODB
);
1626 noticket
= HAVE_OPT (NOTICKET
);
1628 if (HAVE_OPT (ECHO
))
1633 if (HAVE_OPT (X509FMTDER
))
1634 x509ctype
= GNUTLS_X509_FMT_DER
;
1636 x509ctype
= GNUTLS_X509_FMT_PEM
;
1638 generate
= HAVE_OPT (GENERATE
);
1640 if (HAVE_OPT (DHPARAMS
))
1641 dh_params_file
= OPT_ARG (DHPARAMS
);
1643 if (HAVE_OPT (X509KEYFILE
))
1644 x509_keyfile
= OPT_ARG (X509KEYFILE
);
1645 if (HAVE_OPT (X509CERTFILE
))
1646 x509_certfile
= OPT_ARG (X509CERTFILE
);
1648 if (HAVE_OPT (X509DSAKEYFILE
))
1649 x509_dsakeyfile
= OPT_ARG (X509DSAKEYFILE
);
1650 if (HAVE_OPT (X509DSACERTFILE
))
1651 x509_dsacertfile
= OPT_ARG (X509DSACERTFILE
);
1654 if (HAVE_OPT (X509ECCKEYFILE
))
1655 x509_ecckeyfile
= OPT_ARG (X509ECCKEYFILE
);
1656 if (HAVE_OPT (X509CERTFILE
))
1657 x509_ecccertfile
= OPT_ARG (X509ECCCERTFILE
);
1659 if (HAVE_OPT (X509CAFILE
))
1660 x509_cafile
= OPT_ARG (X509CAFILE
);
1661 if (HAVE_OPT (X509CRLFILE
))
1662 x509_crlfile
= OPT_ARG (X509CRLFILE
);
1664 if (HAVE_OPT (PGPKEYFILE
))
1665 pgp_keyfile
= OPT_ARG (PGPKEYFILE
);
1666 if (HAVE_OPT (PGPCERTFILE
))
1667 pgp_certfile
= OPT_ARG (PGPCERTFILE
);
1669 if (HAVE_OPT (PGPKEYRING
))
1670 pgp_keyring
= OPT_ARG (PGPKEYRING
);
1672 if (HAVE_OPT (SRPPASSWD
))
1673 srp_passwd
= OPT_ARG (SRPPASSWD
);
1674 if (HAVE_OPT (SRPPASSWDCONF
))
1675 srp_passwd_conf
= OPT_ARG (SRPPASSWDCONF
);
1677 if (HAVE_OPT (PSKPASSWD
))
1678 psk_passwd
= OPT_ARG (PSKPASSWD
);
1680 if (HAVE_OPT(OCSP_RESPONSE
))
1681 status_response_ocsp
= OPT_ARG(OCSP_RESPONSE
);
1685 /* session resuming support */
1687 #define SESSION_ID_SIZE 32
1688 #define SESSION_DATA_SIZE 1024
1692 char session_id
[SESSION_ID_SIZE
];
1693 unsigned int session_id_size
;
1695 char session_data
[SESSION_DATA_SIZE
];
1696 unsigned int session_data_size
;
1699 static CACHE
*cache_db
;
1700 int cache_db_ptr
= 0;
1705 /* allocate cache_db */
1706 cache_db
= calloc (1, ssl_session_cache
* sizeof (CACHE
));
1710 wrap_db_deinit (void)
1715 wrap_db_store (void *dbf
, gnutls_datum_t key
, gnutls_datum_t data
)
1718 if (cache_db
== NULL
)
1721 if (key
.size
> SESSION_ID_SIZE
)
1723 if (data
.size
> SESSION_DATA_SIZE
)
1726 memcpy (cache_db
[cache_db_ptr
].session_id
, key
.data
, key
.size
);
1727 cache_db
[cache_db_ptr
].session_id_size
= key
.size
;
1729 memcpy (cache_db
[cache_db_ptr
].session_data
, data
.data
, data
.size
);
1730 cache_db
[cache_db_ptr
].session_data_size
= data
.size
;
1733 cache_db_ptr
%= ssl_session_cache
;
1738 static gnutls_datum_t
1739 wrap_db_fetch (void *dbf
, gnutls_datum_t key
)
1741 gnutls_datum_t res
= { NULL
, 0 };
1744 if (cache_db
== NULL
)
1747 for (i
= 0; i
< ssl_session_cache
; i
++)
1749 if (key
.size
== cache_db
[i
].session_id_size
&&
1750 memcmp (key
.data
, cache_db
[i
].session_id
, key
.size
) == 0)
1752 res
.size
= cache_db
[i
].session_data_size
;
1754 res
.data
= gnutls_malloc (res
.size
);
1755 if (res
.data
== NULL
)
1758 memcpy (res
.data
, cache_db
[i
].session_data
, res
.size
);
1767 wrap_db_delete (void *dbf
, gnutls_datum_t key
)
1771 if (cache_db
== NULL
)
1774 for (i
= 0; i
< ssl_session_cache
; i
++)
1776 if (key
.size
== (unsigned int) cache_db
[i
].session_id_size
&&
1777 memcmp (key
.data
, cache_db
[i
].session_id
, key
.size
) == 0)
1780 cache_db
[i
].session_id_size
= 0;
1781 cache_db
[i
].session_data_size
= 0;