1 /*
2  * Copyright (c) 2008
3  *      Matt Harris.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      "This product includes software developed by Matt Harris."
16  * 4. Neither the name of the Mr. Harris nor the names of his contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  * 5. Any modifications and/or variations in the end-product which you are
20  *    distributing from the original source code are clearly noted in
21  *    the standard end-user documentation distributed with any package
22  *    containing this software in either source or binary form, as well
23  *    as on any internet sites or media on which this software is included.
24  *
25  * THIS SOFTWARE IS PROVIDED BY Mr. Harris AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL Mr. Harris OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  *
37  */
38 
39 #include <msocket-internal.h>
40 
41 
42 static SSL *_lms_ssl_list[LMS_HIGHSOCK];
43 static SSL_CTX *_lms_ssl_ctx;
44 static SSL_CTX *_lms_ssl_clientctx;
45 static lms_ssl_store *_lms_ssl_masterstore;
46 #ifndef LMS_SSLV2
47 static char _lms_ssl_sciphers[] = "-ALL:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:AES256-SHA:DHE-RSA-CAMELLIA256-SHA:DHE-DSS-CAMELLIA256-SHA:CAMELLIA256-SHA:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:AES128-SHA:DHE-RSA-CAMELLIA128-SHA:DHE-DSS-CAMELLIA128-SHA:CAMELLIA128-SHA";
48 static char _lms_ssl_cciphers[] = "-ALL:DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:AES256-SHA:DHE-RSA-CAMELLIA256-SHA:DHE-DSS-CAMELLIA256-SHA:CAMELLIA256-SHA:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:AES128-SHA:DHE-RSA-CAMELLIA128-SHA:DHE-DSS-CAMELLIA128-SHA:CAMELLIA128-SHA:IDEA-CBC-SHA:RC4-SHA:EDH-RSA-DES-CBC3-SHA:EDH-DSS-DES-CBC3-SHA:DES-CBC3-SHA";
49 static char _lms_ssl_jciphers[] = "ALL:!ADH:@STRENGTH";
50 #else
51 static char _lms_ssl_sciphers[] = "ALL:!ADH:@STRENGTH";
52 static char _lms_ssl_cciphers[] = "ALL:!ADH:@STRENGTH";
53 #endif /* LMS_SSLV2 */
54 
55 static lms_ssl_store *_lms_ssl_loadfiles(X509 *ca, const char *path);
56 static int _lms_ssl_freestore(lms_ssl_store *s);
57 static int _lms_ssl_getbiofd(BIO *b);
58 
59 
60 /*
61  * lms_ssl_init() initializes the SSL functionality of NGCast
62  *
63  */
lms_ssl_init()64 int lms_ssl_init()
65 {
66 	unsigned int i;
67 	unsigned char *buffer;
68 	X509_STORE *serverstore;
69 	X509_STORE *clientstore;
70 
71 	serverstore = 0;
72 	clientstore = 0;
73 
74 	SSL_library_init();
75 	ERR_load_crypto_strings();
76 
77 	buffer = (unsigned char *)malloc(LMS_SSL_SEEDLEN);
78 	if (!buffer)
79 	{
80 		return(-1);
81 	}
82 	while (RAND_status() != 1)
83 	{
84 		memset(buffer, 0, LMS_SSL_SEEDLEN);
85 
86 		if (lms_rand_get(LMS_SSL_SEEDLEN, buffer) < 0)
87 		{
88 			return(-1);
89 		}
90 
91 		RAND_seed(buffer, LMS_SSL_SEEDLEN);
92 	}
93 	free(buffer);
94 
95 	for (i = 0; i < LMS_HIGHSOCK; ++i)
96 	{
97 		_lms_ssl_list[i] = (SSL *)NULL;
98 	}
99 
100 	SSL_load_error_strings();
101 
102 	// _lms_ssl_masterstore = _lms_ssl_loadfiles(Config->ssl_files);
103 
104 	/* Server CTX */
105 	_lms_ssl_ctx = SSL_CTX_new(SSLv23_server_method());
106 	if (!_lms_ssl_ctx)
107 	{
108 		char ssl_error_buf[128];
109 
110 		ERR_error_string_n(ERR_get_error(), ssl_error_buf, 128);
111 		return(-1);
112 	}
113 	if (SSL_CTX_set_cipher_list(_lms_ssl_ctx, _lms_ssl_sciphers) == 0)
114 	{
115 #ifndef LMS_SSLV2
116 		/* If we can't use our best cipher set, try enabling some less awesome ciphers like 3DES and RC4. */
117 		if (SSL_CTX_set_cipher_list(_lms_ssl_ctx, _lms_ssl_cciphers) == 0)
118 		{
119 			/* Try junk ciphers only as a last resort! */
120 			if (SSL_CTX_set_cipher_list(_lms_ssl_ctx, _lms_ssl_jciphers) == 0)
121 			{
122 				return(-1);
123 			}
124 			else
125 			{
126 			}
127 		}
128 #else
129 		return(-1);
130 #endif /* LMS_SSLV2 */
131 	}
132 #ifdef LMS_SSLV2
133 	SSL_CTX_set_options(_lms_ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE|SSL_OP_SINGLE_DH_USE);
134 #else
135 	SSL_CTX_set_options(_lms_ssl_ctx, SSL_OP_NO_SSLv2|SSL_OP_CIPHER_SERVER_PREFERENCE|SSL_OP_SINGLE_DH_USE);
136 #endif /* LMS_SSLV2 */
137 	SSL_CTX_set_verify(_lms_ssl_ctx, SSL_VERIFY_NONE, NULL);
138 	SSL_CTX_set_mode(_lms_ssl_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
139 
140 	// SSL_CTX_set_cert_store(_lms_ssl_ctx, serverstore);
141 	// SSL_CTX_set_ex_data(_lms_ssl_ctx, 0, );
142 
143 	/* Client CTX */
144 	_lms_ssl_clientctx = SSL_CTX_new(SSLv23_client_method());
145 	if (!_lms_ssl_clientctx)
146 	{
147 		char ssl_error_buf[128];
148 
149 		ERR_error_string_n(ERR_get_error(), ssl_error_buf, 128);
150 		SSL_CTX_free(_lms_ssl_ctx);
151 		return(-1);
152 	}
153 	if (SSL_CTX_set_cipher_list(_lms_ssl_clientctx, _lms_ssl_cciphers) == 0)
154 	{
155 #ifndef LMS_SSLV2
156 		/* Try junk ciphers only as a last resort! */
157 		SSL_CTX_set_cipher_list(_lms_ssl_clientctx, _lms_ssl_jciphers);
158 #else
159 		return(-1);
160 #endif /* LMS_SSLV2 */
161 	}
162 #ifdef LMS_SSLV2
163 	SSL_CTX_set_options(_lms_ssl_clientctx, SSL_OP_SINGLE_DH_USE);
164 #else
165 	SSL_CTX_set_options(_lms_ssl_clientctx, SSL_OP_NO_SSLv2|SSL_OP_SINGLE_DH_USE);
166 #endif /* LMS_SSLV2 */
167 	SSL_CTX_set_verify(_lms_ssl_clientctx, SSL_VERIFY_NONE, NULL);
168 	SSL_CTX_set_mode(_lms_ssl_clientctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
169 
170 	// SSL_CTX_set_cert_store(_lms_ssl_ctx, clientstore);
171 	// SSL_CTX_set_ex_data(_lms_ssl_clientctx, 0, );
172 
173 	return(0);
174 }
175 
176 /*
177  * lms_ssl_startsock() initiates SSL on socket m
178  *
179  * m = the socket on which to begin SSL processing
180  *
181  */
lms_ssl_startsock(MSocket * m)182 int lms_ssl_startsock(MSocket *m)
183 {
184 	SSL *s;
185 
186 	if (!m)
187 	{
188 		errno = EINVAL;
189 		return(-1);
190 	}
191 	else if (m->fd < 0)
192 	{
193 		errno = EINVAL;
194 		return(-1);
195 	}
196 	else if ((m->type != LMSTYPE_STREAM4) && (m->type != LMSTYPE_STREAM6) && (m->type != LMSTYPE_LOCALCLIENT))
197 	{
198 		errno = EINVAL;
199 		return(-1);
200 	}
201 	else if (!(m->opts & LMSOPTION_SSL))
202 	{
203 		errno = ENODEV;
204 		return(-1);
205 	}
206 
207 	if (m->flags & LMSFLG_INBOUND)
208 	{
209 		s = SSL_new(_lms_ssl_ctx);
210 	}
211 	else if (m->flags & LMSFLG_OUTBOUND)
212 	{
213 		s = SSL_new(_lms_ssl_clientctx);
214 	}
215 	else
216 	{
217 		return(-1);
218 	}
219 
220 	if (!s)
221 	{
222 		char *ssl_error_buf;
223 
224 		ssl_error_buf = (char *)malloc(128);
225 		if (!ssl_error_buf)
226 		{
227 			return(-1);
228 		}
229 		memset(ssl_error_buf, 0, 128);
230 		ERR_error_string_n(ERR_get_error(), ssl_error_buf, 128);
231 		return(-1);
232 	}
233 
234 	if (!SSL_set_fd(s, m->fd))
235 	{
236 		char *ssl_error_buf;
237 
238 		ssl_error_buf = (char *)malloc(128);
239 		if (!ssl_error_buf)
240 		{
241 			return(-1);
242 		}
243 		memset(ssl_error_buf, 0, 128);
244 		ERR_error_string_n(ERR_get_error(), ssl_error_buf, 128);
245 		SSL_free(s);
246 		return(-1);
247 	}
248 
249 	_lms_ssl_list[m->fd] = s;
250 
251 	m->flags |= LMSFLG_SSL;
252 
253 	if (m->opts & LMSOPTION_UCREP)
254 	{
255 		lms_ssl_unclean(m);
256 	}
257 
258 	m->func_w = lms_ssl_handshake;
259 	m->func_r = lms_ssl_handshake;
260 	m->flags |= LMSFLG_SSLHDSHK;
261 	if (m->flags & LMSFLG_INBOUND)
262 	{
263 		SSL_set_accept_state(s);
264 	}
265 	else if (m->flags & LMSFLG_OUTBOUND)
266 	{
267 		SSL_set_connect_state(s);
268 	}
269 	else
270 	{
271 	}
272 	lms_ssl_handshake(m);
273 
274 	return(0);
275 }
276 
277 /*
278  * lms_ssl_closesock() sends the SSL shutdown string and such
279  *
280  * m = the socket
281  *
282  */
lms_ssl_closesock(MSocket * m)283 int lms_ssl_closesock(MSocket *m)
284 {
285 	int sav;
286 	int sdval;
287 
288 	if (!m)
289 	{
290 		errno = EINVAL;
291 		return(-1);
292 	}
293 	else if (!(m->flags & LMSFLG_SSL))
294 	{
295 		return(0);
296 	}
297 	else if (!(m->flags & LMSFLG_SSLRDY) && !(m->flags & LMSFLG_SSLHDSHK))
298 	{
299 		return(0);
300 	}
301 	else if (!_lms_ssl_list[m->fd])
302 	{
303 		errno = EINVAL;
304 		return(-1);
305 	}
306 	else if (!(m->flags & LMSFLG_CONNECTED))
307 	{
308 		errno = ENOTCONN;
309 		return(-1);
310 	}
311 
312 	sav = SSL_shutdown(_lms_ssl_list[m->fd]);
313 	if (sav <= 0)
314 	{
315 		/* I don't care if this succeeded or failed, however the error queue on OpenSSL's end must be kept clear if it failed. */
316 		SSL_get_error(_lms_ssl_list[m->fd], sav);
317 	}
318 	sdval = SSL_get_shutdown(_lms_ssl_list[m->fd]);
319 	if (!(sdval & SSL_SENT_SHUTDOWN))
320 	{
321 		SSL_set_shutdown(_lms_ssl_list[m->fd], sdval|SSL_SENT_SHUTDOWN);
322 	}
323 
324 	if (m->flags & LMSFLG_SSLRDY)
325 	{
326 		m->flags &= ~LMSFLG_SSLRDY;
327 	}
328 	if (m->flags & LMSFLG_SSLHDSHK)
329 	{
330 		m->flags &= ~LMSFLG_SSLHDSHK;
331 	}
332 
333 	return(0);
334 }
335 
336 /*
337  * lms_ssl_stopsock() ends SSL on a socket, freeing all structures and removing list entries
338  *
339  * m = the socket
340  *
341  */
lms_ssl_stopsock(MSocket * m)342 int lms_ssl_stopsock(MSocket *m)
343 {
344 	if (!m)
345 	{
346 		errno = EINVAL;
347 		return(-1);
348 	}
349 	else if (!(m->flags & LMSFLG_SSL))
350 	{
351 		return(0);
352 	}
353 	else if (!_lms_ssl_list[m->fd])
354 	{
355 		errno = EINVAL;
356 		return(-1);
357 	}
358 
359 	SSL_free(_lms_ssl_list[m->fd]);
360 	_lms_ssl_list[m->fd] = (SSL *)NULL;
361 	if (m->flags & LMSFLG_SSLRDY)
362 	{
363 		m->flags &= ~LMSFLG_SSLRDY;
364 	}
365 	if (m->flags & LMSFLG_SSLHDSHK)
366 	{
367 		m->flags &= ~LMSFLG_SSLHDSHK;
368 	}
369 	m->flags &= ~LMSFLG_SSL;
370 
371 	return(0);
372 }
373 
374 /*
375  * lms_ssl_unclean() sets a socket as `unclean', meaning it will connect to an unknown (non-NGCast) remote application, and OpenSSL's
376  *                         broken-implementation-compatability bug options should be set.
377  *
378  * m = the socket on which to set the unclean flag
379  *
380  */
lms_ssl_unclean(MSocket * m)381 int lms_ssl_unclean(MSocket *m)
382 {
383 	long curopts;
384 
385 	if (!m)
386 	{
387 		errno = EINVAL;
388 		return(-1);
389 	}
390 
391 	m->opts |= LMSOPTION_UCREP;
392 
393 	if (!(m->flags & LMSFLG_SSL))
394 	{
395 		/*
396 		 * This function can be called to set the flag before the socket is initialized,
397 		 * and lms_ssl_startsock() will call this function again to actually set the
398 		 * OpenSSL options on the (SSL *) pointer for the socket once it is initialized
399 		 * if that flag is set.
400 		 */
401 		return(0);
402 	}
403 	else if (!_lms_ssl_list[m->fd])
404 	{
405 		errno = EINVAL;
406 		return(-1);
407 	}
408 
409 	SSL_set_ssl_method(_lms_ssl_list[m->fd], SSLv23_method());
410 	curopts = SSL_get_options(_lms_ssl_list[m->fd]);
411 #ifndef LMS_SSLV2
412 	if (!(curopts & SSL_OP_NO_SSLv2))
413 	{
414 		curopts |= SSL_OP_NO_SSLv2;
415 	}
416 #endif
417 	if ((m->flags & LMSFLG_OUTBOUND) && (curopts & SSL_OP_CIPHER_SERVER_PREFERENCE))
418 	{
419 		curopts &= ~SSL_OP_CIPHER_SERVER_PREFERENCE;
420 	}
421 	/* - SSL_OP_TLS_ROLLBACK_BUG ; Note that we don't set the MSIE/Microsoft related compatability bug-workarounds here. ;) */
422 	SSL_set_options(_lms_ssl_list[m->fd], curopts|SSL_OP_NETSCAPE_CHALLENGE_BUG|SSL_OP_TLS_D5_BUG|SSL_OP_TLS_BLOCK_PADDING_BUG|SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
423 
424 	return(1);
425 }
426 
427 /*
428  * lms_ssl_read() is the SSL connection input processor
429  *
430  * m = the socket on which to receive data
431  *
432  */
lms_ssl_read(MSocket * m)433 int lms_ssl_read(MSocket *m)
434 {
435 	unsigned char *c;
436 	int sav;
437 	int sav_x;
438 	size_t bufsz;
439 	unsigned char callpfunc;
440 
441 	if (!m)
442 	{
443 		errno = EINVAL;
444 		return(-1);
445 	}
446 	else if (!(m->flags & LMSFLG_CONNECTED))
447 	{
448 		errno = ENOTCONN;
449 		return(-1);
450 	}
451 	else if (!(m->flags & LMSFLG_SSL))
452 	{
453 		errno = EINVAL;
454 		return(-1);
455 	}
456 	else if ((m->type != LMSTYPE_STREAM4) && (m->type != LMSTYPE_STREAM6))
457 	{
458 		errno = EINVAL;
459 		return(-1);
460 	}
461 	else if (!_lms_ssl_list[m->fd])
462 	{
463 		errno = EINVAL;
464 		return(-1);
465 	}
466 
467 	callpfunc = 0;
468 	bufsz = 1024;
469 
470 	c = (unsigned char *)malloc(bufsz);
471 	if (!c)
472 	{
473 		return(-1);
474 	}
475 	memset(c, 0, bufsz);
476 
477 	if ((m->recvQ_sz > 0) && m->recvQ)
478 	{
479 		if (m->recvQ_sz < (m->recvQ_len + bufsz))
480 		{
481 #ifdef HAVE_REALLOCF
482 			m->recvQ = (unsigned char *)reallocf(m->recvQ, (m->recvQ_sz + bufsz));
483 #else
484 			m->recvQ = (unsigned char *)realloc(m->recvQ, (m->recvQ_sz + bufsz));
485 #endif /* HAVE_REALLOCF */
486 			if (!m->recvQ)
487 			{
488 				free(c);
489 				return(-1);
490 			}
491 			m->recvQ_sz += bufsz;
492 		}
493 	}
494 	else
495 	{
496 		m->recvQ = (unsigned char *)malloc(bufsz);
497 		if (!m->recvQ)
498 		{
499 			free(c);
500 			return(-1);
501 		}
502 		m->recvQ_sz = bufsz;
503 	}
504 
505 	while (1)
506 	{
507 		sav = SSL_read(_lms_ssl_list[m->fd], c, bufsz);
508 
509 		sav_x = SSL_get_shutdown(_lms_ssl_list[m->fd]);
510 		if (sav_x & SSL_RECEIVED_SHUTDOWN)
511 		{
512 			lms_ssl_closesock(m);
513 			m->func_e(m);
514 			return(0);
515 		}
516 
517 		if (sav <= 0)
518 		{
519 			sav_x = SSL_get_error(_lms_ssl_list[m->fd], sav);
520 			if ((sav_x == SSL_ERROR_WANT_READ) || (sav_x == SSL_ERROR_WANT_WRITE))
521 			{
522 				break;
523 			}
524 			else if (sav_x == SSL_ERROR_ZERO_RETURN)
525 			{
526 				m->func_e(m);
527 				return(0);
528 			}
529 			else
530 			{
531 				if (sav_x == SSL_ERROR_SSL)
532 				{
533 					char *ssl_error_buf;
534 
535 					ssl_error_buf = (char *)malloc(128);
536 					if (!ssl_error_buf)
537 					{
538 						return(-1);
539 					}
540 					memset(ssl_error_buf, 0, 128);
541 					ERR_error_string_n(ERR_get_error(), ssl_error_buf, 128);
542 					free(ssl_error_buf);
543 				}
544 
545 				m->func_e(m);
546 				return(0);
547 			}
548 
549 			break;
550                 }
551 		else
552 		{
553 			lms_str_ocopy(c, m->recvQ, sav, m->recvQ_len);
554 			m->recvQ_len += sav;
555 			memset(c, 0, bufsz);
556 			callpfunc = 1;
557 			m->bytes_r += sav;
558 		}
559 
560 		if (m->recvQ_sz < (m->recvQ_len + bufsz))
561 		{
562 #ifdef HAVE_REALLOCF
563 			m->recvQ = (unsigned char *)reallocf(m->recvQ, (m->recvQ_sz + bufsz));
564 #else
565 			m->recvQ = (unsigned char *)realloc(m->recvQ, (m->recvQ_sz + bufsz));
566 #endif /* HAVE_REALLOCF */
567 			if (!m->recvQ)
568 			{
569 				free(c);
570 				return(-1);
571 			}
572 			m->recvQ_sz += bufsz;
573 		}
574 	}
575 
576 	m->last_recv = time(NULL);
577 	if (callpfunc)
578 	{
579 		m->func_p(m);
580 	}
581 
582 	free(c);
583 	return(0);
584 }
585 
586 /*
587  * lms_ssl_handshake() is an input processor that deals with the handshake phase
588  *
589  * m = the socket on which to receive data
590  *
591  */
lms_ssl_handshake(MSocket * m)592 int lms_ssl_handshake(MSocket *m)
593 {
594 	int sav;
595 	int sav_x;
596 
597 	if (!m)
598 	{
599 		errno = EINVAL;
600 		return(-1);
601 	}
602 	else if (!_lms_ssl_list[m->fd])
603 	{
604 		errno = EINVAL;
605 		return(-1);
606 	}
607 
608 	sav = SSL_do_handshake(_lms_ssl_list[m->fd]);
609 
610 	if (sav <= 0)
611 	{
612 		sav_x = SSL_get_error(_lms_ssl_list[m->fd], sav);
613 		if ((sav_x == SSL_ERROR_WANT_READ) || (sav_x == SSL_ERROR_WANT_WRITE))
614 		{
615 			return(0);
616 		}
617 		else
618 		{
619 			if (sav_x == SSL_ERROR_SSL)
620 			{
621 				char *ssl_error_buf;
622 
623 				ssl_error_buf = (char *)malloc(128);
624 				if (!ssl_error_buf)
625 				{
626 					return(-1);
627 				}
628 				memset(ssl_error_buf, 0, 128);
629 				ERR_error_string_n(ERR_get_error(), ssl_error_buf, 128);
630 				free(ssl_error_buf);
631 			}
632 
633 			lms_socket_destroy(m);
634 			return(0);
635 		}
636 	}
637 	else
638 	{
639 		/* Handshake completed successfully and we can move on */
640 		m->flags &= ~LMSFLG_SSLHDSHK;
641 		m->flags |= LMSFLG_SSLRDY;
642 		m->func_w = lms_ssl_flushq;
643 		m->func_r = lms_ssl_read;
644 		m->last_recv = time(NULL);
645 	}
646 
647 	return(0);
648 }
649 
650 /*
651  * lms_ssl_flushq() flushes the sendQ of an SSL socket
652  *
653  * m = the socket to flush the sendQ of
654  *
655  */
lms_ssl_flushq(MSocket * m)656 int lms_ssl_flushq(MSocket *m)
657 {
658 	ssize_t rv;
659 	ssize_t sl;
660 	unsigned char *tmpptr;
661 	size_t tmplen;
662 	int sav_x;
663 
664 	if (!m)
665 	{
666 		errno = EINVAL;
667 		return(-1);
668 	}
669 	else if (!(m->flags & LMSFLG_SSL))
670 	{
671 		errno = EINVAL;
672 		return(-1);
673 	}
674 	else if (!_lms_ssl_list[m->fd])
675 	{
676 		errno = EINVAL;
677 		return(-1);
678 	}
679 	else if ((m->type != LMSTYPE_STREAM4) && (m->type != LMSTYPE_STREAM6) && (m->type != LMSTYPE_LOCALCLIENT))
680 	{
681 		errno = EINVAL;
682 		return(-1);
683 	}
684 	else if (!(m->flags & LMSFLG_CONNECTED))
685 	{
686 		errno = ENOTCONN;
687 		return(-1);
688 	}
689 
690 	if ((m->sendQ_len == 0) || (m->sendQ_sz == 0))
691 	{
692 		return(0);
693 	}
694 	if (!m->sendQ)
695 	{
696 #ifdef EDOOFUS
697 		errno = EDOOFUS;
698 #else
699 		errno = EINVAL;
700 #endif
701 		return(-1);
702 	}
703 
704 	sl = 0;
705 	tmpptr = m->sendQ;
706 	tmplen = m->sendQ_len;
707 	while (tmplen > 0)
708 	{
709 		rv = SSL_write(_lms_ssl_list[m->fd], tmpptr, tmplen);
710 		if (rv <= 0)
711 		{
712 			sav_x = SSL_get_error(_lms_ssl_list[m->fd], rv);
713 			if ((sav_x == SSL_ERROR_WANT_READ) || (sav_x == SSL_ERROR_WANT_WRITE))
714 			{
715 				if (sl > 0)
716 				{
717 					lms_socket_clearsq(m, sl);
718 					m->sendQ_len -= sl;
719 					m->last_send = time(NULL);
720 				}
721 				return((int)sl);
722 			}
723 			else
724 			{
725 				if (sav_x == SSL_ERROR_SSL)
726 				{
727 					char *ssl_error_buf;
728 
729 					ssl_error_buf = (char *)malloc(128);
730 					if (!ssl_error_buf)
731 					{
732 						return(-1);
733 					}
734 					memset(ssl_error_buf, 0, 128);
735 					ERR_error_string_n(ERR_get_error(), ssl_error_buf, 128);
736 					free(ssl_error_buf);
737 				}
738 
739 				if (sl > 0)
740 				{
741 					lms_socket_clearsq(m, sl);
742 					m->sendQ_len -= sl;
743 					m->last_send = time(NULL);
744 				}
745 				return((int)sl);
746 			}
747 		}
748 		else
749 		{
750 			sl += rv;
751 			tmplen -= rv;
752 			if (tmplen > 0)
753 			{
754 				tmpptr += rv;
755 			}
756 			m->bytes_s += rv;
757 		}
758 	}
759 
760 	m->sendQ_len = 0;
761 	free(m->sendQ);
762 	m->sendQ = (unsigned char *)NULL;
763 	m->sendQ_sz = 0;
764 
765 	m->last_send = time(NULL);
766 
767 	return((int)sl);
768 }
769 
770 /*
771  * lms_ssl_getclientinfo() returns a pointer to a string containing a bunch of info about the client's SSL connectivity
772  *                            + Allocates memory which must be later free()'d by the caller
773  *
774  * m = the socket about which to get SSL statistics and information
775  *
776  */
lms_ssl_getclientinfo(MSocket * m)777 char *lms_ssl_getclientinfo(MSocket *m)
778 {
779 	char *infobuf;
780 	SSL_CIPHER *clientcipher;
781 	int useless_bits;
782 
783 	if (!m)
784 	{
785 		errno = EINVAL;
786 		return((char *)NULL);
787 	}
788 	else if (!(m->flags & LMSFLG_SSL))
789 	{
790 		errno = EINVAL;
791 		return((char *)NULL);
792 	}
793 	else if (!_lms_ssl_list[m->fd])
794 	{
795 		errno = EINVAL;
796 		return((char *)NULL);
797 	}
798 
799 	/* 48 bytes for this is a wee bit arbitrary, but seems like a good choice, the string is unlikely to be truncated, unless someone comes up with a cipher and gives it a really long name..... */
800 	infobuf = (char *)NULL;
801 #ifdef LMS_HARDCORE_ALLOC
802 	while (!infobuf)
803 	{
804 		infobuf = (char *)malloc(48);
805 	}
806 #else
807 	infobuf = (char *)malloc(48);
808 	if (!infobuf)
809 	{
810 		return((char *)NULL);
811 	}
812 #endif
813 	memset(infobuf, 0, 48);
814 
815 	clientcipher = SSL_get_current_cipher(_lms_ssl_list[m->fd]);
816 	snprintf(infobuf, 48, "%s (%s/%i)", SSL_CIPHER_get_version(clientcipher), SSL_CIPHER_get_name(clientcipher), SSL_CIPHER_get_bits(clientcipher, &useless_bits));
817 
818 	return(infobuf);
819 }
820 
821 /*
822  * _lms_ssl_loadfiles() loads a public/private keypair
823  *
824  * ca = the CA root cert
825  * path = the path (will be appended with '.pub' for the public key, '.priv' for the private key, and '.crt' for the X509 certificate)
826  *
827  */
_lms_ssl_loadfiles(X509 * ca,const char * path)828 lms_ssl_store *_lms_ssl_loadfiles(X509 *ca, const char *path)
829 {
830 	char *pubpath;
831 	char *privpath;
832 	lms_ssl_store *ks;
833 
834 	pubpath = (char *)malloc(MAXPATHLEN + 1);
835 	if (!pubpath)
836 	{
837 		return((lms_ssl_store *)NULL);
838 	}
839 	memset(pubpath, 0, (MAXPATHLEN + 1));
840 	snprintf(pubpath, MAXPATHLEN, "%s.pub", path);
841 	privpath = (char *)malloc(MAXPATHLEN + 1);
842 	if (!privpath)
843 	{
844 		free(pubpath);
845 		return((lms_ssl_store *)NULL);
846 	}
847 	memset(privpath, 0, (MAXPATHLEN + 1));
848 	snprintf(privpath, MAXPATHLEN, "%s.priv", path);
849 
850 	ks = (lms_ssl_store *)NULL;
851 #ifdef LMS_HARDCORE_ALLOC
852 	while (!ks)
853 	{
854 		ks = (lms_ssl_store *)malloc(sizeof(lms_ssl_store));
855 	}
856 #else
857 	ks = (lms_ssl_store *)malloc(sizeof(lms_ssl_store));
858 	if (!ks)
859 	{
860 		free(pubpath);
861 		free(privpath);
862 		return((lms_ssl_store *)NULL);
863 	}
864 #endif
865 	memset(ks, 0, sizeof(lms_ssl_store));
866 
867 	/*
868 	 * ca = CA cert
869 	 * crt = my cert
870 	 * privkey = RSA private key
871 	 * pubkey = RSA public key
872 	 * dhp = DH params
873 	 */
874 
875 #if OPENSSL_VERSION_NUMBER >= 0x10100000
876     ks->ca = X509_dup(ca);
877 #else
878 	memcpy(ks->ca, ca, sizeof(X509));
879 #endif
880 	ks->crt = X509_new();
881 	ks->privkey = RSA_new();
882 	ks->pubkey = RSA_new();
883 	ks->dhp = DH_new();
884 
885 	return(ks);
886 }
887 
888 /*
889  * _lms_ssl_freestore() frees a key/cert store
890  *
891  * s = the lms_ssl_store object to free
892  *
893  */
_lms_ssl_freestore(lms_ssl_store * s)894 int _lms_ssl_freestore(lms_ssl_store *s)
895 {
896 	if (!s)
897 	{
898 		errno = EINVAL;
899 		return(-1);
900 	}
901 
902 	if (s->crt)
903 	{
904 		X509_free(s->crt);
905 	}
906 	if (s->ca)
907 	{
908 		X509_free(s->ca);
909 	}
910 
911 	free(s);
912 
913 	return(0);
914 }
915 
916 /*
917  * _lms_ssl_getbiofd() returns the fd of a BIO object
918  *
919  * b = the OpenSSL BIO object to return the fd of
920  *
921  */
_lms_ssl_getbiofd(BIO * b)922 int _lms_ssl_getbiofd(BIO *b)
923 {
924 	int fd;
925 
926 	if (!b)
927 	{
928 		errno = EINVAL;
929 		return(-1);
930 	}
931 
932 	fd = (int)BIO_ctrl(b, BIO_C_GET_FD, (long)0, (void *)NULL);
933 
934 	return(fd);
935 }
936