rwmconf.c revision 1.1.1.3.24.1 1 1.1.1.3.24.1 tls /* $NetBSD: rwmconf.c,v 1.1.1.3.24.1 2014/08/10 07:09:51 tls Exp $ */
2 1.1.1.2 lukem
3 1.1 lukem /* rwmconf.c - rewrite/map configuration file routines */
4 1.1.1.3.24.1 tls /* $OpenLDAP$ */
5 1.1 lukem /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6 1.1 lukem *
7 1.1.1.3.24.1 tls * Copyright 1999-2014 The OpenLDAP Foundation.
8 1.1 lukem * Portions Copyright 1999-2003 Howard Chu.
9 1.1 lukem * Portions Copyright 2000-2003 Pierangelo Masarati.
10 1.1 lukem * All rights reserved.
11 1.1 lukem *
12 1.1 lukem * Redistribution and use in source and binary forms, with or without
13 1.1 lukem * modification, are permitted only as authorized by the OpenLDAP
14 1.1 lukem * Public License.
15 1.1 lukem *
16 1.1 lukem * A copy of this license is available in the file LICENSE in the
17 1.1 lukem * top-level directory of the distribution or, alternatively, at
18 1.1 lukem * <http://www.OpenLDAP.org/license.html>.
19 1.1 lukem */
20 1.1 lukem /* ACKNOWLEDGEMENTS:
21 1.1 lukem * This work was initially developed by the Howard Chu for inclusion
22 1.1 lukem * in OpenLDAP Software and subsequently enhanced by Pierangelo
23 1.1 lukem * Masarati.
24 1.1 lukem */
25 1.1 lukem
26 1.1 lukem #include "portable.h"
27 1.1 lukem
28 1.1 lukem #ifdef SLAPD_OVER_RWM
29 1.1 lukem
30 1.1 lukem #include <stdio.h>
31 1.1 lukem
32 1.1 lukem #include <ac/string.h>
33 1.1 lukem #include <ac/socket.h>
34 1.1 lukem
35 1.1 lukem #include "slap.h"
36 1.1 lukem #include "rwm.h"
37 1.1 lukem #include "lutil.h"
38 1.1 lukem
39 1.1 lukem int
40 1.1 lukem rwm_map_config(
41 1.1 lukem struct ldapmap *oc_map,
42 1.1 lukem struct ldapmap *at_map,
43 1.1 lukem const char *fname,
44 1.1 lukem int lineno,
45 1.1 lukem int argc,
46 1.1 lukem char **argv )
47 1.1 lukem {
48 1.1 lukem struct ldapmap *map;
49 1.1 lukem struct ldapmapping *mapping;
50 1.1 lukem char *src, *dst;
51 1.1 lukem int is_oc = 0;
52 1.1 lukem int rc = 0;
53 1.1 lukem
54 1.1 lukem if ( argc < 3 || argc > 4 ) {
55 1.1.1.3 adam Debug( LDAP_DEBUG_ANY,
56 1.1 lukem "%s: line %d: syntax is \"map {objectclass | attribute} [<local> | *] {<foreign> | *}\"\n",
57 1.1.1.3 adam fname, lineno, 0 );
58 1.1 lukem return 1;
59 1.1 lukem }
60 1.1 lukem
61 1.1 lukem if ( strcasecmp( argv[1], "objectclass" ) == 0 ) {
62 1.1 lukem map = oc_map;
63 1.1 lukem is_oc = 1;
64 1.1 lukem
65 1.1 lukem } else if ( strcasecmp( argv[1], "attribute" ) == 0 ) {
66 1.1 lukem map = at_map;
67 1.1 lukem
68 1.1 lukem } else {
69 1.1.1.3 adam Debug( LDAP_DEBUG_ANY, "%s: line %d: syntax is "
70 1.1 lukem "\"map {objectclass | attribute} [<local> | *] "
71 1.1 lukem "{<foreign> | *}\"\n",
72 1.1.1.3 adam fname, lineno, 0 );
73 1.1 lukem return 1;
74 1.1 lukem }
75 1.1 lukem
76 1.1.1.2 lukem if ( !is_oc && map->map == NULL ) {
77 1.1.1.2 lukem /* only init if required */
78 1.1.1.2 lukem if ( rwm_map_init( map, &mapping ) != LDAP_SUCCESS ) {
79 1.1.1.2 lukem return 1;
80 1.1.1.2 lukem }
81 1.1.1.2 lukem }
82 1.1.1.2 lukem
83 1.1 lukem if ( strcmp( argv[2], "*" ) == 0 ) {
84 1.1 lukem if ( argc < 4 || strcmp( argv[3], "*" ) == 0 ) {
85 1.1 lukem map->drop_missing = ( argc < 4 );
86 1.1 lukem goto success_return;
87 1.1 lukem }
88 1.1 lukem src = dst = argv[3];
89 1.1 lukem
90 1.1 lukem } else if ( argc < 4 ) {
91 1.1 lukem src = "";
92 1.1 lukem dst = argv[2];
93 1.1 lukem
94 1.1 lukem } else {
95 1.1 lukem src = argv[2];
96 1.1 lukem dst = ( strcmp( argv[3], "*" ) == 0 ? src : argv[3] );
97 1.1 lukem }
98 1.1 lukem
99 1.1 lukem if ( ( map == at_map )
100 1.1 lukem && ( strcasecmp( src, "objectclass" ) == 0
101 1.1 lukem || strcasecmp( dst, "objectclass" ) == 0 ) )
102 1.1 lukem {
103 1.1.1.3 adam Debug( LDAP_DEBUG_ANY,
104 1.1 lukem "%s: line %d: objectclass attribute cannot be mapped\n",
105 1.1.1.3 adam fname, lineno, 0 );
106 1.1 lukem return 1;
107 1.1 lukem }
108 1.1 lukem
109 1.1 lukem mapping = (struct ldapmapping *)ch_calloc( 2,
110 1.1 lukem sizeof(struct ldapmapping) );
111 1.1 lukem if ( mapping == NULL ) {
112 1.1.1.3 adam Debug( LDAP_DEBUG_ANY,
113 1.1 lukem "%s: line %d: out of memory\n",
114 1.1.1.3 adam fname, lineno, 0 );
115 1.1 lukem return 1;
116 1.1 lukem }
117 1.1 lukem ber_str2bv( src, 0, 1, &mapping[0].m_src );
118 1.1 lukem ber_str2bv( dst, 0, 1, &mapping[0].m_dst );
119 1.1 lukem mapping[1].m_src = mapping[0].m_dst;
120 1.1 lukem mapping[1].m_dst = mapping[0].m_src;
121 1.1 lukem
122 1.1 lukem mapping[0].m_flags = RWMMAP_F_NONE;
123 1.1 lukem mapping[1].m_flags = RWMMAP_F_NONE;
124 1.1 lukem
125 1.1 lukem /*
126 1.1 lukem * schema check
127 1.1 lukem */
128 1.1 lukem if ( is_oc ) {
129 1.1 lukem if ( src[0] != '\0' ) {
130 1.1 lukem mapping[0].m_src_oc = oc_bvfind( &mapping[0].m_src );
131 1.1 lukem if ( mapping[0].m_src_oc == NULL ) {
132 1.1.1.3 adam Debug( LDAP_DEBUG_ANY,
133 1.1 lukem "%s: line %d: warning, source objectClass '%s' "
134 1.1 lukem "should be defined in schema\n",
135 1.1 lukem fname, lineno, src );
136 1.1 lukem
137 1.1 lukem /*
138 1.1 lukem * FIXME: this should become an err
139 1.1 lukem */
140 1.1 lukem mapping[0].m_src_oc = ch_malloc( sizeof( ObjectClass ) );
141 1.1 lukem memset( mapping[0].m_src_oc, 0, sizeof( ObjectClass ) );
142 1.1 lukem mapping[0].m_src_oc->soc_cname = mapping[0].m_src;
143 1.1 lukem mapping[0].m_flags |= RWMMAP_F_FREE_SRC;
144 1.1 lukem }
145 1.1 lukem mapping[1].m_dst_oc = mapping[0].m_src_oc;
146 1.1 lukem }
147 1.1 lukem
148 1.1 lukem mapping[0].m_dst_oc = oc_bvfind( &mapping[0].m_dst );
149 1.1 lukem if ( mapping[0].m_dst_oc == NULL ) {
150 1.1.1.3 adam Debug( LDAP_DEBUG_ANY,
151 1.1 lukem "%s: line %d: warning, destination objectClass '%s' "
152 1.1 lukem "is not defined in schema\n",
153 1.1 lukem fname, lineno, dst );
154 1.1 lukem
155 1.1 lukem mapping[0].m_dst_oc = oc_bvfind_undef( &mapping[0].m_dst );
156 1.1 lukem if ( mapping[0].m_dst_oc == NULL ) {
157 1.1.1.3 adam Debug( LDAP_DEBUG_ANY, "%s: line %d: unable to mimic destination objectClass '%s'\n",
158 1.1 lukem fname, lineno, dst );
159 1.1 lukem goto error_return;
160 1.1 lukem }
161 1.1 lukem }
162 1.1 lukem mapping[1].m_src_oc = mapping[0].m_dst_oc;
163 1.1 lukem
164 1.1 lukem mapping[0].m_flags |= RWMMAP_F_IS_OC;
165 1.1 lukem mapping[1].m_flags |= RWMMAP_F_IS_OC;
166 1.1 lukem
167 1.1 lukem } else {
168 1.1 lukem int rc;
169 1.1 lukem const char *text = NULL;
170 1.1 lukem
171 1.1 lukem if ( src[0] != '\0' ) {
172 1.1 lukem rc = slap_bv2ad( &mapping[0].m_src,
173 1.1 lukem &mapping[0].m_src_ad, &text );
174 1.1 lukem if ( rc != LDAP_SUCCESS ) {
175 1.1.1.3 adam Debug( LDAP_DEBUG_ANY,
176 1.1 lukem "%s: line %d: warning, source attributeType '%s' "
177 1.1 lukem "should be defined in schema\n",
178 1.1 lukem fname, lineno, src );
179 1.1 lukem
180 1.1 lukem /*
181 1.1 lukem * we create a fake "proxied" ad
182 1.1 lukem * and add it here.
183 1.1 lukem */
184 1.1 lukem
185 1.1 lukem rc = slap_bv2undef_ad( &mapping[0].m_src,
186 1.1 lukem &mapping[0].m_src_ad, &text,
187 1.1 lukem SLAP_AD_PROXIED );
188 1.1 lukem if ( rc != LDAP_SUCCESS ) {
189 1.1.1.3 adam char prefix[1024];
190 1.1.1.3 adam snprintf( prefix, sizeof(prefix),
191 1.1.1.3 adam "%s: line %d: source attributeType '%s': %d",
192 1.1.1.3 adam fname, lineno, src, rc );
193 1.1.1.3 adam Debug( LDAP_DEBUG_ANY, "%s (%s)\n",
194 1.1.1.3 adam prefix, text ? text : "null", 0 );
195 1.1 lukem goto error_return;
196 1.1 lukem }
197 1.1 lukem
198 1.1 lukem }
199 1.1 lukem mapping[1].m_dst_ad = mapping[0].m_src_ad;
200 1.1 lukem }
201 1.1 lukem
202 1.1 lukem rc = slap_bv2ad( &mapping[0].m_dst, &mapping[0].m_dst_ad, &text );
203 1.1 lukem if ( rc != LDAP_SUCCESS ) {
204 1.1.1.3 adam Debug( LDAP_DEBUG_ANY,
205 1.1 lukem "%s: line %d: warning, destination attributeType '%s' "
206 1.1 lukem "is not defined in schema\n",
207 1.1 lukem fname, lineno, dst );
208 1.1 lukem
209 1.1 lukem rc = slap_bv2undef_ad( &mapping[0].m_dst,
210 1.1 lukem &mapping[0].m_dst_ad, &text,
211 1.1 lukem SLAP_AD_PROXIED );
212 1.1 lukem if ( rc != LDAP_SUCCESS ) {
213 1.1.1.3 adam char prefix[1024];
214 1.1.1.3 adam snprintf( prefix, sizeof(prefix),
215 1.1.1.3 adam "%s: line %d: destination attributeType '%s': %d",
216 1.1.1.3 adam fname, lineno, dst, rc );
217 1.1.1.3 adam Debug( LDAP_DEBUG_ANY, "%s (%s)\n",
218 1.1.1.3 adam prefix, text ? text : "null", 0 );
219 1.1 lukem goto error_return;
220 1.1 lukem }
221 1.1 lukem }
222 1.1 lukem mapping[1].m_src_ad = mapping[0].m_dst_ad;
223 1.1 lukem }
224 1.1 lukem
225 1.1 lukem if ( ( src[0] != '\0' && avl_find( map->map, (caddr_t)mapping, rwm_mapping_cmp ) != NULL)
226 1.1 lukem || avl_find( map->remap, (caddr_t)&mapping[1], rwm_mapping_cmp ) != NULL)
227 1.1 lukem {
228 1.1.1.3 adam Debug( LDAP_DEBUG_ANY,
229 1.1 lukem "%s: line %d: duplicate mapping found.\n",
230 1.1.1.3 adam fname, lineno, 0 );
231 1.1 lukem /* FIXME: free stuff */
232 1.1 lukem goto error_return;
233 1.1 lukem }
234 1.1 lukem
235 1.1 lukem if ( src[0] != '\0' ) {
236 1.1 lukem avl_insert( &map->map, (caddr_t)&mapping[0],
237 1.1 lukem rwm_mapping_cmp, rwm_mapping_dup );
238 1.1 lukem }
239 1.1 lukem avl_insert( &map->remap, (caddr_t)&mapping[1],
240 1.1 lukem rwm_mapping_cmp, rwm_mapping_dup );
241 1.1 lukem
242 1.1 lukem success_return:;
243 1.1 lukem return rc;
244 1.1 lukem
245 1.1 lukem error_return:;
246 1.1 lukem if ( mapping ) {
247 1.1 lukem rwm_mapping_free( mapping );
248 1.1 lukem }
249 1.1 lukem
250 1.1 lukem return 1;
251 1.1 lukem }
252 1.1 lukem
253 1.1 lukem static char *
254 1.1 lukem rwm_suffix_massage_regexize( const char *s )
255 1.1 lukem {
256 1.1 lukem char *res, *ptr;
257 1.1 lukem const char *p, *r;
258 1.1 lukem int i;
259 1.1 lukem
260 1.1 lukem if ( s[0] == '\0' ) {
261 1.1 lukem return ch_strdup( "^(.+)$" );
262 1.1 lukem }
263 1.1 lukem
264 1.1 lukem for ( i = 0, p = s;
265 1.1 lukem ( r = strchr( p, ',' ) ) != NULL;
266 1.1 lukem p = r + 1, i++ )
267 1.1 lukem ;
268 1.1 lukem
269 1.1 lukem res = ch_calloc( sizeof( char ), strlen( s )
270 1.1 lukem + STRLENOF( "((.+),)?" )
271 1.1 lukem + STRLENOF( "[ ]?" ) * i
272 1.1 lukem + STRLENOF( "$" ) + 1 );
273 1.1 lukem
274 1.1 lukem ptr = lutil_strcopy( res, "((.+),)?" );
275 1.1 lukem for ( i = 0, p = s;
276 1.1 lukem ( r = strchr( p, ',' ) ) != NULL;
277 1.1 lukem p = r + 1 , i++ ) {
278 1.1 lukem ptr = lutil_strncopy( ptr, p, r - p + 1 );
279 1.1 lukem ptr = lutil_strcopy( ptr, "[ ]?" );
280 1.1 lukem
281 1.1 lukem if ( r[ 1 ] == ' ' ) {
282 1.1 lukem r++;
283 1.1 lukem }
284 1.1 lukem }
285 1.1 lukem ptr = lutil_strcopy( ptr, p );
286 1.1 lukem ptr[0] = '$';
287 1.1 lukem ptr[1] = '\0';
288 1.1 lukem
289 1.1 lukem return res;
290 1.1 lukem }
291 1.1 lukem
292 1.1 lukem static char *
293 1.1 lukem rwm_suffix_massage_patternize( const char *s, const char *p )
294 1.1 lukem {
295 1.1 lukem ber_len_t len;
296 1.1 lukem char *res, *ptr;
297 1.1 lukem
298 1.1 lukem len = strlen( p );
299 1.1 lukem
300 1.1 lukem if ( s[ 0 ] == '\0' ) {
301 1.1 lukem len++;
302 1.1 lukem }
303 1.1 lukem
304 1.1 lukem res = ch_calloc( sizeof( char ), len + STRLENOF( "%1" ) + 1 );
305 1.1 lukem if ( res == NULL ) {
306 1.1 lukem return NULL;
307 1.1 lukem }
308 1.1 lukem
309 1.1 lukem ptr = lutil_strcopy( res, ( p[0] == '\0' ? "%2" : "%1" ) );
310 1.1 lukem if ( s[ 0 ] == '\0' ) {
311 1.1 lukem ptr[ 0 ] = ',';
312 1.1 lukem ptr++;
313 1.1 lukem }
314 1.1 lukem lutil_strcopy( ptr, p );
315 1.1 lukem
316 1.1 lukem return res;
317 1.1 lukem }
318 1.1 lukem
319 1.1 lukem int
320 1.1 lukem rwm_suffix_massage_config(
321 1.1 lukem struct rewrite_info *info,
322 1.1 lukem struct berval *pvnc,
323 1.1 lukem struct berval *nvnc,
324 1.1 lukem struct berval *prnc,
325 1.1 lukem struct berval *nrnc
326 1.1 lukem )
327 1.1 lukem {
328 1.1 lukem char *rargv[ 5 ];
329 1.1 lukem int line = 0;
330 1.1 lukem
331 1.1 lukem rargv[ 0 ] = "rewriteEngine";
332 1.1 lukem rargv[ 1 ] = "on";
333 1.1 lukem rargv[ 2 ] = NULL;
334 1.1 lukem rewrite_parse( info, "<suffix massage>", ++line, 2, rargv );
335 1.1 lukem
336 1.1 lukem rargv[ 0 ] = "rewriteContext";
337 1.1 lukem rargv[ 1 ] = "default";
338 1.1 lukem rargv[ 2 ] = NULL;
339 1.1 lukem rewrite_parse( info, "<suffix massage>", ++line, 2, rargv );
340 1.1 lukem
341 1.1 lukem rargv[ 0 ] = "rewriteRule";
342 1.1 lukem rargv[ 1 ] = rwm_suffix_massage_regexize( pvnc->bv_val );
343 1.1 lukem rargv[ 2 ] = rwm_suffix_massage_patternize( pvnc->bv_val, prnc->bv_val );
344 1.1 lukem rargv[ 3 ] = ":";
345 1.1 lukem rargv[ 4 ] = NULL;
346 1.1 lukem rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
347 1.1 lukem ch_free( rargv[ 1 ] );
348 1.1 lukem ch_free( rargv[ 2 ] );
349 1.1 lukem
350 1.1 lukem if ( BER_BVISEMPTY( pvnc ) ) {
351 1.1 lukem rargv[ 0 ] = "rewriteRule";
352 1.1 lukem rargv[ 1 ] = "^$";
353 1.1 lukem rargv[ 2 ] = prnc->bv_val;
354 1.1 lukem rargv[ 3 ] = ":";
355 1.1 lukem rargv[ 4 ] = NULL;
356 1.1 lukem rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
357 1.1 lukem }
358 1.1 lukem
359 1.1 lukem rargv[ 0 ] = "rewriteContext";
360 1.1 lukem rargv[ 1 ] = "searchEntryDN";
361 1.1 lukem rargv[ 2 ] = NULL;
362 1.1 lukem rewrite_parse( info, "<suffix massage>", ++line, 2, rargv );
363 1.1 lukem
364 1.1 lukem rargv[ 0 ] = "rewriteRule";
365 1.1 lukem rargv[ 1 ] = rwm_suffix_massage_regexize( prnc->bv_val );
366 1.1 lukem rargv[ 2 ] = rwm_suffix_massage_patternize( prnc->bv_val, pvnc->bv_val );
367 1.1 lukem rargv[ 3 ] = ":";
368 1.1 lukem rargv[ 4 ] = NULL;
369 1.1 lukem rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
370 1.1 lukem ch_free( rargv[ 1 ] );
371 1.1 lukem ch_free( rargv[ 2 ] );
372 1.1 lukem
373 1.1 lukem if ( BER_BVISEMPTY( prnc ) ) {
374 1.1 lukem rargv[ 0 ] = "rewriteRule";
375 1.1 lukem rargv[ 1 ] = "^$";
376 1.1 lukem rargv[ 2 ] = pvnc->bv_val;
377 1.1 lukem rargv[ 3 ] = ":";
378 1.1 lukem rargv[ 4 ] = NULL;
379 1.1 lukem rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
380 1.1 lukem }
381 1.1 lukem
382 1.1 lukem rargv[ 0 ] = "rewriteContext";
383 1.1 lukem rargv[ 1 ] = "matchedDN";
384 1.1 lukem rargv[ 2 ] = "alias";
385 1.1 lukem rargv[ 3 ] = "searchEntryDN";
386 1.1 lukem rargv[ 4 ] = NULL;
387 1.1 lukem rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
388 1.1 lukem
389 1.1 lukem #ifdef RWM_REFERRAL_REWRITE
390 1.1 lukem /* FIXME: we don't want this on by default, do we? */
391 1.1 lukem rargv[ 0 ] = "rewriteContext";
392 1.1 lukem rargv[ 1 ] = "referralDN";
393 1.1 lukem rargv[ 2 ] = "alias";
394 1.1 lukem rargv[ 3 ] = "searchEntryDN";
395 1.1 lukem rargv[ 4 ] = NULL;
396 1.1 lukem rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
397 1.1 lukem #else /* ! RWM_REFERRAL_REWRITE */
398 1.1 lukem rargv[ 0 ] = "rewriteContext";
399 1.1 lukem rargv[ 1 ] = "referralAttrDN";
400 1.1 lukem rargv[ 2 ] = NULL;
401 1.1 lukem rewrite_parse( info, "<suffix massage>", ++line, 2, rargv );
402 1.1 lukem
403 1.1 lukem rargv[ 0 ] = "rewriteContext";
404 1.1 lukem rargv[ 1 ] = "referralDN";
405 1.1 lukem rargv[ 2 ] = NULL;
406 1.1 lukem rewrite_parse( info, "<suffix massage>", ++line, 2, rargv );
407 1.1 lukem #endif /* ! RWM_REFERRAL_REWRITE */
408 1.1 lukem
409 1.1 lukem rargv[ 0 ] = "rewriteContext";
410 1.1 lukem rargv[ 1 ] = "searchAttrDN";
411 1.1 lukem rargv[ 2 ] = "alias";
412 1.1 lukem rargv[ 3 ] = "searchEntryDN";
413 1.1 lukem rargv[ 4 ] = NULL;
414 1.1 lukem rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
415 1.1 lukem
416 1.1 lukem return 0;
417 1.1 lukem }
418 1.1 lukem
419 1.1 lukem #endif /* SLAPD_OVER_RWM */
420