1/* $NetBSD: pagectrl.c,v 1.3 2021/08/14 16:14:56 christos Exp $ */ 2 3/* $OpenLDAP$ */ 4/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 5 * 6 * Copyright 1998-2021 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.3 2021/08/14 16:14:56 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 57int 58ldap_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 102done:; 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 140int 141ldap_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 182int 183ldap_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 237int 238ldap_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