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