From: Isaac Boukris Date: Mon, 12 Aug 2019 11:13:07 +0000 (+0000) Subject: Add GSS_KRB5_NT_X509_CERT name type X-Git-Tag: krb5-1.19-beta1~57 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F1081%2Fhead;p=thirdparty%2Fkrb5.git Add GSS_KRB5_NT_X509_CERT name type If this name type is used for the desired_name parameter of gss_acquire_cred_impersonate_name(), identify the S4U2Self user by certificate. Co-authored with Purand Chand . [ghudson@mit.edu: added documentation; updated to use a boolean at the GSS layer rather than a new krb5 name type; rewrote commit message] ticket: 8923 (new) --- diff --git a/doc/appdev/gssapi.rst b/doc/appdev/gssapi.rst index 66561fd0e1..452ead2a91 100644 --- a/doc/appdev/gssapi.rst +++ b/doc/appdev/gssapi.rst @@ -61,6 +61,12 @@ name types are supported by the krb5 mechanism: is defined in the ```` header. (New in release 1.17.) +* **GSS_KRB5_NT_X509_CERT**: The value should be an X.509 certificate + encoded according to :rfc:`5280`. This name form can be used for + the desired_name parameter of gss_acquire_cred_impersonate_name(), + to identify the S4U2Self user by certificate. (New in release + 1.19.) + Initiator credentials --------------------- diff --git a/src/lib/gssapi/krb5/gssapiP_krb5.h b/src/lib/gssapi/krb5/gssapiP_krb5.h index 2e2c775d63..53d077a0f5 100644 --- a/src/lib/gssapi/krb5/gssapiP_krb5.h +++ b/src/lib/gssapi/krb5/gssapiP_krb5.h @@ -163,6 +163,7 @@ typedef struct _krb5_gss_name_rec { krb5_principal princ; /* immutable */ char *service; /* immutable */ char *host; /* immutable */ + int is_cert; /* immutable */ k5_mutex_t lock; /* protects ad_context only for now */ krb5_authdata_context ad_context; } krb5_gss_name_rec, *krb5_gss_name_t; diff --git a/src/lib/gssapi/krb5/gssapi_krb5.c b/src/lib/gssapi/krb5/gssapi_krb5.c index 128ffffa18..a96d7ceaeb 100644 --- a/src/lib/gssapi/krb5/gssapi_krb5.c +++ b/src/lib/gssapi/krb5/gssapi_krb5.c @@ -152,6 +152,8 @@ const gss_OID_desc krb5_gss_oid_array[] = { {GET_CRED_IMPERSONATOR_OID_LENGTH, GET_CRED_IMPERSONATOR_OID}, /* GSS_KRB5_NT_ENTERPRISE_NAME */ {10, "\052\206\110\206\367\022\001\002\002\006"}, + /* GSS_KRB5_NT_X509_CERT */ + {10, "\052\206\110\206\367\022\001\002\002\007"}, { 0, 0 } }; @@ -170,6 +172,7 @@ const gss_OID GSS_KRB5_NT_PRINCIPAL_NAME = &kg_oids[5]; const gss_OID GSS_KRB5_CRED_NO_CI_FLAGS_X = &kg_oids[7]; const gss_OID GSS_KRB5_GET_CRED_IMPERSONATOR = &kg_oids[8]; const gss_OID GSS_KRB5_NT_ENTERPRISE_NAME = &kg_oids[9]; +const gss_OID GSS_KRB5_NT_X509_CERT = &kg_oids[10]; static const gss_OID_set_desc oidsets[] = { {1, &kg_oids[0]}, /* RFC OID */ diff --git a/src/lib/gssapi/krb5/gssapi_krb5.h b/src/lib/gssapi/krb5/gssapi_krb5.h index e266b59b6f..8141f41db9 100644 --- a/src/lib/gssapi/krb5/gssapi_krb5.h +++ b/src/lib/gssapi/krb5/gssapi_krb5.h @@ -78,6 +78,11 @@ GSS_DLLIMP extern const gss_OID GSS_KRB5_NT_ENTERPRISE_NAME; /* {iso(1) member-body(2) United States(840) mit(113554) infosys(1) gssapi(2) * krb5(2) krb5-enterprise-name(6)}. */ +/* Kerberos X.509 DER-encoded certificate */ +GSS_DLLIMP extern const gss_OID GSS_KRB5_NT_X509_CERT; +/* {iso(1) member-body(2) United States(840) mit(113554) infosys(1) gssapi(2) + * krb5(2) krb5-x509-cert(7)}. */ + GSS_DLLIMP extern const gss_OID gss_mech_krb5; GSS_DLLIMP extern const gss_OID gss_mech_krb5_old; GSS_DLLIMP extern const gss_OID gss_mech_krb5_wrong; diff --git a/src/lib/gssapi/krb5/import_name.c b/src/lib/gssapi/krb5/import_name.c index 21023dd769..f64635a202 100644 --- a/src/lib/gssapi/krb5/import_name.c +++ b/src/lib/gssapi/krb5/import_name.c @@ -136,7 +136,7 @@ krb5_gss_import_name(minor_status, input_name_buffer, #ifndef NO_PASSWORD struct passwd *pw; #endif - int is_composite = 0; + int is_composite = 0, is_cert = 0; krb5_authdata_context ad_context = NULL; OM_uint32 status = GSS_S_FAILURE; krb5_gss_name_t name; @@ -188,6 +188,14 @@ krb5_gss_import_name(minor_status, input_name_buffer, &princ); if (code) goto cleanup; + } else if ((input_name_type != NULL) && + g_OID_equal(input_name_type, GSS_KRB5_NT_X509_CERT)) { + code = krb5_build_principal_ext(context, &princ, 0, NULL, + input_name_buffer->length, + input_name_buffer->value, 0); + if (code) + goto cleanup; + is_cert = 1; } else { #ifndef NO_PASSWORD uid_t uid; @@ -315,6 +323,8 @@ krb5_gss_import_name(minor_status, input_name_buffer, KG_INIT_NAME_NO_COPY, &name); if (code) goto cleanup; + name->is_cert = is_cert; + princ = NULL; ad_context = NULL; service = host = NULL; diff --git a/src/lib/gssapi/krb5/s4u_gss_glue.c b/src/lib/gssapi/krb5/s4u_gss_glue.c index 126ca973ca..7dcfe4e1eb 100644 --- a/src/lib/gssapi/krb5/s4u_gss_glue.c +++ b/src/lib/gssapi/krb5/s4u_gss_glue.c @@ -48,11 +48,15 @@ kg_impersonate_name(OM_uint32 *minor_status, OM_uint32 major_status; krb5_error_code code; krb5_creds in_creds, *out_creds = NULL; + krb5_data *subject_cert = NULL; *output_cred = NULL; memset(&in_creds, 0, sizeof(in_creds)); - in_creds.client = user->princ; + if (user->is_cert) + subject_cert = user->princ->data; + else + in_creds.client = user->princ; in_creds.server = impersonator_cred->name->princ; if (impersonator_cred->req_enctypes != NULL) @@ -77,8 +81,7 @@ kg_impersonate_name(OM_uint32 *minor_status, code = krb5_get_credentials_for_user(context, KRB5_GC_CANONICALIZE | KRB5_GC_NO_STORE, impersonator_cred->ccache, - &in_creds, - NULL, &out_creds); + &in_creds, subject_cert, &out_creds); if (code != 0) { krb5_free_authdata(context, in_creds.authdata); *minor_status = code; diff --git a/src/lib/gssapi/libgssapi_krb5.exports b/src/lib/gssapi/libgssapi_krb5.exports index 166acfa34e..fd4fced8e9 100644 --- a/src/lib/gssapi/libgssapi_krb5.exports +++ b/src/lib/gssapi/libgssapi_krb5.exports @@ -12,6 +12,7 @@ GSS_C_NT_STRING_UID_NAME GSS_C_NT_USER_NAME GSS_KRB5_NT_PRINCIPAL_NAME GSS_KRB5_NT_ENTERPRISE_NAME +GSS_KRB5_NT_X509_CERT GSS_KRB5_CRED_NO_CI_FLAGS_X GSS_KRB5_GET_CRED_IMPERSONATOR GSS_C_MA_MECH_CONCRETE diff --git a/src/lib/gssapi32.def b/src/lib/gssapi32.def index e6b1479bbb..a5a1e4a905 100644 --- a/src/lib/gssapi32.def +++ b/src/lib/gssapi32.def @@ -187,3 +187,5 @@ EXPORTS GSS_C_SEC_CONTEXT_SASL_SSF @149 DATA ; Added in 1.17 GSS_KRB5_NT_ENTERPRISE_NAME @150 DATA +; Added in 1.19 + GSS_KRB5_NT_X509_CERT @151 DATA diff --git a/src/tests/gssapi/common.c b/src/tests/gssapi/common.c index 7ba72f7b27..b49c13d5d4 100644 --- a/src/tests/gssapi/common.c +++ b/src/tests/gssapi/common.c @@ -99,10 +99,12 @@ import_name(const char *str) nametype = (gss_OID)GSS_KRB5_NT_PRINCIPAL_NAME; else if (*str == 'e') nametype = (gss_OID)GSS_KRB5_NT_ENTERPRISE_NAME; + else if (*str == 'c') + nametype = (gss_OID)GSS_KRB5_NT_X509_CERT; else if (*str == 'h') nametype = GSS_C_NT_HOSTBASED_SERVICE; if (nametype == NULL || str[1] != ':') - errout("names must begin with u: or p: or e: or h:"); + errout("names must begin with u: or p: or e: or c: or h:"); buf.value = (char *)str + 2; buf.length = strlen(str) - 2; major = gss_import_name(&minor, &buf, nametype, &name); diff --git a/src/tests/gssapi/t_imp_name.c b/src/tests/gssapi/t_imp_name.c index 3d73dc8fbc..e7dbcc426e 100644 --- a/src/tests/gssapi/t_imp_name.c +++ b/src/tests/gssapi/t_imp_name.c @@ -41,6 +41,8 @@ oid_str(char type) return "{ 1 2 840 113554 1 2 2 1 }"; case 'e': /* GSS_KRB5_NT_ENTERPRISE_NAME */ return "{ 1 2 840 113554 1 2 2 6 }"; + case 'c': /* GSS_KRB5_NT_X509_CERT */ + return "{ 1 2 840 113554 1 2 2 7 }"; case 'h': /* GSS_C_NT_HOSTBASED_SERVICE */ return "{ 1 2 840 113554 1 2 1 4 }"; } diff --git a/src/tests/gssapi/t_s4u.py b/src/tests/gssapi/t_s4u.py index 8077d8c6bf..67eba44dab 100755 --- a/src/tests/gssapi/t_s4u.py +++ b/src/tests/gssapi/t_s4u.py @@ -277,6 +277,16 @@ msgs = ('Getting initial credentials for enterprise\\@abc@SREALM', r1.run([kvno, '-U', 'enterprise@abc', '-F', cert_path, r1.user_princ], expected_trace=msgs) +shutil.copyfile(savefile, r1.ccache) + +mark('S4U2Self using X509 certificate (GSSAPI)') + +r1.run(['./t_s4u', 'c:other', '-', r1.keytab]) +r1.run(['./t_s4u', 'c:user@UREALM', '-', r1.keytab]) + +r1.run(['./t_s4u', '--spnego', 'c:other', '-', r1.keytab]) +r1.run(['./t_s4u', '--spnego', 'c:user@UREALM', '-', r1.keytab]) + r1.stop() r2.stop()