]> granicus.if.org Git - curl/commitdiff
Mark Davies fixed Negotiate authentication over proxy, and also introduced
authorDaniel Stenberg <daniel@haxx.se>
Fri, 21 Sep 2007 11:05:31 +0000 (11:05 +0000)
committerDaniel Stenberg <daniel@haxx.se>
Fri, 21 Sep 2007 11:05:31 +0000 (11:05 +0000)
the --proxy-negotiate command line option to allow a user to explicitly
select it.

CHANGES
RELEASE-NOTES
docs/curl.1
lib/http.c
lib/http_negotiate.c
lib/http_negotiate.h
src/main.c

diff --git a/CHANGES b/CHANGES
index d1da672b9c3d2e051aca41d6c0f6317e579e07f1..c1d55e3cac6260d3b822066ef5288ae0b7d4c365 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -6,6 +6,11 @@
 
                                   Changelog
 
+Daniel S (21 September 2007)
+- Mark Davies fixed Negotiate authentication over proxy, and also introduced
+  the --proxy-negotiate command line option to allow a user to explicitly
+  select it.
+
 Daniel S (19 September 2007)
 - Rob Crittenden provided an NSS update with the following highlights:
 
index c54f0162d283c5c02f0f087f52c9b9566ee8b70b..dcd8635540d6088eb21bbdcedc0a6819d26af012 100644 (file)
@@ -13,6 +13,7 @@ This release includes the following changes:
  
  o automatically append ";type=<a|i>" when using HTTP proxies for FTP urls
  o improved NSS support
+ o added --proxy-negotiate
 
 This release includes the following bugfixes:
 
@@ -20,6 +21,7 @@ This release includes the following bugfixes:
  o ldapv3 support on Windows
  o ldap builds with the MSVC makefiles
  o no HOME and no key given caused SSH auth failure
+ o Negotiate authentication over proxy
 
 This release includes the following known bugs:
 
@@ -36,6 +38,7 @@ New curl mirrors:
 This release would not have looked like this without help, code, reports and
 advice from friends like these:
 
- Dan Fandrich, Michal Marek, Günter Knauf, Rob Crittenden, Immanuel Gregoire
+ Dan Fandrich, Michal Marek, Günter Knauf, Rob Crittenden, Immanuel Gregoire,
+ Mark Davies
  
         Thanks! (and sorry if I forgot to mention someone)
index 2b173699879731b6c60293d765e5246e5b1edbb9..fc2cc13e37fe089017c02a78076cbd62c452cac2 100644 (file)
@@ -774,6 +774,9 @@ meant as a support for Kerberos5 authentication but may be also used along
 with another authentication methods. For more information see IETF draft
 draft-brezak-spnego-http-04.txt.
 
+If you want to enable Negotiate for your proxy authentication, then use
+\fI--proxy-negotiate\fP.
+
 This option requires that the library was built with GSSAPI support. This is
 not very common. Use \fI-V/--version\fP to see if your version supports
 GSS-Negotiate.
@@ -863,6 +866,14 @@ Tells curl to use HTTP Digest authentication when communicating with the given
 proxy. Use \fI--digest\fP for enabling HTTP Digest with a remote host.
 
 If this option is used twice, the second will again disable proxy HTTP Digest.
+.IP "--proxy-negotiate"
+Tells curl to use HTTP Negotiate authentication when communicating
+with the given proxy. Use \fI--negotiate\fP for enabling HTTP Negotiate
+with a remote host.
+
+If this option is used twice, the second will again disable proxy HTTP
+Negotiate.
+
 .IP "--proxy-ntlm"
 Tells curl to use HTTP NTLM authentication when communicating with the given
 proxy. Use \fI--ntlm\fP for enabling NTLM with a remote host.
