]> git.sur5r.net Git - openldap/blob - libraries/libldap/tls_m.c
ITS#8753 Public key pinning support in libldap
[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 explicitly
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 && !ctx->tc_using_pem )
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 multiple 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
1839                 /*
1840                  * Set the SSL version range.  MozNSS SSL versions are the same as openldap's:
1841                  *
1842                  * SSL_LIBRARY_VERSION_TLS_1_* are equivalent to LDAP_OPT_X_TLS_PROTOCOL_TLS1_*
1843                  */
1844                 SSL_VersionRangeGetSupported(ssl_variant_stream, &range); /* this sets the max */
1845                 range.min = lt->lt_protocol_min ? lt->lt_protocol_min : range.min;
1846                 variant = ssl_variant_stream;
1847                 SSL_VersionRangeSetDefault(variant, &range);
1848
1849                 NSS_SetDomesticPolicy();
1850
1851                 PK11_SetPasswordFunc( tlsm_pin_prompt );
1852
1853                 /* register cleanup function */
1854                 if ( tlsm_register_nss_shutdown() ) {
1855                         errcode = PORT_GetError();
1856                         Debug( LDAP_DEBUG_ANY,
1857                                    "TLS: could not register NSS shutdown function: %d:%s\n",
1858                                    errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 );
1859                         return -1;
1860                 }
1861
1862                 if  ( ctx->tc_is_server ) {
1863                         /* 0 means use the defaults here */
1864                         SSL_ConfigServerSessionIDCache( 0, 0, 0, NULL );
1865                 }
1866
1867 #ifndef HAVE_NSS_INITCONTEXT
1868         }
1869 #endif /* HAVE_NSS_INITCONTEXT */
1870
1871         return 0;
1872 }
1873
1874 /*
1875  * Find and verify the certificate.
1876  * The key is loaded and stored in ctx->tc_private_key
1877  */
1878 static int
1879 tlsm_find_and_verify_cert_key( tlsm_ctx *ctx )
1880 {
1881         SECCertificateUsage certUsage;
1882         PRBool checkSig;
1883         SECStatus status;
1884         void *pin_arg;
1885
1886         if ( tlsm_ctx_load_private_key( ctx ) )
1887                 return -1;
1888
1889         pin_arg = SSL_RevealPinArg( ctx->tc_model );
1890         certUsage = ctx->tc_is_server ? certificateUsageSSLServer : certificateUsageSSLClient;
1891         checkSig = ctx->tc_verify_cert ? PR_TRUE : PR_FALSE;
1892
1893         status = tlsm_verify_cert( ctx->tc_certdb, ctx->tc_certificate, pin_arg,
1894                                                            checkSig, certUsage, ctx->tc_warn_only, PR_TRUE );
1895
1896         return status == SECSuccess ? 0 : -1;
1897 }
1898
1899 static int
1900 tlsm_get_client_auth_data( void *arg, PRFileDesc *fd,
1901                                                    CERTDistNames *caNames, CERTCertificate **pRetCert,
1902                                                    SECKEYPrivateKey **pRetKey )
1903 {
1904         tlsm_ctx *ctx = (tlsm_ctx *)arg;
1905
1906         if ( pRetCert )
1907                 *pRetCert = CERT_DupCertificate( ctx->tc_certificate );
1908
1909         if ( pRetKey )
1910                 *pRetKey = SECKEY_CopyPrivateKey( ctx->tc_private_key );
1911
1912         return SECSuccess;
1913 }
1914
1915 /*
1916  * ctx must have a tc_model that is valid
1917 */
1918 static int
1919 tlsm_clientauth_init( tlsm_ctx *ctx )
1920 {
1921         SECStatus status = SECFailure;
1922         int rc;
1923         PRBool saveval;
1924
1925         saveval = ctx->tc_warn_only;
1926         ctx->tc_warn_only = PR_TRUE;
1927         rc = tlsm_find_and_verify_cert_key(ctx);
1928         ctx->tc_warn_only = saveval;
1929         if ( rc ) {
1930                 Debug( LDAP_DEBUG_ANY,
1931                            "TLS: error: unable to set up client certificate authentication for "
1932                            "certificate named %s\n", tlsm_ctx_subject_name(ctx), 0, 0 );
1933                 return -1;
1934         }
1935
1936         status = SSL_GetClientAuthDataHook( ctx->tc_model,
1937                                                                                 tlsm_get_client_auth_data,
1938                                                                                 (void *)ctx );
1939
1940         return ( status == SECSuccess ? 0 : -1 );
1941 }
1942
1943 /*
1944  * Tear down the TLS subsystem. Should only be called once.
1945  */
1946 static void
1947 tlsm_destroy( void )
1948 {
1949 #ifdef LDAP_R_COMPILE
1950         ldap_pvt_thread_mutex_destroy( &tlsm_ctx_count_mutex );
1951         ldap_pvt_thread_mutex_destroy( &tlsm_init_mutex );
1952         ldap_pvt_thread_mutex_destroy( &tlsm_pem_mutex );
1953 #endif
1954 }
1955
1956 static struct ldaptls *
1957 tlsm_copy_config ( const struct ldaptls *config )
1958 {
1959         struct ldaptls *copy;
1960
1961         assert( config );
1962
1963         copy = LDAP_MALLOC( sizeof( *copy ) );
1964         if ( !copy )
1965                 return NULL;
1966
1967         memset( copy, 0, sizeof( *copy ) );
1968
1969         if ( config->lt_certfile )
1970                 copy->lt_certfile = LDAP_STRDUP( config->lt_certfile );
1971         if ( config->lt_keyfile )
1972                 copy->lt_keyfile = LDAP_STRDUP( config->lt_keyfile );
1973         if ( config->lt_dhfile )
1974                 copy->lt_dhfile = LDAP_STRDUP( config->lt_dhfile );
1975         if ( config->lt_cacertfile )
1976                 copy->lt_cacertfile = LDAP_STRDUP( config->lt_cacertfile );
1977         if ( config->lt_cacertdir )
1978                 copy->lt_cacertdir = LDAP_STRDUP( config->lt_cacertdir );
1979         if ( config->lt_ciphersuite )
1980                 copy->lt_ciphersuite = LDAP_STRDUP( config->lt_ciphersuite );
1981         if ( config->lt_crlfile )
1982                 copy->lt_crlfile = LDAP_STRDUP( config->lt_crlfile );
1983         if ( config->lt_randfile )
1984                 copy->lt_randfile = LDAP_STRDUP( config->lt_randfile );
1985
1986         copy->lt_protocol_min = config->lt_protocol_min;
1987
1988         return copy;
1989 }
1990
1991 static void
1992 tlsm_free_config ( struct ldaptls *config )
1993 {
1994         assert( config );
1995
1996         if ( config->lt_certfile )
1997                 LDAP_FREE( config->lt_certfile );
1998         if ( config->lt_keyfile )
1999                 LDAP_FREE( config->lt_keyfile );
2000         if ( config->lt_dhfile )
2001                 LDAP_FREE( config->lt_dhfile );
2002         if ( config->lt_cacertfile )
2003                 LDAP_FREE( config->lt_cacertfile );
2004         if ( config->lt_cacertdir )
2005                 LDAP_FREE( config->lt_cacertdir );
2006         if ( config->lt_ciphersuite )
2007                 LDAP_FREE( config->lt_ciphersuite );
2008         if ( config->lt_crlfile )
2009                 LDAP_FREE( config->lt_crlfile );
2010         if ( config->lt_randfile )
2011                 LDAP_FREE( config->lt_randfile );
2012
2013         LDAP_FREE( config );
2014 }
2015
2016 static tls_ctx *
2017 tlsm_ctx_new ( struct ldapoptions *lo )
2018 {
2019         tlsm_ctx *ctx;
2020
2021         ctx = LDAP_MALLOC( sizeof (*ctx) );
2022         if ( ctx ) {
2023                 ctx->tc_refcnt = 1;
2024 #ifdef LDAP_R_COMPILE
2025                 ldap_pvt_thread_mutex_init( &ctx->tc_refmutex );
2026 #endif
2027                 LDAP_MUTEX_LOCK( &tlsm_ctx_count_mutex );
2028                 ctx->tc_unique = tlsm_ctx_count++;
2029                 LDAP_MUTEX_UNLOCK( &tlsm_ctx_count_mutex );
2030                 ctx->tc_config = NULL; /* populated later by tlsm_ctx_init */
2031                 ctx->tc_certdb = NULL;
2032                 ctx->tc_certdb_slot = NULL;
2033                 ctx->tc_certificate = NULL;
2034                 ctx->tc_private_key = NULL;
2035                 ctx->tc_pin_file = NULL;
2036                 ctx->tc_model = NULL;
2037                 memset(&ctx->tc_callonce, 0, sizeof(ctx->tc_callonce));
2038                 ctx->tc_require_cert = lo->ldo_tls_require_cert;
2039                 ctx->tc_verify_cert = PR_FALSE;
2040                 ctx->tc_using_pem = PR_FALSE;
2041 #ifdef HAVE_NSS_INITCONTEXT
2042                 ctx->tc_initctx = NULL;
2043 #endif /* HAVE_NSS_INITCONTEXT */
2044                 ctx->tc_pem_objs = NULL;
2045                 ctx->tc_n_pem_objs = 0;
2046                 ctx->tc_warn_only = PR_FALSE;
2047         }
2048         return (tls_ctx *)ctx;
2049 }
2050
2051 static void
2052 tlsm_ctx_ref( tls_ctx *ctx )
2053 {
2054         tlsm_ctx *c = (tlsm_ctx *)ctx;
2055         LDAP_MUTEX_LOCK( &c->tc_refmutex );
2056         c->tc_refcnt++;
2057         LDAP_MUTEX_UNLOCK( &c->tc_refmutex );
2058 }
2059
2060 static void
2061 tlsm_ctx_free ( tls_ctx *ctx )
2062 {
2063         tlsm_ctx *c = (tlsm_ctx *)ctx;
2064         int refcount;
2065
2066         if ( !c ) return;
2067
2068         LDAP_MUTEX_LOCK( &c->tc_refmutex );
2069         refcount = --c->tc_refcnt;
2070         LDAP_MUTEX_UNLOCK( &c->tc_refmutex );
2071         if ( refcount )
2072                 return;
2073
2074         LDAP_MUTEX_LOCK( &tlsm_init_mutex );
2075         if ( c->tc_model )
2076                 PR_Close( c->tc_model );
2077         if ( c->tc_certificate )
2078                 CERT_DestroyCertificate( c->tc_certificate );
2079         if ( c->tc_private_key )
2080                 SECKEY_DestroyPrivateKey( c->tc_private_key );
2081         c->tc_certdb = NULL; /* if not the default, may have to clean up */
2082         if ( c->tc_certdb_slot ) {
2083                 if ( SECMOD_CloseUserDB( c->tc_certdb_slot ) ) {
2084                         PRErrorCode errcode = PR_GetError();
2085                         Debug( LDAP_DEBUG_ANY,
2086                                    "TLS: could not close certdb slot - error %d:%s.\n",
2087                                    errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 );
2088                 }
2089         }
2090         if ( c->tc_pin_file ) {
2091                 PL_strfree( c->tc_pin_file );
2092                 c->tc_pin_file = NULL;
2093         }
2094         tlsm_free_pem_objs( c );
2095 #ifdef HAVE_NSS_INITCONTEXT
2096         if ( c->tc_initctx ) {
2097                 if ( NSS_ShutdownContext( c->tc_initctx ) ) {
2098                         PRErrorCode errcode = PR_GetError();
2099                         Debug( LDAP_DEBUG_ANY,
2100                                    "TLS: could not shutdown NSS - error %d:%s.\n",
2101                                    errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 );
2102                 }
2103         }
2104         c->tc_initctx = NULL;
2105 #endif /* HAVE_NSS_INITCONTEXT */
2106         LDAP_MUTEX_UNLOCK( &tlsm_init_mutex );
2107 #ifdef LDAP_R_COMPILE
2108         ldap_pvt_thread_mutex_destroy( &c->tc_refmutex );
2109 #endif
2110
2111         if ( c->tc_config )
2112                 tlsm_free_config( c->tc_config );
2113
2114         LDAP_FREE( c );
2115 }
2116
2117 /*
2118  * initialize a new TLS context
2119  */
2120 static int
2121 tlsm_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server )
2122 {
2123         tlsm_ctx *ctx = (tlsm_ctx *)lo->ldo_tls_ctx;
2124         ctx->tc_config = tlsm_copy_config( lt );
2125         ctx->tc_is_server = is_server;
2126
2127         return 0;
2128 }
2129
2130 /* returns true if the given string looks like
2131    "tokenname" ":" "certnickname"
2132    This is true if there is a ':' colon character
2133    in the string and the colon is not the first
2134    or the last character in the string
2135 */
2136 static int
2137 tlsm_is_tokenname_certnick( const char *certfile )
2138 {
2139         if ( certfile ) {
2140                 const char *ptr = PL_strchr( certfile, ':' );
2141                 return ptr && (ptr != certfile) && (*(ptr+1));
2142         }
2143         return 0;
2144 }
2145
2146 static int
2147 tlsm_deferred_ctx_init( void *arg )
2148 {
2149         tlsm_ctx *ctx = (tlsm_ctx *)arg;
2150         PRBool sslv2 = PR_FALSE;
2151         PRBool sslv3 = PR_TRUE;
2152         PRBool tlsv1 = PR_TRUE;
2153         PRBool request_cert = PR_FALSE;
2154         PRInt32 require_cert = PR_FALSE;
2155         PRFileDesc *fd;
2156         struct ldaptls *lt;
2157
2158         if ( tlsm_deferred_init( ctx ) ) {
2159             Debug( LDAP_DEBUG_ANY,
2160                            "TLS: could not perform TLS system initialization.\n",
2161                            0, 0, 0 );
2162             return -1;
2163         }
2164
2165         ctx->tc_certdb = CERT_GetDefaultCertDB(); /* If there is ever a per-context db, change this */
2166
2167         fd = PR_CreateIOLayerStub( tlsm_layer_id, &tlsm_PR_methods );
2168         if ( fd ) {
2169                 ctx->tc_model = SSL_ImportFD( NULL, fd );
2170         }
2171
2172         if ( !ctx->tc_model ) {
2173                 PRErrorCode err = PR_GetError();
2174                 Debug( LDAP_DEBUG_ANY,
2175                            "TLS: could perform TLS socket I/O layer initialization - error %d:%s.\n",
2176                            err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL );
2177
2178                 if ( fd ) {
2179                         PR_Close( fd );
2180                 }
2181                 return -1;
2182         }
2183
2184         if ( SSL_SetPKCS11PinArg(ctx->tc_model, ctx) ) {
2185                 Debug( LDAP_DEBUG_ANY,
2186                                 "TLS: could not set pin prompt argument\n", 0, 0, 0);
2187                 return -1;
2188         }
2189
2190         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_SECURITY, PR_TRUE ) ) {
2191                 Debug( LDAP_DEBUG_ANY,
2192                        "TLS: could not set secure mode on.\n",
2193                        0, 0, 0 );
2194                 return -1;
2195         }
2196
2197         lt = ctx->tc_config;
2198
2199         /* default is sslv3 and tlsv1 */
2200         if ( lt->lt_protocol_min ) {
2201                 if ( lt->lt_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_SSL3 ) {
2202                         sslv3 = PR_FALSE;
2203                 } else if ( lt->lt_protocol_min <= LDAP_OPT_X_TLS_PROTOCOL_SSL2 ) {
2204                         sslv2 = PR_TRUE;
2205                         Debug( LDAP_DEBUG_ANY,
2206                                "TLS: warning: minimum TLS protocol level set to "
2207                                "include SSLv2 - SSLv2 is insecure - do not use\n", 0, 0, 0 );
2208                 }
2209         }
2210         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_ENABLE_SSL2, sslv2 ) ) {
2211                 Debug( LDAP_DEBUG_ANY,
2212                        "TLS: could not set SSLv2 mode on.\n",
2213                        0, 0, 0 );
2214                 return -1;
2215         }
2216         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_ENABLE_SSL3, sslv3 ) ) {
2217                 Debug( LDAP_DEBUG_ANY,
2218                        "TLS: could not set SSLv3 mode on.\n",
2219                        0, 0, 0 );
2220                 return -1;
2221         }
2222         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_ENABLE_TLS, tlsv1 ) ) {
2223                 Debug( LDAP_DEBUG_ANY,
2224                        "TLS: could not set TLSv1 mode on.\n",
2225                        0, 0, 0 );
2226                 return -1;
2227         }
2228
2229         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_HANDSHAKE_AS_CLIENT, !ctx->tc_is_server ) ) {
2230                 Debug( LDAP_DEBUG_ANY,
2231                        "TLS: could not set handshake as client.\n",
2232                        0, 0, 0 );
2233                 return -1;
2234         }
2235         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_HANDSHAKE_AS_SERVER, ctx->tc_is_server ) ) {
2236                 Debug( LDAP_DEBUG_ANY,
2237                        "TLS: could not set handshake as server.\n",
2238                        0, 0, 0 );
2239                 return -1;
2240         }
2241
2242         if ( lt->lt_ciphersuite ) {
2243                 if ( tlsm_parse_ciphers( ctx, lt->lt_ciphersuite ) ) {
2244                         Debug( LDAP_DEBUG_ANY,
2245                                "TLS: could not set cipher list %s.\n",
2246                                lt->lt_ciphersuite, 0, 0 );
2247                         return -1;
2248                 }
2249         } else if ( tlsm_parse_ciphers( ctx, "DEFAULT" ) ) {
2250                 Debug( LDAP_DEBUG_ANY,
2251                        "TLS: could not set cipher list DEFAULT.\n",
2252                        0, 0, 0 );
2253                 return -1;
2254         }
2255
2256         if ( !ctx->tc_require_cert ) {
2257                 ctx->tc_verify_cert = PR_FALSE;
2258         } else if ( !ctx->tc_is_server ) {
2259                 request_cert = PR_TRUE;
2260                 require_cert = SSL_REQUIRE_NO_ERROR;
2261                 if ( ctx->tc_require_cert == LDAP_OPT_X_TLS_DEMAND ||
2262                      ctx->tc_require_cert == LDAP_OPT_X_TLS_HARD ) {
2263                         require_cert = SSL_REQUIRE_ALWAYS;
2264                 }
2265                 if ( ctx->tc_require_cert != LDAP_OPT_X_TLS_ALLOW )
2266                         ctx->tc_verify_cert = PR_TRUE;
2267         } else { /* server */
2268                 /* server does not request certs by default */
2269                 /* if allow - client may send cert, server will ignore if errors */
2270                 /* if try - client may send cert, server will error if bad cert */
2271                 /* if hard or demand - client must send cert, server will error if bad cert */
2272                 request_cert = PR_TRUE;
2273                 require_cert = SSL_REQUIRE_NO_ERROR;
2274                 if ( ctx->tc_require_cert == LDAP_OPT_X_TLS_DEMAND ||
2275                      ctx->tc_require_cert == LDAP_OPT_X_TLS_HARD ) {
2276                         require_cert = SSL_REQUIRE_ALWAYS;
2277                 }
2278                 if ( ctx->tc_require_cert != LDAP_OPT_X_TLS_ALLOW ) {
2279                         ctx->tc_verify_cert = PR_TRUE;
2280                 } else {
2281                         ctx->tc_warn_only = PR_TRUE;
2282                 }
2283         }
2284
2285         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_REQUEST_CERTIFICATE, request_cert ) ) {
2286                 Debug( LDAP_DEBUG_ANY,
2287                        "TLS: could not set request certificate mode.\n",
2288                        0, 0, 0 );
2289                 return -1;
2290         }
2291                 
2292         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_REQUIRE_CERTIFICATE, require_cert ) ) {
2293                 Debug( LDAP_DEBUG_ANY,
2294                        "TLS: could not set require certificate mode.\n",
2295                        0, 0, 0 );
2296                 return -1;
2297         }
2298
2299         /* set up our cert and key, if any */
2300         if ( lt->lt_certfile ) {
2301
2302                 /* first search in certdb (lt_certfile is nickname) */
2303                 if ( ctx->tc_certdb ) {
2304                         char *tmp_certname;
2305
2306                         if ( tlsm_is_tokenname_certnick( lt->lt_certfile )) {
2307                                 /* assume already in form tokenname:certnickname */
2308                                 tmp_certname = PL_strdup( lt->lt_certfile );
2309                         } else if ( ctx->tc_certdb_slot ) {
2310                                 tmp_certname = PR_smprintf( TLSM_CERTDB_DESC_FMT ":%s", ctx->tc_unique, lt->lt_certfile );
2311                         } else {
2312                                 tmp_certname = PR_smprintf( "%s", lt->lt_certfile );
2313                         }
2314
2315                         ctx->tc_certificate = PK11_FindCertFromNickname( tmp_certname, SSL_RevealPinArg( ctx->tc_model ) );
2316                         PR_smprintf_free( tmp_certname );
2317
2318                         if ( !ctx->tc_certificate ) {
2319                                 PRErrorCode errcode = PR_GetError();
2320                                 Debug( LDAP_DEBUG_ANY,
2321                                            "TLS: error: the certificate '%s' could not be found in the database - error %d:%s.\n",
2322                                            lt->lt_certfile, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
2323                         }
2324                 }
2325
2326                 /* fallback to PEM module (lt_certfile is filename) */
2327                 if ( !ctx->tc_certificate ) {
2328                         if ( !pem_module && tlsm_init_pem_module() ) {
2329                                 int pem_errcode = PORT_GetError();
2330                                 Debug( LDAP_DEBUG_ANY,
2331                                            "TLS: fallback to PEM impossible, module cannot be loaded - error %d:%s.\n",
2332                                            pem_errcode, PR_ErrorToString( pem_errcode, PR_LANGUAGE_I_DEFAULT ), 0 );
2333                                 return -1;
2334                         }
2335
2336                         /* this sets ctx->tc_certificate to the correct value */
2337                         if ( !tlsm_add_cert_from_file( ctx, lt->lt_certfile, PR_FALSE ) ) {
2338                                 ctx->tc_using_pem = PR_TRUE;
2339                         }
2340                 }
2341
2342                 if ( ctx->tc_certificate ) {
2343                         Debug( LDAP_DEBUG_ANY,
2344                                    "TLS: certificate '%s' successfully loaded from %s.\n", lt->lt_certfile,
2345                                    ctx->tc_using_pem ? "PEM file" : "moznss database", 0);
2346                 } else {
2347                         return -1;
2348                 }
2349         }
2350
2351         if ( lt->lt_keyfile ) {
2352                 /* if using the PEM module, load the PEM file specified by lt_keyfile */
2353                 /* otherwise, assume this is the pininfo for the key */
2354                 if ( ctx->tc_using_pem ) {
2355                         int rc = tlsm_add_key_from_file( ctx, lt->lt_keyfile );
2356                         if ( rc ) {
2357                                 return rc;
2358                         }
2359                 } else {
2360                         if ( ctx->tc_pin_file )
2361                                 PL_strfree( ctx->tc_pin_file );
2362                         ctx->tc_pin_file = PL_strdup( lt->lt_keyfile );
2363                 }
2364         }
2365
2366         /* Set up callbacks for use by clients */
2367         if ( !ctx->tc_is_server ) {
2368                 if ( SSL_OptionSet( ctx->tc_model, SSL_NO_CACHE, PR_TRUE ) != SECSuccess ) {
2369                         PRErrorCode err = PR_GetError();
2370                         Debug( LDAP_DEBUG_ANY, 
2371                                "TLS: error: could not set nocache option for moznss - error %d:%s\n",
2372                                err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL );
2373                         return -1;
2374                 }
2375
2376                 if ( SSL_BadCertHook( ctx->tc_model, tlsm_bad_cert_handler, ctx ) != SECSuccess ) {
2377                         PRErrorCode err = PR_GetError();
2378                         Debug( LDAP_DEBUG_ANY, 
2379                                "TLS: error: could not set bad cert handler for moznss - error %d:%s\n",
2380                                err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL );
2381                         return -1;
2382                 }
2383
2384                 /* 
2385                    since a cert has been specified, assume the client wants to do cert auth
2386                 */
2387                 if ( ctx->tc_certificate ) {
2388                         if ( tlsm_clientauth_init( ctx ) ) {
2389                                 Debug( LDAP_DEBUG_ANY, 
2390                                        "TLS: error: unable to set up client certificate authentication using '%s'\n",
2391                                        tlsm_ctx_subject_name(ctx), 0, 0 );
2392                                 return -1;
2393                         }
2394                 }
2395         } else { /* set up secure server */
2396                 SSLKEAType certKEA;
2397                 SECStatus status;
2398
2399                 /* must have a certificate for the server to use */
2400                 if ( !ctx->tc_certificate ) {
2401                         Debug( LDAP_DEBUG_ANY, 
2402                                "TLS: error: no server certificate: must specify a certificate for the server to use\n",
2403                                0, 0, 0 );
2404                         return -1;
2405                 }
2406
2407                 if ( tlsm_find_and_verify_cert_key( ctx ) ) {
2408                         Debug( LDAP_DEBUG_ANY, 
2409                                "TLS: error: unable to find and verify server's cert and key for certificate %s\n",
2410                                tlsm_ctx_subject_name(ctx), 0, 0 );
2411                         return -1;
2412                 }
2413
2414                 /* configure the socket to be a secure server socket */
2415                 certKEA = NSS_FindCertKEAType( ctx->tc_certificate );
2416                 status = SSL_ConfigSecureServer( ctx->tc_model, ctx->tc_certificate, ctx->tc_private_key, certKEA );
2417
2418                 if ( SECSuccess != status ) {
2419                         PRErrorCode err = PR_GetError();
2420                         Debug( LDAP_DEBUG_ANY, 
2421                                "TLS: error: unable to configure secure server using certificate '%s' - error %d:%s\n",
2422                                tlsm_ctx_subject_name(ctx), err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ) );
2423                         return -1;
2424                 }
2425         }
2426
2427         /* Callback for authenticating certificate */
2428         if ( SSL_AuthCertificateHook( ctx->tc_model, tlsm_auth_cert_handler,
2429                                   ctx ) != SECSuccess ) {
2430                 PRErrorCode err = PR_GetError();
2431                 Debug( LDAP_DEBUG_ANY, 
2432                        "TLS: error: could not set auth cert handler for moznss - error %d:%s\n",
2433                        err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL );
2434                 return -1;
2435         }
2436
2437         if ( SSL_HandshakeCallback( ctx->tc_model, tlsm_handshake_complete_cb, ctx ) ) {
2438                 PRErrorCode err = PR_GetError();
2439                 Debug( LDAP_DEBUG_ANY, 
2440                        "TLS: error: could not set handshake callback for moznss - error %d:%s\n",
2441                        err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL );
2442                 return -1;
2443         }
2444
2445         tlsm_free_config( ctx->tc_config );
2446         ctx->tc_config = NULL;
2447
2448         return 0;
2449 }
2450
2451 struct tls_data {
2452         tlsm_session            *session;
2453         Sockbuf_IO_Desc         *sbiod;
2454         /* there seems to be no portable way to determine if the
2455            sockbuf sd has been set to nonblocking mode - the
2456            call to ber_pvt_socket_set_nonblock() takes place
2457            before the tls socket is set up, so we cannot
2458            intercept that call either.
2459            On systems where fcntl is available, we can just
2460            F_GETFL and test for O_NONBLOCK.  On other systems,
2461            we will just see if the IO op returns EAGAIN or EWOULDBLOCK,
2462            and just set this flag */
2463         PRBool              nonblock;
2464         /*
2465          * NSS tries hard to be backwards compatible with SSLv2 clients, or
2466          * clients that send an SSLv2 client hello.  This message is not
2467          * tagged in any way, so NSS has no way to know if the incoming
2468          * message is a valid SSLv2 client hello or just some bogus data
2469          * (or cleartext LDAP).  We store the first byte read from the
2470          * client here.  The most common case will be a client sending
2471          * LDAP data instead of SSL encrypted LDAP data.  This can happen,
2472          * for example, if using ldapsearch -Z - if the starttls fails,
2473          * the client will fallback to plain cleartext LDAP.  So if we
2474          * see that the firstbyte is a valid LDAP tag, we can be
2475          * pretty sure this is happening.
2476          */
2477         ber_tag_t           firsttag;
2478         /*
2479          * NSS doesn't return SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE, etc.
2480          * when it is blocked, so we have to set a flag in the wrapped send
2481          * and recv calls that tells us what operation NSS was last blocked
2482          * on
2483          */
2484 #define TLSM_READ  1
2485 #define TLSM_WRITE 2
2486         int io_flag;
2487 };
2488
2489 static struct tls_data *
2490 tlsm_get_pvt_tls_data( PRFileDesc *fd )
2491 {
2492         struct tls_data         *p;
2493         PRFileDesc *myfd;
2494
2495         if ( !fd ) {
2496                 return NULL;
2497         }
2498
2499         myfd = PR_GetIdentitiesLayer( fd, tlsm_layer_id );
2500
2501         if ( !myfd ) {
2502                 return NULL;
2503         }
2504
2505         p = (struct tls_data *)myfd->secret;
2506
2507         return p;
2508 }
2509
2510 static int
2511 tlsm_is_non_ssl_message( PRFileDesc *fd, ber_tag_t *thebyte )
2512 {
2513         struct tls_data         *p;
2514
2515         if ( thebyte ) {
2516                 *thebyte = LBER_DEFAULT;
2517         }
2518
2519         p = tlsm_get_pvt_tls_data( fd );
2520         if ( p == NULL || p->sbiod == NULL ) {
2521                 return 0;
2522         }
2523
2524         if ( p->firsttag == LBER_SEQUENCE ) {
2525                 if ( thebyte ) {
2526                         *thebyte = p->firsttag;
2527                 }
2528                 return 1;
2529         }
2530
2531         return 0;
2532 }
2533
2534 static tls_session *
2535 tlsm_session_new ( tls_ctx * ctx, int is_server )
2536 {
2537         tlsm_ctx *c = (tlsm_ctx *)ctx;
2538         tlsm_session *session;
2539         PRFileDesc *fd;
2540         PRStatus status;
2541         int rc;
2542
2543         c->tc_is_server = is_server;
2544         LDAP_MUTEX_LOCK( &tlsm_init_mutex );
2545         status = PR_CallOnceWithArg( &c->tc_callonce, tlsm_deferred_ctx_init, c );
2546         LDAP_MUTEX_UNLOCK( &tlsm_init_mutex );
2547         if ( PR_SUCCESS != status ) {
2548                 PRErrorCode err = PR_GetError();
2549                 Debug( LDAP_DEBUG_ANY, 
2550                        "TLS: error: could not initialize moznss security context - error %d:%s\n",
2551                        err, PR_ErrorToString(err, PR_LANGUAGE_I_DEFAULT), NULL );
2552                 return NULL;
2553         }
2554
2555         fd = PR_CreateIOLayerStub( tlsm_layer_id, &tlsm_PR_methods );
2556         if ( !fd ) {
2557                 return NULL;
2558         }
2559
2560         session = SSL_ImportFD( c->tc_model, fd );
2561         if ( !session ) {
2562                 PR_DELETE( fd );
2563                 return NULL;
2564         }
2565
2566         rc = SSL_ResetHandshake( session, is_server );
2567         if ( rc ) {
2568                 PRErrorCode err = PR_GetError();
2569                 Debug( LDAP_DEBUG_TRACE, 
2570                            "TLS: error: new session - reset handshake failure %d - error %d:%s\n",
2571                            rc, err,
2572                            err ? PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ) : "unknown" );
2573                 PR_DELETE( fd );
2574                 PR_Close( session );
2575                 session = NULL;
2576         }
2577
2578         return (tls_session *)session;
2579
2580
2581 static int
2582 tlsm_session_accept_or_connect( tls_session *session, int is_accept )
2583 {
2584         tlsm_session *s = (tlsm_session *)session;
2585         int rc;
2586         const char *op = is_accept ? "accept" : "connect";
2587
2588         if ( pem_module ) {
2589                 LDAP_MUTEX_LOCK( &tlsm_pem_mutex );
2590         }
2591         rc = SSL_ForceHandshake( s );
2592         if ( pem_module ) {
2593                 LDAP_MUTEX_UNLOCK( &tlsm_pem_mutex );
2594         }
2595         if ( rc ) {
2596                 PRErrorCode err = PR_GetError();
2597                 rc = -1;
2598                 if ( err == PR_WOULD_BLOCK_ERROR ) {
2599                         ber_tag_t thetag = LBER_DEFAULT;
2600                         /* see if we are blocked because of a bogus packet */
2601                         if ( tlsm_is_non_ssl_message( s, &thetag ) ) { /* see if we received a non-SSL message */
2602                                 Debug( LDAP_DEBUG_ANY, 
2603                                            "TLS: error: %s - error - received non-SSL message [0x%x]\n",
2604                                            op, (unsigned int)thetag, 0 );
2605                                 /* reset error to something more descriptive */
2606                                 PR_SetError( SSL_ERROR_RX_MALFORMED_HELLO_REQUEST, EPROTO );
2607                         }
2608                 } else {
2609                         Debug( LDAP_DEBUG_ANY, 
2610                                    "TLS: error: %s - force handshake failure: errno %d - moznss error %d\n",
2611                                    op, errno, err );
2612                 }
2613         }
2614
2615         return rc;
2616 }
2617 static int
2618 tlsm_session_accept( tls_session *session )
2619 {
2620         return tlsm_session_accept_or_connect( session, 1 );
2621 }
2622
2623 static int
2624 tlsm_session_connect( LDAP *ld, tls_session *session )
2625 {
2626         return tlsm_session_accept_or_connect( session, 0 );
2627 }
2628
2629 static int
2630 tlsm_session_upflags( Sockbuf *sb, tls_session *session, int rc )
2631 {
2632         int prerror = PR_GetError();
2633
2634         if ( ( prerror == PR_PENDING_INTERRUPT_ERROR ) || ( prerror == PR_WOULD_BLOCK_ERROR ) ) {
2635                 tlsm_session *s = (tlsm_session *)session;
2636                 struct tls_data *p = tlsm_get_pvt_tls_data( s );
2637
2638                 if ( p && ( p->io_flag == TLSM_READ ) ) {
2639                         sb->sb_trans_needs_read = 1;
2640                         return 1;
2641                 } else if ( p && ( p->io_flag == TLSM_WRITE ) ) {
2642                         sb->sb_trans_needs_write = 1;
2643                         return 1;
2644                 }
2645         }
2646
2647         return 0;
2648 }
2649
2650 static char *
2651 tlsm_session_errmsg( tls_session *sess, int rc, char *buf, size_t len )
2652 {
2653         int i;
2654         int prerror = PR_GetError();
2655
2656         i = PR_GetErrorTextLength();
2657         if ( i > len ) {
2658                 char *msg = LDAP_MALLOC( i+1 );
2659                 PR_GetErrorText( msg );
2660                 memcpy( buf, msg, len );
2661                 LDAP_FREE( msg );
2662         } else if ( i ) {
2663                 PR_GetErrorText( buf );
2664         } else if ( prerror ) {
2665                 i = PR_snprintf( buf, len, "TLS error %d:%s",
2666                                                  prerror, PR_ErrorToString( prerror, PR_LANGUAGE_I_DEFAULT ) );
2667         }
2668
2669         return ( i > 0 ) ? buf : NULL;
2670 }
2671
2672 static int
2673 tlsm_session_my_dn( tls_session *session, struct berval *der_dn )
2674 {
2675         tlsm_session *s = (tlsm_session *)session;
2676         CERTCertificate *cert;
2677
2678         cert = SSL_LocalCertificate( 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 static int
2688 tlsm_session_peer_dn( tls_session *session, struct berval *der_dn )
2689 {
2690         tlsm_session *s = (tlsm_session *)session;
2691         CERTCertificate *cert;
2692
2693         cert = SSL_PeerCertificate( s );
2694         if (!cert) return LDAP_INVALID_CREDENTIALS;
2695         
2696         der_dn->bv_val = (char *)cert->derSubject.data;
2697         der_dn->bv_len = cert->derSubject.len;
2698         CERT_DestroyCertificate( cert );
2699         return 0;
2700 }
2701
2702 /* what kind of hostname were we given? */
2703 #define IS_DNS  0
2704 #define IS_IP4  1
2705 #define IS_IP6  2
2706
2707 static int
2708 tlsm_session_chkhost( LDAP *ld, tls_session *session, const char *name_in )
2709 {
2710         tlsm_session *s = (tlsm_session *)session;
2711         CERTCertificate *cert;
2712         const char *name, *domain = NULL, *ptr;
2713         int ret, ntype = IS_DNS, nlen, dlen;
2714 #ifdef LDAP_PF_INET6
2715         struct in6_addr addr;
2716 #else
2717         struct in_addr addr;
2718 #endif
2719         SECItem altname;
2720         SECStatus rv;
2721
2722         if( ldap_int_hostname &&
2723                 ( !name_in || !strcasecmp( name_in, "localhost" ) ) )
2724         {
2725                 name = ldap_int_hostname;
2726         } else {
2727                 name = name_in;
2728         }
2729         nlen = strlen( name );
2730
2731         cert = SSL_PeerCertificate( s );
2732         if (!cert) {
2733                 Debug( LDAP_DEBUG_ANY,
2734                         "TLS: unable to get peer certificate.\n",
2735                         0, 0, 0 );
2736                 /* if this was a fatal condition, things would have
2737                  * aborted long before now.
2738                  */
2739                 return LDAP_SUCCESS;
2740         }
2741
2742 #ifdef LDAP_PF_INET6
2743         if (inet_pton(AF_INET6, name, &addr)) {
2744                 ntype = IS_IP6;
2745         } else 
2746 #endif
2747         if ((ptr = strrchr(name, '.')) && isdigit((unsigned char)ptr[1])) {
2748                 if (inet_aton(name, (struct in_addr *)&addr)) ntype = IS_IP4;
2749         }
2750         if (ntype == IS_DNS ) {
2751                 domain = strchr( name, '.' );
2752                 if ( domain )
2753                         dlen = nlen - ( domain - name );
2754         }
2755
2756         ret = LDAP_LOCAL_ERROR;
2757
2758         rv = CERT_FindCertExtension( cert, SEC_OID_X509_SUBJECT_ALT_NAME,
2759                 &altname );
2760         if ( rv == SECSuccess && altname.data ) {
2761                 PRArenaPool *arena;
2762                 CERTGeneralName *names, *cur;
2763
2764                 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2765                 if ( !arena ) {
2766                         ret = LDAP_NO_MEMORY;
2767                         goto fail;
2768                 }
2769
2770                 names = cur = CERT_DecodeAltNameExtension(arena, &altname);
2771                 if ( !cur )
2772                         goto altfail;
2773
2774                 do {
2775                         char *host;
2776                         int hlen;
2777
2778                         /* ignore empty */
2779                         if ( !cur->name.other.len ) continue;
2780
2781                         host = (char *)cur->name.other.data;
2782                         hlen = cur->name.other.len;
2783
2784                         if ( cur->type == certDNSName ) {
2785                                 if ( ntype != IS_DNS )  continue;
2786
2787                                 /* is this an exact match? */
2788                                 if ( nlen == hlen && !strncasecmp( name, host, nlen )) {
2789                                         ret = LDAP_SUCCESS;
2790                                         break;
2791                                 }
2792
2793                                 /* is this a wildcard match? */
2794                                 if ( domain && host[0] == '*' && host[1] == '.' &&
2795                                         dlen == hlen-1 && !strncasecmp( domain, host+1, dlen )) {
2796                                         ret = LDAP_SUCCESS;
2797                                         break;
2798                                 }
2799                         } else if ( cur->type == certIPAddress ) {
2800                                 if ( ntype == IS_DNS )  continue;
2801                                 
2802 #ifdef LDAP_PF_INET6
2803                                 if (ntype == IS_IP6 && hlen != sizeof(struct in6_addr)) {
2804                                         continue;
2805                                 } else
2806 #endif
2807                                 if (ntype == IS_IP4 && hlen != sizeof(struct in_addr)) {
2808                                         continue;
2809                                 }
2810                                 if (!memcmp(host, &addr, hlen)) {
2811                                         ret = LDAP_SUCCESS;
2812                                         break;
2813                                 }
2814                         }
2815                 } while (( cur = CERT_GetNextGeneralName( cur )) != names );
2816 altfail:
2817                 PORT_FreeArena( arena, PR_FALSE );
2818                 SECITEM_FreeItem( &altname, PR_FALSE );
2819         }
2820         /* no altnames matched, try the CN */
2821         if ( ret != LDAP_SUCCESS ) {
2822                 /* find the last CN */
2823                 CERTRDN *rdn, **rdns;
2824                 CERTAVA *lastava = NULL;
2825                 char buf[2048];
2826
2827                 buf[0] = '\0';
2828                 rdns = cert->subject.rdns;
2829                 while ( rdns && ( rdn = *rdns++ )) {
2830                         CERTAVA *ava, **avas = rdn->avas;
2831                         while ( avas && ( ava = *avas++ )) {
2832                                 if ( CERT_GetAVATag( ava ) == SEC_OID_AVA_COMMON_NAME )
2833                                         lastava = ava;
2834                         }
2835                 }
2836                 if ( lastava ) {
2837                         SECItem *av = CERT_DecodeAVAValue( &lastava->value );
2838                         if ( av ) {
2839                                 if ( av->len == nlen && !strncasecmp( name, (char *)av->data, nlen )) {
2840                                         ret = LDAP_SUCCESS;
2841                                 } else if ( av->data[0] == '*' && av->data[1] == '.' &&
2842                                         domain && dlen == av->len - 1 && !strncasecmp( domain,
2843                                                 (char *)(av->data+1), dlen )) {
2844                                         ret = LDAP_SUCCESS;
2845                                 } else {
2846                                         int len = av->len;
2847                                         if ( len >= sizeof(buf) )
2848                                                 len = sizeof(buf)-1;
2849                                         memcpy( buf, av->data, len );
2850                                         buf[len] = '\0';
2851                                 }
2852                                 SECITEM_FreeItem( av, PR_TRUE );
2853                         }
2854                 }
2855                 if ( ret != LDAP_SUCCESS ) {
2856                         Debug( LDAP_DEBUG_ANY, "TLS: hostname (%s) does not match "
2857                                 "common name in certificate (%s).\n", 
2858                                 name, buf, 0 );
2859                         ret = LDAP_CONNECT_ERROR;
2860                         if ( ld->ld_error ) {
2861                                 LDAP_FREE( ld->ld_error );
2862                         }
2863                         ld->ld_error = LDAP_STRDUP(
2864                                 _("TLS: hostname does not match CN in peer certificate"));
2865                 }
2866         }
2867
2868 fail:
2869         CERT_DestroyCertificate( cert );
2870         return ret;
2871 }
2872
2873 static int
2874 tlsm_session_strength( tls_session *session )
2875 {
2876         tlsm_session *s = (tlsm_session *)session;
2877         int rc, keySize;
2878
2879         rc = SSL_SecurityStatus( s, NULL, NULL, NULL, &keySize,
2880                 NULL, NULL );
2881         return rc ? 0 : keySize;
2882 }
2883
2884 static int
2885 tlsm_session_unique( tls_session *sess, struct berval *buf, int is_server)
2886 {
2887         /* Need upstream support https://bugzilla.mozilla.org/show_bug.cgi?id=563276 */
2888         return 0;
2889 }
2890
2891 /*
2892  * Yet again, we're pasting in glue that MozNSS ought to provide itself.
2893  *
2894  * SSL_LIBRARY_VERSION_TLS_1_* are equivalent to LDAP_OPT_X_TLS_PROTOCOL_TLS1_*
2895  */
2896 static struct {
2897         const char *name;
2898         int num;
2899 } pvers[] = {
2900         { "SSLv2", SSL_LIBRARY_VERSION_2 },
2901         { "SSLv3", SSL_LIBRARY_VERSION_3_0 },
2902         { "TLSv1", SSL_LIBRARY_VERSION_TLS_1_0 },
2903         { "TLSv1.1", SSL_LIBRARY_VERSION_TLS_1_1 },
2904         { "TLSv1.2", SSL_LIBRARY_VERSION_TLS_1_2 },
2905         { "TLSv1.3", SSL_LIBRARY_VERSION_TLS_1_3 },
2906         { NULL, 0 }
2907 };
2908
2909 static const char *
2910 tlsm_session_version( tls_session *sess )
2911 {
2912         tlsm_session *s = (tlsm_session *)sess;
2913         SSLChannelInfo info;
2914         int rc;
2915         rc = SSL_GetChannelInfo( s, &info, sizeof( info ));
2916         if ( rc == 0 ) {
2917                 int i;
2918                 for (i=0; pvers[i].name; i++)
2919                         if (pvers[i].num == info.protocolVersion)
2920                                 return pvers[i].name;
2921         }
2922         return "unknown";
2923 }
2924
2925 static const char *
2926 tlsm_session_cipher( tls_session *sess )
2927 {
2928         tlsm_session *s = (tlsm_session *)sess;
2929         SSLChannelInfo info;
2930         int rc;
2931         rc = SSL_GetChannelInfo( s, &info, sizeof( info ));
2932         if ( rc == 0 ) {
2933                 SSLCipherSuiteInfo csinfo;
2934                 rc = SSL_GetCipherSuiteInfo( info.cipherSuite, &csinfo, sizeof( csinfo ));
2935                 if ( rc == 0 )
2936                         return csinfo.cipherSuiteName;
2937         }
2938         return "unknown";
2939 }
2940
2941 static int
2942 tlsm_session_peercert( tls_session *sess, struct berval *der )
2943 {
2944         tlsm_session *s = (tlsm_session *)sess;
2945         CERTCertificate *cert;
2946         cert = SSL_PeerCertificate( s );
2947         if (!cert)
2948                 return -1;
2949         der->bv_len = cert->derCert.len;
2950         der->bv_val = LDAP_MALLOC( der->bv_len );
2951         if (!der->bv_val)
2952                 return -1;
2953         memcpy( der->bv_val, cert->derCert.data, der->bv_len );
2954         return 0;
2955 }
2956
2957 /*
2958  * TLS support for LBER Sockbufs
2959  */
2960
2961 static PRStatus PR_CALLBACK
2962 tlsm_PR_Close(PRFileDesc *fd)
2963 {
2964         int rc = PR_SUCCESS;
2965
2966         /* we don't need to actually close anything here, just
2967            pop our io layer off the stack */
2968         fd->secret = NULL; /* must have been freed before calling PR_Close */
2969         if ( fd->lower ) {
2970                 fd = PR_PopIOLayer( fd, tlsm_layer_id );
2971                 /* if we are not the last layer, pass the close along */
2972                 if ( fd ) {
2973                         if ( fd->dtor ) {
2974                                 fd->dtor( fd );
2975                         }
2976                         rc = fd->methods->close( fd );
2977                 }
2978         } else {
2979                 /* we are the last layer - just call our dtor */
2980                 fd->dtor(fd);
2981         }
2982
2983         return rc;
2984 }
2985
2986 static PRStatus PR_CALLBACK
2987 tlsm_PR_Shutdown(PRFileDesc *fd, PRShutdownHow how)
2988 {
2989         int rc = PR_SUCCESS;
2990
2991         if ( fd->lower ) {
2992                 rc = PR_Shutdown( fd->lower, how );
2993         }
2994
2995         return rc;
2996 }
2997
2998 static int PR_CALLBACK
2999 tlsm_PR_Recv(PRFileDesc *fd, void *buf, PRInt32 len, PRIntn flags,
3000          PRIntervalTime timeout)
3001 {
3002         struct tls_data         *p;
3003         int rc;
3004
3005         if ( buf == NULL || len <= 0 ) return 0;
3006
3007         p = tlsm_get_pvt_tls_data( fd );
3008
3009         if ( p == NULL || p->sbiod == NULL ) {
3010                 return 0;
3011         }
3012
3013         rc = LBER_SBIOD_READ_NEXT( p->sbiod, buf, len );
3014         if (rc <= 0) {
3015                 tlsm_map_error( errno );
3016                 if ( errno == EAGAIN || errno == EWOULDBLOCK ) {
3017                         p->nonblock = PR_TRUE; /* fd is using non-blocking io */
3018                 } else if ( errno ) { /* real error */
3019                         Debug( LDAP_DEBUG_TRACE, 
3020                                "TLS: error: tlsm_PR_Recv returned %d - error %d:%s\n",
3021                                rc, errno, STRERROR(errno) );
3022                 }
3023         } else if ( ( rc > 0 ) && ( len > 0 ) && ( p->firsttag == LBER_DEFAULT ) ) {
3024                 p->firsttag = (ber_tag_t)*((char *)buf);
3025         }
3026         p->io_flag = TLSM_READ;
3027
3028         return rc;
3029 }
3030
3031 static int PR_CALLBACK
3032 tlsm_PR_Send(PRFileDesc *fd, const void *buf, PRInt32 len, PRIntn flags,
3033          PRIntervalTime timeout)
3034 {
3035         struct tls_data         *p;
3036         int rc;
3037
3038         if ( buf == NULL || len <= 0 ) return 0;
3039
3040         p = tlsm_get_pvt_tls_data( fd );
3041
3042         if ( p == NULL || p->sbiod == NULL ) {
3043                 return 0;
3044         }
3045
3046         rc = LBER_SBIOD_WRITE_NEXT( p->sbiod, (char *)buf, len );
3047         if (rc <= 0) {
3048                 tlsm_map_error( errno );
3049                 if ( errno == EAGAIN || errno == EWOULDBLOCK ) {
3050                         p->nonblock = PR_TRUE;
3051                 } else if ( errno ) { /* real error */
3052                         Debug( LDAP_DEBUG_TRACE, 
3053                                "TLS: error: tlsm_PR_Send returned %d - error %d:%s\n",
3054                                rc, errno, STRERROR(errno) );
3055                 }
3056         }
3057         p->io_flag = TLSM_WRITE;
3058
3059         return rc;
3060 }
3061
3062 static int PR_CALLBACK
3063 tlsm_PR_Read(PRFileDesc *fd, void *buf, PRInt32 len)
3064 {
3065         return tlsm_PR_Recv( fd, buf, len, 0, PR_INTERVAL_NO_TIMEOUT );
3066 }
3067
3068 static int PR_CALLBACK
3069 tlsm_PR_Write(PRFileDesc *fd, const void *buf, PRInt32 len)
3070 {
3071         return tlsm_PR_Send( fd, buf, len, 0, PR_INTERVAL_NO_TIMEOUT );
3072 }
3073
3074 static PRStatus PR_CALLBACK
3075 tlsm_PR_GetPeerName(PRFileDesc *fd, PRNetAddr *addr)
3076 {
3077         struct tls_data         *p;
3078         ber_socklen_t len;
3079
3080         p = tlsm_get_pvt_tls_data( fd );
3081
3082         if ( p == NULL || p->sbiod == NULL ) {
3083                 return PR_FAILURE;
3084         }
3085         len = sizeof(PRNetAddr);
3086         return getpeername( p->sbiod->sbiod_sb->sb_fd, (struct sockaddr *)addr, &len );
3087 }
3088
3089 static PRStatus PR_CALLBACK
3090 tlsm_PR_GetSocketOption(PRFileDesc *fd, PRSocketOptionData *data)
3091 {
3092         struct tls_data         *p;
3093         p = tlsm_get_pvt_tls_data( fd );
3094
3095         if ( p == NULL || data == NULL ) {
3096                 return PR_FAILURE;
3097         }
3098
3099         /* only the nonblocking option is supported at this time
3100            MozNSS SSL code needs it */
3101         if ( data->option != PR_SockOpt_Nonblocking ) {
3102                 PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
3103                 return PR_FAILURE;
3104         }
3105 #ifdef HAVE_FCNTL
3106         int flags = fcntl( p->sbiod->sbiod_sb->sb_fd, F_GETFL );
3107         data->value.non_blocking = (flags & O_NONBLOCK) ? PR_TRUE : PR_FALSE;           
3108 #else /* punt :P */
3109         data->value.non_blocking = p->nonblock;
3110 #endif
3111         return PR_SUCCESS;
3112 }
3113
3114 static PRStatus PR_CALLBACK
3115 tlsm_PR_prs_unimp()
3116 {
3117     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
3118     return PR_FAILURE;
3119 }
3120
3121 static PRFileDesc * PR_CALLBACK
3122 tlsm_PR_pfd_unimp()
3123 {
3124     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
3125     return NULL;
3126 }
3127
3128 static PRInt16 PR_CALLBACK
3129 tlsm_PR_i16_unimp()
3130 {
3131     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
3132     return SECFailure;
3133 }
3134
3135 static PRInt32 PR_CALLBACK
3136 tlsm_PR_i32_unimp()
3137 {
3138     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
3139     return SECFailure;
3140 }
3141
3142 static PRInt64 PR_CALLBACK
3143 tlsm_PR_i64_unimp()
3144 {
3145     PRInt64 res;
3146
3147     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
3148     LL_I2L(res, -1L);
3149     return res;
3150 }
3151
3152 static const PRIOMethods tlsm_PR_methods = {
3153     PR_DESC_LAYERED,
3154     tlsm_PR_Close,                      /* close        */
3155     tlsm_PR_Read,                       /* read         */
3156     tlsm_PR_Write,                      /* write        */
3157     tlsm_PR_i32_unimp,          /* available    */
3158     tlsm_PR_i64_unimp,          /* available64  */
3159     tlsm_PR_prs_unimp,          /* fsync        */
3160     tlsm_PR_i32_unimp,          /* seek         */
3161     tlsm_PR_i64_unimp,          /* seek64       */
3162     tlsm_PR_prs_unimp,          /* fileInfo     */
3163     tlsm_PR_prs_unimp,          /* fileInfo64   */
3164     tlsm_PR_i32_unimp,          /* writev       */
3165     tlsm_PR_prs_unimp,          /* connect      */
3166     tlsm_PR_pfd_unimp,          /* accept       */
3167     tlsm_PR_prs_unimp,          /* bind         */
3168     tlsm_PR_prs_unimp,          /* listen       */
3169     (PRShutdownFN)tlsm_PR_Shutdown,                     /* shutdown     */
3170     tlsm_PR_Recv,                       /* recv         */
3171     tlsm_PR_Send,                       /* send         */
3172     tlsm_PR_i32_unimp,          /* recvfrom     */
3173     tlsm_PR_i32_unimp,          /* sendto       */
3174     (PRPollFN)tlsm_PR_i16_unimp,        /* poll         */
3175     tlsm_PR_i32_unimp,          /* acceptread   */
3176     tlsm_PR_i32_unimp,          /* transmitfile */
3177     tlsm_PR_prs_unimp,          /* getsockname  */
3178     tlsm_PR_GetPeerName,        /* getpeername  */
3179     tlsm_PR_i32_unimp,          /* getsockopt   OBSOLETE */
3180     tlsm_PR_i32_unimp,          /* setsockopt   OBSOLETE */
3181     tlsm_PR_GetSocketOption,            /* getsocketoption   */
3182     tlsm_PR_i32_unimp,          /* setsocketoption   */
3183     tlsm_PR_i32_unimp,          /* Send a (partial) file with header/trailer*/
3184     (PRConnectcontinueFN)tlsm_PR_prs_unimp,             /* connectcontinue */
3185     tlsm_PR_i32_unimp,          /* reserved for future use */
3186     tlsm_PR_i32_unimp,          /* reserved for future use */
3187     tlsm_PR_i32_unimp,          /* reserved for future use */
3188     tlsm_PR_i32_unimp           /* reserved for future use */
3189 };
3190
3191 /*
3192  * Initialize TLS subsystem. Should be called only once.
3193  * See tlsm_deferred_init for the bulk of the init process
3194  */
3195 static int
3196 tlsm_init( void )
3197 {
3198         char *nofork = PR_GetEnv( "NSS_STRICT_NOFORK" );
3199
3200         PR_Init(0, 0, 0);
3201
3202         tlsm_layer_id = PR_GetUniqueIdentity( "OpenLDAP" );
3203
3204         /*
3205          * There are some applications that acquire a crypto context in the parent process
3206          * and expect that crypto context to work after a fork().  This does not work
3207          * with NSS using strict PKCS11 compliance mode.  We set this environment
3208          * variable here to tell the software encryption module/token to allow crypto
3209          * contexts to persist across a fork().  However, if you are using some other
3210          * module or encryption device that supports and expects full PKCS11 semantics,
3211          * the only recourse is to rewrite the application with atfork() handlers to save
3212          * the crypto context in the parent and restore (and SECMOD_RestartModules) the
3213          * context in the child.
3214          */
3215         if ( !nofork ) {
3216                 /* will leak one time */
3217                 char *noforkenvvar = PL_strdup( "NSS_STRICT_NOFORK=DISABLED" );
3218                 PR_SetEnv( noforkenvvar );
3219         }
3220
3221         return 0;
3222 }
3223
3224 static int
3225 tlsm_sb_setup( Sockbuf_IO_Desc *sbiod, void *arg )
3226 {
3227         struct tls_data         *p;
3228         tlsm_session    *session = arg;
3229         PRFileDesc *fd;
3230
3231         assert( sbiod != NULL );
3232
3233         p = LBER_MALLOC( sizeof( *p ) );
3234         if ( p == NULL ) {
3235                 return -1;
3236         }
3237
3238         fd = PR_GetIdentitiesLayer( session, tlsm_layer_id );
3239         if ( !fd ) {
3240                 LBER_FREE( p );
3241                 return -1;
3242         }
3243
3244         fd->secret = (PRFilePrivate *)p;
3245         p->session = session;
3246         p->sbiod = sbiod;
3247         p->firsttag = LBER_DEFAULT;
3248         sbiod->sbiod_pvt = p;
3249         return 0;
3250 }
3251
3252 static int
3253 tlsm_sb_remove( 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_Close( p->session );
3262         LBER_FREE( sbiod->sbiod_pvt );
3263         sbiod->sbiod_pvt = NULL;
3264         return 0;
3265 }
3266
3267 static int
3268 tlsm_sb_close( Sockbuf_IO_Desc *sbiod )
3269 {
3270         struct tls_data         *p;
3271         
3272         assert( sbiod != NULL );
3273         assert( sbiod->sbiod_pvt != NULL );
3274
3275         p = (struct tls_data *)sbiod->sbiod_pvt;
3276         PR_Shutdown( p->session, PR_SHUTDOWN_BOTH );
3277         return 0;
3278 }
3279
3280 static int
3281 tlsm_sb_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
3282 {
3283         struct tls_data         *p;
3284         
3285         assert( sbiod != NULL );
3286         assert( sbiod->sbiod_pvt != NULL );
3287
3288         p = (struct tls_data *)sbiod->sbiod_pvt;
3289         
3290         if ( opt == LBER_SB_OPT_GET_SSL ) {
3291                 *((tlsm_session **)arg) = p->session;
3292                 return 1;
3293                 
3294         } else if ( opt == LBER_SB_OPT_DATA_READY ) {
3295                 if ( p && ( SSL_DataPending( p->session ) > 0 ) ) {
3296                         return 1;
3297                 }
3298                 
3299         }
3300         
3301         return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
3302 }
3303
3304 static ber_slen_t
3305 tlsm_sb_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
3306 {
3307         struct tls_data         *p;
3308         ber_slen_t              ret;
3309         int                     err;
3310
3311         assert( sbiod != NULL );
3312         assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
3313
3314         p = (struct tls_data *)sbiod->sbiod_pvt;
3315
3316         ret = PR_Recv( p->session, buf, len, 0, PR_INTERVAL_NO_TIMEOUT );
3317         if ( ret < 0 ) {
3318                 err = PR_GetError();
3319                 if ( err == PR_PENDING_INTERRUPT_ERROR || err == PR_WOULD_BLOCK_ERROR ) {
3320                         sbiod->sbiod_sb->sb_trans_needs_read = 1;
3321                         sock_errset(EWOULDBLOCK);
3322                 }
3323         } else {
3324                 sbiod->sbiod_sb->sb_trans_needs_read = 0;
3325         }
3326         return ret;
3327 }
3328
3329 static ber_slen_t
3330 tlsm_sb_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
3331 {
3332         struct tls_data         *p;
3333         ber_slen_t              ret;
3334         int                     err;
3335
3336         assert( sbiod != NULL );
3337         assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
3338
3339         p = (struct tls_data *)sbiod->sbiod_pvt;
3340
3341         ret = PR_Send( p->session, (char *)buf, len, 0, PR_INTERVAL_NO_TIMEOUT );
3342         if ( ret < 0 ) {
3343                 err = PR_GetError();
3344                 if ( err == PR_PENDING_INTERRUPT_ERROR || err == PR_WOULD_BLOCK_ERROR ) {
3345                         sbiod->sbiod_sb->sb_trans_needs_write = 1;
3346                         sock_errset(EWOULDBLOCK);
3347                         ret = 0;
3348                 }
3349         } else {
3350                 sbiod->sbiod_sb->sb_trans_needs_write = 0;
3351         }
3352         return ret;
3353 }
3354
3355 static Sockbuf_IO tlsm_sbio =
3356 {
3357         tlsm_sb_setup,          /* sbi_setup */
3358         tlsm_sb_remove,         /* sbi_remove */
3359         tlsm_sb_ctrl,           /* sbi_ctrl */
3360         tlsm_sb_read,           /* sbi_read */
3361         tlsm_sb_write,          /* sbi_write */
3362         tlsm_sb_close           /* sbi_close */
3363 };
3364
3365 tls_impl ldap_int_tls_impl = {
3366         "MozNSS",
3367
3368         tlsm_init,
3369         tlsm_destroy,
3370
3371         tlsm_ctx_new,
3372         tlsm_ctx_ref,
3373         tlsm_ctx_free,
3374         tlsm_ctx_init,
3375
3376         tlsm_session_new,
3377         tlsm_session_connect,
3378         tlsm_session_accept,
3379         tlsm_session_upflags,
3380         tlsm_session_errmsg,
3381         tlsm_session_my_dn,
3382         tlsm_session_peer_dn,
3383         tlsm_session_chkhost,
3384         tlsm_session_strength,
3385         tlsm_session_unique,
3386         tlsm_session_version,
3387         tlsm_session_cipher,
3388         tlsm_session_peercert,
3389         NULL,
3390
3391         &tlsm_sbio,
3392
3393 #ifdef LDAP_R_COMPILE
3394         tlsm_thr_init,
3395 #else
3396         NULL,
3397 #endif
3398
3399         0
3400 };
3401
3402 #endif /* HAVE_MOZNSS */
3403 /*
3404   emacs settings
3405   Local Variables:
3406   indent-tabs-mode: t
3407   tab-width: 4
3408   End:
3409 */