File: | src/serv.c |
Location: | line 1300, column 33 |
Description: | Pass-by-value argument in function call is undefined |
1 | /* | ||
2 | * Copyright (C) 2004, 2006-2012 Free Software Foundation, Inc. | ||
3 | * Copyright (C) 2001,2002 Paul Sheer | ||
4 | * Portions Copyright (C) 2002,2003 Nikos Mavrogiannopoulos | ||
5 | * | ||
6 | * This file is part of GnuTLS. | ||
7 | * | ||
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. | ||
12 | * | ||
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. | ||
17 | * | ||
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/>. | ||
20 | */ | ||
21 | |||
22 | /* This server is heavily modified for GnuTLS by Nikos Mavrogiannopoulos | ||
23 | * (which means it is quite unreadable) | ||
24 | */ | ||
25 | |||
26 | #include <config.h> | ||
27 | |||
28 | #include "common.h" | ||
29 | #include "serv-gaa.h" | ||
30 | #include <stdio.h> | ||
31 | #include <stdlib.h> | ||
32 | #include <errno(*__errno_location ()).h> | ||
33 | #include <sys/types.h> | ||
34 | #include <string.h> | ||
35 | #include <gnutls/gnutls.h> | ||
36 | #include <gnutls/openpgp.h> | ||
37 | #include <sys/time.h> | ||
38 | #include <sys/select.h> | ||
39 | #include <fcntl.h> | ||
40 | #include <list.h> | ||
41 | #include <netdb.h> | ||
42 | #include <unistd.h> | ||
43 | |||
44 | /* Gnulib portability files. */ | ||
45 | #include "progname.h" | ||
46 | #include "version-etc.h" | ||
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; | ||
60 | |||
61 | int verbose; | ||
62 | static int nodb; | ||
63 | static int noticket; | ||
64 | int require_cert; | ||
65 | int disable_client_cert; | ||
66 | |||
67 | char *psk_passwd; | ||
68 | char *srp_passwd; | ||
69 | char *srp_passwd_conf; | ||
70 | char *pgp_keyring; | ||
71 | char *pgp_keyfile; | ||
72 | char *pgp_certfile; | ||
73 | char *x509_keyfile; | ||
74 | char *x509_certfile; | ||
75 | char *x509_dsakeyfile; | ||
76 | char *x509_dsacertfile; | ||
77 | char *x509_ecckeyfile; | ||
78 | char *x509_ecccertfile; | ||
79 | char *x509_cafile; | ||
80 | char *dh_params_file; | ||
81 | char *x509_crlfile = NULL((void*)0); | ||
82 | |||
83 | gnutls_datum_t session_ticket_key; | ||
84 | static void tcp_server(const char* name, int port); | ||
85 | |||
86 | /* end of globals */ | ||
87 | |||
88 | /* This is a sample TCP echo server. | ||
89 | * This will behave as an http server if any argument in the | ||
90 | * command line is present | ||
91 | */ | ||
92 | |||
93 | #define SMALL_READ_TEST(2147483647) (2147483647) | ||
94 | |||
95 | #define GERR(ret)fprintf(stdout, "Error: %s\n", safe_strerror(ret)) fprintf(stdoutstdout, "Error: %s\n", safe_strerror(ret)) | ||
96 | |||
97 | #define HTTP_END"</BODY></HTML>\n\n" "</BODY></HTML>\n\n" | ||
98 | |||
99 | #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" "<!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" | ||
100 | #define HTTP_OK"HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n" "HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n" | ||
101 | |||
102 | #define HTTP_BEGIN"HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n" "\n" "<HTML><BODY>\n" "<CENTER><H1>This is <a href=\"http://www.gnu.org/software/gnutls\">" "GnuTLS</a></H1></CENTER>\n\n" HTTP_OK"HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n" \ | ||
103 | "\n" \ | ||
104 | "<HTML><BODY>\n" \ | ||
105 | "<CENTER><H1>This is <a href=\"http://www.gnu.org/software/gnutls\">" \ | ||
106 | "GnuTLS</a></H1></CENTER>\n\n" | ||
107 | |||
108 | /* These are global */ | ||
109 | gnutls_srp_server_credentials_t srp_cred = NULL((void*)0); | ||
110 | gnutls_psk_server_credentials_t psk_cred = NULL((void*)0); | ||
111 | gnutls_anon_server_credentials_t dh_cred = NULL((void*)0); | ||
112 | gnutls_certificate_credentials_t cert_cred = NULL((void*)0); | ||
113 | |||
114 | static gaainfo info; | ||
115 | |||
116 | const int ssl_session_cache = 128; | ||
117 | |||
118 | static void wrap_db_init (void); | ||
119 | static void wrap_db_deinit (void); | ||
120 | static int wrap_db_store (void *dbf, gnutls_datum_t key, gnutls_datum_t data); | ||
121 | static gnutls_datum_t wrap_db_fetch (void *dbf, gnutls_datum_t key); | ||
122 | static int wrap_db_delete (void *dbf, gnutls_datum_t key); | ||
123 | |||
124 | |||
125 | #define HTTP_STATE_REQUEST1 1 | ||
126 | #define HTTP_STATE_RESPONSE2 2 | ||
127 | #define HTTP_STATE_CLOSING3 3 | ||
128 | |||
129 | LIST_TYPE_DECLARE (listener_item, char *http_request; char *http_response;typedef struct listener_item { struct listener_item *next; struct listener_item *prev; char *http_request; char *http_response ; int request_length; int response_length; int response_written ; int http_state; int listen_socket; int fd; gnutls_session_t tls_session; int handshake_ok; } listener_item | ||
130 | int request_length; int response_length;typedef struct listener_item { struct listener_item *next; struct listener_item *prev; char *http_request; char *http_response ; int request_length; int response_length; int response_written ; int http_state; int listen_socket; int fd; gnutls_session_t tls_session; int handshake_ok; } listener_item | ||
131 | int response_written; int http_state;typedef struct listener_item { struct listener_item *next; struct listener_item *prev; char *http_request; char *http_response ; int request_length; int response_length; int response_written ; int http_state; int listen_socket; int fd; gnutls_session_t tls_session; int handshake_ok; } listener_item | ||
132 | int listen_socket; int fd;typedef struct listener_item { struct listener_item *next; struct listener_item *prev; char *http_request; char *http_response ; int request_length; int response_length; int response_written ; int http_state; int listen_socket; int fd; gnutls_session_t tls_session; int handshake_ok; } listener_item | ||
133 | gnutls_session_t tls_session;typedef struct listener_item { struct listener_item *next; struct listener_item *prev; char *http_request; char *http_response ; int request_length; int response_length; int response_written ; int http_state; int listen_socket; int fd; gnutls_session_t tls_session; int handshake_ok; } listener_item | ||
134 | int handshake_ok;typedef struct listener_item { struct listener_item *next; struct listener_item *prev; char *http_request; char *http_response ; int request_length; int response_length; int response_written ; int http_state; int listen_socket; int fd; gnutls_session_t tls_session; int handshake_ok; } listener_item | ||
135 | )typedef struct listener_item { struct listener_item *next; struct listener_item *prev; char *http_request; char *http_response ; int request_length; int response_length; int response_written ; int http_state; int listen_socket; int fd; gnutls_session_t tls_session; int handshake_ok; } listener_item; | ||
136 | |||
137 | static const char * | ||
138 | safe_strerror (int value) | ||
139 | { | ||
140 | const char *ret = gnutls_strerror (value); | ||
141 | if (ret == NULL((void*)0)) | ||
142 | ret = str_unknown; | ||
143 | return ret; | ||
144 | } | ||
145 | |||
146 | static void | ||
147 | listener_free (listener_item * j) | ||
148 | { | ||
149 | |||
150 | free (j->http_request); | ||
151 | free (j->http_response); | ||
152 | if (j->fd >= 0) | ||
153 | { | ||
154 | gnutls_bye (j->tls_session, GNUTLS_SHUT_WR); | ||
155 | shutdown (j->fd, 2); | ||
156 | close (j->fd); | ||
157 | gnutls_deinit (j->tls_session); | ||
158 | } | ||
159 | } | ||
160 | |||
161 | |||
162 | /* we use primes up to 1024 in this server. | ||
163 | * otherwise we should add them here. | ||
164 | */ | ||
165 | |||
166 | gnutls_dh_params_t dh_params = NULL((void*)0); | ||
167 | gnutls_rsa_params_t rsa_params = NULL((void*)0); | ||
168 | |||
169 | static int | ||
170 | generate_dh_primes (void) | ||
171 | { | ||
172 | int prime_bits = gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH, GNUTLS_SEC_PARAM_NORMAL); | ||
173 | |||
174 | if (gnutls_dh_params_init (&dh_params) < 0) | ||
175 | { | ||
176 | fprintf (stderrstderr, "Error in dh parameter initialization\n"); | ||
177 | exit (1); | ||
178 | } | ||
179 | |||
180 | /* Generate Diffie-Hellman parameters - for use with DHE | ||
181 | * kx algorithms. These should be discarded and regenerated | ||
182 | * once a week or once a month. Depends on the | ||
183 | * security requirements. | ||
184 | */ | ||
185 | printf | ||
186 | ("Generating Diffie-Hellman parameters [%d]. Please wait...\n", | ||
187 | prime_bits); | ||
188 | fflush (stdoutstdout); | ||
189 | |||
190 | if (gnutls_dh_params_generate2 (dh_params, prime_bits) < 0) | ||
191 | { | ||
192 | fprintf (stderrstderr, "Error in prime generation\n"); | ||
193 | exit (1); | ||
194 | } | ||
195 | |||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | static void | ||
200 | read_dh_params (void) | ||
201 | { | ||
202 | char tmpdata[2048]; | ||
203 | int size; | ||
204 | gnutls_datum_t params; | ||
205 | FILE *fd; | ||
206 | |||
207 | if (gnutls_dh_params_init (&dh_params) < 0) | ||
208 | { | ||
209 | fprintf (stderrstderr, "Error in dh parameter initialization\n"); | ||
210 | exit (1); | ||
211 | } | ||
212 | |||
213 | /* read the params file | ||
214 | */ | ||
215 | fd = fopen (dh_params_file, "r"); | ||
216 | if (fd == NULL((void*)0)) | ||
217 | { | ||
218 | fprintf (stderrstderr, "Could not open %s\n", dh_params_file); | ||
219 | exit (1); | ||
220 | } | ||
221 | |||
222 | size = fread (tmpdata, 1, sizeof (tmpdata) - 1, fd); | ||
223 | tmpdata[size] = 0; | ||
224 | fclose (fd); | ||
225 | |||
226 | params.data = (unsigned char *) tmpdata; | ||
227 | params.size = size; | ||
228 | |||
229 | size = | ||
230 | gnutls_dh_params_import_pkcs3 (dh_params, ¶ms, GNUTLS_X509_FMT_PEM); | ||
231 | |||
232 | if (size < 0) | ||
233 | { | ||
234 | fprintf (stderrstderr, "Error parsing dh params: %s\n", safe_strerror (size)); | ||
235 | exit (1); | ||
236 | } | ||
237 | |||
238 | printf ("Read Diffie-Hellman parameters.\n"); | ||
239 | fflush (stdoutstdout); | ||
240 | |||
241 | } | ||
242 | |||
243 | static char pkcs3[] = | ||
244 | "-----BEGIN DH PARAMETERS-----\n" | ||
245 | "MIGGAoGAtkxw2jlsVCsrfLqxrN+IrF/3W8vVFvDzYbLmxi2GQv9s/PQGWP1d9i22\n" | ||
246 | "P2DprfcJknWt7KhCI1SaYseOQIIIAYP78CfyIpGScW/vS8khrw0rlQiyeCvQgF3O\n" | ||
247 | "GeGOEywcw+oQT4SmFOD7H0smJe2CNyjYpexBXQ/A0mbTF9QKm1cCAQU=\n" | ||
248 | "-----END DH PARAMETERS-----\n"; | ||
249 | |||
250 | static int | ||
251 | static_dh_params (void) | ||
252 | { | ||
253 | gnutls_datum_t params = { pkcs3, sizeof (pkcs3) }; | ||
254 | int ret; | ||
255 | |||
256 | if (gnutls_dh_params_init (&dh_params) < 0) | ||
257 | { | ||
258 | fprintf (stderrstderr, "Error in dh parameter initialization\n"); | ||
259 | exit (1); | ||
260 | } | ||
261 | |||
262 | ret = gnutls_dh_params_import_pkcs3 (dh_params, ¶ms, | ||
263 | GNUTLS_X509_FMT_PEM); | ||
264 | |||
265 | if (ret < 0) | ||
266 | { | ||
267 | fprintf (stderrstderr, "Error parsing dh params: %s\n", safe_strerror (ret)); | ||
268 | exit (1); | ||
269 | } | ||
270 | |||
271 | printf ("Set static Diffie-Hellman parameters, consider --dhparams.\n"); | ||
272 | |||
273 | return 0; | ||
274 | } | ||
275 | |||
276 | static int | ||
277 | get_params (gnutls_session_t session, gnutls_params_type_t type, | ||
278 | gnutls_params_st * st) | ||
279 | { | ||
280 | |||
281 | if (type == GNUTLS_PARAMS_RSA_EXPORT) | ||
282 | { | ||
283 | if (rsa_params == NULL((void*)0)) | ||
284 | return -1; | ||
285 | st->params.rsa_export = rsa_params; | ||
286 | } | ||
287 | else if (type == GNUTLS_PARAMS_DH) | ||
288 | { | ||
289 | if (dh_params == NULL((void*)0)) | ||
290 | return -1; | ||
291 | st->params.dh = dh_params; | ||
292 | } | ||
293 | else | ||
294 | return -1; | ||
295 | |||
296 | st->type = type; | ||
297 | st->deinit = 0; | ||
298 | |||
299 | return 0; | ||
300 | } | ||
301 | |||
302 | static int | ||
303 | generate_rsa_params (void) | ||
304 | { | ||
305 | if (gnutls_rsa_params_init (&rsa_params) < 0) | ||
306 | { | ||
307 | fprintf (stderrstderr, "Error in rsa parameter initialization\n"); | ||
308 | exit (1); | ||
309 | } | ||
310 | |||
311 | /* Generate RSA parameters - for use with RSA-export | ||
312 | * cipher suites. These should be discarded and regenerated | ||
313 | * once a day, once every 500 transactions etc. Depends on the | ||
314 | * security requirements. | ||
315 | */ | ||
316 | printf ("Generating temporary RSA parameters. Please wait...\n"); | ||
317 | fflush (stdoutstdout); | ||
318 | |||
319 | if (gnutls_rsa_params_generate2 (rsa_params, 512) < 0) | ||
320 | { | ||
321 | fprintf (stderrstderr, "Error in rsa parameter generation\n"); | ||
322 | exit (1); | ||
323 | } | ||
324 | |||
325 | return 0; | ||
326 | } | ||
327 | |||
328 | LIST_DECLARE_INIT (listener_list, listener_item, listener_free)struct { long length; long item_size; listener_item *head, *tail , *search; void (*free_func) (listener_item *); } listener_list = {0, sizeof (listener_item), 0, 0, 0, (void (*) (listener_item *)) listener_free}; | ||
329 | |||
330 | gnutls_session_t initialize_session (int dtls) | ||
331 | { | ||
332 | gnutls_session_t session; | ||
333 | const char *err; | ||
334 | |||
335 | if (dtls) | ||
336 | gnutls_init (&session, GNUTLS_SERVER1|GNUTLS_DATAGRAM(1<<2)); | ||
337 | else | ||
338 | gnutls_init (&session, GNUTLS_SERVER1); | ||
339 | |||
340 | /* allow the use of private ciphersuites. | ||
341 | */ | ||
342 | gnutls_handshake_set_private_extensions (session, 1); | ||
343 | |||
344 | if (nodb == 0) | ||
345 | { | ||
346 | gnutls_db_set_retrieve_function (session, wrap_db_fetch); | ||
347 | gnutls_db_set_remove_function (session, wrap_db_delete); | ||
348 | gnutls_db_set_store_function (session, wrap_db_store); | ||
349 | gnutls_db_set_ptr (session, NULL((void*)0)); | ||
350 | } | ||
351 | #ifdef ENABLE_SESSION_TICKET | ||
352 | if (noticket == 0) | ||
353 | gnutls_session_ticket_enable_server (session, &session_ticket_key); | ||
354 | #endif | ||
355 | |||
356 | if (gnutls_priority_set_direct (session, info.priorities, &err) < 0) | ||
357 | { | ||
358 | fprintf (stderrstderr, "Syntax error at: %s\n", err); | ||
359 | exit (1); | ||
360 | } | ||
361 | |||
362 | gnutls_credentials_set (session, GNUTLS_CRD_ANON, dh_cred); | ||
363 | |||
364 | if (srp_cred != NULL((void*)0)) | ||
365 | gnutls_credentials_set (session, GNUTLS_CRD_SRP, srp_cred); | ||
366 | |||
367 | if (psk_cred != NULL((void*)0)) | ||
368 | gnutls_credentials_set (session, GNUTLS_CRD_PSK, psk_cred); | ||
369 | |||
370 | if (cert_cred != NULL((void*)0)) | ||
371 | gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, cert_cred); | ||
372 | |||
373 | if (disable_client_cert) | ||
374 | gnutls_certificate_server_set_request (session, GNUTLS_CERT_IGNORE); | ||
375 | else | ||
376 | { | ||
377 | if (require_cert) | ||
378 | gnutls_certificate_server_set_request (session, GNUTLS_CERT_REQUIRE); | ||
379 | else | ||
380 | gnutls_certificate_server_set_request (session, GNUTLS_CERT_REQUEST); | ||
381 | } | ||
382 | |||
383 | return session; | ||
384 | } | ||
385 | |||
386 | #include <gnutls/x509.h> | ||
387 | |||
388 | static const char DEFAULT_DATA[] = | ||
389 | "This is the default message reported by the GnuTLS implementation. " | ||
390 | "For more information please visit " | ||
391 | "<a href=\"http://www.gnutls.org/\">http://www.gnutls.org/</a>."; | ||
392 | |||
393 | /* Creates html with the current session information. | ||
394 | */ | ||
395 | #define tmp_buffer&http_buffer[strlen(http_buffer)] &http_buffer[strlen(http_buffer)] | ||
396 | #define tmp_buffer_sizelen-strlen(http_buffer) len-strlen(http_buffer) | ||
397 | static char * | ||
398 | peer_print_info (gnutls_session_t session, int *ret_length, | ||
399 | const char *header) | ||
400 | { | ||
401 | const char *tmp; | ||
402 | unsigned char sesid[32]; | ||
403 | size_t i, sesid_size; | ||
404 | char *http_buffer; | ||
405 | gnutls_kx_algorithm_t kx_alg; | ||
406 | size_t len = 20 * 1024 + strlen (header); | ||
407 | char *crtinfo = NULL((void*)0); | ||
408 | size_t ncrtinfo = 0; | ||
409 | |||
410 | if (verbose != 0) | ||
411 | { | ||
412 | http_buffer = malloc (len); | ||
413 | if (http_buffer == NULL((void*)0)) | ||
414 | return NULL((void*)0); | ||
415 | |||
416 | strcpy (http_buffer, HTTP_BEGIN"HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n" "\n" "<HTML><BODY>\n" "<CENTER><H1>This is <a href=\"http://www.gnu.org/software/gnutls\">" "GnuTLS</a></H1></CENTER>\n\n"); | ||
417 | strcpy (&http_buffer[sizeof (HTTP_BEGIN"HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n" "\n" "<HTML><BODY>\n" "<CENTER><H1>This is <a href=\"http://www.gnu.org/software/gnutls\">" "GnuTLS</a></H1></CENTER>\n\n") - 1], DEFAULT_DATA); | ||
418 | strcpy (&http_buffer[sizeof (HTTP_BEGIN"HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n" "\n" "<HTML><BODY>\n" "<CENTER><H1>This is <a href=\"http://www.gnu.org/software/gnutls\">" "GnuTLS</a></H1></CENTER>\n\n") + sizeof (DEFAULT_DATA) - 2], | ||
419 | HTTP_END"</BODY></HTML>\n\n"); | ||
420 | *ret_length = | ||
421 | sizeof (DEFAULT_DATA) + sizeof (HTTP_BEGIN"HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n" "\n" "<HTML><BODY>\n" "<CENTER><H1>This is <a href=\"http://www.gnu.org/software/gnutls\">" "GnuTLS</a></H1></CENTER>\n\n") + sizeof (HTTP_END"</BODY></HTML>\n\n") - 3; | ||
422 | return http_buffer; | ||
423 | |||
424 | } | ||
425 | |||
426 | if (gnutls_certificate_type_get (session) == GNUTLS_CRT_X509) | ||
427 | { | ||
428 | const gnutls_datum_t *cert_list; | ||
429 | unsigned int cert_list_size = 0; | ||
430 | |||
431 | cert_list = gnutls_certificate_get_peers (session, &cert_list_size); | ||
432 | |||
433 | for (i = 0; i < cert_list_size; i++) | ||
434 | { | ||
435 | gnutls_x509_crt_t cert; | ||
436 | gnutls_datum_t info; | ||
437 | |||
438 | if (gnutls_x509_crt_init (&cert) == 0 && | ||
439 | gnutls_x509_crt_import (cert, &cert_list[i], | ||
440 | GNUTLS_X509_FMT_DER) == 0 && | ||
441 | gnutls_x509_crt_print (cert, GNUTLS_CRT_PRINT_FULL, &info) == 0) | ||
442 | { | ||
443 | const char *post = "</PRE><P><PRE>"; | ||
444 | |||
445 | crtinfo = realloc (crtinfo, ncrtinfo + info.size + | ||
446 | strlen (post) + 1); | ||
447 | if (crtinfo == NULL((void*)0)) | ||
448 | return NULL((void*)0); | ||
449 | memcpy (crtinfo + ncrtinfo, info.data, info.size); | ||
450 | ncrtinfo += info.size; | ||
451 | memcpy (crtinfo + ncrtinfo, post, strlen (post)); | ||
452 | ncrtinfo += strlen (post); | ||
453 | crtinfo[ncrtinfo] = '\0'; | ||
454 | gnutls_free (info.data); | ||
455 | } | ||
456 | } | ||
457 | } | ||
458 | |||
459 | http_buffer = malloc (len); | ||
460 | if (http_buffer == NULL((void*)0)) | ||
461 | { | ||
462 | free (crtinfo); | ||
463 | return NULL((void*)0); | ||
464 | } | ||
465 | |||
466 | strcpy (http_buffer, HTTP_BEGIN"HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n" "\n" "<HTML><BODY>\n" "<CENTER><H1>This is <a href=\"http://www.gnu.org/software/gnutls\">" "GnuTLS</a></H1></CENTER>\n\n"); | ||
467 | |||
468 | /* print session_id */ | ||
469 | gnutls_session_get_id (session, sesid, &sesid_size); | ||
470 | snprintf (tmp_buffer&http_buffer[strlen(http_buffer)], tmp_buffer_sizelen-strlen(http_buffer), "\n<p>Session ID: <i>"); | ||
471 | for (i = 0; i < sesid_size; i++) | ||
472 | snprintf (tmp_buffer&http_buffer[strlen(http_buffer)], tmp_buffer_sizelen-strlen(http_buffer), "%.2X", sesid[i]); | ||
473 | snprintf (tmp_buffer&http_buffer[strlen(http_buffer)], tmp_buffer_sizelen-strlen(http_buffer), "</i></p>\n"); | ||
474 | snprintf (tmp_buffer&http_buffer[strlen(http_buffer)], tmp_buffer_sizelen-strlen(http_buffer), | ||
475 | "<h5>If your browser supports session resuming, then you should see the " | ||
476 | "same session ID, when you press the <b>reload</b> button.</h5>\n"); | ||
477 | |||
478 | /* Here unlike print_info() we use the kx algorithm to distinguish | ||
479 | * the functions to call. | ||
480 | */ | ||
481 | { | ||
482 | char dns[256]; | ||
483 | size_t dns_size = sizeof (dns); | ||
484 | unsigned int type; | ||
485 | |||
486 | if (gnutls_server_name_get (session, dns, &dns_size, &type, 0) == 0) | ||
487 | { | ||
488 | snprintf (tmp_buffer&http_buffer[strlen(http_buffer)], tmp_buffer_sizelen-strlen(http_buffer), "\n<p>Server Name: %s</p>\n", dns); | ||
489 | } | ||
490 | |||
491 | } | ||
492 | |||
493 | kx_alg = gnutls_kx_get (session); | ||
494 | |||
495 | /* print srp specific data */ | ||
496 | #ifdef ENABLE_SRP1 | ||
497 | if (kx_alg == GNUTLS_KX_SRP) | ||
498 | { | ||
499 | snprintf (tmp_buffer&http_buffer[strlen(http_buffer)], tmp_buffer_sizelen-strlen(http_buffer), "<p>Connected as user '%s'.</p>\n", | ||
500 | gnutls_srp_server_get_username (session)); | ||
501 | } | ||
502 | #endif | ||
503 | |||
504 | #ifdef ENABLE_PSK1 | ||
505 | if (kx_alg == GNUTLS_KX_PSK) | ||
506 | { | ||
507 | snprintf (tmp_buffer&http_buffer[strlen(http_buffer)], tmp_buffer_sizelen-strlen(http_buffer), "<p>Connected as user '%s'.</p>\n", | ||
508 | gnutls_psk_server_get_username (session)); | ||
509 | } | ||
510 | #endif | ||
511 | |||
512 | #ifdef ENABLE_ANON1 | ||
513 | if (kx_alg == GNUTLS_KX_ANON_DH) | ||
514 | { | ||
515 | snprintf (tmp_buffer&http_buffer[strlen(http_buffer)], tmp_buffer_sizelen-strlen(http_buffer), | ||
516 | "<p> Connect using anonymous DH (prime of %d bits)</p>\n", | ||
517 | gnutls_dh_get_prime_bits (session)); | ||
518 | } | ||
519 | #endif | ||
520 | |||
521 | if (kx_alg == GNUTLS_KX_DHE_RSA || kx_alg == GNUTLS_KX_DHE_DSS) | ||
522 | { | ||
523 | snprintf (tmp_buffer&http_buffer[strlen(http_buffer)], tmp_buffer_sizelen-strlen(http_buffer), | ||
524 | "Ephemeral DH using prime of <b>%d</b> bits.<br>\n", | ||
525 | gnutls_dh_get_prime_bits (session)); | ||
526 | } | ||
527 | |||
528 | /* print session information */ | ||
529 | strcat (http_buffer, "<P>\n"); | ||
530 | |||
531 | tmp = gnutls_protocol_get_name (gnutls_protocol_get_version (session)); | ||
532 | if (tmp == NULL((void*)0)) | ||
533 | tmp = str_unknown; | ||
534 | snprintf (tmp_buffer&http_buffer[strlen(http_buffer)], tmp_buffer_sizelen-strlen(http_buffer), | ||
535 | "<TABLE border=1><TR><TD>Protocol version:</TD><TD>%s</TD></TR>\n", | ||
536 | tmp); | ||
537 | |||
538 | if (gnutls_auth_get_type (session) == GNUTLS_CRD_CERTIFICATE) | ||
539 | { | ||
540 | tmp = | ||
541 | gnutls_certificate_type_get_name (gnutls_certificate_type_get | ||
542 | (session)); | ||
543 | if (tmp == NULL((void*)0)) | ||
544 | tmp = str_unknown; | ||
545 | snprintf (tmp_buffer&http_buffer[strlen(http_buffer)], tmp_buffer_sizelen-strlen(http_buffer), "<TR><TD>Certificate Type:</TD><TD>%s</TD></TR>\n", | ||
546 | tmp); | ||
547 | } | ||
548 | |||
549 | tmp = gnutls_kx_get_name (kx_alg); | ||
550 | if (tmp == NULL((void*)0)) | ||
551 | tmp = str_unknown; | ||
552 | snprintf (tmp_buffer&http_buffer[strlen(http_buffer)], tmp_buffer_sizelen-strlen(http_buffer), "<TR><TD>Key Exchange:</TD><TD>%s</TD></TR>\n", tmp); | ||
553 | |||
554 | tmp = gnutls_compression_get_name (gnutls_compression_get (session)); | ||
555 | if (tmp == NULL((void*)0)) | ||
556 | tmp = str_unknown; | ||
557 | snprintf (tmp_buffer&http_buffer[strlen(http_buffer)], tmp_buffer_sizelen-strlen(http_buffer), "<TR><TD>Compression</TD><TD>%s</TD></TR>\n", tmp); | ||
558 | |||
559 | tmp = gnutls_cipher_get_name (gnutls_cipher_get (session)); | ||
560 | if (tmp == NULL((void*)0)) | ||
561 | tmp = str_unknown; | ||
562 | snprintf (tmp_buffer&http_buffer[strlen(http_buffer)], tmp_buffer_sizelen-strlen(http_buffer), "<TR><TD>Cipher</TD><TD>%s</TD></TR>\n", tmp); | ||
563 | |||
564 | tmp = gnutls_mac_get_name (gnutls_mac_get (session)); | ||
565 | if (tmp == NULL((void*)0)) | ||
566 | tmp = str_unknown; | ||
567 | snprintf (tmp_buffer&http_buffer[strlen(http_buffer)], tmp_buffer_sizelen-strlen(http_buffer), "<TR><TD>MAC</TD><TD>%s</TD></TR>\n", tmp); | ||
568 | |||
569 | tmp = gnutls_cipher_suite_get_name (kx_alg, | ||
570 | gnutls_cipher_get (session), | ||
571 | gnutls_mac_get (session)); | ||
572 | if (tmp == NULL((void*)0)) | ||
573 | tmp = str_unknown; | ||
574 | snprintf (tmp_buffer&http_buffer[strlen(http_buffer)], tmp_buffer_sizelen-strlen(http_buffer), "<TR><TD>Ciphersuite</TD><TD>%s</TD></TR></p></TABLE>\n", | ||
575 | tmp); | ||
576 | |||
577 | if (crtinfo) | ||
578 | { | ||
579 | snprintf (tmp_buffer&http_buffer[strlen(http_buffer)], tmp_buffer_sizelen-strlen(http_buffer), "<hr><PRE>%s\n</PRE>\n", crtinfo); | ||
580 | free (crtinfo); | ||
581 | } | ||
582 | |||
583 | snprintf (tmp_buffer&http_buffer[strlen(http_buffer)], tmp_buffer_sizelen-strlen(http_buffer), "<hr><P>Your HTTP header was:<PRE>%s</PRE></P>\n" HTTP_END"</BODY></HTML>\n\n", | ||
584 | header); | ||
585 | |||
586 | *ret_length = strlen (http_buffer); | ||
587 | |||
588 | return http_buffer; | ||
589 | } | ||
590 | |||
591 | const char * | ||
592 | human_addr (const struct sockaddr *sa, socklen_t salen, | ||
593 | char *buf, size_t buflen) | ||
594 | { | ||
595 | const char *save_buf = buf; | ||
596 | size_t l; | ||
597 | |||
598 | if (!buf || !buflen) | ||
599 | return NULL((void*)0); | ||
600 | |||
601 | *buf = '\0'; | ||
602 | |||
603 | switch (sa->sa_family) | ||
604 | { | ||
605 | #if HAVE_IPV61 | ||
606 | case AF_INET610: | ||
607 | snprintf (buf, buflen, "IPv6 "); | ||
608 | break; | ||
609 | #endif | ||
610 | |||
611 | case AF_INET2: | ||
612 | snprintf (buf, buflen, "IPv4 "); | ||
613 | break; | ||
614 | } | ||
615 | |||
616 | l = strlen (buf); | ||
617 | buf += l; | ||
618 | buflen -= l; | ||
619 | |||
620 | if (getnameinfo (sa, salen, buf, buflen, NULL((void*)0), 0, NI_NUMERICHOST1) != 0) | ||
621 | return NULL((void*)0); | ||
622 | |||
623 | l = strlen (buf); | ||
624 | buf += l; | ||
625 | buflen -= l; | ||
626 | |||
627 | strncat (buf, " port ", buflen); | ||
628 | |||
629 | l = strlen (buf); | ||
630 | buf += l; | ||
631 | buflen -= l; | ||
632 | |||
633 | if (getnameinfo (sa, salen, NULL((void*)0), 0, buf, buflen, NI_NUMERICSERV2) != 0) | ||
634 | return NULL((void*)0); | ||
635 | |||
636 | return save_buf; | ||
637 | } | ||
638 | |||
639 | int wait_for_connection(void) | ||
640 | { | ||
641 | listener_item *j; | ||
642 | fd_set rd, wr; | ||
643 | int n, sock = -1; | ||
644 | |||
645 | FD_ZERO (&rd)do { int __d0, __d1; __asm__ __volatile__ ("cld; rep; " "stosq" : "=c" (__d0), "=D" (__d1) : "a" (0), "0" (sizeof (fd_set) / sizeof (__fd_mask)), "1" (&((&rd)->fds_bits)[0]) : "memory"); } while (0); | ||
646 | FD_ZERO (&wr)do { int __d0, __d1; __asm__ __volatile__ ("cld; rep; " "stosq" : "=c" (__d0), "=D" (__d1) : "a" (0), "0" (sizeof (fd_set) / sizeof (__fd_mask)), "1" (&((&wr)->fds_bits)[0]) : "memory"); } while (0); | ||
647 | n = 0; | ||
648 | |||
649 | lloopstart (listener_list, j)for (j = (void *) (listener_list).head; j;) { struct list_item *__tl; __tl = (void *) j->next; | ||
650 | { | ||
651 | if (j->listen_socket) | ||
652 | { | ||
653 | FD_SET (j->fd, &rd)(((&rd)->fds_bits)[((j->fd) / (8 * (int) sizeof (__fd_mask )))] |= ((__fd_mask) 1 << ((j->fd) % (8 * (int) sizeof (__fd_mask))))); | ||
654 | n = MAX (n, j->fd)(((n)>(j->fd))?(n):(j->fd)); | ||
655 | } | ||
656 | } | ||
657 | lloopend (listener_list, j)j = (void *) __tl; }; | ||
658 | |||
659 | /* waiting part */ | ||
660 | n = select (n + 1, &rd, &wr, NULL((void*)0), NULL((void*)0)); | ||
661 | if (n == -1 && errno(*__errno_location ()) == EINTR4) | ||
662 | return -1; | ||
663 | if (n < 0) | ||
664 | { | ||
665 | perror ("select()"); | ||
666 | exit (1); | ||
667 | } | ||
668 | |||
669 | /* find which one is ready */ | ||
670 | lloopstart (listener_list, j)for (j = (void *) (listener_list).head; j;) { struct list_item *__tl; __tl = (void *) j->next; | ||
671 | { | ||
672 | /* a new connection has arrived */ | ||
673 | if (FD_ISSET (j->fd, &rd)((((&rd)->fds_bits)[((j->fd) / (8 * (int) sizeof (__fd_mask )))] & ((__fd_mask) 1 << ((j->fd) % (8 * (int) sizeof (__fd_mask))))) != 0) && j->listen_socket) | ||
674 | { | ||
675 | sock = j->fd; | ||
676 | break; | ||
677 | } | ||
678 | } | ||
679 | lloopend (listener_list, j)j = (void *) __tl; }; | ||
680 | return sock; | ||
681 | } | ||
682 | |||
683 | int | ||
684 | listen_socket (const char *name, int listen_port, int socktype) | ||
685 | { | ||
686 | struct addrinfo hints, *res, *ptr; | ||
687 | char portname[6]; | ||
688 | int s; | ||
689 | int yes; | ||
690 | listener_item *j = NULL((void*)0); | ||
691 | |||
692 | snprintf (portname, sizeof (portname), "%d", listen_port); | ||
693 | memset (&hints, 0, sizeof (hints)); | ||
694 | hints.ai_socktype = socktype; | ||
695 | hints.ai_flags = AI_PASSIVE0x0001 | ||
696 | #ifdef AI_ADDRCONFIG0x0020 | ||
697 | | AI_ADDRCONFIG0x0020 | ||
698 | #endif | ||
699 | ; | ||
700 | |||
701 | if ((s = getaddrinfo (NULL((void*)0), portname, &hints, &res)) != 0) | ||
702 | { | ||
703 | fprintf (stderrstderr, "getaddrinfo() failed: %s\n", gai_strerror (s)); | ||
704 | return -1; | ||
705 | } | ||
706 | |||
707 | for (ptr = res; ptr != NULL((void*)0); ptr = ptr->ai_next) | ||
708 | { | ||
709 | #ifndef HAVE_IPV61 | ||
710 | if (ptr->ai_family != AF_INET2) continue; | ||
711 | #endif | ||
712 | |||
713 | /* Print what we are doing. */ | ||
714 | { | ||
715 | char topbuf[512]; | ||
716 | |||
717 | fprintf (stderrstderr, "%s listening on %s...", | ||
718 | name, human_addr (ptr->ai_addr, ptr->ai_addrlen, | ||
719 | topbuf, sizeof (topbuf))); | ||
720 | } | ||
721 | |||
722 | if ((s = socket (ptr->ai_family, ptr->ai_socktype, | ||
723 | ptr->ai_protocol)) < 0) | ||
724 | { | ||
725 | perror ("socket() failed"); | ||
726 | continue; | ||
727 | } | ||
728 | |||
729 | if (socktype == SOCK_STREAMSOCK_STREAM) | ||
730 | { | ||
731 | yes = 1; | ||
732 | if (setsockopt (s, SOL_SOCKET1, SO_REUSEADDR2, | ||
733 | (const void *) &yes, sizeof (yes)) < 0) | ||
734 | { | ||
735 | perror ("setsockopt() failed"); | ||
736 | close (s); | ||
737 | continue; | ||
738 | } | ||
739 | } | ||
740 | else | ||
741 | { | ||
742 | #if defined(IP_DONTFRAG) | ||
743 | yes = 1; | ||
744 | if (setsockopt (s, IPPROTO_IPIPPROTO_IP, IP_DONTFRAG, | ||
745 | (const void *) &yes, sizeof (yes)) < 0) | ||
746 | perror ("setsockopt(IP_DF) failed"); | ||
747 | #elif defined(IP_MTU_DISCOVER10) | ||
748 | yes = IP_PMTUDISC_DO2; | ||
749 | if (setsockopt(s, IPPROTO_IPIPPROTO_IP, IP_MTU_DISCOVER10, | ||
750 | (const void*) &yes, sizeof (yes)) < 0) | ||
751 | perror ("setsockopt(IP_DF) failed"); | ||
752 | #endif | ||
753 | } | ||
754 | |||
755 | if (bind (s, ptr->ai_addr, ptr->ai_addrlen) < 0) | ||
756 | { | ||
757 | perror ("bind() failed"); | ||
758 | close (s); | ||
759 | continue; | ||
760 | } | ||
761 | |||
762 | if (socktype == SOCK_STREAMSOCK_STREAM) | ||
763 | { | ||
764 | if (listen (s, 10) < 0) | ||
765 | { | ||
766 | perror ("listen() failed"); | ||
767 | exit(1); | ||
768 | } | ||
769 | } | ||
770 | |||
771 | /* new list entry for the connection */ | ||
772 | lappend (listener_list){ struct list_item *__t; __t = (struct list_item *) malloc (( listener_list).item_size); memset (__t, 0, (listener_list).item_size ); __t->prev = (struct list_item *) (listener_list).tail; if (__t->prev) __t->prev->next = __t; __t->next = 0 ; if (!(listener_list).head) (listener_list).head = (void *) __t ; (listener_list).tail = (void *) __t; (listener_list).length ++; }; | ||
773 | j = listener_list.tail; | ||
774 | j->listen_socket = 1; | ||
775 | j->fd = s; | ||
776 | |||
777 | /* Complete earlier message. */ | ||
778 | fprintf (stderrstderr, "done\n"); | ||
779 | } | ||
780 | |||
781 | fflush (stderrstderr); | ||
782 | |||
783 | freeaddrinfo (res); | ||
784 | |||
785 | return s; | ||
786 | } | ||
787 | |||
788 | /* strips \r\n from the end of the string | ||
789 | */ | ||
790 | static void | ||
791 | strip (char *data) | ||
792 | { | ||
793 | int i; | ||
794 | int len = strlen (data); | ||
795 | |||
796 | for (i = 0; i < len; i++) | ||
797 | { | ||
798 | if (data[i] == '\r' && data[i + 1] == '\n' && data[i + 1] == 0) | ||
799 | { | ||
800 | data[i] = '\n'; | ||
801 | data[i + 1] = 0; | ||
802 | break; | ||
803 | } | ||
804 | } | ||
805 | } | ||
806 | |||
807 | static void | ||
808 | get_response (gnutls_session_t session, char *request, | ||
809 | char **response, int *response_length) | ||
810 | { | ||
811 | char *p, *h; | ||
812 | |||
813 | if (http != 0) | ||
814 | { | ||
815 | if (strncmp (request, "GET ", 4)) | ||
816 | goto unimplemented; | ||
817 | |||
818 | if (!(h = strchr (request, '\n'))) | ||
819 | goto unimplemented; | ||
820 | |||
821 | *h++ = '\0'; | ||
822 | while (*h == '\r' || *h == '\n') | ||
823 | h++; | ||
824 | |||
825 | if (!(p = strchr (request + 4, ' '))) | ||
826 | goto unimplemented; | ||
827 | *p = '\0'; | ||
828 | } | ||
829 | /* *response = peer_print_info(session, request+4, h, response_length); */ | ||
830 | if (http != 0) | ||
831 | { | ||
832 | *response = peer_print_info (session, response_length, h); | ||
833 | } | ||
834 | else | ||
835 | { | ||
836 | strip (request); | ||
837 | fprintf (stderrstderr, "received: %s\n", request); | ||
838 | if (request[0] == request[1] && request[0] == '*') | ||
839 | { | ||
840 | if (strncmp | ||
841 | (request, "**REHANDSHAKE**", | ||
842 | sizeof ("**REHANDSHAKE**") - 1) == 0) | ||
843 | { | ||
844 | fprintf (stderrstderr, "*** Sending rehandshake request\n"); | ||
845 | gnutls_rehandshake (session); | ||
846 | } | ||
847 | *response = NULL((void*)0); | ||
848 | *response_length = 0; | ||
849 | return; | ||
850 | } | ||
851 | *response = strdup (request); | ||
852 | *response_length = ((*response) ? strlen (*response) : 0); | ||
853 | } | ||
854 | |||
855 | return; | ||
856 | |||
857 | unimplemented: | ||
858 | *response = strdup (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"); | ||
859 | *response_length = ((*response) ? strlen (*response) : 0); | ||
860 | } | ||
861 | |||
862 | static void terminate (int sig) __attribute__ ((noreturn)); | ||
863 | |||
864 | static void | ||
865 | terminate (int sig) | ||
866 | { | ||
867 | fprintf (stderrstderr, "Exiting via signal %d\n", sig); | ||
868 | exit (1); | ||
869 | } | ||
870 | |||
871 | |||
872 | static void | ||
873 | check_alert (gnutls_session_t session, int ret) | ||
874 | { | ||
875 | if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED-16 | ||
876 | || ret == GNUTLS_E_FATAL_ALERT_RECEIVED-12) | ||
877 | { | ||
878 | int last_alert = gnutls_alert_get (session); | ||
879 | if (last_alert == GNUTLS_A_NO_RENEGOTIATION && | ||
880 | ret == GNUTLS_E_WARNING_ALERT_RECEIVED-16) | ||
881 | printf | ||
882 | ("* Received NO_RENEGOTIATION alert. Client does not support renegotiation.\n"); | ||
883 | else | ||
884 | printf ("* Received alert '%d': %s.\n", last_alert, | ||
885 | gnutls_alert_get_name (last_alert)); | ||
886 | } | ||
887 | } | ||
888 | |||
889 | static void | ||
890 | tls_log_func (int level, const char *str) | ||
891 | { | ||
892 | fprintf (stderrstderr, "|<%d>| %s", level, str); | ||
893 | } | ||
894 | |||
895 | static void | ||
896 | tls_audit_log_func (gnutls_session_t session, const char *str) | ||
897 | { | ||
898 | fprintf (stderrstderr, "|<%p>| %s", session, str); | ||
899 | } | ||
900 | |||
901 | static void gaa_parser (int argc, char **argv); | ||
902 | |||
903 | int | ||
904 | main (int argc, char **argv) | ||
905 | { | ||
906 | int ret; | ||
907 | char name[256]; | ||
908 | |||
909 | set_program_name (argv[0]); | ||
910 | |||
911 | #ifndef _WIN32 | ||
912 | signal (SIGPIPE13, SIG_IGN((__sighandler_t) 1)); | ||
913 | signal (SIGHUP1, SIG_IGN((__sighandler_t) 1)); | ||
914 | signal (SIGTERM15, terminate); | ||
915 | if (signal (SIGINT2, terminate) == SIG_IGN((__sighandler_t) 1)) | ||
916 | signal (SIGINT2, SIG_IGN((__sighandler_t) 1)); /* e.g. background process */ | ||
917 | #endif | ||
918 | |||
919 | sockets_init (); | ||
920 | |||
921 | gaa_parser (argc, argv); | ||
922 | |||
923 | if (nodb == 0) | ||
924 | wrap_db_init (); | ||
925 | |||
926 | if (info.udp != 0) | ||
927 | strcpy(name, "UDP "); | ||
928 | else name[0] = 0; | ||
929 | |||
930 | if (http == 1) | ||
931 | { | ||
932 | strcat (name, "HTTP Server"); | ||
933 | } | ||
934 | else | ||
935 | { | ||
936 | strcat (name, "Echo Server"); | ||
937 | } | ||
938 | |||
939 | gnutls_global_set_log_function (tls_log_func); | ||
940 | gnutls_global_set_audit_log_function (tls_audit_log_func); | ||
941 | gnutls_global_set_log_level (debug); | ||
942 | |||
943 | if ((ret = gnutls_global_init ()) < 0) | ||
944 | { | ||
945 | fprintf (stderrstderr, "global_init: %s\n", gnutls_strerror (ret)); | ||
946 | exit (1); | ||
947 | } | ||
948 | |||
949 | #ifdef ENABLE_PKCS111 | ||
950 | pkcs11_common (); | ||
951 | #endif | ||
952 | |||
953 | /* Note that servers must generate parameters for | ||
954 | * Diffie-Hellman. See gnutls_dh_params_generate(), and | ||
955 | * gnutls_dh_params_set(). | ||
956 | */ | ||
957 | if (generate != 0) | ||
958 | { | ||
959 | generate_rsa_params (); | ||
960 | generate_dh_primes (); | ||
961 | } | ||
962 | else if (dh_params_file) | ||
963 | { | ||
964 | read_dh_params (); | ||
965 | } | ||
966 | else | ||
967 | { | ||
968 | static_dh_params (); | ||
969 | } | ||
970 | |||
971 | if (gnutls_certificate_allocate_credentials (&cert_cred) < 0) | ||
972 | { | ||
973 | fprintf (stderrstderr, "memory error\n"); | ||
974 | exit (1); | ||
975 | } | ||
976 | |||
977 | if (x509_cafile != NULL((void*)0)) | ||
978 | { | ||
979 | if ((ret = gnutls_certificate_set_x509_trust_file | ||
980 | (cert_cred, x509_cafile, x509ctype)) < 0) | ||
981 | { | ||
982 | fprintf (stderrstderr, "Error reading '%s'\n", x509_cafile); | ||
983 | GERR (ret)fprintf(stdout, "Error: %s\n", safe_strerror(ret)); | ||
984 | exit (1); | ||
985 | } | ||
986 | else | ||
987 | { | ||
988 | printf ("Processed %d CA certificate(s).\n", ret); | ||
989 | } | ||
990 | } | ||
991 | #ifdef ENABLE_PKI1 | ||
992 | if (x509_crlfile != NULL((void*)0)) | ||
993 | { | ||
994 | if ((ret = gnutls_certificate_set_x509_crl_file | ||
995 | (cert_cred, x509_crlfile, x509ctype)) < 0) | ||
996 | { | ||
997 | fprintf (stderrstderr, "Error reading '%s'\n", x509_crlfile); | ||
998 | GERR (ret)fprintf(stdout, "Error: %s\n", safe_strerror(ret)); | ||
999 | exit (1); | ||
1000 | } | ||
1001 | else | ||
1002 | { | ||
1003 | printf ("Processed %d CRL(s).\n", ret); | ||
1004 | } | ||
1005 | } | ||
1006 | #endif | ||
1007 | |||
1008 | #ifdef ENABLE_OPENPGP1 | ||
1009 | if (pgp_keyring != NULL((void*)0)) | ||
1010 | { | ||
1011 | ret = | ||
1012 | gnutls_certificate_set_openpgp_keyring_file (cert_cred, pgp_keyring, | ||
1013 | GNUTLS_OPENPGP_FMT_BASE64); | ||
1014 | if (ret < 0) | ||
1015 | { | ||
1016 | fprintf (stderrstderr, "Error setting the OpenPGP keyring file\n"); | ||
1017 | GERR (ret)fprintf(stdout, "Error: %s\n", safe_strerror(ret)); | ||
1018 | } | ||
1019 | } | ||
1020 | |||
1021 | if (pgp_certfile != NULL((void*)0)) | ||
1022 | { | ||
1023 | if (info.pgp_subkey != NULL((void*)0)) | ||
1024 | ret = gnutls_certificate_set_openpgp_key_file2 | ||
1025 | (cert_cred, pgp_certfile, pgp_keyfile, info.pgp_subkey, | ||
1026 | GNUTLS_OPENPGP_FMT_BASE64); | ||
1027 | else | ||
1028 | ret = gnutls_certificate_set_openpgp_key_file | ||
1029 | (cert_cred, pgp_certfile, pgp_keyfile, GNUTLS_OPENPGP_FMT_BASE64); | ||
1030 | |||
1031 | if (ret < 0) | ||
1032 | { | ||
1033 | fprintf (stderrstderr, | ||
1034 | "Error[%d] while reading the OpenPGP key pair ('%s', '%s')\n", | ||
1035 | ret, pgp_certfile, pgp_keyfile); | ||
1036 | GERR (ret)fprintf(stdout, "Error: %s\n", safe_strerror(ret)); | ||
1037 | } | ||
1038 | } | ||
1039 | #endif | ||
1040 | |||
1041 | if (x509_certfile != NULL((void*)0)) | ||
1042 | if ((ret = gnutls_certificate_set_x509_key_file | ||
1043 | (cert_cred, x509_certfile, x509_keyfile, x509ctype)) < 0) | ||
1044 | { | ||
1045 | fprintf (stderrstderr, | ||
1046 | "Error reading '%s' or '%s'\n", x509_certfile, x509_keyfile); | ||
1047 | GERR (ret)fprintf(stdout, "Error: %s\n", safe_strerror(ret)); | ||
1048 | exit (1); | ||
1049 | } | ||
1050 | |||
1051 | if (x509_dsacertfile != NULL((void*)0)) | ||
1052 | if ((ret = gnutls_certificate_set_x509_key_file | ||
1053 | (cert_cred, x509_dsacertfile, x509_dsakeyfile, x509ctype)) < 0) | ||
1054 | { | ||
1055 | fprintf (stderrstderr, "Error reading '%s' or '%s'\n", | ||
1056 | x509_dsacertfile, x509_dsakeyfile); | ||
1057 | GERR (ret)fprintf(stdout, "Error: %s\n", safe_strerror(ret)); | ||
1058 | exit (1); | ||
1059 | } | ||
1060 | |||
1061 | if (x509_ecccertfile != NULL((void*)0)) | ||
1062 | if ((ret = gnutls_certificate_set_x509_key_file | ||
1063 | (cert_cred, x509_ecccertfile, x509_ecckeyfile, x509ctype)) < 0) | ||
1064 | { | ||
1065 | fprintf (stderrstderr, "Error reading '%s' or '%s'\n", | ||
1066 | x509_ecccertfile, x509_ecckeyfile); | ||
1067 | GERR (ret)fprintf(stdout, "Error: %s\n", safe_strerror(ret)); | ||
1068 | exit (1); | ||
1069 | } | ||
1070 | |||
1071 | gnutls_certificate_set_params_function (cert_cred, get_params); | ||
1072 | /* gnutls_certificate_set_dh_params(cert_cred, dh_params); | ||
1073 | * gnutls_certificate_set_rsa_export_params(cert_cred, rsa_params); | ||
1074 | */ | ||
1075 | |||
1076 | /* this is a password file (created with the included srpcrypt utility) | ||
1077 | * Read README.crypt prior to using SRP. | ||
1078 | */ | ||
1079 | #ifdef ENABLE_SRP1 | ||
1080 | if (srp_passwd != NULL((void*)0)) | ||
1081 | { | ||
1082 | gnutls_srp_allocate_server_credentials (&srp_cred); | ||
1083 | |||
1084 | if ((ret = | ||
1085 | gnutls_srp_set_server_credentials_file (srp_cred, srp_passwd, | ||
1086 | srp_passwd_conf)) < 0) | ||
1087 | { | ||
1088 | /* only exit is this function is not disabled | ||
1089 | */ | ||
1090 | fprintf (stderrstderr, "Error while setting SRP parameters\n"); | ||
1091 | GERR (ret)fprintf(stdout, "Error: %s\n", safe_strerror(ret)); | ||
1092 | } | ||
1093 | } | ||
1094 | #endif | ||
1095 | |||
1096 | /* this is a password file | ||
1097 | */ | ||
1098 | #ifdef ENABLE_PSK1 | ||
1099 | if (psk_passwd != NULL((void*)0)) | ||
1100 | { | ||
1101 | gnutls_psk_allocate_server_credentials (&psk_cred); | ||
1102 | |||
1103 | if ((ret = | ||
1104 | gnutls_psk_set_server_credentials_file (psk_cred, psk_passwd)) < 0) | ||
1105 | { | ||
1106 | /* only exit is this function is not disabled | ||
1107 | */ | ||
1108 | fprintf (stderrstderr, "Error while setting PSK parameters\n"); | ||
1109 | GERR (ret)fprintf(stdout, "Error: %s\n", safe_strerror(ret)); | ||
1110 | } | ||
1111 | |||
1112 | if (info.psk_hint) | ||
1113 | { | ||
1114 | ret = gnutls_psk_set_server_credentials_hint (psk_cred, | ||
1115 | info.psk_hint); | ||
1116 | if (ret) | ||
1117 | { | ||
1118 | fprintf (stderrstderr, "Error setting PSK identity hint.\n"); | ||
1119 | GERR (ret)fprintf(stdout, "Error: %s\n", safe_strerror(ret)); | ||
1120 | } | ||
1121 | } | ||
1122 | |||
1123 | gnutls_psk_set_server_params_function (psk_cred, get_params); | ||
1124 | } | ||
1125 | #endif | ||
1126 | |||
1127 | #ifdef ENABLE_ANON1 | ||
1128 | gnutls_anon_allocate_server_credentials (&dh_cred); | ||
1129 | gnutls_anon_set_server_params_function (dh_cred, get_params); | ||
1130 | |||
1131 | /* gnutls_anon_set_server_dh_params(dh_cred, dh_params); */ | ||
1132 | #endif | ||
1133 | |||
1134 | #ifdef ENABLE_SESSION_TICKET | ||
1135 | if (noticket == 0) | ||
1136 | gnutls_session_ticket_key_generate (&session_ticket_key); | ||
1137 | #endif | ||
1138 | |||
1139 | if (info.udp) | ||
1140 | udp_server(name, info.port, info.mtu); | ||
1141 | else | ||
1142 | tcp_server(name, info.port); | ||
1143 | } | ||
1144 | |||
1145 | static void tcp_server(const char* name, int port) | ||
1146 | { | ||
1147 | int n, s; | ||
1148 | char topbuf[512]; | ||
1149 | int accept_fd; | ||
1150 | struct sockaddr_storage client_address; | ||
1151 | socklen_t calen; | ||
| |||
1152 | |||
1153 | s = listen_socket (name, port, SOCK_STREAMSOCK_STREAM); | ||
1154 | if (s < 0) | ||
| |||
1155 | exit (1); | ||
1156 | |||
1157 | for (;;) | ||
| |||
1158 | { | ||
1159 | listener_item *j; | ||
1160 | fd_set rd, wr; | ||
1161 | #ifndef _WIN32 | ||
1162 | int val; | ||
1163 | #endif | ||
1164 | |||
1165 | FD_ZERO (&rd)do { int __d0, __d1; __asm__ __volatile__ ("cld; rep; " "stosq" : "=c" (__d0), "=D" (__d1) : "a" (0), "0" (sizeof (fd_set) / sizeof (__fd_mask)), "1" (&((&rd)->fds_bits)[0]) : "memory"); } while (0); | ||
1166 | FD_ZERO (&wr)do { int __d0, __d1; __asm__ __volatile__ ("cld; rep; " "stosq" : "=c" (__d0), "=D" (__d1) : "a" (0), "0" (sizeof (fd_set) / sizeof (__fd_mask)), "1" (&((&wr)->fds_bits)[0]) : "memory"); } while (0); | ||
1167 | n = 0; | ||
1168 | |||
1169 | /* flag which connections we are reading or writing to within the fd sets */ | ||
1170 | lloopstart (listener_list, j)for (j = (void *) (listener_list).head; j;) { struct list_item *__tl; __tl = (void *) j->next; | ||
1171 | { | ||
1172 | |||
1173 | #ifndef _WIN32 | ||
1174 | val = fcntl (j->fd, F_GETFL3, 0); | ||
1175 | if ((val == -1) || (fcntl (j->fd, F_SETFL4, val | O_NONBLOCK04000) < 0)) | ||
| |||
1176 | { | ||
1177 | perror ("fcntl()"); | ||
1178 | exit (1); | ||
1179 | } | ||
1180 | #endif | ||
1181 | |||
1182 | if (j->listen_socket) | ||
| |||
1183 | { | ||
1184 | FD_SET (j->fd, &rd)(((&rd)->fds_bits)[((j->fd) / (8 * (int) sizeof (__fd_mask )))] |= ((__fd_mask) 1 << ((j->fd) % (8 * (int) sizeof (__fd_mask))))); | ||
1185 | n = MAX (n, j->fd)(((n)>(j->fd))?(n):(j->fd)); | ||
1186 | } | ||
1187 | if (j->http_state == HTTP_STATE_REQUEST1) | ||
| |||
1188 | { | ||
1189 | FD_SET (j->fd, &rd)(((&rd)->fds_bits)[((j->fd) / (8 * (int) sizeof (__fd_mask )))] |= ((__fd_mask) 1 << ((j->fd) % (8 * (int) sizeof (__fd_mask))))); | ||
1190 | n = MAX (n, j->fd)(((n)>(j->fd))?(n):(j->fd)); | ||
1191 | } | ||
1192 | if (j->http_state == HTTP_STATE_RESPONSE2) | ||
| |||
1193 | { | ||
1194 | FD_SET (j->fd, &wr)(((&wr)->fds_bits)[((j->fd) / (8 * (int) sizeof (__fd_mask )))] |= ((__fd_mask) 1 << ((j->fd) % (8 * (int) sizeof (__fd_mask))))); | ||
1195 | n = MAX (n, j->fd)(((n)>(j->fd))?(n):(j->fd)); | ||
1196 | } | ||
1197 | } | ||
1198 | lloopend (listener_list, j)j = (void *) __tl; }; | ||
1199 | |||
1200 | /* core operation */ | ||
1201 | n = select (n + 1, &rd, &wr, NULL((void*)0), NULL((void*)0)); | ||
1202 | if (n == -1 && errno(*__errno_location ()) == EINTR4) | ||
| |||
1203 | continue; | ||
1204 | if (n < 0) | ||
| |||
1205 | { | ||
1206 | perror ("select()"); | ||
1207 | exit (1); | ||
1208 | } | ||
1209 | |||
1210 | /* read or write to each connection as indicated by select()'s return argument */ | ||
1211 | lloopstart (listener_list, j)for (j = (void *) (listener_list).head; j;) { struct list_item *__tl; __tl = (void *) j->next; | ||
1212 | { | ||
1213 | |||
1214 | /* a new connection has arrived */ | ||
1215 | if (FD_ISSET (j->fd, &rd)((((&rd)->fds_bits)[((j->fd) / (8 * (int) sizeof (__fd_mask )))] & ((__fd_mask) 1 << ((j->fd) % (8 * (int) sizeof (__fd_mask))))) != 0) && j->listen_socket) | ||
| |||
1216 | { | ||
1217 | gnutls_session_t tls_session; | ||
1218 | |||
1219 | tls_session = initialize_session (0); | ||
1220 | |||
1221 | calen = sizeof (client_address); | ||
1222 | memset (&client_address, 0, calen); | ||
1223 | accept_fd = accept (j->fd, (struct sockaddr *) &client_address, | ||
1224 | &calen); | ||
1225 | |||
1226 | if (accept_fd < 0) | ||
1227 | { | ||
1228 | perror ("accept()"); | ||
1229 | } | ||
1230 | else | ||
1231 | { | ||
1232 | time_t tt; | ||
1233 | char *ctt; | ||
1234 | |||
1235 | /* new list entry for the connection */ | ||
1236 | lappend (listener_list){ struct list_item *__t; __t = (struct list_item *) malloc (( listener_list).item_size); memset (__t, 0, (listener_list).item_size ); __t->prev = (struct list_item *) (listener_list).tail; if (__t->prev) __t->prev->next = __t; __t->next = 0 ; if (!(listener_list).head) (listener_list).head = (void *) __t ; (listener_list).tail = (void *) __t; (listener_list).length ++; }; | ||
1237 | j = listener_list.tail; | ||
1238 | j->http_request = (char *) strdup (""); | ||
1239 | j->http_state = HTTP_STATE_REQUEST1; | ||
1240 | j->fd = accept_fd; | ||
1241 | |||
1242 | j->tls_session = tls_session; | ||
1243 | gnutls_transport_set_ptr (tls_session, | ||
1244 | (gnutls_transport_ptr_t) | ||
1245 | gl_fd_to_handle (accept_fd)(accept_fd)); | ||
1246 | j->handshake_ok = 0; | ||
1247 | |||
1248 | if (verbose == 0) | ||
1249 | { | ||
1250 | tt = time (0); | ||
1251 | ctt = ctime (&tt); | ||
1252 | ctt[strlen (ctt) - 1] = 0; | ||
1253 | |||
1254 | printf ("\n* Accepted connection from %s on %s\n", | ||
1255 | human_addr ((struct sockaddr *) | ||
1256 | &client_address, calen, topbuf, | ||
1257 | sizeof (topbuf)), ctt); | ||
1258 | } | ||
1259 | } | ||
1260 | } | ||
1261 | |||
1262 | if (FD_ISSET (j->fd, &rd)((((&rd)->fds_bits)[((j->fd) / (8 * (int) sizeof (__fd_mask )))] & ((__fd_mask) 1 << ((j->fd) % (8 * (int) sizeof (__fd_mask))))) != 0) && !j->listen_socket) | ||
| |||
1263 | { | ||
1264 | /* read partial GET request */ | ||
1265 | char buf[1024]; | ||
1266 | int r, ret; | ||
1267 | |||
1268 | if (j->handshake_ok == 0) | ||
| |||
1269 | { | ||
1270 | r = gnutls_handshake (j->tls_session); | ||
1271 | if (r < 0 && gnutls_error_is_fatal (r) == 0) | ||
| |||
1272 | { | ||
1273 | check_alert (j->tls_session, r); | ||
1274 | /* nothing */ | ||
1275 | } | ||
1276 | else if (r < 0 && gnutls_error_is_fatal (r) == 1) | ||
| |||
1277 | { | ||
1278 | check_alert (j->tls_session, r); | ||
1279 | fprintf (stderrstderr, "Error in handshake\n"); | ||
1280 | GERR (r)fprintf(stdout, "Error: %s\n", safe_strerror(r)); | ||
1281 | |||
1282 | do | ||
1283 | { | ||
1284 | ret = | ||
1285 | gnutls_alert_send_appropriate (j->tls_session, r); | ||
1286 | } | ||
1287 | while (ret == GNUTLS_E_AGAIN-28 | ||
1288 | || ret == GNUTLS_E_INTERRUPTED-52); | ||
1289 | j->http_state = HTTP_STATE_CLOSING3; | ||
1290 | } | ||
1291 | else if (r == 0) | ||
| |||
1292 | { | ||
1293 | if (gnutls_session_is_resumed (j->tls_session) != 0 | ||
| |||
1294 | && verbose == 0) | ||
1295 | printf ("*** This is a resumed session\n"); | ||
1296 | |||
1297 | if (verbose == 0) | ||
| |||
1298 | { | ||
1299 | printf ("\n* Successful handshake from %s\n", | ||
1300 | human_addr ((struct sockaddr *) | ||
| |||
1301 | &client_address, calen, topbuf, | ||
1302 | sizeof (topbuf))); | ||
1303 | print_info (j->tls_session, NULL((void*)0), 1); | ||
1304 | } | ||
1305 | j->handshake_ok = 1; | ||
1306 | } | ||
1307 | } | ||
1308 | |||
1309 | if (j->handshake_ok == 1) | ||
1310 | { | ||
1311 | r = gnutls_record_recv (j->tls_session, buf, | ||
1312 | MIN (1024, SMALL_READ_TEST)(((1024)<((2147483647)))?(1024):((2147483647)))); | ||
1313 | if (r == GNUTLS_E_INTERRUPTED-52 || r == GNUTLS_E_AGAIN-28) | ||
1314 | { | ||
1315 | /* do nothing */ | ||
1316 | } | ||
1317 | else if (r <= 0) | ||
1318 | { | ||
1319 | if (r == GNUTLS_E_REHANDSHAKE-37) | ||
1320 | { | ||
1321 | fprintf (stderrstderr, "*** Received hello message\n"); | ||
1322 | do | ||
1323 | { | ||
1324 | r = gnutls_handshake (j->tls_session); | ||
1325 | } | ||
1326 | while (r == GNUTLS_E_INTERRUPTED-52 | ||
1327 | || r == GNUTLS_E_AGAIN-28); | ||
1328 | |||
1329 | if (r < 0) | ||
1330 | { | ||
1331 | do | ||
1332 | { | ||
1333 | ret = gnutls_alert_send_appropriate | ||
1334 | (j->tls_session, r); | ||
1335 | } | ||
1336 | while (ret == GNUTLS_E_AGAIN-28 | ||
1337 | || ret == GNUTLS_E_INTERRUPTED-52); | ||
1338 | |||
1339 | GERR (r)fprintf(stdout, "Error: %s\n", safe_strerror(r)); | ||
1340 | j->http_state = HTTP_STATE_CLOSING3; | ||
1341 | } | ||
1342 | } | ||
1343 | else | ||
1344 | { | ||
1345 | j->http_state = HTTP_STATE_CLOSING3; | ||
1346 | if (r < 0 && r != GNUTLS_E_UNEXPECTED_PACKET_LENGTH-9) | ||
1347 | { | ||
1348 | check_alert (j->tls_session, r); | ||
1349 | fprintf (stderrstderr, "Error while receiving data\n"); | ||
1350 | GERR (r)fprintf(stdout, "Error: %s\n", safe_strerror(r)); | ||
1351 | } | ||
1352 | } | ||
1353 | } | ||
1354 | else | ||
1355 | { | ||
1356 | j->http_request = | ||
1357 | realloc (j->http_request, j->request_length + r + 1); | ||
1358 | if (j->http_request != NULL((void*)0)) | ||
1359 | { | ||
1360 | memcpy (j->http_request + j->request_length, buf, r); | ||
1361 | j->request_length += r; | ||
1362 | j->http_request[j->request_length] = '\0'; | ||
1363 | } | ||
1364 | else | ||
1365 | j->http_state = HTTP_STATE_CLOSING3; | ||
1366 | |||
1367 | } | ||
1368 | /* check if we have a full HTTP header */ | ||
1369 | |||
1370 | j->http_response = NULL((void*)0); | ||
1371 | if (j->http_request != NULL((void*)0)) | ||
1372 | { | ||
1373 | if ((http == 0 && strchr (j->http_request, '\n')) | ||
1374 | || strstr (j->http_request, "\r\n\r\n") | ||
1375 | || strstr (j->http_request, "\n\n")) | ||
1376 | { | ||
1377 | get_response (j->tls_session, j->http_request, | ||
1378 | &j->http_response, &j->response_length); | ||
1379 | j->http_state = HTTP_STATE_RESPONSE2; | ||
1380 | j->response_written = 0; | ||
1381 | } | ||
1382 | } | ||
1383 | } | ||
1384 | } | ||
1385 | if (FD_ISSET (j->fd, &wr)((((&wr)->fds_bits)[((j->fd) / (8 * (int) sizeof (__fd_mask )))] & ((__fd_mask) 1 << ((j->fd) % (8 * (int) sizeof (__fd_mask))))) != 0)) | ||
1386 | { | ||
1387 | /* write partial response request */ | ||
1388 | int r; | ||
1389 | |||
1390 | if (j->handshake_ok == 0) | ||
1391 | { | ||
1392 | r = gnutls_handshake (j->tls_session); | ||
1393 | if (r < 0 && gnutls_error_is_fatal (r) == 0) | ||
1394 | { | ||
1395 | check_alert (j->tls_session, r); | ||
1396 | /* nothing */ | ||
1397 | } | ||
1398 | else if (r < 0 && gnutls_error_is_fatal (r) == 1) | ||
1399 | { | ||
1400 | int ret; | ||
1401 | |||
1402 | j->http_state = HTTP_STATE_CLOSING3; | ||
1403 | check_alert (j->tls_session, r); | ||
1404 | fprintf (stderrstderr, "Error in handshake\n"); | ||
1405 | GERR (r)fprintf(stdout, "Error: %s\n", safe_strerror(r)); | ||
1406 | |||
1407 | do | ||
1408 | { | ||
1409 | ret = | ||
1410 | gnutls_alert_send_appropriate (j->tls_session, r); | ||
1411 | } | ||
1412 | while (ret == GNUTLS_E_AGAIN-28); | ||
1413 | } | ||
1414 | else if (r == 0) | ||
1415 | { | ||
1416 | if (gnutls_session_is_resumed (j->tls_session) != 0 | ||
1417 | && verbose == 0) | ||
1418 | printf ("*** This is a resumed session\n"); | ||
1419 | if (verbose == 0) | ||
1420 | { | ||
1421 | printf ("- connection from %s\n", | ||
1422 | human_addr ((struct sockaddr *) | ||
1423 | &client_address, calen, topbuf, | ||
1424 | sizeof (topbuf))); | ||
1425 | |||
1426 | print_info (j->tls_session, NULL((void*)0), 1); | ||
1427 | } | ||
1428 | j->handshake_ok = 1; | ||
1429 | } | ||
1430 | } | ||
1431 | |||
1432 | if (j->handshake_ok == 1 && j->http_response != NULL((void*)0)) | ||
1433 | { | ||
1434 | /* FIXME if j->http_response == NULL? */ | ||
1435 | r = gnutls_record_send (j->tls_session, | ||
1436 | j->http_response + | ||
1437 | j->response_written, | ||
1438 | MIN (j->response_length -(((j->response_length - j->response_written)<((2147483647 )))?(j->response_length - j->response_written):((2147483647 ))) | ||
1439 | j->response_written,(((j->response_length - j->response_written)<((2147483647 )))?(j->response_length - j->response_written):((2147483647 ))) | ||
1440 | SMALL_READ_TEST)(((j->response_length - j->response_written)<((2147483647 )))?(j->response_length - j->response_written):((2147483647 )))); | ||
1441 | if (r == GNUTLS_E_INTERRUPTED-52 || r == GNUTLS_E_AGAIN-28) | ||
1442 | { | ||
1443 | /* do nothing */ | ||
1444 | } | ||
1445 | else if (r <= 0) | ||
1446 | { | ||
1447 | if (http != 0) | ||
1448 | j->http_state = HTTP_STATE_CLOSING3; | ||
1449 | else | ||
1450 | { | ||
1451 | j->http_state = HTTP_STATE_REQUEST1; | ||
1452 | free (j->http_response); | ||
1453 | j->response_length = 0; | ||
1454 | j->request_length = 0; | ||
1455 | j->http_request[0] = 0; | ||
1456 | } | ||
1457 | |||
1458 | if (r < 0) | ||
1459 | { | ||
1460 | fprintf (stderrstderr, "Error while sending data\n"); | ||
1461 | GERR (r)fprintf(stdout, "Error: %s\n", safe_strerror(r)); | ||
1462 | } | ||
1463 | check_alert (j->tls_session, r); | ||
1464 | } | ||
1465 | else | ||
1466 | { | ||
1467 | j->response_written += r; | ||
1468 | /* check if we have written a complete response */ | ||
1469 | if (j->response_written == j->response_length) | ||
1470 | { | ||
1471 | if (http != 0) | ||
1472 | j->http_state = HTTP_STATE_CLOSING3; | ||
1473 | else | ||
1474 | { | ||
1475 | j->http_state = HTTP_STATE_REQUEST1; | ||
1476 | free (j->http_response); | ||
1477 | j->response_length = 0; | ||
1478 | j->request_length = 0; | ||
1479 | j->http_request[0] = 0; | ||
1480 | } | ||
1481 | } | ||
1482 | } | ||
1483 | } | ||
1484 | else | ||
1485 | { | ||
1486 | j->request_length = 0; | ||
1487 | j->http_request[0] = 0; | ||
1488 | j->http_state = HTTP_STATE_REQUEST1; | ||
1489 | } | ||
1490 | } | ||
1491 | } | ||
1492 | lloopend (listener_list, j)j = (void *) __tl; }; | ||
1493 | |||
1494 | /* loop through all connections, closing those that are in error */ | ||
1495 | lloopstart (listener_list, j)for (j = (void *) (listener_list).head; j;) { struct list_item *__tl; __tl = (void *) j->next; | ||
1496 | { | ||
1497 | if (j->http_state == HTTP_STATE_CLOSING3) | ||
1498 | { | ||
1499 | ldeleteinc (listener_list, j){ struct list_item *__t; (listener_list).search = 0; __t = (void *) j; if ((void *) (listener_list).head == (void *) __t) (listener_list ).head = (listener_list).head->next; if ((void *) (listener_list ).tail == (void *) __t) (listener_list).tail = (listener_list ).tail->prev; if (__t->next) __t->next->prev = __t ->prev; if (__t->prev) __t->prev->next = __t-> next; __t = __t->next; if ((listener_list).free_func) (*(listener_list ).free_func) ((void *) j); free (j); j = (void *) __t; (listener_list ).length--; }; | ||
1500 | } | ||
1501 | } | ||
1502 | lloopend (listener_list, j)j = (void *) __tl; }; | ||
1503 | } | ||
1504 | |||
1505 | |||
1506 | gnutls_certificate_free_credentials (cert_cred); | ||
1507 | |||
1508 | #ifdef ENABLE_SRP1 | ||
1509 | if (srp_cred) | ||
1510 | gnutls_srp_free_server_credentials (srp_cred); | ||
1511 | #endif | ||
1512 | |||
1513 | #ifdef ENABLE_PSK1 | ||
1514 | if (psk_cred) | ||
1515 | gnutls_psk_free_server_credentials (psk_cred); | ||
1516 | #endif | ||
1517 | |||
1518 | #ifdef ENABLE_ANON1 | ||
1519 | gnutls_anon_free_server_credentials (dh_cred); | ||
1520 | #endif | ||
1521 | |||
1522 | #ifdef ENABLE_SESSION_TICKET | ||
1523 | if (noticket == 0) | ||
1524 | gnutls_free (session_ticket_key.data); | ||
1525 | #endif | ||
1526 | |||
1527 | if (nodb == 0) | ||
1528 | wrap_db_deinit (); | ||
1529 | gnutls_global_deinit (); | ||
1530 | |||
1531 | } | ||
1532 | |||
1533 | void | ||
1534 | gaa_parser (int argc, char **argv) | ||
1535 | { | ||
1536 | if (gaa (argc, argv, &info) != -1) | ||
1537 | { | ||
1538 | fprintf (stderrstderr, | ||
1539 | "Error in the arguments. Use the --help or -h parameters to get more information.\n"); | ||
1540 | exit (1); | ||
1541 | } | ||
1542 | |||
1543 | disable_client_cert = info.disable_client_cert; | ||
1544 | require_cert = info.require_cert; | ||
1545 | debug = info.debug; | ||
1546 | verbose = info.quiet; | ||
1547 | nodb = info.nodb; | ||
1548 | noticket = info.noticket; | ||
1549 | |||
1550 | if (info.http == 0) | ||
1551 | http = 0; | ||
1552 | else | ||
1553 | http = 1; | ||
1554 | |||
1555 | if (info.fmtder == 0) | ||
1556 | x509ctype = GNUTLS_X509_FMT_PEM; | ||
1557 | else | ||
1558 | x509ctype = GNUTLS_X509_FMT_DER; | ||
1559 | |||
1560 | if (info.generate == 0) | ||
1561 | generate = 0; | ||
1562 | else | ||
1563 | generate = 1; | ||
1564 | |||
1565 | dh_params_file = info.dh_params_file; | ||
1566 | |||
1567 | x509_certfile = info.x509_certfile; | ||
1568 | x509_keyfile = info.x509_keyfile; | ||
1569 | x509_dsacertfile = info.x509_dsacertfile; | ||
1570 | x509_dsakeyfile = info.x509_dsakeyfile; | ||
1571 | x509_ecccertfile = info.x509_ecccertfile; | ||
1572 | x509_ecckeyfile = info.x509_ecckeyfile; | ||
1573 | x509_cafile = info.x509_cafile; | ||
1574 | x509_crlfile = info.x509_crlfile; | ||
1575 | pgp_certfile = info.pgp_certfile; | ||
1576 | pgp_keyfile = info.pgp_keyfile; | ||
1577 | srp_passwd = info.srp_passwd; | ||
1578 | srp_passwd_conf = info.srp_passwd_conf; | ||
1579 | |||
1580 | psk_passwd = info.psk_passwd; | ||
1581 | |||
1582 | pgp_keyring = info.pgp_keyring; | ||
1583 | } | ||
1584 | |||
1585 | extern void serv_version (void); | ||
1586 | |||
1587 | void | ||
1588 | serv_version (void) | ||
1589 | { | ||
1590 | const char *p = PACKAGE_NAME"GnuTLS"; | ||
1591 | if (strcmp (gnutls_check_version (NULL((void*)0)), PACKAGE_VERSION"3.0.12") != 0) | ||
1592 | p = PACKAGE_STRING"GnuTLS 3.0.12"; | ||
1593 | version_etc (stdoutstdout, program_name, p, gnutls_check_version (NULL((void*)0)), | ||
1594 | "Nikos Mavrogiannopoulos", (char *) NULL((void*)0)); | ||
1595 | } | ||
1596 | |||
1597 | /* session resuming support */ | ||
1598 | |||
1599 | #define SESSION_ID_SIZE32 32 | ||
1600 | #define SESSION_DATA_SIZE1024 1024 | ||
1601 | |||
1602 | typedef struct | ||
1603 | { | ||
1604 | char session_id[SESSION_ID_SIZE32]; | ||
1605 | unsigned int session_id_size; | ||
1606 | |||
1607 | char session_data[SESSION_DATA_SIZE1024]; | ||
1608 | unsigned int session_data_size; | ||
1609 | } CACHE; | ||
1610 | |||
1611 | static CACHE *cache_db; | ||
1612 | int cache_db_ptr = 0; | ||
1613 | |||
1614 | static void | ||
1615 | wrap_db_init (void) | ||
1616 | { | ||
1617 | /* allocate cache_db */ | ||
1618 | cache_db = calloc (1, ssl_session_cache * sizeof (CACHE)); | ||
1619 | } | ||
1620 | |||
1621 | static void | ||
1622 | wrap_db_deinit (void) | ||
1623 | { | ||
1624 | } | ||
1625 | |||
1626 | static int | ||
1627 | wrap_db_store (void *dbf, gnutls_datum_t key, gnutls_datum_t data) | ||
1628 | { | ||
1629 | |||
1630 | if (cache_db == NULL((void*)0)) | ||
1631 | return -1; | ||
1632 | |||
1633 | if (key.size > SESSION_ID_SIZE32) | ||
1634 | return -1; | ||
1635 | if (data.size > SESSION_DATA_SIZE1024) | ||
1636 | return -1; | ||
1637 | |||
1638 | memcpy (cache_db[cache_db_ptr].session_id, key.data, key.size); | ||
1639 | cache_db[cache_db_ptr].session_id_size = key.size; | ||
1640 | |||
1641 | memcpy (cache_db[cache_db_ptr].session_data, data.data, data.size); | ||
1642 | cache_db[cache_db_ptr].session_data_size = data.size; | ||
1643 | |||
1644 | cache_db_ptr++; | ||
1645 | cache_db_ptr %= ssl_session_cache; | ||
1646 | |||
1647 | return 0; | ||
1648 | } | ||
1649 | |||
1650 | static gnutls_datum_t | ||
1651 | wrap_db_fetch (void *dbf, gnutls_datum_t key) | ||
1652 | { | ||
1653 | gnutls_datum_t res = { NULL((void*)0), 0 }; | ||
1654 | int i; | ||
1655 | |||
1656 | if (cache_db == NULL((void*)0)) | ||
1657 | return res; | ||
1658 | |||
1659 | for (i = 0; i < ssl_session_cache; i++) | ||
1660 | { | ||
1661 | if (key.size == cache_db[i].session_id_size && | ||
1662 | memcmp (key.data, cache_db[i].session_id, key.size) == 0) | ||
1663 | { | ||
1664 | res.size = cache_db[i].session_data_size; | ||
1665 | |||
1666 | res.data = gnutls_malloc (res.size); | ||
1667 | if (res.data == NULL((void*)0)) | ||
1668 | return res; | ||
1669 | |||
1670 | memcpy (res.data, cache_db[i].session_data, res.size); | ||
1671 | |||
1672 | return res; | ||
1673 | } | ||
1674 | } | ||
1675 | return res; | ||
1676 | } | ||
1677 | |||
1678 | static int | ||
1679 | wrap_db_delete (void *dbf, gnutls_datum_t key) | ||
1680 | { | ||
1681 | int i; | ||
1682 | |||
1683 | if (cache_db == NULL((void*)0)) | ||
1684 | return -1; | ||
1685 | |||
1686 | for (i = 0; i < ssl_session_cache; i++) | ||
1687 | { | ||
1688 | if (key.size == (unsigned int) cache_db[i].session_id_size && | ||
1689 | memcmp (key.data, cache_db[i].session_id, key.size) == 0) | ||
1690 | { | ||
1691 | |||
1692 | cache_db[i].session_id_size = 0; | ||
1693 | cache_db[i].session_data_size = 0; | ||
1694 | |||
1695 | return 0; | ||
1696 | } | ||
1697 | } | ||
1698 | |||
1699 | return -1; | ||
1700 | } |