1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements.  See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License.  You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/*  apr_ldap_option.c -- LDAP options
18 *
19 *  The LDAP SDK allows the getting and setting of options on an LDAP
20 *  connection.
21 *
22 */
23
24#include "apr.h"
25#include "apu.h"
26#include "apu_config.h"
27
28#if APU_DSO_BUILD
29#define APU_DSO_LDAP_BUILD
30#endif
31
32#include "apr_ldap.h"
33#include "apr_errno.h"
34#include "apr_pools.h"
35#include "apr_strings.h"
36#include "apr_tables.h"
37
38#if APR_HAS_LDAP
39
40static void option_set_cert(apr_pool_t *pool, LDAP *ldap, const void *invalue,
41                           apr_ldap_err_t *result);
42static void option_set_tls(apr_pool_t *pool, LDAP *ldap, const void *invalue,
43                          apr_ldap_err_t *result);
44
45/**
46 * APR LDAP get option function
47 *
48 * This function gets option values from a given LDAP session if
49 * one was specified.
50 */
51APU_DECLARE_LDAP(int) apr_ldap_get_option(apr_pool_t *pool,
52                                          LDAP *ldap,
53                                          int option,
54                                          void *outvalue,
55                                          apr_ldap_err_t **result_err)
56{
57    apr_ldap_err_t *result;
58
59    result = apr_pcalloc(pool, sizeof(apr_ldap_err_t));
60    *result_err = result;
61    if (!result) {
62        return APR_ENOMEM;
63    }
64
65    /* get the option specified using the native LDAP function */
66    result->rc = ldap_get_option(ldap, option, outvalue);
67
68    /* handle the error case */
69    if (result->rc != LDAP_SUCCESS) {
70        result->msg = ldap_err2string(result-> rc);
71        result->reason = apr_pstrdup(pool, "LDAP: Could not get an option");
72        return APR_EGENERAL;
73    }
74
75    return APR_SUCCESS;
76
77}
78
79/**
80 * APR LDAP set option function
81 *
82 * This function sets option values to a given LDAP session if
83 * one was specified.
84 *
85 * Where an option is not supported by an LDAP toolkit, this function
86 * will try and apply legacy functions to achieve the same effect,
87 * depending on the platform.
88 */
89APU_DECLARE_LDAP(int) apr_ldap_set_option(apr_pool_t *pool,
90                                          LDAP *ldap,
91                                          int option,
92                                          const void *invalue,
93                                          apr_ldap_err_t **result_err)
94{
95    apr_ldap_err_t *result;
96
97    result = apr_pcalloc(pool, sizeof(apr_ldap_err_t));
98    *result_err = result;
99    if (!result) {
100        return APR_ENOMEM;
101    }
102
103    switch (option) {
104    case APR_LDAP_OPT_TLS_CERT:
105        option_set_cert(pool, ldap, invalue, result);
106        break;
107
108    case APR_LDAP_OPT_TLS:
109        option_set_tls(pool, ldap, invalue, result);
110        break;
111
112    case APR_LDAP_OPT_VERIFY_CERT:
113#if APR_HAS_NETSCAPE_LDAPSDK || APR_HAS_SOLARIS_LDAPSDK || APR_HAS_MOZILLA_LDAPSK
114        result->reason = "LDAP: Verify certificate not yet supported by APR on the "
115                         "Netscape, Solaris or Mozilla LDAP SDKs";
116        result->rc = -1;
117        return APR_EGENERAL;
118#endif
119#if APR_HAS_NOVELL_LDAPSDK
120        if (*((int*)invalue)) {
121            result->rc = ldapssl_set_verify_mode(LDAPSSL_VERIFY_SERVER);
122        }
123        else {
124            result->rc = ldapssl_set_verify_mode(LDAPSSL_VERIFY_NONE);
125        }
126#endif
127#if APR_HAS_OPENLDAP_LDAPSDK
128#ifdef LDAP_OPT_X_TLS
129		/* This is not a per-connection setting so just pass NULL for the
130		   Ldap connection handle */
131        if (*((int*)invalue)) {
132			int i = LDAP_OPT_X_TLS_DEMAND;
133			result->rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &i);
134        }
135        else {
136			int i = LDAP_OPT_X_TLS_NEVER;
137			result->rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &i);
138        }
139#else
140        result->reason = "LDAP: SSL/TLS not yet supported by APR on this "
141                         "version of the OpenLDAP toolkit";
142        result->rc = -1;
143        return APR_EGENERAL;
144#endif
145#endif
146
147        /* handle the error case */
148        if (result->rc != LDAP_SUCCESS) {
149            result->msg = ldap_err2string(result->rc);
150            result->reason = "LDAP: Could not set verify mode";
151        }
152        break;
153
154    case APR_LDAP_OPT_REFERRALS:
155        /* 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