diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2013-06-03 18:34:10 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2013-06-03 18:34:10 +0000 |
commit | f143c3cab79c59dd57124f19d16ac35253843136 (patch) | |
tree | 9fa67aa3d59e9d96f5f37858e95c4ab91960ea92 /auth/auth_kerb_gss.c | |
parent | 6f61a1acd01dc2ad1d2f5c1f7458702c77c69f9c (diff) | |
download | libserf-tarball-master.tar.gz |
serf-1.2.1HEADserf-1.2.1master
Diffstat (limited to 'auth/auth_kerb_gss.c')
-rw-r--r-- | auth/auth_kerb_gss.c | 78 |
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; } } |