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