]> git.sur5r.net Git - openldap/blob - servers/slapd/back-ldap/config.c
fedc477b90f240ff142f69d18d7fcae0aac0880d
[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 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 int
38 ldap_back_db_config(
39     BackendDB   *be,
40     const char  *fname,
41     int         lineno,
42     int         argc,
43     char        **argv
44 )
45 {
46         struct ldapinfo *li = (struct ldapinfo *) be->be_private;
47
48         if ( li == NULL ) {
49                 fprintf( stderr, "%s: line %d: ldap backend info is null!\n",
50                     fname, lineno );
51                 return( 1 );
52         }
53
54         /* server address to query (depricated, use "uri" directive) */
55         if ( strcasecmp( argv[0], "server" ) == 0 ) {
56                 if (argc != 2) {
57                         fprintf( stderr,
58         "%s: line %d: missing address in \"server <address>\" line\n",
59                             fname, lineno );
60                         return( 1 );
61                 }
62                 if (li->url != NULL)
63                         ch_free(li->url);
64                 li->url = ch_calloc(strlen(argv[1]) + 9, sizeof(char));
65                 if (li->url != NULL) {
66                         strcpy(li->url, "ldap://");
67                         strcat(li->url, argv[1]);
68                         strcat(li->url, "/");
69                 }
70
71         /* URI of server to query (preferred over "server" directive) */
72         } else if ( strcasecmp( argv[0], "uri" ) == 0 ) {
73                 if (argc != 2) {
74                         fprintf( stderr,
75         "%s: line %d: missing address in \"uri <address>\" line\n",
76                             fname, lineno );
77                         return( 1 );
78                 }
79                 if (li->url != NULL)
80                         ch_free(li->url);
81                 li->url = ch_strdup(argv[1]);
82
83         /* name to use for ldap_back_group */
84         } else if ( strcasecmp( argv[0], "binddn" ) == 0 ) {
85                 if (argc != 2) {
86                         fprintf( stderr,
87         "%s: line %d: missing name in \"binddn <name>\" line\n",
88                             fname, lineno );
89                         return( 1 );
90                 }
91                 ber_str2bv( argv[1], 0, 1, &li->binddn );
92
93         /* password to use for ldap_back_group */
94         } else if ( strcasecmp( argv[0], "bindpw" ) == 0 ) {
95                 if (argc != 2) {
96                         fprintf( stderr,
97         "%s: line %d: missing password in \"bindpw <password>\" line\n",
98                             fname, lineno );
99                         return( 1 );
100                 }
101                 ber_str2bv( argv[1], 0, 1, &li->bindpw );
102         
103         /* save bind creds for referral rebinds? */
104         } else if ( strcasecmp( argv[0], "rebind-as-user" ) == 0 ) {
105                 if (argc != 1) {
106                         fprintf( stderr,
107         "%s: line %d: rebind-as-user takes no arguments\n",
108                             fname, lineno );
109                         return( 1 );
110                 }
111                 li->savecred = 1;
112         
113         /* intercept exop_who_am_i? */
114         } else if ( strcasecmp( argv[0], "proxy-whoami" ) == 0 ) {
115                 if (argc != 1) {
116                         fprintf( stderr,
117         "%s: line %d: proxy-whoami takes no arguments\n",
118                             fname, lineno );
119                         return( 1 );
120                 }
121                 load_extop( (struct berval *)&slap_EXOP_WHOAMI,
122                         0, ldap_back_exop_whoami );
123         
124         /* dn massaging */
125         } else if ( strcasecmp( argv[0], "suffixmassage" ) == 0 ) {
126                 BackendDB *tmp_be;
127                 struct berval bvnc, nvnc, pvnc, brnc, nrnc, prnc;
128 #ifdef ENABLE_REWRITE
129                 int rc;
130 #endif /* ENABLE_REWRITE */
131                 
132                 /*
133                  * syntax:
134                  * 
135                  *      suffixmassage <suffix> <massaged suffix>
136                  *
137                  * the <suffix> field must be defined as a valid suffix
138                  * (or suffixAlias?) for the current database;
139                  * the <massaged suffix> shouldn't have already been
140                  * defined as a valid suffix or suffixAlias for the 
141                  * current server
142                  */
143                 if ( argc != 3 ) {
144                         fprintf( stderr, "%s: line %d: syntax is"
145                                        " \"suffixMassage <suffix>"
146                                        " <massaged suffix>\"\n",
147                                 fname, lineno );
148                         return( 1 );
149                 }
150                 
151                 ber_str2bv( argv[1], 0, 0, &bvnc );
152                 if ( dnPrettyNormal( NULL, &bvnc, &pvnc, &nvnc, NULL ) != LDAP_SUCCESS ) {
153                         fprintf( stderr, "%s: line %d: suffix DN %s is invalid\n",
154                                 fname, lineno, bvnc.bv_val );
155                         return( 1 );
156                 }
157                 tmp_be = select_backend( &nvnc, 0, 0 );
158                 if ( tmp_be != NULL && tmp_be != be ) {
159                         fprintf( stderr, "%s: line %d: suffix already in use"
160                                        " by another backend in"
161                                        " \"suffixMassage <suffix>"
162                                        " <massaged suffix>\"\n",
163                                 fname, lineno );
164                         free( nvnc.bv_val );
165                         free( pvnc.bv_val );
166                         return( 1 );
167                 }
168
169                 ber_str2bv( argv[2], 0, 0, &brnc );
170                 if ( dnPrettyNormal( NULL, &brnc, &prnc, &nrnc, NULL ) != LDAP_SUCCESS ) {
171                         fprintf( stderr, "%s: line %d: suffix DN %s is invalid\n",
172                                 fname, lineno, brnc.bv_val );
173                         free( nvnc.bv_val );
174                         free( pvnc.bv_val );
175                         return( 1 );
176                 }
177
178 #if 0
179                 tmp_be = select_backend( &nrnc, 0, 0 );
180                 if ( tmp_be != NULL ) {
181                         fprintf( stderr, "%s: line %d: massaged suffix"
182                                        " already in use by another backend in" 
183                                        " \"suffixMassage <suffix>"
184                                        " <massaged suffix>\"\n",
185                                 fname, lineno );
186                         free( nvnc.bv_val );
187                         free( pvnc.bv_val );
188                         free( nrnc.bv_val );
189                         free( prnc.bv_val );
190                         return( 1 );
191                 }
192 #endif
193
194 #ifdef ENABLE_REWRITE
195                 /*
196                  * The suffix massaging is emulated by means of the
197                  * rewrite capabilities
198                  * FIXME: no extra rewrite capabilities should be added
199                  * to the database
200                  */
201                 rc = suffix_massage_config( li->rwmap.rwm_rw,
202                                 &pvnc, &nvnc, &prnc, &nrnc );
203                 free( nvnc.bv_val );
204                 free( pvnc.bv_val );
205                 free( nrnc.bv_val );
206                 free( prnc.bv_val );
207
208                 return( rc );
209
210 #else /* !ENABLE_REWRITE */
211                 ber_bvarray_add( &li->rwmap.rwm_suffix_massage, &pvnc );
212                 ber_bvarray_add( &li->rwmap.rwm_suffix_massage, &nvnc );
213                 
214                 ber_bvarray_add( &li->rwmap.rwm_suffix_massage, &prnc );
215                 ber_bvarray_add( &li->rwmap.rwm_suffix_massage, &nrnc );
216 #endif /* !ENABLE_REWRITE */
217
218         /* rewrite stuff ... */
219         } else if ( strncasecmp( argv[0], "rewrite", 7 ) == 0 ) {
220 #ifdef ENABLE_REWRITE
221                 return rewrite_parse( li->rwmap.rwm_rw,
222                                 fname, lineno, argc, argv );
223
224 #else /* !ENABLE_REWRITE */
225                 fprintf( stderr, "%s: line %d: rewrite capabilities "
226                                 "are not enabled\n", fname, lineno );
227 #endif /* !ENABLE_REWRITE */
228                 
229         /* objectclass/attribute mapping */
230         } else if ( strcasecmp( argv[0], "map" ) == 0 ) {
231                 return ldap_back_map_config( &li->rwmap.rwm_oc,
232                                 &li->rwmap.rwm_at,
233                                 fname, lineno, argc, argv );
234
235         /* anything else */
236         } else {
237                 return SLAP_CONF_UNKNOWN;
238         }
239         return 0;
240 }
241
242 int
243 ldap_back_map_config(
244                 struct ldapmap  *oc_map,
245                 struct ldapmap  *at_map,
246                 const char      *fname,
247                 int             lineno,
248                 int             argc,
249                 char            **argv )
250 {
251         struct ldapmap          *map;
252         struct ldapmapping      *mapping;
253         char                    *src, *dst;
254         int                     is_oc = 0;
255
256         if ( argc < 3 || argc > 4 ) {
257                 fprintf( stderr,
258         "%s: line %d: syntax is \"map {objectclass | attribute} [<local> | *] {<foreign> | *}\"\n",
259                         fname, lineno );
260                 return 1;
261         }
262
263         if ( strcasecmp( argv[1], "objectclass" ) == 0 ) {
264                 map = oc_map;
265                 is_oc = 1;
266
267         } else if ( strcasecmp( argv[1], "attribute" ) == 0 ) {
268                 map = at_map;
269
270         } else {
271                 fprintf( stderr, "%s: line %d: syntax is "
272                         "\"map {objectclass | attribute} [<local> | *] "
273                         "{<foreign> | *}\"\n",
274                         fname, lineno );
275                 return 1;
276         }
277
278         if ( strcmp( argv[2], "*" ) == 0 ) {
279                 if ( argc < 4 || strcmp( argv[3], "*" ) == 0 ) {
280                         map->drop_missing = ( argc < 4 );
281                         return 0;
282                 }
283                 src = dst = argv[3];
284
285         } else if ( argc < 4 ) {
286                 src = "";
287                 dst = argv[2];
288
289         } else {
290                 src = argv[2];
291                 dst = ( strcmp( argv[3], "*" ) == 0 ? src : argv[3] );
292         }
293
294         if ( ( map == at_map )
295                         && ( strcasecmp( src, "objectclass" ) == 0
296                         || strcasecmp( dst, "objectclass" ) == 0 ) )
297         {
298                 fprintf( stderr,
299                         "%s: line %d: objectclass attribute cannot be mapped\n",
300                         fname, lineno );
301         }
302
303         mapping = (struct ldapmapping *)ch_calloc( 2,
304                 sizeof(struct ldapmapping) );
305         if ( mapping == NULL ) {
306                 fprintf( stderr,
307                         "%s: line %d: out of memory\n",
308                         fname, lineno );
309                 return 1;
310         }
311         ber_str2bv( src, 0, 1, &mapping->src );
312         ber_str2bv( dst, 0, 1, &mapping->dst );
313         mapping[1].src = mapping->dst;
314         mapping[1].dst = mapping->src;
315
316         /*
317          * schema check
318          */
319         if ( is_oc ) {
320                 if ( src[0] != '\0' ) {
321                         if ( oc_bvfind( &mapping->src ) == NULL ) {
322                                 fprintf( stderr,
323         "%s: line %d: warning, source objectClass '%s' "
324         "should be defined in schema\n",
325                                         fname, lineno, src );
326
327                                 /*
328                                  * FIXME: this should become an err
329                                  */
330                         }
331                 }
332
333                 if ( oc_bvfind( &mapping->dst ) == NULL ) {
334                         fprintf( stderr,
335         "%s: line %d: warning, destination objectClass '%s' "
336         "is not defined in schema\n",
337                                 fname, lineno, dst );
338                 }
339         } else {
340                 int                     rc;
341                 const char              *text = NULL;
342                 AttributeDescription    *ad = NULL;
343
344                 if ( src[0] != '\0' ) {
345                         rc = slap_bv2ad( &mapping->src, &ad, &text );
346                         if ( rc != LDAP_SUCCESS ) {
347                                 fprintf( stderr,
348         "%s: line %d: warning, source attributeType '%s' "
349         "should be defined in schema\n",
350                                         fname, lineno, src );
351
352                                 /*
353                                  * FIXME: this should become an err
354                                  */
355                         }
356
357                         ad = NULL;
358                 }
359
360                 rc = slap_bv2ad( &mapping->dst, &ad, &text );
361                 if ( rc != LDAP_SUCCESS ) {
362                         fprintf( stderr,
363         "%s: line %d: warning, destination attributeType '%s' "
364         "is not defined in schema\n",
365                                 fname, lineno, dst );
366                 }
367         }
368
369         if ( (src[0] != '\0' && avl_find( map->map, (caddr_t)mapping, mapping_cmp ) != NULL)
370                         || avl_find( map->remap, (caddr_t)&mapping[1], mapping_cmp ) != NULL)
371         {
372                 fprintf( stderr,
373                         "%s: line %d: duplicate mapping found (ignored)\n",
374                         fname, lineno );
375                 /* FIXME: free stuff */
376                 goto error_return;
377         }
378
379         if ( src[0] != '\0' ) {
380                 avl_insert( &map->map, (caddr_t)mapping,
381                                         mapping_cmp, mapping_dup );
382         }
383         avl_insert( &map->remap, (caddr_t)&mapping[1],
384                                 mapping_cmp, mapping_dup );
385
386         return 0;
387
388 error_return:;
389         if ( mapping ) {
390                 ch_free( mapping->src.bv_val );
391                 ch_free( mapping->dst.bv_val );
392                 ch_free( mapping );
393         }
394
395         return 1;
396 }
397
398 static int
399 ldap_back_exop_whoami(
400         Operation *op,
401         SlapReply *rs )
402 {
403         struct berval *bv = NULL;
404
405         if ( op->oq_extended.rs_reqdata != NULL ) {
406                 /* no request data should be provided */
407                 rs->sr_text = "no request data expected";
408                 return rs->sr_err = LDAP_PROTOCOL_ERROR;
409         }
410
411         rs->sr_err = backend_check_restrictions( op, rs, 
412                         (struct berval *)&slap_EXOP_WHOAMI );
413         if( rs->sr_err != LDAP_SUCCESS ) return rs->sr_err;
414
415         /* if auth'd by back-ldap and request is proxied, forward it */
416         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)) {
417                 struct ldapconn *lc;
418
419                 LDAPControl c, *ctrls[2] = {NULL, NULL};
420                 LDAPMessage *res;
421                 Operation op2 = *op;
422                 ber_int_t msgid;
423
424                 ctrls[0] = &c;
425                 op2.o_ndn = op->o_conn->c_ndn;
426                 lc = ldap_back_getconn(&op2, rs);
427                 if (!lc || !ldap_back_dobind( lc, op, rs )) {
428                         return -1;
429                 }
430                 c.ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;
431                 c.ldctl_iscritical = 1;
432                 c.ldctl_value.bv_val = ch_malloc(op->o_ndn.bv_len+4);
433                 c.ldctl_value.bv_len = op->o_ndn.bv_len + 3;
434                 strcpy(c.ldctl_value.bv_val, "dn:");
435                 strcpy(c.ldctl_value.bv_val+3, op->o_ndn.bv_val);
436
437                 rs->sr_err = ldap_whoami(lc->ld, ctrls, NULL, &msgid);
438                 if (rs->sr_err == LDAP_SUCCESS) {
439                         if (ldap_result(lc->ld, msgid, 1, NULL, &res) == -1) {
440                                 ldap_get_option(lc->ld, LDAP_OPT_ERROR_NUMBER,
441                                         &rs->sr_err);
442                         } else {
443                                 rs->sr_err = ldap_parse_whoami(lc->ld, res, &bv);
444                                 ldap_msgfree(res);
445                         }
446                 }
447                 ch_free(c.ldctl_value.bv_val);
448                 if (rs->sr_err != LDAP_SUCCESS) {
449                         rs->sr_err = ldap_back_map_result(rs);
450                 }
451         } else {
452         /* else just do the same as before */
453                 bv = (struct berval *) ch_malloc( sizeof(struct berval) );
454                 if( op->o_dn.bv_len ) {
455                         bv->bv_len = op->o_dn.bv_len + sizeof("dn:")-1;
456                         bv->bv_val = ch_malloc( bv->bv_len + 1 );
457                         AC_MEMCPY( bv->bv_val, "dn:", sizeof("dn:")-1 );
458                         AC_MEMCPY( &bv->bv_val[sizeof("dn:")-1], op->o_dn.bv_val,
459                                 op->o_dn.bv_len );
460                         bv->bv_val[bv->bv_len] = '\0';
461                 } else {
462                         bv->bv_len = 0;
463                         bv->bv_val = NULL;
464                 }
465         }
466
467         rs->sr_rspdata = bv;
468         return rs->sr_err;
469 }
470
471
472 #ifdef ENABLE_REWRITE
473 static char *
474 suffix_massage_regexize( const char *s )
475 {
476         char *res, *ptr;
477         const char *p, *r;
478         int i;
479
480         for ( i = 0, p = s; 
481                         ( r = strchr( p, ',' ) ) != NULL; 
482                         p = r + 1, i++ )
483                 ;
484
485         res = ch_calloc( sizeof( char ), strlen( s ) + 4 + 4*i + 1 );
486
487         ptr = lutil_strcopy( res, "(.*)" );
488         for ( i = 0, p = s;
489                         ( r = strchr( p, ',' ) ) != NULL;
490                         p = r + 1 , i++ ) {
491                 ptr = lutil_strncopy( ptr, p, r - p + 1 );
492                 ptr = lutil_strcopy( ptr, "[ ]?" );
493
494                 if ( r[ 1 ] == ' ' ) {
495                         r++;
496                 }
497         }
498         lutil_strcopy( ptr, p );
499
500         return res;
501 }
502
503 static char *
504 suffix_massage_patternize( const char *s )
505 {
506         ber_len_t       len;
507         char            *res;
508
509         len = strlen( s );
510
511         res = ch_calloc( sizeof( char ), len + sizeof( "%1" ) );
512         if ( res == NULL ) {
513                 return NULL;
514         }
515
516         strcpy( res, "%1" );
517         strcpy( res + sizeof( "%1" ) - 1, s );
518
519         return res;
520 }
521
522 int
523 suffix_massage_config( 
524                 struct rewrite_info *info,
525                 struct berval *pvnc,
526                 struct berval *nvnc,
527                 struct berval *prnc,
528                 struct berval *nrnc
529 )
530 {
531         char *rargv[ 5 ];
532         int line = 0;
533
534         rargv[ 0 ] = "rewriteEngine";
535         rargv[ 1 ] = "on";
536         rargv[ 2 ] = NULL;
537         rewrite_parse( info, "<suffix massage>", ++line, 2, rargv );
538
539         rargv[ 0 ] = "rewriteContext";
540         rargv[ 1 ] = "default";
541         rargv[ 2 ] = NULL;
542         rewrite_parse( info, "<suffix massage>", ++line, 2, rargv );
543
544         rargv[ 0 ] = "rewriteRule";
545         rargv[ 1 ] = suffix_massage_regexize( pvnc->bv_val );
546         rargv[ 2 ] = suffix_massage_patternize( prnc->bv_val );
547         rargv[ 3 ] = ":";
548         rargv[ 4 ] = NULL;
549         rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
550         ch_free( rargv[ 1 ] );
551         ch_free( rargv[ 2 ] );
552         
553         rargv[ 0 ] = "rewriteContext";
554         rargv[ 1 ] = "searchResult";
555         rargv[ 2 ] = NULL;
556         rewrite_parse( info, "<suffix massage>", ++line, 2, rargv );
557         
558         rargv[ 0 ] = "rewriteRule";
559         rargv[ 1 ] = suffix_massage_regexize( prnc->bv_val );
560         rargv[ 2 ] = suffix_massage_patternize( pvnc->bv_val );
561         rargv[ 3 ] = ":";
562         rargv[ 4 ] = NULL;
563         rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
564         ch_free( rargv[ 1 ] );
565         ch_free( rargv[ 2 ] );
566
567 #if 0
568         /*
569          * FIXME: this is no longer required since now we map filters
570          * based on the parsed filter structure, so we can deal directly
571          * with attribute types and values.  The rewriteContext 
572          * "searchFilter" now refers to the value of attrbutes
573          * with DN syntax.
574          */
575
576         /*
577          * the filter should be rewritten as
578          * 
579          * rewriteRule
580          *      "(.*)member=([^)]+),o=Foo Bar,[ ]?c=US(.*)"
581          *      "%1member=%2,dc=example,dc=com%3"
582          *
583          * where "o=Foo Bar, c=US" is the virtual naming context,
584          * and "dc=example, dc=com" is the real naming context
585          */
586         rargv[ 0 ] = "rewriteContext";
587         rargv[ 1 ] = "searchFilter";
588         rargv[ 2 ] = NULL;
589         rewrite_parse( info, "<suffix massage>", ++line, 2, rargv );
590
591 #if 1 /* rewrite filters */
592         {
593                 /*
594                  * Note: this is far more optimistic than desirable:
595                  * for any AVA value ending with the virtual naming
596                  * context the terminal part will be replaced by the
597                  * real naming context; a better solution would be to
598                  * walk the filter looking for DN-valued attributes,
599                  * and only rewrite those that require rewriting
600                  */
601                 char    vbuf_[BUFSIZ], *vbuf = vbuf_,
602                         rbuf_[BUFSIZ], *rbuf = rbuf_;
603                 int     len;
604
605                 len = snprintf( vbuf, sizeof( vbuf_ ), 
606                                 "(.*)%s\\)(.*)", nvnc->bv_val );
607                 if ( len == -1 ) {
608                         /* 
609                          * traditional behavior: snprintf returns -1 
610                          * if buffer is insufficient
611                          */
612                         return -1;
613
614                 } else if ( len >= (int)sizeof( vbuf_ ) ) {
615                         /* 
616                          * C99: snprintf returns the required size 
617                          */
618                         vbuf = ch_malloc( len + 1 );
619                         len = snprintf( vbuf, len,
620                                         "(.*)%s\\)(.*)", nvnc->bv_val );
621                         assert( len > 0 );
622                 }
623
624                 len = snprintf( rbuf, sizeof( rbuf_ ), "%%1%s)%%2", 
625                                 nrnc->bv_val );
626                 if ( len == -1 ) {
627                         return -1;
628
629                 } else if ( len >= (int)sizeof( rbuf_ ) ) {
630                         rbuf = ch_malloc( len + 1 );
631                         len = snprintf( rbuf, sizeof( rbuf_ ), "%%1%s)%%2", 
632                                         nrnc->bv_val );
633                         assert( len > 0 );
634                 }
635                 
636                 rargv[ 0 ] = "rewriteRule";
637                 rargv[ 1 ] = vbuf;
638                 rargv[ 2 ] = rbuf;
639                 rargv[ 3 ] = ":";
640                 rargv[ 4 ] = NULL;
641                 rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
642
643                 if ( vbuf != vbuf_ ) {
644                         ch_free( vbuf );
645                 }
646
647                 if ( rbuf != rbuf_ ) {
648                         ch_free( rbuf );
649                 }
650         }
651 #endif /* rewrite filters */
652 #endif
653
654 #if 0 /*  "matched" is not normalized */
655         rargv[ 0 ] = "rewriteContext";
656         rargv[ 1 ] = "matchedDn";
657         rargv[ 2 ] = "alias";
658         rargv[ 3 ] = "searchResult";
659         rargv[ 4 ] = NULL;
660         rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
661 #else /* normalize "matched" */
662
663         rargv[ 0 ] = "rewriteContext";
664         rargv[ 1 ] = "matchedDN";
665         rargv[ 2 ] = "alias";
666         rargv[ 3 ] = "searchResult";
667         rargv[ 4 ] = NULL;
668         rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
669
670         rargv[ 0 ] = "rewriteContext";
671         rargv[ 1 ] = "searchAttrDN";
672         rargv[ 2 ] = "alias";
673         rargv[ 3 ] = "searchResult";
674         rargv[ 4 ] = NULL;
675         rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
676
677 #if 0
678         rargv[ 0 ] = "rewriteRule";
679         rargv[ 1 ] = suffix_massage_regexize( prnc->bv_val );
680         rargv[ 2 ] = suffix_massage_patternize( nvnc->bv_val );
681         rargv[ 3 ] = ":";
682         rargv[ 4 ] = NULL;
683         rewrite_parse( info, "<suffix massage>", ++line, 4, rargv );
684         ch_free( rargv[ 1 ] );
685         ch_free( rargv[ 2 ] );
686 #endif /* 0 */
687 #endif /* normalize "matched" */
688
689         return 0;
690 }
691 #endif /* ENABLE_REWRITE */