]> git.sur5r.net Git - openldap/blob - servers/slapd/overlays/rwm.c
21430a77e2447b11b91a37fdb9a8fd5599deab76
[openldap] / servers / slapd / overlays / rwm.c
1 /* rwm.c - rewrite/remap operations */
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 2003 Pierangelo Masarati.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted only as authorized by the OpenLDAP
11  * Public License.
12  *
13  * A copy of this license is available in the file LICENSE in the
14  * top-level directory of the distribution or, alternatively, at
15  * <http://www.OpenLDAP.org/license.html>.
16  */
17
18 #include "portable.h"
19
20 #ifdef SLAPD_OVER_RWM
21
22 #include <stdio.h>
23
24 #include "slap.h"
25 #include "rwm.h"
26
27 static int
28 rwm_op_dn_massage( Operation *op, SlapReply *rs, void *cookie )
29 {
30         slap_overinst           *on = (slap_overinst *) op->o_bd->bd_info;
31         struct ldaprwmap        *rwmap = 
32                         (struct ldaprwmap *)on->on_bi.bi_private;
33
34         struct berval           dn, ndn, mdn = { 0, NULL };
35         int                     rc = 0;
36         dncookie                dc;
37
38         /*
39          * Rewrite the bind dn if needed
40          */
41         dc.rwmap = rwmap;
42 #ifdef ENABLE_REWRITE
43         dc.conn = op->o_conn;
44         dc.rs = rs;
45         dc.ctx = (char *)cookie;
46 #else
47         dc.tofrom = ((int *)cookie)[0];
48         dc.normalized = 0;
49 #endif
50
51         rc = rwm_dn_massage( &dc, &op->o_req_dn, &mdn );
52         if ( rc != LDAP_SUCCESS ) {
53                 return rc;
54         }
55
56         if ( mdn.bv_val == op->o_req_dn.bv_val ) {
57                 return LDAP_SUCCESS;
58         }
59
60         rc = dnPrettyNormal( NULL, &mdn, &dn, &ndn, op->o_tmpmemctx );
61         if ( rc != LDAP_SUCCESS ) {
62                 return rc;
63         }
64
65         if ( mdn.bv_val != dn.bv_val ) {
66                 ch_free( mdn.bv_val );
67         }
68
69         op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx );
70         op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx );
71
72         op->o_req_dn = dn;
73         op->o_req_ndn = ndn;
74
75         return LDAP_SUCCESS;
76 }
77
78 static int
79 rwm_bind( Operation *op, SlapReply *rs )
80 {
81         int     rc;
82
83 #ifdef ENABLE_REWRITE
84         rc = rwm_op_dn_massage( op, rs, "bindDn" );
85 #else
86         rc = 1;
87         rc = rwm_op_dn_massage( op, rs, &rc );
88 #endif
89         if ( rc != LDAP_SUCCESS ) {
90                 return rc;
91         }
92
93         return SLAP_CB_CONTINUE;
94 }
95
96 static int
97 rwm_add( Operation *op, SlapReply *rs )
98 {
99         int     rc;
100
101 #ifdef ENABLE_REWRITE
102         rc = rwm_op_dn_massage( op, rs, "addDn" );
103 #else
104         rc = 1;
105         rc = rwm_op_dn_massage( op, rs, &rc );
106 #endif
107         if ( rc != LDAP_SUCCESS ) {
108                 return rc;
109         }
110
111         /* TODO: rewrite attribute types, values of DN-valued attributes ... */
112         return SLAP_CB_CONTINUE;
113 }
114
115 static int
116 rwm_delete( Operation *op, SlapReply *rs )
117 {
118         int     rc;
119
120 #ifdef ENABLE_REWRITE
121         rc = rwm_op_dn_massage( op, rs, "deleteDn" );
122 #else
123         rc = 1;
124         rc = rwm_op_dn_massage( op, rs, &rc );
125 #endif
126         if ( rc != LDAP_SUCCESS ) {
127                 return rc;
128         }
129
130         return SLAP_CB_CONTINUE;
131 }
132
133 static int
134 rwm_modrdn( Operation *op, SlapReply *rs )
135 {
136         int     rc;
137
138 #ifdef ENABLE_REWRITE
139         rc = rwm_op_dn_massage( op, rs, "renameDn" );
140 #else
141         rc = 1;
142         rc = rwm_op_dn_massage( op, rs, &rc );
143 #endif
144         if ( rc != LDAP_SUCCESS ) {
145                 return rc;
146         }
147
148         /* TODO: rewrite attribute types, values of DN-valued attributes ... */
149         return SLAP_CB_CONTINUE;
150 }
151
152 static int
153 rwm_modify( Operation *op, SlapReply *rs )
154 {
155         int     rc;
156
157 #ifdef ENABLE_REWRITE
158         rc = rwm_op_dn_massage( op, rs, "modifyDn" );
159 #else
160         rc = 1;
161         rc = rwm_op_dn_massage( op, rs, &rc );
162 #endif
163         if ( rc != LDAP_SUCCESS ) {
164                 return rc;
165         }
166
167         /* TODO: rewrite attribute types, values of DN-valued attributes ... */
168         return SLAP_CB_CONTINUE;
169 }
170
171 static int
172 rwm_compare( Operation *op, SlapReply *rs )
173 {
174         int     rc;
175
176 #ifdef ENABLE_REWRITE
177         rc = rwm_op_dn_massage( op, rs, "compareDn" );
178 #else
179         rc = 1;
180         rc = rwm_op_dn_massage( op, rs, &rc );
181 #endif
182         if ( rc != LDAP_SUCCESS ) {
183                 return rc;
184         }
185
186         /* TODO: rewrite attribute types, values of DN-valued attributes ... */
187         return SLAP_CB_CONTINUE;
188 }
189
190 static int
191 rwm_search( Operation *op, SlapReply *rs )
192 {
193         int     rc;
194
195 #ifdef ENABLE_REWRITE
196         rc = rwm_op_dn_massage( op, rs, "searchDn" );
197 #else
198         rc = 1;
199         rc = rwm_op_dn_massage( op, rs, &rc );
200 #endif
201         if ( rc != LDAP_SUCCESS ) {
202                 return rc;
203         }
204
205         /* TODO: rewrite/map filter & attrs */
206         return SLAP_CB_CONTINUE;
207 }
208
209 static int
210 rwm_extended( Operation *op, SlapReply *rs )
211 {
212         int     rc;
213
214 #ifdef ENABLE_REWRITE
215         rc = rwm_op_dn_massage( op, rs, "extendedDn" );
216 #else
217         rc = 1;
218         rc = rwm_op_dn_massage( op, rs, &rc );
219 #endif
220         if ( rc != LDAP_SUCCESS ) {
221                 return rc;
222         }
223
224         /* TODO: rewrite/map extended data ? ... */
225         return 0;
226 }
227
228 static int
229 rwm_matched( Operation *op, SlapReply *rs )
230 {
231         slap_overinst           *on = (slap_overinst *) op->o_bd->bd_info;
232         struct ldaprwmap        *rwmap = 
233                         (struct ldaprwmap *)on->on_bi.bi_private;
234
235         struct berval           dn, mdn;
236         dncookie                dc;
237
238         if ( rs->sr_matched == NULL ) {
239                 return SLAP_CB_CONTINUE;
240         }
241
242         dc.rwmap = rwmap;
243 #ifdef ENABLE_REWRITE
244         dc.conn = op->o_conn;
245         dc.rs = rs;
246         dc.ctx = "matchedDn";
247 #else
248         dc.tofrom = 0;
249         dc.normalized = 0;
250 #endif
251         ber_str2bv( rs->sr_matched, 0, 0, &dn );
252         rwm_dn_massage( &dc, &dn, &mdn );
253
254         if ( mdn.bv_val != dn.bv_val ) {
255                 if ( rs->sr_flags & REP_MATCHED_MUSTBEFREED ) {
256                         ch_free( (void *)rs->sr_matched );
257                 } else {
258                         rs->sr_flags |= REP_MATCHED_MUSTBEFREED;
259                 }
260                 rs->sr_matched = mdn.bv_val;
261         }
262         
263         return SLAP_CB_CONTINUE;
264 }
265
266 static int
267 rwm_send_entry( Operation *op, SlapReply *rs )
268 {
269         slap_overinst           *on = (slap_overinst *) op->o_bd->bd_info;
270         struct ldaprwmap        *rwmap = 
271                         (struct ldaprwmap *)on->on_bi.bi_private;
272
273         Entry           *e = NULL;
274         struct berval   dn = { 0, NULL }, ndn = { 0, NULL };
275         dncookie        dc;
276         int             rc = SLAP_CB_CONTINUE;
277
278         assert( rs->sr_entry );
279
280         e = rs->sr_entry;
281
282         /*
283          * Rewrite the dn of the result, if needed
284          */
285         dc.rwmap = rwmap;
286 #ifdef ENABLE_REWRITE
287         dc.conn = op->o_conn;
288         dc.rs = NULL; 
289         dc.ctx = "searchResultDN";
290 #else
291         dc.tofrom = 0;
292         dc.normalized = 0;
293 #endif
294         if ( rwm_dn_massage( &dc, &e->e_name, &dn ) ) {
295                 return LDAP_OTHER;
296         }
297
298         if ( e->e_name.bv_val == dn.bv_val ) {
299                 return SLAP_CB_CONTINUE;
300         }
301
302         /*
303          * Note: this may fail if the target host(s) schema differs
304          * from the one known to the meta, and a DN with unknown
305          * attributes is returned.
306          */
307         if ( dnNormalize( 0, NULL, NULL, &dn, &ndn, NULL ) != LDAP_SUCCESS ) {
308                 if ( dn.bv_val != e->e_name.bv_val ) {
309                         ch_free( dn.bv_val );
310                 }
311                 rc = LDAP_INVALID_DN_SYNTAX;
312                 goto fail;
313         }
314
315         if ( !( rs->sr_flags & REP_ENTRY_MODIFIABLE ) ) {
316                 e = entry_dup( e );
317                 if ( e == NULL ) {
318                         goto fail;
319                 }
320                 rs->sr_flags |= ( REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED );
321         }
322
323         free( e->e_name.bv_val );
324         free( e->e_nname.bv_val );
325
326         e->e_name = dn;
327         e->e_nname = ndn;
328
329         rs->sr_entry = e;
330
331         /* TODO: map entry attribute types, objectclasses 
332          * and dn-valued attribute values */
333         
334         return SLAP_CB_CONTINUE;
335
336 fail:;
337         if ( dn.bv_val && ( dn.bv_val != e->e_name.bv_val ) ) {
338                 ch_free( dn.bv_val );
339         }
340
341         if ( ndn.bv_val ) {
342                 ch_free( ndn.bv_val );
343         }
344
345         return rc;
346 }
347
348 static int
349 rwm_rw_config(
350     BackendDB   *be,
351     const char  *fname,
352     int         lineno,
353     int         argc,
354     char        **argv
355 )
356 {
357 #ifdef ENABLE_REWRITE
358         slap_overinst           *on = (slap_overinst *) be->bd_info;
359         struct ldaprwmap        *rwmap = 
360                         (struct ldaprwmap *)on->on_bi.bi_private;
361
362         return rewrite_parse( rwmap->rwm_rw,
363                                 fname, lineno, argc, argv );
364
365 #else /* !ENABLE_REWRITE */
366         fprintf( stderr, "%s: line %d: rewrite capabilities "
367                         "are not enabled\n", fname, lineno );
368 #endif /* !ENABLE_REWRITE */
369                 
370         return 0;
371 }
372
373 static int
374 rwm_suffixmassage_config(
375     BackendDB   *be,
376     const char  *fname,
377     int         lineno,
378     int         argc,
379     char        **argv
380 )
381 {
382         slap_overinst           *on = (slap_overinst *) be->bd_info;
383         struct ldaprwmap        *rwmap = 
384                         (struct ldaprwmap *)on->on_bi.bi_private;
385
386         struct berval   bvnc, nvnc, pvnc, brnc, nrnc, prnc;
387 #ifdef ENABLE_REWRITE
388         int             rc;
389 #endif /* ENABLE_REWRITE */
390                 
391         /*
392          * syntax:
393          * 
394          *      suffixmassage <suffix> <massaged suffix>
395          *
396          * the <suffix> field must be defined as a valid suffix
397          * (or suffixAlias?) for the current database;
398          * the <massaged suffix> shouldn't have already been
399          * defined as a valid suffix or suffixAlias for the 
400          * current server
401          */
402         if ( argc != 3 ) {
403                 fprintf( stderr, "%s: line %d: syntax is"
404                                " \"suffixMassage <suffix>"
405                                " <massaged suffix>\"\n",
406                         fname, lineno );
407                 return 1;
408         }
409                 
410         ber_str2bv( argv[1], 0, 0, &bvnc );
411         if ( dnPrettyNormal( NULL, &bvnc, &pvnc, &nvnc, NULL ) != LDAP_SUCCESS ) {
412                 fprintf( stderr, "%s: line %d: suffix DN %s is invalid\n",
413                         fname, lineno, bvnc.bv_val );
414                 return 1;
415         }
416
417         ber_str2bv( argv[2], 0, 0, &brnc );
418         if ( dnPrettyNormal( NULL, &brnc, &prnc, &nrnc, NULL ) != LDAP_SUCCESS ) {
419                 fprintf( stderr, "%s: line %d: suffix DN %s is invalid\n",
420                                 fname, lineno, brnc.bv_val );
421                 free( nvnc.bv_val );
422                 free( pvnc.bv_val );
423                 return 1;
424         }
425
426 #ifdef ENABLE_REWRITE
427         /*
428          * The suffix massaging is emulated 
429          * by means of the rewrite capabilities
430          */
431         rc = rwm_suffix_massage_config( rwmap->rwm_rw,
432                         &pvnc, &nvnc, &prnc, &nrnc );
433         free( nvnc.bv_val );
434         free( pvnc.bv_val );
435         free( nrnc.bv_val );
436         free( prnc.bv_val );
437
438         return( rc );
439
440 #else /* !ENABLE_REWRITE */
441         ber_bvarray_add( &rwmap->rwm_suffix_massage, &pvnc );
442         ber_bvarray_add( &rwmap->rwm_suffix_massage, &nvnc );
443                 
444         ber_bvarray_add( &rwmap->rwm_suffix_massage, &prnc );
445         ber_bvarray_add( &rwmap->rwm_suffix_massage, &nrnc );
446 #endif /* !ENABLE_REWRITE */
447
448         return 0;
449 }
450
451 static int
452 rwm_m_config(
453     BackendDB   *be,
454     const char  *fname,
455     int         lineno,
456     int         argc,
457     char        **argv
458 )
459 {
460         slap_overinst           *on = (slap_overinst *) be->bd_info;
461         struct ldaprwmap        *rwmap = 
462                         (struct ldaprwmap *)on->on_bi.bi_private;
463
464         /* objectclass/attribute mapping */
465         return rwm_map_config( &rwmap->rwm_oc,
466                         &rwmap->rwm_at,
467                         fname, lineno, argc, argv );
468 }
469
470 static int
471 rwm_response( Operation *op, SlapReply *rs )
472 {
473         int     rc;
474
475         if ( op->o_tag == LDAP_REQ_SEARCH && rs->sr_type == REP_SEARCH ) {
476                 return rwm_send_entry( op, rs );
477         }
478
479         switch( op->o_tag ) {
480         case LDAP_REQ_BIND:
481         case LDAP_REQ_ADD:
482         case LDAP_REQ_DELETE:
483         case LDAP_REQ_MODRDN:
484         case LDAP_REQ_MODIFY:
485         case LDAP_REQ_COMPARE:
486         case LDAP_REQ_SEARCH:
487         case LDAP_REQ_EXTENDED:
488                 rc = rwm_matched( op, rs );
489                 break;
490         default:
491                 rc = SLAP_CB_CONTINUE;
492                 break;
493         }
494
495         return rc;
496 }
497
498 static int
499 rwm_config(
500     BackendDB   *be,
501     const char  *fname,
502     int         lineno,
503     int         argc,
504     char        **argv
505 )
506 {
507         int             rc = 0;
508
509         if ( strncasecmp( argv[0], "rewrite", sizeof("rewrite") - 1) == 0 ) {
510                 rc = rwm_rw_config( be, fname, lineno, argc, argv );
511
512         } else if (strcasecmp( argv[0], "map" ) == 0 ) {
513                 rc = rwm_m_config( be, fname, lineno, argc, argv );
514
515         } else if (strcasecmp( argv[0], "suffixmassage" ) == 0 ) {
516                 rc = rwm_suffixmassage_config( be, fname, lineno, argc, argv );
517
518         } else {
519                 rc = SLAP_CONF_UNKNOWN;
520         }
521
522         return rc;
523 }
524
525 static int
526 rwm_over_init(
527         BackendDB *be
528 )
529 {
530         slap_overinst           *on = (slap_overinst *) be->bd_info;
531         struct ldapmapping      *mapping = NULL;
532         struct ldaprwmap        *rwmap;
533
534         rwmap = (struct ldaprwmap *)ch_malloc(sizeof(struct ldaprwmap));
535         memset(rwmap, 0, sizeof(struct ldaprwmap));
536
537 #ifdef ENABLE_REWRITE
538         rwmap->rwm_rw = rewrite_info_init( REWRITE_MODE_USE_DEFAULT );
539         if ( rwmap->rwm_rw == NULL ) {
540                 ch_free( rwmap );
541                 return -1;
542         }
543 #endif /* ENABLE_REWRITE */
544
545         rwm_map_init( &rwmap->rwm_oc, &mapping );
546         rwm_map_init( &rwmap->rwm_at, &mapping );
547
548         on->on_bi.bi_private = (void *)rwmap;
549
550         return 0;
551 }
552
553 static int
554 rwm_destroy(
555         BackendDB *be
556 )
557 {
558         slap_overinst   *on = (slap_overinst *) be->bd_info;
559         int             rc = 0;
560
561         if ( on->on_bi.bi_private ) {
562                 struct ldaprwmap        *rwmap = 
563                         (struct ldaprwmap *)on->on_bi.bi_private;
564
565 #ifdef ENABLE_REWRITE
566                 if (rwmap->rwm_rw) {
567                         rewrite_info_delete( &rwmap->rwm_rw );
568                 }
569 #else /* !ENABLE_REWRITE */
570                 if ( rwmap->rwm_suffix_massage ) {
571                         ber_bvarray_free( rwmap->rwm_suffix_massage );
572                 }
573 #endif /* !ENABLE_REWRITE */
574
575                 avl_free( rwmap->rwm_oc.remap, NULL );
576                 avl_free( rwmap->rwm_oc.map, rwm_mapping_free );
577                 avl_free( rwmap->rwm_at.remap, NULL );
578                 avl_free( rwmap->rwm_at.map, rwm_mapping_free );
579         }
580
581         return rc;
582 }
583
584 static slap_overinst rwm = { { NULL } };
585
586 int
587 rwm_init(void)
588 {
589         memset( &rwm, 0, sizeof(slap_overinst) );
590
591         rwm.on_bi.bi_type = "rewrite-remap";
592         rwm.on_bi.bi_db_init = rwm_over_init;
593         rwm.on_bi.bi_db_config = rwm_config;
594         rwm.on_bi.bi_db_destroy = rwm_destroy;
595
596         rwm.on_bi.bi_op_bind = rwm_bind;
597         rwm.on_bi.bi_op_search = rwm_search;
598         rwm.on_bi.bi_op_compare = rwm_compare;
599         rwm.on_bi.bi_op_modify = rwm_modify;
600         rwm.on_bi.bi_op_modrdn = rwm_modrdn;
601         rwm.on_bi.bi_op_add = rwm_add;
602         rwm.on_bi.bi_op_delete = rwm_delete;
603         rwm.on_bi.bi_extended = rwm_extended;
604
605         rwm.on_response = rwm_response;
606
607         return overlay_register( &rwm );
608 }
609
610 #if SLAPD_OVER_RWM == SLAPD_MOD_DYNAMIC
611 int init_module(int argc, char *argv[]) {
612         return rwm_init();
613 }
614 #endif
615
616 #endif /* SLAPD_OVER_RWM */