]> git.sur5r.net Git - openldap/blob - libraries/libldap/tls_m.c
Acknowledge richm
[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 #define ciphernum 18
144
145 /* cipher attributes  */
146 #define SSL_kRSA  0x00000001L
147 #define SSL_aRSA  0x00000002L
148 #define SSL_aDSS  0x00000004L
149 #define SSL_DSS   SSL_aDSS
150 #define SSL_eNULL 0x00000008L
151 #define SSL_DES   0x00000010L
152 #define SSL_3DES  0x00000020L
153 #define SSL_RC4   0x00000040L
154 #define SSL_RC2   0x00000080L
155 #define SSL_AES   0x00000100L
156 #define SSL_MD5   0x00000200L
157 #define SSL_SHA1  0x00000400L
158 #define SSL_SHA   SSL_SHA1
159 #define SSL_RSA   (SSL_kRSA|SSL_aRSA)
160
161 /* cipher strength */
162 #define SSL_NULL      0x00000001L
163 #define SSL_EXPORT40  0x00000002L
164 #define SSL_EXPORT56  0x00000004L
165 #define SSL_LOW       0x00000008L
166 #define SSL_MEDIUM    0x00000010L
167 #define SSL_HIGH      0x00000020L
168
169 #define SSL2  0x00000001L
170 #define SSL3  0x00000002L
171 /* OpenSSL treats SSL3 and TLSv1 the same */
172 #define TLS1  SSL3
173
174 /* Cipher translation */
175 #define ciphernum 18
176 static cipher_properties ciphers_def[ciphernum] = {
177         /* SSL 2 ciphers */
178         {"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},
179         {"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},
180         {"RC4-MD5", SSL_EN_RC4_128_WITH_MD5, SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_MD5, SSL2, 128, 128, SSL_MEDIUM, SSL_ALLOWED},
181         {"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},
182         {"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},
183         {"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},
184
185         /* SSL3 ciphers */
186         {"RC4-MD5", SSL_RSA_WITH_RC4_128_MD5, SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_MD5, SSL3, 128, 128, SSL_MEDIUM, SSL_ALLOWED},
187         {"RC4-SHA", SSL_RSA_WITH_RC4_128_SHA, SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_SHA1, SSL3, 128, 128, SSL_MEDIUM, SSL_NOT_ALLOWED},
188         {"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},
189         {"DES-CBC-SHA", SSL_RSA_WITH_DES_CBC_SHA, SSL_kRSA|SSL_aRSA|SSL_DES|SSL_SHA1, SSL3, 56, 56, SSL_LOW, SSL_ALLOWED},
190         {"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},
191         {"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},
192         {"NULL-MD5", SSL_RSA_WITH_NULL_MD5, SSL_kRSA|SSL_aRSA|SSL_eNULL|SSL_MD5, SSL3, 0, 0, SSL_NULL, SSL_NOT_ALLOWED},
193         {"NULL-SHA", SSL_RSA_WITH_NULL_SHA, SSL_kRSA|SSL_aRSA|SSL_eNULL|SSL_SHA1, SSL3, 0, 0, SSL_NULL, SSL_NOT_ALLOWED},
194
195         /* TLSv1 ciphers */
196         {"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},
197         {"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},
198         {"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},
199         {"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},
200 };
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         default:
644                 success = SECFailure;
645                 break;
646         }
647
648         return success;
649 }
650
651 static const char *
652 tlsm_dump_security_status(PRFileDesc *fd)
653 {
654         char * cp;      /* bulk cipher name */
655         char * ip;      /* cert issuer DN */
656         char * sp;      /* cert subject DN */
657         int    op;      /* High, Low, Off */
658         int    kp0;     /* total key bits */
659         int    kp1;     /* secret key bits */
660         SSL3Statistics * ssl3stats = SSL_GetStatistics();
661
662         SSL_SecurityStatus( fd, &op, &cp, &kp0, &kp1, &ip, &sp );
663         Debug( LDAP_DEBUG_TRACE,
664                    "TLS certificate verification: subject: %s, issuer: %s, cipher: %s, ",
665                    sp ? sp : "-unknown-", ip ? ip : "-unknown-", cp ? cp : "-unknown-" );
666         PR_Free(cp);
667         PR_Free(ip);
668         PR_Free(sp);
669         Debug( LDAP_DEBUG_TRACE,
670                    "security level: %s, secret key bits: %d, total key bits: %d, ",
671                    ((op == SSL_SECURITY_STATUS_ON_HIGH) ? "high" :
672                         ((op == SSL_SECURITY_STATUS_ON_LOW) ? "low" : "off")),
673                    kp1, kp0 );
674
675         Debug( LDAP_DEBUG_TRACE,
676                    "cache hits: %ld, cache misses: %ld, cache not reusable: %ld\n",
677                    ssl3stats->hch_sid_cache_hits, ssl3stats->hch_sid_cache_misses,
678                    ssl3stats->hch_sid_cache_not_ok );
679
680         return "";
681 }
682
683 static SECStatus
684 tlsm_auth_cert_handler(void *arg, PRFileDesc *fd,
685                        PRBool checksig, PRBool isServer)
686 {
687         SECStatus ret = SSL_AuthCertificate(arg, fd, checksig, isServer);
688
689         Debug( LDAP_DEBUG_TRACE,
690                    "TLS certificate verification: %s: %s,",
691                    ret == SECSuccess ? "ok" : "bad",
692                    tlsm_dump_security_status( fd ), 0 );
693
694         if ( ret != SECSuccess ) {
695                 PRErrorCode errcode = PORT_GetError();
696                 Debug( LDAP_DEBUG_ANY,
697                            "TLS certificate verification: Error, %d: %s\n",
698                            errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), 0 ) ;
699         }
700
701         return ret;
702 }
703
704 static char *
705 tlsm_dirname(const char *pathname)
706 {
707         char *ret = NULL;
708         char *p = NULL;
709         char sep = PR_GetDirectorySeparator();
710
711         if (pathname && (p = PL_strrchr(pathname, sep)) && (p > pathname)) {
712                 ret = PL_strndup(pathname, (p - pathname));
713         }
714
715         return ret;
716 }
717
718 /*
719  * This is the part of the init we defer until we get the
720  * actual security configuration information.  This is
721  * only called once, protected by a PRCallOnce
722  * NOTE: This must be done before the first call to SSL_ImportFD,
723  * especially the setting of the policy
724  * NOTE: This must be called after fork()
725  */
726 static int
727 tlsm_deferred_init( void *arg )
728 {
729         tlsm_ctx *ctx = (tlsm_ctx *)arg;
730         struct ldaptls *lt = ctx->tc_config;
731         char *securitydir = NULL;
732         int needfree = 0;
733         char *val;
734         PRErrorCode errcode;
735
736         /* NSS support for multi-init is coming */
737 #ifndef NSS_MULTI_INIT
738         if ( !NSS_IsInitialized() ) {
739 #endif /* NSS_MULTI_INIT */
740                 /*
741                   MOZNSS_DIR will override everything else - you can
742                   always set MOZNSS_DIR to force the use of this
743                   directory
744                   DEFAULT_MOZNSS_DIR will only be used if the code cannot
745                   find a security dir to use based on the current
746                   settings
747                 */
748                 if ( (val = PR_GetEnv( "MOZNSS_DIR" ) ) && (*val) ) {
749                         securitydir = PL_strdup( val );
750                         needfree = 1;
751                 } else if ( lt->lt_cacertdir ) {
752                         securitydir = lt->lt_cacertdir;
753                 } else if ( lt->lt_cacertfile ) {
754                         securitydir = tlsm_dirname( lt->lt_cacertfile );
755                         needfree = 1;
756                 } else if ( lt->lt_certfile ) {
757                         securitydir = tlsm_dirname( lt->lt_certfile );
758                         needfree = 1;
759                 } else if ( lt->lt_keyfile ) {
760                         securitydir = tlsm_dirname( lt->lt_keyfile );
761                         needfree = 1;
762                 } else if ( (val = PR_GetEnv( "DEFAULT_MOZNSS_DIR" ) ) && (*val) ) {
763                         securitydir = PL_strdup( val );
764                         needfree = 1;
765                 } else {
766                         securitydir = "/etc/pki/nssdb";
767                 }
768
769                 if ( NSS_Initialize( securitydir, "", "", SECMOD_DB, NSS_INIT_READONLY ) ) {
770                         errcode = PORT_GetError();
771                         Debug( LDAP_DEBUG_ANY,
772                                    "TLS: could not initialize moznss using security dir %s - error %d:%s.\n",
773                                    securitydir, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
774                         if ( needfree ) {
775                                 PL_strfree( securitydir );
776                         }
777                         return -1;
778                 }
779
780                 if ( needfree ) {
781                         PL_strfree( securitydir );
782                 }
783
784                 NSS_SetDomesticPolicy();
785                 tlsm_did_init = 1; /* we did the init - we should also clean up */
786 #ifndef NSS_MULTI_INIT
787         }
788 #endif /* NSS_MULTI_INIT */
789
790         return 0;
791 }
792
793 #ifdef READ_PASSWORD_FROM_FILE
794 static char *
795 tlsm_get_pin_from_file(const char *token_name, tlsm_ctx *ctx)
796 {
797         char *pwdstr = NULL;
798         char *contents = NULL;
799         char *lasts = NULL;
800         char *line = NULL;
801         char *candidate = NULL;
802         PRFileInfo file_info;
803         PRFileDesc *pwd_fileptr = PR_Open( ctx->tc_pin_file, PR_RDONLY, 00400 );
804
805         /* open the password file */
806         if ( !pwd_fileptr ) {
807                 PRErrorCode errcode = PR_GetError();
808                 Debug( LDAP_DEBUG_ANY,
809                        "TLS: could not open security pin file %s - error %d:%s.\n",
810                        ctx->tc_pin_file, errcode,
811                        PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
812                 goto done;
813         }
814
815         /* get the file size */
816         if ( PR_SUCCESS != PR_GetFileInfo( ctx->tc_pin_file, &file_info ) ) {
817                 PRErrorCode errcode = PR_GetError();
818                 Debug( LDAP_DEBUG_ANY,
819                        "TLS: could not get file info from pin file %s - error %d:%s.\n",
820                        ctx->tc_pin_file, errcode,
821                        PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
822                 goto done;
823         }
824
825         /* create a buffer to hold the file contents */
826         if ( !( contents = PR_MALLOC( file_info.size + 1 ) ) ) {
827                 PRErrorCode errcode = PR_GetError();
828                 Debug( LDAP_DEBUG_ANY,
829                        "TLS: could not alloc a buffer for contents of pin file %s - error %d:%s.\n",
830                        ctx->tc_pin_file, errcode,
831                        PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
832                 goto done;
833         }
834
835         /* read file into the buffer */
836         if( PR_Read( pwd_fileptr, contents, file_info.size ) <= 0 ) {
837                 PRErrorCode errcode = PR_GetError();
838                 Debug( LDAP_DEBUG_ANY,
839                        "TLS: could not read the file contents from pin file %s - error %d:%s.\n",
840                        ctx->tc_pin_file, errcode,
841                        PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
842                 goto done;
843         }
844
845         /* format is [tokenname:]password EOL [tokenname:]password EOL ... */
846         /* if you want to use a password containing a colon character, use
847            the special tokenname "default" */
848         for ( line = PL_strtok_r( contents, "\r\n", &lasts ); line;
849               line = PL_strtok_r( NULL, "\r\n", &lasts ) ) {
850                 char *colon;
851
852                 if ( !*line ) {
853                         continue; /* skip blank lines */
854                 }
855                 colon = PL_strchr( line, ':' );
856                 if ( colon ) {
857                         if ( *(colon + 1) && token_name &&
858                              !PL_strncmp( token_name, line, colon-line ) ) {
859                                 candidate = colon + 1; /* found a definite match */
860                                 break;
861                         } else if ( !PL_strncmp( DEFAULT_TOKEN_NAME, line, colon-line ) ) {
862                                 candidate = colon + 1; /* found possible match */
863                         }
864                 } else { /* no token name */
865                         candidate = line;
866                 }
867         }
868 done:
869         if ( pwd_fileptr ) {
870                 PR_Close( pwd_fileptr );
871         }
872         if ( candidate ) {
873                 pwdstr = PL_strdup( candidate );
874         }
875         PL_strfree( contents );
876
877         return pwdstr;
878 }
879 #endif /* READ_PASSWORD_FROM_FILE */
880
881 #ifdef READ_PASSWORD_FROM_STDIN
882 /*
883  * Turn the echoing off on a tty.
884  */
885 static void
886 echoOff(int fd)
887 {
888         if ( isatty( fd ) ) {
889                 struct termios tio;
890                 tcgetattr( fd, &tio );
891                 tio.c_lflag &= ~ECHO;
892                 tcsetattr( fd, TCSAFLUSH, &tio );
893         }
894 }
895
896 /*
897  * Turn the echoing on on a tty.
898  */
899 static void
900 echoOn(int fd)
901 {
902         if ( isatty( fd ) ) {
903                 struct termios tio;
904                 tcgetattr( fd, &tio );
905                 tio.c_lflag |= ECHO;
906                 tcsetattr( fd, TCSAFLUSH, &tio );
907                 tcsetattr( fd, TCSAFLUSH, &tio );
908         }
909 }
910 #endif /* READ_PASSWORD_FROM_STDIN */
911
912 /*
913  * This does the actual work of reading the pin/password/pass phrase
914  */
915 static char *
916 tlsm_get_pin(PK11SlotInfo *slot, PRBool retry, tlsm_ctx *ctx)
917 {
918         char *token_name = NULL;
919         char *pwdstr = NULL;
920
921         token_name = PK11_GetTokenName( slot );
922 #ifdef READ_PASSWORD_FROM_FILE
923         /* Try to get the passwords from the password file if it exists.
924          * THIS IS UNSAFE and is provided for convenience only. Without this
925          * capability the server would have to be started in foreground mode
926          * if using an encrypted key.
927          */
928         if ( ctx->tc_pin_file ) {
929                 pwdstr = tlsm_get_pin_from_file( token_name, ctx );
930         }
931 #endif /* RETRIEVE_PASSWORD_FROM_FILE */
932 #ifdef READ_PASSWORD_FROM_STDIN
933         if ( !pwdstr ) {
934                 int infd = PR_FileDesc2NativeHandle( PR_STDIN );
935                 int isTTY = isatty( infd );
936                 unsigned char phrase[200];
937                 /* Prompt for password */
938                 if ( isTTY ) {
939                         fprintf( stdout,
940                                  "Please enter pin, password, or pass phrase for security token '%s': ",
941                                  token_name ? token_name : DEFAULT_TOKEN_NAME );
942                         echoOff( infd );
943                 }
944                 fgets( (char*)phrase, sizeof(phrase), stdin );
945                 if ( isTTY ) {
946                         fprintf( stdout, "\n" );
947                         echoOn( infd );
948                 }
949                 /* stomp on newline */
950                 phrase[strlen((char*)phrase)-1] = 0;
951
952                 pwdstr = PL_strdup( (char*)phrase );
953         }
954
955 #endif /* READ_PASSWORD_FROM_STDIN */
956         return pwdstr;
957 }
958
959 /*
960  * PKCS11 devices (including the internal softokn cert/key database)
961  * may be protected by a pin or password or even pass phrase
962  * MozNSS needs a way for the user to provide that
963  */
964 static char *
965 tlsm_pin_prompt(PK11SlotInfo *slot, PRBool retry, void *arg)
966 {
967         tlsm_ctx *ctx = (tlsm_ctx *)arg;
968
969         return tlsm_get_pin( slot, retry, ctx );
970 }
971
972 static int
973 tlsm_authenticate( tlsm_ctx *ctx, const char *certname, const char *pininfo )
974 {
975         const char *colon = NULL;
976         char *token_name = NULL;
977         PK11SlotInfo *slot = NULL;
978         int rc = -1;
979
980         if ( !certname || !*certname ) {
981                 return 0;
982         }
983
984         PK11_SetPasswordFunc( tlsm_pin_prompt );
985
986         if ( ( colon = PL_strchr( certname, ':' ) ) ) {
987                 token_name = PL_strndup( certname, colon-certname );
988         }
989
990         if ( token_name ) {
991                 slot = PK11_FindSlotByName( token_name );
992         } else {
993                 slot = PK11_GetInternalKeySlot();
994         }
995
996         if ( !slot ) {
997                 PRErrorCode errcode = PR_GetError();
998                 Debug( LDAP_DEBUG_ANY,
999                            "TLS: could not find the slot for security token %s - error %d:%s.\n",
1000                            token_name ? token_name : DEFAULT_TOKEN_NAME, errcode,
1001                            PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1002                 goto done;
1003         }
1004
1005         if ( pininfo ) {
1006                 PL_strfree( ctx->tc_pin_file );
1007                 ctx->tc_pin_file = PL_strdup( pininfo );
1008         }
1009
1010         if ( PK11_NeedLogin( slot ) &&
1011                  ( SECSuccess != PK11_Authenticate( slot, PR_FALSE, ctx ) ) ) {
1012                 PRErrorCode errcode = PR_GetError();
1013                 Debug( LDAP_DEBUG_ANY,
1014                            "TLS: could not authenticate to the security token %s - error %d:%s.\n",
1015                            token_name ? token_name : DEFAULT_TOKEN_NAME, errcode,
1016                            PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1017                 goto done;
1018         } else {
1019                 rc = 0; /* success */
1020         }
1021
1022 done:
1023         PL_strfree( token_name );
1024         if ( slot ) {
1025                 PK11_FreeSlot( slot );
1026         }
1027
1028         return rc;
1029 }
1030
1031 /*
1032  * Find and verify the certificate.
1033  * Either fd is given, in which case the cert will be taken from it via SSL_PeerCertificate
1034  * or certname is given, and it will be searched for by name
1035  */
1036 static int
1037 tlsm_find_and_verify_cert_key(tlsm_ctx *ctx, PRFileDesc *fd, const char *certname, int isServer, CERTCertificate **pRetCert, SECKEYPrivateKey **pRetKey)
1038 {
1039         CERTCertificate *cert = NULL;
1040         int rc = -1;
1041         void *pin_arg = NULL;
1042         SECKEYPrivateKey *key = NULL;
1043
1044         pin_arg = SSL_RevealPinArg( fd );
1045         if ( certname ) {
1046                 cert = PK11_FindCertFromNickname( certname, pin_arg );
1047                 if ( !cert ) {
1048                         PRErrorCode errcode = PR_GetError();
1049                         Debug( LDAP_DEBUG_ANY,
1050                                    "TLS: error: the certificate %s could not be found in the database - error %d:%s\n",
1051                                    certname, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1052                         return -1;
1053                 }
1054         } else {
1055                 /* we are verifying the peer cert
1056                    we also need to swap the isServer meaning */
1057                 cert = SSL_PeerCertificate( fd );
1058                 if ( !cert ) {
1059                         PRErrorCode errcode = PR_GetError();
1060                         Debug( LDAP_DEBUG_ANY,
1061                                    "TLS: error: could not get the certificate from the peer connection - error %d:%s\n",
1062                                    errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ), NULL );
1063                         return -1;
1064                 }
1065                 isServer = !isServer; /* verify the peer's cert instead */
1066         }
1067
1068         key = PK11_FindKeyByAnyCert( cert, pin_arg );
1069         if (key) {
1070                 SECCertificateUsage certUsage;
1071                 PRBool checkSig = PR_TRUE;
1072                 SECStatus status;
1073
1074                 if ( pRetKey ) {
1075                         *pRetKey = key; /* caller will deal with this */
1076                 } else {
1077                         SECKEY_DestroyPrivateKey( key );
1078                 }
1079                 if ( isServer ) {
1080                         certUsage = certificateUsageSSLServer;
1081                 } else {
1082                         certUsage = certificateUsageSSLClient;
1083                 }
1084                 if ( ctx->tc_verify_cert ) {
1085                         checkSig = PR_TRUE;
1086                 } else {
1087                         checkSig = PR_FALSE;
1088                 }
1089                 status = CERT_VerifyCertificateNow( ctx->tc_certdb, cert,
1090                                                                                         checkSig, certUsage,
1091                                                                                         pin_arg, NULL );
1092                 if (status != SECSuccess) {
1093                         PRErrorCode errcode = PR_GetError();
1094                         Debug( LDAP_DEBUG_ANY,
1095                                    "TLS: error: the certificate %s is not valid - error %d:%s\n",
1096                                    certname, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1097                 } else {
1098                         rc = 0; /* success */
1099                 }
1100         } else {
1101                 PRErrorCode errcode = PR_GetError();
1102                 Debug( LDAP_DEBUG_ANY,
1103                            "TLS: error: could not find the private key for certificate %s - error %d:%s\n",
1104                            certname, errcode, PR_ErrorToString( errcode, PR_LANGUAGE_I_DEFAULT ) );
1105         }
1106
1107         if ( pRetCert ) {
1108                 *pRetCert = cert; /* caller will deal with this */
1109         } else {
1110                 CERT_DestroyCertificate( cert );
1111         }
1112
1113     return rc;
1114 }
1115
1116 static int
1117 tlsm_get_client_auth_data( void *arg, PRFileDesc *fd,
1118                                                    CERTDistNames *caNames, CERTCertificate **pRetCert,
1119                                                    SECKEYPrivateKey **pRetKey )
1120 {
1121         tlsm_ctx *ctx = (tlsm_ctx *)arg;
1122         int rc;
1123
1124         /* don't need caNames - this function will call CERT_VerifyCertificateNow
1125            which will verify the cert against the known CAs */
1126         rc = tlsm_find_and_verify_cert_key( ctx, fd, ctx->tc_certname, 0, pRetCert, pRetKey );
1127         if ( rc ) {
1128                 Debug( LDAP_DEBUG_ANY,
1129                            "TLS: error: unable to perform client certificate authentication for "
1130                            "certificate named %s\n", ctx->tc_certname, 0, 0 );
1131                 return SECFailure;
1132         }
1133
1134         return SECSuccess;
1135 }
1136
1137 /*
1138  * ctx must have a tc_model that is valid
1139  * certname is in the form [<tokenname>:]<certnickname>
1140  * where <tokenname> is the name of the PKCS11 token
1141  * and <certnickname> is the nickname of the cert/key in
1142  * the database
1143 */
1144 static int
1145 tlsm_clientauth_init( tlsm_ctx *ctx, const char *certname )
1146 {
1147         SECStatus status = SECFailure;
1148         int rc;
1149
1150         PL_strfree( ctx->tc_certname );
1151         rc = tlsm_find_and_verify_cert_key( ctx, ctx->tc_model, certname, 0, NULL, NULL );
1152         if ( rc ) {
1153                 Debug( LDAP_DEBUG_ANY,
1154                            "TLS: error: unable to set up client certificate authentication for "
1155                            "certificate named %s\n", certname, 0, 0 );
1156                 return -1;
1157         }
1158
1159         ctx->tc_certname = PL_strdup( certname );
1160
1161         status = SSL_GetClientAuthDataHook( ctx->tc_model,
1162                                                                                 tlsm_get_client_auth_data,
1163                                                                                 (void *)ctx );
1164
1165         return ( status == SECSuccess ? 0 : -1 );
1166 }
1167
1168 /*
1169  * Tear down the TLS subsystem. Should only be called once.
1170  */
1171 static void
1172 tlsm_destroy( void )
1173 {
1174         /* Only if we did the actual initialization */
1175         if ( tlsm_did_init ) {
1176                 tlsm_did_init = 0;
1177
1178                 SSL_ShutdownServerSessionIDCache();
1179                 SSL_ClearSessionCache();
1180                 NSS_Shutdown();
1181         }
1182
1183         PR_Cleanup();
1184 }
1185
1186 static tls_ctx *
1187 tlsm_ctx_new ( struct ldapoptions *lo )
1188 {
1189         tlsm_ctx *ctx;
1190
1191         ctx = LDAP_MALLOC( sizeof (*ctx) );
1192         if ( ctx ) {
1193                 ctx->tc_refcnt = 1;
1194 #ifdef LDAP_R_COMPILE
1195                 ldap_pvt_thread_mutex_init( &ctx->tc_refmutex );
1196 #endif
1197                 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 */
1198                 ctx->tc_certdb = NULL;
1199                 ctx->tc_certname = NULL;
1200                 ctx->tc_pin_file = NULL;
1201                 ctx->tc_model = NULL;
1202                 memset(&ctx->tc_callonce, 0, sizeof(ctx->tc_callonce));
1203                 ctx->tc_require_cert = lo->ldo_tls_require_cert;
1204         } else {
1205                 LDAP_FREE( ctx );
1206                 ctx = NULL;
1207         }
1208         return (tls_ctx *)ctx;
1209 }
1210
1211 static void
1212 tlsm_ctx_ref( tls_ctx *ctx )
1213 {
1214         tlsm_ctx *c = (tlsm_ctx *)ctx;
1215 #ifdef LDAP_R_COMPILE
1216         ldap_pvt_thread_mutex_lock( &c->tc_refmutex );
1217 #endif
1218         c->tc_refcnt++;
1219 #ifdef LDAP_R_COMPILE
1220         ldap_pvt_thread_mutex_unlock( &c->tc_refmutex );
1221 #endif
1222 }
1223
1224 static void
1225 tlsm_ctx_free ( tls_ctx *ctx )
1226 {
1227         tlsm_ctx *c = (tlsm_ctx *)ctx;
1228         int refcount;
1229
1230         if ( !c ) return;
1231
1232 #ifdef LDAP_R_COMPILE
1233         ldap_pvt_thread_mutex_lock( &c->tc_refmutex );
1234 #endif
1235         refcount = --c->tc_refcnt;
1236 #ifdef LDAP_R_COMPILE
1237         ldap_pvt_thread_mutex_unlock( &c->tc_refmutex );
1238 #endif
1239         if ( refcount )
1240                 return;
1241         PR_Close( c->tc_model );
1242         c->tc_certdb = NULL; /* if not the default, may have to clean up */
1243         PL_strfree( c->tc_certname );
1244         c->tc_certname = NULL;
1245         PL_strfree( c->tc_pin_file );
1246         c->tc_pin_file = NULL;
1247 #ifdef LDAP_R_COMPILE
1248         ldap_pvt_thread_mutex_destroy( &c->tc_refmutex );
1249 #endif
1250         LDAP_FREE( c );
1251 }
1252
1253 /*
1254  * initialize a new TLS context
1255  */
1256 static int
1257 tlsm_ctx_init( struct ldapoptions *lo, struct ldaptls *lt, int is_server )
1258 {
1259         tlsm_ctx *ctx = (tlsm_ctx *)lo->ldo_tls_ctx;
1260         ctx->tc_is_server = is_server;
1261
1262         return 0;
1263 }
1264
1265 static int
1266 tlsm_deferred_ctx_init( void *arg )
1267 {
1268         tlsm_ctx *ctx = (tlsm_ctx *)arg;
1269         PRBool sslv2 = PR_FALSE;
1270         PRBool sslv3 = PR_TRUE;
1271         PRBool tlsv1 = PR_TRUE;
1272         PRBool request_cert = PR_FALSE;
1273         PRInt32 require_cert = PR_FALSE;
1274         PRFileDesc *fd;
1275         struct ldaptls *lt;
1276
1277         if ( tlsm_deferred_init( ctx ) ) {
1278             Debug( LDAP_DEBUG_ANY,
1279                            "TLS: could perform TLS system initialization.\n",
1280                            0, 0, 0 );
1281             return -1;
1282         }
1283
1284         ctx->tc_certdb = CERT_GetDefaultCertDB(); /* replace with multi-init db call */
1285
1286         fd = PR_CreateIOLayerStub( tlsm_layer_id, &tlsm_PR_methods );
1287         if ( fd ) {
1288                 ctx->tc_model = SSL_ImportFD( NULL, fd );
1289         }
1290
1291         if ( !ctx->tc_model ) {
1292                 PRErrorCode err = PR_GetError();
1293                 Debug( LDAP_DEBUG_ANY,
1294                            "TLS: could perform TLS socket I/O layer initialization - error %d:%s.\n",
1295                            err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL );
1296
1297                 if ( fd ) {
1298                         PR_Close( fd );
1299                 }
1300                 return -1;
1301         }
1302
1303         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_SECURITY, PR_TRUE ) ) {
1304                 Debug( LDAP_DEBUG_ANY,
1305                        "TLS: could not set secure mode on.\n",
1306                        0, 0, 0 );
1307                 return -1;
1308         }
1309
1310         lt = ctx->tc_config;
1311
1312         /* default is sslv3 and tlsv1 */
1313         if ( lt->lt_protocol_min ) {
1314                 if ( lt->lt_protocol_min > LDAP_OPT_X_TLS_PROTOCOL_SSL3 ) {
1315                         sslv3 = PR_FALSE;
1316                 } else if ( lt->lt_protocol_min <= LDAP_OPT_X_TLS_PROTOCOL_SSL2 ) {
1317                         sslv2 = PR_TRUE;
1318                         Debug( LDAP_DEBUG_ANY,
1319                                "TLS: warning: minimum TLS protocol level set to "
1320                                "include SSLv2 - SSLv2 is insecure - do not use\n", 0, 0, 0 );
1321                 }
1322         }
1323         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_ENABLE_SSL2, sslv2 ) ) {
1324                 Debug( LDAP_DEBUG_ANY,
1325                        "TLS: could not set SSLv2 mode on.\n",
1326                        0, 0, 0 );
1327                 return -1;
1328         }
1329         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_ENABLE_SSL3, sslv3 ) ) {
1330                 Debug( LDAP_DEBUG_ANY,
1331                        "TLS: could not set SSLv3 mode on.\n",
1332                        0, 0, 0 );
1333                 return -1;
1334         }
1335         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_ENABLE_TLS, tlsv1 ) ) {
1336                 Debug( LDAP_DEBUG_ANY,
1337                        "TLS: could not set TLSv1 mode on.\n",
1338                        0, 0, 0 );
1339                 return -1;
1340         }
1341
1342         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_HANDSHAKE_AS_CLIENT, !ctx->tc_is_server ) ) {
1343                 Debug( LDAP_DEBUG_ANY,
1344                        "TLS: could not set handshake as client.\n",
1345                        0, 0, 0 );
1346                 return -1;
1347         }
1348         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_HANDSHAKE_AS_SERVER, ctx->tc_is_server ) ) {
1349                 Debug( LDAP_DEBUG_ANY,
1350                        "TLS: could not set handshake as server.\n",
1351                        0, 0, 0 );
1352                 return -1;
1353         }
1354
1355         if ( lt->lt_ciphersuite &&
1356              tlsm_parse_ciphers( ctx, lt->lt_ciphersuite )) {
1357                 Debug( LDAP_DEBUG_ANY,
1358                        "TLS: could not set cipher list %s.\n",
1359                        lt->lt_ciphersuite, 0, 0 );
1360                 return -1;
1361         }
1362
1363         if ( ctx->tc_require_cert ) {
1364                 request_cert = PR_TRUE;
1365                 require_cert = SSL_REQUIRE_NO_ERROR;
1366                 if ( ctx->tc_require_cert == LDAP_OPT_X_TLS_DEMAND ||
1367                      ctx->tc_require_cert == LDAP_OPT_X_TLS_HARD ) {
1368                         require_cert = SSL_REQUIRE_ALWAYS;
1369                 }
1370                 ctx->tc_verify_cert = PR_TRUE;
1371         } else {
1372                 ctx->tc_verify_cert = PR_FALSE;
1373         }
1374
1375         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_REQUEST_CERTIFICATE, request_cert ) ) {
1376                 Debug( LDAP_DEBUG_ANY,
1377                        "TLS: could not set request certificate mode.\n",
1378                        0, 0, 0 );
1379                 return -1;
1380         }
1381                 
1382         if ( SECSuccess != SSL_OptionSet( ctx->tc_model, SSL_REQUIRE_CERTIFICATE, require_cert ) ) {
1383                 Debug( LDAP_DEBUG_ANY,
1384                        "TLS: could not set require certificate mode.\n",
1385                        0, 0, 0 );
1386                 return -1;
1387         }
1388
1389         /* Set up callbacks for use by clients */
1390         if ( !ctx->tc_is_server ) {
1391                 if ( SSL_OptionSet( ctx->tc_model, SSL_NO_CACHE, PR_TRUE ) != SECSuccess ) {
1392                         PRErrorCode err = PR_GetError();
1393                         Debug( LDAP_DEBUG_ANY, 
1394                                "TLS: error: could not set nocache option for moznss - error %d:%s\n",
1395                                err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL );
1396                         return -1;
1397                 }
1398
1399                 if ( SSL_BadCertHook( ctx->tc_model, tlsm_bad_cert_handler, ctx ) != SECSuccess ) {
1400                         PRErrorCode err = PR_GetError();
1401                         Debug( LDAP_DEBUG_ANY, 
1402                                "TLS: error: could not set bad cert handler for moznss - error %d:%s\n",
1403                                err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL );
1404                         return -1;
1405                 }
1406
1407                 /* we don't currently support import of cert/key pair - assume the certfile
1408                    is really the name of a cert/key in the database in the form of
1409                    tokenname:certname - also assume since this is specified, the caller
1410                    wants to attempt client cert auth */
1411                 if ( lt->lt_certfile ) {
1412                         if ( tlsm_authenticate( ctx, lt->lt_certfile, lt->lt_keyfile ) ) {
1413                                 Debug( LDAP_DEBUG_ANY, 
1414                                        "TLS: error: unable to authenticate to the security device for certificate %s\n",
1415                                        lt->lt_certfile, 0, 0 );
1416                                 return -1;
1417                         }
1418                         if ( tlsm_clientauth_init( ctx, lt->lt_certfile ) ) {
1419                                 Debug( LDAP_DEBUG_ANY, 
1420                                        "TLS: error: unable to set up client certificate authentication using %s\n",
1421                                        lt->lt_certfile, 0, 0 );
1422                                 return -1;
1423                         }
1424                 }
1425         } else { /* set up secure server */
1426                 SSLKEAType certKEA;
1427                 CERTCertificate *serverCert;
1428                 SECKEYPrivateKey *serverKey;
1429                 SECStatus status;
1430
1431                 /* must have a certificate for the server to use */
1432                 if ( !lt->lt_certfile ) {
1433                         Debug( LDAP_DEBUG_ANY, 
1434                                "TLS: error: no server certificate: must specify a certificate for the server to use\n",
1435                                0, 0, 0 );
1436                         return -1;
1437                 }
1438
1439                 /* authenticate to the server's token - this will do nothing
1440                    if the key/cert db is not password protected */
1441                 if ( tlsm_authenticate( ctx, lt->lt_certfile, lt->lt_keyfile ) ) {
1442                         Debug( LDAP_DEBUG_ANY, 
1443                                "TLS: error: unable to authenticate to the security device for certificate %s\n",
1444                                lt->lt_certfile, 0, 0 );
1445                         return -1;
1446                 }
1447
1448                 /* get the server's key and cert */
1449                 if ( tlsm_find_and_verify_cert_key( ctx, ctx->tc_model, lt->lt_certfile, ctx->tc_is_server,
1450                                                     &serverCert, &serverKey ) ) {
1451                         Debug( LDAP_DEBUG_ANY, 
1452                                "TLS: error: unable to find and verify server's cert and key for certificate %s\n",
1453                                lt->lt_certfile, 0, 0 );
1454                         return -1;
1455                 }
1456
1457                 certKEA = NSS_FindCertKEAType( serverCert );
1458                 /* configure the socket to be a secure server socket */
1459                 status = SSL_ConfigSecureServer( ctx->tc_model, serverCert, serverKey, certKEA );
1460                 /* SSL_ConfigSecureServer copies these */
1461                 CERT_DestroyCertificate( serverCert );
1462                 SECKEY_DestroyPrivateKey( serverKey );
1463
1464                 if ( SECSuccess != status ) {
1465                         PRErrorCode err = PR_GetError();
1466                         Debug( LDAP_DEBUG_ANY, 
1467                                "TLS: error: unable to configure secure server using certificate %s - error %d:%s\n",
1468                                lt->lt_certfile, err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ) );
1469                         return -1;
1470                 }
1471         }
1472
1473         /* Callback for authenticating certificate */
1474         if ( SSL_AuthCertificateHook( ctx->tc_model, tlsm_auth_cert_handler,
1475                                   ctx->tc_certdb ) != SECSuccess ) {
1476                 PRErrorCode err = PR_GetError();
1477                 Debug( LDAP_DEBUG_ANY, 
1478                        "TLS: error: could not set auth cert handler for moznss - error %d:%s\n",
1479                        err, PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ), NULL );
1480                 return -1;
1481         }
1482
1483         return 0;
1484 }
1485
1486 struct tls_data {
1487         tlsm_session            *session;
1488         Sockbuf_IO_Desc         *sbiod;
1489         /* there seems to be no portable way to determine if the
1490            sockbuf sd has been set to nonblocking mode - the
1491            call to ber_pvt_socket_set_nonblock() takes place
1492            before the tls socket is set up, so we cannot
1493            intercept that call either.
1494            On systems where fcntl is available, we can just
1495            F_GETFL and test for O_NONBLOCK.  On other systems,
1496            we will just see if the IO op returns EAGAIN or EWOULDBLOCK,
1497            and just set this flag */
1498         PRBool              nonblock;
1499 };
1500
1501 static int
1502 tlsm_is_io_ready( PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags )
1503 {
1504         struct tls_data         *p;
1505         PRFileDesc *pollfd = NULL;
1506         PRFileDesc *myfd;
1507         PRPollDesc polldesc;
1508         int rc;
1509
1510         myfd = PR_GetIdentitiesLayer( fd, tlsm_layer_id );
1511
1512         if ( !myfd ) {
1513                 return 0;
1514         }
1515
1516         p = (struct tls_data *)myfd->secret;
1517
1518         if ( p == NULL || p->sbiod == NULL ) {
1519                 return 0;
1520         }
1521
1522         /* wrap the sockbuf fd with a NSPR FD created especially
1523            for use with polling, and only with polling */
1524         pollfd = PR_CreateSocketPollFd( p->sbiod->sbiod_sb->sb_fd );
1525         polldesc.fd = pollfd;
1526         polldesc.in_flags = in_flags;
1527         polldesc.out_flags = 0;
1528
1529         /* do the poll - no waiting, no blocking */
1530         rc = PR_Poll( &polldesc, 1, PR_INTERVAL_NO_WAIT );
1531
1532         /* unwrap the socket */
1533         PR_DestroySocketPollFd( pollfd );
1534
1535         /* rc will be either 1 if IO is ready, 0 if IO is not
1536            ready, or -1 if there was some error (and the caller
1537            should use PR_GetError() to figure out what */
1538         if (out_flags) {
1539                 *out_flags = polldesc.out_flags;
1540         }
1541         return rc;
1542 }
1543
1544 static tls_session *
1545 tlsm_session_new ( tls_ctx * ctx, int is_server )
1546 {
1547         tlsm_ctx *c = (tlsm_ctx *)ctx;
1548         tlsm_session *session;
1549         PRFileDesc *fd;
1550         PRStatus status;
1551
1552         c->tc_is_server = is_server;
1553         status = PR_CallOnceWithArg( &c->tc_callonce, tlsm_deferred_ctx_init, c );
1554         if ( PR_SUCCESS != status ) {
1555                 PRErrorCode err = PR_GetError();
1556                 Debug( LDAP_DEBUG_ANY, 
1557                        "TLS: error: could not initialize moznss security context - error %d:%s\n",
1558                        err, PR_ErrorToString(err, PR_LANGUAGE_I_DEFAULT), NULL );
1559                 return NULL;
1560         }
1561
1562         fd = PR_CreateIOLayerStub( tlsm_layer_id, &tlsm_PR_methods );
1563         if ( !fd ) {
1564                 return NULL;
1565         }
1566
1567         session = SSL_ImportFD( c->tc_model, fd );
1568         if ( !session ) {
1569                 PR_DELETE( fd );
1570                 return NULL;
1571         }
1572
1573         if ( is_server ) {
1574                 /* 0 means use the defaults here */
1575                 SSL_ConfigServerSessionIDCache( 0, 0, 0, NULL );
1576         }
1577
1578         return (tls_session *)session;
1579
1580
1581 static int
1582 tlsm_session_accept( tls_session *session )
1583 {
1584         tlsm_session *s = (tlsm_session *)session;
1585         int rc;
1586         PRErrorCode err;
1587         int waitcounter = 0;
1588
1589         rc = SSL_ResetHandshake( s, PR_TRUE /* server */ );
1590         if (rc) {
1591                 err = PR_GetError();
1592                 Debug( LDAP_DEBUG_TRACE, 
1593                            "TLS: error: accept - reset handshake failure %d - error %d:%s\n",
1594                            rc, err,
1595                            err ? PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ) : "unknown" );
1596         }
1597
1598         do {
1599                 PRInt32 filesReady;
1600                 PRInt16 in_flags;
1601                 PRInt16 out_flags;
1602
1603                 errno = 0;
1604                 rc = SSL_ForceHandshake( s );
1605                 if (rc == SECSuccess) {
1606                         rc = 0;
1607                         break; /* done */
1608                 }
1609                 err = PR_GetError();
1610                 Debug( LDAP_DEBUG_TRACE, 
1611                            "TLS: error: accept - force handshake failure %d - error %d waitcounter %d\n",
1612                            errno, err, waitcounter );
1613                 if ( errno == EAGAIN || errno == EWOULDBLOCK ) {
1614                         waitcounter++;
1615                         in_flags = PR_POLL_READ | PR_POLL_EXCEPT;
1616                         out_flags = 0;
1617                         errno = 0;
1618                         filesReady = tlsm_is_io_ready( s, in_flags, &out_flags );
1619                         if ( filesReady < 0 ) {
1620                                 err = PR_GetError();
1621                                 Debug( LDAP_DEBUG_ANY, 
1622                                            "TLS: error: accept - error waiting for socket to be ready: %d - error %d:%s\n",
1623                                            errno, err,
1624                                            err ? PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ) : "unknown" );
1625                                 rc = -1;
1626                                 break; /* hard error */
1627                         } else if ( out_flags & PR_POLL_NVAL ) {
1628                                 PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
1629                                 Debug( LDAP_DEBUG_ANY, 
1630                                            "TLS: error: accept failure - invalid socket\n",
1631                                            NULL, NULL, NULL );
1632                                 rc = -1;
1633                                 break;
1634                         } else if ( out_flags & PR_POLL_EXCEPT ) {
1635                                 err = PR_GetError();
1636                                 Debug( LDAP_DEBUG_ANY, 
1637                                            "TLS: error: accept - error waiting for socket to be ready: %d - error %d:%s\n",
1638                                            errno, err,
1639                                            err ? PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ) : "unknown" );
1640                                 rc = -1;
1641                                 break; /* hard error */
1642                         }
1643                 } else { /* hard error */
1644                         err = PR_GetError();
1645                         Debug( LDAP_DEBUG_ANY, 
1646                                    "TLS: error: accept - force handshake failure: %d - error %d:%s\n",
1647                                    errno, err,
1648                                    err ? PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ) : "unknown" );
1649                         rc = -1;
1650                         break; /* hard error */
1651                 }
1652         } while (rc == SECFailure);
1653
1654         Debug( LDAP_DEBUG_TRACE, 
1655                    "TLS: accept completed after %d waits\n", waitcounter, NULL, NULL );
1656
1657         return rc;
1658 }
1659
1660 static int
1661 tlsm_session_connect( LDAP *ld, tls_session *session )
1662 {
1663         tlsm_session *s = (tlsm_session *)session;
1664         int rc;
1665         PRErrorCode err;
1666
1667         /* By default, NSS checks the cert hostname for us */
1668         rc = SSL_ResetHandshake( s, PR_FALSE /* server */ );
1669         if (rc) {
1670                 err = PR_GetError();
1671                 Debug( LDAP_DEBUG_TRACE, 
1672                            "TLS: error: connect - reset handshake failure %d - error %d:%s\n",
1673                            rc, err,
1674                            err ? PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ) : "unknown" );
1675         }
1676
1677         rc = SSL_SetURL( s, ld->ld_options.ldo_defludp->lud_host );
1678         if (rc) {
1679                 err = PR_GetError();
1680                 Debug( LDAP_DEBUG_TRACE, 
1681                            "TLS: error: connect - seturl failure %d - error %d:%s\n",
1682                            rc, err,
1683                            err ? PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ) : "unknown" );
1684         }
1685
1686         rc = SSL_ForceHandshake( s );
1687         if (rc) {
1688                 err = PR_GetError();
1689                 Debug( LDAP_DEBUG_TRACE, 
1690                            "TLS: error: connect - force handshake failure %d - error %d:%s\n",
1691                            rc, err,
1692                            err ? PR_ErrorToString( err, PR_LANGUAGE_I_DEFAULT ) : "unknown" );
1693         }
1694
1695         return rc;
1696 }
1697
1698 static int
1699 tlsm_session_upflags( Sockbuf *sb, tls_session *session, int rc )
1700 {
1701         /* Should never happen */
1702         rc = PR_GetError();
1703
1704         if ( rc != PR_PENDING_INTERRUPT_ERROR && rc != PR_WOULD_BLOCK_ERROR )
1705                 return 0;
1706         return 0;
1707 }
1708
1709 static char *
1710 tlsm_session_errmsg( int rc, char *buf, size_t len )
1711 {
1712         int i;
1713
1714         rc = PR_GetError();
1715         i = PR_GetErrorTextLength();
1716         if ( i > len ) {
1717                 char *msg = LDAP_MALLOC( i+1 );
1718                 PR_GetErrorText( msg );
1719                 memcpy( buf, msg, len );
1720                 LDAP_FREE( msg );
1721         } else if ( i ) {
1722                 PR_GetErrorText( buf );
1723         }
1724
1725         return i ? buf : NULL;
1726 }
1727
1728 static int
1729 tlsm_session_my_dn( tls_session *session, struct berval *der_dn )
1730 {
1731         tlsm_session *s = (tlsm_session *)session;
1732         CERTCertificate *cert;
1733
1734         cert = SSL_LocalCertificate( s );
1735         if (!cert) return LDAP_INVALID_CREDENTIALS;
1736
1737         der_dn->bv_val = cert->derSubject.data;
1738         der_dn->bv_len = cert->derSubject.len;
1739         CERT_DestroyCertificate( cert );
1740         return 0;
1741 }
1742
1743 static int
1744 tlsm_session_peer_dn( tls_session *session, struct berval *der_dn )
1745 {
1746         tlsm_session *s = (tlsm_session *)session;
1747         CERTCertificate *cert;
1748
1749         cert = SSL_PeerCertificate( s );
1750         if (!cert) return LDAP_INVALID_CREDENTIALS;
1751         
1752         der_dn->bv_val = cert->derSubject.data;
1753         der_dn->bv_len = cert->derSubject.len;
1754         CERT_DestroyCertificate( cert );
1755         return 0;
1756 }
1757
1758 static int
1759 tlsm_session_chkhost( LDAP *ld, tls_session *session, const char *name_in )
1760 {
1761 /* NSS already does a hostname check */
1762         return LDAP_SUCCESS;
1763 }
1764
1765 static int
1766 tlsm_session_strength( tls_session *session )
1767 {
1768         tlsm_session *s = (tlsm_session *)session;
1769         int rc, keySize;
1770
1771         rc = SSL_SecurityStatus( s, NULL, NULL, NULL, &keySize,
1772                 NULL, NULL );
1773         return rc ? 0 : keySize;
1774 }
1775
1776 /*
1777  * TLS support for LBER Sockbufs
1778  */
1779
1780 static PRStatus PR_CALLBACK
1781 tlsm_PR_Close(PRFileDesc *fd)
1782 {
1783         int rc = PR_SUCCESS;
1784
1785         /* we don't need to actually close anything here, just
1786            pop our io layer off the stack */
1787         fd->secret = NULL; /* must have been freed before calling PR_Close */
1788         if ( fd->lower ) {
1789                 fd = PR_PopIOLayer( fd, tlsm_layer_id );
1790                 /* if we are not the last layer, pass the close along */
1791                 if ( fd ) {
1792                         if ( fd->dtor ) {
1793                                 fd->dtor( fd );
1794                         }
1795                         rc = fd->methods->close( fd );
1796                 }
1797         } else {
1798                 /* we are the last layer - just call our dtor */
1799                 fd->dtor(fd);
1800         }
1801
1802         return rc;
1803 }
1804
1805 static PRStatus PR_CALLBACK
1806 tlsm_PR_Shutdown(PRFileDesc *fd, PRShutdownHow how)
1807 {
1808         int rc = PR_SUCCESS;
1809
1810         if ( fd->lower ) {
1811                 rc = PR_Shutdown( fd->lower, how );
1812         }
1813
1814         return rc;
1815 }
1816
1817 static int PR_CALLBACK
1818 tlsm_PR_Recv(PRFileDesc *fd, void *buf, PRInt32 len, PRIntn flags,
1819          PRIntervalTime timeout)
1820 {
1821         struct tls_data         *p;
1822         int rc;
1823
1824         if ( buf == NULL || len <= 0 ) return 0;
1825
1826         p = (struct tls_data *)fd->secret;
1827
1828         if ( p == NULL || p->sbiod == NULL ) {
1829                 return 0;
1830         }
1831
1832         rc = LBER_SBIOD_READ_NEXT( p->sbiod, buf, len );
1833         if (rc <= 0) {
1834                 tlsm_map_error( errno );
1835                 if ( errno == EAGAIN || errno == EWOULDBLOCK ) {
1836                         p->nonblock = PR_TRUE; /* fd is using non-blocking io */
1837                 } else if ( errno ) { /* real error */
1838                         Debug( LDAP_DEBUG_TRACE, 
1839                                "TLS: error: tlsm_PR_Recv returned %d - error %d:%s\n",
1840                                rc, errno, STRERROR(errno) );
1841                 }
1842         }
1843
1844         return rc;
1845 }
1846
1847 static int PR_CALLBACK
1848 tlsm_PR_Send(PRFileDesc *fd, const void *buf, PRInt32 len, PRIntn flags,
1849          PRIntervalTime timeout)
1850 {
1851         struct tls_data         *p;
1852         int rc;
1853
1854         if ( buf == NULL || len <= 0 ) return 0;
1855
1856         p = (struct tls_data *)fd->secret;
1857
1858         if ( p == NULL || p->sbiod == NULL ) {
1859                 return 0;
1860         }
1861
1862         rc = LBER_SBIOD_WRITE_NEXT( p->sbiod, (char *)buf, len );
1863         if (rc <= 0) {
1864                 tlsm_map_error( errno );
1865                 if ( errno == EAGAIN || errno == EWOULDBLOCK ) {
1866                         p->nonblock = PR_TRUE;
1867                 } else if ( errno ) { /* real error */
1868                         Debug( LDAP_DEBUG_TRACE, 
1869                                "TLS: error: tlsm_PR_Send returned %d - error %d:%s\n",
1870                                rc, errno, STRERROR(errno) );
1871                 }
1872         }
1873
1874         return rc;
1875 }
1876
1877 static int PR_CALLBACK
1878 tlsm_PR_Read(PRFileDesc *fd, void *buf, PRInt32 len)
1879 {
1880         return tlsm_PR_Recv( fd, buf, len, 0, PR_INTERVAL_NO_TIMEOUT );
1881 }
1882
1883 static int PR_CALLBACK
1884 tlsm_PR_Write(PRFileDesc *fd, const void *buf, PRInt32 len)
1885 {
1886         return tlsm_PR_Send( fd, buf, len, 0, PR_INTERVAL_NO_TIMEOUT );
1887 }
1888
1889 static PRStatus PR_CALLBACK
1890 tlsm_PR_GetPeerName(PRFileDesc *fd, PRNetAddr *addr)
1891 {
1892         struct tls_data         *p;
1893         int rc;
1894         ber_socklen_t len;
1895
1896         p = (struct tls_data *)fd->secret;
1897
1898         if ( p == NULL || p->sbiod == NULL ) {
1899                 return PR_FAILURE;
1900         }
1901         len = sizeof(PRNetAddr);
1902         return getpeername( p->sbiod->sbiod_sb->sb_fd, (struct sockaddr *)addr, &len );
1903 }
1904
1905 static PRStatus PR_CALLBACK
1906 tlsm_PR_GetSocketOption(PRFileDesc *fd, PRSocketOptionData *data)
1907 {
1908         struct tls_data         *p;
1909         p = (struct tls_data *)fd->secret;
1910
1911         if ( !data ) {
1912                 return PR_FAILURE;
1913         }
1914
1915         /* only the nonblocking option is supported at this time
1916            MozNSS SSL code needs it */
1917         if ( data->option != PR_SockOpt_Nonblocking ) {
1918                 PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
1919                 return PR_FAILURE;
1920         }
1921 #ifdef HAVE_FCNTL
1922         int flags = fcntl( p->sbiod->sbiod_sb->sb_fd, F_GETFL );
1923         data->value.non_blocking = (flags & O_NONBLOCK) ? PR_TRUE : PR_FALSE;           
1924 #else /* punt :P */
1925         data->value.non_blocking = p->nonblock;
1926 #endif
1927         return PR_SUCCESS;
1928 }
1929
1930 static PRStatus PR_CALLBACK
1931 tlsm_PR_prs_unimp()
1932 {
1933     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
1934     return PR_FAILURE;
1935 }
1936
1937 static PRFileDesc * PR_CALLBACK
1938 tlsm_PR_pfd_unimp()
1939 {
1940     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
1941     return NULL;
1942 }
1943
1944 static PRInt16 PR_CALLBACK
1945 tlsm_PR_i16_unimp()
1946 {
1947     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
1948     return SECFailure;
1949 }
1950
1951 static PRInt32 PR_CALLBACK
1952 tlsm_PR_i32_unimp()
1953 {
1954     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
1955     return SECFailure;
1956 }
1957
1958 static PRInt64 PR_CALLBACK
1959 tlsm_PR_i64_unimp()
1960 {
1961     PRInt64 res;
1962
1963     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
1964     LL_I2L(res, -1L);
1965     return res;
1966 }
1967
1968 static const PRIOMethods tlsm_PR_methods = {
1969     PR_DESC_LAYERED,
1970     tlsm_PR_Close,                      /* close        */
1971     tlsm_PR_Read,                       /* read         */
1972     tlsm_PR_Write,                      /* write        */
1973     tlsm_PR_i32_unimp,          /* available    */
1974     tlsm_PR_i64_unimp,          /* available64  */
1975     tlsm_PR_prs_unimp,          /* fsync        */
1976     tlsm_PR_i32_unimp,          /* seek         */
1977     tlsm_PR_i64_unimp,          /* seek64       */
1978     tlsm_PR_prs_unimp,          /* fileInfo     */
1979     tlsm_PR_prs_unimp,          /* fileInfo64   */
1980     tlsm_PR_i32_unimp,          /* writev       */
1981     tlsm_PR_prs_unimp,          /* connect      */
1982     tlsm_PR_pfd_unimp,          /* accept       */
1983     tlsm_PR_prs_unimp,          /* bind         */
1984     tlsm_PR_prs_unimp,          /* listen       */
1985     (PRShutdownFN)tlsm_PR_Shutdown,                     /* shutdown     */
1986     tlsm_PR_Recv,                       /* recv         */
1987     tlsm_PR_Send,                       /* send         */
1988     tlsm_PR_i32_unimp,          /* recvfrom     */
1989     tlsm_PR_i32_unimp,          /* sendto       */
1990     (PRPollFN)tlsm_PR_i16_unimp,        /* poll         */
1991     tlsm_PR_i32_unimp,          /* acceptread   */
1992     tlsm_PR_i32_unimp,          /* transmitfile */
1993     tlsm_PR_prs_unimp,          /* getsockname  */
1994     tlsm_PR_GetPeerName,        /* getpeername  */
1995     tlsm_PR_i32_unimp,          /* getsockopt   OBSOLETE */
1996     tlsm_PR_i32_unimp,          /* setsockopt   OBSOLETE */
1997     tlsm_PR_GetSocketOption,            /* getsocketoption   */
1998     tlsm_PR_i32_unimp,          /* setsocketoption   */
1999     tlsm_PR_i32_unimp,          /* Send a (partial) file with header/trailer*/
2000     (PRConnectcontinueFN)tlsm_PR_prs_unimp,             /* connectcontinue */
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     tlsm_PR_i32_unimp           /* reserved for future use */
2005 };
2006
2007 /*
2008  * Initialize TLS subsystem. Should be called only once.
2009  */
2010 static int
2011 tlsm_init( void )
2012 {
2013         PR_Init(0, 0, 0);
2014
2015         tlsm_layer_id = PR_GetUniqueIdentity( "OpenLDAP" );
2016
2017         /* see deferred init */
2018         return 0;
2019 }
2020
2021 static int
2022 tlsm_sb_setup( Sockbuf_IO_Desc *sbiod, void *arg )
2023 {
2024         struct tls_data         *p;
2025         tlsm_session    *session = arg;
2026         PRFileDesc *fd;
2027
2028         assert( sbiod != NULL );
2029
2030         p = LBER_MALLOC( sizeof( *p ) );
2031         if ( p == NULL ) {
2032                 return -1;
2033         }
2034
2035         fd = PR_GetIdentitiesLayer( session, tlsm_layer_id );
2036         if ( !fd ) {
2037                 LBER_FREE( p );
2038                 return -1;
2039         }
2040
2041         fd->secret = (PRFilePrivate *)p;
2042         p->session = session;
2043         p->sbiod = sbiod;
2044         sbiod->sbiod_pvt = p;
2045         return 0;
2046 }
2047
2048 static int
2049 tlsm_sb_remove( Sockbuf_IO_Desc *sbiod )
2050 {
2051         struct tls_data         *p;
2052         
2053         assert( sbiod != NULL );
2054         assert( sbiod->sbiod_pvt != NULL );
2055
2056         p = (struct tls_data *)sbiod->sbiod_pvt;
2057         PR_Close( p->session );
2058         LBER_FREE( sbiod->sbiod_pvt );
2059         sbiod->sbiod_pvt = NULL;
2060         return 0;
2061 }
2062
2063 static int
2064 tlsm_sb_close( Sockbuf_IO_Desc *sbiod )
2065 {
2066         struct tls_data         *p;
2067         
2068         assert( sbiod != NULL );
2069         assert( sbiod->sbiod_pvt != NULL );
2070
2071         p = (struct tls_data *)sbiod->sbiod_pvt;
2072         PR_Shutdown( p->session, PR_SHUTDOWN_BOTH );
2073         return 0;
2074 }
2075
2076 static int
2077 tlsm_sb_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg )
2078 {
2079         struct tls_data         *p;
2080         
2081         assert( sbiod != NULL );
2082         assert( sbiod->sbiod_pvt != NULL );
2083
2084         p = (struct tls_data *)sbiod->sbiod_pvt;
2085         
2086         if ( opt == LBER_SB_OPT_GET_SSL ) {
2087                 *((tlsm_session **)arg) = p->session;
2088                 return 1;
2089                 
2090         } else if ( opt == LBER_SB_OPT_DATA_READY ) {
2091                 if ( tlsm_is_io_ready( p->session, PR_POLL_READ, NULL ) > 0 ) {
2092                         return 1;
2093                 }
2094                 
2095         }
2096         
2097         return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg );
2098 }
2099
2100 static ber_slen_t
2101 tlsm_sb_read( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
2102 {
2103         struct tls_data         *p;
2104         ber_slen_t              ret;
2105         int                     err;
2106
2107         assert( sbiod != NULL );
2108         assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
2109
2110         p = (struct tls_data *)sbiod->sbiod_pvt;
2111
2112         ret = PR_Recv( p->session, buf, len, 0, PR_INTERVAL_NO_TIMEOUT );
2113         if ( ret < 0 ) {
2114                 err = PR_GetError();
2115                 if ( err == PR_PENDING_INTERRUPT_ERROR || err == PR_WOULD_BLOCK_ERROR ) {
2116                         sbiod->sbiod_sb->sb_trans_needs_read = 1;
2117                         sock_errset(EWOULDBLOCK);
2118                 }
2119         } else {
2120                 sbiod->sbiod_sb->sb_trans_needs_read = 0;
2121         }
2122         return ret;
2123 }
2124
2125 static ber_slen_t
2126 tlsm_sb_write( Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
2127 {
2128         struct tls_data         *p;
2129         ber_slen_t              ret;
2130         int                     err;
2131
2132         assert( sbiod != NULL );
2133         assert( SOCKBUF_VALID( sbiod->sbiod_sb ) );
2134
2135         p = (struct tls_data *)sbiod->sbiod_pvt;
2136
2137         ret = PR_Send( p->session, (char *)buf, len, 0, PR_INTERVAL_NO_TIMEOUT );
2138         if ( ret < 0 ) {
2139                 err = PR_GetError();
2140                 if ( err == PR_PENDING_INTERRUPT_ERROR || err == PR_WOULD_BLOCK_ERROR ) {
2141                         sbiod->sbiod_sb->sb_trans_needs_write = 1;
2142                         sock_errset(EWOULDBLOCK);
2143                         ret = 0;
2144                 }
2145         } else {
2146                 sbiod->sbiod_sb->sb_trans_needs_write = 0;
2147         }
2148         return ret;
2149 }
2150
2151 static Sockbuf_IO tlsm_sbio =
2152 {
2153         tlsm_sb_setup,          /* sbi_setup */
2154         tlsm_sb_remove,         /* sbi_remove */
2155         tlsm_sb_ctrl,           /* sbi_ctrl */
2156         tlsm_sb_read,           /* sbi_read */
2157         tlsm_sb_write,          /* sbi_write */
2158         tlsm_sb_close           /* sbi_close */
2159 };
2160
2161 tls_impl ldap_int_tls_impl = {
2162         "MozNSS",
2163
2164         tlsm_init,
2165         tlsm_destroy,
2166
2167         tlsm_ctx_new,
2168         tlsm_ctx_ref,
2169         tlsm_ctx_free,
2170         tlsm_ctx_init,
2171
2172         tlsm_session_new,
2173         tlsm_session_connect,
2174         tlsm_session_accept,
2175         tlsm_session_upflags,
2176         tlsm_session_errmsg,
2177         tlsm_session_my_dn,
2178         tlsm_session_peer_dn,
2179         tlsm_session_chkhost,
2180         tlsm_session_strength,
2181
2182         &tlsm_sbio,
2183
2184 #ifdef LDAP_R_COMPILE
2185         tlsm_thr_init,
2186 #else
2187         NULL,
2188 #endif
2189
2190         0
2191 };
2192
2193 #endif /* HAVE_MOZNSS */