From 92a8025f298f107f53f33b8b809bc294e5fb5567 Mon Sep 17 00:00:00 2001 From: Quanah Gibson-Mount Date: Tue, 20 Jul 2021 21:09:58 +0000 Subject: [PATCH] ITS#6244 - Add "now" dynacl module --- contrib/slapd-modules/acl/Makefile | 6 +- contrib/slapd-modules/acl/README.now | 65 ++++++++ contrib/slapd-modules/acl/now.c | 234 +++++++++++++++++++++++++++ 3 files changed, 304 insertions(+), 1 deletion(-) create mode 100644 contrib/slapd-modules/acl/README.now create mode 100644 contrib/slapd-modules/acl/now.c diff --git a/contrib/slapd-modules/acl/Makefile b/contrib/slapd-modules/acl/Makefile index 090575d30f..2195e2d724 100644 --- a/contrib/slapd-modules/acl/Makefile +++ b/contrib/slapd-modules/acl/Makefile @@ -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 diff --git a/contrib/slapd-modules/acl/README.now b/contrib/slapd-modules/acl/README.now new file mode 100644 index 0000000000..5af925558f --- /dev/null +++ b/contrib/slapd-modules/acl/README.now @@ -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 + diff --git a/contrib/slapd-modules/acl/now.c b/contrib/slapd-modules/acl/now.c new file mode 100644 index 0000000000..cc4019bca4 --- /dev/null +++ b/contrib/slapd-modules/acl/now.c @@ -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 + * . + */ +/* 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 + +#include +#include +#include + +/* 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, ×tamp ); + + rc = value_match( &match, now->now_ad, mr, SLAP_MR_ORDERING, + ×tamp, &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 */ -- 2.47.3