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