📄 refint.c
字号:
/* refint.c - referential integrity module *//* $OpenLDAP: pkg/ldap/servers/slapd/overlays/refint.c,v 1.7.2.11 2007/01/02 21:44:08 kurt Exp $ *//* This work is part of OpenLDAP Software <http://www.openldap.org/>. * * Copyright 2004-2007 The OpenLDAP Foundation. * Portions Copyright 2004 Symas Corporation. * 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>. *//* ACKNOWLEDGEMENTS: * This work was initially developed by Symas Corp. for inclusion in * OpenLDAP Software. This work was sponsored by Hewlett-Packard. */#include "portable.h"/* This module maintains referential integrity for a set of * DN-valued attributes by searching for all references to a given * DN whenever the DN is changed or its entry is deleted, and making * the appropriate update. * * Updates are performed using the database rootdn, but the ModifiersName * is always set to refint_dn. */#ifdef SLAPD_OVER_REFINT#include <stdio.h>#include <ac/string.h>#include <ac/socket.h>#include "slap.h"static slap_overinst refint;/* The DN to use in the ModifiersName for all refint updates */static BerValue refint_dn = BER_BVC("cn=Referential Integrity Overlay");typedef struct refint_attrs_s { struct refint_attrs_s *next; AttributeDescription *attr;} refint_attrs;typedef struct dependents_s { struct dependents_s *next; BerValue dn; /* target dn */ Modifications *mm;} dependent_data;typedef struct refint_data_s { const char *message; /* breadcrumbs */ struct refint_attrs_s *attrs; /* list of known attrs */ struct dependents_s *mods; /* modifications returned from callback */ BerValue dn; /* basedn in parent, searchdn in call */ BerValue newdn; /* replacement value for modrdn callback */ BerValue nnewdn; /* normalized replacement value */ BerValue nothing; /* the nothing value, if needed */ BerValue nnothing; /* normalized nothingness */} refint_data;/*** allocate new refint_data;** initialize, copy basedn;** store in on_bi.bi_private;***/static intrefint_db_init( BackendDB *be){ slap_overinst *on = (slap_overinst *)be->bd_info; refint_data *id = ch_malloc(sizeof(refint_data)); id->message = "_init"; id->attrs = NULL; id->newdn.bv_val = NULL; id->nothing.bv_val = NULL; id->nnothing.bv_val = NULL; ber_dupbv( &id->dn, &be->be_nsuffix[0] ); on->on_bi.bi_private = id; return(0);}/*** if command = attributes:** foreach argument:** convert to attribute;** add to configured attribute list;** elseif command = basedn:** set our basedn to argument;***/static intrefint_config( BackendDB *be, const char *fname, int lineno, int argc, char **argv){ slap_overinst *on = (slap_overinst *) be->bd_info; refint_data *id = on->on_bi.bi_private; refint_attrs *ip; const char *text; AttributeDescription *ad; BerValue dn; int i; if(!strcasecmp(*argv, "refint_attributes")) { for(i = 1; i < argc; i++) { for(ip = id->attrs; ip; ip = ip->next) if(!strcmp(argv[i], ip->attr->ad_cname.bv_val)) { Debug(LDAP_DEBUG_ANY, "%s: line %d: duplicate attribute <s>, ignored\n", fname, lineno, argv[i]); continue; } ad = NULL; if(slap_str2ad(argv[i], &ad, &text) != LDAP_SUCCESS) { Debug(LDAP_DEBUG_ANY, "%s: line %d: bad attribute <%s>, ignored\n", fname, lineno, text); continue; /* XXX */ } else if(ad->ad_next) { Debug(LDAP_DEBUG_ANY, "%s: line %d: multiple attributes match <%s>, ignored\n", fname, lineno, argv[i]); continue; } ip = ch_malloc(sizeof(refint_attrs)); ip->attr = ad; ip->next = id->attrs; id->attrs = ip; Debug(LDAP_DEBUG_ANY, "%s: line %d: new attribute <%s>\n", fname, lineno, argv[i]); } } else if(!strcasecmp(*argv, "refint_base")) { /* XXX only one basedn (yet) - need validate argument! */ if(id->dn.bv_val) ch_free(id->dn.bv_val); ber_str2bv( argv[1], 0, 0, &dn ); Debug(LDAP_DEBUG_ANY, "%s: line %d: new baseDN <%s>\n", fname, lineno, argv[1]); if(dnNormalize(0, NULL, NULL, &dn, &id->dn, NULL)) { Debug(LDAP_DEBUG_ANY, "%s: line %d: bad baseDN!\n", fname, lineno, 0); return(1); } } else if(!strcasecmp(*argv, "refint_nothing")) { if(id->nothing.bv_val) ch_free(id->nothing.bv_val); if(id->nnothing.bv_val) ch_free(id->nnothing.bv_val); ber_str2bv( argv[1], 0, 1, &id->nothing ); if(dnNormalize(0, NULL, NULL, &id->nothing, &id->nnothing, NULL)) { Debug(LDAP_DEBUG_ANY, "%s: line %d: bad nothingDN!\n", fname, lineno, 0); return(1); } Debug(LDAP_DEBUG_ANY, "%s: line %d: new nothingDN<%s>\n", fname, lineno, argv[1]); } else { return(SLAP_CONF_UNKNOWN); } id->message = "_config"; return(0);}/*** nothing really happens here;***/static intrefint_open( BackendDB *be){ slap_overinst *on = (slap_overinst *)be->bd_info; refint_data *id = on->on_bi.bi_private; id->message = "_open"; return(0);}/*** foreach configured attribute:** free it;** free our basedn;** (do not) free id->message;** reset on_bi.bi_private;** free our config data;***/static intrefint_close( BackendDB *be){ slap_overinst *on = (slap_overinst *) be->bd_info; refint_data *id = on->on_bi.bi_private; refint_attrs *ii, *ij; id->message = "_close"; for(ii = id->attrs; ii; ii = ij) { ij = ii->next; ch_free(ii); } ch_free(id->dn.bv_val); ch_free(id->nothing.bv_val); ch_free(id->nnothing.bv_val); on->on_bi.bi_private = NULL; /* XXX */ ch_free(id); return(0);}/*** delete callback** generates a list of Modification* from search results*/static intrefint_delete_cb( Operation *op, SlapReply *rs){ Attribute *a; BerVarray b = NULL; refint_data *dd = op->o_callback->sc_private; refint_attrs *ia, *da = dd->attrs; dependent_data *ip; Modifications *mp, *ma; int i; Debug(LDAP_DEBUG_TRACE, "refint_delete_cb <%s>\n", rs->sr_entry ? rs->sr_entry->e_name.bv_val : "NOTHING", 0, 0); if (rs->sr_type != REP_SEARCH || !rs->sr_entry) return(0); dd->message = "_delete_cb"; /* ** foreach configured attribute type: ** if this attr exists in the search result, ** and it has a value matching the target: ** allocate a Modification; ** allocate its array of 2 BerValues; ** if only one value, and we have a configured Nothing: ** allocate additional Modification ** type = MOD_ADD ** BerValues[] = { Nothing, NULL }; ** add to list ** type = MOD_DELETE ** BerValues[] = { our target dn, NULL }; ** add this mod to the list of mods; ** */ ip = ch_malloc(sizeof(dependent_data)); ip->dn.bv_val = NULL; ip->next = NULL; ip->mm = NULL; ma = NULL; for(ia = da; ia; ia = ia->next) { if ( (a = attr_find(rs->sr_entry->e_attrs, ia->attr) ) ) for(i = 0, b = a->a_nvals; b[i].bv_val; i++) if(bvmatch(&dd->dn, &b[i])) { if(!ip->dn.bv_val) ber_dupbv(&ip->dn, &rs->sr_entry->e_nname); if(!b[1].bv_val && dd->nothing.bv_val) { mp = ch_malloc(sizeof(Modifications)); mp->sml_desc = ia->attr; /* XXX */ mp->sml_type = a->a_desc->ad_cname; mp->sml_values = ch_malloc(2 * sizeof(BerValue)); mp->sml_nvalues = ch_malloc(2 * sizeof(BerValue)); mp->sml_values[1].bv_len = mp->sml_nvalues[1].bv_len = 0; mp->sml_values[1].bv_val = mp->sml_nvalues[1].bv_val = NULL; mp->sml_op = LDAP_MOD_ADD; mp->sml_flags = 0; ber_dupbv(&mp->sml_values[0], &dd->nothing); ber_dupbv(&mp->sml_nvalues[0], &dd->nnothing); mp->sml_next = ma; ma = mp; } /* this might violate the object class */ mp = ch_malloc(sizeof(Modifications)); mp->sml_desc = ia->attr; /* XXX */ mp->sml_type = a->a_desc->ad_cname; mp->sml_values = ch_malloc(2 * sizeof(BerValue)); mp->sml_nvalues = ch_malloc(2 * sizeof(BerValue)); mp->sml_values[1].bv_len = mp->sml_nvalues[1].bv_len = 0; mp->sml_values[1].bv_val = mp->sml_nvalues[1].bv_val = NULL; mp->sml_op = LDAP_MOD_DELETE; mp->sml_flags = 0; ber_dupbv(&mp->sml_values[0], &dd->dn); ber_dupbv(&mp->sml_nvalues[0], &mp->sml_values[0]); mp->sml_next = ma; ma = mp; Debug(LDAP_DEBUG_TRACE, "refint_delete_cb: %s: %s\n", a->a_desc->ad_cname.bv_val, dd->dn.bv_val, 0); break; } } ip->mm = ma; ip->next = dd->mods; dd->mods = ip; return(0);}/*** null callback** does nothing*/static intrefint_null_cb( Operation *op, SlapReply *rs){ ((refint_data *)op->o_callback->sc_private)->message = "_null_cb"; return(LDAP_SUCCESS);}/*** modrdn callback** generates a list of Modification* from search results*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -