Skip to content
Snippets Groups Projects
Commit 35de807a authored by Pierangelo Masarati's avatar Pierangelo Masarati
Browse files

add posixGroup access control via dynacl as an example of how dynacl work

parent 99ea177e
Branches
Tags
No related merge requests found
Copyright 2005 The OpenLDAP Foundation. 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.
This directory contains native slapd plugins that implement access rules.
posixgroup.c contains a simple example that implements access control
based on posixGroup membership, loosely inspired by ITS#3849. It should
be made clear that this access control policy does not reflect any
standard track model of handling access control, and should be
essentially viewed as an illustration of the use of the dynamic
extension of access control within slapd.
To use the acl-posixgroup plugin, add:
moduleload acl-posixgroup.so
to your slapd configuration file; it requires "nis.schema" to be loaded.
It is configured using
access to <what>
by dynacl/posixGroup[.{exact,expand}]=<dnpat> {<level>|<priv(s)}
The default is "exact"; in case of "expand", "<dnpat>" results from
the expansion of submatches in the "<what>" portion. "<level>|<priv(s)>"
describe the level of privilege this rule can assume.
No Makefile is provided. Use a command line similar to:
gcc -shared -I../../../include -I../../../servers/slapd -Wall -g \
-o acl-posixgroup.so posixgroup.c
to compile the posixGroup ACL plugin.
/* $OpenLDAP$ */
/*
* Copyright 1998-2005 The OpenLDAP Foundation.
* 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>.
*/
#include <portable.h>
#include <ac/string.h>
#include <slap.h>
#include <lutil.h>
/* Need dynacl... */
#ifdef SLAP_DYNACL
typedef struct pg_t {
slap_style_t pg_style;
struct berval pg_pat;
} pg_t;
static ObjectClass *pg_posixGroup;
static AttributeDescription *pg_memberUid;
static ObjectClass *pg_posixAccount;
static AttributeDescription *pg_uidNumber;
static int pg_dynacl_destroy( void *priv );
static int
pg_dynacl_parse(
const char *fname,
int lineno,
slap_style_t style,
const char *pattern,
void **privp )
{
pg_t *pg;
int rc;
const char *text = NULL;
struct berval pat;
ber_str2bv( pattern, 0, 0, &pat );
pg = ch_calloc( 1, sizeof( pg_t ) );
pg->pg_style = style;
switch ( pg->pg_style ) {
case ACL_STYLE_BASE:
rc = dnNormalize( 0, NULL, NULL, &pat, &pg->pg_pat, NULL );
if ( rc != LDAP_SUCCESS ) {
fprintf( stderr, "%s line %d: posixGroup ACL: "
"unable to normalize DN \"%s\".\n",
fname, lineno, pattern );
goto cleanup;
}
break;
case ACL_STYLE_EXPAND:
ber_dupbv( &pg->pg_pat, &pat );
break;
default:
fprintf( stderr, "%s line %d: posixGroup ACL: "
"unsupported style \"%s\".\n",
fname, lineno, style_strings[ pg->pg_style ] );
goto cleanup;
}
if ( pg_posixGroup == NULL ) {
pg_posixGroup = oc_find( "posixGroup" );
if ( pg_posixGroup == NULL ) {
fprintf( stderr, "%s line %d: posixGroup ACL: "
"unable to lookup \"posixGroup\" "
"objectClass.\n",
fname, lineno );
goto cleanup;
}
pg_posixAccount = oc_find( "posixAccount" );
if ( pg_posixGroup == NULL ) {
fprintf( stderr, "%s line %d: posixGroup ACL: "
"unable to lookup \"posixAccount\" "
"objectClass.\n",
fname, lineno );
goto cleanup;
}
rc = slap_str2ad( "memberUid", &pg_memberUid, &text );
if ( rc != LDAP_SUCCESS ) {
fprintf( stderr, "%s line %d: posixGroup ACL: "
"unable to lookup \"memberUid\" "
"attributeDescription (%d: %s).\n",
fname, lineno, rc, text );
goto cleanup;
}
rc = slap_str2ad( "uidNumber", &pg_uidNumber, &text );
if ( rc != LDAP_SUCCESS ) {
fprintf( stderr, "%s line %d: posixGroup ACL: "
"unable to lookup \"uidNumber\" "
"attributeDescription (%d: %s).\n",
fname, lineno, rc, text );
goto cleanup;
}
}
*privp = (void *)pg;
return 0;
cleanup:
(void)pg_dynacl_destroy( (void *)pg );
return 1;
}
static int
pg_dynacl_unparse(
void *priv,
struct berval *bv )
{
pg_t *pg = (pg_t *)priv;
char *ptr;
bv->bv_len = STRLENOF( " dynacl/posixGroup.expand=" ) + pg->pg_pat.bv_len;
bv->bv_val = ch_malloc( bv->bv_len + 1 );
ptr = lutil_strcopy( bv->bv_val, " dynacl/posixGroup" );
switch ( pg->pg_style ) {
case ACL_STYLE_BASE:
ptr = lutil_strcopy( ptr, ".exact=" );
break;
case ACL_STYLE_EXPAND:
ptr = lutil_strcopy( ptr, ".expand=" );
break;
default:
assert( 0 );
}
ptr = lutil_strncopy( ptr, pg->pg_pat.bv_val, pg->pg_pat.bv_len );
ptr[ 0 ] = '\0';
bv->bv_len = ptr - bv->bv_val;
return 0;
}
static int
pg_dynacl_mask(
void *priv,
struct slap_op *op,
Entry *target,
AttributeDescription *desc,
struct berval *val,
int nmatch,
regmatch_t *matches,
slap_access_t *grant,
slap_access_t *deny )
{
pg_t *pg = (pg_t *)priv;
Entry *group = NULL,
*user = NULL;
int rc;
Backend *be = op->o_bd,
*group_be = NULL,
*user_be = NULL;
struct berval group_ndn;
ACL_INVALIDATE( *deny );
/* get user */
if ( target && dn_match( &target->e_nname, &op->o_ndn ) ) {
user = target;
rc = LDAP_SUCCESS;
} else {
user_be = op->o_bd = select_backend( &op->o_ndn, 0, 0 );
if ( op->o_bd == NULL ) {
op->o_bd = be;
return 0;
}
rc = be_entry_get_rw( op, &op->o_ndn, pg_posixAccount, pg_uidNumber, 0, &user );
}
if ( rc != LDAP_SUCCESS || user == NULL ) {
op->o_bd = be;
return 0;
}
/* get target */
if ( pg->pg_style == ACL_STYLE_EXPAND ) {
char buf[ 1024 ];
struct berval bv;
bv.bv_len = sizeof( buf ) - 1;
bv.bv_val = buf;
if ( acl_string_expand( &bv, &pg->pg_pat,
target->e_nname.bv_val,
nmatch, matches ) )
{
goto cleanup;
}
if ( dnNormalize( 0, NULL, NULL, &bv, &group_ndn,
op->o_tmpmemctx ) != LDAP_SUCCESS )
{
/* did not expand to a valid dn */
goto cleanup;
}
} else {
group_ndn = pg->pg_pat;
}
if ( target && dn_match( &target->e_nname, &group_ndn ) ) {
group = target;
rc = LDAP_SUCCESS;
} else {
group_be = op->o_bd = select_backend( &group_ndn, 0, 0 );
if ( op->o_bd == NULL ) {
goto cleanup;
}
rc = be_entry_get_rw( op, &group_ndn, pg_posixGroup, pg_memberUid, 0, &group );
}
if ( group_ndn.bv_val != pg->pg_pat.bv_val ) {
op->o_tmpfree( group_ndn.bv_val, op->o_tmpmemctx );
}
if ( rc == LDAP_SUCCESS && group != NULL ) {
Attribute *a_uid,
*a_member;
a_uid = attr_find( user->e_attrs, pg_uidNumber);
if ( !a_uid || !BER_BVISNULL( &a_uid->a_nvals[ 1 ] ) ) {
rc = LDAP_NO_SUCH_ATTRIBUTE;
} else {
a_member = attr_find( group->e_attrs, pg_memberUid );
if ( !a_member ) {
rc = LDAP_NO_SUCH_ATTRIBUTE;
} else {
rc = value_find_ex( pg_memberUid,
SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
a_member->a_nvals, &a_uid->a_nvals[ 0 ],
op->o_tmpmemctx );
}
}
} else {
rc = LDAP_NO_SUCH_OBJECT;
}
if ( rc == LDAP_SUCCESS ) {
ACL_LVL_ASSIGN_WRITE( *grant );
}
cleanup:;
if ( group != NULL && group != target ) {
op->o_bd = group_be;
be_entry_release_r( op, group );
op->o_bd = be;
}
if ( user != NULL && user != target ) {
op->o_bd = user_be;
be_entry_release_r( op, group );
op->o_bd = be;
}
return 0;
}
static int
pg_dynacl_destroy(
void *priv )
{
pg_t *pg = (pg_t *)priv;
if ( pg != NULL ) {
if ( !BER_BVISNULL( &pg->pg_pat ) ) {
ber_memfree( pg->pg_pat.bv_val );
}
ch_free( pg );
}
return 0;
}
static struct slap_dynacl_t pg_dynacl = {
"posixGroup",
pg_dynacl_parse,
pg_dynacl_unparse,
pg_dynacl_mask,
pg_dynacl_destroy
};
int
init_module( int argc, char *argv[] )
{
return slap_dynacl_register( &pg_dynacl );
}
#endif /* SLAP_DYNACL */
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment