Date: Fri, 1 Aug 2025 17:21:40 -0700 From: Rick Macklem <rick.macklem@gmail.com> To: FreeBSD CURRENT <freebsd-current@freebsd.org>, Gleb Smirnoff <glebius@freebsd.org>, Benjamin Kaduk <bjkfbsd@gmail.com> Subject: kgssapi and gssd patches for MIT's Kerberos Message-ID: <CAM5tNy6kRjUeJUZwmWSnC_kupAaKrqxn5aXR76p_CtWFEu9bvQ@mail.gmail.com>
index | next in thread | raw e-mail
[-- Attachment #1 --] Hi, The discussion seems to have not had a mailing list on it, so here's what I posted. Maybe some others can do testing (or take a look at them)? Well, here's patches for testing. They are still kinda rough, but I'll be cleaning them up in the coming days and putting them in phabricator. They are attached and can also be found here... https://people.freebsd.org/~rmacklem/gssd.patch https://people.freebsd.org/~rmacklem/kgssapi.patch To make it work, I did.. # pkg install krb5 --> The libraries in /usr/lib are broken, at least in the one week old snapshot I am using for testing. # cp /usr/include/gssapi_krb5/gssapi/gssapi.h /usr/include/gssapi --> So that the correct (MIT) gssapi.h is in /usr/include/gssapi. Then after patching and building, I go into... /usr/obj/usr/src/amd64.amd64/usr.sbin/gssd and then I re-link gssd with cc -o gssd -L/usr/local/lib gssd.pieo gssd_prot.pieo gssd_svc.pieo gssd_xdr.pieo -lkrb5 -lk5crypto -lkrb5profile -lkrb5support -lgssapi_krb5 and then # cp gssd /usr/sbin You might be able to just add "-L/usr/local/lib" to the gssd Makefile, but I didn't feel like messing with it. It now seems to be working ok, using a pre-MIT Heimdal 1.5.2 kdc and pre-MIT system. (I have not yet done any testing with non-FreeBSD systems. I have Solaris 11.4 and a fairly recent 6.12 kernel based Debian, but I haven't set either up for Kerberos.) Good luck with testing, rick ps: I'll post when cleaner patches are on phabricator. [-- Attachment #2 --] --- usr.sbin/gssd/Makefile.sav 2025-07-28 16:49:35.386386000 -0700 +++ usr.sbin/gssd/Makefile 2025-07-31 19:56:16.666434000 -0700 @@ -9,15 +9,14 @@ WARNS?= 1 CFLAGS+= -I. WARNS?= 1 -LIBADD= gssapi .if ${MK_KERBEROS_SUPPORT} != "no" .if ${MK_MITKRB5} != "no" # MIT KRB5 -LIBADD+= krb5 k5crypto krb5profile krb5support +LIBADD= krb5 k5crypto krb5profile krb5support gssapi_krb5 CFLAGS+= -DMK_MITKRB5=yes .else # Heimdal -LIBADD+= krb5 roken +LIBADD= gssapi krb5 roken .endif .else CFLAGS+= -DWITHOUT_KERBEROS --- usr.sbin/gssd/gssd.c.sav 2025-07-26 19:21:27.204328000 -0700 +++ usr.sbin/gssd/gssd.c 2025-08-01 08:32:54.958122000 -0700 @@ -53,6 +53,9 @@ #include <arpa/inet.h> #include <netinet/in.h> #include <gssapi/gssapi.h> +#ifdef MK_MITKRB5 +#include <gssapi/gssapi_krb5.h> +#endif #include <rpc/rpc.h> #include <rpc/rpc_com.h> @@ -335,6 +338,7 @@ gssd_null_1_svc(void *argp, void *result, struct svc_r return (TRUE); } +#ifndef MK_MITKRB5 bool_t gssd_init_sec_context_1_svc(init_sec_context_args *argp, init_sec_context_res *result, struct svc_req *rqstp) { @@ -454,11 +458,40 @@ gssd_init_sec_context_1_svc(init_sec_context_args *arg else result->ctx = gssd_make_resource(ctx); } + + return (TRUE); +} + +bool_t +gssd_supports_lucid_1_svc(void *argp, supports_lucid_res *result, struct svc_req *rqstp) +{ + gssd_verbose_out("gssd_lucid: done\n"); + result->major_status = GSS_S_UNAVAILABLE; return (TRUE); } bool_t +gssd_init_sec_context_plus_1_svc(init_sec_context_plus_args *argp, + init_sec_context_plus_res *result, struct svc_req *rqstp) +{ + + gssd_verbose_out("gssd_init_sec_context_plus: Heimdal\n"); + result->major_status = GSS_S_UNAVAILABLE; + return (TRUE); +} + +bool_t +gssd_accept_sec_context_plus_1_svc(accept_sec_context_plus_args *argp, + accept_sec_context_plus_res *result, struct svc_req *rqstp) +{ + + gssd_verbose_out("gssd_accept_sec_context_plus: Heimdal\n"); + result->major_status = GSS_S_UNAVAILABLE; + return (TRUE); +} + +bool_t gssd_accept_sec_context_1_svc(accept_sec_context_args *argp, accept_sec_context_res *result, struct svc_req *rqstp) { gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; @@ -508,8 +541,342 @@ gssd_accept_sec_context_1_svc(accept_sec_context_args return (TRUE); } +#else /* MK_MITKRB5 */ +bool_t +gssd_supports_lucid_1_svc(void *argp, supports_lucid_res *result, struct svc_req *rqstp) +{ + gssd_verbose_out("gssd_lucid: done\n"); + result->vers = 1; + result->major_status = GSS_S_COMPLETE; + return (TRUE); +} + bool_t +gssd_init_sec_context_1_svc(init_sec_context_args *argp, + init_sec_context_res *result, struct svc_req *rqstp) +{ + + gssd_verbose_out("gssd_init_sec_context_plus: MIT\n"); + result->major_status = GSS_S_UNAVAILABLE; + return (TRUE); +} + +bool_t +gssd_accept_sec_context_1_svc(accept_sec_context_args *argp, + accept_sec_context_res *result, struct svc_req *rqstp) +{ + + gssd_verbose_out("gssd_accept_sec_context_plus: MIT\n"); + result->major_status = GSS_S_UNAVAILABLE; + return (TRUE); +} + +bool_t +gssd_init_sec_context_plus_1_svc(init_sec_context_plus_args *argp, + init_sec_context_plus_res *result, struct svc_req *rqstp) +{ + gss_cred_id_t cred = GSS_C_NO_CREDENTIAL; + gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; + gss_name_t name = GSS_C_NO_NAME; + char ccname[PATH_MAX + 5 + 1], *cp, *cp2; + int gotone, gotcred; + OM_uint32 min_stat; +#ifndef WITHOUT_KERBEROS + gss_buffer_desc principal_desc; + char enctype[sizeof(uint32_t)]; + int key_enctype; + OM_uint32 maj_stat; +#endif + + memset(result, 0, sizeof(*result)); + if (hostbased_initiator_cred != 0 && argp->cred != 0 && + argp->uid == 0) { + /* + * These credentials are for a host based initiator name + * in a keytab file, which should now have credentials + * in /tmp/krb5cc_gssd, because gss_acquire_cred() did + * the equivalent of "kinit -k". + */ + snprintf(ccname, sizeof(ccname), "FILE:%s", + GSSD_CREDENTIAL_CACHE_FILE); + } else if (ccfile_dirlist[0] != '\0' && argp->cred == 0) { + /* + * For the "-s" case and no credentials provided as an + * argument, search the directory list for an appropriate + * credential cache file. If the search fails, return failure. + */ + gotone = 0; + cp = ccfile_dirlist; + do { + cp2 = strchr(cp, ':'); + if (cp2 != NULL) + *cp2 = '\0'; + gotone = find_ccache_file(cp, argp->uid, ccname); + if (gotone != 0) + break; + if (cp2 != NULL) + *cp2++ = ':'; + cp = cp2; + } while (cp != NULL && *cp != '\0'); + if (gotone == 0) { + result->major_status = GSS_S_CREDENTIALS_EXPIRED; + gssd_verbose_out("gssd_init_sec_context_plus: -s no" + " credential cache file found for uid=%d\n", + (int)argp->uid); + return (TRUE); + } + } else { + /* + * If there wasn't a "-s" option or the credentials have + * been provided as an argument, do it the old way. + * When credentials are provided, the uid should be root. + */ + if (argp->cred != 0 && argp->uid != 0) { + if (debug_level == 0) + syslog(LOG_ERR, "gss_init_sec_context_plus:" + " cred for non-root"); + else + fprintf(stderr, "gss_init_sec_context_plus:" + " cred for non-root\n"); + } + snprintf(ccname, sizeof(ccname), "FILE:/tmp/krb5cc_%d", + (int) argp->uid); + } + setenv("KRB5CCNAME", ccname, TRUE); + + if (argp->cred) { + cred = gssd_find_resource(argp->cred); + if (!cred) { + result->major_status = GSS_S_CREDENTIALS_EXPIRED; + gssd_verbose_out("gssd_init_sec_context_plus: cred" + " resource not found\n"); + return (TRUE); + } + } + if (argp->ctx) { + ctx = gssd_find_resource(argp->ctx); + if (!ctx) { + result->major_status = GSS_S_CONTEXT_EXPIRED; + gssd_verbose_out("gssd_init_sec_context_plus: context" + " resource not found\n"); + return (TRUE); + } + } + if (argp->name) { + name = gssd_find_resource(argp->name); + if (!name) { + result->major_status = GSS_S_BAD_NAME; + gssd_verbose_out("gssd_init_sec_context_plus: name" + " resource not found\n"); + return (TRUE); + } + } + gotcred = 0; + + result->major_status = gss_init_sec_context(&result->minor_status, + cred, &ctx, name, argp->mech_type, + argp->req_flags, argp->time_req, argp->input_chan_bindings, + &argp->input_token, &result->actual_mech_type, + &result->output_token, &result->ret_flags, &result->time_rec); + gssd_verbose_out("gssd_init_sec_context_plus: done major=0x%x minor=%d" + " uid=%d\n", (unsigned int)result->major_status, + (int)result->minor_status, (int)argp->uid); + if (gotcred != 0) + gss_release_cred(&min_stat, &cred); + + if (result->actual_mech_type) { +gssd_verbose_out("gssd mech len=%d elem=%p\n", result->actual_mech_type->length, result->actual_mech_type->elements); + /* + * Just to keep the bogus "elements" pointer + * from core dumping the daemon. + */ + result->actual_mech_type = GSS_KRB5_MECH_OID_X; +gssd_verbose_out("gssd aft mech\n"); + } + + if (result->major_status == GSS_S_COMPLETE + || result->major_status == GSS_S_CONTINUE_NEEDED) { + if (argp->ctx) + result->ctx = argp->ctx; + else + result->ctx = gssd_make_resource(ctx); + gssd_verbose_out("gssd_init_ctx=%p arg=%ld res=%ld", ctx, argp->ctx, result->ctx); + } + + if (result->major_status == GSS_S_COMPLETE) { + gss_krb5_lucid_context_v1_t *lctx; + + result->major_status = gss_krb5_export_lucid_sec_context( + &result->minor_status, &ctx, 1, (void *)&lctx); + gssd_verbose_out("gss_lucid: maj=0x%x min=0x%x lctx=%p\n", result->major_status, result->minor_status, lctx); + if (result->major_status == GSS_S_COMPLETE && + lctx != NULL) { + gssd_verbose_out("Got the sucker!!"); + result->initiate = lctx->initiate; + result->endtime = lctx->endtime; + result->send_seq = lctx->send_seq; + result->recv_seq = lctx->recv_seq; + result->protocol = lctx->protocol; + if (lctx->protocol == 0) { + result->rfc_sign = lctx->rfc1964_kd.sign_alg; + result->rfc_seal = lctx->rfc1964_kd.seal_alg; + result->ctx_type = + lctx->rfc1964_kd.ctx_key.type; + result->ctx_key.length = + lctx->rfc1964_kd.ctx_key.length; + result->ctx_key.value = + mem_alloc(result->ctx_key.length); + memcpy(result->ctx_key.value, + lctx->rfc1964_kd.ctx_key.data, + result->ctx_key.length); + } else if (lctx->protocol == 1) { + gssd_verbose_out("accsub=%d\n", lctx->cfx_kd.have_acceptor_subkey); + gssd_verbose_out("ctx ty=%d len=%d k=%p\n", lctx->cfx_kd.ctx_key.type, lctx->cfx_kd.ctx_key.length, lctx->cfx_kd.ctx_key.data); + gssd_verbose_out("sub ty=%d len=%d k=%p\n", lctx->cfx_kd.acceptor_subkey.type, lctx->cfx_kd.acceptor_subkey.length, lctx->cfx_kd.acceptor_subkey.data); + result->have_subkey = + lctx->cfx_kd.have_acceptor_subkey; + result->ctx_type = lctx->cfx_kd.ctx_key.type; + result->ctx_key.length = + lctx->cfx_kd.ctx_key.length; + result->ctx_key.value = + mem_alloc(result->ctx_key.length); + memcpy(result->ctx_key.value, + lctx->cfx_kd.ctx_key.data, + result->ctx_key.length); + if (result->have_subkey != 0) { + result->subkey_type = + lctx->cfx_kd.acceptor_subkey.type; + result->subkey_key.length = + lctx->cfx_kd.acceptor_subkey.length; + result->subkey_key.value = mem_alloc( + result->subkey_key.length); + memcpy(result->subkey_key.value, + lctx->cfx_kd.acceptor_subkey.data, + result->subkey_key.length); + } else { + result->subkey_type = 0; + result->subkey_key.length = 0; + result->subkey_key.value = NULL; + } + } + } + } + + return (TRUE); +} + +bool_t +gssd_accept_sec_context_plus_1_svc(accept_sec_context_plus_args *argp, accept_sec_context_plus_res *result, struct svc_req *rqstp) +{ + gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; + gss_cred_id_t cred = GSS_C_NO_CREDENTIAL; + gss_name_t src_name; + gss_cred_id_t delegated_cred_handle; + + memset(result, 0, sizeof(*result)); + if (argp->ctx) { + ctx = gssd_find_resource(argp->ctx); + if (!ctx) { + result->major_status = GSS_S_CONTEXT_EXPIRED; + gssd_verbose_out("gssd_accept_sec_context: ctx" + " resource not found\n"); + return (TRUE); + } + } + if (argp->cred) { + cred = gssd_find_resource(argp->cred); + if (!cred) { + result->major_status = GSS_S_CREDENTIALS_EXPIRED; + gssd_verbose_out("gssd_accept_sec_context: cred" + " resource not found\n"); + return (TRUE); + } + } + + memset(result, 0, sizeof(*result)); + result->major_status = gss_accept_sec_context(&result->minor_status, + &ctx, cred, &argp->input_token, argp->input_chan_bindings, + &src_name, &result->mech_type, &result->output_token, + &result->ret_flags, &result->time_rec, + &delegated_cred_handle); + gssd_verbose_out("gssd_accept_sec_context: done major=0x%x minor=%d\n", + (unsigned int)result->major_status, (int)result->minor_status); + + if (result->major_status == GSS_S_COMPLETE + || result->major_status == GSS_S_CONTINUE_NEEDED) { + if (argp->ctx) + result->ctx = argp->ctx; + else + result->ctx = gssd_make_resource(ctx); + result->src_name = gssd_make_resource(src_name); + result->delegated_cred_handle = + gssd_make_resource(delegated_cred_handle); + } + + if (result->major_status == GSS_S_COMPLETE) { + gss_krb5_lucid_context_v1_t *lctx; + + result->major_status = gss_krb5_export_lucid_sec_context( + &result->minor_status, &ctx, 1, (void *)&lctx); + gssd_verbose_out("gss_lucid: maj=0x%x min=0x%x lctx=%p\n", result->major_status, result->minor_status, lctx); + if (result->major_status == GSS_S_COMPLETE && + lctx != NULL) { + gssd_verbose_out("Got the sucker!!"); + result->initiate = lctx->initiate; + result->endtime = lctx->endtime; + result->send_seq = lctx->send_seq; + result->recv_seq = lctx->recv_seq; + result->protocol = lctx->protocol; + if (lctx->protocol == 0) { + result->rfc_sign = lctx->rfc1964_kd.sign_alg; + result->rfc_seal = lctx->rfc1964_kd.seal_alg; + result->ctx_type = + lctx->rfc1964_kd.ctx_key.type; + result->ctx_key.length = + lctx->rfc1964_kd.ctx_key.length; + result->ctx_key.value = + mem_alloc(result->ctx_key.length); + memcpy(result->ctx_key.value, + lctx->rfc1964_kd.ctx_key.data, + result->ctx_key.length); + } else if (lctx->protocol == 1) { + gssd_verbose_out("accsub=%d\n", lctx->cfx_kd.have_acceptor_subkey); + gssd_verbose_out("ctx ty=%d len=%d k=%p\n", lctx->cfx_kd.ctx_key.type, lctx->cfx_kd.ctx_key.length, lctx->cfx_kd.ctx_key.data); + gssd_verbose_out("sub ty=%d len=%d k=%p\n", lctx->cfx_kd.acceptor_subkey.type, lctx->cfx_kd.acceptor_subkey.length, lctx->cfx_kd.acceptor_subkey.data); + result->have_subkey = + lctx->cfx_kd.have_acceptor_subkey; + result->ctx_type = lctx->cfx_kd.ctx_key.type; + result->ctx_key.length = + lctx->cfx_kd.ctx_key.length; + result->ctx_key.value = + mem_alloc(result->ctx_key.length); + memcpy(result->ctx_key.value, + lctx->cfx_kd.ctx_key.data, + result->ctx_key.length); + if (result->have_subkey != 0) { + result->subkey_type = + lctx->cfx_kd.acceptor_subkey.type; + result->subkey_key.length = + lctx->cfx_kd.acceptor_subkey.length; + result->subkey_key.value = mem_alloc( + result->subkey_key.length); + memcpy(result->subkey_key.value, + lctx->cfx_kd.acceptor_subkey.data, + result->subkey_key.length); + } else { + result->subkey_type = 0; + result->subkey_key.length = 0; + result->subkey_key.value = NULL; + } + } + } + } + return (TRUE); +} +#endif /* !MK_MITKRB5 */ + +bool_t gssd_delete_sec_context_1_svc(delete_sec_context_args *argp, delete_sec_context_res *result, struct svc_req *rqstp) { gss_ctx_id_t ctx = gssd_find_resource(argp->ctx); [-- Attachment #3 --] --- sys/kgssapi/krb5/krb5_mech.c.sav 2025-07-27 19:20:29.886309000 -0700 +++ sys/kgssapi/krb5/krb5_mech.c 2025-08-01 14:00:25.394711000 -0700 @@ -215,6 +215,18 @@ copy_key(struct krb5_keyblock *from, struct krb5_keybl *to = from; else *to = NULL; +} + +static void +copy_lucid_key(gss_krb5_lucid_key_t *from, struct krb5_keyblock *to) +{ + + to->kk_type = from->type; + to->kk_key.kd_length = from->length; + if (from->length > 0) { + to->kk_key.kd_data = malloc(from->length, M_GSSAPI, M_WAITOK); + memcpy(to->kk_key.kd_data, from->data, from->length); + } } /* @@ -258,6 +270,98 @@ static OM_uint32 } static OM_uint32 +get_lucid_keys(struct krb5_context *kc) +{ + struct krb5_keyblock *keydata; + struct krb5_encryption_class *ec; + struct krb5_key_state *key; + int etype; + + keydata = NULL; + get_acceptor_subkey(kc, &keydata); + if (!keydata) + if ((kc->kc_more_flags & ACCEPTOR_SUBKEY) == 0) + get_initiator_subkey(kc, &keydata); + if (!keydata) + return (GSS_S_FAILURE); + + /* + * GSS-API treats all DES etypes the same and all DES3 etypes + * the same. + */ + switch (keydata->kk_type) { + case ETYPE_DES_CBC_CRC: + case ETYPE_DES_CBC_MD4: + case ETYPE_DES_CBC_MD5: + case ETYPE_DES3_CBC_MD5: + case ETYPE_DES3_CBC_SHA1: + case ETYPE_OLD_DES3_CBC_SHA1: + return (GSS_S_FAILURE); + + default: + etype = keydata->kk_type; + } + + ec = krb5_find_encryption_class(etype); + if (!ec) + return (GSS_S_FAILURE); + + key = krb5_create_key(ec); + krb5_set_key(key, keydata->kk_key.kd_data); + kc->kc_tokenkey = key; + + /* + * We need eight derived keys four for sending and + * four for receiving. + */ + if (is_initiator(kc)) { + /* + * We are initiator. + */ + kc->kc_send_seal_Ke = krb5_get_encryption_key(key, + KG_USAGE_INITIATOR_SEAL); + kc->kc_send_seal_Ki = krb5_get_integrity_key(key, + KG_USAGE_INITIATOR_SEAL); + kc->kc_send_seal_Kc = krb5_get_checksum_key(key, + KG_USAGE_INITIATOR_SEAL); + kc->kc_send_sign_Kc = krb5_get_checksum_key(key, + KG_USAGE_INITIATOR_SIGN); + + kc->kc_recv_seal_Ke = krb5_get_encryption_key(key, + KG_USAGE_ACCEPTOR_SEAL); + kc->kc_recv_seal_Ki = krb5_get_integrity_key(key, + KG_USAGE_ACCEPTOR_SEAL); + kc->kc_recv_seal_Kc = krb5_get_checksum_key(key, + KG_USAGE_ACCEPTOR_SEAL); + kc->kc_recv_sign_Kc = krb5_get_checksum_key(key, + KG_USAGE_ACCEPTOR_SIGN); + } else { + /* + * We are acceptor. + */ + kc->kc_send_seal_Ke = krb5_get_encryption_key(key, + KG_USAGE_ACCEPTOR_SEAL); + kc->kc_send_seal_Ki = krb5_get_integrity_key(key, + KG_USAGE_ACCEPTOR_SEAL); + kc->kc_send_seal_Kc = krb5_get_checksum_key(key, + KG_USAGE_ACCEPTOR_SEAL); + kc->kc_send_sign_Kc = krb5_get_checksum_key(key, + KG_USAGE_ACCEPTOR_SIGN); + + kc->kc_recv_seal_Ke = krb5_get_encryption_key(key, + KG_USAGE_INITIATOR_SEAL); + kc->kc_recv_seal_Ki = krb5_get_integrity_key(key, + KG_USAGE_INITIATOR_SEAL); + kc->kc_recv_seal_Kc = krb5_get_checksum_key(key, + KG_USAGE_INITIATOR_SEAL); + kc->kc_recv_sign_Kc = krb5_get_checksum_key(key, + KG_USAGE_INITIATOR_SIGN); + } + + return (GSS_S_COMPLETE); +} + +static OM_uint32 get_keys(struct krb5_context *kc) { struct krb5_keyblock *keydata; @@ -402,6 +506,77 @@ static OM_uint32 } static OM_uint32 +krb5_lucid_import(gss_ctx_id_t ctx, + enum sec_context_format format, + const gss_buffer_t context_token) +{ + struct krb5_context *kc = (struct krb5_context *)ctx; + gss_krb5_lucid_context_v1_t *lctx = (gss_krb5_lucid_context_v1_t *) + context_token; + OM_uint32 res; + +printf("krb5_import: initiate=%d endtime=%d send_seq=%ld recv_seq=%ld proto=%d\n", lctx->initiate, lctx->endtime, lctx->send_seq, lctx->recv_seq, lctx->protocol); + kc->kc_more_flags = 0; + if (lctx->protocol == 0) { + kc->kc_cksumtype = lctx->rfc1964_kd.sign_alg; + kc->kc_keytype = lctx->rfc1964_kd.seal_alg; + copy_lucid_key(&lctx->rfc1964_kd.ctx_key, + &kc->kc_keyblock); + } else if (lctx->protocol == 1) { +printf("acceptor=%d\n", lctx->cfx_kd.have_acceptor_subkey); + if (lctx->cfx_kd.have_acceptor_subkey != 0) { + if (lctx->initiate != 0) + copy_lucid_key(&lctx->cfx_kd.acceptor_subkey, + &kc->kc_remote_subkey); + else + copy_lucid_key(&lctx->cfx_kd.acceptor_subkey, + &kc->kc_local_subkey); + kc->kc_cksumtype = lctx->cfx_kd.acceptor_subkey.type; + kc->kc_keytype = lctx->cfx_kd.acceptor_subkey.type; + kc->kc_more_flags |= ACCEPTOR_SUBKEY; + } else { + if (lctx->initiate != 0) + copy_lucid_key(&lctx->cfx_kd.ctx_key, + &kc->kc_remote_subkey); + else + copy_lucid_key(&lctx->cfx_kd.ctx_key, + &kc->kc_local_subkey); + kc->kc_cksumtype = lctx->cfx_kd.ctx_key.type; + kc->kc_keytype = lctx->cfx_kd.ctx_key.type; + } + } else { + return (GSS_S_DEFECTIVE_TOKEN); + } +#ifdef notnow + if (flags & SC_KEYBLOCK) + get_keyblock(&p, &len, &kc->kc_keyblock); + if (flags & SC_LOCAL_SUBKEY) + get_keyblock(&p, &len, &kc->kc_local_subkey); + if (flags & SC_REMOTE_SUBKEY) + get_keyblock(&p, &len, &kc->kc_remote_subkey); +#endif + kc->kc_local_seqnumber = lctx->send_seq; + kc->kc_remote_seqnumber = lctx->recv_seq; + if (lctx->initiate != 0) + kc->kc_more_flags |= LOCAL; + kc->kc_lifetime = lctx->endtime; + kc->kc_msg_order.km_flags = 0; + + res = get_lucid_keys(kc); + if (GSS_ERROR(res)) + return (res); + + /* + * We don't need these anymore. + */ + delete_keyblock(&kc->kc_keyblock); + delete_keyblock(&kc->kc_local_subkey); + delete_keyblock(&kc->kc_remote_subkey); + + return (GSS_S_COMPLETE); +} + +static OM_uint32 krb5_import(gss_ctx_id_t ctx, enum sec_context_format format, const gss_buffer_t context_token) @@ -412,6 +587,10 @@ krb5_import(gss_ctx_id_t ctx, size_t len = context_token->length; uint32_t flags; int i; + + /* For MIT, just call krb5_lucid_import(). */ + if (format == MIT_V1) + return (krb5_lucid_import(ctx, format, context_token)); /* * We support heimdal 0.6 and heimdal 1.1 --- sys/kgssapi/gss_impl.c.sav 2025-07-31 13:18:39.391791000 -0700 +++ sys/kgssapi/gss_impl.c 2025-08-01 07:09:09.590174000 -0700 @@ -192,12 +192,18 @@ OM_uint32 } OM_uint32 -kgss_transfer_context(gss_ctx_id_t ctx) +kgss_transfer_context(gss_ctx_id_t ctx, void *lctx) { struct export_sec_context_res res; struct export_sec_context_args args; enum clnt_stat stat; OM_uint32 maj_stat; + + if (lctx != NULL) { + maj_stat = KGSS_IMPORT(ctx, MIT_V1, lctx); + ctx->handle = 0; + return (maj_stat); + } KGSS_CURVNET_SET_QUIET(KGSS_TD_TO_VNET(curthread)); if (!KGSS_VNET(kgss_gssd_handle)) { --- sys/kgssapi/gssapi.h.sav 2025-07-28 14:54:59.588770000 -0700 +++ sys/kgssapi/gssapi.h 2025-08-01 08:08:35.230136000 -0700 @@ -77,6 +77,54 @@ typedef int gss_cred_usage_t; typedef int gss_cred_usage_t; /* + * The structure returned by gss_krb5_export_lucid_sec_context(). + */ +typedef struct gss_krb5_lucid_key { + OM_uint32 type; /* key encryption type */ + OM_uint32 length; /* length of key data */ + void * data; /* actual key data */ +} gss_krb5_lucid_key_t; + +typedef struct gss_krb5_rfc1964_keydata { + OM_uint32 sign_alg; /* signing algorithm */ + OM_uint32 seal_alg; /* seal/encrypt algorithm */ + gss_krb5_lucid_key_t ctx_key; + /* Context key + (Kerberos session key or subkey) */ +} gss_krb5_rfc1964_keydata_t; + +typedef struct gss_krb5_cfx_keydata { + OM_uint32 have_acceptor_subkey; + /* 1 if there is an acceptor_subkey + present, 0 otherwise */ + gss_krb5_lucid_key_t ctx_key; + /* Context key + (Kerberos session key or subkey) */ + gss_krb5_lucid_key_t acceptor_subkey; + /* acceptor-asserted subkey or + 0's if no acceptor subkey */ +} gss_krb5_cfx_keydata_t; + +typedef struct gss_krb5_lucid_context_v1 { + OM_uint32 version; /* Structure version number (1) + MUST be at beginning of struct! */ + OM_uint32 initiate; /* Are we the initiator? */ + OM_uint32 endtime; /* expiration time of context */ + uint64_t send_seq; /* sender sequence number */ + uint64_t recv_seq; /* receive sequence number */ + OM_uint32 protocol; /* 0: rfc1964, + 1: draft-ietf-krb-wg-gssapi-cfx-07 */ + /* + * if (protocol == 0) rfc1964_kd should be used + * and cfx_kd contents are invalid and should be zero + * if (protocol == 1) cfx_kd should be used + * and rfc1964_kd contents are invalid and should be zero + */ + gss_krb5_rfc1964_keydata_t rfc1964_kd; + gss_krb5_cfx_keydata_t cfx_kd; +} gss_krb5_lucid_context_v1_t; + +/* * Flag bits for context-level services. */ #define GSS_C_DELEG_FLAG 1 @@ -406,6 +454,23 @@ OM_uint32 gss_init_sec_context ); OM_uint32 gss_init_sec_context + (OM_uint32 *, /* minor_status */ + const gss_cred_id_t, /* initiator_cred_handle */ + gss_ctx_id_t *, /* context_handle */ + const gss_name_t, /* target_name */ + const gss_OID, /* mech_type */ + OM_uint32, /* req_flags */ + OM_uint32, /* time_req */ + const gss_channel_bindings_t, + /* input_chan_bindings */ + const gss_buffer_t, /* input_token */ + gss_OID *, /* actual_mech_type */ + gss_buffer_t, /* output_token */ + OM_uint32 *, /* ret_flags */ + OM_uint32 * /* time_rec */ + ); + +OM_uint32 gss_init_sec_context_plus (OM_uint32 *, /* minor_status */ const gss_cred_id_t, /* initiator_cred_handle */ gss_ctx_id_t *, /* context_handle */ @@ -422,6 +487,11 @@ OM_uint32 gss_init_sec_context OM_uint32 * /* time_rec */ ); +OM_uint32 gss_supports_lucid + (OM_uint32 *, /* minor_status */ + OM_uint32 * /* vers */ + ); + OM_uint32 gss_accept_sec_context (OM_uint32 *, /* minor_status */ gss_ctx_id_t *, /* context_handle */ @@ -437,6 +507,21 @@ OM_uint32 gss_accept_sec_context gss_cred_id_t * /* delegated_cred_handle */ ); +OM_uint32 gss_accept_sec_context_plus + (OM_uint32 *, /* minor_status */ + gss_ctx_id_t *, /* context_handle */ + const gss_cred_id_t, /* acceptor_cred_handle */ + const gss_buffer_t, /* input_token_buffer */ + const gss_channel_bindings_t, + /* input_chan_bindings */ + gss_name_t *, /* src_name */ + gss_OID *, /* mech_type */ + gss_buffer_t, /* output_token */ + OM_uint32 *, /* ret_flags */ + OM_uint32 *, /* time_rec */ + gss_cred_id_t * /* delegated_cred_handle */ + ); + OM_uint32 gss_delete_sec_context (OM_uint32 *, /* minor_status */ gss_ctx_id_t *, /* context_handle */ --- sys/kgssapi/gssd.x.sav 2025-07-28 14:20:10.370019000 -0700 +++ sys/kgssapi/gssd.x 2025-08-01 08:08:51.162187000 -0700 @@ -70,6 +70,40 @@ struct init_sec_context_args { gss_buffer_desc input_token; }; +struct init_sec_context_plus_res { + uint32_t major_status; + uint32_t minor_status; + gssd_ctx_id_t ctx; + gss_OID actual_mech_type; + gss_buffer_desc output_token; + uint32_t ret_flags; + uint32_t time_rec; + uint32_t initiate; + uint32_t endtime; + uint64_t send_seq; + uint64_t recv_seq; + uint32_t protocol; + uint32_t rfc_sign; + uint32_t rfc_seal; + uint32_t have_subkey; + uint32_t ctx_type; + gss_buffer_desc ctx_key; + uint32_t subkey_type; + gss_buffer_desc subkey_key; +}; + +struct init_sec_context_plus_args { + uint32_t uid; + gssd_cred_id_t cred; + gssd_ctx_id_t ctx; + gssd_name_t name; + gss_OID mech_type; + uint32_t req_flags; + uint32_t time_req; + gss_channel_bindings_t input_chan_bindings; + gss_buffer_desc input_token; +}; + struct accept_sec_context_res { uint32_t major_status; uint32_t minor_status; @@ -83,7 +117,38 @@ struct accept_sec_context_args { }; struct accept_sec_context_args { + gssd_ctx_id_t ctx; + gssd_cred_id_t cred; + gss_buffer_desc input_token; + gss_channel_bindings_t input_chan_bindings; +}; + +struct accept_sec_context_plus_res { + uint32_t major_status; + uint32_t minor_status; gssd_ctx_id_t ctx; + gssd_name_t src_name; + gss_OID mech_type; + gss_buffer_desc output_token; + uint32_t ret_flags; + uint32_t time_rec; + gssd_cred_id_t delegated_cred_handle; + uint32_t initiate; + uint32_t endtime; + uint64_t send_seq; + uint64_t recv_seq; + uint32_t protocol; + uint32_t rfc_sign; + uint32_t rfc_seal; + uint32_t have_subkey; + uint32_t ctx_type; + gss_buffer_desc ctx_key; + uint32_t subkey_type; + gss_buffer_desc subkey_key; +}; + +struct accept_sec_context_plus_args { + gssd_ctx_id_t ctx; gssd_cred_id_t cred; gss_buffer_desc input_token; gss_channel_bindings_t input_chan_bindings; @@ -101,7 +166,8 @@ enum sec_context_format { enum sec_context_format { KGSS_HEIMDAL_0_6, - KGSS_HEIMDAL_1_1 + KGSS_HEIMDAL_1_1, + MIT_V1 }; struct export_sec_context_res { @@ -229,6 +295,11 @@ struct ip_to_dns_args { char ip_addr<NI_MAXHOST>; }; +struct supports_lucid_res { + uint32_t major_status; + uint32_t vers; +}; + program GSSD { version GSSDVERS { void GSSD_NULL(void) = 0; @@ -274,5 +345,14 @@ program GSSD { ip_to_dns_res GSSD_IP_TO_DNS(ip_to_dns_args) = 14; + + init_sec_context_plus_res + GSSD_INIT_SEC_CONTEXT_PLUS(init_sec_context_plus_args) = 15; + + accept_sec_context_plus_res + GSSD_ACCEPT_SEC_CONTEXT_PLUS(accept_sec_context_plus_args) = 16; + + supports_lucid_res + GSSD_SUPPORTS_LUCID(void) = 17; } = 1; } = 0x40677373; --- sys/kgssapi/gss_init_sec_context.c.sav 2025-07-28 15:18:39.148795000 -0700 +++ sys/kgssapi/gss_init_sec_context.c 2025-08-01 08:28:02.689666000 -0700 @@ -57,8 +57,8 @@ gss_init_sec_context(OM_uint32 * minor_status, OM_uint32 * ret_flags, OM_uint32 * time_rec) { - struct init_sec_context_res res; - struct init_sec_context_args args; + struct init_sec_context_plus_res res; + struct init_sec_context_plus_args args; enum clnt_stat stat; gss_ctx_id_t ctx = *context_handle; CLIENT *cl; @@ -91,7 +91,7 @@ gss_init_sec_context(OM_uint32 * minor_status, } bzero(&res, sizeof(res)); - stat = gssd_init_sec_context_1(&args, &res, cl); + stat = gssd_init_sec_context_plus_1(&args, &res, cl); CLNT_RELEASE(cl); if (stat != RPC_SUCCESS) { *minor_status = stat; @@ -101,7 +101,7 @@ gss_init_sec_context(OM_uint32 * minor_status, if (res.major_status != GSS_S_COMPLETE && res.major_status != GSS_S_CONTINUE_NEEDED) { *minor_status = res.minor_status; - xdr_free((xdrproc_t) xdr_init_sec_context_res, &res); + xdr_free((xdrproc_t) xdr_init_sec_context_plus_res, &res); return (res.major_status); } @@ -110,7 +110,7 @@ gss_init_sec_context(OM_uint32 * minor_status, if (!ctx) { ctx = kgss_create_context(res.actual_mech_type); if (!ctx) { - xdr_free((xdrproc_t) xdr_init_sec_context_res, &res); + xdr_free((xdrproc_t) xdr_init_sec_context_plus_res, &res); *minor_status = 0; return (GSS_S_BAD_MECH); } @@ -125,15 +125,168 @@ gss_init_sec_context(OM_uint32 * minor_status, if (time_rec) *time_rec = res.time_rec; - xdr_free((xdrproc_t) xdr_init_sec_context_res, &res); + /* + * If the context establishment is complete, export it from + * userland and hand the result (which includes key material + * etc.) to the kernel implementation. + */ + if (res.major_status == GSS_S_COMPLETE) { + res.major_status = kgss_transfer_context(ctx, NULL); +printf("krb5_import: initiate=%d endtime=%d send_seq=%ld recv_seq=%ld proto=%d\n", res.initiate, res.endtime, res.send_seq, res.recv_seq, res.protocol); + } + xdr_free((xdrproc_t) xdr_init_sec_context_plus_res, &res); + + return (res.major_status); +} + +OM_uint32 +gss_supports_lucid(uint32_t *minor_status, uint32_t *vers) +{ + struct supports_lucid_res res; + enum clnt_stat stat; + CLIENT *cl; + + *minor_status = 0; + + cl = kgss_gssd_client(); + if (cl == NULL) + return (GSS_S_FAILURE); + + bzero(&res, sizeof(res)); + stat = gssd_supports_lucid_1(NULL, &res, cl); + CLNT_RELEASE(cl); + if (stat != RPC_SUCCESS) { + *minor_status = stat; + return (GSS_S_FAILURE); + } + + if (vers) + *vers = res.vers; + + return (res.major_status); +} + +OM_uint32 +gss_init_sec_context_plus(OM_uint32 * minor_status, + const gss_cred_id_t initiator_cred_handle, + gss_ctx_id_t * context_handle, + const gss_name_t target_name, + const gss_OID input_mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + const gss_channel_bindings_t input_chan_bindings, + const gss_buffer_t input_token, + gss_OID * actual_mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec) +{ + struct init_sec_context_plus_res res; + struct init_sec_context_plus_args args; + gss_krb5_lucid_context_v1_t lucid; + enum clnt_stat stat; + gss_ctx_id_t ctx = *context_handle; + CLIENT *cl; + + *minor_status = 0; + + cl = kgss_gssd_client(); + if (cl == NULL) + return (GSS_S_FAILURE); + + args.uid = curthread->td_ucred->cr_uid; + if (initiator_cred_handle) + args.cred = initiator_cred_handle->handle; + else + args.cred = 0; + if (ctx) + args.ctx = ctx->handle; + else + args.ctx = 0; + args.name = target_name->handle; + args.mech_type = input_mech_type; + args.req_flags = req_flags; + args.time_req = time_req; + args.input_chan_bindings = input_chan_bindings; + if (input_token) + args.input_token = *input_token; + else { + args.input_token.length = 0; + args.input_token.value = NULL; + } + + bzero(&res, sizeof(res)); + stat = gssd_init_sec_context_plus_1(&args, &res, cl); + CLNT_RELEASE(cl); + if (stat != RPC_SUCCESS) { + *minor_status = stat; + return (GSS_S_FAILURE); + } + + if (res.major_status != GSS_S_COMPLETE + && res.major_status != GSS_S_CONTINUE_NEEDED) { + *minor_status = res.minor_status; + xdr_free((xdrproc_t) xdr_init_sec_context_plus_res, &res); + return (res.major_status); + } + + *minor_status = res.minor_status; + + if (!ctx) { + ctx = kgss_create_context(res.actual_mech_type); + if (!ctx) { + xdr_free((xdrproc_t) xdr_init_sec_context_plus_res, &res); + *minor_status = 0; + return (GSS_S_BAD_MECH); + } + } + *context_handle = ctx; + ctx->handle = res.ctx; + if (actual_mech_type) + *actual_mech_type = KGSS_MECH_TYPE(ctx); + kgss_copy_buffer(&res.output_token, output_token); + if (ret_flags) + *ret_flags = res.ret_flags; + if (time_rec) + *time_rec = res.time_rec; + /* * If the context establishment is complete, export it from * userland and hand the result (which includes key material * etc.) to the kernel implementation. */ - if (res.major_status == GSS_S_COMPLETE) - res.major_status = kgss_transfer_context(ctx); + if (res.major_status == GSS_S_COMPLETE) { + lucid.initiate = res.initiate; + lucid.endtime = res.endtime; + lucid.send_seq = res.send_seq; + lucid.recv_seq = res.recv_seq; + lucid.protocol = res.protocol; + if (res.protocol == 0) { + lucid.rfc1964_kd.sign_alg = res.rfc_sign; + lucid.rfc1964_kd.seal_alg = res.rfc_seal; + lucid.rfc1964_kd.ctx_key.type = res.ctx_type; + lucid.rfc1964_kd.ctx_key.length = res.ctx_key.length; + lucid.rfc1964_kd.ctx_key.data = res.ctx_key.value; + } else if (res.protocol == 1) { + lucid.cfx_kd.have_acceptor_subkey = res.have_subkey; + lucid.cfx_kd.ctx_key.type = res.ctx_type; + lucid.cfx_kd.ctx_key.length = res.ctx_key.length; + lucid.cfx_kd.ctx_key.data = res.ctx_key.value; + lucid.cfx_kd.acceptor_subkey.type = res.subkey_type; + lucid.cfx_kd.acceptor_subkey.length = + res.subkey_key.length; + lucid.cfx_kd.acceptor_subkey.data = + res.subkey_key.value; + } else { + res.major_status = GSS_S_FAILURE; + } + if (res.major_status == GSS_S_COMPLETE) + res.major_status = kgss_transfer_context(ctx, &lucid); +printf("krb5_import: initiate=%d endtime=%d send_seq=%ld recv_seq=%ld proto=%d\n", res.initiate, res.endtime, res.send_seq, res.recv_seq, res.protocol); + } + xdr_free((xdrproc_t) xdr_init_sec_context_plus_res, &res); + return (res.major_status); } --- sys/kgssapi/gssapi_impl.h.sav 2025-07-31 13:34:46.411242000 -0700 +++ sys/kgssapi/gssapi_impl.h 2025-07-31 13:35:11.717676000 -0700 @@ -78,5 +78,5 @@ extern void kgss_delete_context(gss_ctx_id_t ctx, gss_ extern const char *kgss_find_mech_by_oid(const gss_OID oid); extern gss_ctx_id_t kgss_create_context(gss_OID mech_type); extern void kgss_delete_context(gss_ctx_id_t ctx, gss_buffer_t output_token); -extern OM_uint32 kgss_transfer_context(gss_ctx_id_t ctx); +extern OM_uint32 kgss_transfer_context(gss_ctx_id_t ctx, void *lctx); extern void kgss_copy_buffer(const gss_buffer_t from, gss_buffer_t to); --- sys/kgssapi/gss_accept_sec_context.c.sav 2025-07-31 13:36:34.585391000 -0700 +++ sys/kgssapi/gss_accept_sec_context.c 2025-08-01 07:23:29.409219000 -0700 @@ -138,7 +138,137 @@ OM_uint32 gss_accept_sec_context(OM_uint32 *minor_stat * etc.) to the kernel implementation. */ if (res.major_status == GSS_S_COMPLETE) - res.major_status = kgss_transfer_context(ctx); + res.major_status = kgss_transfer_context(ctx, NULL); return (res.major_status); } + +OM_uint32 gss_accept_sec_context_plus(OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + const gss_cred_id_t acceptor_cred_handle, + const gss_buffer_t input_token, + const gss_channel_bindings_t input_chan_bindings, + gss_name_t *src_name, + gss_OID *mech_type, + gss_buffer_t output_token, + OM_uint32 *ret_flags, + OM_uint32 *time_rec, + gss_cred_id_t *delegated_cred_handle) +{ + struct accept_sec_context_plus_res res; + struct accept_sec_context_plus_args args; + gss_krb5_lucid_context_v1_t lucid; + enum clnt_stat stat; + gss_ctx_id_t ctx = *context_handle; + gss_name_t name; + gss_cred_id_t cred; + CLIENT *cl; + + cl = kgss_gssd_client(); + if (cl == NULL) { + *minor_status = 0; + return (GSS_S_FAILURE); + } + + if (ctx) + args.ctx = ctx->handle; + else + args.ctx = 0; + if (acceptor_cred_handle) + args.cred = acceptor_cred_handle->handle; + else + args.cred = 0; + args.input_token = *input_token; + args.input_chan_bindings = input_chan_bindings; + + bzero(&res, sizeof(res)); + stat = gssd_accept_sec_context_plus_1(&args, &res, cl); + CLNT_RELEASE(cl); + if (stat != RPC_SUCCESS) { + *minor_status = stat; + return (GSS_S_FAILURE); + } + + if (res.major_status != GSS_S_COMPLETE + && res.major_status != GSS_S_CONTINUE_NEEDED) { + *minor_status = res.minor_status; + xdr_free((xdrproc_t) xdr_accept_sec_context_res, &res); + return (res.major_status); + } + + *minor_status = res.minor_status; + + if (!ctx) { + ctx = kgss_create_context(res.mech_type); + if (!ctx) { + xdr_free((xdrproc_t) xdr_accept_sec_context_res, &res); + *minor_status = 0; + return (GSS_S_BAD_MECH); + } + } + *context_handle = ctx; + + ctx->handle = res.ctx; + name = malloc(sizeof(struct _gss_name_t), M_GSSAPI, M_WAITOK); + name->handle = res.src_name; + if (src_name) { + *src_name = name; + } else { + OM_uint32 junk; + gss_release_name(&junk, &name); + } + if (mech_type) + *mech_type = KGSS_MECH_TYPE(ctx); + kgss_copy_buffer(&res.output_token, output_token); + if (ret_flags) + *ret_flags = res.ret_flags; + if (time_rec) + *time_rec = res.time_rec; + cred = malloc(sizeof(struct _gss_cred_id_t), M_GSSAPI, M_WAITOK); + cred->handle = res.delegated_cred_handle; + if (delegated_cred_handle) { + *delegated_cred_handle = cred; + } else { + OM_uint32 junk; + gss_release_cred(&junk, &cred); + } + + /* + * If the context establishment is complete, export it from + * userland and hand the result (which includes key material + * etc.) to the kernel implementation. + */ + if (res.major_status == GSS_S_COMPLETE) { + lucid.initiate = res.initiate; + lucid.endtime = res.endtime; + lucid.send_seq = res.send_seq; + lucid.recv_seq = res.recv_seq; + lucid.protocol = res.protocol; + if (res.protocol == 0) { + lucid.rfc1964_kd.sign_alg = res.rfc_sign; + lucid.rfc1964_kd.seal_alg = res.rfc_seal; + lucid.rfc1964_kd.ctx_key.type = res.ctx_type; + lucid.rfc1964_kd.ctx_key.length = res.ctx_key.length; + lucid.rfc1964_kd.ctx_key.data = res.ctx_key.value; + } else if (res.protocol == 1) { + lucid.cfx_kd.have_acceptor_subkey = res.have_subkey; + lucid.cfx_kd.ctx_key.type = res.ctx_type; + lucid.cfx_kd.ctx_key.length = res.ctx_key.length; + lucid.cfx_kd.ctx_key.data = res.ctx_key.value; + lucid.cfx_kd.acceptor_subkey.type = res.subkey_type; + lucid.cfx_kd.acceptor_subkey.length = + res.subkey_key.length; + lucid.cfx_kd.acceptor_subkey.data = + res.subkey_key.value; + } else { + res.major_status = GSS_S_FAILURE; + } + if (res.major_status == GSS_S_COMPLETE) + res.major_status = kgss_transfer_context(ctx, &lucid); +printf("krb5_import: initiate=%d endtime=%d send_seq=%ld recv_seq=%ld proto=%d\n", res.initiate, res.endtime, res.send_seq, res.recv_seq, res.protocol); + } + + xdr_free((xdrproc_t) xdr_accept_sec_context_res, &res); + + return (res.major_status); +} --- sys/rpc/rpcsec_gss/rpcsec_gss.c.sav 2025-08-01 08:49:31.667000000 -0700 +++ sys/rpc/rpcsec_gss/rpcsec_gss.c 2025-08-01 08:48:25.095100000 -0700 @@ -746,6 +746,7 @@ rpc_gss_init(AUTH *auth, rpc_gss_options_ret_t *option struct rpc_callextra ext; gss_OID mech_oid; gss_OID_set mechlist; + static enum krb_imp my_krb_imp = KRBIMP_UNKNOWN; rpc_gss_log_debug("in rpc_gss_refresh()"); @@ -852,6 +853,14 @@ rpc_gss_init(AUTH *auth, rpc_gss_options_ret_t *option goto out; } + if (my_krb_imp == KRBIMP_UNKNOWN) { + maj_stat = gss_supports_lucid(&min_stat, NULL); + if (maj_stat == GSS_S_COMPLETE) + my_krb_imp = KRBIMP_MIT; + else + my_krb_imp = KRBIMP_HESIOD1; + } + /* GSS context establishment loop. */ memset(&recv_token, 0, sizeof(recv_token)); memset(&gr, 0, sizeof(gr)); @@ -862,20 +871,38 @@ rpc_gss_init(AUTH *auth, rpc_gss_options_ret_t *option for (;;) { crsave = td->td_ucred; td->td_ucred = gd->gd_ucred; - maj_stat = gss_init_sec_context(&min_stat, - gd->gd_options.my_cred, - &gd->gd_ctx, - name, - gd->gd_mech, - gd->gd_options.req_flags, - gd->gd_options.time_req, - gd->gd_options.input_channel_bindings, - recv_tokenp, - &gd->gd_mech, /* used mech */ - &send_token, - &options_ret->ret_flags, - &options_ret->time_req); +printf("gd_mech=%p\n", gd->gd_mech); + if (my_krb_imp == KRBIMP_MIT) + maj_stat = gss_init_sec_context_plus(&min_stat, + gd->gd_options.my_cred, + &gd->gd_ctx, + name, + gd->gd_mech, + gd->gd_options.req_flags, + gd->gd_options.time_req, + gd->gd_options.input_channel_bindings, + recv_tokenp, + &gd->gd_mech, /* used mech */ + &send_token, + &options_ret->ret_flags, + &options_ret->time_req); + else + maj_stat = gss_init_sec_context(&min_stat, + gd->gd_options.my_cred, + &gd->gd_ctx, + name, + gd->gd_mech, + gd->gd_options.req_flags, + gd->gd_options.time_req, + gd->gd_options.input_channel_bindings, + recv_tokenp, + &gd->gd_mech, /* used mech */ + &send_token, + &options_ret->ret_flags, + &options_ret->time_req); td->td_ucred = crsave; +printf("aft gss_init gd_mech=%p\n", gd->gd_mech); +printf("aft gss_init maj=0x%x min=%d\n", maj_stat, min_stat); /* * Free the token which we got from the server (if --- sys/rpc/rpcsec_gss/rpcsec_gss_int.h.sav 2025-08-01 08:38:06.516532000 -0700 +++ sys/rpc/rpcsec_gss/rpcsec_gss_int.h 2025-08-01 08:41:13.861239000 -0700 @@ -73,6 +73,12 @@ struct rpc_gss_init_res { /* Maximum sequence number value. */ #define MAXSEQ 0x80000000 +enum krb_imp { + KRBIMP_UNKNOWN, + KRBIMP_HESIOD1, + KRBIMP_MIT +}; + /* Prototypes. */ __BEGIN_DECLS --- sys/rpc/rpcsec_gss/svc_rpcsec_gss.c.sav 2025-08-01 08:50:21.724849000 -0700 +++ sys/rpc/rpcsec_gss/svc_rpcsec_gss.c 2025-08-01 08:56:44.902388000 -0700 @@ -925,9 +925,19 @@ svc_rpc_gss_accept_sec_context(struct svc_rpc_gss_clie OM_uint32 maj_stat = 0, min_stat = 0, ret_flags; OM_uint32 cred_lifetime; struct svc_rpc_gss_svc_name *sname; + static enum krb_imp my_krb_imp = KRBIMP_UNKNOWN; rpc_gss_log_debug("in svc_rpc_gss_accept_context()"); + if (my_krb_imp == KRBIMP_UNKNOWN) { + maj_stat = gss_supports_lucid(&min_stat, NULL); + if (maj_stat == GSS_S_COMPLETE) + my_krb_imp = KRBIMP_MIT; + else + my_krb_imp = KRBIMP_HESIOD1; + min_stat = 0; + } + /* Deserialize arguments. */ memset(&recv_tok, 0, sizeof(recv_tok)); @@ -949,18 +959,33 @@ svc_rpc_gss_accept_sec_context(struct svc_rpc_gss_clie if (sname->sn_program == rqst->rq_prog && sname->sn_version == rqst->rq_vers) { retry: - gr->gr_major = gss_accept_sec_context( - &gr->gr_minor, - &client->cl_ctx, - sname->sn_cred, - &recv_tok, - GSS_C_NO_CHANNEL_BINDINGS, - &client->cl_cname, - &mech, - &gr->gr_token, - &ret_flags, - &cred_lifetime, - &client->cl_creds); + if (my_krb_imp == KRBIMP_MIT) + gr->gr_major = + gss_accept_sec_context_plus( + &gr->gr_minor, + &client->cl_ctx, + sname->sn_cred, + &recv_tok, + GSS_C_NO_CHANNEL_BINDINGS, + &client->cl_cname, + &mech, + &gr->gr_token, + &ret_flags, + &cred_lifetime, + &client->cl_creds); + else + gr->gr_major = gss_accept_sec_context( + &gr->gr_minor, + &client->cl_ctx, + sname->sn_cred, + &recv_tok, + GSS_C_NO_CHANNEL_BINDINGS, + &client->cl_cname, + &mech, + &gr->gr_token, + &ret_flags, + &cred_lifetime, + &client->cl_creds); if (gr->gr_major == GSS_S_CREDENTIALS_EXPIRED) { /*home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAM5tNy6kRjUeJUZwmWSnC_kupAaKrqxn5aXR76p_CtWFEu9bvQ>
