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