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