Commit b0d2063d authored by Pierangelo Masarati's avatar Pierangelo Masarati
Browse files

client side of draft-wahl-ldap-session

parent 1a59d091
......@@ -33,6 +33,7 @@
#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
......@@ -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[=<attrs>] (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++;
}
......
......@@ -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
......
/* $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 */
......@@ -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
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment