xref: /netbsd-src/external/bsd/openldap/dist/libraries/libldap/pagectrl.c (revision 549b59ed3ccf0d36d3097190a0db27b770f3a839)
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