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