]> git.sur5r.net Git - openldap/blob - libraries/libldap/tls_m.c
ITS#7276 MozNSS: allow CA certdb together with PEM CA bundle file
[openldap] / libraries / libldap / tls_m.c
1 /* tls_m.c - Handle tls/ssl using Mozilla NSS. */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 2008-2012 The OpenLDAP Foundation.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted only as authorized by the OpenLDAP
10  * Public License.
11  *
12  * A copy of this license is available in the file LICENSE in the
13  * top-level directory of the distribution or, alternatively, at
14  * <http://www.OpenLDAP.org/license.html>.
15  */
16 /* ACKNOWLEDGEMENTS: Initial version written by Howard Chu. 
17  * Additional support by Rich Megginson.
18  */
19
20 #include "portable.h"
21
22 #ifdef HAVE_MOZNSS
23
24 #include "ldap_config.h"
25
26 #include <stdio.h>
27
28 #if defined( HAVE_FCNTL_H )
29 #include <fcntl.h>
30 #endif
31
32 #include <ac/stdlib.h>
33 #include <ac/errno.h>
34 #include <ac/socket.h>
35 #include <ac/string.h>
36 #include <ac/ctype.h>
37 #include <ac/time.h>
38 #include <ac/unistd.h>
39 #include <ac/param.h>
40 #include <ac/dirent.h>
41
42 #include "ldap-int.h"
43 #include "ldap-tls.h"
44
45 #define READ_PASSWORD_FROM_STDIN
46 #define READ_PASSWORD_FROM_FILE
47
48 #ifdef READ_PASSWORD_FROM_STDIN
49 #include <termios.h> /* for echo on/off */
50 #endif
51
52 #include <nspr/nspr.h>
53 #include <nspr/private/pprio.h>
54 #include <nss/nss.h>
55 #include <nss/ssl.h>
56 #include <nss/sslerr.h>
57 #include <nss/sslproto.h>
58 #include <nss/pk11pub.h>
59 #include <nss/secerr.h>
60 #include <nss/keyhi.h>
61 #include <nss/secmod.h>
62 #include <nss/cert.h>
63
64 #undef NSS_VERSION_INT
65 #define NSS_VERSION_INT ((NSS_VMAJOR << 24) | (NSS_VMINOR << 16) | \
66         (NSS_VPATCH << 8) | NSS_VBUILD)
67
68 /* NSS 3.12.5 and later have NSS_InitContext */
69 #if NSS_VERSION_INT >= 0x030c0500
70 #define HAVE_NSS_INITCONTEXT 1
71 #endif
72
73 /* NSS 3.12.9 and later have SECMOD_RestartModules */
74 #if NSS_VERSION_INT >= 0x030c0900
75 #define HAVE_SECMOD_RESTARTMODULES 1
76 #endif
77
78 /* InitContext does not currently work in server mode */
79 /* #define INITCONTEXT_HACK 1 */
80
81 typedef struct tlsm_ctx {
82         PRFileDesc *tc_model;
83         int tc_refcnt;
84         PRBool tc_verify_cert;
85         CERTCertDBHandle *tc_certdb;
86         char *tc_certname;
87         char *tc_pin_file;
88         struct ldaptls *tc_config;
89         int tc_is_server;
90         int tc_require_cert;
91         PRCallOnceType tc_callonce;
92         PRBool tc_using_pem;
93         char *tc_slotname; /* if using pem */
94 #ifdef HAVE_NSS_INITCONTEXT
95         NSSInitContext *tc_initctx; /* the NSS context */
96 #endif
97         PK11GenericObject **tc_pem_objs; /* array of objects to free */
98         int tc_n_pem_objs; /* number of objects */
99         PRBool tc_warn_only; /* only warn of errors in validation */
100 #ifdef LDAP_R_COMPILE
101         ldap_pvt_thread_mutex_t tc_refmutex;
102 #endif
103 } tlsm_ctx;
104
105 typedef PRFileDesc tlsm_session;
106
107 static PRDescIdentity   tlsm_layer_id;
108
109 static const PRIOMethods tlsm_PR_methods;
110
111 #define PEM_LIBRARY     "nsspem"
112 #define PEM_MODULE      "PEM"
113 /* hash files for use with cacertdir have this file name suffix */
114 #define PEM_CA_HASH_FILE_SUFFIX ".0"
115 #define PEM_CA_HASH_FILE_SUFFIX_LEN 2
116
117 static SECMODModule *pem_module;
118
119 #define DEFAULT_TOKEN_NAME "default"
120 /* sprintf format used to create token name */
121 #define TLSM_PEM_TOKEN_FMT "PEM Token #%ld"
122
123 static int tlsm_slot_count;
124
125 #define PK11_SETATTRS(x,id,v,l) (x)->type = (id); \
126                 (x)->pValue=(v); (x)->ulValueLen = (l);
127
128 /* forward declaration */
129 static int tlsm_init( void );
130
131 #ifdef LDAP_R_COMPILE
132
133 /* it doesn't seem guaranteed that a client will call
134    tlsm_thr_init in a non-threaded context - so we have
135    to wrap the mutex creation in a prcallonce
136 */
137 static ldap_pvt_thread_mutex_t tlsm_init_mutex;
138 static ldap_pvt_thread_mutex_t tlsm_pem_mutex;
139 static PRCallOnceType tlsm_init_mutex_callonce = {0,0};
140
141 static PRStatus PR_CALLBACK
142 tlsm_thr_init_callonce( void )
143 {
144         if ( ldap_pvt_thread_mutex_init( &tlsm_init_mutex ) ) {
145                 Debug( LDAP_DEBUG_ANY,
146                            "TLS: could not create mutex for moznss initialization: %d\n", errno, 0, 0 );
147                 return PR_FAILURE;
148         }
149
150         if ( ldap_pvt_thread_mutex_init( &tlsm_pem_mutex ) ) {
151                 Debug( LDAP_DEBUG_ANY,
152                            "TLS: could not create mutex for PEM module: %d\n", errno, 0, 0 );
153                 return PR_FAILURE;
154         }
155
156         return PR_SUCCESS;
157 }
158
159 static void
160 tlsm_thr_init( void )
161 {
162     ( void )PR_CallOnce( &tlsm_init_mutex_callonce, tlsm_thr_init_callonce );
163 }
164
165 #endif /* LDAP_R_COMPILE */
166
167 static const char *
168 tlsm_dump_cipher_info(PRFileDesc *fd)
169 {
170         PRUint16 ii;
171
172         for (ii = 0; ii < SSL_NumImplementedCiphers; ++ii) {
173                 PRInt32 cipher = (PRInt32)SSL_ImplementedCiphers[ii];
174                 PRBool enabled = PR_FALSE;
175                 PRInt32 policy = 0;
176                 SSLCipherSuiteInfo info;
177
178                 if (fd) {
179                         SSL_CipherPrefGet(fd, cipher, &enabled);
180                 } else {
181                         SSL_CipherPrefGetDefault(cipher, &enabled);
182                 }
183                 SSL_CipherPolicyGet(cipher, &policy);
184                 SSL_GetCipherSuiteInfo(cipher, &info, (PRUintn)sizeof(info));
185                 Debug( LDAP_DEBUG_TRACE,
186                            "TLS: cipher: %d - %s, enabled: %d, ",
187                            info.cipherSuite, info.cipherSuiteName, enabled );
188                 Debug( LDAP_DEBUG_TRACE,
189                            "policy: %d\n", policy, 0, 0 );
190         }
191
192         return "";
193 }
194
195 /* Cipher definitions */
196 typedef struct {
197         char *ossl_name;    /* The OpenSSL cipher name */
198         int num;            /* The cipher id */
199         int attr;           /* cipher attributes: algorithms, etc */
200         int version;        /* protocol version valid for this cipher */
201         int bits;           /* bits of strength */
202         int alg_bits;       /* bits of the algorithm */
203         int strength;       /* LOW, MEDIUM, HIGH */
204         int enabled;        /* Enabled by default? */
205 } cipher_properties;
206
207 /* cipher attributes  */
208 #define SSL_kRSA  0x00000001L
209 #define SSL_aRSA  0x00000002L
210 #define SSL_aDSS  0x00000004L
211 #define SSL_DSS   SSL_aDSS
212 #define SSL_eNULL 0x00000008L
213 #define SSL_DES   0x00000010L
214 #define SSL_3DES  0x00000020L
215 #define SSL_RC4   0x00000040L
216 #define SSL_RC2   0x00000080L
217 #define SSL_AES   0x00000100L
218 #define SSL_MD5   0x00000200L
219 #define SSL_SHA1  0x00000400L
220 #define SSL_SHA   SSL_SHA1
221 #define SSL_RSA   (SSL_kRSA|SSL_aRSA)
222
223 /* cipher strength */
224 #define SSL_NULL      0x00000001L
225 #define SSL_EXPORT40  0x00000002L
226 #define SSL_EXPORT56  0x00000004L
227 #define SSL_LOW       0x00000008L
228 #define SSL_MEDIUM    0x00000010L
229 #define SSL_HIGH      0x00000020L
230
231 #define SSL2  0x00000001L
232 #define SSL3  0x00000002L
233 /* OpenSSL treats SSL3 and TLSv1 the same */
234 #define TLS1  SSL3
235
236 /* Cipher translation */
237 static cipher_properties ciphers_def[] = {
238         /* SSL 2 ciphers */
239         {"DES-CBC3-MD5", SSL_EN_DES_192_EDE3_CBC_WITH_MD5, SSL_kRSA|SSL_aRSA|SSL_3DES|SSL_MD5, SSL2, 168, 168, SSL_HIGH, SSL_ALLOWED},
240         {"RC2-CBC-MD5", SSL_EN_RC2_128_CBC_WITH_MD5, SSL_kRSA|SSL_aRSA|SSL_RC2|SSL_MD5, SSL2, 128, 128, SSL_MEDIUM, SSL_ALLOWED},
241         {"RC4-MD5", SSL_EN_RC4_128_WITH_MD5, SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_MD5, SSL2, 128, 128, SSL_MEDIUM, SSL_ALLOWED},
242         {"DES-CBC-MD5", SSL_EN_DES_64_CBC_WITH_MD5, SSL_kRSA|SSL_aRSA|SSL_DES|SSL_MD5, SSL2, 56, 56, SSL_LOW, SSL_ALLOWED},
243         {"EXP-RC2-CBC-MD5", SSL_EN_RC2_128_CBC_EXPORT40_WITH_MD5, SSL_kRSA|SSL_aRSA|SSL_RC2|SSL_MD5, SSL2, 40, 128, SSL_EXPORT40, SSL_ALLOWED},
244         {"EXP-RC4-MD5", SSL_EN_RC4_128_EXPORT40_WITH_MD5, SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_MD5, SSL2, 40, 128, SSL_EXPORT40, SSL_ALLOWED},
245
246         /* SSL3 ciphers */
247         {"RC4-MD5", SSL_RSA_WITH_RC4_128_MD5, SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_MD5, SSL3, 128, 128, SSL_MEDIUM, SSL_ALLOWED},
248         {"RC4-SHA", SSL_RSA_WITH_RC4_128_SHA, SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_SHA1, SSL3, 128, 128, SSL_MEDIUM, SSL_ALLOWED},
249         {"DES-CBC3-SHA", SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_kRSA|SSL_aRSA|SSL_3DES|SSL_SHA1, SSL3, 168, 168, SSL_HIGH, SSL_ALLOWED},
250         {"DES-CBC-SHA", SSL_RSA_WITH_DES_CBC_SHA, SSL_kRSA|SSL_aRSA|SSL_DES|SSL_SHA1, SSL3, 56, 56, SSL_LOW, SSL_ALLOWED},
251         {"EXP-RC4-MD5", SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_MD5, SSL3, 40, 128, SSL_EXPORT40, SSL_ALLOWED},
252         {"EXP-RC2-CBC-MD5", SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5, SSL_kRSA|SSL_aRSA|SSL_RC2|SSL_MD5, SSL3, 0, 0, SSL_EXPORT40, SSL_ALLOWED},
253         {"NULL-MD5", SSL_RSA_WITH_NULL_MD5, SSL_kRSA|SSL_aRSA|SSL_eNULL|SSL_MD5, SSL3, 0, 0, SSL_NULL, SSL_NOT_ALLOWED},
254         {"NULL-SHA", SSL_RSA_WITH_NULL_SHA, SSL_kRSA|SSL_aRSA|SSL_eNULL|SSL_SHA1, SSL3, 0, 0, SSL_NULL, SSL_NOT_ALLOWED},
255
256         /* TLSv1 ciphers */
257         {"EXP1024-DES-CBC-SHA", TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, SSL_kRSA|SSL_aRSA|SSL_DES|SSL_SHA, TLS1, 56, 56, SSL_EXPORT56, SSL_ALLOWED},
258         {"EXP1024-RC4-SHA", TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_SHA, TLS1, 56, 56, SSL_EXPORT56, SSL_ALLOWED},
259         {"AES128-SHA", TLS_RSA_WITH_AES_128_CBC_SHA, SSL_kRSA|SSL_aRSA|SSL_AES|SSL_SHA, TLS1, 128, 128, SSL_HIGH, SSL_ALLOWED},
260         {"AES256-SHA", TLS_RSA_WITH_AES_256_CBC_SHA, SSL_kRSA|SSL_aRSA|SSL_AES|SSL_SHA, TLS1, 256, 256, SSL_HIGH, SSL_ALLOWED},
261 };
262
263 #define ciphernum (sizeof(ciphers_def)/sizeof(cipher_properties))
264
265 /* given err which is the current errno, calls PR_SetError with
266    the corresponding NSPR error code */
267 static void 
268 tlsm_map_error(int err)
269 {
270         PRErrorCode prError;
271
272         switch ( err ) {
273         case EACCES:
274                 prError = PR_NO_ACCESS_RIGHTS_ERROR;
275                 break;
276         case EADDRINUSE:
277                 prError = PR_ADDRESS_IN_USE_ERROR;
278                 break;
279         case EADDRNOTAVAIL:
280                 prError = PR_ADDRESS_NOT_AVAILABLE_ERROR;
281                 break;
282         case EAFNOSUPPORT:
283                 prError = PR_ADDRESS_NOT_SUPPORTED_ERROR;
284                 break;
285         case EAGAIN:
286                 prError = PR_WOULD_BLOCK_ERROR;
287                 break;
288         /*
289          * On QNX and Neutrino, EALREADY is defined as EBUSY.
290          */
291 #if EALREADY != EBUSY
292         case EALREADY:
293                 prError = PR_ALREADY_INITIATED_ERROR;
294                 break;
295 #endif
296         case EBADF:
297                 prError = PR_BAD_DESCRIPTOR_ERROR;
298                 break;
299 #ifdef EBADMSG
300         case EBADMSG:
301                 prError = PR_IO_ERROR;
302                 break;
303 #endif
304         case EBUSY:
305                 prError = PR_FILESYSTEM_MOUNTED_ERROR;
306                 break;
307         case ECONNABORTED:
308                 prError = PR_CONNECT_ABORTED_ERROR;
309                 break;
310         case ECONNREFUSED:
311                 prError = PR_CONNECT_REFUSED_ERROR;
312                 break;
313         case ECONNRESET:
314                 prError = PR_CONNECT_RESET_ERROR;
315                 break;
316         case EDEADLK:
317                 prError = PR_DEADLOCK_ERROR;
318                 break;
319 #ifdef EDIRCORRUPTED
320         case EDIRCORRUPTED:
321                 prError = PR_DIRECTORY_CORRUPTED_ERROR;
322                 break;
323 #endif
324 #ifdef EDQUOT
325         case EDQUOT:
326                 prError = PR_NO_DEVICE_SPACE_ERROR;
327                 break;
328 #endif
329         case EEXIST:
330                 prError = PR_FILE_EXISTS_ERROR;
331                 break;
332         case EFAULT:
333                 prError = PR_ACCESS_FAULT_ERROR;
334                 break;
335         case EFBIG:
336                 prError = PR_FILE_TOO_BIG_ERROR;
337                 break;
338         case EHOSTUNREACH:
339                 prError = PR_HOST_UNREACHABLE_ERROR;
340                 break;
341         case EINPROGRESS:
342                 prError = PR_IN_PROGRESS_ERROR;
343                 break;
344         case EINTR:
345                 prError = PR_PENDING_INTERRUPT_ERROR;
346                 break;
347         case EINVAL:
348                 prError = PR_INVALID_ARGUMENT_ERROR;
349                 break;
350         case EIO:
351                 prError = PR_IO_ERROR;
352                 break;
353         case EISCONN:
354                 prError = PR_IS_CONNECTED_ERROR;
355                 break;
356         case EISDIR:
357                 prError = PR_IS_DIRECTORY_ERROR;
358                 break;
359         case ELOOP:
360                 prError = PR_LOOP_ERROR;
361                 break;
362         case EMFILE:
363                 prError = PR_PROC_DESC_TABLE_FULL_ERROR;
364                 break;
365         case EMLINK:
366                 prError = PR_MAX_DIRECTORY_ENTRIES_ERROR;
367                 break;
368         case EMSGSIZE:
369                 prError = PR_INVALID_ARGUMENT_ERROR;
370                 break;
371 #ifdef EMULTIHOP
372         case EMULTIHOP:
373                 prError = PR_REMOTE_FILE_ERROR;
374                 break;
375 #endif
376         case ENAMETOOLONG:
377                 prError = PR_NAME_TOO_LONG_ERROR;
378                 break;
379         case ENETUNREACH:
380                 prError = PR_NETWORK_UNREACHABLE_ERROR;
381                 break;
382         case ENFILE:
383                 prError = PR_SYS_DESC_TABLE_FULL_ERROR;
384                 break;
385         /*
386          * On SCO OpenServer 5, ENOBUFS is defined as ENOSR.
387          */
388 #if defined(ENOBUFS) && (ENOBUFS != ENOSR)
389         case ENOBUFS:
390                 prError = PR_INSUFFICIENT_RESOURCES_ERROR;
391                 break;
392 #endif
393         case ENODEV:
394                 prError = PR_FILE_NOT_FOUND_ERROR;
395                 break;
396         case ENOENT:
397                 prError = PR_FILE_NOT_FOUND_ERROR;
398                 break;
399         case ENOLCK:
400                 prError = PR_FILE_IS_LOCKED_ERROR;
401                 break;
402 #ifdef ENOLINK 
403         case ENOLINK:
404                 prError = PR_REMOTE_FILE_ERROR;
405                 break;
406 #endif
407         case ENOMEM:
408                 prError = PR_OUT_OF_MEMORY_ERROR;
409                 break;
410         case ENOPROTOOPT:
411                 prError = PR_INVALID_ARGUMENT_ERROR;
412                 break;
413         case ENOSPC:
414                 prError = PR_NO_DEVICE_SPACE_ERROR;
415                 break;
416 #ifdef ENOSR
417         case ENOSR:
418                 prError = PR_INSUFFICIENT_RESOURCES_ERROR;
419                 break;
420 #endif
421         case ENOTCONN:
422                 prError = PR_NOT_CONNECTED_ERROR;
423                 break;
424         case ENOTDIR:
425                 prError = PR_NOT_DIRECTORY_ERROR;
426                 break;
427         case ENOTSOCK:
428                 prError = PR_NOT_SOCKET_ERROR;
429                 break;
430         case ENXIO:
431                 prError = PR_FILE_NOT_FOUND_ERROR;
432                 break;
433         case EOPNOTSUPP:
434                 prError = PR_NOT_TCP_SOCKET_ERROR;
435                 break;
436 #ifdef EOVERFLOW
437         case EOVERFLOW:
438                 prError = PR_BUFFER_OVERFLOW_ERROR;
439                 break;
440 #endif
441         case EPERM:
442                 prError = PR_NO_ACCESS_RIGHTS_ERROR;
443                 break;
444         case EPIPE:
445                 prError = PR_CONNECT_RESET_ERROR;
446                 break;
447 #ifdef EPROTO
448         case EPROTO:
449                 prError = PR_IO_ERROR;
450                 break;
451 #endif
452         case EPROTONOSUPPORT:
453                 prError = PR_PROTOCOL_NOT_SUPPORTED_ERROR;
454                 break;
455         case EPROTOTYPE:
456                 prError = PR_ADDRESS_NOT_SUPPORTED_ERROR;
457                 break;
458         case ERANGE:
459                 prError = PR_INVALID_METHOD_ERROR;
460                 break;
461         case EROFS:
462                 prError = PR_READ_ONLY_FILESYSTEM_ERROR;
463                 break;
464         case ESPIPE:
465                 prError = PR_INVALID_METHOD_ERROR;
466                 break;
467         case ETIMEDOUT:
468                 prError = PR_IO_TIMEOUT_ERROR;
469                 break;
470 #if EWOULDBLOCK != EAGAIN
471         case EWOULDBLOCK:
472                 prError = PR_WOULD_BLOCK_ERROR;
473                 break;
474 #endif
475         case EXDEV:
476                 prError = PR_NOT_SAME_DEVICE_ERROR;
477                 break;
478         default:
479                 prError = PR_UNKNOWN_ERROR;
480                 break;
481         }
482         PR_SetError( prError, err );
483 }
484
485 /*
486  * cipher_list is an integer array with the following values:
487  *   -1: never enable this cipher
488  *    0: cipher disabled
489  *    1: cipher enabled
490  */
491 static int
492 nss_parse_ciphers(const char *cipherstr, int cipher_list[ciphernum])
493 {
494         int i;
495         char *cipher;
496         char *ciphers;
497         char *ciphertip;
498         int action;
499         int rv;
500
501         /* All disabled to start */
502         for (i=0; i<ciphernum; i++)
503                 cipher_list[i] = 0;
504
505         ciphertip = strdup(cipherstr);
506         cipher = ciphers = ciphertip;
507
508         while (ciphers && (strlen(ciphers))) {
509                 while ((*cipher) && (isspace(*cipher)))
510                         ++cipher;
511
512                 action = 1;
513                 switch(*cipher) {
514                 case '+': /* Add something */
515                         action = 1;
516                         cipher++;
517                         break;
518                 case '-': /* Subtract something */
519                         action = 0;
520                         cipher++;
521                         break;
522                 case '!':  /* Disable something */
523                         action = -1;
524                         cipher++;
525                         break;
526                 default:
527                         /* do nothing */
528                         break;
529                 }
530
531                 if ((ciphers = strchr(cipher, ':'))) {
532                         *ciphers++ = '\0';
533                 }
534
535                 /* Do the easy one first */
536                 if (!strcmp(cipher, "ALL")) {
537                         for (i=0; i<ciphernum; i++) {
538                                 if (!(ciphers_def[i].attr & SSL_eNULL))
539                                         cipher_list[i] = action;
540                         }
541                 } else if (!strcmp(cipher, "COMPLEMENTOFALL")) {
542                         for (i=0; i<ciphernum; i++) {
543                                 if ((ciphers_def[i].attr & SSL_eNULL))
544                                         cipher_list[i] = action;
545                         }
546                 } else if (!strcmp(cipher, "DEFAULT")) {
547                         for (i=0; i<ciphernum; i++) {
548                                 cipher_list[i] = ciphers_def[i].enabled == SSL_ALLOWED ? 1 : 0;
549                         }
550                 } else {
551                         int mask = 0;
552                         int strength = 0;
553                         int protocol = 0;
554                         char *c;
555
556                         c = cipher;
557                         while (c && (strlen(c))) {
558
559                                 if ((c = strchr(cipher, '+'))) {
560                                         *c++ = '\0';
561                                 }
562
563                                 if (!strcmp(cipher, "RSA")) {
564                                         mask |= SSL_RSA;
565                                 } else if ((!strcmp(cipher, "NULL")) || (!strcmp(cipher, "eNULL"))) {
566                                         mask |= SSL_eNULL;
567                                 } else if (!strcmp(cipher, "AES")) {
568                                         mask |= SSL_AES;
569                                 } else if (!strcmp(cipher, "3DES")) {
570                                         mask |= SSL_3DES;
571                                 } else if (!strcmp(cipher, "DES")) {
572                                         mask |= SSL_DES;
573                                 } else if (!strcmp(cipher, "RC4")) {
574                                         mask |= SSL_RC4;
575                                 } else if (!strcmp(cipher, "RC2")) {
576                                         mask |= SSL_RC2;
577                                 } else if (!strcmp(cipher, "MD5")) {
578                                         mask |= SSL_MD5;
579                                 } else if ((!strcmp(cipher, "SHA")) || (!strcmp(cipher, "SHA1"))) {
580                                         mask |= SSL_SHA1;
581                                 } else if (!strcmp(cipher, "SSLv2")) {
582                                         protocol |= SSL2;
583                                 } else if (!strcmp(cipher, "SSLv3")) {
584                                         protocol |= SSL3;
585                                 } else if (!strcmp(cipher, "TLSv1")) {
586                                         protocol |= TLS1;
587                                 } else if (!strcmp(cipher, "HIGH")) {
588                                         strength |= SSL_HIGH;
589                                 } else if (!strcmp(cipher, "MEDIUM")) {
590                                         strength |= SSL_MEDIUM;
591                                 } else if (!strcmp(cipher, "LOW")) {
592                                         strength |= SSL_LOW;
593                                 } else if ((!strcmp(cipher, "EXPORT")) || (!strcmp(cipher, "EXP"))) {
594                                         strength |= SSL_EXPORT40|SSL_EXPORT56;
595                                 } else if (!strcmp(cipher, "EXPORT40")) {
596                                         strength |= SSL_EXPORT40;
597                                 } else if (!strcmp(cipher, "EXPORT56")) {
598                                         strength |= SSL_EXPORT56;
599                                 }
600
601                                 if (c)
602                                         cipher = c;
603
604                         } /* while */
605
606                         /* If we have a mask, apply it. If not then perhaps they provided
607                          * a specific cipher to enable.
608                          */
609                         if (mask || strength || protocol) {
610                                 for (i=0; i<ciphernum; i++) {
611                                         if (((ciphers_def[i].attr & mask) ||
612                                                  (ciphers_def[i].strength & strength) ||
613                                                  (ciphers_def[i].version & protocol)) &&
614                                                 (cipher_list[i] != -1)) {
615                                                 /* Enable the NULL ciphers only if explicity
616                                                  * requested */
617                                                 if (ciphers_def[i].attr & SSL_eNULL) {
618                                                         if (mask & SSL_eNULL)
619                                                                 cipher_list[i] = action;
620                                                 } else
621                                                         cipher_list[i] = action;
622                                         }
623                                 }
624                         } else {
625                                 for (i=0; i<ciphernum; i++) {
626                                         if (!strcmp(ciphers_def[i].ossl_name, cipher) &&
627                                                 cipher_list[1] != -1)
628                                                 cipher_list[i] = action;
629                                 }
630                         }
631                 }
632
633                 if (ciphers)
634                         cipher = ciphers;
635         }
636
637         /* See if any ciphers were enabled */
638         rv = 0;
639         for (i=0; i<ciphernum; i++) {
640                 if (cipher_list[i] == 1)
641                         rv = 1;
642         }
643
644         free(ciphertip);
645
646         return rv;
647 }
648
649 static int
650 tlsm_parse_ciphers(tlsm_ctx *ctx, const char *str)
651 {
652         int cipher_state[ciphernum];
653         int rv, i;
654
655         if (!ctx)
656                 return 0;
657
658         rv = nss_parse_ciphers(str, cipher_state);
659
660         if (rv) {
661                 /* First disable everything */
662                 for (i = 0; i < SSL_NumImplementedCiphers; i++)
663                         SSL_CipherPrefSet(ctx->tc_model, SSL_ImplementedCiphers[i], SSL_NOT_ALLOWED);
664
665                 /* Now enable what was requested */
666                 for (i=0; i<ciphernum; i++) {
667                         SSLCipherSuiteInfo suite;
668                         PRBool enabled;
669
670                         if (SSL_GetCipherSuiteInfo(ciphers_def[i].num, &suite, sizeof suite)
671                                 == SECSuccess) {
672                                 enabled = cipher_state[i] < 0 ? 0 : cipher_state[i];
673                                 if (enabled == SSL_ALLOWED) {
674                                         if (PK11_IsFIPS() && !suite.isFIPS)    
675                                                 enabled = SSL_NOT_ALLOWED;
676                                 }
677                                 SSL_CipherPrefSet(ctx->tc_model, ciphers_def[i].num, enabled);
678                         }
679                 }
680         }
681
682         return rv == 1 ? 0 : -1;
683 }
684
685 static SECStatus
686 tlsm_bad_cert_handler(void *arg, PRFileDesc *ssl)
687 {
688         SECStatus success = SECSuccess;
689         PRErrorCode err;
690         tlsm_ctx *ctx = (tlsm_ctx *)arg;
691
692         if (!ssl || !ctx) {
693                 return SECFailure;
694         }
695
696         err = PORT_GetError();
697
698         switch (err) {
699         case SEC_ERROR_UNTRUSTED_ISSUER:
700         case SEC_ERROR_UNKNOWN_ISSUER:
701         case SEC_ERROR_EXPIRED_CERTIFICATE:
702         case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
703                 if (ctx->tc_verify_cert) {
704                         success = SECFailure;
705                 }
706                 break;
707         /* we bypass NSS's hostname checks and do our own */
708         case SSL_ERROR_BAD_CERT_DOMAIN:
709                 break;
710         default:
711                 success = SECFailure;
712                 break;
713         }
714
715         return success;
716 }
717
718 static const char *
719 tlsm_dump_security_status(PRFileDesc *fd)
720 {
721         char * cp;      /* bulk cipher name */
722         char * ip;      /* cert issuer DN */
723         char * sp;      /* cert subject DN */
724         int    op;      /* High, Low, Off */
725         int    kp0;     /* total key bits */
726         int    kp1;     /* secret key bits */
727         SSL3Statistics * ssl3stats = SSL_GetStatistics();
728
729         SSL_SecurityStatus( fd, &op, &cp, &kp0, &kp1, &ip, &sp );
730         Debug( LDAP_DEBUG_TRACE,
731                    "TLS certificate verification: subject: %s, issuer: %s, cipher: %s, ",
732                    sp ? sp : "-unknown-", ip ? ip : "-unknown-", cp ? cp : "-unknown-" );
733         PR_Free(cp);
734         PR_Free(ip);
735         PR_Free(sp);
736         Debug( LDAP_DEBUG_TRACE,
737                    "security level: %s, secret key bits: %d, total key bits: %d, ",
738                    ((op == SSL_SECURITY_STATUS_ON_HIGH) ? "high" :
739                         ((op == SSL_SECURITY_STATUS_ON_LOW) ? "low" : "off")),
740                    kp1, kp0 );
741
742         Debug( LDAP_DEBUG_TRACE,
743                    "cache hits: %ld, cache misses: %ld, cache not reusable: %ld\n",
744                    ssl3stats->hch_sid_cache_hits, ssl3stats->hch_sid_cache_misses,
745                    ssl3stats->hch_sid_cache_not_ok );
746
747         return "";
748 }
749
750 static void
751 tlsm_handshake_complete_cb( PRFileDesc *fd, void *client_data )
752 {
753         tlsm_dump_security_status( fd );
754 }
755
756 #ifdef READ_PASSWORD_FROM_FILE
757 static char *
758 tlsm_get_pin_from_file(const char *token_name, tlsm_ctx *ctx)
759 {
760         char *pwdstr = NULL;
761         char *contents = NULL;
762         char *lasts = NULL;
763         char *line = NULL;
764         char *candidate = NULL;
765         PRFileInfo file_info;
766         PRFileDesc *pwd_fileptr = PR_Open( ctx->tc_pin_file, PR_RDONLY, 00400 );
767
768         /* open the password file */
769         if ( !pwd_fileptr ) {
770                 PRErrorCode errcode = PR_GetError();
771                 Debug( LDAP_DEBUG_ANY,
772                        "TLS: could not open security pin file %s - error %d:%s.\n",
773                        ctx->tc_pin_file, errcode,
774                        PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
775                 goto done;
776         }
777
778         /* get the file size */
779         if ( PR_SUCCESS != PR_GetFileInfo( ctx->tc_pin_file, &file_info ) ) {
780                 PRErrorCode errcode = PR_GetError();
781                 Debug( LDAP_DEBUG_ANY,
782                        "TLS: could not get file info from pin file %s - error %d:%s.\n",
783                        ctx->tc_pin_file, errcode,
784                        PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
785                 goto done;
786         }
787
788         /* create a buffer to hold the file contents */
789         if ( !( contents = PR_MALLOC( file_info.size + 1 ) ) ) {
790                 PRErrorCode errcode = PR_GetError();
791                 Debug( LDAP_DEBUG_ANY,
792                        "TLS: could not alloc a buffer for contents of pin file %s - error %d:%s.\n",
793                        ctx->tc_pin_file, errcode,
794                        PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
795                 goto done;
796         }
797
798         /* read file into the buffer */
799         if( PR_Read( pwd_fileptr, contents, file_info.size ) <= 0 ) {
800                 PRErrorCode errcode = PR_GetError();
801                 Debug( LDAP_DEBUG_ANY,
802                        "TLS: could not read the file contents from pin file %s - error %d:%s.\n",
803                        ctx->tc_pin_file, errcode,
804                        PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
805                 goto done;
806         }
807
808         /* format is [tokenname:]password EOL [tokenname:]password EOL ... */
809         /* if you want to use a password containing a colon character, use
810            the special tokenname "default" */
811         for ( line = PL_strtok_r( contents, "\r\n", &lasts ); line;
812               line = PL_strtok_r( NULL, "\r\n", &lasts ) ) {
813                 char *colon;
814
815                 if ( !*line ) {
816                         continue; /* skip blank lines */
817                 }
818                 colon = PL_strchr( line, ':' );
819                 if ( colon ) {
820                         if ( *(colon + 1) && token_name &&
821                              !PL_strncmp( token_name, line, colon-line ) ) {
822                                 candidate = colon + 1; /* found a definite match */
823                                 break;
824                         } else if ( !PL_strncmp( DEFAULT_TOKEN_NAME, line, colon-line ) ) {
825                                 candidate = colon + 1; /* found possible match */
826                         }
827                 } else { /* no token name */
828                         candidate = line;
829                 }
830         }
831 done:
832         if ( pwd_fileptr ) {
833                 PR_Close( pwd_fileptr );
834         }
835         if ( candidate ) {
836                 pwdstr = PL_strdup( candidate );
837         }
838         PL_strfree( contents );
839
840         return pwdstr;
841 }
842 #endif /* READ_PASSWORD_FROM_FILE */
843
844 #ifdef READ_PASSWORD_FROM_STDIN
845 /*
846  * Turn the echoing off on a tty.
847  */
848 static void
849 echoOff(int fd)
850 {
851         if ( isatty( fd ) ) {
852                 struct termios tio;
853                 tcgetattr( fd, &tio );
854                 tio.c_lflag &= ~ECHO;
855                 tcsetattr( fd, TCSAFLUSH, &tio );
856         }
857 }
858
859 /*
860  * Turn the echoing on on a tty.
861  */
862 static void
863 echoOn(int fd)
864 {
865         if ( isatty( fd ) ) {
866                 struct termios tio;
867                 tcgetattr( fd, &tio );
868                 tio.c_lflag |= ECHO;
869                 tcsetattr( fd, TCSAFLUSH, &tio );
870                 tcsetattr( fd, TCSAFLUSH, &tio );
871         }
872 }
873 #endif /* READ_PASSWORD_FROM_STDIN */
874
875 /*
876  * This does the actual work of reading the pin/password/pass phrase
877  */
878 static char *
879 tlsm_get_pin(PK11SlotInfo *slot, PRBool retry, tlsm_ctx *ctx)
880 {
881         char *token_name = NULL;
882         char *pwdstr = NULL;
883
884         token_name = PK11_GetTokenName( slot );
885 #ifdef READ_PASSWORD_FROM_FILE
886         /* Try to get the passwords from the password file if it exists.
887          * THIS IS UNSAFE and is provided for convenience only. Without this
888          * capability the server would have to be started in foreground mode
889          * if using an encrypted key.
890          */
891         if ( ctx->tc_pin_file ) {
892                 pwdstr = tlsm_get_pin_from_file( token_name, ctx );
893         }
894 #endif /* RETRIEVE_PASSWORD_FROM_FILE */
895 #ifdef READ_PASSWORD_FROM_STDIN
896         if ( !pwdstr ) {
897                 int infd = PR_FileDesc2NativeHandle( PR_STDIN );
898                 int isTTY = isatty( infd );
899                 unsigned char phrase[200];
900                 /* Prompt for password */
901                 if ( isTTY ) {
902                         fprintf( stdout,
903                                  "Please enter pin, password, or pass phrase for security token '%s': ",
904                                  token_name ? token_name : DEFAULT_TOKEN_NAME );
905                         echoOff( infd );
906                 }
907                 fgets( (char*)phrase, sizeof(phrase), stdin );
908                 if ( isTTY ) {
909                         fprintf( stdout, "\n" );
910                         echoOn( infd );
911                 }
912                 /* stomp on newline */
913                 phrase[strlen((char*)phrase)-1] = 0;
914
915                 pwdstr = PL_strdup( (char*)phrase );
916         }
917
918 #endif /* READ_PASSWORD_FROM_STDIN */
919         return pwdstr;
920 }
921
922 /*
923  * PKCS11 devices (including the internal softokn cert/key database)
924  * may be protected by a pin or password or even pass phrase
925  * MozNSS needs a way for the user to provide that
926  */
927 static char *
928 tlsm_pin_prompt(PK11SlotInfo *slot, PRBool retry, void *arg)
929 {
930         tlsm_ctx *ctx = (tlsm_ctx *)arg;
931
932         return tlsm_get_pin( slot, retry, ctx );
933 }
934
935 static SECStatus
936 tlsm_get_basic_constraint_extension( CERTCertificate *cert,
937                                                                          CERTBasicConstraints *cbcval )
938 {
939         SECItem encodedVal = { 0, NULL };
940         SECStatus rc;
941
942         rc = CERT_FindCertExtension( cert, SEC_OID_X509_BASIC_CONSTRAINTS,
943                                                                  &encodedVal);
944         if ( rc != SECSuccess ) {
945                 return rc;
946         }
947
948         rc = CERT_DecodeBasicConstraintValue( cbcval, &encodedVal );
949
950         /* free the raw extension data */
951         PORT_Free( encodedVal.data );
952
953         return rc;
954 }
955
956 static PRBool
957 tlsm_cert_is_self_issued( CERTCertificate *cert )
958 {
959         /* A cert is self-issued if its subject and issuer are equal and
960          * both are of non-zero length. 
961          */
962         PRBool is_self_issued = cert &&
963                 (PRBool)SECITEM_ItemsAreEqual( &cert->derIssuer, 
964                                                                            &cert->derSubject ) &&
965                 cert->derSubject.len > 0;
966         return is_self_issued;
967 }
968
969 static SECStatus
970 tlsm_verify_cert(CERTCertDBHandle *handle, CERTCertificate *cert, void *pinarg,
971                                  PRBool checksig, SECCertificateUsage certUsage, int errorToIgnore )
972 {
973         CERTVerifyLog verifylog;
974         SECStatus ret = SECSuccess;
975         const char *name;
976         int debug_level = LDAP_DEBUG_ANY;
977
978         if ( errorToIgnore == -1 ) {
979                 debug_level = LDAP_DEBUG_TRACE;
980         }
981
982         /* the log captures information about every cert in the chain, so we can tell
983            which cert caused the problem and what the problem was */
984         memset( &verifylog, 0, sizeof( verifylog ) );
985         verifylog.arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE );
986         if ( verifylog.arena == NULL ) {
987                 Debug( LDAP_DEBUG_ANY,
988                            "TLS certificate verification: Out of memory for certificate verification logger\n",
989                            0, 0, 0 );
990                 return SECFailure;
991         }
992         ret = CERT_VerifyCertificate( handle, cert, checksig, certUsage, PR_Now(), pinarg, &verifylog,
993                                                                   NULL );
994         if ( ( name = cert->subjectName ) == NULL ) {
995                 name = cert->nickname;
996         }
997         if ( verifylog.head == NULL ) {
998                 /* it is possible for CERT_VerifyCertificate return with an error with no logging */
999                 if ( ret != SECSuccess ) {
1000                         PRErrorCode errcode = PR_GetError();
1001                         Debug( debug_level,
1002                                    "TLS: certificate [%s] is not valid - error %d:%s.\n",
1003                                    name ? name : "(unknown)",
1004                                    errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1005                 }
1006         } else {
1007                 const char *name;
1008                 CERTVerifyLogNode *node;
1009
1010                 ret = SECSuccess; /* reset */
1011                 node = verifylog.head;
1012                 while ( node ) {
1013                         if ( ( name = node->cert->subjectName ) == NULL ) {
1014                                 name = node->cert->nickname;
1015                         }
1016                         if ( node->error ) {
1017                                 /* NSS does not like CA certs that have the basic constraints extension
1018                                    with the CA flag set to FALSE - openssl doesn't check if the cert
1019                                    is self issued */
1020                                 if ( ( node->error == SEC_ERROR_CA_CERT_INVALID ) &&
1021                                          tlsm_cert_is_self_issued( node->cert ) ) {
1022                                         CERTBasicConstraints basicConstraint;
1023                                         SECStatus rv = tlsm_get_basic_constraint_extension( node->cert, &basicConstraint );
1024                                         if ( ( rv == SECSuccess ) && ( basicConstraint.isCA == PR_FALSE ) ) {
1025                                                 Debug( LDAP_DEBUG_TRACE,
1026                                                            "TLS: certificate [%s] is not correct because it is a CA cert and the "
1027                                                            "BasicConstraint CA flag is set to FALSE - allowing for now, but "
1028                                                            "please fix your certs if possible\n", name, 0, 0 );
1029                                         } else { /* does not have basicconstraint, or some other error */
1030                                                 ret = SECFailure;
1031                                                 Debug( debug_level,
1032                                                            "TLS: certificate [%s] is not valid - CA cert is not valid\n",
1033                                                            name, 0, 0 );
1034                                         }
1035                                 } else if ( errorToIgnore && ( node->error == errorToIgnore ) ) {
1036                                         Debug( debug_level,
1037                                                    "TLS: Warning: ignoring error for certificate [%s] - error %ld:%s.\n",
1038                                                    name, node->error, PR_ErrorToString( node->error, PR_LANGUAGE_I_DEFAULT ) );
1039                                 } else {
1040                                         ret = SECFailure;
1041                                         Debug( debug_level,
1042                                                    "TLS: certificate [%s] is not valid - error %ld:%s.\n",
1043                                                    name, node->error, PR_ErrorToString( node->error, PR_LANGUAGE_I_DEFAULT ) );
1044                                 }
1045                         }
1046                         CERT_DestroyCertificate( node->cert );
1047                         node = node->next;
1048                 }
1049         }
1050
1051         PORT_FreeArena( verifylog.arena, PR_FALSE );
1052
1053         if ( ret == SECSuccess ) {
1054                 Debug( LDAP_DEBUG_TRACE,
1055                            "TLS: certificate [%s] is valid\n", name, 0, 0 );
1056         } else if ( errorToIgnore == -1 ) {
1057                 ret = SECSuccess;
1058         }
1059
1060         return ret;
1061 }
1062
1063 static SECStatus
1064 tlsm_auth_cert_handler(void *arg, PRFileDesc *fd,
1065                        PRBool checksig, PRBool isServer)
1066 {
1067         SECCertificateUsage certUsage = isServer ? certificateUsageSSLClient : certificateUsageSSLServer;
1068         SECStatus ret = SECSuccess;
1069         CERTCertificate *peercert = SSL_PeerCertificate( fd );
1070         int errorToIgnore = 0;
1071         tlsm_ctx *ctx = (tlsm_ctx *)arg;
1072
1073         if (ctx && ctx->tc_warn_only )
1074                 errorToIgnore = -1;
1075
1076         ret = tlsm_verify_cert( ctx->tc_certdb, peercert,
1077                                                         SSL_RevealPinArg( fd ),
1078                                                         checksig, certUsage, errorToIgnore );
1079         CERT_DestroyCertificate( peercert );
1080
1081         return ret;
1082 }
1083
1084 static int
1085 tlsm_authenticate_to_slot( tlsm_ctx *ctx, PK11SlotInfo *slot )
1086 {
1087         int rc = -1;
1088
1089         if ( SECSuccess != PK11_Authenticate( slot, PR_FALSE, ctx ) ) {
1090                 char *token_name = PK11_GetTokenName( slot );
1091                 PRErrorCode errcode = PR_GetError();
1092                 Debug( LDAP_DEBUG_ANY,
1093                            "TLS: could not authenticate to the security token %s - error %d:%s.\n",
1094                            token_name ? token_name : DEFAULT_TOKEN_NAME, errcode,
1095                            PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1096         } else {
1097                 rc = 0; /* success */
1098         }
1099
1100         return rc;
1101 }
1102
1103 static SECStatus
1104 tlsm_nss_shutdown_cb( void *appData, void *nssData )
1105 {
1106         SECStatus rc = SECSuccess;
1107
1108         SSL_ShutdownServerSessionIDCache();
1109
1110         if ( pem_module ) {
1111                 SECMOD_UnloadUserModule( pem_module );
1112                 SECMOD_DestroyModule( pem_module );
1113                 pem_module = NULL;
1114         }
1115         return rc;
1116 }
1117
1118 static PRCallOnceType tlsm_register_shutdown_callonce = {0,0};
1119 static PRStatus PR_CALLBACK
1120 tlsm_register_nss_shutdown_cb( void )
1121 {
1122         if ( SECSuccess == NSS_RegisterShutdown( tlsm_nss_shutdown_cb,
1123                                                                                          NULL ) ) {
1124                 return PR_SUCCESS;
1125         }
1126         return PR_FAILURE;
1127 }
1128
1129 static PRStatus
1130 tlsm_register_nss_shutdown( void )
1131 {
1132         return PR_CallOnce( &tlsm_register_shutdown_callonce,
1133                                                 tlsm_register_nss_shutdown_cb );
1134 }
1135
1136 static int
1137 tlsm_init_pem_module( void )
1138 {
1139         int rc = 0;
1140         char *fullname = NULL;
1141         char *configstring = NULL;
1142
1143         if ( pem_module ) {
1144                 return rc;
1145         }
1146
1147         /* not loaded - load it */
1148         /* get the system dependent library name */
1149         fullname = PR_GetLibraryName( NULL, PEM_LIBRARY );
1150         /* Load our PKCS#11 module */
1151         configstring = PR_smprintf( "library=%s name=" PEM_MODULE " parameters=\"\"", fullname );
1152         PL_strfree( fullname );
1153
1154         pem_module = SECMOD_LoadUserModule( configstring, NULL, PR_FALSE );
1155         PR_smprintf_free( configstring );
1156
1157         if ( !pem_module || !pem_module->loaded ) {
1158                 if ( pem_module ) {
1159                         SECMOD_DestroyModule( pem_module );
1160                         pem_module = NULL;
1161                 }
1162                 rc = -1;
1163         }
1164
1165         return rc;
1166 }
1167
1168 static void
1169 tlsm_add_pem_obj( tlsm_ctx *ctx, PK11GenericObject *obj )
1170 {
1171         int idx = ctx->tc_n_pem_objs;
1172         ctx->tc_n_pem_objs++;
1173         ctx->tc_pem_objs = (PK11GenericObject **)
1174                 PORT_Realloc( ctx->tc_pem_objs, ctx->tc_n_pem_objs * sizeof( PK11GenericObject * ) );
1175         ctx->tc_pem_objs[idx] = obj;                                                                                                              
1176 }
1177
1178 static void
1179 tlsm_free_pem_objs( tlsm_ctx *ctx )
1180 {
1181         /* free in reverse order of allocation */
1182         while ( ctx->tc_n_pem_objs-- ) {
1183                 PK11_DestroyGenericObject( ctx->tc_pem_objs[ctx->tc_n_pem_objs] );
1184                 ctx->tc_pem_objs[ctx->tc_n_pem_objs] = NULL;
1185         }
1186         PORT_Free(ctx->tc_pem_objs);
1187         ctx->tc_pem_objs = NULL;
1188         ctx->tc_n_pem_objs = 0;
1189 }
1190
1191 static int
1192 tlsm_add_cert_from_file( tlsm_ctx *ctx, const char *filename, PRBool isca, PRBool istrusted )
1193 {
1194         CK_SLOT_ID slotID;
1195         PK11SlotInfo *slot = NULL;
1196         PK11GenericObject *rv;
1197         CK_ATTRIBUTE *attrs;
1198         CK_ATTRIBUTE theTemplate[20];
1199         CK_BBOOL cktrue = CK_TRUE;
1200         CK_BBOOL ckfalse = CK_FALSE;
1201         CK_OBJECT_CLASS objClass = CKO_CERTIFICATE;
1202         char tmpslotname[64];
1203         char *slotname = NULL;
1204         const char *ptr = NULL;
1205         char sep = PR_GetDirectorySeparator();
1206         PRFileInfo fi;
1207         PRStatus status;
1208
1209         memset( &fi, 0, sizeof(fi) );
1210         status = PR_GetFileInfo( filename, &fi );
1211         if ( PR_SUCCESS != status) {
1212                 PRErrorCode errcode = PR_GetError();
1213                 Debug( LDAP_DEBUG_ANY,
1214                            "TLS: could not read certificate file %s - error %d:%s.\n",
1215                            filename, errcode,
1216                            PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1217                 return -1;
1218         }
1219
1220         if ( fi.type != PR_FILE_FILE ) {
1221                 PR_SetError(PR_IS_DIRECTORY_ERROR, 0);
1222                 Debug( LDAP_DEBUG_ANY,
1223                            "TLS: error: the certificate file %s is not a file.\n",
1224                            filename, 0 ,0 );
1225                 return -1;
1226         }
1227
1228         attrs = theTemplate;
1229
1230         if ( isca ) {
1231                 slotID = 0; /* CA and trust objects use slot 0 */
1232                 PR_snprintf( tmpslotname, sizeof(tmpslotname), TLSM_PEM_TOKEN_FMT, slotID );
1233                 slotname = tmpslotname;
1234                 istrusted = PR_TRUE;
1235         } else {
1236                 if ( ctx->tc_slotname == NULL ) { /* need new slot */
1237                         if ( istrusted ) {
1238                                 slotID = 0;
1239                         } else {
1240                                 slotID = ++tlsm_slot_count;
1241                         }
1242                         ctx->tc_slotname = PR_smprintf( TLSM_PEM_TOKEN_FMT, slotID );
1243                 }
1244                 slotname = ctx->tc_slotname;
1245
1246                 if ( ( ptr = PL_strrchr( filename, sep ) ) ) {
1247                         PL_strfree( ctx->tc_certname );
1248                         ++ptr;
1249                         if ( istrusted ) {
1250                                 /* pemnss conflates trusted certs with CA certs - since there can
1251                                    be more than one CA cert in a file (e.g. ca-bundle.crt) pemnss
1252                                    numbers each trusted cert - in the case of a server cert, there will be
1253                                    only one, so it will be number 0 */
1254                                 ctx->tc_certname = PR_smprintf( "%s:%s - 0", slotname, ptr );
1255                         } else {
1256                                 ctx->tc_certname = PR_smprintf( "%s:%s", slotname, ptr );
1257                         }
1258                 }
1259         }
1260
1261         slot = PK11_FindSlotByName( slotname );
1262
1263         if ( !slot ) {
1264                 PRErrorCode errcode = PR_GetError();
1265                 Debug( LDAP_DEBUG_ANY,
1266                            "TLS: could not find the slot for certificate %s - error %d:%s.\n",
1267                            ctx->tc_certname, errcode,
1268                            PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1269                 return -1;
1270         }
1271
1272         PK11_SETATTRS( attrs, CKA_CLASS, &objClass, sizeof(objClass) ); attrs++;
1273         PK11_SETATTRS( attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL) ); attrs++;
1274         PK11_SETATTRS( attrs, CKA_LABEL, (unsigned char *)filename, strlen(filename)+1 ); attrs++;
1275         if ( istrusted ) {
1276                 PK11_SETATTRS( attrs, CKA_TRUST, &cktrue, sizeof(CK_BBOOL) ); attrs++;
1277         } else {
1278                 PK11_SETATTRS( attrs, CKA_TRUST, &ckfalse, sizeof(CK_BBOOL) ); attrs++;
1279         }
1280         /* This loads the certificate in our PEM module into the appropriate
1281          * slot.
1282          */
1283         rv = PK11_CreateGenericObject( slot, theTemplate, 4, PR_FALSE /* isPerm */ );
1284
1285         PK11_FreeSlot( slot );
1286
1287         if ( !rv ) {
1288                 PRErrorCode errcode = PR_GetError();
1289                 Debug( LDAP_DEBUG_ANY,
1290                            "TLS: could not add the certificate %s - error %d:%s.\n",
1291                            ctx->tc_certname, errcode,
1292                            PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1293                 return -1;
1294         }
1295
1296         tlsm_add_pem_obj( ctx, rv );
1297
1298         return 0;
1299 }
1300
1301 static int
1302 tlsm_add_key_from_file( tlsm_ctx *ctx, const char *filename )
1303 {
1304         CK_SLOT_ID slotID;
1305         PK11SlotInfo * slot = NULL;
1306         PK11GenericObject *rv;
1307         CK_ATTRIBUTE *attrs;
1308         CK_ATTRIBUTE theTemplate[20];
1309         CK_BBOOL cktrue = CK_TRUE;
1310         CK_OBJECT_CLASS objClass = CKO_PRIVATE_KEY;
1311         int retcode = 0;
1312         PRFileInfo fi;
1313         PRStatus status;
1314
1315         memset( &fi, 0, sizeof(fi) );
1316         status = PR_GetFileInfo( filename, &fi );
1317         if ( PR_SUCCESS != status) {
1318                 PRErrorCode errcode = PR_GetError();
1319                 Debug( LDAP_DEBUG_ANY,
1320                            "TLS: could not read key file %s - error %d:%s.\n",
1321                            filename, errcode,
1322                            PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1323                 return -1;
1324         }
1325
1326         if ( fi.type != PR_FILE_FILE ) {
1327                 PR_SetError(PR_IS_DIRECTORY_ERROR, 0);
1328                 Debug( LDAP_DEBUG_ANY,
1329                            "TLS: error: the key file %s is not a file.\n",
1330                            filename, 0 ,0 );
1331                 return -1;
1332         }
1333
1334         attrs = theTemplate;
1335
1336         if ( ctx->tc_slotname == NULL ) { /* need new slot */
1337                 slotID = ++tlsm_slot_count;
1338                 ctx->tc_slotname = PR_smprintf( TLSM_PEM_TOKEN_FMT, slotID );
1339         }
1340         slot = PK11_FindSlotByName( ctx->tc_slotname );
1341
1342         if ( !slot ) {
1343                 PRErrorCode errcode = PR_GetError();
1344                 Debug( LDAP_DEBUG_ANY,
1345                            "TLS: could not find the slot %s for the private key - error %d:%s.\n",
1346                            ctx->tc_slotname, errcode,
1347                            PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1348                 return -1;
1349         }
1350
1351         PK11_SETATTRS( attrs, CKA_CLASS, &objClass, sizeof(objClass) ); attrs++;
1352         PK11_SETATTRS( attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL) ); attrs++;
1353         PK11_SETATTRS( attrs, CKA_LABEL, (unsigned char *)filename, strlen(filename)+1 ); attrs++;
1354         rv = PK11_CreateGenericObject( slot, theTemplate, 3, PR_FALSE /* isPerm */ );
1355
1356         if ( !rv ) {
1357                 PRErrorCode errcode = PR_GetError();
1358                 Debug( LDAP_DEBUG_ANY,
1359                            "TLS: could not add the certificate %s - error %d:%s.\n",
1360                            ctx->tc_certname, errcode,
1361                            PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1362                 retcode = -1;
1363         } else {
1364                 /* When adding an encrypted key the PKCS#11 will be set as removed */
1365                 /* This will force the token to be seen as re-inserted */
1366                 SECMOD_WaitForAnyTokenEvent( pem_module, 0, 0 );
1367                 PK11_IsPresent( slot );
1368                 retcode = 0;
1369         }
1370
1371         PK11_FreeSlot( slot );
1372
1373         if ( !retcode ) {
1374                 tlsm_add_pem_obj( ctx, rv );
1375         }
1376         return retcode;
1377 }
1378
1379 static int
1380 tlsm_init_ca_certs( tlsm_ctx *ctx, const char *cacertfile, const char *cacertdir )
1381 {
1382         PRBool isca = PR_TRUE;
1383         PRStatus status = PR_SUCCESS;
1384         PRErrorCode errcode = PR_SUCCESS;
1385
1386         if ( !cacertfile && !cacertdir ) {
1387                 /* no checking - not good, but allowed */
1388                 return 0;
1389         }
1390
1391         if ( cacertfile ) {
1392                 int rc = tlsm_add_cert_from_file( ctx, cacertfile, isca, PR_TRUE );
1393                 if ( rc ) {
1394                         errcode = PR_GetError();
1395                         Debug( LDAP_DEBUG_ANY,
1396                                    "TLS: %s is not a valid CA certificate file - error %d:%s.\n",
1397                                    cacertfile, errcode,
1398                                    PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1399                         /* failure with cacertfile is a hard failure even if cacertdir is
1400                            also specified and contains valid CA cert files */
1401                         status = PR_FAILURE;
1402                 } else {
1403                         Debug( LDAP_DEBUG_TRACE,
1404                                    "TLS: loaded CA certificate file %s.\n",
1405                                    cacertfile, 0, 0 );
1406                 }
1407         }
1408
1409         /* if cacertfile above failed, we will return failure, even
1410            if there is a valid CA cert in cacertdir - but we still
1411            process cacertdir in case the user has enabled trace level
1412            debugging so they can see the processing for cacertdir too */
1413         /* any cacertdir failures are "soft" failures - if the user specifies
1414            no cert checking, then we allow the tls/ssl to continue, no matter
1415            what was specified for cacertdir, or the contents of the directory
1416            - this is different behavior than that of cacertfile */
1417         if ( cacertdir ) {
1418                 PRFileInfo fi;
1419                 PRDir *dir;
1420                 PRDirEntry *entry;
1421                 PRStatus fistatus = PR_FAILURE;
1422
1423                 memset( &fi, 0, sizeof(fi) );
1424                 fistatus = PR_GetFileInfo( cacertdir, &fi );
1425                 if ( PR_SUCCESS != fistatus) {
1426                         errcode = PR_GetError();
1427                         Debug( LDAP_DEBUG_ANY,
1428                                    "TLS: could not get info about the CA certificate directory %s - error %d:%s.\n",
1429                                    cacertdir, errcode,
1430                                    PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1431                         goto done;
1432                 }
1433
1434                 if ( fi.type != PR_FILE_DIRECTORY ) {
1435                         Debug( LDAP_DEBUG_ANY,
1436                                    "TLS: error: the CA certificate directory %s is not a directory.\n",
1437                                    cacertdir, 0 ,0 );
1438                         goto done;
1439                 }
1440
1441                 dir = PR_OpenDir( cacertdir );
1442                 if ( NULL == dir ) {
1443                         errcode = PR_GetError();
1444                         Debug( LDAP_DEBUG_ANY,
1445                                    "TLS: could not open the CA certificate directory %s - error %d:%s.\n",
1446                                    cacertdir, errcode,
1447                                    PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1448                         goto done;
1449                 }
1450
1451                 do {
1452                         entry = PR_ReadDir( dir, PR_SKIP_BOTH | PR_SKIP_HIDDEN );
1453                         if ( ( NULL != entry ) && ( NULL != entry->name ) ) {
1454                                 char *fullpath = NULL;
1455                                 char *ptr;
1456
1457                                 ptr = PL_strrstr( entry->name, PEM_CA_HASH_FILE_SUFFIX );
1458                                 if ( ( ptr == NULL ) || ( *(ptr + PEM_CA_HASH_FILE_SUFFIX_LEN) != '\0' ) ) {
1459                                         Debug( LDAP_DEBUG_TRACE,
1460                                                    "TLS: file %s does not end in [%s] - does not appear to be a CA certificate "
1461                                                    "directory file with a properly hashed file name - skipping.\n",
1462                                                    entry->name, PEM_CA_HASH_FILE_SUFFIX, 0 );
1463                                         continue;
1464                                 }
1465                                 fullpath = PR_smprintf( "%s/%s", cacertdir, entry->name );
1466                                 if ( !tlsm_add_cert_from_file( ctx, fullpath, isca, PR_TRUE ) ) {
1467                                         Debug( LDAP_DEBUG_TRACE,
1468                                                    "TLS: loaded CA certificate file %s from CA certificate directory %s.\n",
1469                                                    fullpath, cacertdir, 0 );
1470                                 } else {
1471                                         errcode = PR_GetError();
1472                                         Debug( LDAP_DEBUG_TRACE,
1473                                                    "TLS: %s is not a valid CA certificate file - error %d:%s.\n",
1474                                                    fullpath, errcode,
1475                                                    PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1476                                 }
1477                                 PR_smprintf_free( fullpath );
1478                         }
1479                 } while ( NULL != entry );
1480                 PR_CloseDir( dir );
1481         }
1482 done:
1483         if ( status != PR_SUCCESS ) {
1484                 return -1;
1485         }
1486
1487         return 0;
1488 }
1489
1490 /*
1491  * NSS supports having multiple cert/key databases in the same
1492  * directory, each one having a unique string prefix e.g.
1493  * slapd-01-cert8.db - the prefix here is "slapd-01-"
1494  * this function examines the given certdir - if it looks like
1495  * /path/to/directory/prefix it will return the
1496  * /path/to/directory part in realcertdir, and the prefix in prefix
1497  */
1498 static void
1499 tlsm_get_certdb_prefix( const char *certdir, char **realcertdir, char **prefix )
1500 {
1501         char sep = PR_GetDirectorySeparator();
1502         char *ptr = NULL;
1503         struct PRFileInfo prfi;
1504         PRStatus prc;
1505
1506         *realcertdir = (char *)certdir; /* default is the one passed in */
1507
1508         /* if certdir is not given, just return */
1509         if ( !certdir ) {
1510                 return;
1511         }
1512
1513         prc = PR_GetFileInfo( certdir, &prfi );
1514         /* if certdir exists (file or directory) then it cannot specify a prefix */
1515         if ( prc == PR_SUCCESS ) {
1516                 return;
1517         }
1518
1519         /* if certdir was given, and there is a '/' in certdir, see if there
1520            is anything after the last '/' - if so, assume it is the prefix */
1521         if ( ( ( ptr = strrchr( certdir, sep ) ) ) && *(ptr+1) ) {
1522                 *realcertdir = PL_strndup( certdir, ptr-certdir );
1523                 *prefix = PL_strdup( ptr+1 );
1524         }
1525
1526         return;
1527 }
1528
1529 /*
1530  * This is the part of the init we defer until we get the
1531  * actual security configuration information.  This is
1532  * only called once, protected by a PRCallOnce
1533  * NOTE: This must be done before the first call to SSL_ImportFD,
1534  * especially the setting of the policy
1535  * NOTE: This must be called after fork()
1536  */
1537 static int
1538 tlsm_deferred_init( void *arg )
1539 {
1540         tlsm_ctx *ctx = (tlsm_ctx *)arg;
1541         struct ldaptls *lt = ctx->tc_config;
1542         const char *securitydirs[3];
1543         int ii;
1544         int nn;
1545         PRErrorCode errcode = 1;
1546 #ifdef HAVE_NSS_INITCONTEXT
1547         NSSInitParameters initParams;
1548         NSSInitContext *initctx = NULL;
1549 #endif
1550         SECStatus rc;
1551         int done = 0;
1552
1553 #ifdef HAVE_SECMOD_RESTARTMODULES
1554         /* NSS enforces the pkcs11 requirement that modules should be unloaded after
1555            a fork() - since there is no portable way to determine if NSS has been
1556            already initialized in a parent process, we just call SECMOD_RestartModules
1557            with force == FALSE - if the module has been unloaded due to a fork, it will
1558            be reloaded, otherwise, it is a no-op */
1559         if ( SECFailure == ( rc = SECMOD_RestartModules(PR_FALSE /* do not force */) ) ) {
1560                 errcode = PORT_GetError();
1561                 if ( errcode != SEC_ERROR_NOT_INITIALIZED ) {
1562                         Debug( LDAP_DEBUG_TRACE,
1563                                    "TLS: could not restart the security modules: %d:%s\n",
1564                                    errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 );
1565                 } else {
1566                         errcode = 1;
1567                 }
1568         }
1569 #endif
1570
1571 #ifdef HAVE_NSS_INITCONTEXT
1572         memset( &initParams, 0, sizeof( initParams ) );
1573         initParams.length = sizeof( initParams );
1574 #endif /* HAVE_NSS_INITCONTEXT */
1575
1576 #ifdef LDAP_R_COMPILE
1577         if ( PR_CallOnce( &tlsm_init_mutex_callonce, tlsm_thr_init_callonce ) ) {
1578                 return -1;
1579         }
1580 #endif /* LDAP_R_COMPILE */
1581
1582 #ifndef HAVE_NSS_INITCONTEXT
1583         if ( !NSS_IsInitialized() ) {
1584 #endif /* HAVE_NSS_INITCONTEXT */
1585                 /*
1586                   MOZNSS_DIR will override everything else - you can
1587                   always set MOZNSS_DIR to force the use of this
1588                   directory
1589                   If using MOZNSS, specify the location of the moznss db dir
1590                   in the cacertdir directive of the OpenLDAP configuration.
1591                   DEFAULT_MOZNSS_DIR will only be used if the code cannot
1592                   find a security dir to use based on the current
1593                   settings
1594                 */
1595                 nn = 0;
1596                 securitydirs[nn++] = PR_GetEnv( "MOZNSS_DIR" );
1597                 securitydirs[nn++] = lt->lt_cacertdir;
1598                 securitydirs[nn++] = PR_GetEnv( "DEFAULT_MOZNSS_DIR" );
1599                 for ( ii = 0; !done && ( ii < nn ); ++ii ) {
1600                         char *realcertdir = NULL;
1601                         const char *defprefix = "";
1602                         char *prefix = (char *)defprefix;
1603                         const char *securitydir = securitydirs[ii];
1604                         if ( NULL == securitydir ) {
1605                                 continue;
1606                         }
1607
1608                         tlsm_get_certdb_prefix( securitydir, &realcertdir, &prefix );
1609                         LDAP_MUTEX_LOCK( &tlsm_init_mutex );
1610
1611 #ifdef HAVE_NSS_INITCONTEXT
1612 #ifdef INITCONTEXT_HACK
1613                         if ( !NSS_IsInitialized() && ctx->tc_is_server ) {
1614                                 rc = NSS_Initialize( realcertdir, prefix, prefix, SECMOD_DB, NSS_INIT_READONLY );
1615                         } else {
1616                                 initctx = NSS_InitContext( realcertdir, prefix, prefix, SECMOD_DB,
1617                                                                                    &initParams, NSS_INIT_READONLY );
1618                                 rc = (initctx == NULL) ? SECFailure : SECSuccess;
1619                         }
1620 #else
1621                         initctx = NSS_InitContext( realcertdir, prefix, prefix, SECMOD_DB,
1622                                                                            &initParams, NSS_INIT_READONLY );
1623                         rc = (initctx == NULL) ? SECFailure : SECSuccess;
1624 #endif
1625 #else
1626                         rc = NSS_Initialize( realcertdir, prefix, prefix, SECMOD_DB, NSS_INIT_READONLY );
1627 #endif
1628
1629                         LDAP_MUTEX_UNLOCK( &tlsm_init_mutex );
1630
1631                         if ( rc != SECSuccess ) {
1632                                 errcode = PORT_GetError();
1633                                 if ( securitydirs[ii] != lt->lt_cacertdir) {
1634                                         Debug( LDAP_DEBUG_TRACE,
1635                                                    "TLS: could not initialize moznss using security dir %s prefix %s - error %d.\n",
1636                                                    realcertdir, prefix, errcode );
1637                                 }
1638                         } else {
1639                                 /* success */
1640                                 Debug( LDAP_DEBUG_TRACE, "TLS: using moznss security dir %s prefix %s.\n",
1641                                            realcertdir, prefix, 0 );
1642                                 errcode = 0;
1643                                 done = 1;
1644                         }
1645                         if ( realcertdir != securitydir ) {
1646                                 PL_strfree( realcertdir );
1647                         }
1648                         if ( prefix != defprefix ) {
1649                                 PL_strfree( prefix );
1650                         }
1651                 }
1652
1653                 if ( errcode ) { /* no moznss db found, or not using moznss db */
1654                         LDAP_MUTEX_LOCK( &tlsm_init_mutex );
1655 #ifdef HAVE_NSS_INITCONTEXT
1656                         int flags = NSS_INIT_READONLY|NSS_INIT_NOCERTDB|NSS_INIT_NOMODDB;
1657 #ifdef INITCONTEXT_HACK
1658                         if ( !NSS_IsInitialized() && ctx->tc_is_server ) {
1659                                 rc = NSS_NoDB_Init( NULL );
1660                         } else {
1661                                 initctx = NSS_InitContext( "", "", "", SECMOD_DB,
1662                                                                                    &initParams, flags );
1663                                 rc = (initctx == NULL) ? SECFailure : SECSuccess;
1664                         }
1665 #else
1666                         initctx = NSS_InitContext( "", "", "", SECMOD_DB,
1667                                                                            &initParams, flags );
1668                         rc = (initctx == NULL) ? SECFailure : SECSuccess;
1669 #endif
1670 #else
1671                         rc = NSS_NoDB_Init( NULL );
1672 #endif
1673                         LDAP_MUTEX_UNLOCK( &tlsm_init_mutex );
1674                         if ( rc != SECSuccess ) {
1675                                 errcode = PORT_GetError();
1676                                 Debug( LDAP_DEBUG_ANY,
1677                                            "TLS: could not initialize moznss - error %d:%s.\n",
1678                                            errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 );
1679                                 return -1;
1680                         }
1681
1682 #ifdef HAVE_NSS_INITCONTEXT
1683                         ctx->tc_initctx = initctx;
1684 #endif
1685
1686                 }
1687
1688                 if ( errcode || lt->lt_cacertfile ) {
1689                         /* initialize the PEM module */
1690                         LDAP_MUTEX_LOCK( &tlsm_init_mutex );
1691                         if ( tlsm_init_pem_module() ) {
1692                                 LDAP_MUTEX_UNLOCK( &tlsm_init_mutex );
1693                                 int pem_errcode = PORT_GetError();
1694                                 Debug( LDAP_DEBUG_ANY,
1695                                            "TLS: could not initialize moznss PEM module - error %d:%s.\n",
1696                                            pem_errcode, PR_ErrorToString( pem_errcode, PR_LANGUAGE_I_DEFAULT ), 0 );
1697
1698                                 if ( errcode ) /* PEM is required */
1699                                         return -1;
1700
1701                         } else if ( !errcode ) {
1702                                 tlsm_init_ca_certs( ctx, lt->lt_cacertfile, NULL );
1703                         }
1704                         LDAP_MUTEX_UNLOCK( &tlsm_init_mutex );
1705                 }
1706
1707                 if ( errcode ) {
1708                         if ( tlsm_init_ca_certs( ctx, lt->lt_cacertfile, lt->lt_cacertdir ) ) {
1709                                 /* if we tried to use lt->lt_cacertdir as an NSS key/cert db, errcode 
1710                                    will be a value other than 1 - print an error message so that the
1711                                    user will know that failed too */
1712                                 if ( ( errcode != 1 ) && ( lt->lt_cacertdir ) ) {
1713                                         char *realcertdir = NULL;
1714                                         char *prefix = NULL;
1715                                         tlsm_get_certdb_prefix( lt->lt_cacertdir, &realcertdir, &prefix );
1716                                         Debug( LDAP_DEBUG_TRACE,
1717                                                    "TLS: could not initialize moznss using security dir %s prefix %s - error %d.\n",
1718                                                    realcertdir, prefix ? prefix : "", errcode );
1719                                         if ( realcertdir != lt->lt_cacertdir ) {
1720                                                 PL_strfree( realcertdir );
1721                                         }
1722                                         PL_strfree( prefix );
1723                                 }
1724                                 return -1;
1725                         }
1726
1727                         ctx->tc_using_pem = PR_TRUE;
1728                 }
1729
1730 #ifdef HAVE_NSS_INITCONTEXT
1731                 if ( !ctx->tc_initctx ) {
1732                         ctx->tc_initctx = initctx;
1733                 }
1734 #endif
1735
1736                 NSS_SetDomesticPolicy();
1737
1738                 PK11_SetPasswordFunc( tlsm_pin_prompt );
1739
1740                 /* register cleanup function */
1741                 if ( tlsm_register_nss_shutdown() ) {
1742                         errcode = PORT_GetError();
1743                         Debug( LDAP_DEBUG_ANY,
1744                                    "TLS: could not register NSS shutdown function: %d:%s\n",
1745                                    errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 );
1746                         return -1;
1747                 }
1748
1749                 if  ( ctx->tc_is_server ) {
1750                         LDAP_MUTEX_LOCK( &tlsm_init_mutex );
1751                         /* 0 means use the defaults here */
1752                         SSL_ConfigServerSessionIDCache( 0, 0, 0, NULL );
1753                         LDAP_MUTEX_UNLOCK( &tlsm_init_mutex );
1754                 }
1755
1756 #ifndef HAVE_NSS_INITCONTEXT
1757         }
1758 #endif /* HAVE_NSS_INITCONTEXT */
1759
1760         return 0;
1761 }
1762
1763 static int
1764 tlsm_authenticate( tlsm_ctx *ctx, const char *certname, const char *pininfo )
1765 {
1766         const char *colon = NULL;
1767         char *token_name = NULL;
1768         PK11SlotInfo *slot = NULL;
1769         int rc = -1;
1770
1771         if ( !certname || !*certname ) {
1772                 return 0;
1773         }
1774
1775         if ( ( colon = PL_strchr( certname, ':' ) ) ) {
1776                 token_name = PL_strndup( certname, colon-certname );
1777         }
1778
1779         if ( token_name ) {
1780                 slot = PK11_FindSlotByName( token_name );
1781         } else {
1782                 slot = PK11_GetInternalKeySlot();
1783         }
1784
1785         if ( !slot ) {
1786                 PRErrorCode errcode = PR_GetError();
1787                 Debug( LDAP_DEBUG_ANY,
1788                            "TLS: could not find the slot for security token %s - error %d:%s.\n",
1789                            token_name ? token_name : DEFAULT_TOKEN_NAME, errcode,
1790                            PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1791                 goto done;
1792         }
1793
1794         rc = tlsm_authenticate_to_slot( ctx, slot );
1795
1796 done:
1797         PL_strfree( token_name );
1798         if ( slot ) {
1799                 PK11_FreeSlot( slot );
1800         }
1801
1802         return rc;
1803 }
1804
1805 /*
1806  * Find and verify the certificate.
1807  * Either fd is given, in which case the cert will be taken from it via SSL_PeerCertificate
1808  * or certname is given, and it will be searched for by name
1809  */
1810 static int
1811 tlsm_find_and_verify_cert_key(tlsm_ctx *ctx, PRFileDesc *fd, const char *certname, int isServer, CERTCertificate **pRetCert, SECKEYPrivateKey **pRetKey)
1812 {
1813         CERTCertificate *cert = NULL;
1814         int rc = -1;
1815         void *pin_arg = NULL;
1816         SECKEYPrivateKey *key = NULL;
1817
1818         pin_arg = SSL_RevealPinArg( fd );
1819         if ( certname ) {
1820                 cert = PK11_FindCertFromNickname( certname, pin_arg );
1821                 if ( !cert ) {
1822                         PRErrorCode errcode = PR_GetError();
1823                         Debug( LDAP_DEBUG_ANY,
1824                                    "TLS: error: the certificate %s could not be found in the database - error %d:%s\n",
1825                                    certname, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1826                         return -1;
1827                 }
1828         } else {
1829                 /* we are verifying the peer cert
1830                    we also need to swap the isServer meaning */
1831                 cert = SSL_PeerCertificate( fd );
1832                 if ( !cert ) {
1833                         PRErrorCode errcode = PR_GetError();
1834                         Debug( LDAP_DEBUG_ANY,
1835                                    "TLS: error: could not get the certificate from the peer connection - error %d:%s\n",
1836                                    errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), NULL );
1837                         return -1;
1838                 }
1839                 isServer = !isServer; /* verify the peer's cert instead */
1840         }
1841
1842         if ( ctx->tc_slotname ) {
1843                 PK11SlotInfo *slot = PK11_FindSlotByName( ctx->tc_slotname );
1844                 key = PK11_FindPrivateKeyFromCert( slot, cert, NULL );
1845                 PK11_FreeSlot( slot );
1846         } else {
1847                 key = PK11_FindKeyByAnyCert( cert, pin_arg );
1848         }
1849
1850         if (key) {
1851                 SECCertificateUsage certUsage;
1852                 PRBool checkSig = PR_TRUE;
1853                 SECStatus status;
1854                 /* may not have a CA cert - ok - ignore SEC_ERROR_UNKNOWN_ISSUER */
1855                 int errorToIgnore = SEC_ERROR_UNKNOWN_ISSUER;
1856
1857                 if ( pRetKey ) {
1858                         *pRetKey = key; /* caller will deal with this */
1859                 } else {
1860                         SECKEY_DestroyPrivateKey( key );
1861                 }
1862                 if ( isServer ) {
1863                         certUsage = certificateUsageSSLServer;
1864                 } else {
1865                         certUsage = certificateUsageSSLClient;
1866                 }
1867                 if ( ctx->tc_verify_cert ) {
1868                         checkSig = PR_TRUE;
1869                 } else {
1870                         checkSig = PR_FALSE;
1871                 }
1872                 if ( ctx->tc_warn_only ) {
1873                         errorToIgnore = -1;
1874                 }
1875                 status = tlsm_verify_cert( ctx->tc_certdb, cert, pin_arg,
1876                                                                    checkSig, certUsage, errorToIgnore );
1877                 if ( status == SECSuccess ) {
1878                         rc = 0;
1879                 }
1880         } else {
1881                 PRErrorCode errcode = PR_GetError();
1882                 Debug( LDAP_DEBUG_ANY,
1883                            "TLS: error: could not find the private key for certificate %s - error %d:%s\n",
1884                            certname, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1885         }
1886
1887         if ( pRetCert ) {
1888                 *pRetCert = cert; /* caller will deal with this */
1889         } else {
1890                 CERT_DestroyCertificate( cert );
1891         }
1892
1893     return rc;
1894 }
1895
1896 static int
1897 tlsm_get_client_auth_data( void *arg, PRFileDesc *fd,
1898                                                    CERTDistNames *caNames, CERTCertificate **pRetCert,
1899                                                    SECKEYPrivateKey **pRetKey )
1900 {
1901         tlsm_ctx *ctx = (tlsm_ctx *)arg;
1902         int rc;
1903         PRBool saveval;
1904
1905         /* don't need caNames - this function will call CERT_VerifyCertificateNow
1906            which will verify the cert against the known CAs */
1907         saveval = ctx->tc_warn_only;
1908         ctx->tc_warn_only = PR_TRUE;
1909         rc = tlsm_find_and_verify_cert_key( ctx, fd, ctx->tc_certname, 0, pRetCert, pRetKey );
1910         ctx->tc_warn_only = saveval;
1911         if ( rc ) {
1912                 Debug( LDAP_DEBUG_ANY,
1913                            "TLS: error: unable to perform client certificate authentication for "
1914                            "certificate named %s\n", ctx->tc_certname, 0, 0 );
1915                 if ( pRetKey && *pRetKey ) {
1916                         SECKEY_DestroyPrivateKey( *pRetKey );
1917                         *pRetKey = NULL;
1918                 }
1919                 if ( pRetCert && *pRetCert ) {
1920                         CERT_DestroyCertificate( *pRetCert );
1921                         *pRetCert = NULL;
1922                 }
1923                 return SECFailure;
1924         }
1925
1926         return SECSuccess;
1927 }
1928
1929 /*
1930  * ctx must have a tc_model that is valid
1931  * certname is in the form [<tokenname>:]<certnickname>
1932  * where <tokenname> is the name of the PKCS11 token
1933  * and <certnickname> is the nickname of the cert/key in
1934  * the database
1935 */
1936 static int
1937 tlsm_clientauth_init( tlsm_ctx *ctx )
1938 {
1939         SECStatus status = SECFailure;
1940         int rc;
1941         PRBool saveval;
1942
1943         saveval = ctx->tc_warn_only;
1944         ctx->tc_warn_only = PR_TRUE;
1945         rc = tlsm_find_and_verify_cert_key( ctx, ctx->tc_model, ctx->tc_certname, 0, NULL, NULL );
1946         ctx->tc_warn_only = saveval;
1947         if ( rc ) {
1948                 Debug( LDAP_DEBUG_ANY,
1949                            "TLS: error: unable to set up client certificate authentication for "
1950                            "certificate named %s\n", ctx->tc_certname, 0, 0 );
1951                 return -1;
1952         }
1953
1954         status = SSL_GetClientAuthDataHook( ctx->tc_model,
1955                                                                                 tlsm_get_client_auth_data,
1956                                                                                 (void *)ctx );
1957
1958         return ( status == SECSuccess ? 0 : -1 );
1959 }
1960
1961 /*
1962  * Tear down the TLS subsystem. Should only be called once.
1963  */
1964 static void
1965 tlsm_destroy( void )
1966 {
1967 #ifdef LDAP_R_COMPILE
1968         ldap_pvt_thread_mutex_destroy( &tlsm_init_mutex );
1969         ldap_pvt_thread_mutex_destroy( &tlsm_pem_mutex );
1970 #endif
1971 }
1972
1973 static struct ldaptls *
1974 tlsm_copy_config ( const struct ldaptls *config )
1975 {
1976         struct ldaptls *copy;
1977
1978         assert(config);
1979
1980         copy = LDAP_MALLOC(sizeof(*copy));
1981         if (!copy)
1982                 return NULL;
1983
1984         memset(copy, 0, sizeof(*copy));
1985
1986         if (config->lt_certfile)
1987                 copy->lt_certfile = LDAP_STRDUP(config->lt_certfile);
1988         if (config->lt_keyfile)
1989                 copy->lt_keyfile = LDAP_STRDUP(config->lt_keyfile);
1990         if (config->lt_dhfile)
1991                 copy->lt_dhfile = LDAP_STRDUP(config->lt_dhfile);
1992         if (config->lt_cacertfile)
1993                 copy->lt_cacertfile = LDAP_STRDUP(config->lt_cacertfile);
1994         if (config->lt_cacertdir)
1995                 copy->lt_cacertdir = LDAP_STRDUP(config->lt_cacertdir);
1996         if (config->lt_ciphersuite)
1997                 copy->lt_ciphersuite = LDAP_STRDUP(config->lt_ciphersuite);
1998         if (config->lt_crlfile)
1999                 copy->lt_crlfile = LDAP_STRDUP(config->lt_crlfile);
2000         if (config->lt_randfile)
2001                 copy->lt_randfile = LDAP_STRDUP(config->lt_randfile);
2002
2003         copy->lt_protocol_min = config->lt_protocol_min;
2004
2005         return copy;
2006 }
2007
2008 static void
2009 tlsm_free_config ( struct ldaptls *config )
2010 {
2011         assert(config);
2012
2013         if (config->lt_certfile)
2014                 LDAP_FREE(config->lt_certfile);
2015         if (config->lt_keyfile)
2016                 LDAP_FREE(config->lt_keyfile);
2017         if (config->lt_dhfile)
2018                 LDAP_FREE(config->lt_dhfile);
2019         if (config->lt_cacertfile)
2020                 LDAP_FREE(config->lt_cacertfile);
2021         if (config->lt_cacertdir)
2022                 LDAP_FREE(config->lt_cacertdir);
2023         if (config->lt_ciphersuite)
2024                 LDAP_FREE(config->lt_ciphersuite);
2025         if (config->lt_crlfile)
2026                 LDAP_FREE(config->lt_crlfile);
2027         if (config->lt_randfile)
2028                 LDAP_FREE(config->lt_randfile);
2029
2030         LDAP_FREE(config);
2031 }
2032
2033 static tls_ctx *
2034 tlsm_ctx_new ( struct ldapoptions *lo )
2035 {
2036         tlsm_ctx *ctx;
2037
2038         ctx = LDAP_MALLOC( sizeof (*ctx) );
2039         if ( ctx ) {
2040                 ctx->tc_refcnt = 1;
2041 #ifdef LDAP_R_COMPILE
2042                 ldap_pvt_thread_mutex_init( &ctx->tc_refmutex );
2043 #endif
2044                 ctx->tc_config = NULL; /* populated later by tlsm_ctx_init */
2045                 ctx->tc_certdb = NULL;
2046                 ctx->tc_certname = NULL;
2047                 ctx->tc_pin_file = NULL;
2048                 ctx->tc_model = NULL;
2049                 memset(&ctx->tc_callonce, 0, sizeof(ctx->tc_callonce));
2050                 ctx->tc_require_cert = lo->ldo_tls_require_cert;
2051                 ctx->tc_verify_cert = PR_FALSE;
2052                 ctx->tc_using_pem = PR_FALSE;
2053                 ctx->tc_slotname = NULL;
2054 #ifdef HAVE_NSS_INITCONTEXT
2055                 ctx->tc_initctx = NULL;
2056 #endif /* HAVE_NSS_INITCONTEXT */
2057                 ctx->tc_pem_objs = NULL;
2058                 ctx->tc_n_pem_objs = 0;
2059                 ctx->tc_warn_only = PR_FALSE;
2060         }
2061         return (tls_ctx *)ctx;
2062 }
2063
2064 static void
2065 tlsm_ctx_ref( tls_ctx *ctx )
2066 {
2067         tlsm_ctx *c = (tlsm_ctx *)ctx;
2068         LDAP_MUTEX_LOCK( &c->tc_refmutex );
2069         c->tc_refcnt++;
2070         LDAP_MUTEX_UNLOCK( &c->tc_refmutex );
2071 }
2072
2073 static void
2074 tlsm_ctx_free ( tls_ctx *ctx )
2075 {
2076         tlsm_ctx *c = (tlsm_ctx *)ctx;
2077         int refcount;
2078
2079         if ( !c ) return;
2080
2081         LDAP_MUTEX_LOCK( &c->tc_refmutex );
2082         refcount = --c->tc_refcnt;
2083         LDAP_MUTEX_UNLOCK( &c->tc_refmutex );
2084         if ( refcount )
2085                 return;
2086         if ( c->tc_model )
2087                 PR_Close( c->tc_model );
2088         c->tc_certdb = NULL; /* if not the default, may have to clean up */
2089         PL_strfree( c->tc_certname );
2090         c->tc_certname = NULL;
2091         PL_strfree( c->tc_pin_file );
2092         c->tc_pin_file = NULL;
2093         PL_strfree( c->tc_slotname );           
2094         tlsm_free_pem_objs( c );
2095 #ifdef HAVE_NSS_INITCONTEXT
2096         if ( c->tc_initctx ) {
2097                 LDAP_MUTEX_LOCK( &tlsm_init_mutex );
2098                 if ( NSS_ShutdownContext( c->tc_initctx ) ) {
2099                         PRErrorCode errcode = PR_GetError();
2100                         Debug( LDAP_DEBUG_ANY,
2101                                    "TLS: could not shutdown NSS - error %d:%s.\n",
2102                                    errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 );
2103                 }
2104                 LDAP_MUTEX_UNLOCK( &tlsm_init_mutex );
2105         }
2106         c->tc_initctx = NULL;
2107 #endif /* HAVE_NSS_INITCONTEXT */
2108 #ifdef LDAP_R_COMPILE
2109         ldap_pvt_thread_mutex_destroy( &c->tc_refmutex );
2110 #endif
2111
2112         if ( c->tc_config )
2113                 tlsm_free_config( c->tc_config );
2114
2115         LDAP_FREE( c );
2116 }
2117
2118 /*
2119  * initialize a new TLS context
2120  */
2121 static int
2122 tlsm_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server )
2123 {
2124         tlsm_ctx *ctx = (tlsm_ctx *)lo->ldo_tls_ctx;
2125         ctx->tc_config = tlsm_copy_config(lt);
2126         ctx->tc_is_server = is_server;
2127
2128         return 0;
2129 }
2130
2131 static int
2132 tlsm_deferred_ctx_init( void *arg )
2133 {
2134         tlsm_ctx *ctx = (tlsm_ctx *)arg;
2135         PRBool sslv2 = PR_FALSE;
2136         PRBool sslv3 = PR_TRUE;
2137         PRBool tlsv1 = PR_TRUE;
2138         PRBool request_cert = PR_FALSE;
2139         PRInt32 require_cert = PR_FALSE;
2140         PRFileDesc *fd;
2141         struct ldaptls *lt;
2142
2143         if ( tlsm_deferred_init( ctx ) ) {
2144             Debug( LDAP_DEBUG_ANY,
2145                            "TLS: could not perform TLS system initialization.\n",
2146                            0, 0, 0 );
2147             return -1;
2148         }
2149
2150         ctx->tc_certdb = CERT_GetDefaultCertDB(); /* If there is ever a per-context db, change this */
2151
2152         fd = PR_CreateIOLayerStub( tlsm_layer_id, &tlsm_PR_methods );
2153         if ( fd ) {
2154                 ctx->tc_model = SSL_ImportFD( NULL, fd );
2155         }
2156
2157         if ( !ctx->tc_model ) {
2158                 PRErrorCode err = PR_GetError();
2159                 Debug( LDAP_DEBUG_ANY,
2160                            "TLS: could perform TLS socket I/O layer initialization - error %d:%s.\n",
2161                            err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL );
2162
2163                 if ( fd ) {
2164                         PR_Close( fd );
2165                 }
2166                 return -1;
2167         }
2168
2169         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_SECURITY, PR_TRUE ) ) {
2170                 Debug( LDAP_DEBUG_ANY,
2171                        "TLS: could not set secure mode on.\n",
2172                        0, 0, 0 );
2173                 return -1;
2174         }
2175
2176         lt = ctx->tc_config;
2177
2178         /* default is sslv3 and tlsv1 */
2179         if ( lt->lt_protocol_min ) {
2180                 if ( lt->lt_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_SSL3 ) {
2181                         sslv3 = PR_FALSE;
2182                 } else if ( lt->lt_protocol_min <= LDAP_OPT_X_TLS_PROTOCOL_SSL2 ) {
2183                         sslv2 = PR_TRUE;
2184                         Debug( LDAP_DEBUG_ANY,
2185                                "TLS: warning: minimum TLS protocol level set to "
2186                                "include SSLv2 - SSLv2 is insecure - do not use\n", 0, 0, 0 );
2187                 }
2188         }
2189         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_ENABLE_SSL2, sslv2 ) ) {
2190                 Debug( LDAP_DEBUG_ANY,
2191                        "TLS: could not set SSLv2 mode on.\n",
2192                        0, 0, 0 );
2193                 return -1;
2194         }
2195         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_ENABLE_SSL3, sslv3 ) ) {
2196                 Debug( LDAP_DEBUG_ANY,
2197                        "TLS: could not set SSLv3 mode on.\n",
2198                        0, 0, 0 );
2199                 return -1;
2200         }
2201         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_ENABLE_TLS, tlsv1 ) ) {
2202                 Debug( LDAP_DEBUG_ANY,
2203                        "TLS: could not set TLSv1 mode on.\n",
2204                        0, 0, 0 );
2205                 return -1;
2206         }
2207
2208         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_HANDSHAKE_AS_CLIENT, !ctx->tc_is_server ) ) {
2209                 Debug( LDAP_DEBUG_ANY,
2210                        "TLS: could not set handshake as client.\n",
2211                        0, 0, 0 );
2212                 return -1;
2213         }
2214         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_HANDSHAKE_AS_SERVER, ctx->tc_is_server ) ) {
2215                 Debug( LDAP_DEBUG_ANY,
2216                        "TLS: could not set handshake as server.\n",
2217                        0, 0, 0 );
2218                 return -1;
2219         }
2220
2221         if ( lt->lt_ciphersuite &&
2222              tlsm_parse_ciphers( ctx, lt->lt_ciphersuite )) {
2223                 Debug( LDAP_DEBUG_ANY,
2224                        "TLS: could not set cipher list %s.\n",
2225                        lt->lt_ciphersuite, 0, 0 );
2226                 return -1;
2227         } else if ( tlsm_parse_ciphers( ctx, "DEFAULT" ) ) {
2228                 Debug( LDAP_DEBUG_ANY,
2229                        "TLS: could not set cipher list DEFAULT.\n",
2230                        0, 0, 0 );
2231                 return -1;
2232         }
2233
2234         if ( !ctx->tc_require_cert ) {
2235                 ctx->tc_verify_cert = PR_FALSE;
2236         } else if ( !ctx->tc_is_server ) {
2237                 request_cert = PR_TRUE;
2238                 require_cert = SSL_REQUIRE_NO_ERROR;
2239                 if ( ctx->tc_require_cert == LDAP_OPT_X_TLS_DEMAND ||
2240                      ctx->tc_require_cert == LDAP_OPT_X_TLS_HARD ) {
2241                         require_cert = SSL_REQUIRE_ALWAYS;
2242                 }
2243                 if ( ctx->tc_require_cert != LDAP_OPT_X_TLS_ALLOW )
2244                         ctx->tc_verify_cert = PR_TRUE;
2245         } else { /* server */
2246                 /* server does not request certs by default */
2247                 /* if allow - client may send cert, server will ignore if errors */
2248                 /* if try - client may send cert, server will error if bad cert */
2249                 /* if hard or demand - client must send cert, server will error if bad cert */
2250                 request_cert = PR_TRUE;
2251                 require_cert = SSL_REQUIRE_NO_ERROR;
2252                 if ( ctx->tc_require_cert == LDAP_OPT_X_TLS_DEMAND ||
2253                      ctx->tc_require_cert == LDAP_OPT_X_TLS_HARD ) {
2254                         require_cert = SSL_REQUIRE_ALWAYS;
2255                 }
2256                 if ( ctx->tc_require_cert != LDAP_OPT_X_TLS_ALLOW ) {
2257                         ctx->tc_verify_cert = PR_TRUE;
2258                 } else {
2259                         ctx->tc_warn_only = PR_TRUE;
2260                 }
2261         }
2262
2263         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_REQUEST_CERTIFICATE, request_cert ) ) {
2264                 Debug( LDAP_DEBUG_ANY,
2265                        "TLS: could not set request certificate mode.\n",
2266                        0, 0, 0 );
2267                 return -1;
2268         }
2269                 
2270         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_REQUIRE_CERTIFICATE, require_cert ) ) {
2271                 Debug( LDAP_DEBUG_ANY,
2272                        "TLS: could not set require certificate mode.\n",
2273                        0, 0, 0 );
2274                 return -1;
2275         }
2276
2277         /* set up our cert and key, if any */
2278         if ( lt->lt_certfile ) {
2279                 /* if using the PEM module, load the PEM file specified by lt_certfile */
2280                 /* otherwise, assume this is the name of a cert already in the db */
2281                 if ( ctx->tc_using_pem ) {
2282                         /* this sets ctx->tc_certname to the correct value */
2283                         int rc = tlsm_add_cert_from_file( ctx, lt->lt_certfile, PR_FALSE, PR_TRUE );
2284                         if ( rc ) {
2285                                 return rc;
2286                         }
2287                 } else {
2288                         PL_strfree( ctx->tc_certname );
2289                         ctx->tc_certname = PL_strdup( lt->lt_certfile );
2290                 }
2291         }
2292
2293         if ( lt->lt_keyfile ) {
2294                 /* if using the PEM module, load the PEM file specified by lt_keyfile */
2295                 /* otherwise, assume this is the pininfo for the key */
2296                 if ( ctx->tc_using_pem ) {
2297                         /* this sets ctx->tc_certname to the correct value */
2298                         int rc = tlsm_add_key_from_file( ctx, lt->lt_keyfile );
2299                         if ( rc ) {
2300                                 return rc;
2301                         }
2302                 } else {
2303                         PL_strfree( ctx->tc_pin_file );
2304                         ctx->tc_pin_file = PL_strdup( lt->lt_keyfile );
2305                 }
2306         }
2307
2308         /* Set up callbacks for use by clients */
2309         if ( !ctx->tc_is_server ) {
2310                 if ( SSL_OptionSet( ctx->tc_model, SSL_NO_CACHE, PR_TRUE ) != SECSuccess ) {
2311                         PRErrorCode err = PR_GetError();
2312                         Debug( LDAP_DEBUG_ANY, 
2313                                "TLS: error: could not set nocache option for moznss - error %d:%s\n",
2314                                err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL );
2315                         return -1;
2316                 }
2317
2318                 if ( SSL_BadCertHook( ctx->tc_model, tlsm_bad_cert_handler, ctx ) != SECSuccess ) {
2319                         PRErrorCode err = PR_GetError();
2320                         Debug( LDAP_DEBUG_ANY, 
2321                                "TLS: error: could not set bad cert handler for moznss - error %d:%s\n",
2322                                err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL );
2323                         return -1;
2324                 }
2325
2326                 /* 
2327                    since a cert has been specified, assume the client wants to do cert auth
2328                 */
2329                 if ( ctx->tc_certname ) {
2330                         if ( tlsm_authenticate( ctx, ctx->tc_certname, ctx->tc_pin_file ) ) {
2331                                 Debug( LDAP_DEBUG_ANY, 
2332                                        "TLS: error: unable to authenticate to the security device for certificate %s\n",
2333                                        ctx->tc_certname, 0, 0 );
2334                                 return -1;
2335                         }
2336                         if ( tlsm_clientauth_init( ctx ) ) {
2337                                 Debug( LDAP_DEBUG_ANY, 
2338                                        "TLS: error: unable to set up client certificate authentication using %s\n",
2339                                        ctx->tc_certname, 0, 0 );
2340                                 return -1;
2341                         }
2342                 }
2343         } else { /* set up secure server */
2344                 SSLKEAType certKEA;
2345                 CERTCertificate *serverCert = NULL;
2346                 SECKEYPrivateKey *serverKey = NULL;
2347                 SECStatus status;
2348
2349                 /* must have a certificate for the server to use */
2350                 if ( !ctx->tc_certname ) {
2351                         Debug( LDAP_DEBUG_ANY, 
2352                                "TLS: error: no server certificate: must specify a certificate for the server to use\n",
2353                                0, 0, 0 );
2354                         return -1;
2355                 }
2356
2357                 /* authenticate to the server's token - this will do nothing
2358                    if the key/cert db is not password protected */
2359                 if ( tlsm_authenticate( ctx, ctx->tc_certname, ctx->tc_pin_file ) ) {
2360                         Debug( LDAP_DEBUG_ANY, 
2361                                "TLS: error: unable to authenticate to the security device for certificate %s\n",
2362                                ctx->tc_certname, 0, 0 );
2363                         return -1;
2364                 }
2365
2366                 /* get the server's key and cert */
2367                 if ( tlsm_find_and_verify_cert_key( ctx, ctx->tc_model, ctx->tc_certname, ctx->tc_is_server,
2368                                                     &serverCert, &serverKey ) ) {
2369                         Debug( LDAP_DEBUG_ANY, 
2370                                "TLS: error: unable to find and verify server's cert and key for certificate %s\n",
2371                                ctx->tc_certname, 0, 0 );
2372                         CERT_DestroyCertificate( serverCert );
2373                         SECKEY_DestroyPrivateKey( serverKey );
2374                         return -1;
2375                 }
2376
2377                 certKEA = NSS_FindCertKEAType( serverCert );
2378                 /* configure the socket to be a secure server socket */
2379                 status = SSL_ConfigSecureServer( ctx->tc_model, serverCert, serverKey, certKEA );
2380                 /* SSL_ConfigSecureServer copies these */
2381                 CERT_DestroyCertificate( serverCert );
2382                 SECKEY_DestroyPrivateKey( serverKey );
2383
2384                 if ( SECSuccess != status ) {
2385                         PRErrorCode err = PR_GetError();
2386                         Debug( LDAP_DEBUG_ANY, 
2387                                "TLS: error: unable to configure secure server using certificate %s - error %d:%s\n",
2388                                ctx->tc_certname, err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ) );
2389                         return -1;
2390                 }
2391         }
2392
2393         /* Callback for authenticating certificate */
2394         if ( SSL_AuthCertificateHook( ctx->tc_model, tlsm_auth_cert_handler,
2395                                   ctx ) != SECSuccess ) {
2396                 PRErrorCode err = PR_GetError();
2397                 Debug( LDAP_DEBUG_ANY, 
2398                        "TLS: error: could not set auth cert handler for moznss - error %d:%s\n",
2399                        err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL );
2400                 return -1;
2401         }
2402
2403         if ( SSL_HandshakeCallback( ctx->tc_model, tlsm_handshake_complete_cb, ctx ) ) {
2404                 PRErrorCode err = PR_GetError();
2405                 Debug( LDAP_DEBUG_ANY, 
2406                        "TLS: error: could not set handshake callback for moznss - error %d:%s\n",
2407                        err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL );
2408                 return -1;
2409         }
2410
2411         tlsm_free_config( ctx->tc_config );
2412         ctx->tc_config = NULL;
2413
2414         return 0;
2415 }
2416
2417 struct tls_data {
2418         tlsm_session            *session;
2419         Sockbuf_IO_Desc         *sbiod;
2420         /* there seems to be no portable way to determine if the
2421            sockbuf sd has been set to nonblocking mode - the
2422            call to ber_pvt_socket_set_nonblock() takes place
2423            before the tls socket is set up, so we cannot
2424            intercept that call either.
2425            On systems where fcntl is available, we can just
2426            F_GETFL and test for O_NONBLOCK.  On other systems,
2427            we will just see if the IO op returns EAGAIN or EWOULDBLOCK,
2428            and just set this flag */
2429         PRBool              nonblock;
2430         /*
2431          * NSS tries hard to be backwards compatible with SSLv2 clients, or
2432          * clients that send an SSLv2 client hello.  This message is not
2433          * tagged in any way, so NSS has no way to know if the incoming
2434          * message is a valid SSLv2 client hello or just some bogus data
2435          * (or cleartext LDAP).  We store the first byte read from the
2436          * client here.  The most common case will be a client sending
2437          * LDAP data instead of SSL encrypted LDAP data.  This can happen,
2438          * for example, if using ldapsearch -Z - if the starttls fails,
2439          * the client will fallback to plain cleartext LDAP.  So if we
2440          * see that the firstbyte is a valid LDAP tag, we can be
2441          * pretty sure this is happening.
2442          */
2443         ber_tag_t           firsttag;
2444         /*
2445          * NSS doesn't return SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE, etc.
2446          * when it is blocked, so we have to set a flag in the wrapped send
2447          * and recv calls that tells us what operation NSS was last blocked
2448          * on
2449          */
2450 #define TLSM_READ  1
2451 #define TLSM_WRITE 2
2452         int io_flag;
2453 };
2454
2455 static struct tls_data *
2456 tlsm_get_pvt_tls_data( PRFileDesc *fd )
2457 {
2458         struct tls_data         *p;
2459         PRFileDesc *myfd;
2460
2461         if ( !fd ) {
2462                 return NULL;
2463         }
2464
2465         myfd = PR_GetIdentitiesLayer( fd, tlsm_layer_id );
2466
2467         if ( !myfd ) {
2468                 return NULL;
2469         }
2470
2471         p = (struct tls_data *)myfd->secret;
2472
2473         return p;
2474 }
2475
2476 static int
2477 tlsm_is_non_ssl_message( PRFileDesc *fd, ber_tag_t *thebyte )
2478 {
2479         struct tls_data         *p;
2480
2481         if ( thebyte ) {
2482                 *thebyte = LBER_DEFAULT;
2483         }
2484
2485         p = tlsm_get_pvt_tls_data( fd );
2486         if ( p == NULL || p->sbiod == NULL ) {
2487                 return 0;
2488         }
2489
2490         if ( p->firsttag == LBER_SEQUENCE ) {
2491                 if ( thebyte ) {
2492                         *thebyte = p->firsttag;
2493                 }
2494                 return 1;
2495         }
2496
2497         return 0;
2498 }
2499
2500 static tls_session *
2501 tlsm_session_new ( tls_ctx * ctx, int is_server )
2502 {
2503         tlsm_ctx *c = (tlsm_ctx *)ctx;
2504         tlsm_session *session;
2505         PRFileDesc *fd;
2506         PRStatus status;
2507         int rc;
2508
2509         c->tc_is_server = is_server;
2510         status = PR_CallOnceWithArg( &c->tc_callonce, tlsm_deferred_ctx_init, c );
2511         if ( PR_SUCCESS != status ) {
2512                 PRErrorCode err = PR_GetError();
2513                 Debug( LDAP_DEBUG_ANY, 
2514                        "TLS: error: could not initialize moznss security context - error %d:%s\n",
2515                        err, PR_ErrorToString(err, PR_LANGUAGE_I_DEFAULT), NULL );
2516                 return NULL;
2517         }
2518
2519         fd = PR_CreateIOLayerStub( tlsm_layer_id, &tlsm_PR_methods );
2520         if ( !fd ) {
2521                 return NULL;
2522         }
2523
2524         session = SSL_ImportFD( c->tc_model, fd );
2525         if ( !session ) {
2526                 PR_DELETE( fd );
2527                 return NULL;
2528         }
2529
2530         rc = SSL_ResetHandshake( session, is_server );
2531         if ( rc ) {
2532                 PRErrorCode err = PR_GetError();
2533                 Debug( LDAP_DEBUG_TRACE, 
2534                            "TLS: error: new session - reset handshake failure %d - error %d:%s\n",
2535                            rc, err,
2536                            err ? PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ) : "unknown" );
2537                 PR_DELETE( fd );
2538                 PR_Close( session );
2539                 session = NULL;
2540         }
2541
2542         return (tls_session *)session;
2543
2544
2545 static int
2546 tlsm_session_accept_or_connect( tls_session *session, int is_accept )
2547 {
2548         tlsm_session *s = (tlsm_session *)session;
2549         int rc;
2550         const char *op = is_accept ? "accept" : "connect";
2551
2552         if ( pem_module ) {
2553                 LDAP_MUTEX_LOCK( &tlsm_pem_mutex );
2554         }
2555         rc = SSL_ForceHandshake( s );
2556         if ( pem_module ) {
2557                 LDAP_MUTEX_UNLOCK( &tlsm_pem_mutex );
2558         }
2559         if ( rc ) {
2560                 PRErrorCode err = PR_GetError();
2561                 rc = -1;
2562                 if ( err == PR_WOULD_BLOCK_ERROR ) {
2563                         ber_tag_t thetag = LBER_DEFAULT;
2564                         /* see if we are blocked because of a bogus packet */
2565                         if ( tlsm_is_non_ssl_message( s, &thetag ) ) { /* see if we received a non-SSL message */
2566                                 Debug( LDAP_DEBUG_ANY, 
2567                                            "TLS: error: %s - error - received non-SSL message [0x%x]\n",
2568                                            op, (unsigned int)thetag, 0 );
2569                                 /* reset error to something more descriptive */
2570                                 PR_SetError( SSL_ERROR_RX_MALFORMED_HELLO_REQUEST, EPROTO );
2571                         }
2572                 } else {
2573                         Debug( LDAP_DEBUG_ANY, 
2574                                    "TLS: error: %s - force handshake failure: errno %d - moznss error %d\n",
2575                                    op, errno, err );
2576                 }
2577         }
2578
2579         return rc;
2580 }
2581 static int
2582 tlsm_session_accept( tls_session *session )
2583 {
2584         return tlsm_session_accept_or_connect( session, 1 );
2585 }
2586
2587 static int
2588 tlsm_session_connect( LDAP *ld, tls_session *session )
2589 {
2590         return tlsm_session_accept_or_connect( session, 0 );
2591 }
2592
2593 static int
2594 tlsm_session_upflags( Sockbuf *sb, tls_session *session, int rc )
2595 {
2596         int prerror = PR_GetError();
2597
2598         if ( ( prerror == PR_PENDING_INTERRUPT_ERROR ) || ( prerror == PR_WOULD_BLOCK_ERROR ) ) {
2599                 tlsm_session *s = (tlsm_session *)session;
2600                 struct tls_data *p = tlsm_get_pvt_tls_data( s );
2601
2602                 if ( p && ( p->io_flag == TLSM_READ ) ) {
2603                         sb->sb_trans_needs_read = 1;
2604                         return 1;
2605                 } else if ( p && ( p->io_flag == TLSM_WRITE ) ) {
2606                         sb->sb_trans_needs_write = 1;
2607                         return 1;
2608                 }
2609         }
2610
2611         return 0;
2612 }
2613
2614 static char *
2615 tlsm_session_errmsg( tls_session *sess, int rc, char *buf, size_t len )
2616 {
2617         int i;
2618         int prerror = PR_GetError();
2619
2620         i = PR_GetErrorTextLength();
2621         if ( i > len ) {
2622                 char *msg = LDAP_MALLOC( i+1 );
2623                 PR_GetErrorText( msg );
2624                 memcpy( buf, msg, len );
2625                 LDAP_FREE( msg );
2626         } else if ( i ) {
2627                 PR_GetErrorText( buf );
2628         } else if ( prerror ) {
2629                 i = PR_snprintf( buf, len, "TLS error %d:%s",
2630                                                  prerror, PR_ErrorToString( prerror, PR_LANGUAGE_I_DEFAULT ) );
2631         }
2632
2633         return ( i > 0 ) ? buf : NULL;
2634 }
2635
2636 static int
2637 tlsm_session_my_dn( tls_session *session, struct berval *der_dn )
2638 {
2639         tlsm_session *s = (tlsm_session *)session;
2640         CERTCertificate *cert;
2641
2642         cert = SSL_LocalCertificate( s );
2643         if (!cert) return LDAP_INVALID_CREDENTIALS;
2644
2645         der_dn->bv_val = (char *)cert->derSubject.data;
2646         der_dn->bv_len = cert->derSubject.len;
2647         CERT_DestroyCertificate( cert );
2648         return 0;
2649 }
2650
2651 static int
2652 tlsm_session_peer_dn( tls_session *session, struct berval *der_dn )
2653 {
2654         tlsm_session *s = (tlsm_session *)session;
2655         CERTCertificate *cert;
2656
2657         cert = SSL_PeerCertificate( s );
2658         if (!cert) return LDAP_INVALID_CREDENTIALS;
2659         
2660         der_dn->bv_val = (char *)cert->derSubject.data;
2661         der_dn->bv_len = cert->derSubject.len;
2662         CERT_DestroyCertificate( cert );
2663         return 0;
2664 }
2665
2666 /* what kind of hostname were we given? */
2667 #define IS_DNS  0
2668 #define IS_IP4  1
2669 #define IS_IP6  2
2670
2671 static int
2672 tlsm_session_chkhost( LDAP *ld, tls_session *session, const char *name_in )
2673 {
2674         tlsm_session *s = (tlsm_session *)session;
2675         CERTCertificate *cert;
2676         const char *name, *domain = NULL, *ptr;
2677         int ret, ntype = IS_DNS, nlen, dlen;
2678 #ifdef LDAP_PF_INET6
2679         struct in6_addr addr;
2680 #else
2681         struct in_addr addr;
2682 #endif
2683         SECItem altname;
2684         SECStatus rv;
2685
2686         if( ldap_int_hostname &&
2687                 ( !name_in || !strcasecmp( name_in, "localhost" ) ) )
2688         {
2689                 name = ldap_int_hostname;
2690         } else {
2691                 name = name_in;
2692         }
2693         nlen = strlen( name );
2694
2695         cert = SSL_PeerCertificate( s );
2696         if (!cert) {
2697                 Debug( LDAP_DEBUG_ANY,
2698                         "TLS: unable to get peer certificate.\n",
2699                         0, 0, 0 );
2700                 /* if this was a fatal condition, things would have
2701                  * aborted long before now.
2702                  */
2703                 return LDAP_SUCCESS;
2704         }
2705
2706 #ifdef LDAP_PF_INET6
2707         if (inet_pton(AF_INET6, name, &addr)) {
2708                 ntype = IS_IP6;
2709         } else 
2710 #endif
2711         if ((ptr = strrchr(name, '.')) && isdigit((unsigned char)ptr[1])) {
2712                 if (inet_aton(name, (struct in_addr *)&addr)) ntype = IS_IP4;
2713         }
2714         if (ntype == IS_DNS ) {
2715                 domain = strchr( name, '.' );
2716                 if ( domain )
2717                         dlen = nlen - ( domain - name );
2718         }
2719
2720         ret = LDAP_LOCAL_ERROR;
2721
2722         rv = CERT_FindCertExtension( cert, SEC_OID_X509_SUBJECT_ALT_NAME,
2723                 &altname );
2724         if ( rv == SECSuccess && altname.data ) {
2725                 PRArenaPool *arena;
2726                 CERTGeneralName *names, *cur;
2727
2728                 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2729                 if ( !arena ) {
2730                         ret = LDAP_NO_MEMORY;
2731                         goto fail;
2732                 }
2733
2734                 names = cur = CERT_DecodeAltNameExtension(arena, &altname);
2735                 if ( !cur )
2736                         goto altfail;
2737
2738                 do {
2739                         char *host;
2740                         int hlen;
2741
2742                         /* ignore empty */
2743                         if ( !cur->name.other.len ) continue;
2744
2745                         host = (char *)cur->name.other.data;
2746                         hlen = cur->name.other.len;
2747
2748                         if ( cur->type == certDNSName ) {
2749                                 if ( ntype != IS_DNS )  continue;
2750
2751                                 /* is this an exact match? */
2752                                 if ( nlen == hlen && !strncasecmp( name, host, nlen )) {
2753                                         ret = LDAP_SUCCESS;
2754                                         break;
2755                                 }
2756
2757                                 /* is this a wildcard match? */
2758                                 if ( domain && host[0] == '*' && host[1] == '.' &&
2759                                         dlen == hlen-1 && !strncasecmp( domain, host+1, dlen )) {
2760                                         ret = LDAP_SUCCESS;
2761                                         break;
2762                                 }
2763                         } else if ( cur->type == certIPAddress ) {
2764                                 if ( ntype == IS_DNS )  continue;
2765                                 
2766 #ifdef LDAP_PF_INET6
2767                                 if (ntype == IS_IP6 && hlen != sizeof(struct in6_addr)) {
2768                                         continue;
2769                                 } else
2770 #endif
2771                                 if (ntype == IS_IP4 && hlen != sizeof(struct in_addr)) {
2772                                         continue;
2773                                 }
2774                                 if (!memcmp(host, &addr, hlen)) {
2775                                         ret = LDAP_SUCCESS;
2776                                         break;
2777                                 }
2778                         }
2779                 } while (( cur = CERT_GetNextGeneralName( cur )) != names );
2780 altfail:
2781                 PORT_FreeArena( arena, PR_FALSE );
2782                 SECITEM_FreeItem( &altname, PR_FALSE );
2783         }
2784         /* no altnames matched, try the CN */
2785         if ( ret != LDAP_SUCCESS ) {
2786                 /* find the last CN */
2787                 CERTRDN *rdn, **rdns;
2788                 CERTAVA *lastava = NULL;
2789                 char buf[2048];
2790
2791                 buf[0] = '\0';
2792                 rdns = cert->subject.rdns;
2793                 while ( rdns && ( rdn = *rdns++ )) {
2794                         CERTAVA *ava, **avas = rdn->avas;
2795                         while ( avas && ( ava = *avas++ )) {
2796                                 if ( CERT_GetAVATag( ava ) == SEC_OID_AVA_COMMON_NAME )
2797                                         lastava = ava;
2798                         }
2799                 }
2800                 if ( lastava ) {
2801                         SECItem *av = CERT_DecodeAVAValue( &lastava->value );
2802                         if ( av ) {
2803                                 if ( av->len == nlen && !strncasecmp( name, (char *)av->data, nlen )) {
2804                                         ret = LDAP_SUCCESS;
2805                                 } else if ( av->data[0] == '*' && av->data[1] == '.' &&
2806                                         domain && dlen == av->len - 1 && !strncasecmp( domain,
2807                                                 (char *)(av->data+1), dlen )) {
2808                                         ret = LDAP_SUCCESS;
2809                                 } else {
2810                                         int len = av->len;
2811                                         if ( len >= sizeof(buf) )
2812                                                 len = sizeof(buf)-1;
2813                                         memcpy( buf, av->data, len );
2814                                         buf[len] = '\0';
2815                                 }
2816                                 SECITEM_FreeItem( av, PR_TRUE );
2817                         }
2818                 }
2819                 if ( ret != LDAP_SUCCESS ) {
2820                         Debug( LDAP_DEBUG_ANY, "TLS: hostname (%s) does not match "
2821                                 "common name in certificate (%s).\n", 
2822                                 name, buf, 0 );
2823                         ret = LDAP_CONNECT_ERROR;
2824                         if ( ld->ld_error ) {
2825                                 LDAP_FREE( ld->ld_error );
2826                         }
2827                         ld->ld_error = LDAP_STRDUP(
2828                                 _("TLS: hostname does not match CN in peer certificate"));
2829                 }
2830         }
2831
2832 fail:
2833         CERT_DestroyCertificate( cert );
2834         return ret;
2835 }
2836
2837 static int
2838 tlsm_session_strength( tls_session *session )
2839 {
2840         tlsm_session *s = (tlsm_session *)session;
2841         int rc, keySize;
2842
2843         rc = SSL_SecurityStatus( s, NULL, NULL, NULL, &keySize,
2844                 NULL, NULL );
2845         return rc ? 0 : keySize;
2846 }
2847
2848 /*
2849  * TLS support for LBER Sockbufs
2850  */
2851
2852 static PRStatus PR_CALLBACK
2853 tlsm_PR_Close(PRFileDesc *fd)
2854 {
2855         int rc = PR_SUCCESS;
2856
2857         /* we don't need to actually close anything here, just
2858            pop our io layer off the stack */
2859         fd->secret = NULL; /* must have been freed before calling PR_Close */
2860         if ( fd->lower ) {
2861                 fd = PR_PopIOLayer( fd, tlsm_layer_id );
2862                 /* if we are not the last layer, pass the close along */
2863                 if ( fd ) {
2864                         if ( fd->dtor ) {
2865                                 fd->dtor( fd );
2866                         }
2867                         rc = fd->methods->close( fd );
2868                 }
2869         } else {
2870                 /* we are the last layer - just call our dtor */
2871                 fd->dtor(fd);
2872         }
2873
2874         return rc;
2875 }
2876
2877 static PRStatus PR_CALLBACK
2878 tlsm_PR_Shutdown(PRFileDesc *fd, PRShutdownHow how)
2879 {
2880         int rc = PR_SUCCESS;
2881
2882         if ( fd->lower ) {
2883                 rc = PR_Shutdown( fd->lower, how );
2884         }
2885
2886         return rc;
2887 }
2888
2889 static int PR_CALLBACK
2890 tlsm_PR_Recv(PRFileDesc *fd, void *buf, PRInt32 len, PRIntn flags,
2891          PRIntervalTime timeout)
2892 {
2893         struct tls_data         *p;
2894         int rc;
2895
2896         if ( buf == NULL || len <= 0 ) return 0;
2897
2898         p = tlsm_get_pvt_tls_data( fd );
2899
2900         if ( p == NULL || p->sbiod == NULL ) {
2901                 return 0;
2902         }
2903
2904         rc = LBER_SBIOD_READ_NEXT( p->sbiod, buf, len );
2905         if (rc <= 0) {
2906                 tlsm_map_error( errno );
2907                 if ( errno == EAGAIN || errno == EWOULDBLOCK ) {
2908                         p->nonblock = PR_TRUE; /* fd is using non-blocking io */
2909                 } else if ( errno ) { /* real error */
2910                         Debug( LDAP_DEBUG_TRACE, 
2911                                "TLS: error: tlsm_PR_Recv returned %d - error %d:%s\n",
2912                                rc, errno, STRERROR(errno) );
2913                 }
2914         } else if ( ( rc > 0 ) && ( len > 0 ) && ( p->firsttag == LBER_DEFAULT ) ) {
2915                 p->firsttag = (ber_tag_t)*((char *)buf);
2916         }
2917         p->io_flag = TLSM_READ;
2918
2919         return rc;
2920 }
2921
2922 static int PR_CALLBACK
2923 tlsm_PR_Send(PRFileDesc *fd, const void *buf, PRInt32 len, PRIntn flags,
2924          PRIntervalTime timeout)
2925 {
2926         struct tls_data         *p;
2927         int rc;
2928
2929         if ( buf == NULL || len <= 0 ) return 0;
2930
2931         p = tlsm_get_pvt_tls_data( fd );
2932
2933         if ( p == NULL || p->sbiod == NULL ) {
2934                 return 0;
2935         }
2936
2937         rc = LBER_SBIOD_WRITE_NEXT( p->sbiod, (char *)buf, len );
2938         if (rc <= 0) {
2939                 tlsm_map_error( errno );
2940                 if ( errno == EAGAIN || errno == EWOULDBLOCK ) {
2941                         p->nonblock = PR_TRUE;
2942                 } else if ( errno ) { /* real error */
2943                         Debug( LDAP_DEBUG_TRACE, 
2944                                "TLS: error: tlsm_PR_Send returned %d - error %d:%s\n",
2945                                rc, errno, STRERROR(errno) );
2946                 }
2947         }
2948         p->io_flag = TLSM_WRITE;
2949
2950         return rc;
2951 }
2952
2953 static int PR_CALLBACK
2954 tlsm_PR_Read(PRFileDesc *fd, void *buf, PRInt32 len)
2955 {
2956         return tlsm_PR_Recv( fd, buf, len, 0, PR_INTERVAL_NO_TIMEOUT );
2957 }
2958
2959 static int PR_CALLBACK
2960 tlsm_PR_Write(PRFileDesc *fd, const void *buf, PRInt32 len)
2961 {
2962         return tlsm_PR_Send( fd, buf, len, 0, PR_INTERVAL_NO_TIMEOUT );
2963 }
2964
2965 static PRStatus PR_CALLBACK
2966 tlsm_PR_GetPeerName(PRFileDesc *fd, PRNetAddr *addr)
2967 {
2968         struct tls_data         *p;
2969         ber_socklen_t len;
2970
2971         p = tlsm_get_pvt_tls_data( fd );
2972
2973         if ( p == NULL || p->sbiod == NULL ) {
2974                 return PR_FAILURE;
2975         }
2976         len = sizeof(PRNetAddr);
2977         return getpeername( p->sbiod->sbiod_sb->sb_fd, (struct sockaddr *)addr, &len );
2978 }
2979
2980 static PRStatus PR_CALLBACK
2981 tlsm_PR_GetSocketOption(PRFileDesc *fd, PRSocketOptionData *data)
2982 {
2983         struct tls_data         *p;
2984         p = tlsm_get_pvt_tls_data( fd );
2985
2986         if ( p == NULL || data == NULL ) {
2987                 return PR_FAILURE;
2988         }
2989
2990         /* only the nonblocking option is supported at this time
2991            MozNSS SSL code needs it */
2992         if ( data->option != PR_SockOpt_Nonblocking ) {
2993                 PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
2994                 return PR_FAILURE;
2995         }
2996 #ifdef HAVE_FCNTL
2997         int flags = fcntl( p->sbiod->sbiod_sb->sb_fd, F_GETFL );
2998         data->value.non_blocking = (flags & O_NONBLOCK) ? PR_TRUE : PR_FALSE;           
2999 #else /* punt :P */
3000         data->value.non_blocking = p->nonblock;
3001 #endif
3002         return PR_SUCCESS;
3003 }
3004
3005 static PRStatus PR_CALLBACK
3006 tlsm_PR_prs_unimp()
3007 {
3008     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
3009     return PR_FAILURE;
3010 }
3011
3012 static PRFileDesc * PR_CALLBACK
3013 tlsm_PR_pfd_unimp()
3014 {
3015     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
3016     return NULL;
3017 }
3018
3019 static PRInt16 PR_CALLBACK
3020 tlsm_PR_i16_unimp()
3021 {
3022     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
3023     return SECFailure;
3024 }
3025
3026 static PRInt32 PR_CALLBACK
3027 tlsm_PR_i32_unimp()
3028 {
3029     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
3030     return SECFailure;
3031 }
3032
3033 static PRInt64 PR_CALLBACK
3034 tlsm_PR_i64_unimp()
3035 {
3036     PRInt64 res;
3037
3038     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
3039     LL_I2L(res, -1L);
3040     return res;
3041 }
3042
3043 static const PRIOMethods tlsm_PR_methods = {
3044     PR_DESC_LAYERED,
3045     tlsm_PR_Close,                      /* close        */
3046     tlsm_PR_Read,                       /* read         */
3047     tlsm_PR_Write,                      /* write        */
3048     tlsm_PR_i32_unimp,          /* available    */
3049     tlsm_PR_i64_unimp,          /* available64  */
3050     tlsm_PR_prs_unimp,          /* fsync        */
3051     tlsm_PR_i32_unimp,          /* seek         */
3052     tlsm_PR_i64_unimp,          /* seek64       */
3053     tlsm_PR_prs_unimp,          /* fileInfo     */
3054     tlsm_PR_prs_unimp,          /* fileInfo64   */
3055     tlsm_PR_i32_unimp,          /* writev       */
3056     tlsm_PR_prs_unimp,          /* connect      */
3057     tlsm_PR_pfd_unimp,          /* accept       */
3058     tlsm_PR_prs_unimp,          /* bind         */
3059     tlsm_PR_prs_unimp,          /* listen       */
3060     (PRShutdownFN)tlsm_PR_Shutdown,                     /* shutdown     */
3061     tlsm_PR_Recv,                       /* recv         */
3062     tlsm_PR_Send,                       /* send         */
3063     tlsm_PR_i32_unimp,          /* recvfrom     */
3064     tlsm_PR_i32_unimp,          /* sendto       */
3065     (PRPollFN)tlsm_PR_i16_unimp,        /* poll         */
3066     tlsm_PR_i32_unimp,          /* acceptread   */
3067     tlsm_PR_i32_unimp,          /* transmitfile */
3068     tlsm_PR_prs_unimp,          /* getsockname  */
3069     tlsm_PR_GetPeerName,        /* getpeername  */
3070     tlsm_PR_i32_unimp,          /* getsockopt   OBSOLETE */
3071     tlsm_PR_i32_unimp,          /* setsockopt   OBSOLETE */
3072     tlsm_PR_GetSocketOption,            /* getsocketoption   */
3073     tlsm_PR_i32_unimp,          /* setsocketoption   */
3074     tlsm_PR_i32_unimp,          /* Send a (partial) file with header/trailer*/
3075     (PRConnectcontinueFN)tlsm_PR_prs_unimp,             /* connectcontinue */
3076     tlsm_PR_i32_unimp,          /* reserved for future use */
3077     tlsm_PR_i32_unimp,          /* reserved for future use */
3078     tlsm_PR_i32_unimp,          /* reserved for future use */
3079     tlsm_PR_i32_unimp           /* reserved for future use */
3080 };
3081
3082 /*
3083  * Initialize TLS subsystem. Should be called only once.
3084  * See tlsm_deferred_init for the bulk of the init process
3085  */
3086 static int
3087 tlsm_init( void )
3088 {
3089         char *nofork = PR_GetEnv( "NSS_STRICT_NOFORK" );
3090
3091         PR_Init(0, 0, 0);
3092
3093         tlsm_layer_id = PR_GetUniqueIdentity( "OpenLDAP" );
3094
3095         /*
3096          * There are some applications that acquire a crypto context in the parent process
3097          * and expect that crypto context to work after a fork().  This does not work
3098          * with NSS using strict PKCS11 compliance mode.  We set this environment
3099          * variable here to tell the software encryption module/token to allow crypto
3100          * contexts to persist across a fork().  However, if you are using some other
3101          * module or encryption device that supports and expects full PKCS11 semantics,
3102          * the only recourse is to rewrite the application with atfork() handlers to save
3103          * the crypto context in the parent and restore (and SECMOD_RestartModules) the
3104          * context in the child.
3105          */
3106         if ( !nofork ) {
3107                 /* will leak one time */
3108                 char *noforkenvvar = PL_strdup( "NSS_STRICT_NOFORK=DISABLED" );
3109                 PR_SetEnv( noforkenvvar );
3110         }
3111
3112         return 0;
3113 }
3114
3115 static int
3116 tlsm_sb_setup( Sockbuf_IO_Desc *sbiod, void *arg )
3117 {
3118         struct tls_data         *p;
3119         tlsm_session    *session = arg;
3120         PRFileDesc *fd;
3121
3122         assert( sbiod != NULL );
3123
3124         p = LBER_MALLOC( sizeof( *p ) );
3125         if ( p == NULL ) {
3126                 return -1;
3127         }
3128
3129         fd = PR_GetIdentitiesLayer( session, tlsm_layer_id );
3130         if ( !fd ) {
3131                 LBER_FREE( p );
3132                 return -1;
3133         }
3134
3135         fd->secret = (PRFilePrivate *)p;
3136         p->session = session;
3137         p->sbiod = sbiod;
3138         p->firsttag = LBER_DEFAULT;
3139         sbiod->sbiod_pvt = p;
3140         return 0;
3141 }
3142
3143 static int
3144 tlsm_sb_remove( Sockbuf_IO_Desc *sbiod )
3145 {
3146         struct tls_data         *p;
3147         
3148         assert( sbiod != NULL );
3149         assert( sbiod->sbiod_pvt != NULL );
3150
3151         p = (struct tls_data *)sbiod->sbiod_pvt;
3152         PR_Close( p->session );
3153         LBER_FREE( sbiod->sbiod_pvt );
3154         sbiod->sbiod_pvt = NULL;
3155         return 0;
3156 }
3157
3158 static int
3159 tlsm_sb_close( Sockbuf_IO_Desc *sbiod )
3160 {
3161         struct tls_data         *p;
3162         
3163         assert( sbiod != NULL );
3164         assert( sbiod->sbiod_pvt != NULL );
3165
3166         p = (struct tls_data *)sbiod->sbiod_pvt;
3167         PR_Shutdown( p->session, PR_SHUTDOWN_BOTH );
3168         return 0;
3169 }
3170
3171 static int
3172 tlsm_sb_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
3173 {
3174         struct tls_data         *p;
3175         
3176         assert( sbiod != NULL );
3177         assert( sbiod->sbiod_pvt != NULL );
3178
3179         p = (struct tls_data *)sbiod->sbiod_pvt;
3180         
3181         if ( opt == LBER_SB_OPT_GET_SSL ) {
3182                 *((tlsm_session **)arg) = p->session;
3183                 return 1;
3184                 
3185         } else if ( opt == LBER_SB_OPT_DATA_READY ) {
3186                 if ( p && ( SSL_DataPending( p->session ) > 0 ) ) {
3187                         return 1;
3188                 }
3189                 
3190         }
3191         
3192         return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
3193 }
3194
3195 static ber_slen_t
3196 tlsm_sb_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
3197 {
3198         struct tls_data         *p;
3199         ber_slen_t              ret;
3200         int                     err;
3201
3202         assert( sbiod != NULL );
3203         assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
3204
3205         p = (struct tls_data *)sbiod->sbiod_pvt;
3206
3207         ret = PR_Recv( p->session, buf, len, 0, PR_INTERVAL_NO_TIMEOUT );
3208         if ( ret < 0 ) {
3209                 err = PR_GetError();
3210                 if ( err == PR_PENDING_INTERRUPT_ERROR || err == PR_WOULD_BLOCK_ERROR ) {
3211                         sbiod->sbiod_sb->sb_trans_needs_read = 1;
3212                         sock_errset(EWOULDBLOCK);
3213                 }
3214         } else {
3215                 sbiod->sbiod_sb->sb_trans_needs_read = 0;
3216         }
3217         return ret;
3218 }
3219
3220 static ber_slen_t
3221 tlsm_sb_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
3222 {
3223         struct tls_data         *p;
3224         ber_slen_t              ret;
3225         int                     err;
3226
3227         assert( sbiod != NULL );
3228         assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
3229
3230         p = (struct tls_data *)sbiod->sbiod_pvt;
3231
3232         ret = PR_Send( p->session, (char *)buf, len, 0, PR_INTERVAL_NO_TIMEOUT );
3233         if ( ret < 0 ) {
3234                 err = PR_GetError();
3235                 if ( err == PR_PENDING_INTERRUPT_ERROR || err == PR_WOULD_BLOCK_ERROR ) {
3236                         sbiod->sbiod_sb->sb_trans_needs_write = 1;
3237                         sock_errset(EWOULDBLOCK);
3238                         ret = 0;
3239                 }
3240         } else {
3241                 sbiod->sbiod_sb->sb_trans_needs_write = 0;
3242         }
3243         return ret;
3244 }
3245
3246 static Sockbuf_IO tlsm_sbio =
3247 {
3248         tlsm_sb_setup,          /* sbi_setup */
3249         tlsm_sb_remove,         /* sbi_remove */
3250         tlsm_sb_ctrl,           /* sbi_ctrl */
3251         tlsm_sb_read,           /* sbi_read */
3252         tlsm_sb_write,          /* sbi_write */
3253         tlsm_sb_close           /* sbi_close */
3254 };
3255
3256 tls_impl ldap_int_tls_impl = {
3257         "MozNSS",
3258
3259         tlsm_init,
3260         tlsm_destroy,
3261
3262         tlsm_ctx_new,
3263         tlsm_ctx_ref,
3264         tlsm_ctx_free,
3265         tlsm_ctx_init,
3266
3267         tlsm_session_new,
3268         tlsm_session_connect,
3269         tlsm_session_accept,
3270         tlsm_session_upflags,
3271         tlsm_session_errmsg,
3272         tlsm_session_my_dn,
3273         tlsm_session_peer_dn,
3274         tlsm_session_chkhost,
3275         tlsm_session_strength,
3276
3277         &tlsm_sbio,
3278
3279 #ifdef LDAP_R_COMPILE
3280         tlsm_thr_init,
3281 #else
3282         NULL,
3283 #endif
3284
3285         0
3286 };
3287
3288 #endif /* HAVE_MOZNSS */
3289 /*
3290   emacs settings
3291   Local Variables:
3292   indent-tabs-mode: t
3293   tab-width: 4
3294   End:
3295 */