mirror of
https://git.openldap.org/openldap/openldap.git
synced 2024-12-21 03:10:25 +08:00
303 lines
5.9 KiB
C
303 lines
5.9 KiB
C
/* $OpenLDAP$ */
|
|
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
|
*
|
|
* Copyright 1998-2020 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 */
|