|
Packit Service |
9f2c4a |
/* Copyright (C) 2012 the GSS-PROXY contributors, see COPYING for license */
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
#include "gss_plugin.h"
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
static OM_uint32 init_ctx_local(OM_uint32 *minor_status,
|
|
Packit Service |
9f2c4a |
struct gpp_cred_handle *cred_handle,
|
|
Packit Service |
9f2c4a |
struct gpp_context_handle *ctx_handle,
|
|
Packit Service |
9f2c4a |
struct gpp_name_handle *name,
|
|
Packit Service |
9f2c4a |
gss_OID mech_type,
|
|
Packit Service |
9f2c4a |
OM_uint32 req_flags,
|
|
Packit Service |
9f2c4a |
OM_uint32 time_req,
|
|
Packit Service |
9f2c4a |
gss_channel_bindings_t input_cb,
|
|
Packit Service |
9f2c4a |
gss_buffer_t input_token,
|
|
Packit Service |
9f2c4a |
gss_OID *actual_mech_type,
|
|
Packit Service |
9f2c4a |
gss_buffer_t output_token,
|
|
Packit Service |
9f2c4a |
OM_uint32 *ret_flags,
|
|
Packit Service |
9f2c4a |
OM_uint32 *time_rec)
|
|
Packit Service |
9f2c4a |
{
|
|
Packit Service |
9f2c4a |
OM_uint32 maj, min;
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
if (name->remote && !name->local) {
|
|
Packit Service |
9f2c4a |
maj = gpp_name_to_local(&min, name->remote,
|
|
Packit Service |
9f2c4a |
mech_type, &name->local);
|
|
Packit Service |
9f2c4a |
if (maj) {
|
|
Packit Service |
9f2c4a |
goto done;
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
maj = gss_init_sec_context(&min,
|
|
Packit Service |
9f2c4a |
cred_handle->local,
|
|
Packit Service |
9f2c4a |
&ctx_handle->local,
|
|
Packit Service |
9f2c4a |
name->local,
|
|
Packit Service |
9f2c4a |
gpp_special_mech(mech_type),
|
|
Packit Service |
9f2c4a |
req_flags,
|
|
Packit Service |
9f2c4a |
time_req,
|
|
Packit Service |
9f2c4a |
input_cb,
|
|
Packit Service |
9f2c4a |
input_token,
|
|
Packit Service |
9f2c4a |
actual_mech_type,
|
|
Packit Service |
9f2c4a |
output_token,
|
|
Packit Service |
9f2c4a |
ret_flags,
|
|
Packit Service |
9f2c4a |
time_rec);
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
done:
|
|
Packit Service |
9f2c4a |
*minor_status = min;
|
|
Packit Service |
9f2c4a |
return maj;
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
OM_uint32 gssi_init_sec_context(OM_uint32 *minor_status,
|
|
Packit Service |
9f2c4a |
gss_cred_id_t claimant_cred_handle,
|
|
Packit Service |
9f2c4a |
gss_ctx_id_t *context_handle,
|
|
Packit Service |
9f2c4a |
gss_name_t target_name,
|
|
Packit Service |
9f2c4a |
gss_OID mech_type,
|
|
Packit Service |
9f2c4a |
OM_uint32 req_flags,
|
|
Packit Service |
9f2c4a |
OM_uint32 time_req,
|
|
Packit Service |
9f2c4a |
gss_channel_bindings_t input_cb,
|
|
Packit Service |
9f2c4a |
gss_buffer_t input_token,
|
|
Packit Service |
9f2c4a |
gss_OID *actual_mech_type,
|
|
Packit Service |
9f2c4a |
gss_buffer_t output_token,
|
|
Packit Service |
9f2c4a |
OM_uint32 *ret_flags,
|
|
Packit Service |
9f2c4a |
OM_uint32 *time_rec)
|
|
Packit Service |
9f2c4a |
{
|
|
Packit Service |
9f2c4a |
enum gpp_behavior behavior = GPP_UNINITIALIZED;
|
|
Packit Service |
9f2c4a |
struct gpp_context_handle *ctx_handle = NULL;
|
|
Packit Service |
9f2c4a |
struct gpp_cred_handle *cred_handle = NULL;
|
|
Packit Service |
9f2c4a |
gssx_cred *out_cred = NULL;
|
|
Packit Service |
9f2c4a |
struct gpp_name_handle *name;
|
|
Packit Service |
9f2c4a |
OM_uint32 tmaj, tmin;
|
|
Packit Service |
9f2c4a |
OM_uint32 maj, min;
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
GSSI_TRACE();
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
*minor_status = 0;
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
if (target_name == GSS_C_NO_NAME) {
|
|
Packit Service |
9f2c4a |
return GSS_S_CALL_INACCESSIBLE_READ;
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
if (mech_type == GSS_C_NO_OID || gpp_is_special_oid(mech_type)) {
|
|
Packit Service |
9f2c4a |
return GSS_S_BAD_MECH;
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
tmaj = GSS_S_COMPLETE;
|
|
Packit Service |
9f2c4a |
tmin = 0;
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
if (*context_handle) {
|
|
Packit Service |
9f2c4a |
ctx_handle = (struct gpp_context_handle *)*context_handle;
|
|
Packit Service |
9f2c4a |
if (ctx_handle->local) {
|
|
Packit Service |
9f2c4a |
/* ok this means a previous call decided to use the local mech,
|
|
Packit Service |
9f2c4a |
* so let's just re-enter the mechglue here and keep at it */
|
|
Packit Service |
9f2c4a |
behavior = GPP_LOCAL_ONLY;
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
} else {
|
|
Packit Service |
9f2c4a |
ctx_handle = calloc(1, sizeof(struct gpp_context_handle));
|
|
Packit Service |
9f2c4a |
if (!ctx_handle) {
|
|
Packit Service |
9f2c4a |
maj = GSS_S_FAILURE;
|
|
Packit Service |
9f2c4a |
min = ENOMEM;
|
|
Packit Service |
9f2c4a |
goto done;
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
if (claimant_cred_handle != GSS_C_NO_CREDENTIAL) {
|
|
Packit Service |
9f2c4a |
cred_handle = (struct gpp_cred_handle *)claimant_cred_handle;
|
|
Packit Service |
9f2c4a |
if (cred_handle->local) {
|
|
Packit Service |
9f2c4a |
/* ok this means a previous call decided to short circuit to the
|
|
Packit Service |
9f2c4a |
* local mech, so let's just re-enter the mechglue here, as we
|
|
Packit Service |
9f2c4a |
* have no way to export creds yet. */
|
|
Packit Service |
9f2c4a |
behavior = GPP_LOCAL_ONLY;
|
|
Packit Service |
9f2c4a |
} else if (behavior == GPP_LOCAL_ONLY) {
|
|
Packit Service |
9f2c4a |
maj = GSS_S_DEFECTIVE_CREDENTIAL;
|
|
Packit Service |
9f2c4a |
min = 0;
|
|
Packit Service |
9f2c4a |
goto done;
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
} else {
|
|
Packit Service |
9f2c4a |
maj = gpp_cred_handle_init(&min, true, NULL, &cred_handle);
|
|
Packit Service |
9f2c4a |
if (maj) {
|
|
Packit Service |
9f2c4a |
goto done;
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
name = (struct gpp_name_handle *)target_name;
|
|
Packit Service |
9f2c4a |
if (behavior == GPP_UNINITIALIZED) {
|
|
Packit Service |
9f2c4a |
behavior = gpp_get_behavior();
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
/* See if we should try local first */
|
|
Packit Service |
9f2c4a |
if (behavior == GPP_LOCAL_ONLY || behavior == GPP_LOCAL_FIRST) {
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
maj = init_ctx_local(&min, cred_handle, ctx_handle, name,
|
|
Packit Service |
9f2c4a |
mech_type, req_flags, time_req, input_cb,
|
|
Packit Service |
9f2c4a |
input_token, actual_mech_type, output_token,
|
|
Packit Service |
9f2c4a |
ret_flags, time_rec);
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
if (maj == GSS_S_COMPLETE || maj == GSS_S_CONTINUE_NEEDED ||
|
|
Packit Service |
9f2c4a |
behavior == GPP_LOCAL_ONLY) {
|
|
Packit Service |
9f2c4a |
goto done;
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
/* not successful, save actual local error if remote fallback fails */
|
|
Packit Service |
9f2c4a |
tmaj = maj;
|
|
Packit Service |
9f2c4a |
tmin = min;
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
/* Then try with remote */
|
|
Packit Service |
9f2c4a |
if (behavior != GPP_LOCAL_ONLY) {
|
|
Packit Service |
9f2c4a |
if (name->local && !name->remote) {
|
|
Packit Service |
9f2c4a |
maj = gpp_local_to_name(&min, name->local, &name->remote);
|
|
Packit Service |
9f2c4a |
if (maj) {
|
|
Packit Service |
9f2c4a |
goto done;
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
if (!cred_handle->remote) {
|
|
Packit Service |
9f2c4a |
/* we ignore failures here */
|
|
Packit Service |
9f2c4a |
(void)gppint_get_def_creds(&min, GPP_REMOTE_ONLY, NULL,
|
|
Packit Service |
9f2c4a |
GSS_C_INITIATE, &cred_handle);
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
maj = gpm_init_sec_context(&min,
|
|
Packit Service |
9f2c4a |
cred_handle->remote,
|
|
Packit Service |
9f2c4a |
&ctx_handle->remote,
|
|
Packit Service |
9f2c4a |
name->remote,
|
|
Packit Service |
9f2c4a |
mech_type,
|
|
Packit Service |
9f2c4a |
req_flags,
|
|
Packit Service |
9f2c4a |
time_req,
|
|
Packit Service |
9f2c4a |
input_cb,
|
|
Packit Service |
9f2c4a |
input_token,
|
|
Packit Service |
9f2c4a |
actual_mech_type,
|
|
Packit Service |
9f2c4a |
output_token,
|
|
Packit Service |
9f2c4a |
ret_flags,
|
|
Packit Service |
9f2c4a |
time_rec,
|
|
Packit Service |
9f2c4a |
&out_cred);
|
|
Packit Service |
9f2c4a |
if (maj == GSS_S_COMPLETE || maj == GSS_S_CONTINUE_NEEDED) {
|
|
Packit Service |
9f2c4a |
if (out_cred) {
|
|
Packit Service |
9f2c4a |
xdr_free((xdrproc_t)xdr_gssx_cred,
|
|
Packit Service |
9f2c4a |
(char *)cred_handle->remote);
|
|
Packit Service |
9f2c4a |
free(cred_handle->remote);
|
|
Packit Service |
9f2c4a |
cred_handle->remote = out_cred;
|
|
Packit Service |
9f2c4a |
out_cred = NULL;
|
|
Packit Service |
9f2c4a |
/* failuire is not fatal */
|
|
Packit Service |
9f2c4a |
(void)gpp_store_remote_creds(&tmin,
|
|
Packit Service |
9f2c4a |
cred_handle->default_creds,
|
|
Packit Service |
9f2c4a |
&cred_handle->store,
|
|
Packit Service |
9f2c4a |
cred_handle->remote);
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
goto done;
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
if (behavior == GPP_REMOTE_FIRST) {
|
|
Packit Service |
9f2c4a |
/* So remote failed, but we can fallback to local, try that */
|
|
Packit Service |
9f2c4a |
maj = init_ctx_local(&min, cred_handle, ctx_handle, name,
|
|
Packit Service |
9f2c4a |
mech_type, req_flags, time_req, input_cb,
|
|
Packit Service |
9f2c4a |
input_token, actual_mech_type, output_token,
|
|
Packit Service |
9f2c4a |
ret_flags, time_rec);
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
done:
|
|
Packit Service |
9f2c4a |
if (maj != GSS_S_COMPLETE &&
|
|
Packit Service |
9f2c4a |
maj != GSS_S_CONTINUE_NEEDED &&
|
|
Packit Service |
9f2c4a |
tmaj != GSS_S_COMPLETE) {
|
|
Packit Service |
9f2c4a |
maj = tmaj;
|
|
Packit Service |
9f2c4a |
min = tmin;
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
if (maj != GSS_S_COMPLETE && maj != GSS_S_CONTINUE_NEEDED) {
|
|
Packit Service |
9f2c4a |
if (ctx_handle &&
|
|
Packit Service |
9f2c4a |
ctx_handle->local == GSS_C_NO_CONTEXT &&
|
|
Packit Service |
9f2c4a |
ctx_handle->remote == NULL) {
|
|
Packit Service |
9f2c4a |
free(ctx_handle);
|
|
Packit Service |
9f2c4a |
ctx_handle = NULL;
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
*minor_status = gpp_map_error(min);
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
/* always replace the provided context handle to avoid
|
|
Packit Service |
9f2c4a |
* dangling pointers when a context has been passed in */
|
|
Packit Service |
9f2c4a |
*context_handle = (gss_ctx_id_t)ctx_handle;
|
|
Packit Service |
9f2c4a |
|
|
Packit Service |
9f2c4a |
if (claimant_cred_handle == GSS_C_NO_CREDENTIAL) {
|
|
Packit Service |
9f2c4a |
free(cred_handle);
|
|
Packit Service |
9f2c4a |
}
|
|
Packit Service |
9f2c4a |
return maj;
|
|
Packit Service |
9f2c4a |
}
|