summaryrefslogtreecommitdiff
path: root/auth/auth_kerb_gss.c
diff options
context:
space:
mode:
Diffstat (limited to 'auth/auth_kerb_gss.c')
-rw-r--r--auth/auth_kerb_gss.c78
1 files changed, 73 insertions, 5 deletions
diff --git a/auth/auth_kerb_gss.c b/auth/auth_kerb_gss.c
index b7267d6..69d93ab 100644
--- a/auth/auth_kerb_gss.c
+++ b/auth/auth_kerb_gss.c
@@ -13,21 +13,69 @@
* limitations under the License.
*/
+#include "serf.h"
+#include "serf_private.h"
#include "auth_kerb.h"
#ifdef SERF_USE_GSSAPI
#include <apr_strings.h>
#include <gssapi/gssapi.h>
+
+/* This module can support all authentication mechanisms as provided by
+ the GSS-API implementation, but for now it only supports SPNEGO for
+ Negotiate.
+ SPNEGO can delegate authentication to Kerberos if supported by the
+ host. */
+
+#ifndef GSS_SPNEGO_MECHANISM
+static gss_OID_desc spnego_mech_oid = { 6, "\x2b\x06\x01\x05\x05\x02" };
+#define GSS_SPNEGO_MECHANISM &spnego_mech_oid
+#endif
+
struct serf__kerb_context_t
{
/* GSSAPI context */
gss_ctx_id_t gss_ctx;
- /* Mechanism used to authenticate, should be Kerberos. */
+ /* Mechanism used to authenticate. */
gss_OID gss_mech;
};
+static void
+log_error(int verbose_flag, const char *filename,
+ serf__kerb_context_t *ctx,
+ OM_uint32 err_maj_stat,
+ OM_uint32 err_min_stat,
+ const char *msg)
+{
+ OM_uint32 maj_stat, min_stat;
+ gss_buffer_desc stat_buff;
+ OM_uint32 msg_ctx = 0;
+
+ if (verbose_flag) {
+ maj_stat = gss_display_status(&min_stat,
+ err_maj_stat,
+ GSS_C_GSS_CODE,
+ ctx->gss_mech,
+ &msg_ctx,
+ &stat_buff);
+ if (maj_stat == GSS_S_COMPLETE ||
+ maj_stat == GSS_S_FAILURE) {
+ maj_stat = gss_display_status(&min_stat,
+ err_min_stat,
+ GSS_C_MECH_CODE,
+ ctx->gss_mech,
+ &msg_ctx,
+ &stat_buff);
+ }
+
+ serf__log(verbose_flag, filename,
+ "%s (%x,%d): %s\n", msg,
+ err_maj_stat, err_min_stat, stat_buff.value);
+ }
+}
+
/* Cleans the GSS context object, when the pool used to create it gets
cleared or destroyed. */
static apr_status_t
@@ -66,7 +114,7 @@ serf__kerb_create_sec_context(serf__kerb_context_t **ctx_p,
ctx = apr_pcalloc(result_pool, sizeof(*ctx));
ctx->gss_ctx = GSS_C_NO_CONTEXT;
- ctx->gss_mech = GSS_C_NO_OID;
+ ctx->gss_mech = GSS_SPNEGO_MECHANISM;
apr_pool_cleanup_register(result_pool, ctx,
cleanup_ctx,
@@ -78,6 +126,19 @@ serf__kerb_create_sec_context(serf__kerb_context_t **ctx_p,
}
apr_status_t
+serf__kerb_reset_sec_context(serf__kerb_context_t *ctx)
+{
+ OM_uint32 dummy_stat;
+
+ if (ctx->gss_ctx)
+ (void)gss_delete_sec_context(&dummy_stat, &ctx->gss_ctx,
+ GSS_C_NO_BUFFER);
+ ctx->gss_ctx = GSS_C_NO_CONTEXT;
+
+ return APR_SUCCESS;
+}
+
+apr_status_t
serf__kerb_init_sec_context(serf__kerb_context_t *ctx,
const char *service,
const char *hostname,
@@ -92,11 +153,15 @@ serf__kerb_init_sec_context(serf__kerb_context_t *ctx,
OM_uint32 gss_min_stat, gss_maj_stat;
gss_name_t host_gss_name;
gss_buffer_desc bufdesc;
+ gss_OID dummy; /* unused */
/* Get the name for the HTTP service at the target host. */
+ /* TODO: should be shared between multiple requests. */
bufdesc.value = apr_pstrcat(scratch_pool, service, "@", hostname, NULL);
bufdesc.length = strlen(bufdesc.value);
- gss_maj_stat = gss_import_name (&gss_min_stat, &bufdesc, GSS_C_NT_HOSTBASED_SERVICE,
+ serf__log(AUTH_VERBOSE, __FILE__, "Get principal for %s\n", bufdesc.value);
+ gss_maj_stat = gss_import_name (&gss_min_stat, &bufdesc,
+ GSS_C_NT_HOSTBASED_SERVICE,
&host_gss_name);
if(GSS_ERROR(gss_maj_stat)) {
return APR_EGENERAL;
@@ -115,12 +180,12 @@ serf__kerb_init_sec_context(serf__kerb_context_t *ctx,
GSS_C_NO_CREDENTIAL, /* XXXXX claimant_cred_handle */
&ctx->gss_ctx, /* gssapi context handle */
host_gss_name, /* HTTP@server name */
- ctx->gss_mech, /* mech_type (0 ininitially */
+ ctx->gss_mech, /* mech_type (SPNEGO) */
GSS_C_MUTUAL_FLAG, /* ensure the peer authenticates itself */
0, /* default validity period */
GSS_C_NO_CHANNEL_BINDINGS, /* do not use channel bindings */
&gss_input_buf, /* server token, initially empty */
- &ctx->gss_mech, /* actual mech type */
+ &dummy, /* actual mech type */
gss_output_buf_p, /* output_token */
NULL, /* ret_flags */
NULL /* not interested in remaining validity */
@@ -139,6 +204,9 @@ serf__kerb_init_sec_context(serf__kerb_context_t *ctx,
case GSS_S_CONTINUE_NEEDED:
return APR_EAGAIN;
default:
+ log_error(AUTH_VERBOSE, __FILE__, ctx,
+ gss_maj_stat, gss_min_stat,
+ "Error during Kerberos handshake");
return APR_EGENERAL;
}
}