1 /*
2 *
3 * Copyright 1999 Sun Microsystems, Inc. All rights reserved.
4 * Use is subject to license terms.
5 *
6 *
7 * Comments:
8 *
9 */
10
11 #pragma ident "%Z%%M% %I% %E% SMI"
12
13 #include <stdio.h>
14 #include <string.h>
15 #include "lber.h"
16 #include "ldap.h"
17 #include "ldap-private.h"
18 #include "ldap-int.h"
19
20 static int ldap_control_copy_contents(LDAPControl *, LDAPControl *);
21
ldap_control_free(LDAPControl * ctrl)22 void ldap_control_free (LDAPControl *ctrl)
23 {
24 if (ctrl != NULL){
25 if (ctrl->ldctl_oid)
26 free (ctrl->ldctl_oid);
27 if (ctrl->ldctl_value.bv_val != NULL)
28 free (ctrl->ldctl_value.bv_val);
29 free ((char *)ctrl);
30 }
31 return;
32 }
33
ldap_controls_free(LDAPControl ** ctrls)34 void ldap_controls_free (LDAPControl **ctrls)
35 {
36 int i;
37
38 if (ctrls == NULL)
39 return;
40
41 for (i = 0; ctrls[i] != NULL; i++){
42 ldap_control_free(ctrls[i]);
43 }
44 free((char *)ctrls);
45 }
46
ldap_control_dup(LDAPControl * ctrl)47 LDAPControl * ldap_control_dup(LDAPControl *ctrl)
48 {
49 LDAPControl *newctrl;
50
51 if ((newctrl = (LDAPControl *)calloc(1, sizeof(LDAPControl))) == NULL)
52 return (NULL);
53
54 if (ldap_control_copy_contents(newctrl, ctrl) != LDAP_SUCCESS) {
55 free(newctrl);
56 return (NULL);
57 }
58
59 return(newctrl);
60 }
61
62
ldap_control_copy_contents(LDAPControl * ctrl_dst,LDAPControl * ctrl_src)63 static int ldap_control_copy_contents(LDAPControl *ctrl_dst,
64 LDAPControl *ctrl_src)
65 {
66 size_t len;
67
68 if (NULL == ctrl_dst || NULL == ctrl_src) {
69 return (LDAP_PARAM_ERROR);
70 }
71
72 ctrl_dst->ldctl_iscritical = ctrl_src->ldctl_iscritical;
73
74 /* fill in the fields of this new control */
75 if ((ctrl_dst->ldctl_oid = strdup(ctrl_src->ldctl_oid)) == NULL) {
76 return (LDAP_NO_MEMORY);
77 }
78
79 len = (size_t)(ctrl_src->ldctl_value).bv_len;
80 if (ctrl_src->ldctl_value.bv_val == NULL || len <= 0) {
81 ctrl_dst->ldctl_value.bv_len = 0;
82 ctrl_dst->ldctl_value.bv_val = NULL;
83 } else {
84 ctrl_dst->ldctl_value.bv_len = len;
85 if ((ctrl_dst->ldctl_value.bv_val = malloc(len))
86 == NULL) {
87 free(ctrl_dst->ldctl_oid);
88 return (LDAP_NO_MEMORY);
89 }
90 SAFEMEMCPY(ctrl_dst->ldctl_value.bv_val,
91 ctrl_src->ldctl_value.bv_val, len);
92 }
93
94 return (LDAP_SUCCESS);
95 }
96
97
ldap_controls_dup(LDAPControl ** ctrls)98 LDAPControl ** ldap_controls_dup(LDAPControl ** ctrls)
99 {
100 int i;
101 LDAPControl **newctrls;
102
103 for (i = 0; ctrls[i] != NULL; i++);
104 newctrls = (LDAPControl **)calloc(i+1, sizeof(LDAPControl*));
105 if (newctrls == NULL) {
106 return (NULL);
107 }
108
109 for (i = 0; ctrls[i] != NULL; i++) {
110 newctrls[i] = ldap_control_dup(ctrls[i]);
111 if (newctrls[i] == NULL) {
112 ldap_controls_free(newctrls);
113 return (NULL);
114 }
115 }
116 return (newctrls);
117 }
118
ldap_controls_code(BerElement * ber,LDAPControl ** ctrls)119 int ldap_controls_code (BerElement *ber, LDAPControl **ctrls)
120 {
121 int i, rc;
122
123 if (ctrls && ctrls[0]){
124 rc = ber_printf(ber, "t{", LDAP_TAG_CONTROL_LIST);
125 if (rc == -1){
126 ber_free(ber, 1);
127 return(LDAP_ENCODING_ERROR);
128 }
129
130 for (i = 0; ctrls[i] != NULL; i++){
131 rc = ber_printf(ber, "{s", ctrls[i]->ldctl_oid);
132 if (rc == -1){
133 ber_free(ber, 1);
134 return(LDAP_ENCODING_ERROR);
135 }
136 if (ctrls[i]->ldctl_iscritical){
137 rc = ber_printf(ber, "b", ctrls[i]->ldctl_iscritical);
138 if (rc == -1){
139 ber_free(ber, 1);
140 return(LDAP_ENCODING_ERROR);
141 }
142 }
143
144 if (ctrls[i]->ldctl_value.bv_val)
145 rc = ber_printf(ber, "o}", ctrls[i]->ldctl_value.bv_val, ctrls[i]->ldctl_value.bv_len);
146 else
147 rc = ber_printf(ber, "}");
148 if (rc == -1){
149 ber_free(ber, 1);
150 return(LDAP_ENCODING_ERROR);
151 }
152 }
153
154 rc = ber_printf(ber, "}");
155 if (rc == -1){
156 ber_free(ber, 1);
157 return(LDAP_ENCODING_ERROR);
158 }
159 }
160 return (LDAP_SUCCESS);
161 }
162
163 /* Decode the sequence of control from the ber, return a NULL terminated list of LDAPControl* */
ldap_controls_decode(BerElement * ber,int * errcode)164 LDAPControl ** ldap_controls_decode(BerElement *ber, int *errcode)
165 {
166 LDAPControl ** ctrls = NULL;
167
168 char *opaque;
169 unsigned int tag, len;
170 int i = 0, count = 0;
171
172 BerElement tmpber = *ber;
173
174 for (tag = ber_first_element(&tmpber, &len, &opaque);
175 tag != LBER_DEFAULT;
176 tag = ber_next_element(&tmpber, &len, opaque )) {
177 count ++;
178 ber_skip_tag(&tmpber, &len);
179 }
180
181
182 if ((ctrls = (LDAPControl **)calloc(count + 1, sizeof(LDAPControl *))) == NULL){
183 *errcode = LDAP_NO_MEMORY;
184 return(NULL);
185 }
186
187 for (tag = ber_first_element(ber, &len, &opaque );
188 tag != LBER_DEFAULT;
189 tag = ber_next_element (ber, &len, opaque )) {
190 LDAPControl *aCtrl;
191 unsigned int ttag, tlen;
192
193 if ((aCtrl = (LDAPControl *)calloc(1, sizeof(LDAPControl))) == NULL) {
194 *errcode = LDAP_NO_MEMORY;
195 ldap_controls_free(ctrls);
196 return (NULL);
197 }
198 if (ber_scanf(ber, "{a", &aCtrl->ldctl_oid) == LBER_ERROR){
199 *errcode = LDAP_PROTOCOL_ERROR;
200 free(aCtrl);
201 ldap_controls_free(ctrls);
202 return (NULL);
203 }
204 aCtrl->ldctl_iscritical = 0;
205 ttag = ber_peek_tag(ber, &tlen);
206 if (ttag == 0x01) { /* Boolean : criticality */
207 if (ber_scanf(ber, "b", &aCtrl->ldctl_iscritical) == LBER_ERROR){
208 *errcode = LDAP_PROTOCOL_ERROR;
209 free(aCtrl);
210 ldap_controls_free(ctrls);
211 return (NULL);
212 }
213 ttag = ber_peek_tag(ber, &tlen);
214 }
215 if (ttag == 0x04) { /* Octet string : value (it's optional)*/
216 if (ber_scanf(ber, "o", &aCtrl->ldctl_value) == LBER_ERROR){
217 *errcode = LDAP_PROTOCOL_ERROR;
218 free(aCtrl);
219 ldap_controls_free(ctrls);
220 return (NULL);
221 }
222
223 } else if (ttag != LBER_DEFAULT){
224 *errcode = LDAP_PROTOCOL_ERROR;
225 free(aCtrl);
226 ldap_controls_free(ctrls);
227 return (NULL);
228 }
229
230 if (ber_scanf(ber, "}") == LBER_ERROR){
231 *errcode = LDAP_PROTOCOL_ERROR;
232 free(aCtrl);
233 ldap_controls_free(ctrls);
234 return (NULL);
235 }
236 /* add aCtrl in ctrls */
237 ctrls[i++] = aCtrl;
238 }
239 return (ctrls);
240 }
241
242 /* build an allocated LDAPv3 control. Returns an LDAP error code. */
ldap_build_control(char * oid,BerElement * ber,int freeber,char iscritical,LDAPControl ** ctrlp)243 int ldap_build_control(char *oid, BerElement *ber, int freeber,
244 char iscritical, LDAPControl **ctrlp)
245 {
246 int rc;
247 struct berval *bvp;
248
249 if (ber == NULL) {
250 bvp = NULL;
251 } else {
252 /* allocate struct berval with contents of the BER encoding */
253 rc = ber_flatten(ber, &bvp);
254 if (freeber) {
255 ber_free(ber, 1);
256 }
257 if (rc == -1) {
258 return (LDAP_NO_MEMORY);
259 }
260 }
261
262 /* allocate the new control structure */
263 if ((*ctrlp = (LDAPControl *)calloc(1, sizeof (LDAPControl)))
264 == NULL) {
265 if (bvp != NULL) {
266 ber_bvfree(bvp);
267 }
268 return (LDAP_NO_MEMORY);
269 }
270
271 /* fill in the fields of this new control */
272 (*ctrlp)->ldctl_iscritical = iscritical;
273 if (((*ctrlp)->ldctl_oid = strdup(oid)) == NULL) {
274 free(*ctrlp);
275 *ctrlp = NULL;
276 if (bvp != NULL) {
277 ber_bvfree(bvp);
278 }
279 return (LDAP_NO_MEMORY);
280 }
281
282 if (bvp == NULL) {
283 (*ctrlp)->ldctl_value.bv_len = 0;
284 (*ctrlp)->ldctl_value.bv_val = NULL;
285 } else {
286 (*ctrlp)->ldctl_value = *bvp; /* struct copy */
287 free(bvp); /* free container, not contents! */
288 }
289
290 return (LDAP_SUCCESS);
291 }
292