xref: /onnv-gate/usr/src/lib/libldap4/common/controls.c (revision 3857:21b9b714e4ab)
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