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
57 int
ldap_create_page_control_value(LDAP * ld,ber_int_t pagesize,struct berval * cookie,struct berval * value)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
ldap_create_page_control(LDAP * ld,ber_int_t pagesize,struct berval * cookie,int iscritical,LDAPControl ** ctrlp)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
ldap_parse_pageresponse_control(LDAP * ld,LDAPControl * ctrl,ber_int_t * countp,struct berval * cookie)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
ldap_parse_page_control(LDAP * ld,LDAPControl ** ctrls,ber_int_t * countp,struct berval ** cookiep)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