lynx-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

LYNX-DEV Attached: Deltas for authenticated proxy access


From: Iain Barker
Subject: LYNX-DEV Attached: Deltas for authenticated proxy access
Date: 23 May 1997 00:36 EDT

Hi,
        Attached is an ed delta for Lynx v2.7 which I modified to support
authenticated proxy access. I don't know C++ only C so rather than
store proxy information per host using all that fancy realm etc.
structure you have, I just assume that a global setting is OK (this
was primarily designed to let our users get outside of the corporate
firewall) and only update if authentication fails.

It's not clean code, but it works. Suggest you massage it into whatever
for is required for the main distribution.

If a proxy is specified with the standard proxy variables, authentication
using uuencoded basic method is attempted if the proxy server fails without
authentication, based on the authentication required given in the 407 message.
I didn't include ano other authentication schemes because we don't
use them here!

You can specify a userid and password at runtime (which it will
cache for that session only) or invoke Lynx with

  lynx -proxyauth id:pw

for a more permanent method.

I haven't tested it much, but it works for internal authenticated pages,
external pages via an authenticated proxy, and external authenticated pages
via an authenticated proxy.  ie. OK for daily use.

cheers,
        Iain.


-- 
Iain Barker
address@hidden
address@hidden
http://www.yoshac.demon.co.uk/


ed - LYMessages_en.h << '-*-END-*-'
365a
#define USERNAME_PASSWORD_REQUIRED "lynx: Username and Password required!!!"
#define PROXY_USERNAME_PROMPT "Enter Proxy Username: "
#define PROXY_PASSWORD_PROMPT "Proxy Password: "
#define PROXY_USERNAME_PASSWORD_REQUIRED "Proxy Username and Password 
required!!!"
.
364d
w
q
-*-END-*-
ed - HTAABrow.c << '-*-END-*-'
1047a

    /* Never reached */
}





/* BROWSER PUBLIC                                       HTAP_composeAuth()
**
**      SELECT THE PROXY AUTHENTICATION SCHEME AND
**      COMPOSE THE ENTIRE PROXY AUTHORIZATION HEADER LINE
**      IF WE ALREADY KNOW THAT THE PROXY REQUIRES AUTHENTICATION
**
** ON EXIT:
**      returns NULL, if no authorization seems to be needed, or
**              if it is the entire Proxy-authorization: line, e.g.
**
**                 "Proxy-authorization: Basic username:password"
**
**              As usual, this string is automatically freed.
*/
PUBLIC char *HTAP_composeAuth ()
{
    char *proxy_auth_string;
    HTAAScheme scheme;
    int len;

    FREE(HTAP_composeAuthResult);       /* From previous call */

    if (TRACE)
        fprintf(stderr, "Composing Proxy authorization\n");

    proxy_retry = YES;
    
    switch (scheme = HTAA_selectScheme(proxy_setup)) {
      case HTAA_BASIC:
        proxy_auth_string = proxy_compose_auth_string(scheme);
        break;
      default:
        {
            char msg[100];
            sprintf(msg, "%s %s `%s'",
                    "This client doesn't know how to compose authentication",
                    "information for scheme", HTAAScheme_name(scheme));
            HTAlert(msg);
            proxy_auth_string = NULL;
            proxy_retry = NO;
        }
    } /* switch scheme */

    if (!proxy_auth_string)
        /*
         *  Signal a failure. - FM
         */
        return NULL;  /* Added by marca. */
    if (*proxy_auth_string == '\0') {
        /*
         *  Signal an abort. - FM
         */
        StrAllocCopy(HTAP_composeAuthResult, "");
        return(HTAP_composeAuthResult);
    }
    
    len = strlen(proxy_auth_string) + strlen((char *)HTAAScheme_name(scheme)) + 
20;
    if (!(HTAP_composeAuthResult =
                (char*)calloc(1, sizeof(char) * len)))
        outofmem(__FILE__, "HTAP_composeAuth");
    strcpy(HTAP_composeAuthResult, "Proxy-authorization: ");
    strcat(HTAP_composeAuthResult, HTAAScheme_name(scheme));
    strcat(HTAP_composeAuthResult, " ");
    strcat(HTAP_composeAuthResult, proxy_auth_string);
    return HTAP_composeAuthResult;
}

