Здрасте. Прошу прощения, тот патч малость кривой. Полный текст исправленного файла ниже. (с) не мой ;) Основной смысл в том, что IIS начал различать \r\n и \n (не знаю зачем). Точной строки, на которой он начинает выдавать Bad request не выявлено, но после замены всех символов винде легчает. Вот и всё.
-- Konstantin Nikonenko http://www.kot.dp.ua/ /* 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. To WinAdmin: In Basic Authentication, the user is always logged on with local logon rights, which is similar to the user's logging on for an interactive session at the computer's console. (To use Basic Authentication, grant each user account the Log On Locally user right on the IIS server.) There are two potential problems caused by Basic Authentication's use of local logon that administrators should be aware of: Basic Authentication will not succeed if the user account does not have local logon rights. Even if the FrontPage, IIS, and Windows NT configuration appears to be correct, the lack of local logon rights granted to the user in the Windows NT User Manager will prevent Basic Authentication from authenticating the user. With local logon, if a user can obtain physical access to the host computer running IIS, the user will be permitted to start an interactive session at the console. 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_BR15 "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_BR15; 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\r\nProxy-Authenticate: Basic realm=\"%s\""; static char *authreqfmt_b = "%s\r\n realm=\"%s\""; static char *std_template = "\r\n<body>Authorization to proxy-server failed.<p><hr>\r\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\r\n\ Proxy-Authenticate: %s realm=\"%s\"\r\n\r\n\ <body>Authorization to proxy-server failed.<p>\r\n\ Your browser proposed unsupported scheme\r\n\ <hr>\r\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 recv_from_ntlm(int , char *, int type); /* Functions to make dialog with NT HTTP */ static int send_to_ntlm(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; #define C_SIZE 1024 #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\r\n"); return(MOD_CODE_OK); } int mod_unload(void) { printf("Win_http stopped\r\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\r\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\r\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; int unit, s; char client_data[C_SIZE]; if ( !authreq ) { my_xlog(OOPS_LOG_NOTICE|OOPS_LOG_DBG|OOPS_LOG_INFORM, "auth(): Something wrong with Win_http module.\r\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 = NULL; if ( !strncasecmp(authorization, "Basic", 5 ) ) { int rc=0; data = authorization + 5; /* Remove space */ while ( *data && IS_SPACE(*data) ) data++; /* copy data */ while ( *data ) client_data[rc++] = *data++; client_data[rc] = '\0'; if ( rc > 0 ) { char *up=NULL, *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 */ up = base64_decode(client_data); /* up = username:password */ p = strchr(up, ':'); if ( p ) { *p='\0'; p++; IF_STRDUP(rq->proxy_user, up); } free(up); 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, "win_http Basic Auth: Can't connect to NT server %s\r\n", nt_server); close(unit); } /* end if create socket unit */ if ( rc == 2 ) { SET(*flags, MOD_AFLAG_CKACC); UNLOCK_PWF_CONFIG; return(MOD_CODE_OK); } } SET(*flags, MOD_AFLAG_OUT); UNLOCK_PWF_CONFIG; return(MOD_CODE_ERR); /* Not Basic scheme */ } else { if ( !strncasecmp(authorization, "NTLM", 4 ) ) { int rc=0; data = authorization + 4; while ( *data && IS_SPACE(*data) ) data++; while ( *data ) client_data[rc++] = *data++; client_data[rc++] = 0; if ( rc > 0 ) { 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 */ 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) == 1) { /* 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) == 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\r\nReturn to Basic scheme\r\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\r\n", nt_server); close(unit); } /* end if create socket unit */ } /* end if NTLM have data */ } else { my_xlog(OOPS_LOG_NOTICE|OOPS_LOG_DBG|OOPS_LOG_INFORM, "win_http: 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[C_SIZE]; const char *my_content="<HTML><HEAD>Unauthorized<p></HEAD>\r\n<BODY>Unauthorized access</BODY></HTML>\r\n"; if(type == 1){ /* Type is 1 - To Client */ sprintf( serv_request,"\ HTTP/1.1 407 Proxy Authentication Required\r\n\ Proxy-Authenticate: NTLM %s\ Connection: Keep-Alive\r\n\ Content-Length: %d\r\n\ Content-Type: text/html\r\n\r\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\r\n\ Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/msword, application/vnd.ms-powerpoint, */*\r\n\ Accept-Language: ru\r\n\ Accept-Encoding: gzip, deflate\r\n\ User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)\r\n\ Host: %s\r\n\ Connection: Keep-Alive\r\n\ Authorization: NTLM %s\r\n\r\n",nt_server,cl_data); } else { /* type is 2 - Basic */ sprintf( serv_request,"\ HEAD / HTTP/1.1\r\n\ Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/msword, application/vnd.ms-powerpoint, */*\r\n\ Accept-Language: ru\r\n\ Accept-Encoding: gzip, deflate\r\n\ User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)\r\n\ Host: %s\r\n\ Connection: Keep-Alive\r\n\ Authorization: Basic %s\r\n\r\n", nt_server, cl_data); } } send(server, serv_request, strlen(serv_request),0); return 1; } static int recv_from_ntlm(int client, char *cl_data, int type) { char cl_str[1], *where, end_str[C_SIZE]; int data_size, r=0; const char *ntlm_string=" NTLM"; char *w_str=cl_data; struct pollarg polling; if( type == 1 ){ /* Socket to browser set to READ mode */ polling.fd = client; polling.request = FD_POLL_RD; poll_descriptors(1, &polling, READ_ANSW_TIMEOUT*8); } /* Save original string for finish part NTLM auth, to get username */ strcpy(end_str,cl_data); while((data_size=read(client,cl_str,1)) > 0){ if(*cl_str == '\n' && *(w_str-2) == '\n') break; /* Check to save not more then our buffer size */ if(r++ < C_SIZE-1) *(w_str++) = *cl_str; } /* End of string must be NULL */ *w_str = '\0'; if ( type == 1 ){ /* Socket to browser return to WRITE mode */ 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)+1); return 1; } else { if( (strstr(cl_data, "200 OK") != NULL) && (type != 1) ){ char *temp; int i, user_offset, user_len; if (type == 2) { *cl_data = '\0'; return 2; } temp = base64_decode(end_str); user_offset=*(temp+40); user_len =*(temp+36); if(user_len > 63 || user_offset > 255 ) { /* Prevent from hackers */ *cl_data = '\0'; free(temp); return 0; } w_str=cl_data; for(i=0;i<user_len;i+=2){ *(w_str++) = *(temp+user_offset+i); } *w_str = '\0'; free(temp); return 2; } } if(data_size > 0) my_xlog(OOPS_LOG_NOTICE|OOPS_LOG_DBG|OOPS_LOG_INFORM, "Don't know this reply size %d on type %d:\r\n%s\r\n", r, type, cl_data); *cl_data = '\0'; 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\r\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; } ===================================================================== If you would like to unsubscribe from this list send message to [EMAIL PROTECTED] with "unsubscribe oops" in message body. Archive is accessible on http://lists.paco.net/oops-rus/
