1 /* $OpenLDAP$ */
2 /*
3 * Copyright 1998-2021 The OpenLDAP Foundation.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted only as authorized by the OpenLDAP
8 * Public License.
9 *
10 * A copy of this license is available in the file LICENSE in the
11 * top-level directory of the distribution or, alternatively, at
12 * <http://www.OpenLDAP.org/license.html>.
13 */
14 /* ACKNOWLEDGEMENTS:
15 * This work was initially developed by Pierangelo Masarati
16 * for inclusion in OpenLDAP Software.
17 */
18 /*
19 * This dynacl module compares the value of a given attribute type
20 * with the current time. The syntax is
21 *
22 * dynacl/now=<=attr
23 *
24 * where attr is an attribute whose syntax is generalizedTime
25 * with generalizedTimeOrderingMatch as ORDERING rule.
26 */
27
28 #include <portable.h>
29
30 #include <ac/string.h>
31 #include <slap.h>
32 #include <lutil.h>
33
34 /* Need dynacl... */
35
36 #ifdef SLAP_DYNACL
37
38 typedef enum {
39 NOW_GE,
40 NOW_LE
41 } now_style_t;
42
43 typedef struct now_t {
44 AttributeDescription *now_ad;
45 now_style_t now_style;
46 } now_t;
47
48 static int now_dynacl_destroy( void *priv );
49
50 static int
now_dynacl_parse(const char * fname,int lineno,const char * opts,slap_style_t style,const char * pattern,void ** privp)51 now_dynacl_parse(
52 const char *fname,
53 int lineno,
54 const char *opts,
55 slap_style_t style,
56 const char *pattern,
57 void **privp )
58 {
59 now_t *now;
60 now_style_t sty = NOW_GE;
61 AttributeDescription *ad = NULL;
62 int rc;
63 const char *text = NULL;
64 Syntax *syn;
65 MatchingRule *mr;
66
67 syn = syn_find( "1.3.6.1.4.1.1466.115.121.1.24" );
68 if ( syn == NULL ) {
69 fprintf( stderr,
70 "%s line %d: unable to find syntax 1.3.6.1.4.1.1466.115.121.1.24 (generalizedTime)\n",
71 fname, lineno );
72 return 1;
73 }
74
75 mr = mr_find( "generalizedTimeOrderingMatch" );
76 if ( mr == NULL ) {
77 fprintf( stderr,
78 "%s line %d: unable to find generalizedTimeOrderingMatch rule\n",
79 fname, lineno );
80 return 1;
81 }
82
83 if ( strncmp( pattern, ">=", STRLENOF( ">=" ) ) == 0 ) {
84 sty = NOW_GE;
85 pattern += 2;
86
87 } else if ( strncmp( pattern, "<=", STRLENOF( "<=" ) ) == 0 ) {
88 sty = NOW_LE;
89 pattern += 2;
90 }
91
92 rc = slap_str2ad( pattern, &ad, &text );
93 if ( rc != LDAP_SUCCESS ) {
94 fprintf( stderr, "%s line %d: now ACL: "
95 "unable to lookup \"%s\" "
96 "attributeDescription (%d: %s).\n",
97 fname, lineno, pattern, rc, text );
98 return 1;
99 }
100
101 if ( ad->ad_type->sat_syntax != syn ) {
102 fprintf( stderr,
103 "%s line %d: syntax of attribute \"%s\" is not 1.3.6.1.4.1.1466.115.121.1.24 (generalizedTime)\n",
104 fname, lineno, ad->ad_cname.bv_val );
105 return 1;
106 }
107
108 if ( ad->ad_type->sat_ordering != mr ) {
109 fprintf( stderr,
110 "%s line %d: ordering matching rule of attribute \"%s\" is not generalizedTimeOrderingMatch\n",
111 fname, lineno, ad->ad_cname.bv_val );
112 return 1;
113 }
114
115 now = ch_calloc( 1, sizeof( now_t ) );
116 now->now_ad = ad;
117 now->now_style = sty;
118
119 *privp = (void *)now;
120
121 return 0;
122 }
123
124 static int
now_dynacl_unparse(void * priv,struct berval * bv)125 now_dynacl_unparse(
126 void *priv,
127 struct berval *bv )
128 {
129 now_t *now = (now_t *)priv;
130 char *ptr;
131
132 bv->bv_len = STRLENOF( " dynacl/now=" ) + 2 + now->now_ad->ad_cname.bv_len;
133 bv->bv_val = ch_malloc( bv->bv_len + 1 );
134
135 ptr = lutil_strcopy( bv->bv_val, " dynacl/now=" );
136 ptr[ 0 ] = now->now_style == NOW_GE ? '>' : '<';
137 ptr[ 1 ] = '=';
138 ptr += 2;
139 ptr = lutil_strncopy( ptr, now->now_ad->ad_cname.bv_val, now->now_ad->ad_cname.bv_len );
140 ptr[ 0 ] = '\0';
141
142 bv->bv_len = ptr - bv->bv_val;
143
144 return 0;
145 }
146
147 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)148 now_dynacl_mask(
149 void *priv,
150 Operation *op,
151 Entry *target,
152 AttributeDescription *desc,
153 struct berval *val,
154 int nmatch,
155 regmatch_t *matches,
156 slap_access_t *grant,
157 slap_access_t *deny )
158 {
159 now_t *now = (now_t *)priv;
160 int rc;
161 Attribute *a;
162
163 ACL_INVALIDATE( *deny );
164
165 assert( target != NULL );
166
167 a = attr_find( target->e_attrs, now->now_ad );
168 if ( !a ) {
169 rc = LDAP_NO_SUCH_ATTRIBUTE;
170
171 } else {
172 char timebuf[ LDAP_LUTIL_GENTIME_BUFSIZE ];
173 struct berval timestamp;
174 time_t t = slap_get_time();
175 int match;
176 MatchingRule *mr = now->now_ad->ad_type->sat_ordering;
177 const char *text = NULL;
178
179 timestamp.bv_val = timebuf;
180 timestamp.bv_len = sizeof( timebuf );
181
182 slap_timestamp( &t, ×tamp );
183
184 rc = value_match( &match, now->now_ad, mr, SLAP_MR_ORDERING,
185 ×tamp, &a->a_vals[ 0 ], &text );
186 if ( rc == LDAP_SUCCESS ) {
187 if ( now->now_style == NOW_LE ) {
188 match = -match;
189 }
190
191 if ( match >= 0 ) {
192 rc = LDAP_COMPARE_TRUE;
193
194 } else {
195 rc = LDAP_COMPARE_FALSE;
196 }
197 }
198 }
199
200 if ( rc == LDAP_COMPARE_TRUE ) {
201 ACL_LVL_ASSIGN_WRITE( *grant );
202 }
203
204 return 0;
205 }
206
207 static int
now_dynacl_destroy(void * priv)208 now_dynacl_destroy(
209 void *priv )
210 {
211 now_t *now = (now_t *)priv;
212
213 if ( now != NULL ) {
214 ch_free( now );
215 }
216
217 return 0;
218 }
219
220 static struct slap_dynacl_t now_dynacl = {
221 "now",
222 now_dynacl_parse,
223 now_dynacl_unparse,
224 now_dynacl_mask,
225 now_dynacl_destroy
226 };
227
228 int
init_module(int argc,char * argv[])229 init_module( int argc, char *argv[] )
230 {
231 return slap_dynacl_register( &now_dynacl );
232 }
233
234 #endif /* SLAP_DYNACL */
235