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