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