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