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