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