summaryrefslogtreecommitdiffstats
path: root/contrib/slapd-modules/acl/now.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/slapd-modules/acl/now.c')
-rw-r--r--contrib/slapd-modules/acl/now.c234
1 files changed, 234 insertions, 0 deletions
diff --git a/contrib/slapd-modules/acl/now.c b/contrib/slapd-modules/acl/now.c
new file mode 100644
index 0000000..582c01f
--- /dev/null
+++ b/contrib/slapd-modules/acl/now.c
@@ -0,0 +1,234 @@
+/* $OpenLDAP$ */
+/*
+ * Copyright 1998-2022 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 */