Home | History | Annotate | Line # | Download | only in libldap
      1 /*	$NetBSD: pagectrl.c,v 1.4 2025/09/05 21:16:21 christos Exp $	*/
      2 
      3 /* $OpenLDAP$ */
      4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
      5  *
      6  * Copyright 1998-2024 The OpenLDAP Foundation.
      7  * Copyright 2006 Hans Leidekker
      8  * All rights reserved.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted only as authorized by the OpenLDAP
     12  * Public License.
     13  *
     14  * A copy of this license is available in the file LICENSE in the
     15  * top-level directory of the distribution or, alternatively, at
     16  * <http://www.OpenLDAP.org/license.html>.
     17  */
     18 
     19 #include <sys/cdefs.h>
     20 __RCSID("$NetBSD: pagectrl.c,v 1.4 2025/09/05 21:16:21 christos Exp $");
     21 
     22 #include "portable.h"
     23 
     24 #include <stdio.h>
     25 #include <ac/stdlib.h>
     26 #include <ac/string.h>
     27 #include <ac/time.h>
     28 
     29 #include "ldap-int.h"
     30 
     31 /* ---------------------------------------------------------------------------
     32     ldap_create_page_control_value
     33 
     34     Create and encode the value of the paged results control (RFC 2696).
     35 
     36     ld          (IN) An LDAP session handle
     37     pagesize    (IN) Page size requested
     38     cookie      (IN) Opaque structure used by the server to track its
     39                      location in the search results.  NULL on the
     40                      first call.
     41     value      (OUT) Control value, SHOULD be freed by calling
     42 					 ldap_memfree() when done.
     43 
     44     pagedResultsControl ::= SEQUENCE {
     45             controlType     1.2.840.113556.1.4.319,
     46             criticality     BOOLEAN DEFAULT FALSE,
     47             controlValue    searchControlValue }
     48 
     49     searchControlValue ::= SEQUENCE {
     50             size            INTEGER (0..maxInt),
     51                                     -- requested page size from client
     52                                     -- result set size estimate from server
     53             cookie          OCTET STRING }
     54 
     55    ---------------------------------------------------------------------------*/
     56 
     57 int
     58 ldap_create_page_control_value(
     59 	LDAP *ld,
     60 	ber_int_t pagesize,
     61 	struct berval	*cookie,
     62 	struct berval	*value )
     63 {
     64 	BerElement	*ber = NULL;
     65 	ber_tag_t	tag;
     66 	struct berval	null_cookie = { 0, NULL };
     67 
     68 	if ( ld == NULL || value == NULL ||
     69 		pagesize < 1 || pagesize > LDAP_MAXINT )
     70 	{
     71 		if ( ld )
     72 			ld->ld_errno = LDAP_PARAM_ERROR;
     73 		return LDAP_PARAM_ERROR;
     74 	}
     75 
     76 	assert( LDAP_VALID( ld ) );
     77 
     78 	value->bv_val = NULL;
     79 	value->bv_len = 0;
     80 	ld->ld_errno = LDAP_SUCCESS;
     81 
     82 	if ( cookie == NULL ) {
     83 		cookie = &null_cookie;
     84 	}
     85 
     86 	ber = ldap_alloc_ber_with_options( ld );
     87 	if ( ber == NULL ) {
     88 		ld->ld_errno = LDAP_NO_MEMORY;
     89 		return ld->ld_errno;
     90 	}
     91 
     92 	tag = ber_printf( ber, "{iO}", pagesize, cookie );
     93 	if ( tag == LBER_ERROR ) {
     94 		ld->ld_errno = LDAP_ENCODING_ERROR;
     95 		goto done;
     96 	}
     97 
     98 	if ( ber_flatten2( ber, value, 1 ) == -1 ) {
     99 		ld->ld_errno = LDAP_NO_MEMORY;
    100 	}
    101 
    102 done:;
    103 	if ( ber != NULL ) {
    104 		ber_free( ber, 1 );
    105 	}
    106 
    107 	return ld->ld_errno;
    108 }
    109 
    110 
    111 /* ---------------------------------------------------------------------------
    112     ldap_create_page_control
    113 
    114     Create and encode a page control.
    115 
    116     ld          (IN) An LDAP session handle
    117     pagesize    (IN) Page size requested
    118     cookie      (IN) Opaque structure used by the server to track its
    119                      location in the search results.  NULL on the
    120                      first call.
    121     value      (OUT) Control value, SHOULD be freed by calling
    122 					 ldap_memfree() when done.
    123     iscritical  (IN) Criticality
    124     ctrlp      (OUT) LDAP control, SHOULD be freed by calling
    125 					 ldap_control_free() when done.
    126 
    127     pagedResultsControl ::= SEQUENCE {
    128             controlType     1.2.840.113556.1.4.319,
    129             criticality     BOOLEAN DEFAULT FALSE,
    130             controlValue    searchControlValue }
    131 
    132     searchControlValue ::= SEQUENCE {
    133             size            INTEGER (0..maxInt),
    134                                     -- requested page size from client
    135                                     -- result set size estimate from server
    136             cookie          OCTET STRING }
    137 
    138    ---------------------------------------------------------------------------*/
    139 
    140 int
    141 ldap_create_page_control(
    142 	LDAP		*ld,
    143 	ber_int_t	pagesize,
    144 	struct berval	*cookie,
    145 	int		iscritical,
    146 	LDAPControl	**ctrlp )
    147 {
    148 	struct berval	value;
    149 
    150 	if ( ctrlp == NULL ) {
    151 		ld->ld_errno = LDAP_PARAM_ERROR;
    152 		return ld->ld_errno;
    153 	}
    154 
    155 	ld->ld_errno = ldap_create_page_control_value( ld,
    156 		pagesize, cookie, &value );
    157 	if ( ld->ld_errno == LDAP_SUCCESS ) {
    158 		ld->ld_errno = ldap_control_create( LDAP_CONTROL_PAGEDRESULTS,
    159 			iscritical, &value, 0, ctrlp );
    160 		if ( ld->ld_errno != LDAP_SUCCESS ) {
    161 			LDAP_FREE( value.bv_val );
    162 		}
    163 	}
    164 
    165 	return ld->ld_errno;
    166 }
    167 
    168 
    169 /* ---------------------------------------------------------------------------
    170     ldap_parse_pageresponse_control
    171 
    172     Decode a page control.
    173 
    174     ld          (IN) An LDAP session handle
    175     ctrl        (IN) The page response control
    176     count      (OUT) The number of entries in the page.
    177     cookie     (OUT) Opaque cookie.  Use ldap_memfree() to
    178                      free the bv_val member of this structure.
    179 
    180    ---------------------------------------------------------------------------*/
    181 
    182 int
    183 ldap_parse_pageresponse_control(
    184 	LDAP *ld,
    185 	LDAPControl *ctrl,
    186 	ber_int_t *countp,
    187 	struct berval *cookie )
    188 {
    189 	BerElement *ber;
    190 	ber_tag_t tag;
    191 	ber_int_t count;
    192 
    193 	if ( ld == NULL || ctrl == NULL || cookie == NULL ) {
    194 		if ( ld )
    195 			ld->ld_errno = LDAP_PARAM_ERROR;
    196 		return LDAP_PARAM_ERROR;
    197 	}
    198 
    199 	/* Create a BerElement from the berval returned in the control. */
    200 	ber = ber_init( &ctrl->ldctl_value );
    201 
    202 	if ( ber == NULL ) {
    203 		ld->ld_errno = LDAP_NO_MEMORY;
    204 		return ld->ld_errno;
    205 	}
    206 
    207 	/* Extract the count and cookie from the control. */
    208 	tag = ber_scanf( ber, "{io}", &count, cookie );
    209         ber_free( ber, 1 );
    210 
    211 	if ( tag == LBER_ERROR ) {
    212 		ld->ld_errno = LDAP_DECODING_ERROR;
    213 	} else {
    214 		ld->ld_errno = LDAP_SUCCESS;
    215 
    216 		if ( countp != NULL ) {
    217 			*countp = (unsigned long)count;
    218 		}
    219 	}
    220 
    221 	return ld->ld_errno;
    222 }
    223 
    224 /* ---------------------------------------------------------------------------
    225     ldap_parse_page_control
    226 
    227     Decode a page control.
    228 
    229     ld          (IN) An LDAP session handle
    230     ctrls       (IN) Response controls
    231     count      (OUT) The number of entries in the page.
    232     cookie     (OUT) Opaque cookie.  Use ldap_memfree() to
    233                      free the bv_val member of this structure.
    234 
    235    ---------------------------------------------------------------------------*/
    236 
    237 int
    238 ldap_parse_page_control(
    239 	LDAP		*ld,
    240 	LDAPControl	**ctrls,
    241 	ber_int_t *countp,
    242 	struct berval	**cookiep )
    243 {
    244 	LDAPControl *c;
    245 	struct berval	cookie;
    246 
    247 	if ( cookiep == NULL ) {
    248 		ld->ld_errno = LDAP_PARAM_ERROR;
    249 		return ld->ld_errno;
    250 	}
    251 
    252 	if ( ctrls == NULL ) {
    253 		ld->ld_errno =  LDAP_CONTROL_NOT_FOUND;
    254 		return ld->ld_errno;
    255 	}
    256 
    257 	c = ldap_control_find( LDAP_CONTROL_PAGEDRESULTS, ctrls, NULL );
    258 	if ( c == NULL ) {
    259 		/* No page control was found. */
    260 		ld->ld_errno = LDAP_CONTROL_NOT_FOUND;
    261 		return ld->ld_errno;
    262 	}
    263 
    264 	ld->ld_errno = ldap_parse_pageresponse_control( ld, c, countp, &cookie );
    265 	if ( ld->ld_errno == LDAP_SUCCESS ) {
    266 		*cookiep = LDAP_MALLOC( sizeof( struct berval ) );
    267 		if ( *cookiep == NULL ) {
    268 			ld->ld_errno = LDAP_NO_MEMORY;
    269 		} else {
    270 			**cookiep = cookie;
    271 		}
    272 	}
    273 
    274 	return ld->ld_errno;
    275 }
    276 
    277