]> git.sur5r.net Git - openldap/blob - servers/slapd/back-ldap/config.c
7edbd1991520ef49120167973b92edd77bfe56f7
[openldap] / servers / slapd / back-ldap / config.c
1 /* config.c - ldap backend configuration file routine */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 2003-2004 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 #include <stdio.h>
27
28 #include <ac/string.h>
29 #include <ac/socket.h>
30
31 #include "slap.h"
32 #include "back-ldap.h"
33 #include "lutil.h"
34 #undef ldap_debug
35 /* for advanced URL parsing */
36 #include "../../../libraries/libldap/ldap-int.h"
37
38 static SLAP_EXTOP_MAIN_FN ldap_back_exop_whoami;
39
40 static int
41 parse_idassert( BackendDB *be, const char *fname, int lineno,
42                 int argc, char **argv );
43
44 int
45 ldap_back_db_config(
46     BackendDB   *be,
47     const char  *fname,
48     int         lineno,
49     int         argc,
50     char        **argv
51 )
52 {
53         struct ldapinfo *li = (struct ldapinfo *) be->be_private;
54
55         if ( li == NULL ) {
56                 fprintf( stderr, "%s: line %d: ldap backend info is null!\n",
57                     fname, lineno );
58                 return( 1 );
59         }
60
61         /* server address to query (depricated, use "uri" directive) */
62         if ( strcasecmp( argv[0], "server" ) == 0 ) {
63                 ber_len_t       l;
64
65                 if (argc != 2) {
66                         fprintf( stderr,
67         "%s: line %d: missing address in \"server <address>\" line\n",
68                             fname, lineno );
69                         return( 1 );
70                 }
71                 if (li->url != NULL)
72                         ch_free(li->url);
73                 l = strlen( argv[1] ) + STRLENOF( "ldap:///") + 1;
74                 li->url = ch_calloc( l, sizeof( char ) );
75                 if (li->url == NULL) {
76                         fprintf( stderr, "%s: line %d: malloc failed\n" );
77                         return 1;
78                 }
79
80                 snprintf( li->url, l, "ldap://%s/", argv[1] );
81
82         /* URI of server to query (preferred over "server" directive) */
83         } else if ( strcasecmp( argv[0], "uri" ) == 0 ) {
84                 LDAPURLDesc     tmplud, *tmpludp;
85                 int             urlrc;
86
87                 if (argc != 2) {
88                         fprintf( stderr, "%s: line %d: "
89                                 "missing uri "
90                                 "in \"uri <uri>\" line\n",
91                                 fname, lineno );
92                         return( 1 );
93                 }
94                 if ( li->url != NULL ) {
95                         ch_free( li->url );
96                 }
97                 if ( li->lud != NULL ) {
98                         ldap_free_urllist( li->lud );
99                 }
100
101 #if 0
102                 /* PARANOID: DN and more are not required nor allowed */
103                 urlrc = ldap_url_parselist_ext( &li->lud, argv[ 1 ], "\t" );
104 #else
105                 urlrc =  ldap_url_parselist( &li->lud, argv[ 1 ] );
106 #endif
107                 if ( urlrc != LDAP_URL_SUCCESS ) {
108                         char    *why;
109
110                         switch ( urlrc ) {
111                         case LDAP_URL_ERR_MEM:
112                                 why = "no memory";
113                                 break;
114                         case LDAP_URL_ERR_PARAM:
115                                 why = "parameter is bad";
116                                 break;
117                         case LDAP_URL_ERR_BADSCHEME:
118                                 why = "URL doesn't begin with \"[c]ldap[si]://\"";
119                                 break;
120                         case LDAP_URL_ERR_BADENCLOSURE:
121                                 why = "URL is missing trailing \">\"";
122                                 break;
123                         case LDAP_URL_ERR_BADURL:
124                                 why = "URL is bad";
125                         case LDAP_URL_ERR_BADHOST:
126                                 why = "host/port is bad";
127                                 break;
128                         case LDAP_URL_ERR_BADATTRS:
129                                 why = "bad (or missing) attributes";
130                                 break;
131                         case LDAP_URL_ERR_BADSCOPE:
132                                 why = "scope string is invalid (or missing)";
133                                 break;
134                         case LDAP_URL_ERR_BADFILTER:
135                                 why = "bad or missing filter";
136                                 break;
137                         case LDAP_URL_ERR_BADEXTS:
138                                 why = "bad or missing extensions";
139                                 break;
140                         default:
141                                 why = "unknown reason";
142                                 break;
143                         }
144                         fprintf( stderr, "%s: line %d: "
145                                 "unable to parse uri \"%s\" "
146                                 "in \"uri <uri>\" line: %s\n",
147                                 fname, lineno, argv[ 1 ], why );
148                         return 1;
149                 }
150
151                 for ( tmpludp = li->lud; tmpludp; tmpludp = tmpludp->lud_next ) {
152                         if ( ( tmpludp->lud_dn != NULL && tmpludp->lud_dn[0] != '\0' )
153                                         || tmpludp->lud_attrs != NULL
154                                         || tmpludp->lud_filter != NULL
155                                         || tmpludp->lud_exts != NULL )
156                         {
157                                 fprintf( stderr, "%s: line %d: "
158                                         "warning, only protocol, "
159                                         "host and port allowed "
160                                         "in \"uri <uri>\" statement "
161                                         "for \"%s\"\n",
162                                         fname, lineno, argv[1] );
163                         }
164                 }
165
166 #if 0
167                 for ( tmpludp = li->lud; tmpludp; tmpludp = tmpludp->lud_next ) {
168                         char            *tmpurl;
169                         ber_len_t       oldlen = 0, len;
170
171                         tmplud = *tmpludp;
172                         tmplud.lud_dn = "";
173                         tmplud.lud_attrs = NULL;
174                         tmplud.lud_filter = NULL;
175                         if ( !ldap_is_ldapi_url( argv[ 1 ] ) ) {
176                                 tmplud.lud_exts = NULL;
177                                 tmplud.lud_crit_exts = 0;
178                         }
179
180                         tmpurl = ldap_url_desc2str( &tmplud );
181
182                         if ( tmpurl == NULL ) {
183                                 fprintf( stderr, "%s: line %d: "
184                                         "unable to rebuild uri "
185                                         "in \"uri <uri>\" statement "
186                                         "for \"%s\"\n",
187                                         fname, lineno, argv[ 1 ] );
188                                 return 1;
189                         }
190
191                         len = strlen( tmpurl );
192                         if ( li->url ) {
193                                 oldlen = strlen( li->url ) + STRLENOF( " " );
194                         }
195                         li->url = ch_realloc( li->url, oldlen + len + 1);
196                         if ( oldlen ) {
197                                 li->url[oldlen - 1] = " ";
198                         }
199                         AC_MEMCPY( &li->url[oldlen], tmpurl, len + 1 );
200                         ch_free( tmpurl );
201                 }
202 #else
203                 li->url = ch_strdup( argv[ 1 ] );
204 #endif
205
206         /* name to use for ldap_back_group */
207         } else if ( strcasecmp( argv[0], "acl-authcdn" ) == 0
208                         || strcasecmp( argv[0], "binddn" ) == 0 ) {
209                 if (argc != 2) {
210                         fprintf( stderr,
211         "%s: line %d: missing name in \"%s <name>\" line\n",
212                             fname, lineno, argv[0] );
213                         return( 1 );
214                 }
215                 ber_str2bv( argv[1], 0, 1, &li->acl_authcDN );
216
217         /* password to use for ldap_back_group */
218         } else if ( strcasecmp( argv[0], "acl-passwd" ) == 0
219                         || strcasecmp( argv[0], "bindpw" ) == 0 ) {
220                 if (argc != 2) {
221                         fprintf( stderr,
222         "%s: line %d: missing password in \"%s <password>\" line\n",
223                             fname, lineno, argv[0] );
224                         return( 1 );
225                 }
226                 ber_str2bv( argv[1], 0, 1, &li->acl_passwd );
227
228 #ifdef LDAP_BACK_PROXY_AUTHZ
229         /* identity assertion stuff... */
230         } else if ( strncasecmp( argv[0], "idassert-", STRLENOF( "idassert-" ) ) == 0
231                         || strncasecmp( argv[0], "proxyauthz", STRLENOF( "proxyauthz" ) ) == 0 ) {
232                 return parse_idassert( be, fname, lineno, argc, argv );
233 #endif /* LDAP_BACK_PROXY_AUTHZ */
234
235         /* save bind creds for referral rebinds? */
236         } else if ( strcasecmp( argv[0], "rebind-as-user" ) == 0 ) {
237                 if (argc != 1) {
238                         fprintf( stderr,
239         "%s: line %d: rebind-as-user takes no arguments\n",
240                             fname, lineno );
241                         return( 1 );
242                 }
243                 li->savecred = 1;
244         
245         /* intercept exop_who_am_i? */
246         } else if ( strcasecmp( argv[0], "proxy-whoami" ) == 0 ) {
247                 if (argc != 1) {
248                         fprintf( stderr,
249         "%s: line %d: proxy-whoami takes no arguments\n",
250                             fname, lineno );
251                         return( 1 );
252                 }
253                 load_extop( (struct berval *)&slap_EXOP_WHOAMI,
254                         0, ldap_back_exop_whoami );
255         
256         /* dn massaging */
257         } else if ( strcasecmp( argv[0], "suffixmassage" ) == 0 ) {
258                 BackendDB *tmp_be;
259                 struct berval bvnc, nvnc, pvnc, brnc, nrnc, prnc;
260 #ifdef ENABLE_REWRITE
261                 int rc;
262 #endif /* ENABLE_REWRITE */
263                 
264                 /*
265                  * syntax:
266                  * 
267                  *      suffixmassage <suffix> <massaged suffix>
268                  *
269                  * the <suffix> field must be defined as a valid suffix
270                  * (or suffixAlias?) for the current database;
271                  * the <massaged suffix> shouldn't have already been
272                  * defined as a valid suffix or suffixAlias for the 
273                  * current server
274                  */
275                 if ( argc != 3 ) {
276                         fprintf( stderr, "%s: line %d: syntax is"
277                                        " \"suffixMassage <suffix>"
278                                        " <massaged suffix>\"\n",
279                                 fname, lineno );
280                         return( 1 );
281                 }
282                 
283                 ber_str2bv( argv[1], 0, 0, &bvnc );
284                 if ( dnPrettyNormal( NULL, &bvnc, &pvnc, &nvnc, NULL ) != LDAP_SUCCESS ) {
285                         fprintf( stderr, "%s: line %d: suffix DN %s is invalid\n",
286                                 fname, lineno, bvnc.bv_val );
287                         return( 1 );
288                 }
289                 tmp_be = select_backend( &nvnc, 0, 0 );
290                 if ( tmp_be != NULL && tmp_be != be ) {
291                         fprintf( stderr, "%s: line %d: suffix already in use"
292                                        " by another backend in"
293                                        " \"suffixMassage <suffix>"
294                                        " <massaged suffix>\"\n",
295                                 fname, lineno );
296                         free( nvnc.bv_val );
297                         free( pvnc.bv_val );
298                         return( 1 );
299                 }
300
301                 ber_str2bv( argv[2], 0, 0, &brnc );
302                 if ( dnPrettyNormal( NULL, &brnc, &prnc, &nrnc, NULL ) != LDAP_SUCCESS ) {
303                         fprintf( stderr, "%s: line %d: suffix DN %s is invalid\n",
304                                 fname, lineno, brnc.bv_val );
305                         free( nvnc.bv_val );
306                         free( pvnc.bv_val );
307                         return( 1 );
308                 }
309
310 #if 0
311                 tmp_be = select_backend( &nrnc, 0, 0 );
312                 if ( tmp_be != NULL ) {
313                         fprintf( stderr, "%s: line %d: massaged suffix"
314                                        " already in use by another backend in" 
315                                        " \"suffixMassage <suffix>"
316                                        " <massaged suffix>\"\n",
317                                 fname, lineno );
318                         free( nvnc.bv_val );
319                         free( pvnc.bv_val );
320                         free( nrnc.bv_val );
321                         free( prnc.bv_val );
322                         return( 1 );
323                 }
324 #endif
325
326 #ifdef ENABLE_REWRITE
327                 /*
328                  * The suffix massaging is emulated by means of the
329                  * rewrite capabilities
330                  * FIXME: no extra rewrite capabilities should be added
331                  * to the database
332                  */
333                 rc = suffix_massage_config( li->rwmap.rwm_rw,
334                                 &pvnc, &nvnc, &prnc, &nrnc );
335                 free( nvnc.bv_val );
336                 free( pvnc.bv_val );
337                 free( nrnc.bv_val );
338                 free( prnc.bv_val );
339
340                 return( rc );
341
342 #else /* !ENABLE_REWRITE */
343                 ber_bvarray_add( &li->rwmap.rwm_suffix_massage, &pvnc );
344                 ber_bvarray_add( &li->rwmap.rwm_suffix_massage, &nvnc );
345                 
346                 ber_bvarray_add( &li->rwmap.rwm_suffix_massage, &prnc );
347                 ber_bvarray_add( &li->rwmap.rwm_suffix_massage, &nrnc );
348 #endif /* !ENABLE_REWRITE */
349
350         /* rewrite stuff ... */
351         } else if ( strncasecmp( argv[0], "rewrite", 7 ) == 0 ) {
352 #ifdef ENABLE_REWRITE
353                 return rewrite_parse( li->rwmap.rwm_rw,
354                                 fname, lineno, argc, argv );
355
356 #else /* !ENABLE_REWRITE */
357                 fprintf( stderr, "%s: line %d: rewrite capabilities "
358                                 "are not enabled\n", fname, lineno );
359 #endif /* !ENABLE_REWRITE */
360                 
361         /* objectclass/attribute mapping */
362         } else if ( strcasecmp( argv[0], "map" ) == 0 ) {
363                 return ldap_back_map_config( &li->rwmap.rwm_oc,
364                                 &li->rwmap.rwm_at,
365                                 fname, lineno, argc, argv );
366
367         /* anything else */
368         } else {
369                 return SLAP_CONF_UNKNOWN;
370         }
371         return 0;
372 }
373
374 int
375 ldap_back_map_config(
376                 struct ldapmap  *oc_map,
377                 struct ldapmap  *at_map,
378                 const char      *fname,
379                 int             lineno,
380                 int             argc,
381                 char            **argv )
382 {
383         struct ldapmap          *map;
384         struct ldapmapping      *mapping;
385         char                    *src, *dst;
386         int                     is_oc = 0;
387
388         if ( argc < 3 || argc > 4 ) {
389                 fprintf( stderr,
390         "%s: line %d: syntax is \"map {objectclass | attribute} [<local> | *] {<foreign> | *}\"\n",
391                         fname, lineno );
392                 return 1;
393         }
394
395         if ( strcasecmp( argv[1], "objectclass" ) == 0 ) {
396                 map = oc_map;
397                 is_oc = 1;
398
399         } else if ( strcasecmp( argv[1], "attribute" ) == 0 ) {
400                 map = at_map;
401
402         } else {
403                 fprintf( stderr, "%s: line %d: syntax is "
404                         "\"map {objectclass | attribute} [<local> | *] "
405                         "{<foreign> | *}\"\n",
406                         fname, lineno );
407                 return 1;
408         }
409
410         if ( strcmp( argv[2], "*" ) == 0 ) {
411                 if ( argc < 4 || strcmp( argv[3], "*" ) == 0 ) {
412                         map->drop_missing = ( argc < 4 );
413                         return 0;
414                 }
415                 src = dst = argv[3];
416
417         } else if ( argc < 4 ) {
418                 src = "";
419                 dst = argv[2];
420
421         } else {
422                 src = argv[2];
423                 dst = ( strcmp( argv[3], "*" ) == 0 ? src : argv[3] );
424         }
425
426         if ( ( map == at_map )
427                         && ( strcasecmp( src, "objectclass" ) == 0
428                         || strcasecmp( dst, "objectclass" ) == 0 ) )
429         {
430                 fprintf( stderr,
431                         "%s: line %d: objectclass attribute cannot be mapped\n",
432                         fname, lineno );
433         }
434
435         mapping = (struct ldapmapping *)ch_calloc( 2,
436                 sizeof(struct ldapmapping) );
437         if ( mapping == NULL ) {
438                 fprintf( stderr,
439                         "%s: line %d: out of memory\n",
440                         fname, lineno );
441                 return 1;
442         }
443         ber_str2bv( src, 0, 1, &mapping->src );
444         ber_str2bv( dst, 0, 1, &mapping->dst );
445         mapping[1].src = mapping->dst;
446         mapping[1].dst = mapping->src;
447
448         /*
449          * schema check
450          */
451         if ( is_oc ) {
452                 if ( src[0] != '\0' ) {
453                         if ( oc_bvfind( &mapping->src ) == NULL ) {
454                                 fprintf( stderr,
455         "%s: line %d: warning, source objectClass '%s' "
456         "should be defined in schema\n",
457                                         fname, lineno, src );
458
459                                 /*
460                                  * FIXME: this should become an err
461                                  */
462                                 goto error_return;
463                         }
464                 }
465
466                 if ( oc_bvfind( &mapping->dst ) == NULL ) {
467                         fprintf( stderr,
468         "%s: line %d: warning, destination objectClass '%s' "
469         "is not defined in schema\n",
470                                 fname, lineno, dst );
471                 }
472         } else {
473                 int                     rc;
474                 const char              *text = NULL;
475                 AttributeDescription    *ad = NULL;
476
477                 if ( src[0] != '\0' ) {
478                         rc = slap_bv2ad( &mapping->src, &ad, &text );
479                         if ( rc != LDAP_SUCCESS ) {
480                                 fprintf( stderr,
481         "%s: line %d: warning, source attributeType '%s' "
482         "should be defined in schema\n",
483                                         fname, lineno, src );
484
485                                 /*
486                                  * FIXME: this should become an err
487                                  */
488                                 goto error_return;
489                         }
490
491                         ad = NULL;
492                 }
493
494                 rc = slap_bv2ad( &mapping->dst, &ad, &text );
495                 if ( rc != LDAP_SUCCESS ) {
496                         fprintf( stderr,
497         "%s: line %d: warning, destination attributeType '%s' "
498         "is not defined in schema\n",
499                                 fname, lineno, dst );
500                 }
501         }
502
503         if ( (src[0] != '\0' && avl_find( map->map, (caddr_t)mapping, mapping_cmp ) != NULL)
504                         || avl_find( map->remap, (caddr_t)&mapping[1], mapping_cmp ) != NULL)
505         {
506                 fprintf( stderr,
507                         "%s: line %d: duplicate mapping found (ignored)\n",
508                         fname, lineno );
509                 goto error_return;
510         }
511
512         if ( src[0] != '\0' ) {
513                 avl_insert( &map->map, (caddr_t)mapping,
514                                         mapping_cmp, mapping_dup );
515         }
516         avl_insert( &map->remap, (caddr_t)&mapping[1],
517                                 mapping_cmp, mapping_dup );
518
519         return 0;
520
521 error_return:;
522         if ( mapping ) {
523                 ch_free( mapping->src.bv_val );
524                 ch_free( mapping->dst.bv_val );
525                 ch_free( mapping );
526         }
527
528         return 1;
529 }
530
531 static int
532 ldap_back_exop_whoami(
533         Operation *op,
534         SlapReply *rs )
535 {
536         struct berval *bv = NULL;
537
538         if ( op->oq_extended.rs_reqdata != NULL ) {
539                 /* no request data should be provided */
540                 rs->sr_text = "no request data expected";
541                 return rs->sr_err = LDAP_PROTOCOL_ERROR;
542         }
543
544         rs->sr_err = backend_check_restrictions( op, rs, 
545                         (struct berval *)&slap_EXOP_WHOAMI );
546         if( rs->sr_err != LDAP_SUCCESS ) return rs->sr_err;
547
548         /* if auth'd by back-ldap and request is proxied, forward it */
549         if ( op->o_conn->c_authz_backend && !strcmp(op->o_conn->c_authz_backend->be_type, "ldap" ) && !dn_match(&op->o_ndn, &op->o_conn->c_ndn)) {
550                 struct ldapconn *lc;
551
552                 LDAPControl c, *ctrls[2] = {NULL, NULL};
553                 LDAPMessage *res;
554                 Operation op2 = *op;
555                 ber_int_t msgid;
556
557                 ctrls[0] = &c;
558                 op2.o_ndn = op->o_conn->c_ndn;
559                 lc = ldap_back_getconn(&op2, rs);
560                 if (!lc || !ldap_back_dobind( lc, op, rs )) {
561                         return -1;
562                 }
563                 c.ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
564                 c.ldctl_iscritical = 1;
565                 c.ldctl_value.bv_val = ch_malloc(op->o_ndn.bv_len+4);
566                 c.ldctl_value.bv_len = op->o_ndn.bv_len + 3;
567                 strcpy(c.ldctl_value.bv_val, "dn:");
568                 strcpy(c.ldctl_value.bv_val+3, op->o_ndn.bv_val);
569
570                 rs->sr_err = ldap_whoami(lc->ld, ctrls, NULL, &msgid);
571                 if (rs->sr_err == LDAP_SUCCESS) {
572                         if (ldap_result(lc->ld, msgid, 1, NULL, &res) == -1) {
573                                 ldap_get_option(lc->ld, LDAP_OPT_ERROR_NUMBER,
574                                         &rs->sr_err);
575                                 ldap_back_freeconn( op, lc );
576                                 lc = NULL;
577
578                         } else {
579                                 rs->sr_err = ldap_parse_whoami(lc->ld, res, &bv);
580                                 ldap_msgfree(res);
581                         }
582                 }
583                 ch_free(c.ldctl_value.bv_val);
584                 if (rs->sr_err != LDAP_SUCCESS) {
585                         rs->sr_err = slap_map_api2result( rs );
586                 }
587         } else {
588         /* else just do the same as before */
589                 bv = (struct berval *) ch_malloc( sizeof(struct berval) );
590                 if( op->o_dn.bv_len ) {
591                         bv->bv_len = op->o_dn.bv_len + sizeof("dn:") - 1;
592                         bv->bv_val = ch_malloc( bv->bv_len + 1 );
593                         AC_MEMCPY( bv->bv_val, "dn:", sizeof("dn:") - 1 );
594                         AC_MEMCPY( &bv->bv_val[sizeof("dn:") - 1], op->o_dn.bv_val,
595                                 op->o_dn.bv_len );
596                         bv->bv_val[bv->bv_len] = '\0';
597                 } else {
598                         bv->bv_len = 0;
599                         bv->bv_val = NULL;
600                 }
601         }
602
603         rs->sr_rspdata = bv;
604         return rs->sr_err;
605 }
606
607
608 #ifdef ENABLE_REWRITE
609 static char *
610 suffix_massage_regexize( const char *s )
611 {
612         char *res, *ptr;
613         const char *p, *r;
614         int i;
615
616         for ( i = 0, p = s; 
617                         ( r = strchr( p, ',' ) ) != NULL; 
618                         p = r + 1, i++ )
619                 ;
620
621         res = ch_calloc( sizeof( char ), strlen( s ) + 4 + 4*i + 1 );
622
623         ptr = lutil_strcopy( res, "(.*)" );
624         for ( i = 0, p = s;
625                         ( r = strchr( p, ',' ) ) != NULL;
626                         p = r + 1 , i++ ) {
627                 ptr = lutil_strncopy( ptr, p, r - p + 1 );
628                 ptr = lutil_strcopy( ptr, "[ ]?" );
629
630                 if ( r[ 1 ] == ' ' ) {
631                         r++;
632                 }
633         }
634         lutil_strcopy( ptr, p );
635
636         return res;
637 }
638
639 static char *
640 suffix_massage_patternize( const char *s )
641 {
642         ber_len_t       len;
643         char            *res;
644
645         len = strlen( s );
646
647         res = ch_calloc( sizeof( char ), len + sizeof( "%1" ) );
648         if ( res == NULL ) {
649                 return NULL;
650         }
651
652         strcpy( res, "%1" );
653         strcpy( res + sizeof( "%1" ) - 1, s );
654
655         return res;
656 }
657
658 int
659 suffix_massage_config( 
660                 struct rewrite_info *info,
661                 struct berval *pvnc,
662                 struct berval *nvnc,
663                 struct berval *prnc,
664                 struct berval *nrnc
665 )
666 {
667         char *rargv[ 5 ];
668         int line = 0;
669
670         rargv[ 0 ] = "rewriteEngine";
671         rargv[ 1 ] = "on";
672         rargv[ 2 ] = NULL;
673         rewrite_parse( info, "<suffix massage>", ++line, 2, rargv );
674
675         rargv[ 0 ] = "rewriteContext";
676         rargv[ 1 ] = "default";
677         rargv[ 2 ] = NULL;
678         rewrite_parse( info, "<suffix massage>", ++line, 2, rargv );
679
680         rargv[ 0 ] = "rewriteRule";
681         rargv[ 1 ] = suffix_massage_regexize( pvnc->bv_val );
682         rargv[ 2 ] = suffix_massage_patternize( prnc->bv_val );
683         rargv[ 3 ] = ":";
684         rargv[ 4 ] = NULL;
685         rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
686         ch_free( rargv[ 1 ] );
687         ch_free( rargv[ 2 ] );
688         
689         rargv[ 0 ] = "rewriteContext";
690         rargv[ 1 ] = "searchResult";
691         rargv[ 2 ] = NULL;
692         rewrite_parse( info, "<suffix massage>", ++line, 2, rargv );
693         
694         rargv[ 0 ] = "rewriteRule";
695         rargv[ 1 ] = suffix_massage_regexize( prnc->bv_val );
696         rargv[ 2 ] = suffix_massage_patternize( pvnc->bv_val );
697         rargv[ 3 ] = ":";
698         rargv[ 4 ] = NULL;
699         rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
700         ch_free( rargv[ 1 ] );
701         ch_free( rargv[ 2 ] );
702
703         rargv[ 0 ] = "rewriteContext";
704         rargv[ 1 ] = "matchedDN";
705         rargv[ 2 ] = "alias";
706         rargv[ 3 ] = "searchResult";
707         rargv[ 4 ] = NULL;
708         rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
709
710         rargv[ 0 ] = "rewriteContext";
711         rargv[ 1 ] = "searchAttrDN";
712         rargv[ 2 ] = "alias";
713         rargv[ 3 ] = "searchResult";
714         rargv[ 4 ] = NULL;
715         rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
716
717         return 0;
718 }
719 #endif /* ENABLE_REWRITE */
720
721 #ifdef LDAP_BACK_PROXY_AUTHZ
722 static int
723 parse_idassert(
724     BackendDB   *be,
725     const char  *fname,
726     int         lineno,
727     int         argc,
728     char        **argv
729 )
730 {
731         struct ldapinfo *li = (struct ldapinfo *) be->be_private;
732
733         /* identity assertion mode */
734         if ( strcasecmp( argv[0], "idassert-mode" ) == 0 ) {
735                 if ( argc != 2 ) {
736 #ifdef NEW_LOGGING
737                         LDAP_LOG( CONFIG, CRIT, 
738                                 "%s: line %d: illegal args number %d in \"idassert-mode <args>\" line.\n",
739                                 fname, lineno, argc );
740 #else
741                         Debug( LDAP_DEBUG_ANY,
742                                 "%s: line %d: illegal args number %d in \"idassert-mode <args>\" line.\n",
743                                 fname, lineno, argc );
744 #endif
745                         return 1;
746                 }
747
748                 if ( strcasecmp( argv[1], "legacy" ) == 0 ) {
749                         /* will proxyAuthz as client's identity only if bound */
750                         li->idassert_mode = LDAP_BACK_IDASSERT_LEGACY;
751
752                 } else if ( strcasecmp( argv[1], "self" ) == 0 ) {
753                         /* will proxyAuthz as client's identity */
754                         li->idassert_mode = LDAP_BACK_IDASSERT_SELF;
755
756                 } else if ( strcasecmp( argv[1], "anonymous" ) == 0 ) {
757                         /* will proxyAuthz as anonymous */
758                         li->idassert_mode = LDAP_BACK_IDASSERT_ANONYMOUS;
759
760                 } else if ( strcasecmp( argv[1], "none" ) == 0 ) {
761                         /* will not proxyAuthz */
762                         li->idassert_mode = LDAP_BACK_IDASSERT_NOASSERT;
763
764                 } else {
765                         struct berval   id;
766                         int             rc;
767
768                         /* will proxyAuthz as argv[1] */
769                         ber_str2bv( argv[1], 0, 0, &id );
770
771                         if ( strncasecmp( id.bv_val, "u:", STRLENOF( "u:" ) ) == 0 ) {
772                                 /* force lowercase... */
773                                 id.bv_val[0] = 'u';
774                                 li->idassert_mode = LDAP_BACK_IDASSERT_OTHERID;
775                                 ber_dupbv( &li->idassert_authzID, &id );
776
777                         } else {
778                                 struct berval   dn;
779
780                                 /* default is DN? */
781                                 if ( strncasecmp( id.bv_val, "dn:", STRLENOF( "dn:" ) ) == 0 ) {
782                                         id.bv_val += STRLENOF( "dn:" );
783                                         id.bv_len -= STRLENOF( "dn:" );
784                                 }
785
786                                 rc = dnNormalize( 0, NULL, NULL, &id, &dn, NULL );
787                                 if ( rc != LDAP_SUCCESS ) {
788 #ifdef NEW_LOGGING
789                                         LDAP_LOG( CONFIG, CRIT, 
790                                                 "%s: line %d: idassert ID \"%s\" is not a valid DN.\n",
791                                                 fname, lineno, argv[1] );
792 #else
793                                         Debug( LDAP_DEBUG_ANY,
794                                                 "%s: line %d: idassert ID \"%s\" is not a valid DN\n",
795                                                 fname, lineno, argv[1] );
796 #endif
797                                         return 1;
798                                 }
799
800                                 li->idassert_authzID.bv_len = STRLENOF( "dn:" ) + dn.bv_len;
801                                 li->idassert_authzID.bv_val = ch_malloc( li->idassert_authzID.bv_len + 1 );
802                                 AC_MEMCPY( li->idassert_authzID.bv_val, "dn:", STRLENOF( "dn:" ) );
803                                 AC_MEMCPY( &li->idassert_authzID.bv_val[ STRLENOF( "dn:" ) ], dn.bv_val, dn.bv_len + 1 );
804                                 ch_free( dn.bv_val );
805
806                                 li->idassert_mode = LDAP_BACK_IDASSERT_OTHERDN;
807                         }
808                 }
809
810         /* name to use for proxyAuthz propagation */
811         } else if ( strcasecmp( argv[0], "idassert-authcdn" ) == 0
812                         || strcasecmp( argv[0], "proxyauthzdn" ) == 0 )
813         {
814                 struct berval   dn;
815                 int             rc;
816
817                 /* FIXME: "proxyauthzdn" is no longer documented, and
818                  * temporarily supported for backwards compatibility */
819
820                 if ( argc != 2 ) {
821                         fprintf( stderr,
822         "%s: line %d: missing name in \"%s <name>\" line\n",
823                             fname, lineno, argv[0] );
824                         return( 1 );
825                 }
826
827                 if ( !BER_BVISNULL( &li->idassert_authcDN ) ) {
828                         fprintf( stderr, "%s: line %d: "
829                                         "authcDN already defined; replacing...\n",
830                                         fname, lineno );
831                         ch_free( li->idassert_authcDN.bv_val );
832                 }
833                 
834                 ber_str2bv( argv[1], 0, 0, &dn );
835                 rc = dnNormalize( 0, NULL, NULL, &dn, &li->idassert_authcDN, NULL );
836                 if ( rc != LDAP_SUCCESS ) {
837 #ifdef NEW_LOGGING
838                         LDAP_LOG( CONFIG, CRIT, 
839                                 "%s: line %d: idassert ID \"%s\" is not a valid DN.\n",
840                                 fname, lineno, argv[1] );
841 #else
842                         Debug( LDAP_DEBUG_ANY,
843                                 "%s: line %d: idassert ID \"%s\" is not a valid DN\n",
844                                 fname, lineno, argv[1] );
845 #endif
846                         return 1;
847                 }
848
849         /* password to use for proxyAuthz propagation */
850         } else if ( strcasecmp( argv[0], "idassert-passwd" ) == 0
851                         || strcasecmp( argv[0], "proxyauthzpw" ) == 0 )
852         {
853                 /* FIXME: "proxyauthzpw" is no longer documented, and
854                  * temporarily supported for backwards compatibility */
855
856                 if ( argc != 2 ) {
857                         fprintf( stderr,
858         "%s: line %d: missing password in \"%s <password>\" line\n",
859                             fname, lineno, argv[0] );
860                         return( 1 );
861                 }
862
863                 if ( !BER_BVISNULL( &li->idassert_passwd ) ) {
864                         fprintf( stderr, "%s: line %d: "
865                                         "passwd already defined; replacing...\n",
866                                         fname, lineno );
867                         ch_free( li->idassert_passwd.bv_val );
868                 }
869                 
870                 ber_str2bv( argv[1], 0, 1, &li->idassert_passwd );
871
872         /* rules to accept identity assertion... */
873         } else if ( strcasecmp( argv[0], "idassert-authzFrom" ) == 0 ) {
874                 struct berval   rule;
875
876                 ber_str2bv( argv[1], 0, 1, &rule );
877
878                 ber_bvarray_add( &li->idassert_authz, &rule );
879
880         } else if ( strcasecmp( argv[0], "idassert-method" ) == 0 ) {
881                 if ( argc < 2 ) {
882                         fprintf( stderr,
883         "%s: line %d: missing method in \"%s <method>\" line\n",
884                             fname, lineno, argv[0] );
885                         return( 1 );
886                 }
887
888                 if ( strcasecmp( argv[1], "none" ) == 0 ) {
889                         /* FIXME: is this useful? */
890                         li->idassert_authmethod = LDAP_AUTH_NONE;
891
892                         if ( argc != 2 ) {
893                                 fprintf( stderr,
894         "%s: line %d: trailing args in \"%s %s ...\" line ignored\"\n",
895                                         fname, lineno, argv[0], argv[1] );
896                         }
897
898                 } else if ( strcasecmp( argv[1], "simple" ) == 0 ) {
899                         li->idassert_authmethod = LDAP_AUTH_SIMPLE;
900
901                         if ( argc != 2 ) {
902                                 fprintf( stderr,
903         "%s: line %d: trailing args in \"%s %s ...\" line ignored\"\n",
904                                         fname, lineno, argv[0], argv[1] );
905                         }
906
907                 } else if ( strcasecmp( argv[1], "sasl" ) == 0 ) {
908 #ifdef HAVE_CYRUS_SASL
909                         int     arg;
910
911                         for ( arg = 2; arg < argc; arg++ ) {
912                                 if ( strncasecmp( argv[arg], "mech=", STRLENOF( "mech=" ) ) == 0 ) {
913                                         char    *val = argv[arg] + STRLENOF( "mech=" );
914
915                                         if ( !BER_BVISNULL( &li->idassert_sasl_mech ) ) {
916                                                 fprintf( stderr, "%s: line %d: "
917                                                                 "SASL mech already defined; replacing...\n",
918                                                                 fname, lineno );
919                                                 ch_free( li->idassert_sasl_mech.bv_val );
920                                         }
921                                         ber_str2bv( val, 0, 1, &li->idassert_sasl_mech );
922
923                                 } else if ( strncasecmp( argv[arg], "realm=", STRLENOF( "realm=" ) ) == 0 ) {
924                                         char    *val = argv[arg] + STRLENOF( "realm=" );
925
926                                         if ( !BER_BVISNULL( &li->idassert_sasl_realm ) ) {
927                                                 fprintf( stderr, "%s: line %d: "
928                                                                 "SASL realm already defined; replacing...\n",
929                                                                 fname, lineno );
930                                                 ch_free( li->idassert_sasl_realm.bv_val );
931                                         }
932                                         ber_str2bv( val, 0, 1, &li->idassert_sasl_realm );
933
934                                 } else if ( strncasecmp( argv[arg], "authcdn=", STRLENOF( "authcdn=" ) ) == 0 ) {
935                                         char            *val = argv[arg] + STRLENOF( "authcdn=" );
936                                         struct berval   dn;
937                                         int             rc;
938
939                                         if ( !BER_BVISNULL( &li->idassert_authcDN ) ) {
940                                                 fprintf( stderr, "%s: line %d: "
941                                                                 "SASL authcDN already defined; replacing...\n",
942                                                                 fname, lineno );
943                                                 ch_free( li->idassert_authcDN.bv_val );
944                                         }
945                                         if ( strncasecmp( argv[arg], "dn:", STRLENOF( "dn:" ) ) == 0 ) {
946                                                 val += STRLENOF( "dn:" );
947                                         }
948
949                                         ber_str2bv( val, 0, 0, &dn );
950                                         rc = dnNormalize( 0, NULL, NULL, &dn, &li->idassert_authcDN, NULL );
951                                         if ( rc != LDAP_SUCCESS ) {
952 #ifdef NEW_LOGGING
953                                                 LDAP_LOG( CONFIG, CRIT, 
954                                                         "%s: line %d: SASL authcdn \"%s\" is not a valid DN.\n",
955                                                         fname, lineno, val );
956 #else
957                                                 Debug( LDAP_DEBUG_ANY,
958                                                         "%s: line %d: SASL authcdn \"%s\" is not a valid DN\n",
959                                                         fname, lineno, val );
960 #endif
961                                                 return 1;
962                                         }
963
964                                 } else if ( strncasecmp( argv[arg], "authcid=", STRLENOF( "authcid=" ) ) == 0 ) {
965                                         char    *val = argv[arg] + STRLENOF( "authcid=" );
966
967                                         if ( !BER_BVISNULL( &li->idassert_authcID ) ) {
968                                                 fprintf( stderr, "%s: line %d: "
969                                                                 "SASL authcID already defined; replacing...\n",
970                                                                 fname, lineno );
971                                                 ch_free( li->idassert_authcID.bv_val );
972                                         }
973                                         if ( strncasecmp( argv[arg], "u:", STRLENOF( "u:" ) ) == 0 ) {
974                                                 val += STRLENOF( "u:" );
975                                         }
976                                         ber_str2bv( val, 0, 1, &li->idassert_authcID );
977
978                                 } else if ( strncasecmp( argv[arg], "cred=", STRLENOF( "cred=" ) ) == 0 ) {
979                                         char    *val = argv[arg] + STRLENOF( "cred=" );
980
981                                         if ( !BER_BVISNULL( &li->idassert_passwd ) ) {
982                                                 fprintf( stderr, "%s: line %d: "
983                                                                 "SASL cred already defined; replacing...\n",
984                                                                 fname, lineno );
985                                                 ch_free( li->idassert_passwd.bv_val );
986                                         }
987                                         ber_str2bv( val, 0, 1, &li->idassert_passwd );
988
989                                 } else if ( strncasecmp( argv[arg], "authz=", STRLENOF( "authz=" ) ) == 0 ) {
990                                         char    *val = argv[arg] + STRLENOF( "authz=" );
991
992                                         if ( strcasecmp( val, "proxyauthz" ) == 0 ) {
993                                                 li->idassert_flags &= ~LDAP_BACK_AUTH_NATIVE_AUTHZ;
994
995                                         } else if ( strcasecmp( val, "native" ) == 0 ) {
996                                                 li->idassert_flags |= LDAP_BACK_AUTH_NATIVE_AUTHZ;
997
998                                         } else {
999                                                 fprintf( stderr, "%s: line %s: "
1000                                                         "unknown authz mode \"%s\"\n",
1001                                                         fname, lineno, val );
1002                                                 return 1;
1003                                         }
1004
1005                                 } else {
1006                                         fprintf( stderr, "%s: line %d: "
1007                                                         "unknown SASL parameter %s\n",
1008                                                         fname, lineno, argv[arg] );
1009                                         return 1;
1010                                 }
1011                         }
1012
1013                         li->idassert_authmethod = LDAP_AUTH_SASL;
1014
1015 #else /* !HAVE_CYRUS_SASL */
1016                         fprintf( stderr, "%s: line %d: "
1017                                         "compile --with-cyrus-sasl to enable SASL auth\n",
1018                                         fname, lineno );
1019                         return 1;
1020 #endif /* !HAVE_CYRUS_SASL */
1021
1022                 } else {
1023                         fprintf( stderr, "%s: line %d: "
1024                                         "unhandled idassert-method method %s\n",
1025                                         fname, lineno, argv[1] );
1026                         return 1;
1027                 }
1028
1029         } else {
1030                 return SLAP_CONF_UNKNOWN;
1031         }
1032
1033         return 0;
1034 }
1035 #endif /* LDAP_BACK_PROXY_AUTHZ */