]> git.ipfire.org Git - thirdparty/sarg.git/blob - usertab.c
Normalize the messages to have less messages to translate.
[thirdparty/sarg.git] / usertab.c
1 /*
2 * SARG Squid Analysis Report Generator http://sarg.sourceforge.net
3 * 1998, 2013
4 *
5 * SARG donations:
6 * please look at http://sarg.sourceforge.net/donations.php
7 * Support:
8 * http://sourceforge.net/projects/sarg/forums/forum/363374
9 * ---------------------------------------------------------------------
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
24 *
25 */
26
27 #include "include/conf.h"
28 #include "include/defs.h"
29
30 #ifdef HAVE_LDAP_H
31 #define LDAP_DEPRECATED 1
32
33 #include <ldap.h>
34 #include <ldap_cdefs.h>
35 #include <ldap_features.h>
36
37 #if defined(HAVE_ICONV_H)
38 #include <iconv.h>
39 #define USE_ICONV 1
40 #endif //HAVE_ICONV_H
41
42 #endif //HAVE_LDAP_H
43
44 enum UserTabEnum
45 {
46 //! Users matched against the ::UserTabFile file.
47 UTT_File,
48 //! Users matched agains a LDAP.
49 UTT_Ldap,
50 //! No user matching performed.
51 UTT_None
52 };
53
54 enum UserTabEnum which_usertab=UTT_None;
55
56 static char *userfile=NULL;
57
58 #ifdef HAVE_LDAP_H
59 static LDAP *ldap_handle=NULL;
60 #endif //HAVE_LDAP_H
61
62 #ifdef USE_ICONV
63 //! iconv conversion descriptor to convert the string returned by LDAP.
64 static iconv_t ldapiconv=(iconv_t)-1;
65 //! Buffer to store the converted string.
66 static char *ldapconvbuffer=NULL;
67 //! Size of the converted string buffer.
68 static int ldapconvbuffersize=0;
69 #endif
70
71 static void init_file_usertab(const char *UserTabFile)
72 {
73 FILE *fp_usr;
74 long int nreg;
75 char buf[MAXLEN];
76 int z1, z2;
77
78 if((fp_usr=fopen(UserTabFile,"r"))==NULL) {
79 debuga(_("Cannot open file \"%s\": %s\n"),UserTabFile,strerror(errno));
80 exit(EXIT_FAILURE);
81 }
82 if (fseek(fp_usr, 0, SEEK_END)==-1) {
83 debuga(_("Failed to move till the end of the usertab file %s: %s\n"),UserTabFile,strerror(errno));
84 exit(EXIT_FAILURE);
85 }
86 nreg = ftell(fp_usr);
87 if (nreg<0) {
88 debuga(_("Cannot get the size of file %s\n"),UserTabFile);
89 exit(EXIT_FAILURE);
90 }
91 nreg += 100;
92 if (fseek(fp_usr, 0, SEEK_SET)==-1) {
93 debuga(_("Failed to rewind the usertab file %s: %s\n"),UserTabFile,strerror(errno));
94 exit(EXIT_FAILURE);
95 }
96 if((userfile=(char *) malloc(nreg))==NULL){
97 debuga(_("ERROR: Cannot load. Memory fault\n"));
98 exit(EXIT_FAILURE);
99 }
100 userfile[0]='\t';
101 z2=1;
102 while(fgets(buf,sizeof(buf),fp_usr)!=NULL) {
103 if (buf[0]=='#') continue;
104 fixendofline(buf);
105 z1=0;
106 while(buf[z1] && (unsigned char)buf[z1]>' ') {
107 if (z2+3>=nreg) { //need at least 3 additional bytes for the minimum string "\n\t\0"
108 debuga(_("The list of the users is too long in your %s file.\n"),UserTabFile);
109 exit(EXIT_FAILURE);
110 }
111 userfile[z2++]=buf[z1++];
112 }
113 while(buf[z1] && (unsigned char)buf[z1]<=' ') z1++;
114 userfile[z2++]='\n';
115 while(buf[z1] && (unsigned char)buf[z1]>=' ') {
116 if (z2+2>=nreg) { //need at least 2 additional bytes for "\t\0"
117 debuga(_("The list of the users is too long in your %s file.\n"),UserTabFile);
118 exit(EXIT_FAILURE);
119 }
120 userfile[z2++]=buf[z1++];
121 }
122 while(userfile[z2-1]==' ') z2--;
123 userfile[z2++]='\t';
124 }
125 userfile[z2]='\0';
126 fclose(fp_usr);
127 }
128
129 static void get_usertab_name(const char *user,char *name,int namelen)
130 {
131 char warea[MAXLEN];
132 char *str;
133
134 sprintf(warea,"\t%s\n",user);
135 if((str=(char *) strstr(userfile,warea)) == (char *) NULL ) {
136 safe_strcpy(name,user,namelen);
137 } else {
138 str=strchr(str+1,'\n');
139 str++;
140 namelen--;
141 for(z1=0; *str != '\t' && z1<namelen ; z1++) {
142 name[z1]=*str++;
143 }
144 name[z1]='\0';
145 }
146 }
147
148 #ifdef HAVE_LDAP_H
149 static void init_ldap_usertab(void) {
150 char *ldapuri;
151 LDAPURLDesc url;
152 int rc;
153
154 ldap_handle = NULL;
155
156 /* Setting LDAP connection and initializing cache */
157 memset(&url,0,sizeof(url));
158 url.lud_scheme = "ldap";
159 url.lud_host = LDAPHost;
160 url.lud_port = LDAPPort;
161 url.lud_scope = LDAP_SCOPE_DEFAULT;
162 ldapuri = ldap_url_desc2str(&url);
163 if (ldapuri==NULL) {
164 debuga(_("Cannot prepare ldap URI for server %s on port %d\n"),LDAPHost,LDAPPort);
165 exit(EXIT_FAILURE);
166 }
167
168 rc = ldap_initialize(&ldap_handle, ldapuri);
169 if (rc != LDAP_SUCCESS) {
170 debuga(_("Unable to connect to LDAP server %s on port %d: %d (%s)\n"), LDAPHost, LDAPPort, rc, ldap_err2string(rc));
171 exit(EXIT_FAILURE);
172 }
173 ldap_memfree(ldapuri);
174
175 if (ldap_set_option(ldap_handle, LDAP_OPT_REFERRALS, LDAP_OPT_OFF) != LDAP_OPT_SUCCESS) {
176 debuga(_("Could not disable LDAP_OPT_REFERRALS\n"));
177 exit(EXIT_FAILURE);
178 }
179 int ldap_protocol_version = LDAPProtocolVersion;
180 if (ldap_set_option(ldap_handle, LDAP_OPT_PROTOCOL_VERSION, &ldap_protocol_version) != LDAP_SUCCESS) {
181 debuga(_("Could not set LDAP protocol version %d\n"), ldap_protocol_version);
182 exit(EXIT_FAILURE);
183 }
184
185 /* Bind to the LDAP server. */
186 rc = ldap_simple_bind_s( ldap_handle, LDAPBindDN, LDAPBindPW );
187 if ( rc != LDAP_SUCCESS ) {
188 debuga(_("Cannot bind to LDAP server: %s\n"), ldap_err2string(rc));
189 exit(EXIT_FAILURE);
190 }
191
192 #ifdef USE_ICONV
193 // prepare for the string conversion
194 if (LDAPNativeCharset[0]!='\0') {
195 ldapiconv = iconv_open( LDAPNativeCharset, "UTF-8" );
196 if (ldapiconv==(iconv_t)-1) {
197 debuga(_("iconv cannot convert from UTF-8 to %s: %s\n"),LDAPNativeCharset,strerror(errno));
198 exit(EXIT_FAILURE);
199 }
200 }
201 ldapconvbuffer=NULL;
202 ldapconvbuffersize=0;
203 #endif
204
205 /* Initializing cache */
206
207 init_cache();
208 }
209
210 const char * charset_convert( const char * str_in, const char * charset_to )
211 {
212 #ifdef USE_ICONV
213 size_t return_value;
214 const char * str_in_orig;
215 char * str_out;
216 size_t str_in_len;
217 size_t str_out_len;
218
219 str_in_len = strlen( str_in ) + 1;//process the terminating NUL too
220 str_out_len = ( 2 * str_in_len );
221 if (ldapconvbuffer==NULL || ldapconvbuffersize<str_out_len) {
222 ldapconvbuffersize=str_out_len;
223 str_out = realloc(ldapconvbuffer,ldapconvbuffersize);
224 if (!str_out) {
225 debuga(_("Not enough memory to convert a LDAP returned string: %lu bytes required\n"),(unsigned long int)str_out_len);
226 exit(EXIT_FAILURE);
227 }
228 ldapconvbuffer = str_out;
229 } else {
230 str_out = ldapconvbuffer;
231 str_out_len = ldapconvbuffersize;
232 }
233 str_in_orig = str_in;
234 return_value = iconv(ldapiconv, (ICONV_CONST char **)&str_in, &str_in_len, &str_out, &str_out_len );
235 if ( return_value == ( size_t ) -1 ) {
236 debuga(_("iconv failed in string \"%s\":\n"),str_in_orig);
237 switch ( errno ) {
238 /* See "man 3 iconv" for an explanation. */
239 case EILSEQ:
240 debuga(_("Invalid multibyte sequence.\n"));
241 break;
242 case EINVAL:
243 debuga(_("Incomplete multibyte sequence.\n"));
244 break;
245 case E2BIG:
246 debuga(_("No more room.\n"));
247 break;
248 default:
249 debuga(_("Error: %s.\n"),strerror( errno ));
250 }
251 exit(EXIT_FAILURE);
252 }
253 return(ldapconvbuffer);
254 #else //USE_ICONV
255 return(str_in);
256 #endif //USE_ICONV
257 }
258
259 static void get_ldap_name(const char *userlogin,char *mappedname,int namelen)
260 {
261 /* Start searching username in cache */
262 // According to rfc2254 section 4, only *()\ and NUL must be escaped. This list is rather conservative !
263 const char strictchars[] = " ~!@^&(){}|<>?:;\"\'\\[]`,\r\n\0";
264 char filtersearch[256], *searched_in_cache;
265 char searchloginname[3*MAX_USER_LEN];
266 char *attr, **vals;
267 const char *attr_out;
268 const char *ptr;
269 LDAPMessage *result, *e;
270 BerElement *ber;
271 int i;
272 int slen;
273 int rc;
274 char *attrs[2];
275
276 searched_in_cache = search_in_cache(userlogin);
277 if (searched_in_cache!=NULL) {
278 safe_strcpy(mappedname, searched_in_cache,namelen);
279 return;
280 }
281
282 // escape characters according to rfc2254 section 4
283 for (slen=0 , ptr=userlogin ; slen<sizeof(searchloginname)-1 && *ptr ; ptr++) {
284 if (strchr(strictchars,*ptr)) {
285 if (slen+3>=sizeof(searchloginname)-1) break;
286 slen+=sprintf(searchloginname+slen,"\\%02X",*ptr);
287 } else {
288 searchloginname[slen++]=*ptr;
289 }
290 }
291 searchloginname[slen]='\0';
292
293 i=0;
294 ptr=LDAPFilterSearch;
295 while (i<sizeof(filtersearch)-1 && *ptr) {
296 if (ptr[0]=='%' && ptr[1]=='s') {
297 if (i+slen>=sizeof(filtersearch)) break;
298 memcpy(filtersearch+i,searchloginname,slen);
299 i+=slen;
300 ptr+=2;
301 } else {
302 filtersearch[i++]=*ptr++;
303 }
304 }
305 filtersearch[i]='\0';
306
307 /* Search record(s) in LDAP base */
308 attrs[0]=LDAPTargetAttr;
309 attrs[1]=NULL;
310 rc= ldap_search_ext_s(ldap_handle, LDAPBaseSearch, LDAP_SCOPE_SUBTREE, filtersearch, attrs, 0, NULL, NULL, NULL, -1, &result);
311 if (rc != LDAP_SUCCESS) {
312 debuga(_("LDAP search failed: %s\n"), ldap_err2string(rc));
313 debuga(_("looking for \"%s\" at or below \"%s\"\n"),filtersearch,LDAPBaseSearch);
314 safe_strcpy(mappedname,userlogin,namelen);
315 return;
316 }
317
318 if (!(e = ldap_first_entry(ldap_handle, result))) {
319 insert_to_cache(userlogin, userlogin);
320 safe_strcpy(mappedname, userlogin,namelen);
321 return;
322 }
323
324 for (attr = ldap_first_attribute(ldap_handle, e, &ber); attr != NULL; attr = ldap_next_attribute(ldap_handle, e, ber)) {
325 if (!strcasecmp(attr, LDAPTargetAttr)) {
326 if ((vals = (char **)ldap_get_values(ldap_handle, e, attr))!=NULL) {
327 attr_out = charset_convert( vals[0], LDAPNativeCharset );
328 insert_to_cache(userlogin, attr_out);
329 safe_strcpy(mappedname, attr_out, namelen);
330 ldap_memfree(vals);
331 }
332 ldap_memfree(attr);
333 break;
334 }
335 ldap_memfree(attr);
336 }
337 ldap_msgfree(result);
338 }
339 #endif //HAVE_LDAP_H
340
341 void init_usertab(const char *UserTabFile)
342 {
343 if (strcmp(UserTabFile, "ldap") == 0) {
344 if(debug)
345 debuga(_("Loading User table: %s\n"),UserTabFile);
346 #ifdef HAVE_LDAP_H
347 which_usertab=UTT_Ldap;
348 init_ldap_usertab();
349 #else
350 debuga(_("LDAP module not compiled in sarg\n"));
351 exit(EXIT_FAILURE);
352 #endif //HAVE_LDAP_H
353 } else if (UserTabFile[0] != '\0') {
354 if(debug)
355 debuga(_("Loading User table: %s\n"),UserTabFile);
356 which_usertab=UTT_File;
357 init_file_usertab(UserTabFile);
358 } else {
359 which_usertab=UTT_None;
360 }
361 }
362
363 void user_find(char *mappedname, int namelen, const char *userlogin)
364 {
365 if (which_usertab==UTT_File) {
366 get_usertab_name(userlogin,mappedname,namelen);
367 }
368 #ifdef HAVE_LDAP_H
369 else if (which_usertab==UTT_Ldap) {
370 get_ldap_name(userlogin,mappedname,namelen);
371 }
372 #endif //HAVE_LDAP_H
373 else {
374 safe_strcpy(mappedname,userlogin,namelen);
375 }
376 }
377
378 void close_usertab(void)
379 {
380 #ifdef HAVE_LDAP_H
381 if (ldap_handle) {
382 destroy_cache();
383 ldap_unbind(ldap_handle);
384 ldap_handle=NULL;
385 }
386 #endif //HAVE_LDAP_H
387 #ifdef USE_ICONV
388 if (ldapiconv!=(iconv_t)-1) {
389 iconv_close (ldapiconv);
390 ldapiconv=(iconv_t)-1;
391 }
392 if (ldapconvbuffer) {
393 free(ldapconvbuffer);
394 ldapconvbuffer=NULL;
395 }
396 #endif // USE_ICONV
397 if(userfile) {
398 free(userfile);
399 userfile=NULL;
400 }
401 }
402