diff options
| author | Daniel Stenberg <daniel@haxx.se> | 2003-08-11 11:47:45 +0000 | 
|---|---|---|
| committer | Daniel Stenberg <daniel@haxx.se> | 2003-08-11 11:47:45 +0000 | 
| commit | 7a19923afa17dbfa9b45d8620bac003398cf1ebd (patch) | |
| tree | 7c07164c10705218a7f96a7cdb878d9a528354e8 | |
| parent | 3e122a765d7a42435658354852a902e100264ae9 (diff) | |
Serge Semashko added CURLOPT_PROXYAUTH support, and now NTLM for proxies
work.
| -rw-r--r-- | lib/http.c | 125 | ||||
| -rw-r--r-- | lib/http.h | 1 | ||||
| -rw-r--r-- | lib/http_ntlm.c | 5 | ||||
| -rw-r--r-- | lib/transfer.c | 24 | ||||
| -rw-r--r-- | lib/url.c | 25 | ||||
| -rw-r--r-- | lib/urldata.h | 8 | 
6 files changed, 154 insertions, 34 deletions
diff --git a/lib/http.c b/lib/http.c index a59ed8ac1..35f795725 100644 --- a/lib/http.c +++ b/lib/http.c @@ -93,6 +93,7 @@  #include "http_negotiate.h"  #include "url.h"  #include "share.h" +#include "http.h"  #define _MPRINTF_REPLACE /* use our functions only */  #include <curl/mprintf.h> @@ -102,6 +103,8 @@  #include "memdebug.h"  #endif +static CURLcode Curl_output_basic_proxy(struct connectdata *conn); +  /* fread() emulation to provide POST and/or request data */  static int readmoredata(char *buffer,                          size_t size, @@ -430,6 +433,13 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn,    infof(data, "Establish HTTP proxy tunnel to %s:%d\n", hostname, remote_port); +  /* +   * This code currently only supports Basic authentication for this CONNECT +   * request to a proxy. +   */ +  if(conn->bits.proxy_user_passwd) +    Curl_output_basic_proxy(conn); +    /* OK, now send the connect request to the proxy */    result =      Curl_sendf(tunnelsocket, conn, @@ -561,6 +571,8 @@ CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn,    Curl_safefree(conn->allocptr.proxyuserpwd);    conn->allocptr.proxyuserpwd = NULL; +  Curl_http_auth_stage(data, 401); /* move on to the host auth */ +    infof (data, "Proxy replied to CONNECT request\n");    return CURLE_OK;  } @@ -672,6 +684,37 @@ static CURLcode Curl_output_basic(struct connectdata *conn)    return CURLE_OK;  } +static CURLcode Curl_output_basic_proxy(struct connectdata *conn) +{ +  char *authorization; +  struct SessionHandle *data=conn->data; + +  sprintf(data->state.buffer, "%s:%s", conn->proxyuser, conn->proxypasswd); +  if(Curl_base64_encode(data->state.buffer, strlen(data->state.buffer), +                        &authorization) >= 0) { +    Curl_safefree(conn->allocptr.proxyuserpwd); +    conn->allocptr.proxyuserpwd = +      aprintf("Proxy-authorization: Basic %s\015\012", authorization); +    free(authorization); +  } +  else +    return CURLE_OUT_OF_MEMORY; +  return CURLE_OK; +} + +void Curl_http_auth_stage(struct SessionHandle *data, +                          int stage) +{ +  if(stage == 401) +    data->state.authwant = data->set.httpauth; +  else if(stage == 407) +    data->state.authwant = data->set.proxyauth; +  else +    return; /* bad input stage */ +  data->state.authstage = stage; +  data->state.authavail = CURLAUTH_NONE; +} +  CURLcode Curl_http(struct connectdata *conn)  {    struct SessionHandle *data=conn->data; @@ -685,6 +728,13 @@ CURLcode Curl_http(struct connectdata *conn)    char *ptr;    char *request; +  if(!data->state.authstage) { +    if(conn->bits.httpproxy) +      Curl_http_auth_stage(data, 407); +    else +      Curl_http_auth_stage(data, 401); +  } +    if(!conn->proto.http) {      /* Only allocate this struct if we don't already have it! */ @@ -728,40 +778,63 @@ CURLcode Curl_http(struct connectdata *conn)       curl_strequal(data->state.auth_host, conn->hostname) ||       data->set.http_disable_hostname_check_before_authentication) { -#ifdef GSSAPI -    if((data->state.authwant == CURLAUTH_GSSNEGOTIATE) && -       data->state.negotiate.context &&  -       !GSS_ERROR(data->state.negotiate.status)) { -      result = Curl_output_negotiate(conn); -      if (result) -	return result; -    } -    else -#endif +  /* Send proxy authentication header if needed */ +    if (data->state.authstage == 407) {  #ifdef USE_SSLEAY -    if(data->state.authwant == CURLAUTH_NTLM) { -      result = Curl_output_ntlm(conn, FALSE); -      if(result) -        return result; -    } -    else +      if(data->state.authwant == CURLAUTH_NTLM) { +        result = Curl_output_ntlm(conn, TRUE); +        if(result) +          return result; +      } +      else  #endif -    { -      if((data->state.authwant == CURLAUTH_DIGEST) && -         data->state.digest.nonce) { -        result = Curl_output_digest(conn, -                                    (unsigned char *)request, -                                    (unsigned char *)ppath); +      if((data->state.authwant == CURLAUTH_BASIC) && /* Basic */ +         conn->bits.proxy_user_passwd && +         !checkheaders(data, "Proxy-authorization:")) { +        result = Curl_output_basic_proxy(conn);          if(result)            return result; +        /* Switch to web authentication after proxy authentication is done */ +        Curl_http_auth_stage(data, 401);        } -      else if((data->state.authwant == CURLAUTH_BASIC) && /* Basic */ -              conn->bits.user_passwd && -              !checkheaders(data, "Authorization:")) { -        result = Curl_output_basic(conn); +    } +    /* Send web authentication header if needed */ +    if (data->state.authstage == 401) { +#ifdef GSSAPI +      if((data->state.authwant == CURLAUTH_GSSNEGOTIATE) && +         data->state.negotiate.context &&  +         !GSS_ERROR(data->state.negotiate.status)) { +        result = Curl_output_negotiate(conn); +        if (result) +          return result; +      } +      else +#endif +#ifdef USE_SSLEAY +      if(data->state.authwant == CURLAUTH_NTLM) { +        result = Curl_output_ntlm(conn, FALSE);          if(result)            return result;        } +      else +#endif +      { +        if((data->state.authwant == CURLAUTH_DIGEST) && +           data->state.digest.nonce) { +          result = Curl_output_digest(conn, +                                      (unsigned char *)request, +                                      (unsigned char *)ppath); +          if(result) +            return result; +        } +        else if((data->state.authwant == CURLAUTH_BASIC) && /* Basic */ +                conn->bits.user_passwd && +                !checkheaders(data, "Authorization:")) { +          result = Curl_output_basic(conn); +          if(result) +            return result; +        } +      }      }    } diff --git a/lib/http.h b/lib/http.h index da8e5db71..3cbbf841d 100644 --- a/lib/http.h +++ b/lib/http.h @@ -42,5 +42,6 @@ CURLcode Curl_http_connect(struct connectdata *conn);  void Curl_httpchunk_init(struct connectdata *conn);  CHUNKcode Curl_httpchunk_read(struct connectdata *conn, char *datap,                                ssize_t length, ssize_t *wrote); +void Curl_http_auth_stage(struct SessionHandle *data, int stage);  #endif  #endif diff --git a/lib/http_ntlm.c b/lib/http_ntlm.c index 5c6e3df4f..29615a470 100644 --- a/lib/http_ntlm.c +++ b/lib/http_ntlm.c @@ -551,7 +551,10 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,        return CURLE_OUT_OF_MEMORY; /* FIX TODO */      ntlm->state = NTLMSTATE_TYPE3; /* we sent a type-3 */ -     + +    /* Switch to web authentication after proxy authentication is done */ +    if (proxy) +      Curl_http_auth_stage(conn->data, 401);    }    break; diff --git a/lib/transfer.c b/lib/transfer.c index d9f3c8f9b..f33660812 100644 --- a/lib/transfer.c +++ b/lib/transfer.c @@ -726,12 +726,24 @@ CURLcode Curl_readwrite(struct connectdata *conn,                if(data->set.get_filetime)                  data->info.filetime = k->timeofdoc;              } -            else if(checkprefix("WWW-Authenticate:", k->p) && -                    (401 == k->httpcode)) { +            else if((checkprefix("WWW-Authenticate:", k->p) && +                    (401 == k->httpcode)) || +                    (checkprefix("Proxy-authenticate:", k->p) && +                    (407 == k->httpcode))) {                /*                 * This page requires authentication                 */ -              char *start = k->p+strlen("WWW-Authenticate:"); +              char *start = (k->httpcode == 407) ?  +                            k->p+strlen("Proxy-authenticate:"):  +                            k->p+strlen("WWW-Authenticate:"); +              /* +               * Switch from proxy to web authentication and back if needed +               */ +              if (k->httpcode == 407 && data->state.authstage != 407) +                Curl_http_auth_stage(data, 407); +               +              else if (k->httpcode == 401 && data->state.authstage != 401) +                Curl_http_auth_stage(data, 401);                /* pass all white spaces */                while(*start && isspace((int)*start)) @@ -757,7 +769,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,                  if(data->state.authwant == CURLAUTH_NTLM) {                    /* NTLM authentication is activated */                    CURLntlm ntlm = -                    Curl_input_ntlm(conn, FALSE, start); +                    Curl_input_ntlm(conn, k->httpcode == 407, start);                    if(CURLNTLM_BAD != ntlm)                      conn->newurl = strdup(data->change.url); /* clone string */ @@ -1506,8 +1518,8 @@ CURLcode Curl_pretransfer(struct SessionHandle *data)    data->state.errorbuf = FALSE; /* no error has occurred */    /* set preferred authentication, default to basic */ -  data->state.authwant = data->set.httpauth?data->set.httpauth:CURLAUTH_BASIC; -  data->state.authavail = CURLAUTH_NONE; /* nothing so far */ + +  data->state.authstage = 0; /* initialize authentication later */    /* If there was a list of cookie files to read and we haven't done it before,       do it now! */ @@ -312,6 +312,9 @@ CURLcode Curl_open(struct SessionHandle **curl)    data->set.proxytype = CURLPROXY_HTTP; /* defaults to HTTP proxy */ +  data->set.httpauth = CURLAUTH_BASIC; /* defaults to basic authentication */ +  data->set.proxyauth = CURLAUTH_BASIC; /* defaults to basic authentication */ +    /* create an array with connection data struct pointers */    data->state.numconnects = 5; /* hard-coded right now */    data->state.connects = (struct connectdata **) @@ -878,6 +881,26 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, ...)    }    break; +  case CURLOPT_PROXYAUTH: +    /* +     * Set HTTP Authentication type BITMASK. +     */ +  { +    long auth = va_arg(param, long); +    /* switch off bits we can't support */ +#ifndef USE_SSLEAY +    auth &= ~CURLAUTH_NTLM; /* no NTLM without SSL */ +#endif +#ifndef GSSAPI +    auth &= ~CURLAUTH_GSSNEGOTIATE; /* no GSS-Negotiate without GSSAPI */ +#endif +    if(!auth) +      return CURLE_FAILED_INIT; /* no supported types left! */ + +    data->set.proxyauth = auth; +  } +  break; +    case CURLOPT_USERPWD:      /*       * user:password to use in the operation @@ -3066,6 +3089,7 @@ static CURLcode SetupConnection(struct connectdata *conn,    /*************************************************************     * Proxy authentication     *************************************************************/ +#if 0 /* This code is not needed anymore (moved to http.c) */    if(conn->bits.proxy_user_passwd) {      char *authorization;      snprintf(data->state.buffer, BUFSIZE, "%s:%s", @@ -3078,6 +3102,7 @@ static CURLcode SetupConnection(struct connectdata *conn,        free(authorization);      }    } +#endif    /*************************************************************     * Send user-agent to HTTP proxies even if the target protocol diff --git a/lib/urldata.h b/lib/urldata.h index 877c2e98e..a8c8dd13f 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -686,7 +686,12 @@ struct UrlState {    struct negotiatedata negotiate;  #endif -  long authwant;  /* inherited from what the user set with CURLOPT_HTTPAUTH */ +  long authstage; /*   0 - authwant and authavail are still not initialized +                     401 - web authentication is performed +                     407 - proxy authentication is performed */ +  long authwant;  /* initially set to authentication methods requested by +                     client (either with CURLOPT_HTTPAUTH or CURLOPT_PROXYAUTH +                     depending on authstage) */    long authavail; /* what the server reports */  #ifdef USE_ARES @@ -741,6 +746,7 @@ struct UserDefined {    long use_port;     /* which port to use (when not using default) */    char *userpwd;     /* <user:password>, if used */    long httpauth;     /* what kind of HTTP authentication to use (bitmask) */ +  long proxyauth;    /* what kind of proxy authentication to use (bitmask) */    char *set_range;   /* range, if used. See README for detailed specification                          on this syntax. */    long followlocation; /* as in HTTP Location: */  | 
