2 * SARG Squid Analysis Report Generator http://sarg.sourceforge.net
6 * please look at http://sarg.sourceforge.net/donations.php
8 * http://sourceforge.net/projects/sarg/forums/forum/363374
9 * ---------------------------------------------------------------------
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.
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.
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.
27 #include "include/conf.h"
28 #include "include/defs.h"
31 #define LDAP_DEPRECATED 1
34 #include <ldap_cdefs.h>
35 #include <ldap_features.h>
37 #if defined(HAVE_ICONV_H)
46 //! Users matched against the ::UserTabFile file.
48 //! Users matched agains a LDAP.
50 //! No user matching performed.
54 enum UserTabEnum which_usertab
=UTT_None
;
56 static char *userfile
=NULL
;
59 static LDAP
*ldap_handle
=NULL
;
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;
71 static void init_file_usertab(const char *UserTabFile
)
78 if((fp_usr
=fopen(UserTabFile
,"r"))==NULL
) {
79 debuga(__FILE__
,__LINE__
,_("Cannot open file \"%s\": %s\n"),UserTabFile
,strerror(errno
));
82 if (fseek(fp_usr
, 0, SEEK_END
)==-1) {
83 debuga(__FILE__
,__LINE__
,_("Failed to move till the end of file \"%s\": %s\n"),UserTabFile
,strerror(errno
));
88 debuga(__FILE__
,__LINE__
,_("Cannot get the size of file \"%s\"\n"),UserTabFile
);
92 if (fseek(fp_usr
, 0, SEEK_SET
)==-1) {
93 debuga(__FILE__
,__LINE__
,_("Failed to rewind file \"%s\": %s\n"),UserTabFile
,strerror(errno
));
96 if((userfile
=(char *) malloc(nreg
))==NULL
){
97 debuga(__FILE__
,__LINE__
,_("ERROR: Cannot load. Memory fault\n"));
102 while(fgets(buf
,sizeof(buf
),fp_usr
)!=NULL
) {
103 if (buf
[0]=='#') continue;
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(__FILE__
,__LINE__
,_("The list of users is too long in file \"%s\"\n"),UserTabFile
);
111 userfile
[z2
++]=buf
[z1
++];
113 while(buf
[z1
] && (unsigned char)buf
[z1
]<=' ') z1
++;
115 while(buf
[z1
] && (unsigned char)buf
[z1
]>=' ') {
116 if (z2
+2>=nreg
) { //need at least 2 additional bytes for "\t\0"
117 debuga(__FILE__
,__LINE__
,_("The list of users is too long in file \"%s\"\n"),UserTabFile
);
120 userfile
[z2
++]=buf
[z1
++];
122 while(userfile
[z2
-1]==' ') z2
--;
126 if (fclose(fp_usr
)==EOF
) {
127 debuga(__FILE__
,__LINE__
,_("Read error in \"%s\": %s\n"),UserTabFile
,strerror(errno
));
132 static void get_usertab_name(const char *user
,char *name
,int namelen
)
137 sprintf(warea
,"\t%s\n",user
);
138 if((str
=(char *) strstr(userfile
,warea
)) == (char *) NULL
) {
139 safe_strcpy(name
,user
,namelen
);
141 str
=strchr(str
+1,'\n');
144 for(z1
=0; *str
!= '\t' && z1
<namelen
; z1
++) {
152 static void init_ldap_usertab(void) {
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
);
167 debuga(__FILE__
,__LINE__
,_("Cannot prepare ldap URI for server %s on port %d\n"),LDAPHost
,LDAPPort
);
171 rc
= ldap_initialize(&ldap_handle
, ldapuri
);
172 if (rc
!= LDAP_SUCCESS
) {
173 debuga(__FILE__
,__LINE__
,_("Unable to connect to LDAP server %s on port %d: %d (%s)\n"), LDAPHost
, LDAPPort
, rc
, ldap_err2string(rc
));
176 ldap_memfree(ldapuri
);
178 if (ldap_set_option(ldap_handle
, LDAP_OPT_REFERRALS
, LDAP_OPT_OFF
) != LDAP_OPT_SUCCESS
) {
179 debuga(__FILE__
,__LINE__
,_("Could not disable LDAP_OPT_REFERRALS\n"));
182 int ldap_protocol_version
= LDAPProtocolVersion
;
183 if (ldap_set_option(ldap_handle
, LDAP_OPT_PROTOCOL_VERSION
, &ldap_protocol_version
) != LDAP_SUCCESS
) {
184 debuga(__FILE__
,__LINE__
,_("Could not set LDAP protocol version %d\n"), ldap_protocol_version
);
188 /* Bind to the LDAP server. */
189 rc
= ldap_simple_bind_s( ldap_handle
, LDAPBindDN
, LDAPBindPW
);
190 if ( rc
!= LDAP_SUCCESS
) {
191 debuga(__FILE__
,__LINE__
,_("Cannot bind to LDAP server: %s\n"), ldap_err2string(rc
));
196 // prepare for the string conversion
197 if (LDAPNativeCharset
[0]!='\0') {
198 ldapiconv
= iconv_open( LDAPNativeCharset
, "UTF-8" );
199 if (ldapiconv
==(iconv_t
)-1) {
200 debuga(__FILE__
,__LINE__
,_("iconv cannot convert from UTF-8 to %s: %s\n"),LDAPNativeCharset
,strerror(errno
));
205 ldapconvbuffersize
=0;
208 /* Initializing cache */
213 const char * charset_convert( const char * str_in
, const char * charset_to
)
217 const char * str_in_orig
;
222 str_in_len
= strlen( str_in
) + 1;//process the terminating NUL too
223 str_out_len
= ( 2 * str_in_len
);
224 if (ldapconvbuffer
==NULL
|| ldapconvbuffersize
<str_out_len
) {
225 ldapconvbuffersize
=str_out_len
;
226 str_out
= realloc(ldapconvbuffer
,ldapconvbuffersize
);
228 debuga(__FILE__
,__LINE__
,_("Not enough memory to convert a LDAP returned string: %lu bytes required\n"),(unsigned long int)str_out_len
);
231 ldapconvbuffer
= str_out
;
233 str_out
= ldapconvbuffer
;
234 str_out_len
= ldapconvbuffersize
;
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 ) {
239 /* TRANSLATORS: The message is followed by the reason for the failure. */
240 debuga(__FILE__
,__LINE__
,_("iconv failed on string \"%s\":\n"),str_in_orig
);
242 /* See "man 3 iconv" for an explanation. */
244 debuga(__FILE__
,__LINE__
,_("Invalid multibyte sequence.\n"));
247 debuga(__FILE__
,__LINE__
,_("Incomplete multibyte sequence.\n"));
250 debuga(__FILE__
,__LINE__
,_("No more room.\n"));
253 debuga(__FILE__
,__LINE__
,_("Error: %s.\n"),strerror( errno
));
257 return(ldapconvbuffer
);
263 static void get_ldap_name(const char *userlogin
,char *mappedname
,int namelen
)
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
];
271 const char *attr_out
;
273 LDAPMessage
*result
, *e
;
280 searched_in_cache
= search_in_cache(userlogin
);
281 if (searched_in_cache
!=NULL
) {
282 safe_strcpy(mappedname
, searched_in_cache
,namelen
);
286 // escape characters according to rfc2254 section 4
287 for (slen
=0 , ptr
=userlogin
; slen
<sizeof(searchloginname
)-1 && *ptr
; ptr
++) {
288 if (strchr(strictchars
,*ptr
)) {
289 if (slen
+3>=sizeof(searchloginname
)-1) break;
290 slen
+=sprintf(searchloginname
+slen
,"\\%02X",*ptr
);
292 searchloginname
[slen
++]=*ptr
;
295 searchloginname
[slen
]='\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
);
306 filtersearch
[i
++]=*ptr
++;
309 filtersearch
[i
]='\0';
311 /* Search record(s) in LDAP base */
312 attrs
[0]=LDAPTargetAttr
;
314 rc
= ldap_search_ext_s(ldap_handle
, LDAPBaseSearch
, LDAP_SCOPE_SUBTREE
, filtersearch
, attrs
, 0, NULL
, NULL
, NULL
, -1, &result
);
315 if (rc
!= LDAP_SUCCESS
) {
316 debuga(__FILE__
,__LINE__
,_("LDAP search failed: %s\nlooking for \"%s\" at or below \"%s\"\n"), ldap_err2string(rc
),filtersearch
,LDAPBaseSearch
);
317 safe_strcpy(mappedname
,userlogin
,namelen
);
321 if (!(e
= ldap_first_entry(ldap_handle
, result
))) {
322 insert_to_cache(userlogin
, userlogin
);
323 safe_strcpy(mappedname
, userlogin
,namelen
);
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
) {
330 attr_out
= charset_convert( vals
[0], LDAPNativeCharset
);
331 insert_to_cache(userlogin
, attr_out
);
332 safe_strcpy(mappedname
, attr_out
, namelen
);
340 ldap_msgfree(result
);
344 void init_usertab(const char *UserTabFile
)
346 if (strcmp(UserTabFile
, "ldap") == 0) {
348 /* TRANSLATORS: The %s may be the string "ldap" or a file name.*/
349 debuga(__FILE__
,__LINE__
,_("Loading User table from \"%s\"\n"),UserTabFile
);
352 which_usertab
=UTT_Ldap
;
355 debuga(__FILE__
,__LINE__
,_("LDAP module not compiled in sarg\n"));
358 } else if (UserTabFile
[0] != '\0') {
360 debuga(__FILE__
,__LINE__
,_("Loading User table from \"%s\"\n"),UserTabFile
);
361 which_usertab
=UTT_File
;
362 init_file_usertab(UserTabFile
);
364 which_usertab
=UTT_None
;
368 void user_find(char *mappedname
, int namelen
, const char *userlogin
)
370 if (which_usertab
==UTT_File
) {
371 get_usertab_name(userlogin
,mappedname
,namelen
);
374 else if (which_usertab
==UTT_Ldap
) {
375 get_ldap_name(userlogin
,mappedname
,namelen
);
379 safe_strcpy(mappedname
,userlogin
,namelen
);
383 void close_usertab(void)
388 ldap_unbind(ldap_handle
);
393 if (ldapiconv
!=(iconv_t
)-1) {
394 iconv_close (ldapiconv
);
395 ldapiconv
=(iconv_t
)-1;
397 if (ldapconvbuffer
) {
398 free(ldapconvbuffer
);