Index: lib/http.c
===================================================================
--- lib/http.c	(revision 4)
+++ lib/http.c	(working copy)
@@ -664,6 +664,25 @@
   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) {
+    if(conn->allocptr.proxyuserpwd)
+      free(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;
+}
+
 CURLcode Curl_http(struct connectdata *conn)
 {
   struct SessionHandle *data=conn->data;
@@ -677,6 +696,19 @@
   char *ptr;
   char *request;
 
+  if(!data->state.authstage) {
+    if(conn->bits.httpproxy) {
+      data->state.authstage = 407;
+      data->state.authwant = data->set.proxyauth;
+      data->state.authavail = CURLAUTH_NONE; /* nothing so far */
+    }
+    else {
+      data->state.authstage = 401;
+      data->state.authwant = data->set.httpauth;
+      data->state.authavail = CURLAUTH_NONE; /* nothing so far */
+    }
+  }
+
   if(!conn->proto.http) {
     /* Only allocate this struct if we don't already have it! */
 
@@ -720,40 +752,65 @@
      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 */
+        conn->data->state.authstage = 401;
+        conn->data->state.authwant = conn->data->set.httpauth;
+        conn->data->state.authavail = CURLAUTH_NONE;
       }
-      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;
+        }
+      }
     }
   }
 
Index: lib/urldata.h
===================================================================
--- lib/urldata.h	(revision 4)
+++ lib/urldata.h	(working copy)
@@ -665,7 +665,12 @@
   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 */
 };
 
@@ -716,6 +721,7 @@
   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: */
Index: lib/transfer.c
===================================================================
--- lib/transfer.c	(revision 4)
+++ lib/transfer.c	(working copy)
@@ -722,12 +722,30 @@
               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) {
+                data->state.authstage = 407;
+                data->state.authwant = data->set.proxyauth;
+                data->state.authavail = CURLAUTH_NONE;
+              }
+              
+              if (k->httpcode == 401 && data->state.authstage != 401) {
+                data->state.authstage = 401;
+                data->state.authwant = data->set.httpauth;
+                data->state.authavail = CURLAUTH_NONE;
+              }
 
               /* pass all white spaces */
               while(*start && isspace((int)*start))
@@ -753,7 +771,7 @@
                 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 */
@@ -1502,9 +1520,9 @@
   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! */
   if(data->change.cookielist) {
Index: lib/url.c
===================================================================
--- lib/url.c	(revision 4)
+++ lib/url.c	(working copy)
@@ -303,6 +303,9 @@
 
   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 **)
@@ -862,6 +865,26 @@
   }
   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
@@ -2975,6 +2998,7 @@
   /*************************************************************
    * 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",
@@ -2988,6 +3012,7 @@
       free(authorization);
     }
   }
+#endif
 
   /*************************************************************
    * Send user-agent to HTTP proxies even if the target protocol
Index: lib/http_ntlm.c
===================================================================
--- lib/http_ntlm.c	(revision 4)
+++ lib/http_ntlm.c	(working copy)
@@ -551,7 +551,13 @@
       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) {
+      conn->data->state.authstage = 401;
+      conn->data->state.authwant = conn->data->set.httpauth;
+      conn->data->state.authavail = CURLAUTH_NONE;
+    }
   }
   break;
 
Index: include/curl/curl.h
===================================================================
--- include/curl/curl.h	(revision 4)
+++ include/curl/curl.h	(working copy)
@@ -669,6 +669,11 @@
      argument */
   CINIT(SSL_CTX_DATA, OBJECTPOINT, 109),
 
+  /* Set this to a bitmask value to enable the particular authentications
+     methods you like. Use this in combination with CURLOPT_PROXYUSERPWD.
+     Note that setting multiple bits may cause extra network round-trips. */
+  CINIT(PROXYAUTH, LONG, 110),
+
   CURLOPT_LASTENTRY /* the last unused */
 } CURLoption;
 
