]> git.sur5r.net Git - openldap/blob - libraries/libldap/tls_m.c
047aef12aae4f879ddbad604a8a5c4ae28f27091
[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  * This is the part of the init we defer until we get the
1211  * actual security configuration information.  This is
1212  * only called once, protected by a PRCallOnce
1213  * NOTE: This must be done before the first call to SSL_ImportFD,
1214  * especially the setting of the policy
1215  * NOTE: This must be called after fork()
1216  */
1217 static int
1218 tlsm_deferred_init( void *arg )
1219 {
1220         tlsm_ctx *ctx = (tlsm_ctx *)arg;
1221         struct ldaptls *lt = ctx->tc_config;
1222         const char *securitydirs[3];
1223         int ii;
1224         int nn;
1225         PRErrorCode errcode = 1;
1226 #ifdef HAVE_NSS_INITCONTEXT
1227         NSSInitParameters initParams;
1228         NSSInitContext *initctx = NULL;
1229 #endif
1230         SECStatus rc;
1231
1232 #ifdef HAVE_NSS_INITCONTEXT
1233         memset( &initParams, 0, sizeof( initParams ) );
1234         initParams.length = sizeof( initParams );
1235 #endif /* HAVE_NSS_INITCONTEXT */
1236
1237 #ifndef HAVE_NSS_INITCONTEXT
1238         if ( !NSS_IsInitialized() ) {
1239 #endif /* HAVE_NSS_INITCONTEXT */
1240                 /*
1241                   MOZNSS_DIR will override everything else - you can
1242                   always set MOZNSS_DIR to force the use of this
1243                   directory
1244                   If using MOZNSS, specify the location of the moznss db dir
1245                   in the cacertdir directive of the OpenLDAP configuration.
1246                   DEFAULT_MOZNSS_DIR will only be used if the code cannot
1247                   find a security dir to use based on the current
1248                   settings
1249                 */
1250                 nn = 0;
1251                 securitydirs[nn++] = PR_GetEnv( "MOZNSS_DIR" );
1252                 securitydirs[nn++] = lt->lt_cacertdir;
1253                 securitydirs[nn++] = PR_GetEnv( "DEFAULT_MOZNSS_DIR" );
1254                 for ( ii = 0; ii < nn; ++ii ) {
1255                         const char *securitydir = securitydirs[ii];
1256                         if ( NULL == securitydir ) {
1257                                 continue;
1258                         }
1259 #ifdef HAVE_NSS_INITCONTEXT
1260 #ifdef INITCONTEXT_HACK
1261                         if ( !NSS_IsInitialized() && ctx->tc_is_server ) {
1262                                 rc = NSS_Initialize( securitydir, "", "", SECMOD_DB, NSS_INIT_READONLY );
1263                         } else {
1264                                 initctx = NSS_InitContext( securitydir, "", "", SECMOD_DB,
1265                                                                                    &initParams, NSS_INIT_READONLY );
1266                                 rc = (initctx == NULL) ? SECFailure : SECSuccess;
1267                         }
1268 #else
1269                         initctx = NSS_InitContext( securitydir, "", "", SECMOD_DB,
1270                                                                            &initParams, NSS_INIT_READONLY );
1271                         rc = (initctx == NULL) ? SECFailure : SECSuccess;
1272 #endif
1273 #else
1274                         rc = NSS_Initialize( securitydir, "", "", SECMOD_DB, NSS_INIT_READONLY );
1275 #endif
1276
1277                         if ( rc != SECSuccess ) {
1278                                 errcode = PORT_GetError();
1279                                 Debug( LDAP_DEBUG_TRACE,
1280                                            "TLS: could not initialize moznss using security dir %s - error %d:%s.\n",
1281                                            securitydir, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1282                         } else {
1283                                 /* success */
1284                                 Debug( LDAP_DEBUG_TRACE, "TLS: using moznss security dir %s.\n",
1285                                            securitydir, 0, 0 );
1286                                 errcode = 0;
1287                                 break;
1288                         }
1289                 }
1290
1291                 if ( errcode ) { /* no moznss db found, or not using moznss db */
1292 #ifdef HAVE_NSS_INITCONTEXT
1293                         int flags = NSS_INIT_READONLY|NSS_INIT_NOCERTDB|NSS_INIT_NOMODDB;
1294 #ifdef INITCONTEXT_HACK
1295                         if ( !NSS_IsInitialized() && ctx->tc_is_server ) {
1296                                 rc = NSS_NoDB_Init( NULL );
1297                         } else {
1298                                 initctx = NSS_InitContext( "", "", "", SECMOD_DB,
1299                                                                                    &initParams, flags );
1300                                 rc = (initctx == NULL) ? SECFailure : SECSuccess;
1301                         }
1302 #else
1303                         initctx = NSS_InitContext( "", "", "", SECMOD_DB,
1304                                                                            &initParams, flags );
1305                         rc = (initctx == NULL) ? SECFailure : SECSuccess;
1306 #endif
1307 #else
1308                         rc = NSS_NoDB_Init( NULL );
1309 #endif
1310                         if ( rc != SECSuccess ) {
1311                                 errcode = PORT_GetError();
1312                                 Debug( LDAP_DEBUG_ANY,
1313                                            "TLS: could not initialize moznss - error %d:%s.\n",
1314                                            errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 );
1315                                 return -1;
1316                         }
1317
1318 #ifdef HAVE_NSS_INITCONTEXT
1319                         ctx->tc_initctx = initctx;
1320 #endif
1321
1322                         /* initialize the PEM module */
1323                         if ( tlsm_init_pem_module() ) {
1324                                 errcode = PORT_GetError();
1325                                 Debug( LDAP_DEBUG_ANY,
1326                                            "TLS: could not initialize moznss PEM module - error %d:%s.\n",
1327                                            errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 );
1328                                 return -1;
1329                         }
1330
1331                         if ( tlsm_init_ca_certs( ctx, lt->lt_cacertfile, lt->lt_cacertdir ) ) {
1332                                 return -1;
1333                         }
1334
1335                         ctx->tc_using_pem = PR_TRUE;
1336                 }
1337
1338 #ifdef HAVE_NSS_INITCONTEXT
1339                 if ( !ctx->tc_initctx ) {
1340                         ctx->tc_initctx = initctx;
1341                 }
1342 #endif
1343
1344                 NSS_SetDomesticPolicy();
1345
1346                 PK11_SetPasswordFunc( tlsm_pin_prompt );
1347
1348                 /* register cleanup function */
1349                 /* delete the old one, if any */
1350                 NSS_UnregisterShutdown( tlsm_nss_shutdown_cb, NULL );
1351                 NSS_RegisterShutdown( tlsm_nss_shutdown_cb, NULL );
1352
1353 #ifndef HAVE_NSS_INITCONTEXT
1354         }
1355 #endif /* HAVE_NSS_INITCONTEXT */
1356
1357         return 0;
1358 }
1359
1360 static int
1361 tlsm_authenticate( tlsm_ctx *ctx, const char *certname, const char *pininfo )
1362 {
1363         const char *colon = NULL;
1364         char *token_name = NULL;
1365         PK11SlotInfo *slot = NULL;
1366         int rc = -1;
1367
1368         if ( !certname || !*certname ) {
1369                 return 0;
1370         }
1371
1372         if ( ( colon = PL_strchr( certname, ':' ) ) ) {
1373                 token_name = PL_strndup( certname, colon-certname );
1374         }
1375
1376         if ( token_name ) {
1377                 slot = PK11_FindSlotByName( token_name );
1378         } else {
1379                 slot = PK11_GetInternalKeySlot();
1380         }
1381
1382         if ( !slot ) {
1383                 PRErrorCode errcode = PR_GetError();
1384                 Debug( LDAP_DEBUG_ANY,
1385                            "TLS: could not find the slot for security token %s - error %d:%s.\n",
1386                            token_name ? token_name : DEFAULT_TOKEN_NAME, errcode,
1387                            PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1388                 goto done;
1389         }
1390
1391         rc = tlsm_authenticate_to_slot( ctx, slot );
1392
1393 done:
1394         PL_strfree( token_name );
1395         if ( slot ) {
1396                 PK11_FreeSlot( slot );
1397         }
1398
1399         return rc;
1400 }
1401
1402 /*
1403  * Find and verify the certificate.
1404  * Either fd is given, in which case the cert will be taken from it via SSL_PeerCertificate
1405  * or certname is given, and it will be searched for by name
1406  */
1407 static int
1408 tlsm_find_and_verify_cert_key(tlsm_ctx *ctx, PRFileDesc *fd, const char *certname, int isServer, CERTCertificate **pRetCert, SECKEYPrivateKey **pRetKey)
1409 {
1410         CERTCertificate *cert = NULL;
1411         int rc = -1;
1412         void *pin_arg = NULL;
1413         SECKEYPrivateKey *key = NULL;
1414
1415         pin_arg = SSL_RevealPinArg( fd );
1416         if ( certname ) {
1417                 cert = PK11_FindCertFromNickname( certname, pin_arg );
1418                 if ( !cert ) {
1419                         PRErrorCode errcode = PR_GetError();
1420                         Debug( LDAP_DEBUG_ANY,
1421                                    "TLS: error: the certificate %s could not be found in the database - error %d:%s\n",
1422                                    certname, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1423                         return -1;
1424                 }
1425         } else {
1426                 /* we are verifying the peer cert
1427                    we also need to swap the isServer meaning */
1428                 cert = SSL_PeerCertificate( fd );
1429                 if ( !cert ) {
1430                         PRErrorCode errcode = PR_GetError();
1431                         Debug( LDAP_DEBUG_ANY,
1432                                    "TLS: error: could not get the certificate from the peer connection - error %d:%s\n",
1433                                    errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), NULL );
1434                         return -1;
1435                 }
1436                 isServer = !isServer; /* verify the peer's cert instead */
1437         }
1438
1439         if ( ctx->tc_slotname ) {
1440                 PK11SlotInfo *slot = PK11_FindSlotByName( ctx->tc_slotname );
1441                 key = PK11_FindPrivateKeyFromCert( slot, cert, NULL );
1442                 PK11_FreeSlot( slot );
1443         } else {
1444                 key = PK11_FindKeyByAnyCert( cert, pin_arg );
1445         }
1446
1447         if (key) {
1448                 SECCertificateUsage certUsage;
1449                 PRBool checkSig = PR_TRUE;
1450                 SECStatus status;
1451
1452                 if ( pRetKey ) {
1453                         *pRetKey = key; /* caller will deal with this */
1454                 } else {
1455                         SECKEY_DestroyPrivateKey( key );
1456                 }
1457                 if ( isServer ) {
1458                         certUsage = certificateUsageSSLServer;
1459                 } else {
1460                         certUsage = certificateUsageSSLClient;
1461                 }
1462                 if ( ctx->tc_verify_cert ) {
1463                         checkSig = PR_TRUE;
1464                 } else {
1465                         checkSig = PR_FALSE;
1466                 }
1467                 status = CERT_VerifyCertificateNow( ctx->tc_certdb, cert,
1468                                                                                         checkSig, certUsage,
1469                                                                                         pin_arg, NULL );
1470                 if ( status != SECSuccess ) {
1471                         /* NSS doesn't like self-signed CA certs that are also used for 
1472                            TLS/SSL server certs (such as generated by openssl req -x509)
1473                            CERT_VerifyCertificateNow returns SEC_ERROR_UNTRUSTED_ISSUER in that case
1474                            so, see if the cert and issuer are the same cert
1475                         */
1476                         PRErrorCode errcode = PR_GetError();
1477
1478                         if ( errcode == SEC_ERROR_UNTRUSTED_ISSUER ) {
1479                                 CERTCertificate *issuer = CERT_FindCertIssuer( cert, PR_Now(), certUsageSSLServer );
1480                                 if ( NULL == issuer ) {
1481                                         /* no issuer - fail */
1482                                         Debug( LDAP_DEBUG_ANY,
1483                                                    "TLS: error: the server certificate %s has no issuer - "
1484                                                    "please check this certificate for validity\n",
1485                                                    certname, 0, 0 );
1486                                 } else if ( CERT_CompareCerts( cert, issuer ) ) {
1487                                         /* self signed - warn and allow */
1488                                         status = SECSuccess;
1489                                         rc = 0;
1490                                         Debug( LDAP_DEBUG_ANY,
1491                                                    "TLS: warning: using self-signed server certificate %s\n",
1492                                                    certname, 0, 0 );
1493                                 }
1494                                 CERT_DestroyCertificate( issuer );
1495                         }
1496
1497                         if ( status != SECSuccess ) {
1498                                 Debug( LDAP_DEBUG_ANY,
1499                                            "TLS: error: the certificate %s is not valid - error %d:%s\n",
1500                                            certname, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1501                         }
1502                 } else {
1503                         rc = 0; /* success */
1504                 }
1505         } else {
1506                 PRErrorCode errcode = PR_GetError();
1507                 Debug( LDAP_DEBUG_ANY,
1508                            "TLS: error: could not find the private key for certificate %s - error %d:%s\n",
1509                            certname, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1510         }
1511
1512         if ( pRetCert ) {
1513                 *pRetCert = cert; /* caller will deal with this */
1514         } else {
1515                 CERT_DestroyCertificate( cert );
1516         }
1517
1518     return rc;
1519 }
1520
1521 static int
1522 tlsm_get_client_auth_data( void *arg, PRFileDesc *fd,
1523                                                    CERTDistNames *caNames, CERTCertificate **pRetCert,
1524                                                    SECKEYPrivateKey **pRetKey )
1525 {
1526         tlsm_ctx *ctx = (tlsm_ctx *)arg;
1527         int rc;
1528
1529         /* don't need caNames - this function will call CERT_VerifyCertificateNow
1530            which will verify the cert against the known CAs */
1531         rc = tlsm_find_and_verify_cert_key( ctx, fd, ctx->tc_certname, 0, pRetCert, pRetKey );
1532         if ( rc ) {
1533                 Debug( LDAP_DEBUG_ANY,
1534                            "TLS: error: unable to perform client certificate authentication for "
1535                            "certificate named %s\n", ctx->tc_certname, 0, 0 );
1536                 return SECFailure;
1537         }
1538
1539         return SECSuccess;
1540 }
1541
1542 /*
1543  * ctx must have a tc_model that is valid
1544  * certname is in the form [<tokenname>:]<certnickname>
1545  * where <tokenname> is the name of the PKCS11 token
1546  * and <certnickname> is the nickname of the cert/key in
1547  * the database
1548 */
1549 static int
1550 tlsm_clientauth_init( tlsm_ctx *ctx )
1551 {
1552         SECStatus status = SECFailure;
1553         int rc;
1554
1555         rc = tlsm_find_and_verify_cert_key( ctx, ctx->tc_model, ctx->tc_certname, 0, NULL, NULL );
1556         if ( rc ) {
1557                 Debug( LDAP_DEBUG_ANY,
1558                            "TLS: error: unable to set up client certificate authentication for "
1559                            "certificate named %s\n", ctx->tc_certname, 0, 0 );
1560                 return -1;
1561         }
1562
1563         status = SSL_GetClientAuthDataHook( ctx->tc_model,
1564                                                                                 tlsm_get_client_auth_data,
1565                                                                                 (void *)ctx );
1566
1567         return ( status == SECSuccess ? 0 : -1 );
1568 }
1569
1570 /*
1571  * Tear down the TLS subsystem. Should only be called once.
1572  */
1573 static void
1574 tlsm_destroy( void )
1575 {
1576 }
1577
1578 static tls_ctx *
1579 tlsm_ctx_new ( struct ldapoptions *lo )
1580 {
1581         tlsm_ctx *ctx;
1582
1583         ctx = LDAP_MALLOC( sizeof (*ctx) );
1584         if ( ctx ) {
1585                 ctx->tc_refcnt = 1;
1586 #ifdef LDAP_R_COMPILE
1587                 ldap_pvt_thread_mutex_init( &ctx->tc_refmutex );
1588 #endif
1589                 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 */
1590                 ctx->tc_certdb = NULL;
1591                 ctx->tc_certname = NULL;
1592                 ctx->tc_pin_file = NULL;
1593                 ctx->tc_model = NULL;
1594                 memset(&ctx->tc_callonce, 0, sizeof(ctx->tc_callonce));
1595                 ctx->tc_require_cert = lo->ldo_tls_require_cert;
1596                 ctx->tc_verify_cert = PR_FALSE;
1597                 ctx->tc_using_pem = PR_FALSE;
1598                 ctx->tc_slotname = NULL;
1599 #ifdef HAVE_NSS_INITCONTEXT
1600                 ctx->tc_initctx = NULL;
1601 #endif /* HAVE_NSS_INITCONTEXT */
1602                 ctx->tc_pem_objs = NULL;
1603                 ctx->tc_n_pem_objs = 0;
1604         }
1605         return (tls_ctx *)ctx;
1606 }
1607
1608 static void
1609 tlsm_ctx_ref( tls_ctx *ctx )
1610 {
1611         tlsm_ctx *c = (tlsm_ctx *)ctx;
1612 #ifdef LDAP_R_COMPILE
1613         ldap_pvt_thread_mutex_lock( &c->tc_refmutex );
1614 #endif
1615         c->tc_refcnt++;
1616 #ifdef LDAP_R_COMPILE
1617         ldap_pvt_thread_mutex_unlock( &c->tc_refmutex );
1618 #endif
1619 }
1620
1621 static void
1622 tlsm_ctx_free ( tls_ctx *ctx )
1623 {
1624         tlsm_ctx *c = (tlsm_ctx *)ctx;
1625         int refcount;
1626
1627         if ( !c ) return;
1628
1629 #ifdef LDAP_R_COMPILE
1630         ldap_pvt_thread_mutex_lock( &c->tc_refmutex );
1631 #endif
1632         refcount = --c->tc_refcnt;
1633 #ifdef LDAP_R_COMPILE
1634         ldap_pvt_thread_mutex_unlock( &c->tc_refmutex );
1635 #endif
1636         if ( refcount )
1637                 return;
1638         if ( c->tc_model )
1639                 PR_Close( c->tc_model );
1640         c->tc_certdb = NULL; /* if not the default, may have to clean up */
1641         PL_strfree( c->tc_certname );
1642         c->tc_certname = NULL;
1643         PL_strfree( c->tc_pin_file );
1644         c->tc_pin_file = NULL;
1645         PL_strfree( c->tc_slotname );           
1646         tlsm_free_pem_objs( c );
1647 #ifdef HAVE_NSS_INITCONTEXT
1648         if (c->tc_initctx)
1649                 NSS_ShutdownContext( c->tc_initctx );
1650         c->tc_initctx = NULL;
1651 #endif /* HAVE_NSS_INITCONTEXT */
1652 #ifdef LDAP_R_COMPILE
1653         ldap_pvt_thread_mutex_destroy( &c->tc_refmutex );
1654 #endif
1655         LDAP_FREE( c );
1656 }
1657
1658 /*
1659  * initialize a new TLS context
1660  */
1661 static int
1662 tlsm_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server )
1663 {
1664         tlsm_ctx *ctx = (tlsm_ctx *)lo->ldo_tls_ctx;
1665         ctx->tc_is_server = is_server;
1666
1667         return 0;
1668 }
1669
1670 static int
1671 tlsm_deferred_ctx_init( void *arg )
1672 {
1673         tlsm_ctx *ctx = (tlsm_ctx *)arg;
1674         PRBool sslv2 = PR_FALSE;
1675         PRBool sslv3 = PR_TRUE;
1676         PRBool tlsv1 = PR_TRUE;
1677         PRBool request_cert = PR_FALSE;
1678         PRInt32 require_cert = PR_FALSE;
1679         PRFileDesc *fd;
1680         struct ldaptls *lt;
1681
1682         if ( tlsm_deferred_init( ctx ) ) {
1683             Debug( LDAP_DEBUG_ANY,
1684                            "TLS: could perform TLS system initialization.\n",
1685                            0, 0, 0 );
1686             return -1;
1687         }
1688
1689         ctx->tc_certdb = CERT_GetDefaultCertDB(); /* If there is ever a per-context db, change this */
1690
1691         fd = PR_CreateIOLayerStub( tlsm_layer_id, &tlsm_PR_methods );
1692         if ( fd ) {
1693                 ctx->tc_model = SSL_ImportFD( NULL, fd );
1694         }
1695
1696         if ( !ctx->tc_model ) {
1697                 PRErrorCode err = PR_GetError();
1698                 Debug( LDAP_DEBUG_ANY,
1699                            "TLS: could perform TLS socket I/O layer initialization - error %d:%s.\n",
1700                            err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL );
1701
1702                 if ( fd ) {
1703                         PR_Close( fd );
1704                 }
1705                 return -1;
1706         }
1707
1708         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_SECURITY, PR_TRUE ) ) {
1709                 Debug( LDAP_DEBUG_ANY,
1710                        "TLS: could not set secure mode on.\n",
1711                        0, 0, 0 );
1712                 return -1;
1713         }
1714
1715         lt = ctx->tc_config;
1716
1717         /* default is sslv3 and tlsv1 */
1718         if ( lt->lt_protocol_min ) {
1719                 if ( lt->lt_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_SSL3 ) {
1720                         sslv3 = PR_FALSE;
1721                 } else if ( lt->lt_protocol_min <= LDAP_OPT_X_TLS_PROTOCOL_SSL2 ) {
1722                         sslv2 = PR_TRUE;
1723                         Debug( LDAP_DEBUG_ANY,
1724                                "TLS: warning: minimum TLS protocol level set to "
1725                                "include SSLv2 - SSLv2 is insecure - do not use\n", 0, 0, 0 );
1726                 }
1727         }
1728         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_ENABLE_SSL2, sslv2 ) ) {
1729                 Debug( LDAP_DEBUG_ANY,
1730                        "TLS: could not set SSLv2 mode on.\n",
1731                        0, 0, 0 );
1732                 return -1;
1733         }
1734         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_ENABLE_SSL3, sslv3 ) ) {
1735                 Debug( LDAP_DEBUG_ANY,
1736                        "TLS: could not set SSLv3 mode on.\n",
1737                        0, 0, 0 );
1738                 return -1;
1739         }
1740         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_ENABLE_TLS, tlsv1 ) ) {
1741                 Debug( LDAP_DEBUG_ANY,
1742                        "TLS: could not set TLSv1 mode on.\n",
1743                        0, 0, 0 );
1744                 return -1;
1745         }
1746
1747         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_HANDSHAKE_AS_CLIENT, !ctx->tc_is_server ) ) {
1748                 Debug( LDAP_DEBUG_ANY,
1749                        "TLS: could not set handshake as client.\n",
1750                        0, 0, 0 );
1751                 return -1;
1752         }
1753         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_HANDSHAKE_AS_SERVER, ctx->tc_is_server ) ) {
1754                 Debug( LDAP_DEBUG_ANY,
1755                        "TLS: could not set handshake as server.\n",
1756                        0, 0, 0 );
1757                 return -1;
1758         }
1759
1760         if ( lt->lt_ciphersuite &&
1761              tlsm_parse_ciphers( ctx, lt->lt_ciphersuite )) {
1762                 Debug( LDAP_DEBUG_ANY,
1763                        "TLS: could not set cipher list %s.\n",
1764                        lt->lt_ciphersuite, 0, 0 );
1765                 return -1;
1766         }
1767
1768         if ( ctx->tc_require_cert ) {
1769                 request_cert = PR_TRUE;
1770                 require_cert = SSL_REQUIRE_NO_ERROR;
1771                 if ( ctx->tc_require_cert == LDAP_OPT_X_TLS_DEMAND ||
1772                      ctx->tc_require_cert == LDAP_OPT_X_TLS_HARD ) {
1773                         require_cert = SSL_REQUIRE_ALWAYS;
1774                 }
1775                 if ( ctx->tc_require_cert != LDAP_OPT_X_TLS_ALLOW )
1776                         ctx->tc_verify_cert = PR_TRUE;
1777         } else {
1778                 ctx->tc_verify_cert = PR_FALSE;
1779         }
1780
1781         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_REQUEST_CERTIFICATE, request_cert ) ) {
1782                 Debug( LDAP_DEBUG_ANY,
1783                        "TLS: could not set request certificate mode.\n",
1784                        0, 0, 0 );
1785                 return -1;
1786         }
1787                 
1788         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_REQUIRE_CERTIFICATE, require_cert ) ) {
1789                 Debug( LDAP_DEBUG_ANY,
1790                        "TLS: could not set require certificate mode.\n",
1791                        0, 0, 0 );
1792                 return -1;
1793         }
1794
1795         /* set up our cert and key, if any */
1796         if ( lt->lt_certfile ) {
1797                 /* if using the PEM module, load the PEM file specified by lt_certfile */
1798                 /* otherwise, assume this is the name of a cert already in the db */
1799                 if ( ctx->tc_using_pem ) {
1800                         /* this sets ctx->tc_certname to the correct value */
1801                         int rc = tlsm_add_cert_from_file( ctx, lt->lt_certfile, PR_FALSE /* not a ca */ );
1802                         if ( rc ) {
1803                                 return rc;
1804                         }
1805                 } else {
1806                         PL_strfree( ctx->tc_certname );
1807                         ctx->tc_certname = PL_strdup( lt->lt_certfile );
1808                 }
1809         }
1810
1811         if ( lt->lt_keyfile ) {
1812                 /* if using the PEM module, load the PEM file specified by lt_keyfile */
1813                 /* otherwise, assume this is the pininfo for the key */
1814                 if ( ctx->tc_using_pem ) {
1815                         /* this sets ctx->tc_certname to the correct value */
1816                         int rc = tlsm_add_key_from_file( ctx, lt->lt_keyfile );
1817                         if ( rc ) {
1818                                 return rc;
1819                         }
1820                 } else {
1821                         PL_strfree( ctx->tc_pin_file );
1822                         ctx->tc_pin_file = PL_strdup( lt->lt_keyfile );
1823                 }
1824         }
1825
1826         /* Set up callbacks for use by clients */
1827         if ( !ctx->tc_is_server ) {
1828                 if ( SSL_OptionSet( ctx->tc_model, SSL_NO_CACHE, PR_TRUE ) != SECSuccess ) {
1829                         PRErrorCode err = PR_GetError();
1830                         Debug( LDAP_DEBUG_ANY, 
1831                                "TLS: error: could not set nocache option for moznss - error %d:%s\n",
1832                                err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL );
1833                         return -1;
1834                 }
1835
1836                 if ( SSL_BadCertHook( ctx->tc_model, tlsm_bad_cert_handler, ctx ) != SECSuccess ) {
1837                         PRErrorCode err = PR_GetError();
1838                         Debug( LDAP_DEBUG_ANY, 
1839                                "TLS: error: could not set bad cert handler for moznss - error %d:%s\n",
1840                                err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL );
1841                         return -1;
1842                 }
1843
1844                 /* 
1845                    since a cert has been specified, assume the client wants to do cert auth
1846                 */
1847                 if ( ctx->tc_certname ) {
1848                         if ( tlsm_authenticate( ctx, ctx->tc_certname, ctx->tc_pin_file ) ) {
1849                                 Debug( LDAP_DEBUG_ANY, 
1850                                        "TLS: error: unable to authenticate to the security device for certificate %s\n",
1851                                        ctx->tc_certname, 0, 0 );
1852                                 return -1;
1853                         }
1854                         if ( tlsm_clientauth_init( ctx ) ) {
1855                                 Debug( LDAP_DEBUG_ANY, 
1856                                        "TLS: error: unable to set up client certificate authentication using %s\n",
1857                                        ctx->tc_certname, 0, 0 );
1858                                 return -1;
1859                         }
1860                 }
1861         } else { /* set up secure server */
1862                 SSLKEAType certKEA;
1863                 CERTCertificate *serverCert;
1864                 SECKEYPrivateKey *serverKey;
1865                 SECStatus status;
1866
1867                 /* must have a certificate for the server to use */
1868                 if ( !ctx->tc_certname ) {
1869                         Debug( LDAP_DEBUG_ANY, 
1870                                "TLS: error: no server certificate: must specify a certificate for the server to use\n",
1871                                0, 0, 0 );
1872                         return -1;
1873                 }
1874
1875                 /* authenticate to the server's token - this will do nothing
1876                    if the key/cert db is not password protected */
1877                 if ( tlsm_authenticate( ctx, ctx->tc_certname, ctx->tc_pin_file ) ) {
1878                         Debug( LDAP_DEBUG_ANY, 
1879                                "TLS: error: unable to authenticate to the security device for certificate %s\n",
1880                                ctx->tc_certname, 0, 0 );
1881                         return -1;
1882                 }
1883
1884                 /* get the server's key and cert */
1885                 if ( tlsm_find_and_verify_cert_key( ctx, ctx->tc_model, ctx->tc_certname, ctx->tc_is_server,
1886                                                     &serverCert, &serverKey ) ) {
1887                         Debug( LDAP_DEBUG_ANY, 
1888                                "TLS: error: unable to find and verify server's cert and key for certificate %s\n",
1889                                ctx->tc_certname, 0, 0 );
1890                         return -1;
1891                 }
1892
1893                 certKEA = NSS_FindCertKEAType( serverCert );
1894                 /* configure the socket to be a secure server socket */
1895                 status = SSL_ConfigSecureServer( ctx->tc_model, serverCert, serverKey, certKEA );
1896                 /* SSL_ConfigSecureServer copies these */
1897                 CERT_DestroyCertificate( serverCert );
1898                 SECKEY_DestroyPrivateKey( serverKey );
1899
1900                 if ( SECSuccess != status ) {
1901                         PRErrorCode err = PR_GetError();
1902                         Debug( LDAP_DEBUG_ANY, 
1903                                "TLS: error: unable to configure secure server using certificate %s - error %d:%s\n",
1904                                ctx->tc_certname, err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ) );
1905                         return -1;
1906                 }
1907         }
1908
1909         /* Callback for authenticating certificate */
1910         if ( SSL_AuthCertificateHook( ctx->tc_model, tlsm_auth_cert_handler,
1911                                   ctx->tc_certdb ) != SECSuccess ) {
1912                 PRErrorCode err = PR_GetError();
1913                 Debug( LDAP_DEBUG_ANY, 
1914                        "TLS: error: could not set auth cert handler for moznss - error %d:%s\n",
1915                        err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL );
1916                 return -1;
1917         }
1918
1919         return 0;
1920 }
1921
1922 struct tls_data {
1923         tlsm_session            *session;
1924         Sockbuf_IO_Desc         *sbiod;
1925         /* there seems to be no portable way to determine if the
1926            sockbuf sd has been set to nonblocking mode - the
1927            call to ber_pvt_socket_set_nonblock() takes place
1928            before the tls socket is set up, so we cannot
1929            intercept that call either.
1930            On systems where fcntl is available, we can just
1931            F_GETFL and test for O_NONBLOCK.  On other systems,
1932            we will just see if the IO op returns EAGAIN or EWOULDBLOCK,
1933            and just set this flag */
1934         PRBool              nonblock;
1935 };
1936
1937 static int
1938 tlsm_is_io_ready( PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags )
1939 {
1940         struct tls_data         *p;
1941         PRFileDesc *pollfd = NULL;
1942         PRFileDesc *myfd;
1943         PRPollDesc polldesc;
1944         int rc;
1945
1946         myfd = PR_GetIdentitiesLayer( fd, tlsm_layer_id );
1947
1948         if ( !myfd ) {
1949                 return 0;
1950         }
1951
1952         p = (struct tls_data *)myfd->secret;
1953
1954         if ( p == NULL || p->sbiod == NULL ) {
1955                 return 0;
1956         }
1957
1958         /* wrap the sockbuf fd with a NSPR FD created especially
1959            for use with polling, and only with polling */
1960         pollfd = PR_CreateSocketPollFd( p->sbiod->sbiod_sb->sb_fd );
1961         polldesc.fd = pollfd;
1962         polldesc.in_flags = in_flags;
1963         polldesc.out_flags = 0;
1964
1965         /* do the poll - no waiting, no blocking */
1966         rc = PR_Poll( &polldesc, 1, PR_INTERVAL_NO_WAIT );
1967
1968         /* unwrap the socket */
1969         PR_DestroySocketPollFd( pollfd );
1970
1971         /* rc will be either 1 if IO is ready, 0 if IO is not
1972            ready, or -1 if there was some error (and the caller
1973            should use PR_GetError() to figure out what */
1974         if (out_flags) {
1975                 *out_flags = polldesc.out_flags;
1976         }
1977         return rc;
1978 }
1979
1980 static tls_session *
1981 tlsm_session_new ( tls_ctx * ctx, int is_server )
1982 {
1983         tlsm_ctx *c = (tlsm_ctx *)ctx;
1984         tlsm_session *session;
1985         PRFileDesc *fd;
1986         PRStatus status;
1987
1988         c->tc_is_server = is_server;
1989         status = PR_CallOnceWithArg( &c->tc_callonce, tlsm_deferred_ctx_init, c );
1990         if ( PR_SUCCESS != status ) {
1991                 PRErrorCode err = PR_GetError();
1992                 Debug( LDAP_DEBUG_ANY, 
1993                        "TLS: error: could not initialize moznss security context - error %d:%s\n",
1994                        err, PR_ErrorToString(err, PR_LANGUAGE_I_DEFAULT), NULL );
1995                 return NULL;
1996         }
1997
1998         fd = PR_CreateIOLayerStub( tlsm_layer_id, &tlsm_PR_methods );
1999         if ( !fd ) {
2000                 return NULL;
2001         }
2002
2003         session = SSL_ImportFD( c->tc_model, fd );
2004         if ( !session ) {
2005                 PR_DELETE( fd );
2006                 return NULL;
2007         }
2008
2009         if ( is_server ) {
2010                 /* 0 means use the defaults here */
2011                 SSL_ConfigServerSessionIDCache( 0, 0, 0, NULL );
2012         }
2013
2014         return (tls_session *)session;
2015
2016
2017 static int
2018 tlsm_session_accept( tls_session *session )
2019 {
2020         tlsm_session *s = (tlsm_session *)session;
2021         int rc;
2022         PRErrorCode err;
2023         int waitcounter = 0;
2024
2025         rc = SSL_ResetHandshake( s, PR_TRUE /* server */ );
2026         if (rc) {
2027                 err = PR_GetError();
2028                 Debug( LDAP_DEBUG_TRACE, 
2029                            "TLS: error: accept - reset handshake failure %d - error %d:%s\n",
2030                            rc, err,
2031                            err ? PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ) : "unknown" );
2032         }
2033
2034         do {
2035                 PRInt32 filesReady;
2036                 PRInt16 in_flags;
2037                 PRInt16 out_flags;
2038
2039                 errno = 0;
2040                 rc = SSL_ForceHandshake( s );
2041                 if (rc == SECSuccess) {
2042                         rc = 0;
2043                         break; /* done */
2044                 }
2045                 err = PR_GetError();
2046                 Debug( LDAP_DEBUG_TRACE, 
2047                            "TLS: error: accept - force handshake failure %d - error %d waitcounter %d\n",
2048                            errno, err, waitcounter );
2049                 if ( errno == EAGAIN || errno == EWOULDBLOCK ) {
2050                         waitcounter++;
2051                         in_flags = PR_POLL_READ | PR_POLL_EXCEPT;
2052                         out_flags = 0;
2053                         errno = 0;
2054                         filesReady = tlsm_is_io_ready( s, in_flags, &out_flags );
2055                         if ( filesReady < 0 ) {
2056                                 err = PR_GetError();
2057                                 Debug( LDAP_DEBUG_ANY, 
2058                                            "TLS: error: accept - error waiting for socket to be ready: %d - error %d:%s\n",
2059                                            errno, err,
2060                                            err ? PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ) : "unknown" );
2061                                 rc = -1;
2062                                 break; /* hard error */
2063                         } else if ( out_flags & PR_POLL_NVAL ) {
2064                                 PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
2065                                 Debug( LDAP_DEBUG_ANY, 
2066                                            "TLS: error: accept failure - invalid socket\n",
2067                                            NULL, NULL, NULL );
2068                                 rc = -1;
2069                                 break;
2070                         } else if ( out_flags & PR_POLL_EXCEPT ) {
2071                                 err = PR_GetError();
2072                                 Debug( LDAP_DEBUG_ANY, 
2073                                            "TLS: error: accept - error waiting for socket to be ready: %d - error %d:%s\n",
2074                                            errno, err,
2075                                            err ? PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ) : "unknown" );
2076                                 rc = -1;
2077                                 break; /* hard error */
2078                         }
2079                 } else { /* hard error */
2080                         err = PR_GetError();
2081                         Debug( LDAP_DEBUG_ANY, 
2082                                    "TLS: error: accept - force handshake failure: %d - error %d:%s\n",
2083                                    errno, err,
2084                                    err ? PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ) : "unknown" );
2085                         rc = -1;
2086                         break; /* hard error */
2087                 }
2088         } while (rc == SECFailure);
2089
2090         Debug( LDAP_DEBUG_TRACE, 
2091                    "TLS: accept completed after %d waits\n", waitcounter, NULL, NULL );
2092
2093         return rc;
2094 }
2095
2096 static int
2097 tlsm_session_connect( LDAP *ld, tls_session *session )
2098 {
2099         tlsm_session *s = (tlsm_session *)session;
2100         int rc;
2101         PRErrorCode err;
2102
2103         rc = SSL_ResetHandshake( s, PR_FALSE /* server */ );
2104         if (rc) {
2105                 err = PR_GetError();
2106                 Debug( LDAP_DEBUG_TRACE, 
2107                            "TLS: error: connect - reset handshake failure %d - error %d:%s\n",
2108                            rc, err,
2109                            err ? PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ) : "unknown" );
2110         }
2111
2112         rc = SSL_ForceHandshake( s );
2113         if (rc) {
2114                 err = PR_GetError();
2115                 Debug( LDAP_DEBUG_TRACE, 
2116                            "TLS: error: connect - force handshake failure %d - error %d:%s\n",
2117                            rc, err,
2118                            err ? PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ) : "unknown" );
2119         }
2120
2121         return rc;
2122 }
2123
2124 static int
2125 tlsm_session_upflags( Sockbuf *sb, tls_session *session, int rc )
2126 {
2127         /* Should never happen */
2128         rc = PR_GetError();
2129
2130         if ( rc != PR_PENDING_INTERRUPT_ERROR && rc != PR_WOULD_BLOCK_ERROR )
2131                 return 0;
2132         return 0;
2133 }
2134
2135 static char *
2136 tlsm_session_errmsg( tls_session *sess, int rc, char *buf, size_t len )
2137 {
2138         int i;
2139
2140         rc = PR_GetError();
2141         i = PR_GetErrorTextLength();
2142         if ( i > len ) {
2143                 char *msg = LDAP_MALLOC( i+1 );
2144                 PR_GetErrorText( msg );
2145                 memcpy( buf, msg, len );
2146                 LDAP_FREE( msg );
2147         } else if ( i ) {
2148                 PR_GetErrorText( buf );
2149         }
2150
2151         return i ? buf : NULL;
2152 }
2153
2154 static int
2155 tlsm_session_my_dn( tls_session *session, struct berval *der_dn )
2156 {
2157         tlsm_session *s = (tlsm_session *)session;
2158         CERTCertificate *cert;
2159
2160         cert = SSL_LocalCertificate( s );
2161         if (!cert) return LDAP_INVALID_CREDENTIALS;
2162
2163         der_dn->bv_val = cert->derSubject.data;
2164         der_dn->bv_len = cert->derSubject.len;
2165         CERT_DestroyCertificate( cert );
2166         return 0;
2167 }
2168
2169 static int
2170 tlsm_session_peer_dn( tls_session *session, struct berval *der_dn )
2171 {
2172         tlsm_session *s = (tlsm_session *)session;
2173         CERTCertificate *cert;
2174
2175         cert = SSL_PeerCertificate( s );
2176         if (!cert) return LDAP_INVALID_CREDENTIALS;
2177         
2178         der_dn->bv_val = cert->derSubject.data;
2179         der_dn->bv_len = cert->derSubject.len;
2180         CERT_DestroyCertificate( cert );
2181         return 0;
2182 }
2183
2184 /* what kind of hostname were we given? */
2185 #define IS_DNS  0
2186 #define IS_IP4  1
2187 #define IS_IP6  2
2188
2189 static int
2190 tlsm_session_chkhost( LDAP *ld, tls_session *session, const char *name_in )
2191 {
2192         tlsm_session *s = (tlsm_session *)session;
2193         CERTCertificate *cert;
2194         const char *name, *domain = NULL, *ptr;
2195         int i, ret, ntype = IS_DNS, nlen, dlen;
2196 #ifdef LDAP_PF_INET6
2197         struct in6_addr addr;
2198 #else
2199         struct in_addr addr;
2200 #endif
2201         SECItem altname;
2202         SECStatus rv;
2203
2204         if( ldap_int_hostname &&
2205                 ( !name_in || !strcasecmp( name_in, "localhost" ) ) )
2206         {
2207                 name = ldap_int_hostname;
2208         } else {
2209                 name = name_in;
2210         }
2211         nlen = strlen( name );
2212
2213         cert = SSL_PeerCertificate( s );
2214         if (!cert) {
2215                 Debug( LDAP_DEBUG_ANY,
2216                         "TLS: unable to get peer certificate.\n",
2217                         0, 0, 0 );
2218                 /* if this was a fatal condition, things would have
2219                  * aborted long before now.
2220                  */
2221                 return LDAP_SUCCESS;
2222         }
2223
2224 #ifdef LDAP_PF_INET6
2225         if (name[0] == '[' && strchr(name, ']')) {
2226                 char *n2 = ldap_strdup(name+1);
2227                 *strchr(n2, ']') = 0;
2228                 if (inet_pton(AF_INET6, n2, &addr))
2229                         ntype = IS_IP6;
2230                 LDAP_FREE(n2);
2231         } else 
2232 #endif
2233         if ((ptr = strrchr(name, '.')) && isdigit((unsigned char)ptr[1])) {
2234                 if (inet_aton(name, (struct in_addr *)&addr)) ntype = IS_IP4;
2235         }
2236         if (ntype == IS_DNS ) {
2237                 domain = strchr( name, '.' );
2238                 if ( domain )
2239                         dlen = nlen - ( domain - name );
2240         }
2241
2242         ret = LDAP_LOCAL_ERROR;
2243
2244         rv = CERT_FindCertExtension( cert, SEC_OID_X509_SUBJECT_ALT_NAME,
2245                 &altname );
2246         if ( rv == SECSuccess && altname.data ) {
2247                 PRArenaPool *arena;
2248                 CERTGeneralName *names, *cur;
2249
2250                 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2251                 if ( !arena ) {
2252                         ret = LDAP_NO_MEMORY;
2253                         goto fail;
2254                 }
2255
2256                 names = cur = CERT_DecodeAltNameExtension(arena, &altname);
2257                 if ( !cur )
2258                         goto altfail;
2259
2260                 do {
2261                         char *host;
2262                         int hlen;
2263
2264                         /* ignore empty */
2265                         if ( !cur->name.other.len ) continue;
2266
2267                         host = cur->name.other.data;
2268                         hlen = cur->name.other.len;
2269
2270                         if ( cur->type == certDNSName ) {
2271                                 if ( ntype != IS_DNS )  continue;
2272
2273                                 /* is this an exact match? */
2274                                 if ( nlen == hlen && !strncasecmp( name, host, nlen )) {
2275                                         ret = LDAP_SUCCESS;
2276                                         break;
2277                                 }
2278
2279                                 /* is this a wildcard match? */
2280                                 if ( domain && host[0] == '*' && host[1] == '.' &&
2281                                         dlen == hlen-1 && !strncasecmp( domain, host+1, dlen )) {
2282                                         ret = LDAP_SUCCESS;
2283                                         break;
2284                                 }
2285                         } else if ( cur->type == certIPAddress ) {
2286                                 if ( ntype == IS_DNS )  continue;
2287                                 
2288 #ifdef LDAP_PF_INET6
2289                                 if (ntype == IS_IP6 && hlen != sizeof(struct in6_addr)) {
2290                                         continue;
2291                                 } else
2292 #endif
2293                                 if (ntype == IS_IP4 && hlen != sizeof(struct in_addr)) {
2294                                         continue;
2295                                 }
2296                                 if (!memcmp(host, &addr, hlen)) {
2297                                         ret = LDAP_SUCCESS;
2298                                         break;
2299                                 }
2300                         }
2301                 } while (( cur = CERT_GetNextGeneralName( cur )) != names );
2302 altfail:
2303                 PORT_FreeArena( arena, PR_FALSE );
2304                 SECITEM_FreeItem( &altname, PR_FALSE );
2305         }
2306         /* no altnames matched, try the CN */
2307         if ( ret != LDAP_SUCCESS ) {
2308                 /* find the last CN */
2309                 CERTRDN *rdn, **rdns;
2310                 CERTAVA *lastava = NULL;
2311                 char buf[2048];
2312
2313                 buf[0] = '\0';
2314                 rdns = cert->subject.rdns;
2315                 while ( rdns && ( rdn = *rdns++ )) {
2316                         CERTAVA *ava, **avas = rdn->avas;
2317                         while ( avas && ( ava = *avas++ )) {
2318                                 if ( CERT_GetAVATag( ava ) == SEC_OID_AVA_COMMON_NAME )
2319                                         lastava = ava;
2320                         }
2321                 }
2322                 if ( lastava ) {
2323                         SECItem *av = CERT_DecodeAVAValue( &lastava->value );
2324                         if ( av ) {
2325                                 if ( av->len == nlen && !strncasecmp( name, av->data, nlen )) {
2326                                         ret = LDAP_SUCCESS;
2327                                 } else if ( av->data[0] == '*' && av->data[1] == '.' &&
2328                                         domain && dlen == av->len - 1 && !strncasecmp( name,
2329                                                 av->data+1, dlen )) {
2330                                         ret = LDAP_SUCCESS;
2331                                 } else {
2332                                         int len = av->len;
2333                                         if ( len >= sizeof(buf) )
2334                                                 len = sizeof(buf)-1;
2335                                         memcpy( buf, av->data, len );
2336                                         buf[len] = '\0';
2337                                 }
2338                                 SECITEM_FreeItem( av, PR_TRUE );
2339                         }
2340                 }
2341                 if ( ret != LDAP_SUCCESS ) {
2342                         Debug( LDAP_DEBUG_ANY, "TLS: hostname (%s) does not match "
2343                                 "common name in certificate (%s).\n", 
2344                                 name, buf, 0 );
2345                         ret = LDAP_CONNECT_ERROR;
2346                         if ( ld->ld_error ) {
2347                                 LDAP_FREE( ld->ld_error );
2348                         }
2349                         ld->ld_error = LDAP_STRDUP(
2350                                 _("TLS: hostname does not match CN in peer certificate"));
2351                 }
2352         }
2353
2354 fail:
2355         CERT_DestroyCertificate( cert );
2356         return ret;
2357 }
2358
2359 static int
2360 tlsm_session_strength( tls_session *session )
2361 {
2362         tlsm_session *s = (tlsm_session *)session;
2363         int rc, keySize;
2364
2365         rc = SSL_SecurityStatus( s, NULL, NULL, NULL, &keySize,
2366                 NULL, NULL );
2367         return rc ? 0 : keySize;
2368 }
2369
2370 /*
2371  * TLS support for LBER Sockbufs
2372  */
2373
2374 static PRStatus PR_CALLBACK
2375 tlsm_PR_Close(PRFileDesc *fd)
2376 {
2377         int rc = PR_SUCCESS;
2378
2379         /* we don't need to actually close anything here, just
2380            pop our io layer off the stack */
2381         fd->secret = NULL; /* must have been freed before calling PR_Close */
2382         if ( fd->lower ) {
2383                 fd = PR_PopIOLayer( fd, tlsm_layer_id );
2384                 /* if we are not the last layer, pass the close along */
2385                 if ( fd ) {
2386                         if ( fd->dtor ) {
2387                                 fd->dtor( fd );
2388                         }
2389                         rc = fd->methods->close( fd );
2390                 }
2391         } else {
2392                 /* we are the last layer - just call our dtor */
2393                 fd->dtor(fd);
2394         }
2395
2396         return rc;
2397 }
2398
2399 static PRStatus PR_CALLBACK
2400 tlsm_PR_Shutdown(PRFileDesc *fd, PRShutdownHow how)
2401 {
2402         int rc = PR_SUCCESS;
2403
2404         if ( fd->lower ) {
2405                 rc = PR_Shutdown( fd->lower, how );
2406         }
2407
2408         return rc;
2409 }
2410
2411 static int PR_CALLBACK
2412 tlsm_PR_Recv(PRFileDesc *fd, void *buf, PRInt32 len, PRIntn flags,
2413          PRIntervalTime timeout)
2414 {
2415         struct tls_data         *p;
2416         int rc;
2417
2418         if ( buf == NULL || len <= 0 ) return 0;
2419
2420         p = (struct tls_data *)fd->secret;
2421
2422         if ( p == NULL || p->sbiod == NULL ) {
2423                 return 0;
2424         }
2425
2426         rc = LBER_SBIOD_READ_NEXT( p->sbiod, buf, len );
2427         if (rc <= 0) {
2428                 tlsm_map_error( errno );
2429                 if ( errno == EAGAIN || errno == EWOULDBLOCK ) {
2430                         p->nonblock = PR_TRUE; /* fd is using non-blocking io */
2431                 } else if ( errno ) { /* real error */
2432                         Debug( LDAP_DEBUG_TRACE, 
2433                                "TLS: error: tlsm_PR_Recv returned %d - error %d:%s\n",
2434                                rc, errno, STRERROR(errno) );
2435                 }
2436         }
2437
2438         return rc;
2439 }
2440
2441 static int PR_CALLBACK
2442 tlsm_PR_Send(PRFileDesc *fd, const void *buf, PRInt32 len, PRIntn flags,
2443          PRIntervalTime timeout)
2444 {
2445         struct tls_data         *p;
2446         int rc;
2447
2448         if ( buf == NULL || len <= 0 ) return 0;
2449
2450         p = (struct tls_data *)fd->secret;
2451
2452         if ( p == NULL || p->sbiod == NULL ) {
2453                 return 0;
2454         }
2455
2456         rc = LBER_SBIOD_WRITE_NEXT( p->sbiod, (char *)buf, len );
2457         if (rc <= 0) {
2458                 tlsm_map_error( errno );
2459                 if ( errno == EAGAIN || errno == EWOULDBLOCK ) {
2460                         p->nonblock = PR_TRUE;
2461                 } else if ( errno ) { /* real error */
2462                         Debug( LDAP_DEBUG_TRACE, 
2463                                "TLS: error: tlsm_PR_Send returned %d - error %d:%s\n",
2464                                rc, errno, STRERROR(errno) );
2465                 }
2466         }
2467
2468         return rc;
2469 }
2470
2471 static int PR_CALLBACK
2472 tlsm_PR_Read(PRFileDesc *fd, void *buf, PRInt32 len)
2473 {
2474         return tlsm_PR_Recv( fd, buf, len, 0, PR_INTERVAL_NO_TIMEOUT );
2475 }
2476
2477 static int PR_CALLBACK
2478 tlsm_PR_Write(PRFileDesc *fd, const void *buf, PRInt32 len)
2479 {
2480         return tlsm_PR_Send( fd, buf, len, 0, PR_INTERVAL_NO_TIMEOUT );
2481 }
2482
2483 static PRStatus PR_CALLBACK
2484 tlsm_PR_GetPeerName(PRFileDesc *fd, PRNetAddr *addr)
2485 {
2486         struct tls_data         *p;
2487         int rc;
2488         ber_socklen_t len;
2489
2490         p = (struct tls_data *)fd->secret;
2491
2492         if ( p == NULL || p->sbiod == NULL ) {
2493                 return PR_FAILURE;
2494         }
2495         len = sizeof(PRNetAddr);
2496         return getpeername( p->sbiod->sbiod_sb->sb_fd, (struct sockaddr *)addr, &len );
2497 }
2498
2499 static PRStatus PR_CALLBACK
2500 tlsm_PR_GetSocketOption(PRFileDesc *fd, PRSocketOptionData *data)
2501 {
2502         struct tls_data         *p;
2503         p = (struct tls_data *)fd->secret;
2504
2505         if ( !data ) {
2506                 return PR_FAILURE;
2507         }
2508
2509         /* only the nonblocking option is supported at this time
2510            MozNSS SSL code needs it */
2511         if ( data->option != PR_SockOpt_Nonblocking ) {
2512                 PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
2513                 return PR_FAILURE;
2514         }
2515 #ifdef HAVE_FCNTL
2516         int flags = fcntl( p->sbiod->sbiod_sb->sb_fd, F_GETFL );
2517         data->value.non_blocking = (flags & O_NONBLOCK) ? PR_TRUE : PR_FALSE;           
2518 #else /* punt :P */
2519         data->value.non_blocking = p->nonblock;
2520 #endif
2521         return PR_SUCCESS;
2522 }
2523
2524 static PRStatus PR_CALLBACK
2525 tlsm_PR_prs_unimp()
2526 {
2527     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
2528     return PR_FAILURE;
2529 }
2530
2531 static PRFileDesc * PR_CALLBACK
2532 tlsm_PR_pfd_unimp()
2533 {
2534     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
2535     return NULL;
2536 }
2537
2538 static PRInt16 PR_CALLBACK
2539 tlsm_PR_i16_unimp()
2540 {
2541     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
2542     return SECFailure;
2543 }
2544
2545 static PRInt32 PR_CALLBACK
2546 tlsm_PR_i32_unimp()
2547 {
2548     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
2549     return SECFailure;
2550 }
2551
2552 static PRInt64 PR_CALLBACK
2553 tlsm_PR_i64_unimp()
2554 {
2555     PRInt64 res;
2556
2557     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
2558     LL_I2L(res, -1L);
2559     return res;
2560 }
2561
2562 static const PRIOMethods tlsm_PR_methods = {
2563     PR_DESC_LAYERED,
2564     tlsm_PR_Close,                      /* close        */
2565     tlsm_PR_Read,                       /* read         */
2566     tlsm_PR_Write,                      /* write        */
2567     tlsm_PR_i32_unimp,          /* available    */
2568     tlsm_PR_i64_unimp,          /* available64  */
2569     tlsm_PR_prs_unimp,          /* fsync        */
2570     tlsm_PR_i32_unimp,          /* seek         */
2571     tlsm_PR_i64_unimp,          /* seek64       */
2572     tlsm_PR_prs_unimp,          /* fileInfo     */
2573     tlsm_PR_prs_unimp,          /* fileInfo64   */
2574     tlsm_PR_i32_unimp,          /* writev       */
2575     tlsm_PR_prs_unimp,          /* connect      */
2576     tlsm_PR_pfd_unimp,          /* accept       */
2577     tlsm_PR_prs_unimp,          /* bind         */
2578     tlsm_PR_prs_unimp,          /* listen       */
2579     (PRShutdownFN)tlsm_PR_Shutdown,                     /* shutdown     */
2580     tlsm_PR_Recv,                       /* recv         */
2581     tlsm_PR_Send,                       /* send         */
2582     tlsm_PR_i32_unimp,          /* recvfrom     */
2583     tlsm_PR_i32_unimp,          /* sendto       */
2584     (PRPollFN)tlsm_PR_i16_unimp,        /* poll         */
2585     tlsm_PR_i32_unimp,          /* acceptread   */
2586     tlsm_PR_i32_unimp,          /* transmitfile */
2587     tlsm_PR_prs_unimp,          /* getsockname  */
2588     tlsm_PR_GetPeerName,        /* getpeername  */
2589     tlsm_PR_i32_unimp,          /* getsockopt   OBSOLETE */
2590     tlsm_PR_i32_unimp,          /* setsockopt   OBSOLETE */
2591     tlsm_PR_GetSocketOption,            /* getsocketoption   */
2592     tlsm_PR_i32_unimp,          /* setsocketoption   */
2593     tlsm_PR_i32_unimp,          /* Send a (partial) file with header/trailer*/
2594     (PRConnectcontinueFN)tlsm_PR_prs_unimp,             /* connectcontinue */
2595     tlsm_PR_i32_unimp,          /* reserved for future use */
2596     tlsm_PR_i32_unimp,          /* reserved for future use */
2597     tlsm_PR_i32_unimp,          /* reserved for future use */
2598     tlsm_PR_i32_unimp           /* reserved for future use */
2599 };
2600
2601 /*
2602  * Initialize TLS subsystem. Should be called only once.
2603  * See tlsm_deferred_init for the bulk of the init process
2604  */
2605 static int
2606 tlsm_init( void )
2607 {
2608         PR_Init(0, 0, 0);
2609
2610         tlsm_layer_id = PR_GetUniqueIdentity( "OpenLDAP" );
2611
2612         return 0;
2613 }
2614
2615 static int
2616 tlsm_sb_setup( Sockbuf_IO_Desc *sbiod, void *arg )
2617 {
2618         struct tls_data         *p;
2619         tlsm_session    *session = arg;
2620         PRFileDesc *fd;
2621
2622         assert( sbiod != NULL );
2623
2624         p = LBER_MALLOC( sizeof( *p ) );
2625         if ( p == NULL ) {
2626                 return -1;
2627         }
2628
2629         fd = PR_GetIdentitiesLayer( session, tlsm_layer_id );
2630         if ( !fd ) {
2631                 LBER_FREE( p );
2632                 return -1;
2633         }
2634
2635         fd->secret = (PRFilePrivate *)p;
2636         p->session = session;
2637         p->sbiod = sbiod;
2638         sbiod->sbiod_pvt = p;
2639         return 0;
2640 }
2641
2642 static int
2643 tlsm_sb_remove( Sockbuf_IO_Desc *sbiod )
2644 {
2645         struct tls_data         *p;
2646         
2647         assert( sbiod != NULL );
2648         assert( sbiod->sbiod_pvt != NULL );
2649
2650         p = (struct tls_data *)sbiod->sbiod_pvt;
2651         PR_Close( p->session );
2652         LBER_FREE( sbiod->sbiod_pvt );
2653         sbiod->sbiod_pvt = NULL;
2654         return 0;
2655 }
2656
2657 static int
2658 tlsm_sb_close( Sockbuf_IO_Desc *sbiod )
2659 {
2660         struct tls_data         *p;
2661         
2662         assert( sbiod != NULL );
2663         assert( sbiod->sbiod_pvt != NULL );
2664
2665         p = (struct tls_data *)sbiod->sbiod_pvt;
2666         PR_Shutdown( p->session, PR_SHUTDOWN_BOTH );
2667         return 0;
2668 }
2669
2670 static int
2671 tlsm_sb_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
2672 {
2673         struct tls_data         *p;
2674         
2675         assert( sbiod != NULL );
2676         assert( sbiod->sbiod_pvt != NULL );
2677
2678         p = (struct tls_data *)sbiod->sbiod_pvt;
2679         
2680         if ( opt == LBER_SB_OPT_GET_SSL ) {
2681                 *((tlsm_session **)arg) = p->session;
2682                 return 1;
2683                 
2684         } else if ( opt == LBER_SB_OPT_DATA_READY ) {
2685                 if ( tlsm_is_io_ready( p->session, PR_POLL_READ, NULL ) > 0 ) {
2686                         return 1;
2687                 }
2688                 
2689         }
2690         
2691         return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
2692 }
2693
2694 static ber_slen_t
2695 tlsm_sb_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
2696 {
2697         struct tls_data         *p;
2698         ber_slen_t              ret;
2699         int                     err;
2700
2701         assert( sbiod != NULL );
2702         assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
2703
2704         p = (struct tls_data *)sbiod->sbiod_pvt;
2705
2706         ret = PR_Recv( p->session, buf, len, 0, PR_INTERVAL_NO_TIMEOUT );
2707         if ( ret < 0 ) {
2708                 err = PR_GetError();
2709                 if ( err == PR_PENDING_INTERRUPT_ERROR || err == PR_WOULD_BLOCK_ERROR ) {
2710                         sbiod->sbiod_sb->sb_trans_needs_read = 1;
2711                         sock_errset(EWOULDBLOCK);
2712                 }
2713         } else {
2714                 sbiod->sbiod_sb->sb_trans_needs_read = 0;
2715         }
2716         return ret;
2717 }
2718
2719 static ber_slen_t
2720 tlsm_sb_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
2721 {
2722         struct tls_data         *p;
2723         ber_slen_t              ret;
2724         int                     err;
2725
2726         assert( sbiod != NULL );
2727         assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
2728
2729         p = (struct tls_data *)sbiod->sbiod_pvt;
2730
2731         ret = PR_Send( p->session, (char *)buf, len, 0, PR_INTERVAL_NO_TIMEOUT );
2732         if ( ret < 0 ) {
2733                 err = PR_GetError();
2734                 if ( err == PR_PENDING_INTERRUPT_ERROR || err == PR_WOULD_BLOCK_ERROR ) {
2735                         sbiod->sbiod_sb->sb_trans_needs_write = 1;
2736                         sock_errset(EWOULDBLOCK);
2737                         ret = 0;
2738                 }
2739         } else {
2740                 sbiod->sbiod_sb->sb_trans_needs_write = 0;
2741         }
2742         return ret;
2743 }
2744
2745 static Sockbuf_IO tlsm_sbio =
2746 {
2747         tlsm_sb_setup,          /* sbi_setup */
2748         tlsm_sb_remove,         /* sbi_remove */
2749         tlsm_sb_ctrl,           /* sbi_ctrl */
2750         tlsm_sb_read,           /* sbi_read */
2751         tlsm_sb_write,          /* sbi_write */
2752         tlsm_sb_close           /* sbi_close */
2753 };
2754
2755 tls_impl ldap_int_tls_impl = {
2756         "MozNSS",
2757
2758         tlsm_init,
2759         tlsm_destroy,
2760
2761         tlsm_ctx_new,
2762         tlsm_ctx_ref,
2763         tlsm_ctx_free,
2764         tlsm_ctx_init,
2765
2766         tlsm_session_new,
2767         tlsm_session_connect,
2768         tlsm_session_accept,
2769         tlsm_session_upflags,
2770         tlsm_session_errmsg,
2771         tlsm_session_my_dn,
2772         tlsm_session_peer_dn,
2773         tlsm_session_chkhost,
2774         tlsm_session_strength,
2775
2776         &tlsm_sbio,
2777
2778 #ifdef LDAP_R_COMPILE
2779         tlsm_thr_init,
2780 #else
2781         NULL,
2782 #endif
2783
2784         0
2785 };
2786
2787 #endif /* HAVE_MOZNSS */
2788 /*
2789   emacs settings
2790   Local Variables:
2791   indent-tabs-mode: t
2792   tab-width: 4
2793   End:
2794 */