Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/ldap/libldap/extended.c
4394 views
1
/* $OpenLDAP$ */
2
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3
*
4
* Copyright 1998-2024 The OpenLDAP Foundation.
5
* All rights reserved.
6
*
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted only as authorized by the OpenLDAP
9
* Public License.
10
*
11
* A copy of this license is available in the file LICENSE in the
12
* top-level directory of the distribution or, alternatively, at
13
* <http://www.OpenLDAP.org/license.html>.
14
*/
15
16
#include "portable.h"
17
18
#include <stdio.h>
19
#include <ac/stdlib.h>
20
21
#include <ac/socket.h>
22
#include <ac/string.h>
23
#include <ac/time.h>
24
25
#include "ldap-int.h"
26
#include "ldap_log.h"
27
28
BerElement *
29
ldap_build_extended_req(
30
LDAP *ld,
31
LDAP_CONST char *reqoid,
32
struct berval *reqdata,
33
LDAPControl **sctrls,
34
LDAPControl **cctrls,
35
ber_int_t *msgidp )
36
{
37
BerElement *ber;
38
int rc;
39
40
/* create a message to send */
41
if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
42
return( NULL );
43
}
44
45
LDAP_NEXT_MSGID( ld, *msgidp );
46
if ( reqdata != NULL ) {
47
rc = ber_printf( ber, "{it{tstON}", /* '}' */
48
*msgidp, LDAP_REQ_EXTENDED,
49
LDAP_TAG_EXOP_REQ_OID, reqoid,
50
LDAP_TAG_EXOP_REQ_VALUE, reqdata );
51
52
} else {
53
rc = ber_printf( ber, "{it{tsN}", /* '}' */
54
*msgidp, LDAP_REQ_EXTENDED,
55
LDAP_TAG_EXOP_REQ_OID, reqoid );
56
}
57
58
if( rc == -1 ) {
59
ld->ld_errno = LDAP_ENCODING_ERROR;
60
ber_free( ber, 1 );
61
return( NULL );
62
}
63
64
/* Put Server Controls */
65
if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
66
ber_free( ber, 1 );
67
return( NULL );
68
}
69
70
if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) {
71
ld->ld_errno = LDAP_ENCODING_ERROR;
72
ber_free( ber, 1 );
73
return( NULL );
74
}
75
76
return( ber );
77
}
78
79
/*
80
* LDAPv3 Extended Operation Request
81
* ExtendedRequest ::= [APPLICATION 23] SEQUENCE {
82
* requestName [0] LDAPOID,
83
* requestValue [1] OCTET STRING OPTIONAL
84
* }
85
*
86
* LDAPv3 Extended Operation Response
87
* ExtendedResponse ::= [APPLICATION 24] SEQUENCE {
88
* COMPONENTS OF LDAPResult,
89
* responseName [10] LDAPOID OPTIONAL,
90
* response [11] OCTET STRING OPTIONAL
91
* }
92
*
93
* (Source RFC 4511)
94
*/
95
96
int
97
ldap_extended_operation(
98
LDAP *ld,
99
LDAP_CONST char *reqoid,
100
struct berval *reqdata,
101
LDAPControl **sctrls,
102
LDAPControl **cctrls,
103
int *msgidp )
104
{
105
BerElement *ber;
106
ber_int_t id;
107
108
Debug0( LDAP_DEBUG_TRACE, "ldap_extended_operation\n" );
109
110
assert( ld != NULL );
111
assert( LDAP_VALID( ld ) );
112
assert( reqoid != NULL && *reqoid != '\0' );
113
assert( msgidp != NULL );
114
115
/* must be version 3 (or greater) */
116
if ( ld->ld_version < LDAP_VERSION3 ) {
117
ld->ld_errno = LDAP_NOT_SUPPORTED;
118
return( ld->ld_errno );
119
}
120
121
ber = ldap_build_extended_req( ld, reqoid, reqdata,
122
sctrls, cctrls, &id );
123
if ( !ber )
124
return( ld->ld_errno );
125
126
/* send the message */
127
*msgidp = ldap_send_initial_request( ld, LDAP_REQ_EXTENDED, NULL, ber, id );
128
129
return( *msgidp < 0 ? ld->ld_errno : LDAP_SUCCESS );
130
}
131
132
int
133
ldap_extended_operation_s(
134
LDAP *ld,
135
LDAP_CONST char *reqoid,
136
struct berval *reqdata,
137
LDAPControl **sctrls,
138
LDAPControl **cctrls,
139
char **retoidp,
140
struct berval **retdatap )
141
{
142
int rc;
143
int msgid;
144
LDAPMessage *res;
145
146
Debug0( LDAP_DEBUG_TRACE, "ldap_extended_operation_s\n" );
147
148
assert( ld != NULL );
149
assert( LDAP_VALID( ld ) );
150
assert( reqoid != NULL && *reqoid != '\0' );
151
152
rc = ldap_extended_operation( ld, reqoid, reqdata,
153
sctrls, cctrls, &msgid );
154
155
if ( rc != LDAP_SUCCESS ) {
156
return( rc );
157
}
158
159
if ( ldap_result( ld, msgid, LDAP_MSG_ALL, (struct timeval *) NULL, &res ) == -1 || !res ) {
160
return( ld->ld_errno );
161
}
162
163
if ( retoidp != NULL ) *retoidp = NULL;
164
if ( retdatap != NULL ) *retdatap = NULL;
165
166
rc = ldap_parse_extended_result( ld, res, retoidp, retdatap, 0 );
167
168
if( rc != LDAP_SUCCESS ) {
169
ldap_msgfree( res );
170
return rc;
171
}
172
173
return( ldap_result2error( ld, res, 1 ) );
174
}
175
176
/* Parse an extended result */
177
int
178
ldap_parse_extended_result (
179
LDAP *ld,
180
LDAPMessage *res,
181
char **retoidp,
182
struct berval **retdatap,
183
int freeit )
184
{
185
BerElement *ber;
186
ber_tag_t rc;
187
ber_tag_t tag;
188
ber_len_t len;
189
struct berval *resdata;
190
ber_int_t errcode;
191
char *resoid;
192
193
assert( ld != NULL );
194
assert( LDAP_VALID( ld ) );
195
assert( res != NULL );
196
197
Debug0( LDAP_DEBUG_TRACE, "ldap_parse_extended_result\n" );
198
199
if( ld->ld_version < LDAP_VERSION3 ) {
200
ld->ld_errno = LDAP_NOT_SUPPORTED;
201
return ld->ld_errno;
202
}
203
204
if( res->lm_msgtype != LDAP_RES_EXTENDED ) {
205
ld->ld_errno = LDAP_PARAM_ERROR;
206
return ld->ld_errno;
207
}
208
209
if( retoidp != NULL ) *retoidp = NULL;
210
if( retdatap != NULL ) *retdatap = NULL;
211
212
if ( ld->ld_error ) {
213
LDAP_FREE( ld->ld_error );
214
ld->ld_error = NULL;
215
}
216
217
if ( ld->ld_matched ) {
218
LDAP_FREE( ld->ld_matched );
219
ld->ld_matched = NULL;
220
}
221
222
ber = ber_dup( res->lm_ber );
223
224
if ( ber == NULL ) {
225
ld->ld_errno = LDAP_NO_MEMORY;
226
return ld->ld_errno;
227
}
228
229
rc = ber_scanf( ber, "{eAA" /*}*/, &errcode,
230
&ld->ld_matched, &ld->ld_error );
231
232
if( rc == LBER_ERROR ) {
233
ld->ld_errno = LDAP_DECODING_ERROR;
234
ber_free( ber, 0 );
235
return ld->ld_errno;
236
}
237
238
resoid = NULL;
239
resdata = NULL;
240
241
tag = ber_peek_tag( ber, &len );
242
243
if( tag == LDAP_TAG_REFERRAL ) {
244
/* skip over referral */
245
if( ber_scanf( ber, "x" ) == LBER_ERROR ) {
246
ld->ld_errno = LDAP_DECODING_ERROR;
247
ber_free( ber, 0 );
248
return ld->ld_errno;
249
}
250
251
tag = ber_peek_tag( ber, &len );
252
}
253
254
if( tag == LDAP_TAG_EXOP_RES_OID ) {
255
/* we have a resoid */
256
if( ber_scanf( ber, "a", &resoid ) == LBER_ERROR ) {
257
ld->ld_errno = LDAP_DECODING_ERROR;
258
ber_free( ber, 0 );
259
return ld->ld_errno;
260
}
261
262
assert( resoid[ 0 ] != '\0' );
263
264
tag = ber_peek_tag( ber, &len );
265
}
266
267
if( tag == LDAP_TAG_EXOP_RES_VALUE ) {
268
/* we have a resdata */
269
if( ber_scanf( ber, "O", &resdata ) == LBER_ERROR ) {
270
ld->ld_errno = LDAP_DECODING_ERROR;
271
ber_free( ber, 0 );
272
if( resoid != NULL ) LDAP_FREE( resoid );
273
return ld->ld_errno;
274
}
275
}
276
277
ber_free( ber, 0 );
278
279
if( retoidp != NULL ) {
280
*retoidp = resoid;
281
} else {
282
LDAP_FREE( resoid );
283
}
284
285
if( retdatap != NULL ) {
286
*retdatap = resdata;
287
} else {
288
ber_bvfree( resdata );
289
}
290
291
ld->ld_errno = errcode;
292
293
if( freeit ) {
294
ldap_msgfree( res );
295
}
296
297
return LDAP_SUCCESS;
298
}
299
300
301
/* Parse an extended partial */
302
int
303
ldap_parse_intermediate (
304
LDAP *ld,
305
LDAPMessage *res,
306
char **retoidp,
307
struct berval **retdatap,
308
LDAPControl ***serverctrls,
309
int freeit )
310
{
311
BerElement *ber;
312
ber_tag_t tag;
313
ber_len_t len;
314
struct berval *resdata;
315
char *resoid;
316
317
assert( ld != NULL );
318
assert( LDAP_VALID( ld ) );
319
assert( res != NULL );
320
321
Debug0( LDAP_DEBUG_TRACE, "ldap_parse_intermediate\n" );
322
323
if( ld->ld_version < LDAP_VERSION3 ) {
324
ld->ld_errno = LDAP_NOT_SUPPORTED;
325
return ld->ld_errno;
326
}
327
328
if( res->lm_msgtype != LDAP_RES_INTERMEDIATE ) {
329
ld->ld_errno = LDAP_PARAM_ERROR;
330
return ld->ld_errno;
331
}
332
333
if( retoidp != NULL ) *retoidp = NULL;
334
if( retdatap != NULL ) *retdatap = NULL;
335
if( serverctrls != NULL ) *serverctrls = NULL;
336
337
ber = ber_dup( res->lm_ber );
338
339
if ( ber == NULL ) {
340
ld->ld_errno = LDAP_NO_MEMORY;
341
return ld->ld_errno;
342
}
343
344
tag = ber_scanf( ber, "{" /*}*/ );
345
346
if( tag == LBER_ERROR ) {
347
ld->ld_errno = LDAP_DECODING_ERROR;
348
ber_free( ber, 0 );
349
return ld->ld_errno;
350
}
351
352
resoid = NULL;
353
resdata = NULL;
354
355
tag = ber_peek_tag( ber, &len );
356
357
/*
358
* NOTE: accept intermediate and extended response tag values
359
* as older versions of slapd(8) incorrectly used extended
360
* response tags.
361
* Should be removed when 2.2 is moved to Historic.
362
*/
363
if( tag == LDAP_TAG_IM_RES_OID || tag == LDAP_TAG_EXOP_RES_OID ) {
364
/* we have a resoid */
365
if( ber_scanf( ber, "a", &resoid ) == LBER_ERROR ) {
366
ld->ld_errno = LDAP_DECODING_ERROR;
367
ber_free( ber, 0 );
368
return ld->ld_errno;
369
}
370
371
assert( resoid[ 0 ] != '\0' );
372
373
tag = ber_peek_tag( ber, &len );
374
}
375
376
if( tag == LDAP_TAG_IM_RES_VALUE || tag == LDAP_TAG_EXOP_RES_VALUE ) {
377
/* we have a resdata */
378
if( ber_scanf( ber, "O", &resdata ) == LBER_ERROR ) {
379
ld->ld_errno = LDAP_DECODING_ERROR;
380
ber_free( ber, 0 );
381
if( resoid != NULL ) LDAP_FREE( resoid );
382
return ld->ld_errno;
383
}
384
}
385
386
if ( serverctrls == NULL ) {
387
ld->ld_errno = LDAP_SUCCESS;
388
goto free_and_return;
389
}
390
391
if ( ber_scanf( ber, /*{*/ "}" ) == LBER_ERROR ) {
392
ld->ld_errno = LDAP_DECODING_ERROR;
393
goto free_and_return;
394
}
395
396
ld->ld_errno = ldap_pvt_get_controls( ber, serverctrls );
397
398
free_and_return:
399
ber_free( ber, 0 );
400
401
if( retoidp != NULL ) {
402
*retoidp = resoid;
403
} else {
404
LDAP_FREE( resoid );
405
}
406
407
if( retdatap != NULL ) {
408
*retdatap = resdata;
409
} else {
410
ber_bvfree( resdata );
411
}
412
413
if( freeit ) {
414
ldap_msgfree( res );
415
}
416
417
return ld->ld_errno;
418
}
419
420