]> git.sur5r.net Git - openldap/blob - libraries/libldap/vlvctrl.c
ITS#4614 - complain if glue/subordinate are attempted on the same backend
[openldap] / libraries / libldap / vlvctrl.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1998-2006 The OpenLDAP Foundation.
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 /* Portions Copyright (C) 1999, 2000 Novell, Inc. All Rights Reserved.
16  *
17  * THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND
18  * TREATIES. USE, MODIFICATION, AND REDISTRIBUTION OF THIS WORK IS SUBJECT
19  * TO VERSION 2.0.1 OF THE OPENLDAP PUBLIC LICENSE, A COPY OF WHICH IS
20  * AVAILABLE AT HTTP://WWW.OPENLDAP.ORG/LICENSE.HTML OR IN THE FILE "LICENSE"
21  * IN THE TOP-LEVEL DIRECTORY OF THE DISTRIBUTION. ANY USE OR EXPLOITATION
22  * OF THIS WORK OTHER THAN AS AUTHORIZED IN VERSION 2.0.1 OF THE OPENLDAP
23  * PUBLIC LICENSE, OR OTHER PRIOR WRITTEN CONSENT FROM NOVELL, COULD SUBJECT
24  * THE PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY.
25  *---
26  * Note: A verbatim copy of version 2.0.1 of the OpenLDAP Public License
27  * can be found in the file "build/LICENSE-2.0.1" in this distribution
28  * of OpenLDAP Software.
29  */
30 /* Portions Copyright (C) The Internet Society (1997)
31  * ASN.1 fragments are from RFC 2251; see RFC for full legal notices.
32  */
33
34 #include "portable.h"
35
36 #include <stdio.h>
37 #include <ac/stdlib.h>
38 #include <ac/string.h>
39 #include <ac/time.h>
40
41 #include "ldap-int.h"
42
43 #define LDAP_VLVBYINDEX_IDENTIFIER     0xa0L
44 #define LDAP_VLVBYVALUE_IDENTIFIER     0x81L
45 #define LDAP_VLVCONTEXT_IDENTIFIER     0x04L
46
47
48 /*---
49    ldap_create_vlv_control
50    
51    Create and encode the Virtual List View control.
52
53    ld        (IN)  An LDAP session handle.
54    
55    vlvinfop  (IN)  The address of an LDAPVLVInfo structure whose contents 
56                                    are used to construct the value of the control
57                                    that is created.
58    
59    value     (OUT) A struct berval that contains the value to be assigned to the ldctl_value member
60                                    of an LDAPControl structure that contains the 
61                                    VirtualListViewRequest control.
62                                    The bv_val member of the berval structure
63                                    SHOULD be freed when it is no longer in use by
64                                    calling ldap_memfree().
65                                           
66    
67    Ber encoding
68    
69    VirtualListViewRequest ::= SEQUENCE {
70                 beforeCount  INTEGER (0 .. maxInt),
71                 afterCount   INTEGER (0 .. maxInt),
72                 CHOICE {
73                                 byoffset [0] SEQUENCE, {
74                                 offset        INTEGER (0 .. maxInt),
75                                 contentCount  INTEGER (0 .. maxInt) }
76                                 [1] greaterThanOrEqual assertionValue }
77                 contextID     OCTET STRING OPTIONAL }
78           
79    
80    Note:  The first time the VLV control is created, the ldvlv_context
81                   field of the LDAPVLVInfo structure should be set to NULL.
82                   The context obtained from calling ldap_parse_vlv_control()
83                   should be used as the context in the next ldap_create_vlv_control
84                   call.
85
86  ---*/
87
88 int
89 ldap_create_vlv_control_value(
90         LDAP *ld,
91         LDAPVLVInfo *vlvinfop,
92         struct berval *value )
93 {
94         ber_tag_t tag;
95         BerElement *ber;
96
97         if ( ld == NULL || vlvinfop == NULL || value == NULL ) {
98                 if ( ld )
99                         ld->ld_errno = LDAP_PARAM_ERROR;
100                 return LDAP_PARAM_ERROR;
101         }
102
103         assert( LDAP_VALID( ld ) );
104
105         value->bv_val = NULL;
106         value->bv_len = 0;
107
108         ber = ldap_alloc_ber_with_options( ld );
109         if ( ber == NULL ) {
110                 ld->ld_errno = LDAP_NO_MEMORY;
111                 return ld->ld_errno;
112         }
113
114         tag = ber_printf( ber, "{ii" /*}*/,
115                 vlvinfop->ldvlv_before_count,
116                 vlvinfop->ldvlv_after_count );
117         if ( tag == LBER_ERROR ) {
118                 goto error_return;
119         }
120
121         if ( vlvinfop->ldvlv_attrvalue == NULL ) {
122                 tag = ber_printf( ber, "t{iiN}",
123                         LDAP_VLVBYINDEX_IDENTIFIER,
124                         vlvinfop->ldvlv_offset,
125                         vlvinfop->ldvlv_count );
126                 if ( tag == LBER_ERROR ) {
127                         goto error_return;
128                 }
129
130         } else {
131                 tag = ber_printf( ber, "tO",
132                         LDAP_VLVBYVALUE_IDENTIFIER,
133                         vlvinfop->ldvlv_attrvalue );
134                 if ( tag == LBER_ERROR ) {
135                         goto error_return;
136                 }
137         }
138
139         if ( vlvinfop->ldvlv_context ) {
140                 tag = ber_printf( ber, "tO",
141                         LDAP_VLVCONTEXT_IDENTIFIER,
142                         vlvinfop->ldvlv_context );
143                 if ( tag == LBER_ERROR ) {
144                         goto error_return;
145                 }
146         }
147
148         tag = ber_printf( ber, /*{*/ "N}" ); 
149         if ( tag == LBER_ERROR ) {
150                 goto error_return;
151         }
152
153         if ( ber_flatten2( ber, value, 1 ) == -1 ) {
154                 ld->ld_errno = LDAP_NO_MEMORY;
155         }
156
157         if ( 0 ) {
158 error_return:;
159                 ld->ld_errno = LDAP_ENCODING_ERROR;
160         }
161
162         if ( ber != NULL ) {
163                 ber_free( ber, 1 );
164         }
165
166         return ld->ld_errno;
167 }
168
169 /*---
170    ldap_create_vlv_control
171    
172    Create and encode the Virtual List View control.
173
174    ld        (IN)  An LDAP session handle.
175    
176    vlvinfop  (IN)  The address of an LDAPVLVInfo structure whose contents 
177                                    are used to construct the value of the control
178                                    that is created.
179    
180    ctrlp     (OUT) A result parameter that will be assigned the address
181                                    of an LDAPControl structure that contains the 
182                                    VirtualListViewRequest control created by this function.
183                                    The memory occupied by the LDAPControl structure
184                                    SHOULD be freed when it is no longer in use by
185                                    calling ldap_control_free().
186                                           
187    
188    Ber encoding
189    
190    VirtualListViewRequest ::= SEQUENCE {
191                 beforeCount  INTEGER (0 .. maxInt),
192                 afterCount   INTEGER (0 .. maxInt),
193                 CHOICE {
194                                 byoffset [0] SEQUENCE, {
195                                 offset        INTEGER (0 .. maxInt),
196                                 contentCount  INTEGER (0 .. maxInt) }
197                                 [1] greaterThanOrEqual assertionValue }
198                 contextID     OCTET STRING OPTIONAL }
199           
200    
201    Note:  The first time the VLV control is created, the ldvlv_context
202                   field of the LDAPVLVInfo structure should be set to NULL.
203                   The context obtained from calling ldap_parse_vlv_control()
204                   should be used as the context in the next ldap_create_vlv_control
205                   call.
206
207  ---*/
208
209 int
210 ldap_create_vlv_control(
211         LDAP *ld,
212         LDAPVLVInfo *vlvinfop,
213         LDAPControl **ctrlp )
214 {
215         struct berval   value;
216         BerElement      *ber;
217
218         if ( ctrlp == NULL ) {
219                 ld->ld_errno = LDAP_PARAM_ERROR;
220                 return ld->ld_errno;
221         }
222
223         ld->ld_errno = ldap_create_vlv_control_value( ld, vlvinfop, &value );
224         if ( ld->ld_errno == LDAP_SUCCESS ) {
225                 if ((ber = ldap_alloc_ber_with_options(ld)) == NULL) {
226                         ld->ld_errno = LDAP_NO_MEMORY;
227                         return LDAP_NO_MEMORY;
228                 }
229
230                 ld->ld_errno = ldap_create_control( LDAP_CONTROL_VLVREQUEST,
231                         ber, 1, ctrlp );
232                 if ( ld->ld_errno == LDAP_SUCCESS ) {
233                         (*ctrlp)->ldctl_value = value;
234                 } else {
235                         LDAP_FREE( value.bv_val );
236                 }
237                 ber_free(ber, 1);
238         }
239
240         return ld->ld_errno;
241 }
242
243
244 /*---
245    ldap_parse_vlvresponse_control
246    
247    Decode the Virtual List View control return information.
248
249    ld           (IN)   An LDAP session handle.
250    
251    ctrl         (IN)   The address of the LDAPControl structure.
252    
253    target_posp  (OUT)  This result parameter is filled in with the list
254                                            index of the target entry.  If this parameter is
255                                            NULL, the target position is not returned.
256    
257    list_countp  (OUT)  This result parameter is filled in with the server's
258                                            estimate of the size of the list.  If this parameter
259                                            is NULL, the size is not returned.
260    
261    contextp     (OUT)  This result parameter is filled in with the address
262                                            of a struct berval that contains the server-
263                                            generated context identifier if one was returned by
264                                            the server.  If the server did not return a context
265                                            identifier, this parameter will be set to NULL, even
266                                            if an error occured.
267                                            The returned context SHOULD be used in the next call
268                                            to create a VLV sort control.  The struct berval
269                                            returned SHOULD be disposed of by calling ber_bvfree()
270                                            when it is no longer needed.  If NULL is passed for
271                                            contextp, the context identifier is not returned.
272    
273    errcodep     (OUT)  This result parameter is filled in with the VLV
274                                            result code.  If this parameter is NULL, the result
275                                            code is not returned.  
276    
277    
278    Ber encoding
279    
280    VirtualListViewResponse ::= SEQUENCE {
281                 targetPosition    INTEGER (0 .. maxInt),
282                 contentCount     INTEGER (0 .. maxInt),
283                 virtualListViewResult ENUMERATED {
284                 success (0),
285                 operatonsError (1),
286                 unwillingToPerform (53),
287                 insufficientAccessRights (50),
288                 busy (51),
289                 timeLimitExceeded (3),
290                 adminLimitExceeded (11),
291                 sortControlMissing (60),
292                 offsetRangeError (61),
293                 other (80) },
294                 contextID     OCTET STRING OPTIONAL }
295    
296 ---*/
297
298 int
299 ldap_parse_vlvresponse_control(
300         LDAP *ld,
301         LDAPControl *ctrl,
302         ber_int_t *target_posp,
303         ber_int_t *list_countp,
304         struct berval  **contextp,
305         ber_int_t *errcodep )
306 {
307         BerElement  *ber;
308         ber_int_t pos, count, err;
309         ber_tag_t tag, berTag;
310         ber_len_t berLen;
311
312         assert( ld != NULL );
313         assert( LDAP_VALID( ld ) );
314
315         if (contextp) {
316                 *contextp = NULL;        /* Make sure we return a NULL if error occurs. */
317         }
318
319         if (ctrl == NULL) {
320                 ld->ld_errno = LDAP_PARAM_ERROR;
321                 return(ld->ld_errno);
322         }
323
324         if (strcmp(LDAP_CONTROL_VLVRESPONSE, ctrl->ldctl_oid) != 0) {
325                 /* Not VLV Response control */
326                 ld->ld_errno = LDAP_CONTROL_NOT_FOUND;
327                 return(ld->ld_errno);
328         }
329
330         /* Create a BerElement from the berval returned in the control. */
331         ber = ber_init(&ctrl->ldctl_value);
332
333         if (ber == NULL) {
334                 ld->ld_errno = LDAP_NO_MEMORY;
335                 return(ld->ld_errno);
336         }
337
338         /* Extract the data returned in the control. */
339         tag = ber_scanf(ber, "{iie" /*}*/, &pos, &count, &err);
340
341         if( tag == LBER_ERROR) {
342                 ber_free(ber, 1);
343                 ld->ld_errno = LDAP_DECODING_ERROR;
344                 return(ld->ld_errno);
345         }
346
347
348         /* Since the context is the last item encoded, if caller doesn't want
349            it returned, don't decode it. */
350         if (contextp) {
351                 if (LDAP_VLVCONTEXT_IDENTIFIER == ber_peek_tag(ber, &berLen)) {
352                         tag = ber_scanf(ber, "tO", &berTag, contextp);
353
354                         if( tag == LBER_ERROR) {
355                                 ber_free(ber, 1);
356                                 ld->ld_errno = LDAP_DECODING_ERROR;
357                                 return(ld->ld_errno);
358                         }
359                 }
360         }
361
362         ber_free(ber, 1);
363
364         /* Return data to the caller for items that were requested. */
365         if (target_posp) *target_posp = pos;
366         if (list_countp) *list_countp = count;
367         if (errcodep) *errcodep = err;
368
369         ld->ld_errno = LDAP_SUCCESS;
370         return(ld->ld_errno);
371 }