Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/ldap/libldap/controls.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
/* This notice applies to changes, created by or for Novell, Inc.,
16
* to preexisting works for which notices appear elsewhere in this file.
17
*
18
* Copyright (C) 1999, 2000 Novell, Inc. All Rights Reserved.
19
*
20
* THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND TREATIES.
21
* USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO VERSION
22
* 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS AVAILABLE AT
23
* HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE" IN THE
24
* TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION OF THIS
25
* WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP PUBLIC
26
* LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT THE
27
* PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY.
28
*---
29
* Note: A verbatim copy of version 2.0.1 of the OpenLDAP Public License
30
* can be found in the file "build/LICENSE-2.0.1" in this distribution
31
* of OpenLDAP Software.
32
*/
33
34
#include "portable.h"
35
36
#include <ac/stdlib.h>
37
38
#include <ac/time.h>
39
#include <ac/string.h>
40
41
#include "ldap-int.h"
42
43
/* LDAPv3 Controls (RFC 4511)
44
*
45
* Controls ::= SEQUENCE OF control Control
46
*
47
* Control ::= SEQUENCE {
48
* controlType LDAPOID,
49
* criticality BOOLEAN DEFAULT FALSE,
50
* controlValue OCTET STRING OPTIONAL
51
* }
52
*/
53
54
int
55
ldap_pvt_put_control(
56
const LDAPControl *c,
57
BerElement *ber )
58
{
59
if ( ber_printf( ber, "{s" /*}*/, c->ldctl_oid ) == -1 ) {
60
return LDAP_ENCODING_ERROR;
61
}
62
63
if ( c->ldctl_iscritical /* only if true */
64
&& ( ber_printf( ber, "b",
65
(ber_int_t) c->ldctl_iscritical ) == -1 ) )
66
{
67
return LDAP_ENCODING_ERROR;
68
}
69
70
if ( !BER_BVISNULL( &c->ldctl_value ) /* only if we have a value */
71
&& ( ber_printf( ber, "O", &c->ldctl_value ) == -1 ) )
72
{
73
return LDAP_ENCODING_ERROR;
74
}
75
76
if ( ber_printf( ber, /*{*/"N}" ) == -1 ) {
77
return LDAP_ENCODING_ERROR;
78
}
79
80
return LDAP_SUCCESS;
81
}
82
83
84
/*
85
* ldap_int_put_controls
86
*/
87
88
int
89
ldap_int_put_controls(
90
LDAP *ld,
91
LDAPControl *const *ctrls,
92
BerElement *ber )
93
{
94
LDAPControl *const *c;
95
96
assert( ld != NULL );
97
assert( LDAP_VALID( ld ) );
98
assert( ber != NULL );
99
100
if( ctrls == NULL ) {
101
/* use default server controls */
102
ctrls = ld->ld_sctrls;
103
}
104
105
if( ctrls == NULL || *ctrls == NULL ) {
106
return LDAP_SUCCESS;
107
}
108
109
if ( ld->ld_version < LDAP_VERSION3 ) {
110
/* LDAPv2 doesn't support controls,
111
* error if any control is critical
112
*/
113
for( c = ctrls ; *c != NULL; c++ ) {
114
if( (*c)->ldctl_iscritical ) {
115
ld->ld_errno = LDAP_NOT_SUPPORTED;
116
return ld->ld_errno;
117
}
118
}
119
120
return LDAP_SUCCESS;
121
}
122
123
/* Controls are encoded as a sequence of sequences */
124
if( ber_printf( ber, "t{"/*}*/, LDAP_TAG_CONTROLS ) == -1 ) {
125
ld->ld_errno = LDAP_ENCODING_ERROR;
126
return ld->ld_errno;
127
}
128
129
for( c = ctrls ; *c != NULL; c++ ) {
130
ld->ld_errno = ldap_pvt_put_control( *c, ber );
131
if ( ld->ld_errno != LDAP_SUCCESS ) {
132
return ld->ld_errno;
133
}
134
}
135
136
137
if( ber_printf( ber, /*{*/ "}" ) == -1 ) {
138
ld->ld_errno = LDAP_ENCODING_ERROR;
139
return ld->ld_errno;
140
}
141
142
return LDAP_SUCCESS;
143
}
144
145
int ldap_pvt_get_controls(
146
BerElement *ber,
147
LDAPControl ***ctrls )
148
{
149
int nctrls;
150
ber_tag_t tag;
151
ber_len_t len;
152
char *opaque;
153
154
assert( ber != NULL );
155
156
if( ctrls == NULL ) {
157
return LDAP_SUCCESS;
158
}
159
*ctrls = NULL;
160
161
len = ber_pvt_ber_remaining( ber );
162
163
if( len == 0) {
164
/* no controls */
165
return LDAP_SUCCESS;
166
}
167
168
if(( tag = ber_peek_tag( ber, &len )) != LDAP_TAG_CONTROLS ) {
169
if( tag == LBER_ERROR ) {
170
/* decoding error */
171
return LDAP_DECODING_ERROR;
172
}
173
174
/* ignore unexpected input */
175
return LDAP_SUCCESS;
176
}
177
178
/* set through each element */
179
nctrls = 0;
180
*ctrls = LDAP_MALLOC( 1 * sizeof(LDAPControl *) );
181
182
if( *ctrls == NULL ) {
183
return LDAP_NO_MEMORY;
184
}
185
186
*ctrls[nctrls] = NULL;
187
188
for( tag = ber_first_element( ber, &len, &opaque );
189
tag != LBER_ERROR;
190
tag = ber_next_element( ber, &len, opaque ) )
191
{
192
LDAPControl *tctrl;
193
LDAPControl **tctrls;
194
195
tctrl = LDAP_CALLOC( 1, sizeof(LDAPControl) );
196
197
/* allocate pointer space for current controls (nctrls)
198
* + this control + extra NULL
199
*/
200
tctrls = (tctrl == NULL) ? NULL :
201
LDAP_REALLOC(*ctrls, (nctrls+2) * sizeof(LDAPControl *));
202
203
if( tctrls == NULL ) {
204
/* one of the above allocation failed */
205
206
if( tctrl != NULL ) {
207
LDAP_FREE( tctrl );
208
}
209
210
ldap_controls_free(*ctrls);
211
*ctrls = NULL;
212
213
return LDAP_NO_MEMORY;
214
}
215
216
217
tctrls[nctrls++] = tctrl;
218
tctrls[nctrls] = NULL;
219
220
tag = ber_scanf( ber, "{a" /*}*/, &tctrl->ldctl_oid );
221
222
if( tag == LBER_ERROR ) {
223
*ctrls = NULL;
224
ldap_controls_free( tctrls );
225
return LDAP_DECODING_ERROR;
226
}
227
228
tag = ber_peek_tag( ber, &len );
229
230
if( tag == LBER_BOOLEAN ) {
231
ber_int_t crit;
232
tag = ber_scanf( ber, "b", &crit );
233
tctrl->ldctl_iscritical = crit ? (char) 0 : (char) ~0;
234
tag = ber_peek_tag( ber, &len );
235
}
236
237
if( tag == LBER_OCTETSTRING ) {
238
tag = ber_scanf( ber, "o", &tctrl->ldctl_value );
239
} else {
240
BER_BVZERO( &tctrl->ldctl_value );
241
}
242
243
*ctrls = tctrls;
244
}
245
246
return LDAP_SUCCESS;
247
}
248
249
/*
250
* Free a LDAPControl
251
*/
252
void
253
ldap_control_free( LDAPControl *c )
254
{
255
LDAP_MEMORY_DEBUG_ASSERT( c != NULL );
256
257
if ( c != NULL ) {
258
if( c->ldctl_oid != NULL) {
259
LDAP_FREE( c->ldctl_oid );
260
}
261
262
if( c->ldctl_value.bv_val != NULL ) {
263
LDAP_FREE( c->ldctl_value.bv_val );
264
}
265
266
LDAP_FREE( c );
267
}
268
}
269
270
/*
271
* Free an array of LDAPControl's
272
*/
273
void
274
ldap_controls_free( LDAPControl **controls )
275
{
276
LDAP_MEMORY_DEBUG_ASSERT( controls != NULL );
277
278
if ( controls != NULL ) {
279
int i;
280
281
for( i=0; controls[i] != NULL; i++) {
282
ldap_control_free( controls[i] );
283
}
284
285
LDAP_FREE( controls );
286
}
287
}
288
289
/*
290
* Duplicate an array of LDAPControl
291
*/
292
LDAPControl **
293
ldap_controls_dup( LDAPControl *const *controls )
294
{
295
LDAPControl **new;
296
int i;
297
298
if ( controls == NULL ) {
299
return NULL;
300
}
301
302
/* count the controls */
303
for(i=0; controls[i] != NULL; i++) /* empty */ ;
304
305
if( i < 1 ) {
306
/* no controls to duplicate */
307
return NULL;
308
}
309
310
new = (LDAPControl **) LDAP_MALLOC( (i+1) * sizeof(LDAPControl *) );
311
312
if( new == NULL ) {
313
/* memory allocation failure */
314
return NULL;
315
}
316
317
/* duplicate the controls */
318
for(i=0; controls[i] != NULL; i++) {
319
new[i] = ldap_control_dup( controls[i] );
320
321
if( new[i] == NULL ) {
322
ldap_controls_free( new );
323
return NULL;
324
}
325
}
326
327
new[i] = NULL;
328
329
return new;
330
}
331
332
/*
333
* Duplicate a LDAPControl
334
*/
335
LDAPControl *
336
ldap_control_dup( const LDAPControl *c )
337
{
338
LDAPControl *new;
339
340
if ( c == NULL || c->ldctl_oid == NULL ) {
341
return NULL;
342
}
343
344
new = (LDAPControl *) LDAP_MALLOC( sizeof(LDAPControl) );
345
346
if( new == NULL ) {
347
return NULL;
348
}
349
350
new->ldctl_oid = LDAP_STRDUP( c->ldctl_oid );
351
352
if(new->ldctl_oid == NULL) {
353
LDAP_FREE( new );
354
return NULL;
355
}
356
357
if( c->ldctl_value.bv_val != NULL ) {
358
new->ldctl_value.bv_val =
359
(char *) LDAP_MALLOC( c->ldctl_value.bv_len + 1 );
360
361
if(new->ldctl_value.bv_val == NULL) {
362
if(new->ldctl_oid != NULL) {
363
LDAP_FREE( new->ldctl_oid );
364
}
365
LDAP_FREE( new );
366
return NULL;
367
}
368
369
new->ldctl_value.bv_len = c->ldctl_value.bv_len;
370
371
AC_MEMCPY( new->ldctl_value.bv_val, c->ldctl_value.bv_val,
372
c->ldctl_value.bv_len );
373
374
new->ldctl_value.bv_val[new->ldctl_value.bv_len] = '\0';
375
376
} else {
377
new->ldctl_value.bv_len = 0;
378
new->ldctl_value.bv_val = NULL;
379
}
380
381
new->ldctl_iscritical = c->ldctl_iscritical;
382
return new;
383
}
384
385
/*
386
* Find a LDAPControl - deprecated
387
*/
388
LDAPControl *
389
ldap_find_control(
390
LDAP_CONST char *oid,
391
LDAPControl **ctrls )
392
{
393
if( ctrls == NULL || *ctrls == NULL ) {
394
return NULL;
395
}
396
397
for( ; *ctrls != NULL; ctrls++ ) {
398
if( strcmp( (*ctrls)->ldctl_oid, oid ) == 0 ) {
399
return *ctrls;
400
}
401
}
402
403
return NULL;
404
}
405
406
/*
407
* Find a LDAPControl
408
*/
409
LDAPControl *
410
ldap_control_find(
411
LDAP_CONST char *oid,
412
LDAPControl **ctrls,
413
LDAPControl ***nextctrlp )
414
{
415
if ( oid == NULL || ctrls == NULL || *ctrls == NULL ) {
416
return NULL;
417
}
418
419
for( ; *ctrls != NULL; ctrls++ ) {
420
if( strcmp( (*ctrls)->ldctl_oid, oid ) == 0 ) {
421
if ( nextctrlp != NULL ) {
422
*nextctrlp = ctrls + 1;
423
}
424
425
return *ctrls;
426
}
427
}
428
429
if ( nextctrlp != NULL ) {
430
*nextctrlp = NULL;
431
}
432
433
return NULL;
434
}
435
436
/*
437
* Create a LDAPControl, optionally from ber - deprecated
438
*/
439
int
440
ldap_create_control(
441
LDAP_CONST char *requestOID,
442
BerElement *ber,
443
int iscritical,
444
LDAPControl **ctrlp )
445
{
446
LDAPControl *ctrl;
447
448
assert( requestOID != NULL );
449
assert( ctrlp != NULL );
450
451
ctrl = (LDAPControl *) LDAP_MALLOC( sizeof(LDAPControl) );
452
if ( ctrl == NULL ) {
453
return LDAP_NO_MEMORY;
454
}
455
456
BER_BVZERO(&ctrl->ldctl_value);
457
if ( ber && ( ber_flatten2( ber, &ctrl->ldctl_value, 1 ) == -1 )) {
458
LDAP_FREE( ctrl );
459
return LDAP_NO_MEMORY;
460
}
461
462
ctrl->ldctl_oid = LDAP_STRDUP( requestOID );
463
ctrl->ldctl_iscritical = iscritical;
464
465
if ( requestOID != NULL && ctrl->ldctl_oid == NULL ) {
466
ldap_control_free( ctrl );
467
return LDAP_NO_MEMORY;
468
}
469
470
*ctrlp = ctrl;
471
return LDAP_SUCCESS;
472
}
473
474
/*
475
* Create a LDAPControl, optionally from value
476
*/
477
int
478
ldap_control_create(
479
LDAP_CONST char *requestOID,
480
int iscritical,
481
struct berval *value,
482
int dupval,
483
LDAPControl **ctrlp )
484
{
485
LDAPControl *ctrl;
486
487
assert( requestOID != NULL );
488
assert( ctrlp != NULL );
489
490
ctrl = (LDAPControl *) LDAP_CALLOC( sizeof(LDAPControl), 1 );
491
if ( ctrl == NULL ) {
492
return LDAP_NO_MEMORY;
493
}
494
495
ctrl->ldctl_iscritical = iscritical;
496
if ( requestOID != NULL ) {
497
ctrl->ldctl_oid = LDAP_STRDUP( requestOID );
498
if ( ctrl->ldctl_oid == NULL ) {
499
ldap_control_free( ctrl );
500
return LDAP_NO_MEMORY;
501
}
502
}
503
504
if ( value && !BER_BVISNULL( value ) ) {
505
if ( dupval ) {
506
ber_dupbv( &ctrl->ldctl_value, value );
507
if ( BER_BVISNULL( &ctrl->ldctl_value ) ) {
508
ldap_control_free( ctrl );
509
return LDAP_NO_MEMORY;
510
}
511
512
} else {
513
ctrl->ldctl_value = *value;
514
}
515
}
516
517
*ctrlp = ctrl;
518
519
return LDAP_SUCCESS;
520
}
521
522
/*
523
* check for critical client controls and bitch if present
524
* if we ever support critical controls, we'll have to
525
* find a means for maintaining per API call control
526
* information.
527
*/
528
int ldap_int_client_controls( LDAP *ld, LDAPControl **ctrls )
529
{
530
LDAPControl *const *c;
531
532
assert( ld != NULL );
533
assert( LDAP_VALID( ld ) );
534
535
if( ctrls == NULL ) {
536
/* use default client controls */
537
ctrls = ld->ld_cctrls;
538
}
539
540
if( ctrls == NULL || *ctrls == NULL ) {
541
return LDAP_SUCCESS;
542
}
543
544
for( c = ctrls ; *c != NULL; c++ ) {
545
if( (*c)->ldctl_iscritical ) {
546
ld->ld_errno = LDAP_NOT_SUPPORTED;
547
return ld->ld_errno;
548
}
549
}
550
551
return LDAP_SUCCESS;
552
}
553
554