2 * Copyright (C) 2004, 2006, 2007 Free Software Foundation
3 * Copyright (C) 2001,2002 Paul Sheer
4 * Portions Copyright (C) 2002,2003 Nikos Mavroyanopoulos
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 2 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, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 /* This server is heavily modified for GNUTLS by Nikos Mavroyanopoulos
24 * (which means it is quite unreadable)
32 #include <sys/types.h>
34 #include <gnutls/gnutls.h>
35 #include <gnutls/extra.h>
40 #if defined _WIN32 || defined __WIN32__
41 #define select _win_select
45 #include "read-file.h"
47 #include "getaddrinfo.h"
49 /* konqueror cannot handle sending the page in multiple
53 static int generate
= 0;
62 int disable_client_cert
;
66 char *srp_passwd_conf
;
73 char *x509_dsakeyfile
;
74 char *x509_dsacertfile
;
77 char *x509_crlfile
= NULL
;
81 /* This is a sample TCP echo server.
82 * This will behave as an http server if any argument in the
83 * command line is present
86 #define SMALL_READ_TEST (2147483647)
88 #define SA struct sockaddr
89 #define ERR(err,s) if(err==-1) {perror(s);return(1);}
90 #define GERR(ret) fprintf(stdout, "Error: %s\n", safe_strerror(ret))
94 #define max(x,y) ((x) > (y) ? (x) : (y))
96 #define min(x,y) ((x) < (y) ? (x) : (y))
99 #define HTTP_END "</BODY></HTML>\n\n"
101 #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"
102 #define HTTP_OK "HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n"
104 #define HTTP_BEGIN HTTP_OK \
107 "<CENTER><H1>This is <a href=\"http://www.gnu.org/software/gnutls\">" \
108 "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
;
120 const int ssl_session_cache
= 128;
122 static void wrap_db_init (void);
123 static void wrap_db_deinit (void);
124 static int wrap_db_store (void *dbf
, gnutls_datum_t key
, gnutls_datum_t data
);
125 static gnutls_datum_t
wrap_db_fetch (void *dbf
, gnutls_datum_t key
);
126 static int wrap_db_delete (void *dbf
, gnutls_datum_t key
);
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
;
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
)
153 free (j
->http_request
);
154 if (j
->http_response
)
155 free (j
->http_response
);
158 gnutls_bye (j
->tls_session
, GNUTLS_SHUT_WR
);
161 gnutls_deinit (j
->tls_session
);
166 /* we use primes up to 1024 in this server.
167 * otherwise we should add them here.
170 gnutls_dh_params_t dh_params
= NULL
;
171 gnutls_rsa_params_t rsa_params
= NULL
;
174 generate_dh_primes (void)
176 int prime_bits
= 768;
178 if (gnutls_dh_params_init (&dh_params
) < 0)
180 fprintf (stderr
, "Error in dh parameter initialization\n");
184 /* Generate Diffie Hellman parameters - for use with DHE
185 * kx algorithms. These should be discarded and regenerated
186 * once a week or once a month. Depends on the
187 * security requirements.
190 ("Generating Diffie Hellman parameters [%d]. Please wait...\n",
194 if (gnutls_dh_params_generate2 (dh_params
, prime_bits
) < 0)
196 fprintf (stderr
, "Error in prime generation\n");
204 read_dh_params (void)
208 gnutls_datum_t params
;
211 if (gnutls_dh_params_init (&dh_params
) < 0)
213 fprintf (stderr
, "Error in dh parameter initialization\n");
217 /* read the params file
219 fd
= fopen (dh_params_file
, "r");
222 fprintf (stderr
, "Could not open %s\n", dh_params_file
);
226 size
= fread (tmpdata
, 1, sizeof (tmpdata
) - 1, fd
);
230 params
.data
= (unsigned char *) tmpdata
;
234 gnutls_dh_params_import_pkcs3 (dh_params
, ¶ms
, GNUTLS_X509_FMT_PEM
);
238 fprintf (stderr
, "Error parsing dh params: %s\n", safe_strerror (size
));
242 printf ("Read Diffie Hellman parameters.\n");
247 static char pkcs3
[] =
248 "-----BEGIN DH PARAMETERS-----\n"
249 "MIGGAoGAtkxw2jlsVCsrfLqxrN+IrF/3W8vVFvDzYbLmxi2GQv9s/PQGWP1d9i22\n"
250 "P2DprfcJknWt7KhCI1SaYseOQIIIAYP78CfyIpGScW/vS8khrw0rlQiyeCvQgF3O\n"
251 "GeGOEywcw+oQT4SmFOD7H0smJe2CNyjYpexBXQ/A0mbTF9QKm1cCAQU=\n"
252 "-----END DH PARAMETERS-----\n";
255 static_dh_params (void)
257 gnutls_datum_t params
= { pkcs3
, sizeof (pkcs3
) };
260 if (gnutls_dh_params_init (&dh_params
) < 0)
262 fprintf (stderr
, "Error in dh parameter initialization\n");
266 ret
= gnutls_dh_params_import_pkcs3 (dh_params
, ¶ms
, 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 static int protocol_priority
[PRI_MAX
];
334 static int kx_priority
[PRI_MAX
];
335 static int cipher_priority
[PRI_MAX
];
336 static int comp_priority
[PRI_MAX
];
337 static int mac_priority
[PRI_MAX
];
338 static int cert_type_priority
[PRI_MAX
];
341 static int authz_server_formats
[PRI_MAX
] = {
344 static int authz_client_formats
[PRI_MAX
] = {
345 GNUTLS_AUTHZ_X509_ATTR_CERT
,
346 GNUTLS_AUTHZ_SAML_ASSERTION
,
347 GNUTLS_AUTHZ_X509_ATTR_CERT_URL
,
348 GNUTLS_AUTHZ_SAML_ASSERTION_URL
,
353 authz_send_callback (gnutls_session_t session
,
354 const int *client_formats
,
355 const int *server_formats
)
360 printf ("- Client authorization formats: ");
361 for (i
= 0; client_formats
[i
]; i
++)
362 printf ("%d ", client_formats
[i
]);
365 for (i
= 0; server_formats
[i
]; i
++)
367 if (server_formats
[i
] == GNUTLS_AUTHZ_X509_ATTR_CERT
368 && info
.authz_x509_attr_cert
)
371 const char *x509ac
= read_binary_file (info
.authz_x509_attr_cert
,
374 error (EXIT_FAILURE
, errno
, "%s", info
.authz_x509_attr_cert
);
376 printf (" Sending X.509 Attribute Certificate\n");
378 ret
= gnutls_authz_send_x509_attr_cert (session
,
384 if (server_formats
[i
] == GNUTLS_AUTHZ_SAML_ASSERTION
385 && info
.authz_saml_assertion
)
388 const char *samlass
= read_binary_file (info
.authz_saml_assertion
,
391 error (EXIT_FAILURE
, errno
, "%s", info
.authz_saml_assertion
);
393 printf (" Sending SAML assertion\n");
395 ret
= gnutls_authz_send_saml_assertion (session
,
396 samlass
, samlass_len
);
406 authz_recv_callback (gnutls_session_t session
,
407 const int *authz_formats
,
408 gnutls_datum_t
*infos
,
409 const int *hashtypes
,
410 gnutls_datum_t
*hash
)
414 for (i
= 0; authz_formats
[i
]; i
++)
416 printf ("- Received authorization data, format %02x of %d bytes\n",
417 authz_formats
[i
], infos
[i
].size
);
420 for (j
= 0; j
< infos
[i
].size
; j
++)
421 printf ("%02x", infos
[i
].data
[j
]);
424 if (hash
[i
].size
> 0)
427 for (j
= 0; j
< hash
[i
].size
; j
++)
428 printf ("%02x", hash
[i
].data
[j
]);
429 printf (" type %02x\n", hashtypes
[i
]);
439 oprfi_callback (gnutls_session_t session
,
442 const unsigned char *in_oprfi
,
443 unsigned char *out_oprfi
)
445 size_t ourlen
= strlen (info
.opaque_prf_input
);
448 printf ("- Received Opaque PRF data of %d bytes\n", oprfi_len
);
450 for (i
= 0; i
< oprfi_len
; i
++)
451 printf ("%02x", in_oprfi
[i
]);
454 memset(out_oprfi
, 0, oprfi_len
);
455 strncpy (out_oprfi
, info
.opaque_prf_input
, oprfi_len
);
462 initialize_session (void)
464 gnutls_session_t session
;
466 gnutls_init (&session
, GNUTLS_SERVER
);
468 /* allow the use of private ciphersuites.
470 gnutls_handshake_set_private_extensions (session
, 1);
474 gnutls_db_set_retrieve_function (session
, wrap_db_fetch
);
475 gnutls_db_set_remove_function (session
, wrap_db_delete
);
476 gnutls_db_set_store_function (session
, wrap_db_store
);
477 gnutls_db_set_ptr (session
, NULL
);
480 gnutls_set_default_priority (session
);
482 if (cipher_priority
[0])
483 gnutls_cipher_set_priority (session
, cipher_priority
);
484 if (comp_priority
[0])
485 gnutls_compression_set_priority (session
, comp_priority
);
487 gnutls_kx_set_priority (session
, kx_priority
);
488 if (protocol_priority
[0])
489 gnutls_protocol_set_priority (session
, protocol_priority
);
491 gnutls_mac_set_priority (session
, mac_priority
);
492 if (cert_type_priority
[0])
493 gnutls_certificate_type_set_priority (session
, cert_type_priority
);
495 gnutls_credentials_set (session
, GNUTLS_CRD_ANON
, dh_cred
);
497 if (srp_cred
!= NULL
)
498 gnutls_credentials_set (session
, GNUTLS_CRD_SRP
, srp_cred
);
500 if (psk_cred
!= NULL
)
501 gnutls_credentials_set (session
, GNUTLS_CRD_PSK
, psk_cred
);
503 if (cert_cred
!= NULL
)
504 gnutls_credentials_set (session
, GNUTLS_CRD_CERTIFICATE
, cert_cred
);
506 if (disable_client_cert
)
507 gnutls_certificate_server_set_request (session
, GNUTLS_CERT_IGNORE
);
510 gnutls_certificate_server_set_request (session
, GNUTLS_CERT_REQUIRE
);
512 gnutls_certificate_server_set_request (session
, GNUTLS_CERT_REQUEST
);
516 gnutls_authz_enable (session
, authz_client_formats
, authz_server_formats
,
517 authz_recv_callback
, authz_send_callback
);
521 if (info
.opaque_prf_input
)
522 gnutls_oprfi_enable_server (session
, oprfi_callback
, NULL
);
528 #include <gnutls/x509.h>
530 static const char DEFAULT_DATA
[] =
531 "This is the default message reported by the GnuTLS implementation. "
532 "For more information please visit "
533 "<a href=\"http://www.gnutls.org/\">http://www.gnutls.org/</a>.";
535 /* Creates html with the current session information.
537 #define tmp2 &http_buffer[strlen(http_buffer)]
539 peer_print_info (gnutls_session_t session
, int *ret_length
, const char *header
)
542 unsigned char sesid
[32];
543 size_t i
, sesid_size
;
545 gnutls_kx_algorithm_t kx_alg
;
546 size_t len
= 5 * 1024 + strlen (header
);
547 char *crtinfo
= NULL
;
552 http_buffer
= malloc (len
);
553 if (http_buffer
== NULL
)
556 strcpy (http_buffer
, HTTP_BEGIN
);
557 strcpy (&http_buffer
[sizeof (HTTP_BEGIN
) - 1], DEFAULT_DATA
);
558 strcpy (&http_buffer
[sizeof (HTTP_BEGIN
) + sizeof (DEFAULT_DATA
) - 2],
561 sizeof (DEFAULT_DATA
) + sizeof (HTTP_BEGIN
) + sizeof (HTTP_END
) - 3;
566 if (gnutls_certificate_type_get (session
) == GNUTLS_CRT_X509
)
568 const gnutls_datum_t
*cert_list
;
569 unsigned int cert_list_size
= 0;
572 cert_list
= gnutls_certificate_get_peers (session
, &cert_list_size
);
574 for (i
= 0; i
< cert_list_size
; i
++)
576 gnutls_x509_crt_t cert
;
579 if (gnutls_x509_crt_init (&cert
) == 0 &&
580 gnutls_x509_crt_import (cert
, &cert_list
[i
],
581 GNUTLS_X509_FMT_DER
) == 0 &&
582 gnutls_x509_crt_print (cert
, GNUTLS_X509_CRT_FULL
, &info
) == 0)
584 const char *post
= "</PRE><P><PRE>";
586 crtinfo
= realloc (crtinfo
, ncrtinfo
+ info
.size
+
590 memcpy (crtinfo
+ ncrtinfo
, info
.data
, info
.size
);
591 ncrtinfo
+= info
.size
;
592 memcpy (crtinfo
+ ncrtinfo
, post
, strlen (post
));
593 ncrtinfo
+= strlen (post
);
594 crtinfo
[ncrtinfo
] = '\0';
595 gnutls_free (info
.data
);
600 http_buffer
= malloc (len
);
601 if (http_buffer
== NULL
)
604 strcpy (http_buffer
, HTTP_BEGIN
);
606 /* print session_id */
607 gnutls_session_get_id (session
, sesid
, &sesid_size
);
608 sprintf (tmp2
, "\n<p>Session ID: <i>");
609 for (i
= 0; i
< sesid_size
; i
++)
610 sprintf (tmp2
, "%.2X", sesid
[i
]);
611 sprintf (tmp2
, "</i></p>\n");
613 "<h5>If your browser supports session resuming, then you should see the "
614 "same session ID, when you press the <b>reload</b> button.</h5>\n");
616 /* Here unlike print_info() we use the kx algorithm to distinguish
617 * the functions to call.
621 size_t dns_size
= sizeof (dns
);
624 if (gnutls_server_name_get (session
, dns
, &dns_size
, &type
, 0) == 0)
626 sprintf (tmp2
, "\n<p>Server Name: %s</p>\n", dns
);
631 kx_alg
= gnutls_kx_get (session
);
633 /* print srp specific data */
635 if (kx_alg
== GNUTLS_KX_SRP
)
637 sprintf (tmp2
, "<p>Connected as user '%s'.</p>\n",
638 gnutls_srp_server_get_username (session
));
643 if (kx_alg
== GNUTLS_KX_PSK
)
645 sprintf (tmp2
, "<p>Connected as user '%s'.</p>\n",
646 gnutls_psk_server_get_username (session
));
651 if (kx_alg
== GNUTLS_KX_ANON_DH
)
654 "<p> Connect using anonymous DH (prime of %d bits)</p>\n",
655 gnutls_dh_get_prime_bits (session
));
659 if (kx_alg
== GNUTLS_KX_DHE_RSA
|| kx_alg
== GNUTLS_KX_DHE_DSS
)
662 "Ephemeral DH using prime of <b>%d</b> bits.<br>\n",
663 gnutls_dh_get_prime_bits (session
));
666 /* print session information */
667 strcat (http_buffer
, "<P>\n");
669 tmp
= gnutls_protocol_get_name (gnutls_protocol_get_version (session
));
673 "<TABLE border=1><TR><TD>Protocol version:</TD><TD>%s</TD></TR>\n",
676 if (gnutls_auth_get_type (session
) == GNUTLS_CRD_CERTIFICATE
)
679 gnutls_certificate_type_get_name (gnutls_certificate_type_get
683 sprintf (tmp2
, "<TR><TD>Certificate Type:</TD><TD>%s</TD></TR>\n", tmp
);
686 tmp
= gnutls_kx_get_name (kx_alg
);
689 sprintf (tmp2
, "<TR><TD>Key Exchange:</TD><TD>%s</TD></TR>\n", tmp
);
691 tmp
= gnutls_compression_get_name (gnutls_compression_get (session
));
694 sprintf (tmp2
, "<TR><TD>Compression</TD><TD>%s</TD></TR>\n", tmp
);
696 tmp
= gnutls_cipher_get_name (gnutls_cipher_get (session
));
699 sprintf (tmp2
, "<TR><TD>Cipher</TD><TD>%s</TD></TR>\n", tmp
);
701 tmp
= gnutls_mac_get_name (gnutls_mac_get (session
));
704 sprintf (tmp2
, "<TR><TD>MAC</TD><TD>%s</TD></TR>\n", tmp
);
706 tmp
= gnutls_cipher_suite_get_name (kx_alg
,
707 gnutls_cipher_get (session
),
708 gnutls_mac_get (session
));
711 sprintf (tmp2
, "<TR><TD>Ciphersuite</TD><TD>%s</TD></TR></p></TABLE>\n",
716 strcat (http_buffer
, "<hr><PRE>");
717 strcat (http_buffer
, crtinfo
);
718 strcat (http_buffer
, "\n</PRE>\n");
721 strcat (http_buffer
, "<hr><P>Your HTTP header was:<PRE>");
722 strcat (http_buffer
, header
);
723 strcat (http_buffer
, "</PRE></P>");
725 strcat (http_buffer
, "\n" HTTP_END
);
727 *ret_length
= strlen (http_buffer
);
733 listen_socket (const char *name
, int listen_port
)
735 struct addrinfo hints
, *res
, *ptr
;
740 snprintf (portname
, sizeof (portname
), "%d", listen_port
);
741 memset (&hints
, 0, sizeof (hints
));
742 hints
.ai_socktype
= SOCK_STREAM
;
743 hints
.ai_flags
= AI_PASSIVE
;
745 if ((s
= getaddrinfo (NULL
, portname
, &hints
, &res
)) != 0)
747 fprintf (stderr
, "getaddrinfo() failed: %s\n", gai_strerror (s
));
752 for (ptr
= res
; (ptr
!= NULL
) && (s
== -1); ptr
= ptr
->ai_next
)
754 if ((s
= socket (ptr
->ai_family
, ptr
->ai_socktype
, ptr
->ai_protocol
)) < 0)
756 perror ("socket() failed");
762 (s
, SOL_SOCKET
, SO_REUSEADDR
, (const void *) &yes
, sizeof (yes
)) < 0)
764 perror ("setsockopt() failed");
771 if (bind (s
, res
->ai_addr
, res
->ai_addrlen
) < 0)
773 perror ("bind() failed");
777 if (listen (s
, 10) < 0)
779 perror ("listen() failed");
790 printf ("%s ready. Listening to port '%s'.\n\n", name
, portname
);
795 get_response (gnutls_session_t session
, char *request
,
796 char **response
, int *response_length
)
802 if (strncmp (request
, "GET ", 4))
805 if (!(h
= strchr (request
, '\n')))
809 while (*h
== '\r' || *h
== '\n')
812 if (!(p
= strchr (request
+ 4, ' ')))
816 /* *response = peer_print_info(session, request+4, h, response_length); */
819 *response
= peer_print_info (session
, response_length
, h
);
823 *response
= strdup (request
);
824 *response_length
= ((*response
) ? strlen (*response
) : 0);
830 *response
= strdup (HTTP_UNIMPLEMENTED
);
831 *response_length
= ((*response
) ? strlen (*response
) : 0);
837 fprintf (stderr
, "Exiting via signal %d\n", sig
);
843 check_alert (gnutls_session_t session
, int ret
)
845 if (ret
== GNUTLS_E_WARNING_ALERT_RECEIVED
846 || ret
== GNUTLS_E_FATAL_ALERT_RECEIVED
)
848 int last_alert
= gnutls_alert_get (session
);
849 if (last_alert
== GNUTLS_A_NO_RENEGOTIATION
&&
850 ret
== GNUTLS_E_WARNING_ALERT_RECEIVED
)
852 ("* Received NO_RENEGOTIATION alert. Client does not support renegotiation.\n");
854 printf ("* Received alert '%d': %s.\n", last_alert
,
855 gnutls_alert_get_name (last_alert
));
860 tls_log_func (int level
, const char *str
)
862 fprintf (stderr
, "|<%d>| %s", level
, str
);
865 static void gaa_parser (int argc
, char **argv
);
867 static int get_port (const struct sockaddr_storage
*addr
)
869 switch (addr
->ss_family
)
872 return ntohs (((const struct sockaddr_in6
*)addr
)->sin6_port
);
874 return ntohs (((const struct sockaddr_in
*)addr
)->sin_port
);
879 static const char *addr_ntop (const struct sockaddr
*sa
, socklen_t salen
,
880 char *buf
, size_t buflen
)
882 if (getnameinfo (sa
, salen
, buf
, buflen
, NULL
, 0, NI_NUMERICHOST
) == 0)
890 main (int argc
, char **argv
)
896 struct sockaddr_storage client_address
;
900 signal (SIGPIPE
, SIG_IGN
);
901 signal (SIGHUP
, SIG_IGN
);
902 signal (SIGTERM
, terminate
);
903 if (signal (SIGINT
, terminate
) == SIG_IGN
)
904 signal (SIGINT
, SIG_IGN
); /* e.g. background process */
909 gaa_parser (argc
, argv
);
916 strcpy (name
, "HTTP Server");
920 strcpy (name
, "Echo Server");
923 if ((ret
= gnutls_global_init ()) < 0)
925 fprintf (stderr
, "global_init: %s\n", gnutls_strerror (ret
));
928 gnutls_global_set_log_function (tls_log_func
);
929 gnutls_global_set_log_level (debug
);
931 if ((ret
= gnutls_global_init_extra ()) < 0)
933 fprintf (stderr
, "global_init_extra: %s\n", gnutls_strerror (ret
));
937 /* Note that servers must generate parameters for
938 * Diffie Hellman. See gnutls_dh_params_generate(), and
939 * gnutls_dh_params_set().
943 generate_rsa_params ();
944 generate_dh_primes ();
946 else if (dh_params_file
)
955 if (gnutls_certificate_allocate_credentials (&cert_cred
) < 0)
957 fprintf (stderr
, "memory error\n");
961 if (x509_cafile
!= NULL
)
963 if ((ret
= gnutls_certificate_set_x509_trust_file
964 (cert_cred
, x509_cafile
, x509ctype
)) < 0)
966 fprintf (stderr
, "Error reading '%s'\n", x509_cafile
);
972 printf ("Processed %d CA certificate(s).\n", ret
);
976 if (x509_crlfile
!= NULL
)
978 if ((ret
= gnutls_certificate_set_x509_crl_file
979 (cert_cred
, x509_crlfile
, x509ctype
)) < 0)
981 fprintf (stderr
, "Error reading '%s'\n", x509_crlfile
);
987 printf ("Processed %d CRL(s).\n", ret
);
992 #ifdef ENABLE_OPENPGP
993 if (pgp_keyring
!= NULL
)
996 gnutls_certificate_set_openpgp_keyring_file (cert_cred
, pgp_keyring
);
999 fprintf (stderr
, "Error setting the OpenPGP keyring file\n");
1004 if (pgp_trustdb
!= NULL
)
1006 ret
= gnutls_certificate_set_openpgp_trustdb (cert_cred
, pgp_trustdb
);
1009 fprintf (stderr
, "Error setting the OpenPGP trustdb file\n");
1014 if (pgp_certfile
!= NULL
)
1015 if ((ret
= gnutls_certificate_set_openpgp_key_file
1016 (cert_cred
, pgp_certfile
, pgp_keyfile
)) < 0)
1019 "Error[%d] while reading the OpenPGP key pair ('%s', '%s')\n",
1020 ret
, pgp_certfile
, pgp_keyfile
);
1025 if (x509_certfile
!= NULL
)
1026 if ((ret
= gnutls_certificate_set_x509_key_file
1027 (cert_cred
, x509_certfile
, x509_keyfile
, x509ctype
)) < 0)
1030 "Error reading '%s' or '%s'\n", x509_certfile
, x509_keyfile
);
1035 if (x509_dsacertfile
!= NULL
)
1036 if ((ret
= gnutls_certificate_set_x509_key_file
1037 (cert_cred
, x509_dsacertfile
, x509_dsakeyfile
, x509ctype
)) < 0)
1039 fprintf (stderr
, "Error reading '%s' or '%s'\n",
1040 x509_dsacertfile
, x509_dsakeyfile
);
1045 gnutls_certificate_set_params_function (cert_cred
, get_params
);
1046 /* gnutls_certificate_set_dh_params(cert_cred, dh_params);
1047 * gnutls_certificate_set_rsa_export_params(cert_cred, rsa_params);
1050 /* this is a password file (created with the included srpcrypt utility)
1051 * Read README.crypt prior to using SRP.
1054 if (srp_passwd
!= NULL
)
1056 gnutls_srp_allocate_server_credentials (&srp_cred
);
1059 gnutls_srp_set_server_credentials_file (srp_cred
, srp_passwd
,
1060 srp_passwd_conf
)) < 0)
1062 /* only exit is this function is not disabled
1064 fprintf (stderr
, "Error while setting SRP parameters\n");
1070 /* this is a password file
1073 if (psk_passwd
!= NULL
)
1075 gnutls_psk_allocate_server_credentials (&psk_cred
);
1078 gnutls_psk_set_server_credentials_file (psk_cred
, psk_passwd
)) < 0)
1080 /* only exit is this function is not disabled
1082 fprintf (stderr
, "Error while setting PSK parameters\n");
1086 gnutls_psk_set_server_params_function (psk_cred
, get_params
);
1091 gnutls_anon_allocate_server_credentials (&dh_cred
);
1092 gnutls_anon_set_server_params_function (dh_cred
, get_params
);
1094 /* gnutls_anon_set_server_dh_params(dh_cred, dh_params); */
1097 h
= listen_socket (name
, port
);
1111 /* check for new incoming connections */
1115 /* flag which connections we are reading or writing to within the fd sets */
1116 lloopstart (listener_list
, j
)
1120 val
= fcntl (j
->fd
, F_GETFL
, 0);
1121 if ((val
== -1) || (fcntl (j
->fd
, F_SETFL
, val
| O_NONBLOCK
) < 0))
1128 if (j
->http_state
== HTTP_STATE_REQUEST
)
1130 FD_SET (j
->fd
, &rd
);
1133 if (j
->http_state
== HTTP_STATE_RESPONSE
)
1135 FD_SET (j
->fd
, &wr
);
1139 lloopend (listener_list
, j
);
1141 /* core operation */
1142 n
= select (n
+ 1, &rd
, &wr
, NULL
, NULL
);
1143 if (n
== -1 && errno
== EINTR
)
1147 perror ("select()");
1151 /* a new connection has arrived */
1152 if (FD_ISSET (h
, &rd
))
1154 gnutls_session_t tls_session
;
1156 tls_session
= initialize_session ();
1158 calen
= sizeof (client_address
);
1159 memset (&client_address
, 0, calen
);
1160 accept_fd
= accept (h
, (struct sockaddr
*) &client_address
, &calen
);
1164 perror ("accept()");
1171 /* new list entry for the connection */
1172 lappend (listener_list
);
1173 j
= listener_list
.tail
;
1174 j
->http_request
= (char *) strdup ("");
1175 j
->http_state
= HTTP_STATE_REQUEST
;
1178 j
->tls_session
= tls_session
;
1179 gnutls_transport_set_ptr (tls_session
,
1180 (gnutls_transport_ptr_t
) accept_fd
);
1181 j
->handshake_ok
= 0;
1187 ctt
[strlen (ctt
) - 1] = 0;
1190 printf("\n* connection from %s, port %d\n",
1191 inet_ntop(AF_INET, &client_address.sin_addr, topbuf,
1192 sizeof(topbuf)), ntohs(client_address.sin_port));
1199 /* read or write to each connection as indicated by select()'s return argument */
1200 lloopstart (listener_list
, j
)
1202 if (FD_ISSET (j
->fd
, &rd
))
1204 /* read partial GET request */
1208 if (j
->handshake_ok
== 0)
1210 r
= gnutls_handshake (j
->tls_session
);
1211 if (r
< 0 && gnutls_error_is_fatal (r
) == 0)
1213 check_alert (j
->tls_session
, r
);
1216 else if (r
< 0 && gnutls_error_is_fatal (r
) == 1)
1218 check_alert (j
->tls_session
, r
);
1219 fprintf (stderr
, "Error in handshake\n");
1225 gnutls_alert_send_appropriate (j
->tls_session
, r
);
1227 while (ret
== GNUTLS_E_AGAIN
);
1228 j
->http_state
= HTTP_STATE_CLOSING
;
1232 if (gnutls_session_is_resumed (j
->tls_session
) != 0
1234 printf ("*** This is a resumed session\n");
1238 printf ("\n* connection from %s, port %d\n",
1239 addr_ntop ((struct sockaddr
*)&client_address
, calen
,
1240 topbuf
, sizeof (topbuf
)),
1241 get_port (&client_address
));
1242 print_info (j
->tls_session
, NULL
);
1244 j
->handshake_ok
= 1;
1248 if (j
->handshake_ok
== 1)
1250 r
= gnutls_record_recv (j
->tls_session
, buf
,
1251 min (1024, SMALL_READ_TEST
));
1252 if (r
== GNUTLS_E_INTERRUPTED
|| r
== GNUTLS_E_AGAIN
)
1258 j
->http_state
= HTTP_STATE_CLOSING
;
1259 if (r
< 0 && r
!= GNUTLS_E_UNEXPECTED_PACKET_LENGTH
)
1261 check_alert (j
->tls_session
, r
);
1262 fprintf (stderr
, "Error while receiving data\n");
1270 realloc (j
->http_request
, j
->request_length
+ r
+ 1);
1271 if (j
->http_request
!= NULL
)
1273 memcpy (j
->http_request
+ j
->request_length
, buf
, r
);
1274 j
->request_length
+= r
;
1275 j
->http_request
[j
->request_length
] = '\0';
1278 j
->http_state
= HTTP_STATE_CLOSING
;
1281 /* check if we have a full HTTP header */
1283 j
->http_response
= NULL
;
1284 if (j
->http_request
!= NULL
)
1286 if ((http
== 0 && strchr (j
->http_request
, '\n'))
1287 || strstr (j
->http_request
, "\r\n\r\n")
1288 || strstr (j
->http_request
, "\n\n"))
1290 get_response (j
->tls_session
, j
->http_request
,
1291 &j
->http_response
, &j
->response_length
);
1292 j
->http_state
= HTTP_STATE_RESPONSE
;
1293 j
->response_written
= 0;
1298 if (FD_ISSET (j
->fd
, &wr
))
1300 /* write partial response request */
1303 if (j
->handshake_ok
== 0)
1305 r
= gnutls_handshake (j
->tls_session
);
1306 if (r
< 0 && gnutls_error_is_fatal (r
) == 0)
1308 check_alert (j
->tls_session
, r
);
1311 else if (r
< 0 && gnutls_error_is_fatal (r
) == 1)
1315 j
->http_state
= HTTP_STATE_CLOSING
;
1316 check_alert (j
->tls_session
, r
);
1317 fprintf (stderr
, "Error in handshake\n");
1323 gnutls_alert_send_appropriate (j
->tls_session
, r
);
1325 while (ret
== GNUTLS_E_AGAIN
);
1329 if (gnutls_session_is_resumed (j
->tls_session
) != 0
1331 printf ("*** This is a resumed session\n");
1334 printf ("- connection from %s, port %d\n",
1335 addr_ntop ((struct sockaddr
*) &client_address
, calen
,
1336 topbuf
, sizeof (topbuf
)),
1337 get_port (&client_address
));
1339 print_info (j
->tls_session
, NULL
);
1341 j
->handshake_ok
= 1;
1345 if (j
->handshake_ok
== 1)
1347 /* FIXME if j->http_response == NULL? */
1348 r
= gnutls_record_send (j
->tls_session
,
1350 j
->response_written
,
1351 min (j
->response_length
-
1352 j
->response_written
,
1354 if (r
== GNUTLS_E_INTERRUPTED
|| r
== GNUTLS_E_AGAIN
)
1361 j
->http_state
= HTTP_STATE_CLOSING
;
1364 j
->http_state
= HTTP_STATE_REQUEST
;
1365 free (j
->http_response
);
1366 j
->response_length
= 0;
1367 j
->request_length
= 0;
1368 j
->http_request
[0] = 0;
1373 fprintf (stderr
, "Error while sending data\n");
1376 check_alert (j
->tls_session
, r
);
1380 j
->response_written
+= r
;
1381 /* check if we have written a complete response */
1382 if (j
->response_written
== j
->response_length
)
1385 j
->http_state
= HTTP_STATE_CLOSING
;
1388 j
->http_state
= HTTP_STATE_REQUEST
;
1389 free (j
->http_response
);
1390 j
->response_length
= 0;
1391 j
->request_length
= 0;
1392 j
->http_request
[0] = 0;
1399 lloopend (listener_list
, j
);
1401 /* loop through all connections, closing those that are in error */
1402 lloopstart (listener_list
, j
)
1404 if (j
->http_state
== HTTP_STATE_CLOSING
)
1406 ldeleteinc (listener_list
, j
);
1409 lloopend (listener_list
, j
);
1413 gnutls_certificate_free_credentials (cert_cred
);
1417 gnutls_srp_free_server_credentials (srp_cred
);
1422 gnutls_psk_free_server_credentials (psk_cred
);
1426 gnutls_anon_free_server_credentials (dh_cred
);
1431 gnutls_global_deinit ();
1438 gaa_parser (int argc
, char **argv
)
1440 if (gaa (argc
, argv
, &info
) != -1)
1443 "Error in the arguments. Use the --help or -h parameters to get more information.\n");
1447 disable_client_cert
= info
.disable_client_cert
;
1448 require_cert
= info
.require_cert
;
1450 verbose
= info
.quiet
;
1458 if (info
.fmtder
== 0)
1459 x509ctype
= GNUTLS_X509_FMT_PEM
;
1461 x509ctype
= GNUTLS_X509_FMT_DER
;
1463 if (info
.generate
== 0)
1468 dh_params_file
= info
.dh_params_file
;
1472 x509_certfile
= info
.x509_certfile
;
1473 x509_keyfile
= info
.x509_keyfile
;
1474 x509_dsacertfile
= info
.x509_dsacertfile
;
1475 x509_dsakeyfile
= info
.x509_dsakeyfile
;
1476 x509_cafile
= info
.x509_cafile
;
1477 x509_crlfile
= info
.x509_crlfile
;
1478 pgp_certfile
= info
.pgp_certfile
;
1479 pgp_keyfile
= info
.pgp_keyfile
;
1480 srp_passwd
= info
.srp_passwd
;
1481 srp_passwd_conf
= info
.srp_passwd_conf
;
1483 psk_passwd
= info
.psk_passwd
;
1485 pgp_keyring
= info
.pgp_keyring
;
1486 pgp_trustdb
= info
.pgp_trustdb
;
1488 parse_protocols (info
.proto
, info
.nproto
, protocol_priority
);
1489 parse_ciphers (info
.ciphers
, info
.nciphers
, cipher_priority
);
1490 parse_macs (info
.macs
, info
.nmacs
, mac_priority
);
1491 parse_ctypes (info
.ctype
, info
.nctype
, cert_type_priority
);
1492 parse_kx (info
.kx
, info
.nkx
, kx_priority
);
1493 parse_comp (info
.comp
, info
.ncomp
, comp_priority
);
1497 size_t authz_idx
= 0;
1498 if (info
.authz_x509_attr_cert
)
1499 authz_server_formats
[authz_idx
++] = GNUTLS_AUTHZ_X509_ATTR_CERT
;
1500 if (info
.authz_saml_assertion
)
1501 authz_server_formats
[authz_idx
++] = GNUTLS_AUTHZ_SAML_ASSERTION
;
1509 const char *v
= gnutls_check_version (NULL
);
1511 printf ("gnutls-serv (GnuTLS) %s\n", LIBGNUTLS_VERSION
);
1512 if (strcmp (v
, LIBGNUTLS_VERSION
) != 0)
1513 printf ("libgnutls %s\n", v
);
1516 /* session resuming support */
1518 #define SESSION_ID_SIZE 32
1519 #define SESSION_DATA_SIZE 1024
1523 char session_id
[SESSION_ID_SIZE
];
1524 unsigned int session_id_size
;
1526 char session_data
[SESSION_DATA_SIZE
];
1527 unsigned int session_data_size
;
1530 static CACHE
*cache_db
;
1531 int cache_db_ptr
= 0;
1537 /* allocate cache_db */
1538 cache_db
= calloc (1, ssl_session_cache
* sizeof (CACHE
));
1542 wrap_db_deinit (void)
1547 wrap_db_store (void *dbf
, gnutls_datum_t key
, gnutls_datum_t data
)
1550 if (cache_db
== NULL
)
1553 if (key
.size
> SESSION_ID_SIZE
)
1555 if (data
.size
> SESSION_DATA_SIZE
)
1558 memcpy (cache_db
[cache_db_ptr
].session_id
, key
.data
, key
.size
);
1559 cache_db
[cache_db_ptr
].session_id_size
= key
.size
;
1561 memcpy (cache_db
[cache_db_ptr
].session_data
, data
.data
, data
.size
);
1562 cache_db
[cache_db_ptr
].session_data_size
= data
.size
;
1565 cache_db_ptr
%= ssl_session_cache
;
1570 static gnutls_datum_t
1571 wrap_db_fetch (void *dbf
, gnutls_datum_t key
)
1573 gnutls_datum_t res
= { NULL
, 0 };
1576 if (cache_db
== NULL
)
1579 for (i
= 0; i
< ssl_session_cache
; i
++)
1581 if (key
.size
== cache_db
[i
].session_id_size
&&
1582 memcmp (key
.data
, cache_db
[i
].session_id
, key
.size
) == 0)
1586 res
.size
= cache_db
[i
].session_data_size
;
1588 res
.data
= gnutls_malloc (res
.size
);
1589 if (res
.data
== NULL
)
1592 memcpy (res
.data
, cache_db
[i
].session_data
, res
.size
);
1601 wrap_db_delete (void *dbf
, gnutls_datum_t key
)
1605 if (cache_db
== NULL
)
1608 for (i
= 0; i
< ssl_session_cache
; i
++)
1610 if (key
.size
== (unsigned int) cache_db
[i
].session_id_size
&&
1611 memcmp (key
.data
, cache_db
[i
].session_id
, key
.size
) == 0)
1614 cache_db
[i
].session_id_size
= 0;
1615 cache_db
[i
].session_data_size
= 0;
1626 print_serv_license (void)
1628 fputs ("\nCopyright (C) 2001-2003 Paul Sheer, Nikos Mavroyanopoulos\n"
1629 "\nCopyright (C) 2004 Free Software Foundation\n"
1630 "This program is free software; you can redistribute it and/or modify \n"
1631 "it under the terms of the GNU General Public License as published by \n"
1632 "the Free Software Foundation; either version 2 of the License, or \n"
1633 "(at your option) any later version. \n" "\n"
1634 "This program is distributed in the hope that it will be useful, \n"
1635 "but WITHOUT ANY WARRANTY; without even the implied warranty of \n"
1636 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the \n"
1637 "GNU General Public License for more details. \n" "\n"
1638 "You should have received a copy of the GNU General Public License \n"
1639 "along with this program; if not, write to the Free Software \n"
1640 "Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n\n",