index 090aad3d2bbeb6e491c1f1a8954750572b91b09e..67b2d3f554ec7af6d2c87a5c9cc112d6f5f42b5e 100644 (file)
@@ -424,6 +424,18 @@ Curl_http_output_auth(struct connectdata *conn,
   /* Send proxy authentication header if needed */
   if (conn->bits.httpproxy &&
       (conn->bits.tunnel_proxy == proxytunnel)) {
+#ifdef HAVE_GSSAPI
+    if((authproxy->picked == CURLAUTH_GSSNEGOTIATE) &&
+       data->state.negotiate.context &&
+       !GSS_ERROR(data->state.negotiate.status)) {
+      auth="GSS-Negotiate";
+      result = Curl_output_negotiate(conn, TRUE);
+      if (result)
+        return result;
+      authproxy->done = TRUE;
+    } 
+    else
+#endif
 #ifdef USE_NTLM
     if(authproxy->picked == CURLAUTH_NTLM) {
       auth="NTLM";
@@ -486,7 +498,7 @@ Curl_http_output_auth(struct connectdata *conn,
          data->state.negotiate.context &&
          !GSS_ERROR(data->state.negotiate.status)) {
         auth="GSS-Negotiate";
-        result = Curl_output_negotiate(conn);
+        result = Curl_output_negotiate(conn, FALSE);
         if (result)
           return result;
         authhost->done = TRUE;
@@ -593,7 +605,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn,
     authp->avail |= CURLAUTH_GSSNEGOTIATE;
     if(authp->picked == CURLAUTH_GSSNEGOTIATE) {
       /* if exactly this is wanted, go */
-      int neg = Curl_input_negotiate(conn, start);
+      int neg = Curl_input_negotiate(conn, (bool)(httpcode == 407), start);
       if (neg == 0) {
         data->reqdata.newurl = strdup(data->change.url);
         data->state.authproblem = (data->reqdata.newurl == NULL);
index f504c12d804b285dd92689ce7560a307a17bc28c..f5cc6cc6c90c9aefaafe18f075199512d461d5aa 100644 (file)
@@ -49,7 +49,7 @@
 #include "memdebug.h"
 
 static int
-get_gss_name(struct connectdata *conn, gss_name_t *server)
+get_gss_name(struct connectdata *conn, bool proxy, gss_name_t *server)
 {
   struct negotiatedata *neg_ctx = &conn->data->state.negotiate;
   OM_uint32 major_status, minor_status;
@@ -69,11 +69,11 @@ get_gss_name(struct connectdata *conn, gss_name_t *server)
   else
     service = "HTTP";
 
-  token.length = strlen(service) + 1 + strlen(conn->host.name) + 1;
+  token.length = strlen(service) + 1 + strlen(proxy ? conn->proxy.name : conn->host.name) + 1;
   if (token.length + 1 > sizeof(name))
     return EMSGSIZE;
 
-  snprintf(name, sizeof(name), "%s@%s", service, conn->host.name);
+  snprintf(name, sizeof(name), "%s@%s", service, proxy ? conn->proxy.name : conn->host.name);
 
   token.value = (void *) name;
   major_status = gss_import_name(&minor_status,
@@ -113,7 +113,7 @@ log_gss_error(struct connectdata *conn, OM_uint32 error_status, char *prefix)
   infof(conn->data, "%s", buf);
 }
 
-int Curl_input_negotiate(struct connectdata *conn, const char *header)
+int Curl_input_negotiate(struct connectdata *conn, bool proxy, const char *header)
 {
   struct negotiatedata *neg_ctx = &conn->data->state.negotiate;
   OM_uint32 major_status, minor_status, minor_status2;
@@ -156,7 +156,7 @@ int Curl_input_negotiate(struct connectdata *conn, const char *header)
   }
 
   if (neg_ctx->server_name == NULL &&
-      (ret = get_gss_name(conn, &neg_ctx->server_name)))
+      (ret = get_gss_name(conn, proxy, &neg_ctx->server_name)))
     return ret;
 
   header += strlen(neg_ctx->protocol);
@@ -245,7 +245,7 @@ int Curl_input_negotiate(struct connectdata *conn, const char *header)
 }
 
 
-CURLcode Curl_output_negotiate(struct connectdata *conn)
+CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
 {
   struct negotiatedata *neg_ctx = &conn->data->state.negotiate;
   OM_uint32 minor_status;
@@ -299,7 +299,7 @@ CURLcode Curl_output_negotiate(struct connectdata *conn)
     return CURLE_OUT_OF_MEMORY;
 
   conn->allocptr.userpwd =
-    aprintf("Authorization: %s %s\r\n", neg_ctx->protocol, encoded);
+    aprintf("%sAuthorization: %s %s\r\n", proxy ? "Proxy-" : "", neg_ctx->protocol, encoded);
   free(encoded);
   gss_release_buffer(&minor_status, &neg_ctx->output_token);
   return (conn->allocptr.userpwd == NULL) ? CURLE_OUT_OF_MEMORY : CURLE_OK;
index e0507013fd272a4713d20b431ef0adf05d537f1a..669fee586c1629c5fe25e306d1a10ae59e678b09 100644 (file)
 #ifdef HAVE_GSSAPI
 
 /* this is for Negotiate header input */
-int Curl_input_negotiate(struct connectdata *conn, const char *header);
+int Curl_input_negotiate(struct connectdata *conn, bool proxy, const char *header);
 
 /* this is for creating Negotiate header output */
-CURLcode Curl_output_negotiate(struct connectdata *conn);
+CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy);
 
 void Curl_cleanup_negotiate(struct SessionHandle *data);
 
index 3eca434e05aafb4713911033d1fc681860e9c7fd..1fffb969546916599a3a9b99a4b7b8207669411b 100644 (file)
@@ -426,6 +426,7 @@ struct Configurable {
   bool create_dirs;
   bool ftp_create_dirs;
   bool ftp_skip_ip;
+  bool proxynegotiate;
   bool proxyntlm;
   bool proxydigest;
   bool proxybasic;
@@ -690,6 +691,7 @@ static void help(void)
     "    --proxy-anyauth Pick \"any\" proxy authentication method (H)",
     "    --proxy-basic   Use Basic authentication on the proxy (H)",
     "    --proxy-digest  Use Digest authentication on the proxy (H)",
+    "    --proxy-negotiate Use Negotiate authentication on the proxy (H)",
     "    --proxy-ntlm    Use NTLM authentication on the proxy (H)",
     " -P/--ftp-port <address> Use PORT with address instead of PASV (F)",
     " -q                 If used as the first parameter disables .curlrc",
@@ -1492,6 +1494,7 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
     {"$g", "retry",      TRUE},
     {"$h", "retry-delay", TRUE},
     {"$i", "retry-max-time", TRUE},
+    {"$k", "proxy-negotiate",   FALSE},
     {"$m", "ftp-account", TRUE},
     {"$n", "proxy-anyauth", FALSE},
     {"$o", "trace-time", FALSE},
@@ -1892,6 +1895,12 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
           return PARAM_BAD_NUMERIC;
         break;
 
+      case 'k': /* --proxy-negotiate */
+        if(curlinfo->features & CURL_VERSION_GSSNEGOTIATE)
+          config->proxynegotiate ^= TRUE;
+        else
+          return PARAM_LIBCURL_DOESNT_SUPPORT;
+        break;
       case 'm': /* --ftp-account */
         GetStr(&config->ftp_account, nextarg);
         break;
@@ -4302,6 +4311,8 @@ operate(struct Configurable *config, int argc, argv_item_t argv[])
                          config->ftp_create_dirs);
         if(config->proxyanyauth)
           my_setopt(curl, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
+        else if(config->proxynegotiate)
+          my_setopt(curl, CURLOPT_PROXYAUTH, CURLAUTH_GSSNEGOTIATE);
         else if(config->proxyntlm)
           my_setopt(curl, CURLOPT_PROXYAUTH, CURLAUTH_NTLM);
         else if(config->proxydigest)