1 /* $NetBSD: addpartial-overlay.c,v 1.1.1.4 2014/05/28 09:58:27 tron Exp $ */ 2 3 /* addpartial-overlay.c */ 4 /* $OpenLDAP$ */ 5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 2004-2014 The OpenLDAP Foundation. 8 * Portions Copyright (C) 2004 Virginia Tech, David Hawes. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted only as authorized by the OpenLDAP 13 * Public License. 14 * 15 * A copy of this license is available in file LICENSE in the 16 * top-level directory of the distribution or, alternatively, at 17 * http://www.OpenLDAP.org/license.html. 18 */ 19 /* ACKNOLEDGEDMENTS: 20 * This work was initially developed by David Hawes of Virginia Tech 21 * for inclusion in OpenLDAP Software. 22 */ 23 /* addpartial-overlay 24 * 25 * This is an OpenLDAP overlay that intercepts ADD requests, determines if a 26 * change has actually taken place for that record, and then performs a modify 27 * request for those values that have changed (modified, added, deleted). If 28 * the record has not changed in any way, it is ignored. If the record does not 29 * exist, the record falls through to the normal add mechanism. This overlay is 30 * useful for replicating from sources that are not LDAPs where it is easier to 31 * build entire records than to determine the changes (i.e. a database). 32 */ 33 34 #include "portable.h" 35 #include "slap.h" 36 37 static int collect_error_msg_cb( Operation *op, SlapReply *rs); 38 39 static slap_overinst addpartial; 40 41 /** 42 * The meat of the overlay. Search for the record, determine changes, take 43 * action or fall through. 44 */ 45 static int addpartial_add( Operation *op, SlapReply *rs) 46 { 47 Operation nop = *op; 48 Entry *toAdd = NULL; 49 Entry *found = NULL; 50 slap_overinst *on = (slap_overinst *) op->o_bd->bd_info; 51 int rc; 52 53 toAdd = op->oq_add.rs_e; 54 55 Debug(LDAP_DEBUG_TRACE, "%s: toAdd->e_nname.bv_val: %s\n", 56 addpartial.on_bi.bi_type, toAdd->e_nname.bv_val,0); 57 58 /* if the user doesn't have access, fall through to the normal ADD */ 59 if(!access_allowed(op, toAdd, slap_schema.si_ad_entry, 60 NULL, ACL_WRITE, NULL)) 61 { 62 return SLAP_CB_CONTINUE; 63 } 64 65 rc = overlay_entry_get_ov(&nop, &nop.o_req_ndn, NULL, NULL, 0, &found, on); 66 67 if(rc != LDAP_SUCCESS) 68 { 69 Debug(LDAP_DEBUG_TRACE, 70 "%s: no entry found, falling through to normal add\n", 71 addpartial.on_bi.bi_type, 0, 0); 72 return SLAP_CB_CONTINUE; 73 } 74 else 75 { 76 Debug(LDAP_DEBUG_TRACE, "%s: found the dn\n", addpartial.on_bi.bi_type, 77 0,0); 78 79 if(found) 80 { 81 Attribute *attr = NULL; 82 Attribute *at = NULL; 83 int ret; 84 Modifications *mods = NULL; 85 Modifications **modtail = &mods; 86 Modifications *mod = NULL; 87 88 Debug(LDAP_DEBUG_TRACE, "%s: have an entry!\n", 89 addpartial.on_bi.bi_type,0,0); 90 91 /* determine if the changes are in the found entry */ 92 for(attr = toAdd->e_attrs; attr; attr = attr->a_next) 93 { 94 if(attr->a_desc->ad_type->sat_atype.at_usage != 0) continue; 95 96 at = attr_find(found->e_attrs, attr->a_desc); 97 if(!at) 98 { 99 Debug(LDAP_DEBUG_TRACE, "%s: Attribute %s not found!\n", 100 addpartial.on_bi.bi_type, 101 attr->a_desc->ad_cname.bv_val,0); 102 mod = (Modifications *) ch_malloc(sizeof( 103 Modifications)); 104 mod->sml_flags = 0; 105 mod->sml_op = LDAP_MOD_REPLACE | LDAP_MOD_BVALUES; 106 mod->sml_op &= LDAP_MOD_OP; 107 mod->sml_next = NULL; 108 mod->sml_desc = attr->a_desc; 109 mod->sml_type = attr->a_desc->ad_cname; 110 mod->sml_values = attr->a_vals; 111 mod->sml_nvalues = attr->a_nvals; 112 mod->sml_numvals = attr->a_numvals; 113 *modtail = mod; 114 modtail = &mod->sml_next; 115 } 116 else 117 { 118 MatchingRule *mr = attr->a_desc->ad_type->sat_equality; 119 struct berval *bv; 120 const char *text; 121 int acount , bcount; 122 Debug(LDAP_DEBUG_TRACE, "%s: Attribute %s found\n", 123 addpartial.on_bi.bi_type, 124 attr->a_desc->ad_cname.bv_val,0); 125 126 for(bv = attr->a_vals, acount = 0; bv->bv_val != NULL; 127 bv++, acount++) 128 { 129 /* count num values for attr */ 130 } 131 for(bv = at->a_vals, bcount = 0; bv->bv_val != NULL; 132 bv++, bcount++) 133 { 134 /* count num values for attr */ 135 } 136 if(acount != bcount) 137 { 138 Debug(LDAP_DEBUG_TRACE, "%s: acount != bcount, %s\n", 139 addpartial.on_bi.bi_type, 140 "replace all",0); 141 mod = (Modifications *) ch_malloc(sizeof( 142 Modifications)); 143 mod->sml_flags = 0; 144 mod->sml_op = LDAP_MOD_REPLACE | LDAP_MOD_BVALUES; 145 mod->sml_op &= LDAP_MOD_OP; 146 mod->sml_next = NULL; 147 mod->sml_desc = attr->a_desc; 148 mod->sml_type = attr->a_desc->ad_cname; 149 mod->sml_values = attr->a_vals; 150 mod->sml_nvalues = attr->a_nvals; 151 mod->sml_numvals = attr->a_numvals; 152 *modtail = mod; 153 modtail = &mod->sml_next; 154 continue; 155 } 156 157 for(bv = attr->a_vals; bv->bv_val != NULL; bv++) 158 { 159 struct berval *v; 160 ret = -1; 161 162 for(v = at->a_vals; v->bv_val != NULL; v++) 163 { 164 int r; 165 if(mr && ((r = value_match(&ret, attr->a_desc, mr, 166 SLAP_MR_VALUE_OF_ASSERTION_SYNTAX, 167 bv, v, &text)) == 0)) 168 { 169 if(ret == 0) 170 break; 171 } 172 else 173 { 174 Debug(LDAP_DEBUG_TRACE, 175 "%s: \tvalue DNE, r: %d \n", 176 addpartial.on_bi.bi_type, 177 r,0); 178 ret = strcmp(bv->bv_val, v->bv_val); 179 if(ret == 0) 180 break; 181 } 182 } 183 184 if(ret == 0) 185 { 186 Debug(LDAP_DEBUG_TRACE, 187 "%s: \tvalue %s exists, ret: %d\n", 188 addpartial.on_bi.bi_type, bv->bv_val, ret); 189 } 190 else 191 { 192 Debug(LDAP_DEBUG_TRACE, 193 "%s: \tvalue %s DNE, ret: %d\n", 194 addpartial.on_bi.bi_type, bv->bv_val, ret); 195 mod = (Modifications *) ch_malloc(sizeof( 196 Modifications)); 197 mod->sml_flags = 0; 198 mod->sml_op = LDAP_MOD_REPLACE | LDAP_MOD_BVALUES; 199 mod->sml_op &= LDAP_MOD_OP; 200 mod->sml_next = NULL; 201 mod->sml_desc = attr->a_desc; 202 mod->sml_type = attr->a_desc->ad_cname; 203 mod->sml_values = attr->a_vals; 204 mod->sml_nvalues = attr->a_nvals; 205 mod->sml_numvals = attr->a_numvals; 206 *modtail = mod; 207 modtail = &mod->sml_next; 208 break; 209 } 210 } 211 } 212 } 213 214 /* determine if any attributes were deleted */ 215 for(attr = found->e_attrs; attr; attr = attr->a_next) 216 { 217 if(attr->a_desc->ad_type->sat_atype.at_usage != 0) continue; 218 219 at = NULL; 220 at = attr_find(toAdd->e_attrs, attr->a_desc); 221 if(!at) 222 { 223 Debug(LDAP_DEBUG_TRACE, 224 "%s: Attribute %s not found in new entry!!!\n", 225 addpartial.on_bi.bi_type, 226 attr->a_desc->ad_cname.bv_val, 0); 227 mod = (Modifications *) ch_malloc(sizeof( 228 Modifications)); 229 mod->sml_flags = 0; 230 mod->sml_op = LDAP_MOD_REPLACE; 231 mod->sml_next = NULL; 232 mod->sml_desc = attr->a_desc; 233 mod->sml_type = attr->a_desc->ad_cname; 234 mod->sml_values = NULL; 235 mod->sml_nvalues = NULL; 236 mod->sml_numvals = 0; 237 *modtail = mod; 238 modtail = &mod->sml_next; 239 } 240 else 241 { 242 Debug(LDAP_DEBUG_TRACE, 243 "%s: Attribute %s found in new entry\n", 244 addpartial.on_bi.bi_type, 245 at->a_desc->ad_cname.bv_val, 0); 246 } 247 } 248 249 overlay_entry_release_ov(&nop, found, 0, on); 250 251 if(mods) 252 { 253 Modifications *m = NULL; 254 Modifications *toDel; 255 int modcount; 256 slap_callback nullcb = { NULL, collect_error_msg_cb, 257 NULL, NULL }; 258 259 Debug(LDAP_DEBUG_TRACE, "%s: mods to do...\n", 260 addpartial.on_bi.bi_type, 0, 0); 261 262 nop.o_tag = LDAP_REQ_MODIFY; 263 nop.orm_modlist = mods; 264 nop.orm_no_opattrs = 0; 265 nop.o_callback = &nullcb; 266 nop.o_bd->bd_info = (BackendInfo *) on->on_info; 267 268 for(m = mods, modcount = 0; m; m = m->sml_next, 269 modcount++) 270 { 271 /* count number of mods */ 272 } 273 274 Debug(LDAP_DEBUG_TRACE, "%s: number of mods: %d\n", 275 addpartial.on_bi.bi_type, modcount, 0); 276 277 if(nop.o_bd->be_modify) 278 { 279 SlapReply nrs = { REP_RESULT }; 280 rc = (nop.o_bd->be_modify)(&nop, &nrs); 281 } 282 283 if(rc == LDAP_SUCCESS) 284 { 285 Debug(LDAP_DEBUG_TRACE, 286 "%s: modify successful\n", 287 addpartial.on_bi.bi_type, 0, 0); 288 } 289 else 290 { 291 Debug(LDAP_DEBUG_TRACE, "%s: modify unsuccessful: %d\n", 292 addpartial.on_bi.bi_type, rc, 0); 293 rs->sr_err = rc; 294 if(nullcb.sc_private) 295 { 296 rs->sr_text = nullcb.sc_private; 297 } 298 } 299 300 Debug(LDAP_DEBUG_TRACE, "%s: freeing mods...\n", 301 addpartial.on_bi.bi_type, 0, 0); 302 303 for(toDel = mods; toDel; toDel = mods) 304 { 305 mods = mods->sml_next; 306 ch_free(toDel); 307 } 308 } 309 else 310 { 311 Debug(LDAP_DEBUG_TRACE, "%s: no mods to process\n", 312 addpartial.on_bi.bi_type, 0, 0); 313 } 314 } 315 else 316 { 317 Debug(LDAP_DEBUG_TRACE, "%s: no entry!\n", 318 addpartial.on_bi.bi_type, 0, 0); 319 } 320 321 op->o_callback = NULL; 322 send_ldap_result( op, rs ); 323 ch_free((void *)rs->sr_text); 324 rs->sr_text = NULL; 325 326 return LDAP_SUCCESS; 327 } 328 } 329 330 static int collect_error_msg_cb( Operation *op, SlapReply *rs) 331 { 332 if(rs->sr_text) 333 { 334 op->o_callback->sc_private = (void *) ch_strdup(rs->sr_text); 335 } 336 337 return LDAP_SUCCESS; 338 } 339 340 int addpartial_init() 341 { 342 addpartial.on_bi.bi_type = "addpartial"; 343 addpartial.on_bi.bi_op_add = addpartial_add; 344 345 return (overlay_register(&addpartial)); 346 } 347 348 int init_module(int argc, char *argv[]) 349 { 350 return addpartial_init(); 351 } 352