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