xref: /netbsd-src/external/bsd/openldap/dist/contrib/slapd-modules/nops/nops.c (revision b7b7574d3bf8eeb51a1fa3977b59142ec6434a55)
1 /*	$NetBSD: nops.c,v 1.1.1.4 2014/05/28 09:58:27 tron Exp $	*/
2 
3 /* nops.c - Overlay to filter idempotent operations */
4 /* $OpenLDAP$ */
5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6  *
7  * Copyright 2008-2014 The OpenLDAP Foundation.
8  * Copyright 2008 Emmanuel Dreyfus.
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 the file LICENSE in the
16  * top-level directory of the distribution or, alternatively, at
17  * <http://www.OpenLDAP.org/license.html>.
18  */
19 /* ACKNOWLEDGEMENTS:
20  * This work was originally developed by the Emmanuel Dreyfus for
21  * inclusion in OpenLDAP Software.
22  */
23 #include "portable.h"
24 
25 #ifdef SLAPD_OVER_NOPS
26 
27 #include <stdio.h>
28 
29 #include <ac/string.h>
30 #include <ac/socket.h>
31 
32 #include "lutil.h"
33 #include "slap.h"
34 #include "config.h"
35 
36 static ConfigDriver nops_cf_gen;
37 
38 static int nops_cf_gen( ConfigArgs *c ) { return 0; }
39 
40 static void
41 nops_rm_mod( Modifications **mods, Modifications *mod ) {
42 	Modifications *next, *m;
43 
44 	next = mod->sml_next;
45 	if (*mods == mod) {
46 		*mods = next;
47 	} else {
48 		Modifications *m;
49 
50 		for (m = *mods; m; m = m->sml_next) {
51 			if (m->sml_next == mod) {
52 				m->sml_next = next;
53 				break;
54 			}
55 		}
56 	}
57 
58 	mod->sml_next = NULL;
59 	slap_mods_free(mod, 1);
60 
61 	return;
62 }
63 
64 static int
65 nops_modify( Operation *op, SlapReply *rs )
66 {
67 	slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
68 	Backend *be = op->o_bd;
69 	Entry *target_entry = NULL;
70 	Modifications *m;
71 	int rc;
72 
73 	if ((m = op->orm_modlist) == NULL) {
74 		op->o_bd->bd_info = (BackendInfo *)(on->on_info);
75 		send_ldap_error(op, rs, LDAP_INVALID_SYNTAX,
76 				"nops() got null orm_modlist");
77 		return(rs->sr_err);
78 	}
79 
80 	op->o_bd = on->on_info->oi_origdb;
81 	rc = be_entry_get_rw(op, &op->o_req_ndn, NULL, NULL, 0,  &target_entry);
82 	op->o_bd = be;
83 
84 	if (rc != 0 || target_entry == NULL)
85 		return 0;
86 
87 	/*
88 	 * For each attribute modification, check if the
89 	 * modification and the old entry are the same.
90 	 */
91 	while (m) {
92 		int i, j;
93 		int found;
94 		Attribute *a;
95 		BerVarray bm;
96 		BerVarray bt;
97 		Modifications *mc;
98 
99 		mc = m;
100 		m = m->sml_next;
101 
102 		/* Check only replace sub-operations */
103 		if ((mc->sml_op & LDAP_MOD_OP) != LDAP_MOD_REPLACE)
104 			continue;
105 
106 		/* If there is no values, skip */
107 		if (((bm = mc->sml_values ) == NULL ) || (bm[0].bv_val == NULL))
108 			continue;
109 
110 		/* If the attribute does not exist in old entry, skip */
111 		if ((a = attr_find(target_entry->e_attrs, mc->sml_desc)) == NULL)
112 			continue;
113 		if ((bt = a->a_vals) == NULL)
114 			continue;
115 
116 		/* For each value replaced, do we find it in old entry? */
117 		found = 0;
118 		for (i = 0; bm[i].bv_val; i++) {
119 			for (j = 0; bt[j].bv_val; j++) {
120 				if (bm[i].bv_len != bt[j].bv_len)
121 					continue;
122 				if (memcmp(bm[i].bv_val, bt[j].bv_val, bt[j].bv_len) != 0)
123 					continue;
124 
125 				found++;
126 				break;
127 			}
128 		}
129 
130 		/* Did we find as many values as we had in old entry? */
131 		if (i != a->a_numvals || found != a->a_numvals)
132 			continue;
133 
134 		/* This is a nop, remove it */
135 		Debug(LDAP_DEBUG_TRACE, "removing nop on %s%s%s",
136 			a->a_desc->ad_cname.bv_val, "", "");
137 
138 		nops_rm_mod(&op->orm_modlist, mc);
139 	}
140 	if (target_entry) {
141 		op->o_bd = on->on_info->oi_origdb;
142 		be_entry_release_r(op, target_entry);
143 		op->o_bd = be;
144 	}
145 
146 	if ((m = op->orm_modlist) == NULL) {
147 		slap_callback *cb = op->o_callback;
148 
149 		op->o_bd->bd_info = (BackendInfo *)(on->on_info);
150 		op->o_callback = NULL;
151                 send_ldap_error(op, rs, LDAP_SUCCESS, "");
152 		op->o_callback = cb;
153 
154 		return (rs->sr_err);
155 	}
156 
157 	return SLAP_CB_CONTINUE;
158 }
159 
160 static slap_overinst nops_ovl;
161 
162 #if SLAPD_OVER_NOPS == SLAPD_MOD_DYNAMIC
163 static
164 #endif
165 int
166 nops_initialize( void ) {
167 	nops_ovl.on_bi.bi_type = "nops";
168 	nops_ovl.on_bi.bi_op_modify = nops_modify;
169 	return overlay_register( &nops_ovl );
170 }
171 
172 #if SLAPD_OVER_NOPS == SLAPD_MOD_DYNAMIC
173 int init_module(int argc, char *argv[]) {
174 	return nops_initialize();
175 }
176 #endif
177 
178 #endif /* defined(SLAPD_OVER_NOPS) */
179 
180