From 35de807a9388adcad75f33b45415658984d52a8c Mon Sep 17 00:00:00 2001 From: Pierangelo Masarati Date: Wed, 17 Aug 2005 14:32:27 +0000 Subject: [PATCH] add posixGroup access control via dynacl as an example of how dynacl work --- contrib/slapd-modules/acl/README | 36 +++ contrib/slapd-modules/acl/posixgroup.c | 320 +++++++++++++++++++++++++ 2 files changed, 356 insertions(+) create mode 100644 contrib/slapd-modules/acl/README create mode 100644 contrib/slapd-modules/acl/posixgroup.c diff --git a/contrib/slapd-modules/acl/README b/contrib/slapd-modules/acl/README new file mode 100644 index 0000000000..b623ab9acc --- /dev/null +++ b/contrib/slapd-modules/acl/README @@ -0,0 +1,36 @@ +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 + by dynacl/posixGroup[.{exact,expand}]= {|" results from +the expansion of submatches in the "" portion. "|" +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. + diff --git a/contrib/slapd-modules/acl/posixgroup.c b/contrib/slapd-modules/acl/posixgroup.c new file mode 100644 index 0000000000..3f06b7fd58 --- /dev/null +++ b/contrib/slapd-modules/acl/posixgroup.c @@ -0,0 +1,320 @@ +/* $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 + * . + */ + +#include + +#include +#include +#include + +/* 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 */ -- 2.39.5