]> git.sur5r.net Git - openldap/blob - servers/slapd/controls.c
36eeb968f0528f73c1538e4d5dadd53bbf68178f
[openldap] / servers / slapd / controls.c
1 /* $OpenLDAP$ */
2 /* 
3  * Copyright 1999-2000 The OpenLDAP Foundation.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms are permitted only
7  * as authorized by the OpenLDAP Public License.  A copy of this
8  * license is available at http://www.OpenLDAP.org/license.html or
9  * in file LICENSE in the top-level directory of the distribution.
10  */
11 #include "portable.h"
12
13 #include <stdio.h>
14
15 #include <ac/string.h>
16 #include <ac/socket.h>
17
18 #include <ldap_log.h>
19
20 #include "slap.h"
21
22 #include "../../libraries/liblber/lber-int.h"
23
24 char *supportedControls[] = {
25         LDAP_CONTROL_MANAGEDSAIT,
26         NULL
27 };
28
29 int get_ctrls(
30         Connection *conn,
31         Operation *op,
32         int sendres )
33 {
34         int nctrls = 0;
35         ber_tag_t tag;
36         ber_len_t len;
37         char *opaque;
38         BerElement *ber = op->o_ber;
39         LDAPControl ***ctrls = &op->o_ctrls;
40         int rc = LDAP_SUCCESS;
41         char *errmsg = NULL;
42
43         len = ber_pvt_ber_remaining(ber);
44
45         if( len == 0) {
46                 /* no controls */
47                 rc = LDAP_SUCCESS;
48                 return rc;
49         }
50
51         if(( tag = ber_peek_tag( ber, &len )) != LDAP_TAG_CONTROLS ) {
52                 if( tag == LBER_ERROR ) {
53                         rc = SLAPD_DISCONNECT;
54                         errmsg = "unexpected data in PDU";
55                 }
56
57                 goto return_results;
58         }
59
60 #ifdef NEW_LOGGING
61         LDAP_LOG(( "operation", LDAP_LEVEL_ENTRY,
62                    "get_ctrls: conn %d\n", conn->c_connid ));
63 #else
64         Debug( LDAP_DEBUG_TRACE, "=> get_ctrls\n", 0, 0, 0 );
65 #endif
66         if( op->o_protocol < LDAP_VERSION3 ) {
67                 rc = SLAPD_DISCONNECT;
68                 errmsg = "controls require LDAPv3";
69                 goto return_results;
70         }
71
72         /* set through each element */
73         *ctrls = ch_malloc( 1 * sizeof(LDAPControl *) );
74
75 #if 0
76         if( *ctrls == NULL ) {
77                 rc = LDAP_NO_MEMORY;
78                 errmsg = "no memory";
79                 goto return_results;
80         }
81 #endif
82
83         *ctrls[nctrls] = NULL;
84
85         for( tag = ber_first_element( ber, &len, &opaque );
86                 tag != LBER_ERROR;
87                 tag = ber_next_element( ber, &len, opaque ) )
88         {
89                 LDAPControl *tctrl;
90                 LDAPControl **tctrls;
91
92                 tctrl = ch_calloc( 1, sizeof(LDAPControl) );
93                 tctrl->ldctl_oid = NULL;
94                 tctrl->ldctl_value.bv_val = NULL;
95
96                 /* allocate pointer space for current controls (nctrls)
97                  * + this control + extra NULL
98                  */
99                 tctrls = (tctrl == NULL) ? NULL :
100                         ch_realloc(*ctrls, (nctrls+2) * sizeof(LDAPControl *));
101
102 #if 0
103                 if( tctrls == NULL ) {
104                         /* one of the above allocation failed */
105
106                         if( tctrl != NULL ) {
107                                 ch_free( tctrl );
108                         }
109
110                         ldap_controls_free(*ctrls);
111                         *ctrls = NULL;
112
113                         rc = LDAP_NO_MEMORY;
114                         errmsg = "no memory";
115                         goto return_results;
116                 }
117 #endif
118
119                 tctrls[nctrls++] = tctrl;
120                 tctrls[nctrls] = NULL;
121
122                 tag = ber_scanf( ber, "{a" /*}*/, &tctrl->ldctl_oid );
123
124                 if( tag == LBER_ERROR ) {
125 #ifdef NEW_LOGGING
126                         LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
127                                    "get_ctrls: conn %d  get OID failed.\n",
128                                    conn->c_connid ));
129 #else
130                         Debug( LDAP_DEBUG_TRACE, "=> get_ctrls: get oid failed.\n",
131                                 0, 0, 0 );
132 #endif
133                         *ctrls = NULL;
134                         ldap_controls_free( tctrls );
135                         rc = SLAPD_DISCONNECT;
136                         errmsg = "decoding controls error";
137                         goto return_results;
138                 }
139
140                 tag = ber_peek_tag( ber, &len );
141
142                 if( tag == LBER_BOOLEAN ) {
143                         ber_int_t crit;
144                         tag = ber_scanf( ber, "b", &crit );
145
146                         if( tag == LBER_ERROR ) {
147 #ifdef NEW_LOGGING
148                                 LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
149                                            "get_ctrls: conn %d  get crit failed.\n",
150                                            conn->c_connid ));
151 #else
152                                 Debug( LDAP_DEBUG_TRACE, "=> get_ctrls: get crit failed.\n",
153                                         0, 0, 0 );
154 #endif
155                                 *ctrls = NULL;
156                                 ldap_controls_free( tctrls );
157                                 rc = SLAPD_DISCONNECT;
158                                 errmsg = "decoding controls error";
159                                 goto return_results;
160                         }
161
162                         tctrl->ldctl_iscritical = (crit != 0);
163                         tag = ber_peek_tag( ber, &len );
164                 }
165
166 #ifdef NEW_LOGGING
167                 LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
168                            "get_ctrls: conn %d oid=\"%s\" (%scritical)\n",
169                            conn->c_connid, tctrl->ldctl_oid,
170                            tctrl->ldctl_iscritical ? "" : "non" ));
171 #else
172                 Debug( LDAP_DEBUG_TRACE, "=> get_ctrls: oid=\"%s\" (%scritical)\n",
173                         tctrl->ldctl_oid, 
174                         tctrl->ldctl_iscritical ? "" : "non",
175                         0 );
176 #endif
177                 if( tag == LBER_OCTETSTRING ) {
178                         tag = ber_scanf( ber, "o", &tctrl->ldctl_value );
179
180                         if( tag == LBER_ERROR ) {
181 #ifdef NEW_LOGGING
182                                 LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
183                                            "get_ctrls: conn %d  get value failed.\n", conn->c_connid ));
184 #else
185                                 Debug( LDAP_DEBUG_TRACE, "=> get_ctrls: get value failed.\n",
186                                         0, 0, 0 );
187 #endif
188                                 *ctrls = NULL;
189                                 ldap_controls_free( tctrls );
190                                 rc = SLAPD_DISCONNECT;
191                                 errmsg = "decoding controls error";
192                                 goto return_results;
193                         }
194                 }
195
196                 if( tctrl->ldctl_iscritical &&
197                         !charray_inlist( supportedControls, tctrl->ldctl_oid ) )
198                 {
199                         rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
200                         errmsg = "critical extension is unavailable ";
201                         goto return_results;
202                 }
203
204                 *ctrls = tctrls;
205         }
206
207 return_results:
208 #ifdef NEW_LOGGING
209         LDAP_LOG(( "operation", LDAP_LEVEL_RESULTS,
210                    "get_ctrls: conn %d  %d %d %s\n",
211                    conn->c_connid, nctrls, rc, errmsg ? errmsg : "" ));
212 #else
213         Debug( LDAP_DEBUG_TRACE, "<= get_ctrls: %d %d %s\n",
214                 nctrls, rc, errmsg ? errmsg : "");
215 #endif
216
217         if( sendres && rc != LDAP_SUCCESS ) {
218                 if( rc == SLAPD_DISCONNECT ) {
219                         send_ldap_disconnect( conn, op, LDAP_PROTOCOL_ERROR, errmsg );
220                 } else {
221                         send_ldap_result( conn, op, rc,
222                                 NULL, errmsg, NULL, NULL );
223                 }
224         }
225
226         return rc;
227 }
228
229
230 int get_manageDSAit( Operation *op )
231 {
232         int i;
233         if( op == NULL || op->o_ctrls == NULL ) {
234                 return 0;
235         }
236
237         for( i=0; op->o_ctrls[i] != NULL; i++ ) {
238                 if( strcmp( LDAP_CONTROL_MANAGEDSAIT, op->o_ctrls[i]->ldctl_oid )
239                         == 0 )
240                 {
241                         return 1;
242                 }
243         }
244
245         return 0;
246 }