Home | History | Annotate | Line # | Download | only in libldap
      1 /*	$NetBSD: stctrl.c,v 1.4 2025/09/05 21:16:21 christos Exp $	*/
      2 
      3 /* $OpenLDAP$ */
      4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
      5  *
      6  * Copyright 1998-2024 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.4 2025/09/05 21:16:21 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