Back to index

openldap  2.4.31
addpartial-overlay.c
Go to the documentation of this file.
00001 /* addpartial-overlay.c */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00004  *
00005  * Copyright 2004-2012 The OpenLDAP Foundation.
00006  * Portions Copyright (C) 2004 Virginia Tech, David Hawes.
00007  * All rights reserved.
00008  *
00009  * Redistribution and use in source and binary forms, with or without
00010  * modification, are permitted only as authorized by the OpenLDAP
00011  * Public License.
00012  *
00013  * A copy of this license is available in file LICENSE in the
00014  * top-level directory of the distribution or, alternatively, at
00015  * http://www.OpenLDAP.org/license.html.
00016  */
00017 /* ACKNOLEDGEDMENTS:
00018  * This work was initially developed by David Hawes of Virginia Tech
00019  * for inclusion in OpenLDAP Software.
00020  */
00021 /* addpartial-overlay
00022  *
00023  * This is an OpenLDAP overlay that intercepts ADD requests, determines if a
00024  * change has actually taken place for that record, and then performs a modify
00025  * request for those values that have changed (modified, added, deleted).  If
00026  * the record has not changed in any way, it is ignored.  If the record does not
00027  * exist, the record falls through to the normal add mechanism.  This overlay is
00028  * useful for replicating from sources that are not LDAPs where it is easier to
00029  * build entire records than to determine the changes (i.e. a database). 
00030  */
00031 
00032 #include "portable.h" 
00033 #include "slap.h"
00034 
00035 static int collect_error_msg_cb( Operation *op, SlapReply *rs);
00036 
00037 static slap_overinst addpartial;
00038 
00043 static int addpartial_add( Operation *op, SlapReply *rs)
00044 {
00045     Operation nop = *op;
00046     Entry *toAdd = NULL;
00047     Entry *found = NULL;
00048     slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
00049     int rc;
00050 
00051     toAdd = op->oq_add.rs_e;
00052 
00053     Debug(LDAP_DEBUG_TRACE, "%s: toAdd->e_nname.bv_val: %s\n",
00054           addpartial.on_bi.bi_type, toAdd->e_nname.bv_val,0);
00055 
00056     /* if the user doesn't have access, fall through to the normal ADD */
00057     if(!access_allowed(op, toAdd, slap_schema.si_ad_entry,
00058                        NULL, ACL_WRITE, NULL))
00059     {
00060         return SLAP_CB_CONTINUE;
00061     }
00062 
00063     rc = overlay_entry_get_ov(&nop, &nop.o_req_ndn, NULL, NULL, 0, &found, on);
00064 
00065     if(rc != LDAP_SUCCESS)
00066     {
00067         Debug(LDAP_DEBUG_TRACE,
00068               "%s: no entry found, falling through to normal add\n",
00069               addpartial.on_bi.bi_type, 0, 0);
00070         return SLAP_CB_CONTINUE;
00071     }
00072     else
00073     { 
00074         Debug(LDAP_DEBUG_TRACE, "%s: found the dn\n", addpartial.on_bi.bi_type,
00075               0,0);
00076 
00077         if(found)
00078         {
00079             Attribute *attr = NULL;
00080             Attribute *at = NULL;
00081             int ret;
00082             Modifications *mods = NULL;
00083             Modifications **modtail = &mods;
00084             Modifications *mod = NULL;
00085 
00086             Debug(LDAP_DEBUG_TRACE, "%s: have an entry!\n",
00087                   addpartial.on_bi.bi_type,0,0);
00088 
00089            /* determine if the changes are in the found entry */ 
00090             for(attr = toAdd->e_attrs; attr; attr = attr->a_next)
00091             {
00092                 if(attr->a_desc->ad_type->sat_atype.at_usage != 0) continue;
00093 
00094                 at = attr_find(found->e_attrs, attr->a_desc);
00095                 if(!at)
00096                 {
00097                     Debug(LDAP_DEBUG_TRACE, "%s: Attribute %s not found!\n",
00098                           addpartial.on_bi.bi_type,
00099                           attr->a_desc->ad_cname.bv_val,0);
00100                     mod = (Modifications *) ch_malloc(sizeof(
00101                                                             Modifications));
00102                     mod->sml_flags = 0;
00103                     mod->sml_op = LDAP_MOD_REPLACE | LDAP_MOD_BVALUES;
00104                     mod->sml_op &= LDAP_MOD_OP;
00105                     mod->sml_next = NULL;
00106                     mod->sml_desc = attr->a_desc;
00107                     mod->sml_type = attr->a_desc->ad_cname;
00108                     mod->sml_values = attr->a_vals;
00109                     mod->sml_nvalues = attr->a_nvals;
00110                     mod->sml_numvals = attr->a_numvals;
00111                     *modtail = mod;
00112                     modtail = &mod->sml_next;
00113                 }
00114                 else
00115                 {
00116                     MatchingRule *mr = attr->a_desc->ad_type->sat_equality;
00117                     struct berval *bv;
00118                     const char *text;
00119                     int acount , bcount;
00120                     Debug(LDAP_DEBUG_TRACE, "%s: Attribute %s found\n",
00121                           addpartial.on_bi.bi_type,
00122                           attr->a_desc->ad_cname.bv_val,0);
00123 
00124                     for(bv = attr->a_vals, acount = 0; bv->bv_val != NULL; 
00125                         bv++, acount++)
00126                     {
00127                         /* count num values for attr */
00128                     }
00129                     for(bv = at->a_vals, bcount = 0; bv->bv_val != NULL; 
00130                         bv++, bcount++)
00131                     {
00132                         /* count num values for attr */
00133                     }
00134                     if(acount != bcount)
00135                     {
00136                         Debug(LDAP_DEBUG_TRACE, "%s: acount != bcount, %s\n",
00137                               addpartial.on_bi.bi_type,
00138                               "replace all",0);
00139                         mod = (Modifications *) ch_malloc(sizeof(
00140                                                                 Modifications));
00141                         mod->sml_flags = 0;
00142                         mod->sml_op = LDAP_MOD_REPLACE | LDAP_MOD_BVALUES;
00143                         mod->sml_op &= LDAP_MOD_OP;
00144                         mod->sml_next = NULL;
00145                         mod->sml_desc = attr->a_desc;
00146                         mod->sml_type = attr->a_desc->ad_cname;
00147                         mod->sml_values = attr->a_vals;
00148                         mod->sml_nvalues = attr->a_nvals;
00149                         mod->sml_numvals = attr->a_numvals;
00150                         *modtail = mod;
00151                         modtail = &mod->sml_next;
00152                         continue;
00153                     }
00154                     
00155                     for(bv = attr->a_vals; bv->bv_val != NULL; bv++)
00156                     {
00157                         struct berval *v;
00158                         ret = -1;
00159                         
00160                         for(v = at->a_vals; v->bv_val != NULL; v++)
00161                         {
00162                             int r;
00163                             if(mr && ((r = value_match(&ret, attr->a_desc, mr,
00164                                            SLAP_MR_VALUE_OF_ASSERTION_SYNTAX,
00165                                            bv, v, &text)) == 0))
00166                             {
00167                                 if(ret == 0)
00168                                     break;
00169                             }
00170                             else
00171                             {
00172                                 Debug(LDAP_DEBUG_TRACE,
00173                                       "%s: \tvalue DNE, r: %d \n",
00174                                       addpartial.on_bi.bi_type,
00175                                       r,0);
00176                                 ret = strcmp(bv->bv_val, v->bv_val);
00177                                 if(ret == 0)
00178                                     break;
00179                             }
00180                         }
00181 
00182                         if(ret == 0)
00183                         {
00184                             Debug(LDAP_DEBUG_TRACE,
00185                                   "%s: \tvalue %s exists, ret: %d\n",
00186                                   addpartial.on_bi.bi_type, bv->bv_val, ret);
00187                         }
00188                         else
00189                         {
00190                             Debug(LDAP_DEBUG_TRACE,
00191                                   "%s: \tvalue %s DNE, ret: %d\n",
00192                                   addpartial.on_bi.bi_type, bv->bv_val, ret);
00193                             mod = (Modifications *) ch_malloc(sizeof(
00194                                                                 Modifications));
00195                             mod->sml_flags = 0;
00196                             mod->sml_op = LDAP_MOD_REPLACE | LDAP_MOD_BVALUES;
00197                             mod->sml_op &= LDAP_MOD_OP;
00198                             mod->sml_next = NULL;
00199                             mod->sml_desc = attr->a_desc;
00200                             mod->sml_type = attr->a_desc->ad_cname;
00201                             mod->sml_values = attr->a_vals;
00202                             mod->sml_nvalues = attr->a_nvals;
00203                             mod->sml_numvals = attr->a_numvals;
00204                             *modtail = mod;
00205                             modtail = &mod->sml_next;
00206                             break;
00207                         }
00208                     }
00209                 }
00210             }
00211 
00212             /* determine if any attributes were deleted */
00213             for(attr = found->e_attrs; attr; attr = attr->a_next)
00214             {
00215                 if(attr->a_desc->ad_type->sat_atype.at_usage != 0) continue;
00216 
00217                 at = NULL;
00218                 at = attr_find(toAdd->e_attrs, attr->a_desc);
00219                 if(!at)
00220                 {
00221                     Debug(LDAP_DEBUG_TRACE,
00222                           "%s: Attribute %s not found in new entry!!!\n",
00223                           addpartial.on_bi.bi_type,
00224                           attr->a_desc->ad_cname.bv_val, 0);
00225                     mod = (Modifications *) ch_malloc(sizeof(
00226                                                         Modifications));
00227                     mod->sml_flags = 0;
00228                     mod->sml_op = LDAP_MOD_REPLACE;
00229                     mod->sml_next = NULL;
00230                     mod->sml_desc = attr->a_desc;
00231                     mod->sml_type = attr->a_desc->ad_cname;
00232                     mod->sml_values = NULL;
00233                     mod->sml_nvalues = NULL;
00234                     mod->sml_numvals = 0;
00235                     *modtail = mod;
00236                     modtail = &mod->sml_next;
00237                 }
00238                 else
00239                 {
00240                     Debug(LDAP_DEBUG_TRACE,
00241                           "%s: Attribute %s found in new entry\n",
00242                           addpartial.on_bi.bi_type,
00243                           at->a_desc->ad_cname.bv_val, 0);
00244                 }
00245             }
00246 
00247             overlay_entry_release_ov(&nop, found, 0, on);
00248 
00249             if(mods)
00250             {
00251                 Modifications *m = NULL;
00252                 Modifications *toDel;
00253                 int modcount;
00254                 slap_callback nullcb = { NULL, collect_error_msg_cb, 
00255                                          NULL, NULL };
00256 
00257                 Debug(LDAP_DEBUG_TRACE, "%s: mods to do...\n",
00258                       addpartial.on_bi.bi_type, 0, 0);
00259 
00260                 nop.o_tag = LDAP_REQ_MODIFY;
00261                 nop.orm_modlist = mods;
00262                 nop.orm_no_opattrs = 0;
00263                 nop.o_callback = &nullcb;
00264                 nop.o_bd->bd_info = (BackendInfo *) on->on_info;
00265 
00266                 for(m = mods, modcount = 0; m; m = m->sml_next, 
00267                     modcount++)
00268                 {
00269                     /* count number of mods */
00270                 }
00271 
00272                 Debug(LDAP_DEBUG_TRACE, "%s: number of mods: %d\n",
00273                       addpartial.on_bi.bi_type, modcount, 0);
00274 
00275                 if(nop.o_bd->be_modify)
00276                 {
00277                     SlapReply nrs = { REP_RESULT };
00278                     rc = (nop.o_bd->be_modify)(&nop, &nrs);
00279                 }
00280 
00281                 if(rc == LDAP_SUCCESS)
00282                 {
00283                     Debug(LDAP_DEBUG_TRACE,
00284                           "%s: modify successful\n",
00285                           addpartial.on_bi.bi_type, 0, 0);
00286                 }
00287                 else
00288                 {
00289                     Debug(LDAP_DEBUG_TRACE, "%s: modify unsuccessful: %d\n",
00290                           addpartial.on_bi.bi_type, rc, 0);
00291                     rs->sr_err = rc;
00292                     if(nullcb.sc_private)
00293                     {
00294                         rs->sr_text = nullcb.sc_private;
00295                     }
00296                 }
00297 
00298                 Debug(LDAP_DEBUG_TRACE, "%s: freeing mods...\n",
00299                       addpartial.on_bi.bi_type, 0, 0);
00300 
00301                 for(toDel = mods; toDel; toDel = mods)
00302                 {
00303                     mods = mods->sml_next;
00304                     ch_free(toDel);
00305                 }
00306             }
00307             else
00308             {
00309                 Debug(LDAP_DEBUG_TRACE, "%s: no mods to process\n",
00310                       addpartial.on_bi.bi_type, 0, 0);
00311             }
00312         }
00313         else
00314         {
00315             Debug(LDAP_DEBUG_TRACE, "%s: no entry!\n",
00316                   addpartial.on_bi.bi_type, 0, 0);
00317         }
00318 
00319         op->o_callback = NULL;
00320         send_ldap_result( op, rs );
00321         ch_free((void *)rs->sr_text);
00322         rs->sr_text = NULL;
00323 
00324         return LDAP_SUCCESS;
00325     }
00326 }
00327 
00328 static int collect_error_msg_cb( Operation *op, SlapReply *rs)
00329 {
00330     if(rs->sr_text)
00331     {
00332         op->o_callback->sc_private = (void *) ch_strdup(rs->sr_text);
00333     }
00334 
00335     return LDAP_SUCCESS;
00336 }
00337 
00338 int addpartial_init() 
00339 {
00340     addpartial.on_bi.bi_type = "addpartial";
00341     addpartial.on_bi.bi_op_add = addpartial_add;
00342 
00343     return (overlay_register(&addpartial));
00344 }
00345 
00346 int init_module(int argc, char *argv[]) 
00347 {
00348     return addpartial_init();
00349 }