]> 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 explicity
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                 /* Prompt for password */
915                 if ( isTTY ) {
916                         fprintf( stdout,
917                                  "Please enter pin, password, or pass phrase for security token '%s': ",
918                                  token_name ? token_name : DEFAULT_TOKEN_NAME );
919                         echoOff( infd );
920                 }
921                 fgets( (char*)phrase, sizeof(phrase), stdin );
922                 if ( isTTY ) {
923                         fprintf( stdout, "\n" );
924                         echoOn( infd );
925                 }
926                 /* stomp on newline */
927                 phrase[strlen((char*)phrase)-1] = 0;
928
929                 pwdstr = PL_strdup( (char*)phrase );
930         }
931
932 #endif /* READ_PASSWORD_FROM_STDIN */
933         return pwdstr;
934 }
935
936 /*
937  * PKCS11 devices (including the internal softokn cert/key database)
938  * may be protected by a pin or password or even pass phrase
939  * MozNSS needs a way for the user to provide that
940  */
941 static char *
942 tlsm_pin_prompt(PK11SlotInfo *slot, PRBool retry, void *arg)
943 {
944         tlsm_ctx *ctx = (tlsm_ctx *)arg;
945
946         return tlsm_get_pin( slot, retry, ctx );
947 }
948
949 static char *
950 tlsm_ctx_subject_name(tlsm_ctx *ctx)
951 {
952         if ( !ctx || !ctx->tc_certificate )
953                 return "(unknown)";
954
955         return ctx->tc_certificate->subjectName;
956 }
957
958 static SECStatus
959 tlsm_get_basic_constraint_extension( CERTCertificate *cert,
960                                                                          CERTBasicConstraints *cbcval )
961 {
962         SECItem encodedVal = { 0, NULL };
963         SECStatus rc;
964
965         rc = CERT_FindCertExtension( cert, SEC_OID_X509_BASIC_CONSTRAINTS,
966                                                                  &encodedVal);
967         if ( rc != SECSuccess ) {
968                 return rc;
969         }
970
971         rc = CERT_DecodeBasicConstraintValue( cbcval, &encodedVal );
972
973         /* free the raw extension data */
974         PORT_Free( encodedVal.data );
975
976         return rc;
977 }
978
979 static PRBool
980 tlsm_cert_is_self_issued( CERTCertificate *cert )
981 {
982         /* A cert is self-issued if its subject and issuer are equal and
983          * both are of non-zero length. 
984          */
985         PRBool is_self_issued = cert &&
986                 (PRBool)SECITEM_ItemsAreEqual( &cert->derIssuer, 
987                                                                            &cert->derSubject ) &&
988                 cert->derSubject.len > 0;
989         return is_self_issued;
990 }
991
992 /*
993  * The private key for used certificate can be already unlocked by other
994  * thread or library. Find the unlocked key if possible.
995  */
996 static SECKEYPrivateKey *
997 tlsm_find_unlocked_key( tlsm_ctx *ctx, void *pin_arg )
998 {
999         SECKEYPrivateKey *result = NULL;
1000
1001         PK11SlotList *slots = PK11_GetAllSlotsForCert( ctx->tc_certificate, NULL );
1002         if ( !slots ) {
1003                 PRErrorCode errcode = PR_GetError();
1004                 Debug( LDAP_DEBUG_ANY,
1005                                 "TLS: cannot get all slots for certificate '%s' (error %d: %s)",
1006                                 tlsm_ctx_subject_name( ctx ), errcode,
1007                                 PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1008                 return result;
1009         }
1010
1011         PK11SlotListElement *le;
1012         for ( le = slots->head; le; le = le->next ) {
1013                 PK11SlotInfo *slot = le->slot;
1014                 if ( PK11_IsLoggedIn( slot, NULL ) ) {
1015                         result = PK11_FindKeyByDERCert( slot, ctx->tc_certificate, pin_arg );
1016                         break;
1017                 }
1018         }
1019
1020         PK11_FreeSlotList( slots );
1021         return result;
1022 }
1023
1024 static SECStatus
1025 tlsm_verify_cert(CERTCertDBHandle *handle, CERTCertificate *cert, void *pinarg,
1026                                  PRBool checksig, SECCertificateUsage certUsage, PRBool warn_only,
1027                                  PRBool ignore_issuer )
1028 {
1029         CERTVerifyLog verifylog;
1030         SECStatus ret = SECSuccess;
1031         const char *name;
1032         int debug_level = LDAP_DEBUG_ANY;
1033
1034         if ( warn_only ) {
1035                 debug_level = LDAP_DEBUG_TRACE;
1036         }
1037
1038         /* the log captures information about every cert in the chain, so we can tell
1039            which cert caused the problem and what the problem was */
1040         memset( &verifylog, 0, sizeof( verifylog ) );
1041         verifylog.arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE );
1042         if ( verifylog.arena == NULL ) {
1043                 Debug( LDAP_DEBUG_ANY,
1044                            "TLS certificate verification: Out of memory for certificate verification logger\n",
1045                            0, 0, 0 );
1046                 return SECFailure;
1047         }
1048         ret = CERT_VerifyCertificate( handle, cert, checksig, certUsage, PR_Now(), pinarg, &verifylog,
1049                                                                   NULL );
1050         if ( ( name = cert->subjectName ) == NULL ) {
1051                 name = cert->nickname;
1052         }
1053         if ( verifylog.head == NULL ) {
1054                 /* it is possible for CERT_VerifyCertificate return with an error with no logging */
1055                 if ( ret != SECSuccess ) {
1056                         PRErrorCode errcode = PR_GetError();
1057                         Debug( debug_level,
1058                                    "TLS: certificate [%s] is not valid - error %d:%s.\n",
1059                                    name ? name : "(unknown)",
1060                                    errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1061                 }
1062         } else {
1063                 const char *name;
1064                 CERTVerifyLogNode *node;
1065
1066                 ret = SECSuccess; /* reset */
1067                 node = verifylog.head;
1068                 while ( node ) {
1069                         if ( ( name = node->cert->subjectName ) == NULL ) {
1070                                 name = node->cert->nickname;
1071                         }
1072                         if ( node->error ) {
1073                                 /* NSS does not like CA certs that have the basic constraints extension
1074                                    with the CA flag set to FALSE - openssl doesn't check if the cert
1075                                    is self issued */
1076                                 if ( ( node->error == SEC_ERROR_CA_CERT_INVALID ) &&
1077                                          tlsm_cert_is_self_issued( node->cert ) ) {
1078
1079                                         PRErrorCode orig_error = PR_GetError();
1080                                         PRInt32 orig_oserror = PR_GetOSError();
1081
1082                                         CERTBasicConstraints basicConstraint;
1083                                         SECStatus rv = tlsm_get_basic_constraint_extension( node->cert, &basicConstraint );
1084                                         if ( ( rv == SECSuccess ) && ( basicConstraint.isCA == PR_FALSE ) ) {
1085                                                 Debug( LDAP_DEBUG_TRACE,
1086                                                            "TLS: certificate [%s] is not correct because it is a CA cert and the "
1087                                                            "BasicConstraint CA flag is set to FALSE - allowing for now, but "
1088                                                            "please fix your certs if possible\n", name, 0, 0 );
1089                                         } else { /* does not have basicconstraint, or some other error */
1090                                                 ret = SECFailure;
1091                                                 Debug( debug_level,
1092                                                            "TLS: certificate [%s] is not valid - CA cert is not valid\n",
1093                                                            name, 0, 0 );
1094                                         }
1095
1096                                         PR_SetError( orig_error, orig_oserror );
1097
1098                                 } else if ( warn_only || ( ignore_issuer && (
1099                                         node->error == SEC_ERROR_UNKNOWN_ISSUER ||
1100                                         node->error == SEC_ERROR_UNTRUSTED_ISSUER )
1101                                 ) ) {
1102                                         ret = SECSuccess;
1103                                         Debug( debug_level,
1104                                                    "TLS: Warning: ignoring error for certificate [%s] - error %ld:%s.\n",
1105                                                    name, node->error, PR_ErrorToString( node->error, PR_LANGUAGE_I_DEFAULT ) );
1106                                 } else {
1107                                         ret = SECFailure;
1108                                         Debug( debug_level,
1109                                                    "TLS: certificate [%s] is not valid - error %ld:%s.\n",
1110                                                    name, node->error, PR_ErrorToString( node->error, PR_LANGUAGE_I_DEFAULT ) );
1111                                 }
1112                         }
1113                         CERT_DestroyCertificate( node->cert );
1114                         node = node->next;
1115                 }
1116         }
1117
1118         PORT_FreeArena( verifylog.arena, PR_FALSE );
1119
1120         if ( ret == SECSuccess ) {
1121                 Debug( LDAP_DEBUG_TRACE,
1122                            "TLS: certificate [%s] is valid\n", name, 0, 0 );
1123         }
1124
1125         return ret;
1126 }
1127
1128 static SECStatus
1129 tlsm_auth_cert_handler(void *arg, PRFileDesc *fd,
1130                        PRBool checksig, PRBool isServer)
1131 {
1132         SECCertificateUsage certUsage = isServer ? certificateUsageSSLClient : certificateUsageSSLServer;
1133         SECStatus ret = SECSuccess;
1134         CERTCertificate *peercert = SSL_PeerCertificate( fd );
1135         tlsm_ctx *ctx = (tlsm_ctx *)arg;
1136
1137         ret = tlsm_verify_cert( ctx->tc_certdb, peercert,
1138                                                         SSL_RevealPinArg( fd ),
1139                                                         checksig, certUsage, ctx->tc_warn_only, PR_FALSE );
1140         CERT_DestroyCertificate( peercert );
1141
1142         return ret;
1143 }
1144
1145 static PRCallOnceType tlsm_register_shutdown_callonce = {0,0};
1146
1147 static SECStatus
1148 tlsm_nss_shutdown_cb( void *appData, void *nssData )
1149 {
1150         SECStatus rc = SECSuccess;
1151
1152         SSL_ShutdownServerSessionIDCache();
1153
1154         if ( pem_module ) {
1155                 SECMOD_UnloadUserModule( pem_module );
1156                 SECMOD_DestroyModule( pem_module );
1157                 pem_module = NULL;
1158         }
1159
1160         /* init callonce so it can be armed again for cases like persistent daemon with LDAP_OPT_X_TLS_NEWCTX */
1161         tlsm_register_shutdown_callonce.initialized = 0;
1162         tlsm_register_shutdown_callonce.inProgress = 0;
1163         tlsm_register_shutdown_callonce.status = 0;
1164
1165         return rc;
1166 }
1167
1168 static PRStatus PR_CALLBACK
1169 tlsm_register_nss_shutdown_cb( void )
1170 {
1171         if ( SECSuccess == NSS_RegisterShutdown( tlsm_nss_shutdown_cb,
1172                                                                                          NULL ) ) {
1173                 return PR_SUCCESS;
1174         }
1175         return PR_FAILURE;
1176 }
1177
1178 static PRStatus
1179 tlsm_register_nss_shutdown( void )
1180 {
1181         return PR_CallOnce( &tlsm_register_shutdown_callonce,
1182                                                 tlsm_register_nss_shutdown_cb );
1183 }
1184
1185 static int
1186 tlsm_init_pem_module( void )
1187 {
1188         int rc = 0;
1189         char *fullname = NULL;
1190         char *configstring = NULL;
1191
1192         if ( pem_module ) {
1193                 return rc;
1194         }
1195
1196         /* not loaded - load it */
1197         /* get the system dependent library name */
1198         fullname = PR_GetLibraryName( NULL, PEM_LIBRARY );
1199         /* Load our PKCS#11 module */
1200         configstring = PR_smprintf( "library=%s name=" PEM_MODULE " parameters=\"\"", fullname );
1201         PL_strfree( fullname );
1202
1203         pem_module = SECMOD_LoadUserModule( configstring, NULL, PR_FALSE );
1204         PR_smprintf_free( configstring );
1205
1206         if ( !pem_module || !pem_module->loaded ) {
1207                 if ( pem_module ) {
1208                         SECMOD_DestroyModule( pem_module );
1209                         pem_module = NULL;
1210                 }
1211                 rc = -1;
1212         }
1213
1214         return rc;
1215 }
1216
1217 static void
1218 tlsm_add_pem_obj( tlsm_ctx *ctx, PK11GenericObject *obj )
1219 {
1220         int idx = ctx->tc_n_pem_objs;
1221         ctx->tc_n_pem_objs++;
1222         ctx->tc_pem_objs = (PK11GenericObject **)
1223                 PORT_Realloc( ctx->tc_pem_objs, ctx->tc_n_pem_objs * sizeof( PK11GenericObject * ) );
1224         ctx->tc_pem_objs[idx] = obj;                                                                                                              
1225 }
1226
1227 static void
1228 tlsm_free_pem_objs( tlsm_ctx *ctx )
1229 {
1230         /* free in reverse order of allocation */
1231         while ( ctx->tc_n_pem_objs-- ) {
1232                 PK11_DestroyGenericObject( ctx->tc_pem_objs[ctx->tc_n_pem_objs] );
1233                 ctx->tc_pem_objs[ctx->tc_n_pem_objs] = NULL;
1234         }
1235         PORT_Free(ctx->tc_pem_objs);
1236         ctx->tc_pem_objs = NULL;
1237         ctx->tc_n_pem_objs = 0;
1238 }
1239
1240 static int
1241 tlsm_add_cert_from_file( tlsm_ctx *ctx, const char *filename, PRBool isca )
1242 {
1243         PK11SlotInfo *slot;
1244         PK11GenericObject *cert;
1245         CK_ATTRIBUTE attrs[4];
1246         CK_BBOOL cktrue = CK_TRUE;
1247         CK_BBOOL ckfalse = CK_FALSE;
1248         CK_OBJECT_CLASS objClass = CKO_CERTIFICATE;
1249         char *slotname;
1250         PRFileInfo fi;
1251         PRStatus status;
1252         SECItem certDER = { 0, NULL, 0 };
1253
1254         memset( &fi, 0, sizeof(fi) );
1255         status = PR_GetFileInfo( filename, &fi );
1256         if ( PR_SUCCESS != status) {
1257                 PRErrorCode errcode = PR_GetError();
1258                 Debug( LDAP_DEBUG_ANY,
1259                            "TLS: could not read certificate file %s - error %d:%s.\n",
1260                            filename, errcode,
1261                            PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1262                 return -1;
1263         }
1264
1265         if ( fi.type != PR_FILE_FILE ) {
1266                 PR_SetError(PR_IS_DIRECTORY_ERROR, 0);
1267                 Debug( LDAP_DEBUG_ANY,
1268                            "TLS: error: the certificate file %s is not a file.\n",
1269                            filename, 0 ,0 );
1270                 return -1;
1271         }
1272
1273         slotname = isca ? TLSM_PEM_SLOT_CACERTS : TLSM_PEM_SLOT_CERTS;
1274         slot = PK11_FindSlotByName( slotname );
1275
1276         if ( !slot ) {
1277                 PRErrorCode errcode = PR_GetError();
1278                 Debug( LDAP_DEBUG_ANY,
1279                            "TLS: could not find the slot for the certificate '%s' - error %d:%s.\n",
1280                            filename, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1281                 return -1;
1282         }
1283
1284         PK11_SETATTRS( attrs[0], CKA_CLASS, &objClass, sizeof( objClass ) );
1285         PK11_SETATTRS( attrs[1], CKA_TOKEN, &cktrue, sizeof( CK_BBOOL ) );
1286         PK11_SETATTRS( attrs[2], CKA_LABEL, (unsigned char *) filename, strlen( filename ) + 1 );
1287         PK11_SETATTRS( attrs[3], CKA_TRUST, isca ? &cktrue : &ckfalse, sizeof( CK_BBOOL ) );
1288
1289         cert = PK11_CreateGenericObject( slot, attrs, 4, PR_FALSE /* isPerm */ );
1290
1291         if ( !cert ) {
1292                 PRErrorCode errcode = PR_GetError();
1293                 Debug( LDAP_DEBUG_ANY,
1294                            "TLS: could not add the certificate '%s' - error %d:%s.\n",
1295                            filename, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1296                 PK11_FreeSlot( slot );
1297                 return -1;
1298         }
1299
1300         /* if not CA, we store the certificate in ctx->tc_certificate */
1301         if ( !isca ) {
1302                 if ( PK11_ReadRawAttribute( PK11_TypeGeneric, cert, CKA_VALUE, &certDER ) != SECSuccess ) {
1303                         PRErrorCode errcode = PR_GetError();
1304                         Debug( LDAP_DEBUG_ANY,
1305                                         "TLS: could not get DER of the '%s' certificate - error %d:%s.\n",
1306                                         filename, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1307                         PK11_DestroyGenericObject( cert );
1308                         PK11_FreeSlot( slot );
1309                         return -1;
1310                 }
1311
1312                 ctx->tc_certificate = PK11_FindCertFromDERCertItem( slot, &certDER, NULL );
1313                 SECITEM_FreeItem( &certDER, PR_FALSE );
1314
1315                 if ( !ctx->tc_certificate ) {
1316                         PRErrorCode errcode = PR_GetError();
1317                         Debug( LDAP_DEBUG_ANY,
1318                                         "TLS: could not get certificate '%s' using DER - error %d:%s.\n",
1319                                         filename, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1320                         PK11_DestroyGenericObject( cert );
1321                         PK11_FreeSlot( slot );
1322                         return -1;
1323                 }
1324         }
1325
1326         tlsm_add_pem_obj( ctx, cert );
1327
1328         PK11_FreeSlot( slot );
1329
1330         return 0;
1331 }
1332
1333 static int
1334 tlsm_ctx_load_private_key( tlsm_ctx *ctx )
1335 {
1336         if ( !ctx->tc_certificate )
1337                 return -1;
1338
1339         if ( ctx->tc_private_key )
1340                 return 0;
1341
1342         void *pin_arg = SSL_RevealPinArg( ctx->tc_model );
1343
1344         SECKEYPrivateKey *unlocked_key = tlsm_find_unlocked_key( ctx, pin_arg );
1345         Debug( LDAP_DEBUG_ANY,
1346                         "TLS: %s unlocked certificate for certificate '%s'.\n",
1347                         unlocked_key ? "found" : "no", tlsm_ctx_subject_name( ctx ), 0 );
1348
1349         /* prefer unlocked key, then key from opened certdb, then any other */
1350         if ( unlocked_key )
1351                 ctx->tc_private_key = unlocked_key;
1352         else if ( ctx->tc_certdb_slot && !ctx->tc_using_pem )
1353                 ctx->tc_private_key = PK11_FindKeyByDERCert( ctx->tc_certdb_slot, ctx->tc_certificate, pin_arg );
1354         else
1355                 ctx->tc_private_key = PK11_FindKeyByAnyCert( ctx->tc_certificate, pin_arg );
1356
1357         if ( !ctx->tc_private_key ) {
1358                 PRErrorCode errcode = PR_GetError();
1359                 Debug(LDAP_DEBUG_ANY,
1360                                 "TLS: cannot find private key for certificate '%s' (error %d: %s)",
1361                                 tlsm_ctx_subject_name( ctx ), errcode,
1362                                 PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1363                 return -1;
1364         }
1365
1366         return 0;
1367 }
1368
1369 static int
1370 tlsm_add_key_from_file( tlsm_ctx *ctx, const char *filename )
1371 {
1372         PK11SlotInfo * slot = NULL;
1373         PK11GenericObject *key;
1374         CK_ATTRIBUTE attrs[3];
1375         CK_BBOOL cktrue = CK_TRUE;
1376         CK_OBJECT_CLASS objClass = CKO_PRIVATE_KEY;
1377         int retcode = 0;
1378         PRFileInfo fi;
1379         PRStatus status;
1380
1381         memset( &fi, 0, sizeof(fi) );
1382         status = PR_GetFileInfo( filename, &fi );
1383         if ( PR_SUCCESS != status) {
1384                 PRErrorCode errcode = PR_GetError();
1385                 Debug( LDAP_DEBUG_ANY,
1386                            "TLS: could not read key file %s - error %d:%s.\n",
1387                            filename, errcode,
1388                            PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1389                 return -1;
1390         }
1391
1392         if ( fi.type != PR_FILE_FILE ) {
1393                 PR_SetError(PR_IS_DIRECTORY_ERROR, 0);
1394                 Debug( LDAP_DEBUG_ANY,
1395                            "TLS: error: the key file %s is not a file.\n",
1396                            filename, 0 ,0 );
1397                 return -1;
1398         }
1399
1400         slot = PK11_FindSlotByName( TLSM_PEM_SLOT_CERTS );
1401
1402         if ( !slot ) {
1403                 PRErrorCode errcode = PR_GetError();
1404                 Debug( LDAP_DEBUG_ANY,
1405                            "TLS: could not find the slot for the private key '%s' - error %d:%s.\n",
1406                            filename, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1407                 return -1;
1408         }
1409
1410         PK11_SETATTRS( attrs[0], CKA_CLASS, &objClass, sizeof( objClass ) );
1411         PK11_SETATTRS( attrs[1], CKA_TOKEN, &cktrue, sizeof( CK_BBOOL ) );
1412         PK11_SETATTRS( attrs[2], CKA_LABEL, (unsigned char *)filename, strlen( filename ) + 1 );
1413
1414         key = PK11_CreateGenericObject( slot, attrs, 3, PR_FALSE /* isPerm */ );
1415
1416         if ( !key ) {
1417                 PRErrorCode errcode = PR_GetError();
1418                 Debug( LDAP_DEBUG_ANY,
1419                            "TLS: could not add the private key '%s' - error %d:%s.\n",
1420                            filename, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1421                 retcode = -1;
1422         } else {
1423                 tlsm_add_pem_obj( ctx, key );
1424                 retcode = 0;
1425
1426                 /* When adding an encrypted key the PKCS#11 will be set as removed */
1427                 /* This will force the token to be seen as re-inserted */
1428                 SECMOD_WaitForAnyTokenEvent( pem_module, 0, 0 );
1429                 PK11_IsPresent( slot );
1430         }
1431
1432         PK11_FreeSlot( slot );
1433
1434         return retcode;
1435 }
1436
1437 static int
1438 tlsm_init_ca_certs( tlsm_ctx *ctx, const char *cacertfile, const char *cacertdir )
1439 {
1440         PRBool isca = PR_TRUE;
1441         PRStatus status = PR_SUCCESS;
1442         PRErrorCode errcode = PR_SUCCESS;
1443
1444         if ( !cacertfile && !cacertdir ) {
1445                 /* no checking - not good, but allowed */
1446                 return 0;
1447         }
1448
1449         if ( cacertfile ) {
1450                 int rc = tlsm_add_cert_from_file( ctx, cacertfile, isca );
1451                 if ( rc ) {
1452                         errcode = PR_GetError();
1453                         Debug( LDAP_DEBUG_ANY,
1454                                    "TLS: %s is not a valid CA certificate file - error %d:%s.\n",
1455                                    cacertfile, errcode,
1456                                    PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1457                         /* failure with cacertfile is a hard failure even if cacertdir is
1458                            also specified and contains valid CA cert files */
1459                         status = PR_FAILURE;
1460                 } else {
1461                         Debug( LDAP_DEBUG_TRACE,
1462                                    "TLS: loaded CA certificate file %s.\n",
1463                                    cacertfile, 0, 0 );
1464                 }
1465         }
1466
1467         /* if cacertfile above failed, we will return failure, even
1468            if there is a valid CA cert in cacertdir - but we still
1469            process cacertdir in case the user has enabled trace level
1470            debugging so they can see the processing for cacertdir too */
1471         /* any cacertdir failures are "soft" failures - if the user specifies
1472            no cert checking, then we allow the tls/ssl to continue, no matter
1473            what was specified for cacertdir, or the contents of the directory
1474            - this is different behavior than that of cacertfile */
1475         if ( cacertdir ) {
1476                 PRFileInfo fi;
1477                 PRDir *dir;
1478                 PRDirEntry *entry;
1479                 PRStatus fistatus = PR_FAILURE;
1480                 regex_t hashfile_re;
1481
1482                 memset( &fi, 0, sizeof(fi) );
1483                 fistatus = PR_GetFileInfo( cacertdir, &fi );
1484                 if ( PR_SUCCESS != fistatus) {
1485                         errcode = PR_GetError();
1486                         Debug( LDAP_DEBUG_ANY,
1487                                    "TLS: could not get info about the CA certificate directory %s - error %d:%s.\n",
1488                                    cacertdir, errcode,
1489                                    PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1490                         goto done;
1491                 }
1492
1493                 if ( fi.type != PR_FILE_DIRECTORY ) {
1494                         Debug( LDAP_DEBUG_ANY,
1495                                    "TLS: error: the CA certificate directory %s is not a directory.\n",
1496                                    cacertdir, 0 ,0 );
1497                         goto done;
1498                 }
1499
1500                 dir = PR_OpenDir( cacertdir );
1501                 if ( NULL == dir ) {
1502                         errcode = PR_GetError();
1503                         Debug( LDAP_DEBUG_ANY,
1504                                    "TLS: could not open the CA certificate directory %s - error %d:%s.\n",
1505                                    cacertdir, errcode,
1506                                    PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1507                         goto done;
1508                 }
1509
1510                 if ( regcomp( &hashfile_re, PEM_CA_HASH_FILE_REGEX, REG_NOSUB|REG_EXTENDED ) != 0 ) {
1511                         Debug( LDAP_DEBUG_ANY, "TLS: cannot compile regex for CA hash files matching\n", 0, 0, 0 );
1512                         goto done;
1513                 }
1514
1515                 do {
1516                         entry = PR_ReadDir( dir, PR_SKIP_BOTH | PR_SKIP_HIDDEN );
1517                         if ( ( NULL != entry ) && ( NULL != entry->name ) ) {
1518                                 char *fullpath = NULL;
1519                                 int match;
1520
1521                                 match = regexec( &hashfile_re, entry->name, 0, NULL, 0 );
1522                                 if ( match == REG_NOMATCH ) {
1523                                         Debug( LDAP_DEBUG_TRACE,
1524                                                    "TLS: skipping '%s' - filename does not have expected format "
1525                                                    "(certificate hash with numeric suffix)\n", entry->name, 0, 0 );
1526                                         continue;
1527                                 } else if ( match != 0 ) {
1528                                         Debug( LDAP_DEBUG_ANY,
1529                                                    "TLS: cannot execute regex for CA hash file matching (%d).\n",
1530                                                    match, 0, 0 );
1531                                         continue;
1532                                 }
1533
1534                                 fullpath = PR_smprintf( "%s/%s", cacertdir, entry->name );
1535                                 if ( !tlsm_add_cert_from_file( ctx, fullpath, isca ) ) {
1536                                         Debug( LDAP_DEBUG_TRACE,
1537                                                    "TLS: loaded CA certificate file %s from CA certificate directory %s.\n",
1538                                                    fullpath, cacertdir, 0 );
1539                                 } else {
1540                                         errcode = PR_GetError();
1541                                         Debug( LDAP_DEBUG_TRACE,
1542                                                    "TLS: %s is not a valid CA certificate file - error %d:%s.\n",
1543                                                    fullpath, errcode,
1544                                                    PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1545                                 }
1546                                 PR_smprintf_free( fullpath );
1547                         }
1548                 } while ( NULL != entry );
1549                 regfree ( &hashfile_re );
1550                 PR_CloseDir( dir );
1551         }
1552 done:
1553         if ( status != PR_SUCCESS ) {
1554                 return -1;
1555         }
1556
1557         return 0;
1558 }
1559
1560 /*
1561  * NSS supports having multiple cert/key databases in the same
1562  * directory, each one having a unique string prefix e.g.
1563  * slapd-01-cert8.db - the prefix here is "slapd-01-"
1564  * this function examines the given certdir - if it looks like
1565  * /path/to/directory/prefix it will return the
1566  * /path/to/directory part in realcertdir, and the prefix in prefix
1567  */
1568 static void
1569 tlsm_get_certdb_prefix( const char *certdir, char **realcertdir, char **prefix )
1570 {
1571         char sep = PR_GetDirectorySeparator();
1572         char *ptr = NULL;
1573         struct PRFileInfo prfi;
1574         PRStatus prc;
1575
1576         *realcertdir = (char *)certdir; /* default is the one passed in */
1577
1578         /* if certdir is not given, just return */
1579         if ( !certdir ) {
1580                 return;
1581         }
1582
1583         prc = PR_GetFileInfo( certdir, &prfi );
1584         /* if certdir exists (file or directory) then it cannot specify a prefix */
1585         if ( prc == PR_SUCCESS ) {
1586                 return;
1587         }
1588
1589         /* if certdir was given, and there is a '/' in certdir, see if there
1590            is anything after the last '/' - if so, assume it is the prefix */
1591         if ( ( ( ptr = strrchr( certdir, sep ) ) ) && *(ptr+1) ) {
1592                 *realcertdir = PL_strndup( certdir, ptr-certdir );
1593                 *prefix = PL_strdup( ptr+1 );
1594         }
1595
1596         return;
1597 }
1598
1599 /*
1600  * Currently mutiple MozNSS contexts share one certificate storage. When the
1601  * certdb is being opened, only new certificates are added to the storage.
1602  * When different databases are used, conflicting nicknames make the
1603  * certificate lookup by the nickname impossible. In addition a token
1604  * description might be prepended in certain conditions.
1605  *
1606  * In order to make the certificate lookup by nickname possible, we explicitly
1607  * open each database using SECMOD_OpenUserDB and assign it the token
1608  * description. The token description is generated using ctx->tc_unique value,
1609  * which is unique for each context.
1610  */
1611 static PK11SlotInfo *
1612 tlsm_init_open_certdb( tlsm_ctx *ctx, const char *dbdir, const char *prefix )
1613 {
1614         PK11SlotInfo *slot = NULL;
1615         char *token_desc = NULL;
1616         char *config = NULL;
1617
1618         token_desc = PR_smprintf( TLSM_CERTDB_DESC_FMT, ctx->tc_unique );
1619         config = PR_smprintf( "configDir='%s' tokenDescription='%s' certPrefix='%s' keyPrefix='%s' flags=readOnly",
1620                                                                                 dbdir, token_desc, prefix, prefix );
1621         Debug( LDAP_DEBUG_TRACE, "TLS: certdb config: %s\n", config, 0, 0 );
1622
1623         slot = SECMOD_OpenUserDB( config );
1624         if ( !slot ) {
1625                 PRErrorCode errcode = PR_GetError();
1626                 Debug( LDAP_DEBUG_TRACE, "TLS: cannot open certdb '%s', error %d:%s\n", dbdir, errcode,
1627                                                         PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1628         }
1629
1630         if ( token_desc )
1631                 PR_smprintf_free( token_desc );
1632         if ( config )
1633                 PR_smprintf_free( config );
1634
1635         return slot;
1636 }
1637
1638 /*
1639  * This is the part of the init we defer until we get the
1640  * actual security configuration information.  This is
1641  * only called once, protected by a PRCallOnce
1642  * NOTE: This must be done before the first call to SSL_ImportFD,
1643  * especially the setting of the policy
1644  * NOTE: This must be called after fork()
1645  */
1646 static int
1647 tlsm_deferred_init( void *arg )
1648 {
1649         tlsm_ctx *ctx = (tlsm_ctx *)arg;
1650         struct ldaptls *lt = ctx->tc_config;
1651         const char *securitydirs[3];
1652         int ii;
1653         int nn;
1654         PRErrorCode errcode = 1;
1655 #ifdef HAVE_NSS_INITCONTEXT
1656         NSSInitParameters initParams;
1657         NSSInitContext *initctx = NULL;
1658         PK11SlotInfo *certdb_slot = NULL;
1659 #endif
1660         SECStatus rc;
1661         int done = 0;
1662
1663 #ifdef HAVE_SECMOD_RESTARTMODULES
1664         /* NSS enforces the pkcs11 requirement that modules should be unloaded after
1665            a fork() - since there is no portable way to determine if NSS has been
1666            already initialized in a parent process, we just call SECMOD_RestartModules
1667            with force == FALSE - if the module has been unloaded due to a fork, it will
1668            be reloaded, otherwise, it is a no-op */
1669         if ( SECFailure == ( rc = SECMOD_RestartModules(PR_FALSE /* do not force */) ) ) {
1670                 errcode = PORT_GetError();
1671                 if ( errcode != SEC_ERROR_NOT_INITIALIZED ) {
1672                         Debug( LDAP_DEBUG_TRACE,
1673                                    "TLS: could not restart the security modules: %d:%s\n",
1674                                    errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 );
1675                 } else {
1676                         errcode = 1;
1677                 }
1678         }
1679 #endif
1680
1681 #ifdef HAVE_NSS_INITCONTEXT
1682         memset( &initParams, 0, sizeof( initParams ) );
1683         initParams.length = sizeof( initParams );
1684 #endif /* HAVE_NSS_INITCONTEXT */
1685
1686 #ifdef LDAP_R_COMPILE
1687         if ( PR_CallOnce( &tlsm_init_mutex_callonce, tlsm_thr_init_callonce ) ) {
1688                 return -1;
1689         }
1690 #endif /* LDAP_R_COMPILE */
1691
1692 #ifndef HAVE_NSS_INITCONTEXT
1693         if ( !NSS_IsInitialized() ) {
1694 #endif /* HAVE_NSS_INITCONTEXT */
1695                 /*
1696                   MOZNSS_DIR will override everything else - you can
1697                   always set MOZNSS_DIR to force the use of this
1698                   directory
1699                   If using MOZNSS, specify the location of the moznss db dir
1700                   in the cacertdir directive of the OpenLDAP configuration.
1701                   DEFAULT_MOZNSS_DIR will only be used if the code cannot
1702                   find a security dir to use based on the current
1703                   settings
1704                 */
1705                 nn = 0;
1706                 securitydirs[nn++] = PR_GetEnv( "MOZNSS_DIR" );
1707                 securitydirs[nn++] = lt->lt_cacertdir;
1708                 securitydirs[nn++] = PR_GetEnv( "DEFAULT_MOZNSS_DIR" );
1709                 for ( ii = 0; !done && ( ii < nn ); ++ii ) {
1710                         char *realcertdir = NULL;
1711                         const char *defprefix = "";
1712                         char *prefix = (char *)defprefix;
1713                         const char *securitydir = securitydirs[ii];
1714                         if ( NULL == securitydir ) {
1715                                 continue;
1716                         }
1717
1718                         tlsm_get_certdb_prefix( securitydir, &realcertdir, &prefix );
1719
1720                         /* initialize only moddb; certdb will be initialized explicitly */
1721 #ifdef HAVE_NSS_INITCONTEXT
1722 #ifdef INITCONTEXT_HACK
1723                         if ( !NSS_IsInitialized() && ctx->tc_is_server ) {
1724                                 rc = NSS_Initialize( realcertdir, prefix, prefix, SECMOD_DB, NSS_INIT_READONLY );
1725                         } else {
1726                                 initctx = NSS_InitContext( realcertdir, prefix, prefix, SECMOD_DB,
1727                                                                    &initParams, NSS_INIT_READONLY|NSS_INIT_NOCERTDB );
1728                         }
1729 #else
1730                         initctx = NSS_InitContext( realcertdir, prefix, prefix, SECMOD_DB,
1731                                                                    &initParams, NSS_INIT_READONLY|NSS_INIT_NOCERTDB );
1732 #endif
1733                         rc = SECFailure;
1734
1735                         if ( initctx != NULL ) {
1736                                 certdb_slot = tlsm_init_open_certdb( ctx, realcertdir, prefix );
1737                                 if ( certdb_slot ) {
1738                                         rc = SECSuccess;
1739                                         ctx->tc_initctx = initctx;
1740                                         ctx->tc_certdb_slot = certdb_slot;
1741                                 } else {
1742                                         NSS_ShutdownContext( initctx );
1743                                         initctx = NULL;
1744                                 }
1745                         }
1746 #else
1747                         rc = NSS_Initialize( realcertdir, prefix, prefix, SECMOD_DB, NSS_INIT_READONLY );
1748 #endif
1749
1750                         if ( rc != SECSuccess ) {
1751                                 errcode = PORT_GetError();
1752                                 if ( securitydirs[ii] != lt->lt_cacertdir) {
1753                                         Debug( LDAP_DEBUG_TRACE,
1754                                                    "TLS: could not initialize moznss using security dir %s prefix %s - error %d.\n",
1755                                                    realcertdir, prefix, errcode );
1756                                 }
1757                         } else {
1758                                 /* success */
1759                                 Debug( LDAP_DEBUG_TRACE, "TLS: using moznss security dir %s prefix %s.\n",
1760                                            realcertdir, prefix, 0 );
1761                                 errcode = 0;
1762                                 done = 1;
1763                         }
1764                         if ( realcertdir != securitydir ) {
1765                                 PL_strfree( realcertdir );
1766                         }
1767                         if ( prefix != defprefix ) {
1768                                 PL_strfree( prefix );
1769                         }
1770                 }
1771
1772                 if ( errcode ) { /* no moznss db found, or not using moznss db */
1773 #ifdef HAVE_NSS_INITCONTEXT
1774                         int flags = NSS_INIT_READONLY|NSS_INIT_NOCERTDB|NSS_INIT_NOMODDB;
1775 #ifdef INITCONTEXT_HACK
1776                         if ( !NSS_IsInitialized() && ctx->tc_is_server ) {
1777                                 rc = NSS_NoDB_Init( NULL );
1778                         } else {
1779                                 initctx = NSS_InitContext( CERTDB_NONE, PREFIX_NONE, PREFIX_NONE, SECMOD_DB,
1780                                                                                    &initParams, flags );
1781                                 rc = (initctx == NULL) ? SECFailure : SECSuccess;
1782                         }
1783 #else
1784                         initctx = NSS_InitContext( CERTDB_NONE, PREFIX_NONE, PREFIX_NONE, SECMOD_DB,
1785                                                                            &initParams, flags );
1786                         if ( initctx ) {
1787                                 ctx->tc_initctx = initctx;
1788                                 rc = SECSuccess;
1789                         } else {
1790                                 rc = SECFailure;
1791                         }
1792 #endif
1793 #else
1794                         rc = NSS_NoDB_Init( NULL );
1795 #endif
1796                         if ( rc != SECSuccess ) {
1797                                 errcode = PORT_GetError();
1798                                 Debug( LDAP_DEBUG_ANY,
1799                                            "TLS: could not initialize moznss - error %d:%s.\n",
1800                                            errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 );
1801                                 return -1;
1802                         }
1803                 }
1804
1805                 if ( errcode || lt->lt_cacertfile ) {
1806                         /* initialize the PEM module */
1807                         if ( tlsm_init_pem_module() ) {
1808                                 int pem_errcode = PORT_GetError();
1809                                 Debug( LDAP_DEBUG_ANY,
1810                                            "TLS: could not initialize moznss PEM module - error %d:%s.\n",
1811                                            pem_errcode, PR_ErrorToString( pem_errcode, PR_LANGUAGE_I_DEFAULT ), 0 );
1812
1813                                 if ( errcode ) /* PEM is required */
1814                                         return -1;
1815
1816                         } else if ( !errcode ) {
1817                                 tlsm_init_ca_certs( ctx, lt->lt_cacertfile, NULL );
1818                         }
1819                 }
1820
1821                 if ( errcode ) {
1822                         if ( tlsm_init_ca_certs( ctx, lt->lt_cacertfile, lt->lt_cacertdir ) ) {
1823                                 /* if we tried to use lt->lt_cacertdir as an NSS key/cert db, errcode 
1824                                    will be a value other than 1 - print an error message so that the
1825                                    user will know that failed too */
1826                                 if ( ( errcode != 1 ) && ( lt->lt_cacertdir ) ) {
1827                                         char *realcertdir = NULL;
1828                                         char *prefix = NULL;
1829                                         tlsm_get_certdb_prefix( lt->lt_cacertdir, &realcertdir, &prefix );
1830                                         Debug( LDAP_DEBUG_TRACE,
1831                                                    "TLS: could not initialize moznss using security dir %s prefix %s - error %d.\n",
1832                                                    realcertdir, prefix ? prefix : "", errcode );
1833                                         if ( realcertdir != lt->lt_cacertdir ) {
1834                                                 PL_strfree( realcertdir );
1835                                         }
1836                                         PL_strfree( prefix );
1837                                 }
1838                                 return -1;
1839                         }
1840                 }
1841
1842                 NSS_SetDomesticPolicy();
1843
1844                 PK11_SetPasswordFunc( tlsm_pin_prompt );
1845
1846                 /* register cleanup function */
1847                 if ( tlsm_register_nss_shutdown() ) {
1848                         errcode = PORT_GetError();
1849                         Debug( LDAP_DEBUG_ANY,
1850                                    "TLS: could not register NSS shutdown function: %d:%s\n",
1851                                    errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 );
1852                         return -1;
1853                 }
1854
1855                 if  ( ctx->tc_is_server ) {
1856                         /* 0 means use the defaults here */
1857                         SSL_ConfigServerSessionIDCache( 0, 0, 0, NULL );
1858                 }
1859
1860 #ifndef HAVE_NSS_INITCONTEXT
1861         }
1862 #endif /* HAVE_NSS_INITCONTEXT */
1863
1864         return 0;
1865 }
1866
1867 /*
1868  * Find and verify the certificate.
1869  * The key is loaded and stored in ctx->tc_private_key
1870  */
1871 static int
1872 tlsm_find_and_verify_cert_key( tlsm_ctx *ctx )
1873 {
1874         SECCertificateUsage certUsage;
1875         PRBool checkSig;
1876         SECStatus status;
1877         void *pin_arg;
1878
1879         if ( tlsm_ctx_load_private_key( ctx ) )
1880                 return -1;
1881
1882         pin_arg = SSL_RevealPinArg( ctx->tc_model );
1883         certUsage = ctx->tc_is_server ? certificateUsageSSLServer : certificateUsageSSLClient;
1884         checkSig = ctx->tc_verify_cert ? PR_TRUE : PR_FALSE;
1885
1886         status = tlsm_verify_cert( ctx->tc_certdb, ctx->tc_certificate, pin_arg,
1887                                                            checkSig, certUsage, ctx->tc_warn_only, PR_TRUE );
1888
1889         return status == SECSuccess ? 0 : -1;
1890 }
1891
1892 static int
1893 tlsm_get_client_auth_data( void *arg, PRFileDesc *fd,
1894                                                    CERTDistNames *caNames, CERTCertificate **pRetCert,
1895                                                    SECKEYPrivateKey **pRetKey )
1896 {
1897         tlsm_ctx *ctx = (tlsm_ctx *)arg;
1898
1899         if ( pRetCert )
1900                 *pRetCert = CERT_DupCertificate( ctx->tc_certificate );
1901
1902         if ( pRetKey )
1903                 *pRetKey = SECKEY_CopyPrivateKey( ctx->tc_private_key );
1904
1905         return SECSuccess;
1906 }
1907
1908 /*
1909  * ctx must have a tc_model that is valid
1910 */
1911 static int
1912 tlsm_clientauth_init( tlsm_ctx *ctx )
1913 {
1914         SECStatus status = SECFailure;
1915         int rc;
1916         PRBool saveval;
1917
1918         saveval = ctx->tc_warn_only;
1919         ctx->tc_warn_only = PR_TRUE;
1920         rc = tlsm_find_and_verify_cert_key(ctx);
1921         ctx->tc_warn_only = saveval;
1922         if ( rc ) {
1923                 Debug( LDAP_DEBUG_ANY,
1924                            "TLS: error: unable to set up client certificate authentication for "
1925                            "certificate named %s\n", tlsm_ctx_subject_name(ctx), 0, 0 );
1926                 return -1;
1927         }
1928
1929         status = SSL_GetClientAuthDataHook( ctx->tc_model,
1930                                                                                 tlsm_get_client_auth_data,
1931                                                                                 (void *)ctx );
1932
1933         return ( status == SECSuccess ? 0 : -1 );
1934 }
1935
1936 /*
1937  * Tear down the TLS subsystem. Should only be called once.
1938  */
1939 static void
1940 tlsm_destroy( void )
1941 {
1942 #ifdef LDAP_R_COMPILE
1943         ldap_pvt_thread_mutex_destroy( &tlsm_ctx_count_mutex );
1944         ldap_pvt_thread_mutex_destroy( &tlsm_init_mutex );
1945         ldap_pvt_thread_mutex_destroy( &tlsm_pem_mutex );
1946 #endif
1947 }
1948
1949 static struct ldaptls *
1950 tlsm_copy_config ( const struct ldaptls *config )
1951 {
1952         struct ldaptls *copy;
1953
1954         assert( config );
1955
1956         copy = LDAP_MALLOC( sizeof( *copy ) );
1957         if ( !copy )
1958                 return NULL;
1959
1960         memset( copy, 0, sizeof( *copy ) );
1961
1962         if ( config->lt_certfile )
1963                 copy->lt_certfile = LDAP_STRDUP( config->lt_certfile );
1964         if ( config->lt_keyfile )
1965                 copy->lt_keyfile = LDAP_STRDUP( config->lt_keyfile );
1966         if ( config->lt_dhfile )
1967                 copy->lt_dhfile = LDAP_STRDUP( config->lt_dhfile );
1968         if ( config->lt_cacertfile )
1969                 copy->lt_cacertfile = LDAP_STRDUP( config->lt_cacertfile );
1970         if ( config->lt_cacertdir )
1971                 copy->lt_cacertdir = LDAP_STRDUP( config->lt_cacertdir );
1972         if ( config->lt_ciphersuite )
1973                 copy->lt_ciphersuite = LDAP_STRDUP( config->lt_ciphersuite );
1974         if ( config->lt_crlfile )
1975                 copy->lt_crlfile = LDAP_STRDUP( config->lt_crlfile );
1976         if ( config->lt_randfile )
1977                 copy->lt_randfile = LDAP_STRDUP( config->lt_randfile );
1978
1979         copy->lt_protocol_min = config->lt_protocol_min;
1980
1981         return copy;
1982 }
1983
1984 static void
1985 tlsm_free_config ( struct ldaptls *config )
1986 {
1987         assert( config );
1988
1989         if ( config->lt_certfile )
1990                 LDAP_FREE( config->lt_certfile );
1991         if ( config->lt_keyfile )
1992                 LDAP_FREE( config->lt_keyfile );
1993         if ( config->lt_dhfile )
1994                 LDAP_FREE( config->lt_dhfile );
1995         if ( config->lt_cacertfile )
1996                 LDAP_FREE( config->lt_cacertfile );
1997         if ( config->lt_cacertdir )
1998                 LDAP_FREE( config->lt_cacertdir );
1999         if ( config->lt_ciphersuite )
2000                 LDAP_FREE( config->lt_ciphersuite );
2001         if ( config->lt_crlfile )
2002                 LDAP_FREE( config->lt_crlfile );
2003         if ( config->lt_randfile )
2004                 LDAP_FREE( config->lt_randfile );
2005
2006         LDAP_FREE( config );
2007 }
2008
2009 static tls_ctx *
2010 tlsm_ctx_new ( struct ldapoptions *lo )
2011 {
2012         tlsm_ctx *ctx;
2013
2014         ctx = LDAP_MALLOC( sizeof (*ctx) );
2015         if ( ctx ) {
2016                 ctx->tc_refcnt = 1;
2017 #ifdef LDAP_R_COMPILE
2018                 ldap_pvt_thread_mutex_init( &ctx->tc_refmutex );
2019 #endif
2020                 LDAP_MUTEX_LOCK( &tlsm_ctx_count_mutex );
2021                 ctx->tc_unique = tlsm_ctx_count++;
2022                 LDAP_MUTEX_UNLOCK( &tlsm_ctx_count_mutex );
2023                 ctx->tc_config = NULL; /* populated later by tlsm_ctx_init */
2024                 ctx->tc_certdb = NULL;
2025                 ctx->tc_certdb_slot = NULL;
2026                 ctx->tc_certificate = NULL;
2027                 ctx->tc_private_key = NULL;
2028                 ctx->tc_pin_file = NULL;
2029                 ctx->tc_model = NULL;
2030                 memset(&ctx->tc_callonce, 0, sizeof(ctx->tc_callonce));
2031                 ctx->tc_require_cert = lo->ldo_tls_require_cert;
2032                 ctx->tc_verify_cert = PR_FALSE;
2033                 ctx->tc_using_pem = PR_FALSE;
2034 #ifdef HAVE_NSS_INITCONTEXT
2035                 ctx->tc_initctx = NULL;
2036 #endif /* HAVE_NSS_INITCONTEXT */
2037                 ctx->tc_pem_objs = NULL;
2038                 ctx->tc_n_pem_objs = 0;
2039                 ctx->tc_warn_only = PR_FALSE;
2040         }
2041         return (tls_ctx *)ctx;
2042 }
2043
2044 static void
2045 tlsm_ctx_ref( tls_ctx *ctx )
2046 {
2047         tlsm_ctx *c = (tlsm_ctx *)ctx;
2048         LDAP_MUTEX_LOCK( &c->tc_refmutex );
2049         c->tc_refcnt++;
2050         LDAP_MUTEX_UNLOCK( &c->tc_refmutex );
2051 }
2052
2053 static void
2054 tlsm_ctx_free ( tls_ctx *ctx )
2055 {
2056         tlsm_ctx *c = (tlsm_ctx *)ctx;
2057         int refcount;
2058
2059         if ( !c ) return;
2060
2061         LDAP_MUTEX_LOCK( &c->tc_refmutex );
2062         refcount = --c->tc_refcnt;
2063         LDAP_MUTEX_UNLOCK( &c->tc_refmutex );
2064         if ( refcount )
2065                 return;
2066
2067         LDAP_MUTEX_LOCK( &tlsm_init_mutex );
2068         if ( c->tc_model )
2069                 PR_Close( c->tc_model );
2070         if ( c->tc_certificate )
2071                 CERT_DestroyCertificate( c->tc_certificate );
2072         if ( c->tc_private_key )
2073                 SECKEY_DestroyPrivateKey( c->tc_private_key );
2074         c->tc_certdb = NULL; /* if not the default, may have to clean up */
2075         if ( c->tc_certdb_slot ) {
2076                 if ( SECMOD_CloseUserDB( c->tc_certdb_slot ) ) {
2077                         PRErrorCode errcode = PR_GetError();
2078                         Debug( LDAP_DEBUG_ANY,
2079                                    "TLS: could not close certdb slot - error %d:%s.\n",
2080                                    errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 );
2081                 }
2082         }
2083         if ( c->tc_pin_file ) {
2084                 PL_strfree( c->tc_pin_file );
2085                 c->tc_pin_file = NULL;
2086         }
2087         tlsm_free_pem_objs( c );
2088 #ifdef HAVE_NSS_INITCONTEXT
2089         if ( c->tc_initctx ) {
2090                 if ( NSS_ShutdownContext( c->tc_initctx ) ) {
2091                         PRErrorCode errcode = PR_GetError();
2092                         Debug( LDAP_DEBUG_ANY,
2093                                    "TLS: could not shutdown NSS - error %d:%s.\n",
2094                                    errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 );
2095                 }
2096         }
2097         c->tc_initctx = NULL;
2098 #endif /* HAVE_NSS_INITCONTEXT */
2099         LDAP_MUTEX_UNLOCK( &tlsm_init_mutex );
2100 #ifdef LDAP_R_COMPILE
2101         ldap_pvt_thread_mutex_destroy( &c->tc_refmutex );
2102 #endif
2103
2104         if ( c->tc_config )
2105                 tlsm_free_config( c->tc_config );
2106
2107         LDAP_FREE( c );
2108 }
2109
2110 /*
2111  * initialize a new TLS context
2112  */
2113 static int
2114 tlsm_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server )
2115 {
2116         tlsm_ctx *ctx = (tlsm_ctx *)lo->ldo_tls_ctx;
2117         ctx->tc_config = tlsm_copy_config( lt );
2118         ctx->tc_is_server = is_server;
2119
2120         return 0;
2121 }
2122
2123 /* returns true if the given string looks like
2124    "tokenname" ":" "certnickname"
2125    This is true if there is a ':' colon character
2126    in the string and the colon is not the first
2127    or the last character in the string
2128 */
2129 static int
2130 tlsm_is_tokenname_certnick( const char *certfile )
2131 {
2132         if ( certfile ) {
2133                 const char *ptr = PL_strchr( certfile, ':' );
2134                 return ptr && (ptr != certfile) && (*(ptr+1));
2135         }
2136         return 0;
2137 }
2138
2139 static int
2140 tlsm_deferred_ctx_init( void *arg )
2141 {
2142         tlsm_ctx *ctx = (tlsm_ctx *)arg;
2143         PRBool sslv2 = PR_FALSE;
2144         PRBool sslv3 = PR_TRUE;
2145         PRBool tlsv1 = PR_TRUE;
2146         PRBool request_cert = PR_FALSE;
2147         PRInt32 require_cert = PR_FALSE;
2148         PRFileDesc *fd;
2149         struct ldaptls *lt;
2150
2151         if ( tlsm_deferred_init( ctx ) ) {
2152             Debug( LDAP_DEBUG_ANY,
2153                            "TLS: could not perform TLS system initialization.\n",
2154                            0, 0, 0 );
2155             return -1;
2156         }
2157
2158         ctx->tc_certdb = CERT_GetDefaultCertDB(); /* If there is ever a per-context db, change this */
2159
2160         fd = PR_CreateIOLayerStub( tlsm_layer_id, &tlsm_PR_methods );
2161         if ( fd ) {
2162                 ctx->tc_model = SSL_ImportFD( NULL, fd );
2163         }
2164
2165         if ( !ctx->tc_model ) {
2166                 PRErrorCode err = PR_GetError();
2167                 Debug( LDAP_DEBUG_ANY,
2168                            "TLS: could perform TLS socket I/O layer initialization - error %d:%s.\n",
2169                            err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL );
2170
2171                 if ( fd ) {
2172                         PR_Close( fd );
2173                 }
2174                 return -1;
2175         }
2176
2177         if ( SSL_SetPKCS11PinArg(ctx->tc_model, ctx) ) {
2178                 Debug( LDAP_DEBUG_ANY,
2179                                 "TLS: could not set pin prompt argument\n", 0, 0, 0);
2180                 return -1;
2181         }
2182
2183         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_SECURITY, PR_TRUE ) ) {
2184                 Debug( LDAP_DEBUG_ANY,
2185                        "TLS: could not set secure mode on.\n",
2186                        0, 0, 0 );
2187                 return -1;
2188         }
2189
2190         lt = ctx->tc_config;
2191
2192         /* default is sslv3 and tlsv1 */
2193         if ( lt->lt_protocol_min ) {
2194                 if ( lt->lt_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_SSL3 ) {
2195                         sslv3 = PR_FALSE;
2196                 } else if ( lt->lt_protocol_min <= LDAP_OPT_X_TLS_PROTOCOL_SSL2 ) {
2197                         sslv2 = PR_TRUE;
2198                         Debug( LDAP_DEBUG_ANY,
2199                                "TLS: warning: minimum TLS protocol level set to "
2200                                "include SSLv2 - SSLv2 is insecure - do not use\n", 0, 0, 0 );
2201                 }
2202         }
2203         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_ENABLE_SSL2, sslv2 ) ) {
2204                 Debug( LDAP_DEBUG_ANY,
2205                        "TLS: could not set SSLv2 mode on.\n",
2206                        0, 0, 0 );
2207                 return -1;
2208         }
2209         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_ENABLE_SSL3, sslv3 ) ) {
2210                 Debug( LDAP_DEBUG_ANY,
2211                        "TLS: could not set SSLv3 mode on.\n",
2212                        0, 0, 0 );
2213                 return -1;
2214         }
2215         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_ENABLE_TLS, tlsv1 ) ) {
2216                 Debug( LDAP_DEBUG_ANY,
2217                        "TLS: could not set TLSv1 mode on.\n",
2218                        0, 0, 0 );
2219                 return -1;
2220         }
2221
2222         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_HANDSHAKE_AS_CLIENT, !ctx->tc_is_server ) ) {
2223                 Debug( LDAP_DEBUG_ANY,
2224                        "TLS: could not set handshake as client.\n",
2225                        0, 0, 0 );
2226                 return -1;
2227         }
2228         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_HANDSHAKE_AS_SERVER, ctx->tc_is_server ) ) {
2229                 Debug( LDAP_DEBUG_ANY,
2230                        "TLS: could not set handshake as server.\n",
2231                        0, 0, 0 );
2232                 return -1;
2233         }
2234
2235         if ( lt->lt_ciphersuite ) {
2236                 if ( tlsm_parse_ciphers( ctx, lt->lt_ciphersuite ) ) {
2237                         Debug( LDAP_DEBUG_ANY,
2238                                "TLS: could not set cipher list %s.\n",
2239                                lt->lt_ciphersuite, 0, 0 );
2240                         return -1;
2241                 }
2242         } else if ( tlsm_parse_ciphers( ctx, "DEFAULT" ) ) {
2243                 Debug( LDAP_DEBUG_ANY,
2244                        "TLS: could not set cipher list DEFAULT.\n",
2245                        0, 0, 0 );
2246                 return -1;
2247         }
2248
2249         if ( !ctx->tc_require_cert ) {
2250                 ctx->tc_verify_cert = PR_FALSE;
2251         } else if ( !ctx->tc_is_server ) {
2252                 request_cert = PR_TRUE;
2253                 require_cert = SSL_REQUIRE_NO_ERROR;
2254                 if ( ctx->tc_require_cert == LDAP_OPT_X_TLS_DEMAND ||
2255                      ctx->tc_require_cert == LDAP_OPT_X_TLS_HARD ) {
2256                         require_cert = SSL_REQUIRE_ALWAYS;
2257                 }
2258                 if ( ctx->tc_require_cert != LDAP_OPT_X_TLS_ALLOW )
2259                         ctx->tc_verify_cert = PR_TRUE;
2260         } else { /* server */
2261                 /* server does not request certs by default */
2262                 /* if allow - client may send cert, server will ignore if errors */
2263                 /* if try - client may send cert, server will error if bad cert */
2264                 /* if hard or demand - client must send cert, server will error if bad cert */
2265                 request_cert = PR_TRUE;
2266                 require_cert = SSL_REQUIRE_NO_ERROR;
2267                 if ( ctx->tc_require_cert == LDAP_OPT_X_TLS_DEMAND ||
2268                      ctx->tc_require_cert == LDAP_OPT_X_TLS_HARD ) {
2269                         require_cert = SSL_REQUIRE_ALWAYS;
2270                 }
2271                 if ( ctx->tc_require_cert != LDAP_OPT_X_TLS_ALLOW ) {
2272                         ctx->tc_verify_cert = PR_TRUE;
2273                 } else {
2274                         ctx->tc_warn_only = PR_TRUE;
2275                 }
2276         }
2277
2278         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_REQUEST_CERTIFICATE, request_cert ) ) {
2279                 Debug( LDAP_DEBUG_ANY,
2280                        "TLS: could not set request certificate mode.\n",
2281                        0, 0, 0 );
2282                 return -1;
2283         }
2284                 
2285         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_REQUIRE_CERTIFICATE, require_cert ) ) {
2286                 Debug( LDAP_DEBUG_ANY,
2287                        "TLS: could not set require certificate mode.\n",
2288                        0, 0, 0 );
2289                 return -1;
2290         }
2291
2292         /* set up our cert and key, if any */
2293         if ( lt->lt_certfile ) {
2294
2295                 /* first search in certdb (lt_certfile is nickname) */
2296                 if ( ctx->tc_certdb ) {
2297                         char *tmp_certname;
2298
2299                         if ( tlsm_is_tokenname_certnick( lt->lt_certfile )) {
2300                                 /* assume already in form tokenname:certnickname */
2301                                 tmp_certname = PL_strdup( lt->lt_certfile );
2302                         } else if ( ctx->tc_certdb_slot ) {
2303                                 tmp_certname = PR_smprintf( TLSM_CERTDB_DESC_FMT ":%s", ctx->tc_unique, lt->lt_certfile );
2304                         } else {
2305                                 tmp_certname = PR_smprintf( "%s", lt->lt_certfile );
2306                         }
2307
2308                         ctx->tc_certificate = PK11_FindCertFromNickname( tmp_certname, SSL_RevealPinArg( ctx->tc_model ) );
2309                         PR_smprintf_free( tmp_certname );
2310
2311                         if ( !ctx->tc_certificate ) {
2312                                 PRErrorCode errcode = PR_GetError();
2313                                 Debug( LDAP_DEBUG_ANY,
2314                                            "TLS: error: the certificate '%s' could not be found in the database - error %d:%s.\n",
2315                                            lt->lt_certfile, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
2316                         }
2317                 }
2318
2319                 /* fallback to PEM module (lt_certfile is filename) */
2320                 if ( !ctx->tc_certificate ) {
2321                         if ( !pem_module && tlsm_init_pem_module() ) {
2322                                 int pem_errcode = PORT_GetError();
2323                                 Debug( LDAP_DEBUG_ANY,
2324                                            "TLS: fallback to PEM impossible, module cannot be loaded - error %d:%s.\n",
2325                                            pem_errcode, PR_ErrorToString( pem_errcode, PR_LANGUAGE_I_DEFAULT ), 0 );
2326                                 return -1;
2327                         }
2328
2329                         /* this sets ctx->tc_certificate to the correct value */
2330                         if ( !tlsm_add_cert_from_file( ctx, lt->lt_certfile, PR_FALSE ) ) {
2331                                 ctx->tc_using_pem = PR_TRUE;
2332                         }
2333                 }
2334
2335                 if ( ctx->tc_certificate ) {
2336                         Debug( LDAP_DEBUG_ANY,
2337                                    "TLS: certificate '%s' successfully loaded from %s.\n", lt->lt_certfile,
2338                                    ctx->tc_using_pem ? "PEM file" : "moznss database", 0);
2339                 } else {
2340                         return -1;
2341                 }
2342         }
2343
2344         if ( lt->lt_keyfile ) {
2345                 /* if using the PEM module, load the PEM file specified by lt_keyfile */
2346                 /* otherwise, assume this is the pininfo for the key */
2347                 if ( ctx->tc_using_pem ) {
2348                         int rc = tlsm_add_key_from_file( ctx, lt->lt_keyfile );
2349                         if ( rc ) {
2350                                 return rc;
2351                         }
2352                 } else {
2353                         if ( ctx->tc_pin_file )
2354                                 PL_strfree( ctx->tc_pin_file );
2355                         ctx->tc_pin_file = PL_strdup( lt->lt_keyfile );
2356                 }
2357         }
2358
2359         /* Set up callbacks for use by clients */
2360         if ( !ctx->tc_is_server ) {
2361                 if ( SSL_OptionSet( ctx->tc_model, SSL_NO_CACHE, PR_TRUE ) != SECSuccess ) {
2362                         PRErrorCode err = PR_GetError();
2363                         Debug( LDAP_DEBUG_ANY, 
2364                                "TLS: error: could not set nocache option for moznss - error %d:%s\n",
2365                                err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL );
2366                         return -1;
2367                 }
2368
2369                 if ( SSL_BadCertHook( ctx->tc_model, tlsm_bad_cert_handler, ctx ) != SECSuccess ) {
2370                         PRErrorCode err = PR_GetError();
2371                         Debug( LDAP_DEBUG_ANY, 
2372                                "TLS: error: could not set bad cert handler for moznss - error %d:%s\n",
2373                                err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL );
2374                         return -1;
2375                 }
2376
2377                 /* 
2378                    since a cert has been specified, assume the client wants to do cert auth
2379                 */
2380                 if ( ctx->tc_certificate ) {
2381                         if ( tlsm_clientauth_init( ctx ) ) {
2382                                 Debug( LDAP_DEBUG_ANY, 
2383                                        "TLS: error: unable to set up client certificate authentication using '%s'\n",
2384                                        tlsm_ctx_subject_name(ctx), 0, 0 );
2385                                 return -1;
2386                         }
2387                 }
2388         } else { /* set up secure server */
2389                 SSLKEAType certKEA;
2390                 SECStatus status;
2391
2392                 /* must have a certificate for the server to use */
2393                 if ( !ctx->tc_certificate ) {
2394                         Debug( LDAP_DEBUG_ANY, 
2395                                "TLS: error: no server certificate: must specify a certificate for the server to use\n",
2396                                0, 0, 0 );
2397                         return -1;
2398                 }
2399
2400                 if ( tlsm_find_and_verify_cert_key( ctx ) ) {
2401                         Debug( LDAP_DEBUG_ANY, 
2402                                "TLS: error: unable to find and verify server's cert and key for certificate %s\n",
2403                                tlsm_ctx_subject_name(ctx), 0, 0 );
2404                         return -1;
2405                 }
2406
2407                 /* configure the socket to be a secure server socket */
2408                 certKEA = NSS_FindCertKEAType( ctx->tc_certificate );
2409                 status = SSL_ConfigSecureServer( ctx->tc_model, ctx->tc_certificate, ctx->tc_private_key, certKEA );
2410
2411                 if ( SECSuccess != status ) {
2412                         PRErrorCode err = PR_GetError();
2413                         Debug( LDAP_DEBUG_ANY, 
2414                                "TLS: error: unable to configure secure server using certificate '%s' - error %d:%s\n",
2415                                tlsm_ctx_subject_name(ctx), err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ) );
2416                         return -1;
2417                 }
2418         }
2419
2420         /* Callback for authenticating certificate */
2421         if ( SSL_AuthCertificateHook( ctx->tc_model, tlsm_auth_cert_handler,
2422                                   ctx ) != SECSuccess ) {
2423                 PRErrorCode err = PR_GetError();
2424                 Debug( LDAP_DEBUG_ANY, 
2425                        "TLS: error: could not set auth cert handler for moznss - error %d:%s\n",
2426                        err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL );
2427                 return -1;
2428         }
2429
2430         if ( SSL_HandshakeCallback( ctx->tc_model, tlsm_handshake_complete_cb, ctx ) ) {
2431                 PRErrorCode err = PR_GetError();
2432                 Debug( LDAP_DEBUG_ANY, 
2433                        "TLS: error: could not set handshake callback for moznss - error %d:%s\n",
2434                        err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL );
2435                 return -1;
2436         }
2437
2438         tlsm_free_config( ctx->tc_config );
2439         ctx->tc_config = NULL;
2440
2441         return 0;
2442 }
2443
2444 struct tls_data {
2445         tlsm_session            *session;
2446         Sockbuf_IO_Desc         *sbiod;
2447         /* there seems to be no portable way to determine if the
2448            sockbuf sd has been set to nonblocking mode - the
2449            call to ber_pvt_socket_set_nonblock() takes place
2450            before the tls socket is set up, so we cannot
2451            intercept that call either.
2452            On systems where fcntl is available, we can just
2453            F_GETFL and test for O_NONBLOCK.  On other systems,
2454            we will just see if the IO op returns EAGAIN or EWOULDBLOCK,
2455            and just set this flag */
2456         PRBool              nonblock;
2457         /*
2458          * NSS tries hard to be backwards compatible with SSLv2 clients, or
2459          * clients that send an SSLv2 client hello.  This message is not
2460          * tagged in any way, so NSS has no way to know if the incoming
2461          * message is a valid SSLv2 client hello or just some bogus data
2462          * (or cleartext LDAP).  We store the first byte read from the
2463          * client here.  The most common case will be a client sending
2464          * LDAP data instead of SSL encrypted LDAP data.  This can happen,
2465          * for example, if using ldapsearch -Z - if the starttls fails,
2466          * the client will fallback to plain cleartext LDAP.  So if we
2467          * see that the firstbyte is a valid LDAP tag, we can be
2468          * pretty sure this is happening.
2469          */
2470         ber_tag_t           firsttag;
2471         /*
2472          * NSS doesn't return SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE, etc.
2473          * when it is blocked, so we have to set a flag in the wrapped send
2474          * and recv calls that tells us what operation NSS was last blocked
2475          * on
2476          */
2477 #define TLSM_READ  1
2478 #define TLSM_WRITE 2
2479         int io_flag;
2480 };
2481
2482 static struct tls_data *
2483 tlsm_get_pvt_tls_data( PRFileDesc *fd )
2484 {
2485         struct tls_data         *p;
2486         PRFileDesc *myfd;
2487
2488         if ( !fd ) {
2489                 return NULL;
2490         }
2491
2492         myfd = PR_GetIdentitiesLayer( fd, tlsm_layer_id );
2493
2494         if ( !myfd ) {
2495                 return NULL;
2496         }
2497
2498         p = (struct tls_data *)myfd->secret;
2499
2500         return p;
2501 }
2502
2503 static int
2504 tlsm_is_non_ssl_message( PRFileDesc *fd, ber_tag_t *thebyte )
2505 {
2506         struct tls_data         *p;
2507
2508         if ( thebyte ) {
2509                 *thebyte = LBER_DEFAULT;
2510         }
2511
2512         p = tlsm_get_pvt_tls_data( fd );
2513         if ( p == NULL || p->sbiod == NULL ) {
2514                 return 0;
2515         }
2516
2517         if ( p->firsttag == LBER_SEQUENCE ) {
2518                 if ( thebyte ) {
2519                         *thebyte = p->firsttag;
2520                 }
2521                 return 1;
2522         }
2523
2524         return 0;
2525 }
2526
2527 static tls_session *
2528 tlsm_session_new ( tls_ctx * ctx, int is_server )
2529 {
2530         tlsm_ctx *c = (tlsm_ctx *)ctx;
2531         tlsm_session *session;
2532         PRFileDesc *fd;
2533         PRStatus status;
2534         int rc;
2535
2536         c->tc_is_server = is_server;
2537         LDAP_MUTEX_LOCK( &tlsm_init_mutex );
2538         status = PR_CallOnceWithArg( &c->tc_callonce, tlsm_deferred_ctx_init, c );
2539         LDAP_MUTEX_UNLOCK( &tlsm_init_mutex );
2540         if ( PR_SUCCESS != status ) {
2541                 PRErrorCode err = PR_GetError();
2542                 Debug( LDAP_DEBUG_ANY, 
2543                        "TLS: error: could not initialize moznss security context - error %d:%s\n",
2544                        err, PR_ErrorToString(err, PR_LANGUAGE_I_DEFAULT), NULL );
2545                 return NULL;
2546         }
2547
2548         fd = PR_CreateIOLayerStub( tlsm_layer_id, &tlsm_PR_methods );
2549         if ( !fd ) {
2550                 return NULL;
2551         }
2552
2553         session = SSL_ImportFD( c->tc_model, fd );
2554         if ( !session ) {
2555                 PR_DELETE( fd );
2556                 return NULL;
2557         }
2558
2559         rc = SSL_ResetHandshake( session, is_server );
2560         if ( rc ) {
2561                 PRErrorCode err = PR_GetError();
2562                 Debug( LDAP_DEBUG_TRACE, 
2563                            "TLS: error: new session - reset handshake failure %d - error %d:%s\n",
2564                            rc, err,
2565                            err ? PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ) : "unknown" );
2566                 PR_DELETE( fd );
2567                 PR_Close( session );
2568                 session = NULL;
2569         }
2570
2571         return (tls_session *)session;
2572
2573
2574 static int
2575 tlsm_session_accept_or_connect( tls_session *session, int is_accept )
2576 {
2577         tlsm_session *s = (tlsm_session *)session;
2578         int rc;
2579         const char *op = is_accept ? "accept" : "connect";
2580
2581         if ( pem_module ) {
2582                 LDAP_MUTEX_LOCK( &tlsm_pem_mutex );
2583         }
2584         rc = SSL_ForceHandshake( s );
2585         if ( pem_module ) {
2586                 LDAP_MUTEX_UNLOCK( &tlsm_pem_mutex );
2587         }
2588         if ( rc ) {
2589                 PRErrorCode err = PR_GetError();
2590                 rc = -1;
2591                 if ( err == PR_WOULD_BLOCK_ERROR ) {
2592                         ber_tag_t thetag = LBER_DEFAULT;
2593                         /* see if we are blocked because of a bogus packet */
2594                         if ( tlsm_is_non_ssl_message( s, &thetag ) ) { /* see if we received a non-SSL message */
2595                                 Debug( LDAP_DEBUG_ANY, 
2596                                            "TLS: error: %s - error - received non-SSL message [0x%x]\n",
2597                                            op, (unsigned int)thetag, 0 );
2598                                 /* reset error to something more descriptive */
2599                                 PR_SetError( SSL_ERROR_RX_MALFORMED_HELLO_REQUEST, EPROTO );
2600                         }
2601                 } else {
2602                         Debug( LDAP_DEBUG_ANY, 
2603                                    "TLS: error: %s - force handshake failure: errno %d - moznss error %d\n",
2604                                    op, errno, err );
2605                 }
2606         }
2607
2608         return rc;
2609 }
2610 static int
2611 tlsm_session_accept( tls_session *session )
2612 {
2613         return tlsm_session_accept_or_connect( session, 1 );
2614 }
2615
2616 static int
2617 tlsm_session_connect( LDAP *ld, tls_session *session )
2618 {
2619         return tlsm_session_accept_or_connect( session, 0 );
2620 }
2621
2622 static int
2623 tlsm_session_upflags( Sockbuf *sb, tls_session *session, int rc )
2624 {
2625         int prerror = PR_GetError();
2626
2627         if ( ( prerror == PR_PENDING_INTERRUPT_ERROR ) || ( prerror == PR_WOULD_BLOCK_ERROR ) ) {
2628                 tlsm_session *s = (tlsm_session *)session;
2629                 struct tls_data *p = tlsm_get_pvt_tls_data( s );
2630
2631                 if ( p && ( p->io_flag == TLSM_READ ) ) {
2632                         sb->sb_trans_needs_read = 1;
2633                         return 1;
2634                 } else if ( p && ( p->io_flag == TLSM_WRITE ) ) {
2635                         sb->sb_trans_needs_write = 1;
2636                         return 1;
2637                 }
2638         }
2639
2640         return 0;
2641 }
2642
2643 static char *
2644 tlsm_session_errmsg( tls_session *sess, int rc, char *buf, size_t len )
2645 {
2646         int i;
2647         int prerror = PR_GetError();
2648
2649         i = PR_GetErrorTextLength();
2650         if ( i > len ) {
2651                 char *msg = LDAP_MALLOC( i+1 );
2652                 PR_GetErrorText( msg );
2653                 memcpy( buf, msg, len );
2654                 LDAP_FREE( msg );
2655         } else if ( i ) {
2656                 PR_GetErrorText( buf );
2657         } else if ( prerror ) {
2658                 i = PR_snprintf( buf, len, "TLS error %d:%s",
2659                                                  prerror, PR_ErrorToString( prerror, PR_LANGUAGE_I_DEFAULT ) );
2660         }
2661
2662         return ( i > 0 ) ? buf : NULL;
2663 }
2664
2665 static int
2666 tlsm_session_my_dn( tls_session *session, struct berval *der_dn )
2667 {
2668         tlsm_session *s = (tlsm_session *)session;
2669         CERTCertificate *cert;
2670
2671         cert = SSL_LocalCertificate( s );
2672         if (!cert) return LDAP_INVALID_CREDENTIALS;
2673
2674         der_dn->bv_val = (char *)cert->derSubject.data;
2675         der_dn->bv_len = cert->derSubject.len;
2676         CERT_DestroyCertificate( cert );
2677         return 0;
2678 }
2679
2680 static int
2681 tlsm_session_peer_dn( tls_session *session, struct berval *der_dn )
2682 {
2683         tlsm_session *s = (tlsm_session *)session;
2684         CERTCertificate *cert;
2685
2686         cert = SSL_PeerCertificate( s );
2687         if (!cert) return LDAP_INVALID_CREDENTIALS;
2688         
2689         der_dn->bv_val = (char *)cert->derSubject.data;
2690         der_dn->bv_len = cert->derSubject.len;
2691         CERT_DestroyCertificate( cert );
2692         return 0;
2693 }
2694
2695 /* what kind of hostname were we given? */
2696 #define IS_DNS  0
2697 #define IS_IP4  1
2698 #define IS_IP6  2
2699
2700 static int
2701 tlsm_session_chkhost( LDAP *ld, tls_session *session, const char *name_in )
2702 {
2703         tlsm_session *s = (tlsm_session *)session;
2704         CERTCertificate *cert;
2705         const char *name, *domain = NULL, *ptr;
2706         int ret, ntype = IS_DNS, nlen, dlen;
2707 #ifdef LDAP_PF_INET6
2708         struct in6_addr addr;
2709 #else
2710         struct in_addr addr;
2711 #endif
2712         SECItem altname;
2713         SECStatus rv;
2714
2715         if( ldap_int_hostname &&
2716                 ( !name_in || !strcasecmp( name_in, "localhost" ) ) )
2717         {
2718                 name = ldap_int_hostname;
2719         } else {
2720                 name = name_in;
2721         }
2722         nlen = strlen( name );
2723
2724         cert = SSL_PeerCertificate( s );
2725         if (!cert) {
2726                 Debug( LDAP_DEBUG_ANY,
2727                         "TLS: unable to get peer certificate.\n",
2728                         0, 0, 0 );
2729                 /* if this was a fatal condition, things would have
2730                  * aborted long before now.
2731                  */
2732                 return LDAP_SUCCESS;
2733         }
2734
2735 #ifdef LDAP_PF_INET6
2736         if (inet_pton(AF_INET6, name, &addr)) {
2737                 ntype = IS_IP6;
2738         } else 
2739 #endif
2740         if ((ptr = strrchr(name, '.')) && isdigit((unsigned char)ptr[1])) {
2741                 if (inet_aton(name, (struct in_addr *)&addr)) ntype = IS_IP4;
2742         }
2743         if (ntype == IS_DNS ) {
2744                 domain = strchr( name, '.' );
2745                 if ( domain )
2746                         dlen = nlen - ( domain - name );
2747         }
2748
2749         ret = LDAP_LOCAL_ERROR;
2750
2751         rv = CERT_FindCertExtension( cert, SEC_OID_X509_SUBJECT_ALT_NAME,
2752                 &altname );
2753         if ( rv == SECSuccess && altname.data ) {
2754                 PRArenaPool *arena;
2755                 CERTGeneralName *names, *cur;
2756
2757                 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2758                 if ( !arena ) {
2759                         ret = LDAP_NO_MEMORY;
2760                         goto fail;
2761                 }
2762
2763                 names = cur = CERT_DecodeAltNameExtension(arena, &altname);
2764                 if ( !cur )
2765                         goto altfail;
2766
2767                 do {
2768                         char *host;
2769                         int hlen;
2770
2771                         /* ignore empty */
2772                         if ( !cur->name.other.len ) continue;
2773
2774                         host = (char *)cur->name.other.data;
2775                         hlen = cur->name.other.len;
2776
2777                         if ( cur->type == certDNSName ) {
2778                                 if ( ntype != IS_DNS )  continue;
2779
2780                                 /* is this an exact match? */
2781                                 if ( nlen == hlen && !strncasecmp( name, host, nlen )) {
2782                                         ret = LDAP_SUCCESS;
2783                                         break;
2784                                 }
2785
2786                                 /* is this a wildcard match? */
2787                                 if ( domain && host[0] == '*' && host[1] == '.' &&
2788                                         dlen == hlen-1 && !strncasecmp( domain, host+1, dlen )) {
2789                                         ret = LDAP_SUCCESS;
2790                                         break;
2791                                 }
2792                         } else if ( cur->type == certIPAddress ) {
2793                                 if ( ntype == IS_DNS )  continue;
2794                                 
2795 #ifdef LDAP_PF_INET6
2796                                 if (ntype == IS_IP6 && hlen != sizeof(struct in6_addr)) {
2797                                         continue;
2798                                 } else
2799 #endif
2800                                 if (ntype == IS_IP4 && hlen != sizeof(struct in_addr)) {
2801                                         continue;
2802                                 }
2803                                 if (!memcmp(host, &addr, hlen)) {
2804                                         ret = LDAP_SUCCESS;
2805                                         break;
2806                                 }
2807                         }
2808                 } while (( cur = CERT_GetNextGeneralName( cur )) != names );
2809 altfail:
2810                 PORT_FreeArena( arena, PR_FALSE );
2811                 SECITEM_FreeItem( &altname, PR_FALSE );
2812         }
2813         /* no altnames matched, try the CN */
2814         if ( ret != LDAP_SUCCESS ) {
2815                 /* find the last CN */
2816                 CERTRDN *rdn, **rdns;
2817                 CERTAVA *lastava = NULL;
2818                 char buf[2048];
2819
2820                 buf[0] = '\0';
2821                 rdns = cert->subject.rdns;
2822                 while ( rdns && ( rdn = *rdns++ )) {
2823                         CERTAVA *ava, **avas = rdn->avas;
2824                         while ( avas && ( ava = *avas++ )) {
2825                                 if ( CERT_GetAVATag( ava ) == SEC_OID_AVA_COMMON_NAME )
2826                                         lastava = ava;
2827                         }
2828                 }
2829                 if ( lastava ) {
2830                         SECItem *av = CERT_DecodeAVAValue( &lastava->value );
2831                         if ( av ) {
2832                                 if ( av->len == nlen && !strncasecmp( name, (char *)av->data, nlen )) {
2833                                         ret = LDAP_SUCCESS;
2834                                 } else if ( av->data[0] == '*' && av->data[1] == '.' &&
2835                                         domain && dlen == av->len - 1 && !strncasecmp( domain,
2836                                                 (char *)(av->data+1), dlen )) {
2837                                         ret = LDAP_SUCCESS;
2838                                 } else {
2839                                         int len = av->len;
2840                                         if ( len >= sizeof(buf) )
2841                                                 len = sizeof(buf)-1;
2842                                         memcpy( buf, av->data, len );
2843                                         buf[len] = '\0';
2844                                 }
2845                                 SECITEM_FreeItem( av, PR_TRUE );
2846                         }
2847                 }
2848                 if ( ret != LDAP_SUCCESS ) {
2849                         Debug( LDAP_DEBUG_ANY, "TLS: hostname (%s) does not match "
2850                                 "common name in certificate (%s).\n", 
2851                                 name, buf, 0 );
2852                         ret = LDAP_CONNECT_ERROR;
2853                         if ( ld->ld_error ) {
2854                                 LDAP_FREE( ld->ld_error );
2855                         }
2856                         ld->ld_error = LDAP_STRDUP(
2857                                 _("TLS: hostname does not match CN in peer certificate"));
2858                 }
2859         }
2860
2861 fail:
2862         CERT_DestroyCertificate( cert );
2863         return ret;
2864 }
2865
2866 static int
2867 tlsm_session_strength( tls_session *session )
2868 {
2869         tlsm_session *s = (tlsm_session *)session;
2870         int rc, keySize;
2871
2872         rc = SSL_SecurityStatus( s, NULL, NULL, NULL, &keySize,
2873                 NULL, NULL );
2874         return rc ? 0 : keySize;
2875 }
2876
2877 /*
2878  * TLS support for LBER Sockbufs
2879  */
2880
2881 static PRStatus PR_CALLBACK
2882 tlsm_PR_Close(PRFileDesc *fd)
2883 {
2884         int rc = PR_SUCCESS;
2885
2886         /* we don't need to actually close anything here, just
2887            pop our io layer off the stack */
2888         fd->secret = NULL; /* must have been freed before calling PR_Close */
2889         if ( fd->lower ) {
2890                 fd = PR_PopIOLayer( fd, tlsm_layer_id );
2891                 /* if we are not the last layer, pass the close along */
2892                 if ( fd ) {
2893                         if ( fd->dtor ) {
2894                                 fd->dtor( fd );
2895                         }
2896                         rc = fd->methods->close( fd );
2897                 }
2898         } else {
2899                 /* we are the last layer - just call our dtor */
2900                 fd->dtor(fd);
2901         }
2902
2903         return rc;
2904 }
2905
2906 static PRStatus PR_CALLBACK
2907 tlsm_PR_Shutdown(PRFileDesc *fd, PRShutdownHow how)
2908 {
2909         int rc = PR_SUCCESS;
2910
2911         if ( fd->lower ) {
2912                 rc = PR_Shutdown( fd->lower, how );
2913         }
2914
2915         return rc;
2916 }
2917
2918 static int PR_CALLBACK
2919 tlsm_PR_Recv(PRFileDesc *fd, void *buf, PRInt32 len, PRIntn flags,
2920          PRIntervalTime timeout)
2921 {
2922         struct tls_data         *p;
2923         int rc;
2924
2925         if ( buf == NULL || len <= 0 ) return 0;
2926
2927         p = tlsm_get_pvt_tls_data( fd );
2928
2929         if ( p == NULL || p->sbiod == NULL ) {
2930                 return 0;
2931         }
2932
2933         rc = LBER_SBIOD_READ_NEXT( p->sbiod, buf, len );
2934         if (rc <= 0) {
2935                 tlsm_map_error( errno );
2936                 if ( errno == EAGAIN || errno == EWOULDBLOCK ) {
2937                         p->nonblock = PR_TRUE; /* fd is using non-blocking io */
2938                 } else if ( errno ) { /* real error */
2939                         Debug( LDAP_DEBUG_TRACE, 
2940                                "TLS: error: tlsm_PR_Recv returned %d - error %d:%s\n",
2941                                rc, errno, STRERROR(errno) );
2942                 }
2943         } else if ( ( rc > 0 ) && ( len > 0 ) && ( p->firsttag == LBER_DEFAULT ) ) {
2944                 p->firsttag = (ber_tag_t)*((char *)buf);
2945         }
2946         p->io_flag = TLSM_READ;
2947
2948         return rc;
2949 }
2950
2951 static int PR_CALLBACK
2952 tlsm_PR_Send(PRFileDesc *fd, const void *buf, PRInt32 len, PRIntn flags,
2953          PRIntervalTime timeout)
2954 {
2955         struct tls_data         *p;
2956         int rc;
2957
2958         if ( buf == NULL || len <= 0 ) return 0;
2959
2960         p = tlsm_get_pvt_tls_data( fd );
2961
2962         if ( p == NULL || p->sbiod == NULL ) {
2963                 return 0;
2964         }
2965
2966         rc = LBER_SBIOD_WRITE_NEXT( p->sbiod, (char *)buf, len );
2967         if (rc <= 0) {
2968                 tlsm_map_error( errno );
2969                 if ( errno == EAGAIN || errno == EWOULDBLOCK ) {
2970                         p->nonblock = PR_TRUE;
2971                 } else if ( errno ) { /* real error */
2972                         Debug( LDAP_DEBUG_TRACE, 
2973                                "TLS: error: tlsm_PR_Send returned %d - error %d:%s\n",
2974                                rc, errno, STRERROR(errno) );
2975                 }
2976         }
2977         p->io_flag = TLSM_WRITE;
2978
2979         return rc;
2980 }
2981
2982 static int PR_CALLBACK
2983 tlsm_PR_Read(PRFileDesc *fd, void *buf, PRInt32 len)
2984 {
2985         return tlsm_PR_Recv( fd, buf, len, 0, PR_INTERVAL_NO_TIMEOUT );
2986 }
2987
2988 static int PR_CALLBACK
2989 tlsm_PR_Write(PRFileDesc *fd, const void *buf, PRInt32 len)
2990 {
2991         return tlsm_PR_Send( fd, buf, len, 0, PR_INTERVAL_NO_TIMEOUT );
2992 }
2993
2994 static PRStatus PR_CALLBACK
2995 tlsm_PR_GetPeerName(PRFileDesc *fd, PRNetAddr *addr)
2996 {
2997         struct tls_data         *p;
2998         ber_socklen_t len;
2999
3000         p = tlsm_get_pvt_tls_data( fd );
3001
3002         if ( p == NULL || p->sbiod == NULL ) {
3003                 return PR_FAILURE;
3004         }
3005         len = sizeof(PRNetAddr);
3006         return getpeername( p->sbiod->sbiod_sb->sb_fd, (struct sockaddr *)addr, &len );
3007 }
3008
3009 static PRStatus PR_CALLBACK
3010 tlsm_PR_GetSocketOption(PRFileDesc *fd, PRSocketOptionData *data)
3011 {
3012         struct tls_data         *p;
3013         p = tlsm_get_pvt_tls_data( fd );
3014
3015         if ( p == NULL || data == NULL ) {
3016                 return PR_FAILURE;
3017         }
3018
3019         /* only the nonblocking option is supported at this time
3020            MozNSS SSL code needs it */
3021         if ( data->option != PR_SockOpt_Nonblocking ) {
3022                 PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
3023                 return PR_FAILURE;
3024         }
3025 #ifdef HAVE_FCNTL
3026         int flags = fcntl( p->sbiod->sbiod_sb->sb_fd, F_GETFL );
3027         data->value.non_blocking = (flags & O_NONBLOCK) ? PR_TRUE : PR_FALSE;           
3028 #else /* punt :P */
3029         data->value.non_blocking = p->nonblock;
3030 #endif
3031         return PR_SUCCESS;
3032 }
3033
3034 static PRStatus PR_CALLBACK
3035 tlsm_PR_prs_unimp()
3036 {
3037     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
3038     return PR_FAILURE;
3039 }
3040
3041 static PRFileDesc * PR_CALLBACK
3042 tlsm_PR_pfd_unimp()
3043 {
3044     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
3045     return NULL;
3046 }
3047
3048 static PRInt16 PR_CALLBACK
3049 tlsm_PR_i16_unimp()
3050 {
3051     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
3052     return SECFailure;
3053 }
3054
3055 static PRInt32 PR_CALLBACK
3056 tlsm_PR_i32_unimp()
3057 {
3058     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
3059     return SECFailure;
3060 }
3061
3062 static PRInt64 PR_CALLBACK
3063 tlsm_PR_i64_unimp()
3064 {
3065     PRInt64 res;
3066
3067     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
3068     LL_I2L(res, -1L);
3069     return res;
3070 }
3071
3072 static const PRIOMethods tlsm_PR_methods = {
3073     PR_DESC_LAYERED,
3074     tlsm_PR_Close,                      /* close        */
3075     tlsm_PR_Read,                       /* read         */
3076     tlsm_PR_Write,                      /* write        */
3077     tlsm_PR_i32_unimp,          /* available    */
3078     tlsm_PR_i64_unimp,          /* available64  */
3079     tlsm_PR_prs_unimp,          /* fsync        */
3080     tlsm_PR_i32_unimp,          /* seek         */
3081     tlsm_PR_i64_unimp,          /* seek64       */
3082     tlsm_PR_prs_unimp,          /* fileInfo     */
3083     tlsm_PR_prs_unimp,          /* fileInfo64   */
3084     tlsm_PR_i32_unimp,          /* writev       */
3085     tlsm_PR_prs_unimp,          /* connect      */
3086     tlsm_PR_pfd_unimp,          /* accept       */
3087     tlsm_PR_prs_unimp,          /* bind         */
3088     tlsm_PR_prs_unimp,          /* listen       */
3089     (PRShutdownFN)tlsm_PR_Shutdown,                     /* shutdown     */
3090     tlsm_PR_Recv,                       /* recv         */
3091     tlsm_PR_Send,                       /* send         */
3092     tlsm_PR_i32_unimp,          /* recvfrom     */
3093     tlsm_PR_i32_unimp,          /* sendto       */
3094     (PRPollFN)tlsm_PR_i16_unimp,        /* poll         */
3095     tlsm_PR_i32_unimp,          /* acceptread   */
3096     tlsm_PR_i32_unimp,          /* transmitfile */
3097     tlsm_PR_prs_unimp,          /* getsockname  */
3098     tlsm_PR_GetPeerName,        /* getpeername  */
3099     tlsm_PR_i32_unimp,          /* getsockopt   OBSOLETE */
3100     tlsm_PR_i32_unimp,          /* setsockopt   OBSOLETE */
3101     tlsm_PR_GetSocketOption,            /* getsocketoption   */
3102     tlsm_PR_i32_unimp,          /* setsocketoption   */
3103     tlsm_PR_i32_unimp,          /* Send a (partial) file with header/trailer*/
3104     (PRConnectcontinueFN)tlsm_PR_prs_unimp,             /* connectcontinue */
3105     tlsm_PR_i32_unimp,          /* reserved for future use */
3106     tlsm_PR_i32_unimp,          /* reserved for future use */
3107     tlsm_PR_i32_unimp,          /* reserved for future use */
3108     tlsm_PR_i32_unimp           /* reserved for future use */
3109 };
3110
3111 /*
3112  * Initialize TLS subsystem. Should be called only once.
3113  * See tlsm_deferred_init for the bulk of the init process
3114  */
3115 static int
3116 tlsm_init( void )
3117 {
3118         char *nofork = PR_GetEnv( "NSS_STRICT_NOFORK" );
3119
3120         PR_Init(0, 0, 0);
3121
3122         tlsm_layer_id = PR_GetUniqueIdentity( "OpenLDAP" );
3123
3124         /*
3125          * There are some applications that acquire a crypto context in the parent process
3126          * and expect that crypto context to work after a fork().  This does not work
3127          * with NSS using strict PKCS11 compliance mode.  We set this environment
3128          * variable here to tell the software encryption module/token to allow crypto
3129          * contexts to persist across a fork().  However, if you are using some other
3130          * module or encryption device that supports and expects full PKCS11 semantics,
3131          * the only recourse is to rewrite the application with atfork() handlers to save
3132          * the crypto context in the parent and restore (and SECMOD_RestartModules) the
3133          * context in the child.
3134          */
3135         if ( !nofork ) {
3136                 /* will leak one time */
3137                 char *noforkenvvar = PL_strdup( "NSS_STRICT_NOFORK=DISABLED" );
3138                 PR_SetEnv( noforkenvvar );
3139         }
3140
3141         return 0;
3142 }
3143
3144 static int
3145 tlsm_sb_setup( Sockbuf_IO_Desc *sbiod, void *arg )
3146 {
3147         struct tls_data         *p;
3148         tlsm_session    *session = arg;
3149         PRFileDesc *fd;
3150
3151         assert( sbiod != NULL );
3152
3153         p = LBER_MALLOC( sizeof( *p ) );
3154         if ( p == NULL ) {
3155                 return -1;
3156         }
3157
3158         fd = PR_GetIdentitiesLayer( session, tlsm_layer_id );
3159         if ( !fd ) {
3160                 LBER_FREE( p );
3161                 return -1;
3162         }
3163
3164         fd->secret = (PRFilePrivate *)p;
3165         p->session = session;
3166         p->sbiod = sbiod;
3167         p->firsttag = LBER_DEFAULT;
3168         sbiod->sbiod_pvt = p;
3169         return 0;
3170 }
3171
3172 static int
3173 tlsm_sb_remove( Sockbuf_IO_Desc *sbiod )
3174 {
3175         struct tls_data         *p;
3176         
3177         assert( sbiod != NULL );
3178         assert( sbiod->sbiod_pvt != NULL );
3179
3180         p = (struct tls_data *)sbiod->sbiod_pvt;
3181         PR_Close( p->session );
3182         LBER_FREE( sbiod->sbiod_pvt );
3183         sbiod->sbiod_pvt = NULL;
3184         return 0;
3185 }
3186
3187 static int
3188 tlsm_sb_close( Sockbuf_IO_Desc *sbiod )
3189 {
3190         struct tls_data         *p;
3191         
3192         assert( sbiod != NULL );
3193         assert( sbiod->sbiod_pvt != NULL );
3194
3195         p = (struct tls_data *)sbiod->sbiod_pvt;
3196         PR_Shutdown( p->session, PR_SHUTDOWN_BOTH );
3197         return 0;
3198 }
3199
3200 static int
3201 tlsm_sb_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
3202 {
3203         struct tls_data         *p;
3204         
3205         assert( sbiod != NULL );
3206         assert( sbiod->sbiod_pvt != NULL );
3207
3208         p = (struct tls_data *)sbiod->sbiod_pvt;
3209         
3210         if ( opt == LBER_SB_OPT_GET_SSL ) {
3211                 *((tlsm_session **)arg) = p->session;
3212                 return 1;
3213                 
3214         } else if ( opt == LBER_SB_OPT_DATA_READY ) {
3215                 if ( p && ( SSL_DataPending( p->session ) > 0 ) ) {
3216                         return 1;
3217                 }
3218                 
3219         }
3220         
3221         return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
3222 }
3223
3224 static ber_slen_t
3225 tlsm_sb_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
3226 {
3227         struct tls_data         *p;
3228         ber_slen_t              ret;
3229         int                     err;
3230
3231         assert( sbiod != NULL );
3232         assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
3233
3234         p = (struct tls_data *)sbiod->sbiod_pvt;
3235
3236         ret = PR_Recv( p->session, buf, len, 0, PR_INTERVAL_NO_TIMEOUT );
3237         if ( ret < 0 ) {
3238                 err = PR_GetError();
3239                 if ( err == PR_PENDING_INTERRUPT_ERROR || err == PR_WOULD_BLOCK_ERROR ) {
3240                         sbiod->sbiod_sb->sb_trans_needs_read = 1;
3241                         sock_errset(EWOULDBLOCK);
3242                 }
3243         } else {
3244                 sbiod->sbiod_sb->sb_trans_needs_read = 0;
3245         }
3246         return ret;
3247 }
3248
3249 static ber_slen_t
3250 tlsm_sb_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
3251 {
3252         struct tls_data         *p;
3253         ber_slen_t              ret;
3254         int                     err;
3255
3256         assert( sbiod != NULL );
3257         assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
3258
3259         p = (struct tls_data *)sbiod->sbiod_pvt;
3260
3261         ret = PR_Send( p->session, (char *)buf, len, 0, PR_INTERVAL_NO_TIMEOUT );
3262         if ( ret < 0 ) {
3263                 err = PR_GetError();
3264                 if ( err == PR_PENDING_INTERRUPT_ERROR || err == PR_WOULD_BLOCK_ERROR ) {
3265                         sbiod->sbiod_sb->sb_trans_needs_write = 1;
3266                         sock_errset(EWOULDBLOCK);
3267                         ret = 0;
3268                 }
3269         } else {
3270                 sbiod->sbiod_sb->sb_trans_needs_write = 0;
3271         }
3272         return ret;
3273 }
3274
3275 static Sockbuf_IO tlsm_sbio =
3276 {
3277         tlsm_sb_setup,          /* sbi_setup */
3278         tlsm_sb_remove,         /* sbi_remove */
3279         tlsm_sb_ctrl,           /* sbi_ctrl */
3280         tlsm_sb_read,           /* sbi_read */
3281         tlsm_sb_write,          /* sbi_write */
3282         tlsm_sb_close           /* sbi_close */
3283 };
3284
3285 tls_impl ldap_int_tls_impl = {
3286         "MozNSS",
3287
3288         tlsm_init,
3289         tlsm_destroy,
3290
3291         tlsm_ctx_new,
3292         tlsm_ctx_ref,
3293         tlsm_ctx_free,
3294         tlsm_ctx_init,
3295
3296         tlsm_session_new,
3297         tlsm_session_connect,
3298         tlsm_session_accept,
3299         tlsm_session_upflags,
3300         tlsm_session_errmsg,
3301         tlsm_session_my_dn,
3302         tlsm_session_peer_dn,
3303         tlsm_session_chkhost,
3304         tlsm_session_strength,
3305
3306         &tlsm_sbio,
3307
3308 #ifdef LDAP_R_COMPILE
3309         tlsm_thr_init,
3310 #else
3311         NULL,
3312 #endif
3313
3314         0
3315 };
3316
3317 #endif /* HAVE_MOZNSS */
3318 /*
3319   emacs settings
3320   Local Variables:
3321   indent-tabs-mode: t
3322   tab-width: 4
3323   End:
3324 */