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(_("(usertab) Cannot open file %s: %s\n"),UserTabFile
,strerror(errno
));
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
));
88 debuga(_("Cannot get the size of file %s\n"),UserTabFile
);
92 if (fseek(fp_usr
, 0, SEEK_SET
)==-1) {
93 debuga(_("Failed to rewind the usertab file %s: %s\n"),UserTabFile
,strerror(errno
));
96 if((userfile
=(char *) malloc(nreg
))==NULL
){
97 debuga(_("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(_("The list of the users is too long in your %s file.\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(_("The list of the users is too long in your %s file.\n"),UserTabFile
);
120 userfile
[z2
++]=buf
[z1
++];
122 while(userfile
[z2
-1]==' ') z2
--;
129 static void get_usertab_name(const char *user
,char *name
,int namelen
)
134 sprintf(warea
,"\t%s\n",user
);
135 if((str
=(char *) strstr(userfile
,warea
)) == (char *) NULL
) {
136 safe_strcpy(name
,user
,namelen
);
138 str
=strchr(str
+1,'\n');
141 for(z1
=0; *str
!= '\t' && z1
<namelen
; z1
++) {
149 static void init_ldap_usertab(void) {
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
);
164 debuga(_("Cannot prepare ldap URI for server %s on port %d\n"),LDAPHost
,LDAPPort
);
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
));
173 ldap_memfree(ldapuri
);
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"));
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
);
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
));
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
));
202 ldapconvbuffersize
=0;
205 /* Initializing cache */
210 const char * charset_convert( const char * str_in
, const char * charset_to
)
214 const char * str_in_orig
;
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
);
225 debuga(_("Not enough memory to convert a LDAP returned string: %lu bytes required\n"),(unsigned long int)str_out_len
);
228 ldapconvbuffer
= str_out
;
230 str_out
= ldapconvbuffer
;
231 str_out_len
= ldapconvbuffersize
;
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
);
238 /* See "man 3 iconv" for an explanation. */
240 debuga(_("Invalid multibyte sequence.\n"));
243 debuga(_("Incomplete multibyte sequence.\n"));
246 debuga(_("No more room.\n"));
249 debuga(_("Error: %s.\n"),strerror( errno
));
253 return(ldapconvbuffer
);
259 static void get_ldap_name(const char *userlogin
,char *mappedname
,int namelen
)
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
];
267 const char *attr_out
;
269 LDAPMessage
*result
, *e
;
276 searched_in_cache
= search_in_cache(userlogin
);
277 if (searched_in_cache
!=NULL
) {
278 safe_strcpy(mappedname
, searched_in_cache
,namelen
);
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
);
288 searchloginname
[slen
++]=*ptr
;
291 searchloginname
[slen
]='\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
);
302 filtersearch
[i
++]=*ptr
++;
305 filtersearch
[i
]='\0';
307 /* Search record(s) in LDAP base */
308 attrs
[0]=LDAPTargetAttr
;
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
);
318 if (!(e
= ldap_first_entry(ldap_handle
, result
))) {
319 insert_to_cache(userlogin
, userlogin
);
320 safe_strcpy(mappedname
, userlogin
,namelen
);
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
);
337 ldap_msgfree(result
);
341 void init_usertab(const char *UserTabFile
)
343 if (strcmp(UserTabFile
, "ldap") == 0) {
345 debuga(_("Loading User table: %s\n"),UserTabFile
);
347 which_usertab
=UTT_Ldap
;
350 debuga(_("LDAP module not compiled in sarg\n"));
353 } else if (UserTabFile
[0] != '\0') {
355 debuga(_("Loading User table: %s\n"),UserTabFile
);
356 which_usertab
=UTT_File
;
357 init_file_usertab(UserTabFile
);
359 which_usertab
=UTT_None
;
363 void user_find(char *mappedname
, int namelen
, const char *userlogin
)
365 if (which_usertab
==UTT_File
) {
366 get_usertab_name(userlogin
,mappedname
,namelen
);
369 else if (which_usertab
==UTT_Ldap
) {
370 get_ldap_name(userlogin
,mappedname
,namelen
);
374 safe_strcpy(mappedname
,userlogin
,namelen
);
378 void close_usertab(void)
383 ldap_unbind(ldap_handle
);
388 if (ldapiconv
!=(iconv_t
)-1) {
389 iconv_close (ldapiconv
);
390 ldapiconv
=(iconv_t
)-1;
392 if (ldapconvbuffer
) {
393 free(ldapconvbuffer
);