rsaenh: Split CPImportKey into a helper function for each type of key supported.
[wine] / dlls / wldap32 / parse.c
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 }