123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552 |
- /* $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);
- }
|