xref: /netbsd-src/external/bsd/openldap/dist/contrib/slapd-modules/allop/allop.c (revision 549b59ed3ccf0d36d3097190a0db27b770f3a839)
1 /*	$NetBSD: allop.c,v 1.3 2021/08/14 16:14:50 christos Exp $	*/
2 
3 /* allop.c - returns all operational attributes when appropriate */
4 /* $OpenLDAP$ */
5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6  *
7  * Copyright 2005-2021 The OpenLDAP Foundation.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted only as authorized by the OpenLDAP
12  * Public License.
13  *
14  * A copy of this license is available in the file LICENSE in the
15  * top-level directory of the distribution or, alternatively, at
16  * <http://www.OpenLDAP.org/license.html>.
17  */
18 /* ACKNOWLEDGEMENTS:
19  * This work was initially developed by Pierangelo Masarati for inclusion in
20  * OpenLDAP Software.
21  */
22 
23 /*
24  * The intended usage is as a global overlay for use with those clients
25  * that do not make use of the RFC3673 allOp ("+") in the requested
26  * attribute list, but expect all operational attributes to be returned.
27  * Usage: add
28  *
29 
30 overlay		allop
31 allop-URI	<ldapURI>
32 
33  *
34  * if the allop-URI is not given, the rootDSE, i.e. "ldap:///??base",
35  * is assumed.
36  */
37 
38 #include <sys/cdefs.h>
39 __RCSID("$NetBSD: allop.c,v 1.3 2021/08/14 16:14:50 christos Exp $");
40 
41 #include "portable.h"
42 
43 #include <stdio.h>
44 #include <ac/string.h>
45 
46 #include "slap.h"
47 #include "slap-config.h"
48 
49 #define	SLAP_OVER_VERSION_REQUIRE(major,minor,patch) \
50 	( \
51 		( LDAP_VENDOR_VERSION_MAJOR == X || LDAP_VENDOR_VERSION_MAJOR >= (major) ) \
52 		&& ( LDAP_VENDOR_VERSION_MINOR == X || LDAP_VENDOR_VERSION_MINOR >= (minor) ) \
53 		&& ( LDAP_VENDOR_VERSION_PATCH == X || LDAP_VENDOR_VERSION_PATCH >= (patch) ) \
54 	)
55 
56 #if !SLAP_OVER_VERSION_REQUIRE(2,3,0)
57 #error "version mismatch"
58 #endif
59 
60 typedef struct allop_t {
61 	struct berval	ao_ndn;
62 	int		ao_scope;
63 } allop_t;
64 
65 static int
allop_db_config(BackendDB * be,const char * fname,int lineno,int argc,char ** argv)66 allop_db_config(
67 	BackendDB	*be,
68 	const char	*fname,
69 	int		lineno,
70 	int		argc,
71 	char		**argv )
72 {
73 	slap_overinst	*on = (slap_overinst *)be->bd_info;
74 	allop_t		*ao = (allop_t *)on->on_bi.bi_private;
75 
76 	if ( strcasecmp( argv[ 0 ], "allop-uri" ) == 0 ) {
77 		LDAPURLDesc	*lud;
78 		struct berval	dn,
79 				ndn;
80 		int		scope,
81 				rc = LDAP_SUCCESS;
82 
83 		if ( argc != 2 ) {
84 			fprintf( stderr, "%s line %d: "
85 				"need exactly 1 arg "
86 				"in \"allop-uri <ldapURI>\" "
87 				"directive.\n",
88 				fname, lineno );
89 			return 1;
90 		}
91 
92 		if ( ldap_url_parse( argv[ 1 ], &lud ) != LDAP_URL_SUCCESS ) {
93 			return -1;
94 		}
95 
96 		scope = lud->lud_scope;
97 		if ( scope == LDAP_SCOPE_DEFAULT ) {
98 			scope = LDAP_SCOPE_BASE;
99 		}
100 
101 		if ( lud->lud_dn == NULL || lud->lud_dn[ 0 ] == '\0' ) {
102 			if ( scope == LDAP_SCOPE_BASE ) {
103 				BER_BVZERO( &ndn );
104 
105 			} else {
106 				ber_str2bv( "", 0, 1, &ndn );
107 			}
108 
109 		} else {
110 
111 			ber_str2bv( lud->lud_dn, 0, 0, &dn );
112 			rc = dnNormalize( 0, NULL, NULL, &dn, &ndn, NULL );
113 		}
114 
115 		ldap_free_urldesc( lud );
116 		if ( rc != LDAP_SUCCESS ) {
117 			return -1;
118 		}
119 
120 		if ( BER_BVISNULL( &ndn ) ) {
121 			/* rootDSE */
122 			if ( ao != NULL ) {
123 				ch_free( ao->ao_ndn.bv_val );
124 				ch_free( ao );
125 				on->on_bi.bi_private = NULL;
126 			}
127 
128 		} else {
129 			if ( ao == NULL ) {
130 				ao = ch_calloc( 1, sizeof( allop_t ) );
131 				on->on_bi.bi_private = (void *)ao;
132 
133 			} else {
134 				ch_free( ao->ao_ndn.bv_val );
135 			}
136 
137 			ao->ao_ndn = ndn;
138 			ao->ao_scope = scope;
139 		}
140 
141 	} else {
142 		return SLAP_CONF_UNKNOWN;
143 	}
144 
145 	return 0;
146 }
147 
148 static int
allop_db_destroy(BackendDB * be,ConfigReply * cr)149 allop_db_destroy( BackendDB *be, ConfigReply *cr )
150 {
151 	slap_overinst	*on = (slap_overinst *)be->bd_info;
152 	allop_t		*ao = (allop_t *)on->on_bi.bi_private;
153 
154 	if ( ao != NULL ) {
155 		assert( !BER_BVISNULL( &ao->ao_ndn ) );
156 
157 		ch_free( ao->ao_ndn.bv_val );
158 		ch_free( ao );
159 		on->on_bi.bi_private = NULL;
160 	}
161 
162 	return 0;
163 }
164 
165 static int
allop_op_search(Operation * op,SlapReply * rs)166 allop_op_search( Operation *op, SlapReply *rs )
167 {
168 	slap_overinst	*on = (slap_overinst *)op->o_bd->bd_info;
169 	allop_t		*ao = (allop_t *)on->on_bi.bi_private;
170 
171 	slap_mask_t	mask;
172 	int		i,
173 			add_allUser = 0;
174 
175 	if ( ao == NULL ) {
176 		if ( !BER_BVISEMPTY( &op->o_req_ndn )
177 			|| op->ors_scope != LDAP_SCOPE_BASE )
178 		{
179 			return SLAP_CB_CONTINUE;
180 		}
181 
182 	} else {
183 		if ( !dnIsSuffix( &op->o_req_ndn, &ao->ao_ndn ) ) {
184 			return SLAP_CB_CONTINUE;
185 		}
186 
187 		switch ( ao->ao_scope ) {
188 		case LDAP_SCOPE_BASE:
189 			if ( op->o_req_ndn.bv_len != ao->ao_ndn.bv_len ) {
190 				return SLAP_CB_CONTINUE;
191 			}
192 			break;
193 
194 		case LDAP_SCOPE_ONELEVEL:
195 			if ( op->ors_scope == LDAP_SCOPE_BASE ) {
196 				struct berval	rdn = op->o_req_ndn;
197 
198 				rdn.bv_len -= ao->ao_ndn.bv_len + STRLENOF( "," );
199 				if ( !dnIsOneLevelRDN( &rdn ) ) {
200 					return SLAP_CB_CONTINUE;
201 				}
202 
203 				break;
204 			}
205 			return SLAP_CB_CONTINUE;
206 
207 		case LDAP_SCOPE_SUBTREE:
208 			break;
209 		}
210 	}
211 
212 	mask = slap_attr_flags( op->ors_attrs );
213 	if ( SLAP_OPATTRS( mask ) ) {
214 		return SLAP_CB_CONTINUE;
215 	}
216 
217 	if ( !SLAP_USERATTRS( mask ) ) {
218 		return SLAP_CB_CONTINUE;
219 	}
220 
221 	i = 0;
222 	if ( op->ors_attrs == NULL ) {
223 		add_allUser = 1;
224 
225 	} else {
226 		for ( ; !BER_BVISNULL( &op->ors_attrs[ i ].an_name ); i++ )
227 			;
228 	}
229 
230 	op->ors_attrs = op->o_tmprealloc( op->ors_attrs,
231 		sizeof( AttributeName ) * ( i + add_allUser + 2 ),
232 		op->o_tmpmemctx );
233 
234 	if ( add_allUser ) {
235 		op->ors_attrs[ i ] = slap_anlist_all_user_attributes[ 0 ];
236 		i++;
237 	}
238 
239 	op->ors_attrs[ i ] = slap_anlist_all_operational_attributes[ 0 ];
240 
241 	BER_BVZERO( &op->ors_attrs[ i + 1 ].an_name );
242 
243 	return SLAP_CB_CONTINUE;
244 }
245 
246 static slap_overinst 		allop;
247 
248 int
allop_init()249 allop_init()
250 {
251 	allop.on_bi.bi_type = "allop";
252 
253 	allop.on_bi.bi_flags = SLAPO_BFLAG_SINGLE;
254 	allop.on_bi.bi_db_config = allop_db_config;
255 	allop.on_bi.bi_db_destroy = allop_db_destroy;
256 
257 	allop.on_bi.bi_op_search = allop_op_search;
258 
259 	return overlay_register( &allop );
260 }
261 
262 int
init_module(int argc,char * argv[])263 init_module( int argc, char *argv[] )
264 {
265 	return allop_init();
266 }
267 
268