1 /* $NetBSD: xmap.c,v 1.1.1.2 2010/03/08 02:14:20 lukem Exp $ */ 2 3 /* OpenLDAP: pkg/ldap/libraries/librewrite/xmap.c,v 1.12.2.5 2009/01/22 00:00:59 kurt Exp */ 4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 5 * 6 * Copyright 2000-2009 The OpenLDAP Foundation. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted only as authorized by the OpenLDAP 11 * Public License. 12 * 13 * A copy of this license is available in the file LICENSE in the 14 * top-level directory of the distribution or, alternatively, at 15 * <http://www.OpenLDAP.org/license.html>. 16 */ 17 /* ACKNOWLEDGEMENT: 18 * This work was initially developed by Pierangelo Masarati for 19 * inclusion in OpenLDAP Software. 20 */ 21 22 #include <portable.h> 23 24 #include <stdio.h> 25 26 #ifdef HAVE_PWD_H 27 #include <pwd.h> 28 #endif 29 30 #define LDAP_DEPRECATED 1 31 #include "rewrite-int.h" 32 #include "rewrite-map.h" 33 34 /* 35 * Global data 36 */ 37 #ifdef USE_REWRITE_LDAP_PVT_THREADS 38 ldap_pvt_thread_mutex_t xpasswd_mutex; 39 static int xpasswd_mutex_init = 0; 40 #endif /* USE_REWRITE_LDAP_PVT_THREADS */ 41 42 /* 43 * Map parsing 44 * NOTE: these are old-fashion maps; new maps will be parsed on separate 45 * config lines, and referred by name. 46 */ 47 struct rewrite_map * 48 rewrite_xmap_parse( 49 struct rewrite_info *info, 50 const char *s, 51 const char **currpos 52 ) 53 { 54 struct rewrite_map *map; 55 56 assert( info != NULL ); 57 assert( s != NULL ); 58 assert( currpos != NULL ); 59 60 Debug( LDAP_DEBUG_ARGS, "rewrite_xmap_parse: %s\n%s%s", 61 s, "", "" ); 62 63 *currpos = NULL; 64 65 map = calloc( sizeof( struct rewrite_map ), 1 ); 66 if ( map == NULL ) { 67 Debug( LDAP_DEBUG_ANY, "rewrite_xmap_parse:" 68 " calloc failed\n%s%s%s", "", "", "" ); 69 return NULL; 70 } 71 72 /* 73 * Experimental passwd map: 74 * replaces the uid with the matching gecos from /etc/passwd file 75 */ 76 if ( strncasecmp(s, "xpasswd", 7 ) == 0 ) { 77 map->lm_type = REWRITE_MAP_XPWDMAP; 78 map->lm_name = strdup( "xpasswd" ); 79 if ( map->lm_name == NULL ) { 80 free( map ); 81 return NULL; 82 } 83 84 assert( s[7] == '}' ); 85 *currpos = s + 8; 86 87 #ifdef USE_REWRITE_LDAP_PVT_THREADS 88 if ( !xpasswd_mutex_init ) { 89 if ( ldap_pvt_thread_mutex_init( &xpasswd_mutex ) ) { 90 free( map ); 91 return NULL; 92 } 93 } 94 ++xpasswd_mutex_init; 95 #endif /* USE_REWRITE_LDAP_PVT_THREADS */ 96 97 /* Don't really care if fails */ 98 return map; 99 100 /* 101 * Experimental file map: 102 * looks up key in a `key value' ascii file 103 */ 104 } else if ( strncasecmp( s, "xfile", 5 ) == 0 ) { 105 char *filename; 106 const char *p; 107 int l; 108 int c = 5; 109 110 map->lm_type = REWRITE_MAP_XFILEMAP; 111 112 if ( s[ c ] != '(' ) { 113 free( map ); 114 return NULL; 115 } 116 117 /* Must start with '/' for security concerns */ 118 c++; 119 if ( s[ c ] != '/' ) { 120 free( map ); 121 return NULL; 122 } 123 124 for ( p = s + c; p[ 0 ] != '\0' && p[ 0 ] != ')'; p++ ); 125 if ( p[ 0 ] != ')' ) { 126 free( map ); 127 return NULL; 128 } 129 130 l = p - s - c; 131 filename = calloc( sizeof( char ), l + 1 ); 132 if ( filename == NULL ) { 133 free( map ); 134 return NULL; 135 } 136 AC_MEMCPY( filename, s + c, l ); 137 filename[ l ] = '\0'; 138 139 map->lm_args = ( void * )fopen( filename, "r" ); 140 free( filename ); 141 142 if ( map->lm_args == NULL ) { 143 free( map ); 144 return NULL; 145 } 146 147 *currpos = p + 1; 148 149 #ifdef USE_REWRITE_LDAP_PVT_THREADS 150 if ( ldap_pvt_thread_mutex_init( &map->lm_mutex ) ) { 151 fclose( ( FILE * )map->lm_args ); 152 free( map ); 153 return NULL; 154 } 155 #endif /* USE_REWRITE_LDAP_PVT_THREADS */ 156 157 return map; 158 159 /* 160 * Experimental ldap map: 161 * looks up key on the fly (not implemented!) 162 */ 163 } else if ( strncasecmp(s, "xldap", 5 ) == 0 ) { 164 char *p; 165 char *url; 166 int l, rc; 167 int c = 5; 168 LDAPURLDesc *lud; 169 170 if ( s[ c ] != '(' ) { 171 free( map ); 172 return NULL; 173 } 174 c++; 175 176 p = strchr( s, '}' ); 177 if ( p == NULL ) { 178 free( map ); 179 return NULL; 180 } 181 p--; 182 183 *currpos = p + 2; 184 185 /* 186 * Add two bytes for urlencoding of '%s' 187 */ 188 l = p - s - c; 189 url = calloc( sizeof( char ), l + 3 ); 190 if ( url == NULL ) { 191 free( map ); 192 return NULL; 193 } 194 AC_MEMCPY( url, s + c, l ); 195 url[ l ] = '\0'; 196 197 /* 198 * Urlencodes the '%s' for ldap_url_parse 199 */ 200 p = strchr( url, '%' ); 201 if ( p != NULL ) { 202 AC_MEMCPY( p + 3, p + 1, strlen( p + 1 ) + 1 ); 203 p[ 1 ] = '2'; 204 p[ 2 ] = '5'; 205 } 206 207 rc = ldap_url_parse( url, &lud ); 208 free( url ); 209 210 if ( rc != LDAP_SUCCESS ) { 211 free( map ); 212 return NULL; 213 } 214 assert( lud != NULL ); 215 216 map->lm_args = ( void * )lud; 217 map->lm_type = REWRITE_MAP_XLDAPMAP; 218 219 #ifdef USE_REWRITE_LDAP_PVT_THREADS 220 if ( ldap_pvt_thread_mutex_init( &map->lm_mutex ) ) { 221 ldap_free_urldesc( lud ); 222 free( map ); 223 return NULL; 224 } 225 #endif /* USE_REWRITE_LDAP_PVT_THREADS */ 226 227 return map; 228 229 /* Unhandled map */ 230 } 231 232 free( map ); 233 return NULL; 234 } 235 236 /* 237 * Map key -> value resolution 238 * NOTE: these are old-fashion maps; new maps will be parsed on separate 239 * config lines, and referred by name. 240 */ 241 int 242 rewrite_xmap_apply( 243 struct rewrite_info *info, 244 struct rewrite_op *op, 245 struct rewrite_map *map, 246 struct berval *key, 247 struct berval *val 248 ) 249 { 250 int rc = REWRITE_SUCCESS; 251 252 assert( info != NULL ); 253 assert( op != NULL ); 254 assert( map != NULL ); 255 assert( key != NULL ); 256 assert( val != NULL ); 257 258 val->bv_val = NULL; 259 val->bv_len = 0; 260 261 switch ( map->lm_type ) { 262 #ifdef HAVE_GETPWNAM 263 case REWRITE_MAP_XPWDMAP: { 264 struct passwd *pwd; 265 266 #ifdef USE_REWRITE_LDAP_PVT_THREADS 267 ldap_pvt_thread_mutex_lock( &xpasswd_mutex ); 268 #endif /* USE_REWRITE_LDAP_PVT_THREADS */ 269 270 pwd = getpwnam( key->bv_val ); 271 if ( pwd == NULL ) { 272 273 #ifdef USE_REWRITE_LDAP_PVT_THREADS 274 ldap_pvt_thread_mutex_unlock( &xpasswd_mutex ); 275 #endif /* USE_REWRITE_LDAP_PVT_THREADS */ 276 277 rc = LDAP_NO_SUCH_OBJECT; 278 break; 279 } 280 281 #ifdef HAVE_STRUCT_PASSWD_PW_GECOS 282 if ( pwd->pw_gecos != NULL && pwd->pw_gecos[0] != '\0' ) { 283 int l = strlen( pwd->pw_gecos ); 284 285 val->bv_val = strdup( pwd->pw_gecos ); 286 val->bv_len = l; 287 } else 288 #endif /* HAVE_STRUCT_PASSWD_PW_GECOS */ 289 { 290 val->bv_val = strdup( key->bv_val ); 291 val->bv_len = key->bv_len; 292 } 293 294 #ifdef USE_REWRITE_LDAP_PVT_THREADS 295 ldap_pvt_thread_mutex_unlock( &xpasswd_mutex ); 296 #endif /* USE_REWRITE_LDAP_PVT_THREADS */ 297 298 if ( val->bv_val == NULL ) { 299 rc = REWRITE_ERR; 300 } 301 break; 302 } 303 #endif /* HAVE_GETPWNAM*/ 304 305 case REWRITE_MAP_XFILEMAP: { 306 char buf[1024]; 307 308 if ( map->lm_args == NULL ) { 309 rc = REWRITE_ERR; 310 break; 311 } 312 313 #ifdef USE_REWRITE_LDAP_PVT_THREADS 314 ldap_pvt_thread_mutex_lock( &map->lm_mutex ); 315 #endif /* USE_REWRITE_LDAP_PVT_THREADS */ 316 317 rewind( ( FILE * )map->lm_args ); 318 319 while ( fgets( buf, sizeof( buf ), ( FILE * )map->lm_args ) ) { 320 char *p; 321 int blen; 322 323 blen = strlen( buf ); 324 if ( buf[ blen - 1 ] == '\n' ) { 325 buf[ blen - 1 ] = '\0'; 326 } 327 328 p = strtok( buf, " " ); 329 if ( p == NULL ) { 330 #ifdef USE_REWRITE_LDAP_PVT_THREADS 331 ldap_pvt_thread_mutex_unlock( &map->lm_mutex ); 332 #endif /* USE_REWRITE_LDAP_PVT_THREADS */ 333 rc = REWRITE_ERR; 334 goto rc_return; 335 } 336 if ( strcasecmp( p, key->bv_val ) == 0 337 && ( p = strtok( NULL, "" ) ) ) { 338 val->bv_val = strdup( p ); 339 if ( val->bv_val == NULL ) { 340 return REWRITE_ERR; 341 } 342 343 val->bv_len = strlen( p ); 344 345 #ifdef USE_REWRITE_LDAP_PVT_THREADS 346 ldap_pvt_thread_mutex_unlock( &map->lm_mutex ); 347 #endif /* USE_REWRITE_LDAP_PVT_THREADS */ 348 349 goto rc_return; 350 } 351 } 352 353 #ifdef USE_REWRITE_LDAP_PVT_THREADS 354 ldap_pvt_thread_mutex_unlock( &map->lm_mutex ); 355 #endif /* USE_REWRITE_LDAP_PVT_THREADS */ 356 357 rc = REWRITE_ERR; 358 359 break; 360 } 361 362 case REWRITE_MAP_XLDAPMAP: { 363 LDAP *ld; 364 char filter[1024]; 365 LDAPMessage *res = NULL, *entry; 366 LDAPURLDesc *lud = ( LDAPURLDesc * )map->lm_args; 367 int attrsonly = 0; 368 char **values; 369 370 assert( lud != NULL ); 371 372 /* 373 * No mutex because there is no write on the map data 374 */ 375 376 ld = ldap_init( lud->lud_host, lud->lud_port ); 377 if ( ld == NULL ) { 378 rc = REWRITE_ERR; 379 goto rc_return; 380 } 381 382 snprintf( filter, sizeof( filter ), lud->lud_filter, 383 key->bv_val ); 384 385 if ( strcasecmp( lud->lud_attrs[ 0 ], "dn" ) == 0 ) { 386 attrsonly = 1; 387 } 388 rc = ldap_search_s( ld, lud->lud_dn, lud->lud_scope, 389 filter, lud->lud_attrs, attrsonly, &res ); 390 if ( rc != LDAP_SUCCESS ) { 391 ldap_unbind( ld ); 392 rc = REWRITE_ERR; 393 goto rc_return; 394 } 395 396 if ( ldap_count_entries( ld, res ) != 1 ) { 397 ldap_unbind( ld ); 398 rc = REWRITE_ERR; 399 goto rc_return; 400 } 401 402 entry = ldap_first_entry( ld, res ); 403 if ( entry == NULL ) { 404 ldap_msgfree( res ); 405 ldap_unbind( ld ); 406 rc = REWRITE_ERR; 407 goto rc_return; 408 } 409 if ( attrsonly == 1 ) { 410 val->bv_val = ldap_get_dn( ld, entry ); 411 412 } else { 413 values = ldap_get_values( ld, entry, 414 lud->lud_attrs[0] ); 415 if ( values != NULL ) { 416 val->bv_val = strdup( values[ 0 ] ); 417 ldap_value_free( values ); 418 } 419 } 420 421 ldap_msgfree( res ); 422 ldap_unbind( ld ); 423 424 if ( val->bv_val == NULL ) { 425 rc = REWRITE_ERR; 426 goto rc_return; 427 } 428 val->bv_len = strlen( val->bv_val ); 429 430 rc = REWRITE_SUCCESS; 431 } break; 432 } 433 434 rc_return:; 435 return rc; 436 } 437 438 int 439 rewrite_xmap_destroy( 440 struct rewrite_map **pmap 441 ) 442 { 443 struct rewrite_map *map; 444 445 assert( pmap != NULL ); 446 assert( *pmap != NULL ); 447 448 map = *pmap; 449 450 switch ( map->lm_type ) { 451 case REWRITE_MAP_XPWDMAP: 452 #ifdef USE_REWRITE_LDAP_PVT_THREADS 453 --xpasswd_mutex_init; 454 if ( !xpasswd_mutex_init ) { 455 ldap_pvt_thread_mutex_destroy( &xpasswd_mutex ); 456 } 457 #endif /* USE_REWRITE_LDAP_PVT_THREADS */ 458 459 break; 460 461 case REWRITE_MAP_XFILEMAP: 462 #ifdef USE_REWRITE_LDAP_PVT_THREADS 463 ldap_pvt_thread_mutex_lock( &map->lm_mutex ); 464 #endif /* USE_REWRITE_LDAP_PVT_THREADS */ 465 466 if ( map->lm_args ) { 467 fclose( ( FILE * )map->lm_args ); 468 map->lm_args = NULL; 469 } 470 471 #ifdef USE_REWRITE_LDAP_PVT_THREADS 472 ldap_pvt_thread_mutex_unlock( &map->lm_mutex ); 473 ldap_pvt_thread_mutex_destroy( &map->lm_mutex ); 474 #endif /* USE_REWRITE_LDAP_PVT_THREADS */ 475 break; 476 477 case REWRITE_MAP_XLDAPMAP: 478 #ifdef USE_REWRITE_LDAP_PVT_THREADS 479 ldap_pvt_thread_mutex_lock( &map->lm_mutex ); 480 #endif /* USE_REWRITE_LDAP_PVT_THREADS */ 481 482 if ( map->lm_args ) { 483 ldap_free_urldesc( ( LDAPURLDesc * )map->lm_args ); 484 map->lm_args = NULL; 485 } 486 487 #ifdef USE_REWRITE_LDAP_PVT_THREADS 488 ldap_pvt_thread_mutex_unlock( &map->lm_mutex ); 489 ldap_pvt_thread_mutex_destroy( &map->lm_mutex ); 490 #endif /* USE_REWRITE_LDAP_PVT_THREADS */ 491 break; 492 493 default: 494 break; 495 496 } 497 498 free( map->lm_name ); 499 free( map ); 500 *pmap = NULL; 501 502 return 0; 503 } 504 505