1
2 /*-
3 *
4 * New BSD License 2006
5 *
6 * Copyright (c) 2006, Jorgen Lundman
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are
11 * met:
12 *
13 * 1 Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2 Redistributions in binary form must reproduce the above
16 * copyright notice, this list of conditions and the following
17 * disclaimer in the documentation and/or other materials provided
18 * with the distribution.
19 * 3 Neither the name of the stuff nor the names of its contributors
20 * may be used to endorse or promote products derived from this
21 * software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 *
35 */
36
37 // $Id: tls.c,v 1.28 2006/06/30 01:22:58 lundman Exp $
38 // SSL/TLS Support Functions
39 // Jorgen Lundman October 17th, 2002.
40
41 #ifdef WITH_SSL
42
43 #include <stdio.h>
44
45 // If you don't have these, have you installed openssl?
46 #ifdef WIN32
47 #define WINDOWS_LEAN_AND_MEAN
48 #include <winsock2.h> // SSL below includes windows, that includes old winsock, so we do it first
49 #endif
50
51 #include <openssl/ssl.h>
52 #include <openssl/rand.h>
53 #include <openssl/err.h>
54
55 #include <string.h>
56
57 #include "connections.h"
58
59 #include "lion.h"
60 #include "tls.h"
61 #include "sockets.h"
62
63
64 //#define DEBUG
65
66 __RCSID("$LiON: lundman/lion/tls.c,v 1.28 2006/06/30 01:22:58 lundman Exp $");
67
68
69
70
71 static char cfg_tlsciphers[] =
72 "RC4-SHA:RC4-MD5:DHE-DSS-RC4-SHA:DES-CBC3-SHA:DES-CBC3-MD5:EDH-RSA-DES-CBC3-SHA:EDH-DSS-DES-CBC3-SHA";
73
74
75 // Master TLS context
76 static SSL_CTX *tls_ctx = NULL;
77
78 // internal variables to remember which has been initialised
79 int net_client_SSL = 1;
80 int net_server_SSL = 1;
81
82 char *ssl_tlsciphers = NULL;
83 char *ssl_tlsrsafile = NULL;
84 char *ssl_egdsocket = NULL;
85
86
tls_init(void)87 int tls_init( void )
88 {
89 int egdbytes, status;
90
91
92 // Do we even want SSL on?
93 if (!net_client_SSL &&
94 !net_server_SSL)
95 return 0;
96
97 if (!ssl_tlsciphers)
98 ssl_tlsciphers = strdup( cfg_tlsciphers );
99 if (!ssl_egdsocket)
100 ssl_egdsocket = strdup( "/var/run/egd-pool" );
101 if (!ssl_tlsrsafile)
102 ssl_tlsrsafile = strdup( "lion.pem" );
103
104 #ifdef DEBUG
105 printf("Using cipher list: %s\n", ssl_tlsciphers);
106 #endif
107
108 SSL_load_error_strings(); /* readable error messages */
109 SSL_library_init(); /* initialize library */
110
111 tls_ctx = SSL_CTX_new(SSLv23_method());
112
113
114 // Did we get SSL?
115
116 if (!tls_ctx) {
117
118 net_server_SSL = 0;
119 net_client_SSL = 0;
120
121 printf("SSL_CTX_new() %s\r\n",
122 (char *)ERR_error_string(ERR_get_error(), NULL));
123
124 tls_free();
125
126 return -1;
127 }
128
129 // Do we have sufficient random?
130
131 if (RAND_status() != 1) {
132
133 if ( (egdbytes = RAND_egd(ssl_egdsocket)) == -1 ) {
134
135 net_server_SSL = 0;
136 net_client_SSL = 0;
137
138 printf("ssl_init: RAND_egd failed\r\n");
139
140 tls_free();
141
142 return -2;
143 }
144
145 if (RAND_status() != 1) {
146
147 net_server_SSL = 0;
148 net_client_SSL = 0;
149
150 printf("ssl_init: System without entropy source, see TLS.ReadMeFirst\r\n");
151
152 tls_free();
153
154 return -3;
155 }
156 }
157
158
159 // Set some options
160 SSL_CTX_set_options(tls_ctx, SSL_OP_NO_SSLv2);
161 //SSL_CTX_set_options(tls_ctx, SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1);
162 //SSL_CTX_set_options(tls_ctx, SSL_OP_NO_TLSv1);
163 SSL_CTX_set_default_verify_paths(tls_ctx);
164
165
166
167 SSL_CTX_set_session_cache_mode(tls_ctx, SSL_SESS_CACHE_CLIENT);
168 SSL_CTX_set_session_id_context(tls_ctx, (const unsigned char *) "1", 1);
169
170 // That's sufficient for being a client (server communications)
171 // but we also need to load up certificates etc to attempt to
172 // allow clients to SSL with us.
173
174
175 if (net_server_SSL) { // SSL is enabled for clients
176
177
178 status = SSL_CTX_use_certificate_file(tls_ctx, ssl_tlsrsafile,
179 X509_FILETYPE_PEM);
180
181 if (status <= 0) {
182 printf("SSL_CTX_use_certificate_file(%s) %s : %s\n", "",
183 (char *)ERR_error_string(ERR_get_error(), NULL),
184 ssl_tlsrsafile);
185
186 printf("Server SSL AUTH disabled (no certificate).\n");
187
188 net_server_SSL = 0;
189
190
191 } else {
192
193 status = SSL_CTX_use_PrivateKey_file(tls_ctx,ssl_tlsrsafile,
194 X509_FILETYPE_PEM);
195
196 if (status <= 0) {
197 printf("SSL_CTX_use_PrivateKey_file(%s) %s\n", "",
198 (char *)ERR_error_string(ERR_get_error(), NULL));
199 printf("Server SSL AUTH disabled.\n");
200 net_server_SSL = 0;
201 }
202
203 }
204
205 }
206
207
208
209 return 0;
210
211 }
212
213
tls_free(void)214 void tls_free(void)
215 {
216
217 if (tls_ctx) {
218
219 #ifdef DEBUG
220 printf("SSL Released.\n");
221 #endif
222
223 SSL_CTX_free(tls_ctx);
224 tls_ctx = NULL;
225
226 }
227
228 net_server_SSL = 0;
229 net_client_SSL = 0;
230
231 }
232
233
tls_close(connection_t * node)234 void tls_close( connection_t *node )
235 {
236
237 if (node->trace)
238 fprintf(trace_file, "%p: tls_close\n", node);
239
240 if (node->ctx) {
241 #ifdef DEBUG
242 printf("Releasing SSL socket\n");
243 #endif
244
245 SSL_free( node->ctx );
246 node->ctx = NULL;
247 }
248
249 node->use_ssl = 0;
250
251
252 }
253
254
tls_auth(connection_t * node)255 int tls_auth( connection_t *node )
256 {
257
258 #ifdef DEBUG
259 printf("tls_auth(%p): %p\n", node, node->ctx);
260 #endif
261
262 if (node->trace)
263 fprintf(trace_file, "%p: tls_auth\n", node);
264
265 node->ctx = SSL_new(tls_ctx);
266
267 if (!node->ctx) {
268
269 printf("SSL: Failed to create new context -- disabling\n");
270 node->use_ssl = 0;
271
272 return -1;
273
274 }
275
276
277 if (RAND_status() != 1) {
278 printf("ssl_init: System without /dev/urandom, PRNG seeding must be done manually\n");
279 node->use_ssl = 0;
280
281 return -2;
282 }
283
284
285 SSL_set_cipher_list(node->ctx, ssl_tlsciphers);
286
287 #ifdef DEBUG
288 printf("Setting fd %d\n", node->socket);
289 #endif
290
291 if (SSL_set_fd(node->ctx, node->socket ) != 1)
292 printf("SSL_set_fd_error");
293
294
295 // Experimental
296 node->status = ST_SSL_NEG;
297 node->auth_type = LION_SSL_SERVER;
298
299
300 #ifdef DEBUG
301 printf("Status %d\n", node->status);
302 #endif
303
304 tls_cont_auth(node);
305
306 return 1;
307 }
308
309
310
tls_cont_auth(connection_t * node)311 void tls_cont_auth( connection_t *node )
312 {
313 int status, sslerr;
314 char cipher_info[128];
315 SSL_CIPHER *cipher;
316
317
318 if (node->trace)
319 fprintf(trace_file, "%p: tls_cont_auth\n", node);
320
321 #ifdef DEBUG
322 printf("tls_cont_auth: ... %p \n", node);
323 #endif
324 //net_want_select( node->handle, NET_WANT_NONE);
325 node->want_mode = NET_WANT_NONE;
326
327 status = SSL_accept(node->ctx);
328 sslerr = SSL_get_error(node->ctx,status);
329
330
331 // printf("Status %d\n", status);
332
333
334 if (status == 1) {
335
336 cipher = SSL_get_current_cipher(node->ctx);
337 SSL_CIPHER_description(cipher, cipher_info, sizeof(cipher_info));
338
339 #ifdef DEBUG
340 printf("tls_auth_cont: connection %p switched to encryption! Protocol version: %s\n",node, SSL_get_version(node->ctx));
341
342 printf("tls_auth_cont: cipher %s\n", cipher_info);
343 #endif
344
345
346 //printf("[tls] setting misc crap\n");
347 //SSL_set_mode(node->ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
348 //SSL_set_mode(node->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
349 SSL_set_mode(node->ctx,
350 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER|SSL_MODE_ENABLE_PARTIAL_WRITE);
351
352
353 node->use_ssl = 1;
354 node->status = ST_CONNECTED;
355
356 node->auth_type = LION_SSL_OFF;
357
358 // POST EVENT!
359 _lion_userinput( node,
360 node->user_data,
361 LION_CONNECTION_SECURE_ENABLED,
362 0, cipher_info);
363
364 // If we are in delay, we also need to issue connected now.
365 // that is, if we are still connected
366 if (node->want_ssl == LION_SSL_SERVER) {
367
368 node->want_ssl = LION_SSL_OFF;
369
370 if (node->status != ST_DISCONNECT)
371 _lion_userinput( node,
372 node->user_data,
373 LION_CONNECTION_CONNECTED,
374 0, NULL);
375
376 }
377
378 return;
379
380 } else {
381
382 //node->ssl_fd_mode = TLS_NONE;
383
384 switch (sslerr) {
385 case SSL_ERROR_WANT_READ:
386 node->want_mode = NET_WANT_READ;
387 #ifdef DEBUG
388 printf("tls_auth_cont: Setting wantread - %d\n", node->status);
389 #endif
390 //node->ssl_fd_mode = TLS_READ;
391 break;
392 case SSL_ERROR_WANT_WRITE:
393 #ifdef DEBUG
394 printf("tls_auth_cont: Setting wantwrite - %d\n", node->status);
395 #endif
396 node->want_mode = NET_WANT_WRITE;
397 //printf("Setting wantwrite\n");
398 //node->ssl_fd_mode = TLS_WRITE;
399 break;
400 default:
401 #ifdef DEBUG
402 printf("tls_auth_cont: failed (%d, %d, %d)\n",
403 sslerr, status, errno);
404 #endif
405
406 if (node->trace)
407 fprintf(trace_file, "%p: tls_auth_cont: failed (%d, %d, %d) => %s\n",
408 node,
409 sslerr, status, errno,
410 (char *)ERR_error_string(ERR_get_error(), NULL));
411
412 node->use_ssl = 0;
413 node->auth_type = LION_SSL_OFF;
414 node->want_ssl = LION_SSL_OFF;
415 node->status = ST_CONNECTED;
416
417 // POST EVENT!
418 _lion_userinput( node,
419 node->user_data,
420 LION_CONNECTION_SECURE_FAILED,
421 0, NULL); // fixme, SSL_get_error
422
423
424 }
425 }
426 }
427
428
429
430
431
432
433
434
435
tls_read(connection_t * node,void * buf,int num)436 int tls_read(connection_t *node, void *buf, int num)
437 {
438 SSL *ssl;
439 int status, sslerr;
440
441
442 ssl = node->ctx;
443
444 status = SSL_read(ssl, (char *)buf, num);
445 sslerr = SSL_get_error(ssl, status);
446
447 #ifdef DEBUG_VERBOSE
448 printf("tls_read: %d\n", status);
449 #endif
450 #ifdef DEBUG
451 if (node->trace)
452 fprintf(trace_file, "%p: lion_read(%d)\n", node,status);
453 #endif
454
455 if (status == -1) {
456
457 //ud->ssl_ctrl_func = TLS_READ;
458
459 switch (sslerr) {
460
461 // In READ mode, we get this "error" when we normally want more
462 // to read, ie, EWOULDBLOCK. So it isn't really something we set
463 // for read. We DO set it for write?
464 case SSL_ERROR_WANT_READ:
465 //node->want_mode = NET_WANT_READ;
466 #ifdef DEBUG
467 //printf("tls_read: Setting wantread - %d\n", node->status);
468 #endif
469 // printf("tls_read: WANT_READ - do we deal with this?\n");
470 //ud->ssl_ctrl_fd_mode = TLS_READ;
471 return -2;
472 break;
473
474 // Here, it is actually the same as "BUFFERFULL" status.
475 case SSL_ERROR_WANT_WRITE:
476 #ifdef DEBUG
477 printf("tls_read: Setting wantwrite - %d\n", node->status);
478 #endif
479 //printf("tls_read: WANT_WRITE - do we deal with this?\n");
480 node->want_mode = NET_WANT_WRITE;
481 //ud->ssl_ctrl_fd_mode = TLS_WRITE;
482 return -2;
483 break;
484 default:
485 #ifdef DEBUG
486 printf("tls_read_error: %p %d,%d,%d\n", node, sslerr,
487 status, errno);
488 #endif
489 return -1;
490 }
491
492 } else {
493
494 node->want_mode = NET_WANT_NONE;
495 //ud->ssl_ctrl_fd_mode = TLS_NONE;
496
497 }
498
499 return status;
500 }
501
502
tls_write(connection_t * node,void * buf,int num)503 int tls_write(connection_t *node, void *buf, int num)
504 {
505 SSL *ssl;
506 int status, sslerr;
507
508 ssl = node->ctx;
509
510 if (!node->ctx) {
511 printf("[tls_write] ->ctx is NULL!?!\n");
512 return -1;
513 }
514
515 #if 0
516 int poo;
517
518 poo = fcntl(SSL_get_fd(ssl), F_GETFL);
519 if (!(poo & O_NONBLOCK))
520 printf("Warning, %d %d (%d)is blocking.\n",
521 SSL_get_fd(ssl), poo, poo & O_NONBLOCK);
522 #endif
523
524
525
526
527 status = SSL_write(ssl, (char *)buf, num);
528 sslerr = SSL_get_error(ssl, status);
529
530 #if 0
531 {
532 time_t t;
533 time(&t);
534 if (t - lion_global_time >= 2) {
535 printf("SSL_write: operation took long time!\n");
536 poo = fcntl(SSL_get_fd(ssl), F_GETFL);
537 printf("Is nonblock: fd %d %d (%d)\n",
538 SSL_get_fd(ssl), poo, poo & O_NONBLOCK);
539 sockets_setnonblocking(SSL_get_fd(ssl));
540 }
541 }
542 #endif
543
544
545
546 #ifdef DEBUG_VERBOSE
547 printf("tls_write: %d - %s\n", status, (char *)buf);
548 #endif
549 #ifdef DEBUG
550 if (node->trace)
551 fprintf(trace_file, "%p: lion_write(%d)\n", node,status);
552 #endif
553
554
555 if (status == -1) {
556
557 //ud->ssl_ctrl_func = TLS_READ;
558
559 switch (sslerr) {
560
561 case SSL_ERROR_WANT_READ:
562 node->want_mode = NET_WANT_READ;
563 // printf("tls_write: WANT_READ - do we deal with this?\n");
564 //ud->ssl_ctrl_fd_mode = TLS_READ;
565 return -2;
566 break;
567 case SSL_ERROR_WANT_WRITE:
568 //printf("tls_write: WANT_WRITE - do we deal with this?\n");
569 //node->want_mode = NET_WANT_WRITE;
570 //ud->ssl_ctrl_fd_mode = TLS_WRITE;
571 return -2;
572 break;
573 default:
574 #ifdef DEBUG
575 printf("tls_write_error: %p %d,%d,%d\n", node, sslerr,
576 status, errno);
577 #endif
578 // This is often EAGAIN error, so return it as a real error
579 // then we check against EAGAIN.
580 return -1;
581 }
582
583 } else {
584
585 node->want_mode = NET_WANT_NONE;
586 //ud->ssl_ctrl_fd_mode = TLS_NONE;
587
588 }
589
590 return status;
591 }
592
593
594
595
596
597
598
599
600
601
602
603
tls_clauth(connection_t * node)604 int tls_clauth( connection_t *node )
605 {
606
607 #ifdef DEBUG
608 printf("tls_clauth(%p): %p\n", node, node->ctx);
609 #endif
610
611 if (node->trace)
612 fprintf(trace_file, "%p: lion_clauth\n", node);
613
614 node->ctx = SSL_new(tls_ctx);
615
616 if (!node->ctx) {
617
618 printf("SSL: Failed to create new context -- disabling\n");
619 node->use_ssl = 0;
620
621 return -1;
622
623 }
624
625
626 if (RAND_status() != 1) {
627 printf("ssl_init: System without /dev/urandom, PRNG seeding must be done manually\n");
628 node->use_ssl = 0;
629
630 return -2;
631 }
632
633
634 SSL_set_cipher_list(node->ctx, ssl_tlsciphers);
635
636 #ifdef DEBUG
637 printf("Setting fd %d\n", node->socket);
638 #endif
639
640 if (SSL_set_fd(node->ctx, node->socket ) != 1)
641 printf("SSL_set_fd_error");
642
643
644 // Experimental
645 node->status = ST_SSL_NEG;
646 node->auth_type = LION_SSL_CLIENT;
647
648
649 #ifdef DEBUG
650 printf("Status %d\n", node->status);
651 #endif
652
653 tls_cont_clauth(node);
654
655 return 1;
656 }
657
658
659
tls_cont_clauth(connection_t * node)660 void tls_cont_clauth( connection_t *node )
661 {
662 int status, sslerr;
663 char cipher_info[128];
664 SSL_CIPHER *cipher;
665
666 if (node->trace)
667 fprintf(trace_file, "%p: tls_cont_clauth\n", node);
668
669 #ifdef DEBUG
670 printf("tls_cont_clauth: ... \n");
671 #endif
672 //net_want_select( node->handle, NET_WANT_NONE);
673 node->want_mode = NET_WANT_NONE;
674
675 status = SSL_connect(node->ctx);
676 sslerr = SSL_get_error(node->ctx,status);
677
678
679 // printf("Status %d\n", status);
680
681
682 if (status == 1) {
683
684 cipher = SSL_get_current_cipher(node->ctx);
685 SSL_CIPHER_description(cipher, cipher_info, sizeof(cipher_info));
686
687 #ifdef DEBUG
688 printf("tls_clauth_cont: connection %p switched to encryption! Protocol version: %s\n",node, SSL_get_version(node->ctx));
689
690 printf("tls_clauth_cont: cipher %s\n", cipher_info);
691 #endif
692
693 node->use_ssl = 1;
694
695 node->status = ST_CONNECTED;
696
697 node->auth_type = LION_SSL_OFF;
698
699 //SSL_set_mode(node->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
700 SSL_set_mode(node->ctx,
701 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER|SSL_MODE_ENABLE_PARTIAL_WRITE);
702
703 // POST EVENT!
704 _lion_userinput( node,
705 node->user_data,
706 LION_CONNECTION_SECURE_ENABLED,
707 0, cipher_info);
708
709 // If we are in delay, we also need to issue connected now.
710 if (node->want_ssl == LION_SSL_CLIENT) {
711
712 node->want_ssl = LION_SSL_OFF;
713
714 _lion_userinput( node,
715 node->user_data,
716 LION_CONNECTION_CONNECTED,
717 0, NULL);
718 }
719
720 return;
721
722 } else {
723
724 //node->ssl_fd_mode = TLS_NONE;
725
726 switch (sslerr) {
727 case SSL_ERROR_WANT_READ:
728 node->want_mode = NET_WANT_READ;
729 #ifdef DEBUG
730 printf("Setting wantread - %d\n", node->status);
731 #endif
732 //node->ssl_fd_mode = TLS_READ;
733 break;
734 case SSL_ERROR_WANT_WRITE:
735 node->want_mode = NET_WANT_WRITE;
736 //printf("Setting wantwrite\n");
737 //node->ssl_fd_mode = TLS_WRITE;
738 break;
739 default:
740 #ifdef DEBUG
741 printf("tls_clauth_cont: failed (status,sslerr,errno) %d %d %d\n", status, sslerr, errno);
742 #endif
743 if (node->trace)
744 fprintf(trace_file, "%p: tls_clauth_cont: failed (%d, %d, %d) => %s\n",
745 node,
746 sslerr, status, errno,
747 (char *)ERR_error_string(ERR_get_error(), NULL));
748
749 node->use_ssl = 0;
750 node->want_ssl = LION_SSL_OFF;
751 node->auth_type = LION_SSL_OFF;
752
753 // POST EVENT!
754 _lion_userinput( node,
755 node->user_data,
756 LION_CONNECTION_SECURE_FAILED,
757 0, NULL); // fixme
758
759 // if client haven't disconnected, we send connected_event
760 if (node->status != ST_DISCONNECT) {
761
762 // If we are in delay, we also need to issue connected now.
763 if (node->want_ssl == LION_SSL_CLIENT) {
764
765 node->status = ST_CONNECTED;
766
767 _lion_userinput( node,
768 node->user_data,
769 LION_CONNECTION_CONNECTED,
770 0, NULL);
771
772 }
773 }
774 }
775 }
776 }
777
778
779
780
781 //
782 // return 0 - is SSL auth started - SSL_NEG status is set.
783 // return 1 - plain text input.
784 //
tls_peek(connection_t * node)785 int tls_peek(connection_t *node)
786 {
787 char buffer;
788 int ret;
789
790 // peek() ahead, check if its SSL handshake.
791 // if it is, start authentication, if not, return.
792
793 ret = sockets_peek(node->socket, &buffer, 1);
794
795 #ifdef DEBUG
796 printf("SSL Autosensing %d:%x\n", ret, buffer);
797 #endif
798
799 if (ret == 1) {
800
801 // check for SSL handshake, currently, only v2 and v3 is known.
802 if ((buffer == SSL3_RT_HANDSHAKE) ||
803 (buffer & 0x80)) {
804
805 #ifdef DEBUG
806 printf("Autosensed SSL handshake\n");
807 #endif
808
809 return tls_auth(node);
810
811 }
812
813 }
814
815 // It is plain-text, we need to send sec_failed and connected events.
816
817 node->use_ssl = 0;
818 node->want_ssl = LION_SSL_OFF;
819 node->auth_type = LION_SSL_OFF;
820
821
822 _lion_userinput( node,
823 node->user_data,
824 LION_CONNECTION_SECURE_FAILED,
825 0, NULL); // fixme
826
827
828 if (node->socket != ST_DISCONNECT) {
829
830 node->status = ST_CONNECTED;
831
832 _lion_userinput( node,
833 node->user_data,
834 LION_CONNECTION_CONNECTED,
835 0, NULL);
836 }
837
838
839 return 1;
840
841 }
842
843
844
845
846
847
848
849 #endif // WITH_SSL
850