]> git.sur5r.net Git - openldap/blob - libraries/libldap/options.c
Plug memory leaks - free() controls in LDAP*
[openldap] / libraries / libldap / options.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1998-2005 The OpenLDAP Foundation.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted only as authorized by the OpenLDAP
9  * Public License.
10  *
11  * A copy of this license is available in the file LICENSE in the
12  * top-level directory of the distribution or, alternatively, at
13  * <http://www.OpenLDAP.org/license.html>.
14  */
15
16 #include "portable.h"
17
18 #include <stdio.h>
19
20 #include <ac/stdlib.h>
21
22 #include <ac/socket.h>
23 #include <ac/string.h>
24 #include <ac/time.h>
25
26 #include "ldap-int.h"
27
28 #define LDAP_OPT_REBIND_PROC 0x4e814d
29 #define LDAP_OPT_REBIND_PARAMS 0x4e814e
30
31 #define LDAP_OPT_NEXTREF_PROC 0x4e815d
32 #define LDAP_OPT_NEXTREF_PARAMS 0x4e815e
33
34 static const LDAPAPIFeatureInfo features[] = {
35 #ifdef LDAP_API_FEATURE_X_OPENLDAP
36         {       /* OpenLDAP Extensions API Feature */
37                 LDAP_FEATURE_INFO_VERSION,
38                 "X_OPENLDAP",
39                 LDAP_API_FEATURE_X_OPENLDAP
40         },
41 #endif
42
43 #ifdef LDAP_API_FEATURE_THREAD_SAFE
44         {       /* Basic Thread Safe */
45                 LDAP_FEATURE_INFO_VERSION,
46                 "THREAD_SAFE",
47                 LDAP_API_FEATURE_THREAD_SAFE
48         },
49 #endif
50 #ifdef LDAP_API_FEATURE_SESSION_THREAD_SAFE
51         {       /* Session Thread Safe */
52                 LDAP_FEATURE_INFO_VERSION,
53                 "SESSION_THREAD_SAFE",
54                 LDAP_API_FEATURE_SESSION_THREAD_SAFE
55         },
56 #endif
57 #ifdef LDAP_API_FEATURE_OPERATION_THREAD_SAFE
58         {       /* Operation Thread Safe */
59                 LDAP_FEATURE_INFO_VERSION,
60                 "OPERATION_THREAD_SAFE",
61                 LDAP_API_FEATURE_OPERATION_THREAD_SAFE
62         },
63 #endif
64 #ifdef LDAP_API_FEATURE_X_OPENLDAP_REENTRANT
65         {       /* OpenLDAP Reentrant */
66                 LDAP_FEATURE_INFO_VERSION,
67                 "X_OPENLDAP_REENTRANT",
68                 LDAP_API_FEATURE_X_OPENLDAP_REENTRANT
69         },
70 #endif
71 #if defined( LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE ) && \
72         defined( LDAP_THREAD_SAFE )
73         {       /* OpenLDAP Thread Safe */
74                 LDAP_FEATURE_INFO_VERSION,
75                 "X_OPENLDAP_THREAD_SAFE",
76                 LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE
77         },
78 #endif
79 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
80         {       /* V2 Referrals */
81                 LDAP_FEATURE_INFO_VERSION,
82                 "X_OPENLDAP_V2_REFERRALS",
83                 LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
84         },
85 #endif
86         {0, NULL, 0}
87 };
88
89 int
90 ldap_get_option(
91         LDAP    *ld,
92         int             option,
93         void    *outvalue)
94 {
95         struct ldapoptions *lo;
96
97         /* Get pointer to global option structure */
98         lo = LDAP_INT_GLOBAL_OPT();   
99         if (NULL == lo) {
100                 return LDAP_NO_MEMORY;
101         }
102
103         if( lo->ldo_valid != LDAP_INITIALIZED ) {
104                 ldap_int_initialize(lo, NULL);
105         }
106
107         if(ld != NULL) {
108                 assert( LDAP_VALID( ld ) );
109
110                 if( !LDAP_VALID( ld ) ) {
111                         return LDAP_OPT_ERROR;
112                 }
113
114                 lo = &ld->ld_options;
115         }
116
117         if(outvalue == NULL) {
118                 /* no place to get to */
119                 return LDAP_OPT_ERROR;
120         }
121
122         switch(option) {
123         case LDAP_OPT_API_INFO: {
124                         struct ldapapiinfo *info = (struct ldapapiinfo *) outvalue;
125
126                         if(info == NULL) {
127                                 /* outvalue must point to an apiinfo structure */
128                                 return LDAP_OPT_ERROR;
129                         }
130
131                         if(info->ldapai_info_version != LDAP_API_INFO_VERSION) {
132                                 /* api info version mismatch */
133                                 info->ldapai_info_version = LDAP_API_INFO_VERSION;
134                                 return LDAP_OPT_ERROR;
135                         }
136
137                         info->ldapai_api_version = LDAP_API_VERSION;
138                         info->ldapai_protocol_version = LDAP_VERSION_MAX;
139
140                         if(features[0].ldapaif_name == NULL) {
141                                 info->ldapai_extensions = NULL;
142                         } else {
143                                 int i;
144                                 info->ldapai_extensions = LDAP_MALLOC(sizeof(char *) *
145                                         sizeof(features)/sizeof(LDAPAPIFeatureInfo));
146
147                                 for(i=0; features[i].ldapaif_name != NULL; i++) {
148                                         info->ldapai_extensions[i] =
149                                                 LDAP_STRDUP(features[i].ldapaif_name);
150                                 }
151
152                                 info->ldapai_extensions[i] = NULL;
153                         }
154
155                         info->ldapai_vendor_name = LDAP_STRDUP(LDAP_VENDOR_NAME);
156                         info->ldapai_vendor_version = LDAP_VENDOR_VERSION;
157
158                         return LDAP_OPT_SUCCESS;
159                 } break;
160
161         case LDAP_OPT_DESC:
162                 if( ld == NULL || ld->ld_sb == NULL ) {
163                         /* bad param */
164                         break;
165                 } 
166
167                 ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, outvalue );
168                 return LDAP_OPT_SUCCESS;
169
170         case LDAP_OPT_SOCKBUF:
171                 if( ld == NULL ) break;
172                 *(Sockbuf **)outvalue = ld->ld_sb;
173                 return LDAP_OPT_SUCCESS;
174
175         case LDAP_OPT_TIMEOUT:
176                 /* the caller has to free outvalue ! */
177                 if ( ldap_int_timeval_dup( outvalue, lo->ldo_tm_api) != 0 ) {
178                         return LDAP_OPT_ERROR;
179                 }
180                 return LDAP_OPT_SUCCESS;
181                 
182         case LDAP_OPT_NETWORK_TIMEOUT:
183                 /* the caller has to free outvalue ! */
184                 if ( ldap_int_timeval_dup( outvalue, lo->ldo_tm_net ) != 0 ) {
185                         return LDAP_OPT_ERROR;
186                 }
187                 return LDAP_OPT_SUCCESS;
188
189         case LDAP_OPT_DEREF:
190                 * (int *) outvalue = lo->ldo_deref;
191                 return LDAP_OPT_SUCCESS;
192
193         case LDAP_OPT_SIZELIMIT:
194                 * (int *) outvalue = lo->ldo_sizelimit;
195                 return LDAP_OPT_SUCCESS;
196
197         case LDAP_OPT_TIMELIMIT:
198                 * (int *) outvalue = lo->ldo_timelimit;
199                 return LDAP_OPT_SUCCESS;
200
201         case LDAP_OPT_REFERRALS:
202                 * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_REFERRALS);
203                 return LDAP_OPT_SUCCESS;
204                 
205         case LDAP_OPT_RESTART:
206                 * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_RESTART);
207                 return LDAP_OPT_SUCCESS;
208
209         case LDAP_OPT_PROTOCOL_VERSION:
210                 * (int *) outvalue = lo->ldo_version;
211                 return LDAP_OPT_SUCCESS;
212
213         case LDAP_OPT_SERVER_CONTROLS:
214                 * (LDAPControl ***) outvalue =
215                         ldap_controls_dup( lo->ldo_sctrls );
216
217                 return LDAP_OPT_SUCCESS;
218
219         case LDAP_OPT_CLIENT_CONTROLS:
220                 * (LDAPControl ***) outvalue =
221                         ldap_controls_dup( lo->ldo_cctrls );
222
223                 return LDAP_OPT_SUCCESS;
224
225         case LDAP_OPT_HOST_NAME:
226                 * (char **) outvalue = ldap_url_list2hosts(lo->ldo_defludp);
227                 return LDAP_OPT_SUCCESS;
228
229         case LDAP_OPT_URI:
230                 * (char **) outvalue = ldap_url_list2urls(lo->ldo_defludp);
231                 return LDAP_OPT_SUCCESS;
232
233         case LDAP_OPT_ERROR_NUMBER:
234                 if(ld == NULL) {
235                         /* bad param */
236                         break;
237                 } 
238                 * (int *) outvalue = ld->ld_errno;
239                 return LDAP_OPT_SUCCESS;
240
241         case LDAP_OPT_ERROR_STRING:
242                 if(ld == NULL) {
243                         /* bad param */
244                         break;
245                 } 
246
247                 if( ld->ld_error == NULL ) {
248                         * (char **) outvalue = NULL;
249                 } else {
250                         * (char **) outvalue = LDAP_STRDUP(ld->ld_error);
251                 }
252
253                 return LDAP_OPT_SUCCESS;
254
255         case LDAP_OPT_MATCHED_DN:
256                 if(ld == NULL) {
257                         /* bad param */
258                         break;
259                 } 
260
261                 if( ld->ld_matched == NULL ) {
262                         * (char **) outvalue = NULL;
263                 } else {
264                         * (char **) outvalue = LDAP_STRDUP(ld->ld_matched);
265                 }
266
267                 return LDAP_OPT_SUCCESS;
268
269         case LDAP_OPT_REFERRAL_URLS:
270                 if(ld == NULL) {
271                         /* bad param */
272                         break;
273                 } 
274
275                 if( ld->ld_referrals == NULL ) {
276                         * (char ***) outvalue = NULL;
277                 } else {
278                         * (char ***) outvalue = ldap_value_dup(ld->ld_referrals);
279                 }
280
281                 return LDAP_OPT_SUCCESS;
282
283         case LDAP_OPT_API_FEATURE_INFO: {
284                         LDAPAPIFeatureInfo *info = (LDAPAPIFeatureInfo *) outvalue;
285                         int i;
286
287                         if(info == NULL) return LDAP_OPT_ERROR;
288
289                         if(info->ldapaif_info_version != LDAP_FEATURE_INFO_VERSION) {
290                                 /* api info version mismatch */
291                                 info->ldapaif_info_version = LDAP_FEATURE_INFO_VERSION;
292                                 return LDAP_OPT_ERROR;
293                         }
294
295                         if(info->ldapaif_name == NULL) return LDAP_OPT_ERROR;
296
297                         for(i=0; features[i].ldapaif_name != NULL; i++) {
298                                 if(!strcmp(info->ldapaif_name, features[i].ldapaif_name)) {
299                                         info->ldapaif_version =
300                                                 features[i].ldapaif_version;
301                                         return LDAP_OPT_SUCCESS;
302                                 }
303                         }
304                 }
305                 break;
306
307         case LDAP_OPT_DEBUG_LEVEL:
308                 * (int *) outvalue = lo->ldo_debug;
309                 return LDAP_OPT_SUCCESS;
310
311         default:
312 #ifdef HAVE_TLS
313                 if ( ldap_pvt_tls_get_option( ld, option, outvalue ) == 0 ) {
314                         return LDAP_OPT_SUCCESS;
315                 }
316 #endif
317 #ifdef HAVE_CYRUS_SASL
318                 if ( ldap_int_sasl_get_option( ld, option, outvalue ) == 0 ) {
319                         return LDAP_OPT_SUCCESS;
320                 }
321 #endif
322                 /* bad param */
323                 break;
324         }
325
326         return LDAP_OPT_ERROR;
327 }
328
329 int
330 ldap_set_option(
331         LDAP    *ld,
332         int             option,
333         LDAP_CONST void *invalue)
334 {
335         struct ldapoptions *lo;
336         int *dbglvl = NULL;
337
338         /* Get pointer to global option structure */
339         lo = LDAP_INT_GLOBAL_OPT();
340         if (lo == NULL) {
341                 return LDAP_NO_MEMORY;
342         }
343
344         /*
345          * The architecture to turn on debugging has a chicken and egg
346          * problem. Thus, we introduce a fix here.
347          */
348
349         if (option == LDAP_OPT_DEBUG_LEVEL) {
350                 dbglvl = (int *) invalue;
351         }
352
353         if( lo->ldo_valid != LDAP_INITIALIZED ) {
354                 ldap_int_initialize(lo, dbglvl);
355         }
356
357         if(ld != NULL) {
358                 assert( LDAP_VALID( ld ) );
359
360                 if( !LDAP_VALID( ld ) ) {
361                         return LDAP_OPT_ERROR;
362                 }
363
364                 lo = &ld->ld_options;
365         }
366
367         switch(option) {
368         case LDAP_OPT_REFERRALS:
369                 if(invalue == LDAP_OPT_OFF) {
370                         LDAP_BOOL_CLR(lo, LDAP_BOOL_REFERRALS);
371                 } else {
372                         LDAP_BOOL_SET(lo, LDAP_BOOL_REFERRALS);
373                 }
374                 return LDAP_OPT_SUCCESS;
375
376         case LDAP_OPT_RESTART:
377                 if(invalue == LDAP_OPT_OFF) {
378                         LDAP_BOOL_CLR(lo, LDAP_BOOL_RESTART);
379                 } else {
380                         LDAP_BOOL_SET(lo, LDAP_BOOL_RESTART);
381                 }
382                 return LDAP_OPT_SUCCESS;
383         }
384
385         /* options which can withstand invalue == NULL */
386         switch ( option ) {
387         case LDAP_OPT_SERVER_CONTROLS: {
388                         LDAPControl *const *controls =
389                                 (LDAPControl *const *) invalue;
390
391                         if( lo->ldo_sctrls )
392                                 ldap_controls_free( lo->ldo_sctrls );
393
394                         if( controls == NULL || *controls == NULL ) {
395                                 lo->ldo_sctrls = NULL;
396                                 return LDAP_OPT_SUCCESS;
397                         }
398                                 
399                         lo->ldo_sctrls = ldap_controls_dup( controls );
400
401                         if(lo->ldo_sctrls == NULL) {
402                                 /* memory allocation error ? */
403                                 break;
404                         }
405                 } return LDAP_OPT_SUCCESS;
406
407         case LDAP_OPT_CLIENT_CONTROLS: {
408                         LDAPControl *const *controls =
409                                 (LDAPControl *const *) invalue;
410
411                         if( lo->ldo_cctrls )
412                                 ldap_controls_free( lo->ldo_cctrls );
413
414                         if( controls == NULL || *controls == NULL ) {
415                                 lo->ldo_cctrls = NULL;
416                                 return LDAP_OPT_SUCCESS;
417                         }
418                                 
419                         lo->ldo_cctrls = ldap_controls_dup( controls );
420
421                         if(lo->ldo_cctrls == NULL) {
422                                 /* memory allocation error ? */
423                                 break;
424                         }
425                 } return LDAP_OPT_SUCCESS;
426
427         case LDAP_OPT_TIMEOUT: {
428                         const struct timeval *tv = 
429                                 (const struct timeval *) invalue;
430
431                         if ( lo->ldo_tm_api != NULL ) {
432                                 LDAP_FREE( lo->ldo_tm_api );
433                                 lo->ldo_tm_api = NULL;
434                         }
435
436                         if ( ldap_int_timeval_dup( &lo->ldo_tm_api, tv ) != 0 ) {
437                                 return LDAP_OPT_ERROR;
438                         }
439                 } return LDAP_OPT_SUCCESS;
440
441         case LDAP_OPT_NETWORK_TIMEOUT: {
442                         const struct timeval *tv = 
443                                 (const struct timeval *) invalue;
444
445                         if ( lo->ldo_tm_net != NULL ) {
446                                 LDAP_FREE( lo->ldo_tm_net );
447                                 lo->ldo_tm_net = NULL;
448                         }
449
450                         if ( ldap_int_timeval_dup( &lo->ldo_tm_net, tv ) != 0 ) {
451                                 return LDAP_OPT_ERROR;
452                         }
453                 } return LDAP_OPT_SUCCESS;
454
455         /* Only accessed from inside this function by ldap_set_rebind_proc() */
456         case LDAP_OPT_REBIND_PROC: {
457                         lo->ldo_rebind_proc = (LDAP_REBIND_PROC *)invalue;              
458                 } return LDAP_OPT_SUCCESS;
459         case LDAP_OPT_REBIND_PARAMS: {
460                         lo->ldo_rebind_params = (void *)invalue;                
461                 } return LDAP_OPT_SUCCESS;
462
463         /* Only accessed from inside this function by ldap_set_nextref_proc() */
464         case LDAP_OPT_NEXTREF_PROC: {
465                         lo->ldo_nextref_proc = (LDAP_NEXTREF_PROC *)invalue;            
466                 } return LDAP_OPT_SUCCESS;
467         case LDAP_OPT_NEXTREF_PARAMS: {
468                         lo->ldo_nextref_params = (void *)invalue;               
469                 } return LDAP_OPT_SUCCESS;
470         }
471
472         if(invalue == NULL) {
473                 /* no place to set from */
474                 return LDAP_OPT_ERROR;
475         }
476
477         /* options which cannot withstand invalue == NULL */
478
479         switch(option) {
480         case LDAP_OPT_API_INFO:
481         case LDAP_OPT_DESC:
482                 /* READ ONLY */
483                 break;
484
485         case LDAP_OPT_DEREF:
486                 lo->ldo_deref = * (const int *) invalue;
487                 return LDAP_OPT_SUCCESS;
488
489         case LDAP_OPT_SIZELIMIT:
490                 lo->ldo_sizelimit = * (const int *) invalue;
491                 return LDAP_OPT_SUCCESS;
492
493         case LDAP_OPT_TIMELIMIT:
494                 lo->ldo_timelimit = * (const int *) invalue;
495                 return LDAP_OPT_SUCCESS;
496
497         case LDAP_OPT_PROTOCOL_VERSION: {
498                         int vers = * (const int *) invalue;
499                         if (vers < LDAP_VERSION_MIN || vers > LDAP_VERSION_MAX) {
500                                 /* not supported */
501                                 break;
502                         }
503                         lo->ldo_version = vers;
504                 } return LDAP_OPT_SUCCESS;
505
506
507         case LDAP_OPT_HOST_NAME: {
508                         const char *host = (const char *) invalue;
509                         LDAPURLDesc *ludlist = NULL;
510                         int rc = LDAP_OPT_SUCCESS;
511
512                         if(host != NULL) {
513                                 rc = ldap_url_parsehosts( &ludlist, host,
514                                         lo->ldo_defport ? lo->ldo_defport : LDAP_PORT );
515
516                         } else if(ld == NULL) {
517                                 /*
518                                  * must want global default returned
519                                  * to initial condition.
520                                  */
521                                 rc = ldap_url_parselist(&ludlist, "ldap://localhost/");
522
523                         } else {
524                                 /*
525                                  * must want the session default
526                                  *   updated to the current global default
527                                  */
528                                 ludlist = ldap_url_duplist(
529                                         ldap_int_global_options.ldo_defludp);
530                                 if (ludlist == NULL)
531                                         rc = LDAP_NO_MEMORY;
532                         }
533
534                         if (rc == LDAP_OPT_SUCCESS) {
535                                 if (lo->ldo_defludp != NULL)
536                                         ldap_free_urllist(lo->ldo_defludp);
537                                 lo->ldo_defludp = ludlist;
538                         }
539                         return rc;
540                 }
541
542         case LDAP_OPT_URI: {
543                         const char *urls = (const char *) invalue;
544                         LDAPURLDesc *ludlist = NULL;
545                         int rc = LDAP_OPT_SUCCESS;
546
547                         if(urls != NULL) {
548                                 rc = ldap_url_parselist(&ludlist, urls);
549                         } else if(ld == NULL) {
550                                 /*
551                                  * must want global default returned
552                                  * to initial condition.
553                                  */
554                                 rc = ldap_url_parselist(&ludlist, "ldap://localhost/");
555
556                         } else {
557                                 /*
558                                  * must want the session default
559                                  *   updated to the current global default
560                                  */
561                                 ludlist = ldap_url_duplist(
562                                         ldap_int_global_options.ldo_defludp);
563                                 if (ludlist == NULL)
564                                         rc = LDAP_NO_MEMORY;
565                         }
566
567                         switch (rc) {
568                         case LDAP_URL_SUCCESS:          /* Success */
569                                 rc = LDAP_SUCCESS;
570                                 break;
571
572                         case LDAP_URL_ERR_MEM:          /* can't allocate memory space */
573                                 rc = LDAP_NO_MEMORY;
574                                 break;
575
576                         case LDAP_URL_ERR_PARAM:        /* parameter is bad */
577                         case LDAP_URL_ERR_BADSCHEME:    /* URL doesn't begin with "ldap[si]://" */
578                         case LDAP_URL_ERR_BADENCLOSURE: /* URL is missing trailing ">" */
579                         case LDAP_URL_ERR_BADURL:       /* URL is bad */
580                         case LDAP_URL_ERR_BADHOST:      /* host port is bad */
581                         case LDAP_URL_ERR_BADATTRS:     /* bad (or missing) attributes */
582                         case LDAP_URL_ERR_BADSCOPE:     /* scope string is invalid (or missing) */
583                         case LDAP_URL_ERR_BADFILTER:    /* bad or missing filter */
584                         case LDAP_URL_ERR_BADEXTS:      /* bad or missing extensions */
585                                 rc = LDAP_PARAM_ERROR;
586                                 break;
587                         }
588
589                         if (rc == LDAP_OPT_SUCCESS) {
590                                 if (lo->ldo_defludp != NULL)
591                                         ldap_free_urllist(lo->ldo_defludp);
592                                 lo->ldo_defludp = ludlist;
593                         }
594                         return rc;
595                 }
596
597         case LDAP_OPT_ERROR_NUMBER: {
598                         int err = * (const int *) invalue;
599
600                         if(ld == NULL) {
601                                 /* need a struct ldap */
602                                 break;
603                         }
604
605                         ld->ld_errno = err;
606                 } return LDAP_OPT_SUCCESS;
607
608         case LDAP_OPT_ERROR_STRING: {
609                         const char *err = (const char *) invalue;
610
611                         if(ld == NULL) {
612                                 /* need a struct ldap */
613                                 break;
614                         }
615
616                         if( ld->ld_error ) {
617                                 LDAP_FREE(ld->ld_error);
618                         }
619
620                         ld->ld_error = LDAP_STRDUP(err);
621                 } return LDAP_OPT_SUCCESS;
622
623         case LDAP_OPT_MATCHED_DN: {
624                         const char *err = (const char *) invalue;
625
626                         if(ld == NULL) {
627                                 /* need a struct ldap */
628                                 break;
629                         }
630
631                         if( ld->ld_matched ) {
632                                 LDAP_FREE(ld->ld_matched);
633                         }
634
635                         ld->ld_matched = LDAP_STRDUP(err);
636                 } return LDAP_OPT_SUCCESS;
637
638         case LDAP_OPT_REFERRAL_URLS: {
639                         char *const *referrals = (char *const *) invalue;
640                         
641                         if(ld == NULL) {
642                                 /* need a struct ldap */
643                                 break;
644                         }
645
646                         if( ld->ld_referrals ) {
647                                 LDAP_VFREE(ld->ld_referrals);
648                         }
649
650                         ld->ld_referrals = ldap_value_dup(referrals);
651                 } return LDAP_OPT_SUCCESS;
652
653         case LDAP_OPT_API_FEATURE_INFO:
654                 /* read-only */
655                 break;
656
657         case LDAP_OPT_DEBUG_LEVEL:
658                 lo->ldo_debug = * (const int *) invalue;
659                 return LDAP_OPT_SUCCESS;
660
661         default:
662 #ifdef HAVE_TLS
663                 if ( ldap_pvt_tls_set_option( ld, option, (void *)invalue ) == 0 )
664                         return LDAP_OPT_SUCCESS;
665 #endif
666 #ifdef HAVE_CYRUS_SASL
667                 if ( ldap_int_sasl_set_option( ld, option, (void *)invalue ) == 0 )
668                         return LDAP_OPT_SUCCESS;
669 #endif
670                 /* bad param */
671                 break;
672         }
673         return LDAP_OPT_ERROR;
674 }
675
676 int
677 ldap_set_rebind_proc( LDAP *ld, LDAP_REBIND_PROC *proc, void *params )
678 {
679         int rc;
680         rc = ldap_set_option( ld, LDAP_OPT_REBIND_PROC, (void *)proc );
681         if( rc != LDAP_OPT_SUCCESS ) return rc;
682
683         rc = ldap_set_option( ld, LDAP_OPT_REBIND_PARAMS, (void *)params );
684         return rc;
685 }
686
687 int
688 ldap_set_nextref_proc( LDAP *ld, LDAP_NEXTREF_PROC *proc, void *params )
689 {
690         int rc;
691         rc = ldap_set_option( ld, LDAP_OPT_NEXTREF_PROC, (void *)proc );
692         if( rc != LDAP_OPT_SUCCESS ) return rc;
693
694         rc = ldap_set_option( ld, LDAP_OPT_NEXTREF_PARAMS, (void *)params );
695         return rc;
696 }