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