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