]> git.sur5r.net Git - openldap/blob - servers/slapd/back-ldap/config.c
91de42d173784dfaa4dc34093a54e5b21a5f3c42
[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                 int do_retry = 1;
557
558                 ctrls[0] = &c;
559                 op2.o_ndn = op->o_conn->c_ndn;
560                 lc = ldap_back_getconn(&op2, rs);
561                 if (!lc || !ldap_back_dobind( lc, op, rs )) {
562                         return -1;
563                 }
564                 c.ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
565                 c.ldctl_iscritical = 1;
566                 c.ldctl_value.bv_val = ch_malloc(op->o_ndn.bv_len+4);
567                 c.ldctl_value.bv_len = op->o_ndn.bv_len + 3;
568                 strcpy(c.ldctl_value.bv_val, "dn:");
569                 strcpy(c.ldctl_value.bv_val+3, op->o_ndn.bv_val);
570
571 retry:
572                 rs->sr_err = ldap_whoami(lc->ld, ctrls, NULL, &msgid);
573                 if (rs->sr_err == LDAP_SUCCESS) {
574                         if (ldap_result(lc->ld, msgid, 1, NULL, &res) == -1) {
575                                 ldap_get_option(lc->ld, LDAP_OPT_ERROR_NUMBER,
576                                         &rs->sr_err);
577                                 if ( rs->sr_err == LDAP_SERVER_DOWN && do_retry ) {
578                                         do_retry = 0;
579                                         if ( ldap_back_retry( lc, op, rs ) )
580                                                 goto retry;
581                                 }
582                                 ldap_back_freeconn( op, lc );
583                                 lc = NULL;
584
585                         } else {
586                                 rs->sr_err = ldap_parse_whoami(lc->ld, res, &bv);
587                                 ldap_msgfree(res);
588                         }
589                 }
590                 ch_free(c.ldctl_value.bv_val);
591                 if (rs->sr_err != LDAP_SUCCESS) {
592                         rs->sr_err = slap_map_api2result( rs );
593                 }
594         } else {
595         /* else just do the same as before */
596                 bv = (struct berval *) ch_malloc( sizeof(struct berval) );
597                 if( op->o_dn.bv_len ) {
598                         bv->bv_len = op->o_dn.bv_len + sizeof("dn:") - 1;
599                         bv->bv_val = ch_malloc( bv->bv_len + 1 );
600                         AC_MEMCPY( bv->bv_val, "dn:", sizeof("dn:") - 1 );
601                         AC_MEMCPY( &bv->bv_val[sizeof("dn:") - 1], op->o_dn.bv_val,
602                                 op->o_dn.bv_len );
603                         bv->bv_val[bv->bv_len] = '\0';
604                 } else {
605                         bv->bv_len = 0;
606                         bv->bv_val = NULL;
607                 }
608         }
609
610         rs->sr_rspdata = bv;
611         return rs->sr_err;
612 }
613
614
615 #ifdef ENABLE_REWRITE
616 static char *
617 suffix_massage_regexize( const char *s )
618 {
619         char *res, *ptr;
620         const char *p, *r;
621         int i;
622
623         for ( i = 0, p = s; 
624                         ( r = strchr( p, ',' ) ) != NULL; 
625                         p = r + 1, i++ )
626                 ;
627
628         res = ch_calloc( sizeof( char ), strlen( s ) + 4 + 4*i + 1 );
629
630         ptr = lutil_strcopy( res, "(.*)" );
631         for ( i = 0, p = s;
632                         ( r = strchr( p, ',' ) ) != NULL;
633                         p = r + 1 , i++ ) {
634                 ptr = lutil_strncopy( ptr, p, r - p + 1 );
635                 ptr = lutil_strcopy( ptr, "[ ]?" );
636
637                 if ( r[ 1 ] == ' ' ) {
638                         r++;
639                 }
640         }
641         lutil_strcopy( ptr, p );
642
643         return res;
644 }
645
646 static char *
647 suffix_massage_patternize( const char *s )
648 {
649         ber_len_t       len;
650         char            *res;
651
652         len = strlen( s );
653
654         res = ch_calloc( sizeof( char ), len + sizeof( "%1" ) );
655         if ( res == NULL ) {
656                 return NULL;
657         }
658
659         strcpy( res, "%1" );
660         strcpy( res + sizeof( "%1" ) - 1, s );
661
662         return res;
663 }
664
665 int
666 suffix_massage_config( 
667                 struct rewrite_info *info,
668                 struct berval *pvnc,
669                 struct berval *nvnc,
670                 struct berval *prnc,
671                 struct berval *nrnc
672 )
673 {
674         char *rargv[ 5 ];
675         int line = 0;
676
677         rargv[ 0 ] = "rewriteEngine";
678         rargv[ 1 ] = "on";
679         rargv[ 2 ] = NULL;
680         rewrite_parse( info, "<suffix massage>", ++line, 2, rargv );
681
682         rargv[ 0 ] = "rewriteContext";
683         rargv[ 1 ] = "default";
684         rargv[ 2 ] = NULL;
685         rewrite_parse( info, "<suffix massage>", ++line, 2, rargv );
686
687         rargv[ 0 ] = "rewriteRule";
688         rargv[ 1 ] = suffix_massage_regexize( pvnc->bv_val );
689         rargv[ 2 ] = suffix_massage_patternize( prnc->bv_val );
690         rargv[ 3 ] = ":";
691         rargv[ 4 ] = NULL;
692         rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
693         ch_free( rargv[ 1 ] );
694         ch_free( rargv[ 2 ] );
695         
696         rargv[ 0 ] = "rewriteContext";
697         rargv[ 1 ] = "searchResult";
698         rargv[ 2 ] = NULL;
699         rewrite_parse( info, "<suffix massage>", ++line, 2, rargv );
700         
701         rargv[ 0 ] = "rewriteRule";
702         rargv[ 1 ] = suffix_massage_regexize( prnc->bv_val );
703         rargv[ 2 ] = suffix_massage_patternize( pvnc->bv_val );
704         rargv[ 3 ] = ":";
705         rargv[ 4 ] = NULL;
706         rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
707         ch_free( rargv[ 1 ] );
708         ch_free( rargv[ 2 ] );
709
710         rargv[ 0 ] = "rewriteContext";
711         rargv[ 1 ] = "matchedDN";
712         rargv[ 2 ] = "alias";
713         rargv[ 3 ] = "searchResult";
714         rargv[ 4 ] = NULL;
715         rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
716
717         rargv[ 0 ] = "rewriteContext";
718         rargv[ 1 ] = "searchAttrDN";
719         rargv[ 2 ] = "alias";
720         rargv[ 3 ] = "searchResult";
721         rargv[ 4 ] = NULL;
722         rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
723
724         return 0;
725 }
726 #endif /* ENABLE_REWRITE */
727
728 #ifdef LDAP_BACK_PROXY_AUTHZ
729 static int
730 parse_idassert(
731     BackendDB   *be,
732     const char  *fname,
733     int         lineno,
734     int         argc,
735     char        **argv
736 )
737 {
738         struct ldapinfo *li = (struct ldapinfo *) be->be_private;
739
740         /* identity assertion mode */
741         if ( strcasecmp( argv[0], "idassert-mode" ) == 0 ) {
742                 if ( argc != 2 ) {
743                         Debug( LDAP_DEBUG_ANY,
744                                 "%s: line %d: illegal args number %d in \"idassert-mode <args>\" line.\n",
745                                 fname, lineno, argc );
746                         return 1;
747                 }
748
749                 if ( strcasecmp( argv[1], "legacy" ) == 0 ) {
750                         /* will proxyAuthz as client's identity only if bound */
751                         li->idassert_mode = LDAP_BACK_IDASSERT_LEGACY;
752
753                 } else if ( strcasecmp( argv[1], "self" ) == 0 ) {
754                         /* will proxyAuthz as client's identity */
755                         li->idassert_mode = LDAP_BACK_IDASSERT_SELF;
756
757                 } else if ( strcasecmp( argv[1], "anonymous" ) == 0 ) {
758                         /* will proxyAuthz as anonymous */
759                         li->idassert_mode = LDAP_BACK_IDASSERT_ANONYMOUS;
760
761                 } else if ( strcasecmp( argv[1], "none" ) == 0 ) {
762                         /* will not proxyAuthz */
763                         li->idassert_mode = LDAP_BACK_IDASSERT_NOASSERT;
764
765                 } else {
766                         struct berval   id;
767                         int             rc;
768
769                         /* will proxyAuthz as argv[1] */
770                         ber_str2bv( argv[1], 0, 0, &id );
771
772                         if ( strncasecmp( id.bv_val, "u:", STRLENOF( "u:" ) ) == 0 ) {
773                                 /* force lowercase... */
774                                 id.bv_val[0] = 'u';
775                                 li->idassert_mode = LDAP_BACK_IDASSERT_OTHERID;
776                                 ber_dupbv( &li->idassert_authzID, &id );
777
778                         } else {
779                                 struct berval   dn;
780
781                                 /* default is DN? */
782                                 if ( strncasecmp( id.bv_val, "dn:", STRLENOF( "dn:" ) ) == 0 ) {
783                                         id.bv_val += STRLENOF( "dn:" );
784                                         id.bv_len -= STRLENOF( "dn:" );
785                                 }
786
787                                 rc = dnNormalize( 0, NULL, NULL, &id, &dn, NULL );
788                                 if ( rc != LDAP_SUCCESS ) {
789                                         Debug( LDAP_DEBUG_ANY,
790                                                 "%s: line %d: idassert ID \"%s\" is not a valid DN\n",
791                                                 fname, lineno, argv[1] );
792                                         return 1;
793                                 }
794
795                                 li->idassert_authzID.bv_len = STRLENOF( "dn:" ) + dn.bv_len;
796                                 li->idassert_authzID.bv_val = ch_malloc( li->idassert_authzID.bv_len + 1 );
797                                 AC_MEMCPY( li->idassert_authzID.bv_val, "dn:", STRLENOF( "dn:" ) );
798                                 AC_MEMCPY( &li->idassert_authzID.bv_val[ STRLENOF( "dn:" ) ], dn.bv_val, dn.bv_len + 1 );
799                                 ch_free( dn.bv_val );
800
801                                 li->idassert_mode = LDAP_BACK_IDASSERT_OTHERDN;
802                         }
803                 }
804
805         /* name to use for proxyAuthz propagation */
806         } else if ( strcasecmp( argv[0], "idassert-authcdn" ) == 0
807                         || strcasecmp( argv[0], "proxyauthzdn" ) == 0 )
808         {
809                 struct berval   dn;
810                 int             rc;
811
812                 /* FIXME: "proxyauthzdn" is no longer documented, and
813                  * temporarily supported for backwards compatibility */
814
815                 if ( argc != 2 ) {
816                         fprintf( stderr,
817         "%s: line %d: missing name in \"%s <name>\" line\n",
818                             fname, lineno, argv[0] );
819                         return( 1 );
820                 }
821
822                 if ( !BER_BVISNULL( &li->idassert_authcDN ) ) {
823                         fprintf( stderr, "%s: line %d: "
824                                         "authcDN already defined; replacing...\n",
825                                         fname, lineno );
826                         ch_free( li->idassert_authcDN.bv_val );
827                 }
828                 
829                 ber_str2bv( argv[1], 0, 0, &dn );
830                 rc = dnNormalize( 0, NULL, NULL, &dn, &li->idassert_authcDN, NULL );
831                 if ( rc != LDAP_SUCCESS ) {
832                         Debug( LDAP_DEBUG_ANY,
833                                 "%s: line %d: idassert ID \"%s\" is not a valid DN\n",
834                                 fname, lineno, argv[1] );
835                         return 1;
836                 }
837
838         /* password to use for proxyAuthz propagation */
839         } else if ( strcasecmp( argv[0], "idassert-passwd" ) == 0
840                         || strcasecmp( argv[0], "proxyauthzpw" ) == 0 )
841         {
842                 /* FIXME: "proxyauthzpw" is no longer documented, and
843                  * temporarily supported for backwards compatibility */
844
845                 if ( argc != 2 ) {
846                         fprintf( stderr,
847         "%s: line %d: missing password in \"%s <password>\" line\n",
848                             fname, lineno, argv[0] );
849                         return( 1 );
850                 }
851
852                 if ( !BER_BVISNULL( &li->idassert_passwd ) ) {
853                         fprintf( stderr, "%s: line %d: "
854                                         "passwd already defined; replacing...\n",
855                                         fname, lineno );
856                         ch_free( li->idassert_passwd.bv_val );
857                 }
858                 
859                 ber_str2bv( argv[1], 0, 1, &li->idassert_passwd );
860
861         /* rules to accept identity assertion... */
862         } else if ( strcasecmp( argv[0], "idassert-authzFrom" ) == 0 ) {
863                 struct berval   rule;
864
865                 ber_str2bv( argv[1], 0, 1, &rule );
866
867                 ber_bvarray_add( &li->idassert_authz, &rule );
868
869         } else if ( strcasecmp( argv[0], "idassert-method" ) == 0 ) {
870                 if ( argc < 2 ) {
871                         fprintf( stderr,
872         "%s: line %d: missing method in \"%s <method>\" line\n",
873                             fname, lineno, argv[0] );
874                         return( 1 );
875                 }
876
877                 if ( strcasecmp( argv[1], "none" ) == 0 ) {
878                         /* FIXME: is this useful? */
879                         li->idassert_authmethod = LDAP_AUTH_NONE;
880
881                         if ( argc != 2 ) {
882                                 fprintf( stderr,
883         "%s: line %d: trailing args in \"%s %s ...\" line ignored\"\n",
884                                         fname, lineno, argv[0], argv[1] );
885                         }
886
887                 } else if ( strcasecmp( argv[1], "simple" ) == 0 ) {
888                         li->idassert_authmethod = LDAP_AUTH_SIMPLE;
889
890                         if ( argc != 2 ) {
891                                 fprintf( stderr,
892         "%s: line %d: trailing args in \"%s %s ...\" line ignored\"\n",
893                                         fname, lineno, argv[0], argv[1] );
894                         }
895
896                 } else if ( strcasecmp( argv[1], "sasl" ) == 0 ) {
897 #ifdef HAVE_CYRUS_SASL
898                         int     arg;
899
900                         for ( arg = 2; arg < argc; arg++ ) {
901                                 if ( strncasecmp( argv[arg], "mech=", STRLENOF( "mech=" ) ) == 0 ) {
902                                         char    *val = argv[arg] + STRLENOF( "mech=" );
903
904                                         if ( !BER_BVISNULL( &li->idassert_sasl_mech ) ) {
905                                                 fprintf( stderr, "%s: line %d: "
906                                                                 "SASL mech already defined; replacing...\n",
907                                                                 fname, lineno );
908                                                 ch_free( li->idassert_sasl_mech.bv_val );
909                                         }
910                                         ber_str2bv( val, 0, 1, &li->idassert_sasl_mech );
911
912                                 } else if ( strncasecmp( argv[arg], "realm=", STRLENOF( "realm=" ) ) == 0 ) {
913                                         char    *val = argv[arg] + STRLENOF( "realm=" );
914
915                                         if ( !BER_BVISNULL( &li->idassert_sasl_realm ) ) {
916                                                 fprintf( stderr, "%s: line %d: "
917                                                                 "SASL realm already defined; replacing...\n",
918                                                                 fname, lineno );
919                                                 ch_free( li->idassert_sasl_realm.bv_val );
920                                         }
921                                         ber_str2bv( val, 0, 1, &li->idassert_sasl_realm );
922
923                                 } else if ( strncasecmp( argv[arg], "authcdn=", STRLENOF( "authcdn=" ) ) == 0 ) {
924                                         char            *val = argv[arg] + STRLENOF( "authcdn=" );
925                                         struct berval   dn;
926                                         int             rc;
927
928                                         if ( !BER_BVISNULL( &li->idassert_authcDN ) ) {
929                                                 fprintf( stderr, "%s: line %d: "
930                                                                 "SASL authcDN already defined; replacing...\n",
931                                                                 fname, lineno );
932                                                 ch_free( li->idassert_authcDN.bv_val );
933                                         }
934                                         if ( strncasecmp( argv[arg], "dn:", STRLENOF( "dn:" ) ) == 0 ) {
935                                                 val += STRLENOF( "dn:" );
936                                         }
937
938                                         ber_str2bv( val, 0, 0, &dn );
939                                         rc = dnNormalize( 0, NULL, NULL, &dn, &li->idassert_authcDN, NULL );
940                                         if ( rc != LDAP_SUCCESS ) {
941                                                 Debug( LDAP_DEBUG_ANY,
942                                                         "%s: line %d: SASL authcdn \"%s\" is not a valid DN\n",
943                                                         fname, lineno, val );
944                                                 return 1;
945                                         }
946
947                                 } else if ( strncasecmp( argv[arg], "authcid=", STRLENOF( "authcid=" ) ) == 0 ) {
948                                         char    *val = argv[arg] + STRLENOF( "authcid=" );
949
950                                         if ( !BER_BVISNULL( &li->idassert_authcID ) ) {
951                                                 fprintf( stderr, "%s: line %d: "
952                                                                 "SASL authcID already defined; replacing...\n",
953                                                                 fname, lineno );
954                                                 ch_free( li->idassert_authcID.bv_val );
955                                         }
956                                         if ( strncasecmp( argv[arg], "u:", STRLENOF( "u:" ) ) == 0 ) {
957                                                 val += STRLENOF( "u:" );
958                                         }
959                                         ber_str2bv( val, 0, 1, &li->idassert_authcID );
960
961                                 } else if ( strncasecmp( argv[arg], "cred=", STRLENOF( "cred=" ) ) == 0 ) {
962                                         char    *val = argv[arg] + STRLENOF( "cred=" );
963
964                                         if ( !BER_BVISNULL( &li->idassert_passwd ) ) {
965                                                 fprintf( stderr, "%s: line %d: "
966                                                                 "SASL cred already defined; replacing...\n",
967                                                                 fname, lineno );
968                                                 ch_free( li->idassert_passwd.bv_val );
969                                         }
970                                         ber_str2bv( val, 0, 1, &li->idassert_passwd );
971
972                                 } else if ( strncasecmp( argv[arg], "authz=", STRLENOF( "authz=" ) ) == 0 ) {
973                                         char    *val = argv[arg] + STRLENOF( "authz=" );
974
975                                         if ( strcasecmp( val, "proxyauthz" ) == 0 ) {
976                                                 li->idassert_flags &= ~LDAP_BACK_AUTH_NATIVE_AUTHZ;
977
978                                         } else if ( strcasecmp( val, "native" ) == 0 ) {
979                                                 li->idassert_flags |= LDAP_BACK_AUTH_NATIVE_AUTHZ;
980
981                                         } else {
982                                                 fprintf( stderr, "%s: line %s: "
983                                                         "unknown authz mode \"%s\"\n",
984                                                         fname, lineno, val );
985                                                 return 1;
986                                         }
987
988                                 } else {
989                                         fprintf( stderr, "%s: line %d: "
990                                                         "unknown SASL parameter %s\n",
991                                                         fname, lineno, argv[arg] );
992                                         return 1;
993                                 }
994                         }
995
996                         li->idassert_authmethod = LDAP_AUTH_SASL;
997
998 #else /* !HAVE_CYRUS_SASL */
999                         fprintf( stderr, "%s: line %d: "
1000                                         "compile --with-cyrus-sasl to enable SASL auth\n",
1001                                         fname, lineno );
1002                         return 1;
1003 #endif /* !HAVE_CYRUS_SASL */
1004
1005                 } else {
1006                         fprintf( stderr, "%s: line %d: "
1007                                         "unhandled idassert-method method %s\n",
1008                                         fname, lineno, argv[1] );
1009                         return 1;
1010                 }
1011
1012         } else {
1013                 return SLAP_CONF_UNKNOWN;
1014         }
1015
1016         return 0;
1017 }
1018 #endif /* LDAP_BACK_PROXY_AUTHZ */