xref: /netbsd-src/external/bsd/openldap/dist/libraries/libldap/stctrl.c (revision b1c86f5f087524e68db12794ee9c3e3da1ab17a0)
1 /*	$NetBSD: stctrl.c,v 1.1.1.2 2010/03/08 02:14:20 lukem Exp $	*/
2 
3 /* OpenLDAP: pkg/ldap/libraries/libldap/stctrl.c,v 1.3.2.4 2009/01/22 00:00:56 kurt Exp */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5  *
6  * Copyright 1998-2009 The OpenLDAP Foundation.
7  * Portions Copyright 2007 Pierangelo Masarati.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted only as authorized by the OpenLDAP
12  * Public License.
13  *
14  * A copy of this license is available in the file LICENSE in the
15  * top-level directory of the distribution or, alternatively, at
16  * <http://www.OpenLDAP.org/license.html>.
17  */
18 /* ACKNOWLEDGEMENTS:
19  * This work was developed by Pierangelo Masarati for inclusion in
20  * OpenLDAP Software.
21  */
22 
23 #include "portable.h"
24 
25 #include <stdio.h>
26 #include <ac/stdlib.h>
27 #include <ac/string.h>
28 #include <ac/time.h>
29 
30 #include "ldap-int.h"
31 
32 #ifdef LDAP_CONTROL_X_SESSION_TRACKING
33 
34 /*
35  * Client-side of <draft-wahl-ldap-session-03>
36  */
37 
38 int
39 ldap_create_session_tracking_value(
40 	LDAP		*ld,
41 	char		*sessionSourceIp,
42 	char		*sessionSourceName,
43 	char		*formatOID,
44 	struct berval	*sessionTrackingIdentifier,
45 	struct berval	*value )
46 {
47 	BerElement	*ber = NULL;
48 	ber_tag_t	tag;
49 
50 	struct berval	ip, name, oid, id;
51 
52 	if ( ld == NULL ||
53 		formatOID == NULL ||
54 		value == NULL )
55 	{
56 param_error:;
57 		if ( ld ) {
58 			ld->ld_errno = LDAP_PARAM_ERROR;
59 		}
60 
61 		return LDAP_PARAM_ERROR;
62 	}
63 
64 	assert( LDAP_VALID( ld ) );
65 	ld->ld_errno = LDAP_SUCCESS;
66 
67 	/* check sizes according to I.D. */
68 	if ( sessionSourceIp == NULL ) {
69 		BER_BVSTR( &ip, "" );
70 
71 	} else {
72 		ber_str2bv( sessionSourceIp, 0, 0, &ip );
73 		/* NOTE: we're strict because we don't want
74 		 * to send out bad data */
75 		if ( ip.bv_len > 128 ) goto param_error;
76 	}
77 
78 	if ( sessionSourceName == NULL ) {
79 		BER_BVSTR( &name, "" );
80 
81 	} else {
82 		ber_str2bv( sessionSourceName, 0, 0, &name );
83 		/* NOTE: we're strict because we don't want
84 		 * to send out bad data */
85 		if ( name.bv_len > 65536 ) goto param_error;
86 	}
87 
88 	ber_str2bv( formatOID, 0, 0, &oid );
89 	/* NOTE: we're strict because we don't want
90 	 * to send out bad data */
91 	if ( oid.bv_len > 1024 ) goto param_error;
92 
93 	if ( sessionTrackingIdentifier == NULL ||
94 		sessionTrackingIdentifier->bv_val == NULL )
95 	{
96 		BER_BVSTR( &id, "" );
97 
98 	} else {
99 		id = *sessionTrackingIdentifier;
100 	}
101 
102 	/* prepare value */
103 	value->bv_val = NULL;
104 	value->bv_len = 0;
105 
106 	ber = ldap_alloc_ber_with_options( ld );
107 	if ( ber == NULL ) {
108 		ld->ld_errno = LDAP_NO_MEMORY;
109 		return ld->ld_errno;
110 	}
111 
112 	tag = ber_printf( ber, "{OOOO}", &ip, &name, &oid, &id );
113 	if ( tag == LBER_ERROR ) {
114 		ld->ld_errno = LDAP_ENCODING_ERROR;
115 		goto done;
116 	}
117 
118 	if ( ber_flatten2( ber, value, 1 ) == -1 ) {
119 		ld->ld_errno = LDAP_NO_MEMORY;
120 	}
121 
122 done:;
123 	if ( ber != NULL ) {
124 		ber_free( ber, 1 );
125 	}
126 
127 	return ld->ld_errno;
128 }
129 
130 /*
131  * NOTE: this API is bad; it could be much more efficient...
132  */
133 int
134 ldap_create_session_tracking_control(
135 	LDAP		*ld,
136 	char		*sessionSourceIp,
137 	char		*sessionSourceName,
138 	char		*formatOID,
139 	struct berval	*sessionTrackingIdentifier,
140 	LDAPControl	**ctrlp )
141 {
142 	struct berval	value;
143 
144 	if ( ctrlp == NULL ) {
145 		ld->ld_errno = LDAP_PARAM_ERROR;
146 		return ld->ld_errno;
147 	}
148 
149 	ld->ld_errno = ldap_create_session_tracking_value( ld,
150 		sessionSourceIp, sessionSourceName, formatOID,
151 		sessionTrackingIdentifier, &value );
152 	if ( ld->ld_errno == LDAP_SUCCESS ) {
153 		ld->ld_errno = ldap_control_create( LDAP_CONTROL_X_SESSION_TRACKING,
154 			0, &value, 0, ctrlp );
155 		if ( ld->ld_errno != LDAP_SUCCESS ) {
156 			LDAP_FREE( value.bv_val );
157 		}
158 	}
159 
160 	return ld->ld_errno;
161 }
162 
163 int
164 ldap_parse_session_tracking_control(
165 	LDAP *ld,
166 	LDAPControl *ctrl,
167 	struct berval *ip,
168 	struct berval *name,
169 	struct berval *oid,
170 	struct berval *id )
171 {
172 	BerElement	*ber;
173 	ber_tag_t	tag;
174 	ber_len_t	len;
175 
176 	if ( ld == NULL ||
177 		ctrl == NULL ||
178 		ip == NULL ||
179 		name == NULL ||
180 		oid == NULL ||
181 		id == NULL )
182 	{
183 		if ( ld ) {
184 			ld->ld_errno = LDAP_PARAM_ERROR;
185 		}
186 
187 		/* NOTE: we want the caller to get all or nothing;
188 		 * we could allow some of the pointers to be NULL,
189 		 * if one does not want part of the data */
190 		return LDAP_PARAM_ERROR;
191 	}
192 
193 	BER_BVZERO( ip );
194 	BER_BVZERO( name );
195 	BER_BVZERO( oid );
196 	BER_BVZERO( id );
197 
198 	ber = ber_init( &ctrl->ldctl_value );
199 
200 	if ( ber == NULL ) {
201 		ld->ld_errno = LDAP_NO_MEMORY;
202 		return ld->ld_errno;
203 	}
204 
205 	tag = ber_skip_tag( ber, &len );
206 	if ( tag != LBER_SEQUENCE ) {
207 		tag = LBER_ERROR;
208 		goto error;
209 	}
210 
211 	/* sessionSourceIp */
212 	tag = ber_peek_tag( ber, &len );
213 	if ( tag == LBER_DEFAULT ) {
214 		tag = LBER_ERROR;
215 		goto error;
216 	}
217 
218 	if ( len == 0 ) {
219 		tag = ber_skip_tag( ber, &len );
220 
221 	} else {
222 		if ( len > 128 ) {
223 			/* should be LDAP_DECODING_ERROR,
224 			 * but we're liberal in what we accept */
225 		}
226 		tag = ber_scanf( ber, "o", ip );
227 	}
228 
229 	/* sessionSourceName */
230 	tag = ber_peek_tag( ber, &len );
231 	if ( tag == LBER_DEFAULT ) {
232 		tag = LBER_ERROR;
233 		goto error;
234 	}
235 
236 	if ( len == 0 ) {
237 		tag = ber_skip_tag( ber, &len );
238 
239 	} else {
240 		if ( len > 65536 ) {
241 			/* should be LDAP_DECODING_ERROR,
242 			 * but we're liberal in what we accept */
243 		}
244 		tag = ber_scanf( ber, "o", name );
245 	}
246 
247 	/* formatOID */
248 	tag = ber_peek_tag( ber, &len );
249 	if ( tag == LBER_DEFAULT ) {
250 		tag = LBER_ERROR;
251 		goto error;
252 	}
253 
254 	if ( len == 0 ) {
255 		ld->ld_errno = LDAP_DECODING_ERROR;
256 		goto error;
257 
258 	} else {
259 		if ( len > 1024 ) {
260 			/* should be LDAP_DECODING_ERROR,
261 			 * but we're liberal in what we accept */
262 		}
263 		tag = ber_scanf( ber, "o", oid );
264 	}
265 
266 	/* FIXME: should check if it is an OID... leave it to the caller */
267 
268 	/* sessionTrackingIdentifier */
269 	tag = ber_peek_tag( ber, &len );
270 	if ( tag == LBER_DEFAULT ) {
271 		tag = LBER_ERROR;
272 		goto error;
273 	}
274 
275 	if ( len == 0 ) {
276 		tag = ber_skip_tag( ber, &len );
277 
278 	} else {
279 #if 0
280 		if ( len > 65536 ) {
281 			/* should be LDAP_DECODING_ERROR,
282 			 * but we're liberal in what we accept */
283 		}
284 #endif
285 		tag = ber_scanf( ber, "o", id );
286 	}
287 
288 	/* closure */
289 	tag = ber_skip_tag( ber, &len );
290 	if ( tag == LBER_DEFAULT && len == 0 ) {
291 		tag = 0;
292 	}
293 
294 error:;
295 	(void)ber_free( ber, 1 );
296 
297 	if ( tag == LBER_ERROR ) {
298 		return LDAP_DECODING_ERROR;
299 	}
300 
301 	return ld->ld_errno;
302 }
303 
304 #endif /* LDAP_CONTROL_X_SESSION_TRACKING */
305