2 * WLDAP32 - LDAP support for Wine
4 * Copyright 2005 Hans Leidekker
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #include "wine/debug.h"
28 #include "winldap_private.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(wldap32
);
32 #ifndef LDAP_OPT_SERVER_CONTROLS
33 #define LDAP_OPT_SERVER_CONTROLS 0x0012
36 /***********************************************************************
37 * ldap_get_optionA (WLDAP32.@)
39 * See ldap_get_optionW.
41 ULONG CDECL
ldap_get_optionA( LDAP
*ld
, int option
, void *value
)
45 TRACE( "(%p, 0x%08x, %p)\n", ld
, option
, value
);
47 if (!ld
|| !value
) return LDAP_PARAM_ERROR
;
51 case LDAP_OPT_API_FEATURE_INFO
:
53 LDAPAPIFeatureInfoW featureW
;
54 LDAPAPIFeatureInfoA
*featureA
= value
;
56 if (!featureA
->ldapaif_name
) return LDAP_PARAM_ERROR
;
58 featureW
.ldapaif_info_version
= featureA
->ldapaif_info_version
;
59 if (!(featureW
.ldapaif_name
= strAtoW( featureA
->ldapaif_name
))) return LDAP_NO_MEMORY
;
60 featureW
.ldapaif_version
= 0;
62 ret
= ldap_get_optionW( ld
, option
, &featureW
);
64 if (ret
== LDAP_SUCCESS
) featureA
->ldapaif_version
= featureW
.ldapaif_version
;
65 free( featureW
.ldapaif_name
);
68 case LDAP_OPT_API_INFO
:
71 LDAPAPIInfoA
*infoA
= value
;
73 memset( &infoW
, 0, sizeof(infoW
) );
74 infoW
.ldapai_info_version
= infoA
->ldapai_info_version
;
76 ret
= ldap_get_optionW( ld
, option
, &infoW
);
77 if (ret
== LDAP_SUCCESS
)
79 infoA
->ldapai_api_version
= infoW
.ldapai_api_version
;
80 infoA
->ldapai_protocol_version
= infoW
.ldapai_protocol_version
;
82 if (infoW
.ldapai_extensions
&& !(infoA
->ldapai_extensions
= strarrayWtoA( infoW
.ldapai_extensions
)))
83 return LDAP_NO_MEMORY
;
84 if (infoW
.ldapai_vendor_name
&& !(infoA
->ldapai_vendor_name
= strWtoA( infoW
.ldapai_vendor_name
)))
86 ldap_value_freeW( infoW
.ldapai_extensions
);
87 return LDAP_NO_MEMORY
;
89 infoA
->ldapai_vendor_version
= infoW
.ldapai_vendor_version
;
91 ldap_value_freeW( infoW
.ldapai_extensions
);
92 ldap_memfreeW( infoW
.ldapai_vendor_name
);
99 case LDAP_OPT_ERROR_NUMBER
:
100 case LDAP_OPT_PROTOCOL_VERSION
:
101 case LDAP_OPT_REFERRALS
:
102 case LDAP_OPT_SIZELIMIT
:
103 case LDAP_OPT_TIMELIMIT
:
104 return ldap_get_optionW( ld
, option
, value
);
106 case LDAP_OPT_CACHE_ENABLE
:
107 case LDAP_OPT_CACHE_FN_PTRS
:
108 case LDAP_OPT_CACHE_STRATEGY
:
109 case LDAP_OPT_IO_FN_PTRS
:
110 case LDAP_OPT_REBIND_ARG
:
111 case LDAP_OPT_REBIND_FN
:
112 case LDAP_OPT_RESTART
:
113 case LDAP_OPT_THREAD_FN_PTRS
:
114 return LDAP_LOCAL_ERROR
;
116 case LDAP_OPT_AREC_EXCLUSIVE
:
117 case LDAP_OPT_AUTO_RECONNECT
:
118 case LDAP_OPT_CLIENT_CERTIFICATE
:
119 case LDAP_OPT_DNSDOMAIN_NAME
:
120 case LDAP_OPT_ENCRYPT
:
121 case LDAP_OPT_ERROR_STRING
:
122 case LDAP_OPT_FAST_CONCURRENT_BIND
:
123 case LDAP_OPT_GETDSNAME_FLAGS
:
124 case LDAP_OPT_HOST_NAME
:
125 case LDAP_OPT_HOST_REACHABLE
:
126 case LDAP_OPT_PING_KEEP_ALIVE
:
127 case LDAP_OPT_PING_LIMIT
:
128 case LDAP_OPT_PING_WAIT_TIME
:
129 case LDAP_OPT_PROMPT_CREDENTIALS
:
130 case LDAP_OPT_REF_DEREF_CONN_PER_MSG
:
131 case LDAP_OPT_REFERRAL_CALLBACK
:
132 case LDAP_OPT_REFERRAL_HOP_LIMIT
:
133 case LDAP_OPT_ROOTDSE_CACHE
:
134 case LDAP_OPT_SASL_METHOD
:
135 case LDAP_OPT_SECURITY_CONTEXT
:
136 case LDAP_OPT_SEND_TIMEOUT
:
137 case LDAP_OPT_SERVER_CERTIFICATE
:
138 case LDAP_OPT_SERVER_CONTROLS
:
139 case LDAP_OPT_SERVER_ERROR
:
140 case LDAP_OPT_SERVER_EXT_ERROR
:
143 case LDAP_OPT_SSL_INFO
:
144 case LDAP_OPT_SSPI_FLAGS
:
145 case LDAP_OPT_TCP_KEEPALIVE
:
146 FIXME( "Unsupported option: 0x%02x\n", option
);
147 return LDAP_NOT_SUPPORTED
;
150 FIXME( "Unknown option: 0x%02x\n", option
);
151 return LDAP_LOCAL_ERROR
;
155 /***********************************************************************
156 * ldap_get_optionW (WLDAP32.@)
158 * Retrieve option values for a given LDAP context.
161 * ld [I] Pointer to an LDAP context.
162 * option [I] Option to get values for.
163 * value [O] Pointer to option values.
166 * Success: LDAP_SUCCESS
167 * Failure: An LDAP error code.
169 ULONG CDECL
ldap_get_optionW( LDAP
*ld
, int option
, void *value
)
173 TRACE( "(%p, 0x%08x, %p)\n", ld
, option
, value
);
175 if (!ld
|| !value
) return LDAP_PARAM_ERROR
;
179 case LDAP_OPT_API_FEATURE_INFO
:
181 LDAPAPIFeatureInfoU featureU
;
182 LDAPAPIFeatureInfoW
*featureW
= value
;
184 if (!featureW
->ldapaif_name
) return LDAP_PARAM_ERROR
;
186 featureU
.ldapaif_info_version
= featureW
->ldapaif_info_version
;
187 if ((featureU
.ldapaif_name
= strWtoU( featureW
->ldapaif_name
)))
189 struct ldap_get_option_params params
= { CTX(ld
), option
, &featureU
};
190 featureU
.ldapaif_version
= 0;
191 ret
= map_error( LDAP_CALL( ldap_get_option
, ¶ms
));
193 else return LDAP_NO_MEMORY
;
195 if (ret
== LDAP_SUCCESS
) featureW
->ldapaif_version
= featureU
.ldapaif_version
;
196 free( featureU
.ldapaif_name
);
199 case LDAP_OPT_API_INFO
:
202 LDAPAPIInfoW
*infoW
= value
;
203 struct ldap_get_option_params params
= { CTX(ld
), option
, &infoU
};
205 memset( &infoU
, 0, sizeof(infoU
) );
206 infoU
.ldapai_info_version
= infoW
->ldapai_info_version
;
208 ret
= map_error( LDAP_CALL( ldap_get_option
, ¶ms
));
209 if (ret
== LDAP_SUCCESS
)
211 infoW
->ldapai_api_version
= infoU
.ldapai_api_version
;
212 infoW
->ldapai_protocol_version
= infoU
.ldapai_protocol_version
;
214 if (infoU
.ldapai_extensions
&& !(infoW
->ldapai_extensions
= strarrayUtoW( infoU
.ldapai_extensions
)))
215 return LDAP_NO_MEMORY
;
216 if (infoU
.ldapai_vendor_name
&& !(infoW
->ldapai_vendor_name
= strUtoW( infoU
.ldapai_vendor_name
)))
218 LDAP_CALL( ldap_memvfree
, infoU
.ldapai_extensions
);
219 return LDAP_NO_MEMORY
;
221 infoW
->ldapai_vendor_version
= infoU
.ldapai_vendor_version
;
223 LDAP_CALL( ldap_memvfree
, infoU
.ldapai_extensions
);
224 LDAP_CALL( ldap_memfree
, infoU
.ldapai_vendor_name
);
231 case LDAP_OPT_ERROR_NUMBER
:
232 case LDAP_OPT_PROTOCOL_VERSION
:
233 case LDAP_OPT_REFERRALS
:
234 case LDAP_OPT_SIZELIMIT
:
235 case LDAP_OPT_TIMELIMIT
:
237 struct ldap_get_option_params params
= { CTX(ld
), option
, value
};
238 return map_error( LDAP_CALL( ldap_get_option
, ¶ms
));
241 case LDAP_OPT_CACHE_ENABLE
:
242 case LDAP_OPT_CACHE_FN_PTRS
:
243 case LDAP_OPT_CACHE_STRATEGY
:
244 case LDAP_OPT_IO_FN_PTRS
:
245 case LDAP_OPT_REBIND_ARG
:
246 case LDAP_OPT_REBIND_FN
:
247 case LDAP_OPT_RESTART
:
248 case LDAP_OPT_THREAD_FN_PTRS
:
249 return LDAP_LOCAL_ERROR
;
251 case LDAP_OPT_AREC_EXCLUSIVE
:
252 case LDAP_OPT_AUTO_RECONNECT
:
253 case LDAP_OPT_CLIENT_CERTIFICATE
:
254 case LDAP_OPT_DNSDOMAIN_NAME
:
255 case LDAP_OPT_ENCRYPT
:
256 case LDAP_OPT_ERROR_STRING
:
257 case LDAP_OPT_FAST_CONCURRENT_BIND
:
258 case LDAP_OPT_GETDSNAME_FLAGS
:
259 case LDAP_OPT_HOST_NAME
:
260 case LDAP_OPT_HOST_REACHABLE
:
261 case LDAP_OPT_PING_KEEP_ALIVE
:
262 case LDAP_OPT_PING_LIMIT
:
263 case LDAP_OPT_PING_WAIT_TIME
:
264 case LDAP_OPT_PROMPT_CREDENTIALS
:
265 case LDAP_OPT_REF_DEREF_CONN_PER_MSG
:
266 case LDAP_OPT_REFERRAL_CALLBACK
:
267 case LDAP_OPT_REFERRAL_HOP_LIMIT
:
268 case LDAP_OPT_ROOTDSE_CACHE
:
269 case LDAP_OPT_SASL_METHOD
:
270 case LDAP_OPT_SECURITY_CONTEXT
:
271 case LDAP_OPT_SEND_TIMEOUT
:
272 case LDAP_OPT_SERVER_CERTIFICATE
:
273 case LDAP_OPT_SERVER_CONTROLS
:
274 case LDAP_OPT_SERVER_ERROR
:
275 case LDAP_OPT_SERVER_EXT_ERROR
:
278 case LDAP_OPT_SSL_INFO
:
279 case LDAP_OPT_SSPI_FLAGS
:
280 case LDAP_OPT_TCP_KEEPALIVE
:
281 FIXME( "Unsupported option: 0x%02x\n", option
);
282 return LDAP_NOT_SUPPORTED
;
285 FIXME( "Unknown option: 0x%02x\n", option
);
286 return LDAP_LOCAL_ERROR
;
290 /***********************************************************************
291 * ldap_set_optionA (WLDAP32.@)
293 * See ldap_set_optionW.
295 ULONG CDECL
ldap_set_optionA( LDAP
*ld
, int option
, void *value
)
299 TRACE( "(%p, 0x%08x, %p)\n", ld
, option
, value
);
301 if (!ld
) return LDAP_PARAM_ERROR
;
305 case LDAP_OPT_SERVER_CONTROLS
:
307 LDAPControlW
**ctrlsW
;
308 if (!(ctrlsW
= controlarrayAtoW( value
))) return LDAP_NO_MEMORY
;
309 ret
= ldap_set_optionW( ld
, option
, ctrlsW
);
310 controlarrayfreeW( ctrlsW
);
315 case LDAP_OPT_ERROR_NUMBER
:
316 case LDAP_OPT_PROTOCOL_VERSION
:
317 case LDAP_OPT_REFERRALS
:
318 case LDAP_OPT_SIZELIMIT
:
319 case LDAP_OPT_TIMELIMIT
:
320 return ldap_set_optionW( ld
, option
, value
);
322 case LDAP_OPT_CACHE_ENABLE
:
323 case LDAP_OPT_CACHE_FN_PTRS
:
324 case LDAP_OPT_CACHE_STRATEGY
:
325 case LDAP_OPT_IO_FN_PTRS
:
326 case LDAP_OPT_REBIND_ARG
:
327 case LDAP_OPT_REBIND_FN
:
328 case LDAP_OPT_RESTART
:
329 case LDAP_OPT_THREAD_FN_PTRS
:
330 return LDAP_LOCAL_ERROR
;
332 case LDAP_OPT_API_FEATURE_INFO
:
333 case LDAP_OPT_API_INFO
:
334 return LDAP_UNWILLING_TO_PERFORM
;
336 case LDAP_OPT_AREC_EXCLUSIVE
:
337 case LDAP_OPT_AUTO_RECONNECT
:
338 case LDAP_OPT_CLIENT_CERTIFICATE
:
339 case LDAP_OPT_DNSDOMAIN_NAME
:
340 case LDAP_OPT_ENCRYPT
:
341 case LDAP_OPT_ERROR_STRING
:
342 case LDAP_OPT_FAST_CONCURRENT_BIND
:
343 case LDAP_OPT_GETDSNAME_FLAGS
:
344 case LDAP_OPT_HOST_NAME
:
345 case LDAP_OPT_HOST_REACHABLE
:
346 case LDAP_OPT_PING_KEEP_ALIVE
:
347 case LDAP_OPT_PING_LIMIT
:
348 case LDAP_OPT_PING_WAIT_TIME
:
349 case LDAP_OPT_PROMPT_CREDENTIALS
:
350 case LDAP_OPT_REF_DEREF_CONN_PER_MSG
:
351 case LDAP_OPT_REFERRAL_CALLBACK
:
352 case LDAP_OPT_REFERRAL_HOP_LIMIT
:
353 case LDAP_OPT_ROOTDSE_CACHE
:
354 case LDAP_OPT_SASL_METHOD
:
355 case LDAP_OPT_SECURITY_CONTEXT
:
356 case LDAP_OPT_SEND_TIMEOUT
:
357 case LDAP_OPT_SERVER_CERTIFICATE
:
358 case LDAP_OPT_SERVER_ERROR
:
359 case LDAP_OPT_SERVER_EXT_ERROR
:
362 case LDAP_OPT_SSL_INFO
:
363 case LDAP_OPT_SSPI_FLAGS
:
364 case LDAP_OPT_TCP_KEEPALIVE
:
365 FIXME( "Unsupported option: 0x%02x\n", option
);
366 return LDAP_NOT_SUPPORTED
;
369 FIXME( "Unknown option: 0x%02x\n", option
);
370 return LDAP_LOCAL_ERROR
;
374 static BOOL
query_supported_server_ctrls( LDAP
*ld
)
376 char *attrs
[] = { (char *)"supportedControl", NULL
};
378 struct bervalU
**ctrls
= SERVER_CTRLS(ld
);
383 struct ldap_search_ext_s_params params
= { CTX(ld
), (char *)"", LDAP_SCOPE_BASE
,
384 (char *)"(objectClass=*)", attrs
, FALSE
, NULL
, NULL
, NULL
, 0, &res
};
385 ret
= map_error( LDAP_CALL( ldap_search_ext_s
, ¶ms
));
389 if (ret
== LDAP_SUCCESS
)
391 struct ldap_first_entry_params params
= { CTX(ld
), res
, &entry
};
392 if (!LDAP_CALL( ldap_first_entry
, ¶ms
))
395 struct ldap_get_values_len_params get_params
= { CTX(ld
), entry
, attrs
[0], &ctrls
};
396 LDAP_CALL( ldap_get_values_len
, &get_params
);
397 count
= LDAP_CALL( ldap_count_values_len
, ctrls
);
398 for (i
= 0; i
< count
; i
++) TRACE("%u: %s\n", i
, debugstr_an( ctrls
[i
]->bv_val
, ctrls
[i
]->bv_len
));
399 *(struct bervalU
***)&SERVER_CTRLS(ld
) = ctrls
;
404 LDAP_CALL( ldap_msgfree
, res
);
405 return ctrls
!= NULL
;
408 static BOOL
is_supported_server_ctrls( LDAP
*ld
, LDAPControlU
**ctrls
)
410 ULONG user_count
, server_count
, i
, n
, supported
= 0;
412 if (!query_supported_server_ctrls( ld
))
413 return TRUE
; /* can't verify, let the server handle it on next query */
415 user_count
= controlarraylenU( ctrls
);
416 server_count
= LDAP_CALL( ldap_count_values_len
, SERVER_CTRLS(ld
) );
418 for (n
= 0; n
< user_count
; n
++)
420 TRACE("looking for %s\n", debugstr_a(ctrls
[n
]->ldctl_oid
));
422 for (i
= 0; i
< server_count
; i
++)
424 struct bervalU
**server_ctrls
= SERVER_CTRLS(ld
);
425 if (!strncmp( ctrls
[n
]->ldctl_oid
, server_ctrls
[i
]->bv_val
, server_ctrls
[i
]->bv_len
))
433 return supported
== user_count
;
436 /***********************************************************************
437 * ldap_set_optionW (WLDAP32.@)
439 * Set option values for a given LDAP context.
442 * ld [I] Pointer to an LDAP context.
443 * option [I] Option to set values for.
444 * value [I] Pointer to option values.
447 * Success: LDAP_SUCCESS
448 * Failure: An LDAP error code.
451 * Set value to LDAP_OPT_ON or LDAP_OPT_OFF for on/off options.
453 ULONG CDECL
ldap_set_optionW( LDAP
*ld
, int option
, void *value
)
457 TRACE( "(%p, 0x%08x, %p)\n", ld
, option
, value
);
459 if (!ld
) return LDAP_PARAM_ERROR
;
463 case LDAP_OPT_SERVER_CONTROLS
:
465 LDAPControlU
**ctrlsU
;
467 if (!(ctrlsU
= controlarrayWtoU( value
))) return LDAP_NO_MEMORY
;
469 if (!is_supported_server_ctrls( ld
, ctrlsU
))
470 ret
= LDAP_PARAM_ERROR
;
473 struct ldap_set_option_params params
= { CTX(ld
), option
, ctrlsU
};
474 ret
= map_error( LDAP_CALL( ldap_set_option
, ¶ms
));
476 controlarrayfreeU( ctrlsU
);
479 case LDAP_OPT_REFERRALS
:
481 struct ldap_set_option_params params
= { CTX(ld
), option
, LDAP_OPT_ON
};
482 if (value
== LDAP_OPT_OFF
)
483 params
.value
= LDAP_OPT_OFF
;
485 FIXME("upgrading referral value %p to LDAP_OPT_ON (OpenLDAP lacks sufficient granularity)\n", value
);
486 return map_error( LDAP_CALL( ldap_set_option
, ¶ms
));
490 case LDAP_OPT_ERROR_NUMBER
:
491 case LDAP_OPT_PROTOCOL_VERSION
:
492 case LDAP_OPT_SIZELIMIT
:
493 case LDAP_OPT_TIMELIMIT
:
495 struct ldap_set_option_params params
= { CTX(ld
), option
, value
};
496 return map_error( LDAP_CALL( ldap_set_option
, ¶ms
));
499 case LDAP_OPT_CACHE_ENABLE
:
500 case LDAP_OPT_CACHE_FN_PTRS
:
501 case LDAP_OPT_CACHE_STRATEGY
:
502 case LDAP_OPT_IO_FN_PTRS
:
503 case LDAP_OPT_REBIND_ARG
:
504 case LDAP_OPT_REBIND_FN
:
505 case LDAP_OPT_RESTART
:
506 case LDAP_OPT_THREAD_FN_PTRS
:
507 return LDAP_LOCAL_ERROR
;
509 case LDAP_OPT_API_FEATURE_INFO
:
510 case LDAP_OPT_API_INFO
:
511 return LDAP_UNWILLING_TO_PERFORM
;
513 case LDAP_OPT_AREC_EXCLUSIVE
:
514 case LDAP_OPT_AUTO_RECONNECT
:
515 case LDAP_OPT_CLIENT_CERTIFICATE
:
516 case LDAP_OPT_DNSDOMAIN_NAME
:
517 case LDAP_OPT_ENCRYPT
:
518 case LDAP_OPT_ERROR_STRING
:
519 case LDAP_OPT_FAST_CONCURRENT_BIND
:
520 case LDAP_OPT_GETDSNAME_FLAGS
:
521 case LDAP_OPT_HOST_NAME
:
522 case LDAP_OPT_HOST_REACHABLE
:
523 case LDAP_OPT_PING_KEEP_ALIVE
:
524 case LDAP_OPT_PING_LIMIT
:
525 case LDAP_OPT_PING_WAIT_TIME
:
526 case LDAP_OPT_PROMPT_CREDENTIALS
:
527 case LDAP_OPT_REF_DEREF_CONN_PER_MSG
:
528 case LDAP_OPT_REFERRAL_CALLBACK
:
529 case LDAP_OPT_REFERRAL_HOP_LIMIT
:
530 case LDAP_OPT_ROOTDSE_CACHE
:
531 case LDAP_OPT_SASL_METHOD
:
532 case LDAP_OPT_SECURITY_CONTEXT
:
533 case LDAP_OPT_SEND_TIMEOUT
:
534 case LDAP_OPT_SERVER_CERTIFICATE
:
535 case LDAP_OPT_SERVER_ERROR
:
536 case LDAP_OPT_SERVER_EXT_ERROR
:
539 case LDAP_OPT_SSL_INFO
:
540 case LDAP_OPT_SSPI_FLAGS
:
541 case LDAP_OPT_TCP_KEEPALIVE
:
542 FIXME( "Unsupported option: 0x%02x\n", option
);
543 return LDAP_NOT_SUPPORTED
;
546 FIXME( "Unknown option: 0x%02x\n", option
);
547 return LDAP_LOCAL_ERROR
;