1 /* 2 * WLDAP32 - LDAP support for Wine 3 * 4 * Copyright 2005 Hans Leidekker 5 * 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. 10 * 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. 15 * 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 19 */ 20 21 #include "config.h" 22 23 #include "wine/port.h" 24 #include "wine/debug.h" 25 26 #include <stdarg.h> 27 28 #include "windef.h" 29 #include "winbase.h" 30 #include "winnls.h" 31 32 #ifdef HAVE_LDAP_H 33 #include <ldap.h> 34 #endif 35 36 #include "winldap_private.h" 37 #include "wldap32.h" 38 39 WINE_DEFAULT_DEBUG_CHANNEL(wldap32); 40 41 /*********************************************************************** 42 * ldap_parse_extended_resultA (WLDAP32.@) 43 * 44 * See ldap_parse_extended_resultW. 45 */ 46 ULONG CDECL ldap_parse_extended_resultA( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *result, 47 PCHAR *oid, struct WLDAP32_berval **data, BOOLEAN free ) 48 { 49 ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED; 50 #ifdef HAVE_LDAP 51 WCHAR *oidW = NULL; 52 53 TRACE( "(%p, %p, %p, %p, 0x%02x)\n", ld, result, oid, data, free ); 54 55 if (!ld) return WLDAP32_LDAP_PARAM_ERROR; 56 if (!result) return WLDAP32_LDAP_NO_RESULTS_RETURNED; 57 58 ret = ldap_parse_extended_resultW( ld, result, &oidW, data, free ); 59 60 if (oid) { 61 *oid = strWtoA( oidW ); 62 if (!*oid) ret = WLDAP32_LDAP_NO_MEMORY; 63 ldap_memfreeW( oidW ); 64 } 65 66 #endif 67 return ret; 68 } 69 70 /*********************************************************************** 71 * ldap_parse_extended_resultW (WLDAP32.@) 72 * 73 * Parse the result of an extended operation. 74 * 75 * PARAMS 76 * ld [I] Pointer to an LDAP context. 77 * result [I] Result message from an extended operation. 78 * oid [O] OID of the extended operation. 79 * data [O] Result data. 80 * free [I] Free the result message? 81 * 82 * RETURNS 83 * Success: LDAP_SUCCESS 84 * Failure: An LDAP error code. 85 * 86 * NOTES 87 * Free the OID and result data with ldap_memfree. Pass a nonzero 88 * value for 'free' or call ldap_msgfree to free the result message. 89 */ 90 ULONG CDECL ldap_parse_extended_resultW( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *result, 91 PWCHAR *oid, struct WLDAP32_berval **data, BOOLEAN free ) 92 { 93 ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED; 94 #ifdef HAVE_LDAP 95 char *oidU = NULL; 96 97 TRACE( "(%p, %p, %p, %p, 0x%02x)\n", ld, result, oid, data, free ); 98 99 if (!ld) return WLDAP32_LDAP_PARAM_ERROR; 100 if (!result) return WLDAP32_LDAP_NO_RESULTS_RETURNED; 101 102 ret = map_error( ldap_parse_extended_result( ld, result, &oidU, (struct berval **)data, free ) ); 103 104 if (oid) { 105 *oid = strUtoW( oidU ); 106 if (!*oid) ret = WLDAP32_LDAP_NO_MEMORY; 107 ldap_memfree( oidU ); 108 } 109 110 #endif 111 return ret; 112 } 113 114 /*********************************************************************** 115 * ldap_parse_referenceA (WLDAP32.@) 116 * 117 * See ldap_parse_referenceW. 118 */ 119 ULONG CDECL ldap_parse_referenceA( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *message, 120 PCHAR **referrals ) 121 { 122 ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED; 123 #ifdef HAVE_LDAP 124 WCHAR **referralsW = NULL; 125 126 TRACE( "(%p, %p, %p)\n", ld, message, referrals ); 127 128 if (!ld) return ~0u; 129 130 ret = ldap_parse_referenceW( ld, message, &referralsW ); 131 132 *referrals = strarrayWtoA( referralsW ); 133 ldap_value_freeW( referralsW ); 134 135 #endif 136 return ret; 137 } 138 139 /*********************************************************************** 140 * ldap_parse_referenceW (WLDAP32.@) 141 * 142 * Return any referrals from a result message. 143 * 144 * PARAMS 145 * ld [I] Pointer to an LDAP context. 146 * result [I] Result message. 147 * referrals [O] Array of referral URLs. 148 * 149 * RETURNS 150 * Success: LDAP_SUCCESS 151 * Failure: An LDAP error code. 152 * 153 * NOTES 154 * Free the referrals with ldap_value_free. 155 */ 156 ULONG CDECL ldap_parse_referenceW( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *message, 157 PWCHAR **referrals ) 158 { 159 ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED; 160 #ifdef HAVE_LDAP_PARSE_REFERENCE 161 char **referralsU = NULL; 162 163 TRACE( "(%p, %p, %p)\n", ld, message, referrals ); 164 165 if (!ld) return ~0u; 166 167 ret = map_error( ldap_parse_reference( ld, message, &referralsU, NULL, 0 )); 168 169 *referrals = strarrayUtoW( referralsU ); 170 ldap_memfree( referralsU ); 171 172 #endif 173 return ret; 174 } 175 176 /*********************************************************************** 177 * ldap_parse_resultA (WLDAP32.@) 178 * 179 * See ldap_parse_resultW. 180 */ 181 ULONG CDECL ldap_parse_resultA( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *result, 182 ULONG *retcode, PCHAR *matched, PCHAR *error, PCHAR **referrals, 183 PLDAPControlA **serverctrls, BOOLEAN free ) 184 { 185 ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED; 186 #ifdef HAVE_LDAP 187 WCHAR *matchedW = NULL, *errorW = NULL, **referralsW = NULL; 188 LDAPControlW **serverctrlsW = NULL; 189 190 TRACE( "(%p, %p, %p, %p, %p, %p, %p, 0x%02x)\n", ld, result, retcode, 191 matched, error, referrals, serverctrls, free ); 192 193 if (!ld) return WLDAP32_LDAP_PARAM_ERROR; 194 195 ret = ldap_parse_resultW( ld, result, retcode, &matchedW, &errorW, 196 &referralsW, &serverctrlsW, free ); 197 198 if (matched) *matched = strWtoA( matchedW ); 199 if (error) *error = strWtoA( errorW ); 200 201 if (referrals) *referrals = strarrayWtoA( referralsW ); 202 if (serverctrls) *serverctrls = controlarrayWtoA( serverctrlsW ); 203 204 ldap_memfreeW( matchedW ); 205 ldap_memfreeW( errorW ); 206 ldap_value_freeW( referralsW ); 207 ldap_controls_freeW( serverctrlsW ); 208 209 #endif 210 return ret; 211 } 212 213 /*********************************************************************** 214 * ldap_parse_resultW (WLDAP32.@) 215 * 216 * Parse a result message. 217 * 218 * PARAMS 219 * ld [I] Pointer to an LDAP context. 220 * result [I] Result message. 221 * retcode [O] Return code for the server operation. 222 * matched [O] DNs matched in the operation. 223 * error [O] Error message for the operation. 224 * referrals [O] Referrals found in the result message. 225 * serverctrls [O] Controls used in the operation. 226 * free [I] Free the result message? 227 * 228 * RETURNS 229 * Success: LDAP_SUCCESS 230 * Failure: An LDAP error code. 231 * 232 * NOTES 233 * Free the DNs and error message with ldap_memfree. Free 234 * the referrals with ldap_value_free and the controls with 235 * ldap_controls_free. Pass a nonzero value for 'free' or call 236 * ldap_msgfree to free the result message. 237 */ 238 ULONG CDECL ldap_parse_resultW( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *result, 239 ULONG *retcode, PWCHAR *matched, PWCHAR *error, PWCHAR **referrals, 240 PLDAPControlW **serverctrls, BOOLEAN free ) 241 { 242 ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED; 243 #ifdef HAVE_LDAP 244 char *matchedU = NULL, *errorU = NULL, **referralsU = NULL; 245 LDAPControl **serverctrlsU = NULL; 246 247 TRACE( "(%p, %p, %p, %p, %p, %p, %p, 0x%02x)\n", ld, result, retcode, 248 matched, error, referrals, serverctrls, free ); 249 250 if (!ld) return WLDAP32_LDAP_PARAM_ERROR; 251 252 ret = map_error( ldap_parse_result( ld, result, (int *)retcode, &matchedU, &errorU, 253 &referralsU, &serverctrlsU, free )); 254 255 if (matched) *matched = strUtoW( matchedU ); 256 if (error) *error = strUtoW( errorU ); 257 258 if (referrals) *referrals = strarrayUtoW( referralsU ); 259 if (serverctrls) *serverctrls = controlarrayUtoW( serverctrlsU ); 260 261 ldap_memfree( matchedU ); 262 ldap_memfree( errorU ); 263 strarrayfreeU( referralsU ); 264 ldap_controls_free( serverctrlsU ); 265 266 #endif 267 return ret; 268 } 269 270 /*********************************************************************** 271 * ldap_parse_sort_controlA (WLDAP32.@) 272 * 273 * See ldap_parse_sort_controlW. 274 */ 275 ULONG CDECL ldap_parse_sort_controlA( WLDAP32_LDAP *ld, PLDAPControlA *control, 276 ULONG *result, PCHAR *attr ) 277 { 278 ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED; 279 #ifdef HAVE_LDAP 280 WCHAR *attrW = NULL; 281 LDAPControlW **controlW = NULL; 282 283 TRACE( "(%p, %p, %p, %p)\n", ld, control, result, attr ); 284 285 if (!ld) return WLDAP32_LDAP_PARAM_ERROR; 286 if (!control) return WLDAP32_LDAP_CONTROL_NOT_FOUND; 287 288 controlW = controlarrayAtoW( control ); 289 if (!controlW) return WLDAP32_LDAP_NO_MEMORY; 290 291 ret = ldap_parse_sort_controlW( ld, controlW, result, &attrW ); 292 293 *attr = strWtoA( attrW ); 294 controlarrayfreeW( controlW ); 295 296 #endif 297 return ret; 298 } 299 300 /*********************************************************************** 301 * ldap_parse_sort_controlW (WLDAP32.@) 302 * 303 * Parse a sort control. 304 * 305 * PARAMS 306 * ld [I] Pointer to an LDAP context. 307 * control [I] Control obtained from a result message. 308 * result [O] Result code. 309 * attr [O] Failing attribute. 310 * 311 * RETURNS 312 * Success: LDAP_SUCCESS 313 * Failure: An LDAP error code. 314 * 315 * NOTES 316 * If the function fails, free the failing attribute with ldap_memfree. 317 */ 318 ULONG CDECL ldap_parse_sort_controlW( WLDAP32_LDAP *ld, PLDAPControlW *control, 319 ULONG *result, PWCHAR *attr ) 320 { 321 ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED; 322 #ifdef HAVE_LDAP 323 char *attrU = NULL; 324 LDAPControl **controlU = NULL; 325 #ifdef HAVE_LDAP_PARSE_SORT_CONTROL 326 unsigned long res; 327 #elif defined(HAVE_LDAP_PARSE_SORTRESPONSE_CONTROL) 328 ber_int_t res; 329 LDAPControl *sortcontrol = NULL; 330 unsigned int i; 331 #endif 332 333 TRACE( "(%p, %p, %p, %p)\n", ld, control, result, attr ); 334 335 if (!ld) return WLDAP32_LDAP_PARAM_ERROR; 336 if (!control) return WLDAP32_LDAP_CONTROL_NOT_FOUND; 337 338 controlU = controlarrayWtoU( control ); 339 if (!controlU) return WLDAP32_LDAP_NO_MEMORY; 340 341 #ifdef HAVE_LDAP_PARSE_SORT_CONTROL 342 if (!(ret = ldap_parse_sort_control( ld, controlU, &res, &attrU ))) 343 { 344 *result = res; 345 *attr = strUtoW( attrU ); 346 } 347 #elif defined(HAVE_LDAP_PARSE_SORTRESPONSE_CONTROL) 348 for (i = 0; controlU[i]; i++) 349 { 350 if (!strcmp( LDAP_SERVER_RESP_SORT_OID, controlU[i]->ldctl_oid )) 351 sortcontrol = controlU[i]; 352 } 353 if (!sortcontrol) 354 { 355 controlarrayfreeU( controlU ); 356 return WLDAP32_LDAP_CONTROL_NOT_FOUND; 357 } 358 if (!(ret = ldap_parse_sortresponse_control( ld, sortcontrol, &res, &attrU ))) 359 { 360 *result = res; 361 *attr = strUtoW( attrU ); 362 } 363 #endif 364 controlarrayfreeU( controlU ); 365 366 #endif 367 return map_error( ret ); 368 } 369 370 /*********************************************************************** 371 * ldap_parse_vlv_controlA (WLDAP32.@) 372 * 373 * See ldap_parse_vlv_controlW. 374 */ 375 INT CDECL ldap_parse_vlv_controlA( WLDAP32_LDAP *ld, PLDAPControlA *control, 376 PULONG targetpos, PULONG listcount, 377 struct WLDAP32_berval **context, PINT errcode ) 378 { 379 int ret = WLDAP32_LDAP_NOT_SUPPORTED; 380 #ifdef HAVE_LDAP 381 LDAPControlW **controlW = NULL; 382 383 TRACE( "(%p, %p, %p, %p, %p, %p)\n", ld, control, targetpos, 384 listcount, context, errcode ); 385 386 if (!ld) return ~0u; 387 388 if (control) { 389 controlW = controlarrayAtoW( control ); 390 if (!controlW) return WLDAP32_LDAP_NO_MEMORY; 391 } 392 393 ret = ldap_parse_vlv_controlW( ld, controlW, targetpos, listcount, 394 context, errcode ); 395 396 controlarrayfreeW( controlW ); 397 398 #endif 399 return ret; 400 } 401 402 /*********************************************************************** 403 * ldap_parse_vlv_controlW (WLDAP32.@) 404 * 405 * Parse a virtual list view control. 406 * 407 * PARAMS 408 * ld [I] Pointer to an LDAP context. 409 * control [I] Controls obtained from a result message. 410 * targetpos [O] Position of the target in the result list. 411 * listcount [O] Estimate of the number of results in the list. 412 * context [O] Server side context. 413 * errcode [O] Error code from the listview operation. 414 * 415 * RETURNS 416 * Success: LDAP_SUCCESS 417 * Failure: An LDAP error code. 418 * 419 * NOTES 420 * Free the server context with ber_bvfree. 421 */ 422 INT CDECL ldap_parse_vlv_controlW( WLDAP32_LDAP *ld, PLDAPControlW *control, 423 PULONG targetpos, PULONG listcount, 424 struct WLDAP32_berval **context, PINT errcode ) 425 { 426 int ret = WLDAP32_LDAP_NOT_SUPPORTED; 427 #ifdef HAVE_LDAP 428 LDAPControl **controlU = NULL; 429 #ifdef HAVE_LDAP_PARSE_VLV_CONTROL 430 unsigned long pos, count; 431 #elif defined(HAVE_LDAP_PARSE_VLVRESPONSE_CONTROL) 432 ber_int_t pos, count; 433 LDAPControl *vlvcontrol = NULL; 434 unsigned int i; 435 #endif 436 437 TRACE( "(%p, %p, %p, %p, %p, %p)\n", ld, control, targetpos, 438 listcount, context, errcode ); 439 440 if (!ld || !control) return ~0u; 441 442 controlU = controlarrayWtoU( control ); 443 if (!controlU) return WLDAP32_LDAP_NO_MEMORY; 444 445 #ifdef HAVE_LDAP_PARSE_VLV_CONTROL 446 if (!(ret = ldap_parse_vlv_control( ld, controlU, &pos, &count, 447 context, errcode ))) 448 { 449 *targetpos = pos; 450 *listcount = count; 451 } 452 #elif defined(HAVE_LDAP_PARSE_VLVRESPONSE_CONTROL) 453 for (i = 0; controlU[i]; i++) 454 { 455 if (!strcmp( LDAP_CONTROL_VLVRESPONSE, controlU[i]->ldctl_oid )) 456 vlvcontrol = controlU[i]; 457 } 458 if (!vlvcontrol) 459 { 460 controlarrayfreeU( controlU ); 461 return WLDAP32_LDAP_CONTROL_NOT_FOUND; 462 } 463 if (!(ret = ldap_parse_vlvresponse_control( ld, vlvcontrol, &pos, &count, 464 (struct berval **)context, errcode ))) 465 { 466 *targetpos = pos; 467 *listcount = count; 468 } 469 #endif 470 controlarrayfreeU( controlU ); 471 472 #endif 473 return map_error( ret ); 474 } 475