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