aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES5
-rw-r--r--RELEASE-NOTES5
-rw-r--r--docs/curl.111
-rw-r--r--lib/http.c16
-rw-r--r--lib/http_negotiate.c14
-rw-r--r--lib/http_negotiate.h4
-rw-r--r--src/main.c11
7 files changed, 54 insertions, 12 deletions
diff --git a/CHANGES b/CHANGES
index d1da672b9..c1d55e3ca 100644
--- 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:
diff --git a/RELEASE-NOTES b/RELEASE-NOTES
index c54f0162d..dcd863554 100644
--- a/RELEASE-NOTES
+++ b/RELEASE-NOTES
@@ -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)
diff --git a/docs/curl.1 b/docs/curl.1
index 2b1736998..fc2cc13e3 100644
--- a/docs/curl.1
+++ b/docs/curl.1
@@ -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.
diff --git a/lib/http.c b/lib/http.c
index 090aad3d2..67b2d3f55 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -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);
diff --git a/lib/http_negotiate.c b/lib/http_negotiate.c
index f504c12d8..f5cc6cc6c 100644
--- a/lib/http_negotiate.c
+++ b/lib/http_negotiate.c
@@ -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;
diff --git a/lib/http_negotiate.h b/lib/http_negotiate.h
index e0507013f..669fee586 100644
--- a/lib/http_negotiate.h
+++ b/lib/http_negotiate.h
@@ -27,10 +27,10 @@
#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);
diff --git a/src/main.c b/src/main.c
index 3eca434e0..1fffb9695 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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)