From b0d2063d92cdc0e2cba9ebd2994f5d77274a3c97 Mon Sep 17 00:00:00 2001 From: Pierangelo Masarati Date: Tue, 21 Aug 2007 23:52:03 +0000 Subject: [PATCH] client side of draft-wahl-ldap-session --- clients/tools/common.c | 78 +++++++- libraries/libldap/Makefile.in | 4 +- libraries/libldap/stctrl.c | 316 ++++++++++++++++++++++++++++++++ libraries/libldap_r/Makefile.in | 4 +- 4 files changed, 397 insertions(+), 5 deletions(-) create mode 100644 libraries/libldap/stctrl.c diff --git a/clients/tools/common.c b/clients/tools/common.c index 7fd62d5101..058e8413af 100644 --- a/clients/tools/common.c +++ b/clients/tools/common.c @@ -33,6 +33,7 @@ #include #include #include +#include #ifdef HAVE_CYRUS_SASL #ifdef HAVE_SASL_SASL_H @@ -113,6 +114,10 @@ int chaining = 0; static int chainingResolve = -1; static int chainingContinuation = -1; #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */ +#ifdef LDAP_CONTROL_X_SESSION_TRACKING +static int sessionTracking = 0; +struct berval stValue; +#endif /* LDAP_CONTROL_X_SESSION_TRACKING */ LDAPControl *unknown_ctrls = NULL; int unknown_ctrls_num = 0; @@ -204,6 +209,9 @@ N_(" [!]preread[=] (a comma-separated attribute list)\n") #ifdef LDAP_DEVEL N_(" [!]relax\n") #endif +#ifdef LDAP_CONTROL_X_SESSION_TRACKING +N_(" [!]sessiontracking\n") +#endif /* LDAP_CONTROL_X_SESSION_TRACKING */ N_(" abandon, cancel, ignore (SIGINT sends abandon/cancel,\n" " or ignores response; if critical, doesn't wait for SIGINT.\n" " not really controls)\n") @@ -522,6 +530,15 @@ tool_args( int argc, char **argv ) gotintr = abcan; } +#ifdef LDAP_CONTROL_X_SESSION_TRACKING + } else if ( strcasecmp( control, "sessiontracking" ) == 0 ) { + if ( sessionTracking ) { + fprintf( stderr, "%s: session tracking can be only specified once\n", prog ); + exit( EXIT_FAILURE ); + } + sessionTracking = 1; +#endif /* LDAP_CONTROL_X_SESSION_TRACKING */ + } else if ( tool_is_oid( control ) ) { LDAPControl *tmpctrls, ctrl; @@ -935,6 +952,9 @@ tool_args( int argc, char **argv ) #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR chaining || #endif +#ifdef LDAP_CONTROL_X_SESSION_TRACKING + sessionTracking || +#endif /* LDAP_CONTROL_X_SESSION_TRACKING */ noop || ppolicy || preread || postread ) { fprintf( stderr, "%s: -e/-M incompatible with LDAPv2\n", prog ); @@ -1355,7 +1375,7 @@ void tool_server_controls( LDAP *ld, LDAPControl *extra_c, int count ) { int i = 0, j, crit = 0, err; - LDAPControl c[12], **ctrls; + LDAPControl c[16], **ctrls; if ( ! ( assertctl || authzid @@ -1373,6 +1393,9 @@ tool_server_controls( LDAP *ld, LDAPControl *extra_c, int count ) #ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR || chaining #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */ +#ifdef LDAP_CONTROL_X_SESSION_TRACKING + || sessionTracking +#endif /* LDAP_CONTROL_X_SESSION_TRACKING */ || count || unknown_ctrls_num ) ) { @@ -1587,6 +1610,59 @@ tool_server_controls( LDAP *ld, LDAPControl *extra_c, int count ) } #endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */ +#ifdef LDAP_CONTROL_X_SESSION_TRACKING + if ( sessionTracking ) { + if ( stValue.bv_val == NULL ) { + char *ip = NULL, *name = NULL; + struct berval id = { 0 }; + char namebuf[ HOST_NAME_MAX ]; + + if ( gethostname( namebuf, sizeof( namebuf ) ) == 0 ) { + struct hostent *h; + struct in_addr addr; + + name = namebuf; + + h = gethostbyname( name ); + if ( h != NULL ) { + AC_MEMCPY( &addr, h->h_addr, sizeof( addr ) ); + ip = inet_ntoa( addr ); + } + } + +#ifdef HAVE_CYRUS_SASL + if ( sasl_authz_id != NULL ) { + ber_str2bv( sasl_authz_id, 0, 0, &id ); + + } else if ( sasl_authc_id != NULL ) { + ber_str2bv( sasl_authc_id, 0, 0, &id ); + + } else +#endif /* HAVE_CYRUS_SASL */ + if ( binddn != NULL ) { + ber_str2bv( binddn, 0, 0, &id ); + + } else { + ber_str2bv( "anonymous", 0, 0, &id ); + } + + if ( ldap_create_session_tracking_value( ld, + ip, name, "1.3.6.1.4.1.21008.108.63.1.3", &id, + &stValue ) ) + { + fprintf( stderr, _("Session tracking control encoding error!\n") ); + exit( EXIT_FAILURE ); + } + } + + c[i].ldctl_oid = LDAP_CONTROL_X_SESSION_TRACKING; + c[i].ldctl_iscritical = 0; + ber_dupbv( &c[i].ldctl_value, &stValue ); + ctrls[i] = &c[i]; + i++; + } +#endif /* LDAP_CONTROL_X_SESSION_TRACKING */ + while ( count-- ) { ctrls[i++] = extra_c++; } diff --git a/libraries/libldap/Makefile.in b/libraries/libldap/Makefile.in index 8b62c45cc1..c031db0738 100644 --- a/libraries/libldap/Makefile.in +++ b/libraries/libldap/Makefile.in @@ -26,7 +26,7 @@ SRCS = bind.c open.c result.c error.c compare.c search.c \ request.c os-ip.c url.c pagectrl.c sortctrl.c vlvctrl.c \ init.c options.c print.c string.c util-int.c schema.c \ charray.c tls.c os-local.c dnssrv.c utf-8.c utf-8-conv.c \ - turn.c ppolicy.c dds.c txn.c ldap_sync.c + turn.c ppolicy.c dds.c txn.c ldap_sync.c stctrl.c OBJS = bind.lo open.lo result.lo error.lo compare.lo search.lo \ controls.lo messages.lo references.lo extended.lo cyrus.lo \ @@ -37,7 +37,7 @@ OBJS = bind.lo open.lo result.lo error.lo compare.lo search.lo \ request.lo os-ip.lo url.lo pagectrl.lo sortctrl.lo vlvctrl.lo \ init.lo options.lo print.lo string.lo util-int.lo schema.lo \ charray.lo tls.lo os-local.lo dnssrv.lo utf-8.lo utf-8-conv.lo \ - turn.lo ppolicy.lo dds.lo txn.lo ldap_sync.lo + turn.lo ppolicy.lo dds.lo txn.lo ldap_sync.lo stctrl.lo LDAP_INCDIR= ../../include LDAP_LIBDIR= ../../libraries diff --git a/libraries/libldap/stctrl.c b/libraries/libldap/stctrl.c new file mode 100644 index 0000000000..84284e11db --- /dev/null +++ b/libraries/libldap/stctrl.c @@ -0,0 +1,316 @@ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software . + * + * Copyright 1998-2007 The OpenLDAP Foundation. + * Portions Copyright 2007 Pierangelo Masarati. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ +/* ACKNOWLEDGEMENTS: + * This work was developed by Pierangelo Masarati for inclusion in + * OpenLDAP Software. + */ + +#include "portable.h" + +#include +#include +#include +#include + +#include "ldap-int.h" + +#ifdef LDAP_CONTROL_X_SESSION_TRACKING + +/* + * Client-side of + */ + +int +ldap_create_session_tracking_value( + LDAP *ld, + char *sessionSourceIp, + char *sessionSourceName, + char *formatOID, + struct berval *sessionTrackingIdentifier, + struct berval *value ) +{ + BerElement *ber = NULL; + ber_tag_t tag; + + struct berval ip, name, oid, id; + + if ( ld == NULL || + formatOID == NULL || + value == NULL ) + { +param_error:; + if ( ld ) { + ld->ld_errno = LDAP_PARAM_ERROR; + } + + return LDAP_PARAM_ERROR; + } + + assert( LDAP_VALID( ld ) ); + + /* check sizes according to I.D. */ + if ( sessionSourceIp == NULL ) { + BER_BVSTR( &ip, "" ); + + } else { + ber_str2bv( sessionSourceIp, 0, 0, &ip ); + /* NOTE: we're strict because we don't want + * to send out bad data */ + if ( ip.bv_len > 128 ) goto param_error; + } + + if ( sessionSourceName == NULL ) { + BER_BVSTR( &name, "" ); + + } else { + ber_str2bv( sessionSourceName, 0, 0, &name ); + /* NOTE: we're strict because we don't want + * to send out bad data */ + if ( name.bv_len > 65536 ) goto param_error; + } + + ber_str2bv( formatOID, 0, 0, &oid ); + /* NOTE: we're strict because we don't want + * to send out bad data */ + if ( oid.bv_len > 1024 ) goto param_error; + + if ( sessionTrackingIdentifier == NULL || + sessionTrackingIdentifier->bv_val == NULL ) + { + BER_BVSTR( &id, "" ); + + } else { + id = *sessionTrackingIdentifier; + } + + /* prepare value */ + value->bv_val = NULL; + value->bv_len = 0; + + ber = ldap_alloc_ber_with_options( ld ); + if ( ber == NULL ) { + ld->ld_errno = LDAP_NO_MEMORY; + return ld->ld_errno; + } + + tag = ber_printf( ber, "{OOOO}", &ip, &name, &oid, &id ); + if ( tag == LBER_ERROR ) { + ld->ld_errno = LDAP_ENCODING_ERROR; + goto done; + } + + if ( ber_flatten2( ber, value, 1 ) == -1 ) { + ld->ld_errno = LDAP_NO_MEMORY; + } + +done:; + if ( ber != NULL ) { + ber_free( ber, 1 ); + } + + return ld->ld_errno; +} + +/* + * NOTE: this API is bad; it could be much more efficient... + */ +int +ldap_create_session_tracking( + LDAP *ld, + char *sessionSourceIp, + char *sessionSourceName, + char *formatOID, + struct berval *sessionTrackingIdentifier, + LDAPControl **ctrlp ) +{ + struct berval value; + BerElement *ber; + + if ( ctrlp == NULL ) { + ld->ld_errno = LDAP_PARAM_ERROR; + return ld->ld_errno; + } + + ld->ld_errno = ldap_create_session_tracking_value( ld, + sessionSourceIp, sessionSourceName, formatOID, + sessionTrackingIdentifier, &value ); + if ( ld->ld_errno == LDAP_SUCCESS ) { + ber = ldap_alloc_ber_with_options( ld ); + if ( ber == NULL ) { + ld->ld_errno = LDAP_NO_MEMORY; + return LDAP_NO_MEMORY; + } + + ld->ld_errno = ldap_create_control( LDAP_CONTROL_X_SESSION_TRACKING, + ber, 0, ctrlp ); + if ( ld->ld_errno == LDAP_SUCCESS ) { + (*ctrlp)->ldctl_value = value; + + } else { + LDAP_FREE( value.bv_val ); + } + ber_free( ber, 1 ); + } + + return ld->ld_errno; +} + +int +ldap_parse_session_tracking_control( + LDAP *ld, + LDAPControl *ctrl, + struct berval *ip, + struct berval *name, + struct berval *oid, + struct berval *id ) +{ + BerElement *ber; + ber_tag_t tag; + ber_len_t len; + + if ( ld == NULL || + ctrl == NULL || + ip == NULL || + name == NULL || + oid == NULL || + id == NULL ) + { + if ( ld ) { + ld->ld_errno = LDAP_PARAM_ERROR; + } + + /* NOTE: we want the caller to get all or nothing; + * we could allow some of the pointers to be NULL, + * if one does not want part of the data */ + return LDAP_PARAM_ERROR; + } + + ip->bv_val = NULL; + ip->bv_len = 0; + name->bv_val = NULL; + name->bv_len = 0; + oid->bv_val = NULL; + oid->bv_len = 0; + id->bv_val = NULL; + id->bv_len = 0; + + ber = ber_init( &ctrl->ldctl_value ); + + if ( ber == NULL ) { + ld->ld_errno = LDAP_NO_MEMORY; + return ld->ld_errno; + } + + tag = ber_skip_tag( ber, &len ); + if ( tag != LBER_SEQUENCE ) { + tag = LBER_ERROR; + goto error; + } + + /* sessionSourceIp */ + tag = ber_peek_tag( ber, &len ); + if ( tag == LBER_DEFAULT ) { + tag = LBER_ERROR; + goto error; + } + + if ( len == 0 ) { + tag = ber_skip_tag( ber, &len ); + + } else { + if ( len > 128 ) { + /* should be LDAP_DECODING_ERROR, + * but we're liberal in what we accept */ + } + tag = ber_scanf( ber, "o", ip ); + } + + /* sessionSourceName */ + tag = ber_peek_tag( ber, &len ); + if ( tag == LBER_DEFAULT ) { + tag = LBER_ERROR; + goto error; + } + + if ( len == 0 ) { + tag = ber_skip_tag( ber, &len ); + + } else { + if ( len > 65536 ) { + /* should be LDAP_DECODING_ERROR, + * but we're liberal in what we accept */ + } + tag = ber_scanf( ber, "o", name ); + } + + /* formatOID */ + tag = ber_peek_tag( ber, &len ); + if ( tag == LBER_DEFAULT ) { + tag = LBER_ERROR; + goto error; + } + + if ( len == 0 ) { + ld->ld_errno = LDAP_DECODING_ERROR; + goto error; + + } else { + if ( len > 1024 ) { + /* should be LDAP_DECODING_ERROR, + * but we're liberal in what we accept */ + } + tag = ber_scanf( ber, "o", oid ); + } + + /* FIXME: should check if it is an OID... leave it to the caller */ + + /* sessionTrackingIdentifier */ + tag = ber_peek_tag( ber, &len ); + if ( tag == LBER_DEFAULT ) { + tag = LBER_ERROR; + goto error; + } + + if ( len == 0 ) { + tag = ber_skip_tag( ber, &len ); + + } else { +#if 0 + if ( len > 65536 ) { + /* should be LDAP_DECODING_ERROR, + * but we're liberal in what we accept */ + } +#endif + tag = ber_scanf( ber, "o", id ); + } + + /* closure */ + tag = ber_skip_tag( ber, &len ); + if ( tag == LBER_DEFAULT && len == 0 ) { + tag = 0; + } + +error:; + (void)ber_free( ber, 1 ); + + if ( tag == LBER_ERROR ) { + return LDAP_DECODING_ERROR; + } + + return ld->ld_errno; +} + +#endif /* LDAP_CONTROL_X_SESSION_TRACKING */ diff --git a/libraries/libldap_r/Makefile.in b/libraries/libldap_r/Makefile.in index f52f427518..48df9f7550 100644 --- a/libraries/libldap_r/Makefile.in +++ b/libraries/libldap_r/Makefile.in @@ -28,7 +28,7 @@ XXSRCS = apitest.c test.c \ request.c os-ip.c url.c pagectrl.c sortctrl.c vlvctrl.c \ init.c options.c print.c string.c util-int.c schema.c \ charray.c tls.c os-local.c dnssrv.c utf-8.c utf-8-conv.c \ - turn.c ppolicy.c dds.c txn.c ldap_sync.c + turn.c ppolicy.c dds.c txn.c ldap_sync.c stctrl.c SRCS = threads.c rdwr.c rmutex.c tpool.c rq.c \ thr_posix.c thr_cthreads.c thr_thr.c thr_lwp.c thr_nt.c \ thr_pth.c thr_stub.c thr_debug.c @@ -44,7 +44,7 @@ OBJS = threads.lo rdwr.lo rmutex.lo tpool.lo rq.lo \ request.lo os-ip.lo url.lo pagectrl.lo sortctrl.lo vlvctrl.lo \ init.lo options.lo print.lo string.lo util-int.lo schema.lo \ charray.lo tls.lo os-local.lo dnssrv.lo utf-8.lo utf-8-conv.lo \ - turn.lo ppolicy.lo dds.lo txn.lo ldap_sync.lo + turn.lo ppolicy.lo dds.lo txn.lo ldap_sync.lo stctrl.lo LDAP_INCDIR= ../../include LDAP_LIBDIR= ../../libraries -- 2.39.5