1 /*
2 * Copyright 2002-2003 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 */
5
6 #pragma ident "%Z%%M% %I% %E% SMI"
7
8 /*
9 * The contents of this file are subject to the Netscape Public
10 * License Version 1.1 (the "License"); you may not use this file
11 * except in compliance with the License. You may obtain a copy of
12 * the License at http://www.mozilla.org/NPL/
13 *
14 * Software distributed under the License is distributed on an "AS
15 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
16 * implied. See the License for the specific language governing
17 * rights and limitations under the License.
18 *
19 * The Original Code is Mozilla Communicator client code, released
20 * March 31, 1998.
21 *
22 * The Initial Developer of the Original Code is Netscape
23 * Communications Corporation. Portions created by Netscape are
24 * Copyright (C) 1998-1999 Netscape Communications Corporation. All
25 * Rights Reserved.
26 *
27 * Contributor(s):
28 */
29 #include "ldap-int.h"
30
31 #define LDAP_GET_BITOPT( ld, bit ) \
32 ((ld)->ld_options & bit ) != 0 ? 1 : 0
33
34 static int nsldapi_get_api_info( LDAPAPIInfo *aip );
35 static int nsldapi_get_feature_info( LDAPAPIFeatureInfo *fip );
36
37
38 int
39 LDAP_CALL
ldap_get_option(LDAP * ld,int option,void * optdata)40 ldap_get_option( LDAP *ld, int option, void *optdata )
41 {
42 int rc = 0;
43
44 if ( !nsldapi_initialized ) {
45 nsldapi_initialize_defaults();
46 }
47
48 /*
49 * optdata MUST be a valid pointer...
50 */
51 if (NULL == optdata)
52 {
53 return(LDAP_PARAM_ERROR);
54 }
55 /*
56 * process global options (not associated with an LDAP session handle)
57 */
58 if ( option == LDAP_OPT_MEMALLOC_FN_PTRS ) {
59 /* struct copy */
60 *((struct ldap_memalloc_fns *)optdata) = nsldapi_memalloc_fns;
61 return( 0 );
62 }
63
64 if ( option == LDAP_OPT_API_INFO ) {
65 rc = nsldapi_get_api_info( (LDAPAPIInfo *)optdata );
66 if ( rc != LDAP_SUCCESS ) {
67 if ( ld != NULL ) {
68 LDAP_SET_LDERRNO( ld, rc, NULL, NULL );
69 }
70 return( -1 );
71 }
72 return( 0 );
73 }
74 /*
75 * LDAP_OPT_DEBUG_LEVEL is global
76 */
77 if (LDAP_OPT_DEBUG_LEVEL == option)
78 {
79 #ifdef LDAP_DEBUG
80 *((int *) optdata) = ldap_debug;
81 #endif /* LDAP_DEBUG */
82 return ( 0 );
83 }
84
85 /*
86 * if ld is NULL, arrange to return options from our default settings
87 */
88 if ( ld == NULL ) {
89 ld = &nsldapi_ld_defaults;
90 }
91
92 if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) {
93 return( -1 ); /* punt */
94 }
95
96
97 if (ld != &nsldapi_ld_defaults)
98 LDAP_MUTEX_LOCK( ld, LDAP_OPTION_LOCK );
99 switch( option ) {
100 #ifdef LDAP_DNS
101 case LDAP_OPT_DNS:
102 *((int *) optdata) = LDAP_GET_BITOPT( ld, LDAP_BITOPT_DNS );
103 break;
104 #endif
105
106 case LDAP_OPT_REFERRALS:
107 *((int *) optdata) =
108 LDAP_GET_BITOPT( ld, LDAP_BITOPT_REFERRALS );
109 break;
110
111 #ifdef LDAP_SSLIO_HOOKS
112 case LDAP_OPT_SSL:
113 *((int *) optdata) = LDAP_GET_BITOPT( ld, LDAP_BITOPT_SSL );
114 break;
115 #endif
116 case LDAP_OPT_RESTART:
117 *((int *) optdata) = LDAP_GET_BITOPT( ld, LDAP_BITOPT_RESTART );
118 break;
119
120 case LDAP_OPT_RECONNECT:
121 *((int *) optdata) =
122 LDAP_GET_BITOPT( ld, LDAP_BITOPT_RECONNECT );
123 break;
124
125 #ifdef LDAP_ASYNC_IO
126 case LDAP_OPT_ASYNC_CONNECT:
127 *((int *) optdata) =
128 LDAP_GET_BITOPT( ld, LDAP_BITOPT_ASYNC );
129 break;
130 #endif /* LDAP_ASYNC_IO */
131
132 /* stuff in the sockbuf */
133 case LDAP_X_OPT_SOCKBUF:
134 *((Sockbuf **) optdata) = ld->ld_sbp;
135 break;
136 case LDAP_OPT_DESC:
137 if ( ber_sockbuf_get_option( ld->ld_sbp,
138 LBER_SOCKBUF_OPT_DESC, optdata ) != 0 ) {
139 LDAP_SET_LDERRNO( ld, LDAP_LOCAL_ERROR, NULL, NULL );
140 rc = -1;
141 }
142 break;
143
144 /* fields in the LDAP structure */
145 case LDAP_OPT_DEREF:
146 *((int *) optdata) = ld->ld_deref;
147 break;
148 case LDAP_OPT_SIZELIMIT:
149 *((int *) optdata) = ld->ld_sizelimit;
150 break;
151 case LDAP_OPT_TIMELIMIT:
152 *((int *) optdata) = ld->ld_timelimit;
153 break;
154 case LDAP_OPT_REFERRAL_HOP_LIMIT:
155 *((int *) optdata) = ld->ld_refhoplimit;
156 break;
157 case LDAP_OPT_PROTOCOL_VERSION:
158 *((int *) optdata) = ld->ld_version;
159 break;
160 case LDAP_OPT_SERVER_CONTROLS:
161 /* fall through */
162 case LDAP_OPT_CLIENT_CONTROLS:
163 *((LDAPControl ***)optdata) = NULL;
164 /* nsldapi_dup_controls returns -1 and sets lderrno on error */
165 rc = nsldapi_dup_controls( ld, (LDAPControl ***)optdata,
166 ( option == LDAP_OPT_SERVER_CONTROLS ) ?
167 ld->ld_servercontrols : ld->ld_clientcontrols );
168 break;
169
170 /* rebind proc */
171 case LDAP_OPT_REBIND_FN:
172 *((LDAP_REBINDPROC_CALLBACK **) optdata) = ld->ld_rebind_fn;
173 break;
174 case LDAP_OPT_REBIND_ARG:
175 *((void **) optdata) = ld->ld_rebind_arg;
176 break;
177
178 #ifdef LDAP_SSLIO_HOOKS
179 /* i/o function pointers */
180 case LDAP_OPT_IO_FN_PTRS:
181 if ( ld->ld_io_fns_ptr == NULL ) {
182 memset( optdata, 0, sizeof( struct ldap_io_fns ));
183 } else {
184 /* struct copy */
185 *((struct ldap_io_fns *)optdata) = *(ld->ld_io_fns_ptr);
186 }
187 break;
188
189 /* extended i/o function pointers */
190 case LDAP_X_OPT_EXTIO_FN_PTRS:
191 if ( ((struct ldap_x_ext_io_fns *) optdata)->lextiof_size == LDAP_X_EXTIO_FNS_SIZE_REV0) {
192 ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_close = ld->ld_extclose_fn;
193 ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_connect = ld->ld_extconnect_fn;
194 ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_read = ld->ld_extread_fn;
195 ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_write = ld->ld_extwrite_fn;
196 ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_poll = ld->ld_extpoll_fn;
197 ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_newhandle = ld->ld_extnewhandle_fn;
198 ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_disposehandle = ld->ld_extdisposehandle_fn;
199 ((struct ldap_x_ext_io_fns_rev0 *) optdata)->lextiof_session_arg = ld->ld_ext_session_arg;
200 } else if ( ((struct ldap_x_ext_io_fns *) optdata)->lextiof_size ==
201 LDAP_X_EXTIO_FNS_SIZE ) {
202 /* struct copy */
203 *((struct ldap_x_ext_io_fns *) optdata) = ld->ld_ext_io_fns;
204 } else {
205 LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL );
206 rc = -1;
207 }
208 break;
209 #endif /* LDAP_SSLIO_HOOKS */
210
211 /* thread function pointers */
212 case LDAP_OPT_THREAD_FN_PTRS:
213 /* struct copy */
214 *((struct ldap_thread_fns *) optdata) = ld->ld_thread;
215 break;
216
217 /* DNS function pointers */
218 case LDAP_OPT_DNS_FN_PTRS:
219 /* struct copy */
220 *((struct ldap_dns_fns *) optdata) = ld->ld_dnsfn;
221 break;
222
223 /* cache function pointers */
224 case LDAP_OPT_CACHE_FN_PTRS:
225 /* struct copy */
226 *((struct ldap_cache_fns *) optdata) = ld->ld_cache;
227 break;
228 case LDAP_OPT_CACHE_STRATEGY:
229 *((int *) optdata) = ld->ld_cache_strategy;
230 break;
231 case LDAP_OPT_CACHE_ENABLE:
232 *((int *) optdata) = ld->ld_cache_on;
233 break;
234
235 case LDAP_OPT_ERROR_NUMBER:
236 *((int *) optdata) = LDAP_GET_LDERRNO( ld, NULL, NULL );
237 break;
238
239 case LDAP_OPT_ERROR_STRING:
240 (void)LDAP_GET_LDERRNO( ld, NULL, (char **)optdata );
241 *((char **) optdata) = nsldapi_strdup( *((char **) optdata ));
242 break;
243
244 case LDAP_OPT_MATCHED_DN:
245 (void)LDAP_GET_LDERRNO( ld, (char **)optdata, NULL );
246 *((char **) optdata) = nsldapi_strdup( *((char **) optdata ));
247 break;
248
249 case LDAP_OPT_PREFERRED_LANGUAGE:
250 if ( NULL != ld->ld_preferred_language ) {
251 *((char **) optdata) =
252 nsldapi_strdup(ld->ld_preferred_language);
253 } else {
254 *((char **) optdata) = NULL;
255 }
256 break;
257
258 case LDAP_OPT_API_FEATURE_INFO:
259 rc = nsldapi_get_feature_info( (LDAPAPIFeatureInfo *)optdata );
260 if ( rc != LDAP_SUCCESS ) {
261 LDAP_SET_LDERRNO( ld, rc, NULL, NULL );
262 rc = -1;
263 }
264 break;
265
266 case LDAP_OPT_HOST_NAME:
267 *((char **) optdata) = nsldapi_strdup( ld->ld_defhost );
268 break;
269
270 case LDAP_X_OPT_CONNECT_TIMEOUT:
271 *((int *) optdata) = ld->ld_connect_timeout;
272 break;
273
274 #ifdef LDAP_SASLIO_HOOKS
275 /* SASL options */
276 case LDAP_OPT_X_SASL_MECH:
277 *((char **) optdata) = nsldapi_strdup(ld->ld_def_sasl_mech);
278 break;
279 case LDAP_OPT_X_SASL_REALM:
280 *((char **) optdata) = nsldapi_strdup(ld->ld_def_sasl_realm);
281 break;
282 case LDAP_OPT_X_SASL_AUTHCID:
283 *((char **) optdata) = nsldapi_strdup(ld->ld_def_sasl_authcid);
284 break;
285 case LDAP_OPT_X_SASL_AUTHZID:
286 *((char **) optdata) = nsldapi_strdup(ld->ld_def_sasl_authzid);
287 break;
288 case LDAP_OPT_X_SASL_SSF:
289 {
290 int sc;
291 sasl_ssf_t *ssf;
292 sasl_conn_t *ctx;
293 if( ld->ld_defconn == NULL ||
294 ld->ld_defconn->lconn_sb == NULL ) {
295 return -1;
296 }
297 ctx = (sasl_conn_t *)(ld->ld_defconn->lconn_sb->sb_sasl_ctx);
298 if ( ctx == NULL ) {
299 return -1;
300 }
301 sc = sasl_getprop( ctx, SASL_SSF, (const void **) &ssf );
302 if ( sc != SASL_OK ) {
303 return -1;
304 }
305 *((sasl_ssf_t *) optdata) = *ssf;
306 }
307 break;
308 case LDAP_OPT_X_SASL_SSF_MIN:
309 *((sasl_ssf_t *) optdata) = ld->ld_sasl_secprops.min_ssf;
310 break;
311 case LDAP_OPT_X_SASL_SSF_MAX:
312 *((sasl_ssf_t *) optdata) = ld->ld_sasl_secprops.max_ssf;
313 break;
314 case LDAP_OPT_X_SASL_MAXBUFSIZE:
315 *((sasl_ssf_t *) optdata) = ld->ld_sasl_secprops.maxbufsize;
316 break;
317 case LDAP_OPT_X_SASL_SSF_EXTERNAL:
318 case LDAP_OPT_X_SASL_SECPROPS:
319 /*
320 * These options are write only. Making these options
321 * read/write would expose semi-private interfaces of libsasl
322 * for which there are no cross platform/standardized
323 * definitions.
324 */
325 LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL );
326 rc = -1;
327 break;
328 #endif
329
330 default:
331 LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL );
332 rc = -1;
333 }
334 if (ld != &nsldapi_ld_defaults)
335 LDAP_MUTEX_UNLOCK( ld, LDAP_OPTION_LOCK );
336 return( rc );
337 }
338
339
340 /*
341 * Table of extended API features we support.
342 * The first field is the version of the info. strcuture itself; we do not
343 * use the ones from this table so it is okay to leave as zero.
344 */
345 static LDAPAPIFeatureInfo nsldapi_extensions[] = {
346 { 0, "SERVER_SIDE_SORT", LDAP_API_FEATURE_SERVER_SIDE_SORT },
347 { 0, "VIRTUAL_LIST_VIEW", LDAP_API_FEATURE_VIRTUAL_LIST_VIEW },
348 { 0, "PERSISTENT_SEARCH", LDAP_API_FEATURE_PERSISTENT_SEARCH },
349 { 0, "PROXY_AUTHORIZATION", LDAP_API_FEATURE_PROXY_AUTHORIZATION },
350 { 0, "X_LDERRNO", LDAP_API_FEATURE_X_LDERRNO },
351 { 0, "X_MEMCACHE", LDAP_API_FEATURE_X_MEMCACHE },
352 { 0, "X_IO_FUNCTIONS", LDAP_API_FEATURE_X_IO_FUNCTIONS },
353 { 0, "X_EXTIO_FUNCTIONS", LDAP_API_FEATURE_X_EXTIO_FUNCTIONS },
354 { 0, "X_DNS_FUNCTIONS", LDAP_API_FEATURE_X_DNS_FUNCTIONS },
355 { 0, "X_MEMALLOC_FUNCTIONS", LDAP_API_FEATURE_X_MEMALLOC_FUNCTIONS },
356 { 0, "X_THREAD_FUNCTIONS", LDAP_API_FEATURE_X_THREAD_FUNCTIONS },
357 { 0, "X_EXTHREAD_FUNCTIONS", LDAP_API_FEATURE_X_EXTHREAD_FUNCTIONS },
358 { 0, "X_GETLANGVALUES", LDAP_API_FEATURE_X_GETLANGVALUES },
359 { 0, "X_CLIENT_SIDE_SORT", LDAP_API_FEATURE_X_CLIENT_SIDE_SORT },
360 { 0, "X_URL_FUNCTIONS", LDAP_API_FEATURE_X_URL_FUNCTIONS },
361 { 0, "X_FILTER_FUNCTIONS", LDAP_API_FEATURE_X_FILTER_FUNCTIONS },
362 };
363
364 #define NSLDAPI_EXTENSIONS_COUNT \
365 (sizeof(nsldapi_extensions)/sizeof(LDAPAPIFeatureInfo))
366
367 /*
368 * Retrieve information about this implementation of the LDAP API.
369 * Returns an LDAP error code.
370 */
371 static int
nsldapi_get_api_info(LDAPAPIInfo * aip)372 nsldapi_get_api_info( LDAPAPIInfo *aip )
373 {
374 int i;
375
376 if ( aip == NULL ) {
377 return( LDAP_PARAM_ERROR );
378 }
379
380 aip->ldapai_api_version = LDAP_API_VERSION;
381
382 if ( aip->ldapai_info_version != LDAP_API_INFO_VERSION ) {
383 aip->ldapai_info_version = LDAP_API_INFO_VERSION;
384 return( LDAP_PARAM_ERROR );
385 }
386
387 aip->ldapai_protocol_version = LDAP_VERSION_MAX;
388 aip->ldapai_vendor_version = LDAP_VENDOR_VERSION;
389
390 if (( aip->ldapai_vendor_name = nsldapi_strdup( LDAP_VENDOR_NAME ))
391 == NULL ) {
392 return( LDAP_NO_MEMORY );
393 }
394
395 if ( NSLDAPI_EXTENSIONS_COUNT < 1 ) {
396 aip->ldapai_extensions = NULL;
397 } else {
398 if (( aip->ldapai_extensions = NSLDAPI_CALLOC(
399 NSLDAPI_EXTENSIONS_COUNT + 1, sizeof(char *))) == NULL ) {
400 NSLDAPI_FREE( aip->ldapai_vendor_name );
401 aip->ldapai_vendor_name = NULL;
402 return( LDAP_NO_MEMORY );
403 }
404
405 for ( i = 0; i < NSLDAPI_EXTENSIONS_COUNT; ++i ) {
406 if (( aip->ldapai_extensions[i] = nsldapi_strdup(
407 nsldapi_extensions[i].ldapaif_name )) == NULL ) {
408 ldap_value_free( aip->ldapai_extensions );
409 NSLDAPI_FREE( aip->ldapai_vendor_name );
410 aip->ldapai_extensions = NULL;
411 aip->ldapai_vendor_name = NULL;
412 return( LDAP_NO_MEMORY );
413 }
414 }
415 }
416
417 return( LDAP_SUCCESS );
418 }
419
420
421 /*
422 * Retrieves information about a specific extended feature of the LDAP API/
423 * Returns an LDAP error code.
424 */
425 static int
nsldapi_get_feature_info(LDAPAPIFeatureInfo * fip)426 nsldapi_get_feature_info( LDAPAPIFeatureInfo *fip )
427 {
428 int i;
429
430 if ( fip == NULL || fip->ldapaif_name == NULL ) {
431 return( LDAP_PARAM_ERROR );
432 }
433
434 if ( fip->ldapaif_info_version != LDAP_FEATURE_INFO_VERSION ) {
435 fip->ldapaif_info_version = LDAP_FEATURE_INFO_VERSION;
436 return( LDAP_PARAM_ERROR );
437 }
438
439 for ( i = 0; i < NSLDAPI_EXTENSIONS_COUNT; ++i ) {
440 if ( strcmp( fip->ldapaif_name,
441 nsldapi_extensions[i].ldapaif_name ) == 0 ) {
442 fip->ldapaif_version =
443 nsldapi_extensions[i].ldapaif_version;
444 break;
445 }
446 }
447
448 return(( i < NSLDAPI_EXTENSIONS_COUNT ) ? LDAP_SUCCESS
449 : LDAP_PARAM_ERROR );
450 }
451