]> git.ipfire.org Git - thirdparty/openldap.git/commitdiff
ITS#6244 - Add "now" dynacl module
authorQuanah Gibson-Mount <quanah@openldap.org>
Tue, 20 Jul 2021 21:09:58 +0000 (21:09 +0000)
committerQuanah Gibson-Mount <quanah@openldap.org>
Thu, 22 Jul 2021 17:12:58 +0000 (17:12 +0000)
contrib/slapd-modules/acl/Makefile
contrib/slapd-modules/acl/README.now [new file with mode: 0644]
contrib/slapd-modules/acl/now.c [new file with mode: 0644]

index 090575d30fe62c521ccdcb3f6bcee667c8aac9c1..2195e2d7242bea4202cf671e352bc2eee2861241 100644 (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
 
diff --git a/contrib/slapd-modules/acl/README.now b/contrib/slapd-modules/acl/README.now
new file mode 100644 (file)
index 0000000..5af9255
--- /dev/null
@@ -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 (file)
index 0000000..cc4019b
--- /dev/null
@@ -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 */