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
28 static char ldifescape[128] = {
29 1, 1, 1, 1, 1, 1, 1, 1,
30 1, 1, 1, 1, 1, 1, 1, 1,
31 1, 1, 1, 1, 1, 1, 1, 1,
32 1, 1, 1, 1, 1, 1, 1, 1,
33
34 0, 0, 0, 0, 0, 0, 0, 0,
35 1, 1, 1, 0, 0, 0, 0, 0,
36 0, 0, 0, 0, 0, 0, 0, 0,
37 0, 0, 0, 0, 0, 0, 0, 0,
38
39 0, 0, 0, 0, 0, 0, 0, 0,
40 0, 0, 0, 0, 0, 0, 0, 0,
41 0, 0, 0, 0, 0, 0, 0, 0,
42 0, 0, 0, 0, 1, 0, 0, 0,
43
44 0, 0, 0, 0, 0, 0, 0, 0,
45 0, 0, 0, 0, 0, 0, 0, 0,
46 0, 0, 0, 0, 0, 0, 0, 0,
47 0, 0, 0, 0, 0, 0, 0, 1
48 };
49
50 #define LDIFNEEDFLTESCAPE(c) ((c) & 0x80 || ldifescape[(unsigned)(c)])
51
ldif_bv2escaped_filter_value_len(char * val,size_t val_len)52 static size_t ldif_bv2escaped_filter_value_len(char *val,size_t val_len)
53 {
54 size_t i,l;
55
56 if(val == NULL || val_len == 0){
57 ldiflog(LOG0,"fatal error: file %s line %d",__FILE__,__LINE__);
58 exit(EXITLDERROR);
59 }
60
61 for(l = 0,i = 0;i < val_len;l++,i++){
62 char c = val[i];
63
64 if(LDIFNEEDFLTESCAPE(c)){
65 l += 2;
66 }
67 }
68 return l;
69 }
70
ldif_bv2escaped_filter_value(char * inval,size_t inval_len,char ** poutval)71 void ldif_bv2escaped_filter_value(char *inval,size_t inval_len,char **poutval)
72 {
73 size_t i,l,o;
74 char *out;
75
76 if(inval == NULL || inval_len == 0 || poutval == NULL){
77 ldiflog(LOG0,"fatal error: file %s line %d",__FILE__,__LINE__);
78 exit(EXITLDERROR);
79 }
80
81 l = ldif_bv2escaped_filter_value_len(inval,inval_len);
82 out = LDALLOC(l + 1,sizeof(char));
83 *poutval = out;
84
85 if(l == inval_len){
86 memcpy(out,inval,inval_len);
87 return;
88 }
89
90 o = 0;
91 for(i = 0;i < inval_len;i++){
92 char c = inval[i];
93
94 if(LDIFNEEDFLTESCAPE(c)){
95 out[o++] = '\\';
96 out[o++] = "0123456789ABCDEF"[0x0f & (c>>4)];
97 out[o++] = "0123456789ABCDEF"[0x0f & c];
98 }
99 else{
100 out[o++] = c;
101 }
102 }
103 out[o] = '\0';
104
105 return;
106 }
107
ldifgetfilter(struct s_ldifentry * sldifentry,char ** filter)108 int ldifgetfilter(struct s_ldifentry *sldifentry,char **filter)
109 {
110 struct s_ldifentry *psldifentry;
111 struct s_ldifval *psldifval;
112
113 char *cfilter = ldifgetpconf(CONFFILTER);
114 char *cgroup = ldifgetpconf(CONFGROUP);
115
116 psldifentry = sldifentry;
117 while(psldifentry != NULL){
118 if(strcasecmp(cfilter,psldifentry->var) == 0){
119 char *cval;
120 size_t filter_len;
121
122 psldifval = psldifentry->vallist;
123
124 ldif_bv2escaped_filter_value(psldifval->val,psldifval->val_len,&cval);
125 filter_len = strlen("(&()(=))") +
126 strlen(cgroup) +
127 strlen(cfilter) +
128 strlen(cval) +
129 1;
130 *filter = LDALLOC(filter_len,sizeof(char));
131 /*
132 this statement crashes on fc8 08.12.2007 for large cval > 30k
133 sprintf(*filter,"(&(%s)(%s=%s))",cgroup,cfilter,cval);
134 */
135 strcat(*filter,"(&(");
136 strcat(*filter,cgroup);
137 strcat(*filter,")(");
138 strcat(*filter,cfilter);
139 strcat(*filter,"=");
140 strcat(*filter,cval);
141 strcat(*filter,"))");
142
143 if(psldifval->val_len != strlen(cval)){
144 ldiflog(LOG0,"hossa [%s]",cval);
145 }
146
147 if(psldifval->next != NULL){
148 ldiflog(LOG0,"error: filter attribute [%s] not single valued",cfilter);
149 exit(EXITLDERROR);
150 }
151
152 free(cval);
153 return 0;
154 }
155 psldifentry = psldifentry->next;
156 }
157 return -1;
158 }
159
ldiffiltercheck(struct s_schema * sschema)160 void ldiffiltercheck(struct s_schema *sschema)
161 {
162 char *cfilter = ldifgetpconf(CONFFILTER);
163
164 if(ldifschemaequal(sschema,cfilter) == 0){
165 ldiflog(LOG0,"error: filter attribute [%s] cannot be used, because",cfilter);
166 ldiflog(LOG0,"error: the ldap schema does not define EQUALITY method",cfilter);
167 exit(EXITLDERROR);
168 }
169 }
170