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