aboutsummaryrefslogtreecommitdiff
path: root/lib/gssapi/krb5/accept_sec_context.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gssapi/krb5/accept_sec_context.c')
-rw-r--r--lib/gssapi/krb5/accept_sec_context.c134
1 files changed, 79 insertions, 55 deletions
diff --git a/lib/gssapi/krb5/accept_sec_context.c b/lib/gssapi/krb5/accept_sec_context.c
index e35cc10e560c..3f8e2740e212 100644
--- a/lib/gssapi/krb5/accept_sec_context.c
+++ b/lib/gssapi/krb5/accept_sec_context.c
@@ -149,50 +149,39 @@ _gsskrb5i_is_cfx(krb5_context context, gsskrb5_ctx ctx, int acceptor)
static OM_uint32
-gsskrb5_accept_delegated_token
-(OM_uint32 * minor_status,
- gsskrb5_ctx ctx,
- krb5_context context,
- gss_cred_id_t * delegated_cred_handle
- )
+gsskrb5_accept_delegated_token(OM_uint32 *minor_status,
+ gsskrb5_ctx ctx,
+ krb5_context context,
+ gss_cred_id_t *delegated_cred_handle)
{
krb5_ccache ccache = NULL;
krb5_error_code kret;
int32_t ac_flags, ret = GSS_S_COMPLETE;
+ gsskrb5_cred handle;
*minor_status = 0;
/* XXX Create a new delegated_cred_handle? */
- if (delegated_cred_handle == NULL) {
- ret = GSS_S_COMPLETE;
- goto out;
- }
+ if (delegated_cred_handle == NULL)
+ return GSS_S_COMPLETE;
*delegated_cred_handle = NULL;
- kret = krb5_cc_new_unique (context, krb5_cc_type_memory,
- NULL, &ccache);
- if (kret) {
- ctx->flags &= ~GSS_C_DELEG_FLAG;
- goto out;
+ kret = krb5_cc_resolve(context, "MEMORY:anonymous", &ccache);
+ if (kret == 0)
+ kret = krb5_cc_initialize(context, ccache, ctx->source);
+ if (kret == 0) {
+ (void) krb5_auth_con_removeflags(context,
+ ctx->auth_context,
+ KRB5_AUTH_CONTEXT_DO_TIME,
+ &ac_flags);
+ kret = krb5_rd_cred2(context,
+ ctx->auth_context,
+ ccache,
+ &ctx->fwd_data);
+ (void) krb5_auth_con_setflags(context,
+ ctx->auth_context,
+ ac_flags);
}
-
- kret = krb5_cc_initialize(context, ccache, ctx->source);
- if (kret) {
- ctx->flags &= ~GSS_C_DELEG_FLAG;
- goto out;
- }
-
- krb5_auth_con_removeflags(context,
- ctx->auth_context,
- KRB5_AUTH_CONTEXT_DO_TIME,
- &ac_flags);
- kret = krb5_rd_cred2(context,
- ctx->auth_context,
- ccache,
- &ctx->fwd_data);
- krb5_auth_con_setflags(context,
- ctx->auth_context,
- ac_flags);
if (kret) {
ctx->flags &= ~GSS_C_DELEG_FLAG;
ret = GSS_S_FAILURE;
@@ -200,31 +189,54 @@ gsskrb5_accept_delegated_token
goto out;
}
- if (delegated_cred_handle) {
- gsskrb5_cred handle;
-
- ret = _gsskrb5_krb5_import_cred(minor_status,
- ccache,
- NULL,
- NULL,
- delegated_cred_handle);
- if (ret != GSS_S_COMPLETE)
- goto out;
+ ret = _gsskrb5_krb5_import_cred(minor_status,
+ &ccache,
+ NULL,
+ NULL,
+ delegated_cred_handle);
+ if (ret != GSS_S_COMPLETE)
+ goto out;
- handle = (gsskrb5_cred) *delegated_cred_handle;
+ handle = (gsskrb5_cred) *delegated_cred_handle;
+ handle->cred_flags |= GSS_CF_DESTROY_CRED_ON_RELEASE;
- handle->cred_flags |= GSS_CF_DESTROY_CRED_ON_RELEASE;
- krb5_cc_close(context, ccache);
- ccache = NULL;
+ /*
+ * A root TGT is one of the form krbtgt/REALM@SAME-REALM.
+ *
+ * A destination TGT is a root TGT for the same realm as the acceptor
+ * service's realm.
+ *
+ * Normally clients delegate a root TGT for the client's realm.
+ *
+ * In some deployments clients may want to delegate destination TGTs as
+ * a form of constrained delegation: so that the destination service
+ * cannot use the delegated credential to impersonate the client
+ * principal to services in its home realm (due to KDC lineage/transit
+ * checks). In those deployments there may not even be a route back to
+ * the KDCs of the client's realm, and attempting to use a
+ * non-destination TGT might even lead to timeouts.
+ *
+ * We could simply pretend not to have obtained a credential, except
+ * that a) we don't (yet) have an app name here for the appdefault we
+ * need to check, b) the application really wants to be able to log a
+ * message about the delegated credential being no good.
+ *
+ * Thus we leave it to _gsskrb5_store_cred_into2() to decide what to do
+ * with non-destination TGTs. To do that, it needs the realm of the
+ * acceptor service, which we record here.
+ */
+ handle->destination_realm =
+ strdup(krb5_principal_get_realm(context, ctx->target));
+ if (handle->destination_realm == NULL) {
+ _gsskrb5_release_cred(minor_status, delegated_cred_handle);
+ *minor_status = krb5_enomem(context);
+ ret = GSS_S_FAILURE;
+ goto out;
}
out:
if (ccache) {
- /* Don't destroy the default cred cache */
- if (delegated_cred_handle == NULL)
- krb5_cc_close(context, ccache);
- else
- krb5_cc_destroy(context, ccache);
+ krb5_cc_close(context, ccache);
}
return ret;
}
@@ -377,6 +389,13 @@ gsskrb5_acceptor_start(OM_uint32 * minor_status,
GSS_KRB5_MECHANISM);
if (ret) {
+ /* Could be a raw AP-REQ (check for APPLICATION tag) */
+ if (input_token_buffer->length == 0 ||
+ ((const uint8_t *)input_token_buffer->value)[0] != 0x6E) {
+ *minor_status = ASN1_MISPLACED_FIELD;
+ return GSS_S_DEFECTIVE_TOKEN;
+ }
+
/* Assume that there is no OID wrapping. */
indata.length = input_token_buffer->length;
indata.data = input_token_buffer->value;
@@ -443,7 +462,10 @@ gsskrb5_acceptor_start(OM_uint32 * minor_status,
* lets only send the error token on clock skew, that
* limit when send error token for non-MUTUAL.
*/
- free_Authenticator(ctx->auth_context->authenticator);
+ krb5_auth_con_free(context, ctx->auth_context);
+ krb5_auth_con_free(context, ctx->deleg_auth_context);
+ ctx->deleg_auth_context = NULL;
+ ctx->auth_context = NULL;
return send_error_token(minor_status, context, kret,
server, &indata, output_token);
} else if (kret) {
@@ -532,9 +554,10 @@ gsskrb5_acceptor_start(OM_uint32 * minor_status,
if (authenticator->cksum != NULL
&& authenticator->cksum->cksumtype == CKSUMTYPE_GSSAPI) {
- ret = _gsskrb5_verify_8003_checksum(minor_status,
+ ret = _gsskrb5_verify_8003_checksum(context,
+ minor_status,
input_chan_bindings,
- authenticator->cksum,
+ authenticator,
&ctx->flags,
&ctx->fwd_data);
@@ -561,6 +584,7 @@ gsskrb5_acceptor_start(OM_uint32 * minor_status,
* GSSAPI checksum here
*/
+ _krb5_crypto_set_flags(context, crypto, KRB5_CRYPTO_FLAG_ALLOW_UNKEYED_CHECKSUM);
kret = krb5_verify_checksum(context,
crypto, KRB5_KU_AP_REQ_AUTH_CKSUM, NULL, 0,
authenticator->cksum);