1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3 *
4 * Copyright 1998-2021 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
52 int
ldap_create_page_control_value(LDAP * ld,ber_int_t pagesize,struct berval * cookie,struct berval * value)53 ldap_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
97 done:;
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
135 int
ldap_create_page_control(LDAP * ld,ber_int_t pagesize,struct berval * cookie,int iscritical,LDAPControl ** ctrlp)136 ldap_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
177 int
ldap_parse_pageresponse_control(LDAP * ld,LDAPControl * ctrl,ber_int_t * countp,struct berval * cookie)178 ldap_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
232 int
ldap_parse_page_control(LDAP * ld,LDAPControl ** ctrls,ber_int_t * countp,struct berval ** cookiep)233 ldap_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