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