]> git.sur5r.net Git - openldap/blob - libraries/libldap/stctrl.c
ITS#5300
[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_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 */