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