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