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