1 /* rwm.c - rewrite/remap operations */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 2003-2015 The OpenLDAP Foundation.
6 * Portions Copyright 2003 Pierangelo Masarati.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted only as authorized by the OpenLDAP
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>.
24 #include <ac/string.h>
31 typedef struct rwm_op_state {
39 AttributeName *mapped_attrs;
43 typedef struct rwm_op_cb {
49 rwm_db_destroy( BackendDB *be, ConfigReply *cr );
52 rwm_send_entry( Operation *op, SlapReply *rs );
55 rwm_op_rollback( Operation *op, SlapReply *rs, rwm_op_state *ros )
57 /* in case of successful extended operation cleanup
58 * gets called *after* (ITS#6632); this hack counts
59 * on others to cleanup our o_req_dn/o_req_ndn,
60 * while we cleanup theirs. */
61 if ( ros->r_tag == LDAP_REQ_EXTENDED && rs->sr_err == LDAP_SUCCESS ) {
62 if ( !BER_BVISNULL( &ros->rx_dn ) ) {
63 ch_free( ros->rx_dn.bv_val );
65 if ( !BER_BVISNULL( &ros->rx_ndn ) ) {
66 ch_free( ros->rx_ndn.bv_val );
70 if ( !BER_BVISNULL( &ros->ro_dn ) ) {
71 op->o_req_dn = ros->ro_dn;
73 if ( !BER_BVISNULL( &ros->ro_ndn ) ) {
74 op->o_req_ndn = ros->ro_ndn;
77 if ( !BER_BVISNULL( &ros->r_dn )
78 && ros->r_dn.bv_val != ros->ro_dn.bv_val )
80 assert( ros->r_dn.bv_val != ros->r_ndn.bv_val );
81 ch_free( ros->r_dn.bv_val );
84 if ( !BER_BVISNULL( &ros->r_ndn )
85 && ros->r_ndn.bv_val != ros->ro_ndn.bv_val )
87 ch_free( ros->r_ndn.bv_val );
91 BER_BVZERO( &ros->r_dn );
92 BER_BVZERO( &ros->r_ndn );
93 BER_BVZERO( &ros->ro_dn );
94 BER_BVZERO( &ros->ro_ndn );
95 BER_BVZERO( &ros->rx_dn );
96 BER_BVZERO( &ros->rx_ndn );
98 switch( ros->r_tag ) {
99 case LDAP_REQ_COMPARE:
100 if ( op->orc_ava->aa_value.bv_val != ros->orc_ava->aa_value.bv_val )
101 op->o_tmpfree( op->orc_ava->aa_value.bv_val, op->o_tmpmemctx );
102 op->orc_ava = ros->orc_ava;
104 case LDAP_REQ_MODIFY:
105 slap_mods_free( op->orm_modlist, 1 );
106 op->orm_modlist = ros->orm_modlist;
108 case LDAP_REQ_MODRDN:
109 if ( op->orr_newSup != ros->orr_newSup ) {
110 if ( op->orr_newSup ) {
111 ch_free( op->orr_newSup->bv_val );
112 ch_free( op->orr_nnewSup->bv_val );
113 op->o_tmpfree( op->orr_newSup, op->o_tmpmemctx );
114 op->o_tmpfree( op->orr_nnewSup, op->o_tmpmemctx );
116 op->orr_newSup = ros->orr_newSup;
117 op->orr_nnewSup = ros->orr_nnewSup;
119 if ( op->orr_newrdn.bv_val != ros->orr_newrdn.bv_val ) {
120 ch_free( op->orr_newrdn.bv_val );
121 ch_free( op->orr_nnewrdn.bv_val );
122 op->orr_newrdn = ros->orr_newrdn;
123 op->orr_nnewrdn = ros->orr_nnewrdn;
126 case LDAP_REQ_SEARCH:
127 op->o_tmpfree( ros->mapped_attrs, op->o_tmpmemctx );
128 filter_free_x( op, op->ors_filter, 1 );
129 op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx );
130 op->ors_attrs = ros->ors_attrs;
131 op->ors_filter = ros->ors_filter;
132 op->ors_filterstr = ros->ors_filterstr;
134 case LDAP_REQ_EXTENDED:
135 if ( op->ore_reqdata != ros->ore_reqdata ) {
136 ber_bvfree( op->ore_reqdata );
137 op->ore_reqdata = ros->ore_reqdata;
141 if ( rs->sr_err == LDAP_SUCCESS ) {
143 ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
144 /* too late, c_mutex released */
145 Debug( LDAP_DEBUG_ANY, "*** DN: \"%s\" => \"%s\"\n",
146 op->o_conn->c_ndn.bv_val,
147 op->o_req_ndn.bv_val );
148 ber_bvreplace( &op->o_conn->c_ndn,
150 ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
159 rwm_op_cleanup( Operation *op, SlapReply *rs )
161 slap_callback *cb = op->o_callback;
162 rwm_op_state *ros = cb->sc_private;
164 if ( rs->sr_type == REP_RESULT || rs->sr_type == REP_EXTENDED ||
165 op->o_abandon || rs->sr_err == SLAPD_ABANDON )
167 rwm_op_rollback( op, rs, ros );
169 op->o_callback = op->o_callback->sc_next;
170 op->o_tmpfree( cb, op->o_tmpmemctx );
173 return SLAP_CB_CONTINUE;
177 rwm_callback_get( Operation *op )
181 roc = op->o_tmpcalloc( 1, sizeof( struct rwm_op_cb ), op->o_tmpmemctx );
182 roc->cb.sc_cleanup = rwm_op_cleanup;
183 roc->cb.sc_response = NULL;
184 roc->cb.sc_next = op->o_callback;
185 roc->cb.sc_private = &roc->ros;
186 roc->ros.r_tag = op->o_tag;
187 roc->ros.ro_dn = op->o_req_dn;
188 roc->ros.ro_ndn = op->o_req_ndn;
189 BER_BVZERO( &roc->ros.r_dn );
190 BER_BVZERO( &roc->ros.r_ndn );
191 BER_BVZERO( &roc->ros.rx_dn );
192 BER_BVZERO( &roc->ros.rx_ndn );
193 roc->ros.mapped_attrs = NULL;
194 roc->ros.o_request = op->o_request;
201 rwm_op_dn_massage( Operation *op, SlapReply *rs, void *cookie,
204 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
205 struct ldaprwmap *rwmap =
206 (struct ldaprwmap *)on->on_bi.bi_private;
208 struct berval dn = BER_BVNULL,
214 * Rewrite the dn if needed
217 dc.conn = op->o_conn;
219 dc.ctx = (char *)cookie;
221 /* NOTE: in those cases where only the ndn is available,
222 * and the caller sets op->o_req_dn = op->o_req_ndn,
223 * only rewrite the op->o_req_ndn and use it as
224 * op->o_req_dn as well */
226 if ( op->o_req_dn.bv_val != op->o_req_ndn.bv_val ) {
228 rc = rwm_dn_massage_pretty_normalize( &dc, &op->o_req_dn, &dn, &ndn );
230 rc = rwm_dn_massage_normalize( &dc, &op->o_req_ndn, &ndn );
233 if ( rc != LDAP_SUCCESS ) {
237 if ( ( op->o_req_dn.bv_val != op->o_req_ndn.bv_val && dn.bv_val == op->o_req_dn.bv_val )
238 || ndn.bv_val == op->o_req_ndn.bv_val )
243 if ( op->o_req_dn.bv_val != op->o_req_ndn.bv_val ) {
245 assert( BER_BVISNULL( &ros->r_dn ) );
251 assert( BER_BVISNULL( &ros->r_ndn ) );
254 if ( ros->r_tag == LDAP_REQ_EXTENDED ) {
255 ros->rx_dn = ros->r_dn;
256 ros->rx_ndn = ros->r_ndn;
263 rwm_op_add( Operation *op, SlapReply *rs )
265 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
266 struct ldaprwmap *rwmap =
267 (struct ldaprwmap *)on->on_bi.bi_private;
271 Attribute **ap = NULL;
272 char *olddn = op->o_req_dn.bv_val;
275 rwm_op_cb *roc = rwm_callback_get( op );
277 rc = rwm_op_dn_massage( op, rs, "addDN", &roc->ros );
278 if ( rc != LDAP_SUCCESS ) {
279 op->o_bd->bd_info = (BackendInfo *)on->on_info;
280 send_ldap_error( op, rs, rc, "addDN massage error" );
284 if ( olddn != op->o_req_dn.bv_val ) {
285 ber_bvreplace( &op->ora_e->e_name, &op->o_req_dn );
286 ber_bvreplace( &op->ora_e->e_nname, &op->o_req_ndn );
289 /* Count number of attributes in entry */
290 isupdate = be_shadow_update( op );
291 for ( i = 0, ap = &op->oq_add.rs_e->e_attrs; *ap; ) {
294 if ( (*ap)->a_desc == slap_schema.si_ad_objectClass ||
295 (*ap)->a_desc == slap_schema.si_ad_structuralObjectClass )
299 last = (*ap)->a_numvals - 1;
300 for ( j = 0; !BER_BVISNULL( &(*ap)->a_vals[ j ] ); j++ ) {
301 struct ldapmapping *mapping = NULL;
303 ( void )rwm_mapping( &rwmap->rwm_oc, &(*ap)->a_vals[ j ],
305 if ( mapping == NULL ) {
306 if ( rwmap->rwm_at.drop_missing ) {
307 /* FIXME: we allow to remove objectClasses as well;
308 * if the resulting entry is inconsistent, that's
309 * the relayed database's business...
311 ch_free( (*ap)->a_vals[ j ].bv_val );
313 (*ap)->a_vals[ j ] = (*ap)->a_vals[ last ];
315 BER_BVZERO( &(*ap)->a_vals[ last ] );
322 ch_free( (*ap)->a_vals[ j ].bv_val );
323 ber_dupbv( &(*ap)->a_vals[ j ], &mapping->m_dst );
327 } else if ( !isupdate && !get_relax( op ) && (*ap)->a_desc->ad_type->sat_no_user_mod )
332 struct ldapmapping *mapping = NULL;
334 ( void )rwm_mapping( &rwmap->rwm_at, &(*ap)->a_desc->ad_cname,
336 if ( mapping == NULL ) {
337 if ( rwmap->rwm_at.drop_missing ) {
342 if ( (*ap)->a_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
343 || ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
346 * FIXME: rewrite could fail; in this case
347 * the operation should give up, right?
349 rc = rwm_dnattr_rewrite( op, rs, "addAttrDN",
351 (*ap)->a_nvals ? &(*ap)->a_nvals : NULL );
356 } else if ( (*ap)->a_desc == slap_schema.si_ad_ref ) {
357 rc = rwm_referral_rewrite( op, rs, "referralAttrDN",
359 (*ap)->a_nvals ? &(*ap)->a_nvals : NULL );
360 if ( rc != LDAP_SUCCESS ) {
365 if ( mapping != NULL ) {
366 assert( mapping->m_dst_ad != NULL );
367 (*ap)->a_desc = mapping->m_dst_ad;
376 /* FIXME: leaking attribute/values? */
383 op->o_callback = &roc->cb;
385 return SLAP_CB_CONTINUE;
389 rwm_conn_init( BackendDB *be, Connection *conn )
391 slap_overinst *on = (slap_overinst *) be->bd_info;
392 struct ldaprwmap *rwmap =
393 (struct ldaprwmap *)on->on_bi.bi_private;
395 ( void )rewrite_session_init( rwmap->rwm_rw, conn );
397 return SLAP_CB_CONTINUE;
401 rwm_conn_destroy( BackendDB *be, Connection *conn )
403 slap_overinst *on = (slap_overinst *) be->bd_info;
404 struct ldaprwmap *rwmap =
405 (struct ldaprwmap *)on->on_bi.bi_private;
407 ( void )rewrite_session_delete( rwmap->rwm_rw, conn );
409 return SLAP_CB_CONTINUE;
413 rwm_op_bind( Operation *op, SlapReply *rs )
415 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
418 rwm_op_cb *roc = rwm_callback_get( op );
420 rc = rwm_op_dn_massage( op, rs, "bindDN", &roc->ros );
421 if ( rc != LDAP_SUCCESS ) {
422 op->o_bd->bd_info = (BackendInfo *)on->on_info;
423 send_ldap_error( op, rs, rc, "bindDN massage error" );
427 overlay_callback_after_backover( op, &roc->cb, 1 );
429 return SLAP_CB_CONTINUE;
433 rwm_op_unbind( Operation *op, SlapReply *rs )
435 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
436 struct ldaprwmap *rwmap =
437 (struct ldaprwmap *)on->on_bi.bi_private;
439 rewrite_session_delete( rwmap->rwm_rw, op->o_conn );
441 return SLAP_CB_CONTINUE;
445 rwm_op_compare( Operation *op, SlapReply *rs )
447 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
448 struct ldaprwmap *rwmap =
449 (struct ldaprwmap *)on->on_bi.bi_private;
452 struct berval mapped_vals[2] = { BER_BVNULL, BER_BVNULL };
454 rwm_op_cb *roc = rwm_callback_get( op );
456 rc = rwm_op_dn_massage( op, rs, "compareDN", &roc->ros );
457 if ( rc != LDAP_SUCCESS ) {
458 op->o_bd->bd_info = (BackendInfo *)on->on_info;
459 send_ldap_error( op, rs, rc, "compareDN massage error" );
463 /* if the attribute is an objectClass, try to remap its value */
464 if ( op->orc_ava->aa_desc == slap_schema.si_ad_objectClass
465 || op->orc_ava->aa_desc == slap_schema.si_ad_structuralObjectClass )
467 rwm_map( &rwmap->rwm_oc, &op->orc_ava->aa_value,
468 &mapped_vals[0], RWM_MAP );
469 if ( BER_BVISNULL( &mapped_vals[0] ) || BER_BVISEMPTY( &mapped_vals[0] ) )
471 op->o_bd->bd_info = (BackendInfo *)on->on_info;
472 send_ldap_error( op, rs, LDAP_OTHER, "compare objectClass map error" );
475 } else if ( mapped_vals[0].bv_val != op->orc_ava->aa_value.bv_val ) {
476 ber_dupbv_x( &op->orc_ava->aa_value, &mapped_vals[0],
481 struct ldapmapping *mapping = NULL;
482 AttributeDescription *ad = op->orc_ava->aa_desc;
484 ( void )rwm_mapping( &rwmap->rwm_at, &op->orc_ava->aa_desc->ad_cname,
486 if ( mapping == NULL ) {
487 if ( rwmap->rwm_at.drop_missing ) {
488 op->o_bd->bd_info = (BackendInfo *)on->on_info;
489 send_ldap_error( op, rs, LDAP_OTHER, "compare attributeType map error" );
494 assert( mapping->m_dst_ad != NULL );
495 ad = mapping->m_dst_ad;
498 if ( op->orc_ava->aa_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
499 || ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
501 struct berval *mapped_valsp[2];
503 mapped_valsp[0] = &mapped_vals[0];
504 mapped_valsp[1] = &mapped_vals[1];
506 mapped_vals[0] = op->orc_ava->aa_value;
508 rc = rwm_dnattr_rewrite( op, rs, "compareAttrDN", NULL, mapped_valsp );
510 if ( rc != LDAP_SUCCESS ) {
511 op->o_bd->bd_info = (BackendInfo *)on->on_info;
512 send_ldap_error( op, rs, rc, "compareAttrDN massage error" );
516 if ( mapped_vals[ 0 ].bv_val != op->orc_ava->aa_value.bv_val ) {
517 /* NOTE: if we get here, rwm_dnattr_rewrite()
518 * already freed the old value, so now
520 ber_dupbv_x( &op->orc_ava->aa_value, &mapped_vals[0],
522 ber_memfree_x( mapped_vals[ 0 ].bv_val, NULL );
525 op->orc_ava->aa_desc = ad;
528 op->o_callback = &roc->cb;
530 return SLAP_CB_CONTINUE;
534 rwm_op_delete( Operation *op, SlapReply *rs )
536 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
539 rwm_op_cb *roc = rwm_callback_get( op );
541 rc = rwm_op_dn_massage( op, rs, "deleteDN", &roc->ros );
542 if ( rc != LDAP_SUCCESS ) {
543 op->o_bd->bd_info = (BackendInfo *)on->on_info;
544 send_ldap_error( op, rs, rc, "deleteDN massage error" );
548 op->o_callback = &roc->cb;
550 return SLAP_CB_CONTINUE;
554 rwm_op_modify( Operation *op, SlapReply *rs )
556 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
557 struct ldaprwmap *rwmap =
558 (struct ldaprwmap *)on->on_bi.bi_private;
564 rwm_op_cb *roc = rwm_callback_get( op );
566 rc = rwm_op_dn_massage( op, rs, "modifyDN", &roc->ros );
567 if ( rc != LDAP_SUCCESS ) {
568 op->o_bd->bd_info = (BackendInfo *)on->on_info;
569 send_ldap_error( op, rs, rc, "modifyDN massage error" );
573 isupdate = be_shadow_update( op );
574 for ( mlp = &op->orm_modlist; *mlp; ) {
576 Modifications *ml = *mlp;
577 struct ldapmapping *mapping = NULL;
579 /* ml points to a temporary mod until needs duplication */
580 if ( ml->sml_desc == slap_schema.si_ad_objectClass
581 || ml->sml_desc == slap_schema.si_ad_structuralObjectClass )
585 } else if ( !isupdate && !get_relax( op ) && ml->sml_desc->ad_type->sat_no_user_mod )
587 ml = ch_malloc( sizeof( Modifications ) );
589 if ( (*mlp)->sml_values ) {
590 ber_bvarray_dup_x( &ml->sml_values, (*mlp)->sml_values, NULL );
591 if ( (*mlp)->sml_nvalues ) {
592 ber_bvarray_dup_x( &ml->sml_nvalues, (*mlp)->sml_nvalues, NULL );
601 drop_missing = rwm_mapping( &rwmap->rwm_at,
602 &ml->sml_desc->ad_cname,
604 if ( drop_missing || ( mapping != NULL && BER_BVISNULL( &mapping->m_dst ) ) )
610 /* duplicate the modlist */
611 ml = ch_malloc( sizeof( Modifications ));
615 if ( ml->sml_values != NULL ) {
619 for ( num = 0; !BER_BVISNULL( &ml->sml_values[ num ] ); num++ )
622 bva = ch_malloc( (num+1) * sizeof( struct berval ));
623 for (i=0; i<num; i++)
624 ber_dupbv( &bva[i], &ml->sml_values[i] );
625 BER_BVZERO( &bva[i] );
626 ml->sml_values = bva;
628 if ( ml->sml_nvalues ) {
629 bva = ch_malloc( (num+1) * sizeof( struct berval ));
630 for (i=0; i<num; i++)
631 ber_dupbv( &bva[i], &ml->sml_nvalues[i] );
632 BER_BVZERO( &bva[i] );
633 ml->sml_nvalues = bva;
641 for ( j = 0; !BER_BVISNULL( &ml->sml_values[ j ] ); j++ ) {
642 struct ldapmapping *oc_mapping = NULL;
644 ( void )rwm_mapping( &rwmap->rwm_oc, &ml->sml_values[ j ],
645 &oc_mapping, RWM_MAP );
646 if ( oc_mapping == NULL ) {
647 if ( rwmap->rwm_at.drop_missing ) {
648 /* FIXME: we allow to remove objectClasses as well;
649 * if the resulting entry is inconsistent, that's
650 * the relayed database's business...
653 ch_free( ml->sml_values[ j ].bv_val );
654 ml->sml_values[ j ] = ml->sml_values[ last ];
656 BER_BVZERO( &ml->sml_values[ last ] );
662 ch_free( ml->sml_values[ j ].bv_val );
663 ber_dupbv( &ml->sml_values[ j ], &oc_mapping->m_dst );
668 if ( ml->sml_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
669 || ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
671 rc = rwm_dnattr_rewrite( op, rs, "modifyAttrDN",
673 ml->sml_nvalues ? &ml->sml_nvalues : NULL );
675 } else if ( ml->sml_desc == slap_schema.si_ad_ref ) {
676 rc = rwm_referral_rewrite( op, rs,
679 ml->sml_nvalues ? &ml->sml_nvalues : NULL );
680 if ( rc != LDAP_SUCCESS ) {
685 if ( rc != LDAP_SUCCESS ) {
692 if ( mapping != NULL ) {
693 /* use new attribute description */
694 assert( mapping->m_dst_ad != NULL );
695 ml->sml_desc = mapping->m_dst_ad;
702 *mlp = (*mlp)->sml_next;
707 *mlp = (*mlp)->sml_next;
708 slap_mod_free( &ml->sml_mod, 0 );
712 op->o_callback = &roc->cb;
714 return SLAP_CB_CONTINUE;
718 rwm_op_modrdn( Operation *op, SlapReply *rs )
720 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
721 struct ldaprwmap *rwmap =
722 (struct ldaprwmap *)on->on_bi.bi_private;
727 rwm_op_cb *roc = rwm_callback_get( op );
729 if ( op->orr_newSup ) {
730 struct berval nnewSup = BER_BVNULL;
731 struct berval newSup = BER_BVNULL;
734 * Rewrite the new superior, if defined and required
737 dc.conn = op->o_conn;
739 dc.ctx = "newSuperiorDN";
740 newSup = *op->orr_newSup;
741 nnewSup = *op->orr_nnewSup;
742 rc = rwm_dn_massage_pretty_normalize( &dc, op->orr_newSup, &newSup, &nnewSup );
743 if ( rc != LDAP_SUCCESS ) {
744 op->o_bd->bd_info = (BackendInfo *)on->on_info;
745 send_ldap_error( op, rs, rc, "newSuperiorDN massage error" );
749 if ( op->orr_newSup->bv_val != newSup.bv_val ) {
750 op->orr_newSup = op->o_tmpalloc( sizeof( struct berval ),
752 op->orr_nnewSup = op->o_tmpalloc( sizeof( struct berval ),
754 *op->orr_newSup = newSup;
755 *op->orr_nnewSup = nnewSup;
760 * Rewrite the newRDN, if needed
763 struct berval newrdn = BER_BVNULL;
764 struct berval nnewrdn = BER_BVNULL;
767 dc.conn = op->o_conn;
770 newrdn = op->orr_newrdn;
771 nnewrdn = op->orr_nnewrdn;
772 rc = rwm_dn_massage_pretty_normalize( &dc, &op->orr_newrdn, &newrdn, &nnewrdn );
773 if ( rc != LDAP_SUCCESS ) {
774 op->o_bd->bd_info = (BackendInfo *)on->on_info;
775 send_ldap_error( op, rs, rc, "newRDN massage error" );
779 if ( op->orr_newrdn.bv_val != newrdn.bv_val ) {
780 op->orr_newrdn = newrdn;
781 op->orr_nnewrdn = nnewrdn;
786 * Rewrite the dn, if needed
788 rc = rwm_op_dn_massage( op, rs, "renameDN", &roc->ros );
789 if ( rc != LDAP_SUCCESS ) {
790 op->o_bd->bd_info = (BackendInfo *)on->on_info;
791 send_ldap_error( op, rs, rc, "renameDN massage error" );
795 op->o_callback = &roc->cb;
797 rc = SLAP_CB_CONTINUE;
801 if ( op->orr_newSup != roc->ros.orr_newSup ) {
802 ch_free( op->orr_newSup->bv_val );
803 ch_free( op->orr_nnewSup->bv_val );
804 op->o_tmpfree( op->orr_newSup, op->o_tmpmemctx );
805 op->o_tmpfree( op->orr_nnewSup, op->o_tmpmemctx );
806 op->orr_newSup = roc->ros.orr_newSup;
807 op->orr_nnewSup = roc->ros.orr_nnewSup;
810 if ( op->orr_newrdn.bv_val != roc->ros.orr_newrdn.bv_val ) {
811 ch_free( op->orr_newrdn.bv_val );
812 ch_free( op->orr_nnewrdn.bv_val );
813 op->orr_newrdn = roc->ros.orr_newrdn;
814 op->orr_nnewrdn = roc->ros.orr_nnewrdn;
823 rwm_swap_attrs( Operation *op, SlapReply *rs )
825 slap_callback *cb = op->o_callback;
826 rwm_op_state *ros = cb->sc_private;
828 rs->sr_attrs = ros->ors_attrs;
830 /* other overlays might have touched op->ors_attrs,
831 * so we restore the original version here, otherwise
832 * attribute-mapping might fail */
833 op->ors_attrs = ros->mapped_attrs;
835 return SLAP_CB_CONTINUE;
839 * NOTE: this implementation of get/release entry is probably far from
840 * optimal. The rationale consists in intercepting the request directed
841 * to the underlying database, in order to rewrite/remap the request,
842 * perform it using the modified data, duplicate the resulting entry
843 * and finally free it when release is called.
844 * This implies that subsequent overlays are not called, as the request
845 * is directly shunted to the underlying database.
848 rwm_entry_release_rw( Operation *op, Entry *e, int rw )
850 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
853 if ( ((BackendInfo *)on->on_info->oi_orig)->bi_entry_get_rw == NULL ) {
854 return SLAP_CB_CONTINUE;
857 /* just free entry if (probably) ours */
858 if ( e->e_private == NULL && BER_BVISNULL( &e->e_bv ) ) {
863 return SLAP_CB_CONTINUE;
867 rwm_entry_get_rw( Operation *op, struct berval *ndn,
868 ObjectClass *oc, AttributeDescription *at, int rw, Entry **ep )
870 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
874 SlapReply rs = { REP_SEARCH };
876 rwm_op_state ros = { 0 };
877 struct berval mndn = BER_BVNULL;
879 if ( ((BackendInfo *)on->on_info->oi_orig)->bi_entry_get_rw == NULL ) {
880 return SLAP_CB_CONTINUE;
884 op2.o_tag = LDAP_REQ_SEARCH;
887 op2.o_req_ndn = *ndn;
888 rc = rwm_op_dn_massage( &op2, &rs, "searchDN", &ros );
889 if ( rc != LDAP_SUCCESS ) {
893 mndn = BER_BVISNULL( &ros.r_ndn ) ? *ndn : ros.r_ndn;
895 /* map attribute & objectClass */
905 op2.o_bd->bd_info = (BackendInfo *)on->on_info->oi_orig;
906 op2.ors_attrs = slap_anlist_all_attributes;
907 rc = op2.o_bd->bd_info->bi_entry_get_rw( &op2, &mndn, oc, at, rw, ep );
908 if ( rc == LDAP_SUCCESS && *ep != NULL ) {
909 /* we assume be_entry_release() needs to be called */
910 rs.sr_flags = REP_ENTRY_MUSTRELEASE;
913 /* duplicate & release */
914 op2.o_bd->bd_info = (BackendInfo *)on;
915 rc = rwm_send_entry( &op2, &rs );
916 RS_ASSERT( rs.sr_flags & REP_ENTRY_MUSTFLUSH );
917 if ( rc == SLAP_CB_CONTINUE ) {
921 assert( rc != LDAP_SUCCESS && rs.sr_entry == *ep );
923 op2.o_bd->bd_info = (BackendInfo *)on->on_info;
924 be_entry_release_r( &op2, rs.sr_entry );
925 op2.o_bd->bd_info = (BackendInfo *)on;
929 if ( !BER_BVISNULL( &ros.r_ndn) && ros.r_ndn.bv_val != ndn->bv_val ) {
930 op->o_tmpfree( ros.r_ndn.bv_val, op->o_tmpmemctx );
937 rwm_op_search( Operation *op, SlapReply *rs )
939 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
940 struct ldaprwmap *rwmap =
941 (struct ldaprwmap *)on->on_bi.bi_private;
946 struct berval fstr = BER_BVNULL;
949 AttributeName *an = NULL;
953 rwm_op_cb *roc = rwm_callback_get( op );
955 rc = rewrite_session_var_set( rwmap->rwm_rw, op->o_conn,
956 "searchFilter", op->ors_filterstr.bv_val );
957 if ( rc == LDAP_SUCCESS )
958 rc = rwm_op_dn_massage( op, rs, "searchDN", &roc->ros );
959 if ( rc != LDAP_SUCCESS ) {
960 text = "searchDN massage error";
965 * Rewrite the dn if needed
968 dc.conn = op->o_conn;
970 dc.ctx = "searchFilterAttrDN";
972 rc = rwm_filter_map_rewrite( op, &dc, op->ors_filter, &fstr );
973 if ( rc != LDAP_SUCCESS ) {
974 text = "searchFilter/searchFilterAttrDN massage error";
978 f = str2filter_x( op, fstr.bv_val );
981 text = "massaged filter parse error";
986 op->ors_filterstr = fstr;
988 rc = rwm_map_attrnames( op, &rwmap->rwm_at, &rwmap->rwm_oc,
989 op->ors_attrs, &an, RWM_MAP );
990 if ( rc != LDAP_SUCCESS ) {
991 text = "attribute list mapping error";
996 /* store the mapped Attributes for later usage, in
997 * the case that other overlays change op->ors_attrs */
998 roc->ros.mapped_attrs = an;
999 roc->cb.sc_response = rwm_swap_attrs;
1001 op->o_callback = &roc->cb;
1003 return SLAP_CB_CONTINUE;
1011 filter_free_x( op, f, 1 );
1014 if ( !BER_BVISNULL( &fstr ) ) {
1015 op->o_tmpfree( fstr.bv_val, op->o_tmpmemctx );
1018 rwm_op_rollback( op, rs, &roc->ros );
1019 op->oq_search = roc->ros.oq_search;
1020 op->o_tmpfree( roc, op->o_tmpmemctx );
1022 op->o_bd->bd_info = (BackendInfo *)on->on_info;
1023 send_ldap_error( op, rs, rc, text );
1030 rwm_exop_passwd( Operation *op, SlapReply *rs )
1032 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
1036 struct berval id = BER_BVNULL,
1039 BerElement *ber = NULL;
1041 if ( !BER_BVISNULL( &op->o_req_ndn ) ) {
1042 return LDAP_SUCCESS;
1045 if ( !SLAP_ISGLOBALOVERLAY( op->o_bd ) ) {
1046 rs->sr_err = LDAP_OTHER;
1050 rs->sr_err = slap_passwd_parse( op->ore_reqdata, &id,
1051 &pwold, &pwnew, &rs->sr_text );
1052 if ( rs->sr_err != LDAP_SUCCESS ) {
1056 if ( !BER_BVISNULL( &id ) ) {
1057 char idNul = id.bv_val[id.bv_len];
1058 id.bv_val[id.bv_len] = '\0';
1059 rs->sr_err = dnPrettyNormal( NULL, &id, &op->o_req_dn,
1060 &op->o_req_ndn, op->o_tmpmemctx );
1061 id.bv_val[id.bv_len] = idNul;
1062 if ( rs->sr_err != LDAP_SUCCESS ) {
1063 rs->sr_text = "Invalid DN";
1068 ber_dupbv_x( &op->o_req_dn, &op->o_dn, op->o_tmpmemctx );
1069 ber_dupbv_x( &op->o_req_ndn, &op->o_ndn, op->o_tmpmemctx );
1072 roc = rwm_callback_get( op );
1074 rc = rwm_op_dn_massage( op, rs, "extendedDN", &roc->ros );
1075 if ( rc != LDAP_SUCCESS ) {
1076 op->o_bd->bd_info = (BackendInfo *)on->on_info;
1077 send_ldap_error( op, rs, rc, "extendedDN massage error" );
1081 ber = ber_alloc_t( LBER_USE_DER );
1083 rs->sr_err = LDAP_OTHER;
1084 rs->sr_text = "No memory";
1087 ber_printf( ber, "{" );
1088 if ( !BER_BVISNULL( &id )) {
1089 ber_printf( ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_ID,
1092 if ( !BER_BVISNULL( &pwold )) {
1093 ber_printf( ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_OLD, &pwold );
1095 if ( !BER_BVISNULL( &pwnew )) {
1096 ber_printf( ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_NEW, &pwnew );
1098 ber_printf( ber, "N}" );
1099 ber_flatten( ber, &op->ore_reqdata );
1102 op->o_callback = &roc->cb;
1104 return SLAP_CB_CONTINUE;
1107 static struct exop {
1109 BI_op_extended *extended;
1111 { BER_BVC(LDAP_EXOP_MODIFY_PASSWD), rwm_exop_passwd },
1112 { BER_BVNULL, NULL }
1116 rwm_extended( Operation *op, SlapReply *rs )
1118 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
1124 for ( i = 0; exop_table[i].extended != NULL; i++ ) {
1125 if ( bvmatch( &exop_table[i].oid, &op->oq_extended.rs_reqoid ) )
1127 rc = exop_table[i].extended( op, rs );
1132 case SLAP_CB_CONTINUE:
1137 send_ldap_result( op, rs );
1144 roc = rwm_callback_get( op );
1146 rc = rwm_op_dn_massage( op, rs, "extendedDN", &roc->ros );
1147 if ( rc != LDAP_SUCCESS ) {
1148 op->o_bd->bd_info = (BackendInfo *)on->on_info;
1149 send_ldap_error( op, rs, rc, "extendedDN massage error" );
1153 /* TODO: rewrite/map extended data ? ... */
1154 op->o_callback = &roc->cb;
1156 return SLAP_CB_CONTINUE;
1160 rwm_matched( Operation *op, SlapReply *rs )
1162 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
1163 struct ldaprwmap *rwmap =
1164 (struct ldaprwmap *)on->on_bi.bi_private;
1166 struct berval dn, mdn;
1170 if ( rs->sr_matched == NULL ) {
1175 dc.conn = op->o_conn;
1177 dc.ctx = "matchedDN";
1178 ber_str2bv( rs->sr_matched, 0, 0, &dn );
1180 rc = rwm_dn_massage_pretty( &dc, &dn, &mdn );
1181 if ( rc != LDAP_SUCCESS ) {
1183 rs->sr_text = "Rewrite error";
1185 } else if ( mdn.bv_val != dn.bv_val ) {
1186 if ( rs->sr_flags & REP_MATCHED_MUSTBEFREED ) {
1187 ch_free( (void *)rs->sr_matched );
1190 rs->sr_flags |= REP_MATCHED_MUSTBEFREED;
1192 rs->sr_matched = mdn.bv_val;
1197 rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first, int stripEntryDN )
1199 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
1200 struct ldaprwmap *rwmap =
1201 (struct ldaprwmap *)on->on_bi.bi_private;
1207 int check_duplicate_attrs = 0;
1210 * Rewrite the dn attrs, if needed
1213 dc.conn = op->o_conn;
1216 /* FIXME: the entries are in the remote mapping form;
1217 * so we need to select those attributes we are willing
1218 * to return, and remap them accordingly */
1220 /* FIXME: in principle, one could map an attribute
1221 * on top of another, which already exists.
1222 * As such, in the end there might exist more than
1223 * one instance of an attribute.
1224 * We should at least check if this occurs, and issue
1225 * an error (because multiple instances of attrs in
1226 * response are not valid), or merge the values (what
1227 * about duplicate values?) */
1228 isupdate = be_shadow_update( op );
1229 for ( ap = a_first; *ap; ) {
1230 struct ldapmapping *mapping = NULL;
1235 if ( ( rwmap->rwm_flags & RWM_F_DROP_UNREQUESTED_ATTRS ) &&
1236 op->ors_attrs != NULL &&
1237 !SLAP_USERATTRS( rs->sr_attr_flags ) &&
1238 !ad_inlist( (*ap)->a_desc, op->ors_attrs ) )
1243 drop_missing = rwm_mapping( &rwmap->rwm_at,
1244 &(*ap)->a_desc->ad_cname, &mapping, RWM_REMAP );
1245 if ( drop_missing || ( mapping != NULL && BER_BVISEMPTY( &mapping->m_dst ) ) )
1249 if ( mapping != NULL ) {
1250 assert( mapping->m_dst_ad != NULL );
1252 /* try to normalize mapped Attributes if the original
1253 * AttributeType was not normalized */
1254 if ( (!(*ap)->a_desc->ad_type->sat_equality ||
1255 !(*ap)->a_desc->ad_type->sat_equality->smr_normalize) &&
1256 mapping->m_dst_ad->ad_type->sat_equality &&
1257 mapping->m_dst_ad->ad_type->sat_equality->smr_normalize )
1259 if ((rwmap->rwm_flags & RWM_F_NORMALIZE_MAPPED_ATTRS))
1263 last = (*ap)->a_numvals;
1266 (*ap)->a_nvals = ch_malloc( (last+1) * sizeof(struct berval) );
1268 for ( i = 0; !BER_BVISNULL( &(*ap)->a_vals[i]); i++ ) {
1271 * check that each value is valid per syntax
1272 * and pretty if appropriate
1274 rc = mapping->m_dst_ad->ad_type->sat_equality->smr_normalize(
1275 SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
1276 mapping->m_dst_ad->ad_type->sat_syntax,
1277 mapping->m_dst_ad->ad_type->sat_equality,
1278 &(*ap)->a_vals[i], &(*ap)->a_nvals[i],
1281 if ( rc != LDAP_SUCCESS ) {
1282 /* FIXME: this is wrong, putting a non-normalized value
1283 * into nvals. But when a proxy sends us bogus data,
1284 * we still need to give it to the client, even if it
1285 * violates the syntax. I.e., we don't want to silently
1286 * drop things and trigger an apparent data loss.
1288 ber_dupbv( &(*ap)->a_nvals[i], &(*ap)->a_vals[i] );
1291 BER_BVZERO( &(*ap)->a_nvals[i] );
1295 assert( (*ap)->a_nvals == (*ap)->a_vals );
1296 (*ap)->a_nvals = NULL;
1297 ber_bvarray_dup_x( &(*ap)->a_nvals, (*ap)->a_vals, NULL );
1301 /* rewrite the attribute description */
1302 (*ap)->a_desc = mapping->m_dst_ad;
1304 /* will need to check for duplicate attrs */
1305 check_duplicate_attrs++;
1308 if ( (*ap)->a_desc == slap_schema.si_ad_entryDN ) {
1309 if ( stripEntryDN ) {
1310 /* will be generated by frontend */
1314 } else if ( !isupdate
1316 && (*ap)->a_desc->ad_type->sat_no_user_mod
1317 && (*ap)->a_desc->ad_type != slap_schema.si_at_undefined )
1322 if ( last == -1 ) { /* not yet counted */
1323 last = (*ap)->a_numvals;
1327 /* empty? leave it in place because of attrsonly and vlv */
1332 if ( (*ap)->a_desc == slap_schema.si_ad_objectClass
1333 || (*ap)->a_desc == slap_schema.si_ad_structuralObjectClass )
1337 for ( bv = (*ap)->a_vals; !BER_BVISNULL( bv ); bv++ ) {
1338 struct berval mapped;
1340 rwm_map( &rwmap->rwm_oc, &bv[0], &mapped, RWM_REMAP );
1341 if ( BER_BVISNULL( &mapped ) || BER_BVISEMPTY( &mapped ) ) {
1343 ch_free( bv[0].bv_val );
1344 BER_BVZERO( &bv[0] );
1345 if ( &(*ap)->a_vals[last] > &bv[0] ) {
1346 bv[0] = (*ap)->a_vals[last];
1347 BER_BVZERO( &(*ap)->a_vals[last] );
1352 } else if ( mapped.bv_val != bv[0].bv_val
1353 && ber_bvstrcasecmp( &mapped, &bv[0] ) != 0 )
1357 for ( i = 0; !BER_BVISNULL( &(*ap)->a_vals[ i ] ); i++ ) {
1358 if ( &(*ap)->a_vals[ i ] == bv ) {
1362 if ( ber_bvstrcasecmp( &mapped, &(*ap)->a_vals[ i ] ) == 0 ) {
1367 if ( !BER_BVISNULL( &(*ap)->a_vals[ i ] ) ) {
1372 * FIXME: after LBER_FREEing
1373 * the value is replaced by
1374 * ch_alloc'ed memory
1376 ber_bvreplace( &bv[0], &mapped );
1378 /* FIXME: will need to check
1379 * if the structuralObjectClass
1385 * It is necessary to try to rewrite attributes with
1386 * dn syntax because they might be used in ACLs as
1387 * members of groups; since ACLs are applied to the
1388 * rewritten stuff, no dn-based subject clause could
1389 * be used at the ldap backend side (see
1390 * http://www.OpenLDAP.org/faq/data/cache/452.html)
1391 * The problem can be overcome by moving the dn-based
1392 * ACLs to the target directory server, and letting
1393 * everything pass thru the ldap backend. */
1394 /* FIXME: handle distinguishedName-like syntaxes, like
1395 * nameAndOptionalUID */
1396 } else if ( (*ap)->a_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
1397 || ( mapping != NULL && mapping->m_src_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
1399 dc.ctx = "searchAttrDN";
1400 rc = rwm_dnattr_result_rewrite( &dc, (*ap)->a_vals, (*ap)->a_nvals );
1401 if ( rc != LDAP_SUCCESS ) {
1405 } else if ( (*ap)->a_desc == slap_schema.si_ad_ref ) {
1406 dc.ctx = "searchAttrDN";
1407 rc = rwm_referral_result_rewrite( &dc, (*ap)->a_vals );
1408 if ( rc != LDAP_SUCCESS ) {
1415 ap = &(*ap)->a_next;
1420 *ap = (*ap)->a_next;
1425 /* only check if some mapping occurred */
1426 if ( check_duplicate_attrs ) {
1427 for ( ap = a_first; *ap != NULL; ap = &(*ap)->a_next ) {
1430 for ( tap = &(*ap)->a_next; *tap != NULL; ) {
1431 if ( (*tap)->a_desc == (*ap)->a_desc ) {
1433 Modification mod = { 0 };
1434 const char *text = NULL;
1435 char textbuf[ SLAP_TEXT_BUFLEN ];
1436 Attribute *next = (*tap)->a_next;
1438 BER_BVSTR( &e.e_name, "" );
1439 BER_BVSTR( &e.e_nname, "" );
1441 mod.sm_op = LDAP_MOD_ADD;
1442 mod.sm_desc = (*ap)->a_desc;
1443 mod.sm_type = mod.sm_desc->ad_cname;
1444 mod.sm_numvals = (*tap)->a_numvals;
1445 mod.sm_values = (*tap)->a_vals;
1446 if ( (*tap)->a_nvals != (*tap)->a_vals ) {
1447 mod.sm_nvalues = (*tap)->a_nvals;
1450 (void)modify_add_values( &e, &mod,
1452 &text, textbuf, sizeof( textbuf ) );
1454 /* should not insert new attrs! */
1455 assert( e.e_attrs == *ap );
1461 tap = &(*tap)->a_next;
1470 /* Should return SLAP_CB_CONTINUE or failure, never LDAP_SUCCESS. */
1472 rwm_send_entry( Operation *op, SlapReply *rs )
1474 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
1475 struct ldaprwmap *rwmap =
1476 (struct ldaprwmap *)on->on_bi.bi_private;
1479 struct berval dn = BER_BVNULL,
1484 assert( rs->sr_entry != NULL );
1487 * Rewrite the dn of the result, if needed
1490 dc.conn = op->o_conn;
1492 dc.ctx = "searchEntryDN";
1495 if ( !( rs->sr_flags & REP_ENTRY_MODIFIABLE ) ) {
1496 /* FIXME: all we need to duplicate are:
1499 * - attributes that are requested
1500 * - no values if attrsonly is set
1504 rc = LDAP_NO_MEMORY;
1507 } else if ( rs->sr_flags & REP_ENTRY_MUSTRELEASE ) {
1508 /* ITS#6423: REP_ENTRY_MUSTRELEASE incompatible
1509 * with REP_ENTRY_MODIFIABLE */
1516 * Note: this may fail if the target host(s) schema differs
1517 * from the one known to the meta, and a DN with unknown
1518 * attributes is returned.
1522 rc = rwm_dn_massage_pretty_normalize( &dc, &e->e_name, &dn, &ndn );
1523 if ( rc != LDAP_SUCCESS ) {
1528 if ( e->e_name.bv_val != dn.bv_val ) {
1529 ch_free( e->e_name.bv_val );
1530 ch_free( e->e_nname.bv_val );
1536 /* TODO: map entry attribute types, objectclasses
1537 * and dn-valued attribute values */
1539 /* FIXME: the entries are in the remote mapping form;
1540 * so we need to select those attributes we are willing
1541 * to return, and remap them accordingly */
1542 (void)rwm_attrs( op, rs, &e->e_attrs, 1 );
1544 if ( e != rs->sr_entry ) {
1545 /* Reimplementing rs_replace_entry(), I suppose to
1546 * bypass our own dubious rwm_entry_release_rw() */
1547 if ( rs->sr_flags & REP_ENTRY_MUSTRELEASE ) {
1548 rs->sr_flags ^= REP_ENTRY_MUSTRELEASE;
1549 op->o_bd->bd_info = (BackendInfo *)on->on_info;
1550 be_entry_release_r( op, rs->sr_entry );
1551 op->o_bd->bd_info = (BackendInfo *)on;
1552 } else if ( rs->sr_flags & REP_ENTRY_MUSTBEFREED ) {
1553 entry_free( rs->sr_entry );
1556 rs->sr_flags |= REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED;
1559 return SLAP_CB_CONTINUE;
1562 if ( e != NULL && e != rs->sr_entry ) {
1563 if ( e->e_name.bv_val == dn.bv_val ) {
1564 BER_BVZERO( &e->e_name );
1567 if ( e->e_nname.bv_val == ndn.bv_val ) {
1568 BER_BVZERO( &e->e_nname );
1574 if ( !BER_BVISNULL( &dn ) ) {
1575 ch_free( dn.bv_val );
1578 if ( !BER_BVISNULL( &ndn ) ) {
1579 ch_free( ndn.bv_val );
1586 rwm_operational( Operation *op, SlapReply *rs )
1588 /* FIXME: the entries are in the remote mapping form;
1589 * so we need to select those attributes we are willing
1590 * to return, and remap them accordingly */
1591 if ( rs->sr_operational_attrs ) {
1592 rwm_attrs( op, rs, &rs->sr_operational_attrs, 1 );
1595 return SLAP_CB_CONTINUE;
1599 /* don't use this; it cannot be reverted, and leaves op->o_req_dn
1600 * rewritten for subsequent operations; fine for plain suffixmassage,
1601 * but destroys everything else */
1603 rwm_chk_referrals( Operation *op, SlapReply *rs )
1605 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
1608 rc = rwm_op_dn_massage( op, rs, "referralCheckDN" );
1609 if ( rc != LDAP_SUCCESS ) {
1610 op->o_bd->bd_info = (BackendInfo *)on->on_info;
1611 send_ldap_error( op, rs, rc, "referralCheckDN massage error" );
1615 return SLAP_CB_CONTINUE;
1627 slap_overinst *on = (slap_overinst *) be->bd_info;
1628 struct ldaprwmap *rwmap =
1629 (struct ldaprwmap *)on->on_bi.bi_private;
1631 return rewrite_parse( rwmap->rwm_rw,
1632 fname, lineno, argc, argv );
1638 rwm_suffixmassage_config(
1645 slap_overinst *on = (slap_overinst *) be->bd_info;
1646 struct ldaprwmap *rwmap =
1647 (struct ldaprwmap *)on->on_bi.bi_private;
1649 struct berval bvnc, nvnc, pvnc, brnc, nrnc, prnc;
1656 * suffixmassage [<suffix>] <massaged suffix>
1658 * the [<suffix>] field must be defined as a valid suffix
1659 * for the current database;
1660 * the <massaged suffix> shouldn't have already been
1661 * defined as a valid suffix for the current server
1664 if ( be->be_suffix == NULL ) {
1665 Debug( LDAP_DEBUG_ANY, "%s: line %d: "
1666 " \"suffixMassage [<suffix>]"
1667 " <massaged suffix>\" without "
1668 "<suffix> part requires database "
1669 "suffix be defined first.\n",
1673 bvnc = be->be_suffix[ 0 ];
1676 } else if ( argc == 3 ) {
1677 ber_str2bv( argv[ 1 ], 0, 0, &bvnc );
1681 Debug( LDAP_DEBUG_ANY, "%s: line %d: syntax is"
1682 " \"suffixMassage [<suffix>]"
1683 " <massaged suffix>\"\n",
1688 if ( dnPrettyNormal( NULL, &bvnc, &pvnc, &nvnc, NULL ) != LDAP_SUCCESS ) {
1689 Debug( LDAP_DEBUG_ANY, "%s: line %d: suffix DN %s is invalid\n",
1690 fname, lineno, bvnc.bv_val );
1694 ber_str2bv( argv[ massaged ], 0, 0, &brnc );
1695 if ( dnPrettyNormal( NULL, &brnc, &prnc, &nrnc, NULL ) != LDAP_SUCCESS ) {
1696 Debug( LDAP_DEBUG_ANY, "%s: line %d: suffix DN %s is invalid\n",
1697 fname, lineno, brnc.bv_val );
1698 free( nvnc.bv_val );
1699 free( pvnc.bv_val );
1704 * The suffix massaging is emulated
1705 * by means of the rewrite capabilities
1707 rc = rwm_suffix_massage_config( rwmap->rwm_rw,
1708 &pvnc, &nvnc, &prnc, &nrnc );
1709 free( nvnc.bv_val );
1710 free( pvnc.bv_val );
1711 free( nrnc.bv_val );
1712 free( prnc.bv_val );
1725 slap_overinst *on = (slap_overinst *) be->bd_info;
1726 struct ldaprwmap *rwmap =
1727 (struct ldaprwmap *)on->on_bi.bi_private;
1729 /* objectclass/attribute mapping */
1730 return rwm_map_config( &rwmap->rwm_oc,
1732 fname, lineno, argc, argv );
1736 rwm_response( Operation *op, SlapReply *rs )
1738 slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
1739 struct ldaprwmap *rwmap =
1740 (struct ldaprwmap *)on->on_bi.bi_private;
1744 if ( op->o_tag == LDAP_REQ_SEARCH && rs->sr_type == REP_SEARCH ) {
1745 return rwm_send_entry( op, rs );
1748 switch( op->o_tag ) {
1749 case LDAP_REQ_SEARCH:
1752 case LDAP_REQ_DELETE:
1753 case LDAP_REQ_MODRDN:
1754 case LDAP_REQ_MODIFY:
1755 case LDAP_REQ_COMPARE:
1756 case LDAP_REQ_EXTENDED:
1761 * Rewrite the dn of the referrals, if needed
1764 dc.conn = op->o_conn;
1766 dc.ctx = "referralDN";
1767 rc = rwm_referral_result_rewrite( &dc, rs->sr_ref );
1768 /* FIXME: impossible, so far */
1769 if ( rc != LDAP_SUCCESS ) {
1775 rwm_matched( op, rs );
1779 return SLAP_CB_CONTINUE;
1790 slap_overinst *on = (slap_overinst *) be->bd_info;
1791 struct ldaprwmap *rwmap =
1792 (struct ldaprwmap *)on->on_bi.bi_private;
1797 if ( strncasecmp( argv[ 0 ], "rwm-", STRLENOF( "rwm-" ) ) == 0 ) {
1799 argv[ 0 ] = &argv0[ STRLENOF( "rwm-" ) ];
1802 if ( strncasecmp( argv[0], "rewrite", STRLENOF("rewrite") ) == 0 ) {
1803 rc = rwm_rw_config( be, fname, lineno, argc, argv );
1805 } else if ( strcasecmp( argv[0], "map" ) == 0 ) {
1806 rc = rwm_m_config( be, fname, lineno, argc, argv );
1808 } else if ( strcasecmp( argv[0], "suffixmassage" ) == 0 ) {
1809 rc = rwm_suffixmassage_config( be, fname, lineno, argc, argv );
1811 } else if ( strcasecmp( argv[0], "t-f-support" ) == 0 ) {
1813 Debug( LDAP_DEBUG_ANY,
1814 "%s: line %d: \"t-f-support {no|yes|discover}\" needs 1 argument.\n",
1819 if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
1820 rwmap->rwm_flags &= ~(RWM_F_SUPPORT_T_F_MASK2);
1822 } else if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
1823 rwmap->rwm_flags |= RWM_F_SUPPORT_T_F;
1825 /* TODO: not implemented yet */
1826 } else if ( strcasecmp( argv[ 1 ], "discover" ) == 0 ) {
1827 Debug( LDAP_DEBUG_ANY,
1828 "%s: line %d: \"discover\" not supported yet "
1829 "in \"t-f-support {no|yes|discover}\".\n",
1833 rwmap->rwm_flags |= RWM_F_SUPPORT_T_F_DISCOVER;
1837 Debug( LDAP_DEBUG_ANY,
1838 "%s: line %d: unknown value \"%s\" for \"t-f-support {no|yes|discover}\".\n",
1839 fname, lineno, argv[ 1 ] );
1843 } else if ( strcasecmp( argv[0], "normalize-mapped-attrs" ) == 0 ) {
1845 Debug( LDAP_DEBUG_ANY,
1846 "%s: line %d: \"normalize-mapped-attrs {no|yes}\" needs 1 argument.\n",
1851 if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
1852 rwmap->rwm_flags &= ~(RWM_F_NORMALIZE_MAPPED_ATTRS);
1854 } else if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
1855 rwmap->rwm_flags |= RWM_F_NORMALIZE_MAPPED_ATTRS;
1859 rc = SLAP_CONF_UNKNOWN;
1870 * dynamic configuration...
1880 RWM_CF_NORMALIZE_MAPPED,
1881 RWM_CF_DROP_UNREQUESTED,
1886 static slap_verbmasks t_f_mode[] = {
1887 { BER_BVC( "true" ), RWM_F_SUPPORT_T_F },
1888 { BER_BVC( "yes" ), RWM_F_SUPPORT_T_F },
1889 { BER_BVC( "discover" ), RWM_F_SUPPORT_T_F_DISCOVER },
1890 { BER_BVC( "false" ), RWM_F_NONE },
1891 { BER_BVC( "no" ), RWM_F_NONE },
1895 static ConfigDriver rwm_cf_gen;
1897 static ConfigTable rwmcfg[] = {
1898 { "rwm-rewrite", "rewrite",
1899 2, 0, STRLENOF("rwm-rewrite"),
1900 ARG_MAGIC|RWM_CF_REWRITE, rwm_cf_gen,
1901 "( OLcfgOvAt:16.1 NAME 'olcRwmRewrite' "
1902 "DESC 'Rewrites strings' "
1903 "EQUALITY caseIgnoreMatch "
1904 "SYNTAX OMsDirectoryString "
1905 "X-ORDERED 'VALUES' )",
1908 { "rwm-suffixmassage", "[virtual]> <real",
1909 2, 3, 0, ARG_MAGIC|RWM_CF_REWRITE, rwm_cf_gen,
1912 { "rwm-t-f-support", "true|false|discover",
1913 2, 2, 0, ARG_MAGIC|RWM_CF_T_F_SUPPORT, rwm_cf_gen,
1914 "( OLcfgOvAt:16.2 NAME 'olcRwmTFSupport' "
1915 "DESC 'Absolute filters support' "
1916 "SYNTAX OMsDirectoryString "
1920 { "rwm-map", "{objectClass|attribute}",
1921 2, 4, 0, ARG_MAGIC|RWM_CF_MAP, rwm_cf_gen,
1922 "( OLcfgOvAt:16.3 NAME 'olcRwmMap' "
1923 "DESC 'maps attributes/objectClasses' "
1924 "EQUALITY caseIgnoreMatch "
1925 "SYNTAX OMsDirectoryString "
1926 "X-ORDERED 'VALUES' )",
1929 { "rwm-normalize-mapped-attrs", "true|false",
1930 2, 2, 0, ARG_MAGIC|ARG_ON_OFF|RWM_CF_NORMALIZE_MAPPED, rwm_cf_gen,
1931 "( OLcfgOvAt:16.4 NAME 'olcRwmNormalizeMapped' "
1932 "DESC 'Normalize mapped attributes/objectClasses' "
1933 "SYNTAX OMsBoolean "
1937 { "rwm-drop-unrequested-attrs", "true|false",
1938 2, 2, 0, ARG_MAGIC|ARG_ON_OFF|RWM_CF_DROP_UNREQUESTED, rwm_cf_gen,
1939 "( OLcfgOvAt:16.5 NAME 'olcRwmDropUnrequested' "
1940 "DESC 'Drop unrequested attributes' "
1941 "SYNTAX OMsBoolean "
1945 { NULL, NULL, 0, 0, 0, ARG_IGNORED }
1948 static ConfigOCs rwmocs[] = {
1949 { "( OLcfgOvOc:16.1 "
1950 "NAME 'olcRwmConfig' "
1951 "DESC 'Rewrite/remap configuration' "
1952 "SUP olcOverlayConfig "
1955 "olcRwmTFSupport $ "
1957 "olcRwmNormalizeMapped $ "
1958 "olcRwmDropUnrequested"
1960 Cft_Overlay, rwmcfg, NULL, NULL },
1965 slap_bv_x_ordered_unparse( BerVarray in, BerVarray *out )
1968 BerVarray bva = NULL;
1969 char ibuf[32], *ptr;
1972 assert( in != NULL );
1974 for ( i = 0; !BER_BVISNULL( &in[i] ); i++ )
1983 bva = ch_malloc( ( i + 1 ) * sizeof(struct berval) );
1984 BER_BVZERO( &bva[ 0 ] );
1986 for ( i = 0; !BER_BVISNULL( &in[i] ); i++ ) {
1987 idx.bv_len = snprintf( idx.bv_val, sizeof( ibuf ), "{%d}", i );
1988 if ( idx.bv_len >= sizeof( ibuf ) ) {
1989 ber_bvarray_free( bva );
1993 bva[i].bv_len = idx.bv_len + in[i].bv_len;
1994 bva[i].bv_val = ch_malloc( bva[i].bv_len + 1 );
1995 ptr = lutil_strcopy( bva[i].bv_val, ibuf );
1996 ptr = lutil_strcopy( ptr, in[i].bv_val );
1998 BER_BVZERO( &bva[ i + 1 ] );
2013 line = ldap_charray2str( argv, "\" \"" );
2014 if ( line != NULL ) {
2015 int len = strlen( argv[ 0 ] );
2017 ber_str2bv( line, 0, 0, &bv );
2018 AC_MEMCPY( &bv.bv_val[ len ], &bv.bv_val[ len + 1 ],
2019 bv.bv_len - ( len + 1 ) );
2020 bv.bv_val[ bv.bv_len - 1 ] = '"';
2023 ber_bvarray_add( bva, &bv );
2036 rwm_bva_rewrite_add(
2037 struct ldaprwmap *rwmap,
2041 return rwm_bva_add( &rwmap->rwm_bva_rewrite, idx, argv );
2047 struct ldaprwmap *rwmap,
2051 return rwm_bva_add( &rwmap->rwm_bva_map, idx, argv );
2056 rwm_info_init( struct rewrite_info ** rwm_rw )
2060 *rwm_rw = rewrite_info_init( REWRITE_MODE_USE_DEFAULT );
2061 if ( *rwm_rw == NULL ) {
2065 /* this rewriteContext by default must be null;
2066 * rules can be added if required */
2067 rargv[ 0 ] = "rewriteContext";
2068 rargv[ 1 ] = "searchFilter";
2070 rewrite_parse( *rwm_rw, "<suffix massage>", 1, 2, rargv );
2072 rargv[ 0 ] = "rewriteContext";
2073 rargv[ 1 ] = "default";
2075 rewrite_parse( *rwm_rw, "<suffix massage>", 2, 2, rargv );
2081 rwm_cf_gen( ConfigArgs *c )
2083 slap_overinst *on = (slap_overinst *)c->bi;
2084 struct ldaprwmap *rwmap =
2085 (struct ldaprwmap *)on->on_bi.bi_private;
2095 if ( c->op == SLAP_CONFIG_EMIT ) {
2096 struct berval bv = BER_BVNULL;
2098 switch ( c->type ) {
2099 case RWM_CF_REWRITE:
2100 if ( rwmap->rwm_bva_rewrite == NULL ) {
2104 slap_bv_x_ordered_unparse( rwmap->rwm_bva_rewrite, &c->rvalue_vals );
2105 if ( !c->rvalue_vals ) {
2111 case RWM_CF_T_F_SUPPORT:
2112 enum_to_verb( t_f_mode, (rwmap->rwm_flags & RWM_F_SUPPORT_T_F_MASK2), &bv );
2113 if ( BER_BVISNULL( &bv ) ) {
2114 /* there's something wrong... */
2119 value_add_one( &c->rvalue_vals, &bv );
2124 if ( rwmap->rwm_bva_map == NULL ) {
2128 slap_bv_x_ordered_unparse( rwmap->rwm_bva_map, &c->rvalue_vals );
2129 if ( !c->rvalue_vals ) {
2135 case RWM_CF_NORMALIZE_MAPPED:
2136 c->value_int = ( rwmap->rwm_flags & RWM_F_NORMALIZE_MAPPED_ATTRS );
2139 case RWM_CF_DROP_UNREQUESTED:
2140 c->value_int = ( rwmap->rwm_flags & RWM_F_DROP_UNREQUESTED_ATTRS );
2150 } else if ( c->op == LDAP_MOD_DELETE ) {
2151 switch ( c->type ) {
2152 case RWM_CF_REWRITE:
2153 if ( c->valx >= 0 ) {
2156 for ( i = 0; !BER_BVISNULL( &rwmap->rwm_bva_rewrite[ i ] ); i++ )
2159 if ( c->valx >= i ) {
2164 ber_memfree( rwmap->rwm_bva_rewrite[ c->valx ].bv_val );
2165 for ( i = c->valx; !BER_BVISNULL( &rwmap->rwm_bva_rewrite[ i + 1 ] ); i++ )
2167 rwmap->rwm_bva_rewrite[ i ] = rwmap->rwm_bva_rewrite[ i + 1 ];
2169 BER_BVZERO( &rwmap->rwm_bva_rewrite[ i ] );
2171 rewrite_info_delete( &rwmap->rwm_rw );
2172 assert( rwmap->rwm_rw == NULL );
2174 rc = rwm_info_init( &rwmap->rwm_rw );
2176 for ( i = 0; !BER_BVISNULL( &rwmap->rwm_bva_rewrite[ i ] ); i++ )
2178 ConfigArgs ca = { 0 };
2180 ca.line = rwmap->rwm_bva_rewrite[ i ].bv_val;
2182 init_config_argv( &ca );
2183 config_parse_ldif( &ca );
2185 argv0 = ca.argv[ 0 ];
2186 ca.argv[ 0 ] += STRLENOF( "rwm-" );
2188 if ( strcasecmp( ca.argv[ 0 ], "suffixmassage" ) == 0 ) {
2189 rc = rwm_suffixmassage_config( &db, c->fname, c->lineno,
2193 rc = rwm_rw_config( &db, c->fname, c->lineno,
2197 ca.argv[ 0 ] = argv0;
2199 ch_free( ca.tline );
2205 } else if ( rwmap->rwm_rw != NULL ) {
2206 rewrite_info_delete( &rwmap->rwm_rw );
2207 assert( rwmap->rwm_rw == NULL );
2209 ber_bvarray_free( rwmap->rwm_bva_rewrite );
2210 rwmap->rwm_bva_rewrite = NULL;
2212 rc = rwm_info_init( &rwmap->rwm_rw );
2216 case RWM_CF_T_F_SUPPORT:
2217 rwmap->rwm_flags &= ~RWM_F_SUPPORT_T_F_MASK2;
2221 if ( c->valx >= 0 ) {
2222 struct ldapmap rwm_oc = rwmap->rwm_oc;
2223 struct ldapmap rwm_at = rwmap->rwm_at;
2227 if ( rwmap->rwm_bva_map ) {
2228 for ( ; !BER_BVISNULL( &rwmap->rwm_bva_map[ cnt ] ); cnt++ )
2232 if ( c->valx >= cnt ) {
2237 memset( &rwmap->rwm_oc, 0, sizeof( rwmap->rwm_oc ) );
2238 memset( &rwmap->rwm_at, 0, sizeof( rwmap->rwm_at ) );
2240 /* re-parse all mappings except the one
2241 * that needs to be eliminated */
2243 for ( cnt = 0; !BER_BVISNULL( &rwmap->rwm_bva_map[ cnt ] ); cnt++ ) {
2244 ConfigArgs ca = { 0 };
2246 if ( cnt == c->valx ) {
2250 ca.line = rwmap->rwm_bva_map[ cnt ].bv_val;
2252 init_config_argv( &ca );
2253 config_parse_ldif( &ca );
2255 argv[1] = ca.argv[0];
2256 argv[2] = ca.argv[1];
2257 argv[3] = ca.argv[2];
2258 argv[4] = ca.argv[3];
2260 rc = rwm_m_config( &db, c->fname, c->lineno, ca.argc + 1, argv );
2262 ch_free( ca.tline );
2265 /* in case of failure, restore
2266 * the existing mapping */
2268 avl_free( rwmap->rwm_oc.remap, rwm_mapping_dst_free );
2269 avl_free( rwmap->rwm_oc.map, rwm_mapping_free );
2270 avl_free( rwmap->rwm_at.remap, rwm_mapping_dst_free );
2271 avl_free( rwmap->rwm_at.map, rwm_mapping_free );
2272 rwmap->rwm_oc = rwm_oc;
2273 rwmap->rwm_at = rwm_at;
2278 /* in case of success, destroy the old mapping
2279 * and eliminate the deleted one */
2281 avl_free( rwm_oc.remap, rwm_mapping_dst_free );
2282 avl_free( rwm_oc.map, rwm_mapping_free );
2283 avl_free( rwm_at.remap, rwm_mapping_dst_free );
2284 avl_free( rwm_at.map, rwm_mapping_free );
2286 ber_memfree( rwmap->rwm_bva_map[ c->valx ].bv_val );
2287 for ( cnt = c->valx; !BER_BVISNULL( &rwmap->rwm_bva_map[ cnt ] ); cnt++ ) {
2288 rwmap->rwm_bva_map[ cnt ] = rwmap->rwm_bva_map[ cnt + 1 ];
2293 avl_free( rwmap->rwm_oc.remap, rwm_mapping_dst_free );
2294 avl_free( rwmap->rwm_oc.map, rwm_mapping_free );
2295 avl_free( rwmap->rwm_at.remap, rwm_mapping_dst_free );
2296 avl_free( rwmap->rwm_at.map, rwm_mapping_free );
2298 rwmap->rwm_oc.remap = NULL;
2299 rwmap->rwm_oc.map = NULL;
2300 rwmap->rwm_at.remap = NULL;
2301 rwmap->rwm_at.map = NULL;
2303 ber_bvarray_free( rwmap->rwm_bva_map );
2304 rwmap->rwm_bva_map = NULL;
2308 case RWM_CF_NORMALIZE_MAPPED:
2309 rwmap->rwm_flags &= ~RWM_F_NORMALIZE_MAPPED_ATTRS;
2312 case RWM_CF_DROP_UNREQUESTED:
2313 rwmap->rwm_flags &= ~RWM_F_DROP_UNREQUESTED_ATTRS;
2322 if ( strncasecmp( c->argv[ 0 ], "olcRwm", STRLENOF( "olcRwm" ) ) == 0 ) {
2326 switch ( c->type ) {
2327 case RWM_CF_REWRITE:
2328 if ( c->valx >= 0 ) {
2329 struct rewrite_info *rwm_rw = rwmap->rwm_rw;
2332 for ( last = 0; rwmap->rwm_bva_rewrite && !BER_BVISNULL( &rwmap->rwm_bva_rewrite[ last ] ); last++ )
2335 if ( c->valx > last ) {
2339 rwmap->rwm_rw = NULL;
2340 rc = rwm_info_init( &rwmap->rwm_rw );
2342 for ( i = 0; i < c->valx; i++ ) {
2343 ConfigArgs ca = { 0 };
2345 ca.line = rwmap->rwm_bva_rewrite[ i ].bv_val;
2347 init_config_argv( &ca );
2348 config_parse_ldif( &ca );
2350 argv0 = ca.argv[ 0 ];
2351 ca.argv[ 0 ] += STRLENOF( "rwm-" );
2353 if ( strcasecmp( ca.argv[ 0 ], "suffixmassage" ) == 0 ) {
2354 rc = rwm_suffixmassage_config( &db, c->fname, c->lineno,
2358 rc = rwm_rw_config( &db, c->fname, c->lineno,
2362 ca.argv[ 0 ] = argv0;
2364 ch_free( ca.tline );
2370 argv0 = c->argv[ idx0 ];
2371 if ( strncasecmp( argv0, "rwm-", STRLENOF( "rwm-" ) ) != 0 ) {
2374 c->argv[ idx0 ] += STRLENOF( "rwm-" );
2375 if ( strcasecmp( c->argv[ idx0 ], "suffixmassage" ) == 0 ) {
2376 rc = rwm_suffixmassage_config( &db, c->fname, c->lineno,
2377 c->argc - idx0, &c->argv[ idx0 ] );
2380 rc = rwm_rw_config( &db, c->fname, c->lineno,
2381 c->argc - idx0, &c->argv[ idx0 ] );
2383 c->argv[ idx0 ] = argv0;
2385 rewrite_info_delete( &rwmap->rwm_rw );
2386 assert( rwmap->rwm_rw == NULL );
2388 rwmap->rwm_rw = rwm_rw;
2392 for ( i = c->valx; rwmap->rwm_bva_rewrite && !BER_BVISNULL( &rwmap->rwm_bva_rewrite[ i ] ); i++ )
2394 ConfigArgs ca = { 0 };
2396 ca.line = rwmap->rwm_bva_rewrite[ i ].bv_val;
2398 init_config_argv( &ca );
2399 config_parse_ldif( &ca );
2401 argv0 = ca.argv[ 0 ];
2402 ca.argv[ 0 ] += STRLENOF( "rwm-" );
2404 if ( strcasecmp( ca.argv[ 0 ], "suffixmassage" ) == 0 ) {
2405 rc = rwm_suffixmassage_config( &db, c->fname, c->lineno,
2409 rc = rwm_rw_config( &db, c->fname, c->lineno,
2413 ca.argv[ 0 ] = argv0;
2415 ch_free( ca.tline );
2421 rwmap->rwm_bva_rewrite = ch_realloc( rwmap->rwm_bva_rewrite,
2422 ( last + 2 )*sizeof( struct berval ) );
2423 BER_BVZERO( &rwmap->rwm_bva_rewrite[last+1] );
2425 for ( i = last - 1; i >= c->valx; i-- )
2427 rwmap->rwm_bva_rewrite[ i + 1 ] = rwmap->rwm_bva_rewrite[ i ];
2430 rwm_bva_rewrite_add( rwmap, c->valx, &c->argv[ idx0 ] );
2432 rewrite_info_delete( &rwm_rw );
2433 assert( rwm_rw == NULL );
2438 argv0 = c->argv[ idx0 ];
2439 if ( strncasecmp( argv0, "rwm-", STRLENOF( "rwm-" ) ) != 0 ) {
2442 c->argv[ idx0 ] += STRLENOF( "rwm-" );
2443 if ( strcasecmp( c->argv[ idx0 ], "suffixmassage" ) == 0 ) {
2444 rc = rwm_suffixmassage_config( &db, c->fname, c->lineno,
2445 c->argc - idx0, &c->argv[ idx0 ] );
2448 rc = rwm_rw_config( &db, c->fname, c->lineno,
2449 c->argc - idx0, &c->argv[ idx0 ] );
2451 c->argv[ idx0 ] = argv0;
2456 rwm_bva_rewrite_add( rwmap, -1, &c->argv[ idx0 ] );
2460 case RWM_CF_T_F_SUPPORT:
2461 rc = verb_to_mask( c->argv[ 1 ], t_f_mode );
2462 if ( BER_BVISNULL( &t_f_mode[ rc ].word ) ) {
2466 rwmap->rwm_flags &= ~RWM_F_SUPPORT_T_F_MASK2;
2467 rwmap->rwm_flags |= t_f_mode[ rc ].mask;
2472 if ( c->valx >= 0 ) {
2473 struct ldapmap rwm_oc = rwmap->rwm_oc;
2474 struct ldapmap rwm_at = rwmap->rwm_at;
2478 if ( rwmap->rwm_bva_map ) {
2479 for ( ; !BER_BVISNULL( &rwmap->rwm_bva_map[ cnt ] ); cnt++ )
2483 if ( c->valx >= cnt ) {
2487 memset( &rwmap->rwm_oc, 0, sizeof( rwmap->rwm_oc ) );
2488 memset( &rwmap->rwm_at, 0, sizeof( rwmap->rwm_at ) );
2490 /* re-parse all mappings, including the one
2491 * that needs to be added */
2493 for ( cnt = 0; cnt < c->valx; cnt++ ) {
2494 ConfigArgs ca = { 0 };
2496 ca.line = rwmap->rwm_bva_map[ cnt ].bv_val;
2498 init_config_argv( &ca );
2499 config_parse_ldif( &ca );
2501 argv[1] = ca.argv[0];
2502 argv[2] = ca.argv[1];
2503 argv[3] = ca.argv[2];
2504 argv[4] = ca.argv[3];
2506 rc = rwm_m_config( &db, c->fname, c->lineno, ca.argc + 1, argv );
2508 ch_free( ca.tline );
2511 /* in case of failure, restore
2512 * the existing mapping */
2520 rc = rwm_m_config( &db, c->fname, c->lineno, c->argc, c->argv );
2526 if ( rwmap->rwm_bva_map ) {
2527 for ( ; !BER_BVISNULL( &rwmap->rwm_bva_map[ cnt ] ); cnt++ ) {
2528 ConfigArgs ca = { 0 };
2530 ca.line = rwmap->rwm_bva_map[ cnt ].bv_val;
2532 init_config_argv( &ca );
2533 config_parse_ldif( &ca );
2535 argv[1] = ca.argv[0];
2536 argv[2] = ca.argv[1];
2537 argv[3] = ca.argv[2];
2538 argv[4] = ca.argv[3];
2540 rc = rwm_m_config( &db, c->fname, c->lineno, ca.argc + 1, argv );
2542 ch_free( ca.tline );
2545 /* in case of failure, restore
2546 * the existing mapping */
2553 /* in case of success, destroy the old mapping
2554 * and add the new one */
2557 struct berval bv, *bvp = &bv;
2559 if ( rwm_bva_add( &bvp, 0, &c->argv[ idx0 ] ) ) {
2564 tmp = ber_memrealloc( rwmap->rwm_bva_map,
2565 sizeof( struct berval )*( cnt + 2 ) );
2566 if ( tmp == NULL ) {
2567 ber_memfree( bv.bv_val );
2571 rwmap->rwm_bva_map = tmp;
2572 BER_BVZERO( &rwmap->rwm_bva_map[ cnt + 1 ] );
2574 avl_free( rwm_oc.remap, rwm_mapping_dst_free );
2575 avl_free( rwm_oc.map, rwm_mapping_free );
2576 avl_free( rwm_at.remap, rwm_mapping_dst_free );
2577 avl_free( rwm_at.map, rwm_mapping_free );
2579 for ( ; cnt-- > c->valx; ) {
2580 rwmap->rwm_bva_map[ cnt + 1 ] = rwmap->rwm_bva_map[ cnt ];
2582 rwmap->rwm_bva_map[ c->valx ] = bv;
2586 avl_free( rwmap->rwm_oc.remap, rwm_mapping_dst_free );
2587 avl_free( rwmap->rwm_oc.map, rwm_mapping_free );
2588 avl_free( rwmap->rwm_at.remap, rwm_mapping_dst_free );
2589 avl_free( rwmap->rwm_at.map, rwm_mapping_free );
2590 rwmap->rwm_oc = rwm_oc;
2591 rwmap->rwm_at = rwm_at;
2597 argv0 = c->argv[ 0 ];
2598 c->argv[ 0 ] += STRLENOF( "rwm-" );
2599 rc = rwm_m_config( &db, c->fname, c->lineno, c->argc, c->argv );
2600 c->argv[ 0 ] = argv0;
2608 line = ldap_charray2str( &c->argv[ 1 ], " " );
2609 if ( line != NULL ) {
2610 ber_str2bv( line, 0, 0, &bv );
2611 ber_bvarray_add( &rwmap->rwm_bva_map, &bv );
2616 case RWM_CF_NORMALIZE_MAPPED:
2617 if ( c->value_int ) {
2618 rwmap->rwm_flags |= RWM_F_NORMALIZE_MAPPED_ATTRS;
2620 rwmap->rwm_flags &= ~RWM_F_NORMALIZE_MAPPED_ATTRS;
2624 case RWM_CF_DROP_UNREQUESTED:
2625 if ( c->value_int ) {
2626 rwmap->rwm_flags |= RWM_F_DROP_UNREQUESTED_ATTRS;
2628 rwmap->rwm_flags &= ~RWM_F_DROP_UNREQUESTED_ATTRS;
2645 slap_overinst *on = (slap_overinst *) be->bd_info;
2646 struct ldaprwmap *rwmap;
2649 rwmap = (struct ldaprwmap *)ch_calloc( 1, sizeof( struct ldaprwmap ) );
2652 rwmap->rwm_flags = RWM_F_DROP_UNREQUESTED_ATTRS;
2654 rc = rwm_info_init( &rwmap->rwm_rw );
2656 on->on_bi.bi_private = (void *)rwmap;
2659 (void)rwm_db_destroy( be, NULL );
2670 slap_overinst *on = (slap_overinst *) be->bd_info;
2673 if ( on->on_bi.bi_private ) {
2674 struct ldaprwmap *rwmap =
2675 (struct ldaprwmap *)on->on_bi.bi_private;
2677 if ( rwmap->rwm_rw ) {
2678 rewrite_info_delete( &rwmap->rwm_rw );
2679 if ( rwmap->rwm_bva_rewrite )
2680 ber_bvarray_free( rwmap->rwm_bva_rewrite );
2683 avl_free( rwmap->rwm_oc.remap, rwm_mapping_dst_free );
2684 avl_free( rwmap->rwm_oc.map, rwm_mapping_free );
2685 avl_free( rwmap->rwm_at.remap, rwm_mapping_dst_free );
2686 avl_free( rwmap->rwm_at.map, rwm_mapping_free );
2687 ber_bvarray_free( rwmap->rwm_bva_map );
2695 static slap_overinst rwm = { { NULL } };
2697 #if SLAPD_OVER_RWM == SLAPD_MOD_DYNAMIC
2699 #endif /* SLAPD_OVER_RWM == SLAPD_MOD_DYNAMIC */
2701 rwm_initialize( void )
2705 /* Make sure we don't exceed the bits reserved for userland */
2706 config_check_userland( RWM_CF_LAST );
2708 memset( &rwm, 0, sizeof( slap_overinst ) );
2710 rwm.on_bi.bi_type = "rwm";
2711 rwm.on_bi.bi_flags =
2712 SLAPO_BFLAG_SINGLE |
2715 rwm.on_bi.bi_db_init = rwm_db_init;
2716 rwm.on_bi.bi_db_config = rwm_db_config;
2717 rwm.on_bi.bi_db_destroy = rwm_db_destroy;
2719 rwm.on_bi.bi_op_bind = rwm_op_bind;
2720 rwm.on_bi.bi_op_search = rwm_op_search;
2721 rwm.on_bi.bi_op_compare = rwm_op_compare;
2722 rwm.on_bi.bi_op_modify = rwm_op_modify;
2723 rwm.on_bi.bi_op_modrdn = rwm_op_modrdn;
2724 rwm.on_bi.bi_op_add = rwm_op_add;
2725 rwm.on_bi.bi_op_delete = rwm_op_delete;
2726 rwm.on_bi.bi_op_unbind = rwm_op_unbind;
2727 rwm.on_bi.bi_extended = rwm_extended;
2729 rwm.on_bi.bi_entry_release_rw = rwm_entry_release_rw;
2730 rwm.on_bi.bi_entry_get_rw = rwm_entry_get_rw;
2733 rwm.on_bi.bi_operational = rwm_operational;
2734 rwm.on_bi.bi_chk_referrals = 0 /* rwm_chk_referrals */ ;
2736 rwm.on_bi.bi_connection_init = rwm_conn_init;
2737 rwm.on_bi.bi_connection_destroy = rwm_conn_destroy;
2739 rwm.on_response = rwm_response;
2741 rwm.on_bi.bi_cf_ocs = rwmocs;
2743 rc = config_register_schema( rwmcfg, rwmocs );
2748 return overlay_register( &rwm );
2751 #if SLAPD_OVER_RWM == SLAPD_MOD_DYNAMIC
2753 init_module( int argc, char *argv[] )
2755 return rwm_initialize();
2757 #endif /* SLAPD_OVER_RWM == SLAPD_MOD_DYNAMIC */
2759 #endif /* SLAPD_OVER_RWM */