1 /*-
2 ***********************************************************************
3 *
4 * $Id: ssl.c,v 1.22 2012/01/07 07:56:14 mavrik Exp $
5 *
6 ***********************************************************************
7 *
8 * Copyright 2001-2012 The WebJob Project, All Rights Reserved.
9 *
10 ***********************************************************************
11 */
12 #include "all-includes.h"
13
14 /*-
15 ***********************************************************************
16 *
17 * SslBoot
18 *
19 ***********************************************************************
20 */
21 void
SslBoot(void)22 SslBoot(void)
23 {
24 unsigned char aucSeed[SSL_SEED_LENGTH];
25
26 /*-
27 *********************************************************************
28 *
29 * Initialize SSL library, error strings, and random seed.
30 *
31 *********************************************************************
32 */
33 SSL_library_init();
34 SSL_load_error_strings();
35 RAND_seed(SslGenerateSeed(aucSeed, SSL_SEED_LENGTH), SSL_SEED_LENGTH);
36 }
37
38
39 /*-
40 ***********************************************************************
41 *
42 * SslConnect
43 *
44 ***********************************************************************
45 */
46 SSL *
SslConnect(int iSocket,SSL_CTX * psslCTX,char * pcError)47 SslConnect(int iSocket, SSL_CTX *psslCTX, char *pcError)
48 {
49 const char acRoutine[] = "SslConnect()";
50 char acLocalError[MESSAGE_SIZE] = "";
51 int iError;
52 SSL *pssl;
53
54 pssl = SSL_new(psslCTX);
55 if (pssl == NULL)
56 {
57 ERR_error_string(ERR_get_error(), acLocalError);
58 snprintf(pcError, MESSAGE_SIZE, "%s: SSL_new(): %s", acRoutine, acLocalError);
59 return NULL;
60 }
61
62 iError = SSL_set_fd(pssl, iSocket);
63 if (iError == 0)
64 {
65 ERR_error_string(ERR_get_error(), acLocalError);
66 snprintf(pcError, MESSAGE_SIZE, "%s: SSL_set_fd(): %s", acRoutine, acLocalError);
67 SSL_free(pssl);
68 return NULL;
69 }
70
71 iError = SSL_connect(pssl);
72 if (iError <= 0)
73 {
74 ERR_error_string(ERR_get_error(), acLocalError);
75 snprintf(pcError, MESSAGE_SIZE, "%s: SSL_connect(): %s", acRoutine, acLocalError);
76 SSL_free(pssl);
77 return NULL;
78 }
79
80 return pssl;
81 }
82
83
84 /*-
85 ***********************************************************************
86 *
87 * SslFreeProperties
88 *
89 ***********************************************************************
90 */
91 void
SslFreeProperties(SSL_PROPERTIES * psSslProperties)92 SslFreeProperties(SSL_PROPERTIES *psSslProperties)
93 {
94 if (psSslProperties != NULL)
95 {
96 if (psSslProperties->pcPublicCertFile != NULL)
97 {
98 free(psSslProperties->pcPublicCertFile);
99 }
100 if (psSslProperties->pcPrivateKeyFile != NULL)
101 {
102 free(psSslProperties->pcPrivateKeyFile);
103 }
104 if (psSslProperties->pcPassPhrase != NULL)
105 {
106 free(psSslProperties->pcPassPhrase);
107 }
108 if (psSslProperties->pcBundledCAsFile != NULL)
109 {
110 free(psSslProperties->pcBundledCAsFile);
111 }
112 if (psSslProperties->pcExpectedPeerCN != NULL)
113 {
114 free(psSslProperties->pcExpectedPeerCN);
115 }
116 if (psSslProperties->psslCTX != NULL)
117 {
118 SSL_CTX_free(psSslProperties->psslCTX);
119 }
120 free(psSslProperties);
121 }
122 }
123
124
125 /*-
126 ***********************************************************************
127 *
128 * SslGenerateSeed
129 *
130 ***********************************************************************
131 */
132 unsigned char *
SslGenerateSeed(unsigned char * pucSeed,unsigned long iLength)133 SslGenerateSeed(unsigned char *pucSeed, unsigned long iLength)
134 {
135 unsigned long i;
136 unsigned long j;
137 unsigned long ulLRS32b;
138
139 #ifdef WIN32
140 ulLRS32b = (unsigned long) GetTickCount() ^ (unsigned long) time(NULL);
141 #else
142 ulLRS32b = (((unsigned long) getpid()) << 16) ^ (unsigned long) time(NULL);
143 #endif
144 for (i = 0; i < iLength; i++)
145 {
146 for (j = 0, pucSeed[i] = 0; j < 8; j++)
147 {
148 pucSeed[i] |= (ulLRS32b & 1) << j;
149 ulLRS32b = ((((ulLRS32b >> 7) ^ (ulLRS32b >> 6) ^ (ulLRS32b >> 2) ^ (ulLRS32b >> 0)) & 1) << 31) | (ulLRS32b >> 1);
150 }
151 }
152 return pucSeed;
153 }
154
155
156 /*-
157 ***********************************************************************
158 *
159 * SslGetVersion
160 *
161 ***********************************************************************
162 */
163 char *
SslGetVersion(void)164 SslGetVersion(void)
165 {
166 static char acSslVersion[SSL_MAX_VERSION_LENGTH] = "";
167 static char acSslPatch[2] = "";
168 static char acSslPatchCodes[] = " abcdefghijklmnopqrstuvwxyz";
169 int iPatch = (OPENSSL_VERSION_NUMBER >> 4) & 0xff;
170
171 /*-
172 *********************************************************************
173 *
174 * The OpenSSL version number allocates 8 bits to the major number,
175 * 8 bits to the minor number, 8 bits to the fix number, 8 bits to
176 * the patch number, and 4 bits to the status number. This has the
177 * following breakout.
178 *
179 * +--------+--------+--------+--------+----+
180 * |33333322|22222222|11111111|11 | |
181 * |54321098|76543210|98765432|10987654|3210|
182 * |--------|--------|--------|--------|----+
183 * |MMMMMMMM|mmmmmmmm|ffffffff|pppppppp|ssss|
184 * +--------+--------+--------|--------+----+
185 * ^^^^^^^^ ^^^^^^^^ ^^^^^^^^ ^^^^^^^^ ^^^^
186 * | | | | |
187 * | | | | +-----> s - status (0.....15)
188 * | | | +----------> p - patch (0....255)
189 * | | +--------------------> f - fix (0....255)
190 * | +----------------------------> m - minor (0....255)
191 * +-------------------------------------> M - major (0....255)
192 *
193 * Note that this represents a 36-bit number, which may require
194 * 64-bit handling at some point. See OPENSSL_VERSION_NUMBER(3)
195 * for details,
196 *
197 *********************************************************************
198 */
199 if (iPatch == 0)
200 {
201 acSslPatch[0] = 0;
202 }
203 else if (iPatch > 0 && iPatch < 27)
204 {
205 acSslPatch[0] = acSslPatchCodes[iPatch];
206 }
207 else
208 {
209 acSslPatch[0] = '?';
210 }
211 acSslPatch[1] = 0;
212
213 snprintf(acSslVersion, SSL_MAX_VERSION_LENGTH, "ssl(%d.%d.%d%s)",
214 (int)((OPENSSL_VERSION_NUMBER >> 28) & 0xff),
215 (int)((OPENSSL_VERSION_NUMBER >> 20) & 0xff),
216 (int)((OPENSSL_VERSION_NUMBER >> 12) & 0xff),
217 acSslPatch
218 );
219
220 return acSslVersion;
221 }
222
223
224 /*-
225 ***********************************************************************
226 *
227 * SslInitializeCTX
228 *
229 ***********************************************************************
230 */
231 SSL_CTX *
SslInitializeCTX(SSL_PROPERTIES * psProperties,char * pcError)232 SslInitializeCTX(SSL_PROPERTIES *psProperties, char *pcError)
233 {
234 const char acRoutine[] = "SslInitializeCTX()";
235 char acLocalError[MESSAGE_SIZE] = "";
236
237 /*-
238 *********************************************************************
239 *
240 * Initialize SSL context.
241 *
242 *********************************************************************
243 */
244 psProperties->psslCTX = SSL_CTX_new(SSLv23_client_method());
245 SSL_CTX_set_options(psProperties->psslCTX, SSL_OP_NO_SSL2 );
246 if (psProperties->psslCTX == NULL)
247 {
248 ERR_error_string(ERR_get_error(), acLocalError);
249 snprintf(pcError, MESSAGE_SIZE, "%s: SSL_CTX_new(): %s", acRoutine, acLocalError);
250 return NULL;
251 }
252
253 /*-
254 *********************************************************************
255 *
256 * Setup SSL certificate verification. Load the bundled certificate
257 * authorities file. A common name (CN) and a positive chain length
258 * must be specified to activate PEER verification. If you want to
259 * override the default handler, write a routine and reference it in
260 * the 3rd argument to SSL_CTX_set_verify().
261 *
262 *********************************************************************
263 */
264 if (psProperties->iVerifyPeerCert)
265 {
266 if(psProperties->pcExpectedPeerCN == NULL)
267 {
268 snprintf(pcError, MESSAGE_SIZE, "%s: Undefined Expected Peer Common Name.", acRoutine);
269 SSL_CTX_free(psProperties->psslCTX);
270 return NULL;
271 }
272 if(psProperties->pcBundledCAsFile == NULL)
273 {
274 snprintf(pcError, MESSAGE_SIZE, "%s: Undefined Bundled Certificate Authorities File.", acRoutine);
275 SSL_CTX_free(psProperties->psslCTX);
276 return NULL;
277 }
278 if(psProperties->iMaxChainLength < 1)
279 {
280 snprintf(pcError, MESSAGE_SIZE, "%s: MaxChainLength must be greater than one.", acRoutine);
281 SSL_CTX_free(psProperties->psslCTX);
282 return NULL;
283 }
284
285 SSL_CTX_set_verify_depth(psProperties->psslCTX, psProperties->iMaxChainLength);
286
287 SSL_CTX_set_verify(psProperties->psslCTX, SSL_VERIFY_PEER, NULL);
288
289 if (!SSL_CTX_load_verify_locations(psProperties->psslCTX, psProperties->pcBundledCAsFile, NULL))
290 {
291 ERR_error_string(ERR_get_error(), acLocalError);
292 snprintf(pcError, MESSAGE_SIZE, "%s: SSL_CTX_load_verify_locations(): %s", acRoutine, acLocalError);
293 SSL_CTX_free(psProperties->psslCTX);
294 return NULL;
295 }
296 }
297 else
298 {
299 SSL_CTX_set_verify(psProperties->psslCTX, SSL_VERIFY_NONE, NULL);
300 }
301
302 /*-
303 *********************************************************************
304 *
305 * Set up a password handler, if needed.
306 *
307 *********************************************************************
308 */
309 if (SSL_POOL_SEED && SSL_POOL_TAPS > 1)
310 {
311 static unsigned char aucPool[SSL_POOL_SIZE];
312 static unsigned char aucTaps[SSL_POOL_TAPS];
313 SSL_NEW_POOL(aucPool, SSL_POOL_SIZE, SSL_POOL_SEED);
314 SSL_TAP_POOL(aucTaps, aucPool);
315 SSL_CTX_set_default_passwd_cb(psProperties->psslCTX, SslPassPhraseHandler);
316 SSL_CTX_set_default_passwd_cb_userdata(psProperties->psslCTX, (void *) aucTaps);
317 }
318
319 if (psProperties->pcPassPhrase != NULL && psProperties->pcPassPhrase[0])
320 {
321 SSL_CTX_set_default_passwd_cb(psProperties->psslCTX, SslPassPhraseHandler);
322 SSL_CTX_set_default_passwd_cb_userdata(psProperties->psslCTX, (void *) psProperties->pcPassPhrase);
323 }
324
325 /*-
326 *********************************************************************
327 *
328 * Load key file and certificate file, if needed.
329 *
330 *********************************************************************
331 */
332 if (psProperties->iUseCertificate)
333 {
334 if (psProperties->pcPublicCertFile == NULL)
335 {
336 snprintf(pcError, MESSAGE_SIZE, "%s: Undefined Public Certificate File.", acRoutine);
337 SSL_CTX_free(psProperties->psslCTX);
338 return NULL;
339 }
340 if (psProperties->pcPrivateKeyFile == NULL)
341 {
342 snprintf(pcError, MESSAGE_SIZE, "%s: Undefined Private Key File.", acRoutine);
343 SSL_CTX_free(psProperties->psslCTX);
344 return NULL;
345 }
346
347 if (!SSL_CTX_use_certificate_file(psProperties->psslCTX, psProperties->pcPublicCertFile, SSL_FILETYPE_PEM))
348 {
349 ERR_error_string(ERR_get_error(), acLocalError);
350 snprintf(pcError, MESSAGE_SIZE, "%s: SSL_CTX_use_certificate_file(): %s", acRoutine, acLocalError);
351 SSL_CTX_free(psProperties->psslCTX);
352 return NULL;
353 }
354 if (!SSL_CTX_use_PrivateKey_file(psProperties->psslCTX, psProperties->pcPrivateKeyFile, SSL_FILETYPE_PEM))
355 {
356 ERR_error_string(ERR_get_error(), acLocalError);
357 snprintf(pcError, MESSAGE_SIZE, "%s: SSL_CTX_use_PrivateKey_file(): %s", acRoutine, acLocalError);
358 SSL_CTX_free(psProperties->psslCTX);
359 return NULL;
360 }
361 }
362
363 return psProperties->psslCTX;
364 }
365
366
367 /*-
368 ***********************************************************************
369 *
370 * SslNewProperties
371 *
372 ***********************************************************************
373 */
374 SSL_PROPERTIES *
SslNewProperties(char * pcError)375 SslNewProperties(char *pcError)
376 {
377 const char acRoutine[] = "SslNewProperties()";
378 char acLocalError[MESSAGE_SIZE] = "";
379 int iError;
380 SSL_PROPERTIES *psSslProperties;
381
382 psSslProperties = (SSL_PROPERTIES *) malloc(sizeof(SSL_PROPERTIES));
383 if (psSslProperties == NULL)
384 {
385 snprintf(pcError, MESSAGE_SIZE, "%s: malloc(): %s", acRoutine, strerror(errno));
386 return NULL;
387 }
388 memset(psSslProperties, 0, sizeof(SSL_PROPERTIES));
389
390 iError = SslSetPublicCertFile(psSslProperties, "", acLocalError);
391 if (iError == -1)
392 {
393 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
394 SslFreeProperties(psSslProperties);
395 return NULL;
396 }
397 iError = SslSetPrivateKeyFile(psSslProperties, "", acLocalError);
398 if (iError == -1)
399 {
400 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
401 SslFreeProperties(psSslProperties);
402 return NULL;
403 }
404 iError = SslSetPassPhrase(psSslProperties, "", acLocalError);
405 if (iError == -1)
406 {
407 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
408 SslFreeProperties(psSslProperties);
409 return NULL;
410 }
411 iError = SslSetBundledCAsFile(psSslProperties, "", acLocalError);
412 if (iError == -1)
413 {
414 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
415 SslFreeProperties(psSslProperties);
416 return NULL;
417 }
418 iError = SslSetExpectedPeerCN(psSslProperties, "", acLocalError);
419 if (iError == -1)
420 {
421 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
422 SslFreeProperties(psSslProperties);
423 return NULL;
424 }
425
426 psSslProperties->iMaxChainLength = SSL_DEFAULT_CHAIN_LENGTH;
427
428 return psSslProperties;
429 }
430
431
432 /*-
433 ***********************************************************************
434 *
435 * SslPassPhraseHandler
436 *
437 ***********************************************************************
438 */
439 int
SslPassPhraseHandler(char * pcPassPhrase,int iSize,int iRWFlag,void * pUserData)440 SslPassPhraseHandler(char *pcPassPhrase, int iSize, int iRWFlag, void *pUserData)
441 {
442 int iLength;
443
444 iLength = strlen((char *) pUserData);
445 if (iLength < iSize)
446 {
447 strncpy(pcPassPhrase, (char *) pUserData, iLength + 1);
448 return iLength;
449 }
450 else
451 {
452 pcPassPhrase[0] = 0;
453 return 0;
454 }
455 }
456
457
458 /*-
459 ***********************************************************************
460 *
461 * SslRead
462 *
463 ***********************************************************************
464 */
465 int
SslRead(SSL * ssl,char * pcData,int iLength,char * pcError)466 SslRead(SSL *ssl, char *pcData, int iLength, char *pcError)
467 {
468 const char acRoutine[] = "SslRead()";
469 char acLocalError[MESSAGE_SIZE] = "";
470 int iDone;
471 int iNRead;
472 int iRRetries;
473
474 iDone = iRRetries = 0;
475
476 iNRead = SSL_read(ssl, pcData, iLength);
477
478 while (iDone == 0)
479 {
480 iDone = 1;
481 switch (SSL_get_error(ssl, iNRead))
482 {
483 case SSL_ERROR_NONE:
484 return iNRead;
485 break;
486
487 case SSL_ERROR_SSL:
488 ERR_error_string(ERR_get_error(), acLocalError);
489 snprintf(pcError, MESSAGE_SIZE, "%s: SSL_read(): SSL_ERROR_SSL: %s", acRoutine, acLocalError);
490 return -1;
491 break;
492
493 case SSL_ERROR_WANT_READ:
494 if (++iRRetries < SSL_RETRY_LIMIT)
495 {
496 snprintf(pcError, MESSAGE_SIZE, "%s: SSL_read(): SSL_ERROR_WANT_READ", acRoutine);
497 iNRead = SSL_read(ssl, pcData, iLength);
498 iDone = 0;
499 }
500 else
501 {
502 snprintf(pcError, MESSAGE_SIZE, "%s: SSL_read(): SSL_ERROR_WANT_READ: Retry limit reached!", acRoutine);
503 return -1;
504 }
505 break;
506
507 case SSL_ERROR_WANT_WRITE:
508 snprintf(pcError, MESSAGE_SIZE, "%s: SSL_read(): SSL_ERROR_WANT_WRITE", acRoutine);
509 return -1;
510 break;
511
512 case SSL_ERROR_WANT_X509_LOOKUP:
513 snprintf(pcError, MESSAGE_SIZE, "%s: SSL_read(): SSL_ERROR_WANT_X509_LOOKUP", acRoutine);
514 return -1;
515 break;
516
517 case SSL_ERROR_SYSCALL:
518 if (ERR_peek_error())
519 {
520 ERR_error_string(ERR_get_error(), acLocalError);
521 }
522 if (iNRead == -1)
523 {
524 snprintf(pcError, MESSAGE_SIZE, "%s: SSL_read(): SSL_ERROR_SYSCALL: Underlying I/O error: %s", acRoutine, strerror(errno));
525 return -1;
526 }
527 else
528 {
529 snprintf(pcError, MESSAGE_SIZE, "%s: SSL_read(): SSL_ERROR_SYSCALL: Unexpected EOF.", acRoutine);
530 return -1;
531 }
532 break;
533
534 case SSL_ERROR_ZERO_RETURN:
535 snprintf(pcError, MESSAGE_SIZE, "%s: SSL_read(): SSL_ERROR_ZERO_RETURN: The SSL connection has been closed.", acRoutine);
536 return 0;
537 break;
538
539 default:
540 snprintf(pcError, MESSAGE_SIZE, "%s: SSL_read(): Undefined error.", acRoutine);
541 return -1;
542 break;
543 }
544 }
545 return -1;
546 }
547
548
549 /*-
550 ***********************************************************************
551 *
552 * SslSessionCleanup
553 *
554 ***********************************************************************
555 */
556 void
SslSessionCleanup(SSL * ssl)557 SslSessionCleanup(SSL *ssl)
558 {
559 if (ssl != NULL)
560 {
561 SSL_shutdown(ssl);
562 SSL_free(ssl);
563 }
564 }
565
566
567 /*-
568 ***********************************************************************
569 *
570 * SslSetBundledCAsFile
571 *
572 ***********************************************************************
573 */
574 int
SslSetBundledCAsFile(SSL_PROPERTIES * psProperties,char * pcBundledCAsFile,char * pcError)575 SslSetBundledCAsFile(SSL_PROPERTIES *psProperties, char *pcBundledCAsFile, char *pcError)
576 {
577 const char acRoutine[] = "SslSetBundledCAsFile()";
578 char acLocalError[MESSAGE_SIZE] = "";
579 int iError;
580
581 if (psProperties == NULL)
582 {
583 snprintf(pcError, MESSAGE_SIZE, "%s: Undefined SslProperties.", acRoutine);
584 return -1;
585 }
586
587 iError = SslSetDynamicString(&psProperties->pcBundledCAsFile, pcBundledCAsFile, acLocalError);
588 if (iError == -1)
589 {
590 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
591 return -1;
592 }
593
594 return 0;
595 }
596
597
598 /*-
599 ***********************************************************************
600 *
601 * SslSetDynamicString
602 *
603 ***********************************************************************
604 */
605 int
SslSetDynamicString(char ** ppcValue,char * pcNewValue,char * pcError)606 SslSetDynamicString(char **ppcValue, char *pcNewValue, char *pcError)
607 {
608 const char acRoutine[] = "SslSetDynamicString()";
609 char *pcTempValue;
610 int iLength;
611
612 /*-
613 *********************************************************************
614 *
615 * The caller is expected to free this memory.
616 *
617 *********************************************************************
618 */
619 iLength = strlen(pcNewValue);
620 pcTempValue = realloc(*ppcValue, iLength + 1);
621 {
622 if (pcTempValue == NULL)
623 {
624 snprintf(pcError, MESSAGE_SIZE, "%s: realloc(): %s", acRoutine, strerror(errno));
625 return -1;
626 }
627 *ppcValue = pcTempValue;
628 }
629 strncpy(*ppcValue, pcNewValue, iLength + 1);
630
631 return 0;
632 }
633
634
635 /*-
636 ***********************************************************************
637 *
638 * SslSetExpectedPeerCN
639 *
640 ***********************************************************************
641 */
642 int
SslSetExpectedPeerCN(SSL_PROPERTIES * psProperties,char * pcExpectedPeerCN,char * pcError)643 SslSetExpectedPeerCN(SSL_PROPERTIES *psProperties, char *pcExpectedPeerCN, char *pcError)
644 {
645 const char acRoutine[] = "SslSetExpectedPeerCN()";
646 char acLocalError[MESSAGE_SIZE] = "";
647 int iError;
648
649 if (psProperties == NULL)
650 {
651 snprintf(pcError, MESSAGE_SIZE, "%s: Undefined SslProperties.", acRoutine);
652 return -1;
653 }
654
655 iError = SslSetDynamicString(&psProperties->pcExpectedPeerCN, pcExpectedPeerCN, acLocalError);
656 if (iError == -1)
657 {
658 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
659 return -1;
660 }
661
662 return 0;
663 }
664
665
666 /*-
667 ***********************************************************************
668 *
669 * SslSetPassPhrase
670 *
671 ***********************************************************************
672 */
673 int
SslSetPassPhrase(SSL_PROPERTIES * psProperties,char * pcPassPhrase,char * pcError)674 SslSetPassPhrase(SSL_PROPERTIES *psProperties, char *pcPassPhrase, char *pcError)
675 {
676 const char acRoutine[] = "SslSetPassPhrase()";
677 char acLocalError[MESSAGE_SIZE] = "";
678 int iError;
679
680 if (psProperties == NULL)
681 {
682 snprintf(pcError, MESSAGE_SIZE, "%s: Undefined SslProperties.", acRoutine);
683 return -1;
684 }
685
686 iError = SslSetDynamicString(&psProperties->pcPassPhrase, pcPassPhrase, acLocalError);
687 if (iError == -1)
688 {
689 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
690 return -1;
691 }
692
693 return 0;
694 }
695
696
697 /*-
698 ***********************************************************************
699 *
700 * SslSetPrivateKeyFile
701 *
702 ***********************************************************************
703 */
704 int
SslSetPrivateKeyFile(SSL_PROPERTIES * psProperties,char * pcPrivateKeyFile,char * pcError)705 SslSetPrivateKeyFile(SSL_PROPERTIES *psProperties, char *pcPrivateKeyFile, char *pcError)
706 {
707 const char acRoutine[] = "SslSetPrivateKeyFile()";
708 char acLocalError[MESSAGE_SIZE] = "";
709 int iError;
710
711 if (psProperties == NULL)
712 {
713 snprintf(pcError, MESSAGE_SIZE, "%s: Undefined SslProperties.", acRoutine);
714 return -1;
715 }
716
717 iError = SslSetDynamicString(&psProperties->pcPrivateKeyFile, pcPrivateKeyFile, acLocalError);
718 if (iError == -1)
719 {
720 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
721 return -1;
722 }
723
724 return 0;
725 }
726
727
728 /*-
729 ***********************************************************************
730 *
731 * SslSetPublicCertFile
732 *
733 ***********************************************************************
734 */
735 int
SslSetPublicCertFile(SSL_PROPERTIES * psProperties,char * pcPublicCertFile,char * pcError)736 SslSetPublicCertFile(SSL_PROPERTIES *psProperties, char *pcPublicCertFile, char *pcError)
737 {
738 const char acRoutine[] = "SslSetPublicCertFile()";
739 char acLocalError[MESSAGE_SIZE] = "";
740 int iError;
741
742 if (psProperties == NULL)
743 {
744 snprintf(pcError, MESSAGE_SIZE, "%s: Undefined SslProperties.", acRoutine);
745 return -1;
746 }
747
748 iError = SslSetDynamicString(&psProperties->pcPublicCertFile, pcPublicCertFile, acLocalError);
749 if (iError == -1)
750 {
751 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
752 return -1;
753 }
754
755 return 0;
756 }
757
758
759 /*-
760 ***********************************************************************
761 *
762 * SslVerifyCN
763 *
764 ***********************************************************************
765 */
766 int
SslVerifyCN(SSL * ssl,char * pcCN,char * pcError)767 SslVerifyCN(SSL *ssl, char *pcCN, char *pcError)
768 {
769 const char acRoutine[] = "SslVerifyCN()";
770 char acPeerCN[SSL_MAX_COMMON_NAME_LENGTH];
771 X509 *psX509Cert;
772
773 if (SSL_get_verify_result(ssl) != X509_V_OK)
774 {
775 snprintf(pcError, MESSAGE_SIZE, "%s: SSL_get_verify_result(): Invalid Certificate.", acRoutine);
776 return -1;
777 }
778
779 psX509Cert = SSL_get_peer_certificate(ssl);
780 if (psX509Cert == NULL)
781 {
782 snprintf(pcError, MESSAGE_SIZE, "%s: SSL_get_peer_certificate(): Missing Certificate.", acRoutine);
783 return -1;
784 }
785
786 X509_NAME_get_text_by_NID(X509_get_subject_name(psX509Cert), NID_commonName, acPeerCN, SSL_MAX_COMMON_NAME_LENGTH);
787
788 X509_free(psX509Cert);
789
790 if (strcmp(acPeerCN, pcCN) != 0)
791 {
792 snprintf(pcError, MESSAGE_SIZE, "%s: CN = [%s] != [%s]: Common Name Mismatch.", acRoutine, acPeerCN, pcCN);
793 return -1;
794 }
795
796 return 0;
797 }
798
799
800 /*-
801 ***********************************************************************
802 *
803 * SslWrite
804 *
805 ***********************************************************************
806 */
807 int
SslWrite(SSL * ssl,char * pcData,int iLength,char * pcError)808 SslWrite(SSL *ssl, char *pcData, int iLength, char *pcError)
809 {
810 const char acRoutine[] = "SslWrite()";
811 char acLocalError[MESSAGE_SIZE] = "";
812 int iNSent;
813 int iOffset;
814 int iToSend;
815 int iWRetries;
816
817 iToSend = iLength;
818
819 iOffset = iWRetries = 0;
820
821 do
822 {
823 iNSent = SSL_write(ssl, &pcData[iOffset], iToSend);
824
825 switch (SSL_get_error(ssl, iNSent))
826 {
827 case SSL_ERROR_NONE:
828 iToSend -= iNSent;
829 iOffset += iNSent;
830 break;
831
832 case SSL_ERROR_SSL:
833 snprintf(pcError, MESSAGE_SIZE, "%s: SSL_write(): SSL_ERROR_SSL", acRoutine);
834 return -1;
835 break;
836
837 case SSL_ERROR_WANT_READ:
838 snprintf(pcError, MESSAGE_SIZE, "%s: SSL_write(): SSL_ERROR_WANT_READ", acRoutine);
839 return -1;
840 break;
841
842 case SSL_ERROR_WANT_WRITE:
843 /*-
844 *****************************************************************
845 *
846 * Resend the same buffer (openssl knows what to do). Give up if
847 * we reach SSL_RETRY_LIMIT.
848 *
849 *****************************************************************
850 */
851 if (++iWRetries >= SSL_RETRY_LIMIT)
852 {
853 snprintf(pcError, MESSAGE_SIZE, "%s: SSL_write(): SSL_ERROR_WANT_WRITE: Retry limit reached!", acRoutine);
854 return -1;
855 }
856 break;
857
858 case SSL_ERROR_WANT_X509_LOOKUP:
859 snprintf(pcError, MESSAGE_SIZE, "%s: SSL_write(): SSL_ERROR_WANT_X509_LOOKUP", acRoutine);
860 return -1;
861 break;
862
863 case SSL_ERROR_SYSCALL:
864 if (ERR_peek_error())
865 {
866 ERR_error_string(ERR_get_error(), acLocalError);
867 }
868 if (iNSent == -1)
869 {
870 snprintf(pcError, MESSAGE_SIZE, "%s: SSL_write(): SSL_ERROR_SYSCALL: Underlying I/O error: %s", acRoutine, strerror(errno));
871 }
872 else
873 {
874 snprintf(pcError, MESSAGE_SIZE, "%s: SSL_write(): SSL_ERROR_SYSCALL: Unexpected EOF.", acRoutine);
875 }
876 return -1;
877 break;
878
879 case SSL_ERROR_ZERO_RETURN:
880 snprintf(pcError, MESSAGE_SIZE, "%s: SSL_write(): SSL_ERROR_ZERO_RETURN: The SSL connection has been closed.", acRoutine);
881 return -1;
882 break;
883
884 default:
885 snprintf(pcError, MESSAGE_SIZE, "%s: SSL_write(): Undefined error.", acRoutine);
886 return -1;
887 break;
888 }
889 } while (iToSend > 0);
890
891 return iOffset;
892 }
893