Здрасте.

Прошу прощения, тот патч малость кривой. Полный текст исправленного файла
ниже. (с) не мой ;)
Основной смысл в том, что 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/

Дати відповідь електронним листом