From: Kurt Zeilenga Date: Sun, 4 Jul 1999 18:46:24 +0000 (+0000) Subject: HEADS UP: connections are forced to "anonymous" status upon receiving X-Git-Tag: OPENLDAP_REL_ENG_2_BP~197 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=106eef41d8489ab5e55813f2b995e48884f64e16;p=openldap HEADS UP: connections are forced to "anonymous" status upon receiving of a bind request and, upon failure, are left "anonymous." Rework ACL code to hide access testing within macros to facilate additions and eventual redesign. Addition of #ifdef SLAPD_ACLAUTH to conditional include EXPERIMENTAL "auth" access controls. Adds ACL_AUTH "auth" access level (above none, below "compare"). bind requires anonymous access at this level or above access to "entry"/"userPassword"/"krbName". This allows administrators to restrict which entries can be bound to. (This will likely become default behavior after testing has completed). --- diff --git a/servers/slapd/acl.c b/servers/slapd/acl.c index 695174ec7d..85cdda5515 100644 --- a/servers/slapd/acl.c +++ b/servers/slapd/acl.c @@ -266,19 +266,19 @@ acl_access_allowed( if ( strcmp( edn, op->o_ndn ) == 0 ) { Debug( LDAP_DEBUG_ACL, "<= acl_access_allowed: matched by clause #%d access %s\n", - i, (b->a_access & ~ACL_SELF) >= - access ? "granted" : "denied", 0 ); + i, ACL_GRANT(b->a_access, access) + ? "granted" : "denied", 0 ); - return( (b->a_access & ~ACL_SELF) >= access ); + return ACL_GRANT(b->a_access, access ); } } else { if ( regex_matches( b->a_dnpat, odn, edn, matches ) ) { Debug( LDAP_DEBUG_ACL, "<= acl_access_allowed: matched by clause #%d access %s\n", - i, (b->a_access & ~ACL_SELF) >= access ? - "granted" : "denied", 0 ); + i, ACL_GRANT(b->a_access, access) + ? "granted" : "denied", 0 ); - return( (b->a_access & ~ACL_SELF) >= access ); + return ACL_GRANT(b->a_access, access ); } } } @@ -288,10 +288,10 @@ acl_access_allowed( { Debug( LDAP_DEBUG_ACL, "<= acl_access_allowed: matched by clause #%d access %s\n", - i, (b->a_access & ~ACL_SELF) >= access ? - "granted" : "denied", 0 ); + i, ACL_GRANT(b->a_access, access) + ? "granted" : "denied", 0 ); - return( (b->a_access & ~ACL_SELF) >= access ); + return ACL_GRANT(b->a_access, access ); } } if ( b->a_domainpat != NULL ) { @@ -302,10 +302,10 @@ acl_access_allowed( { Debug( LDAP_DEBUG_ACL, "<= acl_access_allowed: matched by clause #%d access %s\n", - i, (b->a_access & ~ACL_SELF) >= access ? - "granted" : "denied", 0 ); + i, ACL_GRANT(b->a_access, access) + ? "granted" : "denied", 0 ); - return( (b->a_access & ~ACL_SELF) >= access ); + return ACL_GRANT(b->a_access, access ); } } if ( b->a_dnattr != NULL && op->o_ndn != NULL ) { @@ -315,7 +315,7 @@ acl_access_allowed( if ( (at = attr_find( e->e_attrs, b->a_dnattr )) != NULL && value_find( at->a_vals, &bv, at->a_syntax, 3 ) == 0 ) { - if ( (b->a_access & ACL_SELF) && + if ( ACL_IS_SELF(b->a_access) && (val == NULL || value_cmp( &bv, val, at->a_syntax, 2 )) ) { continue; @@ -323,14 +323,14 @@ acl_access_allowed( Debug( LDAP_DEBUG_ACL, "<= acl_acces_allowed: matched by clause #%d access %s\n", - i, (b->a_access & ~ACL_SELF) >= access ? - "granted" : "denied", 0 ); + i, ACL_GRANT(b->a_access, access) + ? "granted" : "denied", 0 ); - return( (b->a_access & ~ACL_SELF) >= access ); + return ACL_GRANT(b->a_access, access ); } /* asker not listed in dnattr - check for self access */ - if ( ! (b->a_access & ACL_SELF) || val == NULL || + if ( ! ACL_IS_SELF(b->a_access) || val == NULL || value_cmp( &bv, val, at->a_syntax, 2 ) != 0 ) { continue; @@ -338,10 +338,10 @@ acl_access_allowed( Debug( LDAP_DEBUG_ACL, "<= acl_access_allowed: matched by clause #%d (self) access %s\n", - i, (b->a_access & ~ACL_SELF) >= access ? "granted" - : "denied", 0 ); + i, ACL_GRANT(b->a_access, access) + ? "granted" : "denied", 0 ); - return( (b->a_access & ~ACL_SELF) >= access ); + return ACL_GRANT(b->a_access, access ); } #ifdef SLAPD_ACLGROUPS if ( b->a_group != NULL && op->o_ndn != NULL ) { @@ -356,12 +356,12 @@ acl_access_allowed( (void) dn_normalize_case(buf); if (backend_group(be, e, buf, odn, - b->a_objectclassvalue, b->a_groupattrname) == 0) + b->a_group_oc, b->a_group_at) == 0) { Debug( LDAP_DEBUG_ACL, "<= acl_access_allowed: matched by clause #%d (group) access granted\n", i, 0, 0 ); - return( (b->a_access & ~ACL_SELF) >= access ); + return ACL_GRANT(b->a_access, access ); } } #endif /* SLAPD_ACLGROUPS */ diff --git a/servers/slapd/aclparse.c b/servers/slapd/aclparse.c index 00f9201131..65d0450317 100644 --- a/servers/slapd/aclparse.c +++ b/servers/slapd/aclparse.c @@ -206,7 +206,6 @@ parse_acl( } else if ( strncasecmp( left, "group", sizeof("group")-1 ) == 0 ) { char *name = NULL; char *value = NULL; - regtest(fname, lineno, right); /* format of string is "group/objectClassValue/groupAttrName" */ @@ -216,21 +215,22 @@ parse_acl( *name++ = '\0'; } + regtest(fname, lineno, right); b->a_group = dn_upcase(ch_strdup( right )); if (value && *value) { - b->a_objectclassvalue = ch_strdup(value); + b->a_group_oc = ch_strdup(value); *--value = '/'; } else - b->a_objectclassvalue = ch_strdup("groupOfNames"); + b->a_group_oc = ch_strdup("groupOfNames"); if (name && *name) { - b->a_groupattrname = ch_strdup(name); + b->a_group_at = ch_strdup(name); *--name = '/'; } else - b->a_groupattrname = ch_strdup("member"); + b->a_group_at = ch_strdup("member"); @@ -263,7 +263,7 @@ parse_acl( /* get */ split( argv[i], '=', &left, &right ); - if ( (b->a_access = str2access( left )) == -1 ) { + if ( ACL_IS_INVALID(ACL_SET(str2access( left ),b->a_access)) ) { fprintf( stderr, "%s: line %d: expecting got \"%s\"\n", fname, lineno, left ); @@ -311,21 +311,25 @@ access2str( int access ) { static char buf[12]; - if ( access & ACL_SELF ) { + if ( ACL_IS_SELF( access ) ) { strcpy( buf, "self" ); } else { buf[0] = '\0'; } - if ( access & ACL_NONE ) { + if ( ACL_IS_NONE(access) ) { strcat( buf, "none" ); - } else if ( access & ACL_COMPARE ) { +#ifdef SLAPD_ACLAUTH + } else if ( ACL_IS_AUTH(access) ) { + strcat( buf, "auth" ); +#endif + } else if ( ACL_IS_COMPARE(access) ) { strcat( buf, "compare" ); - } else if ( access & ACL_SEARCH ) { + } else if ( ACL_IS_SEARCH(access) ) { strcat( buf, "search" ); - } else if ( access & ACL_READ ) { + } else if ( ACL_IS_READ(access) ) { strcat( buf, "read" ); - } else if ( access & ACL_WRITE ) { + } else if ( ACL_IS_WRITE(access) ) { strcat( buf, "write" ); } else { strcat( buf, "unknown" ); @@ -339,24 +343,29 @@ str2access( char *str ) { int access; - access = 0; + ACL_CLR(access); + if ( strncasecmp( str, "self", 4 ) == 0 ) { - access |= ACL_SELF; + ACL_SET_SELF(access); str += 4; } if ( strcasecmp( str, "none" ) == 0 ) { - access |= ACL_NONE; + ACL_SET_NONE(access); +#ifdef SLAPD_ACLAUTH + } else if ( strcasecmp( str, "auth" ) == 0 ) { + ACL_SET_AUTH(access); +#endif } else if ( strcasecmp( str, "compare" ) == 0 ) { - access |= ACL_COMPARE; + ACL_SET_COMPARE(access); } else if ( strcasecmp( str, "search" ) == 0 ) { - access |= ACL_SEARCH; + ACL_SET_SEARCH(access); } else if ( strcasecmp( str, "read" ) == 0 ) { - access |= ACL_READ; + ACL_SET_READ(access); } else if ( strcasecmp( str, "write" ) == 0 ) { - access |= ACL_WRITE; + ACL_SET_WRITE(access); } else { - access = -1; + ACL_SET_INVALID(access); } return( access ); @@ -365,12 +374,22 @@ str2access( char *str ) static void acl_usage( void ) { - fprintf( stderr, "\n ::= access to [ by ]+ \n" ); - fprintf( stderr, " ::= * | [dn=] [filter=] [attrs=]\n" ); - fprintf( stderr, " ::= | , \n" ); - fprintf( stderr, " ::= | entry | children\n" ); - fprintf( stderr, " ::= * | self | dn= | addr= |\n\tdomain= | dnattr=\n" ); - fprintf( stderr, " ::= [self]{none | compare | search | read | write }\n" ); + fprintf( stderr, "\n" + " ::= access to [ by ]+ \n" + " ::= * | [dn=] [filter=] [attrs=]\n" + " ::= | , \n" + " ::= | entry | children\n" + " ::= * | self | dn= | addr=\n" + "\t| domain= | dnattr=\n" +#ifdef SLAPD_ACLGROUPS + "\t| group[/[/]]=\n" +#endif +#ifdef SLAPD_ACLAUTH + " ::= [self]{none|auth|compare|search|read|write}\n" +#else + " ::= [self]{none|auth|compare|search|read|write}\n" +#endif + ); exit( 1 ); } @@ -425,10 +444,10 @@ print_access( struct access *b ) #ifdef SLAPD_ACLGROUPS else if ( b->a_group != NULL ) { fprintf( stderr, " group: %s", b->a_group ); - if ( b->a_objectclassvalue ) - fprintf( stderr, " objectClassValue: %s", b->a_objectclassvalue ); - if ( b->a_groupattrname ) - fprintf( stderr, " groupAttrName: %s", b->a_groupattrname ); + if ( b->a_group_oc ) + fprintf( stderr, " objectClass: %s", b->a_group_oc ); + if ( b->a_group_at ) + fprintf( stderr, " attributeType: %s", b->a_group_at ); } #endif fprintf( stderr, "\n" ); diff --git a/servers/slapd/back-ldbm/bind.c b/servers/slapd/back-ldbm/bind.c index bf05252337..51ddf32bf7 100644 --- a/servers/slapd/back-ldbm/bind.c +++ b/servers/slapd/back-ldbm/bind.c @@ -112,6 +112,16 @@ ldbm_back_bind( /* check for deleted */ +#ifdef SLAPD_ACLAUTH + if ( ! access_allowed( be, conn, op, e, + "entry", NULL, ACL_AUTH ) ) + { + send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, "", "" ); + rc = 1; + goto return_results; + } +#endif + switch ( method ) { case LDAP_AUTH_SIMPLE: if ( cred->bv_len == 0 ) { @@ -131,6 +141,16 @@ ldbm_back_bind( goto return_results; } +#ifdef SLAPD_ACLAUTH + if ( ! access_allowed( be, conn, op, e, + "userpassword", NULL, ACL_AUTH ) ) + { + send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, "", "" ); + rc = 1; + goto return_results; + } +#endif + if ( (a = attr_find( e->e_attrs, "userpassword" )) == NULL ) { send_ldap_result( conn, op, LDAP_INAPPROPRIATE_AUTH, NULL, NULL ); @@ -154,6 +174,15 @@ ldbm_back_bind( #ifdef HAVE_KERBEROS case LDAP_AUTH_KRBV41: +#ifdef SLAPD_ACLAUTH + if ( ! access_allowed( be, conn, op, e, + "krbname", NULL, ACL_AUTH ) ) + { + send_ldap_result( conn, op, LDAP_INSUFFICIENT_ACCESS, "", "" ); + rc = 1; + goto return_results; + } +#endif if ( krbv4_ldap_auth( be, cred, &ad ) != LDAP_SUCCESS ) { send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS, NULL, NULL ); @@ -167,7 +196,7 @@ ldbm_back_bind( * no krbName values present: check against DN */ if ( strcasecmp( dn, krbname ) == 0 ) { - rc = 0; /* XXX wild ass guess */ + rc = 0; break; } send_ldap_result( conn, op, LDAP_INAPPROPRIATE_AUTH, diff --git a/servers/slapd/bind.c b/servers/slapd/bind.c index 8a11db02b0..9d721a71e0 100644 --- a/servers/slapd/bind.c +++ b/servers/slapd/bind.c @@ -69,6 +69,16 @@ do_bind( ldap_pvt_thread_mutex_unlock( &conn->c_mutex ); + if ( op->o_ndn != NULL ) { + free( op->o_ndn ); + op->o_ndn = NULL; + } + + if ( op->o_dn != NULL ) { + free( op->o_dn ); + op->o_dn = NULL; + } + /* * Parse the bind request. It looks like this: * diff --git a/servers/slapd/config.c b/servers/slapd/config.c index f2f0cd79a0..1dfbdf2a98 100644 --- a/servers/slapd/config.c +++ b/servers/slapd/config.c @@ -425,18 +425,19 @@ read_config( char *fname ) return( 1 ); } if ( be == NULL ) { - if ( (global_default_access = - str2access( cargv[1] )) == -1 ) { + if ( ACL_IS_INVALID(ACL_SET(str2access(cargv[1]), + global_default_access)) ) { Debug( LDAP_DEBUG_ANY, "%s: line %d: bad access \"%s\" expecting [self]{none|compare|read|write}\n", fname, lineno, cargv[1] ); return( 1 ); } } else { - if ( (be->be_dfltaccess = - str2access( cargv[1] )) == -1 ) { + if ( ACL_IS_INVALID(ACL_SET(str2access(cargv[1]), + be->be_dfltaccess)) ) { Debug( LDAP_DEBUG_ANY, -"%s: line %d: bad access \"%s\" expecting [self]{none|compare|read|write}\n", + "%s: line %d: bad access \"%s\", " + "expecting [self]{none|compare|search|read|write}\n", fname, lineno, cargv[1] ); return( 1 ); } diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index d52b63f8bc..6d9608f8ca 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -176,12 +176,47 @@ typedef struct entry { /* the "by" part */ struct access { -#define ACL_NONE 0x01 -#define ACL_COMPARE 0x02 -#define ACL_SEARCH 0x04 -#define ACL_READ 0x08 -#define ACL_WRITE 0x10 -#define ACL_SELF 0x40 +#define ACL_NONE 0x0001 +/* #define SLAPD_ACLAUTH 1 */ +#ifdef SLAPD_ACLAUTH +#define ACL_AUTH 0x0002 +#endif +#define ACL_COMPARE 0x0004 +#define ACL_SEARCH 0x0008 +#define ACL_READ 0x0010 +#define ACL_WRITE 0x0020 +#define ACL_SELF 0x4000 +#define ACL_INVALID -1 + +#define ACL_IS(lvl,a) (((a) & (lvl)) == (lvl)) + +#define ACL_IS_NONE(a) ACL_IS(ACL_SELF,(a)) +#define ACL_IS_AUTH(a) ACL_IS(ACL_AUTH,(a)) +#define ACL_IS_COMPARE(a) ACL_IS(ACL_COMPARE,(a)) +#define ACL_IS_SEARCH(a) ACL_IS(ACL_SEARCH,(a)) +#define ACL_IS_READ(a) ACL_IS(ACL_READ,(a)) +#define ACL_IS_WRITE(a) ACL_IS(ACL_WRITE,(a)) +#define ACL_IS_SELF(a) ACL_IS(ACL_SELF,(a)) +#define ACL_IS_INVALID(a) ACL_IS(ACL_INVALID,(a)) + + +#define ACL_CLR(a) ((a) = 0) +#define ACL_SET(lvl,a) ((a) |= (lvl)) +#define ACL_SET_NONE(a) ACL_SET(ACL_SELF,(a)) +#define ACL_SET_AUTH(a) ACL_SET(ACL_AUTH,(a)) +#define ACL_SET_COMPARE(a) ACL_SET(ACL_COMPARE,(a)) +#define ACL_SET_SEARCH(a) ACL_SET(ACL_SEARCH,(a)) +#define ACL_SET_READ(a) ACL_SET(ACL_READ,(a)) +#define ACL_SET_WRITE(a) ACL_SET(ACL_WRITE,(a)) +#define ACL_SET_SELF(a) ACL_SET(ACL_SELF,(a)) +#define ACL_SET_INVALID(a) ACL_SET(ACL_INVALID,(a)) + +#define ACL_PRIV_MASK 0x00ff +#define ACL_PRIV(a) ((a) & ACL_PRIV_MASK) +#define ACL_GRANT(lvl,a) (ACL_PRIV(a) >= (lvl)) +#define ACL_TEST + + int a_access; char *a_dnpat; @@ -191,8 +226,8 @@ struct access { #ifdef SLAPD_ACLGROUPS char *a_group; - char *a_objectclassvalue; - char *a_groupattrname; + char *a_group_oc; + char *a_group_at; #endif struct access *a_next; };