1 /* 2 * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 * The contents of this file are subject to the Netscape Public 8 * License Version 1.1 (the "License"); you may not use this file 9 * except in compliance with the License. You may obtain a copy of 10 * the License at http://www.mozilla.org/NPL/ 11 * 12 * Software distributed under the License is distributed on an "AS 13 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or 14 * implied. See the License for the specific language governing 15 * rights and limitations under the License. 16 * 17 * The Original Code is Mozilla Communicator client code, released 18 * March 31, 1998. 19 * 20 * The Initial Developer of the Original Code is Netscape 21 * Communications Corporation. Portions created by Netscape are 22 * Copyright (C) 1998-1999 Netscape Communications Corporation. All 23 * Rights Reserved. 24 * 25 * Contributor(s): 26 */ 27 /* 28 * setoption.c - ldap_set_option implementation 29 */ 30 31 #include "ldap-int.h" 32 #ifdef _SOLARIS_SDK 33 #include "solaris-priv.h" 34 #endif 35 36 extern int nsldapi_sasl_secprops(const char *in, 37 sasl_security_properties_t *secprops); 38 39 #define LDAP_SETCLR_BITOPT(ld, bit, optdata) \ 40 if (optdata != NULL) { \ 41 (ld)->ld_options |= bit; \ 42 } else { \ 43 (ld)->ld_options &= ~bit; \ 44 } 45 46 47 int 48 LDAP_CALL 49 ldap_set_option(LDAP *ld, int option, const void *optdata) 50 { 51 int rc, i; 52 char *matched, *errstr; 53 54 if (!nsldapi_initialized) { 55 nsldapi_initialize_defaults(); 56 } 57 58 /* 59 * process global options (not associated with an LDAP session handle) 60 */ 61 if (option == LDAP_OPT_MEMALLOC_FN_PTRS) { 62 struct lber_memalloc_fns memalloc_fns; 63 64 /* set libldap ones via a struct copy */ 65 nsldapi_memalloc_fns = *((struct ldap_memalloc_fns *)optdata); 66 67 /* also set liblber memory allocation callbacks */ 68 memalloc_fns.lbermem_malloc = 69 nsldapi_memalloc_fns.ldapmem_malloc; 70 memalloc_fns.lbermem_calloc = 71 nsldapi_memalloc_fns.ldapmem_calloc; 72 memalloc_fns.lbermem_realloc = 73 nsldapi_memalloc_fns.ldapmem_realloc; 74 memalloc_fns.lbermem_free = 75 nsldapi_memalloc_fns.ldapmem_free; 76 if (ber_set_option(NULL, LBER_OPT_MEMALLOC_FN_PTRS, 77 &memalloc_fns) != 0) { 78 return (-1); 79 } 80 81 return (0); 82 } 83 /* 84 * LDAP_OPT_DEBUG_LEVEL is global 85 */ 86 if (LDAP_OPT_DEBUG_LEVEL == option) { 87 #ifdef LDAP_DEBUG 88 ldap_debug = *((int *)optdata); 89 #endif 90 return (0); 91 } 92 93 /* 94 * if ld is NULL, arrange to modify our default settings 95 */ 96 if (ld == NULL) { 97 ld = &nsldapi_ld_defaults; 98 #ifdef LDAP_DEBUG 99 ldap_debug = 0; 100 #endif 101 102 } 103 104 /* 105 * process options that are associated with an LDAP session handle 106 */ 107 if (!NSLDAPI_VALID_LDAP_POINTER(ld)) { 108 return (-1); /* punt */ 109 } 110 111 rc = 0; 112 if (ld != &nsldapi_ld_defaults && 113 option != LDAP_OPT_EXTRA_THREAD_FN_PTRS && 114 option != LDAP_OPT_THREAD_FN_PTRS) { 115 LDAP_MUTEX_LOCK(ld, LDAP_OPTION_LOCK); 116 } 117 switch (option) { 118 /* options that can be turned on and off */ 119 #ifdef LDAP_DNS 120 case LDAP_OPT_DNS: 121 LDAP_SETCLR_BITOPT(ld, LDAP_BITOPT_DNS, optdata); 122 break; 123 #endif 124 125 case LDAP_OPT_REFERRALS: 126 LDAP_SETCLR_BITOPT(ld, LDAP_BITOPT_REFERRALS, optdata); 127 break; 128 129 #ifdef LDAP_SSLIO_HOOKS 130 case LDAP_OPT_SSL: 131 LDAP_SETCLR_BITOPT(ld, LDAP_BITOPT_SSL, optdata); 132 break; 133 #endif 134 135 case LDAP_OPT_RESTART: 136 LDAP_SETCLR_BITOPT(ld, LDAP_BITOPT_RESTART, optdata); 137 break; 138 139 case LDAP_OPT_RECONNECT: 140 LDAP_SETCLR_BITOPT(ld, LDAP_BITOPT_RECONNECT, optdata); 141 break; 142 143 #ifdef LDAP_ASYNC_IO 144 case LDAP_OPT_ASYNC_CONNECT: 145 LDAP_SETCLR_BITOPT(ld, LDAP_BITOPT_ASYNC, optdata); 146 break; 147 #endif /* LDAP_ASYNC_IO */ 148 149 /* fields in the LDAP structure */ 150 case LDAP_OPT_DEREF: 151 ld->ld_deref = *((int *)optdata); 152 break; 153 case LDAP_OPT_SIZELIMIT: 154 ld->ld_sizelimit = *((int *)optdata); 155 break; 156 case LDAP_OPT_TIMELIMIT: 157 ld->ld_timelimit = *((int *)optdata); 158 break; 159 case LDAP_OPT_REFERRAL_HOP_LIMIT: 160 ld->ld_refhoplimit = *((int *)optdata); 161 break; 162 case LDAP_OPT_PROTOCOL_VERSION: 163 ld->ld_version = *((int *)optdata); 164 if (ld->ld_defconn != NULL) { /* also set in default conn. */ 165 ld->ld_defconn->lconn_version = ld->ld_version; 166 } 167 break; 168 case LDAP_OPT_SERVER_CONTROLS: 169 /* nsldapi_dup_controls returns -1 and sets lderrno on error */ 170 rc = nsldapi_dup_controls(ld, &ld->ld_servercontrols, 171 (LDAPControl **)optdata); 172 break; 173 case LDAP_OPT_CLIENT_CONTROLS: 174 /* nsldapi_dup_controls returns -1 and sets lderrno on error */ 175 rc = nsldapi_dup_controls(ld, &ld->ld_clientcontrols, 176 (LDAPControl **)optdata); 177 break; 178 179 /* rebind proc */ 180 case LDAP_OPT_REBIND_FN: 181 ld->ld_rebind_fn = (LDAP_REBINDPROC_CALLBACK *) optdata; 182 break; 183 case LDAP_OPT_REBIND_ARG: 184 ld->ld_rebind_arg = (void *) optdata; 185 break; 186 187 #ifdef LDAP_SSLIO_HOOKS 188 /* i/o function pointers */ 189 case LDAP_OPT_IO_FN_PTRS: 190 if ((rc = nsldapi_install_compat_io_fns(ld, 191 (struct ldap_io_fns *)optdata)) != LDAP_SUCCESS) { 192 LDAP_SET_LDERRNO(ld, rc, NULL, NULL); 193 rc = -1; 194 } 195 break; 196 197 /* extended i/o function pointers */ 198 case LDAP_X_OPT_EXTIO_FN_PTRS: 199 /* denotes use of old iofns struct (no writev) */ 200 if (((struct ldap_x_ext_io_fns_rev0 *)optdata)->lextiof_size == 201 LDAP_X_EXTIO_FNS_SIZE_REV0) { 202 ld->ld_extio_size = LDAP_X_EXTIO_FNS_SIZE; 203 ld->ld_extclose_fn = 204 ((struct ldap_x_ext_io_fns_rev0 *)optdata)->lextiof_close; 205 ld->ld_extconnect_fn = 206 ((struct ldap_x_ext_io_fns_rev0 *)optdata)->lextiof_connect; 207 ld->ld_extread_fn = 208 ((struct ldap_x_ext_io_fns_rev0 *)optdata)->lextiof_read; 209 ld->ld_extwrite_fn = 210 ((struct ldap_x_ext_io_fns_rev0 *)optdata)->lextiof_write; 211 ld->ld_extpoll_fn = 212 ((struct ldap_x_ext_io_fns_rev0 *)optdata)->lextiof_poll; 213 ld->ld_extnewhandle_fn = 214 ((struct ldap_x_ext_io_fns_rev0 *)optdata)->lextiof_newhandle; 215 ld->ld_extdisposehandle_fn = 216 ((struct ldap_x_ext_io_fns_rev0 *)optdata)-> 217 lextiof_disposehandle; 218 ld->ld_ext_session_arg = 219 ((struct ldap_x_ext_io_fns_rev0 *)optdata)->lextiof_session_arg; 220 ld->ld_extwritev_fn = NULL; 221 if (ber_sockbuf_set_option(ld->ld_sbp, LBER_SOCKBUF_OPT_EXT_IO_FNS, 222 &(ld->ld_ext_io_fns)) != 0) { 223 return (LDAP_LOCAL_ERROR); 224 } 225 } else { 226 /* struct copy */ 227 ld->ld_ext_io_fns = *((struct ldap_x_ext_io_fns *)optdata); 228 } 229 if ((rc = nsldapi_install_lber_extiofns(ld, ld->ld_sbp)) 230 != LDAP_SUCCESS) { 231 LDAP_SET_LDERRNO(ld, rc, NULL, NULL); 232 rc = -1; 233 } 234 break; 235 #endif 236 237 /* thread function pointers */ 238 case LDAP_OPT_THREAD_FN_PTRS: 239 /* 240 * It is only safe to set the thread function pointers 241 * when one thread is using the LDAP session handle. 242 */ 243 /* free existing mutexes (some are allocated by ldap_init()) */ 244 nsldapi_mutex_free_all(ld); 245 246 /* struct copy */ 247 ld->ld_thread = *((struct ldap_thread_fns *)optdata); 248 249 /* allocate new mutexes */ 250 nsldapi_mutex_alloc_all(ld); 251 252 /* LDAP_OPTION_LOCK was never locked... so just return */ 253 return (rc); 254 255 /* extra thread function pointers */ 256 case LDAP_OPT_EXTRA_THREAD_FN_PTRS: 257 /* The extra thread funcs will only pick up the threadid */ 258 ld->ld_thread2 = *((struct ldap_extra_thread_fns *)optdata); 259 260 /* Reset the rest of the structure preserving the threadid fn */ 261 ld->ld_mutex_trylock_fn = (LDAP_TF_MUTEX_TRYLOCK_CALLBACK *)NULL; 262 ld->ld_sema_alloc_fn = (LDAP_TF_SEMA_ALLOC_CALLBACK *) NULL; 263 ld->ld_sema_free_fn = (LDAP_TF_SEMA_FREE_CALLBACK *) NULL; 264 ld->ld_sema_wait_fn = (LDAP_TF_SEMA_WAIT_CALLBACK *) NULL; 265 ld->ld_sema_post_fn = (LDAP_TF_SEMA_POST_CALLBACK *) NULL; 266 267 /* We assume that only one thread is active when replacing */ 268 /* the threadid function. We will now proceed and reset all */ 269 /* of the threadid/refcounts */ 270 for (i = 0; i < LDAP_MAX_LOCK; i++) { 271 ld->ld_mutex_threadid[i] = (void *) -1; 272 ld->ld_mutex_refcnt[i] = 0; 273 } 274 275 return (rc); 276 277 /* DNS function pointers */ 278 case LDAP_OPT_DNS_FN_PTRS: 279 /* struct copy */ 280 ld->ld_dnsfn = *((struct ldap_dns_fns *)optdata); 281 break; 282 283 /* cache function pointers */ 284 case LDAP_OPT_CACHE_FN_PTRS: 285 /* struct copy */ 286 ld->ld_cache = *((struct ldap_cache_fns *)optdata); 287 break; 288 case LDAP_OPT_CACHE_STRATEGY: 289 ld->ld_cache_strategy = *((int *)optdata); 290 break; 291 case LDAP_OPT_CACHE_ENABLE: 292 ld->ld_cache_on = *((int *)optdata); 293 break; 294 295 case LDAP_OPT_ERROR_NUMBER: 296 LDAP_GET_LDERRNO(ld, &matched, &errstr); 297 matched = nsldapi_strdup(matched); 298 errstr = nsldapi_strdup(errstr); 299 LDAP_SET_LDERRNO(ld, *((int *)optdata), matched, errstr); 300 break; 301 302 case LDAP_OPT_ERROR_STRING: 303 rc = LDAP_GET_LDERRNO(ld, &matched, NULL); 304 matched = nsldapi_strdup(matched); 305 LDAP_SET_LDERRNO(ld, rc, matched, 306 nsldapi_strdup((char *)optdata)); 307 rc = LDAP_SUCCESS; 308 break; 309 310 case LDAP_OPT_MATCHED_DN: 311 rc = LDAP_GET_LDERRNO(ld, NULL, &errstr); 312 errstr = nsldapi_strdup(errstr); 313 LDAP_SET_LDERRNO(ld, rc, 314 nsldapi_strdup((char *)optdata), errstr); 315 rc = LDAP_SUCCESS; 316 break; 317 318 case LDAP_OPT_PREFERRED_LANGUAGE: 319 if (NULL != ld->ld_preferred_language) { 320 NSLDAPI_FREE(ld->ld_preferred_language); 321 } 322 ld->ld_preferred_language = nsldapi_strdup((char *)optdata); 323 break; 324 325 case LDAP_OPT_HOST_NAME: 326 if (NULL != ld->ld_defhost) { 327 NSLDAPI_FREE(ld->ld_defhost); 328 } 329 ld->ld_defhost = nsldapi_strdup((char *)optdata); 330 break; 331 332 case LDAP_X_OPT_CONNECT_TIMEOUT: 333 ld->ld_connect_timeout = *((int *)optdata); 334 break; 335 336 #ifdef _SOLARIS_SDK 337 /* recursion prevention dns functions */ 338 case LDAP_X_OPT_DNS_SKIPDB: 339 rc = prldap_x_install_dns_skipdb(ld, (const char *)optdata); 340 break; 341 #endif 342 #ifdef LDAP_SASLIO_HOOKS 343 /* SASL options */ 344 case LDAP_OPT_X_SASL_MECH: 345 if (NULL != ld->ld_def_sasl_mech) { 346 347 NSLDAPI_FREE(ld->ld_def_sasl_mech); 348 } 349 ld->ld_def_sasl_mech = nsldapi_strdup((char *)optdata); 350 break; 351 case LDAP_OPT_X_SASL_REALM: 352 if (NULL != ld->ld_def_sasl_realm) { 353 NSLDAPI_FREE(ld->ld_def_sasl_realm); 354 } 355 ld->ld_def_sasl_realm = nsldapi_strdup((char *)optdata); 356 break; 357 case LDAP_OPT_X_SASL_AUTHCID: 358 if (NULL != ld->ld_def_sasl_authcid) { 359 NSLDAPI_FREE(ld->ld_def_sasl_authcid); 360 } 361 ld->ld_def_sasl_authcid = nsldapi_strdup((char *)optdata); 362 break; 363 case LDAP_OPT_X_SASL_AUTHZID: 364 if (NULL != ld->ld_def_sasl_authzid) { 365 NSLDAPI_FREE(ld->ld_def_sasl_authzid); 366 } 367 ld->ld_def_sasl_authzid = nsldapi_strdup((char *)optdata); 368 break; 369 case LDAP_OPT_X_SASL_SSF_EXTERNAL: 370 { 371 int sc; 372 sasl_ssf_t extprops; 373 sasl_conn_t *ctx; 374 if (ld->ld_defconn == NULL || 375 ld->ld_defconn->lconn_sb == NULL) { 376 return (-1); 377 } 378 ctx = (sasl_conn_t *) 379 (ld->ld_defconn->lconn_sb->sb_sasl_ctx); 380 if (ctx == NULL) { 381 return (-1); 382 } 383 memset(&extprops, 0L, sizeof (extprops)); 384 extprops = * ((sasl_ssf_t *)optdata); 385 sc = sasl_setprop(ctx, SASL_SSF_EXTERNAL, 386 (void *) &extprops); 387 if (sc != SASL_OK) { 388 return (-1); 389 } 390 } 391 break; 392 case LDAP_OPT_X_SASL_SECPROPS: 393 { 394 int sc; 395 sc = nsldapi_sasl_secprops((char *)optdata, 396 &ld->ld_sasl_secprops); 397 return (sc == LDAP_SUCCESS ? 0 : -1); 398 } 399 case LDAP_OPT_X_SASL_SSF_MIN: 400 ld->ld_sasl_secprops.min_ssf = *((sasl_ssf_t *)optdata); 401 break; 402 case LDAP_OPT_X_SASL_SSF_MAX: 403 ld->ld_sasl_secprops.max_ssf = *((sasl_ssf_t *)optdata); 404 break; 405 case LDAP_OPT_X_SASL_MAXBUFSIZE: 406 ld->ld_sasl_secprops.maxbufsize = *((sasl_ssf_t *)optdata); 407 break; 408 case LDAP_OPT_X_SASL_SSF: /* read only */ 409 LDAP_SET_LDERRNO(ld, LDAP_PARAM_ERROR, NULL, NULL); 410 rc = -1; 411 break; 412 #endif 413 414 default: 415 LDAP_SET_LDERRNO(ld, LDAP_PARAM_ERROR, NULL, NULL); 416 rc = -1; 417 } 418 419 if (ld != &nsldapi_ld_defaults) { 420 LDAP_MUTEX_UNLOCK(ld, LDAP_OPTION_LOCK); 421 } 422 return (rc); 423 } 424