1 /* $OpenLDAP: pkg/ldap/libraries/libldap/stctrl.c,v 1.3.2.2 2008/02/11 23:26:41 kurt Exp $ */ 2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 3 * 4 * Copyright 1998-2008 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 */ 302