1 /*        $NetBSD: options.c,v 1.3 2021/08/14 16:14:56 christos Exp $ */
2 
3 /* $OpenLDAP$ */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5  *
6  * Copyright 1998-2021 The OpenLDAP Foundation.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted only as authorized by the OpenLDAP
11  * Public License.
12  *
13  * A copy of this license is available in the file LICENSE in the
14  * top-level directory of the distribution or, alternatively, at
15  * <http://www.OpenLDAP.org/license.html>.
16  */
17 
18 #include <sys/cdefs.h>
19 __RCSID("$NetBSD: options.c,v 1.3 2021/08/14 16:14:56 christos Exp $");
20 
21 #include "portable.h"
22 
23 #include <stdio.h>
24 
25 #include <ac/stdlib.h>
26 
27 #include <ac/socket.h>
28 #include <ac/string.h>
29 #include <ac/time.h>
30 
31 #include "ldap-int.h"
32 
33 #define LDAP_OPT_REBIND_PROC 0x4e814d
34 #define LDAP_OPT_REBIND_PARAMS 0x4e814e
35 
36 #define LDAP_OPT_NEXTREF_PROC 0x4e815d
37 #define LDAP_OPT_NEXTREF_PARAMS 0x4e815e
38 
39 #define LDAP_OPT_URLLIST_PROC 0x4e816d
40 #define LDAP_OPT_URLLIST_PARAMS 0x4e816e
41 
42 static const LDAPAPIFeatureInfo features[] = {
43 #ifdef LDAP_API_FEATURE_X_OPENLDAP
44           {         /* OpenLDAP Extensions API Feature */
45                     LDAP_FEATURE_INFO_VERSION,
46                     "X_OPENLDAP",
47                     LDAP_API_FEATURE_X_OPENLDAP
48           },
49 #endif
50 
51 #ifdef LDAP_API_FEATURE_THREAD_SAFE
52           {         /* Basic Thread Safe */
53                     LDAP_FEATURE_INFO_VERSION,
54                     "THREAD_SAFE",
55                     LDAP_API_FEATURE_THREAD_SAFE
56           },
57 #endif
58 #ifdef LDAP_API_FEATURE_SESSION_THREAD_SAFE
59           {         /* Session Thread Safe */
60                     LDAP_FEATURE_INFO_VERSION,
61                     "SESSION_THREAD_SAFE",
62                     LDAP_API_FEATURE_SESSION_THREAD_SAFE
63           },
64 #endif
65 #ifdef LDAP_API_FEATURE_OPERATION_THREAD_SAFE
66           {         /* Operation Thread Safe */
67                     LDAP_FEATURE_INFO_VERSION,
68                     "OPERATION_THREAD_SAFE",
69                     LDAP_API_FEATURE_OPERATION_THREAD_SAFE
70           },
71 #endif
72 #ifdef LDAP_API_FEATURE_X_OPENLDAP_REENTRANT
73           {         /* OpenLDAP Reentrant */
74                     LDAP_FEATURE_INFO_VERSION,
75                     "X_OPENLDAP_REENTRANT",
76                     LDAP_API_FEATURE_X_OPENLDAP_REENTRANT
77           },
78 #endif
79 #ifdef LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE
80           {         /* OpenLDAP Thread Safe */
81                     LDAP_FEATURE_INFO_VERSION,
82                     "X_OPENLDAP_THREAD_SAFE",
83                     LDAP_API_FEATURE_X_OPENLDAP_THREAD_SAFE
84           },
85 #endif
86 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
87           {         /* V2 Referrals */
88                     LDAP_FEATURE_INFO_VERSION,
89                     "X_OPENLDAP_V2_REFERRALS",
90                     LDAP_API_FEATURE_X_OPENLDAP_V2_REFERRALS
91           },
92 #endif
93           {0, NULL, 0}
94 };
95 
96 int
ldap_get_option(LDAP * ld,int option,void * outvalue)97 ldap_get_option(
98           LDAP      *ld,
99           int                 option,
100           void      *outvalue)
101 {
102           struct ldapoptions *lo;
103           int rc = LDAP_OPT_ERROR;
104 
105           /* Get pointer to global option structure */
106           lo = LDAP_INT_GLOBAL_OPT();
107           if (NULL == lo)     {
108                     return LDAP_NO_MEMORY;
109           }
110 
111           if( lo->ldo_valid != LDAP_INITIALIZED ) {
112                     ldap_int_initialize(lo, NULL);
113                     if ( lo->ldo_valid != LDAP_INITIALIZED )
114                               return LDAP_LOCAL_ERROR;
115           }
116 
117           if(ld != NULL) {
118                     if( !LDAP_VALID( ld ) ) {
119                               return LDAP_OPT_ERROR;
120                     }
121 
122                     lo = &ld->ld_options;
123           }
124 
125           if(outvalue == NULL) {
126                     /* no place to get to */
127                     return LDAP_OPT_ERROR;
128           }
129 
130           LDAP_MUTEX_LOCK( &lo->ldo_mutex );
131 
132           switch(option) {
133           case LDAP_OPT_API_INFO: {
134                               struct ldapapiinfo *info = (struct ldapapiinfo *) outvalue;
135 
136                               if(info == NULL) {
137                                         /* outvalue must point to an apiinfo structure */
138                                         break;    /* LDAP_OPT_ERROR */
139                               }
140 
141                               if(info->ldapai_info_version != LDAP_API_INFO_VERSION) {
142                                         /* api info version mismatch */
143                                         info->ldapai_info_version = LDAP_API_INFO_VERSION;
144                                         break;    /* LDAP_OPT_ERROR */
145                               }
146 
147                               info->ldapai_api_version = LDAP_API_VERSION;
148                               info->ldapai_protocol_version = LDAP_VERSION_MAX;
149 
150                               if(features[0].ldapaif_name == NULL) {
151                                         info->ldapai_extensions = NULL;
152                               } else {
153                                         int i;
154                                         info->ldapai_extensions = LDAP_MALLOC(sizeof(char *) *
155                                                   sizeof(features)/sizeof(LDAPAPIFeatureInfo));
156                                         if ( info->ldapai_extensions == NULL ) {
157                                                   rc = LDAP_NO_MEMORY;
158                                                   break;
159                                         }
160 
161                                         for(i=0; features[i].ldapaif_name != NULL; i++) {
162                                                   info->ldapai_extensions[i] =
163                                                             LDAP_STRDUP(features[i].ldapaif_name);
164                                                   if ( info->ldapai_extensions[i] == NULL ) {
165                                                             rc = LDAP_NO_MEMORY;
166                                                             break;
167                                                   }
168                                         }
169                                         if ( features[i].ldapaif_name != NULL ) {
170                                                   break; /* LDAP_NO_MEMORY */
171                                         }
172 
173                                         info->ldapai_extensions[i] = NULL;
174                               }
175 
176                               info->ldapai_vendor_name = LDAP_STRDUP(LDAP_VENDOR_NAME);
177                               info->ldapai_vendor_version = LDAP_VENDOR_VERSION;
178 
179                               rc = LDAP_OPT_SUCCESS;
180                               break;
181                     } break;
182 
183           case LDAP_OPT_DESC:
184                     if( ld == NULL || ld->ld_sb == NULL ) {
185                               /* bad param */
186                               break;
187                     }
188 
189                     ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, outvalue );
190                     rc = LDAP_OPT_SUCCESS;
191                     break;
192 
193           case LDAP_OPT_SOCKBUF:
194                     if( ld == NULL ) break;
195                     *(Sockbuf **)outvalue = ld->ld_sb;
196                     rc = LDAP_OPT_SUCCESS;
197                     break;
198 
199           case LDAP_OPT_TIMEOUT:
200                     /* the caller has to free outvalue ! */
201                     if ( lo->ldo_tm_api.tv_sec < 0 ) {
202                               *(void **)outvalue = NULL;
203                     } else if ( ldap_int_timeval_dup( outvalue, &lo->ldo_tm_api ) != 0 ) {
204                               break;    /* LDAP_OPT_ERROR */
205                     }
206                     rc = LDAP_OPT_SUCCESS;
207                     break;
208 
209           case LDAP_OPT_NETWORK_TIMEOUT:
210                     /* the caller has to free outvalue ! */
211                     if ( lo->ldo_tm_net.tv_sec < 0 ) {
212                               *(void **)outvalue = NULL;
213                     } else if ( ldap_int_timeval_dup( outvalue, &lo->ldo_tm_net ) != 0 ) {
214                               break;    /* LDAP_OPT_ERROR */
215                     }
216                     rc = LDAP_OPT_SUCCESS;
217                     break;
218 
219           case LDAP_OPT_DEREF:
220                     * (int *) outvalue = lo->ldo_deref;
221                     rc = LDAP_OPT_SUCCESS;
222                     break;
223 
224           case LDAP_OPT_SIZELIMIT:
225                     * (int *) outvalue = lo->ldo_sizelimit;
226                     rc = LDAP_OPT_SUCCESS;
227                     break;
228 
229           case LDAP_OPT_TIMELIMIT:
230                     * (int *) outvalue = lo->ldo_timelimit;
231                     rc = LDAP_OPT_SUCCESS;
232                     break;
233 
234           case LDAP_OPT_REFERRALS:
235                     * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_REFERRALS);
236                     rc = LDAP_OPT_SUCCESS;
237                     break;
238 
239           case LDAP_OPT_RESTART:
240                     * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_RESTART);
241                     rc = LDAP_OPT_SUCCESS;
242                     break;
243 
244           case LDAP_OPT_PROTOCOL_VERSION:
245                     * (int *) outvalue = lo->ldo_version;
246                     rc = LDAP_OPT_SUCCESS;
247                     break;
248 
249           case LDAP_OPT_SERVER_CONTROLS:
250                     * (LDAPControl ***) outvalue =
251                               ldap_controls_dup( lo->ldo_sctrls );
252                     rc = LDAP_OPT_SUCCESS;
253                     break;
254 
255           case LDAP_OPT_CLIENT_CONTROLS:
256                     * (LDAPControl ***) outvalue =
257                               ldap_controls_dup( lo->ldo_cctrls );
258                     rc = LDAP_OPT_SUCCESS;
259                     break;
260 
261           case LDAP_OPT_HOST_NAME:
262                     * (char **) outvalue = ldap_url_list2hosts(lo->ldo_defludp);
263                     rc = LDAP_OPT_SUCCESS;
264                     break;
265 
266           case LDAP_OPT_SOCKET_BIND_ADDRESSES:
267                     if ( lo->ldo_local_ip_addrs.local_ip_addrs == NULL ) {
268                               * (void **) outvalue = NULL;
269                     }
270                     else {
271                               * (char **) outvalue =
272                                         LDAP_STRDUP( lo->ldo_local_ip_addrs.local_ip_addrs );
273                     }
274                     rc = LDAP_OPT_SUCCESS;
275                     break;
276 
277           case LDAP_OPT_URI:
278                     * (char **) outvalue = ldap_url_list2urls(lo->ldo_defludp);
279                     rc = LDAP_OPT_SUCCESS;
280                     break;
281 
282           case LDAP_OPT_DEFBASE:
283                     if( lo->ldo_defbase == NULL ) {
284                               * (char **) outvalue = NULL;
285                     } else {
286                               * (char **) outvalue = LDAP_STRDUP(lo->ldo_defbase);
287                     }
288                     rc = LDAP_OPT_SUCCESS;
289                     break;
290 
291           case LDAP_OPT_CONNECT_ASYNC:
292                     * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_CONNECT_ASYNC);
293                     rc = LDAP_OPT_SUCCESS;
294                     break;
295 
296           case LDAP_OPT_CONNECT_CB:
297                     {
298                               /* Getting deletes the specified callback */
299                               ldaplist **ll = &lo->ldo_conn_cbs;
300                               for (;*ll;ll = &(*ll)->ll_next) {
301                                         if ((*ll)->ll_data == outvalue) {
302                                                   ldaplist *lc = *ll;
303                                                   *ll = lc->ll_next;
304                                                   LDAP_FREE(lc);
305                                                   break;
306                                         }
307                               }
308                     }
309                     rc = LDAP_OPT_SUCCESS;
310                     break;
311 
312           case LDAP_OPT_RESULT_CODE:
313                     if(ld == NULL) {
314                               /* bad param */
315                               break;
316                     }
317                     * (int *) outvalue = ld->ld_errno;
318                     rc = LDAP_OPT_SUCCESS;
319                     break;
320 
321           case LDAP_OPT_DIAGNOSTIC_MESSAGE:
322                     if(ld == NULL) {
323                               /* bad param */
324                               break;
325                     }
326 
327                     if( ld->ld_error == NULL ) {
328                               * (char **) outvalue = NULL;
329                     } else {
330                               * (char **) outvalue = LDAP_STRDUP(ld->ld_error);
331                     }
332                     rc = LDAP_OPT_SUCCESS;
333                     break;
334 
335           case LDAP_OPT_MATCHED_DN:
336                     if(ld == NULL) {
337                               /* bad param */
338                               break;
339                     }
340 
341                     if( ld->ld_matched == NULL ) {
342                               * (char **) outvalue = NULL;
343                     } else {
344                               * (char **) outvalue = LDAP_STRDUP( ld->ld_matched );
345                     }
346                     rc = LDAP_OPT_SUCCESS;
347                     break;
348 
349           case LDAP_OPT_REFERRAL_URLS:
350                     if(ld == NULL) {
351                               /* bad param */
352                               break;
353                     }
354 
355                     if( ld->ld_referrals == NULL ) {
356                               * (char ***) outvalue = NULL;
357                     } else {
358                               * (char ***) outvalue = ldap_value_dup(ld->ld_referrals);
359                     }
360                     rc = LDAP_OPT_SUCCESS;
361                     break;
362 
363           case LDAP_OPT_API_FEATURE_INFO: {
364                               LDAPAPIFeatureInfo *info = (LDAPAPIFeatureInfo *) outvalue;
365                               int i;
366 
367                               if(info == NULL)
368                                         break;    /* LDAP_OPT_ERROR */
369 
370                               if(info->ldapaif_info_version != LDAP_FEATURE_INFO_VERSION) {
371                                         /* api info version mismatch */
372                                         info->ldapaif_info_version = LDAP_FEATURE_INFO_VERSION;
373                                         break;    /* LDAP_OPT_ERROR */
374                               }
375 
376                               if(info->ldapaif_name == NULL)
377                                         break;    /* LDAP_OPT_ERROR */
378 
379                               for(i=0; features[i].ldapaif_name != NULL; i++) {
380                                         if(!strcmp(info->ldapaif_name, features[i].ldapaif_name)) {
381                                                   info->ldapaif_version =
382                                                             features[i].ldapaif_version;
383                                                   rc = LDAP_OPT_SUCCESS;
384                                                   break;
385                                         }
386                               }
387                     }
388                     break;
389 
390           case LDAP_OPT_DEBUG_LEVEL:
391                     * (int *) outvalue = lo->ldo_debug;
392                     rc = LDAP_OPT_SUCCESS;
393                     break;
394 
395           case LDAP_OPT_SESSION_REFCNT:
396                     if(ld == NULL) {
397                               /* bad param */
398                               break;
399                     }
400                     LDAP_MUTEX_LOCK( &ld->ld_ldcmutex );
401                     * (int *) outvalue = ld->ld_ldcrefcnt;
402                     LDAP_MUTEX_UNLOCK( &ld->ld_ldcmutex );
403                     rc = LDAP_OPT_SUCCESS;
404                     break;
405 
406           case LDAP_OPT_KEEPCONN:
407                     * (int *) outvalue = (int) LDAP_BOOL_GET(lo, LDAP_BOOL_KEEPCONN);
408                     rc = LDAP_OPT_SUCCESS;
409                     break;
410 
411           case LDAP_OPT_X_KEEPALIVE_IDLE:
412                     * (int *) outvalue = lo->ldo_keepalive_idle;
413                     rc = LDAP_OPT_SUCCESS;
414                     break;
415 
416           case LDAP_OPT_X_KEEPALIVE_PROBES:
417                     * (int *) outvalue = lo->ldo_keepalive_probes;
418                     rc = LDAP_OPT_SUCCESS;
419                     break;
420 
421           case LDAP_OPT_X_KEEPALIVE_INTERVAL:
422                     * (int *) outvalue = lo->ldo_keepalive_interval;
423                     rc = LDAP_OPT_SUCCESS;
424                     break;
425 
426           case LDAP_OPT_TCP_USER_TIMEOUT:
427                     * (unsigned int *) outvalue = lo->ldo_tcp_user_timeout;
428                     rc = LDAP_OPT_SUCCESS;
429                     break;
430 
431           default:
432 #ifdef HAVE_TLS
433                     if ( ldap_pvt_tls_get_option( ld, option, outvalue ) == 0 ) {
434                               rc = LDAP_OPT_SUCCESS;
435                               break;
436                     }
437 #endif
438 #ifdef HAVE_CYRUS_SASL
439                     if ( ldap_int_sasl_get_option( ld, option, outvalue ) == 0 ) {
440                               rc = LDAP_OPT_SUCCESS;
441                               break;
442                     }
443 #endif
444 #ifdef HAVE_GSSAPI
445                     if ( ldap_int_gssapi_get_option( ld, option, outvalue ) == 0 ) {
446                               rc = LDAP_OPT_SUCCESS;
447                               break;
448                     }
449 #endif
450                     /* bad param */
451                     break;
452           }
453 
454           LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
455           return ( rc );
456 }
457 
458 int
ldap_set_option(LDAP * ld,int option,LDAP_CONST void * invalue)459 ldap_set_option(
460           LDAP      *ld,
461           int                 option,
462           LDAP_CONST void     *invalue)
463 {
464           struct ldapoptions *lo;
465           int *dbglvl = NULL;
466           int rc = LDAP_OPT_ERROR;
467 
468           /* Get pointer to global option structure */
469           lo = LDAP_INT_GLOBAL_OPT();
470           if (lo == NULL)     {
471                     return LDAP_NO_MEMORY;
472           }
473 
474           /*
475            * The architecture to turn on debugging has a chicken and egg
476            * problem. Thus, we introduce a fix here.
477            */
478 
479           if (option == LDAP_OPT_DEBUG_LEVEL) {
480                     dbglvl = (int *) invalue;
481           }
482 
483           if( lo->ldo_valid != LDAP_INITIALIZED ) {
484                     ldap_int_initialize(lo, dbglvl);
485                     if ( lo->ldo_valid != LDAP_INITIALIZED )
486                               return LDAP_LOCAL_ERROR;
487           }
488 
489           if(ld != NULL) {
490                     assert( LDAP_VALID( ld ) );
491 
492                     if( !LDAP_VALID( ld ) ) {
493                               return LDAP_OPT_ERROR;
494                     }
495 
496                     lo = &ld->ld_options;
497           }
498 
499           LDAP_MUTEX_LOCK( &lo->ldo_mutex );
500 
501           switch ( option ) {
502 
503           /* options with boolean values */
504           case LDAP_OPT_REFERRALS:
505                     if(invalue == LDAP_OPT_OFF) {
506                               LDAP_BOOL_CLR(lo, LDAP_BOOL_REFERRALS);
507                     } else {
508                               LDAP_BOOL_SET(lo, LDAP_BOOL_REFERRALS);
509                     }
510                     rc = LDAP_OPT_SUCCESS;
511                     break;
512 
513           case LDAP_OPT_RESTART:
514                     if(invalue == LDAP_OPT_OFF) {
515                               LDAP_BOOL_CLR(lo, LDAP_BOOL_RESTART);
516                     } else {
517                               LDAP_BOOL_SET(lo, LDAP_BOOL_RESTART);
518                     }
519                     rc = LDAP_OPT_SUCCESS;
520                     break;
521 
522           case LDAP_OPT_CONNECT_ASYNC:
523                     if(invalue == LDAP_OPT_OFF) {
524                               LDAP_BOOL_CLR(lo, LDAP_BOOL_CONNECT_ASYNC);
525                     } else {
526                               LDAP_BOOL_SET(lo, LDAP_BOOL_CONNECT_ASYNC);
527                     }
528                     rc = LDAP_OPT_SUCCESS;
529                     break;
530 
531           case LDAP_OPT_KEEPCONN:
532                     if(invalue == LDAP_OPT_OFF) {
533                               LDAP_BOOL_CLR(lo, LDAP_BOOL_KEEPCONN);
534                     } else {
535                               LDAP_BOOL_SET(lo, LDAP_BOOL_KEEPCONN);
536                     }
537                     rc = LDAP_OPT_SUCCESS;
538                     break;
539           /* options which can withstand invalue == NULL */
540           case LDAP_OPT_SERVER_CONTROLS: {
541                               LDAPControl *const *controls =
542                                         (LDAPControl *const *) invalue;
543 
544                               if( lo->ldo_sctrls )
545                                         ldap_controls_free( lo->ldo_sctrls );
546 
547                               if( controls == NULL || *controls == NULL ) {
548                                         lo->ldo_sctrls = NULL;
549                                         rc = LDAP_OPT_SUCCESS;
550                                         break;
551                               }
552 
553                               lo->ldo_sctrls = ldap_controls_dup( controls );
554 
555                               if(lo->ldo_sctrls == NULL) {
556                                         /* memory allocation error ? */
557                                         break;    /* LDAP_OPT_ERROR */
558                               }
559                     }
560                     rc = LDAP_OPT_SUCCESS;
561                     break;
562 
563           case LDAP_OPT_CLIENT_CONTROLS: {
564                               LDAPControl *const *controls =
565                                         (LDAPControl *const *) invalue;
566 
567                               if( lo->ldo_cctrls )
568                                         ldap_controls_free( lo->ldo_cctrls );
569 
570                               if( controls == NULL || *controls == NULL ) {
571                                         lo->ldo_cctrls = NULL;
572                                         rc = LDAP_OPT_SUCCESS;
573                                         break;
574                               }
575 
576                               lo->ldo_cctrls = ldap_controls_dup( controls );
577 
578                               if(lo->ldo_cctrls == NULL) {
579                                         /* memory allocation error ? */
580                                         break;    /* LDAP_OPT_ERROR */
581                               }
582                     }
583                     rc = LDAP_OPT_SUCCESS;
584                     break;
585 
586 
587           case LDAP_OPT_HOST_NAME: {
588                               const char *host = (const char *) invalue;
589                               LDAPURLDesc *ludlist = NULL;
590                               rc = LDAP_OPT_SUCCESS;
591 
592                               if(host != NULL) {
593                                         rc = ldap_url_parsehosts( &ludlist, host,
594                                                   lo->ldo_defport ? lo->ldo_defport : LDAP_PORT );
595 
596                               } else if(ld == NULL) {
597                                         /*
598                                          * must want global default returned
599                                          * to initial condition.
600                                          */
601                                         rc = ldap_url_parselist_ext(&ludlist, "ldap://localhost/", NULL,
602                                                   LDAP_PVT_URL_PARSE_NOEMPTY_HOST
603                                                   | LDAP_PVT_URL_PARSE_DEF_PORT );
604 
605                               } else {
606                                         /*
607                                          * must want the session default
608                                          *   updated to the current global default
609                                          */
610                                         ludlist = ldap_url_duplist(
611                                                   ldap_int_global_options.ldo_defludp);
612                                         if (ludlist == NULL)
613                                                   rc = LDAP_NO_MEMORY;
614                               }
615 
616                               if (rc == LDAP_OPT_SUCCESS) {
617                                         if (lo->ldo_defludp != NULL)
618                                                   ldap_free_urllist(lo->ldo_defludp);
619                                         lo->ldo_defludp = ludlist;
620                               }
621                               break;
622                     }
623 
624           case LDAP_OPT_SOCKET_BIND_ADDRESSES: {
625                               const char *source_ip = (const char *) invalue;
626                               char **source_ip_lst = NULL;
627 
628                               ldapsourceip temp_source_ip;
629                               memset( &temp_source_ip, 0, sizeof( ldapsourceip ) );
630                               rc = LDAP_OPT_SUCCESS;
631                               if( source_ip == NULL ) {
632                                         if ( ld->ld_options.ldo_local_ip_addrs.local_ip_addrs ) {
633                                                   LDAP_FREE( ld->ld_options.ldo_local_ip_addrs.local_ip_addrs );
634                                                   memset( &ld->ld_options.ldo_local_ip_addrs, 0,
635                                                             sizeof( ldapsourceip ) );
636                                         }
637                               }
638                               else {
639                                         source_ip_lst = ldap_str2charray( source_ip, " " );
640 
641                                         if ( source_ip_lst == NULL )
642                                                   rc =  LDAP_NO_MEMORY;
643 
644                                         if( rc == LDAP_OPT_SUCCESS ) {
645                                                   rc = ldap_validate_and_fill_sourceip ( source_ip_lst,
646                                                             &temp_source_ip );
647                                                   ldap_charray_free( source_ip_lst );
648                                         }
649                                         if ( rc == LDAP_OPT_SUCCESS ) {
650                                                   if ( lo->ldo_local_ip_addrs.local_ip_addrs != NULL ) {
651                                                             LDAP_FREE( lo->ldo_local_ip_addrs.local_ip_addrs );
652                                                             lo->ldo_local_ip_addrs.local_ip_addrs = NULL;
653                                                   }
654                                                   lo->ldo_local_ip_addrs = temp_source_ip;
655                                                   lo->ldo_local_ip_addrs.local_ip_addrs = LDAP_STRDUP( source_ip );
656                                         }
657                               }
658                               break;
659                     }
660 
661           case LDAP_OPT_URI: {
662                               const char *urls = (const char *) invalue;
663                               LDAPURLDesc *ludlist = NULL;
664                               rc = LDAP_OPT_SUCCESS;
665 
666                               if(urls != NULL) {
667                                         rc = ldap_url_parselist_ext(&ludlist, urls, NULL,
668                                                   LDAP_PVT_URL_PARSE_NOEMPTY_HOST
669                                                   | LDAP_PVT_URL_PARSE_DEF_PORT );
670                               } else if(ld == NULL) {
671                                         /*
672                                          * must want global default returned
673                                          * to initial condition.
674                                          */
675                                         rc = ldap_url_parselist_ext(&ludlist, "ldap://localhost/", NULL,
676                                                   LDAP_PVT_URL_PARSE_NOEMPTY_HOST
677                                                   | LDAP_PVT_URL_PARSE_DEF_PORT );
678 
679                               } else {
680                                         /*
681                                          * must want the session default
682                                          *   updated to the current global default
683                                          */
684                                         ludlist = ldap_url_duplist(
685                                                   ldap_int_global_options.ldo_defludp);
686                                         if (ludlist == NULL)
687                                                   rc = LDAP_URL_ERR_MEM;
688                               }
689 
690                               switch (rc) {
691                               case LDAP_URL_SUCCESS:                  /* Success */
692                                         rc = LDAP_SUCCESS;
693                                         break;
694 
695                               case LDAP_URL_ERR_MEM:                  /* can't allocate memory space */
696                                         rc = LDAP_NO_MEMORY;
697                                         break;
698 
699                               case LDAP_URL_ERR_PARAM:      /* parameter is bad */
700                               case LDAP_URL_ERR_BADSCHEME:  /* URL doesn't begin with "ldap[si]://" */
701                               case LDAP_URL_ERR_BADENCLOSURE:         /* URL is missing trailing ">" */
702                               case LDAP_URL_ERR_BADURL:     /* URL is bad */
703                               case LDAP_URL_ERR_BADHOST:    /* host port is bad */
704                               case LDAP_URL_ERR_BADATTRS:   /* bad (or missing) attributes */
705                               case LDAP_URL_ERR_BADSCOPE:   /* scope string is invalid (or missing) */
706                               case LDAP_URL_ERR_BADFILTER:  /* bad or missing filter */
707                               case LDAP_URL_ERR_BADEXTS:    /* bad or missing extensions */
708                                         rc = LDAP_PARAM_ERROR;
709                                         break;
710                               }
711 
712                               if (rc == LDAP_SUCCESS) {
713                                         if (lo->ldo_defludp != NULL)
714                                                   ldap_free_urllist(lo->ldo_defludp);
715                                         lo->ldo_defludp = ludlist;
716                               }
717                               break;
718                     }
719 
720           case LDAP_OPT_DEFBASE: {
721                               const char *newbase = (const char *) invalue;
722                               char *defbase = NULL;
723 
724                               if ( newbase != NULL ) {
725                                         defbase = LDAP_STRDUP( newbase );
726                                         if ( defbase == NULL ) {
727                                                   rc = LDAP_NO_MEMORY;
728                                                   break;
729                                         }
730 
731                               } else if ( ld != NULL ) {
732                                         defbase = LDAP_STRDUP( ldap_int_global_options.ldo_defbase );
733                                         if ( defbase == NULL ) {
734                                                   rc = LDAP_NO_MEMORY;
735                                                   break;
736                                         }
737                               }
738 
739                               if ( lo->ldo_defbase != NULL )
740                                         LDAP_FREE( lo->ldo_defbase );
741                               lo->ldo_defbase = defbase;
742                     }
743                     rc = LDAP_OPT_SUCCESS;
744                     break;
745 
746           case LDAP_OPT_DIAGNOSTIC_MESSAGE: {
747                               const char *err = (const char *) invalue;
748 
749                               if(ld == NULL) {
750                                         /* need a struct ldap */
751                                         break;    /* LDAP_OPT_ERROR */
752                               }
753 
754                               if( ld->ld_error ) {
755                                         LDAP_FREE(ld->ld_error);
756                                         ld->ld_error = NULL;
757                               }
758 
759                               if ( err ) {
760                                         ld->ld_error = LDAP_STRDUP(err);
761                               }
762                     }
763                     rc = LDAP_OPT_SUCCESS;
764                     break;
765 
766           case LDAP_OPT_MATCHED_DN: {
767                               const char *matched = (const char *) invalue;
768 
769                               if (ld == NULL) {
770                                         /* need a struct ldap */
771                                         break;    /* LDAP_OPT_ERROR */
772                               }
773 
774                               if( ld->ld_matched ) {
775                                         LDAP_FREE(ld->ld_matched);
776                                         ld->ld_matched = NULL;
777                               }
778 
779                               if ( matched ) {
780                                         ld->ld_matched = LDAP_STRDUP( matched );
781                               }
782                     }
783                     rc = LDAP_OPT_SUCCESS;
784                     break;
785 
786           case LDAP_OPT_REFERRAL_URLS: {
787                               char *const *referrals = (char *const *) invalue;
788 
789                               if(ld == NULL) {
790                                         /* need a struct ldap */
791                                         break;    /* LDAP_OPT_ERROR */
792                               }
793 
794                               if( ld->ld_referrals ) {
795                                         LDAP_VFREE(ld->ld_referrals);
796                               }
797 
798                               if ( referrals ) {
799                                         ld->ld_referrals = ldap_value_dup(referrals);
800                               }
801                     }
802                     rc = LDAP_OPT_SUCCESS;
803                     break;
804 
805           /* Only accessed from inside this function by ldap_set_rebind_proc() */
806           case LDAP_OPT_REBIND_PROC: {
807                               lo->ldo_rebind_proc = (LDAP_REBIND_PROC *)invalue;
808                     }
809                     rc = LDAP_OPT_SUCCESS;
810                     break;
811           case LDAP_OPT_REBIND_PARAMS: {
812                               lo->ldo_rebind_params = (void *)invalue;
813                     }
814                     rc = LDAP_OPT_SUCCESS;
815                     break;
816 
817           /* Only accessed from inside this function by ldap_set_nextref_proc() */
818           case LDAP_OPT_NEXTREF_PROC: {
819                               lo->ldo_nextref_proc = (LDAP_NEXTREF_PROC *)invalue;
820                     }
821                     rc = LDAP_OPT_SUCCESS;
822                     break;
823           case LDAP_OPT_NEXTREF_PARAMS: {
824                               lo->ldo_nextref_params = (void *)invalue;
825                     }
826                     rc = LDAP_OPT_SUCCESS;
827                     break;
828 
829           /* Only accessed from inside this function by ldap_set_urllist_proc() */
830           case LDAP_OPT_URLLIST_PROC: {
831                               lo->ldo_urllist_proc = (LDAP_URLLIST_PROC *)invalue;
832                     }
833                     rc = LDAP_OPT_SUCCESS;
834                     break;
835           case LDAP_OPT_URLLIST_PARAMS: {
836                               lo->ldo_urllist_params = (void *)invalue;
837                     }
838                     rc = LDAP_OPT_SUCCESS;
839                     break;
840 
841           /* read-only options */
842           case LDAP_OPT_API_INFO:
843           case LDAP_OPT_DESC:
844           case LDAP_OPT_SOCKBUF:
845           case LDAP_OPT_API_FEATURE_INFO:
846                     break;    /* LDAP_OPT_ERROR */
847 
848           /* options which cannot withstand invalue == NULL */
849           case LDAP_OPT_DEREF:
850           case LDAP_OPT_SIZELIMIT:
851           case LDAP_OPT_TIMELIMIT:
852           case LDAP_OPT_PROTOCOL_VERSION:
853           case LDAP_OPT_RESULT_CODE:
854           case LDAP_OPT_DEBUG_LEVEL:
855           case LDAP_OPT_TIMEOUT:
856           case LDAP_OPT_NETWORK_TIMEOUT:
857           case LDAP_OPT_CONNECT_CB:
858           case LDAP_OPT_X_KEEPALIVE_IDLE:
859           case LDAP_OPT_X_KEEPALIVE_PROBES :
860           case LDAP_OPT_X_KEEPALIVE_INTERVAL :
861           case LDAP_OPT_TCP_USER_TIMEOUT:
862                     if(invalue == NULL) {
863                               /* no place to set from */
864                               LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
865                               return ( LDAP_OPT_ERROR );
866                     }
867                     break;
868 
869           default:
870 #ifdef HAVE_TLS
871                     if ( ldap_pvt_tls_set_option( ld, option, (void *)invalue ) == 0 ) {
872                               LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
873                               return ( LDAP_OPT_SUCCESS );
874                     }
875 #endif
876 #ifdef HAVE_CYRUS_SASL
877                     if ( ldap_int_sasl_set_option( ld, option, (void *)invalue ) == 0 ) {
878                               LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
879                               return ( LDAP_OPT_SUCCESS );
880                     }
881 #endif
882 #ifdef HAVE_GSSAPI
883                     if ( ldap_int_gssapi_set_option( ld, option, (void *)invalue ) == 0 ) {
884                               LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
885                               return ( LDAP_OPT_SUCCESS );
886                     }
887 #endif
888                     /* bad param */
889                     break;    /* LDAP_OPT_ERROR */
890           }
891 
892           /* options which cannot withstand invalue == NULL */
893 
894           switch(option) {
895           case LDAP_OPT_DEREF:
896                     /* FIXME: check value for protocol compliance? */
897                     lo->ldo_deref = * (const int *) invalue;
898                     rc = LDAP_OPT_SUCCESS;
899                     break;
900 
901           case LDAP_OPT_SIZELIMIT:
902                     /* FIXME: check value for protocol compliance? */
903                     lo->ldo_sizelimit = * (const int *) invalue;
904                     rc = LDAP_OPT_SUCCESS;
905                     break;
906 
907           case LDAP_OPT_TIMELIMIT:
908                     /* FIXME: check value for protocol compliance? */
909                     lo->ldo_timelimit = * (const int *) invalue;
910                     rc = LDAP_OPT_SUCCESS;
911                     break;
912 
913           case LDAP_OPT_TIMEOUT: {
914                               const struct timeval *tv =
915                                         (const struct timeval *) invalue;
916 
917                               lo->ldo_tm_api = *tv;
918                     }
919                     rc = LDAP_OPT_SUCCESS;
920                     break;
921 
922           case LDAP_OPT_NETWORK_TIMEOUT: {
923                               const struct timeval *tv =
924                                         (const struct timeval *) invalue;
925 
926                               lo->ldo_tm_net = *tv;
927                     }
928                     rc = LDAP_OPT_SUCCESS;
929                     break;
930 
931           case LDAP_OPT_PROTOCOL_VERSION: {
932                               int vers = * (const int *) invalue;
933                               if (vers < LDAP_VERSION_MIN || vers > LDAP_VERSION_MAX) {
934                                         /* not supported */
935                                         break;
936                               }
937                               lo->ldo_version = vers;
938                     }
939                     rc = LDAP_OPT_SUCCESS;
940                     break;
941 
942           case LDAP_OPT_RESULT_CODE: {
943                               int err = * (const int *) invalue;
944 
945                               if(ld == NULL) {
946                                         /* need a struct ldap */
947                                         break;
948                               }
949 
950                               ld->ld_errno = err;
951                     }
952                     rc = LDAP_OPT_SUCCESS;
953                     break;
954 
955           case LDAP_OPT_DEBUG_LEVEL:
956                     lo->ldo_debug = * (const int *) invalue;
957                     rc = LDAP_OPT_SUCCESS;
958                     break;
959 
960           case LDAP_OPT_CONNECT_CB:
961                     {
962                               /* setting pushes the callback */
963                               ldaplist *ll;
964                               ll = LDAP_MALLOC( sizeof( *ll ));
965                               if ( ll == NULL ) {
966                                         rc = LDAP_NO_MEMORY;
967                                         break;
968                               }
969 
970                               ll->ll_data = (void *)invalue;
971                               ll->ll_next = lo->ldo_conn_cbs;
972                               lo->ldo_conn_cbs = ll;
973                     }
974                     rc = LDAP_OPT_SUCCESS;
975                     break;
976           case LDAP_OPT_X_KEEPALIVE_IDLE:
977                     lo->ldo_keepalive_idle = * (const int *) invalue;
978                     rc = LDAP_OPT_SUCCESS;
979                     break;
980           case LDAP_OPT_X_KEEPALIVE_PROBES :
981                     lo->ldo_keepalive_probes = * (const int *) invalue;
982                     rc = LDAP_OPT_SUCCESS;
983                     break;
984           case LDAP_OPT_X_KEEPALIVE_INTERVAL :
985                     lo->ldo_keepalive_interval = * (const int *) invalue;
986                     rc = LDAP_OPT_SUCCESS;
987                     break;
988           case LDAP_OPT_TCP_USER_TIMEOUT:
989                     lo->ldo_tcp_user_timeout = * (const unsigned int *) invalue;
990                     rc = LDAP_OPT_SUCCESS;
991                     break;
992 
993           }
994           LDAP_MUTEX_UNLOCK( &lo->ldo_mutex );
995           return ( rc );
996 }
997 
998 int
ldap_set_rebind_proc(LDAP * ld,LDAP_REBIND_PROC * proc,void * params)999 ldap_set_rebind_proc( LDAP *ld, LDAP_REBIND_PROC *proc, void *params )
1000 {
1001           int rc;
1002           rc = ldap_set_option( ld, LDAP_OPT_REBIND_PROC, (void *)proc );
1003           if( rc != LDAP_OPT_SUCCESS ) return rc;
1004 
1005           rc = ldap_set_option( ld, LDAP_OPT_REBIND_PARAMS, (void *)params );
1006           return rc;
1007 }
1008 
1009 int
ldap_set_nextref_proc(LDAP * ld,LDAP_NEXTREF_PROC * proc,void * params)1010 ldap_set_nextref_proc( LDAP *ld, LDAP_NEXTREF_PROC *proc, void *params )
1011 {
1012           int rc;
1013           rc = ldap_set_option( ld, LDAP_OPT_NEXTREF_PROC, (void *)proc );
1014           if( rc != LDAP_OPT_SUCCESS ) return rc;
1015 
1016           rc = ldap_set_option( ld, LDAP_OPT_NEXTREF_PARAMS, (void *)params );
1017           return rc;
1018 }
1019 
1020 int
ldap_set_urllist_proc(LDAP * ld,LDAP_URLLIST_PROC * proc,void * params)1021 ldap_set_urllist_proc( LDAP *ld, LDAP_URLLIST_PROC *proc, void *params )
1022 {
1023           int rc;
1024           rc = ldap_set_option( ld, LDAP_OPT_URLLIST_PROC, (void *)proc );
1025           if( rc != LDAP_OPT_SUCCESS ) return rc;
1026 
1027           rc = ldap_set_option( ld, LDAP_OPT_URLLIST_PARAMS, (void *)params );
1028           return rc;
1029 }
1030