Commit 7a19923a authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

Serge Semashko added CURLOPT_PROXYAUTH support, and now NTLM for proxies

work.
parent 3e122a76
Loading
Loading
Loading
Loading
+99 −26
Original line number Diff line number Diff line
@@ -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,6 +778,28 @@ CURLcode Curl_http(struct connectdata *conn)
     curl_strequal(data->state.auth_host, conn->hostname) ||
     data->set.http_disable_hostname_check_before_authentication) {

  /* 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, TRUE);
        if(result)
          return result;
      }
      else
#endif
      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);
      }
    }
    /* Send web authentication header if needed */
    if (data->state.authstage == 401) {
#ifdef GSSAPI
      if((data->state.authwant == CURLAUTH_GSSNEGOTIATE) &&
         data->state.negotiate.context && 
@@ -764,6 +836,7 @@ CURLcode Curl_http(struct connectdata *conn)
        }
      }
    }
  }

  if((data->change.referer) && !checkheaders(data, "Referer:")) {
    if(conn->allocptr.ref)
+1 −0
Original line number Diff line number Diff line
@@ -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
+4 −1
Original line number Diff line number Diff line
@@ -552,6 +552,9 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,

    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;

+18 −6
Original line number Diff line number Diff line
@@ -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! */
+25 −0
Original line number Diff line number Diff line
@@ -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
Loading