1/* $NetBSD: stctrl.c,v 1.1.1.3 2010/12/12 15:21:37 adam Exp $ */ 2 3/* OpenLDAP: pkg/ldap/libraries/libldap/stctrl.c,v 1.3.2.5 2010/04/13 20:23:00 kurt Exp */ 4/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 5 * 6 * Copyright 1998-2010 The OpenLDAP Foundation. 7 * Portions Copyright 2007 Pierangelo Masarati. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted only as authorized by the OpenLDAP 12 * Public License. 13 * 14 * A copy of this license is available in the file LICENSE in the 15 * top-level directory of the distribution or, alternatively, at 16 * <http://www.OpenLDAP.org/license.html>. 17 */ 18/* ACKNOWLEDGEMENTS: 19 * This work was developed by Pierangelo Masarati for inclusion in 20 * OpenLDAP Software. 21 */ 22 23#include "portable.h" 24 25#include <stdio.h> 26#include <ac/stdlib.h> 27#include <ac/string.h> 28#include <ac/time.h> 29 30#include "ldap-int.h" 31 32#ifdef LDAP_CONTROL_X_SESSION_TRACKING 33 34/* 35 * Client-side of <draft-wahl-ldap-session-03> 36 */ 37 38int 39ldap_create_session_tracking_value( 40 LDAP *ld, 41 char *sessionSourceIp, 42 char *sessionSourceName, 43 char *formatOID, 44 struct berval *sessionTrackingIdentifier, 45 struct berval *value ) 46{ 47 BerElement *ber = NULL; 48 ber_tag_t tag; 49 50 struct berval ip, name, oid, id; 51 52 if ( ld == NULL || 53 formatOID == NULL || 54 value == NULL ) 55 { 56param_error:; 57 if ( ld ) { 58 ld->ld_errno = LDAP_PARAM_ERROR; 59 } 60 61 return LDAP_PARAM_ERROR; 62 } 63 64 assert( LDAP_VALID( ld ) ); 65 ld->ld_errno = LDAP_SUCCESS; 66 67 /* check sizes according to I.D. */ 68 if ( sessionSourceIp == NULL ) { 69 BER_BVSTR( &ip, "" ); 70 71 } else { 72 ber_str2bv( sessionSourceIp, 0, 0, &ip ); 73 /* NOTE: we're strict because we don't want 74 * to send out bad data */ 75 if ( ip.bv_len > 128 ) goto param_error; 76 } 77 78 if ( sessionSourceName == NULL ) { 79 BER_BVSTR( &name, "" ); 80 81 } else { 82 ber_str2bv( sessionSourceName, 0, 0, &name ); 83 /* NOTE: we're strict because we don't want 84 * to send out bad data */ 85 if ( name.bv_len > 65536 ) goto param_error; 86 } 87 88 ber_str2bv( formatOID, 0, 0, &oid ); 89 /* NOTE: we're strict because we don't want 90 * to send out bad data */ 91 if ( oid.bv_len > 1024 ) goto param_error; 92 93 if ( sessionTrackingIdentifier == NULL || 94 sessionTrackingIdentifier->bv_val == NULL ) 95 { 96 BER_BVSTR( &id, "" ); 97 98 } else { 99 id = *sessionTrackingIdentifier; 100 } 101 102 /* prepare value */ 103 value->bv_val = NULL; 104 value->bv_len = 0; 105 106 ber = ldap_alloc_ber_with_options( ld ); 107 if ( ber == NULL ) { 108 ld->ld_errno = LDAP_NO_MEMORY; 109 return ld->ld_errno; 110 } 111 112 tag = ber_printf( ber, "{OOOO}", &ip, &name, &oid, &id ); 113 if ( tag == LBER_ERROR ) { 114 ld->ld_errno = LDAP_ENCODING_ERROR; 115 goto done; 116 } 117 118 if ( ber_flatten2( ber, value, 1 ) == -1 ) { 119 ld->ld_errno = LDAP_NO_MEMORY; 120 } 121 122done:; 123 if ( ber != NULL ) { 124 ber_free( ber, 1 ); 125 } 126 127 return ld->ld_errno; 128} 129 130/* 131 * NOTE: this API is bad; it could be much more efficient... 132 */ 133int 134ldap_create_session_tracking_control( 135 LDAP *ld, 136 char *sessionSourceIp, 137 char *sessionSourceName, 138 char *formatOID, 139 struct berval *sessionTrackingIdentifier, 140 LDAPControl **ctrlp ) 141{ 142 struct berval value; 143 144 if ( ctrlp == NULL ) { 145 ld->ld_errno = LDAP_PARAM_ERROR; 146 return ld->ld_errno; 147 } 148 149 ld->ld_errno = ldap_create_session_tracking_value( ld, 150 sessionSourceIp, sessionSourceName, formatOID, 151 sessionTrackingIdentifier, &value ); 152 if ( ld->ld_errno == LDAP_SUCCESS ) { 153 ld->ld_errno = ldap_control_create( LDAP_CONTROL_X_SESSION_TRACKING, 154 0, &value, 0, ctrlp ); 155 if ( ld->ld_errno != LDAP_SUCCESS ) { 156 LDAP_FREE( value.bv_val ); 157 } 158 } 159 160 return ld->ld_errno; 161} 162 163int 164ldap_parse_session_tracking_control( 165 LDAP *ld, 166 LDAPControl *ctrl, 167 struct berval *ip, 168 struct berval *name, 169 struct berval *oid, 170 struct berval *id ) 171{ 172 BerElement *ber; 173 ber_tag_t tag; 174 ber_len_t len; 175 176 if ( ld == NULL || 177 ctrl == NULL || 178 ip == NULL || 179 name == NULL || 180 oid == NULL || 181 id == NULL ) 182 { 183 if ( ld ) { 184 ld->ld_errno = LDAP_PARAM_ERROR; 185 } 186 187 /* NOTE: we want the caller to get all or nothing; 188 * we could allow some of the pointers to be NULL, 189 * if one does not want part of the data */ 190 return LDAP_PARAM_ERROR; 191 } 192 193 BER_BVZERO( ip ); 194 BER_BVZERO( name ); 195 BER_BVZERO( oid ); 196 BER_BVZERO( id ); 197 198 ber = ber_init( &ctrl->ldctl_value ); 199 200 if ( ber == NULL ) { 201 ld->ld_errno = LDAP_NO_MEMORY; 202 return ld->ld_errno; 203 } 204 205 tag = ber_skip_tag( ber, &len ); 206 if ( tag != LBER_SEQUENCE ) { 207 tag = LBER_ERROR; 208 goto error; 209 } 210 211 /* sessionSourceIp */ 212 tag = ber_peek_tag( ber, &len ); 213 if ( tag == LBER_DEFAULT ) { 214 tag = LBER_ERROR; 215 goto error; 216 } 217 218 if ( len == 0 ) { 219 tag = ber_skip_tag( ber, &len ); 220 221 } else { 222 if ( len > 128 ) { 223 /* should be LDAP_DECODING_ERROR, 224 * but we're liberal in what we accept */ 225 } 226 tag = ber_scanf( ber, "o", ip ); 227 } 228 229 /* sessionSourceName */ 230 tag = ber_peek_tag( ber, &len ); 231 if ( tag == LBER_DEFAULT ) { 232 tag = LBER_ERROR; 233 goto error; 234 } 235 236 if ( len == 0 ) { 237 tag = ber_skip_tag( ber, &len ); 238 239 } else { 240 if ( len > 65536 ) { 241 /* should be LDAP_DECODING_ERROR, 242 * but we're liberal in what we accept */ 243 } 244 tag = ber_scanf( ber, "o", name ); 245 } 246 247 /* formatOID */ 248 tag = ber_peek_tag( ber, &len ); 249 if ( tag == LBER_DEFAULT ) { 250 tag = LBER_ERROR; 251 goto error; 252 } 253 254 if ( len == 0 ) { 255 ld->ld_errno = LDAP_DECODING_ERROR; 256 goto error; 257 258 } else { 259 if ( len > 1024 ) { 260 /* should be LDAP_DECODING_ERROR, 261 * but we're liberal in what we accept */ 262 } 263 tag = ber_scanf( ber, "o", oid ); 264 } 265 266 /* FIXME: should check if it is an OID... leave it to the caller */ 267 268 /* sessionTrackingIdentifier */ 269 tag = ber_peek_tag( ber, &len ); 270 if ( tag == LBER_DEFAULT ) { 271 tag = LBER_ERROR; 272 goto error; 273 } 274 275 if ( len == 0 ) { 276 tag = ber_skip_tag( ber, &len ); 277 278 } else { 279#if 0 280 if ( len > 65536 ) { 281 /* should be LDAP_DECODING_ERROR, 282 * but we're liberal in what we accept */ 283 } 284#endif 285 tag = ber_scanf( ber, "o", id ); 286 } 287 288 /* closure */ 289 tag = ber_skip_tag( ber, &len ); 290 if ( tag == LBER_DEFAULT && len == 0 ) { 291 tag = 0; 292 } 293 294error:; 295 (void)ber_free( ber, 1 ); 296 297 if ( tag == LBER_ERROR ) { 298 return LDAP_DECODING_ERROR; 299 } 300 301 return ld->ld_errno; 302} 303 304#endif /* LDAP_CONTROL_X_SESSION_TRACKING */ 305