]> git.sur5r.net Git - openldap/blob - libraries/libldap/stctrl.c
b61f388def7f768775bb21c361558cfe012b11c1
[openldap] / libraries / libldap / stctrl.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1998-2017 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         ld->ld_errno = LDAP_SUCCESS;
64
65         /* check sizes according to I.D. */
66         if ( sessionSourceIp == NULL ) {
67                 BER_BVSTR( &ip, "" );
68
69         } else {
70                 ber_str2bv( sessionSourceIp, 0, 0, &ip );
71                 /* NOTE: we're strict because we don't want
72                  * to send out bad data */
73                 if ( ip.bv_len > 128 ) goto param_error;
74         }
75
76         if ( sessionSourceName == NULL ) {
77                 BER_BVSTR( &name, "" );
78
79         } else {
80                 ber_str2bv( sessionSourceName, 0, 0, &name );
81                 /* NOTE: we're strict because we don't want
82                  * to send out bad data */
83                 if ( name.bv_len > 65536 ) goto param_error;
84         }
85
86         ber_str2bv( formatOID, 0, 0, &oid );
87         /* NOTE: we're strict because we don't want
88          * to send out bad data */
89         if ( oid.bv_len > 1024 ) goto param_error;
90
91         if ( sessionTrackingIdentifier == NULL ||
92                 sessionTrackingIdentifier->bv_val == NULL )
93         {
94                 BER_BVSTR( &id, "" );
95
96         } else {
97                 id = *sessionTrackingIdentifier;
98         }
99
100         /* prepare value */
101         value->bv_val = NULL;
102         value->bv_len = 0;
103
104         ber = ldap_alloc_ber_with_options( ld );
105         if ( ber == NULL ) {
106                 ld->ld_errno = LDAP_NO_MEMORY;
107                 return ld->ld_errno;
108         }
109
110         tag = ber_printf( ber, "{OOOO}", &ip, &name, &oid, &id );
111         if ( tag == LBER_ERROR ) {
112                 ld->ld_errno = LDAP_ENCODING_ERROR;
113                 goto done;
114         }
115
116         if ( ber_flatten2( ber, value, 1 ) == -1 ) {
117                 ld->ld_errno = LDAP_NO_MEMORY;
118         }
119
120 done:;
121         if ( ber != NULL ) {
122                 ber_free( ber, 1 );
123         }
124
125         return ld->ld_errno;
126 }
127
128 /*
129  * NOTE: this API is bad; it could be much more efficient...
130  */
131 int
132 ldap_create_session_tracking_control(
133         LDAP            *ld,
134         char            *sessionSourceIp,
135         char            *sessionSourceName,
136         char            *formatOID,
137         struct berval   *sessionTrackingIdentifier,
138         LDAPControl     **ctrlp )
139 {
140         struct berval   value;
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                 ld->ld_errno = ldap_control_create( LDAP_CONTROL_X_SESSION_TRACKING,
152                         0, &value, 0, ctrlp );
153                 if ( ld->ld_errno != LDAP_SUCCESS ) {
154                         LDAP_FREE( value.bv_val );
155                 }
156         }
157
158         return ld->ld_errno;
159 }
160
161 int
162 ldap_parse_session_tracking_control(
163         LDAP *ld,
164         LDAPControl *ctrl,
165         struct berval *ip,
166         struct berval *name,
167         struct berval *oid,
168         struct berval *id )
169 {
170         BerElement      *ber;
171         ber_tag_t       tag;
172         ber_len_t       len;
173
174         if ( ld == NULL || 
175                 ctrl == NULL || 
176                 ip == NULL ||
177                 name == NULL ||
178                 oid == NULL ||
179                 id == NULL )
180         {
181                 if ( ld ) {
182                         ld->ld_errno = LDAP_PARAM_ERROR;
183                 }
184
185                 /* NOTE: we want the caller to get all or nothing;
186                  * we could allow some of the pointers to be NULL,
187                  * if one does not want part of the data */
188                 return LDAP_PARAM_ERROR;
189         }
190
191         BER_BVZERO( ip );
192         BER_BVZERO( name );
193         BER_BVZERO( oid );
194         BER_BVZERO( id );
195
196         ber = ber_init( &ctrl->ldctl_value );
197
198         if ( ber == NULL ) {
199                 ld->ld_errno = LDAP_NO_MEMORY;
200                 return ld->ld_errno;
201         }
202
203         tag = ber_skip_tag( ber, &len );
204         if ( tag != LBER_SEQUENCE ) {
205                 tag = LBER_ERROR;
206                 goto error;
207         }
208
209         /* sessionSourceIp */
210         tag = ber_peek_tag( ber, &len );
211         if ( tag == LBER_DEFAULT ) {
212                 tag = LBER_ERROR;
213                 goto error;
214         }
215
216         if ( len == 0 ) {
217                 tag = ber_skip_tag( ber, &len );
218
219         } else {
220                 if ( len > 128 ) {
221                         /* should be LDAP_DECODING_ERROR,
222                          * but we're liberal in what we accept */
223                 }
224                 tag = ber_scanf( ber, "o", ip );
225         }
226
227         /* sessionSourceName */
228         tag = ber_peek_tag( ber, &len );
229         if ( tag == LBER_DEFAULT ) {
230                 tag = LBER_ERROR;
231                 goto error;
232         }
233
234         if ( len == 0 ) {
235                 tag = ber_skip_tag( ber, &len );
236
237         } else {
238                 if ( len > 65536 ) {
239                         /* should be LDAP_DECODING_ERROR,
240                          * but we're liberal in what we accept */
241                 }
242                 tag = ber_scanf( ber, "o", name );
243         }
244
245         /* formatOID */
246         tag = ber_peek_tag( ber, &len );
247         if ( tag == LBER_DEFAULT ) {
248                 tag = LBER_ERROR;
249                 goto error;
250         }
251
252         if ( len == 0 ) {
253                 ld->ld_errno = LDAP_DECODING_ERROR;
254                 goto error;
255
256         } else {
257                 if ( len > 1024 ) {
258                         /* should be LDAP_DECODING_ERROR,
259                          * but we're liberal in what we accept */
260                 }
261                 tag = ber_scanf( ber, "o", oid );
262         }
263
264         /* FIXME: should check if it is an OID... leave it to the caller */
265
266         /* sessionTrackingIdentifier */
267         tag = ber_peek_tag( ber, &len );
268         if ( tag == LBER_DEFAULT ) {
269                 tag = LBER_ERROR;
270                 goto error;
271         }
272
273         if ( len == 0 ) {
274                 tag = ber_skip_tag( ber, &len );
275
276         } else {
277 #if 0
278                 if ( len > 65536 ) {
279                         /* should be LDAP_DECODING_ERROR,
280                          * but we're liberal in what we accept */
281                 }
282 #endif
283                 tag = ber_scanf( ber, "o", id );
284         }
285
286         /* closure */
287         tag = ber_skip_tag( ber, &len );
288         if ( tag == LBER_DEFAULT && len == 0 ) {
289                 tag = 0;
290         }
291
292 error:;
293         (void)ber_free( ber, 1 );
294
295         if ( tag == LBER_ERROR ) {
296                 return LDAP_DECODING_ERROR;
297         }
298
299         return ld->ld_errno;
300 }
301
302 #endif /* LDAP_CONTROL_X_SESSION_TRACKING */