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