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