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