mirror of
https://git.openldap.org/openldap/openldap.git
synced 2026-02-03 20:40:05 -05:00
add authzSyntax for authzTo/authzFrom attributes; add X-ORDERED 'VALUES' if support for ordered_value_{validate,pretty,normalize} is present; exploit normalization in slap_parseURI (only #ifdef LDAP_DEVEL)
This commit is contained in:
parent
53a4d530d9
commit
d10250d9f6
6 changed files with 867 additions and 20 deletions
|
|
@ -908,8 +908,22 @@ ldap_back_cf_gen( ConfigArgs *c )
|
|||
|
||||
case LDAP_BACK_CFG_IDASSERT_AUTHZFROM: {
|
||||
struct berval bv;
|
||||
#ifdef SLAP_AUTHZ_SYNTAX
|
||||
struct berval in;
|
||||
int rc;
|
||||
|
||||
ber_str2bv( c->argv[ 1 ], 0, 0, &in );
|
||||
rc = authzNormalize( 0, NULL, NULL, &in, &bv, NULL );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
fprintf( stderr, "%s: %d: "
|
||||
"\"idassert-authzFrom <authz>\": "
|
||||
"invalid syntax.\n",
|
||||
c->fname, c->lineno );
|
||||
return 1;
|
||||
}
|
||||
#else /* !SLAP_AUTHZ_SYNTAX */
|
||||
ber_str2bv( c->argv[ 1 ], 0, 1, &bv );
|
||||
#endif /* !SLAP_AUTHZ_SYNTAX */
|
||||
ber_bvarray_add( &li->idassert_authz, &bv );
|
||||
} break;
|
||||
|
||||
|
|
|
|||
|
|
@ -1337,6 +1337,31 @@ LDAP_SLAPD_F (int) slap_sasl_rewrite_config LDAP_P((
|
|||
int argc,
|
||||
char **argv ));
|
||||
#endif /* SLAP_AUTH_REWRITE */
|
||||
#ifdef SLAP_AUTHZ_SYNTAX
|
||||
LDAP_SLAPD_F (int) authzValidate LDAP_P((
|
||||
Syntax *syn, struct berval *in ));
|
||||
#if 0
|
||||
LDAP_SLAPD_F (int) authzMatch LDAP_P((
|
||||
int *matchp,
|
||||
slap_mask_t flags,
|
||||
Syntax *syntax,
|
||||
MatchingRule *mr,
|
||||
struct berval *value,
|
||||
void *assertedValue ));
|
||||
#endif
|
||||
LDAP_SLAPD_F (int) authzPretty LDAP_P((
|
||||
Syntax *syntax,
|
||||
struct berval *val,
|
||||
struct berval *out,
|
||||
void *ctx ));
|
||||
LDAP_SLAPD_F (int) authzNormalize LDAP_P((
|
||||
slap_mask_t usage,
|
||||
Syntax *syntax,
|
||||
MatchingRule *mr,
|
||||
struct berval *val,
|
||||
struct berval *normalized,
|
||||
void *ctx ));
|
||||
#endif /* SLAP_AUTHZ_SYNTAX */
|
||||
|
||||
/*
|
||||
* schema.c
|
||||
|
|
|
|||
|
|
@ -203,13 +203,744 @@ int slap_parse_user( struct berval *id, struct berval *user,
|
|||
return LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
static int slap_parseURI( Operation *op, struct berval *uri,
|
||||
struct berval *base, struct berval *nbase,
|
||||
int *scope, Filter **filter, struct berval *fstr )
|
||||
#ifdef SLAP_AUTHZ_SYNTAX
|
||||
int
|
||||
authzValidate(
|
||||
Syntax *syntax,
|
||||
struct berval *in )
|
||||
{
|
||||
struct berval bv;
|
||||
int rc;
|
||||
LDAPURLDesc *ludp;
|
||||
struct berval bv;
|
||||
int rc = LDAP_INVALID_SYNTAX;
|
||||
LDAPURLDesc *ludp = NULL;
|
||||
int scope = -1;
|
||||
|
||||
/*
|
||||
* 1) <DN>
|
||||
* 2) dn[.{exact|children|subtree|onelevel}]:{*|<DN>}
|
||||
* 3) dn.regex:<pattern>
|
||||
* 4) u[.mech[/realm]]:<ID>
|
||||
* 5) group[/<groupClass>[/<memberAttr>]]:<DN>
|
||||
* 6) <URL>
|
||||
*/
|
||||
|
||||
assert( in != NULL );
|
||||
assert( !BER_BVISNULL( in ) );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE,
|
||||
"authzValidate: parsing %s\n", in->bv_val, 0, 0 );
|
||||
|
||||
/*
|
||||
* 2) dn[.{exact|children|subtree|onelevel}]:{*|<DN>}
|
||||
* 3) dn.regex:<pattern>
|
||||
*
|
||||
* <DN> must pass DN normalization
|
||||
*/
|
||||
if ( !strncasecmp( in->bv_val, "dn", STRLENOF( "dn" ) ) ) {
|
||||
bv.bv_val = in->bv_val + STRLENOF( "dn" );
|
||||
|
||||
if ( bv.bv_val[ 0 ] == '.' ) {
|
||||
bv.bv_val++;
|
||||
|
||||
if ( !strncasecmp( bv.bv_val, "exact:", STRLENOF( "exact:" ) ) ) {
|
||||
bv.bv_val += STRLENOF( "exact:" );
|
||||
scope = LDAP_X_SCOPE_EXACT;
|
||||
|
||||
} else if ( !strncasecmp( bv.bv_val, "regex:", STRLENOF( "regex:" ) ) ) {
|
||||
bv.bv_val += STRLENOF( "regex:" );
|
||||
scope = LDAP_X_SCOPE_REGEX;
|
||||
|
||||
} else if ( !strncasecmp( bv.bv_val, "children:", STRLENOF( "children:" ) ) ) {
|
||||
bv.bv_val += STRLENOF( "children:" );
|
||||
scope = LDAP_X_SCOPE_CHILDREN;
|
||||
|
||||
} else if ( !strncasecmp( bv.bv_val, "subtree:", STRLENOF( "subtree:" ) ) ) {
|
||||
bv.bv_val += STRLENOF( "subtree:" );
|
||||
scope = LDAP_X_SCOPE_SUBTREE;
|
||||
|
||||
} else if ( !strncasecmp( bv.bv_val, "onelevel:", STRLENOF( "onelevel:" ) ) ) {
|
||||
bv.bv_val += STRLENOF( "onelevel:" );
|
||||
scope = LDAP_X_SCOPE_ONELEVEL;
|
||||
|
||||
} else {
|
||||
return LDAP_INVALID_SYNTAX;
|
||||
}
|
||||
|
||||
} else {
|
||||
if ( bv.bv_val[ 0 ] != ':' ) {
|
||||
return LDAP_INVALID_SYNTAX;
|
||||
}
|
||||
scope = LDAP_X_SCOPE_EXACT;
|
||||
bv.bv_val++;
|
||||
}
|
||||
|
||||
bv.bv_val += strspn( bv.bv_val, " " );
|
||||
/* jump here in case no type specification was present
|
||||
* and uri was not an URI... HEADS-UP: assuming EXACT */
|
||||
is_dn: bv.bv_len = in->bv_len - ( bv.bv_val - in->bv_val );
|
||||
|
||||
/* a single '*' means any DN without using regexes */
|
||||
if ( ber_bvccmp( &bv, '*' ) ) {
|
||||
/* LDAP_X_SCOPE_USERS */
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
switch ( scope ) {
|
||||
case LDAP_X_SCOPE_EXACT:
|
||||
case LDAP_X_SCOPE_CHILDREN:
|
||||
case LDAP_X_SCOPE_SUBTREE:
|
||||
case LDAP_X_SCOPE_ONELEVEL:
|
||||
return dnValidate( NULL, &bv );
|
||||
|
||||
case LDAP_X_SCOPE_REGEX:
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
||||
/*
|
||||
* 4) u[.mech[/realm]]:<ID>
|
||||
*/
|
||||
} else if ( ( in->bv_val[ 0 ] == 'u' || in->bv_val[ 0 ] == 'U' )
|
||||
&& ( in->bv_val[ 1 ] == ':'
|
||||
|| in->bv_val[ 1 ] == '/'
|
||||
|| in->bv_val[ 1 ] == '.' ) )
|
||||
{
|
||||
char buf[ SLAP_LDAPDN_MAXLEN ];
|
||||
struct berval id,
|
||||
user = BER_BVNULL,
|
||||
realm = BER_BVNULL,
|
||||
mech = BER_BVNULL;
|
||||
|
||||
if ( sizeof( buf ) <= in->bv_len ) {
|
||||
return LDAP_INVALID_SYNTAX;
|
||||
}
|
||||
|
||||
id.bv_len = in->bv_len;
|
||||
id.bv_val = buf;
|
||||
strncpy( buf, in->bv_val, sizeof( buf ) );
|
||||
|
||||
rc = slap_parse_user( &id, &user, &realm, &mech );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
return LDAP_INVALID_SYNTAX;
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
||||
/*
|
||||
* 5) group[/groupClass[/memberAttr]]:<DN>
|
||||
*
|
||||
* <groupClass> defaults to "groupOfNames"
|
||||
* <memberAttr> defaults to "member"
|
||||
*
|
||||
* <DN> must pass DN normalization
|
||||
*/
|
||||
} else if ( strncasecmp( in->bv_val, "group", STRLENOF( "group" ) ) == 0 )
|
||||
{
|
||||
struct berval group_dn = BER_BVNULL,
|
||||
group_oc = BER_BVNULL,
|
||||
member_at = BER_BVNULL;
|
||||
|
||||
bv.bv_val = in->bv_val + STRLENOF( "group" );
|
||||
group_dn.bv_val = strchr( bv.bv_val, ':' );
|
||||
if ( group_dn.bv_val == NULL ) {
|
||||
/* last chance: assume it's a(n exact) DN ... */
|
||||
bv.bv_val = in->bv_val;
|
||||
scope = LDAP_X_SCOPE_EXACT;
|
||||
goto is_dn;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: we assume that "member" and "groupOfNames"
|
||||
* are present in schema...
|
||||
*/
|
||||
if ( bv.bv_val[ 0 ] == '/' ) {
|
||||
group_oc.bv_val = &bv.bv_val[ 1 ];
|
||||
|
||||
member_at.bv_val = strchr( group_oc.bv_val, '/' );
|
||||
if ( member_at.bv_val ) {
|
||||
AttributeDescription *ad = NULL;
|
||||
const char *text = NULL;
|
||||
|
||||
group_oc.bv_len = member_at.bv_val - group_oc.bv_val;
|
||||
member_at.bv_val++;
|
||||
member_at.bv_len = group_dn.bv_val - member_at.bv_val;
|
||||
rc = slap_bv2ad( &member_at, &ad, &text );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
} else {
|
||||
group_oc.bv_len = group_dn.bv_val - group_oc.bv_val;
|
||||
|
||||
if ( oc_bvfind( &group_oc ) == NULL ) {
|
||||
return LDAP_INVALID_SYNTAX;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
group_dn.bv_val++;
|
||||
group_dn.bv_len = in->bv_len - ( group_dn.bv_val - in->bv_val );
|
||||
|
||||
rc = dnValidate( NULL, &group_dn );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* ldap:///<base>??<scope>?<filter>
|
||||
* <scope> ::= {base|one|subtree}
|
||||
*
|
||||
* <scope> defaults to "base"
|
||||
* <base> must pass DN normalization
|
||||
* <filter> must pass str2filter()
|
||||
*/
|
||||
rc = ldap_url_parse( in->bv_val, &ludp );
|
||||
switch ( rc ) {
|
||||
case LDAP_URL_SUCCESS:
|
||||
/* FIXME: the check is pedantic, but I think it's necessary,
|
||||
* because people tend to use things like ldaps:// which
|
||||
* gives the idea SSL is being used. Maybe we could
|
||||
* accept ldapi:// as well, but the point is that we use
|
||||
* an URL as an easy means to define bits of a search with
|
||||
* little parsing.
|
||||
*/
|
||||
if ( strcasecmp( ludp->lud_scheme, "ldap" ) != 0 ) {
|
||||
/*
|
||||
* must be ldap:///
|
||||
*/
|
||||
rc = LDAP_INVALID_SYNTAX;
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
|
||||
case LDAP_URL_ERR_BADSCHEME:
|
||||
/*
|
||||
* last chance: assume it's a(n exact) DN ...
|
||||
*
|
||||
* NOTE: must pass DN normalization
|
||||
*/
|
||||
ldap_free_urldesc( ludp );
|
||||
bv.bv_val = in->bv_val;
|
||||
scope = LDAP_X_SCOPE_EXACT;
|
||||
goto is_dn;
|
||||
|
||||
default:
|
||||
rc = LDAP_INVALID_SYNTAX;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ( ( ludp->lud_host && *ludp->lud_host )
|
||||
|| ludp->lud_attrs || ludp->lud_exts )
|
||||
{
|
||||
/* host part must be empty */
|
||||
/* attrs and extensions parts must be empty */
|
||||
rc = LDAP_INVALID_SYNTAX;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Grab the filter */
|
||||
if ( ludp->lud_filter ) {
|
||||
Filter *f = str2filter( ludp->lud_filter );
|
||||
if ( f == NULL ) {
|
||||
rc = LDAP_INVALID_SYNTAX;
|
||||
goto done;
|
||||
}
|
||||
filter_free( f );
|
||||
}
|
||||
|
||||
/* Grab the searchbase */
|
||||
assert( ludp->lud_dn );
|
||||
ber_str2bv( ludp->lud_dn, 0, 0, &bv );
|
||||
rc = dnValidate( NULL, &bv );
|
||||
|
||||
done:
|
||||
ldap_free_urldesc( ludp );
|
||||
return( rc );
|
||||
}
|
||||
|
||||
#if 0
|
||||
int
|
||||
authzMatch(
|
||||
int *matchp,
|
||||
slap_mask_t flags,
|
||||
Syntax *syntax,
|
||||
MatchingRule *mr,
|
||||
struct berval *value,
|
||||
void *assertedValue )
|
||||
{
|
||||
return octetStringMatch( matchp, flags, syntax, mr, value, assertedValue );
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
authzPrettyNormal(
|
||||
struct berval *val,
|
||||
struct berval *normalized,
|
||||
void *ctx,
|
||||
int normalize )
|
||||
{
|
||||
struct berval bv;
|
||||
int rc = LDAP_INVALID_SYNTAX;
|
||||
LDAPURLDesc *ludp = NULL;
|
||||
char *lud_dn = NULL,
|
||||
*lud_filter = NULL;
|
||||
int scope = -1;
|
||||
|
||||
/*
|
||||
* 1) <DN>
|
||||
* 2) dn[.{exact|children|subtree|onelevel}]:{*|<DN>}
|
||||
* 3) dn.regex:<pattern>
|
||||
* 4) u[.mech[/realm]]:<ID>
|
||||
* 5) group[/<groupClass>[/<memberAttr>]]:<DN>
|
||||
* 6) <URL>
|
||||
*/
|
||||
|
||||
assert( val != NULL );
|
||||
assert( !BER_BVISNULL( val ) );
|
||||
|
||||
/*
|
||||
* 2) dn[.{exact|children|subtree|onelevel}]:{*|<DN>}
|
||||
* 3) dn.regex:<pattern>
|
||||
*
|
||||
* <DN> must pass DN normalization
|
||||
*/
|
||||
if ( !strncasecmp( val->bv_val, "dn", STRLENOF( "dn" ) ) ) {
|
||||
struct berval out = BER_BVNULL,
|
||||
prefix = BER_BVNULL;
|
||||
char *ptr;
|
||||
|
||||
bv.bv_val = val->bv_val + STRLENOF( "dn" );
|
||||
|
||||
if ( bv.bv_val[ 0 ] == '.' ) {
|
||||
bv.bv_val++;
|
||||
|
||||
if ( !strncasecmp( bv.bv_val, "exact:", STRLENOF( "exact:" ) ) ) {
|
||||
bv.bv_val += STRLENOF( "exact:" );
|
||||
scope = LDAP_X_SCOPE_EXACT;
|
||||
|
||||
} else if ( !strncasecmp( bv.bv_val, "regex:", STRLENOF( "regex:" ) ) ) {
|
||||
bv.bv_val += STRLENOF( "regex:" );
|
||||
scope = LDAP_X_SCOPE_REGEX;
|
||||
|
||||
} else if ( !strncasecmp( bv.bv_val, "children:", STRLENOF( "children:" ) ) ) {
|
||||
bv.bv_val += STRLENOF( "children:" );
|
||||
scope = LDAP_X_SCOPE_CHILDREN;
|
||||
|
||||
} else if ( !strncasecmp( bv.bv_val, "subtree:", STRLENOF( "subtree:" ) ) ) {
|
||||
bv.bv_val += STRLENOF( "subtree:" );
|
||||
scope = LDAP_X_SCOPE_SUBTREE;
|
||||
|
||||
} else if ( !strncasecmp( bv.bv_val, "onelevel:", STRLENOF( "onelevel:" ) ) ) {
|
||||
bv.bv_val += STRLENOF( "onelevel:" );
|
||||
scope = LDAP_X_SCOPE_ONELEVEL;
|
||||
|
||||
} else {
|
||||
return LDAP_INVALID_SYNTAX;
|
||||
}
|
||||
|
||||
} else {
|
||||
if ( bv.bv_val[ 0 ] != ':' ) {
|
||||
return LDAP_INVALID_SYNTAX;
|
||||
}
|
||||
scope = LDAP_X_SCOPE_EXACT;
|
||||
bv.bv_val++;
|
||||
}
|
||||
|
||||
bv.bv_val += strspn( bv.bv_val, " " );
|
||||
/* jump here in case no type specification was present
|
||||
* and uri was not an URI... HEADS-UP: assuming EXACT */
|
||||
is_dn: bv.bv_len = val->bv_len - ( bv.bv_val - val->bv_val );
|
||||
|
||||
/* a single '*' means any DN without using regexes */
|
||||
if ( ber_bvccmp( &bv, '*' ) ) {
|
||||
ber_str2bv_x( "dn:*", STRLENOF( "dn:*" ), 1, normalized, ctx );
|
||||
return LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
switch ( scope ) {
|
||||
case LDAP_X_SCOPE_EXACT:
|
||||
case LDAP_X_SCOPE_CHILDREN:
|
||||
case LDAP_X_SCOPE_SUBTREE:
|
||||
case LDAP_X_SCOPE_ONELEVEL:
|
||||
if ( normalize ) {
|
||||
rc = dnNormalize( 0, NULL, NULL, &bv, &out, ctx );
|
||||
} else {
|
||||
rc = dnPretty( NULL, &bv, &out, ctx );
|
||||
}
|
||||
if( rc != LDAP_SUCCESS ) {
|
||||
return LDAP_INVALID_SYNTAX;
|
||||
}
|
||||
break;
|
||||
|
||||
case LDAP_X_SCOPE_REGEX:
|
||||
normalized->bv_len = STRLENOF( "dn.regex:" ) + bv.bv_len;
|
||||
normalized->bv_val = ber_memalloc_x( normalized->bv_len + 1, ctx );
|
||||
ptr = lutil_strcopy( normalized->bv_val, "dn.regex:" );
|
||||
ptr = lutil_strncopy( ptr, bv.bv_val, bv.bv_len );
|
||||
ptr[ 0 ] = '\0';
|
||||
return LDAP_SUCCESS;
|
||||
|
||||
default:
|
||||
return LDAP_INVALID_SYNTAX;
|
||||
}
|
||||
|
||||
/* prepare prefix */
|
||||
switch ( scope ) {
|
||||
case LDAP_X_SCOPE_EXACT:
|
||||
BER_BVSTR( &prefix, "dn:" );
|
||||
break;
|
||||
|
||||
case LDAP_X_SCOPE_CHILDREN:
|
||||
BER_BVSTR( &prefix, "dn.children:" );
|
||||
break;
|
||||
|
||||
case LDAP_X_SCOPE_SUBTREE:
|
||||
BER_BVSTR( &prefix, "dn.subtree:" );
|
||||
break;
|
||||
|
||||
case LDAP_X_SCOPE_ONELEVEL:
|
||||
BER_BVSTR( &prefix, "dn.onelevel:" );
|
||||
break;
|
||||
|
||||
default:
|
||||
assert( 0 );
|
||||
break;
|
||||
}
|
||||
|
||||
normalized->bv_len = prefix.bv_len + out.bv_len;
|
||||
normalized->bv_val = ber_memalloc_x( normalized->bv_len + 1, ctx );
|
||||
|
||||
ptr = lutil_strcopy( normalized->bv_val, prefix.bv_val );
|
||||
ptr = lutil_strncopy( ptr, out.bv_val, out.bv_len );
|
||||
ptr[ 0 ] = '\0';
|
||||
ber_memfree_x( out.bv_val, ctx );
|
||||
|
||||
return LDAP_SUCCESS;
|
||||
|
||||
/*
|
||||
* 4) u[.mech[/realm]]:<ID>
|
||||
*/
|
||||
} else if ( ( val->bv_val[ 0 ] == 'u' || val->bv_val[ 0 ] == 'U' )
|
||||
&& ( val->bv_val[ 1 ] == ':'
|
||||
|| val->bv_val[ 1 ] == '/'
|
||||
|| val->bv_val[ 1 ] == '.' ) )
|
||||
{
|
||||
char buf[ SLAP_LDAPDN_MAXLEN ];
|
||||
struct berval id,
|
||||
user = BER_BVNULL,
|
||||
realm = BER_BVNULL,
|
||||
mech = BER_BVNULL;
|
||||
|
||||
if ( sizeof( buf ) <= val->bv_len ) {
|
||||
return LDAP_INVALID_SYNTAX;
|
||||
}
|
||||
|
||||
id.bv_len = val->bv_len;
|
||||
id.bv_val = buf;
|
||||
strncpy( buf, val->bv_val, sizeof( buf ) );
|
||||
|
||||
rc = slap_parse_user( &id, &user, &realm, &mech );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
return LDAP_INVALID_SYNTAX;
|
||||
}
|
||||
|
||||
ber_dupbv_x( normalized, val, ctx );
|
||||
|
||||
return rc;
|
||||
|
||||
/*
|
||||
* 5) group[/groupClass[/memberAttr]]:<DN>
|
||||
*
|
||||
* <groupClass> defaults to "groupOfNames"
|
||||
* <memberAttr> defaults to "member"
|
||||
*
|
||||
* <DN> must pass DN normalization
|
||||
*/
|
||||
} else if ( strncasecmp( val->bv_val, "group", STRLENOF( "group" ) ) == 0 )
|
||||
{
|
||||
struct berval group_dn = BER_BVNULL,
|
||||
group_oc = BER_BVNULL,
|
||||
member_at = BER_BVNULL,
|
||||
out = BER_BVNULL;
|
||||
char *ptr;
|
||||
|
||||
bv.bv_val = val->bv_val + STRLENOF( "group" );
|
||||
group_dn.bv_val = strchr( bv.bv_val, ':' );
|
||||
if ( group_dn.bv_val == NULL ) {
|
||||
/* last chance: assume it's a(n exact) DN ... */
|
||||
bv.bv_val = val->bv_val;
|
||||
scope = LDAP_X_SCOPE_EXACT;
|
||||
goto is_dn;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: we assume that "member" and "groupOfNames"
|
||||
* are present in schema...
|
||||
*/
|
||||
if ( bv.bv_val[ 0 ] == '/' ) {
|
||||
group_oc.bv_val = &bv.bv_val[ 1 ];
|
||||
|
||||
member_at.bv_val = strchr( group_oc.bv_val, '/' );
|
||||
if ( member_at.bv_val ) {
|
||||
AttributeDescription *ad = NULL;
|
||||
const char *text = NULL;
|
||||
|
||||
group_oc.bv_len = member_at.bv_val - group_oc.bv_val;
|
||||
member_at.bv_val++;
|
||||
member_at.bv_len = group_dn.bv_val - member_at.bv_val;
|
||||
rc = slap_bv2ad( &member_at, &ad, &text );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
member_at = ad->ad_cname;
|
||||
|
||||
} else {
|
||||
ObjectClass *oc = NULL;
|
||||
|
||||
group_oc.bv_len = group_dn.bv_val - group_oc.bv_val;
|
||||
|
||||
oc = oc_bvfind( &group_oc );
|
||||
if ( oc == NULL ) {
|
||||
return LDAP_INVALID_SYNTAX;
|
||||
}
|
||||
|
||||
group_oc = oc->soc_cname;
|
||||
}
|
||||
}
|
||||
|
||||
group_dn.bv_val++;
|
||||
group_dn.bv_len = val->bv_len - ( group_dn.bv_val - val->bv_val );
|
||||
|
||||
if ( normalize ) {
|
||||
rc = dnNormalize( 0, NULL, NULL, &group_dn, &out, ctx );
|
||||
} else {
|
||||
rc = dnPretty( NULL, &group_dn, &out, ctx );
|
||||
}
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
normalized->bv_len = STRLENOF( "group" ":" ) + out.bv_len;
|
||||
if ( !BER_BVISNULL( &group_oc ) ) {
|
||||
normalized->bv_len += STRLENOF( "/" ) + group_oc.bv_len;
|
||||
if ( !BER_BVISNULL( &member_at ) ) {
|
||||
normalized->bv_len += STRLENOF( "/" ) + member_at.bv_len;
|
||||
}
|
||||
}
|
||||
|
||||
normalized->bv_val = ber_memalloc_x( normalized->bv_len + 1, ctx );
|
||||
ptr = lutil_strcopy( normalized->bv_val, "group" );
|
||||
if ( !BER_BVISNULL( &group_oc ) ) {
|
||||
ptr[ 0 ] = '/';
|
||||
ptr++;
|
||||
ptr = lutil_strncopy( ptr, group_oc.bv_val, group_oc.bv_len );
|
||||
if ( !BER_BVISNULL( &member_at ) ) {
|
||||
ptr[ 0 ] = '/';
|
||||
ptr++;
|
||||
ptr = lutil_strncopy( ptr, member_at.bv_val, member_at.bv_len );
|
||||
}
|
||||
}
|
||||
ptr[ 0 ] = ':';
|
||||
ptr++;
|
||||
ptr = lutil_strncopy( ptr, out.bv_val, out.bv_len );
|
||||
ptr[ 0 ] = '\0';
|
||||
ber_memfree_x( out.bv_val, ctx );
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* ldap:///<base>??<scope>?<filter>
|
||||
* <scope> ::= {base|one|subtree}
|
||||
*
|
||||
* <scope> defaults to "base"
|
||||
* <base> must pass DN normalization
|
||||
* <filter> must pass str2filter()
|
||||
*/
|
||||
rc = ldap_url_parse( val->bv_val, &ludp );
|
||||
switch ( rc ) {
|
||||
case LDAP_URL_SUCCESS:
|
||||
/* FIXME: the check is pedantic, but I think it's necessary,
|
||||
* because people tend to use things like ldaps:// which
|
||||
* gives the idea SSL is being used. Maybe we could
|
||||
* accept ldapi:// as well, but the point is that we use
|
||||
* an URL as an easy means to define bits of a search with
|
||||
* little parsing.
|
||||
*/
|
||||
if ( strcasecmp( ludp->lud_scheme, "ldap" ) != 0 ) {
|
||||
/*
|
||||
* must be ldap:///
|
||||
*/
|
||||
rc = LDAP_INVALID_SYNTAX;
|
||||
goto done;
|
||||
}
|
||||
|
||||
AC_MEMCPY( ludp->lud_scheme, "ldap", STRLENOF( "ldap" ) );
|
||||
break;
|
||||
|
||||
case LDAP_URL_ERR_BADSCHEME:
|
||||
/*
|
||||
* last chance: assume it's a(n exact) DN ...
|
||||
*
|
||||
* NOTE: must pass DN normalization
|
||||
*/
|
||||
ldap_free_urldesc( ludp );
|
||||
bv.bv_val = val->bv_val;
|
||||
scope = LDAP_X_SCOPE_EXACT;
|
||||
goto is_dn;
|
||||
|
||||
default:
|
||||
rc = LDAP_INVALID_SYNTAX;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ( ( ludp->lud_host && *ludp->lud_host )
|
||||
|| ludp->lud_attrs || ludp->lud_exts )
|
||||
{
|
||||
/* host part must be empty */
|
||||
/* attrs and extensions parts must be empty */
|
||||
rc = LDAP_INVALID_SYNTAX;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Grab the filter */
|
||||
if ( ludp->lud_filter ) {
|
||||
struct berval filterstr;
|
||||
Filter *f;
|
||||
|
||||
lud_filter = ludp->lud_filter;
|
||||
|
||||
f = str2filter( lud_filter );
|
||||
if ( f == NULL ) {
|
||||
rc = LDAP_INVALID_SYNTAX;
|
||||
goto done;
|
||||
}
|
||||
filter2bv( f, &filterstr );
|
||||
filter_free( f );
|
||||
if ( BER_BVISNULL( &filterstr ) ) {
|
||||
rc = LDAP_INVALID_SYNTAX;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ludp->lud_filter = filterstr.bv_val;
|
||||
}
|
||||
|
||||
/* Grab the searchbase */
|
||||
assert( ludp->lud_dn );
|
||||
if ( ludp->lud_dn ) {
|
||||
struct berval out = BER_BVNULL;
|
||||
|
||||
lud_dn = ludp->lud_dn;
|
||||
|
||||
ber_str2bv( lud_dn, 0, 0, &bv );
|
||||
if ( normalize ) {
|
||||
rc = dnNormalize( 0, NULL, NULL, &bv, &out, ctx );
|
||||
} else {
|
||||
rc = dnPretty( NULL, &bv, &out, ctx );
|
||||
}
|
||||
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
ludp->lud_dn = out.bv_val;
|
||||
}
|
||||
|
||||
ludp->lud_port = 0;
|
||||
normalized->bv_val = ldap_url_desc2str( ludp );
|
||||
if ( normalized->bv_val ) {
|
||||
normalized->bv_len = strlen( normalized->bv_val );
|
||||
|
||||
} else {
|
||||
rc = LDAP_INVALID_SYNTAX;
|
||||
}
|
||||
|
||||
done:
|
||||
if ( lud_filter ) {
|
||||
if ( ludp->lud_filter != lud_filter ) {
|
||||
ber_memfree( ludp->lud_filter );
|
||||
}
|
||||
ludp->lud_filter = lud_filter;
|
||||
}
|
||||
|
||||
if ( lud_dn ) {
|
||||
if ( ludp->lud_dn != lud_dn ) {
|
||||
ber_memfree( ludp->lud_dn );
|
||||
}
|
||||
ludp->lud_dn = lud_dn;
|
||||
}
|
||||
|
||||
ldap_free_urldesc( ludp );
|
||||
|
||||
return( rc );
|
||||
}
|
||||
|
||||
int
|
||||
authzNormalize(
|
||||
slap_mask_t usage,
|
||||
Syntax *syntax,
|
||||
MatchingRule *mr,
|
||||
struct berval *val,
|
||||
struct berval *normalized,
|
||||
void *ctx )
|
||||
{
|
||||
int rc;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, ">>> authzNormalize: <%s>\n",
|
||||
val->bv_val, 0, 0 );
|
||||
|
||||
rc = authzPrettyNormal( val, normalized, ctx, 1 );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<<< authzNormalize: <%s> (%d)\n",
|
||||
normalized->bv_val, rc, 0 );
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
authzPretty(
|
||||
Syntax *syntax,
|
||||
struct berval *val,
|
||||
struct berval *out,
|
||||
void *ctx)
|
||||
{
|
||||
int rc;
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, ">>> authzPretty: <%s>\n",
|
||||
val->bv_val, 0, 0 );
|
||||
|
||||
rc = authzPrettyNormal( val, out, ctx, 0 );
|
||||
|
||||
Debug( LDAP_DEBUG_TRACE, "<<< authzPretty: <%s> (%d)\n",
|
||||
out->bv_val, rc, 0 );
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
#endif /* SLAP_AUTHZ_SYNTAX */
|
||||
|
||||
static int
|
||||
slap_parseURI(
|
||||
Operation *op,
|
||||
struct berval *uri,
|
||||
struct berval *base,
|
||||
struct berval *nbase,
|
||||
int *scope,
|
||||
Filter **filter,
|
||||
struct berval *fstr,
|
||||
int normalize )
|
||||
{
|
||||
struct berval bv;
|
||||
int rc;
|
||||
LDAPURLDesc *ludp;
|
||||
|
||||
#ifdef SLAP_ORDERED_PRETTYNORM
|
||||
struct berval idx;
|
||||
#endif /* SLAP_ORDERED_PRETTYNORM */
|
||||
|
||||
assert( uri != NULL && !BER_BVISNULL( uri ) );
|
||||
BER_BVZERO( base );
|
||||
|
|
@ -223,6 +954,21 @@ static int slap_parseURI( Operation *op, struct berval *uri,
|
|||
|
||||
rc = LDAP_PROTOCOL_ERROR;
|
||||
|
||||
#ifdef SLAP_ORDERED_PRETTYNORM
|
||||
idx = *uri;
|
||||
if ( idx.bv_val[ 0 ] == '{' ) {
|
||||
char *ptr;
|
||||
|
||||
ptr = strchr( idx.bv_val, '}' ) + 1;
|
||||
|
||||
assert( ptr != (void *)1 );
|
||||
|
||||
idx.bv_len -= ptr - idx.bv_val;
|
||||
idx.bv_val = ptr;
|
||||
uri = &idx;
|
||||
}
|
||||
#endif /* SLAP_ORDERED_PRETTYNORM */
|
||||
|
||||
/*
|
||||
* dn[.<dnstyle>]:<dnpattern>
|
||||
* <dnstyle> ::= {exact|regex|children|subtree|onelevel}
|
||||
|
|
@ -283,9 +1029,14 @@ is_dn: bv.bv_len = uri->bv_len - (bv.bv_val - uri->bv_val);
|
|||
case LDAP_X_SCOPE_CHILDREN:
|
||||
case LDAP_X_SCOPE_SUBTREE:
|
||||
case LDAP_X_SCOPE_ONELEVEL:
|
||||
rc = dnNormalize( 0, NULL, NULL, &bv, nbase, op->o_tmpmemctx );
|
||||
if( rc != LDAP_SUCCESS ) {
|
||||
*scope = -1;
|
||||
if ( normalize ) {
|
||||
rc = dnNormalize( 0, NULL, NULL, &bv, nbase, op->o_tmpmemctx );
|
||||
if( rc != LDAP_SUCCESS ) {
|
||||
*scope = -1;
|
||||
}
|
||||
} else {
|
||||
ber_dupbv_x( nbase, &bv, op->o_tmpmemctx );
|
||||
rc = LDAP_SUCCESS;
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -390,10 +1141,15 @@ is_dn: bv.bv_len = uri->bv_len - (bv.bv_val - uri->bv_val);
|
|||
group_dn.bv_val++;
|
||||
group_dn.bv_len = uri->bv_len - ( group_dn.bv_val - uri->bv_val );
|
||||
|
||||
rc = dnNormalize( 0, NULL, NULL, &group_dn, nbase, op->o_tmpmemctx );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
*scope = -1;
|
||||
return rc;
|
||||
if ( normalize ) {
|
||||
rc = dnNormalize( 0, NULL, NULL, &group_dn, nbase, op->o_tmpmemctx );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
*scope = -1;
|
||||
return rc;
|
||||
}
|
||||
} else {
|
||||
ber_dupbv_x( nbase, &group_dn, op->o_tmpmemctx );
|
||||
rc = LDAP_SUCCESS;
|
||||
}
|
||||
*scope = LDAP_X_SCOPE_GROUP;
|
||||
|
||||
|
|
@ -481,7 +1237,12 @@ is_dn: bv.bv_len = uri->bv_len - (bv.bv_val - uri->bv_val);
|
|||
|
||||
/* Grab the searchbase */
|
||||
ber_str2bv( ludp->lud_dn, 0, 0, base );
|
||||
rc = dnNormalize( 0, NULL, NULL, base, nbase, op->o_tmpmemctx );
|
||||
if ( normalize ) {
|
||||
rc = dnNormalize( 0, NULL, NULL, base, nbase, op->o_tmpmemctx );
|
||||
} else {
|
||||
ber_dupbv_x( nbase, base, op->o_tmpmemctx );
|
||||
rc = LDAP_SUCCESS;
|
||||
}
|
||||
|
||||
done:
|
||||
if( rc != LDAP_SUCCESS ) {
|
||||
|
|
@ -909,9 +1670,16 @@ slap_sasl_match( Operation *opx, struct berval *rule,
|
|||
"===>slap_sasl_match: comparing DN %s to rule %s\n",
|
||||
assertDN->bv_val, rule->bv_val, 0 );
|
||||
|
||||
rc = slap_parseURI( opx, rule, &base,
|
||||
&op.o_req_ndn, &op.ors_scope, &op.ors_filter,
|
||||
&op.ors_filterstr );
|
||||
/* NOTE: don't normalize rule if authz syntax is enabled */
|
||||
rc = slap_parseURI( opx, rule, &base, &op.o_req_ndn,
|
||||
&op.ors_scope, &op.ors_filter, &op.ors_filterstr,
|
||||
#ifdef SLAP_AUTHZ_SYNTAX
|
||||
0
|
||||
#else /* ! SLAP_AUTHZ_SYNTAX */
|
||||
1
|
||||
#endif /* ! SLAP_AUTHZ_SYNTAX */
|
||||
);
|
||||
|
||||
if( rc != LDAP_SUCCESS ) goto CONCLUDED;
|
||||
|
||||
switch ( op.ors_scope ) {
|
||||
|
|
@ -1166,9 +1934,10 @@ slap_sasl2dn(
|
|||
goto FINISHED;
|
||||
}
|
||||
|
||||
rc = slap_parseURI( opx, ®out, &base,
|
||||
&op.o_req_ndn, &op.ors_scope, &op.ors_filter,
|
||||
&op.ors_filterstr );
|
||||
/* NOTE: always normalize regout because it results
|
||||
* from string submatch expansion */
|
||||
rc = slap_parseURI( opx, ®out, &base, &op.o_req_ndn,
|
||||
&op.ors_scope, &op.ors_filter, &op.ors_filterstr, 1 );
|
||||
if ( !BER_BVISNULL( ®out ) ) slap_sl_free( regout.bv_val, opx->o_tmpmemctx );
|
||||
if ( rc != LDAP_SUCCESS ) {
|
||||
goto FINISHED;
|
||||
|
|
|
|||
|
|
@ -69,6 +69,11 @@
|
|||
#define csnIndexer generalizedTimeIndexer
|
||||
#define csnFilter generalizedTimeFilter
|
||||
|
||||
#ifdef SLAP_AUTHZ_SYNTAX
|
||||
/* FIXME: temporary */
|
||||
#define authzMatch octetStringMatch
|
||||
#endif /* SLAP_AUTHZ_SYNTAX */
|
||||
|
||||
unsigned int index_substr_if_minlen = SLAP_INDEX_SUBSTR_IF_MINLEN_DEFAULT;
|
||||
unsigned int index_substr_if_maxlen = SLAP_INDEX_SUBSTR_IF_MAXLEN_DEFAULT;
|
||||
unsigned int index_substr_any_len = SLAP_INDEX_SUBSTR_ANY_LEN_DEFAULT;
|
||||
|
|
@ -3441,6 +3446,13 @@ static slap_syntax_defs_rec syntax_defs[] = {
|
|||
/* OpenLDAP Void Syntax */
|
||||
{"( 1.3.6.1.4.1.4203.1.1.1 DESC 'OpenLDAP void' )" ,
|
||||
SLAP_SYNTAX_HIDE, inValidate, NULL},
|
||||
|
||||
#ifdef SLAP_AUTHZ_SYNTAX
|
||||
/* FIXME: OID is unused, but not registered yet */
|
||||
{"( 1.3.6.1.4.1.4203.666.2.7 DESC 'OpenLDAP authz' )",
|
||||
SLAP_SYNTAX_HIDE, authzValidate, authzPretty},
|
||||
#endif /* SLAP_AUTHZ_SYNTAX */
|
||||
|
||||
{NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
|
|
@ -3886,6 +3898,16 @@ static slap_mrule_defs_rec mrule_defs[] = {
|
|||
NULL, NULL,
|
||||
"CSNMatch" },
|
||||
|
||||
#ifdef SLAP_AUTHZ_SYNTAX
|
||||
/* FIXME: OID is unused, but not registered yet */
|
||||
{"( 1.3.6.1.4.1.4203.666.4.12 NAME 'authzMatch' "
|
||||
"SYNTAX 1.3.6.1.4.1.4203.666.2.7 )",
|
||||
SLAP_MR_HIDE | SLAP_MR_EQUALITY, NULL,
|
||||
NULL, authzNormalize, authzMatch,
|
||||
NULL, NULL,
|
||||
NULL},
|
||||
#endif /* SLAP_AUTHZ_SYNTAX */
|
||||
|
||||
{NULL, SLAP_MR_NONE, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL,
|
||||
NULL }
|
||||
|
|
|
|||
|
|
@ -854,8 +854,16 @@ static struct slap_schema_ad_map {
|
|||
{ "authzTo", "( 1.3.6.1.4.1.4203.666.1.8 "
|
||||
"NAME ( 'authzTo' 'saslAuthzTo' ) "
|
||||
"DESC 'proxy authorization targets' "
|
||||
#ifdef SLAP_AUTHZ_SYNTAX
|
||||
"EQUALITY authzMatch "
|
||||
"SYNTAX 1.3.6.1.4.1.4203.666.2.7 "
|
||||
#else /* ! SLAP_AUTHZ_SYNTAX */
|
||||
"EQUALITY caseExactMatch "
|
||||
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 "
|
||||
#endif /* ! SLAP_AUTHZ_SYNTAX */
|
||||
#ifdef SLAP_ORDERED_PRETTYNORM
|
||||
"X-ORDERED 'VALUES' "
|
||||
#endif /* SLAP_ORDERED_PRETTYNORM */
|
||||
"USAGE distributedOperation )",
|
||||
NULL, SLAP_AT_HIDE,
|
||||
NULL, NULL,
|
||||
|
|
@ -864,8 +872,16 @@ static struct slap_schema_ad_map {
|
|||
{ "authzFrom", "( 1.3.6.1.4.1.4203.666.1.9 "
|
||||
"NAME ( 'authzFrom' 'saslAuthzFrom' ) "
|
||||
"DESC 'proxy authorization sources' "
|
||||
#ifdef SLAP_AUTHZ_SYNTAX
|
||||
"EQUALITY authzMatch "
|
||||
"SYNTAX 1.3.6.1.4.1.4203.666.2.7 "
|
||||
#else /* ! SLAP_AUTHZ_SYNTAX */
|
||||
"EQUALITY caseExactMatch "
|
||||
"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 "
|
||||
#endif /* ! SLAP_AUTHZ_SYNTAX */
|
||||
#ifdef SLAP_ORDERED_PRETTYNORM
|
||||
"X-ORDERED 'VALUES' "
|
||||
#endif /* SLAP_ORDERED_PRETTYNORM */
|
||||
"USAGE distributedOperation )",
|
||||
NULL, SLAP_AT_HIDE,
|
||||
NULL, NULL,
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ LDAP_BEGIN_DECL
|
|||
#define SLAPD_CONF_UNKNOWN_BAILOUT
|
||||
|
||||
#define SLAP_ORDERED_PRETTYNORM
|
||||
#define SLAP_AUTHZ_SYNTAX
|
||||
|
||||
#ifdef ENABLE_REWRITE
|
||||
#define SLAP_AUTH_REWRITE 1 /* use librewrite for sasl-regexp */
|
||||
|
|
|
|||
Loading…
Reference in a new issue