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