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