mirror of
https://github.com/PowerShell/openssh-portable.git
synced 2025-07-28 16:24:39 +02:00
Fixed various unhandled failure paths in Kerb GSS/SSPI adapter (#393)
This commit is contained in:
parent
d9773976a7
commit
aaf11e2149
@ -121,10 +121,14 @@ gss_indicate_mechs(_Out_ OM_uint32 * minor_status, _Outptr_ gss_OID_set *mech_se
|
|||||||
return GSS_S_FAILURE;
|
return GSS_S_FAILURE;
|
||||||
|
|
||||||
/* create an list that contains the one oid that we support */
|
/* create an list that contains the one oid that we support */
|
||||||
if (gss_create_empty_oid_set(minor_status, mech_set) != GSS_S_COMPLETE ||
|
if (gss_create_empty_oid_set(minor_status, mech_set) != GSS_S_COMPLETE)
|
||||||
gss_add_oid_set_member(minor_status, GSS_C_NT_HOSTBASED_SERVICE, mech_set) != GSS_S_COMPLETE)
|
|
||||||
return GSS_S_FAILURE;
|
return GSS_S_FAILURE;
|
||||||
|
|
||||||
|
if (gss_add_oid_set_member(minor_status, GSS_C_NT_HOSTBASED_SERVICE, mech_set) != GSS_S_COMPLETE) {
|
||||||
|
gss_release_oid_set(minor_status, mech_set);
|
||||||
|
return GSS_S_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
return GSS_S_COMPLETE;
|
return GSS_S_COMPLETE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -393,11 +397,19 @@ gss_acquire_cred(_Out_ OM_uint32 *minor_status, _In_opt_ gss_name_t desired_name
|
|||||||
_In_opt_ OM_uint32 time_req, _In_opt_ gss_OID_set desired_mechs, _In_ gss_cred_usage_t cred_usage,
|
_In_opt_ OM_uint32 time_req, _In_opt_ gss_OID_set desired_mechs, _In_ gss_cred_usage_t cred_usage,
|
||||||
_Outptr_opt_ gss_cred_id_t * output_cred_handle, _Outptr_opt_ gss_OID_set *actual_mechs, _Out_opt_ OM_uint32 *time_rec)
|
_Outptr_opt_ gss_cred_id_t * output_cred_handle, _Outptr_opt_ gss_OID_set *actual_mechs, _Out_opt_ OM_uint32 *time_rec)
|
||||||
{
|
{
|
||||||
|
OM_uint32 ret = GSS_S_FAILURE;
|
||||||
|
SYSTEMTIME current_time_system;
|
||||||
|
wchar_t * desired_name_utf16 = NULL;
|
||||||
|
CredHandle cred_handle, *p_cred_handle = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
if (output_cred_handle != NULL)
|
||||||
|
*output_cred_handle = NULL;
|
||||||
|
|
||||||
if (ssh_gss_sspi_init(minor_status) == 0)
|
if (ssh_gss_sspi_init(minor_status) == 0)
|
||||||
return GSS_S_FAILURE;
|
goto done;
|
||||||
|
|
||||||
/* get the current time so we can determine expiration if requested */
|
/* get the current time so we can determine expiration if requested */
|
||||||
SYSTEMTIME current_time_system;
|
|
||||||
GetSystemTime(¤t_time_system);
|
GetSystemTime(¤t_time_system);
|
||||||
|
|
||||||
/* translate credential usage parameters */
|
/* translate credential usage parameters */
|
||||||
@ -407,24 +419,24 @@ gss_acquire_cred(_Out_ OM_uint32 *minor_status, _In_opt_ gss_name_t desired_name
|
|||||||
else if (cred_usage == GSS_C_BOTH) cred_usage_local = SECPKG_CRED_BOTH;
|
else if (cred_usage == GSS_C_BOTH) cred_usage_local = SECPKG_CRED_BOTH;
|
||||||
|
|
||||||
/* convert input name to unicode so we can process usernames with special characters */
|
/* convert input name to unicode so we can process usernames with special characters */
|
||||||
wchar_t * desired_name_utf16 = utf8_to_utf16(desired_name);
|
if ((desired_name_utf16 = utf8_to_utf16(desired_name)) == NULL)
|
||||||
|
goto done;
|
||||||
|
|
||||||
/* acquire a handle to existing credentials -- in many cases the name will
|
/* acquire a handle to existing credentials -- in many cases the name will
|
||||||
* be null in which case the credentials of the current user are used */
|
* be null in which case the credentials of the current user are used */
|
||||||
CredHandle cred_handle;
|
|
||||||
TimeStamp expiry;
|
TimeStamp expiry;
|
||||||
SECURITY_STATUS status = SecFunctions->AcquireCredentialsHandleW(desired_name_utf16, MICROSOFT_KERBEROS_NAME_W, cred_usage_local,
|
SECURITY_STATUS status = SecFunctions->AcquireCredentialsHandleW(desired_name_utf16, MICROSOFT_KERBEROS_NAME_W, cred_usage_local,
|
||||||
NULL, NULL, NULL, NULL, &cred_handle, &expiry);
|
NULL, NULL, NULL, NULL, &cred_handle, &expiry);
|
||||||
free(desired_name_utf16);
|
|
||||||
|
|
||||||
/* fail immediately if errors occurred */
|
/* fail immediately if errors occurred */
|
||||||
if (status != SEC_E_OK)
|
if (status != SEC_E_OK)
|
||||||
return GSS_S_FAILURE;
|
goto done;
|
||||||
|
|
||||||
|
p_cred_handle = &cred_handle;
|
||||||
/* copy credential data out of local buffer */
|
/* copy credential data out of local buffer */
|
||||||
if (output_cred_handle != NULL) {
|
if (output_cred_handle != NULL) {
|
||||||
if ((*output_cred_handle = malloc(sizeof(struct cred_st))) == NULL)
|
if ((*output_cred_handle = malloc(sizeof(struct cred_st))) == NULL)
|
||||||
return GSS_S_FAILURE;
|
goto done;
|
||||||
(*output_cred_handle)->isToken = 0;
|
(*output_cred_handle)->isToken = 0;
|
||||||
(*output_cred_handle)->credHandle = cred_handle;
|
(*output_cred_handle)->credHandle = cred_handle;
|
||||||
}
|
}
|
||||||
@ -437,10 +449,23 @@ gss_acquire_cred(_Out_ OM_uint32 *minor_status, _In_opt_ gss_name_t desired_name
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* set actual supported mechs if requested */
|
/* set actual supported mechs if requested */
|
||||||
if (actual_mechs != NULL)
|
if (actual_mechs != NULL && gss_indicate_mechs(minor_status, actual_mechs) != GSS_S_COMPLETE)
|
||||||
gss_indicate_mechs(minor_status, actual_mechs);
|
goto done;
|
||||||
|
|
||||||
return GSS_S_COMPLETE;
|
ret = GSS_S_COMPLETE;
|
||||||
|
done:
|
||||||
|
if (desired_name_utf16)
|
||||||
|
free(desired_name_utf16);
|
||||||
|
if (ret != GSS_S_COMPLETE) {
|
||||||
|
if (p_cred_handle)
|
||||||
|
SecFunctions->FreeCredentialsHandle(p_cred_handle);
|
||||||
|
if (output_cred_handle && *output_cred_handle) {
|
||||||
|
free(*output_cred_handle);
|
||||||
|
*output_cred_handle = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -458,21 +483,35 @@ gss_init_sec_context(
|
|||||||
_In_ gss_buffer_t input_token, _Inout_ gss_OID * actual_mech_type, _Inout_ gss_buffer_t output_token, _Out_ OM_uint32 * ret_flags,
|
_In_ gss_buffer_t input_token, _Inout_ gss_OID * actual_mech_type, _Inout_ gss_buffer_t output_token, _Out_ OM_uint32 * ret_flags,
|
||||||
_Out_ OM_uint32 * time_rec)
|
_Out_ OM_uint32 * time_rec)
|
||||||
{
|
{
|
||||||
|
OM_uint32 ret = GSS_S_FAILURE;
|
||||||
|
wchar_t * target_name_utf16 = NULL;
|
||||||
|
gss_ctx_id_t p_ctx_h = NULL;
|
||||||
|
|
||||||
|
output_token->value = NULL;
|
||||||
|
|
||||||
if (ssh_gss_sspi_init(minor_status) == 0)
|
if (ssh_gss_sspi_init(minor_status) == 0)
|
||||||
return GSS_S_FAILURE;
|
goto done;
|
||||||
|
|
||||||
/* make sure we support the passed type */
|
/* make sure we support the passed type */
|
||||||
if (mech_type->length != GSS_C_NT_HOSTBASED_SERVICE->length ||
|
if (mech_type->length != GSS_C_NT_HOSTBASED_SERVICE->length ||
|
||||||
memcmp(mech_type->elements, GSS_C_NT_HOSTBASED_SERVICE->elements, mech_type->length) != 0)
|
memcmp(mech_type->elements, GSS_C_NT_HOSTBASED_SERVICE->elements, mech_type->length) != 0) {
|
||||||
return GSS_S_BAD_NAMETYPE;
|
ret = GSS_S_BAD_NAMETYPE;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned long sspi_req_flags = ISC_REQ_ALLOCATE_MEMORY;
|
unsigned long sspi_req_flags = ISC_REQ_ALLOCATE_MEMORY;
|
||||||
if (req_flags & GSS_C_MUTUAL_FLAG) sspi_req_flags |= ISC_REQ_MUTUAL_AUTH;
|
if (req_flags & GSS_C_MUTUAL_FLAG)
|
||||||
if (req_flags & GSS_C_CONF_FLAG) sspi_req_flags |= ISC_REQ_CONFIDENTIALITY;
|
sspi_req_flags |= ISC_REQ_MUTUAL_AUTH;
|
||||||
if (req_flags & GSS_C_REPLAY_FLAG) sspi_req_flags |= ISC_REQ_REPLAY_DETECT;
|
if (req_flags & GSS_C_CONF_FLAG)
|
||||||
if (req_flags & GSS_C_DELEG_FLAG) sspi_req_flags |= ISC_REQ_DELEGATE;
|
sspi_req_flags |= ISC_REQ_CONFIDENTIALITY;
|
||||||
if (req_flags & GSS_C_INTEG_FLAG) sspi_req_flags |= ISC_REQ_INTEGRITY;
|
if (req_flags & GSS_C_REPLAY_FLAG)
|
||||||
if (req_flags & GSS_C_SEQUENCE_FLAG) sspi_req_flags |= ISC_REQ_SEQUENCE_DETECT;
|
sspi_req_flags |= ISC_REQ_REPLAY_DETECT;
|
||||||
|
if (req_flags & GSS_C_DELEG_FLAG)
|
||||||
|
sspi_req_flags |= ISC_REQ_DELEGATE;
|
||||||
|
if (req_flags & GSS_C_INTEG_FLAG)
|
||||||
|
sspi_req_flags |= ISC_REQ_INTEGRITY;
|
||||||
|
if (req_flags & GSS_C_SEQUENCE_FLAG)
|
||||||
|
sspi_req_flags |= ISC_REQ_SEQUENCE_DETECT;
|
||||||
|
|
||||||
/* determine if this is the first call (no input buffer available) */
|
/* determine if this is the first call (no input buffer available) */
|
||||||
gss_buffer_desc empty_buffer = GSS_C_EMPTY_BUFFER;
|
gss_buffer_desc empty_buffer = GSS_C_EMPTY_BUFFER;
|
||||||
@ -502,13 +541,16 @@ gss_init_sec_context(
|
|||||||
TimeStamp expiry_cred;
|
TimeStamp expiry_cred;
|
||||||
if (SecFunctions->AcquireCredentialsHandleW(NULL, MICROSOFT_KERBEROS_NAME_W, SECPKG_CRED_OUTBOUND,
|
if (SecFunctions->AcquireCredentialsHandleW(NULL, MICROSOFT_KERBEROS_NAME_W, SECPKG_CRED_OUTBOUND,
|
||||||
NULL, NULL, NULL, NULL, &cred_handle, &expiry_cred) != SEC_E_OK)
|
NULL, NULL, NULL, NULL, &cred_handle, &expiry_cred) != SEC_E_OK)
|
||||||
return GSS_S_FAILURE;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* condition the string for windows */
|
/* condition the string for windows */
|
||||||
wchar_t * target_name_utf16 = utf8_to_utf16(target_name);
|
if ((target_name_utf16 = utf8_to_utf16(target_name)) == NULL)
|
||||||
if (wcsncmp(target_name_utf16, L"host@", wcslen(L"host@")) == 0) *wcschr(target_name_utf16, L'@') = L'/';
|
goto done;
|
||||||
|
|
||||||
|
if (wcsncmp(target_name_utf16, L"host@", wcslen(L"host@")) == 0)
|
||||||
|
*wcschr(target_name_utf16, L'@') = L'/';
|
||||||
|
|
||||||
TimeStamp expiry;
|
TimeStamp expiry;
|
||||||
LONG sspi_ret_flags = 0;
|
LONG sspi_ret_flags = 0;
|
||||||
@ -518,27 +560,34 @@ gss_init_sec_context(
|
|||||||
(*context_handle == GSS_C_NO_CONTEXT) ? NULL : *context_handle,
|
(*context_handle == GSS_C_NO_CONTEXT) ? NULL : *context_handle,
|
||||||
target_name_utf16, sspi_req_flags, 0, SECURITY_NATIVE_DREP, (no_input_buffer) ? NULL : &input_buffer,
|
target_name_utf16, sspi_req_flags, 0, SECURITY_NATIVE_DREP, (no_input_buffer) ? NULL : &input_buffer,
|
||||||
0, (*context_handle != NULL) ? NULL : &out_context, &output_buffer, &sspi_ret_flags, (time_rec == NULL) ? NULL : &expiry);
|
0, (*context_handle != NULL) ? NULL : &out_context, &output_buffer, &sspi_ret_flags, (time_rec == NULL) ? NULL : &expiry);
|
||||||
free(target_name_utf16);
|
|
||||||
|
|
||||||
/* check if error occurred */
|
/* check if error occurred */
|
||||||
if (status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED)
|
if (status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED)
|
||||||
return GSS_S_FAILURE;
|
goto done;
|
||||||
|
|
||||||
/* copy output token to output buffer */
|
/* copy output token to output buffer */
|
||||||
output_token->length = output_buffer_token.cbBuffer;
|
output_token->length = output_buffer_token.cbBuffer;
|
||||||
output_token->value = malloc(output_token->length);
|
if ((output_token->value = malloc(output_token->length)) == NULL)
|
||||||
|
goto done;
|
||||||
|
|
||||||
memcpy(output_token->value, output_buffer_token.pvBuffer, output_token->length);
|
memcpy(output_token->value, output_buffer_token.pvBuffer, output_token->length);
|
||||||
SecFunctions->FreeContextBuffer(output_buffer_token.pvBuffer);
|
SecFunctions->FreeContextBuffer(output_buffer_token.pvBuffer);
|
||||||
|
|
||||||
/* if requested, translate returned flags that are actually available */
|
/* if requested, translate returned flags that are actually available */
|
||||||
if (ret_flags != NULL) {
|
if (ret_flags != NULL) {
|
||||||
*ret_flags = 0;
|
*ret_flags = 0;
|
||||||
if (sspi_ret_flags & ISC_RET_MUTUAL_AUTH) *ret_flags |= GSS_C_MUTUAL_FLAG;
|
if (sspi_ret_flags & ISC_RET_MUTUAL_AUTH)
|
||||||
if (sspi_ret_flags & ISC_RET_CONFIDENTIALITY) *ret_flags |= GSS_C_CONF_FLAG;
|
*ret_flags |= GSS_C_MUTUAL_FLAG;
|
||||||
if (sspi_ret_flags & ISC_RET_REPLAY_DETECT) *ret_flags |= GSS_C_REPLAY_FLAG;
|
if (sspi_ret_flags & ISC_RET_CONFIDENTIALITY)
|
||||||
if (sspi_ret_flags & ISC_RET_DELEGATE) *ret_flags |= GSS_C_DELEG_FLAG;
|
*ret_flags |= GSS_C_CONF_FLAG;
|
||||||
if (sspi_ret_flags & ISC_RET_INTEGRITY) *ret_flags |= GSS_C_INTEG_FLAG;
|
if (sspi_ret_flags & ISC_RET_REPLAY_DETECT)
|
||||||
if (sspi_ret_flags & ISC_RET_SEQUENCE_DETECT) *ret_flags |= GSS_C_SEQUENCE_FLAG;
|
*ret_flags |= GSS_C_REPLAY_FLAG;
|
||||||
|
if (sspi_ret_flags & ISC_RET_DELEGATE)
|
||||||
|
*ret_flags |= GSS_C_DELEG_FLAG;
|
||||||
|
if (sspi_ret_flags & ISC_RET_INTEGRITY)
|
||||||
|
*ret_flags |= GSS_C_INTEG_FLAG;
|
||||||
|
if (sspi_ret_flags & ISC_RET_SEQUENCE_DETECT)
|
||||||
|
*ret_flags |= GSS_C_SEQUENCE_FLAG;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* report if delegation was requested by not fulfilled */
|
/* report if delegation was requested by not fulfilled */
|
||||||
@ -558,11 +607,28 @@ gss_init_sec_context(
|
|||||||
|
|
||||||
/* copy the credential context structure to the caller */
|
/* copy the credential context structure to the caller */
|
||||||
if (*context_handle == GSS_C_NO_CONTEXT) {
|
if (*context_handle == GSS_C_NO_CONTEXT) {
|
||||||
*context_handle = malloc(sizeof(out_context));
|
if ((p_ctx_h = malloc(sizeof(out_context))) == NULL)
|
||||||
|
goto done;
|
||||||
|
*context_handle = p_ctx_h;
|
||||||
memcpy(*context_handle, &out_context, sizeof(out_context));
|
memcpy(*context_handle, &out_context, sizeof(out_context));
|
||||||
}
|
}
|
||||||
|
|
||||||
return (status == SEC_I_CONTINUE_NEEDED) ? GSS_S_CONTINUE_NEEDED : GSS_S_COMPLETE;
|
ret = (status == SEC_I_CONTINUE_NEEDED) ? GSS_S_CONTINUE_NEEDED : GSS_S_COMPLETE;
|
||||||
|
done:
|
||||||
|
if (target_name_utf16)
|
||||||
|
free(target_name_utf16);
|
||||||
|
|
||||||
|
if (ret != GSS_S_COMPLETE && ret != GSS_S_CONTINUE_NEEDED) {
|
||||||
|
if (output_token->value) {
|
||||||
|
free(output_token->value);
|
||||||
|
output_token->value = NULL;
|
||||||
|
}
|
||||||
|
if (p_ctx_h)
|
||||||
|
free(p_ctx_h);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -676,13 +742,19 @@ OM_uint32
|
|||||||
gss_get_mic(_Out_ OM_uint32 * minor_status, _In_ gss_ctx_id_t context_handle,
|
gss_get_mic(_Out_ OM_uint32 * minor_status, _In_ gss_ctx_id_t context_handle,
|
||||||
_In_opt_ gss_qop_t qop_req, _In_ gss_buffer_t message_buffer, _Out_ gss_buffer_t message_token)
|
_In_opt_ gss_qop_t qop_req, _In_ gss_buffer_t message_buffer, _Out_ gss_buffer_t message_token)
|
||||||
{
|
{
|
||||||
|
OM_uint32 ret = GSS_S_FAILURE;
|
||||||
|
|
||||||
|
message_token->value = NULL;
|
||||||
if (ssh_gss_sspi_init(minor_status) == 0)
|
if (ssh_gss_sspi_init(minor_status) == 0)
|
||||||
return GSS_S_FAILURE;
|
goto done;
|
||||||
|
|
||||||
/* determine the max possible signature and allocate memory to support it */
|
/* determine the max possible signature and allocate memory to support it */
|
||||||
SecPkgContext_Sizes sizes;
|
SecPkgContext_Sizes sizes;
|
||||||
SecFunctions->QueryContextAttributesW(context_handle, SECPKG_ATTR_SIZES, &sizes);
|
if (SecFunctions->QueryContextAttributesW(context_handle, SECPKG_ATTR_SIZES, &sizes) != SEC_E_OK)
|
||||||
message_token->value = malloc(sizes.cbMaxSignature);
|
goto done;
|
||||||
|
if ((message_token->value = malloc(sizes.cbMaxSignature)) == NULL)
|
||||||
|
goto done;
|
||||||
|
|
||||||
message_token->length = sizes.cbMaxSignature;
|
message_token->length = sizes.cbMaxSignature;
|
||||||
|
|
||||||
/* translate the message and token to a security buffer so we can sign it */
|
/* translate the message and token to a security buffer so we can sign it */
|
||||||
@ -696,15 +768,24 @@ gss_get_mic(_Out_ OM_uint32 * minor_status, _In_ gss_ctx_id_t context_handle,
|
|||||||
const SECURITY_STATUS status = SecFunctions->MakeSignature(context_handle, qop, &sign_buffer, 0);
|
const SECURITY_STATUS status = SecFunctions->MakeSignature(context_handle, qop, &sign_buffer, 0);
|
||||||
|
|
||||||
/* translate error codes */
|
/* translate error codes */
|
||||||
OM_uint32 return_code = GSS_S_COMPLETE;
|
|
||||||
if (status != SEC_E_OK) {
|
if (status != SEC_E_OK) {
|
||||||
if (status == SEC_E_CONTEXT_EXPIRED) return_code = GSS_S_CONTEXT_EXPIRED;
|
if (status == SEC_E_CONTEXT_EXPIRED)
|
||||||
else if (status == SEC_E_QOP_NOT_SUPPORTED) return_code = GSS_S_BAD_QOP;
|
ret = GSS_S_CONTEXT_EXPIRED;
|
||||||
else return_code = GSS_S_FAILURE;
|
else if (status == SEC_E_QOP_NOT_SUPPORTED)
|
||||||
free(message_token->value);
|
ret = GSS_S_BAD_QOP;
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
return return_code;
|
ret = GSS_S_COMPLETE;
|
||||||
|
|
||||||
|
done:
|
||||||
|
if (ret != GSS_S_COMPLETE) {
|
||||||
|
if (message_token->value) {
|
||||||
|
free(message_token->value);
|
||||||
|
message_token->value = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -726,8 +807,16 @@ gss_accept_sec_context(_Out_ OM_uint32 * minor_status, _Inout_opt_ gss_ctx_id_t
|
|||||||
_Out_opt_ gss_name_t * src_name, _Out_opt_ gss_OID * mech_type, _Outptr_ gss_buffer_t output_token,
|
_Out_opt_ gss_name_t * src_name, _Out_opt_ gss_OID * mech_type, _Outptr_ gss_buffer_t output_token,
|
||||||
_Out_ OM_uint32 * ret_flags, _Out_opt_ OM_uint32 * time_rec, _Outptr_opt_ gss_cred_id_t * delegated_cred_handle)
|
_Out_ OM_uint32 * ret_flags, _Out_opt_ OM_uint32 * time_rec, _Outptr_opt_ gss_cred_id_t * delegated_cred_handle)
|
||||||
{
|
{
|
||||||
|
OM_uint32 ret = GSS_S_FAILURE;
|
||||||
|
gss_ctx_id_t p_ctx_h = NULL;
|
||||||
|
|
||||||
|
*src_name = NULL;
|
||||||
|
|
||||||
|
if (delegated_cred_handle != NULL)
|
||||||
|
*delegated_cred_handle = NULL;
|
||||||
|
|
||||||
if (ssh_gss_sspi_init(minor_status) == 0)
|
if (ssh_gss_sspi_init(minor_status) == 0)
|
||||||
return GSS_S_FAILURE;
|
goto done;
|
||||||
|
|
||||||
/* setup input buffer */
|
/* setup input buffer */
|
||||||
SecBuffer input_buffer_token = { (unsigned long) input_token_buffer->length,
|
SecBuffer input_buffer_token = { (unsigned long) input_token_buffer->length,
|
||||||
@ -757,9 +846,11 @@ gss_accept_sec_context(_Out_ OM_uint32 * minor_status, _Inout_opt_ gss_ctx_id_t
|
|||||||
|
|
||||||
/* translate error codes */
|
/* translate error codes */
|
||||||
if (status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) {
|
if (status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED) {
|
||||||
if (status == SEC_E_INVALID_TOKEN) return GSS_S_DEFECTIVE_TOKEN;
|
if (status == SEC_E_INVALID_TOKEN)
|
||||||
else if (status == SEC_E_INVALID_HANDLE) return GSS_S_NO_CONTEXT;
|
ret = GSS_S_DEFECTIVE_TOKEN;
|
||||||
else return GSS_S_FAILURE;
|
else if (status == SEC_E_INVALID_HANDLE)
|
||||||
|
ret = GSS_S_NO_CONTEXT;
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* only do checks on the finalized context (no continue needed) */
|
/* only do checks on the finalized context (no continue needed) */
|
||||||
@ -768,32 +859,41 @@ gss_accept_sec_context(_Out_ OM_uint32 * minor_status, _Inout_opt_ gss_ctx_id_t
|
|||||||
SecPkgContext_NativeNamesW target;
|
SecPkgContext_NativeNamesW target;
|
||||||
if (SecFunctions->QueryContextAttributesW((*context_handle == GSS_C_NO_CONTEXT) ? &sspi_context_handle : *context_handle,
|
if (SecFunctions->QueryContextAttributesW((*context_handle == GSS_C_NO_CONTEXT) ? &sspi_context_handle : *context_handle,
|
||||||
SECPKG_ATTR_NATIVE_NAMES, &target) != SEC_E_OK)
|
SECPKG_ATTR_NATIVE_NAMES, &target) != SEC_E_OK)
|
||||||
return GSS_S_FAILURE;
|
goto done;
|
||||||
|
|
||||||
const int valid_spn = _wcsnicmp(target.sServerName, L"host/", wcslen(L"host/")) == 0;
|
const int valid_spn = _wcsnicmp(target.sServerName, L"host/", wcslen(L"host/")) == 0;
|
||||||
FreeContextBuffer(target.sServerName);
|
FreeContextBuffer(target.sServerName);
|
||||||
FreeContextBuffer(target.sClientName);
|
FreeContextBuffer(target.sClientName);
|
||||||
if (valid_spn == 0) {
|
if (valid_spn == 0) {
|
||||||
debug("client passed an invalid principal name");
|
debug("client passed an invalid principal name");
|
||||||
return GSS_S_FAILURE;
|
ret = GSS_S_FAILURE;
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copy the context handler to the caller */
|
/* copy the context handler to the caller */
|
||||||
if (*context_handle == GSS_C_NO_CONTEXT) {
|
if (*context_handle == GSS_C_NO_CONTEXT) {
|
||||||
*context_handle = malloc(sizeof(CtxtHandle));
|
if ((p_ctx_h = malloc(sizeof(CtxtHandle))) == NULL)
|
||||||
|
goto done;
|
||||||
|
*context_handle = p_ctx_h;
|
||||||
memcpy(*context_handle, &sspi_context_handle, sizeof(CtxtHandle));
|
memcpy(*context_handle, &sspi_context_handle, sizeof(CtxtHandle));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if requested, translate returned flags that are actually available */
|
/* if requested, translate returned flags that are actually available */
|
||||||
if (ret_flags != NULL) {
|
if (ret_flags != NULL) {
|
||||||
*ret_flags = 0;
|
*ret_flags = 0;
|
||||||
if (sspi_ret_flags & ASC_RET_MUTUAL_AUTH) *ret_flags |= GSS_C_MUTUAL_FLAG;
|
if (sspi_ret_flags & ASC_RET_MUTUAL_AUTH)
|
||||||
if (sspi_ret_flags & ASC_RET_CONFIDENTIALITY) *ret_flags |= GSS_C_CONF_FLAG;
|
*ret_flags |= GSS_C_MUTUAL_FLAG;
|
||||||
if (sspi_ret_flags & ASC_RET_REPLAY_DETECT) *ret_flags |= GSS_C_REPLAY_FLAG;
|
if (sspi_ret_flags & ASC_RET_CONFIDENTIALITY)
|
||||||
if (sspi_ret_flags & ASC_RET_DELEGATE) *ret_flags |= GSS_C_DELEG_FLAG;
|
*ret_flags |= GSS_C_CONF_FLAG;
|
||||||
if (sspi_ret_flags & ASC_RET_INTEGRITY) *ret_flags |= GSS_C_INTEG_FLAG;
|
if (sspi_ret_flags & ASC_RET_REPLAY_DETECT)
|
||||||
if (sspi_ret_flags & ASC_RET_SEQUENCE_DETECT) *ret_flags |= GSS_C_SEQUENCE_FLAG;
|
*ret_flags |= GSS_C_REPLAY_FLAG;
|
||||||
|
if (sspi_ret_flags & ASC_RET_DELEGATE)
|
||||||
|
*ret_flags |= GSS_C_DELEG_FLAG;
|
||||||
|
if (sspi_ret_flags & ASC_RET_INTEGRITY)
|
||||||
|
*ret_flags |= GSS_C_INTEG_FLAG;
|
||||||
|
if (sspi_ret_flags & ASC_RET_SEQUENCE_DETECT)
|
||||||
|
*ret_flags |= GSS_C_SEQUENCE_FLAG;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* report if delegation was requested by not fulfilled */
|
/* report if delegation was requested by not fulfilled */
|
||||||
@ -816,10 +916,12 @@ gss_accept_sec_context(_Out_ OM_uint32 * minor_status, _Inout_opt_ gss_ctx_id_t
|
|||||||
/* extract the username from the context handle will be domain\samaccountname format */
|
/* extract the username from the context handle will be domain\samaccountname format */
|
||||||
SecPkgContext_NamesW NamesBuffer;
|
SecPkgContext_NamesW NamesBuffer;
|
||||||
if (SecFunctions->QueryContextAttributesW(*context_handle, SECPKG_ATTR_NAMES, &NamesBuffer) != SEC_E_OK)
|
if (SecFunctions->QueryContextAttributesW(*context_handle, SECPKG_ATTR_NAMES, &NamesBuffer) != SEC_E_OK)
|
||||||
return GSS_S_FAILURE;
|
goto done;
|
||||||
|
|
||||||
/* copy to internal utf8 string and free the sspi string */
|
/* copy to internal utf8 string and free the sspi string */
|
||||||
*src_name = utf16_to_utf8(NamesBuffer.sUserName);
|
if ((*src_name = utf16_to_utf8(NamesBuffer.sUserName)) == NULL)
|
||||||
|
goto done;
|
||||||
|
|
||||||
FreeContextBuffer(NamesBuffer.sUserName);
|
FreeContextBuffer(NamesBuffer.sUserName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -832,13 +934,25 @@ gss_accept_sec_context(_Out_ OM_uint32 * minor_status, _Inout_opt_ gss_ctx_id_t
|
|||||||
/* get the user token for impersonation */
|
/* get the user token for impersonation */
|
||||||
if (delegated_cred_handle != NULL) {
|
if (delegated_cred_handle != NULL) {
|
||||||
if ((*delegated_cred_handle = malloc(sizeof(struct cred_st))) == NULL)
|
if ((*delegated_cred_handle = malloc(sizeof(struct cred_st))) == NULL)
|
||||||
return GSS_S_FAILURE;
|
goto done;
|
||||||
SecFunctions->QuerySecurityContextToken(*context_handle, &sspi_auth_user);
|
if (SecFunctions->QuerySecurityContextToken(*context_handle, &sspi_auth_user) != SEC_E_OK)
|
||||||
|
goto done;
|
||||||
(*delegated_cred_handle)->isToken = 1;
|
(*delegated_cred_handle)->isToken = 1;
|
||||||
(*delegated_cred_handle)->token = sspi_auth_user;
|
(*delegated_cred_handle)->token = sspi_auth_user;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (status == SEC_I_CONTINUE_NEEDED) ? GSS_S_CONTINUE_NEEDED : GSS_S_COMPLETE;
|
ret = (status == SEC_I_CONTINUE_NEEDED) ? GSS_S_CONTINUE_NEEDED : GSS_S_COMPLETE;
|
||||||
|
|
||||||
|
done:
|
||||||
|
if (ret != GSS_S_COMPLETE && ret != GSS_S_CONTINUE_NEEDED) {
|
||||||
|
if (p_ctx_h)
|
||||||
|
free(p_ctx_h);
|
||||||
|
if (*src_name)
|
||||||
|
free(*src_name);
|
||||||
|
if (delegated_cred_handle && *delegated_cred_handle)
|
||||||
|
free(*delegated_cred_handle);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -850,10 +964,12 @@ OM_uint32
|
|||||||
gss_display_name(_Out_ OM_uint32 * minor_status, _In_ gss_name_t input_name,
|
gss_display_name(_Out_ OM_uint32 * minor_status, _In_ gss_name_t input_name,
|
||||||
_Out_ gss_buffer_t output_name_buffer, _Out_ gss_OID * output_name_type)
|
_Out_ gss_buffer_t output_name_buffer, _Out_ gss_OID * output_name_type)
|
||||||
{
|
{
|
||||||
if (ssh_gss_sspi_init(minor_status) == 0) return GSS_S_FAILURE;
|
if (ssh_gss_sspi_init(minor_status) == 0)
|
||||||
|
return GSS_S_FAILURE;
|
||||||
|
|
||||||
output_name_buffer->length = strlen(input_name) + 1;
|
output_name_buffer->length = strlen(input_name) + 1;
|
||||||
output_name_buffer->value = _strdup(input_name);
|
if ((output_name_buffer->value = _strdup(input_name)) == NULL)
|
||||||
|
return GSS_S_FAILURE;
|
||||||
|
|
||||||
/* set the output oid type if requested */
|
/* set the output oid type if requested */
|
||||||
if (output_name_type != NULL)
|
if (output_name_type != NULL)
|
||||||
@ -882,33 +998,57 @@ gss_display_status(_In_ OM_uint32 * minor_status, _In_ OM_uint32 status_value, _
|
|||||||
|
|
||||||
/* lookup textual representation of the numeric status code */
|
/* lookup textual representation of the numeric status code */
|
||||||
char * message_string = NULL;
|
char * message_string = NULL;
|
||||||
if (status_value == GSS_S_COMPLETE) message_string = "GSS_S_COMPLETE";
|
if (status_value == GSS_S_COMPLETE)
|
||||||
else if (status_value == GSS_S_BAD_BINDINGS) message_string = "GSS_S_BAD_BINDINGS";
|
message_string = "GSS_S_COMPLETE";
|
||||||
else if (status_value == GSS_S_BAD_MECH) message_string = "GSS_S_BAD_MECH";
|
else if (status_value == GSS_S_BAD_BINDINGS)
|
||||||
else if (status_value == GSS_S_BAD_NAME) message_string = "GSS_S_BAD_NAME";
|
message_string = "GSS_S_BAD_BINDINGS";
|
||||||
else if (status_value == GSS_S_BAD_NAMETYPE) message_string = "GSS_S_BAD_NAMETYPE";
|
else if (status_value == GSS_S_BAD_MECH)
|
||||||
else if (status_value == GSS_S_BAD_QOP) message_string = "GSS_S_BAD_QOP";
|
message_string = "GSS_S_BAD_MECH";
|
||||||
else if (status_value == GSS_S_BAD_SIG) message_string = "GSS_S_BAD_SIG";
|
else if (status_value == GSS_S_BAD_NAME)
|
||||||
else if (status_value == GSS_S_BAD_STATUS) message_string = "GSS_S_BAD_STATUS";
|
message_string = "GSS_S_BAD_NAME";
|
||||||
else if (status_value == GSS_S_CONTEXT_EXPIRED) message_string = "GSS_S_CONTEXT_EXPIRED";
|
else if (status_value == GSS_S_BAD_NAMETYPE)
|
||||||
else if (status_value == GSS_S_CONTINUE_NEEDED) message_string = "GSS_S_CONTINUE_NEEDED";
|
message_string = "GSS_S_BAD_NAMETYPE";
|
||||||
else if (status_value == GSS_S_CREDENTIALS_EXPIRED) message_string = "GSS_S_CREDENTIALS_EXPIRED";
|
else if (status_value == GSS_S_BAD_QOP)
|
||||||
else if (status_value == GSS_S_DEFECTIVE_CREDENTIAL) message_string = "GSS_S_DEFECTIVE_CREDENTIAL";
|
message_string = "GSS_S_BAD_QOP";
|
||||||
else if (status_value == GSS_S_DEFECTIVE_TOKEN) message_string = "GSS_S_DEFECTIVE_TOKEN";
|
else if (status_value == GSS_S_BAD_SIG)
|
||||||
else if (status_value == GSS_S_DUPLICATE_ELEMENT) message_string = "GSS_S_DUPLICATE_ELEMENT";
|
message_string = "GSS_S_BAD_SIG";
|
||||||
else if (status_value == GSS_S_DUPLICATE_TOKEN) message_string = "GSS_S_DUPLICATE_TOKEN";
|
else if (status_value == GSS_S_BAD_STATUS)
|
||||||
else if (status_value == GSS_S_FAILURE) message_string = "GSS_S_FAILURE";
|
message_string = "GSS_S_BAD_STATUS";
|
||||||
else if (status_value == GSS_S_NAME_NOT_MN) message_string = "GSS_S_NAME_NOT_MN";
|
else if (status_value == GSS_S_CONTEXT_EXPIRED)
|
||||||
else if (status_value == GSS_S_NO_CONTEXT) message_string = "GSS_S_NO_CONTEXT";
|
message_string = "GSS_S_CONTEXT_EXPIRED";
|
||||||
else if (status_value == GSS_S_NO_CRED) message_string = "GSS_S_NO_CRED";
|
else if (status_value == GSS_S_CONTINUE_NEEDED)
|
||||||
else if (status_value == GSS_S_OLD_TOKEN) message_string = "GSS_S_OLD_TOKEN";
|
message_string = "GSS_S_CONTINUE_NEEDED";
|
||||||
else if (status_value == GSS_S_UNAUTHORIZED) message_string = "GSS_S_UNAUTHORIZED";
|
else if (status_value == GSS_S_CREDENTIALS_EXPIRED)
|
||||||
else if (status_value == GSS_S_UNAVAILABLE) message_string = "GSS_S_UNAVAILABLE";
|
message_string = "GSS_S_CREDENTIALS_EXPIRED";
|
||||||
else if (status_value == GSS_S_UNSEQ_TOKEN) message_string = "GSS_S_UNSEQ_TOKEN";
|
else if (status_value == GSS_S_DEFECTIVE_CREDENTIAL)
|
||||||
|
message_string = "GSS_S_DEFECTIVE_CREDENTIAL";
|
||||||
|
else if (status_value == GSS_S_DEFECTIVE_TOKEN)
|
||||||
|
message_string = "GSS_S_DEFECTIVE_TOKEN";
|
||||||
|
else if (status_value == GSS_S_DUPLICATE_ELEMENT)
|
||||||
|
message_string = "GSS_S_DUPLICATE_ELEMENT";
|
||||||
|
else if (status_value == GSS_S_DUPLICATE_TOKEN)
|
||||||
|
message_string = "GSS_S_DUPLICATE_TOKEN";
|
||||||
|
else if (status_value == GSS_S_FAILURE)
|
||||||
|
message_string = "GSS_S_FAILURE";
|
||||||
|
else if (status_value == GSS_S_NAME_NOT_MN)
|
||||||
|
message_string = "GSS_S_NAME_NOT_MN";
|
||||||
|
else if (status_value == GSS_S_NO_CONTEXT)
|
||||||
|
message_string = "GSS_S_NO_CONTEXT";
|
||||||
|
else if (status_value == GSS_S_NO_CRED)
|
||||||
|
message_string = "GSS_S_NO_CRED";
|
||||||
|
else if (status_value == GSS_S_OLD_TOKEN)
|
||||||
|
message_string = "GSS_S_OLD_TOKEN";
|
||||||
|
else if (status_value == GSS_S_UNAUTHORIZED)
|
||||||
|
message_string = "GSS_S_UNAUTHORIZED";
|
||||||
|
else if (status_value == GSS_S_UNAVAILABLE)
|
||||||
|
message_string = "GSS_S_UNAVAILABLE";
|
||||||
|
else if (status_value == GSS_S_UNSEQ_TOKEN)
|
||||||
|
message_string = "GSS_S_UNSEQ_TOKEN";
|
||||||
|
|
||||||
/* copy local status string to the output buffer */
|
/* copy local status string to the output buffer */
|
||||||
status_string->length = strlen(message_string) + 1;
|
status_string->length = strlen(message_string) + 1;
|
||||||
status_string->value = _strdup(message_string);
|
if ((status_string->value = _strdup(message_string)) == NULL)
|
||||||
|
return GSS_S_FAILURE;
|
||||||
|
|
||||||
/* no supplementary messages available */
|
/* no supplementary messages available */
|
||||||
*message_context = 0;
|
*message_context = 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user