Hello oops-users,
1096976240.000 2246 192.168.1.25 TCP_MISS/200 5602 GET http://zadorno.com/ kot
DIRECT/zadorno.com text/html
1096976242.000 414 192.168.1.25 TCP_MISS/200 2407 GET
http://zadorno.com/archives/dance.gif kot DIRECT/zadorno.com image/gif
1096976242.000 496 192.168.1.25 TCP_MISS/200 5857 GET
http://zadorno.com/archives/Edos_05-10-012-1.jpg kot DIRECT/zadorno.com image/jpeg
1096976242.000 2800 192.168.1.25 TCP_ERROR/200 4027 GET http://zadorno.com/zadorno.css
kot DIRECT/zadorno.com text/css
и всё, дальше не отдаёт :( почему так может случаться? В логах совсем
пусто :((( код ошибки не при делах - обрывается и просто так :(
NTLM, т.е. IE работает прекрасно, а вот опера... Может я чего
проглядел?
--
Best regards,
Konstantin Nikonenko http://www.kot.dp.ua/
P.S. Теперь как отдельный модуль ;)
В IIS разрешить внутреннюю проверку и обычным текстом, анонимус
запретить ;)
/usr/local/src/oops# grep -Ri win_http * | grep -v "win_http.c"
src/modules.c: insert_module(&win_http.general, (struct general_module
**)&auth_first);
src/modules.h:extern struct auth_module win_http;
src/modules/Makefile.in: [EMAIL PROTECTED]@ \
src/modules/Makefile: win_http.so \
module pam {
# This line is string in client's auth request header
realm Enter You Login and Password to access.
scheme Basic
service oops
template /usr/local/oops/auth_template.html
}
module win_http {
# This line is string in client's auth request header
realm Enter You Login and Password to access.
# Possible are 'Basic' or 'NTLM' only
# If basic is set - we never request to client other scheme
# If NTLM auth is fails proxy request Basic Auth and only after there denied
scheme NTLM
# NT server IP (only), where all users are live.
nt_server 192.168.1.6
# Now we are supported only HTTP service helper
nt_port HTTP
template /usr/local/oops/auth_template.html
}
/*
Copyright (C) 1999 Igor Khasilev, [EMAIL PROTECTED]
Copyright (C) 2003,2004 Konstantin Nikonenko, <[EMAIL PROTECTED]>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* From Kostya:
to setup Win IIS Server remove flag from anonymous login to main page,
allow Plain text auth and internal mechanism.
You can manupalete allow user or deny from real time ;)
*/
#include "../oops.h"
#include "../modules.h"
#define MODULE_NAME "win_http"
#define MODULE_INFO "Auth using NTLM or Basic on Win2k HTTP server"
#define MODULE_BR14 "Auth using Win2k HTTP server"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined(MODULES)
#define MODPREF
#else
#define MODPREF static
#endif
MODPREF char module_type = MODULE_AUTH;
MODPREF char module_name[] = MODULE_NAME;
MODPREF char module_info[MODINFOLEN] = MODULE_BR14;
MODPREF int mod_load(void);
MODPREF int mod_unload(void);
MODPREF int mod_config_beg(int), mod_config_end(int),
mod_config(char*,int), mod_run(void);
MODPREF int auth(int so, struct group *group, struct request* rq, int
*flags);
struct auth_module win_http = {
{
NULL, NULL,
MODULE_NAME,
mod_load,
mod_unload,
mod_config_beg,
mod_config_end,
mod_config,
NULL,
MODULE_AUTH,
MODULE_INFO,
mod_run
},
auth
};
static pthread_rwlock_t pwf_lock;
static char *pwds = NULL;
static char *template = NULL;
static time_t pwf_mtime, pwf_check_time;
static time_t pwf_template_mtime, pwf_template_check_time;
static int pwf_template_len;
static char pwf_name[MAXPATHLEN];
static char pwf_template[MAXPATHLEN];
static char pwf_charset[64];
static char realm[64];
static enum {Basic,NTLM} scheme = Basic;
static char *authreq = NULL;
static int authreqlen;
static char *authreqfmt = "%s\nProxy-Authenticate: Basic realm=\"%s\"";
static char *authreqfmt_b = "%s\n realm=\"%s\"";
static char *std_template = "\n<body>Authorization to proxy-server
failed.<p><hr>\n\
<i><font size=-1>by \'win_http\' module to Oops.";
static int std_template_len;
static int pwf_charset_len;
static int badschlen;
static char *badsch=NULL;
static char *badschfmt = "HTTP/1.0 407 Proxy Authentication required\n\
Proxy-Authenticate: %s realm=\"%s\"\n\n\
<body>Authorization to proxy-server failed.<p>\n\
Your browser proposed unsupported scheme\n\
<hr>\n\
<i><font size=-1>by \'Win-http\' module to Oops.";
#define RDLOCK_PWF_CONFIG pthread_rwlock_rdlock(&pwf_lock)
#define WRLOCK_PWF_CONFIG pthread_rwlock_wrlock(&pwf_lock)
#define UNLOCK_PWF_CONFIG pthread_rwlock_unlock(&pwf_lock)
static void reload_pwf_template(void);
static void check_pwf_template_age(void);
static void send_auth_req(int, struct request *);
static int read_from(int , char *, int type); // Functions to make dialog
with NT HTTP
static int send_to(int, char *, int type); // service about NTLM auth.
types: 0 - server, 1-client, 2-Basic
static char nt_server[16]; // NT Server IP, not name
static unsigned int nt_port=80; // port, where we send NTLM structures
static struct servent *sp;
static struct sockaddr_in hin;
static int unit, s;
static char client_data[2047];
#if !defined(SOLARIS)
pthread_mutex_t crypt_lock;
#endif
int
mod_run(void)
{
return(MOD_CODE_OK);
}
int
mod_load(void)
{
snprintf(module_info, sizeof(module_info)-1, MODULE_INFO);
pthread_rwlock_init(&pwf_lock, NULL);
#if !defined(SOLARIS)
pthread_mutex_init(&crypt_lock, NULL);
#endif
std_template_len = strlen(std_template);
printf("WIN_HTTP started\n");
return(MOD_CODE_OK);
}
int
mod_unload(void)
{
printf("Win_http stopped\n");
pthread_rwlock_destroy(&pwf_lock);
return(MOD_CODE_OK);
}
int
mod_config_beg(int i)
{
WRLOCK_PWF_CONFIG ;
if ( pwds ) free(pwds); pwds = 0;
if ( authreq ) free(authreq); authreq = 0;
if ( badsch ) free(badsch); badsch = 0;
if ( template ) free(template); template = 0;
pwf_name[0] = 0;
pwf_template[0] = 0;
pwf_charset[0] = 0;
pwf_mtime = pwf_template_mtime = 0;
strcpy(realm, "oops") ;
nt_server[0] = 0;
scheme = Basic;
pwf_check_time = 0 ;
pwf_mtime = 0 ;
UNLOCK_PWF_CONFIG ;
return(MOD_CODE_OK);
}
int
mod_config_end(int i)
{
char *sch="None";
WRLOCK_PWF_CONFIG ;
if ( scheme == Basic ) {
sch = "Basic";
// If basic is set - we never request to client other scheme
authreqfmt = authreqfmt_b;
} else {
if ( scheme == NTLM ){
sch = "NTLM";
} else {
my_xlog(OOPS_LOG_NOTICE|OOPS_LOG_DBG|OOPS_LOG_INFORM, "Win_http: Unsupported
scheme\n");
UNLOCK_PWF_CONFIG ;
return(MOD_CODE_ERR);
}
}
authreqlen = 0;
authreq = malloc(strlen(authreqfmt)+1+strlen(realm)+strlen(sch));
if ( authreq ) {
sprintf(authreq, authreqfmt, sch, realm);
authreqlen = strlen(authreq);
}
badschlen = 0;
badsch = malloc(strlen(badschfmt)+1+strlen(realm)+strlen(sch));
if ( badsch ) {
sprintf(badsch, badschfmt, sch, realm);
badschlen = strlen(badsch);
}
if ( pwf_template[0] )
reload_pwf_template();
UNLOCK_PWF_CONFIG ;
return(MOD_CODE_OK);
}
int
mod_config(char *config, int i)
{
char *p = config;
WRLOCK_PWF_CONFIG ;
while( *p && IS_SPACE(*p) ) p++;
if ( !strncasecmp(p, "realm", 5) ) {
p += 5;
while (*p && IS_SPACE(*p) ) p++;
strncpy(realm, p, sizeof(realm) -1 );
} else
if ( !strncasecmp(p, "template", 8) ) {
p += 8;
while (*p && IS_SPACE(*p) ) p++;
strncpy(pwf_template, p, sizeof(pwf_template) -1 );
} else
if ( !strncasecmp(p, "charset", 7) ) {
p += 7;
while (*p && IS_SPACE(*p) ) p++;
sprintf(pwf_charset, "Content-Type: text/html; charset=%.20s\n", p);
pwf_charset_len = strlen(pwf_charset);
} else
if ( !strncasecmp(p, "scheme", 6) ) {
p += 6;
while (*p && IS_SPACE(*p) ) p++;
if ( !strcasecmp(p, "basic") ) scheme = Basic;
if ( !strcasecmp(p, "NTLM") ) scheme = NTLM;
}
if ( !strncasecmp(p, "nt_server", 9) ) {
p += 9;
while (*p && IS_SPACE(*p) ) p++;
strncpy(nt_server, p, sizeof(nt_server) -1);
}
if ( !strncasecmp(p, "nt_port", 7) ) {
p += 7;
while (*p && IS_SPACE(*p) ) p++;
if ( !strcasecmp(p, "HTTP") ) nt_port = 80;
}
UNLOCK_PWF_CONFIG ;
return(MOD_CODE_OK);
}
int
auth(int so, struct group *group, struct request* rq, int *flags) {
char *authorization = NULL;
struct output_object *reply_obj = NULL;
if ( !authreq ) {
my_xlog(OOPS_LOG_NOTICE|OOPS_LOG_DBG|OOPS_LOG_INFORM, "auth(): Something wrong
with Win_http module.\n");
return(MOD_CODE_OK);
}
WRLOCK_PWF_CONFIG ;
if ( rq->av_pairs)
authorization = attr_value(rq->av_pairs, "Proxy-Authorization");
if ( !authorization ) {
/* send 407 Proxy Authentication Required */
send_auth_req(so, rq);
SET(*flags, MOD_AFLAG_OUT);
UNLOCK_PWF_CONFIG;
return(MOD_CODE_ERR);
} else {
char *data;
if ( !strncasecmp(authorization, "Basic", 5 ) ) {
int rc;
char *up=NULL, *p;
data = authorization + 5;
while ( *data && IS_SPACE(*data) ) data++;
send_to_ntlm(unit, client_data, 0);
if ( *data ) up = base64_decode(data);
if ( up ) {
/* up = username:password */
p = strchr(up, ':');
if ( p ) { *p=0; p++; }
hin.sin_family = AF_INET; // host byte order
hin.sin_port = htons(nt_port); // short, network byte order
hin.sin_addr.s_addr = inet_addr(nt_server);
memset(&(hin.sin_zero), '\0', 8); // zero the rest of the struct
memcpy(client_data, data, 2047);
if ((unit=socket(AF_INET,SOCK_STREAM,0)) > 0)
{
if (connect(unit,(struct sockaddr *)&hin,sizeof(hin)) != -1)
{
send_to_ntlm(unit, client_data, 2);
rc = recv_from_ntlm(unit, client_data, 2);
// end if connect
} else
my_xlog(OOPS_LOG_NOTICE|OOPS_LOG_DBG|OOPS_LOG_INFORM, "Can't
connect to server %s\n", nt_server);
close(unit);
} // end if create socket unit
if ( rc != 2 ) {
/*failed*/
free(up);
send_auth_req(so, rq);
SET(*flags, MOD_AFLAG_OUT);
UNLOCK_PWF_CONFIG;
return(MOD_CODE_ERR);
} else {
IF_STRDUP(rq->proxy_user, up);
free(up);
SET(*flags, MOD_AFLAG_CKACC);
UNLOCK_PWF_CONFIG;
return(MOD_CODE_OK);
}
} /* up != NULL */
} else {
if ( !strncasecmp(authorization, "NTLM", 4 ) ) {
data = authorization + 4;
while ( *data && IS_SPACE(*data) ) data++;
if ( *data ) {
hin.sin_family = AF_INET; // host byte order
hin.sin_port = htons(nt_port); // short, network byte order
hin.sin_addr.s_addr = inet_addr(nt_server);
memset(&(hin.sin_zero), '\0', 8); // zero the rest of the struct
memcpy(client_data, data, 2047);
if ((unit=socket(AF_INET,SOCK_STREAM,0)) > 0)
{
if (connect(unit,(struct sockaddr *)&hin,sizeof(hin)) != -1)
{
// Step 2
// We are received first NTLN hash from client and now send to
HTTP
// Client -> Server NTLM 1 hash
send_to_ntlm(unit, client_data, 0);
if(recv_from_ntlm(unit, client_data,0))
{
// Server -> Client NTLM 2 hash
// Reply to client second hash, who was received from NT HTTP
send_to_ntlm(so, client_data, 1);
if( recv_from_ntlm(so, client_data, 1) ) {
// Step 3
// Client -> Server NTLM 3 hash
// Client encode server unswer and we send it ti HTTP
send_to_ntlm(unit, client_data, 0);
if(recv_from_ntlm(unit, client_data,0) == 2){
// Server -> Got HTTP 200 Ok
close(unit);
IF_STRDUP(rq->proxy_user, client_data);
SET(*flags, MOD_AFLAG_CKACC);
UNLOCK_PWF_CONFIG;
return(MOD_CODE_OK);
} else {
my_xlog(OOPS_LOG_NOTICE|OOPS_LOG_DBG|OOPS_LOG_INFORM, "Code NTLM is not 200\nReturn to
Basic scheme\n");
}
}
} // end if receive_from_ntlm
// end if connect
} else my_xlog(OOPS_LOG_NOTICE|OOPS_LOG_DBG|OOPS_LOG_INFORM, "Can't
connect to server %s\n", nt_server);
close(unit);
} // end if create socket unit
} // end if NTLM have data
// Begin proposal Basic scheme
sprintf(client_data, "\
HTTP/1.1 407 Proxy Authentication Required\n\
Proxy-Authenticate: Basic realm %s\n\
Connection: Keep-Alive\n\
Content-Type: text/html\n\n", realm);
send(so, client_data, sizeof(client_data), 0);
SET(*flags, MOD_AFLAG_OUT);
UNLOCK_PWF_CONFIG;
return(MOD_CODE_ERR);
} else {
/* we do not support any schemes except Basic or NTLM */
writet(so, badsch, badschlen, 30);
SET(*flags, MOD_AFLAG_OUT);
}
}
UNLOCK_PWF_CONFIG;
return(MOD_CODE_ERR);
}
}
int send_to_ntlm(int server, char *cl_data, int type)
{
char serv_request[2047];
const char *my_content="<HTML><HEAD>Unauthorized<p></HEAD>\n<BODY>Unauthorized
access</BODY></HTML>\n";
memset(serv_request, '\0', 2047);
if(type == 1){
// Type is 1 - To Client
sprintf( serv_request,"\
HTTP/1.1 407 Proxy Authentication Required\n\
Proxy-Authenticate: NTLM %s\
Connection: Keep-Alive\n\
Content-Length: %d\n\
Content-Type: text/html\n\n%s", cl_data, strlen(my_content), my_content);
} else {
if(type == 0){
// Type is 0 - To Server
sprintf( serv_request,"\
HEAD / HTTP/1.1\n\
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel,
application/msword, application/vnd.ms-powerpoint, */*\n\
Accept-Language: ru\n\
Accept-Encoding: gzip, deflate\n\
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)\n\
Host: %s\n\
Connection: Keep-Alive\n\
Authorization: NTLM %s\n\n",nt_server,cl_data);
} else {
// type is 2 - Basic
sprintf( serv_request,"\
HEAD / HTTP/1.1\n\
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel,
application/msword, application/vnd.ms-powerpoint, */*\n\
Accept-Language: ru\n\
Accept-Encoding: gzip, deflate\n\
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)\n\
Host: %s\n\
Connection: Keep-Alive\n\
Authorization: Basic %s\n\n",nt_server,cl_data);
}
}
send(server, serv_request, strlen(serv_request),0);
return 1;
}
int recv_from_ntlm(int client, char *cl_data, int type)
{
char cl_str[1], *str_str, *where, end_str[2047];
int data_size, r;
const char *ntlm_string=" NTLM ";
char *w_str=cl_data;
struct pollarg polling;
memcpy(end_str,cl_data,2047);
memset(cl_data,'\0', 2047);
if( type ){
forever() {
polling.fd = client;
polling.request = FD_POLL_RD;
r = poll_descriptors(1, &polling, READ_ANSW_TIMEOUT*8);
if ( r < 0 ) {
my_xlog(OOPS_LOG_SEVERE, "recv_from_ntlm(): select: error.\n");
return 0;
}
if ( r == 0 ) {
my_xlog(OOPS_LOG_SEVERE, "recv_from_ntlm(): select: timed out.\n");
return 0;
}
if ( IS_HUPED(&polling) ) {
my_xlog(OOPS_LOG_SEVERE, "recv_from_ntlm(): Client closed connection too
early.\n");
return 0;
}
if ( IS_READABLE(&polling) )
break;
}
}
while((data_size=recv(client,cl_str,1,0)) != -1){
if(*cl_str == '\n' && *(w_str-2) == '\n') break;
*(w_str++) = *cl_str;
}
if ( type ){
polling.fd = client;
polling.request = FD_POLL_WR;
poll_descriptors(1, &polling, READ_ANSW_TIMEOUT*8);
}
// Search NTLM string
if( (where=strstr(cl_data, ntlm_string)) != NULL){
w_str = where;
while( *where++ != '\n' );
*where = '\0';
strcpy(cl_data, w_str+strlen(ntlm_string));
return 1;
} else {
if( (where=strstr(cl_data, "200 OK")) != NULL ){
if (type == 2) return 2;
char *temp = base64_decode(end_str), username[255];
int user_offset, user_len, i;
user_offset=*(temp+40);
user_len =*(temp+36);
memset(cl_data, '\0', user_len);
for(i=0;i<user_len;i+=2){
*(cl_data++) = *(temp+user_offset+i);
}
free(temp);
return 2;
}
}
if(data_size == -1) perror("recv()");
my_xlog(OOPS_LOG_NOTICE|OOPS_LOG_DBG|OOPS_LOG_INFORM, "Unknown NTLM reply\n");
return 0;
}
/*
static void
check_pwf_template_age(void)
{
if ( global_sec_timer - pwf_template_check_time < 60 ) return;
reload_pwf_template();
}
*/
static void
reload_pwf_template(void)
{
struct stat sb;
int rc, size, fd;
if ( !pwf_template[0] ) return;
my_xlog(OOPS_LOG_NOTICE|OOPS_LOG_DBG|OOPS_LOG_INFORM, "Win_http: reload pwf
template\n");
rc = stat(pwf_template, &sb);
if ( rc != -1 ) {
if ( sb.st_mtime <= pwf_template_mtime ) return;
size = sb.st_size;
if ( size <= 0 ) return;
if ( template ) free(template); template = NULL;
template = xmalloc(size,"reload_pwf_template(): 1");
if ( template ) {
fd = open(pwf_template, O_RDONLY);
if ( fd != -1 ) {
rc = read(fd, template, size);
if ( rc != size ) {
free(template);template = NULL;
} else {
pwf_template_mtime = sb.st_mtime;
pwf_template_check_time = global_sec_timer;
pwf_template_len = size;
}
close(fd);
} else {
free(template); template = NULL;
}
}
}
}
static void
send_auth_req(int so, struct request *rq)
{
struct output_object *obj;
struct buff *body;
int rc;
obj = xmalloc(sizeof(*obj),"send_auth_req(): obj");
if ( !obj )
return;
bzero(obj, sizeof(*obj));
put_av_pair(&obj->headers,"HTTP/1.0", "407 Proxy Authentication Required");
put_av_pair(&obj->headers,"Proxy-Authenticate:", authreq);
put_av_pair(&obj->headers,"Content-Type:", "text/html");
if ( !template ) body = alloc_buff(std_template_len);
else body = alloc_buff(pwf_template_len);
if ( body ) {
obj->body = body;
if ( !template )
rc = attach_data(std_template, std_template_len, body);
else
rc = attach_data(template, pwf_template_len, body);
if ( !rc )
process_output_object(so, obj, rq);
}
free_output_obj(obj);
return;
}