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