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