diff options
Diffstat (limited to 'libraries/libldap/psearchctrl.c')
-rw-r--r-- | libraries/libldap/psearchctrl.c | 348 |
1 files changed, 348 insertions, 0 deletions
diff --git a/libraries/libldap/psearchctrl.c b/libraries/libldap/psearchctrl.c new file mode 100644 index 0000000..b465873 --- /dev/null +++ b/libraries/libldap/psearchctrl.c @@ -0,0 +1,348 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software <http://www.openldap.org/>. + * + * Copyright 1998-2022 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>. + */ +/* ACKNOWLEDGEMENTS: + * This work was developed by Howard Chu for inclusion in + * OpenLDAP Software. + */ + +#include "portable.h" + +#include <stdio.h> +#include <ac/stdlib.h> +#include <ac/string.h> +#include <ac/time.h> + +#include "ldap-int.h" + +/* Based on draft-ietf-ldapext-c-api-psearch-00 */ + +/* --------------------------------------------------------------------------- + ldap_create_persistentsearch_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(). + + changetypes (IN) A bit-sensitive field that indicates which kinds of + changes the client wants to be informed about. Its + value should be LDAP_CHANGETYPE_ANY, or any logical-OR + combination of LDAP_CHANGETYPE_ADD, + LDAP_CHANGETYPE_DELETE, LDAP_CHANGETYPE_MODIFY, and + LDAP_CHANGETYPE_MODDN. This field corresponds to the + changeType element of the BER-encoded PersistentSearch + control value itself. + + changesonly (IN) A Boolean field that indicates whether the client + wishes to only receive searchResultEntry messages for + entries that have been changed. If non-zero, only + entries that result from changes are returned; other- + wise, all of the static entries that match the search + criteria are returned before the server begins change + notification. This field corresponds to the changes- + Only element of the BER-encoded PersistentSearch con- + trol value itself. + + return_echg_ctls (IN) A Boolean field that indicates whether the server + should send back an Entry Change Notification control + with each searchResultEntry that is returned due to a + change to an entry. If non-zero, Entry Change + Notification controls are requested; if zero, they are + not. This field corresponds to the returnECs element + of the BER-encoded PersistentSearch control value + itself. + + value (OUT) Contains the control value; the bv_val member of the berval structure + SHOULD be freed by calling ldap_memfree() when done. + + ---------------------------------------------------------------------------*/ + +int +ldap_create_persistentsearch_control_value( + LDAP *ld, + int changetypes, + int changesonly, + int return_echg_ctls, + 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 ( value == NULL ) { + ld->ld_errno = LDAP_PARAM_ERROR; + return LDAP_PARAM_ERROR; + } + if (( changetypes & 0x0f ) != changetypes ) { + 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, "{ibb}", changetypes, changesonly, return_echg_ctls ); + 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_persistentsearch_control + + Create and encode the persistent search control. + + ld (IN) An LDAP session handle, as obtained from a call to + ldap_init(). + + changetypes (IN) A bit-sensitive field that indicates which kinds of + changes the client wants to be informed about. Its + value should be LDAP_CHANGETYPE_ANY, or any logical-OR + combination of LDAP_CHANGETYPE_ADD, + LDAP_CHANGETYPE_DELETE, LDAP_CHANGETYPE_MODIFY, and + LDAP_CHANGETYPE_MODDN. This field corresponds to the + changeType element of the BER-encoded PersistentSearch + control value itself. + + changesonly (IN) A Boolean field that indicates whether the client + wishes to only receive searchResultEntry messages for + entries that have been changed. If non-zero, only + entries that result from changes are returned; other- + wise, all of the static entries that match the search + criteria are returned before the server begins change + notification. This field corresponds to the changes- + Only element of the BER-encoded PersistentSearch con- + trol value itself. + + return_echg_ctls (IN) A Boolean field that indicates whether the server + should send back an Entry Change Notification control + with each searchResultEntry that is returned due to a + change to an entry. If non-zero, Entry Change + Notification controls are requested; if zero, they are + not. This field corresponds to the returnECs element + of the BER-encoded PersistentSearch control value + itself. + + 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. + + ---------------------------------------------------------------------------*/ + +int +ldap_create_persistentsearch_control( + LDAP *ld, + int changetypes, + int changesonly, + int return_echg_ctls, + 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_persistentsearch_control_value( ld, changetypes, changesonly, return_echg_ctls, &value ); + if ( ld->ld_errno == LDAP_SUCCESS ) { + ld->ld_errno = ldap_control_create( LDAP_CONTROL_PERSIST_REQUEST, + isCritical, &value, 0, ctrlp ); + if ( ld->ld_errno != LDAP_SUCCESS ) { + LDAP_FREE( value.bv_val ); + } + } + + return ld->ld_errno; +} + + +/* --------------------------------------------------------------------------- + ldap_parse_entrychange_control + + Decode the entry change notification 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. + + chgtypep (OUT) This result parameter is filled in with one of the + following values to indicate the type of change that was + made that caused the entry to be returned: + LDAP_CONTROL_PERSIST_ENTRY_CHANGE_ADD (1), + LDAP_CONTROL_PERSIST_ENTRY_CHANGE_DELETE (2), + LDAP_CONTROL_PERSIST_ENTRY_CHANGE_MODIFY (4), or + LDAP_CONTROL_PERSIST_ENTRY_CHANGE_RENAME (8). + If this parameter is NULL, the change type information + is not returned. + + prevdnp (OUT) This result parameter points to the DN the + entry had before it was renamed and/or moved by a + modifyDN operation. It is set to NULL for other types + of changes. If this parameter is NULL, the previous DN + information is not returned. The returned value is a + pointer to the contents of the control; it is not a + copy of the data. + + chgnumpresentp (OUT) This result parameter is filled in with a non-zero + value if a change number was returned in the control + (the change number is optional and servers MAY choose + not to return it). If this parameter is NULL, no indication + of whether the change number was present is returned. + + chgnump (OUT) This result parameter is filled in with the change number + if one was returned in the control. If this parameter + is NULL, the change number is not returned. + + ---------------------------------------------------------------------------*/ + +int +ldap_parse_entrychange_control( + LDAP *ld, + LDAPControl *ctrl, + int *chgtypep, + struct berval *prevdnp, + int *chgnumpresentp, + long *chgnump ) +{ + BerElement *ber; + ber_tag_t tag, berTag; + ber_len_t berLen; + ber_int_t chgtype; + + assert( ld != NULL ); + assert( LDAP_VALID( ld ) ); + assert( ctrl != NULL ); + + if (ld == NULL) { + return LDAP_PARAM_ERROR; + } + + if (ctrl == NULL) { + ld->ld_errno = LDAP_PARAM_ERROR; + return(ld->ld_errno); + } + + if ( !ctrl->ldctl_value.bv_val ) { + ld->ld_errno = LDAP_DECODING_ERROR; + 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); + } + + if ( prevdnp != NULL ) { + BER_BVZERO( prevdnp ); + } + if ( chgnumpresentp != NULL ) + *chgnumpresentp = 0; + if ( chgnump != NULL ) + *chgnump = 0; + + /* Extract the change type from the control. */ + tag = ber_scanf(ber, "{e" /*}*/, &chgtype); + + if( tag != LBER_ENUMERATED ) { + ber_free(ber, 1); + ld->ld_errno = LDAP_DECODING_ERROR; + return(ld->ld_errno); + } + if ( chgtypep != NULL ) + *chgtypep = chgtype; + + tag = ber_peek_tag( ber, &berLen ); + if ( berLen ) { + if (tag == LBER_OCTETSTRING) { + if (prevdnp != NULL) { + tag = ber_get_stringbv( ber, prevdnp, 0 ); + } else { + struct berval bv; + tag = ber_skip_element( ber, &bv ); + } + if ( tag == LBER_ERROR ) { + ber_free(ber, 1); + ld->ld_errno = LDAP_DECODING_ERROR; + return(ld->ld_errno); + } + tag = ber_peek_tag( ber, &berLen ); + } + + if ( chgnumpresentp != NULL || chgnump != NULL ) { + ber_int_t chgnum = 0; + int present = 0; + if (tag == LBER_INTEGER) { + present = 1; + tag = ber_get_int( ber, &chgnum ); + if ( tag == LBER_ERROR ) { + ber_free(ber, 1); + ld->ld_errno = LDAP_DECODING_ERROR; + return(ld->ld_errno); + } + if ( chgnumpresentp != NULL ) + *chgnumpresentp = present; + if ( chgnump != NULL ) + *chgnump = chgnum; + } + } + } + + ber_free(ber,1); + + ld->ld_errno = LDAP_SUCCESS; + return(ld->ld_errno); +} |