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