1 /*	$NetBSD: allop.c,v 1.1.1.3 2010/12/12 15:18:54 adam Exp $	*/
2 
3 /* allop.c - returns all operational attributes when appropriate */
4 /* OpenLDAP: pkg/ldap/contrib/slapd-modules/allop/allop.c,v 1.3.2.5 2010/04/13 20:22:25 kurt Exp */
5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6  *
7  * Copyright 2005-2010 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 "portable.h"
39 
40 #include <stdio.h>
41 #include <ac/string.h>
42 
43 #include "slap.h"
44 #include "config.h"
45 
46 #define	SLAP_OVER_VERSION_REQUIRE(major,minor,patch) \
47 	( \
48 		( LDAP_VENDOR_VERSION_MAJOR == X || LDAP_VENDOR_VERSION_MAJOR >= (major) ) \
49 		&& ( LDAP_VENDOR_VERSION_MINOR == X || LDAP_VENDOR_VERSION_MINOR >= (minor) ) \
50 		&& ( LDAP_VENDOR_VERSION_PATCH == X || LDAP_VENDOR_VERSION_PATCH >= (patch) ) \
51 	)
52 
53 #if !SLAP_OVER_VERSION_REQUIRE(2,3,0)
54 #error "version mismatch"
55 #endif
56 
57 typedef struct allop_t {
58 	struct berval	ao_ndn;
59 	int		ao_scope;
60 } allop_t;
61 
62 static int
63 allop_db_config(
64 	BackendDB	*be,
65 	const char	*fname,
66 	int		lineno,
67 	int		argc,
68 	char		**argv )
69 {
70 	slap_overinst	*on = (slap_overinst *)be->bd_info;
71 	allop_t		*ao = (allop_t *)on->on_bi.bi_private;
72 
73 	if ( strcasecmp( argv[ 0 ], "allop-uri" ) == 0 ) {
74 		LDAPURLDesc	*lud;
75 		struct berval	dn,
76 				ndn;
77 		int		scope,
78 				rc = LDAP_SUCCESS;
79 
80 		if ( argc != 2 ) {
81 			fprintf( stderr, "%s line %d: "
82 				"need exactly 1 arg "
83 				"in \"allop-uri <ldapURI>\" "
84 				"directive.\n",
85 				fname, lineno );
86 			return 1;
87 		}
88 
89 		if ( ldap_url_parse( argv[ 1 ], &lud ) != LDAP_URL_SUCCESS ) {
90 			return -1;
91 		}
92 
93 		scope = lud->lud_scope;
94 		if ( scope == LDAP_SCOPE_DEFAULT ) {
95 			scope = LDAP_SCOPE_BASE;
96 		}
97 
98 		if ( lud->lud_dn == NULL || lud->lud_dn[ 0 ] == '\0' ) {
99 			if ( scope == LDAP_SCOPE_BASE ) {
100 				BER_BVZERO( &ndn );
101 
102 			} else {
103 				ber_str2bv( "", 0, 1, &ndn );
104 			}
105 
106 		} else {
107 
108 			ber_str2bv( lud->lud_dn, 0, 0, &dn );
109 			rc = dnNormalize( 0, NULL, NULL, &dn, &ndn, NULL );
110 		}
111 
112 		ldap_free_urldesc( lud );
113 		if ( rc != LDAP_SUCCESS ) {
114 			return -1;
115 		}
116 
117 		if ( BER_BVISNULL( &ndn ) ) {
118 			/* rootDSE */
119 			if ( ao != NULL ) {
120 				ch_free( ao->ao_ndn.bv_val );
121 				ch_free( ao );
122 				on->on_bi.bi_private = NULL;
123 			}
124 
125 		} else {
126 			if ( ao == NULL ) {
127 				ao = ch_calloc( 1, sizeof( allop_t ) );
128 				on->on_bi.bi_private = (void *)ao;
129 
130 			} else {
131 				ch_free( ao->ao_ndn.bv_val );
132 			}
133 
134 			ao->ao_ndn = ndn;
135 			ao->ao_scope = scope;
136 		}
137 
138 	} else {
139 		return SLAP_CONF_UNKNOWN;
140 	}
141 
142 	return 0;
143 }
144 
145 static int
146 allop_db_destroy( BackendDB *be, ConfigReply *cr )
147 {
148 	slap_overinst	*on = (slap_overinst *)be->bd_info;
149 	allop_t		*ao = (allop_t *)on->on_bi.bi_private;
150 
151 	if ( ao != NULL ) {
152 		assert( !BER_BVISNULL( &ao->ao_ndn ) );
153 
154 		ch_free( ao->ao_ndn.bv_val );
155 		ch_free( ao );
156 		on->on_bi.bi_private = NULL;
157 	}
158 
159 	return 0;
160 }
161 
162 static int
163 allop_op_search( Operation *op, SlapReply *rs )
164 {
165 	slap_overinst	*on = (slap_overinst *)op->o_bd->bd_info;
166 	allop_t		*ao = (allop_t *)on->on_bi.bi_private;
167 
168 	slap_mask_t	mask;
169 	int		i,
170 			add_allUser = 0;
171 
172 	if ( ao == NULL ) {
173 		if ( !BER_BVISEMPTY( &op->o_req_ndn )
174 			|| op->ors_scope != LDAP_SCOPE_BASE )
175 		{
176 			return SLAP_CB_CONTINUE;
177 		}
178 
179 	} else {
180 		if ( !dnIsSuffix( &op->o_req_ndn, &ao->ao_ndn ) ) {
181 			return SLAP_CB_CONTINUE;
182 		}
183 
184 		switch ( ao->ao_scope ) {
185 		case LDAP_SCOPE_BASE:
186 			if ( op->o_req_ndn.bv_len != ao->ao_ndn.bv_len ) {
187 				return SLAP_CB_CONTINUE;
188 			}
189 			break;
190 
191 		case LDAP_SCOPE_ONELEVEL:
192 			if ( op->ors_scope == LDAP_SCOPE_BASE ) {
193 				struct berval	rdn = op->o_req_ndn;
194 
195 				rdn.bv_len -= ao->ao_ndn.bv_len + STRLENOF( "," );
196 				if ( !dnIsOneLevelRDN( &rdn ) ) {
197 					return SLAP_CB_CONTINUE;
198 				}
199 
200 				break;
201 			}
202 			return SLAP_CB_CONTINUE;
203 
204 		case LDAP_SCOPE_SUBTREE:
205 			break;
206 		}
207 	}
208 
209 	mask = slap_attr_flags( op->ors_attrs );
210 	if ( SLAP_OPATTRS( mask ) ) {
211 		return SLAP_CB_CONTINUE;
212 	}
213 
214 	if ( !SLAP_USERATTRS( mask ) ) {
215 		return SLAP_CB_CONTINUE;
216 	}
217 
218 	i = 0;
219 	if ( op->ors_attrs == NULL ) {
220 		add_allUser = 1;
221 
222 	} else {
223 		for ( ; !BER_BVISNULL( &op->ors_attrs[ i ].an_name ); i++ )
224 			;
225 	}
226 
227 	op->ors_attrs = op->o_tmprealloc( op->ors_attrs,
228 		sizeof( AttributeName ) * ( i + add_allUser + 2 ),
229 		op->o_tmpmemctx );
230 
231 	if ( add_allUser ) {
232 		op->ors_attrs[ i ] = slap_anlist_all_user_attributes[ 0 ];
233 		i++;
234 	}
235 
236 	op->ors_attrs[ i ] = slap_anlist_all_operational_attributes[ 0 ];
237 
238 	BER_BVZERO( &op->ors_attrs[ i + 1 ].an_name );
239 
240 	return SLAP_CB_CONTINUE;
241 }
242 
243 static slap_overinst 		allop;
244 
245 int
246 allop_init()
247 {
248 	allop.on_bi.bi_type = "allop";
249 
250 	allop.on_bi.bi_db_config = allop_db_config;
251 	allop.on_bi.bi_db_destroy = allop_db_destroy;
252 
253 	allop.on_bi.bi_op_search = allop_op_search;
254 
255 	return overlay_register( &allop );
256 }
257 
258 int
259 init_module( int argc, char *argv[] )
260 {
261 	return allop_init();
262 }
263 
264