xref: /netbsd-src/external/bsd/openldap/dist/libraries/libldap/stctrl.c (revision 549b59ed3ccf0d36d3097190a0db27b770f3a839)
1*549b59edSchristos /*	$NetBSD: stctrl.c,v 1.3 2021/08/14 16:14:56 christos Exp $	*/
24e6df137Slukem 
3d11b170bStron /* $OpenLDAP$ */
42de962bdSlukem /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
52de962bdSlukem  *
6*549b59edSchristos  * Copyright 1998-2021 The OpenLDAP Foundation.
72de962bdSlukem  * Portions Copyright 2007 Pierangelo Masarati.
82de962bdSlukem  * All rights reserved.
92de962bdSlukem  *
102de962bdSlukem  * Redistribution and use in source and binary forms, with or without
112de962bdSlukem  * modification, are permitted only as authorized by the OpenLDAP
122de962bdSlukem  * Public License.
132de962bdSlukem  *
142de962bdSlukem  * A copy of this license is available in the file LICENSE in the
152de962bdSlukem  * top-level directory of the distribution or, alternatively, at
162de962bdSlukem  * <http://www.OpenLDAP.org/license.html>.
172de962bdSlukem  */
182de962bdSlukem /* ACKNOWLEDGEMENTS:
192de962bdSlukem  * This work was developed by Pierangelo Masarati for inclusion in
202de962bdSlukem  * OpenLDAP Software.
212de962bdSlukem  */
222de962bdSlukem 
23376af7d7Schristos #include <sys/cdefs.h>
24*549b59edSchristos __RCSID("$NetBSD: stctrl.c,v 1.3 2021/08/14 16:14:56 christos Exp $");
25376af7d7Schristos 
262de962bdSlukem #include "portable.h"
272de962bdSlukem 
282de962bdSlukem #include <stdio.h>
292de962bdSlukem #include <ac/stdlib.h>
302de962bdSlukem #include <ac/string.h>
312de962bdSlukem #include <ac/time.h>
322de962bdSlukem 
332de962bdSlukem #include "ldap-int.h"
342de962bdSlukem 
352de962bdSlukem #ifdef LDAP_CONTROL_X_SESSION_TRACKING
362de962bdSlukem 
372de962bdSlukem /*
382de962bdSlukem  * Client-side of <draft-wahl-ldap-session-03>
392de962bdSlukem  */
402de962bdSlukem 
412de962bdSlukem int
ldap_create_session_tracking_value(LDAP * ld,char * sessionSourceIp,char * sessionSourceName,char * formatOID,struct berval * sessionTrackingIdentifier,struct berval * value)422de962bdSlukem ldap_create_session_tracking_value(
432de962bdSlukem 	LDAP		*ld,
442de962bdSlukem 	char		*sessionSourceIp,
452de962bdSlukem 	char		*sessionSourceName,
462de962bdSlukem 	char		*formatOID,
472de962bdSlukem 	struct berval	*sessionTrackingIdentifier,
482de962bdSlukem 	struct berval	*value )
492de962bdSlukem {
502de962bdSlukem 	BerElement	*ber = NULL;
512de962bdSlukem 	ber_tag_t	tag;
522de962bdSlukem 
532de962bdSlukem 	struct berval	ip, name, oid, id;
542de962bdSlukem 
552de962bdSlukem 	if ( ld == NULL ||
562de962bdSlukem 		formatOID == NULL ||
572de962bdSlukem 		value == NULL )
582de962bdSlukem 	{
592de962bdSlukem param_error:;
602de962bdSlukem 		if ( ld ) {
612de962bdSlukem 			ld->ld_errno = LDAP_PARAM_ERROR;
622de962bdSlukem 		}
632de962bdSlukem 
642de962bdSlukem 		return LDAP_PARAM_ERROR;
652de962bdSlukem 	}
662de962bdSlukem 
672de962bdSlukem 	assert( LDAP_VALID( ld ) );
684e6df137Slukem 	ld->ld_errno = LDAP_SUCCESS;
692de962bdSlukem 
702de962bdSlukem 	/* check sizes according to I.D. */
712de962bdSlukem 	if ( sessionSourceIp == NULL ) {
722de962bdSlukem 		BER_BVSTR( &ip, "" );
732de962bdSlukem 
742de962bdSlukem 	} else {
752de962bdSlukem 		ber_str2bv( sessionSourceIp, 0, 0, &ip );
762de962bdSlukem 		/* NOTE: we're strict because we don't want
772de962bdSlukem 		 * to send out bad data */
782de962bdSlukem 		if ( ip.bv_len > 128 ) goto param_error;
792de962bdSlukem 	}
802de962bdSlukem 
812de962bdSlukem 	if ( sessionSourceName == NULL ) {
822de962bdSlukem 		BER_BVSTR( &name, "" );
832de962bdSlukem 
842de962bdSlukem 	} else {
852de962bdSlukem 		ber_str2bv( sessionSourceName, 0, 0, &name );
862de962bdSlukem 		/* NOTE: we're strict because we don't want
872de962bdSlukem 		 * to send out bad data */
882de962bdSlukem 		if ( name.bv_len > 65536 ) goto param_error;
892de962bdSlukem 	}
902de962bdSlukem 
912de962bdSlukem 	ber_str2bv( formatOID, 0, 0, &oid );
922de962bdSlukem 	/* NOTE: we're strict because we don't want
932de962bdSlukem 	 * to send out bad data */
942de962bdSlukem 	if ( oid.bv_len > 1024 ) goto param_error;
952de962bdSlukem 
962de962bdSlukem 	if ( sessionTrackingIdentifier == NULL ||
972de962bdSlukem 		sessionTrackingIdentifier->bv_val == NULL )
982de962bdSlukem 	{
992de962bdSlukem 		BER_BVSTR( &id, "" );
1002de962bdSlukem 
1012de962bdSlukem 	} else {
1022de962bdSlukem 		id = *sessionTrackingIdentifier;
1032de962bdSlukem 	}
1042de962bdSlukem 
1052de962bdSlukem 	/* prepare value */
1062de962bdSlukem 	value->bv_val = NULL;
1072de962bdSlukem 	value->bv_len = 0;
1082de962bdSlukem 
1092de962bdSlukem 	ber = ldap_alloc_ber_with_options( ld );
1102de962bdSlukem 	if ( ber == NULL ) {
1112de962bdSlukem 		ld->ld_errno = LDAP_NO_MEMORY;
1122de962bdSlukem 		return ld->ld_errno;
1132de962bdSlukem 	}
1142de962bdSlukem 
1152de962bdSlukem 	tag = ber_printf( ber, "{OOOO}", &ip, &name, &oid, &id );
1162de962bdSlukem 	if ( tag == LBER_ERROR ) {
1172de962bdSlukem 		ld->ld_errno = LDAP_ENCODING_ERROR;
1182de962bdSlukem 		goto done;
1192de962bdSlukem 	}
1202de962bdSlukem 
1212de962bdSlukem 	if ( ber_flatten2( ber, value, 1 ) == -1 ) {
1222de962bdSlukem 		ld->ld_errno = LDAP_NO_MEMORY;
1232de962bdSlukem 	}
1242de962bdSlukem 
1252de962bdSlukem done:;
1262de962bdSlukem 	if ( ber != NULL ) {
1272de962bdSlukem 		ber_free( ber, 1 );
1282de962bdSlukem 	}
1292de962bdSlukem 
1302de962bdSlukem 	return ld->ld_errno;
1312de962bdSlukem }
1322de962bdSlukem 
1332de962bdSlukem /*
1342de962bdSlukem  * NOTE: this API is bad; it could be much more efficient...
1352de962bdSlukem  */
1362de962bdSlukem int
ldap_create_session_tracking_control(LDAP * ld,char * sessionSourceIp,char * sessionSourceName,char * formatOID,struct berval * sessionTrackingIdentifier,LDAPControl ** ctrlp)1372de962bdSlukem ldap_create_session_tracking_control(
1382de962bdSlukem 	LDAP		*ld,
1392de962bdSlukem 	char		*sessionSourceIp,
1402de962bdSlukem 	char		*sessionSourceName,
1412de962bdSlukem 	char		*formatOID,
1422de962bdSlukem 	struct berval	*sessionTrackingIdentifier,
1432de962bdSlukem 	LDAPControl	**ctrlp )
1442de962bdSlukem {
1452de962bdSlukem 	struct berval	value;
1462de962bdSlukem 
1472de962bdSlukem 	if ( ctrlp == NULL ) {
1482de962bdSlukem 		ld->ld_errno = LDAP_PARAM_ERROR;
1492de962bdSlukem 		return ld->ld_errno;
1502de962bdSlukem 	}
1512de962bdSlukem 
1522de962bdSlukem 	ld->ld_errno = ldap_create_session_tracking_value( ld,
1532de962bdSlukem 		sessionSourceIp, sessionSourceName, formatOID,
1542de962bdSlukem 		sessionTrackingIdentifier, &value );
1552de962bdSlukem 	if ( ld->ld_errno == LDAP_SUCCESS ) {
1562de962bdSlukem 		ld->ld_errno = ldap_control_create( LDAP_CONTROL_X_SESSION_TRACKING,
1572de962bdSlukem 			0, &value, 0, ctrlp );
1582de962bdSlukem 		if ( ld->ld_errno != LDAP_SUCCESS ) {
1592de962bdSlukem 			LDAP_FREE( value.bv_val );
1602de962bdSlukem 		}
1612de962bdSlukem 	}
1622de962bdSlukem 
1632de962bdSlukem 	return ld->ld_errno;
1642de962bdSlukem }
1652de962bdSlukem 
1662de962bdSlukem int
ldap_parse_session_tracking_control(LDAP * ld,LDAPControl * ctrl,struct berval * ip,struct berval * name,struct berval * oid,struct berval * id)1672de962bdSlukem ldap_parse_session_tracking_control(
1682de962bdSlukem 	LDAP *ld,
1692de962bdSlukem 	LDAPControl *ctrl,
1702de962bdSlukem 	struct berval *ip,
1712de962bdSlukem 	struct berval *name,
1722de962bdSlukem 	struct berval *oid,
1732de962bdSlukem 	struct berval *id )
1742de962bdSlukem {
1752de962bdSlukem 	BerElement	*ber;
1762de962bdSlukem 	ber_tag_t	tag;
1772de962bdSlukem 	ber_len_t	len;
1782de962bdSlukem 
1792de962bdSlukem 	if ( ld == NULL ||
1802de962bdSlukem 		ctrl == NULL ||
1812de962bdSlukem 		ip == NULL ||
1822de962bdSlukem 		name == NULL ||
1832de962bdSlukem 		oid == NULL ||
1842de962bdSlukem 		id == NULL )
1852de962bdSlukem 	{
1862de962bdSlukem 		if ( ld ) {
1872de962bdSlukem 			ld->ld_errno = LDAP_PARAM_ERROR;
1882de962bdSlukem 		}
1892de962bdSlukem 
1902de962bdSlukem 		/* NOTE: we want the caller to get all or nothing;
1912de962bdSlukem 		 * we could allow some of the pointers to be NULL,
1922de962bdSlukem 		 * if one does not want part of the data */
1932de962bdSlukem 		return LDAP_PARAM_ERROR;
1942de962bdSlukem 	}
1952de962bdSlukem 
1962de962bdSlukem 	BER_BVZERO( ip );
1972de962bdSlukem 	BER_BVZERO( name );
1982de962bdSlukem 	BER_BVZERO( oid );
1992de962bdSlukem 	BER_BVZERO( id );
2002de962bdSlukem 
2012de962bdSlukem 	ber = ber_init( &ctrl->ldctl_value );
2022de962bdSlukem 
2032de962bdSlukem 	if ( ber == NULL ) {
2042de962bdSlukem 		ld->ld_errno = LDAP_NO_MEMORY;
2052de962bdSlukem 		return ld->ld_errno;
2062de962bdSlukem 	}
2072de962bdSlukem 
2082de962bdSlukem 	tag = ber_skip_tag( ber, &len );
2092de962bdSlukem 	if ( tag != LBER_SEQUENCE ) {
2102de962bdSlukem 		tag = LBER_ERROR;
2112de962bdSlukem 		goto error;
2122de962bdSlukem 	}
2132de962bdSlukem 
2142de962bdSlukem 	/* sessionSourceIp */
2152de962bdSlukem 	tag = ber_peek_tag( ber, &len );
2162de962bdSlukem 	if ( tag == LBER_DEFAULT ) {
2172de962bdSlukem 		tag = LBER_ERROR;
2182de962bdSlukem 		goto error;
2192de962bdSlukem 	}
2202de962bdSlukem 
2212de962bdSlukem 	if ( len == 0 ) {
2222de962bdSlukem 		tag = ber_skip_tag( ber, &len );
2232de962bdSlukem 
2242de962bdSlukem 	} else {
2252de962bdSlukem 		if ( len > 128 ) {
2262de962bdSlukem 			/* should be LDAP_DECODING_ERROR,
2272de962bdSlukem 			 * but we're liberal in what we accept */
2282de962bdSlukem 		}
2292de962bdSlukem 		tag = ber_scanf( ber, "o", ip );
2302de962bdSlukem 	}
2312de962bdSlukem 
2322de962bdSlukem 	/* sessionSourceName */
2332de962bdSlukem 	tag = ber_peek_tag( ber, &len );
2342de962bdSlukem 	if ( tag == LBER_DEFAULT ) {
2352de962bdSlukem 		tag = LBER_ERROR;
2362de962bdSlukem 		goto error;
2372de962bdSlukem 	}
2382de962bdSlukem 
2392de962bdSlukem 	if ( len == 0 ) {
2402de962bdSlukem 		tag = ber_skip_tag( ber, &len );
2412de962bdSlukem 
2422de962bdSlukem 	} else {
2432de962bdSlukem 		if ( len > 65536 ) {
2442de962bdSlukem 			/* should be LDAP_DECODING_ERROR,
2452de962bdSlukem 			 * but we're liberal in what we accept */
2462de962bdSlukem 		}
2472de962bdSlukem 		tag = ber_scanf( ber, "o", name );
2482de962bdSlukem 	}
2492de962bdSlukem 
2502de962bdSlukem 	/* formatOID */
2512de962bdSlukem 	tag = ber_peek_tag( ber, &len );
2522de962bdSlukem 	if ( tag == LBER_DEFAULT ) {
2532de962bdSlukem 		tag = LBER_ERROR;
2542de962bdSlukem 		goto error;
2552de962bdSlukem 	}
2562de962bdSlukem 
2572de962bdSlukem 	if ( len == 0 ) {
2582de962bdSlukem 		ld->ld_errno = LDAP_DECODING_ERROR;
2592de962bdSlukem 		goto error;
2602de962bdSlukem 
2612de962bdSlukem 	} else {
2622de962bdSlukem 		if ( len > 1024 ) {
2632de962bdSlukem 			/* should be LDAP_DECODING_ERROR,
2642de962bdSlukem 			 * but we're liberal in what we accept */
2652de962bdSlukem 		}
2662de962bdSlukem 		tag = ber_scanf( ber, "o", oid );
2672de962bdSlukem 	}
2682de962bdSlukem 
2692de962bdSlukem 	/* FIXME: should check if it is an OID... leave it to the caller */
2702de962bdSlukem 
2712de962bdSlukem 	/* sessionTrackingIdentifier */
2722de962bdSlukem 	tag = ber_peek_tag( ber, &len );
2732de962bdSlukem 	if ( tag == LBER_DEFAULT ) {
2742de962bdSlukem 		tag = LBER_ERROR;
2752de962bdSlukem 		goto error;
2762de962bdSlukem 	}
2772de962bdSlukem 
2782de962bdSlukem 	if ( len == 0 ) {
2792de962bdSlukem 		tag = ber_skip_tag( ber, &len );
2802de962bdSlukem 
2812de962bdSlukem 	} else {
2822de962bdSlukem #if 0
2832de962bdSlukem 		if ( len > 65536 ) {
2842de962bdSlukem 			/* should be LDAP_DECODING_ERROR,
2852de962bdSlukem 			 * but we're liberal in what we accept */
2862de962bdSlukem 		}
2872de962bdSlukem #endif
2882de962bdSlukem 		tag = ber_scanf( ber, "o", id );
2892de962bdSlukem 	}
2902de962bdSlukem 
2912de962bdSlukem 	/* closure */
2922de962bdSlukem 	tag = ber_skip_tag( ber, &len );
2932de962bdSlukem 	if ( tag == LBER_DEFAULT && len == 0 ) {
2942de962bdSlukem 		tag = 0;
2952de962bdSlukem 	}
2962de962bdSlukem 
2972de962bdSlukem error:;
2982de962bdSlukem 	(void)ber_free( ber, 1 );
2992de962bdSlukem 
3002de962bdSlukem 	if ( tag == LBER_ERROR ) {
3012de962bdSlukem 		return LDAP_DECODING_ERROR;
3022de962bdSlukem 	}
3032de962bdSlukem 
3042de962bdSlukem 	return ld->ld_errno;
3052de962bdSlukem }
3062de962bdSlukem 
3072de962bdSlukem #endif /* LDAP_CONTROL_X_SESSION_TRACKING */
308