mirror of https://github.com/moparisthebest/curl
Tim Bartley's patch that makes the GSSNEGOTIATE option work for Microsoft's
"Negotiate" authentication as well.
This commit is contained in:
parent
0efcb57623
commit
fd42247cac
|
@ -312,7 +312,8 @@ CURLcode Curl_http_auth(struct connectdata *conn,
|
||||||
start++;
|
start++;
|
||||||
|
|
||||||
#ifdef GSSAPI
|
#ifdef GSSAPI
|
||||||
if (checkprefix("GSS-Negotiate", start)) {
|
if (checkprefix("GSS-Negotiate", start) ||
|
||||||
|
checkprefix("Negotiate", start)) {
|
||||||
*availp |= CURLAUTH_GSSNEGOTIATE;
|
*availp |= CURLAUTH_GSSNEGOTIATE;
|
||||||
if(data->state.authwant == CURLAUTH_GSSNEGOTIATE) {
|
if(data->state.authwant == CURLAUTH_GSSNEGOTIATE) {
|
||||||
/* if exactly this is wanted, go */
|
/* if exactly this is wanted, go */
|
||||||
|
|
|
@ -50,24 +50,35 @@
|
||||||
static int
|
static int
|
||||||
get_gss_name(struct connectdata *conn, gss_name_t *server)
|
get_gss_name(struct connectdata *conn, gss_name_t *server)
|
||||||
{
|
{
|
||||||
|
struct negotiatedata *neg_ctx = &conn->data->state.negotiate;
|
||||||
OM_uint32 major_status, minor_status;
|
OM_uint32 major_status, minor_status;
|
||||||
gss_buffer_desc token = GSS_C_EMPTY_BUFFER;
|
gss_buffer_desc token = GSS_C_EMPTY_BUFFER;
|
||||||
char name[2048];
|
char name[2048];
|
||||||
|
const char* service;
|
||||||
|
|
||||||
/* GSSAPI implementation by Globus (known as GSI) requires the name to be
|
/* GSSAPI implementation by Globus (known as GSI) requires the name to be
|
||||||
of form "<service>/<fqdn>" instead of <service>@<fqdn> (ie. slash instead
|
of form "<service>/<fqdn>" instead of <service>@<fqdn> (ie. slash instead
|
||||||
of at-sign). Also GSI servers are often identified as 'host' not 'khttp'.
|
of at-sign). Also GSI servers are often identified as 'host' not 'khttp'.
|
||||||
Change following lines if you want to use GSI */
|
Change following lines if you want to use GSI */
|
||||||
token.length = strlen("khttp@") + strlen(conn->hostname) + 1;
|
|
||||||
|
/* IIS uses the <service>@<fqdn> form but uses 'http' as the service name */
|
||||||
|
|
||||||
|
if (neg_ctx->gss)
|
||||||
|
service = "khttp";
|
||||||
|
else
|
||||||
|
service = "http";
|
||||||
|
|
||||||
|
token.length = strlen(service) + 1 + strlen(conn->hostname) + 1;
|
||||||
if (token.length + 1 > sizeof(name))
|
if (token.length + 1 > sizeof(name))
|
||||||
return EMSGSIZE;
|
return EMSGSIZE;
|
||||||
sprintf(name, "khttp@%s", conn->hostname);
|
sprintf(name, "%s@%s", service, conn->hostname);
|
||||||
|
|
||||||
token.value = (void *) name;
|
token.value = (void *) name;
|
||||||
major_status = gss_import_name(&minor_status,
|
major_status = gss_import_name(&minor_status,
|
||||||
&token,
|
&token,
|
||||||
GSS_C_NT_HOSTBASED_SERVICE,
|
GSS_C_NT_HOSTBASED_SERVICE,
|
||||||
server);
|
server);
|
||||||
|
|
||||||
return GSS_ERROR(major_status) ? -1 : 0;
|
return GSS_ERROR(major_status) ? -1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,12 +118,32 @@ int Curl_input_negotiate(struct connectdata *conn, char *header)
|
||||||
gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
|
gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
|
||||||
int ret;
|
int ret;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
bool gss;
|
||||||
|
const char* protocol;
|
||||||
|
|
||||||
while(*header && isspace((int)*header))
|
while(*header && isspace((int)*header))
|
||||||
header++;
|
header++;
|
||||||
if(!checkprefix("GSS-Negotiate", header))
|
if(checkprefix("GSS-Negotiate", header)) {
|
||||||
|
protocol = "GSS-Negotiate";
|
||||||
|
gss = TRUE;
|
||||||
|
}
|
||||||
|
else if (checkprefix("Negotiate", header)) {
|
||||||
|
protocol = "Negotiate";
|
||||||
|
gss = FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (neg_ctx->context) {
|
||||||
|
if (neg_ctx->gss != gss) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
neg_ctx->protocol = protocol;
|
||||||
|
neg_ctx->gss = gss;
|
||||||
|
}
|
||||||
|
|
||||||
if (neg_ctx->context && neg_ctx->status == GSS_S_COMPLETE) {
|
if (neg_ctx->context && neg_ctx->status == GSS_S_COMPLETE) {
|
||||||
/* We finished succesfully our part of authentication, but server
|
/* We finished succesfully our part of authentication, but server
|
||||||
* rejected it (since we're again here). Exit with an error since we
|
* rejected it (since we're again here). Exit with an error since we
|
||||||
|
@ -125,7 +156,7 @@ int Curl_input_negotiate(struct connectdata *conn, char *header)
|
||||||
(ret = get_gss_name(conn, &neg_ctx->server_name)))
|
(ret = get_gss_name(conn, &neg_ctx->server_name)))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
header += strlen("GSS-Negotiate");
|
header += strlen(neg_ctx->protocol);
|
||||||
while(*header && isspace((int)*header))
|
while(*header && isspace((int)*header))
|
||||||
header++;
|
header++;
|
||||||
|
|
||||||
|
@ -188,7 +219,7 @@ CURLcode Curl_output_negotiate(struct connectdata *conn)
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
|
||||||
conn->allocptr.userpwd =
|
conn->allocptr.userpwd =
|
||||||
aprintf("Authorization: GSS-Negotiate %s\r\n", encoded);
|
aprintf("Authorization: %s %s\r\n", neg_ctx->protocol, encoded);
|
||||||
free(encoded);
|
free(encoded);
|
||||||
gss_release_buffer(&minor_status, &neg_ctx->output_token);
|
gss_release_buffer(&minor_status, &neg_ctx->output_token);
|
||||||
return (conn->allocptr.userpwd == NULL) ? CURLE_OUT_OF_MEMORY : CURLE_OK;
|
return (conn->allocptr.userpwd == NULL) ? CURLE_OUT_OF_MEMORY : CURLE_OK;
|
||||||
|
|
|
@ -186,6 +186,8 @@ struct ntlmdata {
|
||||||
|
|
||||||
#ifdef GSSAPI
|
#ifdef GSSAPI
|
||||||
struct negotiatedata {
|
struct negotiatedata {
|
||||||
|
bool gss; /* Whether we're processing GSS-Negotiate or Negotiate */
|
||||||
|
const char* protocol; /* "GSS-Negotiate" or "Negotiate" */
|
||||||
OM_uint32 status;
|
OM_uint32 status;
|
||||||
gss_ctx_id_t context;
|
gss_ctx_id_t context;
|
||||||
gss_name_t server_name;
|
gss_name_t server_name;
|
||||||
|
|
Loading…
Reference in New Issue