📄 rwm.c
字号:
/* rwm.c - rewrite/remap operations *//* $OpenLDAP: pkg/ldap/servers/slapd/overlays/rwm.c,v 1.37.2.18 2007/01/05 09:47:11 ando Exp $ *//* This work is part of OpenLDAP Software <http://www.openldap.org/>. * * Copyright 2003-2007 The OpenLDAP Foundation. * Portions Copyright 2003 Pierangelo Masarati. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted only as authorized by the OpenLDAP * Public License. * * A copy of this license is available in the file LICENSE in the * top-level directory of the distribution or, alternatively, at * <http://www.OpenLDAP.org/license.html>. */#include "portable.h"#ifdef SLAPD_OVER_RWM#include <stdio.h>#include <ac/string.h>#include "slap.h"#include "rwm.h"typedef struct rwm_op_state { ber_tag_t r_tag; struct berval ro_dn; struct berval ro_ndn; struct berval r_dn; struct berval r_ndn; OpRequest o_request;} rwm_op_state;static intrwm_db_destroy( BackendDB *be );typedef struct rwm_op_cb { slap_callback cb; rwm_op_state ros;} rwm_op_cb;static intrwm_op_cleanup( Operation *op, SlapReply *rs ){ slap_callback *cb = op->o_callback; rwm_op_state *ros = cb->sc_private; if ( rs->sr_type == REP_RESULT || rs->sr_type == REP_EXTENDED || op->o_abandon || rs->sr_err == SLAPD_ABANDON ) { op->o_req_dn = ros->ro_dn; op->o_req_ndn = ros->ro_ndn; if ( !BER_BVISEMPTY( &ros->r_dn )) ch_free( ros->r_dn.bv_val ); if ( !BER_BVISEMPTY( &ros->r_ndn )) ch_free( ros->r_ndn.bv_val ); switch( ros->r_tag ) { case LDAP_REQ_COMPARE: if ( op->orc_ava->aa_value.bv_val != ros->orc_ava->aa_value.bv_val ) op->o_tmpfree( op->orc_ava->aa_value.bv_val, op->o_tmpmemctx ); op->orc_ava = ros->orc_ava; break; case LDAP_REQ_MODIFY: slap_mods_free( op->orm_modlist, 1 ); op->orm_modlist = ros->orm_modlist; break; case LDAP_REQ_MODRDN: if ( op->orr_newSup != ros->orr_newSup ) { ch_free( op->orr_newSup->bv_val ); ch_free( op->orr_nnewSup->bv_val ); op->o_tmpfree( op->orr_newSup, op->o_tmpmemctx ); op->o_tmpfree( op->orr_nnewSup, op->o_tmpmemctx ); op->orr_newSup = ros->orr_newSup; op->orr_nnewSup = ros->orr_nnewSup; } break; case LDAP_REQ_SEARCH: ch_free( op->ors_attrs ); filter_free_x( op, op->ors_filter ); ch_free( op->ors_filterstr.bv_val ); op->ors_attrs = ros->ors_attrs; op->ors_filter = ros->ors_filter; op->ors_filterstr = ros->ors_filterstr; break; case LDAP_REQ_EXTENDED: if ( op->ore_reqdata != ros->ore_reqdata ) { ber_bvfree( op->ore_reqdata ); op->ore_reqdata = ros->ore_reqdata; } break; default: break; } op->o_callback = op->o_callback->sc_next; op->o_tmpfree( cb, op->o_tmpmemctx ); } return SLAP_CB_CONTINUE;}static rwm_op_cb *rwm_callback_get( Operation *op, SlapReply *rs ){ rwm_op_cb *roc = NULL; roc = op->o_tmpalloc( sizeof( struct rwm_op_cb ), op->o_tmpmemctx ); roc->cb.sc_cleanup = rwm_op_cleanup; roc->cb.sc_response = NULL; roc->cb.sc_next = op->o_callback; roc->cb.sc_private = &roc->ros; roc->ros.r_tag = op->o_tag; roc->ros.ro_dn = op->o_req_dn; roc->ros.ro_ndn = op->o_req_ndn; roc->ros.o_request = op->o_request; BER_BVZERO( &roc->ros.r_dn ); BER_BVZERO( &roc->ros.r_ndn ); return roc;}static intrwm_op_dn_massage( Operation *op, SlapReply *rs, void *cookie, rwm_op_state *ros ){ slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; struct ldaprwmap *rwmap = (struct ldaprwmap *)on->on_bi.bi_private; struct berval dn = BER_BVNULL, ndn = BER_BVNULL; int rc = 0; dncookie dc; /* * Rewrite the dn if needed */ dc.rwmap = rwmap;#ifdef ENABLE_REWRITE dc.conn = op->o_conn; dc.rs = rs; dc.ctx = (char *)cookie;#else /* ! ENABLE_REWRITE */ dc.tofrom = ((int *)cookie)[0]; dc.normalized = 0;#endif /* ! ENABLE_REWRITE */ /* NOTE: in those cases where only the ndn is available, * and the caller sets op->o_req_dn = op->o_req_ndn, * only rewrite the op->o_req_ndn and use it as * op->o_req_dn as well */ ndn = op->o_req_ndn; if ( op->o_req_dn.bv_val != op->o_req_ndn.bv_val ) { dn = op->o_req_dn; rc = rwm_dn_massage_pretty_normalize( &dc, &op->o_req_dn, &dn, &ndn ); } else { rc = rwm_dn_massage_normalize( &dc, &op->o_req_ndn, &ndn ); } if ( rc != LDAP_SUCCESS ) { return rc; } if ( ( op->o_req_dn.bv_val != op->o_req_ndn.bv_val && dn.bv_val == op->o_req_dn.bv_val ) || ndn.bv_val == op->o_req_ndn.bv_val ) { return LDAP_SUCCESS; } if ( op->o_req_dn.bv_val != op->o_req_ndn.bv_val ) { op->o_req_dn = dn; ros->r_dn = dn; } else { op->o_req_dn = ndn; } ros->r_ndn = ndn; op->o_req_ndn = ndn; return LDAP_SUCCESS;}static intrwm_op_add( Operation *op, SlapReply *rs ){ slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; struct ldaprwmap *rwmap = (struct ldaprwmap *)on->on_bi.bi_private; int rc, i; Attribute **ap = NULL; char *olddn = op->o_req_dn.bv_val; int isupdate; rwm_op_cb *roc = rwm_callback_get( op, rs );#ifdef ENABLE_REWRITE rc = rwm_op_dn_massage( op, rs, "addDN", &roc->ros );#else /* ! ENABLE_REWRITE */ rc = 1; rc = rwm_op_dn_massage( op, rs, &rc, &roc->ros );#endif /* ! ENABLE_REWRITE */ if ( rc != LDAP_SUCCESS ) { op->o_bd->bd_info = (BackendInfo *)on->on_info; send_ldap_error( op, rs, rc, "addDN massage error" ); return -1; } if ( olddn != op->o_req_dn.bv_val ) { ber_bvreplace( &op->ora_e->e_name, &op->o_req_dn ); ber_bvreplace( &op->ora_e->e_nname, &op->o_req_ndn ); } /* Count number of attributes in entry */ isupdate = be_shadow_update( op ); for ( i = 0, ap = &op->oq_add.rs_e->e_attrs; *ap; ) { Attribute *a; if ( (*ap)->a_desc == slap_schema.si_ad_objectClass || (*ap)->a_desc == slap_schema.si_ad_structuralObjectClass ) { int j, last; for ( last = 0; !BER_BVISNULL( &(*ap)->a_vals[ last ] ); last++ ) /* count values */ ; last--; for ( j = 0; !BER_BVISNULL( &(*ap)->a_vals[ j ] ); j++ ) { struct ldapmapping *mapping = NULL; ( void )rwm_mapping( &rwmap->rwm_oc, &(*ap)->a_vals[ j ], &mapping, RWM_MAP ); if ( mapping == NULL ) { if ( rwmap->rwm_at.drop_missing ) { /* FIXME: we allow to remove objectClasses as well; * if the resulting entry is inconsistent, that's * the relayed database's business... */ ch_free( (*ap)->a_vals[ j ].bv_val ); if ( last > j ) { (*ap)->a_vals[ j ] = (*ap)->a_vals[ last ]; } BER_BVZERO( &(*ap)->a_vals[ last ] ); last--; j--; } } else { ch_free( (*ap)->a_vals[ j ].bv_val ); ber_dupbv( &(*ap)->a_vals[ j ], &mapping->m_dst ); } } } else if ( !isupdate && !get_manageDIT( op ) && (*ap)->a_desc->ad_type->sat_no_user_mod ) { goto next_attr; } else { struct ldapmapping *mapping = NULL; ( void )rwm_mapping( &rwmap->rwm_at, &(*ap)->a_desc->ad_cname, &mapping, RWM_MAP ); if ( mapping == NULL ) { if ( rwmap->rwm_at.drop_missing ) { goto cleanup_attr; } } if ( (*ap)->a_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName || ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) ) { /* * FIXME: rewrite could fail; in this case * the operation should give up, right? */#ifdef ENABLE_REWRITE rc = rwm_dnattr_rewrite( op, rs, "addAttrDN", (*ap)->a_vals, (*ap)->a_nvals ? &(*ap)->a_nvals : NULL );#else /* ! ENABLE_REWRITE */ rc = 1; rc = rwm_dnattr_rewrite( op, rs, &rc, (*ap)->a_vals, (*ap)->a_nvals ? &(*ap)->a_nvals : NULL );#endif /* ! ENABLE_REWRITE */ if ( rc ) { goto cleanup_attr; } } else if ( (*ap)->a_desc == slap_schema.si_ad_ref ) {#ifdef ENABLE_REWRITE rc = rwm_referral_rewrite( op, rs, "referralAttrDN", (*ap)->a_vals, (*ap)->a_nvals ? &(*ap)->a_nvals : NULL );#else /* ! ENABLE_REWRITE */ rc = 1; rc = rwm_referral_rewrite( op, rs, &rc, (*ap)->a_vals, (*ap)->a_nvals ? &(*ap)->a_nvals : NULL );#endif /* ! ENABLE_REWRITE */ if ( rc != LDAP_SUCCESS ) { goto cleanup_attr; } } if ( mapping != NULL ) { assert( mapping->m_dst_ad != NULL ); (*ap)->a_desc = mapping->m_dst_ad; } }next_attr:; ap = &(*ap)->a_next; continue;cleanup_attr:; /* FIXME: leaking attribute/values? */ a = *ap; *ap = (*ap)->a_next; attr_free( a ); } op->o_callback = &roc->cb; return SLAP_CB_CONTINUE;}#ifdef ENABLE_REWRITEstatic intrwm_conn_init( BackendDB *be, Connection *conn ){ slap_overinst *on = (slap_overinst *) be->bd_info; struct ldaprwmap *rwmap = (struct ldaprwmap *)on->on_bi.bi_private; ( void )rewrite_session_init( rwmap->rwm_rw, conn ); return SLAP_CB_CONTINUE;}static intrwm_conn_destroy( BackendDB *be, Connection *conn ){ slap_overinst *on = (slap_overinst *) be->bd_info; struct ldaprwmap *rwmap = (struct ldaprwmap *)on->on_bi.bi_private; ( void )rewrite_session_delete( rwmap->rwm_rw, conn ); return SLAP_CB_CONTINUE;}#endif /* ENABLE_REWRITE */static intrwm_op_bind( Operation *op, SlapReply *rs ){ slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; int rc; rwm_op_cb *roc = rwm_callback_get( op, rs );#ifdef ENABLE_REWRITE rc = rwm_op_dn_massage( op, rs, "bindDN", &roc->ros );#else /* ! ENABLE_REWRITE */ rc = 1; rc = rwm_op_dn_massage( op, rs, &rc, &roc->ros );#endif /* ! ENABLE_REWRITE */ if ( rc != LDAP_SUCCESS ) { op->o_bd->bd_info = (BackendInfo *)on->on_info; send_ldap_error( op, rs, rc, "bindDN massage error" ); return -1; } op->o_callback = &roc->cb; return SLAP_CB_CONTINUE;}static intrwm_op_unbind( Operation *op, SlapReply *rs ){ slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; struct ldaprwmap *rwmap = (struct ldaprwmap *)on->on_bi.bi_private;#ifdef ENABLE_REWRITE rewrite_session_delete( rwmap->rwm_rw, op->o_conn );#endif /* ENABLE_REWRITE */ return SLAP_CB_CONTINUE;}static intrwm_op_compare( Operation *op, SlapReply *rs ){ slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; struct ldaprwmap *rwmap = (struct ldaprwmap *)on->on_bi.bi_private; int rc; struct berval mapped_vals[2] = { BER_BVNULL, BER_BVNULL }; rwm_op_cb *roc = rwm_callback_get( op, rs );#ifdef ENABLE_REWRITE rc = rwm_op_dn_massage( op, rs, "compareDN", &roc->ros );#else /* ! ENABLE_REWRITE */ rc = 1; rc = rwm_op_dn_massage( op, rs, &rc, &roc->ros );#endif /* ! ENABLE_REWRITE */ if ( rc != LDAP_SUCCESS ) { op->o_bd->bd_info = (BackendInfo *)on->on_info; send_ldap_error( op, rs, rc, "compareDN massage error" ); return -1; } /* if the attribute is an objectClass, try to remap its value */ if ( op->orc_ava->aa_desc == slap_schema.si_ad_objectClass || op->orc_ava->aa_desc == slap_schema.si_ad_structuralObjectClass ) { rwm_map( &rwmap->rwm_oc, &op->orc_ava->aa_value, &mapped_vals[0], RWM_MAP ); if ( BER_BVISNULL( &mapped_vals[0] ) || BER_BVISEMPTY( &mapped_vals[0] ) ) { op->o_bd->bd_info = (BackendInfo *)on->on_info; send_ldap_error( op, rs, LDAP_OTHER, "compare objectClass map error" ); return -1; } else if ( mapped_vals[0].bv_val != op->orc_ava->aa_value.bv_val ) { ber_dupbv_x( &op->orc_ava->aa_value, &mapped_vals[0], op->o_tmpmemctx ); } } else { struct ldapmapping *mapping = NULL; AttributeDescription *ad = op->orc_ava->aa_desc; ( void )rwm_mapping( &rwmap->rwm_at, &op->orc_ava->aa_desc->ad_cname, &mapping, RWM_MAP ); if ( mapping == NULL ) { if ( rwmap->rwm_at.drop_missing ) { op->o_bd->bd_info = (BackendInfo *)on->on_info; send_ldap_error( op, rs, LDAP_OTHER, "compare attributeType map error" ); return -1; } } else { assert( mapping->m_dst_ad != NULL ); ad = mapping->m_dst_ad; } if ( op->orc_ava->aa_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName || ( mapping != NULL && mapping->m_dst_ad->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName ) ) { struct berval *mapped_valsp[2]; mapped_valsp[0] = &mapped_vals[0]; mapped_valsp[1] = &mapped_vals[1]; mapped_vals[0] = op->orc_ava->aa_value;#ifdef ENABLE_REWRITE rc = rwm_dnattr_rewrite( op, rs, "compareAttrDN", NULL, mapped_valsp );#else /* ! ENABLE_REWRITE */ rc = 1; rc = rwm_dnattr_rewrite( op, rs, &rc, NULL, mapped_valsp );#endif /* ! ENABLE_REWRITE */ if ( rc != LDAP_SUCCESS ) { op->o_bd->bd_info = (BackendInfo *)on->on_info; send_ldap_error( op, rs, rc, "compareAttrDN massage error" ); return -1; } if ( mapped_vals[ 0 ].bv_val != op->orc_ava->aa_value.bv_val ) { /* NOTE: if we get here, rwm_dnattr_rewrite() * already freed the old value, so now * it's invalid */ ber_dupbv_x( &op->orc_ava->aa_value, &mapped_vals[0], op->o_tmpmemctx ); ber_memfree_x( mapped_vals[ 0 ].bv_val, NULL ); } } op->orc_ava->aa_desc = ad; } op->o_callback = &roc->cb; return SLAP_CB_CONTINUE;}static intrwm_op_delete( Operation *op, SlapReply *rs ){ slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; int rc; rwm_op_cb *roc = rwm_callback_get( op, rs );#ifdef ENABLE_REWRITE rc = rwm_op_dn_massage( op, rs, "deleteDN", &roc->ros );#else /* ! ENABLE_REWRITE */ rc = 1; rc = rwm_op_dn_massage( op, rs, &rc, &roc->ros );#endif /* ! ENABLE_REWRITE */ if ( rc != LDAP_SUCCESS ) { op->o_bd->bd_info = (BackendInfo *)on->on_info; send_ldap_error( op, rs, rc, "deleteDN massage error" ); return -1; } op->o_callback = &roc->cb; return SLAP_CB_CONTINUE;}static intrwm_op_modify( Operation *op, SlapReply *rs ){ slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; struct ldaprwmap *rwmap = (struct ldaprwmap *)on->on_bi.bi_private; int isupdate; Modifications **mlp; int rc; rwm_op_cb *roc = rwm_callback_get( op, rs );#ifdef ENABLE_REWRITE rc = rwm_op_dn_massage( op, rs, "modifyDN", &roc->ros );#else /* ! ENABLE_REWRITE */ rc = 1; rc = rwm_op_dn_massage( op, rs, &rc, &roc->ros );#endif /* ! ENABLE_REWRITE */ if ( rc != LDAP_SUCCESS ) { op->o_bd->bd_info = (BackendInfo *)on->on_info; send_ldap_error( op, rs, rc, "modifyDN massage error" ); return -1; } isupdate = be_shadow_update( op ); for ( mlp = &op->oq_modify.rs_modlist; *mlp; ) { int is_oc = 0; Modifications *ml; struct ldapmapping *mapping = NULL; /* duplicate the modlist */ ml = ch_malloc( sizeof( Modifications )); *ml = **mlp; *mlp = ml; if ( ml->sml_desc == slap_schema.si_ad_objectClass || ml->sml_desc == slap_schema.si_ad_structuralObjectClass ) { is_oc = 1; } else if ( !isupdate && !get_manageDIT( op ) && (*mlp)->sml_desc->ad_type->sat_no_user_mod ) { goto next_mod; } else { int drop_missing; drop_missing = rwm_mapping( &rwmap->rwm_at, &ml->sml_desc->ad_cname, &mapping, RWM_MAP ); if ( drop_missing || ( mapping != NULL && BER_BVISNULL( &mapping->m_dst ) ) ) { goto cleanup_mod; } } if ( ml->sml_values != NULL ) { int i, num; struct berval *bva; for ( num = 0; !BER_BVISNULL( &ml->sml_values[ num ] ); num++ ) /* count values */ ; bva = ch_malloc( (num+1) * sizeof( struct berval )); for (i=0; i<num; i++) ber_dupbv( &bva[i], &ml->sml_values[i] ); BER_BVZERO( &bva[i] ); ml->sml_values = bva; if ( ml->sml_nvalues ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -