summaryrefslogtreecommitdiffstats
path: root/libraries/libldap/stctrl.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/libldap/stctrl.c')
-rw-r--r--libraries/libldap/stctrl.c302
1 files changed, 302 insertions, 0 deletions
diff --git a/libraries/libldap/stctrl.c b/libraries/libldap/stctrl.c
new file mode 100644
index 0000000..8d2d06a
--- /dev/null
+++ b/libraries/libldap/stctrl.c
@@ -0,0 +1,302 @@
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 1998-2021 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 ) );
+ ld->ld_errno = LDAP_SUCCESS;
+
+ /* 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_control(
+ LDAP *ld,
+ char *sessionSourceIp,
+ char *sessionSourceName,
+ char *formatOID,
+ struct berval *sessionTrackingIdentifier,
+ LDAPControl **ctrlp )
+{
+ struct berval value;
+
+ 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 ) {
+ ld->ld_errno = ldap_control_create( LDAP_CONTROL_X_SESSION_TRACKING,
+ 0, &value, 0, ctrlp );
+ if ( ld->ld_errno != LDAP_SUCCESS ) {
+ LDAP_FREE( value.bv_val );
+ }
+ }
+
+ 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;
+ }
+
+ BER_BVZERO( ip );
+ BER_BVZERO( name );
+ BER_BVZERO( oid );
+ BER_BVZERO( id );
+
+ 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 */