sarg  2.4.0
About: SARG ia a Squid Analysis Report Generator.
  Fossies Dox: sarg-2.4.0.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

usertab.c
Go to the documentation of this file.
1 /*
2  * SARG Squid Analysis Report Generator http://sarg.sourceforge.net
3  * 1998, 2015
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  */
31 #include "include/conf.h"
32 #include "include/defs.h"
33 
34 #ifdef HAVE_LDAP_H
35 #define LDAP_DEPRECATED 1
36 
37 #include <ldap.h>
38 #include <ldap_cdefs.h>
39 #include <ldap_features.h>
40 
41 #if defined(HAVE_ICONV_H)
42 #include <iconv.h>
43 #define USE_ICONV 1
44 #endif //HAVE_ICONV_H
45 
46 #endif //HAVE_LDAP_H
47 
53 {
60 };
61 
67 
68 static char *userfile=NULL;
69 
70 #ifdef HAVE_LDAP_H
71 static LDAP *ldap_handle=NULL;
72 #endif //HAVE_LDAP_H
73 
74 #ifdef USE_ICONV
75 static iconv_t ldapiconv=(iconv_t)-1;
78 static char *ldapconvbuffer=NULL;
80 static int ldapconvbuffersize=0;
81 #endif
82 
97 static void init_file_usertab(const char *UserTabFile)
98 {
99  FILE *fp_usr;
100  long int nreg;
101  char buf[MAXLEN];
102  int z1, z2;
103 
104  if ((fp_usr=fopen(UserTabFile,"r"))==NULL) {
105  debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),UserTabFile,strerror(errno));
106  exit(EXIT_FAILURE);
107  }
108  if (fseek(fp_usr, 0, SEEK_END)==-1) {
109  debuga(__FILE__,__LINE__,_("Failed to move till the end of file \"%s\": %s\n"),UserTabFile,strerror(errno));
110  exit(EXIT_FAILURE);
111  }
112  nreg = ftell(fp_usr);
113  if (nreg<0) {
114  debuga(__FILE__,__LINE__,_("Cannot get the size of file \"%s\"\n"),UserTabFile);
115  exit(EXIT_FAILURE);
116  }
117  nreg += 100;
118  if (fseek(fp_usr, 0, SEEK_SET)==-1) {
119  debuga(__FILE__,__LINE__,_("Failed to rewind file \"%s\": %s\n"),UserTabFile,strerror(errno));
120  exit(EXIT_FAILURE);
121  }
122  if ((userfile=(char *) malloc(nreg))==NULL){
123  debuga(__FILE__,__LINE__,_("ERROR: Cannot load. Memory fault\n"));
124  exit(EXIT_FAILURE);
125  }
126  userfile[0]='\t';
127  z2=1;
128  while(fgets(buf,sizeof(buf),fp_usr)!=NULL) {
129  if (buf[0]=='#') continue;
130  fixendofline(buf);
131  z1=0;
132  while(buf[z1] && (unsigned char)buf[z1]>' ') {
133  if (z2+3>=nreg) { //need at least 3 additional bytes for the minimum string "\n\t\0"
134  debuga(__FILE__,__LINE__,_("The list of users is too long in file \"%s\"\n"),UserTabFile);
135  exit(EXIT_FAILURE);
136  }
137  userfile[z2++]=buf[z1++];
138  }
139  while(buf[z1] && (unsigned char)buf[z1]<=' ') z1++;
140  userfile[z2++]='\n';
141  while(buf[z1] && (unsigned char)buf[z1]>=' ') {
142  if (z2+2>=nreg) { //need at least 2 additional bytes for "\t\0"
143  debuga(__FILE__,__LINE__,_("The list of users is too long in file \"%s\"\n"),UserTabFile);
144  exit(EXIT_FAILURE);
145  }
146  userfile[z2++]=buf[z1++];
147  }
148  while(userfile[z2-1]==' ') z2--;
149  userfile[z2++]='\t';
150  }
151  userfile[z2]='\0';
152  if (fclose(fp_usr)==EOF) {
153  debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),UserTabFile,strerror(errno));
154  exit(EXIT_FAILURE);
155  }
156 }
157 
168 static void get_usertab_name(const char *user,char *name,int namelen)
169 {
170  char warea[MAXLEN];
171  char *str;
172 
173  sprintf(warea,"\t%s\n",user);
174  if ((str=(char *) strstr(userfile,warea)) == (char *) NULL ) {
175  safe_strcpy(name,user,namelen);
176  } else {
177  str=strchr(str+1,'\n');
178  str++;
179  namelen--;
180  for (z1=0; *str != '\t' && z1<namelen ; z1++) {
181  name[z1]=*str++;
182  }
183  name[z1]='\0';
184  }
185 }
186 
187 #ifdef HAVE_LDAP_H
188 
191 static void connect_ldap(void)
192 {
193  char *ldapuri;
194  LDAPURLDesc url;
195  int rc;
196 
197  if (ldap_handle)
198  ldap_unbind(ldap_handle);
199 
200  /* Setting LDAP connection and initializing cache */
201  memset(&url,0,sizeof(url));
202  url.lud_scheme = "ldap";
203  url.lud_host = LDAPHost;
204  url.lud_port = LDAPPort;
205  url.lud_scope = LDAP_SCOPE_DEFAULT;
206  ldapuri = ldap_url_desc2str(&url);
207  if (ldapuri==NULL) {
208  debuga(__FILE__,__LINE__,_("Cannot prepare ldap URI for server %s on port %d\n"),LDAPHost,LDAPPort);
209  exit(EXIT_FAILURE);
210  }
211 
212  rc = ldap_initialize(&ldap_handle, ldapuri);
213  if (rc != LDAP_SUCCESS) {
214  debuga(__FILE__,__LINE__,_("Unable to connect to LDAP server %s on port %d: %d (%s)\n"), LDAPHost, LDAPPort, rc, ldap_err2string(rc));
215  exit(EXIT_FAILURE);
216  }
217  ldap_memfree(ldapuri);
218 
219  if (ldap_set_option(ldap_handle, LDAP_OPT_REFERRALS, LDAP_OPT_OFF) != LDAP_OPT_SUCCESS) {
220  debuga(__FILE__,__LINE__,_("Could not disable LDAP_OPT_REFERRALS\n"));
221  exit(EXIT_FAILURE);
222  }
223  int ldap_protocol_version = LDAPProtocolVersion;
224  if (ldap_set_option(ldap_handle, LDAP_OPT_PROTOCOL_VERSION, &ldap_protocol_version) != LDAP_SUCCESS) {
225  debuga(__FILE__,__LINE__,_("Could not set LDAP protocol version %d\n"), ldap_protocol_version);
226  exit(EXIT_FAILURE);
227  }
228 
229  /* Bind to the LDAP server. */
230  rc = ldap_simple_bind_s( ldap_handle, LDAPBindDN, LDAPBindPW );
231  if ( rc != LDAP_SUCCESS ) {
232  debuga(__FILE__,__LINE__,_("Cannot bind to LDAP server: %s\n"), ldap_err2string(rc));
233  exit(EXIT_FAILURE);
234  }
235 }
236 
241 static void init_ldap_usertab(void)
242 {
243  ldap_handle = NULL;
244  connect_ldap();
245 
246 #ifdef USE_ICONV
247  // prepare for the string conversion
248  if (LDAPNativeCharset[0]!='\0') {
249  ldapiconv = iconv_open( LDAPNativeCharset, "UTF-8" );
250  if (ldapiconv==(iconv_t)-1) {
251  debuga(__FILE__,__LINE__,_("iconv cannot convert from UTF-8 to %s: %s\n"),LDAPNativeCharset,strerror(errno));
252  exit(EXIT_FAILURE);
253  }
254  }
255  ldapconvbuffer=NULL;
256  ldapconvbuffersize=0;
257 #endif
258 
259  /* Initializing cache */
260  init_cache();
261 }
262 
263 const char * charset_convert( const char * str_in, const char * charset_to )
264 {
265 #ifdef USE_ICONV
266  size_t return_value;
267  const char * str_in_orig;
268  char * str_out;
269  size_t str_in_len;
270  size_t str_out_len;
271 
272  str_in_len = strlen( str_in ) + 1;//process the terminating NUL too
273  str_out_len = ( 2 * str_in_len );
274  if (ldapconvbuffer==NULL || ldapconvbuffersize<str_out_len) {
275  ldapconvbuffersize=str_out_len;
276  str_out = realloc(ldapconvbuffer,ldapconvbuffersize);
277  if (!str_out) {
278  debuga(__FILE__,__LINE__,_("Not enough memory to convert a LDAP returned string: %lu bytes required\n"),(unsigned long int)str_out_len);
279  exit(EXIT_FAILURE);
280  }
281  ldapconvbuffer = str_out;
282  } else {
283  str_out = ldapconvbuffer;
284  str_out_len = ldapconvbuffersize;
285  }
286  str_in_orig = str_in;
287  return_value = iconv(ldapiconv, (ICONV_CONST char **)&str_in, &str_in_len, &str_out, &str_out_len );
288  if ( return_value == ( size_t ) -1 ) {
289  /* TRANSLATORS: The message is followed by the reason for the failure. */
290  debuga(__FILE__,__LINE__,_("iconv failed on string \"%s\":\n"),str_in_orig);
291  switch ( errno ) {
292  /* See "man 3 iconv" for an explanation. */
293  case EILSEQ:
294  debuga(__FILE__,__LINE__,_("Invalid multibyte sequence.\n"));
295  break;
296  case EINVAL:
297  debuga(__FILE__,__LINE__,_("Incomplete multibyte sequence.\n"));
298  break;
299  case E2BIG:
300  debuga(__FILE__,__LINE__,_("No more room.\n"));
301  break;
302  default:
303  debuga(__FILE__,__LINE__,_("Error: %s.\n"),strerror( errno ));
304  }
305  exit(EXIT_FAILURE);
306  }
307  return(ldapconvbuffer);
308 #else //USE_ICONV
309  return(str_in);
310 #endif //USE_ICONV
311 }
312 
323 static void get_ldap_name(const char *userlogin,char *mappedname,int namelen)
324 {
325  /* Start searching username in cache */
326  // According to rfc2254 section 4, only *()\ and NUL must be escaped. This list is rather conservative !
327  const char strictchars[] = " ~!@^&(){}|<>?:;\"\'\\[]`,\r\n\0";
328  char filtersearch[256], *searched_in_cache;
329  char searchloginname[3*MAX_USER_LEN];
330  char *attr, **vals;
331  const char *attr_out;
332  const char *ptr;
333  LDAPMessage *result, *e;
334  BerElement *ber;
335  int i;
336  int slen;
337  int rc;
338  char *attrs[2];
339 
340  searched_in_cache = search_in_cache(userlogin);
341  if (searched_in_cache!=NULL) {
342  safe_strcpy(mappedname, searched_in_cache,namelen);
343  return;
344  }
345 
346  // escape characters according to rfc2254 section 4
347  for (slen=0 , ptr=userlogin ; slen<sizeof(searchloginname)-1 && *ptr ; ptr++) {
348  if (strchr(strictchars,*ptr)) {
349  if (slen+3>=sizeof(searchloginname)-1) break;
350  slen+=sprintf(searchloginname+slen,"\\%02X",*ptr);
351  } else {
352  searchloginname[slen++]=*ptr;
353  }
354  }
355  searchloginname[slen]='\0';
356 
357  i=0;
358  ptr=LDAPFilterSearch;
359  while (i<sizeof(filtersearch)-1 && *ptr) {
360  if (ptr[0]=='%' && ptr[1]=='s') {
361  if (i+slen>=sizeof(filtersearch)) break;
362  memcpy(filtersearch+i,searchloginname,slen);
363  i+=slen;
364  ptr+=2;
365  } else {
366  filtersearch[i++]=*ptr++;
367  }
368  }
369  filtersearch[i]='\0';
370 
371  /* Search record(s) in LDAP base */
372  attrs[0]=LDAPTargetAttr;
373  attrs[1]=NULL;
374  rc=ldap_search_ext_s(ldap_handle, LDAPBaseSearch, LDAP_SCOPE_SUBTREE, filtersearch, attrs, 0, NULL, NULL, NULL, -1, &result);
375  if (rc != LDAP_SUCCESS) {
376  /*
377  * We know the connection was successfully established once. If it fails now,
378  * it may be because the server timed out between two requests or because
379  * there is an error in the request.
380  *
381  * Just in case the failure is due to a timeout, we try to connect and send
382  * the query again.
383  */
384  connect_ldap();
385  rc=ldap_search_ext_s(ldap_handle, LDAPBaseSearch, LDAP_SCOPE_SUBTREE, filtersearch, attrs, 0, NULL, NULL, NULL, -1, &result);
386  if (rc != LDAP_SUCCESS) {
387  debuga(__FILE__,__LINE__,_("LDAP search failed: %s\nlooking for \"%s\" at or below \"%s\"\n"), ldap_err2string(rc),filtersearch,LDAPBaseSearch);
388  safe_strcpy(mappedname,userlogin,namelen);
389  return;
390  }
391  }
392 
393  if (!(e = ldap_first_entry(ldap_handle, result))) {
394  insert_to_cache(userlogin, userlogin);
395  safe_strcpy(mappedname, userlogin,namelen);
396  return;
397  }
398 
399  for (attr = ldap_first_attribute(ldap_handle, e, &ber); attr != NULL; attr = ldap_next_attribute(ldap_handle, e, ber)) {
400  if (!strcasecmp(attr, LDAPTargetAttr)) {
401  if ((vals = (char **)ldap_get_values(ldap_handle, e, attr))!=NULL) {
402  attr_out = charset_convert( vals[0], LDAPNativeCharset );
403  insert_to_cache(userlogin, attr_out);
404  safe_strcpy(mappedname, attr_out, namelen);
405  ldap_memfree(vals);
406  }
407  ldap_memfree(attr);
408  break;
409  }
410  ldap_memfree(attr);
411  }
412  ldap_msgfree(result);
413 }
414 #endif //HAVE_LDAP_H
415 
426 void init_usertab(const char *UserTabFile)
427 {
428  if (strcmp(UserTabFile, "ldap") == 0) {
429  if (debug) {
430  /* TRANSLATORS: The %s may be the string "ldap" or a file name.*/
431  debuga(__FILE__,__LINE__,_("Loading User table from \"%s\"\n"),UserTabFile);
432  }
433 #ifdef HAVE_LDAP_H
435  init_ldap_usertab();
436 #else
437  debuga(__FILE__,__LINE__,_("LDAP module not compiled in sarg\n"));
438  exit(EXIT_FAILURE);
439 #endif //HAVE_LDAP_H
440  } else if (UserTabFile[0] != '\0') {
441  if (debug)
442  debuga(__FILE__,__LINE__,_("Loading User table from \"%s\"\n"),UserTabFile);
445  } else {
447  }
448 }
449 
460 void user_find(char *mappedname, int namelen, const char *userlogin)
461 {
462  if (which_usertab==UTT_File) {
463  get_usertab_name(userlogin,mappedname,namelen);
464  }
465 #ifdef HAVE_LDAP_H
466  else if (which_usertab==UTT_Ldap) {
467  get_ldap_name(userlogin,mappedname,namelen);
468  }
469 #endif //HAVE_LDAP_H
470  else {
471  safe_strcpy(mappedname,userlogin,namelen);
472  }
473 }
474 
478 void close_usertab(void)
479 {
480 #ifdef HAVE_LDAP_H
481  if (ldap_handle) {
482  destroy_cache();
483  ldap_unbind(ldap_handle);
484  ldap_handle=NULL;
485  }
486 #endif //HAVE_LDAP_H
487 #ifdef USE_ICONV
488  if (ldapiconv!=(iconv_t)-1) {
489  iconv_close (ldapiconv);
490  ldapiconv=(iconv_t)-1;
491  }
492  if (ldapconvbuffer) {
493  free(ldapconvbuffer);
494  ldapconvbuffer=NULL;
495  }
496 #endif // USE_ICONV
497  if (userfile) {
498  free(userfile);
499  userfile=NULL;
500  }
501 }
502 
close_usertab
void close_usertab(void)
Definition: usertab.c:478
LDAPProtocolVersion
int LDAPProtocolVersion
Definition: conf.h:449
debuga
void debuga(const char *File, int Line, const char *msg,...)
Definition: util.c:601
rc
int rc
Definition: conf.h:500
LDAPNativeCharset
char LDAPNativeCharset[20]
Character set to convert the LDAP returned string to.
Definition: conf.h:454
UserTabFile
char UserTabFile[255]
Definition: conf.h:333
LDAPFilterSearch
char LDAPFilterSearch[512]
Definition: conf.h:451
LDAPHost
char LDAPHost[255]
Definition: conf.h:445
UTT_None
@ UTT_None
No user matching performed.
Definition: usertab.c:59
init_file_usertab
static void init_file_usertab(const char *UserTabFile)
Definition: usertab.c:97
_
#define _(String)
Definition: conf.h:155
MAXLEN
#define MAXLEN
Definition: conf.h:176
user_find
void user_find(char *mappedname, int namelen, const char *userlogin)
Definition: usertab.c:460
MAX_USER_LEN
#define MAX_USER_LEN
Definition: conf.h:179
LDAPPort
int LDAPPort
Definition: conf.h:448
warea
char warea[20000]
Definition: conf.h:334
name
char name[20000]
Definition: conf.h:335
which_usertab
enum UserTabEnum which_usertab
Definition: usertab.c:66
init_cache
void init_cache(void)
Definition: btree_cache.c:288
destroy_cache
void destroy_cache(void)
Definition: btree_cache.c:330
UTT_Ldap
@ UTT_Ldap
Users matched agains a LDAP.
Definition: usertab.c:57
search_in_cache
char * search_in_cache(const char *key)
Definition: btree_cache.c:319
get_usertab_name
static void get_usertab_name(const char *user, char *name, int namelen)
Definition: usertab.c:168
conf.h
Include headers and define global variables. */.
z2
int z2
Definition: conf.h:481
userfile
static char * userfile
Definition: usertab.c:68
LDAPTargetAttr
char LDAPTargetAttr[64]
Definition: conf.h:452
LDAPBaseSearch
char LDAPBaseSearch[255]
Definition: conf.h:450
insert_to_cache
int insert_to_cache(const char *key, const char *value)
Definition: btree_cache.c:295
UTT_File
@ UTT_File
Users matched against the UserTabFile file.
Definition: usertab.c:55
safe_strcpy
void safe_strcpy(char *dest, const char *src, int length)
Definition: util.c:1550
LDAPBindPW
char LDAPBindPW[255]
Definition: conf.h:447
defs.h
Declaration of the structures and functions.
LDAPBindDN
char LDAPBindDN[512]
Definition: conf.h:446
z1
int z1
Definition: conf.h:481
init_usertab
void init_usertab(const char *UserTabFile)
Definition: usertab.c:426
fixendofline
void fixendofline(char *str)
Definition: util.c:1911
debug
int debug
Definition: conf.h:489
UserTabEnum
UserTabEnum
Definition: usertab.c:52