version 1.88, 2003/05/25 01:56:58
|
version 1.88.2.17, 2004/06/16 18:19:56
|
Line 1
|
Line 1
|
/* $OpenLDAP$ */ |
/* $OpenLDAP: pkg/ldap/servers/slapd/saslauthz.c,v 1.88.2.16 2004/06/04 03:39:43 kurt Exp $ */ |
/* |
/* This work is part of OpenLDAP Software <http://www.openldap.org/>. |
* Copyright 1998-2003 The OpenLDAP Foundation, All Rights Reserved. |
|
* COPYING RESTRICTIONS APPLY, see COPYRIGHT file |
|
*/ |
|
/* |
|
* Copyright (c) 2000, Mark Adamson, Carnegie Mellon. All rights reserved. |
|
* This software is not subject to any license of Carnegie Mellon University. |
|
* |
* |
* Redistribution and use in source and binary forms are permitted without |
* Copyright 1998-2004 The OpenLDAP Foundation. |
* restriction or fee of any kind as long as this notice is preserved. |
* Portions Copyright 2000 Mark Adamson, Carnegie Mellon. |
|
* All rights reserved. |
* |
* |
* The name "Carnegie Mellon" must not be used to endorse or promote |
* Redistribution and use in source and binary forms, with or without |
* products derived from this software without prior written permission. |
* 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>. |
*/ |
*/ |
|
|
#include "portable.h" |
#include "portable.h" |
Line 30
|
Line 29
|
|
|
#define SASLREGEX_REPLACE 10 |
#define SASLREGEX_REPLACE 10 |
|
|
|
#define LDAP_X_SCOPE_EXACT ((ber_int_t) 0x0010) |
|
#define LDAP_X_SCOPE_REGEX ((ber_int_t) 0x0020) |
|
#define LDAP_X_SCOPE_CHILDREN ((ber_int_t) 0x0030) |
|
#define LDAP_X_SCOPE_SUBTREE ((ber_int_t) 0x0040) |
|
#define LDAP_X_SCOPE_ONELEVEL ((ber_int_t) 0x0050) |
|
|
|
/* |
|
* IDs in DNauthzid form can now have a type specifier, that |
|
* influences how they are used in related operations. |
|
* |
|
* syntax: dn[.{exact|regex}]:<val> |
|
* |
|
* dn.exact: the value must pass normalization and is used |
|
* in exact DN match. |
|
* dn.regex: the value is treated as a regular expression |
|
* in matching DN values in saslAuthz{To|From} |
|
* attributes. |
|
* dn: for backwards compatibility reasons, the value |
|
* is treated as a regular expression, and thus |
|
* it is not normalized nor validated; it is used |
|
* in exact or regex comparisons based on the |
|
* context. |
|
* |
|
* IDs in DNauthzid form can now have a type specifier, that |
|
* influences how they are used in related operations. |
|
* |
|
* syntax: u[.mech[/realm]]:<val> |
|
* |
|
* where mech is a SIMPLE, AUTHZ, or a SASL mechanism name |
|
* and realm is mechanism specific realm (separate to those |
|
* which are representable as part of the principal). |
|
*/ |
|
|
typedef struct sasl_regexp { |
typedef struct sasl_regexp { |
char *sr_match; /* regexp match pattern */ |
char *sr_match; /* regexp match pattern */ |
char *sr_replace; /* regexp replace pattern */ |
char *sr_replace; /* regexp replace pattern */ |
regex_t sr_workspace; /* workspace for regexp engine */ |
regex_t sr_workspace; /* workspace for regexp engine */ |
int sr_offset[SASLREGEX_REPLACE+2]; /* offsets of $1,$2... in *replace */ |
int sr_offset[SASLREGEX_REPLACE+2]; /* offsets of $1,$2... in *replace */ |
} SaslRegexp_t; |
} SaslRegexp_t; |
|
|
static int nSaslRegexp = 0; |
static int nSaslRegexp = 0; |
static SaslRegexp_t *SaslRegexp = NULL; |
static SaslRegexp_t *SaslRegexp = NULL; |
|
|
/* What SASL proxy authorization policies are allowed? */ |
/* What SASL proxy authorization policies are allowed? */ |
#define SASL_AUTHZ_NONE 0 |
#define SASL_AUTHZ_NONE 0x00 |
#define SASL_AUTHZ_FROM 1 |
#define SASL_AUTHZ_FROM 0x01 |
#define SASL_AUTHZ_TO 2 |
#define SASL_AUTHZ_TO 0x02 |
|
#define SASL_AUTHZ_AND 0x10 |
|
|
static int authz_policy = SASL_AUTHZ_NONE; |
static int authz_policy = SASL_AUTHZ_NONE; |
|
|
Line 57 int slap_sasl_setpolicy( const char *arg
|
Line 90 int slap_sasl_setpolicy( const char *arg
|
authz_policy = SASL_AUTHZ_FROM; |
authz_policy = SASL_AUTHZ_FROM; |
} else if ( strcasecmp( arg, "to" ) == 0 ) { |
} else if ( strcasecmp( arg, "to" ) == 0 ) { |
authz_policy = SASL_AUTHZ_TO; |
authz_policy = SASL_AUTHZ_TO; |
} else if ( strcasecmp( arg, "both" ) == 0 ) { |
} else if ( strcasecmp( arg, "both" ) == 0 || strcasecmp( arg, "any" ) == 0 ) { |
authz_policy = SASL_AUTHZ_FROM | SASL_AUTHZ_TO; |
authz_policy = SASL_AUTHZ_FROM | SASL_AUTHZ_TO; |
|
} else if ( strcasecmp( arg, "all" ) == 0 ) { |
|
authz_policy = SASL_AUTHZ_FROM | SASL_AUTHZ_TO | SASL_AUTHZ_AND; |
} else { |
} else { |
rc = LDAP_OTHER; |
rc = LDAP_OTHER; |
} |
} |
return rc; |
return rc; |
} |
} |
|
|
/* URI format: ldap://<host>/<base>[?[<attrs>][?[<scope>][?[<filter>]]]] */ |
int slap_parse_user( struct berval *id, struct berval *user, |
|
struct berval *realm, struct berval *mech ) |
|
{ |
|
char u; |
|
|
|
assert( id ); |
|
assert( id->bv_val ); |
|
assert( user ); |
|
assert( realm ); |
|
assert( mech ); |
|
|
|
u = id->bv_val[ 0 ]; |
|
|
|
if ( u != 'u' && u != 'U' ) { |
|
/* called with something other than u: */ |
|
return LDAP_PROTOCOL_ERROR; |
|
} |
|
|
|
/* uauthzid form: |
|
* u[.mech[/realm]]:user |
|
*/ |
|
|
|
user->bv_val = strchr( id->bv_val, ':' ); |
|
if ( user->bv_val == NULL ) { |
|
return LDAP_PROTOCOL_ERROR; |
|
} |
|
user->bv_val[ 0 ] = '\0'; |
|
user->bv_val++; |
|
user->bv_len = id->bv_len - ( user->bv_val - id->bv_val ); |
|
|
|
mech->bv_val = strchr( id->bv_val, '.' ); |
|
if ( mech->bv_val != NULL ) { |
|
mech->bv_val[ 0 ] = '\0'; |
|
mech->bv_val++; |
|
|
|
realm->bv_val = strchr( mech->bv_val, '/' ); |
|
|
|
if ( realm->bv_val ) { |
|
realm->bv_val[ 0 ] = '\0'; |
|
realm->bv_val++; |
|
mech->bv_len = realm->bv_val - mech->bv_val - 1; |
|
realm->bv_len = user->bv_val - realm->bv_val - 1; |
|
} else { |
|
mech->bv_len = user->bv_val - mech->bv_val - 1; |
|
} |
|
|
|
} else { |
|
realm->bv_val = NULL; |
|
} |
|
|
|
if ( id->bv_val[ 1 ] != '\0' ) { |
|
return LDAP_PROTOCOL_ERROR; |
|
} |
|
|
|
if ( mech->bv_val != NULL ) { |
|
assert( mech->bv_val == id->bv_val + 2 ); |
|
|
|
AC_MEMCPY( mech->bv_val - 2, mech->bv_val, mech->bv_len + 1 ); |
|
mech->bv_val -= 2; |
|
} |
|
|
|
if ( realm->bv_val ) { |
|
assert( realm->bv_val >= id->bv_val + 2 ); |
|
|
|
AC_MEMCPY( realm->bv_val - 2, realm->bv_val, realm->bv_len + 1 ); |
|
realm->bv_val -= 2; |
|
} |
|
|
|
/* leave "u:" before user */ |
|
user->bv_val -= 2; |
|
user->bv_len += 2; |
|
user->bv_val[ 0 ] = u; |
|
user->bv_val[ 1 ] = ':'; |
|
|
|
return LDAP_SUCCESS; |
|
} |
|
|
static int slap_parseURI( Operation *op, struct berval *uri, |
static int slap_parseURI( Operation *op, struct berval *uri, |
struct berval *searchbase, int *scope, Filter **filter ) |
struct berval *base, struct berval *nbase, |
|
int *scope, Filter **filter, struct berval *fstr ) |
{ |
{ |
struct berval bv; |
struct berval bv; |
int rc; |
int rc; |
LDAPURLDesc *ludp; |
LDAPURLDesc *ludp; |
|
|
assert( uri != NULL && uri->bv_val != NULL ); |
assert( uri != NULL && uri->bv_val != NULL ); |
searchbase->bv_val = NULL; |
base->bv_val = NULL; |
searchbase->bv_len = 0; |
base->bv_len = 0; |
|
nbase->bv_val = NULL; |
|
nbase->bv_len = 0; |
|
fstr->bv_val = NULL; |
|
fstr->bv_len = 0; |
*scope = -1; |
*scope = -1; |
*filter = NULL; |
*filter = NULL; |
|
|
Line 84 static int slap_parseURI( Operation *op,
|
Line 199 static int slap_parseURI( Operation *op,
|
LDAP_LOG( TRANSPORT, ENTRY, |
LDAP_LOG( TRANSPORT, ENTRY, |
"slap_parseURI: parsing %s\n", uri->bv_val, 0, 0 ); |
"slap_parseURI: parsing %s\n", uri->bv_val, 0, 0 ); |
#else |
#else |
Debug( LDAP_DEBUG_TRACE, "slap_parseURI: parsing %s\n", uri->bv_val, 0, 0 ); |
Debug( LDAP_DEBUG_TRACE, |
|
"slap_parseURI: parsing %s\n", uri->bv_val, 0, 0 ); |
#endif |
#endif |
|
|
/* If it does not look like a URI, assume it is a DN */ |
rc = LDAP_PROTOCOL_ERROR; |
if( !strncasecmp( uri->bv_val, "dn:", sizeof("dn:")-1 ) ) { |
if ( !strncasecmp( uri->bv_val, "dn", sizeof( "dn" ) - 1 ) ) { |
bv.bv_val = uri->bv_val + sizeof("dn:")-1; |
bv.bv_val = uri->bv_val + sizeof( "dn" ) - 1; |
|
|
|
if ( bv.bv_val[ 0 ] == '.' ) { |
|
bv.bv_val++; |
|
|
|
if ( !strncasecmp( bv.bv_val, "exact:", sizeof( "exact:" ) - 1 ) ) { |
|
bv.bv_val += sizeof( "exact:" ) - 1; |
|
*scope = LDAP_X_SCOPE_EXACT; |
|
|
|
} else if ( !strncasecmp( bv.bv_val, "regex:", sizeof( "regex:" ) - 1 ) ) { |
|
bv.bv_val += sizeof( "regex:" ) - 1; |
|
*scope = LDAP_X_SCOPE_REGEX; |
|
|
|
} else if ( !strncasecmp( bv.bv_val, "children:", sizeof( "chldren:" ) - 1 ) ) { |
|
bv.bv_val += sizeof( "children:" ) - 1; |
|
*scope = LDAP_X_SCOPE_CHILDREN; |
|
|
|
} else if ( !strncasecmp( bv.bv_val, "subtree:", sizeof( "subtree:" ) - 1 ) ) { |
|
bv.bv_val += sizeof( "subtree:" ) - 1; |
|
*scope = LDAP_X_SCOPE_SUBTREE; |
|
|
|
} else if ( !strncasecmp( bv.bv_val, "onelevel:", sizeof( "onelevel:" ) - 1 ) ) { |
|
bv.bv_val += sizeof( "onelevel:" ) - 1; |
|
*scope = LDAP_X_SCOPE_ONELEVEL; |
|
|
|
} else { |
|
return LDAP_PROTOCOL_ERROR; |
|
} |
|
} else { |
|
if ( bv.bv_val[ 0 ] != ':' ) { |
|
return LDAP_PROTOCOL_ERROR; |
|
} |
|
*scope = LDAP_X_SCOPE_EXACT; |
|
bv.bv_val++; |
|
} |
|
|
bv.bv_val += strspn( bv.bv_val, " " ); |
bv.bv_val += strspn( bv.bv_val, " " ); |
|
/* jump here in case no type specification was present |
|
* and uir was not an URI... HEADS-UP: assuming EXACT */ |
|
is_dn: bv.bv_len = uri->bv_len - (bv.bv_val - uri->bv_val); |
|
|
|
switch ( *scope ) { |
|
case LDAP_X_SCOPE_EXACT: |
|
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; |
|
} |
|
break; |
|
|
is_dn: bv.bv_len = uri->bv_len - (bv.bv_val - uri->bv_val); |
case LDAP_X_SCOPE_REGEX: |
|
ber_dupbv_x( nbase, &bv, op->o_tmpmemctx ); |
|
rc = LDAP_SUCCESS; |
|
break; |
|
|
rc = dnNormalize( 0, NULL, NULL, &bv, searchbase, op->o_tmpmemctx ); |
default: |
if( rc == LDAP_SUCCESS ) { |
*scope = -1; |
*scope = LDAP_SCOPE_BASE; |
break; |
} |
} |
return( rc ); |
|
} |
|
|
|
|
return rc; |
|
|
|
} else if ( ( uri->bv_val[ 0 ] == 'u' || uri->bv_val[ 0 ] == 'U' ) |
|
&& ( uri->bv_val[ 1 ] == ':' |
|
|| uri->bv_val[ 1 ] == '/' |
|
|| uri->bv_val[ 1 ] == '.' ) ) |
|
{ |
|
Connection c = *op->o_conn; |
|
char buf[ SLAP_LDAPDN_MAXLEN ]; |
|
struct berval id, |
|
user = BER_BVNULL, |
|
realm = BER_BVNULL, |
|
mech = BER_BVNULL; |
|
|
|
if ( sizeof( buf ) <= uri->bv_len ) { |
|
return LDAP_INVALID_SYNTAX; |
|
} |
|
|
|
id.bv_len = uri->bv_len; |
|
id.bv_val = buf; |
|
strncpy( buf, uri->bv_val, sizeof( buf ) ); |
|
|
|
rc = slap_parse_user( &id, &user, &realm, &mech ); |
|
if ( rc != LDAP_SUCCESS ) { |
|
return rc; |
|
} |
|
|
|
if ( mech.bv_val ) { |
|
c.c_sasl_bind_mech = mech; |
|
} else { |
|
c.c_sasl_bind_mech.bv_val = "AUTHZ"; |
|
c.c_sasl_bind_mech.bv_len = sizeof( "AUTHZ" ) - 1; |
|
} |
|
|
|
rc = slap_sasl_getdn( &c, op, user.bv_val, user.bv_len, |
|
realm.bv_val, nbase, SLAP_GETDN_AUTHZID ); |
|
|
|
if ( rc == LDAP_SUCCESS ) { |
|
*scope = LDAP_X_SCOPE_EXACT; |
|
} |
|
|
|
return rc; |
|
} |
|
|
rc = ldap_url_parse( uri->bv_val, &ludp ); |
rc = ldap_url_parse( uri->bv_val, &ludp ); |
if ( rc == LDAP_URL_ERR_BADSCHEME ) { |
if ( rc == LDAP_URL_ERR_BADSCHEME ) { |
|
/* last chance: assume it's a(n exact) DN ... */ |
bv.bv_val = uri->bv_val; |
bv.bv_val = uri->bv_val; |
|
*scope = LDAP_X_SCOPE_EXACT; |
goto is_dn; |
goto is_dn; |
} |
} |
|
|
Line 114 is_dn: bv.bv_len = uri->bv_len - (bv.bv_
|
Line 326 is_dn: bv.bv_len = uri->bv_len - (bv.bv_
|
if (( ludp->lud_host && *ludp->lud_host ) |
if (( ludp->lud_host && *ludp->lud_host ) |
|| ludp->lud_attrs || ludp->lud_exts ) |
|| ludp->lud_attrs || ludp->lud_exts ) |
{ |
{ |
/* host part should be empty */ |
/* host part must be empty */ |
/* attrs and extensions parts should be empty */ |
/* attrs and extensions parts must be empty */ |
return LDAP_PROTOCOL_ERROR; |
rc = LDAP_PROTOCOL_ERROR; |
|
goto done; |
} |
} |
|
|
/* Grab the scope */ |
/* Grab the scope */ |
Line 129 is_dn: bv.bv_len = uri->bv_len - (bv.bv_
|
Line 342 is_dn: bv.bv_len = uri->bv_len - (bv.bv_
|
rc = LDAP_PROTOCOL_ERROR; |
rc = LDAP_PROTOCOL_ERROR; |
goto done; |
goto done; |
} |
} |
|
ber_str2bv( ludp->lud_filter, 0, 0, fstr ); |
} |
} |
|
|
/* Grab the searchbase */ |
/* Grab the searchbase */ |
bv.bv_val = ludp->lud_dn; |
ber_str2bv( ludp->lud_dn, 0, 0, base ); |
bv.bv_len = strlen( bv.bv_val ); |
rc = dnNormalize( 0, NULL, NULL, base, nbase, op->o_tmpmemctx ); |
rc = dnNormalize( 0, NULL, NULL, &bv, searchbase, op->o_tmpmemctx ); |
|
|
|
done: |
done: |
if( rc != LDAP_SUCCESS ) { |
if( rc != LDAP_SUCCESS ) { |
if( *filter ) filter_free_x( op, *filter ); |
if( *filter ) filter_free_x( op, *filter ); |
|
base->bv_val = NULL; |
|
base->bv_len = 0; |
|
fstr->bv_val = NULL; |
|
fstr->bv_len = 0; |
|
} else { |
|
/* Don't free these, return them to caller */ |
|
ludp->lud_filter = NULL; |
|
ludp->lud_dn = NULL; |
} |
} |
|
|
ldap_free_urldesc( ludp ); |
ldap_free_urldesc( ludp ); |
Line 278 static void slap_sasl_rx_exp(
|
Line 499 static void slap_sasl_rx_exp(
|
LDAP URI to find the matching LDAP entry, using the pattern matching |
LDAP URI to find the matching LDAP entry, using the pattern matching |
strings given in the saslregexp config file directive(s) */ |
strings given in the saslregexp config file directive(s) */ |
|
|
static int slap_sasl_regexp( struct berval *in, struct berval *out, void *ctx ) |
static int slap_sasl_regexp( struct berval *in, struct berval *out, |
|
int flags, void *ctx ) |
{ |
{ |
char *saslname = in->bv_val; |
char *saslname = in->bv_val; |
SaslRegexp_t *reg; |
SaslRegexp_t *reg; |
Line 340 static int sasl_sc_sasl2dn( Operation *o
|
Line 562 static int sasl_sc_sasl2dn( Operation *o
|
if( ndn->bv_val ) { |
if( ndn->bv_val ) { |
o->o_tmpfree(ndn->bv_val, o->o_tmpmemctx); |
o->o_tmpfree(ndn->bv_val, o->o_tmpmemctx); |
ndn->bv_val = NULL; |
ndn->bv_val = NULL; |
|
ndn->bv_len = 0; |
|
|
#ifdef NEW_LOGGING |
#ifdef NEW_LOGGING |
LDAP_LOG( TRANSPORT, DETAIL1, |
LDAP_LOG( TRANSPORT, DETAIL1, |
"slap_sasl2dn: search DN returned more than 1 entry\n", 0, 0, 0 ); |
"slap_sc_sasl2dn: search DN returned more than 1 entry\n", 0, 0, 0 ); |
#else |
#else |
Debug( LDAP_DEBUG_TRACE, |
Debug( LDAP_DEBUG_TRACE, |
"slap_sasl2dn: search DN returned more than 1 entry\n", 0,0,0 ); |
"slap_sc_sasl2dn: search DN returned more than 1 entry\n", 0, 0, 0 ); |
#endif |
#endif |
return -1; |
return -1; |
} |
} |
Line 385 static int sasl_sc_smatch( Operation *o,
|
Line 608 static int sasl_sc_smatch( Operation *o,
|
*/ |
*/ |
|
|
static |
static |
int slap_sasl_match(Operation *opx, struct berval *rule, struct berval *assertDN, struct berval *authc ) |
int slap_sasl_match( Operation *opx, struct berval *rule, |
|
struct berval *assertDN, struct berval *authc ) |
{ |
{ |
int rc; |
int rc; |
regex_t reg; |
regex_t reg; |
smatch_info sm; |
smatch_info sm; |
slap_callback cb = { sasl_sc_smatch, NULL }; |
slap_callback cb = { NULL, sasl_sc_smatch, NULL, NULL }; |
Operation op = {0}; |
Operation op = {0}; |
SlapReply rs = {REP_RESULT}; |
SlapReply rs = {REP_RESULT}; |
|
|
Line 404 int slap_sasl_match(Operation *opx, stru
|
Line 628 int slap_sasl_match(Operation *opx, stru
|
assertDN->bv_val, rule->bv_val, 0 ); |
assertDN->bv_val, rule->bv_val, 0 ); |
#endif |
#endif |
|
|
rc = slap_parseURI( opx, rule, &op.o_req_ndn, &op.oq_search.rs_scope, &op.oq_search.rs_filter ); |
rc = slap_parseURI( opx, rule, &op.o_req_dn, |
|
&op.o_req_ndn, &op.oq_search.rs_scope, &op.oq_search.rs_filter, |
|
&op.ors_filterstr ); |
if( rc != LDAP_SUCCESS ) goto CONCLUDED; |
if( rc != LDAP_SUCCESS ) goto CONCLUDED; |
|
|
/* Massive shortcut: search scope == base */ |
switch ( op.oq_search.rs_scope ) { |
if( op.oq_search.rs_scope == LDAP_SCOPE_BASE ) { |
case LDAP_X_SCOPE_EXACT: |
|
exact_match: |
|
if ( dn_match( &op.o_req_ndn, assertDN ) ) { |
|
rc = LDAP_SUCCESS; |
|
} else { |
|
rc = LDAP_INAPPROPRIATE_AUTH; |
|
} |
|
goto CONCLUDED; |
|
|
|
case LDAP_X_SCOPE_CHILDREN: |
|
case LDAP_X_SCOPE_SUBTREE: |
|
case LDAP_X_SCOPE_ONELEVEL: |
|
{ |
|
int d = assertDN->bv_len - op.o_req_ndn.bv_len; |
|
|
|
rc = LDAP_INAPPROPRIATE_AUTH; |
|
|
|
if ( d == 0 && op.oq_search.rs_scope == LDAP_X_SCOPE_SUBTREE ) { |
|
goto exact_match; |
|
|
|
} else if ( d > 0 ) { |
|
struct berval bv; |
|
|
|
bv.bv_len = op.o_req_ndn.bv_len; |
|
bv.bv_val = assertDN->bv_val + d; |
|
|
|
if ( bv.bv_val[ -1 ] == ',' && dn_match( &op.o_req_ndn, &bv ) ) { |
|
switch ( op.oq_search.rs_scope ) { |
|
case LDAP_X_SCOPE_SUBTREE: |
|
case LDAP_X_SCOPE_CHILDREN: |
|
rc = LDAP_SUCCESS; |
|
break; |
|
|
|
case LDAP_X_SCOPE_ONELEVEL: |
|
{ |
|
struct berval pdn; |
|
|
|
dnParent( assertDN, &pdn ); |
|
/* the common portion of the DN |
|
* already matches, so only check |
|
* if parent DN of assertedDN |
|
* is all the pattern */ |
|
if ( pdn.bv_len == op.o_req_ndn.bv_len ) { |
|
rc = LDAP_SUCCESS; |
|
} |
|
break; |
|
} |
|
default: |
|
/* at present, impossible */ |
|
assert( 0 ); |
|
} |
|
} |
|
} |
|
goto CONCLUDED; |
|
} |
|
|
|
case LDAP_X_SCOPE_REGEX: |
rc = regcomp(®, op.o_req_ndn.bv_val, |
rc = regcomp(®, op.o_req_ndn.bv_val, |
REG_EXTENDED|REG_ICASE|REG_NOSUB); |
REG_EXTENDED|REG_ICASE|REG_NOSUB); |
if ( rc == 0 ) { |
if ( rc == 0 ) { |
Line 421 int slap_sasl_match(Operation *opx, stru
|
Line 703 int slap_sasl_match(Operation *opx, stru
|
rc = LDAP_INAPPROPRIATE_AUTH; |
rc = LDAP_INAPPROPRIATE_AUTH; |
} |
} |
goto CONCLUDED; |
goto CONCLUDED; |
|
|
|
default: |
|
break; |
} |
} |
|
|
/* Must run an internal search. */ |
/* Must run an internal search. */ |
|
if ( op.oq_search.rs_filter == NULL ) { |
|
rc = LDAP_FILTER_ERROR; |
|
goto CONCLUDED; |
|
} |
|
|
#ifdef NEW_LOGGING |
#ifdef NEW_LOGGING |
LDAP_LOG( TRANSPORT, DETAIL1, |
LDAP_LOG( TRANSPORT, DETAIL1, |
Line 455 int slap_sasl_match(Operation *opx, stru
|
Line 744 int slap_sasl_match(Operation *opx, stru
|
op.o_threadctx = opx->o_threadctx; |
op.o_threadctx = opx->o_threadctx; |
op.o_tmpmemctx = opx->o_tmpmemctx; |
op.o_tmpmemctx = opx->o_tmpmemctx; |
op.o_tmpmfuncs = opx->o_tmpmfuncs; |
op.o_tmpmfuncs = opx->o_tmpmfuncs; |
|
#ifdef LDAP_SLAPI |
|
op.o_pb = opx->o_pb; |
|
#endif |
op.o_conn = opx->o_conn; |
op.o_conn = opx->o_conn; |
op.o_connid = opx->o_connid; |
op.o_connid = opx->o_connid; |
|
op.o_req_dn = op.o_req_ndn; |
|
op.oq_search.rs_slimit = 1; |
|
op.oq_search.rs_tlimit = SLAP_NO_LIMIT; |
|
op.o_sync_slog_size = -1; |
|
|
op.o_bd->be_search( &op, &rs ); |
op.o_bd->be_search( &op, &rs ); |
|
|
Line 467 int slap_sasl_match(Operation *opx, stru
|
Line 763 int slap_sasl_match(Operation *opx, stru
|
} |
} |
|
|
CONCLUDED: |
CONCLUDED: |
if( op.o_req_ndn.bv_len ) sl_free( op.o_req_ndn.bv_val, opx->o_tmpmemctx ); |
if( op.o_req_dn.bv_val && op.o_req_dn.bv_val != op.o_req_ndn.bv_val ) ch_free( op.o_req_dn.bv_val ); |
|
if( op.o_req_ndn.bv_val ) sl_free( op.o_req_ndn.bv_val, opx->o_tmpmemctx ); |
if( op.oq_search.rs_filter ) filter_free_x( opx, op.oq_search.rs_filter ); |
if( op.oq_search.rs_filter ) filter_free_x( opx, op.oq_search.rs_filter ); |
|
if( op.ors_filterstr.bv_val ) ch_free( op.ors_filterstr.bv_val ); |
|
|
#ifdef NEW_LOGGING |
#ifdef NEW_LOGGING |
LDAP_LOG( TRANSPORT, ENTRY, |
LDAP_LOG( TRANSPORT, ENTRY, |
Line 515 slap_sasl_check_authz( Operation *op,
|
Line 813 slap_sasl_check_authz( Operation *op,
|
if( rc != LDAP_SUCCESS ) goto COMPLETE; |
if( rc != LDAP_SUCCESS ) goto COMPLETE; |
|
|
/* Check if the *assertDN matches any **vals */ |
/* Check if the *assertDN matches any **vals */ |
for( i=0; vals[i].bv_val != NULL; i++ ) { |
if( vals != NULL ) { |
rc = slap_sasl_match( op, &vals[i], assertDN, authc ); |
for( i=0; vals[i].bv_val != NULL; i++ ) { |
if ( rc == LDAP_SUCCESS ) goto COMPLETE; |
rc = slap_sasl_match( op, &vals[i], assertDN, authc ); |
|
if ( rc == LDAP_SUCCESS ) goto COMPLETE; |
|
} |
} |
} |
rc = LDAP_INAPPROPRIATE_AUTH; |
rc = LDAP_INAPPROPRIATE_AUTH; |
|
|
Line 546 COMPLETE:
|
Line 846 COMPLETE:
|
* entry, return the DN of that one entry. |
* entry, return the DN of that one entry. |
*/ |
*/ |
void slap_sasl2dn( Operation *opx, |
void slap_sasl2dn( Operation *opx, |
struct berval *saslname, struct berval *sasldn ) |
struct berval *saslname, struct berval *sasldn, int flags ) |
{ |
{ |
int rc; |
int rc; |
slap_callback cb = { sasl_sc_sasl2dn, NULL }; |
slap_callback cb = { NULL, sasl_sc_sasl2dn, NULL, NULL }; |
Operation op = {0}; |
Operation op = {0}; |
SlapReply rs = {REP_RESULT}; |
SlapReply rs = {REP_RESULT}; |
struct berval regout = { 0, NULL }; |
struct berval regout = BER_BVNULL; |
|
|
#ifdef NEW_LOGGING |
#ifdef NEW_LOGGING |
LDAP_LOG( TRANSPORT, ENTRY, |
LDAP_LOG( TRANSPORT, ENTRY, |
Line 569 void slap_sasl2dn( Operation *opx,
|
Line 869 void slap_sasl2dn( Operation *opx,
|
cb.sc_private = sasldn; |
cb.sc_private = sasldn; |
|
|
/* Convert the SASL name into a minimal URI */ |
/* Convert the SASL name into a minimal URI */ |
if( !slap_sasl_regexp( saslname, ®out, opx->o_tmpmemctx ) ) { |
if( !slap_sasl_regexp( saslname, ®out, flags, opx->o_tmpmemctx ) ) { |
goto FINISHED; |
goto FINISHED; |
} |
} |
|
|
rc = slap_parseURI( opx, ®out, &op.o_req_ndn, &op.oq_search.rs_scope, &op.oq_search.rs_filter ); |
rc = slap_parseURI( opx, ®out, &op.o_req_dn, |
|
&op.o_req_ndn, &op.oq_search.rs_scope, &op.oq_search.rs_filter, |
|
&op.ors_filterstr ); |
if( regout.bv_val ) sl_free( regout.bv_val, opx->o_tmpmemctx ); |
if( regout.bv_val ) sl_free( regout.bv_val, opx->o_tmpmemctx ); |
if( rc != LDAP_SUCCESS ) { |
if( rc != LDAP_SUCCESS ) { |
goto FINISHED; |
goto FINISHED; |
Line 582 void slap_sasl2dn( Operation *opx,
|
Line 884 void slap_sasl2dn( Operation *opx,
|
/* Must do an internal search */ |
/* Must do an internal search */ |
op.o_bd = select_backend( &op.o_req_ndn, 0, 1 ); |
op.o_bd = select_backend( &op.o_req_ndn, 0, 1 ); |
|
|
/* Massive shortcut: search scope == base */ |
switch ( op.oq_search.rs_scope ) { |
if( op.oq_search.rs_scope == LDAP_SCOPE_BASE ) { |
case LDAP_X_SCOPE_EXACT: |
*sasldn = op.o_req_ndn; |
*sasldn = op.o_req_ndn; |
op.o_req_ndn.bv_len = 0; |
op.o_req_ndn.bv_len = 0; |
op.o_req_ndn.bv_val = NULL; |
op.o_req_ndn.bv_val = NULL; |
|
/* intentionally continue to next case */ |
|
|
|
case LDAP_X_SCOPE_REGEX: |
|
case LDAP_X_SCOPE_SUBTREE: |
|
case LDAP_X_SCOPE_CHILDREN: |
|
case LDAP_X_SCOPE_ONELEVEL: |
|
/* correctly parsed, but illegal */ |
goto FINISHED; |
goto FINISHED; |
|
|
|
case LDAP_SCOPE_BASE: |
|
case LDAP_SCOPE_ONELEVEL: |
|
case LDAP_SCOPE_SUBTREE: |
|
#ifdef LDAP_SCOPE_SUBORDINATE |
|
case LDAP_SCOPE_SUBORDINATE: |
|
#endif |
|
/* do a search */ |
|
break; |
|
|
|
default: |
|
/* catch unhandled cases (there shouldn't be) */ |
|
assert( 0 ); |
} |
} |
|
|
#ifdef NEW_LOGGING |
#ifdef NEW_LOGGING |
Line 616 void slap_sasl2dn( Operation *opx,
|
Line 938 void slap_sasl2dn( Operation *opx,
|
op.o_threadctx = opx->o_threadctx; |
op.o_threadctx = opx->o_threadctx; |
op.o_tmpmemctx = opx->o_tmpmemctx; |
op.o_tmpmemctx = opx->o_tmpmemctx; |
op.o_tmpmfuncs = opx->o_tmpmfuncs; |
op.o_tmpmfuncs = opx->o_tmpmfuncs; |
|
#ifdef LDAP_SLAPI |
|
op.o_pb = opx->o_pb; |
|
#endif |
op.oq_search.rs_deref = LDAP_DEREF_NEVER; |
op.oq_search.rs_deref = LDAP_DEREF_NEVER; |
op.oq_search.rs_slimit = 1; |
op.oq_search.rs_slimit = 1; |
|
op.oq_search.rs_tlimit = SLAP_NO_LIMIT; |
op.oq_search.rs_attrsonly = 1; |
op.oq_search.rs_attrsonly = 1; |
|
op.o_req_dn = op.o_req_ndn; |
|
|
op.o_bd->be_search( &op, &rs ); |
op.o_bd->be_search( &op, &rs ); |
|
|
Line 626 FINISHED:
|
Line 953 FINISHED:
|
if( sasldn->bv_len ) { |
if( sasldn->bv_len ) { |
opx->o_conn->c_authz_backend = op.o_bd; |
opx->o_conn->c_authz_backend = op.o_bd; |
} |
} |
if( op.o_req_ndn.bv_len ) ch_free( op.o_req_ndn.bv_val ); |
if( op.o_req_dn.bv_len ) ch_free( op.o_req_dn.bv_val ); |
|
if( op.o_req_ndn.bv_len ) sl_free( op.o_req_ndn.bv_val, opx->o_tmpmemctx ); |
if( op.oq_search.rs_filter ) filter_free_x( opx, op.oq_search.rs_filter ); |
if( op.oq_search.rs_filter ) filter_free_x( opx, op.oq_search.rs_filter ); |
|
if( op.ors_filterstr.bv_len ) ch_free( op.ors_filterstr.bv_val ); |
|
|
#ifdef NEW_LOGGING |
#ifdef NEW_LOGGING |
LDAP_LOG( TRANSPORT, ENTRY, |
LDAP_LOG( TRANSPORT, ENTRY, |
Line 674 int slap_sasl_authorized( Operation *op,
|
Line 1003 int slap_sasl_authorized( Operation *op,
|
} |
} |
|
|
/* Allow the manager to authorize as any DN. */ |
/* Allow the manager to authorize as any DN. */ |
if( op->o_conn->c_authz_backend && be_isroot( op->o_conn->c_authz_backend, authcDN )) { |
if( op->o_conn->c_authz_backend && |
|
be_isroot_dn( op->o_conn->c_authz_backend, authcDN )) |
|
{ |
rc = LDAP_SUCCESS; |
rc = LDAP_SUCCESS; |
goto DONE; |
goto DONE; |
} |
} |
Line 683 int slap_sasl_authorized( Operation *op,
|
Line 1014 int slap_sasl_authorized( Operation *op,
|
if( authz_policy & SASL_AUTHZ_TO ) { |
if( authz_policy & SASL_AUTHZ_TO ) { |
rc = slap_sasl_check_authz( op, authcDN, authzDN, |
rc = slap_sasl_check_authz( op, authcDN, authzDN, |
slap_schema.si_ad_saslAuthzTo, authcDN ); |
slap_schema.si_ad_saslAuthzTo, authcDN ); |
if( rc == LDAP_SUCCESS ) { |
if( rc == LDAP_SUCCESS && !(authz_policy & SASL_AUTHZ_AND) ) { |
goto DONE; |
goto DONE; |
} |
} |
} |
} |