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, &timestamp );
183 
184 		rc = value_match( &match, now->now_ad, mr, SLAP_MR_ORDERING,
185 			&timestamp, &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