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