1 /* rwm.c - rewrite/remap operations */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 2003-2010 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 ch_free( op->orr_newSup->bv_val );
111 ch_free( op->orr_nnewSup->bv_val );
112 op->o_tmpfree( op->orr_newSup, op->o_tmpmemctx );
113 op->o_tmpfree( op->orr_nnewSup, op->o_tmpmemctx );
114 op->orr_newSup = ros->orr_newSup;
115 op->orr_nnewSup = ros->orr_nnewSup;
117 if ( op->orr_newrdn.bv_val != ros->orr_newrdn.bv_val ) {
118 ch_free( op->orr_newrdn.bv_val );
119 ch_free( op->orr_nnewrdn.bv_val );
120 op->orr_newrdn = ros->orr_newrdn;
121 op->orr_nnewrdn = ros->orr_nnewrdn;
124 case LDAP_REQ_SEARCH:
125 op->o_tmpfree( ros->mapped_attrs, op->o_tmpmemctx );
126 filter_free_x( op, op->ors_filter, 1 );
127 op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx );
128 op->ors_attrs = ros->ors_attrs;
129 op->ors_filter = ros->ors_filter;
130 op->ors_filterstr = ros->ors_filterstr;
132 case LDAP_REQ_EXTENDED:
133 if ( op->ore_reqdata != ros->ore_reqdata ) {
134 ber_bvfree( op->ore_reqdata );
135 op->ore_reqdata = ros->ore_reqdata;
139 if ( rs->sr_err == LDAP_SUCCESS ) {
141 ldap_pvt_thread_mutex_lock( &op->o_conn->c_mutex );
142 /* too late, c_mutex released */
143 Debug( LDAP_DEBUG_ANY, "*** DN: \"%s\" => \"%s\"\n",
144 op->o_conn->c_ndn.bv_val,
145 op->o_req_ndn.bv_val );
146 ber_bvreplace( &op->o_conn->c_ndn,
148 ldap_pvt_thread_mutex_unlock( &op->o_conn->c_mutex );
157 rwm_op_cleanup( Operation *op, SlapReply *rs )
159 slap_callback *cb = op->o_callback;
160 rwm_op_state *ros = cb->sc_private;
162 if ( rs->sr_type == REP_RESULT || rs->sr_type == REP_EXTENDED ||
163 op->o_abandon || rs->sr_err == SLAPD_ABANDON )
165 rwm_op_rollback( op, rs, ros );
167 op->o_callback = op->o_callback->sc_next;
168 op->o_tmpfree( cb, op->o_tmpmemctx );
171 return SLAP_CB_CONTINUE;
175 rwm_callback_get( Operation *op, SlapReply *rs )
177 rwm_op_cb *roc = NULL;
179 roc = op->o_tmpalloc( sizeof( struct rwm_op_cb ), op->o_tmpmemctx );
180 roc->cb.sc_cleanup = rwm_op_cleanup;
181 roc->cb.sc_response = NULL;
182 roc->cb.sc_next = op->o_callback;
183 roc->cb.sc_private = &roc->ros;
184 roc->ros.r_tag = op->o_tag;
185 roc->ros.ro_dn = op->o_req_dn;
186 roc->ros.ro_ndn = op->o_req_ndn;
187 roc->ros.o_request = op->o_request;
188 BER_BVZERO( &roc->ros.r_dn );
189 BER_BVZERO( &roc->ros.r_ndn );
196 rwm_op_dn_massage( Operation *op, SlapReply *rs, void *cookie,
199 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
200 struct ldaprwmap *rwmap =
201 (struct ldaprwmap *)on->on_bi.bi_private;
203 struct berval dn = BER_BVNULL,
209 * Rewrite the dn if needed
212 dc.conn = op->o_conn;
214 dc.ctx = (char *)cookie;
216 /* NOTE: in those cases where only the ndn is available,
217 * and the caller sets op->o_req_dn = op->o_req_ndn,
218 * only rewrite the op->o_req_ndn and use it as
219 * op->o_req_dn as well */
221 if ( op->o_req_dn.bv_val != op->o_req_ndn.bv_val ) {
223 rc = rwm_dn_massage_pretty_normalize( &dc, &op->o_req_dn, &dn, &ndn );
225 rc = rwm_dn_massage_normalize( &dc, &op->o_req_ndn, &ndn );
228 if ( rc != LDAP_SUCCESS ) {
232 if ( ( op->o_req_dn.bv_val != op->o_req_ndn.bv_val && dn.bv_val == op->o_req_dn.bv_val )
233 || ndn.bv_val == op->o_req_ndn.bv_val )
238 if ( op->o_req_dn.bv_val != op->o_req_ndn.bv_val ) {
240 assert( BER_BVISNULL( &ros->r_dn ) );
246 assert( BER_BVISNULL( &ros->r_ndn ) );
249 if ( ros->r_tag == LDAP_REQ_EXTENDED ) {
250 ros->rx_dn = ros->r_dn;
251 ros->rx_ndn = ros->r_ndn;
258 rwm_op_add( Operation *op, SlapReply *rs )
260 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
261 struct ldaprwmap *rwmap =
262 (struct ldaprwmap *)on->on_bi.bi_private;
266 Attribute **ap = NULL;
267 char *olddn = op->o_req_dn.bv_val;
270 rwm_op_cb *roc = rwm_callback_get( op, rs );
272 rc = rwm_op_dn_massage( op, rs, "addDN", &roc->ros );
273 if ( rc != LDAP_SUCCESS ) {
274 op->o_bd->bd_info = (BackendInfo *)on->on_info;
275 send_ldap_error( op, rs, rc, "addDN massage error" );
279 if ( olddn != op->o_req_dn.bv_val ) {
280 ber_bvreplace( &op->ora_e->e_name, &op->o_req_dn );
281 ber_bvreplace( &op->ora_e->e_nname, &op->o_req_ndn );
284 /* Count number of attributes in entry */
285 isupdate = be_shadow_update( op );
286 for ( i = 0, ap = &op->oq_add.rs_e->e_attrs; *ap; ) {
289 if ( (*ap)->a_desc == slap_schema.si_ad_objectClass ||
290 (*ap)->a_desc == slap_schema.si_ad_structuralObjectClass )
294 last = (*ap)->a_numvals - 1;
295 for ( j = 0; !BER_BVISNULL( &(*ap)->a_vals[ j ] ); j++ ) {
296 struct ldapmapping *mapping = NULL;
298 ( void )rwm_mapping( &rwmap->rwm_oc, &(*ap)->a_vals[ j ],
300 if ( mapping == NULL ) {
301 if ( rwmap->rwm_at.drop_missing ) {
302 /* FIXME: we allow to remove objectClasses as well;
303 * if the resulting entry is inconsistent, that's
304 * the relayed database's business...
306 ch_free( (*ap)->a_vals[ j ].bv_val );
308 (*ap)->a_vals[ j ] = (*ap)->a_vals[ last ];
310 BER_BVZERO( &(*ap)->a_vals[ last ] );
317 ch_free( (*ap)->a_vals[ j ].bv_val );
318 ber_dupbv( &(*ap)->a_vals[ j ], &mapping->m_dst );
322 } else if ( !isupdate && !get_relax( op ) && (*ap)->a_desc->ad_type->sat_no_user_mod )
327 struct ldapmapping *mapping = NULL;
329 ( void )rwm_mapping( &rwmap->rwm_at, &(*ap)->a_desc->ad_cname,
331 if ( mapping == NULL ) {
332 if ( rwmap->rwm_at.drop_missing ) {
337 if ( (*ap)->a_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
338 || ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
341 * FIXME: rewrite could fail; in this case
342 * the operation should give up, right?
344 rc = rwm_dnattr_rewrite( op, rs, "addAttrDN",
346 (*ap)->a_nvals ? &(*ap)->a_nvals : NULL );
351 } else if ( (*ap)->a_desc == slap_schema.si_ad_ref ) {
352 rc = rwm_referral_rewrite( op, rs, "referralAttrDN",
354 (*ap)->a_nvals ? &(*ap)->a_nvals : NULL );
355 if ( rc != LDAP_SUCCESS ) {
360 if ( mapping != NULL ) {
361 assert( mapping->m_dst_ad != NULL );
362 (*ap)->a_desc = mapping->m_dst_ad;
371 /* FIXME: leaking attribute/values? */
378 op->o_callback = &roc->cb;
380 return SLAP_CB_CONTINUE;
384 rwm_conn_init( BackendDB *be, Connection *conn )
386 slap_overinst *on = (slap_overinst *) be->bd_info;
387 struct ldaprwmap *rwmap =
388 (struct ldaprwmap *)on->on_bi.bi_private;
390 ( void )rewrite_session_init( rwmap->rwm_rw, conn );
392 return SLAP_CB_CONTINUE;
396 rwm_conn_destroy( BackendDB *be, Connection *conn )
398 slap_overinst *on = (slap_overinst *) be->bd_info;
399 struct ldaprwmap *rwmap =
400 (struct ldaprwmap *)on->on_bi.bi_private;
402 ( void )rewrite_session_delete( rwmap->rwm_rw, conn );
404 return SLAP_CB_CONTINUE;
408 rwm_op_bind( Operation *op, SlapReply *rs )
410 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
413 rwm_op_cb *roc = rwm_callback_get( op, rs );
415 rc = rwm_op_dn_massage( op, rs, "bindDN", &roc->ros );
416 if ( rc != LDAP_SUCCESS ) {
417 op->o_bd->bd_info = (BackendInfo *)on->on_info;
418 send_ldap_error( op, rs, rc, "bindDN massage error" );
422 overlay_callback_after_backover( op, &roc->cb, 1 );
424 return SLAP_CB_CONTINUE;
428 rwm_op_unbind( Operation *op, SlapReply *rs )
430 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
431 struct ldaprwmap *rwmap =
432 (struct ldaprwmap *)on->on_bi.bi_private;
434 rewrite_session_delete( rwmap->rwm_rw, op->o_conn );
436 return SLAP_CB_CONTINUE;
440 rwm_op_compare( Operation *op, SlapReply *rs )
442 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
443 struct ldaprwmap *rwmap =
444 (struct ldaprwmap *)on->on_bi.bi_private;
447 struct berval mapped_vals[2] = { BER_BVNULL, BER_BVNULL };
449 rwm_op_cb *roc = rwm_callback_get( op, rs );
451 rc = rwm_op_dn_massage( op, rs, "compareDN", &roc->ros );
452 if ( rc != LDAP_SUCCESS ) {
453 op->o_bd->bd_info = (BackendInfo *)on->on_info;
454 send_ldap_error( op, rs, rc, "compareDN massage error" );
458 /* if the attribute is an objectClass, try to remap its value */
459 if ( op->orc_ava->aa_desc == slap_schema.si_ad_objectClass
460 || op->orc_ava->aa_desc == slap_schema.si_ad_structuralObjectClass )
462 rwm_map( &rwmap->rwm_oc, &op->orc_ava->aa_value,
463 &mapped_vals[0], RWM_MAP );
464 if ( BER_BVISNULL( &mapped_vals[0] ) || BER_BVISEMPTY( &mapped_vals[0] ) )
466 op->o_bd->bd_info = (BackendInfo *)on->on_info;
467 send_ldap_error( op, rs, LDAP_OTHER, "compare objectClass map error" );
470 } else if ( mapped_vals[0].bv_val != op->orc_ava->aa_value.bv_val ) {
471 ber_dupbv_x( &op->orc_ava->aa_value, &mapped_vals[0],
476 struct ldapmapping *mapping = NULL;
477 AttributeDescription *ad = op->orc_ava->aa_desc;
479 ( void )rwm_mapping( &rwmap->rwm_at, &op->orc_ava->aa_desc->ad_cname,
481 if ( mapping == NULL ) {
482 if ( rwmap->rwm_at.drop_missing ) {
483 op->o_bd->bd_info = (BackendInfo *)on->on_info;
484 send_ldap_error( op, rs, LDAP_OTHER, "compare attributeType map error" );
489 assert( mapping->m_dst_ad != NULL );
490 ad = mapping->m_dst_ad;
493 if ( op->orc_ava->aa_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
494 || ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
496 struct berval *mapped_valsp[2];
498 mapped_valsp[0] = &mapped_vals[0];
499 mapped_valsp[1] = &mapped_vals[1];
501 mapped_vals[0] = op->orc_ava->aa_value;
503 rc = rwm_dnattr_rewrite( op, rs, "compareAttrDN", NULL, mapped_valsp );
505 if ( rc != LDAP_SUCCESS ) {
506 op->o_bd->bd_info = (BackendInfo *)on->on_info;
507 send_ldap_error( op, rs, rc, "compareAttrDN massage error" );
511 if ( mapped_vals[ 0 ].bv_val != op->orc_ava->aa_value.bv_val ) {
512 /* NOTE: if we get here, rwm_dnattr_rewrite()
513 * already freed the old value, so now
515 ber_dupbv_x( &op->orc_ava->aa_value, &mapped_vals[0],
517 ber_memfree_x( mapped_vals[ 0 ].bv_val, NULL );
520 op->orc_ava->aa_desc = ad;
523 op->o_callback = &roc->cb;
525 return SLAP_CB_CONTINUE;
529 rwm_op_delete( Operation *op, SlapReply *rs )
531 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
534 rwm_op_cb *roc = rwm_callback_get( op, rs );
536 rc = rwm_op_dn_massage( op, rs, "deleteDN", &roc->ros );
537 if ( rc != LDAP_SUCCESS ) {
538 op->o_bd->bd_info = (BackendInfo *)on->on_info;
539 send_ldap_error( op, rs, rc, "deleteDN massage error" );
543 op->o_callback = &roc->cb;
545 return SLAP_CB_CONTINUE;
549 rwm_op_modify( Operation *op, SlapReply *rs )
551 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
552 struct ldaprwmap *rwmap =
553 (struct ldaprwmap *)on->on_bi.bi_private;
559 rwm_op_cb *roc = rwm_callback_get( op, rs );
561 rc = rwm_op_dn_massage( op, rs, "modifyDN", &roc->ros );
562 if ( rc != LDAP_SUCCESS ) {
563 op->o_bd->bd_info = (BackendInfo *)on->on_info;
564 send_ldap_error( op, rs, rc, "modifyDN massage error" );
568 isupdate = be_shadow_update( op );
569 for ( mlp = &op->orm_modlist; *mlp; ) {
571 Modifications *ml = *mlp;
572 struct ldapmapping *mapping = NULL;
574 /* ml points to a temporary mod until needs duplication */
575 if ( ml->sml_desc == slap_schema.si_ad_objectClass
576 || ml->sml_desc == slap_schema.si_ad_structuralObjectClass )
580 } else if ( !isupdate && !get_relax( op ) && ml->sml_desc->ad_type->sat_no_user_mod )
582 ml = ch_malloc( sizeof( Modifications ) );
584 if ( (*mlp)->sml_values ) {
585 ber_bvarray_dup_x( &ml->sml_values, (*mlp)->sml_values, NULL );
586 if ( (*mlp)->sml_nvalues ) {
587 ber_bvarray_dup_x( &ml->sml_nvalues, (*mlp)->sml_nvalues, NULL );
596 drop_missing = rwm_mapping( &rwmap->rwm_at,
597 &ml->sml_desc->ad_cname,
599 if ( drop_missing || ( mapping != NULL && BER_BVISNULL( &mapping->m_dst ) ) )
605 /* duplicate the modlist */
606 ml = ch_malloc( sizeof( Modifications ));
610 if ( ml->sml_values != NULL ) {
614 for ( num = 0; !BER_BVISNULL( &ml->sml_values[ num ] ); num++ )
617 bva = ch_malloc( (num+1) * sizeof( struct berval ));
618 for (i=0; i<num; i++)
619 ber_dupbv( &bva[i], &ml->sml_values[i] );
620 BER_BVZERO( &bva[i] );
621 ml->sml_values = bva;
623 if ( ml->sml_nvalues ) {
624 bva = ch_malloc( (num+1) * sizeof( struct berval ));
625 for (i=0; i<num; i++)
626 ber_dupbv( &bva[i], &ml->sml_nvalues[i] );
627 BER_BVZERO( &bva[i] );
628 ml->sml_nvalues = bva;
636 for ( j = 0; !BER_BVISNULL( &ml->sml_values[ j ] ); j++ ) {
637 struct ldapmapping *oc_mapping = NULL;
639 ( void )rwm_mapping( &rwmap->rwm_oc, &ml->sml_values[ j ],
640 &oc_mapping, RWM_MAP );
641 if ( oc_mapping == NULL ) {
642 if ( rwmap->rwm_at.drop_missing ) {
643 /* FIXME: we allow to remove objectClasses as well;
644 * if the resulting entry is inconsistent, that's
645 * the relayed database's business...
648 ch_free( ml->sml_values[ j ].bv_val );
649 ml->sml_values[ j ] = ml->sml_values[ last ];
651 BER_BVZERO( &ml->sml_values[ last ] );
657 ch_free( ml->sml_values[ j ].bv_val );
658 ber_dupbv( &ml->sml_values[ j ], &oc_mapping->m_dst );
663 if ( ml->sml_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
664 || ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
666 rc = rwm_dnattr_rewrite( op, rs, "modifyAttrDN",
668 ml->sml_nvalues ? &ml->sml_nvalues : NULL );
670 } else if ( ml->sml_desc == slap_schema.si_ad_ref ) {
671 rc = rwm_referral_rewrite( op, rs,
674 ml->sml_nvalues ? &ml->sml_nvalues : NULL );
675 if ( rc != LDAP_SUCCESS ) {
680 if ( rc != LDAP_SUCCESS ) {
687 if ( mapping != NULL ) {
688 /* use new attribute description */
689 assert( mapping->m_dst_ad != NULL );
690 ml->sml_desc = mapping->m_dst_ad;
698 *mlp = (*mlp)->sml_next;
699 slap_mod_free( &ml->sml_mod, 0 );
703 op->o_callback = &roc->cb;
705 return SLAP_CB_CONTINUE;
709 rwm_op_modrdn( Operation *op, SlapReply *rs )
711 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
712 struct ldaprwmap *rwmap =
713 (struct ldaprwmap *)on->on_bi.bi_private;
718 rwm_op_cb *roc = rwm_callback_get( op, rs );
720 if ( op->orr_newSup ) {
721 struct berval nnewSup = BER_BVNULL;
722 struct berval newSup = BER_BVNULL;
725 * Rewrite the new superior, if defined and required
728 dc.conn = op->o_conn;
730 dc.ctx = "newSuperiorDN";
731 newSup = *op->orr_newSup;
732 nnewSup = *op->orr_nnewSup;
733 rc = rwm_dn_massage_pretty_normalize( &dc, op->orr_newSup, &newSup, &nnewSup );
734 if ( rc != LDAP_SUCCESS ) {
735 op->o_bd->bd_info = (BackendInfo *)on->on_info;
736 send_ldap_error( op, rs, rc, "newSuperiorDN massage error" );
740 if ( op->orr_newSup->bv_val != newSup.bv_val ) {
741 op->orr_newSup = op->o_tmpalloc( sizeof( struct berval ),
743 op->orr_nnewSup = op->o_tmpalloc( sizeof( struct berval ),
745 *op->orr_newSup = newSup;
746 *op->orr_nnewSup = nnewSup;
751 * Rewrite the newRDN, if needed
754 struct berval newrdn = BER_BVNULL;
755 struct berval nnewrdn = BER_BVNULL;
758 dc.conn = op->o_conn;
761 newrdn = op->orr_newrdn;
762 nnewrdn = op->orr_nnewrdn;
763 rc = rwm_dn_massage_pretty_normalize( &dc, &op->orr_newrdn, &newrdn, &nnewrdn );
764 if ( rc != LDAP_SUCCESS ) {
765 op->o_bd->bd_info = (BackendInfo *)on->on_info;
766 send_ldap_error( op, rs, rc, "newRDN massage error" );
770 if ( op->orr_newrdn.bv_val != newrdn.bv_val ) {
771 op->orr_newrdn = newrdn;
772 op->orr_nnewrdn = nnewrdn;
777 * Rewrite the dn, if needed
779 rc = rwm_op_dn_massage( op, rs, "renameDN", &roc->ros );
780 if ( rc != LDAP_SUCCESS ) {
781 op->o_bd->bd_info = (BackendInfo *)on->on_info;
782 send_ldap_error( op, rs, rc, "renameDN massage error" );
786 op->o_callback = &roc->cb;
788 rc = SLAP_CB_CONTINUE;
792 if ( op->orr_newSup != roc->ros.orr_newSup ) {
793 ch_free( op->orr_newSup->bv_val );
794 ch_free( op->orr_nnewSup->bv_val );
795 op->o_tmpfree( op->orr_newSup, op->o_tmpmemctx );
796 op->o_tmpfree( op->orr_nnewSup, op->o_tmpmemctx );
797 op->orr_newSup = roc->ros.orr_newSup;
798 op->orr_nnewSup = roc->ros.orr_nnewSup;
801 if ( op->orr_newrdn.bv_val != roc->ros.orr_newrdn.bv_val ) {
802 ch_free( op->orr_newrdn.bv_val );
803 ch_free( op->orr_nnewrdn.bv_val );
804 op->orr_newrdn = roc->ros.orr_newrdn;
805 op->orr_nnewrdn = roc->ros.orr_nnewrdn;
814 rwm_swap_attrs( Operation *op, SlapReply *rs )
816 slap_callback *cb = op->o_callback;
817 rwm_op_state *ros = cb->sc_private;
819 rs->sr_attrs = ros->ors_attrs;
821 /* other overlays might have touched op->ors_attrs,
822 * so we restore the original version here, otherwise
823 * attribute-mapping might fail */
824 op->ors_attrs = ros->mapped_attrs;
826 return SLAP_CB_CONTINUE;
830 * NOTE: this implementation of get/release entry is probably far from
831 * optimal. The rationale consists in intercepting the request directed
832 * to the underlying database, in order to rewrite/remap the request,
833 * perform it using the modified data, duplicate the resulting entry
834 * and finally free it when release is called.
835 * This implies that subsequent overlays are not called, as the request
836 * is directly shunted to the underlying database.
839 rwm_entry_release_rw( Operation *op, Entry *e, int rw )
841 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
844 if ( ((BackendInfo *)on->on_info->oi_orig)->bi_entry_get_rw == NULL ) {
845 return SLAP_CB_CONTINUE;
848 /* just free entry if (probably) ours */
849 if ( e->e_private == NULL && BER_BVISNULL( &e->e_bv ) ) {
854 return SLAP_CB_CONTINUE;
858 rwm_entry_get_rw( Operation *op, struct berval *ndn,
859 ObjectClass *oc, AttributeDescription *at, int rw, Entry **ep )
861 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
862 struct ldaprwmap *rwmap =
863 (struct ldaprwmap *)on->on_bi.bi_private;
870 SlapReply rs = { REP_SEARCH };
872 rwm_op_state ros = { 0 };
873 struct berval mndn = BER_BVNULL;
875 if ( ((BackendInfo *)on->on_info->oi_orig)->bi_entry_get_rw == NULL ) {
876 return SLAP_CB_CONTINUE;
880 op2.o_tag = LDAP_REQ_SEARCH;
883 op2.o_req_ndn = *ndn;
884 rc = rwm_op_dn_massage( &op2, &rs, "searchDN", &ros );
885 if ( rc != LDAP_SUCCESS ) {
889 mndn = BER_BVISNULL( &ros.r_ndn ) ? *ndn : ros.r_ndn;
891 /* map attribute & objectClass */
901 op2.o_bd->bd_info = (BackendInfo *)on->on_info->oi_orig;
902 op2.ors_attrs = slap_anlist_all_attributes;
903 rc = op2.o_bd->bd_info->bi_entry_get_rw( &op2, &mndn, oc, at, rw, ep );
904 if ( rc == LDAP_SUCCESS && *ep != NULL ) {
905 /* we assume be_entry_release() needs to be called */
906 rs.sr_flags = REP_ENTRY_MUSTRELEASE;
909 /* duplicate & release */
910 op2.o_bd->bd_info = (BackendInfo *)on;
911 rc = rwm_send_entry( &op2, &rs );
912 if ( rc == SLAP_CB_CONTINUE ) {
918 if ( !BER_BVISNULL( &ros.r_ndn) && ros.r_ndn.bv_val != ndn->bv_val ) {
919 op->o_tmpfree( ros.r_ndn.bv_val, op->o_tmpmemctx );
926 rwm_op_search( Operation *op, SlapReply *rs )
928 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
929 struct ldaprwmap *rwmap =
930 (struct ldaprwmap *)on->on_bi.bi_private;
935 struct berval fstr = BER_BVNULL;
938 AttributeName *an = NULL;
942 rwm_op_cb *roc = rwm_callback_get( op, rs );
944 rc = rewrite_session_var_set( rwmap->rwm_rw, op->o_conn,
945 "searchFilter", op->ors_filterstr.bv_val );
946 if ( rc == LDAP_SUCCESS )
947 rc = rwm_op_dn_massage( op, rs, "searchDN", &roc->ros );
948 if ( rc != LDAP_SUCCESS ) {
949 text = "searchDN massage error";
954 * Rewrite the dn if needed
957 dc.conn = op->o_conn;
959 dc.ctx = "searchFilterAttrDN";
961 rc = rwm_filter_map_rewrite( op, &dc, op->ors_filter, &fstr );
962 if ( rc != LDAP_SUCCESS ) {
963 text = "searchFilter/searchFilterAttrDN massage error";
967 f = str2filter_x( op, fstr.bv_val );
970 text = "massaged filter parse error";
975 op->ors_filterstr = fstr;
977 rc = rwm_map_attrnames( op, &rwmap->rwm_at, &rwmap->rwm_oc,
978 op->ors_attrs, &an, RWM_MAP );
979 if ( rc != LDAP_SUCCESS ) {
980 text = "attribute list mapping error";
985 /* store the mapped Attributes for later usage, in
986 * the case that other overlays change op->ors_attrs */
987 roc->ros.mapped_attrs = an;
988 roc->cb.sc_response = rwm_swap_attrs;
990 op->o_callback = &roc->cb;
992 return SLAP_CB_CONTINUE;
1000 filter_free_x( op, f, 1 );
1003 if ( !BER_BVISNULL( &fstr ) ) {
1004 op->o_tmpfree( fstr.bv_val, op->o_tmpmemctx );
1007 rwm_op_rollback( op, rs, &roc->ros );
1008 op->oq_search = roc->ros.oq_search;
1009 op->o_tmpfree( roc, op->o_tmpmemctx );
1011 op->o_bd->bd_info = (BackendInfo *)on->on_info;
1012 send_ldap_error( op, rs, rc, text );
1019 rwm_exop_passwd( Operation *op, SlapReply *rs )
1021 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
1025 struct berval id = BER_BVNULL,
1028 BerElement *ber = NULL;
1030 if ( !BER_BVISNULL( &op->o_req_ndn ) ) {
1031 return LDAP_SUCCESS;
1034 if ( !SLAP_ISGLOBALOVERLAY( op->o_bd ) ) {
1035 rs->sr_err = LDAP_OTHER;
1039 rs->sr_err = slap_passwd_parse( op->ore_reqdata, &id,
1040 &pwold, &pwnew, &rs->sr_text );
1041 if ( rs->sr_err != LDAP_SUCCESS ) {
1045 if ( !BER_BVISNULL( &id ) ) {
1046 char idNul = id.bv_val[id.bv_len];
1047 id.bv_val[id.bv_len] = '\0';
1048 rs->sr_err = dnPrettyNormal( NULL, &id, &op->o_req_dn,
1049 &op->o_req_ndn, op->o_tmpmemctx );
1050 id.bv_val[id.bv_len] = idNul;
1051 if ( rs->sr_err != LDAP_SUCCESS ) {
1052 rs->sr_text = "Invalid DN";
1057 ber_dupbv_x( &op->o_req_dn, &op->o_dn, op->o_tmpmemctx );
1058 ber_dupbv_x( &op->o_req_ndn, &op->o_ndn, op->o_tmpmemctx );
1061 roc = rwm_callback_get( op, rs );
1063 rc = rwm_op_dn_massage( op, rs, "extendedDN", &roc->ros );
1064 if ( rc != LDAP_SUCCESS ) {
1065 op->o_bd->bd_info = (BackendInfo *)on->on_info;
1066 send_ldap_error( op, rs, rc, "extendedDN massage error" );
1070 ber = ber_alloc_t( LBER_USE_DER );
1072 rs->sr_err = LDAP_OTHER;
1073 rs->sr_text = "No memory";
1076 ber_printf( ber, "{" );
1077 if ( !BER_BVISNULL( &id )) {
1078 ber_printf( ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_ID,
1081 if ( !BER_BVISNULL( &pwold )) {
1082 ber_printf( ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_OLD, &pwold );
1084 if ( !BER_BVISNULL( &pwnew )) {
1085 ber_printf( ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_NEW, &pwnew );
1087 ber_printf( ber, "N}" );
1088 ber_flatten( ber, &op->ore_reqdata );
1091 op->o_callback = &roc->cb;
1093 return SLAP_CB_CONTINUE;
1096 static struct exop {
1098 BI_op_extended *extended;
1100 { BER_BVC(LDAP_EXOP_MODIFY_PASSWD), rwm_exop_passwd },
1101 { BER_BVNULL, NULL }
1105 rwm_extended( Operation *op, SlapReply *rs )
1107 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
1113 for ( i = 0; exop_table[i].extended != NULL; i++ ) {
1114 if ( bvmatch( &exop_table[i].oid, &op->oq_extended.rs_reqoid ) )
1116 rc = exop_table[i].extended( op, rs );
1121 case SLAP_CB_CONTINUE:
1126 send_ldap_result( op, rs );
1133 roc = rwm_callback_get( op, rs );
1135 rc = rwm_op_dn_massage( op, rs, "extendedDN", &roc->ros );
1136 if ( rc != LDAP_SUCCESS ) {
1137 op->o_bd->bd_info = (BackendInfo *)on->on_info;
1138 send_ldap_error( op, rs, rc, "extendedDN massage error" );
1142 /* TODO: rewrite/map extended data ? ... */
1143 op->o_callback = &roc->cb;
1145 return SLAP_CB_CONTINUE;
1149 rwm_matched( Operation *op, SlapReply *rs )
1151 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
1152 struct ldaprwmap *rwmap =
1153 (struct ldaprwmap *)on->on_bi.bi_private;
1155 struct berval dn, mdn;
1159 if ( rs->sr_matched == NULL ) {
1160 return SLAP_CB_CONTINUE;
1164 dc.conn = op->o_conn;
1166 dc.ctx = "matchedDN";
1167 ber_str2bv( rs->sr_matched, 0, 0, &dn );
1169 rc = rwm_dn_massage_pretty( &dc, &dn, &mdn );
1170 if ( rc != LDAP_SUCCESS ) {
1172 rs->sr_text = "Rewrite error";
1176 if ( mdn.bv_val != dn.bv_val ) {
1177 if ( rs->sr_flags & REP_MATCHED_MUSTBEFREED ) {
1178 ch_free( (void *)rs->sr_matched );
1181 rs->sr_flags |= REP_MATCHED_MUSTBEFREED;
1183 rs->sr_matched = mdn.bv_val;
1186 return SLAP_CB_CONTINUE;
1190 rwm_attrs( Operation *op, SlapReply *rs, Attribute** a_first, int stripEntryDN )
1192 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
1193 struct ldaprwmap *rwmap =
1194 (struct ldaprwmap *)on->on_bi.bi_private;
1200 int check_duplicate_attrs = 0;
1203 * Rewrite the dn attrs, if needed
1206 dc.conn = op->o_conn;
1209 /* FIXME: the entries are in the remote mapping form;
1210 * so we need to select those attributes we are willing
1211 * to return, and remap them accordingly */
1213 /* FIXME: in principle, one could map an attribute
1214 * on top of another, which already exists.
1215 * As such, in the end there might exist more than
1216 * one instance of an attribute.
1217 * We should at least check if this occurs, and issue
1218 * an error (because multiple instances of attrs in
1219 * response are not valid), or merge the values (what
1220 * about duplicate values?) */
1221 isupdate = be_shadow_update( op );
1222 for ( ap = a_first; *ap; ) {
1223 struct ldapmapping *mapping = NULL;
1228 if ( ( rwmap->rwm_flags & RWM_F_DROP_UNREQUESTED_ATTRS ) &&
1229 op->ors_attrs != NULL &&
1230 !SLAP_USERATTRS( rs->sr_attr_flags ) &&
1231 !ad_inlist( (*ap)->a_desc, op->ors_attrs ) )
1236 drop_missing = rwm_mapping( &rwmap->rwm_at,
1237 &(*ap)->a_desc->ad_cname, &mapping, RWM_REMAP );
1238 if ( drop_missing || ( mapping != NULL && BER_BVISEMPTY( &mapping->m_dst ) ) )
1242 if ( mapping != NULL ) {
1243 assert( mapping->m_dst_ad != NULL );
1245 /* try to normalize mapped Attributes if the original
1246 * AttributeType was not normalized */
1247 if ( (!(*ap)->a_desc->ad_type->sat_equality ||
1248 !(*ap)->a_desc->ad_type->sat_equality->smr_normalize) &&
1249 mapping->m_dst_ad->ad_type->sat_equality &&
1250 mapping->m_dst_ad->ad_type->sat_equality->smr_normalize )
1252 if ((rwmap->rwm_flags & RWM_F_NORMALIZE_MAPPED_ATTRS))
1256 last = (*ap)->a_numvals;
1259 (*ap)->a_nvals = ch_malloc( (last+1) * sizeof(struct berval) );
1261 for ( i = 0; !BER_BVISNULL( &(*ap)->a_vals[i]); i++ ) {
1264 * check that each value is valid per syntax
1265 * and pretty if appropriate
1267 rc = mapping->m_dst_ad->ad_type->sat_equality->smr_normalize(
1268 SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
1269 mapping->m_dst_ad->ad_type->sat_syntax,
1270 mapping->m_dst_ad->ad_type->sat_equality,
1271 &(*ap)->a_vals[i], &(*ap)->a_nvals[i],
1274 if ( rc != LDAP_SUCCESS ) {
1275 BER_BVZERO( &(*ap)->a_nvals[i] );
1278 BER_BVZERO( &(*ap)->a_nvals[i] );
1282 assert( (*ap)->a_nvals == (*ap)->a_vals );
1283 (*ap)->a_nvals = NULL;
1284 ber_bvarray_dup_x( &(*ap)->a_nvals, (*ap)->a_vals, NULL );
1288 /* rewrite the attribute description */
1289 (*ap)->a_desc = mapping->m_dst_ad;
1291 /* will need to check for duplicate attrs */
1292 check_duplicate_attrs++;
1295 if ( (*ap)->a_desc == slap_schema.si_ad_entryDN ) {
1296 if ( stripEntryDN ) {
1297 /* will be generated by frontend */
1301 } else if ( !isupdate
1303 && (*ap)->a_desc->ad_type->sat_no_user_mod
1304 && (*ap)->a_desc->ad_type != slap_schema.si_at_undefined )
1309 if ( last == -1 ) { /* not yet counted */
1310 last = (*ap)->a_numvals;
1314 /* empty? leave it in place because of attrsonly and vlv */
1319 if ( (*ap)->a_desc == slap_schema.si_ad_objectClass
1320 || (*ap)->a_desc == slap_schema.si_ad_structuralObjectClass )
1324 for ( bv = (*ap)->a_vals; !BER_BVISNULL( bv ); bv++ ) {
1325 struct berval mapped;
1327 rwm_map( &rwmap->rwm_oc, &bv[0], &mapped, RWM_REMAP );
1328 if ( BER_BVISNULL( &mapped ) || BER_BVISEMPTY( &mapped ) ) {
1330 ch_free( bv[0].bv_val );
1331 BER_BVZERO( &bv[0] );
1332 if ( &(*ap)->a_vals[last] > &bv[0] ) {
1333 bv[0] = (*ap)->a_vals[last];
1334 BER_BVZERO( &(*ap)->a_vals[last] );
1339 } else if ( mapped.bv_val != bv[0].bv_val
1340 && ber_bvstrcasecmp( &mapped, &bv[0] ) != 0 )
1344 for ( i = 0; !BER_BVISNULL( &(*ap)->a_vals[ i ] ); i++ ) {
1345 if ( &(*ap)->a_vals[ i ] == bv ) {
1349 if ( ber_bvstrcasecmp( &mapped, &(*ap)->a_vals[ i ] ) == 0 ) {
1354 if ( !BER_BVISNULL( &(*ap)->a_vals[ i ] ) ) {
1359 * FIXME: after LBER_FREEing
1360 * the value is replaced by
1361 * ch_alloc'ed memory
1363 ber_bvreplace( &bv[0], &mapped );
1365 /* FIXME: will need to check
1366 * if the structuralObjectClass
1372 * It is necessary to try to rewrite attributes with
1373 * dn syntax because they might be used in ACLs as
1374 * members of groups; since ACLs are applied to the
1375 * rewritten stuff, no dn-based subject clause could
1376 * be used at the ldap backend side (see
1377 * http://www.OpenLDAP.org/faq/data/cache/452.html)
1378 * The problem can be overcome by moving the dn-based
1379 * ACLs to the target directory server, and letting
1380 * everything pass thru the ldap backend. */
1381 /* FIXME: handle distinguishedName-like syntaxes, like
1382 * nameAndOptionalUID */
1383 } else if ( (*ap)->a_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName
1384 || ( mapping != NULL && mapping->m_src_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) )
1386 dc.ctx = "searchAttrDN";
1387 rc = rwm_dnattr_result_rewrite( &dc, (*ap)->a_vals, (*ap)->a_nvals );
1388 if ( rc != LDAP_SUCCESS ) {
1392 } else if ( (*ap)->a_desc == slap_schema.si_ad_ref ) {
1393 dc.ctx = "searchAttrDN";
1394 rc = rwm_referral_result_rewrite( &dc, (*ap)->a_vals );
1395 if ( rc != LDAP_SUCCESS ) {
1402 ap = &(*ap)->a_next;
1407 *ap = (*ap)->a_next;
1412 /* only check if some mapping occurred */
1413 if ( check_duplicate_attrs ) {
1414 for ( ap = a_first; *ap != NULL; ap = &(*ap)->a_next ) {
1417 for ( tap = &(*ap)->a_next; *tap != NULL; ) {
1418 if ( (*tap)->a_desc == (*ap)->a_desc ) {
1420 Modification mod = { 0 };
1421 const char *text = NULL;
1422 char textbuf[ SLAP_TEXT_BUFLEN ];
1423 Attribute *next = (*tap)->a_next;
1425 BER_BVSTR( &e.e_name, "" );
1426 BER_BVSTR( &e.e_nname, "" );
1428 mod.sm_op = LDAP_MOD_ADD;
1429 mod.sm_desc = (*ap)->a_desc;
1430 mod.sm_type = mod.sm_desc->ad_cname;
1431 mod.sm_numvals = (*tap)->a_numvals;
1432 mod.sm_values = (*tap)->a_vals;
1433 if ( (*tap)->a_nvals != (*tap)->a_vals ) {
1434 mod.sm_nvalues = (*tap)->a_nvals;
1437 (void)modify_add_values( &e, &mod,
1439 &text, textbuf, sizeof( textbuf ) );
1441 /* should not insert new attrs! */
1442 assert( e.e_attrs == *ap );
1448 tap = &(*tap)->a_next;
1458 rwm_send_entry( Operation *op, SlapReply *rs )
1460 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
1461 struct ldaprwmap *rwmap =
1462 (struct ldaprwmap *)on->on_bi.bi_private;
1466 struct berval dn = BER_BVNULL,
1471 assert( rs->sr_entry != NULL );
1474 * Rewrite the dn of the result, if needed
1477 dc.conn = op->o_conn;
1479 dc.ctx = "searchEntryDN";
1482 flags = rs->sr_flags;
1483 if ( !( rs->sr_flags & REP_ENTRY_MODIFIABLE ) ) {
1484 /* FIXME: all we need to duplicate are:
1487 * - attributes that are requested
1488 * - no values if attrsonly is set
1493 rc = LDAP_NO_MEMORY;
1497 flags &= ~REP_ENTRY_MUSTRELEASE;
1498 flags |= ( REP_ENTRY_MODIFIABLE | REP_ENTRY_MUSTBEFREED );
1502 * Note: this may fail if the target host(s) schema differs
1503 * from the one known to the meta, and a DN with unknown
1504 * attributes is returned.
1508 rc = rwm_dn_massage_pretty_normalize( &dc, &e->e_name, &dn, &ndn );
1509 if ( rc != LDAP_SUCCESS ) {
1514 if ( e->e_name.bv_val != dn.bv_val ) {
1515 ch_free( e->e_name.bv_val );
1516 ch_free( e->e_nname.bv_val );
1522 /* TODO: map entry attribute types, objectclasses
1523 * and dn-valued attribute values */
1525 /* FIXME: the entries are in the remote mapping form;
1526 * so we need to select those attributes we are willing
1527 * to return, and remap them accordingly */
1528 (void)rwm_attrs( op, rs, &e->e_attrs, 1 );
1530 if ( rs->sr_flags & REP_ENTRY_MUSTRELEASE ) {
1531 /* ITS#6423: REP_ENTRY_MUSTRELEASE incompatible
1532 * with REP_ENTRY_MODIFIABLE */
1533 if ( rs->sr_entry == e ) {
1538 op->o_bd->bd_info = (BackendInfo *)on->on_info;
1539 be_entry_release_r( op, rs->sr_entry );
1540 op->o_bd->bd_info = (BackendInfo *)on;
1544 rs->sr_flags = flags;
1546 return SLAP_CB_CONTINUE;
1549 if ( e != NULL && e != rs->sr_entry ) {
1550 if ( e->e_name.bv_val == dn.bv_val ) {
1551 BER_BVZERO( &e->e_name );
1554 if ( e->e_nname.bv_val == ndn.bv_val ) {
1555 BER_BVZERO( &e->e_nname );
1561 if ( !BER_BVISNULL( &dn ) ) {
1562 ch_free( dn.bv_val );
1565 if ( !BER_BVISNULL( &ndn ) ) {
1566 ch_free( ndn.bv_val );
1573 rwm_operational( Operation *op, SlapReply *rs )
1575 /* FIXME: the entries are in the remote mapping form;
1576 * so we need to select those attributes we are willing
1577 * to return, and remap them accordingly */
1578 if ( rs->sr_operational_attrs ) {
1579 rwm_attrs( op, rs, &rs->sr_operational_attrs, 1 );
1582 return SLAP_CB_CONTINUE;
1586 /* don't use this; it cannot be reverted, and leaves op->o_req_dn
1587 * rewritten for subsequent operations; fine for plain suffixmassage,
1588 * but destroys everything else */
1590 rwm_chk_referrals( Operation *op, SlapReply *rs )
1592 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
1595 rc = rwm_op_dn_massage( op, rs, "referralCheckDN" );
1596 if ( rc != LDAP_SUCCESS ) {
1597 op->o_bd->bd_info = (BackendInfo *)on->on_info;
1598 send_ldap_error( op, rs, rc, "referralCheckDN massage error" );
1602 return SLAP_CB_CONTINUE;
1614 slap_overinst *on = (slap_overinst *) be->bd_info;
1615 struct ldaprwmap *rwmap =
1616 (struct ldaprwmap *)on->on_bi.bi_private;
1618 return rewrite_parse( rwmap->rwm_rw,
1619 fname, lineno, argc, argv );
1625 rwm_suffixmassage_config(
1632 slap_overinst *on = (slap_overinst *) be->bd_info;
1633 struct ldaprwmap *rwmap =
1634 (struct ldaprwmap *)on->on_bi.bi_private;
1636 struct berval bvnc, nvnc, pvnc, brnc, nrnc, prnc;
1643 * suffixmassage [<suffix>] <massaged suffix>
1645 * the [<suffix>] field must be defined as a valid suffix
1646 * for the current database;
1647 * the <massaged suffix> shouldn't have already been
1648 * defined as a valid suffix for the current server
1651 if ( be->be_suffix == NULL ) {
1652 Debug( LDAP_DEBUG_ANY, "%s: line %d: "
1653 " \"suffixMassage [<suffix>]"
1654 " <massaged suffix>\" without "
1655 "<suffix> part requires database "
1656 "suffix be defined first.\n",
1660 bvnc = be->be_suffix[ 0 ];
1663 } else if ( argc == 3 ) {
1664 ber_str2bv( argv[ 1 ], 0, 0, &bvnc );
1668 Debug( LDAP_DEBUG_ANY, "%s: line %d: syntax is"
1669 " \"suffixMassage [<suffix>]"
1670 " <massaged suffix>\"\n",
1675 if ( dnPrettyNormal( NULL, &bvnc, &pvnc, &nvnc, NULL ) != LDAP_SUCCESS ) {
1676 Debug( LDAP_DEBUG_ANY, "%s: line %d: suffix DN %s is invalid\n",
1677 fname, lineno, bvnc.bv_val );
1681 ber_str2bv( argv[ massaged ], 0, 0, &brnc );
1682 if ( dnPrettyNormal( NULL, &brnc, &prnc, &nrnc, NULL ) != LDAP_SUCCESS ) {
1683 Debug( LDAP_DEBUG_ANY, "%s: line %d: suffix DN %s is invalid\n",
1684 fname, lineno, brnc.bv_val );
1685 free( nvnc.bv_val );
1686 free( pvnc.bv_val );
1691 * The suffix massaging is emulated
1692 * by means of the rewrite capabilities
1694 rc = rwm_suffix_massage_config( rwmap->rwm_rw,
1695 &pvnc, &nvnc, &prnc, &nrnc );
1696 free( nvnc.bv_val );
1697 free( pvnc.bv_val );
1698 free( nrnc.bv_val );
1699 free( prnc.bv_val );
1712 slap_overinst *on = (slap_overinst *) be->bd_info;
1713 struct ldaprwmap *rwmap =
1714 (struct ldaprwmap *)on->on_bi.bi_private;
1716 /* objectclass/attribute mapping */
1717 return rwm_map_config( &rwmap->rwm_oc,
1719 fname, lineno, argc, argv );
1723 rwm_response( Operation *op, SlapReply *rs )
1725 slap_overinst *on = (slap_overinst *)op->o_bd->bd_info;
1726 struct ldaprwmap *rwmap =
1727 (struct ldaprwmap *)on->on_bi.bi_private;
1731 if ( op->o_tag == LDAP_REQ_SEARCH && rs->sr_type == REP_SEARCH ) {
1732 return rwm_send_entry( op, rs );
1735 switch( op->o_tag ) {
1736 case LDAP_REQ_SEARCH:
1739 case LDAP_REQ_DELETE:
1740 case LDAP_REQ_MODRDN:
1741 case LDAP_REQ_MODIFY:
1742 case LDAP_REQ_COMPARE:
1743 case LDAP_REQ_EXTENDED:
1748 * Rewrite the dn of the referrals, if needed
1751 dc.conn = op->o_conn;
1753 dc.ctx = "referralDN";
1754 rc = rwm_referral_result_rewrite( &dc, rs->sr_ref );
1755 if ( rc != LDAP_SUCCESS ) {
1760 rc = rwm_matched( op, rs );
1764 rc = SLAP_CB_CONTINUE;
1779 slap_overinst *on = (slap_overinst *) be->bd_info;
1780 struct ldaprwmap *rwmap =
1781 (struct ldaprwmap *)on->on_bi.bi_private;
1786 if ( strncasecmp( argv[ 0 ], "rwm-", STRLENOF( "rwm-" ) ) == 0 ) {
1788 argv[ 0 ] = &argv0[ STRLENOF( "rwm-" ) ];
1791 if ( strncasecmp( argv[0], "rewrite", STRLENOF("rewrite") ) == 0 ) {
1792 rc = rwm_rw_config( be, fname, lineno, argc, argv );
1794 } else if ( strcasecmp( argv[0], "map" ) == 0 ) {
1795 rc = rwm_m_config( be, fname, lineno, argc, argv );
1797 } else if ( strcasecmp( argv[0], "suffixmassage" ) == 0 ) {
1798 rc = rwm_suffixmassage_config( be, fname, lineno, argc, argv );
1800 } else if ( strcasecmp( argv[0], "t-f-support" ) == 0 ) {
1802 Debug( LDAP_DEBUG_ANY,
1803 "%s: line %d: \"t-f-support {no|yes|discover}\" needs 1 argument.\n",
1808 if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
1809 rwmap->rwm_flags &= ~(RWM_F_SUPPORT_T_F_MASK2);
1811 } else if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
1812 rwmap->rwm_flags |= RWM_F_SUPPORT_T_F;
1814 /* TODO: not implemented yet */
1815 } else if ( strcasecmp( argv[ 1 ], "discover" ) == 0 ) {
1816 Debug( LDAP_DEBUG_ANY,
1817 "%s: line %d: \"discover\" not supported yet "
1818 "in \"t-f-support {no|yes|discover}\".\n",
1822 rwmap->rwm_flags |= RWM_F_SUPPORT_T_F_DISCOVER;
1826 Debug( LDAP_DEBUG_ANY,
1827 "%s: line %d: unknown value \"%s\" for \"t-f-support {no|yes|discover}\".\n",
1828 fname, lineno, argv[ 1 ] );
1832 } else if ( strcasecmp( argv[0], "normalize-mapped-attrs" ) == 0 ) {
1834 Debug( LDAP_DEBUG_ANY,
1835 "%s: line %d: \"normalize-mapped-attrs {no|yes}\" needs 1 argument.\n",
1840 if ( strcasecmp( argv[ 1 ], "no" ) == 0 ) {
1841 rwmap->rwm_flags &= ~(RWM_F_NORMALIZE_MAPPED_ATTRS);
1843 } else if ( strcasecmp( argv[ 1 ], "yes" ) == 0 ) {
1844 rwmap->rwm_flags |= RWM_F_NORMALIZE_MAPPED_ATTRS;
1848 rc = SLAP_CONF_UNKNOWN;
1859 * dynamic configuration...
1869 RWM_CF_NORMALIZE_MAPPED,
1870 RWM_CF_DROP_UNREQUESTED,
1875 static slap_verbmasks t_f_mode[] = {
1876 { BER_BVC( "true" ), RWM_F_SUPPORT_T_F },
1877 { BER_BVC( "yes" ), RWM_F_SUPPORT_T_F },
1878 { BER_BVC( "discover" ), RWM_F_SUPPORT_T_F_DISCOVER },
1879 { BER_BVC( "false" ), RWM_F_NONE },
1880 { BER_BVC( "no" ), RWM_F_NONE },
1884 static ConfigDriver rwm_cf_gen;
1886 static ConfigTable rwmcfg[] = {
1887 { "rwm-rewrite", "rewrite",
1888 2, 0, STRLENOF("rwm-rewrite"),
1889 ARG_MAGIC|RWM_CF_REWRITE, rwm_cf_gen,
1890 "( OLcfgOvAt:16.1 NAME 'olcRwmRewrite' "
1891 "DESC 'Rewrites strings' "
1892 "EQUALITY caseIgnoreMatch "
1893 "SYNTAX OMsDirectoryString "
1894 "X-ORDERED 'VALUES' )",
1897 { "rwm-suffixmassage", "[virtual]> <real",
1898 2, 3, 0, ARG_MAGIC|RWM_CF_REWRITE, rwm_cf_gen,
1901 { "rwm-t-f-support", "true|false|discover",
1902 2, 2, 0, ARG_MAGIC|RWM_CF_T_F_SUPPORT, rwm_cf_gen,
1903 "( OLcfgOvAt:16.2 NAME 'olcRwmTFSupport' "
1904 "DESC 'Absolute filters support' "
1905 "SYNTAX OMsDirectoryString "
1909 { "rwm-map", "{objectClass|attribute}",
1910 2, 4, 0, ARG_MAGIC|RWM_CF_MAP, rwm_cf_gen,
1911 "( OLcfgOvAt:16.3 NAME 'olcRwmMap' "
1912 "DESC 'maps attributes/objectClasses' "
1913 "EQUALITY caseIgnoreMatch "
1914 "SYNTAX OMsDirectoryString "
1915 "X-ORDERED 'VALUES' )",
1918 { "rwm-normalize-mapped-attrs", "true|false",
1919 2, 2, 0, ARG_MAGIC|ARG_ON_OFF|RWM_CF_NORMALIZE_MAPPED, rwm_cf_gen,
1920 "( OLcfgOvAt:16.4 NAME 'olcRwmNormalizeMapped' "
1921 "DESC 'Normalize mapped attributes/objectClasses' "
1922 "SYNTAX OMsBoolean "
1926 { "rwm-drop-unrequested-attrs", "true|false",
1927 2, 2, 0, ARG_MAGIC|ARG_ON_OFF|RWM_CF_DROP_UNREQUESTED, rwm_cf_gen,
1928 "( OLcfgOvAt:16.5 NAME 'olcRwmDropUnrequested' "
1929 "DESC 'Drop unrequested attributes' "
1930 "SYNTAX OMsBoolean "
1934 { NULL, NULL, 0, 0, 0, ARG_IGNORED }
1937 static ConfigOCs rwmocs[] = {
1938 { "( OLcfgOvOc:16.1 "
1939 "NAME 'olcRwmConfig' "
1940 "DESC 'Rewrite/remap configuration' "
1941 "SUP olcOverlayConfig "
1944 "olcRwmTFSupport $ "
1946 "olcRwmNormalizeMapped "
1948 Cft_Overlay, rwmcfg, NULL, NULL },
1953 slap_bv_x_ordered_unparse( BerVarray in, BerVarray *out )
1956 BerVarray bva = NULL;
1957 char ibuf[32], *ptr;
1960 assert( in != NULL );
1962 for ( i = 0; !BER_BVISNULL( &in[i] ); i++ )
1971 bva = ch_malloc( ( i + 1 ) * sizeof(struct berval) );
1972 BER_BVZERO( &bva[ 0 ] );
1974 for ( i = 0; !BER_BVISNULL( &in[i] ); i++ ) {
1975 idx.bv_len = snprintf( idx.bv_val, sizeof( ibuf ), "{%d}", i );
1976 if ( idx.bv_len >= sizeof( ibuf ) ) {
1977 ber_bvarray_free( bva );
1981 bva[i].bv_len = idx.bv_len + in[i].bv_len;
1982 bva[i].bv_val = ch_malloc( bva[i].bv_len + 1 );
1983 ptr = lutil_strcopy( bva[i].bv_val, ibuf );
1984 ptr = lutil_strcopy( ptr, in[i].bv_val );
1986 BER_BVZERO( &bva[ i + 1 ] );
2001 line = ldap_charray2str( argv, "\" \"" );
2002 if ( line != NULL ) {
2003 int len = strlen( argv[ 0 ] );
2005 ber_str2bv( line, 0, 0, &bv );
2006 AC_MEMCPY( &bv.bv_val[ len ], &bv.bv_val[ len + 1 ],
2007 bv.bv_len - ( len + 1 ) );
2008 bv.bv_val[ bv.bv_len - 1 ] = '"';
2011 ber_bvarray_add( bva, &bv );
2024 rwm_bva_rewrite_add(
2025 struct ldaprwmap *rwmap,
2029 return rwm_bva_add( &rwmap->rwm_bva_rewrite, idx, argv );
2034 struct ldaprwmap *rwmap,
2038 return rwm_bva_add( &rwmap->rwm_bva_map, idx, argv );
2042 rwm_info_init( struct rewrite_info ** rwm_rw )
2046 *rwm_rw = rewrite_info_init( REWRITE_MODE_USE_DEFAULT );
2047 if ( *rwm_rw == NULL ) {
2051 /* this rewriteContext by default must be null;
2052 * rules can be added if required */
2053 rargv[ 0 ] = "rewriteContext";
2054 rargv[ 1 ] = "searchFilter";
2056 rewrite_parse( *rwm_rw, "<suffix massage>", 1, 2, rargv );
2058 rargv[ 0 ] = "rewriteContext";
2059 rargv[ 1 ] = "default";
2061 rewrite_parse( *rwm_rw, "<suffix massage>", 2, 2, rargv );
2067 rwm_cf_gen( ConfigArgs *c )
2069 slap_overinst *on = (slap_overinst *)c->bi;
2070 struct ldaprwmap *rwmap =
2071 (struct ldaprwmap *)on->on_bi.bi_private;
2081 if ( c->op == SLAP_CONFIG_EMIT ) {
2082 struct berval bv = BER_BVNULL;
2084 switch ( c->type ) {
2085 case RWM_CF_REWRITE:
2086 if ( rwmap->rwm_bva_rewrite == NULL ) {
2090 slap_bv_x_ordered_unparse( rwmap->rwm_bva_rewrite, &c->rvalue_vals );
2091 if ( !c->rvalue_vals ) {
2097 case RWM_CF_T_F_SUPPORT:
2098 enum_to_verb( t_f_mode, (rwmap->rwm_flags & RWM_F_SUPPORT_T_F_MASK2), &bv );
2099 if ( BER_BVISNULL( &bv ) ) {
2100 /* there's something wrong... */
2105 value_add_one( &c->rvalue_vals, &bv );
2110 if ( rwmap->rwm_bva_map == NULL ) {
2114 slap_bv_x_ordered_unparse( rwmap->rwm_bva_map, &c->rvalue_vals );
2115 if ( !c->rvalue_vals ) {
2121 case RWM_CF_NORMALIZE_MAPPED:
2122 c->value_int = ( rwmap->rwm_flags & RWM_F_NORMALIZE_MAPPED_ATTRS );
2125 case RWM_CF_DROP_UNREQUESTED:
2126 c->value_int = ( rwmap->rwm_flags & RWM_F_DROP_UNREQUESTED_ATTRS );
2136 } else if ( c->op == LDAP_MOD_DELETE ) {
2137 switch ( c->type ) {
2138 case RWM_CF_REWRITE:
2139 if ( c->valx >= 0 ) {
2142 for ( i = 0; !BER_BVISNULL( &rwmap->rwm_bva_rewrite[ i ] ); i++ )
2145 if ( c->valx >= i ) {
2150 ber_memfree( rwmap->rwm_bva_rewrite[ c->valx ].bv_val );
2151 for ( i = c->valx; !BER_BVISNULL( &rwmap->rwm_bva_rewrite[ i + 1 ] ); i++ )
2153 rwmap->rwm_bva_rewrite[ i ] = rwmap->rwm_bva_rewrite[ i + 1 ];
2155 BER_BVZERO( &rwmap->rwm_bva_rewrite[ i ] );
2157 rewrite_info_delete( &rwmap->rwm_rw );
2158 assert( rwmap->rwm_rw == NULL );
2160 rc = rwm_info_init( &rwmap->rwm_rw );
2162 for ( i = 0; !BER_BVISNULL( &rwmap->rwm_bva_rewrite[ i ] ); i++ )
2164 ConfigArgs ca = { 0 };
2166 ca.line = rwmap->rwm_bva_rewrite[ i ].bv_val;
2168 config_fp_parse_line( &ca );
2170 if ( strcasecmp( ca.argv[ 0 ], "suffixmassage" ) == 0 ) {
2171 rc = rwm_suffixmassage_config( &db, c->fname, c->lineno,
2175 rc = rwm_rw_config( &db, c->fname, c->lineno,
2179 ch_free( ca.tline );
2185 } else if ( rwmap->rwm_rw != NULL ) {
2186 rewrite_info_delete( &rwmap->rwm_rw );
2187 assert( rwmap->rwm_rw == NULL );
2189 ber_bvarray_free( rwmap->rwm_bva_rewrite );
2190 rwmap->rwm_bva_rewrite = NULL;
2192 rc = rwm_info_init( &rwmap->rwm_rw );
2196 case RWM_CF_T_F_SUPPORT:
2197 rwmap->rwm_flags &= ~RWM_F_SUPPORT_T_F_MASK2;
2201 if ( c->valx >= 0 ) {
2202 struct ldapmap rwm_oc = rwmap->rwm_oc;
2203 struct ldapmap rwm_at = rwmap->rwm_at;
2207 if ( rwmap->rwm_bva_map ) {
2208 for ( ; !BER_BVISNULL( &rwmap->rwm_bva_map[ cnt ] ); cnt++ )
2212 if ( c->valx >= cnt ) {
2217 memset( &rwmap->rwm_oc, 0, sizeof( rwmap->rwm_oc ) );
2218 memset( &rwmap->rwm_at, 0, sizeof( rwmap->rwm_at ) );
2220 /* re-parse all mappings except the one
2221 * that needs to be eliminated */
2223 for ( cnt = 0; !BER_BVISNULL( &rwmap->rwm_bva_map[ cnt ] ); cnt++ ) {
2224 ConfigArgs ca = { 0 };
2226 if ( cnt == c->valx ) {
2230 ca.line = rwmap->rwm_bva_map[ cnt ].bv_val;
2232 config_fp_parse_line( &ca );
2234 argv[1] = ca.argv[0];
2235 argv[2] = ca.argv[1];
2236 argv[3] = ca.argv[2];
2237 argv[4] = ca.argv[3];
2239 rc = rwm_m_config( &db, c->fname, c->lineno, ca.argc + 1, argv );
2241 ch_free( ca.tline );
2244 /* in case of failure, restore
2245 * the existing mapping */
2247 avl_free( rwmap->rwm_oc.remap, rwm_mapping_dst_free );
2248 avl_free( rwmap->rwm_oc.map, rwm_mapping_free );
2249 avl_free( rwmap->rwm_at.remap, rwm_mapping_dst_free );
2250 avl_free( rwmap->rwm_at.map, rwm_mapping_free );
2251 rwmap->rwm_oc = rwm_oc;
2252 rwmap->rwm_at = rwm_at;
2257 /* in case of success, destroy the old mapping
2258 * and eliminate the deleted one */
2260 avl_free( rwm_oc.remap, rwm_mapping_dst_free );
2261 avl_free( rwm_oc.map, rwm_mapping_free );
2262 avl_free( rwm_at.remap, rwm_mapping_dst_free );
2263 avl_free( rwm_at.map, rwm_mapping_free );
2265 ber_memfree( rwmap->rwm_bva_map[ c->valx ].bv_val );
2266 for ( cnt = c->valx; !BER_BVISNULL( &rwmap->rwm_bva_map[ cnt ] ); cnt++ ) {
2267 rwmap->rwm_bva_map[ cnt ] = rwmap->rwm_bva_map[ cnt + 1 ];
2272 avl_free( rwmap->rwm_oc.remap, rwm_mapping_dst_free );
2273 avl_free( rwmap->rwm_oc.map, rwm_mapping_free );
2274 avl_free( rwmap->rwm_at.remap, rwm_mapping_dst_free );
2275 avl_free( rwmap->rwm_at.map, rwm_mapping_free );
2277 rwmap->rwm_oc.remap = NULL;
2278 rwmap->rwm_oc.map = NULL;
2279 rwmap->rwm_at.remap = NULL;
2280 rwmap->rwm_at.map = NULL;
2282 ber_bvarray_free( rwmap->rwm_bva_map );
2283 rwmap->rwm_bva_map = NULL;
2287 case RWM_CF_NORMALIZE_MAPPED:
2288 rwmap->rwm_flags &= ~RWM_F_NORMALIZE_MAPPED_ATTRS;
2291 case RWM_CF_DROP_UNREQUESTED:
2292 rwmap->rwm_flags &= ~RWM_F_DROP_UNREQUESTED_ATTRS;
2301 if ( strncasecmp( c->argv[ 0 ], "olcRwm", STRLENOF( "olcRwm" ) ) == 0 ) {
2305 switch ( c->type ) {
2306 case RWM_CF_REWRITE:
2307 if ( c->valx >= 0 ) {
2308 struct rewrite_info *rwm_rw = rwmap->rwm_rw;
2311 for ( last = 0; rwmap->rwm_bva_rewrite && !BER_BVISNULL( &rwmap->rwm_bva_rewrite[ last ] ); last++ )
2314 if ( c->valx > last ) {
2318 rwmap->rwm_rw = NULL;
2319 rc = rwm_info_init( &rwmap->rwm_rw );
2321 for ( i = 0; i < c->valx; i++ ) {
2322 ConfigArgs ca = { 0 };
2324 ca.line = rwmap->rwm_bva_rewrite[ i ].bv_val;
2326 config_fp_parse_line( &ca );
2328 argv0 = ca.argv[ 0 ];
2329 ca.argv[ 0 ] += STRLENOF( "rwm-" );
2331 if ( strcasecmp( ca.argv[ 0 ], "suffixmassage" ) == 0 ) {
2332 rc = rwm_suffixmassage_config( &db, c->fname, c->lineno,
2336 rc = rwm_rw_config( &db, c->fname, c->lineno,
2340 ca.argv[ 0 ] = argv0;
2342 ch_free( ca.tline );
2348 argv0 = c->argv[ idx0 ];
2349 if ( strncasecmp( argv0, "rwm-", STRLENOF( "rwm-" ) ) != 0 ) {
2352 c->argv[ idx0 ] += STRLENOF( "rwm-" );
2353 if ( strcasecmp( c->argv[ idx0 ], "suffixmassage" ) == 0 ) {
2354 rc = rwm_suffixmassage_config( &db, c->fname, c->lineno,
2355 c->argc - idx0, &c->argv[ idx0 ] );
2358 rc = rwm_rw_config( &db, c->fname, c->lineno,
2359 c->argc - idx0, &c->argv[ idx0 ] );
2361 c->argv[ idx0 ] = argv0;
2363 rewrite_info_delete( &rwmap->rwm_rw );
2364 assert( rwmap->rwm_rw == NULL );
2366 rwmap->rwm_rw = rwm_rw;
2370 for ( i = c->valx; rwmap->rwm_bva_rewrite && !BER_BVISNULL( &rwmap->rwm_bva_rewrite[ i ] ); i++ )
2372 ConfigArgs ca = { 0 };
2374 ca.line = rwmap->rwm_bva_rewrite[ i ].bv_val;
2376 config_fp_parse_line( &ca );
2378 argv0 = ca.argv[ 0 ];
2379 ca.argv[ 0 ] += STRLENOF( "rwm-" );
2381 if ( strcasecmp( ca.argv[ 0 ], "suffixmassage" ) == 0 ) {
2382 rc = rwm_suffixmassage_config( &db, c->fname, c->lineno,
2386 rc = rwm_rw_config( &db, c->fname, c->lineno,
2390 ca.argv[ 0 ] = argv0;
2392 ch_free( ca.tline );
2398 rwmap->rwm_bva_rewrite = ch_realloc( rwmap->rwm_bva_rewrite,
2399 ( last + 2 )*sizeof( struct berval ) );
2400 BER_BVZERO( &rwmap->rwm_bva_rewrite[last+1] );
2402 for ( i = last - 1; i >= c->valx; i-- )
2404 rwmap->rwm_bva_rewrite[ i + 1 ] = rwmap->rwm_bva_rewrite[ i ];
2407 rwm_bva_rewrite_add( rwmap, c->valx, &c->argv[ idx0 ] );
2409 rewrite_info_delete( &rwm_rw );
2410 assert( rwm_rw == NULL );
2415 argv0 = c->argv[ idx0 ];
2416 if ( strncasecmp( argv0, "rwm-", STRLENOF( "rwm-" ) ) != 0 ) {
2419 c->argv[ idx0 ] += STRLENOF( "rwm-" );
2420 if ( strcasecmp( c->argv[ idx0 ], "suffixmassage" ) == 0 ) {
2421 rc = rwm_suffixmassage_config( &db, c->fname, c->lineno,
2422 c->argc - idx0, &c->argv[ idx0 ] );
2425 rc = rwm_rw_config( &db, c->fname, c->lineno,
2426 c->argc - idx0, &c->argv[ idx0 ] );
2428 c->argv[ idx0 ] = argv0;
2433 rwm_bva_rewrite_add( rwmap, -1, &c->argv[ idx0 ] );
2437 case RWM_CF_T_F_SUPPORT:
2438 rc = verb_to_mask( c->argv[ 1 ], t_f_mode );
2439 if ( BER_BVISNULL( &t_f_mode[ rc ].word ) ) {
2443 rwmap->rwm_flags &= ~RWM_F_SUPPORT_T_F_MASK2;
2444 rwmap->rwm_flags |= t_f_mode[ rc ].mask;
2449 if ( c->valx >= 0 ) {
2450 struct ldapmap rwm_oc = rwmap->rwm_oc;
2451 struct ldapmap rwm_at = rwmap->rwm_at;
2455 if ( rwmap->rwm_bva_map ) {
2456 for ( ; !BER_BVISNULL( &rwmap->rwm_bva_map[ cnt ] ); cnt++ )
2460 if ( c->valx >= cnt ) {
2464 memset( &rwmap->rwm_oc, 0, sizeof( rwmap->rwm_oc ) );
2465 memset( &rwmap->rwm_at, 0, sizeof( rwmap->rwm_at ) );
2467 /* re-parse all mappings, including the one
2468 * that needs to be added */
2470 for ( cnt = 0; cnt < c->valx; cnt++ ) {
2471 ConfigArgs ca = { 0 };
2473 ca.line = rwmap->rwm_bva_map[ cnt ].bv_val;
2475 config_fp_parse_line( &ca );
2477 argv[1] = ca.argv[0];
2478 argv[2] = ca.argv[1];
2479 argv[3] = ca.argv[2];
2480 argv[4] = ca.argv[3];
2482 rc = rwm_m_config( &db, c->fname, c->lineno, ca.argc + 1, argv );
2484 ch_free( ca.tline );
2487 /* in case of failure, restore
2488 * the existing mapping */
2496 rc = rwm_m_config( &db, c->fname, c->lineno, c->argc, c->argv );
2502 if ( rwmap->rwm_bva_map ) {
2503 for ( ; !BER_BVISNULL( &rwmap->rwm_bva_map[ cnt ] ); cnt++ ) {
2504 ConfigArgs ca = { 0 };
2506 ca.line = rwmap->rwm_bva_map[ cnt ].bv_val;
2508 config_fp_parse_line( &ca );
2510 argv[1] = ca.argv[0];
2511 argv[2] = ca.argv[1];
2512 argv[3] = ca.argv[2];
2513 argv[4] = ca.argv[3];
2515 rc = rwm_m_config( &db, c->fname, c->lineno, ca.argc + 1, argv );
2517 ch_free( ca.tline );
2520 /* in case of failure, restore
2521 * the existing mapping */
2528 /* in case of success, destroy the old mapping
2529 * and add the new one */
2532 struct berval bv, *bvp = &bv;
2534 if ( rwm_bva_add( &bvp, 0, &c->argv[ idx0 ] ) ) {
2539 tmp = ber_memrealloc( rwmap->rwm_bva_map,
2540 sizeof( struct berval )*( cnt + 2 ) );
2541 if ( tmp == NULL ) {
2542 ber_memfree( bv.bv_val );
2546 rwmap->rwm_bva_map = tmp;
2547 BER_BVZERO( &rwmap->rwm_bva_map[ cnt + 1 ] );
2549 avl_free( rwm_oc.remap, rwm_mapping_dst_free );
2550 avl_free( rwm_oc.map, rwm_mapping_free );
2551 avl_free( rwm_at.remap, rwm_mapping_dst_free );
2552 avl_free( rwm_at.map, rwm_mapping_free );
2554 for ( ; cnt-- > c->valx; ) {
2555 rwmap->rwm_bva_map[ cnt + 1 ] = rwmap->rwm_bva_map[ cnt ];
2557 rwmap->rwm_bva_map[ c->valx ] = bv;
2561 avl_free( rwmap->rwm_oc.remap, rwm_mapping_dst_free );
2562 avl_free( rwmap->rwm_oc.map, rwm_mapping_free );
2563 avl_free( rwmap->rwm_at.remap, rwm_mapping_dst_free );
2564 avl_free( rwmap->rwm_at.map, rwm_mapping_free );
2565 rwmap->rwm_oc = rwm_oc;
2566 rwmap->rwm_at = rwm_at;
2572 argv0 = c->argv[ 0 ];
2573 c->argv[ 0 ] += STRLENOF( "rwm-" );
2574 rc = rwm_m_config( &db, c->fname, c->lineno, c->argc, c->argv );
2575 c->argv[ 0 ] = argv0;
2583 line = ldap_charray2str( &c->argv[ 1 ], " " );
2584 if ( line != NULL ) {
2585 ber_str2bv( line, 0, 0, &bv );
2586 ber_bvarray_add( &rwmap->rwm_bva_map, &bv );
2591 case RWM_CF_NORMALIZE_MAPPED:
2592 if ( c->value_int ) {
2593 rwmap->rwm_flags |= RWM_F_NORMALIZE_MAPPED_ATTRS;
2595 rwmap->rwm_flags &= ~RWM_F_NORMALIZE_MAPPED_ATTRS;
2599 case RWM_CF_DROP_UNREQUESTED:
2600 if ( c->value_int ) {
2601 rwmap->rwm_flags |= RWM_F_DROP_UNREQUESTED_ATTRS;
2603 rwmap->rwm_flags &= ~RWM_F_DROP_UNREQUESTED_ATTRS;
2620 slap_overinst *on = (slap_overinst *) be->bd_info;
2621 struct ldaprwmap *rwmap;
2624 rwmap = (struct ldaprwmap *)ch_calloc( 1, sizeof( struct ldaprwmap ) );
2627 rwmap->rwm_flags = RWM_F_DROP_UNREQUESTED_ATTRS;
2629 rc = rwm_info_init( &rwmap->rwm_rw );
2631 on->on_bi.bi_private = (void *)rwmap;
2634 (void)rwm_db_destroy( be, NULL );
2645 slap_overinst *on = (slap_overinst *) be->bd_info;
2648 if ( on->on_bi.bi_private ) {
2649 struct ldaprwmap *rwmap =
2650 (struct ldaprwmap *)on->on_bi.bi_private;
2652 if ( rwmap->rwm_rw ) {
2653 rewrite_info_delete( &rwmap->rwm_rw );
2654 if ( rwmap->rwm_bva_rewrite )
2655 ber_bvarray_free( rwmap->rwm_bva_rewrite );
2658 avl_free( rwmap->rwm_oc.remap, rwm_mapping_dst_free );
2659 avl_free( rwmap->rwm_oc.map, rwm_mapping_free );
2660 avl_free( rwmap->rwm_at.remap, rwm_mapping_dst_free );
2661 avl_free( rwmap->rwm_at.map, rwm_mapping_free );
2662 ber_bvarray_free( rwmap->rwm_bva_map );
2670 static slap_overinst rwm = { { NULL } };
2672 #if SLAPD_OVER_RWM == SLAPD_MOD_DYNAMIC
2674 #endif /* SLAPD_OVER_RWM == SLAPD_MOD_DYNAMIC */
2676 rwm_initialize( void )
2680 /* Make sure we don't exceed the bits reserved for userland */
2681 config_check_userland( RWM_CF_LAST );
2683 memset( &rwm, 0, sizeof( slap_overinst ) );
2685 rwm.on_bi.bi_type = "rwm";
2686 rwm.on_bi.bi_flags =
2687 SLAPO_BFLAG_SINGLE |
2690 rwm.on_bi.bi_db_init = rwm_db_init;
2691 rwm.on_bi.bi_db_config = rwm_db_config;
2692 rwm.on_bi.bi_db_destroy = rwm_db_destroy;
2694 rwm.on_bi.bi_op_bind = rwm_op_bind;
2695 rwm.on_bi.bi_op_search = rwm_op_search;
2696 rwm.on_bi.bi_op_compare = rwm_op_compare;
2697 rwm.on_bi.bi_op_modify = rwm_op_modify;
2698 rwm.on_bi.bi_op_modrdn = rwm_op_modrdn;
2699 rwm.on_bi.bi_op_add = rwm_op_add;
2700 rwm.on_bi.bi_op_delete = rwm_op_delete;
2701 rwm.on_bi.bi_op_unbind = rwm_op_unbind;
2702 rwm.on_bi.bi_extended = rwm_extended;
2704 rwm.on_bi.bi_entry_release_rw = rwm_entry_release_rw;
2705 rwm.on_bi.bi_entry_get_rw = rwm_entry_get_rw;
2708 rwm.on_bi.bi_operational = rwm_operational;
2709 rwm.on_bi.bi_chk_referrals = 0 /* rwm_chk_referrals */ ;
2711 rwm.on_bi.bi_connection_init = rwm_conn_init;
2712 rwm.on_bi.bi_connection_destroy = rwm_conn_destroy;
2714 rwm.on_response = rwm_response;
2716 rwm.on_bi.bi_cf_ocs = rwmocs;
2718 rc = config_register_schema( rwmcfg, rwmocs );
2723 return overlay_register( &rwm );
2726 #if SLAPD_OVER_RWM == SLAPD_MOD_DYNAMIC
2728 init_module( int argc, char *argv[] )
2730 return rwm_initialize();
2732 #endif /* SLAPD_OVER_RWM == SLAPD_MOD_DYNAMIC */
2734 #endif /* SLAPD_OVER_RWM */