]> git.sur5r.net Git - openldap/blob - servers/slapd/controls.c
Add support for unsolicited notifications.
[openldap] / servers / slapd / controls.c
1 /* 
2  * Copyright 1999 The OpenLDAP Foundation.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted only
6  * as authorized by the OpenLDAP Public License.  A copy of this
7  * license is available at http://www.OpenLDAP.org/license.html or
8  * in file LICENSE in the top-level directory of the distribution.
9  */
10 #include "portable.h"
11
12 #include <stdio.h>
13 #include <ac/socket.h>
14
15 #include "slap.h"
16
17 #include "../../libraries/liblber/lber-int.h"
18
19 char *supportedControls[] = {
20         NULL
21 };
22
23 int get_ctrls(
24         Connection *conn,
25         Operation *op,
26         int sendres )
27 {
28         int nctrls;
29         ber_tag_t tag;
30         ber_len_t len;
31         char *opaque;
32         BerElement *ber = op->o_ber;
33         LDAPControl ***ctrls = &op->o_ctrls;
34         int rc = LDAP_SUCCESS;
35         char *errmsg = NULL;
36
37         len = ber_pvt_ber_remaining(ber);
38
39         if( len == 0) {
40                 /* no controls */
41                 rc = LDAP_SUCCESS;
42                 goto return_results;
43         }
44
45         if(( tag = ber_peek_tag( ber, &len )) != LDAP_TAG_CONTROLS ) {
46                 if( tag == LBER_ERROR ) {
47                         rc = -1;
48                         errmsg = "unexpected data in PDU";
49                 }
50
51                 goto return_results;
52         }
53
54         if( op->o_protocol < LDAP_VERSION3 ) {
55                 rc = -1;
56                 errmsg = "controls require LDAPv3";
57                 goto return_results;
58         }
59
60         /* set through each element */
61         nctrls = 0;
62         *ctrls = ch_malloc( 1 * sizeof(LDAPControl *) );
63
64 #if 0
65         if( *ctrls == NULL ) {
66                 rc = LDAP_NO_MEMORY;
67                 errmsg = "no memory";
68                 goto return_results;
69         }
70 #endif
71
72         ctrls[nctrls] = NULL;
73
74         for( tag = ber_first_element( ber, &len, &opaque );
75                 tag != LBER_ERROR;
76                 tag = ber_next_element( ber, &len, opaque ) )
77         {
78                 LDAPControl *tctrl;
79                 LDAPControl **tctrls;
80
81                 tctrl = ch_calloc( 1, sizeof(LDAPControl) );
82
83                 /* allocate pointer space for current controls (nctrls)
84                  * + this control + extra NULL
85                  */
86                 tctrls = (tctrl == NULL) ? NULL :
87                         ch_realloc(*ctrls, (nctrls+2) * sizeof(LDAPControl *));
88
89 #if 0
90                 if( tctrls == NULL ) {
91                         /* one of the above allocation failed */
92
93                         if( tctrl != NULL ) {
94                                 ch_free( tctrl );
95                         }
96
97                         ldap_controls_free(*ctrls);
98                         *ctrls = NULL;
99
100                         rc = LDAP_NO_MEMORY;
101                         errmsg = "no memory";
102                         goto return_results;
103                 }
104 #endif
105
106
107                 tctrls[nctrls++] = tctrl;
108                 tctrls[nctrls] = NULL;
109
110                 tag = ber_scanf( ber, "{a" /*}*/, &tctrl->ldctl_oid );
111
112                 if( tag != LBER_ERROR ) {
113                         tag = ber_peek_tag( ber, &len );
114                 }
115
116                 if( tag == LBER_BOOLEAN ) {
117                         ber_int_t crit;
118                         tag = ber_scanf( ber, "b", &crit );
119                         tctrl->ldctl_iscritical = crit ? (char) 0 : (char) ~0;
120                 }
121
122                 if( tag != LBER_ERROR ) {
123                         tag = ber_peek_tag( ber, &len );
124                 }
125
126                 if( tag == LBER_OCTETSTRING ) {
127                         tag = ber_scanf( ber, "o", &tctrl->ldctl_value );
128
129                 } else {
130                         tctrl->ldctl_value.bv_val = NULL;
131                 }
132
133                 if( tag == LBER_ERROR ) {
134                         *ctrls = NULL;
135                         ldap_controls_free( tctrls );
136                         rc = -1;
137                         errmsg = "decoding controls error";
138                         goto return_results;
139                 }
140
141                 if( tctrl->ldctl_iscritical &&
142                         !charray_inlist( supportedControls, tctrl->ldctl_oid ) )
143                 {
144                         rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
145                         errmsg = "critical extension is unavailable ";
146                         goto return_results;
147                 }
148
149                 *ctrls = tctrls;
150         }
151
152 return_results:
153         if( sendres && rc != LDAP_SUCCESS ) {
154                 if( rc == -1 ) {
155                         send_ldap_disconnect( conn, op, rc, errmsg );
156                 } else {
157                         send_ldap_result( conn, op, rc, NULL, errmsg );
158                 }
159         }
160
161         return rc;
162 }