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