- Make local neon copy support gssapi correctly (#150132)
parent
b9773b1340
commit
ea11941c4d
@ -0,0 +1,516 @@
|
|||||||
|
|
||||||
|
Update to the GSSAPI implementation from HEAD.
|
||||||
|
|
||||||
|
--- neon/src/ne_auth.c (revision 309)
|
||||||
|
+++ neon/src/ne_auth.c (working copy)
|
||||||
|
@@ -161,8 +161,11 @@
|
||||||
|
/* This used for Basic auth */
|
||||||
|
char *basic;
|
||||||
|
#ifdef HAVE_GSSAPI
|
||||||
|
- /* This used for GSSAPI auth */
|
||||||
|
+ /* for the GSSAPI/Negotiate scheme: */
|
||||||
|
char *gssapi_token;
|
||||||
|
+ gss_ctx_id_t gssctx;
|
||||||
|
+ gss_name_t gssname;
|
||||||
|
+ gss_OID gssmech;
|
||||||
|
#endif
|
||||||
|
/* These all used for Digest auth */
|
||||||
|
char *realm;
|
||||||
|
@@ -202,7 +205,7 @@
|
||||||
|
struct ne_md5_ctx response_body;
|
||||||
|
|
||||||
|
/* Results of response-header callbacks */
|
||||||
|
- char *auth_hdr, *auth_info_hdr;
|
||||||
|
+ ne_buffer *auth_hdr, *auth_info_hdr;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void clean_session(auth_session *sess)
|
||||||
|
@@ -214,6 +217,17 @@
|
||||||
|
NE_FREE(sess->opaque);
|
||||||
|
NE_FREE(sess->realm);
|
||||||
|
#ifdef HAVE_GSSAPI
|
||||||
|
+ {
|
||||||
|
+ int major;
|
||||||
|
+
|
||||||
|
+ if (sess->gssctx != GSS_C_NO_CONTEXT)
|
||||||
|
+ gss_delete_sec_context(&major, sess->gssctx, GSS_C_NO_BUFFER);
|
||||||
|
+
|
||||||
|
+ if (sess->gssmech != GSS_C_NO_OID) {
|
||||||
|
+ gss_release_oid(&major, &sess->gssmech);
|
||||||
|
+ sess->gssmech = GSS_C_NO_OID;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
NE_FREE(sess->gssapi_token);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
@@ -321,69 +335,162 @@
|
||||||
|
/* Add GSSAPI authentication credentials to a request */
|
||||||
|
static char *request_gssapi(auth_session *sess)
|
||||||
|
{
|
||||||
|
- return ne_concat("Negotiate ", sess->gssapi_token, "\r\n", NULL);
|
||||||
|
+ if (sess->gssapi_token)
|
||||||
|
+ return ne_concat("Negotiate ", sess->gssapi_token, "\r\n", NULL);
|
||||||
|
+ else
|
||||||
|
+ return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int get_gss_name(gss_name_t *server, auth_session *sess)
|
||||||
|
+/* Create an GSSAPI name for server HOSTNAME; returns non-zero on
|
||||||
|
+ * error. */
|
||||||
|
+static void get_gss_name(gss_name_t *server, const char *hostname)
|
||||||
|
{
|
||||||
|
- unsigned int major_status, minor_status;
|
||||||
|
+ unsigned int major, minor;
|
||||||
|
gss_buffer_desc token = GSS_C_EMPTY_BUFFER;
|
||||||
|
|
||||||
|
- token.value = ne_concat("HTTP@", sess->sess->server.hostname, NULL);
|
||||||
|
+ token.value = ne_concat("HTTP@", hostname, NULL);
|
||||||
|
token.length = strlen(token.value);
|
||||||
|
|
||||||
|
- major_status = gss_import_name(&minor_status, &token,
|
||||||
|
- GSS_C_NT_HOSTBASED_SERVICE,
|
||||||
|
- server);
|
||||||
|
- return GSS_ERROR(major_status) ? -1 : 0;
|
||||||
|
+ major = gss_import_name(&minor, &token, GSS_C_NT_HOSTBASED_SERVICE,
|
||||||
|
+ server);
|
||||||
|
+ ne_free(token.value);
|
||||||
|
+
|
||||||
|
+ if (GSS_ERROR(major)) {
|
||||||
|
+ NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: gss_import_name failed.\n");
|
||||||
|
+ *server = GSS_C_NO_NAME;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
-/* Examine a GSSAPI auth challenge; returns 0 if a valid challenge,
|
||||||
|
- * else non-zero. */
|
||||||
|
-static int
|
||||||
|
-gssapi_challenge(auth_session *sess, struct auth_challenge *parms)
|
||||||
|
+/* Append GSSAPI error(s) for STATUS of type TYPE to BUF; prepending
|
||||||
|
+ * ": " to each error if *FLAG is non-zero, setting *FLAG after an
|
||||||
|
+ * error has been appended. */
|
||||||
|
+static void make_gss_error(ne_buffer *buf, int *flag,
|
||||||
|
+ unsigned int status, int type)
|
||||||
|
{
|
||||||
|
- gss_ctx_id_t context;
|
||||||
|
- gss_name_t server_name;
|
||||||
|
- unsigned int major_status, minor_status;
|
||||||
|
- gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
|
||||||
|
- gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
|
||||||
|
+ int major, minor;
|
||||||
|
+ int context = 0;
|
||||||
|
+
|
||||||
|
+ do {
|
||||||
|
+ gss_buffer_desc msg;
|
||||||
|
+ major = gss_display_status(&minor, status, type,
|
||||||
|
+ GSS_C_NO_OID, &context, &msg);
|
||||||
|
+ if (major == GSS_S_COMPLETE && msg.length) {
|
||||||
|
+ if ((*flag)++) ne_buffer_append(buf, ": ", 2);
|
||||||
|
+ ne_buffer_append(buf, msg.value, msg.length);
|
||||||
|
+ }
|
||||||
|
+ if (msg.length) gss_release_buffer(&minor, &msg);
|
||||||
|
+ } while (context);
|
||||||
|
+}
|
||||||
|
|
||||||
|
- clean_session(sess);
|
||||||
|
+/* Continue a GSS-API Negotiate exchange, using input TOKEN if
|
||||||
|
+ * non-NULL. Returns non-zero on error. */
|
||||||
|
+static int continue_negotiate(auth_session *sess, const char *token)
|
||||||
|
+{
|
||||||
|
+ unsigned int major, minor;
|
||||||
|
+ gss_buffer_desc input = GSS_C_EMPTY_BUFFER;
|
||||||
|
+ gss_buffer_desc output = GSS_C_EMPTY_BUFFER;
|
||||||
|
+ unsigned char *bintoken = NULL;
|
||||||
|
+ int ret;
|
||||||
|
+ gss_OID mech = sess->gssmech;
|
||||||
|
|
||||||
|
- if (get_gss_name(&server_name, sess))
|
||||||
|
+ if (token) {
|
||||||
|
+ input.length = ne_unbase64(token, &bintoken);
|
||||||
|
+ if (input.length == 0) {
|
||||||
|
+ NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: Invalid input [%s].\n",
|
||||||
|
+ token);
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+ input.value = bintoken;
|
||||||
|
+ NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: Continuation token [%s]\n", token);
|
||||||
|
+ }
|
||||||
|
+ else if (sess->gssctx != GSS_C_NO_CONTEXT) {
|
||||||
|
+ NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: Reset incomplete context.\n");
|
||||||
|
+ gss_delete_sec_context(&minor, &sess->gssctx, GSS_C_NO_BUFFER);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ major = gss_init_sec_context(&minor, GSS_C_NO_CREDENTIAL, &sess->gssctx,
|
||||||
|
+ sess->gssname, mech,
|
||||||
|
+ GSS_C_MUTUAL_FLAG, GSS_C_INDEFINITE,
|
||||||
|
+ GSS_C_NO_CHANNEL_BINDINGS,
|
||||||
|
+ &input, &sess->gssmech, &output, NULL, NULL);
|
||||||
|
+
|
||||||
|
+ /* done with the input token. */
|
||||||
|
+ if (bintoken) ne_free(bintoken);
|
||||||
|
+
|
||||||
|
+ if (GSS_ERROR(major)) {
|
||||||
|
+ ne_buffer *err = ne_buffer_create();
|
||||||
|
+ int flag = 0;
|
||||||
|
+
|
||||||
|
+ make_gss_error(err, &flag, major, GSS_C_GSS_CODE);
|
||||||
|
+ make_gss_error(err, &flag, minor, GSS_C_MECH_CODE);
|
||||||
|
+ NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: Error: %s\n", err->data);
|
||||||
|
+ ne_set_error(sess->sess, _("GSSAPI authentication error (%s)"),
|
||||||
|
+ err->data);
|
||||||
|
+ ne_buffer_destroy(err);
|
||||||
|
return -1;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- major_status = gss_init_sec_context(&minor_status,
|
||||||
|
- GSS_C_NO_CREDENTIAL,
|
||||||
|
- &context,
|
||||||
|
- server_name,
|
||||||
|
- GSS_C_NO_OID,
|
||||||
|
- 0,
|
||||||
|
- GSS_C_INDEFINITE,
|
||||||
|
- GSS_C_NO_CHANNEL_BINDINGS,
|
||||||
|
- &input_token,
|
||||||
|
- NULL,
|
||||||
|
- &output_token,
|
||||||
|
- NULL,
|
||||||
|
- NULL);
|
||||||
|
- gss_release_name(&minor_status, &server_name);
|
||||||
|
+ if (major == GSS_S_CONTINUE_NEEDED || major == GSS_S_COMPLETE) {
|
||||||
|
+ NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: init_sec_context OK. (major=%d)\n",
|
||||||
|
+ major);
|
||||||
|
+ ret = 0;
|
||||||
|
+ }
|
||||||
|
+ else {
|
||||||
|
+ NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: Init failure %d.\n", major);
|
||||||
|
+ ret = -1;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- if (GSS_ERROR(major_status)) {
|
||||||
|
- NE_DEBUG(NE_DBG_HTTPAUTH, "gss_init_sec_context failed.\n");
|
||||||
|
+ if (major != GSS_S_CONTINUE_NEEDED) {
|
||||||
|
+ /* context no longer needed: destroy it */
|
||||||
|
+ gss_delete_sec_context(&minor, &sess->gssctx, GSS_C_NO_BUFFER);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (output.length) {
|
||||||
|
+ sess->gssapi_token = ne_base64(output.value, output.length);
|
||||||
|
+ NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: Output token: [%s]\n",
|
||||||
|
+ sess->gssapi_token);
|
||||||
|
+ gss_release_buffer(&minor, &output);
|
||||||
|
+ } else {
|
||||||
|
+ NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: No output token.\n");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Process a Negotiate challange CHALL in session SESS; returns zero
|
||||||
|
+ * if challenge is accepted. */
|
||||||
|
+static int gssapi_challenge(auth_session *sess, struct auth_challenge *chall)
|
||||||
|
+{
|
||||||
|
+ int ret = continue_negotiate(sess, chall->opaque);
|
||||||
|
+ if (ret == 0)
|
||||||
|
+ sess->scheme = auth_scheme_gssapi;
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* Verify the header HDR in a Negotiate response. */
|
||||||
|
+static int verify_negotiate_response(auth_session *sess, char *hdr)
|
||||||
|
+{
|
||||||
|
+ char *sep, *ptr = strchr(hdr, ' ');
|
||||||
|
+
|
||||||
|
+ if (strncmp(hdr, "Negotiate", ptr - hdr) != 0) {
|
||||||
|
+ NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: Not a Negotiate response!\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (output_token.length == 0)
|
||||||
|
- return -1;
|
||||||
|
+ ptr++;
|
||||||
|
|
||||||
|
- sess->gssapi_token = ne_base64(output_token.value, output_token.length);
|
||||||
|
- gss_release_buffer(&major_status, &output_token);
|
||||||
|
+ if (strlen(ptr) == 0) {
|
||||||
|
+ NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: No token in Negotiate response!\n");
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
- NE_DEBUG(NE_DBG_HTTPAUTH,
|
||||||
|
- "Base64 encoded GSSAPI challenge: %s.\n", sess->gssapi_token);
|
||||||
|
- sess->scheme = auth_scheme_gssapi;
|
||||||
|
- return 0;
|
||||||
|
+ if ((sep = strchr(ptr, ',')) != NULL)
|
||||||
|
+ *sep = '\0';
|
||||||
|
+ if ((sep = strchr(ptr, ' ')) != NULL)
|
||||||
|
+ *sep = '\0';
|
||||||
|
+
|
||||||
|
+ NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: Negotiate response token [%s]\n", ptr);
|
||||||
|
+ return continue_negotiate(sess, ptr);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@@ -637,7 +744,8 @@
|
||||||
|
*pnt = '\0';
|
||||||
|
*value = pnt + 1;
|
||||||
|
state = AFTER_EQ;
|
||||||
|
- } else if (*pnt == ' ' && ischall && *key != NULL) {
|
||||||
|
+ } else if ((*pnt == ' ' || *pnt == ',')
|
||||||
|
+ && ischall && *key != NULL) {
|
||||||
|
*value = NULL;
|
||||||
|
*pnt = '\0';
|
||||||
|
*hdr = pnt + 1;
|
||||||
|
@@ -679,8 +787,8 @@
|
||||||
|
* 0 if it gives a valid authentication for the server
|
||||||
|
* non-zero otherwise (don't believe the response in this case!).
|
||||||
|
*/
|
||||||
|
-static int verify_response(struct auth_request *req, auth_session *sess,
|
||||||
|
- const char *value)
|
||||||
|
+static int verify_digest_response(struct auth_request *req, auth_session *sess,
|
||||||
|
+ const char *value)
|
||||||
|
{
|
||||||
|
char *hdr, *pnt, *key, *val;
|
||||||
|
auth_qop qop = auth_qop_none;
|
||||||
|
@@ -842,36 +950,39 @@
|
||||||
|
while (!tokenize(&pnt, &key, &val, 1)) {
|
||||||
|
|
||||||
|
if (val == NULL) {
|
||||||
|
- /* We have a new challenge */
|
||||||
|
- NE_DEBUG(NE_DBG_HTTPAUTH, "New challenge for scheme [%s]\n", key);
|
||||||
|
- chall = ne_calloc(sizeof *chall);
|
||||||
|
+ auth_scheme scheme;
|
||||||
|
|
||||||
|
- chall->next = challenges;
|
||||||
|
- challenges = chall;
|
||||||
|
- /* Initialize the challenge parameters */
|
||||||
|
- /* Which auth-scheme is it (case-insensitive matching) */
|
||||||
|
if (strcasecmp(key, "basic") == 0) {
|
||||||
|
- NE_DEBUG(NE_DBG_HTTPAUTH, "Basic scheme.\n");
|
||||||
|
- chall->scheme = auth_scheme_basic;
|
||||||
|
+ scheme = auth_scheme_basic;
|
||||||
|
} else if (strcasecmp(key, "digest") == 0) {
|
||||||
|
- NE_DEBUG(NE_DBG_HTTPAUTH, "Digest scheme.\n");
|
||||||
|
- chall->scheme = auth_scheme_digest;
|
||||||
|
-#ifdef HAVE_GSSAPI
|
||||||
|
+ scheme = auth_scheme_digest;
|
||||||
|
+ }
|
||||||
|
+#ifdef HAVE_GSSAPI
|
||||||
|
+ /* cope with a Negotiate parameter which doesn't match the
|
||||||
|
+ * auth-param due to the broken spec. */
|
||||||
|
+ else if (chall && chall->scheme == auth_scheme_gssapi
|
||||||
|
+ && chall->opaque == NULL) {
|
||||||
|
+ chall->opaque = key;
|
||||||
|
+ continue;
|
||||||
|
} else if (strcasecmp(key, "negotiate") == 0) {
|
||||||
|
- NE_DEBUG(NE_DBG_HTTPAUTH, "GSSAPI scheme.\n");
|
||||||
|
- chall->scheme = auth_scheme_gssapi;
|
||||||
|
+ scheme = auth_scheme_gssapi;
|
||||||
|
+ }
|
||||||
|
#endif
|
||||||
|
- } else {
|
||||||
|
- NE_DEBUG(NE_DBG_HTTPAUTH, "Unknown scheme.\n");
|
||||||
|
- ne_free(chall);
|
||||||
|
- challenges = NULL;
|
||||||
|
- break;
|
||||||
|
+ else {
|
||||||
|
+ NE_DEBUG(NE_DBG_HTTPAUTH, "Ignoring challenge '%s'.\n", key);
|
||||||
|
+ chall = NULL;
|
||||||
|
+ continue;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ NE_DEBUG(NE_DBG_HTTPAUTH, "New '%s' challenge.\n", key);
|
||||||
|
+ chall = ne_calloc(sizeof *chall);
|
||||||
|
+ chall->scheme = scheme;
|
||||||
|
+ chall->next = challenges;
|
||||||
|
+ challenges = chall;
|
||||||
|
continue;
|
||||||
|
} else if (chall == NULL) {
|
||||||
|
- /* If we haven't got an auth-scheme, and we're
|
||||||
|
- * haven't yet found a challenge, skip this pair.
|
||||||
|
- */
|
||||||
|
+ /* Ignore pairs for an unknown challenge. */
|
||||||
|
+ NE_DEBUG(NE_DBG_HTTPAUTH, "Ignored pair: %s = %s\n", key, val);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -924,15 +1035,17 @@
|
||||||
|
success = 0;
|
||||||
|
|
||||||
|
#ifdef HAVE_GSSAPI
|
||||||
|
- if (strcmp(ne_get_scheme(sess->sess), "https") == 0) {
|
||||||
|
+ /* Ignore Negotiate challenges from origin servers which don't
|
||||||
|
+ * come over SSL. */
|
||||||
|
+ if (sess->spec == &ah_proxy_class || sess->context != AUTH_ANY) {
|
||||||
|
NE_DEBUG(NE_DBG_HTTPAUTH, "Looking for GSSAPI.\n");
|
||||||
|
/* Try a GSSAPI challenge */
|
||||||
|
for (chall = challenges; chall != NULL; chall = chall->next) {
|
||||||
|
if (chall->scheme == auth_scheme_gssapi) {
|
||||||
|
- if (!gssapi_challenge(sess, chall)) {
|
||||||
|
- success = 1;
|
||||||
|
- break;
|
||||||
|
- }
|
||||||
|
+ if (!gssapi_challenge(sess, chall)) {
|
||||||
|
+ success = 1;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -993,6 +1106,14 @@
|
||||||
|
ne_md5_process_bytes(block, length, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* Collect auth challenges into an ne_buffer */
|
||||||
|
+static void ah_collect_header(void *userdata, const char *value)
|
||||||
|
+{
|
||||||
|
+ ne_buffer *ar = userdata;
|
||||||
|
+ if (ne_buffer_size(ar)) ne_buffer_append(ar, ", ", 2);
|
||||||
|
+ ne_buffer_zappend(ar, value);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static void ah_create(ne_request *req, void *session, const char *method,
|
||||||
|
const char *uri)
|
||||||
|
{
|
||||||
|
@@ -1009,14 +1130,14 @@
|
||||||
|
areq->method = method;
|
||||||
|
areq->uri = uri;
|
||||||
|
areq->request = req;
|
||||||
|
+ areq->auth_hdr = ne_buffer_create();
|
||||||
|
+ areq->auth_info_hdr = ne_buffer_create();
|
||||||
|
|
||||||
|
ne_add_response_header_handler(req, sess->spec->resp_hdr,
|
||||||
|
- ne_duplicate_header, &areq->auth_hdr);
|
||||||
|
-
|
||||||
|
+ ah_collect_header, areq->auth_hdr);
|
||||||
|
|
||||||
|
ne_add_response_header_handler(req, sess->spec->resp_info_hdr,
|
||||||
|
- ne_duplicate_header,
|
||||||
|
- &areq->auth_info_hdr);
|
||||||
|
+ ah_collect_header, areq->auth_info_hdr);
|
||||||
|
|
||||||
|
sess->attempt = 0;
|
||||||
|
|
||||||
|
@@ -1035,7 +1156,7 @@
|
||||||
|
} else {
|
||||||
|
char *value;
|
||||||
|
|
||||||
|
- NE_DEBUG(NE_DBG_HTTPAUTH, "Handling.");
|
||||||
|
+ NE_DEBUG(NE_DBG_HTTPAUTH, "Handling auth session.\n");
|
||||||
|
req->will_handle = 1;
|
||||||
|
|
||||||
|
if (sess->qop == auth_qop_auth_int) {
|
||||||
|
@@ -1082,22 +1203,44 @@
|
||||||
|
|
||||||
|
if (!areq) return NE_OK;
|
||||||
|
|
||||||
|
+#ifdef HAVE_GSSAPI
|
||||||
|
+ /* whatever happens: forget the GSSAPI token cached thus far */
|
||||||
|
+ if (sess->gssapi_token) {
|
||||||
|
+ ne_free(sess->gssapi_token);
|
||||||
|
+ sess->gssapi_token = NULL;
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
NE_DEBUG(NE_DBG_HTTPAUTH,
|
||||||
|
"ah_post_send (#%d), code is %d (want %d), %s is %s\n",
|
||||||
|
sess->attempt, status->code, sess->spec->status_code,
|
||||||
|
- sess->spec->resp_hdr, SAFELY(areq->auth_hdr));
|
||||||
|
- if (areq->auth_info_hdr != NULL &&
|
||||||
|
- verify_response(areq, sess, areq->auth_info_hdr)) {
|
||||||
|
- NE_DEBUG(NE_DBG_HTTPAUTH, "Response authentication invalid.\n");
|
||||||
|
- ne_set_error(sess->sess, "%s", _(sess->spec->fail_msg));
|
||||||
|
- ret = NE_ERROR;
|
||||||
|
- } else if ((status->code == sess->spec->status_code ||
|
||||||
|
- (status->code == 401 && sess->context == AUTH_CONNECT)) &&
|
||||||
|
- areq->auth_hdr != NULL) {
|
||||||
|
+ sess->spec->resp_hdr, areq->auth_hdr->data);
|
||||||
|
+ if (ne_buffer_size(areq->auth_info_hdr)
|
||||||
|
+ && sess->scheme == auth_scheme_digest) {
|
||||||
|
+ if (verify_digest_response(areq, sess, areq->auth_info_hdr->data)) {
|
||||||
|
+ NE_DEBUG(NE_DBG_HTTPAUTH, "Response authentication invalid.\n");
|
||||||
|
+ ne_set_error(sess->sess, "%s", _(sess->spec->fail_msg));
|
||||||
|
+ ret = NE_ERROR;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+#ifdef HAVE_GSSAPI
|
||||||
|
+ /* one must wonder... has Mr Brezak actually read RFC2617? */
|
||||||
|
+ else if (sess->scheme == auth_scheme_gssapi
|
||||||
|
+ && (status->klass == 2 || status->klass == 3)
|
||||||
|
+ && ne_buffer_size(areq->auth_hdr)) {
|
||||||
|
+ if (verify_negotiate_response(sess, areq->auth_hdr->data)) {
|
||||||
|
+ NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: Mutual auth failed.\n");
|
||||||
|
+ ret = NE_ERROR;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+#endif /* HAVE_GSSAPI */
|
||||||
|
+ else if ((status->code == sess->spec->status_code ||
|
||||||
|
+ (status->code == 401 && sess->context == AUTH_CONNECT)) &&
|
||||||
|
+ ne_buffer_size(areq->auth_hdr)) {
|
||||||
|
/* note above: allow a 401 in response to a CONNECT request
|
||||||
|
* from a proxy since some buggy proxies send that. */
|
||||||
|
- NE_DEBUG(NE_DBG_HTTPAUTH, "Got challenge with code %d.\n", status->code);
|
||||||
|
- if (!auth_challenge(sess, areq->auth_hdr)) {
|
||||||
|
+ NE_DEBUG(NE_DBG_HTTPAUTH, "Got challenge (code %d).\n", status->code);
|
||||||
|
+ if (!auth_challenge(sess, areq->auth_hdr->data)) {
|
||||||
|
ret = NE_RETRY;
|
||||||
|
} else {
|
||||||
|
clean_session(sess);
|
||||||
|
@@ -1105,9 +1248,9 @@
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- NE_FREE(areq->auth_info_hdr);
|
||||||
|
- NE_FREE(areq->auth_hdr);
|
||||||
|
-
|
||||||
|
+ ne_buffer_clear(areq->auth_hdr);
|
||||||
|
+ ne_buffer_clear(areq->auth_info_hdr);
|
||||||
|
+
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1115,13 +1258,25 @@
|
||||||
|
{
|
||||||
|
auth_session *sess = session;
|
||||||
|
struct auth_request *areq = ne_get_request_private(req, sess->spec->id);
|
||||||
|
- if (areq) ne_free(areq);
|
||||||
|
+
|
||||||
|
+ if (areq) {
|
||||||
|
+ ne_buffer_destroy(areq->auth_info_hdr);
|
||||||
|
+ ne_buffer_destroy(areq->auth_hdr);
|
||||||
|
+ ne_free(areq);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
static void free_auth(void *cookie)
|
||||||
|
{
|
||||||
|
auth_session *sess = cookie;
|
||||||
|
|
||||||
|
+#ifdef HAVE_GSSAPI
|
||||||
|
+ if (sess->gssname != GSS_C_NO_NAME) {
|
||||||
|
+ int major;
|
||||||
|
+ gss_release_name(&major, sess->gssname);
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
clean_session(sess);
|
||||||
|
ne_free(sess);
|
||||||
|
}
|
||||||
|
@@ -1137,10 +1292,17 @@
|
||||||
|
ahs->sess = sess;
|
||||||
|
ahs->spec = ahc;
|
||||||
|
|
||||||
|
- if (strcmp(ne_get_scheme(sess), "https") == 0)
|
||||||
|
+ if (strcmp(ne_get_scheme(sess), "https") == 0) {
|
||||||
|
ahs->context = isproxy ? AUTH_CONNECT : AUTH_NOTCONNECT;
|
||||||
|
- else
|
||||||
|
+ } else {
|
||||||
|
ahs->context = AUTH_ANY;
|
||||||
|
+ }
|
||||||
|
+#ifdef HAVE_GSSAPI
|
||||||
|
+ get_gss_name(&ahs->gssname, (isproxy ? sess->proxy.hostname
|
||||||
|
+ : sess->server.hostname));
|
||||||
|
+ ahs->gssctx = GSS_C_NO_CONTEXT;
|
||||||
|
+ ahs->gssmech = GSS_C_NO_OID;
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
/* Register hooks */
|
||||||
|
ne_hook_create_request(sess, ah_create, ahs);
|
Loading…
Reference in new issue