2022-06-07 04:35:45 -04:00
|
|
|
/* $OpenLDAP$ */
|
|
|
|
|
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
|
|
|
|
*
|
2024-03-26 15:45:07 -04:00
|
|
|
* Copyright 2000-2024 The OpenLDAP Foundation.
|
2022-06-07 04:35:45 -04:00
|
|
|
* 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>.
|
|
|
|
|
*/
|
|
|
|
|
/* ACKNOWLEDGEMENT:
|
|
|
|
|
* This work was initially developed by Ondřej Kuzník for inclusion in OpenLDAP
|
|
|
|
|
* Software.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <portable.h>
|
|
|
|
|
|
|
|
|
|
#define LDAP_DEPRECATED 1
|
|
|
|
|
#include "rewrite-int.h"
|
|
|
|
|
#include "rewrite-map.h"
|
|
|
|
|
|
|
|
|
|
#include <ldap_pvt.h>
|
|
|
|
|
|
|
|
|
|
typedef int (escape_fn)( struct berval *input, struct berval *output );
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Map configuration, a NULL-terminated list of escape_fn pointers
|
|
|
|
|
*/
|
|
|
|
|
struct escape_map_data {
|
|
|
|
|
escape_fn **fn;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* (un)escape functions
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
map_escape_to_filter( struct berval *input, struct berval *output )
|
|
|
|
|
{
|
|
|
|
|
return ldap_bv2escaped_filter_value( input, output );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
map_unescape_filter( struct berval *input, struct berval *output )
|
|
|
|
|
{
|
|
|
|
|
ber_slen_t len;
|
|
|
|
|
|
|
|
|
|
if ( ber_dupbv( output, input ) == NULL ) {
|
|
|
|
|
return REWRITE_ERR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
len = ldap_pvt_filter_value_unescape( output->bv_val );
|
2022-09-02 07:58:48 -04:00
|
|
|
if ( len < 0 ) {
|
|
|
|
|
ber_memfree( output->bv_val );
|
|
|
|
|
return REWRITE_ERR;
|
|
|
|
|
}
|
2022-06-07 04:35:45 -04:00
|
|
|
output->bv_len = len;
|
|
|
|
|
|
|
|
|
|
return LDAP_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
map_escape_to_dn( struct berval *input, struct berval *output )
|
|
|
|
|
{
|
|
|
|
|
LDAPAVA ava = { .la_attr = BER_BVC("uid"),
|
|
|
|
|
.la_value = *input,
|
|
|
|
|
.la_flags = LDAP_AVA_STRING },
|
|
|
|
|
*ava_[] = { &ava, NULL };
|
|
|
|
|
LDAPRDN rdn[] = { ava_, NULL };
|
|
|
|
|
LDAPDN dn = rdn;
|
|
|
|
|
struct berval dnstr;
|
|
|
|
|
char *p;
|
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
|
|
rc = ldap_dn2bv( dn, &dnstr, LDAP_DN_FORMAT_LDAPV3 );
|
|
|
|
|
if ( rc != LDAP_SUCCESS ) {
|
|
|
|
|
return REWRITE_ERR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p = strchr( dnstr.bv_val, '=' );
|
|
|
|
|
p++;
|
|
|
|
|
|
|
|
|
|
output->bv_len = dnstr.bv_len - ( p - dnstr.bv_val );
|
|
|
|
|
output->bv_val = malloc( output->bv_len + 1 );
|
|
|
|
|
if ( output->bv_val == NULL ) {
|
|
|
|
|
free( dnstr.bv_val );
|
|
|
|
|
return REWRITE_ERR;
|
|
|
|
|
}
|
|
|
|
|
memcpy( output->bv_val, p, output->bv_len );
|
|
|
|
|
output->bv_val[output->bv_len] = '\0';
|
|
|
|
|
|
|
|
|
|
free( dnstr.bv_val );
|
|
|
|
|
return REWRITE_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
map_unescape_dn( struct berval *input, struct berval *output )
|
|
|
|
|
{
|
|
|
|
|
LDAPDN dn;
|
|
|
|
|
struct berval fake_dn;
|
|
|
|
|
char *p;
|
|
|
|
|
int rc = REWRITE_SUCCESS;
|
|
|
|
|
|
|
|
|
|
fake_dn.bv_len = STRLENOF("uid=") + input->bv_len;
|
2022-08-30 08:22:45 -04:00
|
|
|
fake_dn.bv_val = p = malloc( fake_dn.bv_len + 1 );
|
2022-06-07 04:35:45 -04:00
|
|
|
if ( p == NULL ) {
|
|
|
|
|
return REWRITE_ERR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
memcpy( p, "uid=", STRLENOF("uid=") );
|
|
|
|
|
p += STRLENOF("uid=");
|
|
|
|
|
memcpy( p, input->bv_val, input->bv_len );
|
2022-08-30 08:22:45 -04:00
|
|
|
fake_dn.bv_val[fake_dn.bv_len] = '\0';
|
2022-06-07 04:35:45 -04:00
|
|
|
|
|
|
|
|
if ( ldap_bv2dn( &fake_dn, &dn, LDAP_DN_FORMAT_LDAPV3 ) != LDAP_SUCCESS ) {
|
2022-08-30 08:22:45 -04:00
|
|
|
free( fake_dn.bv_val );
|
2022-06-07 04:35:45 -04:00
|
|
|
return REWRITE_ERR;
|
|
|
|
|
}
|
|
|
|
|
if ( ber_dupbv( output, &dn[0][0]->la_value ) == NULL ) {
|
|
|
|
|
rc = REWRITE_ERR;
|
|
|
|
|
}
|
|
|
|
|
ldap_dnfree( dn );
|
2022-08-30 08:22:45 -04:00
|
|
|
free( fake_dn.bv_val );
|
2022-06-07 04:35:45 -04:00
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Registered callbacks */
|
|
|
|
|
|
|
|
|
|
static void *
|
|
|
|
|
map_escape_parse(
|
|
|
|
|
const char *fname,
|
|
|
|
|
int lineno,
|
|
|
|
|
int argc,
|
|
|
|
|
char **argv
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
escape_fn **fns;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
assert( fname != NULL );
|
|
|
|
|
assert( argv != NULL );
|
|
|
|
|
|
|
|
|
|
if ( argc < 1 ) {
|
|
|
|
|
Debug( LDAP_DEBUG_ANY,
|
|
|
|
|
"[%s:%d] escape map needs at least one operation\n",
|
|
|
|
|
fname, lineno );
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fns = calloc( sizeof(escape_fn *), argc + 1 );
|
|
|
|
|
if ( fns == NULL ) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for ( i = 0; i < argc; i++ ) {
|
|
|
|
|
if ( strcasecmp( argv[i], "escape2dn" ) == 0 ) {
|
|
|
|
|
fns[i] = map_escape_to_dn;
|
|
|
|
|
} else if ( strcasecmp( argv[i], "escape2filter" ) == 0 ) {
|
|
|
|
|
fns[i] = map_escape_to_filter;
|
|
|
|
|
} else if ( strcasecmp( argv[i], "unescapedn" ) == 0 ) {
|
|
|
|
|
fns[i] = map_unescape_dn;
|
|
|
|
|
} else if ( strcasecmp( argv[i], "unescapefilter" ) == 0 ) {
|
|
|
|
|
fns[i] = map_unescape_filter;
|
|
|
|
|
} else {
|
|
|
|
|
Debug( LDAP_DEBUG_ANY,
|
|
|
|
|
"[%s:%d] unknown option %s (ignored)\n",
|
|
|
|
|
fname, lineno, argv[i] );
|
|
|
|
|
free( fns );
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (void *)fns;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
map_escape_apply(
|
|
|
|
|
void *private,
|
|
|
|
|
const char *input,
|
|
|
|
|
struct berval *output )
|
|
|
|
|
{
|
|
|
|
|
escape_fn **fns = private;
|
2022-08-30 08:22:45 -04:00
|
|
|
struct berval tmpin, tmpout = BER_BVNULL;
|
2022-06-07 04:35:45 -04:00
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
assert( private != NULL );
|
|
|
|
|
assert( input != NULL );
|
|
|
|
|
assert( output != NULL );
|
|
|
|
|
|
|
|
|
|
ber_str2bv( input, 0, 1, &tmpin );
|
|
|
|
|
|
|
|
|
|
for ( i=0; fns[i]; i++ ) {
|
|
|
|
|
int rc = fns[i]( &tmpin, &tmpout );
|
|
|
|
|
free( tmpin.bv_val );
|
|
|
|
|
if ( rc != REWRITE_SUCCESS ) {
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
tmpin = tmpout;
|
2022-08-30 08:22:45 -04:00
|
|
|
BER_BVZERO( &tmpout );
|
2022-06-07 04:35:45 -04:00
|
|
|
}
|
|
|
|
|
*output = tmpin;
|
|
|
|
|
|
|
|
|
|
return REWRITE_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
map_escape_destroy(
|
|
|
|
|
void *private
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
struct ldap_map_data *data = private;
|
|
|
|
|
|
|
|
|
|
assert( private != NULL );
|
|
|
|
|
free( data );
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const rewrite_mapper rewrite_escape_mapper = {
|
|
|
|
|
"escape",
|
|
|
|
|
map_escape_parse,
|
|
|
|
|
map_escape_apply,
|
|
|
|
|
map_escape_destroy
|
|
|
|
|
};
|