apr_ldap_option.c revision 272461
190792Sgshapiro/* Licensed to the Apache Software Foundation (ASF) under one or more 290792Sgshapiro * contributor license agreements. See the NOTICE file distributed with 390792Sgshapiro * this work for additional information regarding copyright ownership. 490792Sgshapiro * The ASF licenses this file to You under the Apache License, Version 2.0 590792Sgshapiro * (the "License"); you may not use this file except in compliance with 690792Sgshapiro * the License. You may obtain a copy of the License at 790792Sgshapiro * 890792Sgshapiro * http://www.apache.org/licenses/LICENSE-2.0 990792Sgshapiro * 1090792Sgshapiro * Unless required by applicable law or agreed to in writing, software 1198121Sgshapiro * distributed under the License is distributed on an "AS IS" BASIS, 1290792Sgshapiro * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1390792Sgshapiro * See the License for the specific language governing permissions and 1490792Sgshapiro * limitations under the License. 1590792Sgshapiro */ 1690792Sgshapiro 1790792Sgshapiro/* apr_ldap_option.c -- LDAP options 1890792Sgshapiro * 1990792Sgshapiro * The LDAP SDK allows the getting and setting of options on an LDAP 2090792Sgshapiro * connection. 2190792Sgshapiro * 2290792Sgshapiro */ 2390792Sgshapiro 2490792Sgshapiro#include "apr.h" 2590792Sgshapiro#include "apu.h" 2690792Sgshapiro#include "apu_config.h" 2790792Sgshapiro 2890792Sgshapiro#if APU_DSO_BUILD 2990792Sgshapiro#define APU_DSO_LDAP_BUILD 3090792Sgshapiro#endif 3190792Sgshapiro 3290792Sgshapiro#include "apr_ldap.h" 3390792Sgshapiro#include "apr_errno.h" 3490792Sgshapiro#include "apr_pools.h" 3590792Sgshapiro#include "apr_strings.h" 3690792Sgshapiro#include "apr_tables.h" 3790792Sgshapiro 3890792Sgshapiro#if APR_HAS_LDAP 3990792Sgshapiro 4090792Sgshapirostatic void option_set_cert(apr_pool_t *pool, LDAP *ldap, const void *invalue, 4190792Sgshapiro apr_ldap_err_t *result); 4290792Sgshapirostatic void option_set_tls(apr_pool_t *pool, LDAP *ldap, const void *invalue, 4390792Sgshapiro apr_ldap_err_t *result); 4490792Sgshapiro 4590792Sgshapiro/** 4690792Sgshapiro * APR LDAP get option function 4790792Sgshapiro * 4890792Sgshapiro * This function gets option values from a given LDAP session if 4990792Sgshapiro * one was specified. 5090792Sgshapiro */ 5190792SgshapiroAPU_DECLARE_LDAP(int) apr_ldap_get_option(apr_pool_t *pool, 5290792Sgshapiro LDAP *ldap, 5390792Sgshapiro int option, 5490792Sgshapiro void *outvalue, 5590792Sgshapiro apr_ldap_err_t **result_err) 5690792Sgshapiro{ 5790792Sgshapiro apr_ldap_err_t *result; 5890792Sgshapiro 5990792Sgshapiro result = apr_pcalloc(pool, sizeof(apr_ldap_err_t)); 6090792Sgshapiro *result_err = result; 6190792Sgshapiro if (!result) { 6290792Sgshapiro return APR_ENOMEM; 6390792Sgshapiro } 6490792Sgshapiro 6590792Sgshapiro /* get the option specified using the native LDAP function */ 6690792Sgshapiro result->rc = ldap_get_option(ldap, option, outvalue); 6790792Sgshapiro 6890792Sgshapiro /* handle the error case */ 6990792Sgshapiro if (result->rc != LDAP_SUCCESS) { 7090792Sgshapiro result->msg = ldap_err2string(result-> rc); 7190792Sgshapiro result->reason = apr_pstrdup(pool, "LDAP: Could not get an option"); 7290792Sgshapiro return APR_EGENERAL; 7390792Sgshapiro } 7490792Sgshapiro 7590792Sgshapiro return APR_SUCCESS; 7690792Sgshapiro 7790792Sgshapiro} 7890792Sgshapiro 7990792Sgshapiro/** 8090792Sgshapiro * APR LDAP set option function 8190792Sgshapiro * 8290792Sgshapiro * This function sets option values to a given LDAP session if 8390792Sgshapiro * one was specified. 8490792Sgshapiro * 8590792Sgshapiro * Where an option is not supported by an LDAP toolkit, this function 8690792Sgshapiro * will try and apply legacy functions to achieve the same effect, 8790792Sgshapiro * depending on the platform. 8890792Sgshapiro */ 8990792SgshapiroAPU_DECLARE_LDAP(int) apr_ldap_set_option(apr_pool_t *pool, 9090792Sgshapiro LDAP *ldap, 9190792Sgshapiro int option, 9290792Sgshapiro const void *invalue, 9390792Sgshapiro apr_ldap_err_t **result_err) 9490792Sgshapiro{ 9590792Sgshapiro apr_ldap_err_t *result; 9690792Sgshapiro 9790792Sgshapiro result = apr_pcalloc(pool, sizeof(apr_ldap_err_t)); 9890792Sgshapiro *result_err = result; 9990792Sgshapiro if (!result) { 10090792Sgshapiro return APR_ENOMEM; 10190792Sgshapiro } 10290792Sgshapiro 10390792Sgshapiro switch (option) { 10490792Sgshapiro case APR_LDAP_OPT_TLS_CERT: 10590792Sgshapiro option_set_cert(pool, ldap, invalue, result); 10690792Sgshapiro break; 10790792Sgshapiro 10890792Sgshapiro case APR_LDAP_OPT_TLS: 10990792Sgshapiro option_set_tls(pool, ldap, invalue, result); 11090792Sgshapiro break; 11190792Sgshapiro 11290792Sgshapiro case APR_LDAP_OPT_VERIFY_CERT: 11390792Sgshapiro#if APR_HAS_NETSCAPE_LDAPSDK || APR_HAS_SOLARIS_LDAPSDK || APR_HAS_MOZILLA_LDAPSK 11490792Sgshapiro result->reason = "LDAP: Verify certificate not yet supported by APR on the " 11590792Sgshapiro "Netscape, Solaris or Mozilla LDAP SDKs"; 11690792Sgshapiro result->rc = -1; 11790792Sgshapiro return APR_EGENERAL; 11890792Sgshapiro#endif 11990792Sgshapiro#if APR_HAS_NOVELL_LDAPSDK 12090792Sgshapiro if (*((int*)invalue)) { 12190792Sgshapiro result->rc = ldapssl_set_verify_mode(LDAPSSL_VERIFY_SERVER); 12290792Sgshapiro } 12390792Sgshapiro else { 12490792Sgshapiro result->rc = ldapssl_set_verify_mode(LDAPSSL_VERIFY_NONE); 12590792Sgshapiro } 12690792Sgshapiro#endif 12790792Sgshapiro#if APR_HAS_OPENLDAP_LDAPSDK 12890792Sgshapiro#ifdef LDAP_OPT_X_TLS 12990792Sgshapiro /* This is not a per-connection setting so just pass NULL for the 13090792Sgshapiro Ldap connection handle */ 13190792Sgshapiro if (*((int*)invalue)) { 13290792Sgshapiro int i = LDAP_OPT_X_TLS_DEMAND; 13390792Sgshapiro result->rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &i); 13490792Sgshapiro } 13590792Sgshapiro else { 13690792Sgshapiro int i = LDAP_OPT_X_TLS_NEVER; 13790792Sgshapiro result->rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &i); 13890792Sgshapiro } 13990792Sgshapiro#else 14090792Sgshapiro result->reason = "LDAP: SSL/TLS not yet supported by APR on this " 14190792Sgshapiro "version of the OpenLDAP toolkit"; 14290792Sgshapiro result->rc = -1; 14390792Sgshapiro return APR_EGENERAL; 14490792Sgshapiro#endif 14590792Sgshapiro#endif 14690792Sgshapiro 14790792Sgshapiro /* handle the error case */ 14890792Sgshapiro if (result->rc != LDAP_SUCCESS) { 14990792Sgshapiro result->msg = ldap_err2string(result->rc); 15090792Sgshapiro result->reason = "LDAP: Could not set verify mode"; 15190792Sgshapiro } 15290792Sgshapiro break; 15390792Sgshapiro 15490792Sgshapiro case APR_LDAP_OPT_REFERRALS: 15590792Sgshapiro /* Setting this option is supported on at least TIVOLI_SDK and OpenLDAP. Folks 156 * who know the NOVELL, NETSCAPE, MOZILLA, and SOLARIS SDKs should note here if 157 * the SDK at least tolerates this option being set, or add an elif to handle 158 * special cases (i.e. different LDAP_OPT_X value). 159 */ 160 result->rc = ldap_set_option(ldap, LDAP_OPT_REFERRALS, (void *)invalue); 161 162 if (result->rc != LDAP_SUCCESS) { 163 result->reason = "Unable to set LDAP_OPT_REFERRALS."; 164 return(result->rc); 165 } 166 break; 167 168 case APR_LDAP_OPT_REFHOPLIMIT: 169#if !defined(LDAP_OPT_REFHOPLIMIT) || APR_HAS_NOVELL_LDAPSDK 170 /* If the LDAP_OPT_REFHOPLIMIT symbol is missing, assume that the 171 * particular LDAP library has a reasonable default. So far certain 172 * versions of the OpenLDAP SDK miss this symbol (but default to 5), 173 * and the Microsoft SDK misses the symbol (the default is not known). 174 */ 175 result->rc = LDAP_SUCCESS; 176#else 177 /* Setting this option is supported on at least TIVOLI_SDK. Folks who know 178 * the NOVELL, NETSCAPE, MOZILLA, and SOLARIS SDKs should note here if 179 * the SDK at least tolerates this option being set, or add an elif to handle 180 * special cases so an error isn't returned if there is a perfectly good 181 * default value that just can't be changed (like openLDAP). 182 */ 183 result->rc = ldap_set_option(ldap, LDAP_OPT_REFHOPLIMIT, (void *)invalue); 184#endif 185 186 if (result->rc != LDAP_SUCCESS) { 187 result->reason = "Unable to set LDAP_OPT_REFHOPLIMIT."; 188 return(result->rc); 189 } 190 break; 191 192 default: 193 /* set the option specified using the native LDAP function */ 194 result->rc = ldap_set_option(ldap, option, (void *)invalue); 195 196 /* handle the error case */ 197 if (result->rc != LDAP_SUCCESS) { 198 result->msg = ldap_err2string(result->rc); 199 result->reason = "LDAP: Could not set an option"; 200 } 201 break; 202 } 203 204 /* handle the error case */ 205 if (result->rc != LDAP_SUCCESS) { 206 return APR_EGENERAL; 207 } 208 209 return APR_SUCCESS; 210 211} 212 213/** 214 * Handle APR_LDAP_OPT_TLS 215 * 216 * This function sets the type of TLS to be applied to this connection. 217 * The options are: 218 * APR_LDAP_NONE: no encryption 219 * APR_LDAP_SSL: SSL encryption (ldaps://) 220 * APR_LDAP_STARTTLS: STARTTLS encryption 221 * APR_LDAP_STOPTLS: Stop existing TLS connecttion 222 */ 223static void option_set_tls(apr_pool_t *pool, LDAP *ldap, const void *invalue, 224 apr_ldap_err_t *result) 225{ 226#if APR_HAS_LDAP_SSL /* compiled with ssl support */ 227 228 int tls = * (const int *)invalue; 229 230 /* Netscape/Mozilla/Solaris SDK */ 231#if APR_HAS_NETSCAPE_LDAPSDK || APR_HAS_SOLARIS_LDAPSDK || APR_HAS_MOZILLA_LDAPSK 232#if APR_HAS_LDAPSSL_INSTALL_ROUTINES 233 if (tls == APR_LDAP_SSL) { 234 result->rc = ldapssl_install_routines(ldap); 235#ifdef LDAP_OPT_SSL 236 /* apparently Netscape and Mozilla need this too, Solaris doesn't */ 237 if (result->rc == LDAP_SUCCESS) { 238 result->rc = ldap_set_option(ldap, LDAP_OPT_SSL, LDAP_OPT_ON); 239 } 240#endif 241 if (result->rc != LDAP_SUCCESS) { 242 result->msg = ldap_err2string(result->rc); 243 result->reason = "LDAP: Could not switch SSL on for this " 244 "connection."; 245 } 246 } 247 else if (tls == APR_LDAP_STARTTLS) { 248 result->reason = "LDAP: STARTTLS is not supported by the " 249 "Netscape/Mozilla/Solaris SDK"; 250 result->rc = -1; 251 } 252 else if (tls == APR_LDAP_STOPTLS) { 253 result->reason = "LDAP: STOPTLS is not supported by the " 254 "Netscape/Mozilla/Solaris SDK"; 255 result->rc = -1; 256 } 257#else 258 if (tls != APR_LDAP_NONE) { 259 result->reason = "LDAP: SSL/TLS is not supported by this version " 260 "of the Netscape/Mozilla/Solaris SDK"; 261 result->rc = -1; 262 } 263#endif 264#endif 265 266 /* Novell SDK */ 267#if APR_HAS_NOVELL_LDAPSDK 268 /* ldapssl_install_routines(ldap) 269 * Behavior is unpredictable when other LDAP functions are called 270 * between the ldap_init function and the ldapssl_install_routines 271 * function. 272 * 273 * STARTTLS is supported by the ldap_start_tls_s() method 274 */ 275 if (tls == APR_LDAP_SSL) { 276 result->rc = ldapssl_install_routines(ldap); 277 if (result->rc != LDAP_SUCCESS) { 278 result->msg = ldap_err2string(result->rc); 279 result->reason = "LDAP: Could not switch SSL on for this " 280 "connection."; 281 } 282 } 283 if (tls == APR_LDAP_STARTTLS) { 284 result->rc = ldapssl_start_tls(ldap); 285 if (result->rc != LDAP_SUCCESS) { 286 result->msg = ldap_err2string(result->rc); 287 result->reason = "LDAP: Could not start TLS on this connection"; 288 } 289 } 290 else if (tls == APR_LDAP_STOPTLS) { 291 result->rc = ldapssl_stop_tls(ldap); 292 if (result->rc != LDAP_SUCCESS) { 293 result->msg = ldap_err2string(result->rc); 294 result->reason = "LDAP: Could not stop TLS on this connection"; 295 } 296 } 297#endif 298 299 /* OpenLDAP SDK */ 300#if APR_HAS_OPENLDAP_LDAPSDK 301#ifdef LDAP_OPT_X_TLS 302 if (tls == APR_LDAP_SSL) { 303 int SSLmode = LDAP_OPT_X_TLS_HARD; 304 result->rc = ldap_set_option(ldap, LDAP_OPT_X_TLS, &SSLmode); 305 if (result->rc != LDAP_SUCCESS) { 306 result->reason = "LDAP: ldap_set_option failed. " 307 "Could not set LDAP_OPT_X_TLS to " 308 "LDAP_OPT_X_TLS_HARD"; 309 result->msg = ldap_err2string(result->rc); 310 } 311 } 312 else if (tls == APR_LDAP_STARTTLS) { 313 result->rc = ldap_start_tls_s(ldap, NULL, NULL); 314 if (result->rc != LDAP_SUCCESS) { 315 result->reason = "LDAP: ldap_start_tls_s() failed"; 316 result->msg = ldap_err2string(result->rc); 317 } 318 } 319 else if (tls == APR_LDAP_STOPTLS) { 320 result->reason = "LDAP: STOPTLS is not supported by the " 321 "OpenLDAP SDK"; 322 result->rc = -1; 323 } 324#else 325 if (tls != APR_LDAP_NONE) { 326 result->reason = "LDAP: SSL/TLS not yet supported by APR on this " 327 "version of the OpenLDAP toolkit"; 328 result->rc = -1; 329 } 330#endif 331#endif 332 333 /* Microsoft SDK */ 334#if APR_HAS_MICROSOFT_LDAPSDK 335 if (tls == APR_LDAP_NONE) { 336 ULONG ul = (ULONG) LDAP_OPT_OFF; 337 result->rc = ldap_set_option(ldap, LDAP_OPT_SSL, &ul); 338 if (result->rc != LDAP_SUCCESS) { 339 result->reason = "LDAP: an attempt to set LDAP_OPT_SSL off " 340 "failed."; 341 result->msg = ldap_err2string(result->rc); 342 } 343 } 344 else if (tls == APR_LDAP_SSL) { 345 ULONG ul = (ULONG) LDAP_OPT_ON; 346 result->rc = ldap_set_option(ldap, LDAP_OPT_SSL, &ul); 347 if (result->rc != LDAP_SUCCESS) { 348 result->reason = "LDAP: an attempt to set LDAP_OPT_SSL on " 349 "failed."; 350 result->msg = ldap_err2string(result->rc); 351 } 352 } 353#if APR_HAS_LDAP_START_TLS_S 354 else if (tls == APR_LDAP_STARTTLS) { 355 result->rc = ldap_start_tls_s(ldap, NULL, NULL, NULL, NULL); 356 if (result->rc != LDAP_SUCCESS) { 357 result->reason = "LDAP: ldap_start_tls_s() failed"; 358 result->msg = ldap_err2string(result->rc); 359 } 360 } 361 else if (tls == APR_LDAP_STOPTLS) { 362 result->rc = ldap_stop_tls_s(ldap); 363 if (result->rc != LDAP_SUCCESS) { 364 result->reason = "LDAP: ldap_stop_tls_s() failed"; 365 result->msg = ldap_err2string(result->rc); 366 } 367 } 368#endif 369#endif 370 371#if APR_HAS_OTHER_LDAPSDK 372 if (tls != APR_LDAP_NONE) { 373 result->reason = "LDAP: SSL/TLS is currently not supported by " 374 "APR on this LDAP SDK"; 375 result->rc = -1; 376 } 377#endif 378 379#endif /* APR_HAS_LDAP_SSL */ 380 381} 382 383/** 384 * Handle APR_LDAP_OPT_TLS_CACERTFILE 385 * 386 * This function sets the CA certificate for further SSL/TLS connections. 387 * 388 * The file provided are in different formats depending on the toolkit used: 389 * 390 * Netscape: cert7.db file 391 * Novell: PEM or DER 392 * OpenLDAP: PEM (others supported?) 393 * Microsoft: unknown 394 * Solaris: unknown 395 */ 396static void option_set_cert(apr_pool_t *pool, LDAP *ldap, 397 const void *invalue, apr_ldap_err_t *result) 398{ 399#if APR_HAS_LDAP_SSL 400#if APR_HAS_LDAPSSL_CLIENT_INIT || APR_HAS_OPENLDAP_LDAPSDK 401 apr_array_header_t *certs = (apr_array_header_t *)invalue; 402 struct apr_ldap_opt_tls_cert_t *ents = (struct apr_ldap_opt_tls_cert_t *)certs->elts; 403 int i = 0; 404#endif 405 406 /* Netscape/Mozilla/Solaris SDK */ 407#if APR_HAS_NETSCAPE_LDAPSDK || APR_HAS_SOLARIS_LDAPSDK || APR_HAS_MOZILLA_LDAPSDK 408#if APR_HAS_LDAPSSL_CLIENT_INIT 409 const char *nickname = NULL; 410 const char *secmod = NULL; 411 const char *key3db = NULL; 412 const char *cert7db = NULL; 413 const char *password = NULL; 414 415 /* set up cert7.db, key3.db and secmod parameters */ 416 for (i = 0; i < certs->nelts; i++) { 417 switch (ents[i].type) { 418 case APR_LDAP_CA_TYPE_CERT7_DB: 419 cert7db = ents[i].path; 420 break; 421 case APR_LDAP_CA_TYPE_SECMOD: 422 secmod = ents[i].path; 423 break; 424 case APR_LDAP_CERT_TYPE_KEY3_DB: 425 key3db = ents[i].path; 426 break; 427 case APR_LDAP_CERT_TYPE_NICKNAME: 428 nickname = ents[i].path; 429 password = ents[i].password; 430 break; 431 default: 432 result->rc = -1; 433 result->reason = "LDAP: The Netscape/Mozilla LDAP SDK only " 434 "understands the CERT7, KEY3 and SECMOD " 435 "file types."; 436 break; 437 } 438 if (result->rc != LDAP_SUCCESS) { 439 break; 440 } 441 } 442 443 /* actually set the certificate parameters */ 444 if (result->rc == LDAP_SUCCESS) { 445 if (nickname) { 446 result->rc = ldapssl_enable_clientauth(ldap, "", 447 (char *)password, 448 (char *)nickname); 449 if (result->rc != LDAP_SUCCESS) { 450 result->reason = "LDAP: could not set client certificate: " 451 "ldapssl_enable_clientauth() failed."; 452 result->msg = ldap_err2string(result->rc); 453 } 454 } 455 else if (secmod) { 456 result->rc = ldapssl_advclientauth_init(cert7db, NULL, 457 key3db ? 1 : 0, key3db, NULL, 458 1, secmod, LDAPSSL_AUTH_CNCHECK); 459 if (result->rc != LDAP_SUCCESS) { 460 result->reason = "LDAP: ldapssl_advclientauth_init() failed."; 461 result->msg = ldap_err2string(result->rc); 462 } 463 } 464 else if (key3db) { 465 result->rc = ldapssl_clientauth_init(cert7db, NULL, 466 1, key3db, NULL); 467 if (result->rc != LDAP_SUCCESS) { 468 result->reason = "LDAP: ldapssl_clientauth_init() failed."; 469 result->msg = ldap_err2string(result->rc); 470 } 471 } 472 else { 473 result->rc = ldapssl_client_init(cert7db, NULL); 474 if (result->rc != LDAP_SUCCESS) { 475 result->reason = "LDAP: ldapssl_client_init() failed."; 476 result->msg = ldap_err2string(result->rc); 477 } 478 } 479 } 480#else 481 result->reason = "LDAP: SSL/TLS ldapssl_client_init() function not " 482 "supported by this Netscape/Mozilla/Solaris SDK. " 483 "Certificate authority file not set"; 484 result->rc = -1; 485#endif 486#endif 487 488 /* Novell SDK */ 489#if APR_HAS_NOVELL_LDAPSDK 490#if APR_HAS_LDAPSSL_CLIENT_INIT && APR_HAS_LDAPSSL_ADD_TRUSTED_CERT && APR_HAS_LDAPSSL_CLIENT_DEINIT 491 /* The Novell library cannot support per connection certificates. Error 492 * out if the ldap handle is provided. 493 */ 494 if (ldap) { 495 result->rc = -1; 496 result->reason = "LDAP: The Novell LDAP SDK cannot support the setting " 497 "of certificates or keys on a per connection basis."; 498 } 499 /* Novell's library needs to be initialised first */ 500 else { 501 result->rc = ldapssl_client_init(NULL, NULL); 502 if (result->rc != LDAP_SUCCESS) { 503 result->msg = ldap_err2string(result-> rc); 504 result->reason = apr_pstrdup(pool, "LDAP: Could not " 505 "initialize SSL"); 506 } 507 } 508 /* set one or more certificates */ 509 for (i = 0; LDAP_SUCCESS == result->rc && i < certs->nelts; i++) { 510 /* Novell SDK supports DER or BASE64 files. */ 511 switch (ents[i].type) { 512 case APR_LDAP_CA_TYPE_DER: 513 result->rc = ldapssl_add_trusted_cert((void *)ents[i].path, 514 LDAPSSL_CERT_FILETYPE_DER); 515 result->msg = ldap_err2string(result->rc); 516 break; 517 case APR_LDAP_CA_TYPE_BASE64: 518 result->rc = ldapssl_add_trusted_cert((void *)ents[i].path, 519 LDAPSSL_CERT_FILETYPE_B64); 520 result->msg = ldap_err2string(result->rc); 521 break; 522 case APR_LDAP_CERT_TYPE_DER: 523 result->rc = ldapssl_set_client_cert((void *)ents[i].path, 524 LDAPSSL_CERT_FILETYPE_DER, 525 (void*)ents[i].password); 526 result->msg = ldap_err2string(result->rc); 527 break; 528 case APR_LDAP_CERT_TYPE_BASE64: 529 result->rc = ldapssl_set_client_cert((void *)ents[i].path, 530 LDAPSSL_CERT_FILETYPE_B64, 531 (void*)ents[i].password); 532 result->msg = ldap_err2string(result->rc); 533 break; 534 case APR_LDAP_CERT_TYPE_PFX: 535 result->rc = ldapssl_set_client_cert((void *)ents[i].path, 536 LDAPSSL_FILETYPE_P12, 537 (void*)ents[i].password); 538 result->msg = ldap_err2string(result->rc); 539 break; 540 case APR_LDAP_KEY_TYPE_DER: 541 result->rc = ldapssl_set_client_private_key((void *)ents[i].path, 542 LDAPSSL_CERT_FILETYPE_DER, 543 (void*)ents[i].password); 544 result->msg = ldap_err2string(result->rc); 545 break; 546 case APR_LDAP_KEY_TYPE_BASE64: 547 result->rc = ldapssl_set_client_private_key((void *)ents[i].path, 548 LDAPSSL_CERT_FILETYPE_B64, 549 (void*)ents[i].password); 550 result->msg = ldap_err2string(result->rc); 551 break; 552 case APR_LDAP_KEY_TYPE_PFX: 553 result->rc = ldapssl_set_client_private_key((void *)ents[i].path, 554 LDAPSSL_FILETYPE_P12, 555 (void*)ents[i].password); 556 result->msg = ldap_err2string(result->rc); 557 break; 558 default: 559 result->rc = -1; 560 result->reason = "LDAP: The Novell LDAP SDK only understands the " 561 "DER and PEM (BASE64) file types."; 562 break; 563 } 564 if (result->rc != LDAP_SUCCESS) { 565 break; 566 } 567 } 568#else 569 result->reason = "LDAP: ldapssl_client_init(), " 570 "ldapssl_add_trusted_cert() or " 571 "ldapssl_client_deinit() functions not supported " 572 "by this Novell SDK. Certificate authority file " 573 "not set"; 574 result->rc = -1; 575#endif 576#endif 577 578 /* OpenLDAP SDK */ 579#if APR_HAS_OPENLDAP_LDAPSDK 580#ifdef LDAP_OPT_X_TLS_CACERTFILE 581 /* set one or more certificates */ 582 /* FIXME: make it support setting directories as well as files */ 583 for (i = 0; i < certs->nelts; i++) { 584 /* OpenLDAP SDK supports BASE64 files. */ 585 switch (ents[i].type) { 586 case APR_LDAP_CA_TYPE_BASE64: 587 result->rc = ldap_set_option(ldap, LDAP_OPT_X_TLS_CACERTFILE, 588 (void *)ents[i].path); 589 result->msg = ldap_err2string(result->rc); 590 break; 591 case APR_LDAP_CERT_TYPE_BASE64: 592 result->rc = ldap_set_option(ldap, LDAP_OPT_X_TLS_CERTFILE, 593 (void *)ents[i].path); 594 result->msg = ldap_err2string(result->rc); 595 break; 596 case APR_LDAP_KEY_TYPE_BASE64: 597 result->rc = ldap_set_option(ldap, LDAP_OPT_X_TLS_KEYFILE, 598 (void *)ents[i].path); 599 result->msg = ldap_err2string(result->rc); 600 break; 601#ifdef LDAP_OPT_X_TLS_CACERTDIR 602 case APR_LDAP_CA_TYPE_CACERTDIR_BASE64: 603 result->rc = ldap_set_option(ldap, LDAP_OPT_X_TLS_CACERTDIR, 604 (void *)ents[i].path); 605 result->msg = ldap_err2string(result->rc); 606 break; 607#endif 608 default: 609 result->rc = -1; 610 result->reason = "LDAP: The OpenLDAP SDK only understands the " 611 "PEM (BASE64) file type."; 612 break; 613 } 614 if (result->rc != LDAP_SUCCESS) { 615 break; 616 } 617 } 618#else 619 result->reason = "LDAP: LDAP_OPT_X_TLS_CACERTFILE not " 620 "defined by this OpenLDAP SDK. Certificate " 621 "authority file not set"; 622 result->rc = -1; 623#endif 624#endif 625 626 /* Microsoft SDK */ 627#if APR_HAS_MICROSOFT_LDAPSDK 628 /* Microsoft SDK use the registry certificate store - error out 629 * here with a message explaining this. */ 630 result->reason = "LDAP: CA certificates cannot be set using this method, " 631 "as they are stored in the registry instead."; 632 result->rc = -1; 633#endif 634 635 /* SDK not recognised */ 636#if APR_HAS_OTHER_LDAPSDK 637 result->reason = "LDAP: LDAP_OPT_X_TLS_CACERTFILE not " 638 "defined by this LDAP SDK. Certificate " 639 "authority file not set"; 640 result->rc = -1; 641#endif 642 643#else /* not compiled with SSL Support */ 644 result->reason = "LDAP: Attempt to set certificate(s) failed. " 645 "Not built with SSL support"; 646 result->rc = -1; 647#endif /* APR_HAS_LDAP_SSL */ 648 649} 650 651#endif /* APR_HAS_LDAP */ 652 653