/* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * * Copyright 1998-2013 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 * . */ /* ACKNOWLEDGEMENTS: * This work was developed by Pierangelo Masarati for inclusion in * OpenLDAP Software. */ #include "portable.h" #include #include #include #include #include "ldap-int.h" #ifdef LDAP_CONTROL_X_SESSION_TRACKING /* * Client-side of */ 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 */