1/* $OpenLDAP$ */ 2/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 3 * 4 * Copyright 1998-2011 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 36int 37ldap_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 { 54param_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 120done:; 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 */ 131int 132ldap_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 161int 162ldap_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 292error:; 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 */ 303