Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/ldap/libldap/sortctrl.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
/* Portions Copyright (C) 1999, 2000 Novell, Inc. All Rights Reserved.
16
*
17
* THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND
18
* TREATIES. USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT
19
* TO VERSION 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS
20
* AVAILABLE AT HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE"
21
* IN THE TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION
22
* OF THIS WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP
23
* PUBLIC LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT
24
* THE PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY.
25
*/
26
/* Note: A verbatim copy of version 2.0.1 of the OpenLDAP Public License
27
* can be found in the file "build/LICENSE-2.0.1" in this distribution
28
* of OpenLDAP Software.
29
*/
30
31
#include "portable.h"
32
33
#include <stdio.h>
34
#include <ac/stdlib.h>
35
#include <ac/string.h>
36
#include <ac/time.h>
37
38
#include "ldap-int.h"
39
40
#define LDAP_MATCHRULE_IDENTIFIER 0x80L
41
#define LDAP_REVERSEORDER_IDENTIFIER 0x81L
42
#define LDAP_ATTRTYPES_IDENTIFIER 0x80L
43
44
45
46
/* ---------------------------------------------------------------------------
47
countKeys
48
49
Internal function to determine the number of keys in the string.
50
51
keyString (IN) String of items separated by whitespace.
52
---------------------------------------------------------------------------*/
53
54
static int countKeys(char *keyString)
55
{
56
char *p = keyString;
57
int count = 0;
58
59
for (;;)
60
{
61
while (LDAP_SPACE(*p)) /* Skip leading whitespace */
62
p++;
63
64
if (*p == '\0') /* End of string? */
65
return count;
66
67
count++; /* Found start of a key */
68
69
while (!LDAP_SPACE(*p)) /* Skip till next space or end of string. */
70
if (*p++ == '\0')
71
return count;
72
}
73
}
74
75
76
/* ---------------------------------------------------------------------------
77
readNextKey
78
79
Internal function to parse the next sort key in the string.
80
Allocate an LDAPSortKey structure and initialize it with
81
attribute name, reverse flag, and matching rule OID.
82
83
Each sort key in the string has the format:
84
[whitespace][-]attribute[:[OID]]
85
86
pNextKey (IN/OUT) Points to the next key in the sortkey string to parse.
87
The pointer is updated to point to the next character
88
after the sortkey being parsed.
89
90
key (OUT) Points to the address of an LDAPSortKey structure
91
which has been allocated by this routine and
92
initialized with information from the next sortkey.
93
---------------------------------------------------------------------------*/
94
95
static int readNextKey( char **pNextKey, LDAPSortKey **key)
96
{
97
char *p = *pNextKey;
98
int rev = 0;
99
char *attrStart;
100
int attrLen;
101
char *oidStart = NULL;
102
int oidLen = 0;
103
104
/* Skip leading white space. */
105
while (LDAP_SPACE(*p))
106
p++;
107
108
if (*p == '-') /* Check if the reverse flag is present. */
109
{
110
rev=1;
111
p++;
112
}
113
114
/* We're now positioned at the start of the attribute. */
115
attrStart = p;
116
117
/* Get the length of the attribute until the next whitespace or ":". */
118
attrLen = strcspn(p, " \t:");
119
p += attrLen;
120
121
if (attrLen == 0) /* If no attribute name was present, quit. */
122
return LDAP_PARAM_ERROR;
123
124
if (*p == ':')
125
{
126
oidStart = ++p; /* Start of the OID, after the colon */
127
oidLen = strcspn(p, " \t"); /* Get length of OID till next whitespace */
128
p += oidLen;
129
}
130
131
*pNextKey = p; /* Update argument to point to next key */
132
133
/* Allocate an LDAPSortKey structure */
134
*key = LDAP_MALLOC(sizeof(LDAPSortKey));
135
if (*key == NULL) return LDAP_NO_MEMORY;
136
137
/* Allocate memory for the attribute and copy to it. */
138
(*key)->attributeType = LDAP_MALLOC(attrLen+1);
139
if ((*key)->attributeType == NULL) {
140
LDAP_FREE(*key);
141
return LDAP_NO_MEMORY;
142
}
143
144
strncpy((*key)->attributeType, attrStart, attrLen);
145
(*key)->attributeType[attrLen] = 0;
146
147
/* If present, allocate memory for the OID and copy to it. */
148
if (oidLen) {
149
(*key)->orderingRule = LDAP_MALLOC(oidLen+1);
150
if ((*key)->orderingRule == NULL) {
151
LDAP_FREE((*key)->attributeType);
152
LDAP_FREE(*key);
153
return LDAP_NO_MEMORY;
154
}
155
strncpy((*key)->orderingRule, oidStart, oidLen);
156
(*key)->orderingRule[oidLen] = 0;
157
158
} else {
159
(*key)->orderingRule = NULL;
160
}
161
162
(*key)->reverseOrder = rev;
163
164
return LDAP_SUCCESS;
165
}
166
167
168
/* ---------------------------------------------------------------------------
169
ldap_create_sort_keylist
170
171
Create an array of pointers to LDAPSortKey structures, containing the
172
information specified by the string representation of one or more
173
sort keys.
174
175
sortKeyList (OUT) Points to a null-terminated array of pointers to
176
LDAPSortKey structures allocated by this routine.
177
This memory SHOULD be freed by the calling program
178
using ldap_free_sort_keylist().
179
180
keyString (IN) Points to a string of one or more sort keys.
181
182
---------------------------------------------------------------------------*/
183
184
int
185
ldap_create_sort_keylist ( LDAPSortKey ***sortKeyList, char *keyString )
186
{
187
int numKeys, rc, i;
188
char *nextKey;
189
LDAPSortKey **keyList = NULL;
190
191
assert( sortKeyList != NULL );
192
assert( keyString != NULL );
193
194
*sortKeyList = NULL;
195
196
/* Determine the number of sort keys so we can allocate memory. */
197
if (( numKeys = countKeys(keyString)) == 0) {
198
return LDAP_PARAM_ERROR;
199
}
200
201
/* Allocate the array of pointers. Initialize to NULL. */
202
keyList=(LDAPSortKey**)LBER_CALLOC(numKeys+1, sizeof(LDAPSortKey*));
203
if ( keyList == NULL) return LDAP_NO_MEMORY;
204
205
/* For each sort key in the string, create an LDAPSortKey structure
206
and add it to the list.
207
*/
208
nextKey = keyString; /* Points to the next key in the string */
209
for (i=0; i < numKeys; i++) {
210
rc = readNextKey(&nextKey, &keyList[i]);
211
212
if (rc != LDAP_SUCCESS) {
213
ldap_free_sort_keylist(keyList);
214
return rc;
215
}
216
}
217
218
*sortKeyList = keyList;
219
return LDAP_SUCCESS;
220
}
221
222
223
/* ---------------------------------------------------------------------------
224
ldap_free_sort_keylist
225
226
Frees the sort key structures created by ldap_create_sort_keylist().
227
Frees the memory referenced by the LDAPSortKey structures,
228
the LDAPSortKey structures themselves, and the array of pointers
229
to the structures.
230
231
keyList (IN) Points to an array of pointers to LDAPSortKey structures.
232
---------------------------------------------------------------------------*/
233
234
void
235
ldap_free_sort_keylist ( LDAPSortKey **keyList )
236
{
237
int i;
238
LDAPSortKey *nextKeyp;
239
240
if (keyList == NULL) return;
241
242
i=0;
243
while ( 0 != (nextKeyp = keyList[i++]) ) {
244
if (nextKeyp->attributeType) {
245
LBER_FREE(nextKeyp->attributeType);
246
}
247
248
if (nextKeyp->orderingRule != NULL) {
249
LBER_FREE(nextKeyp->orderingRule);
250
}
251
252
LBER_FREE(nextKeyp);
253
}
254
255
LBER_FREE(keyList);
256
}
257
258
259
/* ---------------------------------------------------------------------------
260
ldap_create_sort_control_value
261
262
Create and encode the value of the server-side sort control.
263
264
ld (IN) An LDAP session handle, as obtained from a call to
265
ldap_init().
266
267
keyList (IN) Points to a null-terminated array of pointers to
268
LDAPSortKey structures, containing a description of
269
each of the sort keys to be used. The description
270
consists of an attribute name, ascending/descending flag,
271
and an optional matching rule (OID) to use.
272
273
value (OUT) Contains the control value; the bv_val member of the berval structure
274
SHOULD be freed by calling ldap_memfree() when done.
275
276
277
Ber encoding
278
279
SortKeyList ::= SEQUENCE OF SEQUENCE {
280
attributeType AttributeDescription,
281
orderingRule [0] MatchingRuleId OPTIONAL,
282
reverseOrder [1] BOOLEAN DEFAULT FALSE }
283
284
---------------------------------------------------------------------------*/
285
286
int
287
ldap_create_sort_control_value(
288
LDAP *ld,
289
LDAPSortKey **keyList,
290
struct berval *value )
291
{
292
int i;
293
BerElement *ber = NULL;
294
ber_tag_t tag;
295
296
assert( ld != NULL );
297
assert( LDAP_VALID( ld ) );
298
299
if ( ld == NULL ) return LDAP_PARAM_ERROR;
300
if ( keyList == NULL || value == NULL ) {
301
ld->ld_errno = LDAP_PARAM_ERROR;
302
return LDAP_PARAM_ERROR;
303
}
304
305
value->bv_val = NULL;
306
value->bv_len = 0;
307
ld->ld_errno = LDAP_SUCCESS;
308
309
ber = ldap_alloc_ber_with_options( ld );
310
if ( ber == NULL) {
311
ld->ld_errno = LDAP_NO_MEMORY;
312
return ld->ld_errno;
313
}
314
315
tag = ber_printf( ber, "{" /*}*/ );
316
if ( tag == LBER_ERROR ) {
317
goto error_return;
318
}
319
320
for ( i = 0; keyList[i] != NULL; i++ ) {
321
tag = ber_printf( ber, "{s" /*}*/, keyList[i]->attributeType );
322
if ( tag == LBER_ERROR ) {
323
goto error_return;
324
}
325
326
if ( keyList[i]->orderingRule != NULL ) {
327
tag = ber_printf( ber, "ts",
328
LDAP_MATCHRULE_IDENTIFIER,
329
keyList[i]->orderingRule );
330
331
if ( tag == LBER_ERROR ) {
332
goto error_return;
333
}
334
}
335
336
if ( keyList[i]->reverseOrder ) {
337
tag = ber_printf( ber, "tb",
338
LDAP_REVERSEORDER_IDENTIFIER,
339
keyList[i]->reverseOrder );
340
341
if ( tag == LBER_ERROR ) {
342
goto error_return;
343
}
344
}
345
346
tag = ber_printf( ber, /*{*/ "N}" );
347
if ( tag == LBER_ERROR ) {
348
goto error_return;
349
}
350
}
351
352
tag = ber_printf( ber, /*{*/ "N}" );
353
if ( tag == LBER_ERROR ) {
354
goto error_return;
355
}
356
357
if ( ber_flatten2( ber, value, 1 ) == -1 ) {
358
ld->ld_errno = LDAP_NO_MEMORY;
359
}
360
361
if ( 0 ) {
362
error_return:;
363
ld->ld_errno = LDAP_ENCODING_ERROR;
364
}
365
366
if ( ber != NULL ) {
367
ber_free( ber, 1 );
368
}
369
370
return ld->ld_errno;
371
}
372
373
374
/* ---------------------------------------------------------------------------
375
ldap_create_sort_control
376
377
Create and encode the server-side sort control.
378
379
ld (IN) An LDAP session handle, as obtained from a call to
380
ldap_init().
381
382
keyList (IN) Points to a null-terminated array of pointers to
383
LDAPSortKey structures, containing a description of
384
each of the sort keys to be used. The description
385
consists of an attribute name, ascending/descending flag,
386
and an optional matching rule (OID) to use.
387
388
isCritical (IN) 0 - Indicates the control is not critical to the operation.
389
non-zero - The control is critical to the operation.
390
391
ctrlp (OUT) Returns a pointer to the LDAPControl created. This control
392
SHOULD be freed by calling ldap_control_free() when done.
393
394
395
Ber encoding
396
397
SortKeyList ::= SEQUENCE OF SEQUENCE {
398
attributeType AttributeDescription,
399
orderingRule [0] MatchingRuleId OPTIONAL,
400
reverseOrder [1] BOOLEAN DEFAULT FALSE }
401
402
---------------------------------------------------------------------------*/
403
404
int
405
ldap_create_sort_control(
406
LDAP *ld,
407
LDAPSortKey **keyList,
408
int isCritical,
409
LDAPControl **ctrlp )
410
{
411
struct berval value;
412
413
assert( ld != NULL );
414
assert( LDAP_VALID( ld ) );
415
416
if ( ld == NULL ) {
417
return LDAP_PARAM_ERROR;
418
}
419
420
if ( ctrlp == NULL ) {
421
ld->ld_errno = LDAP_PARAM_ERROR;
422
return ld->ld_errno;
423
}
424
425
ld->ld_errno = ldap_create_sort_control_value( ld, keyList, &value );
426
if ( ld->ld_errno == LDAP_SUCCESS ) {
427
ld->ld_errno = ldap_control_create( LDAP_CONTROL_SORTREQUEST,
428
isCritical, &value, 0, ctrlp );
429
if ( ld->ld_errno != LDAP_SUCCESS ) {
430
LDAP_FREE( value.bv_val );
431
}
432
}
433
434
return ld->ld_errno;
435
}
436
437
438
/* ---------------------------------------------------------------------------
439
ldap_parse_sortedresult_control
440
441
Decode the server-side sort control return information.
442
443
ld (IN) An LDAP session handle, as obtained from a call to
444
ldap_init().
445
446
ctrl (IN) The address of the LDAP Control Structure.
447
448
returnCode (OUT) This result parameter is filled in with the sort control
449
result code. This parameter MUST not be NULL.
450
451
attribute (OUT) If an error occurred the server may return a string
452
indicating the first attribute in the sortkey list
453
that was in error. If a string is returned, the memory
454
should be freed with ldap_memfree. If this parameter is
455
NULL, no string is returned.
456
457
458
Ber encoding for sort control
459
460
SortResult ::= SEQUENCE {
461
sortResult ENUMERATED {
462
success (0), -- results are sorted
463
operationsError (1), -- server internal failure
464
timeLimitExceeded (3), -- timelimit reached before
465
-- sorting was completed
466
strongAuthRequired (8), -- refused to return sorted
467
-- results via insecure
468
-- protocol
469
adminLimitExceeded (11), -- too many matching entries
470
-- for the server to sort
471
noSuchAttribute (16), -- unrecognized attribute
472
-- type in sort key
473
inappropriateMatching (18), -- unrecognized or inappro-
474
-- priate matching rule in
475
-- sort key
476
insufficientAccessRights (50), -- refused to return sorted
477
-- results to this client
478
busy (51), -- too busy to process
479
unwillingToPerform (53), -- unable to sort
480
other (80)
481
},
482
attributeType [0] AttributeDescription OPTIONAL }
483
---------------------------------------------------------------------------*/
484
485
int
486
ldap_parse_sortresponse_control(
487
LDAP *ld,
488
LDAPControl *ctrl,
489
ber_int_t *returnCode,
490
char **attribute )
491
{
492
BerElement *ber;
493
ber_tag_t tag, berTag;
494
ber_len_t berLen;
495
496
assert( ld != NULL );
497
assert( LDAP_VALID( ld ) );
498
499
if (ld == NULL) {
500
return LDAP_PARAM_ERROR;
501
}
502
503
if (ctrl == NULL) {
504
ld->ld_errno = LDAP_PARAM_ERROR;
505
return(ld->ld_errno);
506
}
507
508
if (attribute) {
509
*attribute = NULL;
510
}
511
512
if ( strcmp(LDAP_CONTROL_SORTRESPONSE, ctrl->ldctl_oid) != 0 ) {
513
/* Not sort result control */
514
ld->ld_errno = LDAP_CONTROL_NOT_FOUND;
515
return(ld->ld_errno);
516
}
517
518
/* Create a BerElement from the berval returned in the control. */
519
ber = ber_init(&ctrl->ldctl_value);
520
521
if (ber == NULL) {
522
ld->ld_errno = LDAP_NO_MEMORY;
523
return(ld->ld_errno);
524
}
525
526
/* Extract the result code from the control. */
527
tag = ber_scanf(ber, "{e" /*}*/, returnCode);
528
529
if( tag == LBER_ERROR ) {
530
ber_free(ber, 1);
531
ld->ld_errno = LDAP_DECODING_ERROR;
532
return(ld->ld_errno);
533
}
534
535
/* If caller wants the attribute name, and if it's present in the control,
536
extract the attribute name which caused the error. */
537
if (attribute && (LDAP_ATTRTYPES_IDENTIFIER == ber_peek_tag(ber, &berLen)))
538
{
539
tag = ber_scanf(ber, "ta", &berTag, attribute);
540
541
if (tag == LBER_ERROR ) {
542
ber_free(ber, 1);
543
ld->ld_errno = LDAP_DECODING_ERROR;
544
return(ld->ld_errno);
545
}
546
}
547
548
ber_free(ber,1);
549
550
ld->ld_errno = LDAP_SUCCESS;
551
return(ld->ld_errno);
552
}
553
554