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