]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/apr-util/ldap/apr_ldap_option.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / apr-util / ldap / apr_ldap_option.c
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
40 static void option_set_cert(apr_pool_t *pool, LDAP *ldap, const void *invalue,
41                            apr_ldap_err_t *result);
42 static 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  */
51 APU_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  */
89 APU_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  */
223 static 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  */
396 static 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