ITS#6244 - Add "now" dynacl module

This commit is contained in:
Quanah Gibson-Mount 2021-07-20 21:09:58 +00:00
parent 2c0707cf13
commit 92a8025f29
3 changed files with 304 additions and 1 deletions

View File

@ -13,7 +13,7 @@ DEFS =
INCS = $(LDAP_INC)
LIBS = $(LDAP_LIB)
PROGRAMS = posixgroup.la gssacl.la
PROGRAMS = posixgroup.la gssacl.la now.la
LTVER = 0:0:0
prefix=/usr/local
@ -39,6 +39,10 @@ gssacl.la: gssacl.lo
$(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -version-info $(LTVER) \
-rpath $(moduledir) -module -o $@ $? $(LIBS)
now.la: now.lo
$(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -version-info $(LTVER) \
-rpath $(moduledir) -module -o $@ $? $(LIBS)
clean:
rm -rf *.o *.lo *.la .libs

View File

@ -0,0 +1,65 @@
# create a simple slapd.conf (e.g. by running test003)
# define the attributes (replace MyOID with a valid OID)
attributetype ( MyOID:1 NAME 'validityStarts'
EQUALITY generalizedTimeMatch
ORDERING generalizedTimeOrderingMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )
attributetype ( MyOID:2 NAME 'validityEnds'
EQUALITY generalizedTimeMatch
ORDERING generalizedTimeOrderingMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 )
# load the module
moduleload "now_dynacl.so"
# and apply the following access rules
access to dn.exact="dc=example,dc=com"
by * read
access to dn.children="dc=example,dc=com"
by dynacl/now=">=validityStarts" read break
access to dn.children="dc=example,dc=com"
by dynacl/now="<=validityEnds" read
# Then load the LDIF
dn: cn=Too Late,dc=example,dc=com
objectClass: device
objectClass: extensibleObject
cn: Too Late
validityStarts: 20000101000000Z
validityEnds: 20100101000000Z
dn: cn=Just in Time,dc=example,dc=com
objectClass: device
objectClass: extensibleObject
cn: Just in Time
validityStarts: 20100101000000Z
validityEnds: 20200101000000Z
dn: cn=Too Early,dc=example,dc=com
objectClass: device
objectClass: extensibleObject
cn: Too Early
validityStarts: 20200101000000Z
validityEnds: 20300101000000Z
# an anonymous ldapsearch should only find the entry
$ ldapsearch -x -H ldap://:9011 -b dc=example,dc=com -LLL 1.1
dn: cn=Just in Time,dc=example,dc=com

View File

@ -0,0 +1,234 @@
/* $OpenLDAP$ */
/*
* Copyright 1998-2021 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>.
*/
/* ACKNOWLEDGEMENTS:
* This work was initially developed by Pierangelo Masarati
* for inclusion in OpenLDAP Software.
*/
/*
* This dynacl module compares the value of a given attribute type
* with the current time. The syntax is
*
* dynacl/now=<=attr
*
* where attr is an attribute whose syntax is generalizedTime
* with generalizedTimeOrderingMatch as ORDERING rule.
*/
#include <portable.h>
#include <ac/string.h>
#include <slap.h>
#include <lutil.h>
/* Need dynacl... */
#ifdef SLAP_DYNACL
typedef enum {
NOW_GE,
NOW_LE
} now_style_t;
typedef struct now_t {
AttributeDescription *now_ad;
now_style_t now_style;
} now_t;
static int now_dynacl_destroy( void *priv );
static int
now_dynacl_parse(
const char *fname,
int lineno,
const char *opts,
slap_style_t style,
const char *pattern,
void **privp )
{
now_t *now;
now_style_t sty = NOW_GE;
AttributeDescription *ad = NULL;
int rc;
const char *text = NULL;
Syntax *syn;
MatchingRule *mr;
syn = syn_find( "1.3.6.1.4.1.1466.115.121.1.24" );
if ( syn == NULL ) {
fprintf( stderr,
"%s line %d: unable to find syntax 1.3.6.1.4.1.1466.115.121.1.24 (generalizedTime)\n",
fname, lineno );
return 1;
}
mr = mr_find( "generalizedTimeOrderingMatch" );
if ( mr == NULL ) {
fprintf( stderr,
"%s line %d: unable to find generalizedTimeOrderingMatch rule\n",
fname, lineno );
return 1;
}
if ( strncmp( pattern, ">=", STRLENOF( ">=" ) ) == 0 ) {
sty = NOW_GE;
pattern += 2;
} else if ( strncmp( pattern, "<=", STRLENOF( "<=" ) ) == 0 ) {
sty = NOW_LE;
pattern += 2;
}
rc = slap_str2ad( pattern, &ad, &text );
if ( rc != LDAP_SUCCESS ) {
fprintf( stderr, "%s line %d: now ACL: "
"unable to lookup \"%s\" "
"attributeDescription (%d: %s).\n",
fname, lineno, pattern, rc, text );
return 1;
}
if ( ad->ad_type->sat_syntax != syn ) {
fprintf( stderr,
"%s line %d: syntax of attribute \"%s\" is not 1.3.6.1.4.1.1466.115.121.1.24 (generalizedTime)\n",
fname, lineno, ad->ad_cname.bv_val );
return 1;
}
if ( ad->ad_type->sat_ordering != mr ) {
fprintf( stderr,
"%s line %d: ordering matching rule of attribute \"%s\" is not generalizedTimeOrderingMatch\n",
fname, lineno, ad->ad_cname.bv_val );
return 1;
}
now = ch_calloc( 1, sizeof( now_t ) );
now->now_ad = ad;
now->now_style = sty;
*privp = (void *)now;
return 0;
}
static int
now_dynacl_unparse(
void *priv,
struct berval *bv )
{
now_t *now = (now_t *)priv;
char *ptr;
bv->bv_len = STRLENOF( " dynacl/now=" ) + 2 + now->now_ad->ad_cname.bv_len;
bv->bv_val = ch_malloc( bv->bv_len + 1 );
ptr = lutil_strcopy( bv->bv_val, " dynacl/now=" );
ptr[ 0 ] = now->now_style == NOW_GE ? '>' : '<';
ptr[ 1 ] = '=';
ptr += 2;
ptr = lutil_strncopy( ptr, now->now_ad->ad_cname.bv_val, now->now_ad->ad_cname.bv_len );
ptr[ 0 ] = '\0';
bv->bv_len = ptr - bv->bv_val;
return 0;
}
static int
now_dynacl_mask(
void *priv,
Operation *op,
Entry *target,
AttributeDescription *desc,
struct berval *val,
int nmatch,
regmatch_t *matches,
slap_access_t *grant,
slap_access_t *deny )
{
now_t *now = (now_t *)priv;
int rc;
Attribute *a;
ACL_INVALIDATE( *deny );
assert( target != NULL );
a = attr_find( target->e_attrs, now->now_ad );
if ( !a ) {
rc = LDAP_NO_SUCH_ATTRIBUTE;
} else {
char timebuf[ LDAP_LUTIL_GENTIME_BUFSIZE ];
struct berval timestamp;
time_t t = slap_get_time();
int match;
MatchingRule *mr = now->now_ad->ad_type->sat_ordering;
const char *text = NULL;
timestamp.bv_val = timebuf;
timestamp.bv_len = sizeof( timebuf );
slap_timestamp( &t, &timestamp );
rc = value_match( &match, now->now_ad, mr, SLAP_MR_ORDERING,
&timestamp, &a->a_vals[ 0 ], &text );
if ( rc == LDAP_SUCCESS ) {
if ( now->now_style == NOW_LE ) {
match = -match;
}
if ( match >= 0 ) {
rc = LDAP_COMPARE_TRUE;
} else {
rc = LDAP_COMPARE_FALSE;
}
}
}
if ( rc == LDAP_COMPARE_TRUE ) {
ACL_LVL_ASSIGN_WRITE( *grant );
}
return 0;
}
static int
now_dynacl_destroy(
void *priv )
{
now_t *now = (now_t *)priv;
if ( now != NULL ) {
ch_free( now );
}
return 0;
}
static struct slap_dynacl_t now_dynacl = {
"now",
now_dynacl_parse,
now_dynacl_unparse,
now_dynacl_mask,
now_dynacl_destroy
};
int
init_module( int argc, char *argv[] )
{
return slap_dynacl_register( &now_dynacl );
}
#endif /* SLAP_DYNACL */