Commit 01fbca59 authored by Kurt Zeilenga's avatar Kurt Zeilenga
Browse files

Sync with HEAD

parent b2da42b8
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 */
......@@ -37,22 +37,19 @@ directive.
.TP
.B syncprov-checkpoint <ops> <minutes>
After a write operation has succeeded, write the contextCSN to the underlying
database if <ops> write operations or more than <minutes> time have passed
database if
.B <ops>
write operations or more than
.B <minutes>
time have passed
since the last checkpoint. Checkpointing is disabled by default.
.TP
.B syncprov-sessionlog <sid> <size>
Specify a session log for recording information about entries that have been
scoped out of the content identified by
.BR <sid> .
The number of entries in the log is limited by
.BR <size> .
Both
.B <sid>
and
.B <size>
must be non-negative integers, and
.B <sid>
can have no more than three decimal digits.
.B syncprov-sessionlog <ops>
Specify a session log for recording information about write operations made
on the database. The
.B <ops>
specifies the number of operations that are recorded in the log. All write
operations (except Adds) are recorded in the log.
When using the session log, it is helpful to set an eq index on the
entryUUID attribute in the underlying database.
.SH FILES
......
......@@ -58,7 +58,7 @@ attributes, as these will generally not be unique, nor are they operational
attributes.
.TP
.B unique_attributes <attribute...>
Specify one or more attributes which for which uniqueness will be enforced.
Specify one or more attributes for which uniqueness will be enforced.
If not specified, all attributes which are not operational (eg, system
attributes such as
.B entryUUID )
......@@ -79,7 +79,15 @@ on the
list, and included in the
.B unique_attributes
list, in that order. This makes it possible to create interesting and
unusable configurations.
unusable configurations. Usually only one of
.B unique_ignore
or
.B unique_attributes
should be configured; use
.B unique_ignore
if the majority of attributes should be unique, and use
.B unique_attributes
if only a small set of attributes should be unique.
.LP
Typical attributes for the
.B unique_ignore
......
......@@ -62,7 +62,14 @@ cannot be used in conjunction with the
option.
.TP
.BI \-a " filter"
Only dump entries matching the asserted filter.
Only dump entries matching the asserted filter.
For example
slapcat -a \\
"(!(entryDN:dnSubtreeMatch:=ou=People,dc=example,dc=com))"
will dump all but the "ou=People,dc=example,dc=com" subtree
of the "dc=example,dc=com" database.
.TP
.BI \-s " subtree-dn"
Only dump entries in the subtree specified by this DN.
......
......@@ -530,6 +530,7 @@ int slapi_x_backend_get_flags( const Slapi_Backend *be, unsigned long *flags );
#define SLAPI_X_OPERATION_DELETE_GLUE_PARENT 1305
#define SLAPI_X_MANAGEDIT 1306
#define SLAPI_X_OPERATION_NO_SCHEMA_CHECK 1307
#define SLAPI_X_ADD_STRUCTURAL_CLASS 1308
/* Authentication types */
#define SLAPD_AUTH_NONE "none"
......
......@@ -1228,14 +1228,9 @@ ldap_url_duplist (LDAPURLDesc *ludlist)
return dest;
}
int
ldap_url_parselist (LDAPURLDesc **ludlist, const char *url )
{
return ldap_url_parselist_ext( ludlist, url, ", " );
}
int
ldap_url_parselist_ext (LDAPURLDesc **ludlist, const char *url, const char *sep )
static int
ldap_url_parselist_int (LDAPURLDesc **ludlist, const char *url, const char *sep,
int (*url_parse)( const char *, LDAPURLDesc ** ) )
{
int i, rc;
LDAPURLDesc *ludp;
......@@ -1254,7 +1249,7 @@ ldap_url_parselist_ext (LDAPURLDesc **ludlist, const char *url, const char *sep
for (i = 0; urls[i] != NULL; i++) ;
/* ...and put them in the "stack" backward */
while (--i >= 0) {
rc = ldap_url_parse( urls[i], &ludp );
rc = url_parse( urls[i], &ludp );
if ( rc != 0 ) {
ldap_charray_free(urls);
ldap_free_urllist(*ludlist);
......@@ -1268,6 +1263,18 @@ ldap_url_parselist_ext (LDAPURLDesc **ludlist, const char *url, const char *sep
return LDAP_URL_SUCCESS;
}
int
ldap_url_parselist (LDAPURLDesc **ludlist, const char *url )
{
return ldap_url_parselist_int( ludlist, url, ", ", ldap_url_parse );
}
int
ldap_url_parselist_ext (LDAPURLDesc **ludlist, const char *url, const char *sep )
{
return ldap_url_parselist_int( ludlist, url, sep, ldap_url_parse_ext );
}
int
ldap_url_parsehosts(
LDAPURLDesc **ludlist,
......
......@@ -206,10 +206,7 @@ struct rewrite_rule {
char *lr_pattern;
char *lr_subststring;
char *lr_flagstring;
#ifdef USE_REWRITE_LDAP_PVT_THREADS
ldap_pvt_thread_mutex_t lr_mutex;
#endif /* USE_REWRITE_LDAP_PVT_THREADS */
regex_t lr_regex;
regex_t lr_regex;
/*
* I was thinking about some kind of per-rule mutex, but there's
......
......@@ -346,14 +346,6 @@ rewrite_rule_compile(
return REWRITE_ERR;
}
#ifdef USE_REWRITE_LDAP_PVT_THREADS
if ( ldap_pvt_thread_mutex_init( &rule->lr_mutex ) ) {
regfree( &rule->lr_regex );
free( rule );
return REWRITE_ERR;
}
#endif /* USE_REWRITE_LDAP_PVT_THREADS */
/*
* Just to remember them ...
*/
......@@ -427,13 +419,7 @@ recurse:;
op->lo_num_passes++;
#ifdef USE_REWRITE_LDAP_PVT_THREADS
ldap_pvt_thread_mutex_lock( &rule->lr_mutex );
#endif /* USE_REWRITE_LDAP_PVT_THREADS */
rc = regexec( &rule->lr_regex, string, nmatch, match, 0 );
#ifdef USE_REWRITE_LDAP_PVT_THREADS
ldap_pvt_thread_mutex_unlock( &rule->lr_mutex );
#endif /* USE_REWRITE_LDAP_PVT_THREADS */
if ( rc != 0 ) {
if ( *result == NULL && string != arg ) {
free( string );
......@@ -503,9 +489,6 @@ rewrite_rule_destroy(
}
regfree( &rule->lr_regex );
#ifdef USE_REWRITE_LDAP_PVT_THREADS
ldap_pvt_thread_mutex_destroy( &rule->lr_mutex );
#endif /* USE_REWRITE_LDAP_PVT_THREADS */
for ( action = rule->lr_action; action; ) {
struct rewrite_action *curraction = action;
......
......@@ -38,6 +38,7 @@ SRCS = main.c globals.c bconfig.c config.c daemon.c \
backover.c ctxcsn.c ldapsync.c frontend.c \
slapadd.c slapcat.c slapcommon.c slapdn.c slapindex.c \
slappasswd.c slaptest.c slapauth.c slapacl.c component.c \
aci.c \
$(@PLAT@_SRCS)
OBJS = main.o globals.o bconfig.o config.o daemon.o \
......@@ -55,6 +56,7 @@ OBJS = main.o globals.o bconfig.o config.o daemon.o \
backover.o ctxcsn.o ldapsync.o frontend.o \
slapadd.o slapcat.o slapcommon.o slapdn.o slapindex.o \
slappasswd.o slaptest.o slapauth.o slapacl.o component.o \
aci.o \
$(@PLAT@_OBJS)
LDAP_INCDIR= ../../include -I$(srcdir) -I$(srcdir)/slapi -I.
......
......@@ -51,6 +51,9 @@ do_abandon( Operation *op, SlapReply *rs )
return SLAPD_DISCONNECT;
}
Statslog( LDAP_DEBUG_STATS, "%s ABANDON msg=%ld\n",
op->o_log_prefix, (long) id, 0, 0, 0 );
if( get_ctrls( op, rs, 0 ) != LDAP_SUCCESS ) {
Debug( LDAP_DEBUG_ANY, "do_abandon: get_ctrls failed\n", 0, 0 ,0 );
return rs->sr_err;
......
This diff is collapsed.
This diff is collapsed.
......@@ -1109,7 +1109,7 @@ parse_acl(
}
} else {
b->a_group_oc = oc_find(SLAPD_GROUP_CLASS);
b->a_group_oc = oc_find( SLAPD_GROUP_CLASS );
if( b->a_group_oc == NULL ) {
fprintf( stderr,
......@@ -2250,6 +2250,20 @@ access_free( Access *a )
if ( !BER_BVISNULL( &a->a_group_pat ) ) {
free( a->a_group_pat.bv_val );
}
if ( a->a_dynacl != NULL ) {
slap_dynacl_t *da;
for ( da = a->a_dynacl; da; ) {
slap_dynacl_t *tmp = da;
da = da->da_next;
if ( tmp->da_destroy ) {
tmp->da_destroy( tmp->da_private );
}
ch_free( tmp );
}
}
free( a );
}
......@@ -2263,6 +2277,9 @@ acl_free( AccessControl *a )
filter_free( a->acl_filter );
}
if ( !BER_BVISNULL( &a->acl_dn_pat ) ) {
if ( a->acl_dn_style == ACL_STYLE_REGEX ) {
regfree( &a->acl_dn_re );
}
free ( a->acl_dn_pat.bv_val );
}
if ( a->acl_attrs ) {
......@@ -2523,8 +2540,9 @@ access2text( Access *b, char *ptr )
for ( da = b->a_dynacl; da; da = da->da_next ) {
if ( da->da_unparse ) {
struct berval bv;