mirror of
https://github.com/samba-team/samba.git
synced 2024-12-22 13:34:15 +03:00
auth/kerberos: Move gse_get_session_key() to common code and use in gensec_gssapi
Thie ensures that both code bases use the same logic to determine the use of NEW_SPNEGO. Andrew Bartlett
This commit is contained in:
parent
a315350341
commit
674278d5b0
@ -22,6 +22,7 @@
|
||||
#ifdef HAVE_KRB5
|
||||
|
||||
#include "libcli/auth/krb5_wrap.h"
|
||||
#include "lib/util/asn1.h"
|
||||
|
||||
#if 0
|
||||
/* FIXME - need proper configure/waf test
|
||||
@ -47,6 +48,26 @@ const gss_OID_desc * const gss_mech_krb5_old = krb5_gss_oid_array+1;
|
||||
const gss_OID_desc * const gss_mech_krb5_wrong = krb5_gss_oid_array+2;
|
||||
#endif
|
||||
|
||||
#ifndef GSS_KRB5_INQ_SSPI_SESSION_KEY_OID
|
||||
#define GSS_KRB5_INQ_SSPI_SESSION_KEY_OID_LENGTH 11
|
||||
#define GSS_KRB5_INQ_SSPI_SESSION_KEY_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x05"
|
||||
#endif
|
||||
|
||||
gss_OID_desc gse_sesskey_inq_oid = {
|
||||
GSS_KRB5_INQ_SSPI_SESSION_KEY_OID_LENGTH,
|
||||
(void *)GSS_KRB5_INQ_SSPI_SESSION_KEY_OID
|
||||
};
|
||||
|
||||
#ifndef GSS_KRB5_SESSION_KEY_ENCTYPE_OID
|
||||
#define GSS_KRB5_SESSION_KEY_ENCTYPE_OID_LENGTH 10
|
||||
#define GSS_KRB5_SESSION_KEY_ENCTYPE_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x04"
|
||||
#endif
|
||||
|
||||
gss_OID_desc gse_sesskeytype_oid = {
|
||||
GSS_KRB5_SESSION_KEY_ENCTYPE_OID_LENGTH,
|
||||
(void *)GSS_KRB5_SESSION_KEY_ENCTYPE_OID
|
||||
};
|
||||
|
||||
/* The Heimdal OID for getting the PAC */
|
||||
#define EXTRACT_PAC_AUTHZ_DATA_FROM_SEC_CONTEXT_OID_LENGTH 8
|
||||
/* EXTRACTION OID AUTHZ ID */
|
||||
@ -149,4 +170,96 @@ NTSTATUS gssapi_obtain_pac_blob(TALLOC_CTX *mem_ctx,
|
||||
#endif
|
||||
return NT_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
NTSTATUS gssapi_get_session_key(TALLOC_CTX *mem_ctx,
|
||||
gss_ctx_id_t gssapi_context,
|
||||
DATA_BLOB *session_key,
|
||||
uint32_t *keytype)
|
||||
{
|
||||
OM_uint32 gss_min, gss_maj;
|
||||
gss_buffer_set_t set = GSS_C_NO_BUFFER_SET;
|
||||
|
||||
gss_maj = gss_inquire_sec_context_by_oid(
|
||||
&gss_min, gssapi_context,
|
||||
&gse_sesskey_inq_oid, &set);
|
||||
if (gss_maj) {
|
||||
DEBUG(0, ("gss_inquire_sec_context_by_oid failed [%s]\n",
|
||||
gssapi_error_string(mem_ctx, gss_maj, gss_min, gss_mech_krb5)));
|
||||
return NT_STATUS_NO_USER_SESSION_KEY;
|
||||
}
|
||||
|
||||
if ((set == GSS_C_NO_BUFFER_SET) ||
|
||||
(set->count == 0)) {
|
||||
#ifdef HAVE_GSSKRB5_GET_SUBKEY
|
||||
krb5_keyblock *subkey;
|
||||
gss_maj = gsskrb5_get_subkey(&gss_min,
|
||||
gssapi_context,
|
||||
&subkey);
|
||||
if (gss_maj != 0) {
|
||||
DEBUG(1, ("NO session key for this mech\n"));
|
||||
return NT_STATUS_NO_USER_SESSION_KEY;
|
||||
}
|
||||
if (session_key) {
|
||||
*session_key = data_blob_talloc(mem_ctx,
|
||||
KRB5_KEY_DATA(subkey), KRB5_KEY_LENGTH(subkey));
|
||||
}
|
||||
if (keytype) {
|
||||
*keytype = KRB5_KEY_TYPE(subkey);
|
||||
}
|
||||
krb5_free_keyblock(NULL /* should be krb5_context */, subkey);
|
||||
return NT_STATUS_OK;
|
||||
#else
|
||||
DEBUG(0, ("gss_inquire_sec_context_by_oid returned unknown "
|
||||
"OID for data in results:\n"));
|
||||
dump_data(1, (uint8_t *)set->elements[1].value,
|
||||
set->elements[1].length);
|
||||
return NT_STATUS_NO_USER_SESSION_KEY;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (session_key) {
|
||||
*session_key = data_blob_talloc(mem_ctx, set->elements[0].value,
|
||||
set->elements[0].length);
|
||||
}
|
||||
|
||||
if (keytype) {
|
||||
char *oid;
|
||||
char *p, *q = NULL;
|
||||
|
||||
if (set->count < 2
|
||||
|| memcmp(set->elements[1].value,
|
||||
gse_sesskeytype_oid.elements,
|
||||
gse_sesskeytype_oid.length) != 0) {
|
||||
/* Perhaps a non-krb5 session key */
|
||||
*keytype = 0;
|
||||
gss_maj = gss_release_buffer_set(&gss_min, &set);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
if (!ber_read_OID_String(mem_ctx,
|
||||
data_blob_const(set->elements[1].value,
|
||||
set->elements[1].length), &oid)) {
|
||||
TALLOC_FREE(oid);
|
||||
gss_maj = gss_release_buffer_set(&gss_min, &set);
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
p = strrchr(oid, '.');
|
||||
if (!p) {
|
||||
TALLOC_FREE(oid);
|
||||
gss_maj = gss_release_buffer_set(&gss_min, &set);
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
} else {
|
||||
p++;
|
||||
*keytype = strtoul(p, &q, 10);
|
||||
if (q == NULL || *q != '\0') {
|
||||
TALLOC_FREE(oid);
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
TALLOC_FREE(oid);
|
||||
}
|
||||
|
||||
gss_maj = gss_release_buffer_set(&gss_min, &set);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -24,6 +24,18 @@
|
||||
struct PAC_SIGNATURE_DATA;
|
||||
struct PAC_DATA;
|
||||
|
||||
#ifdef HAVE_KRB5_KEYBLOCK_KEYVALUE /* Heimdal */
|
||||
#define KRB5_KEY_TYPE(k) ((k)->keytype)
|
||||
#define KRB5_KEY_LENGTH(k) ((k)->keyvalue.length)
|
||||
#define KRB5_KEY_DATA(k) ((k)->keyvalue.data)
|
||||
#define KRB5_KEY_DATA_CAST void
|
||||
#else /* MIT */
|
||||
#define KRB5_KEY_TYPE(k) ((k)->enctype)
|
||||
#define KRB5_KEY_LENGTH(k) ((k)->length)
|
||||
#define KRB5_KEY_DATA(k) ((k)->contents)
|
||||
#define KRB5_KEY_DATA_CAST krb5_octet
|
||||
#endif /* HAVE_KRB5_KEYBLOCK_KEYVALUE */
|
||||
|
||||
int create_kerberos_key_from_string_direct(krb5_context context,
|
||||
krb5_principal host_princ,
|
||||
krb5_data *password,
|
||||
@ -76,6 +88,11 @@ NTSTATUS gssapi_obtain_pac_blob(TALLOC_CTX *mem_ctx,
|
||||
gss_ctx_id_t gssapi_context,
|
||||
gss_name_t gss_client_name,
|
||||
DATA_BLOB *pac_data);
|
||||
NTSTATUS gssapi_get_session_key(TALLOC_CTX *mem_ctx,
|
||||
gss_ctx_id_t gssapi_context,
|
||||
DATA_BLOB *session_key,
|
||||
uint32_t *keytype);
|
||||
|
||||
DATA_BLOB gensec_gssapi_gen_krb5_wrap(TALLOC_CTX *mem_ctx, const DATA_BLOB *ticket, const uint8_t tok_id[2]);
|
||||
|
||||
bool gensec_gssapi_parse_krb5_wrap(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob, DATA_BLOB *ticket, uint8_t tok_id[2]);
|
||||
|
@ -66,18 +66,6 @@ typedef struct {
|
||||
#endif /* defined(HAVE_MAGIC_IN_KRB5_ADDRESS) && defined(HAVE_ADDRTYPE_IN_KRB5_ADDRESS) */
|
||||
} smb_krb5_addresses;
|
||||
|
||||
#ifdef HAVE_KRB5_KEYBLOCK_KEYVALUE /* Heimdal */
|
||||
#define KRB5_KEY_TYPE(k) ((k)->keytype)
|
||||
#define KRB5_KEY_LENGTH(k) ((k)->keyvalue.length)
|
||||
#define KRB5_KEY_DATA(k) ((k)->keyvalue.data)
|
||||
#define KRB5_KEY_DATA_CAST void
|
||||
#else /* MIT */
|
||||
#define KRB5_KEY_TYPE(k) ((k)->enctype)
|
||||
#define KRB5_KEY_LENGTH(k) ((k)->length)
|
||||
#define KRB5_KEY_DATA(k) ((k)->contents)
|
||||
#define KRB5_KEY_DATA_CAST krb5_octet
|
||||
#endif /* HAVE_KRB5_KEYBLOCK_KEYVALUE */
|
||||
|
||||
#ifdef HAVE_KRB5_KEYTAB_ENTRY_KEY /* MIT */
|
||||
#define KRB5_KT_KEY(k) (&(k)->key)
|
||||
#elif HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK /* Heimdal */
|
||||
|
@ -35,26 +35,6 @@
|
||||
#include "smb_krb5.h"
|
||||
#include "gse_krb5.h"
|
||||
|
||||
#ifndef GSS_KRB5_INQ_SSPI_SESSION_KEY_OID
|
||||
#define GSS_KRB5_INQ_SSPI_SESSION_KEY_OID_LENGTH 11
|
||||
#define GSS_KRB5_INQ_SSPI_SESSION_KEY_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x05"
|
||||
#endif
|
||||
|
||||
gss_OID_desc gse_sesskey_inq_oid = {
|
||||
GSS_KRB5_INQ_SSPI_SESSION_KEY_OID_LENGTH,
|
||||
(void *)GSS_KRB5_INQ_SSPI_SESSION_KEY_OID
|
||||
};
|
||||
|
||||
#ifndef GSS_KRB5_SESSION_KEY_ENCTYPE_OID
|
||||
#define GSS_KRB5_SESSION_KEY_ENCTYPE_OID_LENGTH 10
|
||||
#define GSS_KRB5_SESSION_KEY_ENCTYPE_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x04"
|
||||
#endif
|
||||
|
||||
gss_OID_desc gse_sesskeytype_oid = {
|
||||
GSS_KRB5_SESSION_KEY_ENCTYPE_OID_LENGTH,
|
||||
(void *)GSS_KRB5_SESSION_KEY_ENCTYPE_OID
|
||||
};
|
||||
|
||||
static char *gse_errstr(TALLOC_CTX *mem_ctx, OM_uint32 maj, OM_uint32 min);
|
||||
|
||||
struct gse_context {
|
||||
@ -563,96 +543,6 @@ done:
|
||||
return errstr;
|
||||
}
|
||||
|
||||
static NTSTATUS gse_get_session_key(TALLOC_CTX *mem_ctx,
|
||||
struct gse_context *gse_ctx,
|
||||
DATA_BLOB *session_key,
|
||||
uint32_t *keytype)
|
||||
{
|
||||
OM_uint32 gss_min, gss_maj;
|
||||
gss_buffer_set_t set = GSS_C_NO_BUFFER_SET;
|
||||
|
||||
gss_maj = gss_inquire_sec_context_by_oid(
|
||||
&gss_min, gse_ctx->gssapi_context,
|
||||
&gse_sesskey_inq_oid, &set);
|
||||
if (gss_maj) {
|
||||
DEBUG(0, ("gss_inquire_sec_context_by_oid failed [%s]\n",
|
||||
gse_errstr(talloc_tos(), gss_maj, gss_min)));
|
||||
return NT_STATUS_NO_USER_SESSION_KEY;
|
||||
}
|
||||
|
||||
if ((set == GSS_C_NO_BUFFER_SET) ||
|
||||
(set->count == 0)) {
|
||||
#ifdef HAVE_GSSKRB5_GET_SUBKEY
|
||||
krb5_keyblock *subkey;
|
||||
gss_maj = gsskrb5_get_subkey(&gss_min,
|
||||
gse_ctx->gssapi_context,
|
||||
&subkey);
|
||||
if (gss_maj != 0) {
|
||||
DEBUG(1, ("NO session key for this mech\n"));
|
||||
return NT_STATUS_NO_USER_SESSION_KEY;
|
||||
}
|
||||
if (session_key) {
|
||||
*session_key = data_blob_talloc(mem_ctx,
|
||||
KRB5_KEY_DATA(subkey), KRB5_KEY_LENGTH(subkey));
|
||||
}
|
||||
if (keytype) {
|
||||
*keytype = KRB5_KEY_TYPE(subkey);
|
||||
}
|
||||
krb5_free_keyblock(NULL /* should be krb5_context */, subkey);
|
||||
return NT_STATUS_OK;
|
||||
#else
|
||||
DEBUG(0, ("gss_inquire_sec_context_by_oid returned unknown "
|
||||
"OID for data in results:\n"));
|
||||
dump_data(1, (uint8_t *)set->elements[1].value,
|
||||
set->elements[1].length);
|
||||
return NT_STATUS_NO_USER_SESSION_KEY;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (session_key) {
|
||||
*session_key = data_blob_talloc(mem_ctx, set->elements[0].value,
|
||||
set->elements[0].length);
|
||||
}
|
||||
|
||||
if (keytype) {
|
||||
char *oid;
|
||||
char *p, *q = NULL;
|
||||
|
||||
if (set->count < 2
|
||||
|| memcmp(set->elements[1].value,
|
||||
gse_sesskeytype_oid.elements,
|
||||
gse_sesskeytype_oid.length) != 0) {
|
||||
/* Perhaps a non-krb5 session key */
|
||||
*keytype = 0;
|
||||
gss_maj = gss_release_buffer_set(&gss_min, &set);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
if (!ber_read_OID_String(talloc_tos(),
|
||||
data_blob_const(set->elements[1].value,
|
||||
set->elements[1].length), &oid)) {
|
||||
TALLOC_FREE(oid);
|
||||
gss_maj = gss_release_buffer_set(&gss_min, &set);
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
p = strrchr(oid, '.');
|
||||
if (!p) {
|
||||
TALLOC_FREE(oid);
|
||||
gss_maj = gss_release_buffer_set(&gss_min, &set);
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
} else {
|
||||
p++;
|
||||
*keytype = strtoul(p, &q, 10);
|
||||
if (q == NULL || *q != '\0') {
|
||||
return NT_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
TALLOC_FREE(oid);
|
||||
}
|
||||
|
||||
gss_maj = gss_release_buffer_set(&gss_min, &set);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static size_t gse_get_signature_length(struct gse_context *gse_ctx,
|
||||
bool seal, size_t payload_size)
|
||||
{
|
||||
@ -1125,8 +1015,8 @@ static bool gensec_gse_have_feature(struct gensec_security *gensec_security,
|
||||
return false;
|
||||
}
|
||||
|
||||
status = gse_get_session_key(talloc_tos(),
|
||||
gse_ctx, NULL, &keytype);
|
||||
status = gssapi_get_session_key(talloc_tos(),
|
||||
gse_ctx->gssapi_context, NULL, &keytype);
|
||||
/*
|
||||
* We should do a proper sig on the mechListMic unless
|
||||
* we know we have to be backwards compatible with
|
||||
@ -1168,7 +1058,7 @@ static NTSTATUS gensec_gse_session_key(struct gensec_security *gensec_security,
|
||||
talloc_get_type_abort(gensec_security->private_data,
|
||||
struct gse_context);
|
||||
|
||||
return gse_get_session_key(mem_ctx, gse_ctx, session_key, NULL);
|
||||
return gssapi_get_session_key(mem_ctx, gse_ctx->gssapi_context, session_key, NULL);
|
||||
}
|
||||
|
||||
/* Get some basic (and authorization) information about the user on
|
||||
|
@ -1229,6 +1229,7 @@ static bool gensec_gssapi_have_feature(struct gensec_security *gensec_security,
|
||||
}
|
||||
if (feature & GENSEC_FEATURE_NEW_SPNEGO) {
|
||||
NTSTATUS status;
|
||||
uint32_t keytype;
|
||||
|
||||
if (!(gensec_gssapi_state->gss_got_flags & GSS_C_INTEG_FLAG)) {
|
||||
return false;
|
||||
@ -1241,16 +1242,27 @@ static bool gensec_gssapi_have_feature(struct gensec_security *gensec_security,
|
||||
return false;
|
||||
}
|
||||
|
||||
status = gensec_gssapi_init_lucid(gensec_gssapi_state);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
return false;
|
||||
status = gssapi_get_session_key(gensec_gssapi_state,
|
||||
gensec_gssapi_state->gssapi_context, NULL, &keytype);
|
||||
/*
|
||||
* We should do a proper sig on the mechListMic unless
|
||||
* we know we have to be backwards compatible with
|
||||
* earlier windows versions.
|
||||
*
|
||||
* Negotiating a non-krb5
|
||||
* mech for example should be regarded as having
|
||||
* NEW_SPNEGO
|
||||
*/
|
||||
if (NT_STATUS_IS_OK(status)) {
|
||||
switch (keytype) {
|
||||
case ENCTYPE_DES_CBC_CRC:
|
||||
case ENCTYPE_DES_CBC_MD5:
|
||||
case ENCTYPE_ARCFOUR_HMAC:
|
||||
case ENCTYPE_DES3_CBC_SHA1:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (gensec_gssapi_state->lucid->protocol == 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
/* We can always do async (rather than strict request/reply) packets. */
|
||||
if (feature & GENSEC_FEATURE_ASYNC_REPLIES) {
|
||||
@ -1271,30 +1283,7 @@ static NTSTATUS gensec_gssapi_session_key(struct gensec_security *gensec_securit
|
||||
{
|
||||
struct gensec_gssapi_state *gensec_gssapi_state
|
||||
= talloc_get_type(gensec_security->private_data, struct gensec_gssapi_state);
|
||||
OM_uint32 maj_stat, min_stat;
|
||||
krb5_keyblock *subkey;
|
||||
|
||||
if (gensec_gssapi_state->sasl_state != STAGE_DONE) {
|
||||
return NT_STATUS_NO_USER_SESSION_KEY;
|
||||
}
|
||||
|
||||
maj_stat = gsskrb5_get_subkey(&min_stat,
|
||||
gensec_gssapi_state->gssapi_context,
|
||||
&subkey);
|
||||
if (maj_stat != 0) {
|
||||
DEBUG(1, ("NO session key for this mech\n"));
|
||||
return NT_STATUS_NO_USER_SESSION_KEY;
|
||||
}
|
||||
|
||||
DEBUG(10, ("Got KRB5 session key of length %d%s\n",
|
||||
(int)KRB5_KEY_LENGTH(subkey),
|
||||
(gensec_gssapi_state->sasl_state == STAGE_DONE)?" (done)":""));
|
||||
*session_key = data_blob_talloc(mem_ctx,
|
||||
KRB5_KEY_DATA(subkey), KRB5_KEY_LENGTH(subkey));
|
||||
krb5_free_keyblock(gensec_gssapi_state->smb_krb5_context->krb5_context, subkey);
|
||||
dump_data_pw("KRB5 Session Key:\n", session_key->data, session_key->length);
|
||||
|
||||
return NT_STATUS_OK;
|
||||
return gssapi_get_session_key(mem_ctx, gensec_gssapi_state->gssapi_context, session_key, NULL);
|
||||
}
|
||||
|
||||
/* Get some basic (and authorization) information about the user on
|
||||
|
Loading…
Reference in New Issue
Block a user