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