1/* tls.c - Handle tls/ssl. */ 2/* $OpenLDAP$ */ 3/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 4 * 5 * Copyright 1998-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: restructured by Howard Chu. 17 */ 18 19#include "portable.h" 20#include "ldap_config.h" 21 22#include <stdio.h> 23 24#include <ac/stdlib.h> 25#include <ac/errno.h> 26#include <ac/socket.h> 27#include <ac/string.h> 28#include <ac/ctype.h> 29#include <ac/time.h> 30#include <ac/unistd.h> 31#include <ac/param.h> 32#include <ac/dirent.h> 33 34#include "ldap-int.h" 35 36#ifdef HAVE_TLS 37 38#include "ldap-tls.h" 39 40static tls_impl *tls_imp = &ldap_int_tls_impl; 41#define HAS_TLS( sb ) ber_sockbuf_ctrl( sb, LBER_SB_OPT_HAS_IO, \ 42 (void *)tls_imp->ti_sbio ) 43 44#ifdef __APPLE__ 45#include <Security/Security.h> 46#include <syslog.h> 47#include <sys/stat.h> 48 49static void tls_get_cert_from_keychain( char *host ); 50#endif 51 52#endif /* HAVE_TLS */ 53 54/* RFC2459 minimum required set of supported attribute types 55 * in a certificate DN 56 */ 57typedef struct oid_name { 58 struct berval oid; 59 struct berval name; 60} oid_name; 61 62static oid_name oids[] = { 63 { BER_BVC("2.5.4.3"), BER_BVC("cn") }, 64 { BER_BVC("2.5.4.4"), BER_BVC("sn") }, 65 { BER_BVC("2.5.4.6"), BER_BVC("c") }, 66 { BER_BVC("2.5.4.7"), BER_BVC("l") }, 67 { BER_BVC("2.5.4.8"), BER_BVC("st") }, 68 { BER_BVC("2.5.4.10"), BER_BVC("o") }, 69 { BER_BVC("2.5.4.11"), BER_BVC("ou") }, 70 { BER_BVC("2.5.4.12"), BER_BVC("title") }, 71 { BER_BVC("2.5.4.41"), BER_BVC("name") }, 72 { BER_BVC("2.5.4.42"), BER_BVC("givenName") }, 73 { BER_BVC("2.5.4.43"), BER_BVC("initials") }, 74 { BER_BVC("2.5.4.44"), BER_BVC("generationQualifier") }, 75 { BER_BVC("2.5.4.46"), BER_BVC("dnQualifier") }, 76 { BER_BVC("1.2.840.113549.1.9.1"), BER_BVC("email") }, 77 { BER_BVC("0.9.2342.19200300.100.1.25"), BER_BVC("dc") }, 78 { BER_BVNULL, BER_BVNULL } 79}; 80 81#ifdef HAVE_TLS 82 83void 84ldap_pvt_tls_ctx_free ( void *c ) 85{ 86 if ( !c ) return; 87 tls_imp->ti_ctx_free( c ); 88} 89 90static void 91tls_ctx_ref( tls_ctx *ctx ) 92{ 93 if ( !ctx ) return; 94 95 tls_imp->ti_ctx_ref( ctx ); 96} 97 98#ifdef LDAP_R_COMPILE 99/* 100 * an extra mutex for the default ctx. 101 */ 102static ldap_pvt_thread_mutex_t tls_def_ctx_mutex; 103#endif 104 105void 106ldap_int_tls_destroy( struct ldapoptions *lo ) 107{ 108 if ( lo->ldo_tls_ctx ) { 109 ldap_pvt_tls_ctx_free( lo->ldo_tls_ctx ); 110 lo->ldo_tls_ctx = NULL; 111 } 112 113 if ( lo->ldo_tls_certfile ) { 114 LDAP_FREE( lo->ldo_tls_certfile ); 115 lo->ldo_tls_certfile = NULL; 116 } 117 if ( lo->ldo_tls_keyfile ) { 118 LDAP_FREE( lo->ldo_tls_keyfile ); 119 lo->ldo_tls_keyfile = NULL; 120 } 121 if ( lo->ldo_tls_dhfile ) { 122 LDAP_FREE( lo->ldo_tls_dhfile ); 123 lo->ldo_tls_dhfile = NULL; 124 } 125 if ( lo->ldo_tls_cacertfile ) { 126 LDAP_FREE( lo->ldo_tls_cacertfile ); 127 lo->ldo_tls_cacertfile = NULL; 128 } 129 if ( lo->ldo_tls_cacertdir ) { 130 LDAP_FREE( lo->ldo_tls_cacertdir ); 131 lo->ldo_tls_cacertdir = NULL; 132 } 133 if ( lo->ldo_tls_ciphersuite ) { 134 LDAP_FREE( lo->ldo_tls_ciphersuite ); 135 lo->ldo_tls_ciphersuite = NULL; 136 } 137 if ( lo->ldo_tls_crlfile ) { 138 LDAP_FREE( lo->ldo_tls_crlfile ); 139 lo->ldo_tls_crlfile = NULL; 140 } 141#ifdef __APPLE__ 142 if ( lo->ldo_tls_cert_ref ) { 143 CFRelease( lo->ldo_tls_cert_ref ); 144 lo->ldo_tls_cert_ref = NULL; 145 } 146#endif 147} 148 149/* 150 * Tear down the TLS subsystem. Should only be called once. 151 */ 152void 153ldap_pvt_tls_destroy( void ) 154{ 155 struct ldapoptions *lo = LDAP_INT_GLOBAL_OPT(); 156 157 ldap_int_tls_destroy( lo ); 158 159 tls_imp->ti_tls_destroy(); 160} 161 162/* 163 * Initialize a particular TLS implementation. 164 * Called once per implementation. 165 */ 166static int 167tls_init(tls_impl *impl ) 168{ 169 static int tls_initialized = 0; 170 171 if ( !tls_initialized++ ) { 172#ifdef LDAP_R_COMPILE 173 ldap_pvt_thread_mutex_init( &tls_def_ctx_mutex ); 174#endif 175 } 176 177 if ( impl->ti_inited++ ) return 0; 178 179#ifdef LDAP_R_COMPILE 180 impl->ti_thr_init(); 181#endif 182 return impl->ti_tls_init(); 183} 184 185/* 186 * Initialize TLS subsystem. Called once per implementation. 187 */ 188int 189ldap_pvt_tls_init( void ) 190{ 191 return tls_init( tls_imp ); 192} 193 194/* 195 * initialize a new TLS context 196 */ 197static int 198ldap_int_tls_init_ctx( struct ldapoptions *lo, int is_server ) 199{ 200 int rc = 0; 201 tls_impl *ti = tls_imp; 202 struct ldaptls lts = lo->ldo_tls_info; 203 204 if ( lo->ldo_tls_ctx ) 205 return 0; 206 207 tls_init( ti ); 208#ifdef __APPLE__ 209 if(is_server && !lts.lt_server_ident_ref_name) 210 { 211 return LDAP_NOT_SUPPORTED; 212 } 213#else 214 if ( is_server && !lts.lt_certfile && !lts.lt_keyfile && 215 !lts.lt_cacertfile && !lts.lt_cacertdir ) { 216 /* minimum configuration not provided */ 217 return LDAP_NOT_SUPPORTED; 218 } 219#endif 220 221#ifdef HAVE_EBCDIC 222 /* This ASCII/EBCDIC handling is a real pain! */ 223 if ( lts.lt_ciphersuite ) { 224 lts.lt_ciphersuite = LDAP_STRDUP( lts.lt_ciphersuite ); 225 __atoe( lts.lt_ciphersuite ); 226 } 227 if ( lts.lt_cacertfile ) { 228 lts.lt_cacertfile = LDAP_STRDUP( lts.lt_cacertfile ); 229 __atoe( lts.lt_cacertfile ); 230 } 231 if ( lts.lt_certfile ) { 232 lts.lt_certfile = LDAP_STRDUP( lts.lt_certfile ); 233 __atoe( lts.lt_certfile ); 234 } 235 if ( lts.lt_keyfile ) { 236 lts.lt_keyfile = LDAP_STRDUP( lts.lt_keyfile ); 237 __atoe( lts.lt_keyfile ); 238 } 239 if ( lts.lt_crlfile ) { 240 lts.lt_crlfile = LDAP_STRDUP( lts.lt_crlfile ); 241 __atoe( lts.lt_crlfile ); 242 } 243 if ( lts.lt_cacertdir ) { 244 lts.lt_cacertdir = LDAP_STRDUP( lts.lt_cacertdir ); 245 __atoe( lts.lt_cacertdir ); 246 } 247 if ( lts.lt_dhfile ) { 248 lts.lt_dhfile = LDAP_STRDUP( lts.lt_dhfile ); 249 __atoe( lts.lt_dhfile ); 250 } 251#endif 252 lo->ldo_tls_ctx = ti->ti_ctx_new( lo ); 253 if ( lo->ldo_tls_ctx == NULL ) { 254 Debug( LDAP_DEBUG_ANY, 255 "TLS: could not allocate default ctx.\n", 256 0,0,0); 257 rc = -1; 258 goto error_exit; 259 } 260 261 rc = ti->ti_ctx_init( lo, <s, is_server ); 262 263error_exit: 264 if ( rc < 0 && lo->ldo_tls_ctx != NULL ) { 265 ldap_pvt_tls_ctx_free( lo->ldo_tls_ctx ); 266 lo->ldo_tls_ctx = NULL; 267 } 268#ifdef HAVE_EBCDIC 269 LDAP_FREE( lts.lt_ciphersuite ); 270 LDAP_FREE( lts.lt_cacertfile ); 271 LDAP_FREE( lts.lt_certfile ); 272 LDAP_FREE( lts.lt_keyfile ); 273 LDAP_FREE( lts.lt_crlfile ); 274 LDAP_FREE( lts.lt_cacertdir ); 275 LDAP_FREE( lts.lt_dhfile ); 276#endif 277 return rc; 278} 279 280/* 281 * initialize the default context 282 */ 283int 284ldap_pvt_tls_init_def_ctx( int is_server ) 285{ 286 struct ldapoptions *lo = LDAP_INT_GLOBAL_OPT(); 287 int rc; 288 LDAP_MUTEX_LOCK( &tls_def_ctx_mutex ); 289 rc = ldap_int_tls_init_ctx( lo, is_server ); 290 LDAP_MUTEX_UNLOCK( &tls_def_ctx_mutex ); 291 return rc; 292} 293 294static tls_session * 295alloc_handle( void *ctx_arg, int is_server ) 296{ 297 tls_ctx *ctx; 298 tls_session *ssl; 299 300 if ( ctx_arg ) { 301 ctx = ctx_arg; 302 } else { 303 struct ldapoptions *lo = LDAP_INT_GLOBAL_OPT(); 304 if ( ldap_pvt_tls_init_def_ctx( is_server ) < 0 ) return NULL; 305 ctx = lo->ldo_tls_ctx; 306 } 307 308 ssl = tls_imp->ti_session_new( ctx, is_server ); 309 if ( ssl == NULL ) { 310 Debug( LDAP_DEBUG_ANY,"TLS: can't create ssl handle.\n",0,0,0); 311 return NULL; 312 } 313 return ssl; 314} 315 316static int 317update_flags( Sockbuf *sb, tls_session * ssl, int rc ) 318{ 319 sb->sb_trans_needs_read = 0; 320 sb->sb_trans_needs_write = 0; 321 322 return tls_imp->ti_session_upflags( sb, ssl, rc ); 323} 324 325/* 326 * Call this to do a TLS connect on a sockbuf. ctx_arg can be 327 * a SSL_CTX * or NULL, in which case the default ctx is used. 328 * 329 * Return value: 330 * 331 * 0 - Success. Connection is ready for communication. 332 * <0 - Error. Can't create a TLS stream. 333 * >0 - Partial success. 334 * Do a select (using information from lber_pvt_sb_needs_{read,write} 335 * and call again. 336 */ 337 338static int 339ldap_int_tls_connect( LDAP *ld, LDAPConn *conn ) 340{ 341 Sockbuf *sb = conn->lconn_sb; 342 int err; 343 tls_session *ssl = NULL; 344 345 if ( HAS_TLS( sb )) { 346 ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_SSL, (void *)&ssl ); 347 } else { 348 struct ldapoptions *lo; 349 tls_ctx *ctx; 350 351 ctx = ld->ld_options.ldo_tls_ctx; 352 353 ssl = alloc_handle( ctx, 0 ); 354 355 if ( ssl == NULL ) return -1; 356 357#ifdef LDAP_DEBUG 358 ber_sockbuf_add_io( sb, &ber_sockbuf_io_debug, 359 LBER_SBIOD_LEVEL_TRANSPORT, (void *)"tls_" ); 360#endif 361 ber_sockbuf_add_io( sb, tls_imp->ti_sbio, 362 LBER_SBIOD_LEVEL_TRANSPORT, (void *)ssl ); 363 364 lo = LDAP_INT_GLOBAL_OPT(); 365 if( ctx == NULL ) { 366 ctx = lo->ldo_tls_ctx; 367 ld->ld_options.ldo_tls_ctx = ctx; 368 tls_ctx_ref( ctx ); 369 } 370 if ( ld->ld_options.ldo_tls_connect_cb ) 371 ld->ld_options.ldo_tls_connect_cb( ld, ssl, ctx, 372 ld->ld_options.ldo_tls_connect_arg ); 373 if ( lo && lo->ldo_tls_connect_cb && lo->ldo_tls_connect_cb != 374 ld->ld_options.ldo_tls_connect_cb ) 375 lo->ldo_tls_connect_cb( ld, ssl, ctx, lo->ldo_tls_connect_arg ); 376 } 377 378 err = tls_imp->ti_session_connect( ld, ssl ); 379 380#ifdef HAVE_WINSOCK 381 errno = WSAGetLastError(); 382#endif 383 384 if ( err < 0 ) 385 { 386 char buf[256], *msg; 387 if ( update_flags( sb, ssl, err )) { 388 return 1; 389 } 390 391 msg = tls_imp->ti_session_errmsg( ssl, err, buf, sizeof(buf) ); 392 if ( msg ) { 393 if ( ld->ld_error ) { 394 LDAP_FREE( ld->ld_error ); 395 } 396 ld->ld_error = LDAP_STRDUP( msg ); 397#ifdef HAVE_EBCDIC 398 if ( ld->ld_error ) __etoa(ld->ld_error); 399#endif 400 } 401 402 Debug( LDAP_DEBUG_ANY,"TLS: can't connect: %s.\n", 403 ld->ld_error ? ld->ld_error : "" ,0,0); 404 405 ber_sockbuf_remove_io( sb, tls_imp->ti_sbio, 406 LBER_SBIOD_LEVEL_TRANSPORT ); 407#ifdef LDAP_DEBUG 408 ber_sockbuf_remove_io( sb, &ber_sockbuf_io_debug, 409 LBER_SBIOD_LEVEL_TRANSPORT ); 410#endif 411 return -1; 412 } 413 414 return 0; 415} 416 417/* 418 * Call this to do a TLS accept on a sockbuf. 419 * Everything else is the same as with tls_connect. 420 */ 421int 422ldap_pvt_tls_accept( Sockbuf *sb, void *ctx_arg ) 423{ 424 int err; 425 tls_session *ssl = NULL; 426 427 if ( HAS_TLS( sb )) { 428 ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_SSL, (void *)&ssl ); 429 } else { 430 ssl = alloc_handle( ctx_arg, 1 ); 431 if ( ssl == NULL ) return -1; 432 433#ifdef LDAP_DEBUG 434 ber_sockbuf_add_io( sb, &ber_sockbuf_io_debug, 435 LBER_SBIOD_LEVEL_TRANSPORT, (void *)"tls_" ); 436#endif 437 ber_sockbuf_add_io( sb, tls_imp->ti_sbio, 438 LBER_SBIOD_LEVEL_TRANSPORT, (void *)ssl ); 439 } 440 441 err = tls_imp->ti_session_accept( ssl ); 442 443#ifdef HAVE_WINSOCK 444 errno = WSAGetLastError(); 445#endif 446 447 if ( err < 0 ) 448 { 449 if ( update_flags( sb, ssl, err )) return 1; 450 451 if ( DebugTest( LDAP_DEBUG_ANY ) ) { 452 char buf[256], *msg; 453 msg = tls_imp->ti_session_errmsg( ssl, err, buf, sizeof(buf) ); 454 Debug( LDAP_DEBUG_ANY,"TLS: can't accept: %s.\n", 455 msg ? msg : "(unknown)", 0, 0 ); 456 } 457 458 ber_sockbuf_remove_io( sb, tls_imp->ti_sbio, 459 LBER_SBIOD_LEVEL_TRANSPORT ); 460#ifdef LDAP_DEBUG 461 ber_sockbuf_remove_io( sb, &ber_sockbuf_io_debug, 462 LBER_SBIOD_LEVEL_TRANSPORT ); 463#endif 464 return -1; 465 } 466 return 0; 467} 468 469int 470ldap_pvt_tls_inplace ( Sockbuf *sb ) 471{ 472 return HAS_TLS( sb ) ? 1 : 0; 473} 474 475int 476ldap_tls_inplace( LDAP *ld ) 477{ 478 Sockbuf *sb = NULL; 479 480 if ( ld->ld_defconn && ld->ld_defconn->lconn_sb ) { 481 sb = ld->ld_defconn->lconn_sb; 482 483 } else if ( ld->ld_sb ) { 484 sb = ld->ld_sb; 485 486 } else { 487 return 0; 488 } 489 490 return ldap_pvt_tls_inplace( sb ); 491} 492 493int 494ldap_pvt_tls_get_peer_dn( void *s, struct berval *dn, 495 LDAPDN_rewrite_dummy *func, unsigned flags ) 496{ 497 tls_session *session = s; 498 struct berval bvdn; 499 int rc; 500 501 rc = tls_imp->ti_session_peer_dn( session, &bvdn ); 502 if ( rc ) return rc; 503 504 rc = ldap_X509dn2bv( &bvdn, dn, 505 (LDAPDN_rewrite_func *)func, flags); 506 return rc; 507} 508 509int 510ldap_pvt_tls_check_hostname( LDAP *ld, void *s, const char *name_in ) 511{ 512 tls_session *session = s; 513 514 return tls_imp->ti_session_chkhost( ld, session, name_in ); 515} 516 517int 518ldap_int_tls_config( LDAP *ld, int option, const char *arg ) 519{ 520 int i; 521 522 switch( option ) { 523 case LDAP_OPT_X_TLS_CACERTFILE: 524 case LDAP_OPT_X_TLS_CACERTDIR: 525 case LDAP_OPT_X_TLS_CERTFILE: 526 case LDAP_OPT_X_TLS_KEYFILE: 527 case LDAP_OPT_X_TLS_RANDOM_FILE: 528 case LDAP_OPT_X_TLS_CIPHER_SUITE: 529 case LDAP_OPT_X_TLS_DHFILE: 530 case LDAP_OPT_X_TLS_CRLFILE: /* GnuTLS only */ 531 return ldap_pvt_tls_set_option( ld, option, (void *) arg ); 532 533 case LDAP_OPT_X_TLS_REQUIRE_CERT: 534 case LDAP_OPT_X_TLS: 535 i = -1; 536 if ( strcasecmp( arg, "never" ) == 0 ) { 537 i = LDAP_OPT_X_TLS_NEVER ; 538 539 } else if ( strcasecmp( arg, "demand" ) == 0 ) { 540 i = LDAP_OPT_X_TLS_DEMAND ; 541 542 } else if ( strcasecmp( arg, "allow" ) == 0 ) { 543 i = LDAP_OPT_X_TLS_ALLOW ; 544 545 } else if ( strcasecmp( arg, "try" ) == 0 ) { 546 i = LDAP_OPT_X_TLS_TRY ; 547 548 } else if ( ( strcasecmp( arg, "hard" ) == 0 ) || 549 ( strcasecmp( arg, "on" ) == 0 ) || 550 ( strcasecmp( arg, "yes" ) == 0) || 551 ( strcasecmp( arg, "true" ) == 0 ) ) 552 { 553 i = LDAP_OPT_X_TLS_HARD ; 554 } 555 556 if (i >= 0) { 557 return ldap_pvt_tls_set_option( ld, option, &i ); 558 } 559 return -1; 560 case LDAP_OPT_X_TLS_PROTOCOL_MIN: { 561 char *next; 562 long l; 563 l = strtol( arg, &next, 10 ); 564 if ( l < 0 || l > 0xff || next == arg || 565 ( *next != '\0' && *next != '.' ) ) 566 return -1; 567 i = l << 8; 568 if (*next == '.') { 569 arg = next + 1; 570 l = strtol( arg, &next, 10 ); 571 if ( l < 0 || l > 0xff || next == arg || *next != '\0' ) 572 return -1; 573 i += l; 574 } 575 return ldap_pvt_tls_set_option( ld, option, &i ); 576 } 577#ifdef HAVE_OPENSSL_CRL 578 case LDAP_OPT_X_TLS_CRLCHECK: /* OpenSSL only */ 579 i = -1; 580 if ( strcasecmp( arg, "none" ) == 0 ) { 581 i = LDAP_OPT_X_TLS_CRL_NONE ; 582 } else if ( strcasecmp( arg, "peer" ) == 0 ) { 583 i = LDAP_OPT_X_TLS_CRL_PEER ; 584 } else if ( strcasecmp( arg, "all" ) == 0 ) { 585 i = LDAP_OPT_X_TLS_CRL_ALL ; 586 } 587 if (i >= 0) { 588 return ldap_pvt_tls_set_option( ld, option, &i ); 589 } 590 return -1; 591#endif 592 } 593 return -1; 594} 595 596int 597ldap_pvt_tls_get_option( LDAP *ld, int option, void *arg ) 598{ 599 struct ldapoptions *lo; 600 601 if( option == LDAP_OPT_X_TLS_PACKAGE ) { 602 *(char **)arg = LDAP_STRDUP( tls_imp->ti_name ); 603 return 0; 604 } 605 606 if( ld != NULL ) { 607 assert( LDAP_VALID( ld ) ); 608 609 if( !LDAP_VALID( ld ) ) { 610 return LDAP_OPT_ERROR; 611 } 612 613 lo = &ld->ld_options; 614 615 } else { 616 /* Get pointer to global option structure */ 617 lo = LDAP_INT_GLOBAL_OPT(); 618 if ( lo == NULL ) { 619 return LDAP_NO_MEMORY; 620 } 621 } 622 623 switch( option ) { 624 case LDAP_OPT_X_TLS: 625 *(int *)arg = lo->ldo_tls_mode; 626 break; 627 case LDAP_OPT_X_TLS_CTX: 628 *(void **)arg = lo->ldo_tls_ctx; 629 if ( lo->ldo_tls_ctx ) { 630 tls_ctx_ref( lo->ldo_tls_ctx ); 631 } 632 break; 633 case LDAP_OPT_X_TLS_CACERTFILE: 634 *(char **)arg = lo->ldo_tls_cacertfile ? 635 LDAP_STRDUP( lo->ldo_tls_cacertfile ) : NULL; 636 break; 637 case LDAP_OPT_X_TLS_CACERTDIR: 638 *(char **)arg = lo->ldo_tls_cacertdir ? 639 LDAP_STRDUP( lo->ldo_tls_cacertdir ) : NULL; 640 break; 641 case LDAP_OPT_X_TLS_CERTFILE: 642 *(char **)arg = lo->ldo_tls_certfile ? 643 LDAP_STRDUP( lo->ldo_tls_certfile ) : NULL; 644 break; 645 case LDAP_OPT_X_TLS_KEYFILE: 646 *(char **)arg = lo->ldo_tls_keyfile ? 647 LDAP_STRDUP( lo->ldo_tls_keyfile ) : NULL; 648 break; 649 case LDAP_OPT_X_TLS_DHFILE: 650 *(char **)arg = lo->ldo_tls_dhfile ? 651 LDAP_STRDUP( lo->ldo_tls_dhfile ) : NULL; 652 break; 653 case LDAP_OPT_X_TLS_CRLFILE: /* GnuTLS only */ 654 *(char **)arg = lo->ldo_tls_crlfile ? 655 LDAP_STRDUP( lo->ldo_tls_crlfile ) : NULL; 656 break; 657 case LDAP_OPT_X_TLS_REQUIRE_CERT: 658 *(int *)arg = lo->ldo_tls_require_cert; 659 break; 660#ifdef HAVE_OPENSSL_CRL 661 case LDAP_OPT_X_TLS_CRLCHECK: /* OpenSSL only */ 662 *(int *)arg = lo->ldo_tls_crlcheck; 663 break; 664#endif 665 case LDAP_OPT_X_TLS_CIPHER_SUITE: 666 *(char **)arg = lo->ldo_tls_ciphersuite ? 667 LDAP_STRDUP( lo->ldo_tls_ciphersuite ) : NULL; 668 break; 669 case LDAP_OPT_X_TLS_PROTOCOL_MIN: 670 *(int *)arg = lo->ldo_tls_protocol_min; 671 break; 672 case LDAP_OPT_X_TLS_RANDOM_FILE: 673 *(char **)arg = lo->ldo_tls_randfile ? 674 LDAP_STRDUP( lo->ldo_tls_randfile ) : NULL; 675 break; 676 case LDAP_OPT_X_TLS_SSL_CTX: { 677 void *retval = 0; 678 if ( ld != NULL ) { 679 LDAPConn *conn = ld->ld_defconn; 680 if ( conn != NULL ) { 681 Sockbuf *sb = conn->lconn_sb; 682 retval = ldap_pvt_tls_sb_ctx( sb ); 683 } 684 } 685 *(void **)arg = retval; 686 break; 687 } 688 case LDAP_OPT_X_TLS_CONNECT_CB: 689 *(LDAP_TLS_CONNECT_CB **)arg = lo->ldo_tls_connect_cb; 690 break; 691 case LDAP_OPT_X_TLS_CONNECT_ARG: 692 *(void **)arg = lo->ldo_tls_connect_arg; 693 break; 694 695#ifdef __APPLE__ 696 case LDAP_OPT_X_TLS_CERT_IDENTITY: 697 *(char **)arg = lo->ldo_tls_server_ident_ref_name ? 698 LDAP_STRDUP( lo->ldo_tls_server_ident_ref_name) : NULL; 699 break; 700#endif 701 702 default: 703 return -1; 704 } 705 return 0; 706} 707 708int 709ldap_pvt_tls_set_option( LDAP *ld, int option, void *arg ) 710{ 711 struct ldapoptions *lo; 712 713 if( ld != NULL ) { 714 assert( LDAP_VALID( ld ) ); 715 716 if( !LDAP_VALID( ld ) ) { 717 return LDAP_OPT_ERROR; 718 } 719 720 lo = &ld->ld_options; 721 722 } else { 723 /* Get pointer to global option structure */ 724 lo = LDAP_INT_GLOBAL_OPT(); 725 if ( lo == NULL ) { 726 return LDAP_NO_MEMORY; 727 } 728 } 729 730 switch( option ) { 731 case LDAP_OPT_X_TLS: 732 if ( !arg ) return -1; 733 734 switch( *(int *) arg ) { 735 case LDAP_OPT_X_TLS_NEVER: 736 case LDAP_OPT_X_TLS_DEMAND: 737 case LDAP_OPT_X_TLS_ALLOW: 738 case LDAP_OPT_X_TLS_TRY: 739 case LDAP_OPT_X_TLS_HARD: 740 if (lo != NULL) { 741 lo->ldo_tls_mode = *(int *)arg; 742 } 743 744 return 0; 745 } 746 return -1; 747 748 case LDAP_OPT_X_TLS_CTX: 749 if ( lo->ldo_tls_ctx ) 750 ldap_pvt_tls_ctx_free( lo->ldo_tls_ctx ); 751 lo->ldo_tls_ctx = arg; 752 tls_ctx_ref( lo->ldo_tls_ctx ); 753 return 0; 754 case LDAP_OPT_X_TLS_CONNECT_CB: 755 lo->ldo_tls_connect_cb = (LDAP_TLS_CONNECT_CB *)arg; 756 return 0; 757 case LDAP_OPT_X_TLS_CONNECT_ARG: 758 lo->ldo_tls_connect_arg = arg; 759 return 0; 760 case LDAP_OPT_X_TLS_CACERTFILE: 761 if ( lo->ldo_tls_cacertfile ) LDAP_FREE( lo->ldo_tls_cacertfile ); 762 lo->ldo_tls_cacertfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL; 763 return 0; 764 case LDAP_OPT_X_TLS_CACERTDIR: 765 if ( lo->ldo_tls_cacertdir ) LDAP_FREE( lo->ldo_tls_cacertdir ); 766 lo->ldo_tls_cacertdir = arg ? LDAP_STRDUP( (char *) arg ) : NULL; 767 return 0; 768 case LDAP_OPT_X_TLS_CERTFILE: 769 if ( lo->ldo_tls_certfile ) LDAP_FREE( lo->ldo_tls_certfile ); 770 lo->ldo_tls_certfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL; 771 return 0; 772 case LDAP_OPT_X_TLS_KEYFILE: 773 if ( lo->ldo_tls_keyfile ) LDAP_FREE( lo->ldo_tls_keyfile ); 774 lo->ldo_tls_keyfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL; 775 return 0; 776 case LDAP_OPT_X_TLS_DHFILE: 777 if ( lo->ldo_tls_dhfile ) LDAP_FREE( lo->ldo_tls_dhfile ); 778 lo->ldo_tls_dhfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL; 779 return 0; 780 case LDAP_OPT_X_TLS_CRLFILE: /* GnuTLS only */ 781 if ( lo->ldo_tls_crlfile ) LDAP_FREE( lo->ldo_tls_crlfile ); 782 lo->ldo_tls_crlfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL; 783 return 0; 784 case LDAP_OPT_X_TLS_REQUIRE_CERT: 785 if ( !arg ) return -1; 786 switch( *(int *) arg ) { 787 case LDAP_OPT_X_TLS_NEVER: 788 case LDAP_OPT_X_TLS_DEMAND: 789 case LDAP_OPT_X_TLS_ALLOW: 790 case LDAP_OPT_X_TLS_TRY: 791 case LDAP_OPT_X_TLS_HARD: 792 lo->ldo_tls_require_cert = * (int *) arg; 793 return 0; 794 } 795 return -1; 796#ifdef HAVE_OPENSSL_CRL 797 case LDAP_OPT_X_TLS_CRLCHECK: /* OpenSSL only */ 798 if ( !arg ) return -1; 799 switch( *(int *) arg ) { 800 case LDAP_OPT_X_TLS_CRL_NONE: 801 case LDAP_OPT_X_TLS_CRL_PEER: 802 case LDAP_OPT_X_TLS_CRL_ALL: 803 lo->ldo_tls_crlcheck = * (int *) arg; 804 return 0; 805 } 806 return -1; 807#endif 808 case LDAP_OPT_X_TLS_CIPHER_SUITE: 809 if ( lo->ldo_tls_ciphersuite ) LDAP_FREE( lo->ldo_tls_ciphersuite ); 810 lo->ldo_tls_ciphersuite = arg ? LDAP_STRDUP( (char *) arg ) : NULL; 811 return 0; 812 813 case LDAP_OPT_X_TLS_PROTOCOL_MIN: 814 if ( !arg ) return -1; 815 lo->ldo_tls_protocol_min = *(int *)arg; 816 return 0; 817 case LDAP_OPT_X_TLS_RANDOM_FILE: 818 if ( ld != NULL ) 819 return -1; 820 if ( lo->ldo_tls_randfile ) LDAP_FREE (lo->ldo_tls_randfile ); 821 lo->ldo_tls_randfile = arg ? LDAP_STRDUP( (char *) arg ) : NULL; 822 break; 823#ifdef __APPLE__ 824 case LDAP_OPT_X_TLS_CERT_IDENTITY: 825 if( lo->ldo_tls_server_ident_ref_name) LDAP_FREE(lo->ldo_tls_server_ident_ref_name); 826 lo->ldo_tls_server_ident_ref_name = arg ? LDAP_STRDUP( (char*) arg) : NULL; 827 return 0; 828 829 case LDAP_OPT_X_TLS_PASSPHRASE: 830 if( lo->ldo_tls_passphrase) LDAP_FREE(lo->ldo_tls_passphrase); 831 lo->ldo_tls_passphrase = arg ? LDAP_STRDUP( (char*) arg) : NULL; 832 return 0; 833#endif 834 case LDAP_OPT_X_TLS_NEWCTX: 835 if ( !arg ) return -1; 836 if ( lo->ldo_tls_ctx ) 837 ldap_pvt_tls_ctx_free( lo->ldo_tls_ctx ); 838 lo->ldo_tls_ctx = NULL; 839 return ldap_int_tls_init_ctx( lo, *(int *)arg ); 840 default: 841 return -1; 842 } 843 return 0; 844} 845 846int 847ldap_int_tls_start ( LDAP *ld, LDAPConn *conn, LDAPURLDesc *srv ) 848{ 849 Sockbuf *sb; 850 char *host; 851 void *ssl; 852 853 if ( !conn ) 854 return LDAP_PARAM_ERROR; 855 856 sb = conn->lconn_sb; 857 if( srv ) { 858 host = srv->lud_host; 859 } else { 860 host = conn->lconn_server->lud_host; 861 } 862 863 /* avoid NULL host */ 864 if( host == NULL ) { 865 host = "localhost"; 866 } 867 868 (void) tls_init( tls_imp ); 869 870#ifdef __APPLE__ 871 /* Get the host's certificate from the keychain if possible, and stash 872 * it in the options for use once the SSL context is created. 873 */ 874 tls_get_cert_from_keychain( host ); 875#endif 876 877 /* 878 * Fortunately, the lib uses blocking io... 879 */ 880 if ( ldap_int_tls_connect( ld, conn ) < 0 ) { 881 ld->ld_errno = LDAP_CONNECT_ERROR; 882 return (ld->ld_errno); 883 } 884 885 ssl = ldap_pvt_tls_sb_ctx( sb ); 886 assert( ssl != NULL ); 887 888 /* 889 * compare host with name(s) in certificate 890 */ 891 if (ld->ld_options.ldo_tls_require_cert != LDAP_OPT_X_TLS_NEVER && 892 ld->ld_options.ldo_tls_require_cert != LDAP_OPT_X_TLS_ALLOW) { 893 ld->ld_errno = ldap_pvt_tls_check_hostname( ld, ssl, host ); 894 if (ld->ld_errno != LDAP_SUCCESS) { 895#ifdef __APPLE__ 896 /* If the hostname is really an IP address, do the reverse 897 * lookup and see if that matches the cert. 898 */ 899 char *hostname = ldap_host_connected_to( sb, host ); 900 if (hostname) { 901 Debug( LDAP_DEBUG_ANY, 902 "TLS reverse lookup of '%s' is '%s', checking if that matches the certificate common name\n", 903 host, hostname, 0); 904 905 ld->ld_errno = ldap_pvt_tls_check_hostname( ld, ssl, hostname ); 906 free(hostname); 907 hostname = NULL; 908 } 909#endif 910 return ld->ld_errno; 911 } 912 } 913 914 return LDAP_SUCCESS; 915} 916 917void * 918ldap_pvt_tls_sb_ctx( Sockbuf *sb ) 919{ 920 void *p = NULL; 921 922 ber_sockbuf_ctrl( sb, LBER_SB_OPT_GET_SSL, (void *)&p ); 923 return p; 924} 925 926int 927ldap_pvt_tls_get_strength( void *s ) 928{ 929 tls_session *session = s; 930 931 return tls_imp->ti_session_strength( session ); 932} 933 934int 935ldap_pvt_tls_get_my_dn( void *s, struct berval *dn, LDAPDN_rewrite_dummy *func, unsigned flags ) 936{ 937 tls_session *session = s; 938 struct berval der_dn; 939 int rc; 940 941 rc = tls_imp->ti_session_my_dn( session, &der_dn ); 942 if ( rc == LDAP_SUCCESS ) 943 rc = ldap_X509dn2bv(&der_dn, dn, (LDAPDN_rewrite_func *)func, flags ); 944 return rc; 945} 946#endif /* HAVE_TLS */ 947 948int 949ldap_start_tls( LDAP *ld, 950 LDAPControl **serverctrls, 951 LDAPControl **clientctrls, 952 int *msgidp ) 953{ 954 return ldap_extended_operation( ld, LDAP_EXOP_START_TLS, 955 NULL, serverctrls, clientctrls, msgidp ); 956} 957 958int 959ldap_install_tls( LDAP *ld ) 960{ 961#ifndef HAVE_TLS 962 return LDAP_NOT_SUPPORTED; 963#else 964 if ( ldap_tls_inplace( ld ) ) { 965 return LDAP_LOCAL_ERROR; 966 } 967 968 return ldap_int_tls_start( ld, ld->ld_defconn, NULL ); 969#endif 970} 971 972int 973ldap_start_tls_s ( LDAP *ld, 974 LDAPControl **serverctrls, 975 LDAPControl **clientctrls ) 976{ 977#ifndef HAVE_TLS 978 return LDAP_NOT_SUPPORTED; 979#else 980 int rc; 981 char *rspoid = NULL; 982 struct berval *rspdata = NULL; 983 984 /* XXYYZ: this initiates operation only on default connection! */ 985 986 if ( ldap_tls_inplace( ld ) ) { 987 return LDAP_LOCAL_ERROR; 988 } 989 990 rc = ldap_extended_operation_s( ld, LDAP_EXOP_START_TLS, 991 NULL, serverctrls, clientctrls, &rspoid, &rspdata ); 992 993 if ( rspoid != NULL ) { 994 LDAP_FREE(rspoid); 995 } 996 997 if ( rspdata != NULL ) { 998 ber_bvfree( rspdata ); 999 } 1000 1001 if ( rc == LDAP_SUCCESS ) { 1002 rc = ldap_int_tls_start( ld, ld->ld_defconn, NULL ); 1003 } 1004 1005 return rc; 1006#endif 1007} 1008 1009/* These tags probably all belong in lber.h, but they're 1010 * not normally encountered when processing LDAP, so maybe 1011 * they belong somewhere else instead. 1012 */ 1013 1014#define LBER_TAG_OID ((ber_tag_t) 0x06UL) 1015 1016/* Tags for string types used in a DirectoryString. 1017 * 1018 * Note that IA5string is not one of the defined choices for 1019 * DirectoryString in X.520, but it gets used for email AVAs. 1020 */ 1021#define LBER_TAG_UTF8 ((ber_tag_t) 0x0cUL) 1022#define LBER_TAG_PRINTABLE ((ber_tag_t) 0x13UL) 1023#define LBER_TAG_TELETEX ((ber_tag_t) 0x14UL) 1024#define LBER_TAG_IA5 ((ber_tag_t) 0x16UL) 1025#define LBER_TAG_UNIVERSAL ((ber_tag_t) 0x1cUL) 1026#define LBER_TAG_BMP ((ber_tag_t) 0x1eUL) 1027 1028static oid_name * 1029find_oid( struct berval *oid ) 1030{ 1031 int i; 1032 1033 for ( i=0; !BER_BVISNULL( &oids[i].oid ); i++ ) { 1034 if ( oids[i].oid.bv_len != oid->bv_len ) continue; 1035 if ( !strcmp( oids[i].oid.bv_val, oid->bv_val )) 1036 return &oids[i]; 1037 } 1038 return NULL; 1039} 1040 1041/* Converts BER Bitstring value to LDAP BitString value (RFC4517) 1042 * 1043 * berValue : IN 1044 * rfc4517Value: OUT 1045 * 1046 * berValue and ldapValue should not be NULL 1047 */ 1048 1049#define BITS_PER_BYTE 8 1050#define SQUOTE_LENGTH 1 1051#define B_CHAR_LENGTH 1 1052#define STR_OVERHEAD (2*SQUOTE_LENGTH + B_CHAR_LENGTH) 1053 1054static int 1055der_to_ldap_BitString (struct berval *berValue, 1056 struct berval *ldapValue) 1057{ 1058 ber_len_t bitPadding=0; 1059 ber_len_t bits, maxBits; 1060 char *tmpStr; 1061 unsigned char byte; 1062 ber_len_t bitLength; 1063 ber_len_t valLen; 1064 unsigned char* valPtr; 1065 1066 ldapValue->bv_len=0; 1067 ldapValue->bv_val=NULL; 1068 1069 /* Gets padding and points to binary data */ 1070 valLen=berValue->bv_len; 1071 valPtr=(unsigned char*)berValue->bv_val; 1072 if (valLen) { 1073 bitPadding=(ber_len_t)(valPtr[0]); 1074 valLen--; 1075 valPtr++; 1076 } 1077 /* If Block is non DER encoding fixes to DER encoding */ 1078 if (bitPadding >= BITS_PER_BYTE) { 1079 if (valLen*BITS_PER_BYTE > bitPadding ) { 1080 valLen-=(bitPadding/BITS_PER_BYTE); 1081 bitPadding%=BITS_PER_BYTE; 1082 } else { 1083 valLen=0; 1084 bitPadding=0; 1085 } 1086 } 1087 /* Just in case bad encoding */ 1088 if (valLen*BITS_PER_BYTE < bitPadding ) { 1089 bitPadding=0; 1090 valLen=0; 1091 } 1092 1093 /* Gets buffer to hold RFC4517 Bit String format */ 1094 bitLength=valLen*BITS_PER_BYTE-bitPadding; 1095 tmpStr=LDAP_MALLOC(bitLength + STR_OVERHEAD + 1); 1096 1097 if (!tmpStr) 1098 return LDAP_NO_MEMORY; 1099 1100 ldapValue->bv_val=tmpStr; 1101 ldapValue->bv_len=bitLength + STR_OVERHEAD; 1102 1103 /* Formatting in '*binary-digit'B format */ 1104 maxBits=BITS_PER_BYTE; 1105 *tmpStr++ ='\''; 1106 while(valLen) { 1107 byte=*valPtr; 1108 if (valLen==1) 1109 maxBits-=bitPadding; 1110 for (bits=0; bits<maxBits; bits++) { 1111 if (0x80 & byte) 1112 *tmpStr='1'; 1113 else 1114 *tmpStr='0'; 1115 tmpStr++; 1116 byte<<=1; 1117 } 1118 valPtr++; 1119 valLen--; 1120 } 1121 *tmpStr++ ='\''; 1122 *tmpStr++ ='B'; 1123 *tmpStr=0; 1124 1125 return LDAP_SUCCESS; 1126} 1127 1128/* Convert a structured DN from an X.509 certificate into an LDAPV3 DN. 1129 * x509_name must be raw DER. If func is non-NULL, the 1130 * constructed DN will use numeric OIDs to identify attributeTypes, 1131 * and the func() will be invoked to rewrite the DN with the given 1132 * flags. 1133 * 1134 * Otherwise the DN will use shortNames from a hardcoded table. 1135 */ 1136int 1137ldap_X509dn2bv( void *x509_name, struct berval *bv, LDAPDN_rewrite_func *func, 1138 unsigned flags ) 1139{ 1140 LDAPDN newDN; 1141 LDAPRDN newRDN; 1142 LDAPAVA *newAVA, *baseAVA; 1143 BerElementBuffer berbuf; 1144 BerElement *ber = (BerElement *)&berbuf; 1145 char oids[8192], *oidptr = oids, *oidbuf = NULL; 1146 void *ptrs[2048]; 1147 char *dn_end, *rdn_end; 1148 int i, navas, nrdns, rc = LDAP_SUCCESS; 1149 size_t dnsize, oidrem = sizeof(oids), oidsize = 0; 1150 int csize; 1151 ber_tag_t tag; 1152 ber_len_t len; 1153 oid_name *oidname; 1154 1155 struct berval Oid, Val, oid2, *in = x509_name; 1156 1157 assert( bv != NULL ); 1158 1159 bv->bv_len = 0; 1160 bv->bv_val = NULL; 1161 1162 navas = 0; 1163 nrdns = 0; 1164 1165 /* A DN is a SEQUENCE of RDNs. An RDN is a SET of AVAs. 1166 * An AVA is a SEQUENCE of attr and value. 1167 * Count the number of AVAs and RDNs 1168 */ 1169 ber_init2( ber, in, LBER_USE_DER ); 1170 tag = ber_peek_tag( ber, &len ); 1171 if ( tag != LBER_SEQUENCE ) 1172 return LDAP_DECODING_ERROR; 1173 1174 for ( tag = ber_first_element( ber, &len, &dn_end ); 1175 tag == LBER_SET; 1176 tag = ber_next_element( ber, &len, dn_end )) { 1177 nrdns++; 1178 for ( tag = ber_first_element( ber, &len, &rdn_end ); 1179 tag == LBER_SEQUENCE; 1180 tag = ber_next_element( ber, &len, rdn_end )) { 1181 tag = ber_skip_tag( ber, &len ); 1182 ber_skip_data( ber, len ); 1183 navas++; 1184 } 1185 } 1186 1187 /* Allocate the DN/RDN/AVA stuff as a single block */ 1188 dnsize = sizeof(LDAPRDN) * (nrdns+1); 1189 dnsize += sizeof(LDAPAVA *) * (navas+nrdns); 1190 dnsize += sizeof(LDAPAVA) * navas; 1191 if (dnsize > sizeof(ptrs)) { 1192 newDN = (LDAPDN)LDAP_MALLOC( dnsize ); 1193 if ( newDN == NULL ) 1194 return LDAP_NO_MEMORY; 1195 } else { 1196 newDN = (LDAPDN)(char *)ptrs; 1197 } 1198 1199 newDN[nrdns] = NULL; 1200 newRDN = (LDAPRDN)(newDN + nrdns+1); 1201 newAVA = (LDAPAVA *)(newRDN + navas + nrdns); 1202 baseAVA = newAVA; 1203 1204 /* Rewind and start extracting */ 1205 ber_rewind( ber ); 1206 1207 tag = ber_first_element( ber, &len, &dn_end ); 1208 for ( i = nrdns - 1; i >= 0; i-- ) { 1209 newDN[i] = newRDN; 1210 1211 for ( tag = ber_first_element( ber, &len, &rdn_end ); 1212 tag == LBER_SEQUENCE; 1213 tag = ber_next_element( ber, &len, rdn_end )) { 1214 1215 *newRDN++ = newAVA; 1216 tag = ber_skip_tag( ber, &len ); 1217 tag = ber_get_stringbv( ber, &Oid, LBER_BV_NOTERM ); 1218 if ( tag != LBER_TAG_OID ) { 1219 rc = LDAP_DECODING_ERROR; 1220 goto nomem; 1221 } 1222 1223 oid2.bv_val = oidptr; 1224 oid2.bv_len = oidrem; 1225 if ( ber_decode_oid( &Oid, &oid2 ) < 0 ) { 1226 rc = LDAP_DECODING_ERROR; 1227 goto nomem; 1228 } 1229 oidname = find_oid( &oid2 ); 1230 if ( !oidname ) { 1231 newAVA->la_attr = oid2; 1232 oidptr += oid2.bv_len + 1; 1233 oidrem -= oid2.bv_len + 1; 1234 1235 /* Running out of OID buffer space? */ 1236 if (oidrem < 128) { 1237 if ( oidsize == 0 ) { 1238 oidsize = sizeof(oids) * 2; 1239 oidrem = oidsize; 1240 oidbuf = LDAP_MALLOC( oidsize ); 1241 if ( oidbuf == NULL ) goto nomem; 1242 oidptr = oidbuf; 1243 } else { 1244 char *old = oidbuf; 1245 oidbuf = LDAP_REALLOC( oidbuf, oidsize*2 ); 1246 if ( oidbuf == NULL ) goto nomem; 1247 /* Buffer moved! Fix AVA pointers */ 1248 if ( old != oidbuf ) { 1249 LDAPAVA *a; 1250 long dif = oidbuf - old; 1251 1252 for (a=baseAVA; a<=newAVA; a++){ 1253 if (a->la_attr.bv_val >= old && 1254 a->la_attr.bv_val <= (old + oidsize)) 1255 a->la_attr.bv_val += dif; 1256 } 1257 } 1258 oidptr = oidbuf + oidsize - oidrem; 1259 oidrem += oidsize; 1260 oidsize *= 2; 1261 } 1262 } 1263 } else { 1264 if ( func ) { 1265 newAVA->la_attr = oidname->oid; 1266 } else { 1267 newAVA->la_attr = oidname->name; 1268 } 1269 } 1270 newAVA->la_private = NULL; 1271 newAVA->la_flags = LDAP_AVA_STRING; 1272 tag = ber_get_stringbv( ber, &Val, LBER_BV_NOTERM ); 1273 switch(tag) { 1274 case LBER_TAG_UNIVERSAL: 1275 /* This uses 32-bit ISO 10646-1 */ 1276 csize = 4; goto to_utf8; 1277 case LBER_TAG_BMP: 1278 /* This uses 16-bit ISO 10646-1 */ 1279 csize = 2; goto to_utf8; 1280 case LBER_TAG_TELETEX: 1281 /* This uses 8-bit, assume ISO 8859-1 */ 1282 csize = 1; 1283to_utf8: rc = ldap_ucs_to_utf8s( &Val, csize, &newAVA->la_value ); 1284 newAVA->la_flags |= LDAP_AVA_NONPRINTABLE; 1285allocd: 1286 newAVA->la_flags |= LDAP_AVA_FREE_VALUE; 1287 if (rc != LDAP_SUCCESS) goto nomem; 1288 break; 1289 case LBER_TAG_UTF8: 1290 newAVA->la_flags |= LDAP_AVA_NONPRINTABLE; 1291 /* This is already in UTF-8 encoding */ 1292 case LBER_TAG_IA5: 1293 case LBER_TAG_PRINTABLE: 1294 /* These are always 7-bit strings */ 1295 newAVA->la_value = Val; 1296 break; 1297 case LBER_BITSTRING: 1298 /* X.690 bitString value converted to RFC4517 Bit String */ 1299 rc = der_to_ldap_BitString( &Val, &newAVA->la_value ); 1300 goto allocd; 1301 default: 1302 /* Not a string type at all */ 1303 newAVA->la_flags = 0; 1304 newAVA->la_value = Val; 1305 break; 1306 } 1307 newAVA++; 1308 } 1309 *newRDN++ = NULL; 1310 tag = ber_next_element( ber, &len, dn_end ); 1311 } 1312 1313 if ( func ) { 1314 rc = func( newDN, flags, NULL ); 1315 if ( rc != LDAP_SUCCESS ) 1316 goto nomem; 1317 } 1318 1319 rc = ldap_dn2bv_x( newDN, bv, LDAP_DN_FORMAT_LDAPV3, NULL ); 1320 1321nomem: 1322 for (;baseAVA < newAVA; baseAVA++) { 1323 if (baseAVA->la_flags & LDAP_AVA_FREE_ATTR) 1324 LDAP_FREE( baseAVA->la_attr.bv_val ); 1325 if (baseAVA->la_flags & LDAP_AVA_FREE_VALUE) 1326 LDAP_FREE( baseAVA->la_value.bv_val ); 1327 } 1328 1329 if ( oidsize != 0 ) 1330 LDAP_FREE( oidbuf ); 1331 if ( newDN != (LDAPDN)(char *) ptrs ) 1332 LDAP_FREE( newDN ); 1333 return rc; 1334} 1335 1336#ifdef HAVE_TLS 1337#ifdef __APPLE__ 1338 1339#define SYSTEM_KEYCHAIN_PATH "/Library/Keychains/System.keychain" 1340static void 1341tls_get_cert_from_keychain( char *host ) 1342{ 1343 /* Cert info is kept in the global options. */ 1344 struct ldapoptions *lo = LDAP_INT_GLOBAL_OPT(); 1345 if ( !lo ) return; 1346 1347 /* If the server identity option is set, don't need to do anything 1348 * as the certificate will get set in the SSL context during context 1349 * initialization. 1350 */ 1351 if (lo->ldo_tls_server_ident_ref_name) { 1352 return; 1353 } 1354 1355 /* If the cert is set in the options, don't override it. */ 1356 if ( lo->ldo_tls_cacertfile || lo->ldo_tls_certfile ) { 1357 Debug( LDAP_DEBUG_ANY, 1358 "TLS: not reading certificate from keychain, option %s is set\n", 1359 lo->ldo_tls_cacertfile ? "cacertfile" : "certfile", 0, 0 ); 1360 1361 return; 1362 } 1363 1364 SecKeychainRef keychainRef = NULL; 1365 OSStatus status = SecKeychainOpen( SYSTEM_KEYCHAIN_PATH, &keychainRef ); 1366 if ( status != errSecSuccess ) { 1367 Debug( LDAP_DEBUG_ANY, "TLS: SecKeychainOpen failed for keychain %s: %d", 1368 SYSTEM_KEYCHAIN_PATH, (int)status, 0 ); 1369 syslog( LOG_ERR, "TLS: SecKeychainOpen failed for keychain %s: %d", 1370 SYSTEM_KEYCHAIN_PATH, (int)status, 0 ); 1371 cssmPerror( "SecKeychainOpen", status ); 1372 return; 1373 } 1374 1375 SecKeychainSearchRef searchRef = NULL; 1376 status = SecKeychainSearchCreateFromAttributes( keychainRef, kSecCertificateItemClass, NULL, &searchRef ); 1377 if ( status != errSecSuccess ) { 1378 Debug( LDAP_DEBUG_ANY, "TLS: SecKeychainSearchCreateFromAttributes failed: %d", 1379 (int)status, 0, 0 ); 1380 syslog( LOG_ERR, "TLS: SecKeychainSearchCreateFromAttributes failed: %d", (int)status ); 1381 cssmPerror( "SecKeychainSearchCreateFromAttributes", status ); 1382 } 1383 1384 while ( status == errSecSuccess ) { 1385 1386 SecCertificateRef certificateRef = NULL; 1387 status = SecKeychainSearchCopyNext( searchRef, (SecKeychainItemRef*)&certificateRef ); 1388 1389 /* Bail on any error. */ 1390 if ( status != errSecSuccess ) { 1391 /* Only complain if the error is something other than 1392 * the normal search end. 1393 */ 1394 if ( status != errSecItemNotFound ) { 1395 Debug( LDAP_DEBUG_ANY, "TLS: SecKeychainSearchCopyNext failed: %d", 1396 (int)status, 0, 0 ); 1397 syslog( LOG_ERR, "SecKeychainSearchCopyNext failed: %d", (int)status ); 1398 cssmPerror( "SecKeychainSearchCopyNext", status ); 1399 } 1400 break; 1401 } 1402 1403 /* Extract the name from the certificate. Will check against the host 1404 * name passed in. 1405 */ 1406 CFStringRef commonName = NULL; 1407 status = SecCertificateCopyCommonName( certificateRef, &commonName ); 1408 if ( status != errSecSuccess || !commonName ) { 1409 Debug( LDAP_DEBUG_ANY, "TLS: SecCertificateCopyCommonName failed: %d", 1410 (int)status, 0, 0 ); 1411 cssmPerror( "SecCertificateCopyCommonName", status ); 1412 1413 /* Reset 'status' to allow the loop to continue. No need to 1414 * stop just because we can't get the name from one of the 1415 * certs. 1416 */ 1417 status = errSecSuccess; 1418 } 1419 else { 1420 /* If the common name in the certificate matches the host name, save 1421 * the certificate reference in the options data for later use. 1422 */ 1423 char commonNameCStr[PATH_MAX]; 1424 if ( !CFStringGetCString( commonName, 1425 commonNameCStr, 1426 sizeof(commonNameCStr), 1427 kCFStringEncodingUTF8 ) ) 1428 { 1429 Debug( LDAP_DEBUG_ANY, 1430 "TLS: Unable to convert certificate common name CFString into C String", 1431 0, 0, 0); 1432 } 1433 CFRelease( commonName ); 1434 1435 if ( commonNameCStr && strcmp( commonNameCStr, host ) == 0 ) { 1436 if ( lo->ldo_tls_cert_ref ) { 1437 CFRelease( lo->ldo_tls_cert_ref ); 1438 } 1439 1440 lo->ldo_tls_cert_ref = certificateRef; 1441 status = !errSecSuccess; /* cert found - terminate the loop */ 1442 } 1443 } 1444 1445 /* Only release the ref if we don't care about it. Refs we care 1446 * about get released later (when the connection is closed). 1447 */ 1448 if ( lo->ldo_tls_cert_ref != certificateRef ) { 1449 CFRelease( certificateRef ); 1450 } 1451 } 1452 1453 if ( searchRef ) { 1454 CFRelease( searchRef ); 1455 } 1456 1457 CFRelease( keychainRef ); 1458 1459 Debug( LDAP_DEBUG_ANY, 1460 "TLS: %s certificate in keychain for host \"%s\"\n", 1461 lo->ldo_tls_cert_ref ? "found" : "did not find", host, 0 ); 1462} 1463 1464#endif /* __APPLE__ */ 1465#endif /* HAVE_TLS */ 1466 1467