summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimo Sorce <simo@redhat.com>2013-11-15 10:33:52 -0500
committerGünther Deschner <gdeschner@redhat.com>2013-11-19 14:34:47 +0100
commit556ea844a5783f9876ee748e1c686bb268f54e8a (patch)
treee21df0795873b1f5a77b6e82bc4d8d69dee99ee2
parentb8901d1d20a5d0ef1a3118bfe5816e04c09e6cf5 (diff)
downloadgss-proxy-556ea844a5783f9876ee748e1c686bb268f54e8a.tar.gz
gss-proxy-556ea844a5783f9876ee748e1c686bb268f54e8a.tar.xz
gss-proxy-556ea844a5783f9876ee748e1c686bb268f54e8a.zip
Fix continuations in context establishment calls
Properly support continuations, including returning the rigth error code and exporting partial contexts. Fixes multistep authentications in particular for the initialization case which always uses continuations. Resolves: https://fedorahosted.org/gss-proxy/ticket/108 Reviewed-by: Günther Deschner <gdeschner@redhat.com>
-rw-r--r--proxy/src/client/gpm_init_sec_context.c21
-rw-r--r--proxy/src/gp_export.c33
-rw-r--r--proxy/src/gp_export.h3
-rw-r--r--proxy/src/gp_rpc_accept_sec_context.c20
-rw-r--r--proxy/src/gp_rpc_get_mic.c2
-rw-r--r--proxy/src/gp_rpc_init_sec_context.c16
-rw-r--r--proxy/src/gp_rpc_unwrap.c2
-rw-r--r--proxy/src/gp_rpc_verify_mic.c2
-rw-r--r--proxy/src/gp_rpc_wrap.c2
9 files changed, 77 insertions, 24 deletions
diff --git a/proxy/src/client/gpm_init_sec_context.c b/proxy/src/client/gpm_init_sec_context.c
index b6ce34f..f6dfe53 100644
--- a/proxy/src/client/gpm_init_sec_context.c
+++ b/proxy/src/client/gpm_init_sec_context.c
@@ -104,13 +104,6 @@ OM_uint32 gpm_init_sec_context(OM_uint32 *minor_status,
}
}
- if (res->status.major_status) {
- gpm_save_status(&res->status);
- ret_maj = res->status.major_status;
- ret_min = res->status.minor_status;
- goto done;
- }
-
if (res->context_handle) {
ctx = res->context_handle;
/* we are stealing the delegated creds on success, so we do not want
@@ -118,12 +111,18 @@ OM_uint32 gpm_init_sec_context(OM_uint32 *minor_status,
res->context_handle = NULL;
}
- ret = gp_conv_gssx_to_buffer_alloc(res->output_token, &outbuf);
- if (ret) {
- gpm_save_internal_status(ret, strerror(ret));
- goto done;
+ if (res->output_token) {
+ ret = gp_conv_gssx_to_buffer_alloc(res->output_token, &outbuf);
+ if (ret) {
+ gpm_save_internal_status(ret, strerror(ret));
+ goto done;
+ }
}
+ ret_maj = res->status.major_status;
+ ret_min = res->status.minor_status;
+ gpm_save_status(&res->status);
+
done:
if (ret != 0) {
ret_min = ret;
diff --git a/proxy/src/gp_export.c b/proxy/src/gp_export.c
index 51dd686..3cd5148 100644
--- a/proxy/src/gp_export.c
+++ b/proxy/src/gp_export.c
@@ -390,6 +390,7 @@ done:
#define LINUX_LUCID_V1 "linux_lucid_v1"
enum exp_ctx_types {
+ EXP_CTX_PARTIAL = -1, /* cannot be specified by client */
EXP_CTX_DEFAULT = 0,
EXP_CTX_LINUX_LUCID_V1 = 1,
};
@@ -418,6 +419,11 @@ int gp_get_exported_context_type(struct gssx_call_ctx *ctx)
return EXP_CTX_DEFAULT;
}
+int gp_get_continue_needed_type(void)
+{
+ return EXP_CTX_PARTIAL;
+}
+
#define KRB5_CTX_FLAG_INITIATOR 0x00000001
#define KRB5_CTX_FLAG_CFX 0x00000002
#define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY 0x00000004
@@ -513,7 +519,7 @@ done:
}
-uint32_t gp_export_ctx_id_to_gssx(uint32_t *min, int type,
+uint32_t gp_export_ctx_id_to_gssx(uint32_t *min, int type, gss_OID mech,
gss_ctx_id_t *in, gssx_ctx *out)
{
uint32_t ret_maj;
@@ -529,9 +535,6 @@ uint32_t gp_export_ctx_id_to_gssx(uint32_t *min, int type,
int is_open;
int ret;
-/* TODO: For mechs that need multiple roundtrips to complete */
- /* out->state; */
-
/* we do not need the client to release anything until we handle state */
out->needs_release = false;
@@ -539,6 +542,11 @@ uint32_t gp_export_ctx_id_to_gssx(uint32_t *min, int type,
&lifetime_rec, &mech_type, &ctx_flags,
&is_locally_initiated, &is_open);
if (ret_maj) {
+ if (type == EXP_CTX_PARTIAL) {
+ /* This may happen on partially established context,
+ * so just go on and put in what we can */
+ goto export;
+ }
goto done;
}
@@ -571,9 +579,26 @@ uint32_t gp_export_ctx_id_to_gssx(uint32_t *min, int type,
out->open = true;
}
+export:
/* note: once converted the original context token is not usable anymore,
* so this must be the last call to use it */
switch (type) {
+ case EXP_CTX_PARTIAL:
+ /* this happens only when a init_sec_context call returns a partially
+ * initialized context so we return only what we have, not much */
+ ret = gp_conv_oid_to_gssx(mech, &out->mech);
+ if (ret) {
+ ret_maj = GSS_S_FAILURE;
+ ret_min = ret;
+ goto done;
+ }
+
+ out->locally_initiated = true;
+ out->open = false;
+
+ /* out->state; */
+
+ /* fall through */
case EXP_CTX_DEFAULT:
ret_maj = gss_export_sec_context(&ret_min, in, &export_buffer);
if (ret_maj) {
diff --git a/proxy/src/gp_export.h b/proxy/src/gp_export.h
index 58c0040..03e5d18 100644
--- a/proxy/src/gp_export.h
+++ b/proxy/src/gp_export.h
@@ -37,7 +37,8 @@ uint32_t gp_import_gssx_cred(uint32_t *min, struct gp_call_ctx *gpcall,
gssx_cred *cred, gss_cred_id_t *out);
int gp_get_exported_context_type(struct gssx_call_ctx *ctx);
-uint32_t gp_export_ctx_id_to_gssx(uint32_t *min, int type,
+int gp_get_continue_needed_type(void);
+uint32_t gp_export_ctx_id_to_gssx(uint32_t *min, int type, gss_OID mech,
gss_ctx_id_t *in, gssx_ctx *out);
uint32_t gp_import_gssx_to_ctx_id(uint32_t *min, int type,
gssx_ctx *in, gss_ctx_id_t *out);
diff --git a/proxy/src/gp_rpc_accept_sec_context.c b/proxy/src/gp_rpc_accept_sec_context.c
index 40370aa..efbf07a 100644
--- a/proxy/src/gp_rpc_accept_sec_context.c
+++ b/proxy/src/gp_rpc_accept_sec_context.c
@@ -46,6 +46,8 @@ int gp_accept_sec_context(struct gp_call_ctx *gpcall,
gss_cred_id_t *pdch = NULL;
int exp_ctx_type;
int exp_creds_type;
+ uint32_t acpt_maj;
+ uint32_t acpt_min;
int ret;
asca = &arg->accept_sec_context;
@@ -109,17 +111,25 @@ int gp_accept_sec_context(struct gp_call_ctx *gpcall,
&ret_flags,
NULL,
pdch);
- if (ret_maj) {
+ if (ret_maj != GSS_S_COMPLETE &&
+ ret_maj != GSS_S_CONTINUE_NEEDED) {
goto done;
+ } else {
+ acpt_maj = ret_maj;
+ acpt_min = ret_min;
+ }
+ if (acpt_maj == GSS_S_CONTINUE_NEEDED) {
+ exp_ctx_type = gp_get_continue_needed_type();
}
+
ascr->context_handle = calloc(1, sizeof(gssx_ctx));
if (!ascr->context_handle) {
ret_maj = GSS_S_FAILURE;
ret_min = ENOMEM;
goto done;
}
- ret_maj = gp_export_ctx_id_to_gssx(&ret_min, exp_ctx_type,
+ ret_maj = gp_export_ctx_id_to_gssx(&ret_min, exp_ctx_type, oid,
&ctx, ascr->context_handle);
if (ret_maj) {
goto done;
@@ -138,7 +148,7 @@ int gp_accept_sec_context(struct gp_call_ctx *gpcall,
goto done;
}
- if ((ret_flags & GSS_C_DELEG_FLAG) && asca->ret_deleg_cred) {
+ if ((ret_flags & GSS_C_DELEG_FLAG) && asca->ret_deleg_cred && dch) {
ascr->delegated_cred_handle = calloc(1, sizeof(gssx_cred));
if (!ascr->delegated_cred_handle) {
ret_maj = GSS_S_FAILURE;
@@ -159,6 +169,10 @@ int gp_accept_sec_context(struct gp_call_ctx *gpcall,
&ascr->options.options_val);
done:
+ if (ret_maj == GSS_S_COMPLETE) {
+ ret_maj = acpt_maj;
+ ret_min = acpt_min;
+ }
ret = gp_conv_status_to_gssx(&asca->call_ctx,
ret_maj, ret_min, oid,
&ascr->status);
diff --git a/proxy/src/gp_rpc_get_mic.c b/proxy/src/gp_rpc_get_mic.c
index ca60fe4..2db7d3f 100644
--- a/proxy/src/gp_rpc_get_mic.c
+++ b/proxy/src/gp_rpc_get_mic.c
@@ -73,7 +73,7 @@ int gp_get_mic(struct gp_call_ctx *gpcall,
goto done;
}
- ret_maj = gp_export_ctx_id_to_gssx(&ret_min, exp_ctx_type,
+ ret_maj = gp_export_ctx_id_to_gssx(&ret_min, exp_ctx_type, GSS_C_NO_OID,
&context_handle,
gmr->context_handle);
if (ret_maj) {
diff --git a/proxy/src/gp_rpc_init_sec_context.c b/proxy/src/gp_rpc_init_sec_context.c
index 944389c..2781238 100644
--- a/proxy/src/gp_rpc_init_sec_context.c
+++ b/proxy/src/gp_rpc_init_sec_context.c
@@ -45,6 +45,8 @@ int gp_init_sec_context(struct gp_call_ctx *gpcall,
gss_buffer_desc obuf = GSS_C_EMPTY_BUFFER;
uint32_t ret_maj;
uint32_t ret_min;
+ uint32_t init_maj;
+ uint32_t init_min;
int exp_ctx_type;
int ret;
@@ -121,6 +123,12 @@ int gp_init_sec_context(struct gp_call_ctx *gpcall,
if (ret_maj != GSS_S_COMPLETE &&
ret_maj != GSS_S_CONTINUE_NEEDED) {
goto done;
+ } else {
+ init_maj = ret_maj;
+ init_min = ret_min;
+ }
+ if (init_maj == GSS_S_CONTINUE_NEEDED) {
+ exp_ctx_type = gp_get_continue_needed_type();
}
iscr->context_handle = calloc(1, sizeof(gssx_ctx));
@@ -129,7 +137,7 @@ int gp_init_sec_context(struct gp_call_ctx *gpcall,
ret_min = ENOMEM;
goto done;
}
- ret_maj = gp_export_ctx_id_to_gssx(&ret_min, exp_ctx_type,
+ ret_maj = gp_export_ctx_id_to_gssx(&ret_min, exp_ctx_type, mech_type,
&ctx, iscr->context_handle);
if (ret_maj) {
goto done;
@@ -150,7 +158,13 @@ int gp_init_sec_context(struct gp_call_ctx *gpcall,
}
}
+ ret_maj = GSS_S_COMPLETE;
+
done:
+ if (ret_maj == GSS_S_COMPLETE) {
+ ret_maj = init_maj;
+ ret_min = init_min;
+ }
ret = gp_conv_status_to_gssx(&isca->call_ctx,
ret_maj, ret_min, mech_type,
&iscr->status);
diff --git a/proxy/src/gp_rpc_unwrap.c b/proxy/src/gp_rpc_unwrap.c
index a20b8ea..faffa82 100644
--- a/proxy/src/gp_rpc_unwrap.c
+++ b/proxy/src/gp_rpc_unwrap.c
@@ -85,7 +85,7 @@ int gp_unwrap(struct gp_call_ctx *gpcall,
goto done;
}
- ret_maj = gp_export_ctx_id_to_gssx(&ret_min, exp_ctx_type,
+ ret_maj = gp_export_ctx_id_to_gssx(&ret_min, exp_ctx_type, GSS_C_NO_OID,
&context_handle,
uwr->context_handle);
if (ret_maj) {
diff --git a/proxy/src/gp_rpc_verify_mic.c b/proxy/src/gp_rpc_verify_mic.c
index 68369a0..a2d3f7e 100644
--- a/proxy/src/gp_rpc_verify_mic.c
+++ b/proxy/src/gp_rpc_verify_mic.c
@@ -76,7 +76,7 @@ int gp_verify_mic(struct gp_call_ctx *gpcall,
goto done;
}
- ret_maj = gp_export_ctx_id_to_gssx(&ret_min, exp_ctx_type,
+ ret_maj = gp_export_ctx_id_to_gssx(&ret_min, exp_ctx_type, GSS_C_NO_OID,
&context_handle,
vmr->context_handle);
if (ret_maj) {
diff --git a/proxy/src/gp_rpc_wrap.c b/proxy/src/gp_rpc_wrap.c
index d17c292..c2da7ba 100644
--- a/proxy/src/gp_rpc_wrap.c
+++ b/proxy/src/gp_rpc_wrap.c
@@ -85,7 +85,7 @@ int gp_wrap(struct gp_call_ctx *gpcall,
goto done;
}
- ret_maj = gp_export_ctx_id_to_gssx(&ret_min, exp_ctx_type,
+ ret_maj = gp_export_ctx_id_to_gssx(&ret_min, exp_ctx_type, GSS_C_NO_OID,
&context_handle, wr->context_handle);
if (ret_maj) {
goto done;