]> git.sur5r.net Git - openldap/commitdiff
client side of draft-wahl-ldap-session
authorPierangelo Masarati <ando@openldap.org>
Tue, 21 Aug 2007 23:52:03 +0000 (23:52 +0000)
committerPierangelo Masarati <ando@openldap.org>
Tue, 21 Aug 2007 23:52:03 +0000 (23:52 +0000)
clients/tools/common.c
libraries/libldap/Makefile.in
libraries/libldap/stctrl.c [new file with mode: 0644]
libraries/libldap_r/Makefile.in

index 7fd62d510178504f024988513555dfa8214b7aba..058e8413af18217c50b028ce22a4d250be74b11f 100644 (file)
@@ -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++;
        }
index 8b62c45cc1c873cae80fd3d878379e9cd1c889dc..c031db07385b346e2e3f1f22114318efbc40dbcc 100644 (file)
@@ -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 (file)
index 0000000..84284e1
--- /dev/null
@@ -0,0 +1,316 @@
+/* $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 */
index f52f427518ed0adab50f0bd2fd7abeb788885bff..48df9f7550c4661d0b0f65c6afced1dee6cf3efb 100644 (file)
@@ -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