]> git.ipfire.org Git - thirdparty/sarg.git/blame - usertab.c
Rename configure.in as configure.ac
[thirdparty/sarg.git] / usertab.c
CommitLineData
7179962a 1/*
7179962a 2 * SARG Squid Analysis Report Generator http://sarg.sourceforge.net
110ce984 3 * 1998, 2015
7179962a
PO
4 *
5 * SARG donations:
6 * please look at http://sarg.sourceforge.net/donations.php
ac422f9b
FM
7 * Support:
8 * http://sourceforge.net/projects/sarg/forums/forum/363374
7179962a
PO
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
965c4a6f
FM
30#ifdef HAVE_LDAP_H
31#define LDAP_DEPRECATED 1
32
7179962a
PO
33#include <ldap.h>
34#include <ldap_cdefs.h>
35#include <ldap_features.h>
fd75cd90
FM
36
37#if defined(HAVE_ICONV_H)
38#include <iconv.h>
39#define USE_ICONV 1
40#endif //HAVE_ICONV_H
41
965c4a6f 42#endif //HAVE_LDAP_H
7179962a 43
965c4a6f
FM
44enum UserTabEnum
45{
9bd92830
FM
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
965c4a6f
FM
52};
53
54enum UserTabEnum which_usertab=UTT_None;
7179962a 55
965c4a6f 56static char *userfile=NULL;
7179962a 57
965c4a6f
FM
58#ifdef HAVE_LDAP_H
59static LDAP *ldap_handle=NULL;
60#endif //HAVE_LDAP_H
61
fd75cd90
FM
62#ifdef USE_ICONV
63//! iconv conversion descriptor to convert the string returned by LDAP.
64static iconv_t ldapiconv=(iconv_t)-1;
65//! Buffer to store the converted string.
66static char *ldapconvbuffer=NULL;
67//! Size of the converted string buffer.
68static int ldapconvbuffersize=0;
69#endif
70
965c4a6f
FM
71static void init_file_usertab(const char *UserTabFile)
72{
9bd92830
FM
73 FILE *fp_usr;
74 long int nreg;
75 char buf[MAXLEN];
76 int z1, z2;
965c4a6f 77
9bd92830 78 if((fp_usr=fopen(UserTabFile,"r"))==NULL) {
af961877 79 debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),UserTabFile,strerror(errno));
9bd92830
FM
80 exit(EXIT_FAILURE);
81 }
82 if (fseek(fp_usr, 0, SEEK_END)==-1) {
af961877 83 debuga(__FILE__,__LINE__,_("Failed to move till the end of file \"%s\": %s\n"),UserTabFile,strerror(errno));
9bd92830
FM
84 exit(EXIT_FAILURE);
85 }
86 nreg = ftell(fp_usr);
87 if (nreg<0) {
af961877 88 debuga(__FILE__,__LINE__,_("Cannot get the size of file \"%s\"\n"),UserTabFile);
9bd92830
FM
89 exit(EXIT_FAILURE);
90 }
91 nreg += 100;
92 if (fseek(fp_usr, 0, SEEK_SET)==-1) {
af961877 93 debuga(__FILE__,__LINE__,_("Failed to rewind file \"%s\": %s\n"),UserTabFile,strerror(errno));
9bd92830
FM
94 exit(EXIT_FAILURE);
95 }
96 if((userfile=(char *) malloc(nreg))==NULL){
af961877 97 debuga(__FILE__,__LINE__,_("ERROR: Cannot load. Memory fault\n"));
9bd92830
FM
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"
af961877 108 debuga(__FILE__,__LINE__,_("The list of users is too long in file \"%s\"\n"),UserTabFile);
9bd92830
FM
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"
af961877 117 debuga(__FILE__,__LINE__,_("The list of users is too long in file \"%s\"\n"),UserTabFile);
9bd92830
FM
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';
204781f4 126 if (fclose(fp_usr)==EOF) {
af961877 127 debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),UserTabFile,strerror(errno));
204781f4
FM
128 exit(EXIT_FAILURE);
129 }
965c4a6f
FM
130}
131
132static void get_usertab_name(const char *user,char *name,int namelen)
133{
9bd92830
FM
134 char warea[MAXLEN];
135 char *str;
965c4a6f 136
9bd92830
FM
137 sprintf(warea,"\t%s\n",user);
138 if((str=(char *) strstr(userfile,warea)) == (char *) NULL ) {
a87d4d11 139 safe_strcpy(name,user,namelen);
9bd92830
FM
140 } else {
141 str=strchr(str+1,'\n');
142 str++;
a87d4d11 143 namelen--;
9bd92830
FM
144 for(z1=0; *str != '\t' && z1<namelen ; z1++) {
145 name[z1]=*str++;
146 }
a87d4d11 147 name[z1]='\0';
9bd92830 148 }
965c4a6f
FM
149}
150
151#ifdef HAVE_LDAP_H
152static void init_ldap_usertab(void) {
0ee7618e
FM
153 char *ldapuri;
154 LDAPURLDesc url;
155 int rc;
156
9bd92830 157 ldap_handle = NULL;
0ee7618e
FM
158
159 /* Setting LDAP connection and initializing cache */
160 memset(&url,0,sizeof(url));
161 url.lud_scheme = "ldap";
162 url.lud_host = LDAPHost;
163 url.lud_port = LDAPPort;
164 url.lud_scope = LDAP_SCOPE_DEFAULT;
165 ldapuri = ldap_url_desc2str(&url);
166 if (ldapuri==NULL) {
af961877 167 debuga(__FILE__,__LINE__,_("Cannot prepare ldap URI for server %s on port %d\n"),LDAPHost,LDAPPort);
9bd92830
FM
168 exit(EXIT_FAILURE);
169 }
7179962a 170
0ee7618e
FM
171 rc = ldap_initialize(&ldap_handle, ldapuri);
172 if (rc != LDAP_SUCCESS) {
af961877 173 debuga(__FILE__,__LINE__,_("Unable to connect to LDAP server %s on port %d: %d (%s)\n"), LDAPHost, LDAPPort, rc, ldap_err2string(rc));
0ee7618e
FM
174 exit(EXIT_FAILURE);
175 }
176 ldap_memfree(ldapuri);
177
52fe76a6 178 if (ldap_set_option(ldap_handle, LDAP_OPT_REFERRALS, LDAP_OPT_OFF) != LDAP_OPT_SUCCESS) {
af961877 179 debuga(__FILE__,__LINE__,_("Could not disable LDAP_OPT_REFERRALS\n"));
52fe76a6
FM
180 exit(EXIT_FAILURE);
181 }
9bd92830
FM
182 int ldap_protocol_version = LDAPProtocolVersion;
183 if (ldap_set_option(ldap_handle, LDAP_OPT_PROTOCOL_VERSION, &ldap_protocol_version) != LDAP_SUCCESS) {
af961877 184 debuga(__FILE__,__LINE__,_("Could not set LDAP protocol version %d\n"), ldap_protocol_version);
9bd92830
FM
185 exit(EXIT_FAILURE);
186 }
7179962a 187
9bd92830 188 /* Bind to the LDAP server. */
9bd92830
FM
189 rc = ldap_simple_bind_s( ldap_handle, LDAPBindDN, LDAPBindPW );
190 if ( rc != LDAP_SUCCESS ) {
af961877 191 debuga(__FILE__,__LINE__,_("Cannot bind to LDAP server: %s\n"), ldap_err2string(rc));
9bd92830
FM
192 exit(EXIT_FAILURE);
193 }
965c4a6f 194
fd75cd90
FM
195#ifdef USE_ICONV
196 // prepare for the string conversion
197 if (LDAPNativeCharset[0]!='\0') {
198 ldapiconv = iconv_open( LDAPNativeCharset, "UTF-8" );
199 if (ldapiconv==(iconv_t)-1) {
af961877 200 debuga(__FILE__,__LINE__,_("iconv cannot convert from UTF-8 to %s: %s\n"),LDAPNativeCharset,strerror(errno));
fd75cd90
FM
201 exit(EXIT_FAILURE);
202 }
203 }
204 ldapconvbuffer=NULL;
205 ldapconvbuffersize=0;
206#endif
207
9bd92830 208 /* Initializing cache */
7179962a 209
9bd92830 210 init_cache();
7179962a
PO
211}
212
fd75cd90
FM
213const char * charset_convert( const char * str_in, const char * charset_to )
214{
215#ifdef USE_ICONV
216 size_t return_value;
217 const char * str_in_orig;
218 char * str_out;
219 size_t str_in_len;
220 size_t str_out_len;
221
26ed86a9 222 str_in_len = strlen( str_in ) + 1;//process the terminating NUL too
fd75cd90
FM
223 str_out_len = ( 2 * str_in_len );
224 if (ldapconvbuffer==NULL || ldapconvbuffersize<str_out_len) {
225 ldapconvbuffersize=str_out_len;
26ed86a9 226 str_out = realloc(ldapconvbuffer,ldapconvbuffersize);
fd75cd90 227 if (!str_out) {
af961877 228 debuga(__FILE__,__LINE__,_("Not enough memory to convert a LDAP returned string: %lu bytes required\n"),(unsigned long int)str_out_len);
fd75cd90
FM
229 exit(EXIT_FAILURE);
230 }
231 ldapconvbuffer = str_out;
232 } else {
233 str_out = ldapconvbuffer;
26ed86a9 234 str_out_len = ldapconvbuffersize;
fd75cd90
FM
235 }
236 str_in_orig = str_in;
237 return_value = iconv(ldapiconv, (ICONV_CONST char **)&str_in, &str_in_len, &str_out, &str_out_len );
238 if ( return_value == ( size_t ) -1 ) {
2eb432c7 239 /* TRANSLATORS: The message is followed by the reason for the failure. */
af961877 240 debuga(__FILE__,__LINE__,_("iconv failed on string \"%s\":\n"),str_in_orig);
fd75cd90
FM
241 switch ( errno ) {
242 /* See "man 3 iconv" for an explanation. */
243 case EILSEQ:
af961877 244 debuga(__FILE__,__LINE__,_("Invalid multibyte sequence.\n"));
fd75cd90
FM
245 break;
246 case EINVAL:
af961877 247 debuga(__FILE__,__LINE__,_("Incomplete multibyte sequence.\n"));
fd75cd90
FM
248 break;
249 case E2BIG:
af961877 250 debuga(__FILE__,__LINE__,_("No more room.\n"));
fd75cd90
FM
251 break;
252 default:
af961877 253 debuga(__FILE__,__LINE__,_("Error: %s.\n"),strerror( errno ));
fd75cd90
FM
254 }
255 exit(EXIT_FAILURE);
256 }
257 return(ldapconvbuffer);
258#else //USE_ICONV
259 return(str_in);
260#endif //USE_ICONV
261}
262
965c4a6f
FM
263static void get_ldap_name(const char *userlogin,char *mappedname,int namelen)
264{
9bd92830
FM
265 /* Start searching username in cache */
266 // According to rfc2254 section 4, only *()\ and NUL must be escaped. This list is rather conservative !
267 const char strictchars[] = " ~!@^&(){}|<>?:;\"\'\\[]`,\r\n\0";
268 char filtersearch[256], *searched_in_cache;
269 char searchloginname[3*MAX_USER_LEN];
270 char *attr, **vals;
fd75cd90 271 const char *attr_out;
0ee7618e 272 const char *ptr;
9bd92830
FM
273 LDAPMessage *result, *e;
274 BerElement *ber;
275 int i;
d1d8390c
FM
276 int slen;
277 int rc;
0bfbafc0 278 char *attrs[2];
0ee7618e
FM
279
280 searched_in_cache = search_in_cache(userlogin);
281 if (searched_in_cache!=NULL) {
a87d4d11 282 safe_strcpy(mappedname, searched_in_cache,namelen);
0ee7618e
FM
283 return;
284 }
1b048c43 285
0ee7618e 286 // escape characters according to rfc2254 section 4
d1d8390c 287 for (slen=0 , ptr=userlogin ; slen<sizeof(searchloginname)-1 && *ptr ; ptr++) {
0ee7618e 288 if (strchr(strictchars,*ptr)) {
d1d8390c 289 if (slen+3>=sizeof(searchloginname)-1) break;
63413116 290 slen+=sprintf(searchloginname+slen,"\\%02X",*ptr);
9bd92830 291 } else {
d1d8390c 292 searchloginname[slen++]=*ptr;
9bd92830
FM
293 }
294 }
d1d8390c
FM
295 searchloginname[slen]='\0';
296
297 i=0;
298 ptr=LDAPFilterSearch;
299 while (i<sizeof(filtersearch)-1 && *ptr) {
300 if (ptr[0]=='%' && ptr[1]=='s') {
301 if (i+slen>=sizeof(filtersearch)) break;
302 memcpy(filtersearch+i,searchloginname,slen);
303 i+=slen;
304 ptr+=2;
305 } else {
306 filtersearch[i++]=*ptr++;
307 }
308 }
309 filtersearch[i]='\0';
965c4a6f 310
0ee7618e
FM
311 /* Search record(s) in LDAP base */
312 attrs[0]=LDAPTargetAttr;
0bfbafc0 313 attrs[1]=NULL;
d1d8390c 314 rc= ldap_search_ext_s(ldap_handle, LDAPBaseSearch, LDAP_SCOPE_SUBTREE, filtersearch, attrs, 0, NULL, NULL, NULL, -1, &result);
0ee7618e 315 if (rc != LDAP_SUCCESS) {
af961877 316 debuga(__FILE__,__LINE__,_("LDAP search failed: %s\nlooking for \"%s\" at or below \"%s\"\n"), ldap_err2string(rc),filtersearch,LDAPBaseSearch);
a87d4d11 317 safe_strcpy(mappedname,userlogin,namelen);
0ee7618e
FM
318 return;
319 }
965c4a6f 320
0ee7618e
FM
321 if (!(e = ldap_first_entry(ldap_handle, result))) {
322 insert_to_cache(userlogin, userlogin);
a87d4d11 323 safe_strcpy(mappedname, userlogin,namelen);
0ee7618e
FM
324 return;
325 }
965c4a6f 326
0ee7618e
FM
327 for (attr = ldap_first_attribute(ldap_handle, e, &ber); attr != NULL; attr = ldap_next_attribute(ldap_handle, e, ber)) {
328 if (!strcasecmp(attr, LDAPTargetAttr)) {
329 if ((vals = (char **)ldap_get_values(ldap_handle, e, attr))!=NULL) {
fd75cd90
FM
330 attr_out = charset_convert( vals[0], LDAPNativeCharset );
331 insert_to_cache(userlogin, attr_out);
332 safe_strcpy(mappedname, attr_out, namelen);
0ee7618e 333 ldap_memfree(vals);
9bd92830 334 }
0ee7618e
FM
335 ldap_memfree(attr);
336 break;
337 }
338 ldap_memfree(attr);
9bd92830 339 }
0ee7618e 340 ldap_msgfree(result);
965c4a6f
FM
341}
342#endif //HAVE_LDAP_H
343
344void init_usertab(const char *UserTabFile)
345{
9bd92830 346 if (strcmp(UserTabFile, "ldap") == 0) {
2eb432c7
FM
347 if(debug) {
348 /* TRANSLATORS: The %s may be the string "ldap" or a file name.*/
af961877 349 debuga(__FILE__,__LINE__,_("Loading User table from \"%s\"\n"),UserTabFile);
2eb432c7 350 }
965c4a6f 351#ifdef HAVE_LDAP_H
9bd92830
FM
352 which_usertab=UTT_Ldap;
353 init_ldap_usertab();
965c4a6f 354#else
af961877 355 debuga(__FILE__,__LINE__,_("LDAP module not compiled in sarg\n"));
9bd92830 356 exit(EXIT_FAILURE);
965c4a6f 357#endif //HAVE_LDAP_H
9bd92830
FM
358 } else if (UserTabFile[0] != '\0') {
359 if(debug)
af961877 360 debuga(__FILE__,__LINE__,_("Loading User table from \"%s\"\n"),UserTabFile);
9bd92830
FM
361 which_usertab=UTT_File;
362 init_file_usertab(UserTabFile);
363 } else {
364 which_usertab=UTT_None;
365 }
965c4a6f
FM
366}
367
368void user_find(char *mappedname, int namelen, const char *userlogin)
369{
9bd92830
FM
370 if (which_usertab==UTT_File) {
371 get_usertab_name(userlogin,mappedname,namelen);
372 }
965c4a6f 373#ifdef HAVE_LDAP_H
9bd92830
FM
374 else if (which_usertab==UTT_Ldap) {
375 get_ldap_name(userlogin,mappedname,namelen);
376 }
965c4a6f 377#endif //HAVE_LDAP_H
9bd92830 378 else {
a87d4d11 379 safe_strcpy(mappedname,userlogin,namelen);
9bd92830 380 }
7179962a
PO
381}
382
965c4a6f
FM
383void close_usertab(void)
384{
385#ifdef HAVE_LDAP_H
9bd92830
FM
386 if (ldap_handle) {
387 destroy_cache();
388 ldap_unbind(ldap_handle);
389 ldap_handle=NULL;
390 }
965c4a6f 391#endif //HAVE_LDAP_H
fd75cd90
FM
392#ifdef USE_ICONV
393 if (ldapiconv!=(iconv_t)-1) {
394 iconv_close (ldapiconv);
395 ldapiconv=(iconv_t)-1;
396 }
397 if (ldapconvbuffer) {
398 free(ldapconvbuffer);
399 ldapconvbuffer=NULL;
400 }
401#endif // USE_ICONV
9bd92830
FM
402 if(userfile) {
403 free(userfile);
404 userfile=NULL;
405 }
7179962a
PO
406}
407