1 /* vi:ai:et:ts=8 sw=2
2 */
3 /*
4 * wzdftpd - a modular and cool ftp server
5 * Copyright (C) 2002-2004 Pierre Chifflier
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 *
21 * As a special exemption, Pierre Chifflier
22 * and other respective copyright holders give permission to link this program
23 * with OpenSSL, and distribute the resulting executable, without including
24 * the source code for OpenSSL in the source distribution.
25 */
26
27 #include "wzd_all.h"
28
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
32
33 #ifdef HAVE_OPENSSL
34
35 #if defined(WIN32) || (defined(__CYGWIN__) && defined(WINSOCK_SUPPORT))
36 #include <winsock2.h>
37 #else
38 #include <dlfcn.h>
39 #endif
40
41 #include <openssl/ssl.h>
42 #include <openssl/rand.h>
43 #include <openssl/err.h>
44
45 #include <stdio.h>
46 #include <string.h>
47 #include <fcntl.h>
48
49 #include "wzd_structs.h"
50 #include "wzd_log.h"
51
52 #include "wzd_tls.h"
53
54 #include "wzd_configfile.h"
55 #include "wzd_messages.h"
56
57 #include "wzd_debug.h"
58
59
60 /** @brief SSL connection objects */
61 struct wzd_ssl_t {
62 SSL * obj;
63 SSL * data_ssl;
64 ssl_fd_mode_t ssl_fd_mode;
65 };
66
67
68
tls_context_init(wzd_context_t * context)69 void tls_context_init(wzd_context_t * context)
70 {
71 context->ssl = wzd_malloc(sizeof(struct wzd_ssl_t));
72 memset(context->ssl,0,sizeof(struct wzd_ssl_t));
73 }
74
75 /*************** tls_auth_setfd_set *********************/
76
tls_auth_setfd_set(wzd_context_t * context,fd_set * r,fd_set * w)77 void tls_auth_setfd_set(wzd_context_t * context, fd_set *r, fd_set *w)
78 {
79 unsigned int socket;
80
81 WZD_ASSERT_VOID(context != NULL);
82 WZD_ASSERT_VOID(context->ssl != NULL);
83
84 socket = SSL_get_fd(context->ssl->obj);
85
86 if (context->ssl->ssl_fd_mode == TLS_READ)
87 FD_SET(socket,r);
88 else if (context->ssl->ssl_fd_mode == TLS_WRITE)
89 FD_SET(socket,w);
90 }
91
92 /*************** tls_auth_data_setfd_set ***************/
93
tls_auth_data_setfd_set(wzd_context_t * context,fd_set * r,fd_set * w)94 void tls_auth_data_setfd_set(wzd_context_t * context, fd_set *r, fd_set *w)
95 {
96 unsigned int socket;
97
98 WZD_ASSERT_VOID(context != NULL);
99 WZD_ASSERT_VOID(context->ssl != NULL);
100
101 socket = SSL_get_fd(context->ssl->data_ssl);
102
103 if (context->ssl->ssl_fd_mode == TLS_READ)
104 FD_SET(socket,r);
105 else if (context->ssl->ssl_fd_mode == TLS_WRITE)
106 FD_SET(socket,w);
107 }
108
109
_tls_verify_callback(int preverify_ok,X509_STORE_CTX * x509_ctx)110 static int _tls_verify_callback(int preverify_ok, X509_STORE_CTX *x509_ctx)
111 {
112 #ifdef DEBUG
113 out_log(LEVEL_FLOOD,"_tls_verify_callback (%d, %p)\n",preverify_ok,x509_ctx);
114 #endif
115
116 return 1;
117 }
118
_tls_X509NameCmp(X509_NAME ** a,X509_NAME ** b)119 static int _tls_X509NameCmp(X509_NAME **a, X509_NAME **b)
120 {
121 return(X509_NAME_cmp(*a, *b));
122 }
123
_tls_push_ca_list(STACK_OF (X509_NAME)* ca_list,const char * ca_file)124 static void _tls_push_ca_list(STACK_OF(X509_NAME) *ca_list, const char *ca_file)
125 {
126 STACK_OF(X509_NAME) *sk;
127 int i;
128
129 if (!(sk = SSL_load_client_CA_file(ca_file))) return;
130
131 for (i=0; i<sk_X509_NAME_num(sk); i++) {
132 char name_buf[256];
133 X509_NAME *name;
134
135 name = sk_X509_NAME_value(sk, i);
136 out_err(LEVEL_FLOOD,"CA certificate: %s\n",X509_NAME_oneline(name, name_buf, sizeof(name_buf)));
137
138 /*
139 * note that SSL_load_client_CA_file() checks for duplicates,
140 * but since we call it multiple times when reading a directory
141 * we must also check for duplicates ourselves.
142 */
143
144 if (sk_X509_NAME_find(ca_list, name) < 0) {
145 /* this will be freed when ca_list is */
146 sk_X509_NAME_push(ca_list, name);
147 }
148 else {
149 /* need to free this ourselves, else it will leak */
150 X509_NAME_free(name);
151 }
152 }
153
154 sk_X509_NAME_free(sk);
155 }
156
STACK_OF(X509_NAME)157 static STACK_OF(X509_NAME) * _tls_init_ca_list(const char *ca_file, const char *ca_path)
158 {
159 STACK_OF(X509_NAME) * ca_list;
160
161 /* sorted order */
162 ca_list = sk_X509_NAME_new(_tls_X509NameCmp);
163
164 if (ca_file) {
165 _tls_push_ca_list(ca_list,ca_file);
166 }
167
168 /*
169 * Process CA certificate path files
170 */
171 if (ca_path) {
172 /* parse directory and call _tls_push_ca_list(ca_list,ca_file)
173 * for each entry
174 */
175 }
176
177 /*
178 * Cleanup
179 */
180 (void)sk_X509_NAME_set_cmp_func(ca_list, NULL);
181
182 return ca_list;
183 }
184
185 /*************** tls_init ****************************/
186
tls_init(void)187 int tls_init(void)
188 {
189 int status;
190 SSL_CTX * tls_ctx;
191 char * tls_certificate;
192 char * tls_certificate_key;
193 char * tls_ca_file=NULL, * tls_ca_path=NULL;
194 wzd_string_t * str;
195
196 if (CFG_GET_OPTION(mainConfig,CFG_OPT_DISABLE_TLS)) {
197 out_log(LEVEL_INFO,"TLS Disabled by config\n");
198 return 0;
199 }
200
201 {
202 str = config_get_string(mainConfig->cfg_file, "GLOBAL", "tls_certificate", NULL);
203 if (!str) {
204 out_log(LEVEL_CRITICAL,"TLS: no certificate provided. (use tls_certificate directive in config)\n");
205 return 1;
206 }
207 /** \bug FIXME memory leak here !! */
208 tls_certificate = strdup(str_tochar(str));
209 str_deallocate(str);
210 /* ignore errors */
211 str = config_get_string(mainConfig->cfg_file, "GLOBAL", "tls_ca_file", NULL);
212 if (str) {
213 /** \bug FIXME memory leak here !! */
214 tls_ca_file = strdup(str_tochar(str));
215 str_deallocate(str);
216 }
217 str = config_get_string(mainConfig->cfg_file, "GLOBAL", "tls_ca_path", NULL);
218 if (str) {
219 /** \bug FIXME memory leak here !! */
220 tls_ca_path = strdup(str_tochar(str));
221 str_deallocate(str);
222 }
223 }
224
225 out_log(LEVEL_INFO,"Initializing TLS (this can take a while).\n");
226
227 ERR_load_ERR_strings();
228 SSL_load_error_strings(); /* readable error messages */
229 SSL_library_init(); /* initialize library */
230
231 mainConfig->tls_ctx = tls_ctx = SSL_CTX_new(SSLv23_server_method());
232 if (!tls_ctx) {
233 out_log(LEVEL_CRITICAL,"SSL_CTX_new() %s\r\n",(char *)ERR_error_string(ERR_get_error(), NULL));
234 return 1;
235 }
236
237 if (RAND_status() != 1) {
238 out_log(LEVEL_HIGH,"ssl_init: System without entropy source\n");
239 }
240
241 /* TODO choose the ssl algorithm ? */
242 SSL_CTX_set_options(tls_ctx, SSL_OP_NO_SSLv2);
243 SSL_CTX_set_default_verify_paths(tls_ctx);
244
245 /* set certificate */
246 /* from manual: SSL_CTX_use_certificate_chain_file should be prefered to
247 * SSL_CTX_use_certificate_file
248 */
249 /* status = SSL_CTX_use_certificate_file(tls_ctx, mainConfig->tls_certificate, X509_FILETYPE_PEM);*/
250 status = SSL_CTX_use_certificate_chain_file(tls_ctx, tls_certificate);
251 if (status <= 0) {
252 out_log(LEVEL_CRITICAL,"SSL_CTX_use_certificate_chain_file(%s) %s\n", tls_certificate, (char *)ERR_error_string(ERR_get_error(), NULL));
253 SSL_CTX_free(tls_ctx);
254 mainConfig->tls_ctx = NULL;
255 return 1;
256 }
257
258 /* set private key file - usually the same */
259 {
260 str = config_get_string(mainConfig->cfg_file, "GLOBAL", "tls_certificate_key", NULL);
261 if (str) {
262 /** \bug FIXME memory leak here !! */
263 tls_certificate_key = strdup(str_tochar(str));
264 str_deallocate(str);
265 } else {
266 /* if no key provided, try using the same certificate */
267 tls_certificate_key = tls_certificate;
268 }
269 }
270
271 status = SSL_CTX_use_PrivateKey_file(tls_ctx, tls_certificate_key, X509_FILETYPE_PEM);
272 if (status <= 0) {
273 out_log(LEVEL_CRITICAL,"SSL_CTX_use_PrivateKey_file(%s) %s\n", tls_certificate_key, (char *)ERR_error_string(ERR_get_error(), NULL));
274 SSL_CTX_free(tls_ctx);
275 mainConfig->tls_ctx = NULL;
276 return 1;
277 }
278
279 SSL_CTX_set_verify(tls_ctx, SSL_VERIFY_PEER, _tls_verify_callback);
280
281 if (tls_ca_file || tls_ca_path) {
282 STACK_OF(X509_NAME) * ca_list;
283
284 if (!SSL_CTX_load_verify_locations(tls_ctx, tls_ca_file, tls_ca_path))
285 {
286 out_log(LEVEL_CRITICAL,"SSL_CTX_load_verify_locations(%s,%s) %s\n", tls_ca_file, tls_ca_path, (char *)ERR_error_string(ERR_get_error(), NULL));
287 SSL_CTX_free(tls_ctx);
288 mainConfig->tls_ctx = NULL;
289 return 1;
290 }
291
292 ca_list = _tls_init_ca_list(tls_ca_file,tls_ca_path);
293 if (!ca_list) {
294 out_log(LEVEL_CRITICAL,"_tls_init_ca_list(%s,%s) %s\n", tls_ca_file, tls_ca_path, (char *)ERR_error_string(ERR_get_error(), NULL));
295 SSL_CTX_free(tls_ctx);
296 mainConfig->tls_ctx = NULL;
297 return 1;
298 }
299
300 SSL_CTX_set_client_CA_list(tls_ctx, ca_list);
301 }
302
303 SSL_CTX_set_session_cache_mode(tls_ctx, SSL_SESS_CACHE_CLIENT);
304 SSL_CTX_set_session_id_context(tls_ctx, (const unsigned char *) "1", 1);
305
306 out_log(LEVEL_INFO,"TLS initialization successful.\n");
307
308 return 0;
309 }
310
311 /*************** tls_exit ****************************/
312
tls_exit(void)313 int tls_exit(void)
314 {
315 if (CFG_GET_OPTION(mainConfig,CFG_OPT_DISABLE_TLS)) {
316 return 0;
317 }
318 EVP_cleanup();
319 CRYPTO_cleanup_all_ex_data();
320
321 ERR_clear_error();
322 ERR_remove_state(0);
323
324 ERR_free_strings();
325
326 SSL_CTX_free(mainConfig->tls_ctx);
327 return 0;
328 }
329
330
331 /*************** tls_read ****************************/
332
tls_read(fd_t sock,char * msg,size_t length,int flags,unsigned int timeout,void * vcontext)333 int tls_read(fd_t sock, char *msg, size_t length, int flags, unsigned int timeout, void * vcontext)
334 {
335 wzd_context_t * context = (wzd_context_t*)vcontext;
336 SSL * ssl;
337 int ret;
338 int sslerr;
339 int r;
340 fd_set fd_r, fd_w;
341 struct timeval tv;
342
343 WZD_ASSERT(context != NULL);
344 WZD_ASSERT(context->ssl != NULL);
345
346 /* FIXME bad conception of parameters ... */
347 if (sock == context->controlfd)
348 {
349 ssl = context->ssl->obj;
350 }
351 else
352 {
353 ssl = context->ssl->data_ssl;
354 /* XXX we assume that if sock != context->controlfd, then we have datas ... */
355 }
356 do {
357 ret = SSL_read(ssl, msg, length);
358 sslerr = SSL_get_error(ssl, ret);
359 if (ret>0) {
360 r = 1;
361 break;
362 }
363
364 FD_ZERO(&fd_r);
365 FD_ZERO(&fd_w);
366 tv.tv_sec = timeout;
367 tv.tv_usec = 0;
368
369 switch (sslerr) {
370 case SSL_ERROR_WANT_READ:
371 FD_SET(sock,&fd_r);
372 break;
373 case SSL_ERROR_WANT_WRITE:
374 FD_SET(sock,&fd_w);
375 break;
376 default:
377 /* FIXME - could also mean peer has closed connection - test error code ? */
378 if (sslerr == SSL_ERROR_ZERO_RETURN) { /* remote host has closed connection */
379 return -1;
380 }
381 out_err(LEVEL_INFO,"SSL_read failed %d\n",sslerr);
382 return -1;
383 }
384
385 r = select(sock+1,&fd_r,&fd_w,NULL,&tv);
386 } while (ret == -1 && r != 0);
387
388 if (r==0)
389 return -1;
390 return ret;
391 }
392
393 /*************** tls_write ***************************/
394
tls_write(fd_t sock,const char * msg,size_t length,int flags,unsigned int timeout,void * vcontext)395 int tls_write(fd_t sock, const char *msg, size_t length, int flags, unsigned int timeout, void * vcontext)
396 {
397 wzd_context_t * context = (wzd_context_t*)vcontext;
398 SSL * ssl;
399 int ret;
400 int sslerr;
401 int r;
402 fd_set fd_r, fd_w;
403 struct timeval tv;
404
405 WZD_ASSERT(context != NULL);
406 WZD_ASSERT(context->ssl != NULL);
407
408 /* FIXME bad conception of parameters ... */
409 if (sock == context->controlfd)
410 ssl = context->ssl->obj;
411 else
412 ssl = context->ssl->data_ssl;
413 /* XXX we assume that if sock != context->controlfd, then we have datas ... */
414
415 WZD_ASSERT( ssl != NULL );
416
417 do {
418 ret = SSL_write(ssl, msg, length);
419 sslerr = SSL_get_error(ssl, ret);
420
421 if (ret > 0) {
422 r = 1;
423 break;
424 }
425
426 FD_ZERO(&fd_r);
427 FD_ZERO(&fd_w);
428 tv.tv_sec = timeout;
429 tv.tv_usec = 0;
430
431 switch (sslerr) {
432 case SSL_ERROR_WANT_READ:
433 FD_SET(sock,&fd_r);
434 break;
435 case SSL_ERROR_WANT_WRITE:
436 FD_SET(sock,&fd_w);
437 break;
438 default:
439 out_err(LEVEL_INFO,"SSL_write failed\n");
440 return -1;
441 }
442
443 r = select(sock+1,&fd_r,&fd_w,NULL,&tv);
444 } while (ret == -1 && r != 0);
445
446 if (r==0)
447 return -1;
448 return ret;
449 }
450
451 /*************** tls_auth ****************************/
452
453 /** The mode distinction is REALLY important
454 *
455 * in implicit mode, we do not send anything (there's no client at this point)
456 *
457 * in explicit mode, the client is waiting for our answer
458 */
tls_auth(const char * type,wzd_context_t * context)459 int tls_auth (const char *type, wzd_context_t * context)
460 {
461 int ret;
462 char * tls_cipher_list;
463 wzd_string_t * str;
464
465 WZD_ASSERT(mainConfig->tls_ctx != NULL);
466 if (mainConfig->tls_ctx == NULL) {
467 out_log(LEVEL_CRITICAL,"tls_auth (%d): TLS was NOT initialized, but we're trying to auth a client !\n",__LINE__);
468 return -1;
469 }
470
471 #if 0
472 if (!type || type[0]==0) return 1;
473
474 if (strcasecmp(type,"SSL")==0 || mainConfig->tls_type == TLS_IMPLICIT)
475 context->ssl.data_mode = TLS_PRIV; /* SSL must hava encrypted data connection */
476 else
477 context->ssl.data_mode = TLS_CLEAR;
478
479 if (mainConfig->tls_type != TLS_IMPLICIT) {
480 ret = send_message_with_args(234, context, type);
481 }
482 #endif
483
484 {
485 str = config_get_string(mainConfig->cfg_file, "GLOBAL", "tls_cipher_list", NULL);
486 if (str) {
487 /** \bug FIXME memory leak here !! */
488 tls_cipher_list = strdup(str_tochar(str));
489 str_deallocate(str);
490 } else {
491 tls_cipher_list = "ALL";
492 }
493 }
494
495 context->ssl->obj = SSL_new(mainConfig->tls_ctx);
496 if (context->ssl->obj == NULL) {
497 out_log(LEVEL_CRITICAL,"SSL_new failed (%s)\n",ERR_error_string(ERR_get_error(),NULL));
498 return 1;
499 }
500 SSL_set_cipher_list(context->ssl->obj,tls_cipher_list);
501 ret = SSL_set_fd(context->ssl->obj,context->controlfd);
502 if (ret != 1) {
503 out_log(LEVEL_CRITICAL,"SSL_set_fd failed (%s)\n",ERR_error_string(ERR_get_error(),NULL));
504 return 1;
505 }
506
507 #ifdef WZD_DBG_TLS
508 out_err(LEVEL_HIGH,"tls_auth ok\n");
509 #endif
510
511 return tls_auth_cont(context);
512 }
513
514 /*************** tls_auth_cont ***********************/
515
tls_auth_cont(wzd_context_t * context)516 int tls_auth_cont(wzd_context_t * context)
517 {
518 /* non blocking test */
519 #if 1
520 SSL * ssl = context->ssl->obj;
521 unsigned int fd;
522 int ret, status, sslerr;
523 fd_set fd_r, fd_w;
524 struct timeval tv;
525
526 #ifdef WZD_DBG_TLS
527 out_err(LEVEL_HIGH,"TLS: Non-blocking accept\n");
528 #endif
529
530 SSL_set_accept_state(ssl);
531 fd = SSL_get_fd(ssl);
532 /* ensure socket is non-blocking */
533 #if defined(WIN32) || (defined(__CYGWIN__) && defined(WINSOCK_SUPPORT))
534 {
535 unsigned long noBlock=1;
536 ioctlsocket(fd,FIONBIO,&noBlock);
537 }
538 #else
539 fcntl(fd,F_SETFL,(fcntl(fd,F_GETFL)|O_NONBLOCK));
540 #endif
541 do {
542 status = SSL_accept(ssl);
543 sslerr = SSL_get_error(ssl,status);
544 if (status == 1) {
545 out_log(LEVEL_INFO,"control connection succesfully switched to ssl (cipher: %s)\n",SSL_get_cipher(ssl));
546 ret = 1;
547 break;
548 } else {
549 context->ssl->ssl_fd_mode = TLS_NONE;
550 FD_ZERO(&fd_r);
551 FD_ZERO(&fd_w);
552 tv.tv_usec = 0;
553 tv.tv_sec = 5;
554 switch (sslerr) {
555 case SSL_ERROR_WANT_READ:
556 FD_SET(fd,&fd_r);
557 context->ssl->ssl_fd_mode = TLS_READ;
558 break;
559 case SSL_ERROR_WANT_WRITE:
560 FD_SET(fd,&fd_w);
561 context->ssl->ssl_fd_mode = TLS_WRITE;
562 break;
563 default:
564 out_log(LEVEL_HIGH,"Error accepting connection: ret %d error code %d : %s\n",status,sslerr,
565 ERR_error_string(SSL_get_error(context->ssl->obj,status),NULL));
566 out_log(LEVEL_HIGH,"Error accepting connection: ret %d error code %ld : %s\n",status,ERR_get_error(),
567 ERR_error_string(ERR_get_error(),NULL));
568 return 1;
569 }
570 ret = select(fd+1,&fd_r,&fd_w,NULL,&tv);
571 if ( ! (FD_ISSET(fd,&fd_r) || FD_ISSET(fd,&fd_w)) ) { /* timeout */
572 out_err(LEVEL_HIGH,"tls_auth_cont failed\n");
573 return -1;
574 }
575 }
576 } while (status == -1 && ret != 0);
577
578 if (ret==0) {
579 out_err(LEVEL_CRITICAL,"tls_auth_cont failed\n");
580 return -1;
581 }
582
583 context->ssl->data_ssl = NULL;
584
585 /* set read/write functions */
586 context->read_fct = (read_fct_t)tls_read;
587 context->write_fct = (write_fct_t)tls_write;
588
589 return 0;
590 #else
591 int ret;
592
593 #ifdef WZD_DBG_TLS
594 out_err(LEVEL_HIGH,"TLS: Blocking accept\n");
595 #endif
596
597 ret = SSL_accept(context->ssl.obj);
598 if (ret == 1) {
599 } else {
600 context->ssl.ssl_fd_mode = TLS_NONE;
601 switch (ret) {
602 case SSL_ERROR_WANT_READ:
603 context->ssl.ssl_fd_mode = TLS_READ;
604 break;
605 case SSL_ERROR_WANT_WRITE:
606 context->ssl.ssl_fd_mode = TLS_WRITE;
607 break;
608 default:
609 out_log(LEVEL_HIGH,"Error accepting connection: ret %d error code %d : %s\n",ret,SSL_get_error(context->ssl.obj,ret),
610 ERR_error_string(SSL_get_error(context->ssl.obj,ret),NULL));
611 out_log(LEVEL_HIGH,"Error accepting connection: ret %d error code %d : %s\n",ret,ERR_get_error(),
612 ERR_error_string(ERR_get_error(),NULL));
613 return 1;
614 }
615 }
616
617 context->ssl.data_ssl = NULL;
618
619 /* set read/write functions */
620 context->read_fct = (read_fct_t)tls_read;
621 context->write_fct = (write_fct_t)tls_write;
622
623 return 0;
624 #endif
625 }
626
627 /*************** tls_init_datamode *******************/
628
tls_init_datamode(int sock,wzd_context_t * context)629 int tls_init_datamode(int sock, wzd_context_t * context)
630 {
631 char * tls_cipher_list;
632 wzd_string_t * str;
633
634 if (!context->ssl->data_ssl) {
635 context->ssl->data_ssl = SSL_new(mainConfig->tls_ctx);
636 }
637 else {
638 out_log(LEVEL_CRITICAL,"tls_init_datamode: this should NOT be happening\n");
639 return 1;
640 }
641
642 if (!context->ssl->data_ssl) {
643 out_log(LEVEL_CRITICAL,"SSL_new error\n");
644 return 1;
645 }
646
647 {
648 str = config_get_string(mainConfig->cfg_file, "GLOBAL", "tls_cipher_list", NULL);
649 if (str) {
650 /** \bug FIXME memory leak here !! */
651 tls_cipher_list = strdup(str_tochar(str));
652 str_deallocate(str);
653 } else {
654 tls_cipher_list = "ALL";
655 }
656 }
657
658 SSL_set_cipher_list(context->ssl->data_ssl, tls_cipher_list);
659
660 #if defined(WIN32) || (defined(__CYGWIN__) && defined(WINSOCK_SUPPORT))
661 {
662 unsigned long noBlock=1;
663 ioctlsocket(sock,FIONBIO,&noBlock);
664 }
665 #else
666 fcntl(sock,F_SETFL,(fcntl(sock,F_GETFL)|O_NONBLOCK));
667 #endif
668 if (SSL_set_fd(context->ssl->data_ssl, sock) != 1)
669 /* FIXME PORT ? */
670 out_log(LEVEL_CRITICAL,"SSL_set_fd error\n");
671
672 return tls_auth_data_cont(context);
673 }
674
675 /*************** tls_auth_data_cont ******************/
676
tls_auth_data_cont(wzd_context_t * context)677 int tls_auth_data_cont(wzd_context_t * context)
678 {
679 SSL * ssl = context->ssl->data_ssl;
680 int status, sslerr;
681 fd_set fd_r, fd_w;
682 struct timeval tv;
683 unsigned int fd,r;
684
685 if (context->tls_role == TLS_SERVER_MODE)
686 SSL_set_accept_state(ssl);
687 else
688 SSL_set_connect_state(ssl);
689
690 fd = SSL_get_fd(ssl);
691 do {
692 if (context->tls_role == TLS_SERVER_MODE)
693 status = SSL_accept(ssl);
694 else
695 status = SSL_connect(ssl);
696
697 sslerr = SSL_get_error(ssl,status);
698
699 if (status==1) {
700 out_log(LEVEL_INFO,"Data connection succesfully switched to ssl (cipher: %s)\n",SSL_get_cipher(ssl));
701 context->tls_data_mode = TLS_PRIV;
702 return 0;
703 } else {
704 FD_ZERO(&fd_r);
705 FD_ZERO(&fd_w);
706 tv.tv_usec = 0;
707 tv.tv_sec = 5;
708 switch (sslerr) {
709 case SSL_ERROR_WANT_READ:
710 FD_SET(fd,&fd_r);
711 out_err(LEVEL_FLOOD,"SSL_ERROR_WANT_READ\n");
712 break;
713 case SSL_ERROR_WANT_WRITE:
714 FD_SET(fd,&fd_w);
715 out_err(LEVEL_FLOOD,"SSL_ERROR_WANT_WRITE\n");
716 break;
717 default:
718 out_log(LEVEL_HIGH,"tls_auth_data_cont: error accepting: %s\n",
719 (char*)ERR_error_string(sslerr,NULL));
720 tls_close_data(context);
721 return 1;
722 }
723 r = select(fd+1, &fd_r, &fd_w, NULL, &tv);
724 }
725 } while (status == -1 && r != 0);
726
727 if (r == 0) {
728 out_err(LEVEL_CRITICAL,"tls_auth_data_cont failed\n");
729 tls_close_data(context);
730 return -1;
731 }
732
733 return 0;
734 }
735
736 /*************** tls_close_data **********************/
737
tls_close_data(wzd_context_t * context)738 int tls_close_data(wzd_context_t * context)
739 {
740 if (context->ssl->data_ssl) {
741 if (SSL_shutdown(context->ssl->data_ssl)==0)
742 SSL_shutdown(context->ssl->data_ssl);
743 SSL_free(context->ssl->data_ssl);
744 }
745 context->ssl->data_ssl = NULL;
746
747 return 0;
748 }
749
750 /***************** tls_free **************************/
751
tls_free(wzd_context_t * context)752 int tls_free(wzd_context_t * context)
753 {
754 tls_close_data(context);
755 if (context->ssl->obj) {
756 if (SSL_shutdown(context->ssl->obj)==0)
757 SSL_shutdown(context->ssl->obj);
758 SSL_free(context->ssl->obj);
759 }
760 context->ssl->obj = NULL;
761
762 ERR_remove_state(0);
763 ERR_clear_error();
764 return 0;
765 }
766
ssl_get_obj(wzd_context_t * context)767 void * ssl_get_obj(wzd_context_t * context)
768 {
769 if (context && context->ssl) return context->ssl->obj;
770
771 return NULL;
772 }
773
774 #endif /* HAVE_OPENSSL */
775
776 #ifdef HAVE_GNUTLS
777
778 #include <stdlib.h>
779 #include <stdio.h>
780
781 #include <gnutls/gnutls.h>
782 #include <errno.h>
783 #include <pthread.h>
784 GCRY_THREAD_OPTION_PTHREAD_IMPL;
785
786 #include <fcntl.h>
787
788 /** \warning setting this value to > 512 will cause problems for compatibility
789 * with OpenSSL
790 */
791 #define SERVER_DH_BITS 768
792 #define CLIENT_DH_BITS 512
793
794 #define DH_BITS 1024
795
796
797 #include "wzd_structs.h"
798 #include "wzd_log.h"
799
800 #include "wzd_configfile.h"
801 #include "wzd_crontab.h"
802 #include "wzd_libmain.h"
803 #include "wzd_tls.h"
804
805 #include "wzd_messages.h"
806
807 #include "wzd_debug.h"
808
809 /*************** tls_init ****************************/
810
811 /* These are global */
812 static gnutls_certificate_credentials x509_cred;
813 static gnutls_dh_params dh_params;
814
generate_dh_params(void)815 static int generate_dh_params(void)
816 {
817
818 /* Generate Diffie Hellman parameters - for use with DHE
819 * kx algorithms. These should be discarded and regenerated
820 * once a day, once a week or once a month. Depending on the
821 * security requirements.
822 */
823 gnutls_dh_params_init(&dh_params);
824 gnutls_dh_params_generate2(dh_params, SERVER_DH_BITS);
825
826 return 0;
827 }
828
tls_dh_params_regenerate(void)829 int tls_dh_params_regenerate(void)
830 {
831 int ret;
832 gnutls_dh_params new, tmp;
833
834 if (CFG_GET_OPTION(mainConfig,CFG_OPT_DISABLE_TLS)) {
835 out_log(LEVEL_FLOOD,"TLS Disabled by config (tls_dh_params_regenerate)\n");
836 return 0;
837 }
838
839 /* generate a new DH key */
840 ret = gnutls_dh_params_init(&new);
841 if (ret < 0) {
842 out_log(LEVEL_HIGH,"error initializing dh parameters object: %s.\n", gnutls_strerror(ret));
843 return -1;
844 }
845
846 gnutls_dh_params_generate2(new, SERVER_DH_BITS);
847
848 WZD_MUTEX_LOCK(SET_MUTEX_GLOBAL);
849 tmp = dh_params;
850 dh_params = new;
851
852 gnutls_certificate_set_dh_params(x509_cred, dh_params);
853
854 WZD_MUTEX_UNLOCK(SET_MUTEX_GLOBAL);
855
856 gnutls_dh_params_deinit(tmp);
857
858 out_log(LEVEL_INFO,"- Regenerated %d bits Diffie-Hellman key for TLS.\n", SERVER_DH_BITS);
859
860 return 0;
861 }
862
tls_context_init(wzd_context_t * context)863 void tls_context_init(wzd_context_t * context)
864 {
865 }
866
tls_init(void)867 int tls_init(void)
868 {
869 char * tls_certificate;
870 char * tls_certificate_key;
871 char * tls_ca_file=NULL;
872 wzd_string_t * str;
873
874 if (CFG_GET_OPTION(mainConfig,CFG_OPT_DISABLE_TLS)) {
875 out_log(LEVEL_INFO,"TLS Disabled by config\n");
876 return 0;
877 }
878
879 {
880 str = config_get_string(mainConfig->cfg_file, "GLOBAL", "tls_certificate", NULL);
881 if (!str) {
882 out_log(LEVEL_CRITICAL,"TLS: no certificate provided. (use tls_certificate directive in config)\n");
883 return 1;
884 }
885 /** \bug FIXME memory leak here !! */
886 tls_certificate = strdup(str_tochar(str));
887 str_deallocate(str);
888 }
889
890 out_log(LEVEL_INFO,"Initializing TLS (this can take a while).\n");
891
892 /* The order matters.
893 */
894 gnutls_global_init();
895
896 /** \todo TODO XXX move this code to global init ? */
897 gnutls_certificate_allocate_credentials(&x509_cred);
898 if (tls_ca_file) {
899 gnutls_certificate_set_x509_trust_file(x509_cred, tls_ca_file,
900 GNUTLS_X509_FMT_PEM);
901 }
902
903 /*
904 gnutls_certificate_set_x509_crl_file(x509_cred, CRLFILE,
905 GNUTLS_X509_FMT_PEM);
906 */
907 {
908 str = config_get_string(mainConfig->cfg_file, "GLOBAL", "tls_certificate_key", NULL);
909 if (str) {
910 /** \bug FIXME memory leak here !! */
911 tls_certificate_key = strdup(str_tochar(str));
912 str_deallocate(str);
913 } else {
914 /* if no key provided, try using the same certificate */
915 tls_certificate_key = tls_certificate;
916 }
917 }
918
919 gnutls_certificate_set_x509_key_file(x509_cred,
920 tls_certificate /* CERTFILE */,
921 tls_certificate_key /* KEYFILE */,
922 GNUTLS_X509_FMT_PEM);
923
924 generate_dh_params();
925
926 gnutls_certificate_set_dh_params(x509_cred, dh_params);
927
928 out_log(LEVEL_INFO,"TLS initialization successful.\n");
929
930 return 0;
931 }
932
tls_exit(void)933 int tls_exit(void)
934 {
935 if (CFG_GET_OPTION(mainConfig,CFG_OPT_DISABLE_TLS)) {
936 return 0;
937 }
938
939 gnutls_certificate_free_credentials(x509_cred);
940 gnutls_global_deinit();
941
942 return 0;
943 }
944
initialize_tls_session(gnutls_connection_end con_end)945 static gnutls_session initialize_tls_session(gnutls_connection_end con_end)
946 {
947 gnutls_session session;
948
949 gnutls_init(&session, con_end);
950
951 /* Allow connections to servers that have OpenPGP keys as well.
952 */
953 gnutls_priority_set_direct(session, "NORMAL:+CTYPE-OPENPGP", NULL);
954
955 gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred);
956
957 if (con_end == GNUTLS_SERVER) {
958 /* request client certificate if any.
959 */
960 gnutls_certificate_server_set_request(session, GNUTLS_CERT_REQUEST);
961 }
962
963 gnutls_dh_set_prime_bits(session, CLIENT_DH_BITS); /* OpenSSL will not be able to support more */
964
965 return session;
966 }
967
tls_auth(const char * type,wzd_context_t * context)968 int tls_auth (const char *type, wzd_context_t * context)
969 {
970 int ret;
971 gnutls_session session;
972 int fd = context->controlfd;
973 int was_writing=0;
974 fd_set fd_r, fd_w;
975 struct timeval tv;
976 wzd_string_t * str;
977 char * tls_cipher_list;
978
979
980 session = initialize_tls_session(GNUTLS_SERVER);
981
982 gnutls_transport_set_ptr(session, (gnutls_transport_ptr) fd);
983
984 {
985 str = config_get_string(mainConfig->cfg_file, "GLOBAL", "tls_cipher_list", NULL);
986 if (str) {
987 /** \bug FIXME memory leak here !! */
988 tls_cipher_list = strdup(str_tochar(str));
989 str_deallocate(str);
990 } else {
991 tls_cipher_list = "ALL";
992 }
993 }
994
995 /** \todo XXX parse TLS cipher names */
996
997 /* ensure socket is non-blocking */
998 #if defined(_MSC_VER) || (defined(__CYGWIN__) && defined(WINSOCK_SUPPORT))
999 {
1000 unsigned long noBlock=1;
1001 ioctlsocket(fd,FIONBIO,&noBlock);
1002 }
1003 #else
1004 fcntl(fd,F_SETFL,(fcntl(fd,F_GETFL)|O_NONBLOCK));
1005 #endif
1006
1007 /* Perform the TLS handshake
1008 */
1009 do {
1010 ret = gnutls_handshake(session);
1011 if (ret == 0) {
1012 out_log(LEVEL_FLOOD,"control connection succesfully switched to ssl (cipher: %s)\n",gnutls_cipher_get_name(gnutls_cipher_get(session)));
1013 break;
1014 }
1015 if (gnutls_error_is_fatal(ret)) {
1016 out_log(LEVEL_HIGH,"GnuTLS: handshake failed: %s\n",gnutls_strerror(ret));
1017 gnutls_deinit(session);
1018 return 1;
1019 }
1020 switch (ret) {
1021 case GNUTLS_E_AGAIN:
1022 case GNUTLS_E_INTERRUPTED:
1023 was_writing = gnutls_record_get_direction(session);
1024 break;
1025 default:
1026 out_log(LEVEL_HIGH,"GnuTLS: handshake failed, unknown non-fatal error: %s\n",gnutls_strerror(ret));
1027 gnutls_deinit(session);
1028 return 1;
1029 }
1030
1031 /* we need to wait before continuing the handshake */
1032 FD_ZERO(&fd_r);
1033 FD_ZERO(&fd_w);
1034 tv.tv_usec = 0;
1035 tv.tv_sec = 5;
1036 if (was_writing) { FD_SET(fd,&fd_w); }
1037 else { FD_SET(fd,&fd_r); }
1038
1039 ret = select(fd+1, &fd_r, &fd_w, NULL, &tv);
1040
1041 if ( ! (FD_ISSET(fd,&fd_r) || FD_ISSET(fd,&fd_w)) ) { /* timeout */
1042 out_log(LEVEL_HIGH,"GnuTLS: tls_auth failed !\n");
1043 gnutls_deinit(session);
1044 return 1;
1045 }
1046 ret = 1;
1047 } while (ret != 0);
1048
1049 /* set read/write functions */
1050 context->read_fct = (read_fct_t)tls_read;
1051 context->write_fct = (write_fct_t)tls_write;
1052
1053 context->tls.session = malloc(sizeof(gnutls_session));
1054 *( (gnutls_session*)context->tls.session) = session;
1055
1056 return 0;
1057 }
1058
tls_auth_cont(wzd_context_t * context)1059 int tls_auth_cont(wzd_context_t * context)
1060 {
1061 out_log(LEVEL_CRITICAL,"Function not implemented: %s\n",__FUNCTION__);
1062 return 0;
1063 }
1064
tls_init_datamode(int sock,wzd_context_t * context)1065 int tls_init_datamode(int sock, wzd_context_t * context)
1066 {
1067 int ret;
1068 gnutls_session session;
1069 int was_writing=0;
1070 fd_set fd_r, fd_w;
1071 struct timeval tv;
1072
1073 if (context->tls.data_session) {
1074 out_log(LEVEL_NORMAL,"tls_init_datamode: a data session already exist (%p) !\n",
1075 context->tls.data_session);
1076 return 1;
1077 }
1078
1079 session = initialize_tls_session( (context->tls_role == TLS_SERVER_MODE) ? GNUTLS_SERVER : GNUTLS_CLIENT );
1080
1081 gnutls_transport_set_ptr(session, (gnutls_transport_ptr) sock);
1082
1083 /* ensure socket is non-blocking */
1084 #if defined(_MSC_VER) || (defined(__CYGWIN__) && defined(WINSOCK_SUPPORT))
1085 {
1086 unsigned long noBlock=1;
1087 ioctlsocket(fd,FIONBIO,&noBlock);
1088 }
1089 #else
1090 fcntl(sock,F_SETFL,(fcntl(sock,F_GETFL)|O_NONBLOCK));
1091 #endif
1092
1093 /* Perform the TLS handshake
1094 */
1095 do {
1096 ret = gnutls_handshake(session);
1097 if (ret == 0) {
1098 out_log(LEVEL_FLOOD,"Data connection succesfully switched to ssl (cipher: %s)\n",gnutls_cipher_get_name(gnutls_cipher_get(session)));
1099 break;
1100 }
1101 if (gnutls_error_is_fatal(ret)) {
1102 out_log(LEVEL_HIGH,"GnuTLS: handshake failed: %s\n",gnutls_strerror(ret));
1103 gnutls_deinit(session);
1104 return 1;
1105 }
1106 switch (ret) {
1107 case GNUTLS_E_AGAIN:
1108 case GNUTLS_E_INTERRUPTED:
1109 was_writing = gnutls_record_get_direction(session);
1110 break;
1111 default:
1112 out_log(LEVEL_HIGH,"GnuTLS: handshake failed, unknown non-fatal error: %s\n",gnutls_strerror(ret));
1113 gnutls_deinit(session);
1114 return 1;
1115 }
1116
1117 /* we need to wait before continuing the handshake */
1118 FD_ZERO(&fd_r);
1119 FD_ZERO(&fd_w);
1120 tv.tv_usec = 0;
1121 tv.tv_sec = 5;
1122 if (was_writing) { FD_SET(sock,&fd_w); }
1123 else { FD_SET(sock,&fd_r); }
1124
1125 ret = select(sock+1, &fd_r, &fd_w, NULL, &tv);
1126
1127 if ( ! (FD_ISSET(sock,&fd_r) || FD_ISSET(sock,&fd_w)) ) { /* timeout */
1128 out_log(LEVEL_HIGH,"GnuTLS: tls_auth failed !\n");
1129 gnutls_deinit(session);
1130 return 1;
1131 }
1132 ret = 1;
1133 } while (ret != 0);
1134
1135
1136 context->tls.data_session = malloc(sizeof(gnutls_session));
1137 *( (gnutls_session*)context->tls.data_session) = session;
1138
1139 return 0;
1140 }
1141
tls_close_data(wzd_context_t * context)1142 int tls_close_data(wzd_context_t * context)
1143 {
1144 if (CFG_GET_OPTION(mainConfig,CFG_OPT_DISABLE_TLS)) {
1145 return 0;
1146 }
1147
1148 if (context->tls.data_session) {
1149 int ret;
1150 #if 0
1151 int alert;
1152 #endif
1153
1154 ret = gnutls_bye(*(gnutls_session*)context->tls.data_session,GNUTLS_SHUT_RDWR);
1155 gnutls_deinit( *(gnutls_session*)context->tls.data_session );
1156 free ( (gnutls_session*)context->tls.data_session );
1157
1158 /* removed because it causes an infinite loop when the client is SmartFTP */
1159 #if 0
1160 do {
1161 ret = gnutls_bye(*(gnutls_session*)context->tls.data_session,GNUTLS_SHUT_RDWR);
1162 if (ret == 0) break;
1163
1164 if (gnutls_error_is_fatal(ret)) {
1165 out_log(LEVEL_HIGH,"gnutls_bye (data) returned %d (%s)\n",ret,gnutls_strerror(ret));
1166 break;
1167 }
1168 switch(ret) {
1169 case GNUTLS_E_INTERRUPTED:
1170 case GNUTLS_E_AGAIN:
1171
1172 /** \todo poll on fd before calling function again */
1173 usleep(100);
1174
1175 continue;
1176 case GNUTLS_E_WARNING_ALERT_RECEIVED:
1177 case GNUTLS_E_FATAL_ALERT_RECEIVED:
1178 alert = gnutls_alert_get (*(gnutls_session*)context->tls.data_session);
1179 out_log(LEVEL_INFO,"* Received alert [%d]: %s\n", alert,
1180 gnutls_alert_get_name(alert));
1181 return -1;
1182 default:
1183 if (ret < 0) {
1184 out_log(LEVEL_HIGH,"* unhandled error (%d)\n",ret);
1185 return -1;
1186 }
1187 }
1188 } while (ret);
1189
1190 gnutls_deinit( *(gnutls_session*)context->tls.data_session );
1191 free ( (gnutls_session*)context->tls.data_session );
1192 #endif
1193 }
1194 context->tls.data_session = NULL;
1195 return 0;
1196 }
1197
tls_free(wzd_context_t * context)1198 int tls_free(wzd_context_t * context)
1199 {
1200 if (CFG_GET_OPTION(mainConfig,CFG_OPT_DISABLE_TLS)) {
1201 return 0;
1202 }
1203
1204 tls_close_data(context);
1205 if (context->tls.session) {
1206 int ret;
1207 int alert;
1208 int count=0;
1209
1210 do {
1211 ret = gnutls_bye(*(gnutls_session*)context->tls.session,GNUTLS_SHUT_RDWR);
1212 if (ret == 0) break;
1213
1214 if (gnutls_error_is_fatal(ret)) {
1215 out_log(LEVEL_HIGH,"gnutls_bye (control) returned %d (%s)\n",ret,gnutls_strerror(ret));
1216 break;
1217 }
1218 switch(ret) {
1219 case GNUTLS_E_INTERRUPTED:
1220 case GNUTLS_E_AGAIN:
1221 if (++count > 10) {
1222 out_log(LEVEL_INFO,"WARNING I had to forcibly close the TLS connection (too many errors %s : %d)\n",gnutls_strerror(ret),ret);
1223 ret = 0;
1224 break;
1225 }
1226
1227 /** \todo poll on fd before calling function again */
1228 usleep(100);
1229
1230 continue;
1231 case GNUTLS_E_WARNING_ALERT_RECEIVED:
1232 case GNUTLS_E_FATAL_ALERT_RECEIVED:
1233 alert = gnutls_alert_get (*(gnutls_session*)context->tls.session);
1234 out_log(LEVEL_INFO,"* Received alert [%d]: %s\n", alert,
1235 gnutls_alert_get_name(alert));
1236 return -1;
1237 default:
1238 if (ret < 0) {
1239 out_log(LEVEL_HIGH,"* unhandled error (%d)\n",ret);
1240 return -1;
1241 }
1242 }
1243 } while (ret);
1244
1245 gnutls_deinit( *(gnutls_session*)context->tls.session );
1246 free ( (gnutls_session*)context->tls.session );
1247 }
1248 context->tls.session = NULL;
1249 return 0;
1250 }
1251
tls_read(fd_t sock,char * msg,size_t length,int flags,unsigned int timeout,void * vcontext)1252 int tls_read(fd_t sock, char *msg, size_t length, int flags, unsigned int timeout, void * vcontext)
1253 {
1254 wzd_context_t * context = vcontext;
1255 int ret=0, r;
1256 fd_set fd_r;
1257 struct timeval tv;
1258 gnutls_session * session;
1259 int alert;
1260
1261 if (sock == context->controlfd)
1262 session = context->tls.session;
1263 else
1264 session = context->tls.data_session;
1265
1266 do {
1267 ret = gnutls_record_recv(*session, msg, length);
1268 if (ret >= 0) return ret;
1269
1270 if (gnutls_error_is_fatal(ret)) {
1271 out_log(LEVEL_HIGH,"gnutls_record_recv returned %d (%s) on %s connection\n",ret,gnutls_strerror(ret),(sock==context->controlfd)?"control":"data");
1272 return -1;
1273 }
1274 switch(ret) {
1275 case GNUTLS_E_INTERRUPTED:
1276 case GNUTLS_E_AGAIN:
1277 FD_ZERO(&fd_r);
1278 FD_SET(sock,&fd_r);
1279 tv.tv_sec = timeout;
1280 tv.tv_usec = 0;
1281
1282 if (timeout) {
1283 r = select(sock+1,&fd_r,NULL,NULL,&tv);
1284 if (r <= 0) return -1;
1285 }
1286
1287 continue;
1288 case GNUTLS_E_WARNING_ALERT_RECEIVED:
1289 case GNUTLS_E_FATAL_ALERT_RECEIVED:
1290 alert = gnutls_alert_get (*session);
1291 out_log(LEVEL_INFO,"* Received alert [%d]: %s\n", alert,
1292 gnutls_alert_get_name(alert));
1293 return -1;
1294 case GNUTLS_E_REHANDSHAKE:
1295 out_log(LEVEL_HIGH,"* Received re-handshake request (gnutls)\n");
1296 out_log(LEVEL_HIGH,"* Report this to authors !\n");
1297 return -1;
1298 default:
1299 if (ret < 0) {
1300 out_log(LEVEL_HIGH,"* unhandled error (%d)\n",ret);
1301 return -1;
1302 }
1303 }
1304 } while (1);
1305
1306 return ret;
1307 }
1308
tls_write(fd_t sock,const char * msg,size_t length,int flags,unsigned int timeout,void * vcontext)1309 int tls_write(fd_t sock, const char *msg, size_t length, int flags, unsigned int timeout, void * vcontext)
1310 {
1311 wzd_context_t * context = vcontext;
1312 int ret=0, r;
1313 fd_set fd_w;
1314 struct timeval tv;
1315 gnutls_session * session;
1316 int alert;
1317
1318 if (sock == context->controlfd)
1319 session = context->tls.session;
1320 else
1321 session = context->tls.data_session;
1322
1323 do {
1324 ret = gnutls_record_send(*session, msg, length);
1325 if (ret >= 0) return ret;
1326
1327 if (gnutls_error_is_fatal(ret)) {
1328 out_log(LEVEL_HIGH,"gnutls_record_send returned %d (%s)\n",ret,gnutls_strerror(ret));
1329 return -1;
1330 }
1331 switch(ret) {
1332 case GNUTLS_E_AGAIN:
1333 case GNUTLS_E_INTERRUPTED:
1334
1335 FD_ZERO(&fd_w);
1336 FD_SET(sock,&fd_w);
1337 tv.tv_sec = timeout;
1338 tv.tv_usec = 0;
1339
1340 r = select(sock+1,NULL,&fd_w,NULL,&tv);
1341 if (r <= 0) return -1;
1342
1343 continue;
1344 case GNUTLS_E_WARNING_ALERT_RECEIVED:
1345 case GNUTLS_E_FATAL_ALERT_RECEIVED:
1346 alert = gnutls_alert_get (*session);
1347 out_log(LEVEL_INFO,"* Received alert [%d]: %s\n", alert,
1348 gnutls_alert_get_name(alert));
1349 return -1;
1350 case GNUTLS_E_REHANDSHAKE:
1351 out_log(LEVEL_HIGH,"* Received re-handshake request (gnutls)\n");
1352 out_log(LEVEL_HIGH,"* Report this to authors !\n");
1353 return -1;
1354 }
1355 } while (1);
1356
1357 return ret;
1358 }
1359
1360 #endif /* HAVE_GNUTLS */
1361
1362 #if !defined(HAVE_OPENSSL) && !defined(HAVE_GNUTLS)
1363
1364 #include "wzd_structs.h"
1365 #include "wzd_log.h"
1366
tls_context_init(wzd_context_t * context)1367 void tls_context_init(wzd_context_t * context)
1368 {
1369 }
1370
tls_auth(const char * type,wzd_context_t * context)1371 int tls_auth (const char *type, wzd_context_t * context)
1372 {
1373 return -1;
1374 }
1375
tls_init(void)1376 int tls_init(void)
1377 {
1378 return -1;
1379 }
1380
tls_exit(void)1381 int tls_exit(void)
1382 {
1383 return -1;
1384 }
1385
1386 #endif /* !defined(HAVE_OPENSSL) && !defined(HAVE_GNUTLS) */
1387
1388