/* BROWSER PUBLIC                               HTAP_shouldRetryWithAuth()
**
**              DETERMINES IF WE SHOULD RETRY THE PROXY
**              WITH AUTHORIZATION
**              (OR IF ALREADY RETRIED, WITH A DIFFERENT
**              USERNAME AND/OR PASSWORD (IF MISSPELLED))
** ON ENTRY:
**      start_of_headers is the first block already read from socket,
**                      but status line skipped; i.e. points to the
**                      start of the header section.
**      length          is the remaining length of the first block.
**      soc             is the socket to read the rest of server reply.
**
**                      This function should only be called when
**                      server has replied with a 407 (Unauthorized)
**                      status code.
** ON EXIT:
**      returns         YES, if connection should be retried.
**                      NO, otherwise.
*/
PUBLIC BOOL HTAP_shouldRetryWithAuth ARGS4(char *, start_of_headers,
                                           int,    length,
                                           void *, handle,
                                           int,    soc)
{
    HTAAScheme scheme;
    char *line = NULL;
    int num_schemes = 0;
    HTList *proxy_valid_schemes = HTList_new();
    HTAssocList **proxy_scheme_specifics = NULL;
    char *temp = NULL;

    /*
    **  Read server reply header lines
    */
    if (TRACE)
        fprintf(stderr, "Server reply header lines:\n");

    HTAA_setupReader(start_of_headers, length, handle, soc);
    while (NULL != (line = HTAA_getUnfoldedLine())  &&  *line != '\0') {
        if (TRACE)
            fprintf(stderr, "%s\n", line);

        if (strchr(line, ':')) {        /* Valid header line */

            char *p = line;
            char *fieldname = HTNextField(&p);
            char *arg1 = HTNextField(&p);
            char *args = p;
            
            if (0==strcasecomp(fieldname, "Proxy-authenticate:")) {
                if (!(arg1 && *arg1 && args && *args)) {
                    temp = (char *)calloc(1, strlen(line) +
                                             (arg1 ? strlen(arg1) : 0) +
                                             (args ? strlen(args) : 0) + 24);
                    if (!temp)
                        outofmem(__FILE__, "HTAP_shouldRetryWithAuth");
                    sprintf(temp, "Invalid header '%s%s%s%s%s'", line,
                                  ((arg1 && *arg1) ? " "  : ""),
                                  ((arg1 && *arg1) ? arg1 : ""),
                                  ((args && *args) ? " "  : ""),
                                  ((args && *args) ? args : ""));
                    HTAlert(temp);
                    FREE(temp);
                }
                else if (HTAA_UNKNOWN != (scheme = HTAAScheme_enum(arg1))) {
                    HTList_addObject(proxy_valid_schemes, (void*)scheme);
                    if (!proxy_scheme_specifics) {
                        int i;
                        proxy_scheme_specifics = (HTAssocList**)
                            calloc(1, HTAA_MAX_SCHEMES * sizeof(HTAssocList*));
                        if (!proxy_scheme_specifics)
                            outofmem(__FILE__, "HTAA_shouldRetryWithAuth");
                        for (i=0; i < HTAA_MAX_SCHEMES; i++)
                            proxy_scheme_specifics[i] = NULL;
                    }
                    proxy_scheme_specifics[scheme] = HTAA_parseArgList(args);
                    num_schemes++;
                }
                else if (TRACE) {
                    fprintf(stderr, "Unknown scheme `%s' %s\n",
                            (arg1 ? arg1 : "(null)"),
                            "in Proxy-authenticate: field");
                }
            }

        } /* if a valid header line */
        else if (TRACE) {
            fprintf(stderr, "Invalid header line `%s' ignored\n", line);
        } /* else invalid header line */

        FREE(line);
    } /* while header lines remain */
    FREE(line);


    /*
    **  So should we retry with authorization
    */
    if (num_schemes == 0) {             /* No authentication valid */
        proxy_setup = NULL;
        return NO;
    }

    if (proxy_retry) {
        /* So we have already tried with authorization. */
        /* Either we don't have access or username or   */
        /* password was misspelled.                     */

        if (NO == HTConfirm("Proxy authorization failed.  Retry?")) {
            proxy_setup = NULL;
            proxy_retry=NO;
            return NO;
        } /* HTConfirm(...) == NO */
        else { /* re-ask username+password (if misspelled) */
            proxy_retry = YES;
            return YES;
        } /* HTConfirm(...) == YES */
    } /* if proxy_setup != NULL */

    HTAlert("Access without authorization denied -- retrying");
    return YES;
.
519a
/***************** Basic Proxy Authentication ************************/

/* PRIVATE                                              
proxy_compose_auth_string(scheme)
**
**              COMPOSE Basic PROXY AUTHENTICATION STRING;
**              PROMPTS FOR USERNAME AND PASSWORD IF NEEDED
**
** ON ENTRY:
**      scheme          HTAA_BASIC or invalid 
**
** ON EXIT:
**      returns         a newly composed authorization string,
**                      NULL, if something fails.
** NOTE:
**      Like throughout the entire AA package, no string or structure
**      returned by AA package needs to (or should) be freed.
**
*/
PRIVATE char *proxy_compose_auth_string ARGS1(HTAAScheme,       scheme)
{
    char *cleartext = NULL;     /* Cleartext presentation */
    char *ciphertext = NULL;    /* Encrypted presentation */
    int len;
    char *msg = NULL;
    char *username = NULL;
    char *password = NULL;

    FREE(proxy_compose_auth_stringResult);      /* From previous call */

    if (scheme != HTAA_BASIC)
        return NULL;

    HTPromptProxyUsernameAndPassword(msg, &username, &password);

    if (!username || !password) {
         /*
         *  Signals to retry. - FM
         */
        return NULL;
    } else if (*username == '\0' || *password == '\0') {
         /*
         *  Signals to abort. - FM
         */
         StrAllocCopy(proxy_compose_auth_stringResult, "");
         return proxy_compose_auth_stringResult;
    }
    
    len = strlen(username ? username : "") +
          strlen(password ? password : "") + 3;

    if (!(cleartext  = (char*)calloc(1, sizeof(char) * len)))
        outofmem(__FILE__, "proxy_compose_auth_string");

    if (username)
        strcpy(cleartext, username);
    else
        *cleartext = '\0';

    strcat(cleartext, ":");

    if (password)
        strcat(cleartext, password);

    /* scheme == HTAA_BASIC */
    if (!(proxy_compose_auth_stringResult =
                                (char*)calloc(1, (4 * ((len+2)/3)) + 1)))
    outofmem(__FILE__, "proxy_compose_auth_string");

    HTUU_encode((unsigned char *)cleartext, strlen(cleartext),
                    proxy_compose_auth_stringResult);
    FREE(cleartext);
    
    return proxy_compose_auth_stringResult;
}


.
419a

.
117a
PRIVATE HTAASetup *proxy_setup= NULL;   /* The proxy setup */
.
115a
PRIVATE BOOL proxy_retry        = NO;
.
112a
PRIVATE char *HTAP_composeAuthResult = NULL;
PRIVATE char *proxy_compose_auth_stringResult = NULL;   /* Uuencoded 
presentation */

.
94a

.
w
q
-*-END-*-
ed - HTAABrow.h << '-*-END-*-'
133c

/* Account Authorisation code modified to support Proxy Authorisation */
/* Iain Barker (address@hidden), 21 May 1997. */

/* PUBLIC                                               HTAP_composeAuth()
**
**      COMPOSE THE ENTIRE PROXY AUTHORIZATION HEADER LINE 
**
** ON EXIT:
**      returns NULL, if no authorization seems to be needed, or
**              if it is the entire Authorization: line, e.g.
**
**                 "Authorization: basic username:password"
**
**              As usual, this string is automatically freed.
*/
PUBLIC char *HTAP_composeAuth ();


/* BROWSER PUBLIC                               HTAP_shouldRetryWithAuth()
**
**              DETERMINES IF WE SHOULD RETRY THE SERVER
**              WITH AUTHORIZATION
**              (OR IF ALREADY RETRIED, WITH A DIFFERENT
**              USERNAME AND/OR PASSWORD (IF MISSPELLED))
** ON ENTRY:
**      start_of_headers is the first block already read from socket,
**                      but status line skipped; i.e. points to the
**                      start of the header section.
**      length          is the remaining length of the first block.
**      soc             is the socket to read the rest of server reply.
**
**                      This function should only be called when
**                      server has replied with a 401 (Unauthorized)
**                      status code.
** ON EXIT:
**      returns         YES, if connection should be retried.
**                           The node containing all the necessary
**                           information is
**                              * either constructed if it does not exist
**                              * or password is reset to NULL to indicate
**                                that username and password should be
**                                reprompted when composing Authorization:
**                                field (in function HTAP_composeAuth()).
**                      NO, otherwise.
*/
PUBLIC BOOL HTAP_shouldRetryWithAuth PARAMS((char *     start_of_headers,
                                             int        length,
                                             void *     handle,
                                             int        soc));

.
131d
w
q
-*-END-*-
ed - HTTP.c << '-*-END-*-'
1280,1284c
                if (show_407)
                    break;

                proxy_reqs_auth=YES;

                /* Reset values to force user re-entry */
                if (proxy_retrying == YES)
                {
                    proxy_retrying=NO;
                    proxyauth=NULL;
                }

                if (HTAP_shouldRetryWithAuth(start_of_data, length,
                                             (void *)handle, s)) {

                    HTTP_NETCLOSE(s, handle);
                    if (dump_output_immediately && !proxyauth) {
                        fprintf(stderr,
                                "HTTP: Proxy authorization required.\n");
                        fprintf(stderr,
                                "       Use the -proxyauth=id:pw parameter.\n");
                        status = HT_NO_DATA;
                        goto clean_up;
                    }

                    if (TRACE) 
                        fprintf(stderr, "%s %d %s\n",
                              "HTTP: close socket", s,
                              "to retry with Proxy Authorization");

                    _HTProgress (
                        "Retrying with proxy authorization information.");
                    FREE(line_buffer);
                    FREE(line_kept_clean);
                    proxy_retrying=YES;
                    goto try_again;
                    break;
                }
.
1274,1278c
                 *  Authorization for proxy server required.
                 *  If show_407 is set, proceed to showing the
                 *  407 body.  Otherwise, if we can set up
                 *  authorization based on the Proxy-Authenticate
                 *  header, and the user provides a username and
                 *  password, try again.  Otherwise, check whether
                 *  to show the 407 body or restore the current
                 *  document. - IB
.
436a
        /* set the proxy authorisation if required */
        if (using_proxy && proxy_reqs_auth) 
        {

            if ((proxyauth == NULL) || (*proxyauth == '\0'))  
                    proxyauth = HTAP_composeAuth();

            /*
            **  If proxyauth is not NULL nor zero-length, it's
            **  a proxy authorization header to be included.
            */ 
            if ((proxyauth != NULL) && (*proxyauth != '\0'))
            {
                    sprintf(line, "%s%c%c", proxyauth, CR, LF);
                    StrAllocCat(command, line);
        
                    if (TRACE)
                         fprintf(stderr, "HTTP: Sending proxy authorization: 
%s\n", proxyauth);

            } else if (proxyauth && *proxyauth == '\0')
          {
            /*
            **  If proxyauth is a zero-length string, the user either
            **  cancelled or goofed at the username and password
            **  prompt.
            */
            if (!(traversal || dump_output_immediately) &&
                HTConfirm("Proceed without a username and password?")) 
                        show_407 = TRUE;
            else {
                if (traversal || dump_output_immediately)
                    HTAlert("Can't proceed without a username and password.");
                FREE(command);
                status = HT_NOT_LOADED;
                goto done;
            }
          }
        } else if (TRACE)
                fprintf(stderr, "HTTP: Not sending proxy authorization \n");
      

        /* set page authentication */
.
126a
  BOOL show_407 = FALSE;
.
119a

.
57a
PUBLIC char * proxyauth;        /* last value of the auth coded string */
PUBLIC BOOL proxy_reqs_auth, proxy_retrying = FALSE;

.
w
q
-*-END-*-
ed - HTAlert.c << '-*-END-*-'
233a

/*      Prompt both username and password.       
HTPromptProxyUsernameAndPassword()
**      ----------------------------------
**
**  On entry,
**      Msg             is the prompting message.
**      *username and
**      *password       are char pointers; they are changed
**                      to point to result strings.
**
**                      If *username is not NULL, it is taken
**                      to point to  a default value.
**                      Initial value of *password is
**                      completely discarded.
**
**  On exit,
**      *username and *password point to newly allocated
**      strings -- original strings pointed to by them
**      are NOT freed.
**
*/
PUBLIC void HTPromptProxyUsernameAndPassword ARGS3(
        CONST char *,   Msg,
        char **,        username,
        char **,        password)
{
    if (proxy_authentication_info[0] && proxy_authentication_info[1]) {
        /* 
        **  -proxyauth parameter gave us both the username and password to use 
        */
        StrAllocCopy(*username, proxy_authentication_info[0]);
        FREE(proxy_authentication_info[0]);
        StrAllocCopy(*password, proxy_authentication_info[1]);
        FREE(proxy_authentication_info[1]);
    } else if (dump_output_immediately) {
        if (proxy_authentication_info[0]) {
            /*
            **  Use the command line username. - FM
            */
            StrAllocCopy(*username, proxy_authentication_info[0]);
            FREE(proxy_authentication_info[0]);
        } else {
            /*
            **  Default to a zero-length string. - FM
            */
            StrAllocCopy(*username, "");
        }
        if (proxy_authentication_info[1]) {
            /*
            **  Use the command line password. - FM
            */
            StrAllocCopy(*password, proxy_authentication_info[1]);
            FREE(proxy_authentication_info[1]);
        } else {
            /*
            **  Default to a zero-length string. - FM
            */
            StrAllocCopy(*password, "");
        }
        printf("\n%s\n", PROXY_USERNAME_PASSWORD_REQUIRED);
    } else {
        if (proxy_authentication_info[0]) {
            /*
            **  Offer command line username in the prompt
            */
            StrAllocCopy(*username, proxy_authentication_info[0]);
            FREE(proxy_authentication_info[0]);
        }
        if (Msg != NULL) {
            *username = HTPrompt(Msg, *username);
        } else {
            *username = HTPrompt(PROXY_USERNAME_PROMPT, *username);
        }
        if (proxy_authentication_info[1]) {
            /*
            **  Use the command line password for the first realm. - FM
            */
            StrAllocCopy(*password, proxy_authentication_info[1]);
            FREE(proxy_authentication_info[1]);
        } else if (*username != NULL && *username[0] != '\0') {
            /*
            **  If we have a non-zero length username,
            **  prompt for the password. - FM
            */
            *password = HTPromptPassword(PROXY_PASSWORD_PROMPT);
        } else {
            /*
            **  Return a zero-length password. - FM
            */
            StrAllocCopy(*password, "");
        }
        
    }
}

.
w
q
-*-END-*-
ed - HTAlert.h << '-*-END-*-'
59a
/*      Prompt both username and password       
HTPromptProxyUsernameAndPassword()
**      ---------------------------------
** On entry,
**      Msg             is the prompting message.
**      *username and
**      *password       are char pointers; they are changed
**                      to point to result strings.
**
**                      If *username is not NULL, it is taken
**                      to point to  a default value.
**                      Initial value of *password is
**                      completely discarded.
**
** On exit,
**      *username and *password point to newly allocated
**      strings -- original strings pointed to by them
**      are NOT freed.
**
*/
extern void HTPromptProxyUsernameAndPassword PARAMS((
        CONST char *    Msg,
        char **         username,
        char **         password));


.
w
q
-*-END-*-
ed - LYGlobalDefs.h << '-*-END-*-'
233a
extern char *proxy_authentication_info[2]; /* Id:Password for proxy */
.
w
q
-*-END-*-
ed - LYMain.c << '-*-END-*-'
2037a
    printf("    -proxyauth=id:pw proxy authentication information\n");
.
1727a
    } else if (strncmp(argv[0], "-proxyauth", 5) == 0) {
        /*
         *  Authentication information for proxy
         */
        char *auth_info = NULL;
        
        if (nextarg) {
            StrAllocCopy(auth_info, cp);
            memset(cp, ' ', strlen(cp));/* Let's not show too much */
        }
        if (auth_info != NULL)  {
            if ((cp = strchr(auth_info, ':')) != NULL) { /* Pw */
                *cp++ = '\0';   /* Terminate ID */
                if (*cp) {
                    HTUnEscape(cp);
                    StrAllocCopy(proxy_authentication_info[1], cp);
                }
            }
            if (*auth_info) { /* Id */
                HTUnEscape(auth_info);
                StrAllocCopy(proxy_authentication_info[0], auth_info);
            }
            FREE(auth_info);
        }

.
403a
    FREE(proxy_authentication_info[0]);
    FREE(proxy_authentication_info[1]);
.
277a
PUBLIC char *proxy_authentication_info[2] = {NULL, NULL};
.
w
q
-*-END-*-

reply via email to

[Prev in Thread] Current Thread [Next in Thread]