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