#include <ac/unistd.h>
#include <ac/errno.h>
#include <ac/time.h>
+#include <ac/socket.h>
#ifdef HAVE_CYRUS_SASL
#ifdef HAVE_SASL_SASL_H
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;
#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")
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;
#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 );
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
#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 ) )
{
}
#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++;
}
--- /dev/null
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * 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
+ * <http://www.OpenLDAP.org/license.html>.
+ */
+/* ACKNOWLEDGEMENTS:
+ * This work was developed by Pierangelo Masarati for inclusion in
+ * OpenLDAP Software.
+ */
+
+#include "portable.h"
+
+#include <stdio.h>
+#include <ac/stdlib.h>
+#include <ac/string.h>
+#include <ac/time.h>
+
+#include "ldap-int.h"
+
+#ifdef LDAP_CONTROL_X_SESSION_TRACKING
+
+/*
+ * Client-side of <draft-wahl-ldap-session-03>
+ */
+
+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 */