]> git.sur5r.net Git - openldap/blob - libraries/libldap/stctrl.c
client side of draft-wahl-ldap-session
[openldap] / libraries / libldap / stctrl.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1998-2007 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(
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         BerElement      *ber;
141
142         if ( ctrlp == NULL ) {
143                 ld->ld_errno = LDAP_PARAM_ERROR;
144                 return ld->ld_errno;
145         }
146
147         ld->ld_errno = ldap_create_session_tracking_value( ld,
148                 sessionSourceIp, sessionSourceName, formatOID,
149                 sessionTrackingIdentifier, &value );
150         if ( ld->ld_errno == LDAP_SUCCESS ) {
151                 ber = ldap_alloc_ber_with_options( ld );
152                 if ( ber == NULL ) {
153                         ld->ld_errno = LDAP_NO_MEMORY;
154                         return LDAP_NO_MEMORY;
155                 }
156
157                 ld->ld_errno = ldap_create_control( LDAP_CONTROL_X_SESSION_TRACKING,
158                         ber, 0, ctrlp );
159                 if ( ld->ld_errno == LDAP_SUCCESS ) {
160                         (*ctrlp)->ldctl_value = value;
161
162                 } else {
163                         LDAP_FREE( value.bv_val );
164                 }
165                 ber_free( ber, 1 );
166         }
167
168         return ld->ld_errno;
169 }
170
171 int
172 ldap_parse_session_tracking_control(
173         LDAP *ld,
174         LDAPControl *ctrl,
175         struct berval *ip,
176         struct berval *name,
177         struct berval *oid,
178         struct berval *id )
179 {
180         BerElement      *ber;
181         ber_tag_t       tag;
182         ber_len_t       len;
183
184         if ( ld == NULL || 
185                 ctrl == NULL || 
186                 ip == NULL ||
187                 name == NULL ||
188                 oid == NULL ||
189                 id == NULL )
190         {
191                 if ( ld ) {
192                         ld->ld_errno = LDAP_PARAM_ERROR;
193                 }
194
195                 /* NOTE: we want the caller to get all or nothing;
196                  * we could allow some of the pointers to be NULL,
197                  * if one does not want part of the data */
198                 return LDAP_PARAM_ERROR;
199         }
200
201         ip->bv_val = NULL;
202         ip->bv_len = 0;
203         name->bv_val = NULL;
204         name->bv_len = 0;
205         oid->bv_val = NULL;
206         oid->bv_len = 0;
207         id->bv_val = NULL;
208         id->bv_len = 0;
209
210         ber = ber_init( &ctrl->ldctl_value );
211
212         if ( ber == NULL ) {
213                 ld->ld_errno = LDAP_NO_MEMORY;
214                 return ld->ld_errno;
215         }
216
217         tag = ber_skip_tag( ber, &len );
218         if ( tag != LBER_SEQUENCE ) {
219                 tag = LBER_ERROR;
220                 goto error;
221         }
222
223         /* sessionSourceIp */
224         tag = ber_peek_tag( ber, &len );
225         if ( tag == LBER_DEFAULT ) {
226                 tag = LBER_ERROR;
227                 goto error;
228         }
229
230         if ( len == 0 ) {
231                 tag = ber_skip_tag( ber, &len );
232
233         } else {
234                 if ( len > 128 ) {
235                         /* should be LDAP_DECODING_ERROR,
236                          * but we're liberal in what we accept */
237                 }
238                 tag = ber_scanf( ber, "o", ip );
239         }
240
241         /* sessionSourceName */
242         tag = ber_peek_tag( ber, &len );
243         if ( tag == LBER_DEFAULT ) {
244                 tag = LBER_ERROR;
245                 goto error;
246         }
247
248         if ( len == 0 ) {
249                 tag = ber_skip_tag( ber, &len );
250
251         } else {
252                 if ( len > 65536 ) {
253                         /* should be LDAP_DECODING_ERROR,
254                          * but we're liberal in what we accept */
255                 }
256                 tag = ber_scanf( ber, "o", name );
257         }
258
259         /* formatOID */
260         tag = ber_peek_tag( ber, &len );
261         if ( tag == LBER_DEFAULT ) {
262                 tag = LBER_ERROR;
263                 goto error;
264         }
265
266         if ( len == 0 ) {
267                 ld->ld_errno = LDAP_DECODING_ERROR;
268                 goto error;
269
270         } else {
271                 if ( len > 1024 ) {
272                         /* should be LDAP_DECODING_ERROR,
273                          * but we're liberal in what we accept */
274                 }
275                 tag = ber_scanf( ber, "o", oid );
276         }
277
278         /* FIXME: should check if it is an OID... leave it to the caller */
279
280         /* sessionTrackingIdentifier */
281         tag = ber_peek_tag( ber, &len );
282         if ( tag == LBER_DEFAULT ) {
283                 tag = LBER_ERROR;
284                 goto error;
285         }
286
287         if ( len == 0 ) {
288                 tag = ber_skip_tag( ber, &len );
289
290         } else {
291 #if 0
292                 if ( len > 65536 ) {
293                         /* should be LDAP_DECODING_ERROR,
294                          * but we're liberal in what we accept */
295                 }
296 #endif
297                 tag = ber_scanf( ber, "o", id );
298         }
299
300         /* closure */
301         tag = ber_skip_tag( ber, &len );
302         if ( tag == LBER_DEFAULT && len == 0 ) {
303                 tag = 0;
304         }
305
306 error:;
307         (void)ber_free( ber, 1 );
308
309         if ( tag == LBER_ERROR ) {
310                 return LDAP_DECODING_ERROR;
311         }
312
313         return ld->ld_errno;
314 }
315
316 #endif /* LDAP_CONTROL_X_SESSION_TRACKING */