1 /*
2 ldapdiff
3 Copyright (C) 2000-2008 Thomas.Reith@rhoen.de
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <lber.h>
20 #include <ldap.h>
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include "ldapdiff.h"
27
cmodentry(struct s_modentry ** smodentry,char * var,char * val,size_t val_len,teattrtype val_type,temodentry emodentry)28 static void cmodentry(struct s_modentry **smodentry,char *var,char *val,size_t val_len,teattrtype val_type,temodentry emodentry)
29 {
30 struct s_modentry *psmodentry;
31 struct s_modentry *ptsmodentry;
32 struct s_ldifval *psmodentryval;
33 struct s_ldifval *ptsmodentryval;
34
35 if(var == NULL || val == NULL){
36 return;
37 }
38
39 psmodentryval = LDALLOC(1,sizeof(struct s_ldifval));
40 psmodentryval->val = LDBINDUP(val,val_len);
41 psmodentryval->val_len = val_len;
42
43 psmodentry = *smodentry;
44 while(psmodentry != NULL){
45 if(strcasecmp(psmodentry->var,var) == 0){
46 ptsmodentryval = psmodentry->vallist;
47 while(ptsmodentryval->next != NULL){
48 ptsmodentryval = ptsmodentryval->next;
49 }
50 ptsmodentryval->next = psmodentryval;
51 return;
52 }
53 psmodentry = psmodentry->next;
54 }
55
56 ptsmodentry = LDALLOC(1,sizeof(struct s_modentry));
57 ptsmodentry->var = LDDUP(var);
58 ptsmodentry->vallist = psmodentryval;
59 ptsmodentry->val_type = val_type;
60 ptsmodentry->modtype = emodentry;
61
62 if(*smodentry == NULL){
63 *smodentry = ptsmodentry;
64 }
65 else{
66 struct s_modentry *usmodentry;
67 usmodentry = *smodentry;
68 while(usmodentry != NULL){
69 if(usmodentry->next == NULL){
70 usmodentry->next = ptsmodentry;
71 return;
72 }
73 usmodentry = usmodentry->next;
74 }
75 }
76 }
77
cmod(struct s_mod ** smod,char * dnvar,char * dnval,char * var,char * val,size_t val_len,teattrtype val_type,temod emod,temodentry emodentry)78 static void cmod(struct s_mod **smod,char *dnvar,char *dnval,char *var,char *val,size_t val_len,teattrtype val_type,temod emod,temodentry emodentry)
79 {
80 struct s_mod *psmod;
81 struct s_mod *ptsmod;
82
83 psmod = *smod;
84 while(psmod != NULL){
85 if(strcmp(psmod->dnval,dnval) == 0 && psmod->modtype == emod){
86 cmodentry(&psmod->attrlist,var,val,val_len,val_type,emodentry);
87 return;
88 }
89 psmod = psmod->next;
90 }
91
92 ptsmod = LDALLOC(1,sizeof(struct s_mod));
93 ptsmod->dnvar = LDDUP(dnvar);
94 ptsmod->dnval = LDDUP(dnval);
95 ptsmod->modtype = emod;
96
97 cmodentry(&ptsmod->attrlist,var,val,val_len,val_type,emodentry);
98 if(*smod == NULL){
99 *smod = ptsmod;
100 }
101 else{
102 struct s_mod *usmod;
103 usmod = *smod;
104 while(usmod != NULL){
105 if(usmod->next == NULL){
106 usmod->next = ptsmod;
107 return;
108 }
109 usmod = usmod->next;
110 }
111 }
112 }
113
ldifcmp(LDAP * ld,struct s_ldif * sldif,struct s_ldif * sldap,struct s_mod ** smod,struct s_schema * sschema)114 void ldifcmp(LDAP *ld,struct s_ldif *sldif,struct s_ldif *sldap,struct s_mod **smod,struct s_schema *sschema)
115 {
116 struct s_ldifentry *psldifentry;
117 struct s_ldifentry *psldapentry;
118 struct s_ldifval *psldifval;
119 struct s_ldifval *psldapval;
120 int attr_found;
121 int attr_modifybydeladd = 0;
122
123 psldifentry = sldif->attrlist;
124 while(psldifentry != NULL){
125 if(ldifcheckignore(psldifentry->var) == ATTRIGNORE){
126 ldiflog(LOG2,"ignore attr: %s",sldif->dnval);
127 psldifval = psldifentry->vallist;
128 while(psldifval != NULL){
129 ldiflogval(LOG2," %s: %s",psldifentry->var,psldifval->val,psldifval->val_len);
130 psldifval = psldifval->next;
131 }
132 }
133 else{
134 attr_found = 0;
135 psldapentry = sldap->attrlist;
136 while(psldapentry != NULL){
137 if(strcasecmp(psldifentry->var,psldapentry->var) == 0){
138 int ldifcount = 0;
139 int ldapcount = 0;
140
141 attr_found = 1;
142
143 psldifval = psldifentry->vallist;
144 while(psldifval != NULL){
145 if(ldifcheckignoreval(psldifval->val) != ATTRIGNORE){
146 ldifcount++;
147 }
148 else{
149 ldiflog(LOG2,"ignore ldif attrval: %s",sldif->dnval);
150 ldiflog(LOG2,"ignore ldif attrval: %s",psldifval->val);
151 }
152 psldifval = psldifval->next;
153 }
154
155 psldapval = psldapentry->vallist;
156 while(psldapval != NULL){
157 if(ldifcheckignoreval(psldapval->val) != ATTRIGNORE){
158 ldapcount++;
159 }
160 else{
161 ldiflog(LOG2,"ignore ldap attrval: %s",sldap->dnval);
162 ldiflog(LOG2,"ignore ldap attrval: %s",psldapval->val);
163 }
164 psldapval = psldapval->next;
165 }
166
167 if(ldapcount == ldifcount){
168 ldapcount = 0;
169 psldifval = psldifentry->vallist;
170 while(psldifval != NULL){
171 psldapval = psldapentry->vallist;
172 while(psldapval != NULL){
173 if(psldifval->val_len == psldapval->val_len){
174 if(memcmp(psldifval->val,psldapval->val,psldifval->val_len) == 0){
175 ldapcount++;
176 }
177 else{
178 /*
179 compare objectClass values case insensitive
180 */
181 if(strcasecmp(psldapentry->var,OCNAME) == 0){
182 if(strncasecmp(psldifval->val,psldapval->val,psldifval->val_len) == 0){
183 ldapcount++;
184 }
185 }
186 }
187 }
188 psldapval = psldapval->next;
189 }
190 psldifval = psldifval->next;
191 }
192 }
193
194 if(ldifcount != ldapcount){
195 /*
196 case 1: attribute is different in ldif file
197 */
198 ldiflog(LOG2,"replace attr: %s",sldif->dnval);
199 psldapval = psldapentry->vallist;
200 while(psldapval != NULL){
201 ldiflogval(LOG2," %s: %s ->",psldapentry->var,psldapval->val,psldapval->val_len);
202 psldapval = psldapval->next;
203 }
204 psldifval = psldifentry->vallist;
205 while(psldifval != NULL){
206 if(strcmp(ldifgetpconf(CONFMODIFYBYDELADD),"yes") != 0){
207 cmod(smod,sldif->dnvar,sldif->dnval,psldifentry->var,psldifval->val,psldifval->val_len,psldifentry->val_type,MODMODIFY,MODATTRREPLACE);
208 }
209 ldiflogval(LOG2," %s: %s",psldifentry->var,psldifval->val,psldifval->val_len);
210 attr_modifybydeladd = 1;
211 psldifval = psldifval->next;
212 }
213 }
214 }
215 psldapentry = psldapentry->next;
216 }
217
218 if(attr_found == 0){
219 /*
220 case 2: attribute doesn't exist in ldap
221 */
222 psldifval = psldifentry->vallist;
223 while(psldifval != NULL){
224 if(strcmp(ldifgetpconf(CONFMODIFYBYDELADD),"yes") != 0){
225 cmod(smod,sldif->dnvar,sldif->dnval,psldifentry->var,psldifval->val,psldifval->val_len,psldifentry->val_type,MODMODIFY,MODATTRADD);
226 }
227 ldiflog(LOG2,"add attr: %s",sldif->dnval);
228 ldiflogval(LOG2," %s: %s",psldifentry->var,psldifval->val,psldifval->val_len);
229 attr_modifybydeladd = 1;
230 psldifval = psldifval->next;
231 }
232 }
233 }
234 psldifentry = psldifentry->next;
235 }
236
237 psldapentry = sldap->attrlist;
238 while(psldapentry != NULL){
239 if(ldifcheckignore(psldapentry->var) == ATTRIGNORE){
240 ldiflog(LOG2,"ignore attr: %s",sldap->dnval);
241 psldapval = psldapentry->vallist;
242 while(psldapval != NULL){
243 ldiflogval(LOG2," %s: %s",psldapentry->var,psldapval->val,psldapval->val_len);
244 psldapval = psldapval->next;
245 }
246 }
247 else{
248 psldifentry = sldif->attrlist;
249 attr_found = 0;
250 while(psldifentry != NULL){
251 if(strcasecmp(psldapentry->var,psldifentry->var) == 0){
252 attr_found++;
253 }
254 psldifentry = psldifentry->next;
255 }
256 if(attr_found == 0){
257 /*
258 case 3: attribute doesn't exist in ldif
259 */
260 if((strcmp(ldifgetpconf(CONFDELETEATTRIBUTE),"yes") == 0) ||
261 (strstr(ldifgetpconf(CONFDELETEATTRIBUTE), psldapentry->var) != NULL)){
262 psldapval = psldapentry->vallist;
263 while(psldapval != NULL){
264 if(strcmp(ldifgetpconf(CONFMODIFYBYDELADD),"yes") != 0){
265 cmod(smod,sldap->dnvar,sldap->dnval,psldapentry->var,psldapval->val,psldapval->val_len,psldapentry->val_type,MODMODIFY,MODATTRDELETE);
266 }
267 ldiflog(LOG2,"delete attr: %s",sldap->dnval);
268 ldiflogval(LOG2," %s: %s",psldapentry->var,psldapval->val,psldapval->val_len);
269 attr_modifybydeladd = 1;
270 psldapval = psldapval->next;
271 }
272 }
273 else{
274 ldiflog(LOG2,"deletion disabled: %s",sldap->dnval);
275 }
276 }
277 }
278 psldapentry = psldapentry->next;
279 }
280
281 /*
282 if there are any replacement attributes and "confmodbydelete: yes" in ldapdiff.conf,
283 every detected entry will be deleted and the entry from the ldif file will be added
284 */
285 if(attr_modifybydeladd == 1 && strcmp(ldifgetpconf(CONFMODIFYBYDELADD),"yes") == 0){
286 ldiflog(LOG2,"delete & add: %s",sldif->dnval);
287 ldifdeletedn(sldif->dnvar,sldif->dnval,smod);
288 ldifadddn(sldif,smod);
289 }
290 }
291
ldifadddn(struct s_ldif * sldif,struct s_mod ** smod)292 void ldifadddn(struct s_ldif *sldif,struct s_mod **smod)
293 {
294 struct s_ldifentry *psldifentry;
295 struct s_ldifval *psldifval;
296
297 psldifentry = sldif->attrlist;
298 while(psldifentry != NULL){
299 if(ldifcheckignore(psldifentry->var) == ATTRIGNORE){
300 ldiflog(LOG2,"ignore attr: %s",sldif->dnval);
301 psldifval = psldifentry->vallist;
302 while(psldifval != NULL){
303 ldiflogval(LOG2," %s: %s",psldifentry->var,psldifval->val,psldifval->val_len);
304 psldifval = psldifval->next;
305 }
306 }
307 else{
308 if(strcmp(ldifgetpconf(CONFADDENTRY),"yes") == 0){
309 psldifval = psldifentry->vallist;
310 while(psldifval != NULL){
311 cmod(smod,sldif->dnvar,sldif->dnval,psldifentry->var,psldifval->val,psldifval->val_len,psldifentry->val_type,MODADD,MODATTRADD);
312 ldiflog(LOG2,"add entry: %s",sldif->dnval);
313 ldiflogval(LOG2," %s: %s",psldifentry->var,psldifval->val,psldifval->val_len);
314 psldifval = psldifval->next;
315 }
316 }
317 else{
318 ldiflog(LOG2,"addition disabled: %s", sldif->dnval);
319 }
320 }
321 psldifentry = psldifentry->next;
322 }
323 }
324
ldifdeletedn(char * dnvar,char * dnval,struct s_mod ** smod)325 void ldifdeletedn(char *dnvar,char *dnval,struct s_mod **smod)
326 {
327 if(strcmp(ldifgetpconf(CONFDELETEENTRY),"yes") == 0){
328 cmod(smod,dnvar,dnval,NULL,NULL,0,0,MODDELETE,MODATTRDELETE);
329 ldiflog(LOG2,"del entry: %s",dnval);
330 }
331 else{
332 ldiflog(LOG2,"deletion disabled: %s",dnval);
333 }
334 }
335
ldifdnalreadyexist(LDAP * ld,char * dn)336 int ldifdnalreadyexist(LDAP *ld,char *dn)
337 {
338 int cn;
339 int rc;
340 LDAPMessage *lr = NULL;
341
342 #ifndef USE_DEPRECATED_API
343 rc = ldap_search_ext_s(ld,dn,LDAP_SCOPE_BASE,"(objectClass=*)",NULL,0,NULL,NULL,NULL,LDAP_MAXINT,&lr);
344
345 if(rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_OBJECT){
346 ldiflog(LOG0,"ldap_search_ext_s() failed: file: %s, line: %d",__FILE__,__LINE__);
347 ldiflog(LOG0,"ldap_err2string(): %s",ldap_err2string(rc));
348 exit(EXITLDERROR);
349 }
350 #else
351 rc = ldap_search_s(ld,dn,LDAP_SCOPE_BASE,"(objectClass=*)",NULL,0,&lr);
352
353 if(rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_OBJECT){
354 ldiflog(LOG0,"ldap_search() failed: file: %s, line: %d",__FILE__,__LINE__);
355 ldiflog(LOG0,"ldap_err2string(): %s",ldap_err2string(rc));
356 exit(EXITLDERROR);
357 }
358 #endif
359
360 if((cn = ldap_count_entries(ld,lr)) == -1){
361 ldiflog(LOG0,"ldap_count_entries() failed: file: %s, line: %d",__FILE__,__LINE__);
362 ldap_get_option(ld,LDAP_OPT_ERROR_NUMBER,&rc);
363 ldiflog(LOG0,"ldap_err2string(): %s",ldap_err2string(rc));
364 exit(EXITLDERROR);
365 }
366
367 if(ldap_msgfree(lr) == -1){
368 ldiflog(LOG0,"ldap_msgfree() failed: file: %s, line: %d",__FILE__,__LINE__);
369 exit(EXITLDERROR);
370 }
371
372 return cn;
373 }
374