diff --git a/sys/kgssapi/gss_accept_sec_context.c b/sys/kgssapi/gss_accept_sec_context.c --- a/sys/kgssapi/gss_accept_sec_context.c +++ b/sys/kgssapi/gss_accept_sec_context.c @@ -41,6 +41,11 @@ #include "gssd.h" #include "kgss_if.h" +/* + * This function should only be called when the gssd + * daemon running on the system is an old one that + * does not use gss_krb5_export_lucid_sec_context(). + */ OM_uint32 gss_accept_sec_context(OM_uint32 *minor_status, gss_ctx_id_t *context_handle, const gss_cred_id_t acceptor_cred_handle, @@ -138,7 +143,145 @@ * 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); +} + +/* + * This function should be called when the gssd daemon is + * one that uses gss_krb5_export_lucid_sec_context(). + * There is a lot of code common with + * gss_accept_sec_context(). However, the structures used + * are not the same and future changes may be needed for + * this one. As such, I have not factored out the common + * code. + * gss_supports_lucid() may be used to check to see if the + * gssd daemon uses gss_krb5_export_lucid_sec_context(). + */ +OM_uint32 gss_accept_sec_context_lucid_v1(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, + gss_buffer_t exported_name, + uid_t *uidp, + gid_t *gidp, + int *numgroups, + gid_t *groups) +{ + struct accept_sec_context_lucid_v1_res res; + struct accept_sec_context_lucid_v1_args args; + 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_lucid_v1_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) { + int i, n; + + /* First, get the unix credentials. */ + *uidp = res.uid; + *gidp = res.gid; + n = res.gidlist.gidlist_len; + if (n > *numgroups) + n = *numgroups; + for (i = 0; i < n; i++) + groups[i] = res.gidlist.gidlist_val[i]; + *numgroups = n; + + /* Next, get the exported_name. */ + kgss_copy_buffer(&res.exported_name, exported_name); + + /* Now, handle the lucid credential setup. */ + res.major_status = kgss_transfer_context(ctx, &res.lucid); + if (res.major_status != GSS_S_COMPLETE) + printf("gss_accept_sec_context_lucid_v1: " + "transfer failed\n"); + } + + xdr_free((xdrproc_t) xdr_accept_sec_context_res, &res); return (res.major_status); } diff --git a/sys/kgssapi/gss_impl.c b/sys/kgssapi/gss_impl.c --- a/sys/kgssapi/gss_impl.c +++ b/sys/kgssapi/gss_impl.c @@ -192,13 +192,19 @@ } 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)) { KGSS_CURVNET_RESTORE(); diff --git a/sys/kgssapi/gss_init_sec_context.c b/sys/kgssapi/gss_init_sec_context.c --- a/sys/kgssapi/gss_init_sec_context.c +++ b/sys/kgssapi/gss_init_sec_context.c @@ -42,6 +42,11 @@ #include "gssd.h" #include "kgss_if.h" +/* + * This function should only be called when the gssd + * daemon running on the system is an old one that + * does not use gss_krb5_export_lucid_sec_context(). + */ OM_uint32 gss_init_sec_context(OM_uint32 * minor_status, const gss_cred_id_t initiator_cred_handle, @@ -133,7 +138,145 @@ * 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_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); +} + +/* + * This function should be called when the gssd daemon is + * one that uses gss_krb5_export_lucid_sec_context(). + * There is a lot of code common with + * gss_init_sec_context(). However, the structures used + * are not the same and future changes may be needed for + * this one. As such, I have not factored out the common + * code. + * gss_supports_lucid() may be used to check to see if the + * gssd daemon uses gss_krb5_export_lucid_sec_context(). + */ +OM_uint32 +gss_init_sec_context_lucid_v1(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_lucid_v1_res res; + struct init_sec_context_lucid_v1_args args; + 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_lucid_v1_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_lucid_v1_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_lucid_v1_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, &res.lucid); + if (res.major_status != GSS_S_COMPLETE) + printf("gss_init_sec_context_lucid_v1: " + "transfer failed\n"); + } + + xdr_free((xdrproc_t) xdr_init_sec_context_lucid_v1_res, &res); return (res.major_status); } diff --git a/sys/kgssapi/gssapi.h b/sys/kgssapi/gssapi.h --- a/sys/kgssapi/gssapi.h +++ b/sys/kgssapi/gssapi.h @@ -422,6 +422,28 @@ OM_uint32 * /* time_rec */ ); +OM_uint32 gss_init_sec_context_lucid_v1 + (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_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 +459,26 @@ gss_cred_id_t * /* delegated_cred_handle */ ); +OM_uint32 gss_accept_sec_context_lucid_v1 + (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 */ + gss_buffer_t, /* exported_name */ + uid_t *, /* Unix cred */ + gid_t *, + int *, /* Number of groups */ + gid_t * /* groups list */ + ); + OM_uint32 gss_delete_sec_context (OM_uint32 *, /* minor_status */ gss_ctx_id_t *, /* context_handle */ diff --git a/sys/kgssapi/gssapi_impl.h b/sys/kgssapi/gssapi_impl.h --- a/sys/kgssapi/gssapi_impl.h +++ b/sys/kgssapi/gssapi_impl.h @@ -78,5 +78,5 @@ 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); diff --git a/sys/kgssapi/gssd.x b/sys/kgssapi/gssd.x --- a/sys/kgssapi/gssd.x +++ b/sys/kgssapi/gssd.x @@ -48,6 +48,21 @@ typedef uint64_t gssd_cred_id_t; typedef uint64_t gssd_name_t; +struct kgss_lucid_desc { + 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_res { uint32_t major_status; uint32_t minor_status; @@ -70,6 +85,29 @@ gss_buffer_desc input_token; }; +struct init_sec_context_lucid_v1_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; + kgss_lucid_desc lucid; +}; + +struct init_sec_context_lucid_v1_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; @@ -89,6 +127,30 @@ gss_channel_bindings_t input_chan_bindings; }; +struct accept_sec_context_lucid_v1_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; + kgss_lucid_desc lucid; + gss_buffer_desc exported_name; + uint32_t uid; + uint32_t gid; + uint32_t gidlist<>; +}; + +struct accept_sec_context_lucid_v1_args { + gssd_ctx_id_t ctx; + gssd_cred_id_t cred; + gss_buffer_desc input_token; + gss_channel_bindings_t input_chan_bindings; +}; + struct delete_sec_context_res { uint32_t major_status; uint32_t minor_status; @@ -101,7 +163,8 @@ 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 +292,11 @@ char ip_addr; }; +struct supports_lucid_res { + uint32_t major_status; + uint32_t vers; +}; + program GSSD { version GSSDVERS { void GSSD_NULL(void) = 0; @@ -274,5 +342,14 @@ ip_to_dns_res GSSD_IP_TO_DNS(ip_to_dns_args) = 14; + + init_sec_context_lucid_v1_res + GSSD_INIT_SEC_CONTEXT_LUCID_V1(init_sec_context_lucid_v1_args) = 15; + + accept_sec_context_lucid_v1_res + GSSD_ACCEPT_SEC_CONTEXT_LUCID_V1(accept_sec_context_lucid_v1_args) = 16; + + supports_lucid_res + GSSD_SUPPORTS_LUCID(void) = 17; } = 1; } = 0x40677373; diff --git a/sys/kgssapi/krb5/krb5_mech.c b/sys/kgssapi/krb5/krb5_mech.c --- a/sys/kgssapi/krb5/krb5_mech.c +++ b/sys/kgssapi/krb5/krb5_mech.c @@ -217,6 +217,18 @@ *to = NULL; } +static void +copy_lucid_key(gss_buffer_desc *from, uint32_t type, struct krb5_keyblock *to) +{ + + to->kk_type = 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->value, from->length); + } +} + /* * Return non-zero if we are initiator. */ @@ -401,6 +413,70 @@ mtx_init(&kc->kc_lock, "krb5 gss lock", NULL, MTX_DEF); } +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; + kgss_lucid_desc *lctx = (kgss_lucid_desc *)context_token; + OM_uint32 res; + + kc->kc_more_flags = 0; + if (lctx->protocol == 0) { + kc->kc_cksumtype = lctx->rfc_sign; + kc->kc_keytype = lctx->rfc_seal; + copy_lucid_key(&lctx->ctx_key, lctx->ctx_type, + &kc->kc_keyblock); + } else if (lctx->protocol == 1) { + if (lctx->have_subkey != 0) { + if (lctx->initiate != 0) + copy_lucid_key(&lctx->subkey_key, + lctx->subkey_type, + &kc->kc_remote_subkey); + else + copy_lucid_key(&lctx->subkey_key, + lctx->subkey_type, + &kc->kc_local_subkey); + kc->kc_cksumtype = lctx->subkey_type; + kc->kc_keytype = lctx->subkey_type; + kc->kc_more_flags |= ACCEPTOR_SUBKEY; + } else { + if (lctx->initiate != 0) + copy_lucid_key(&lctx->ctx_key, + lctx->ctx_type, + &kc->kc_remote_subkey); + else + copy_lucid_key(&lctx->ctx_key, + lctx->ctx_type, + &kc->kc_local_subkey); + kc->kc_cksumtype = lctx->ctx_type; + kc->kc_keytype = lctx->ctx_type; + } + } else { + return (GSS_S_DEFECTIVE_TOKEN); + } + 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_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, @@ -413,6 +489,10 @@ 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 */ diff --git a/sys/rpc/rpcsec_gss/rpcsec_gss.c b/sys/rpc/rpcsec_gss/rpcsec_gss.c --- a/sys/rpc/rpcsec_gss/rpcsec_gss.c +++ b/sys/rpc/rpcsec_gss/rpcsec_gss.c @@ -746,6 +746,7 @@ 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 @@ 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,19 +871,34 @@ 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); + if (my_krb_imp == KRBIMP_MIT) + maj_stat = gss_init_sec_context_lucid_v1(&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; /* diff --git a/sys/rpc/rpcsec_gss/rpcsec_gss_int.h b/sys/rpc/rpcsec_gss/rpcsec_gss_int.h --- a/sys/rpc/rpcsec_gss/rpcsec_gss_int.h +++ b/sys/rpc/rpcsec_gss/rpcsec_gss_int.h @@ -73,6 +73,12 @@ /* Maximum sequence number value. */ #define MAXSEQ 0x80000000 +enum krb_imp { + KRBIMP_UNKNOWN, + KRBIMP_HESIOD1, + KRBIMP_MIT +}; + /* Prototypes. */ __BEGIN_DECLS diff --git a/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c b/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c --- a/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c +++ b/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c @@ -925,9 +925,29 @@ OM_uint32 maj_stat = 0, min_stat = 0, ret_flags; OM_uint32 cred_lifetime; struct svc_rpc_gss_svc_name *sname; + gss_buffer_desc export_name; + rpc_gss_ucred_t *uc = &client->cl_ucred; + int numgroups; + 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; + } + + if (my_krb_imp == KRBIMP_MIT) { + uc->uid = 65534; + uc->gid = 65534; + uc->gidlist = client->cl_gid_storage; + numgroups = NGROUPS; + } + /* Deserialize arguments. */ memset(&recv_tok, 0, sizeof(recv_tok)); @@ -949,18 +969,38 @@ 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_lucid_v1( + &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, + &export_name, + &uc->uid, + &uc->gid, + &numgroups, + &uc->gidlist[0]); + 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) { /* @@ -982,18 +1022,37 @@ return (FALSE); } } else { - gr->gr_major = gss_accept_sec_context( - &gr->gr_minor, - &client->cl_ctx, - client->cl_sname->sn_cred, - &recv_tok, - GSS_C_NO_CHANNEL_BINDINGS, - &client->cl_cname, - &mech, - &gr->gr_token, - &ret_flags, - &cred_lifetime, - NULL); + if (my_krb_imp == KRBIMP_MIT) + gr->gr_major = gss_accept_sec_context_lucid_v1( + &gr->gr_minor, + &client->cl_ctx, + client->cl_sname->sn_cred, + &recv_tok, + GSS_C_NO_CHANNEL_BINDINGS, + &client->cl_cname, + &mech, + &gr->gr_token, + &ret_flags, + &cred_lifetime, + NULL, + &export_name, + &uc->uid, + &uc->gid, + &numgroups, + &uc->gidlist[0]); + else + gr->gr_major = gss_accept_sec_context( + &gr->gr_minor, + &client->cl_ctx, + client->cl_sname->sn_cred, + &recv_tok, + GSS_C_NO_CHANNEL_BINDINGS, + &client->cl_cname, + &mech, + &gr->gr_token, + &ret_flags, + &cred_lifetime, + NULL); } sx_xunlock(&svc_rpc_gss_lock); @@ -1009,8 +1068,12 @@ rpc_gss_log_status("accept_sec_context", client->cl_mech, gr->gr_major, gr->gr_minor); client->cl_state = CLIENT_STALE; + if (my_krb_imp == KRBIMP_MIT) + uc->gidlen = 0; return (TRUE); } + if (my_krb_imp == KRBIMP_MIT) + uc->gidlen = numgroups; gr->gr_handle.value = &client->cl_id; gr->gr_handle.length = sizeof(client->cl_id); @@ -1022,8 +1085,6 @@ client->cl_done_callback = FALSE; if (gr->gr_major == GSS_S_COMPLETE) { - gss_buffer_desc export_name; - /* * Change client expiration time to be near when the * client creds expire (or 24 hours if we can't figure @@ -1046,8 +1107,10 @@ */ client->cl_rawcred.version = RPCSEC_GSS_VERSION; rpc_gss_oid_to_mech(mech, &client->cl_rawcred.mechanism); - maj_stat = gss_export_name(&min_stat, client->cl_cname, - &export_name); + maj_stat = GSS_S_COMPLETE; + if (my_krb_imp != KRBIMP_MIT) + maj_stat = gss_export_name(&min_stat, client->cl_cname, + &export_name); if (maj_stat != GSS_S_COMPLETE) { rpc_gss_log_status("gss_export_name", client->cl_mech, maj_stat, min_stat); @@ -1068,7 +1131,8 @@ * Use gss_pname_to_uid to map to unix creds. For * kerberos5, this uses krb5_aname_to_localname. */ - svc_rpc_gss_build_ucred(client, client->cl_cname); + if (my_krb_imp != KRBIMP_MIT) + svc_rpc_gss_build_ucred(client, client->cl_cname); svc_rpc_gss_set_flavor(client); gss_release_name(&min_stat, &client->cl_cname); diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile --- a/usr.sbin/Makefile +++ b/usr.sbin/Makefile @@ -140,7 +140,9 @@ SUBDIR.${MK_FLOPPY}+= fdread SUBDIR.${MK_FLOPPY}+= fdwrite SUBDIR.${MK_FREEBSD_UPDATE}+= freebsd-update +.if ${MK_KERBEROS_SUPPORT} != "no" SUBDIR.${MK_GSSAPI}+= gssd +.endif SUBDIR.${MK_GPIO}+= gpioctl SUBDIR.${MK_HYPERV}+= hyperv SUBDIR.${MK_INET6}+= ip6addrctl diff --git a/usr.sbin/gssd/Makefile b/usr.sbin/gssd/Makefile --- a/usr.sbin/gssd/Makefile +++ b/usr.sbin/gssd/Makefile @@ -9,18 +9,13 @@ 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 -.endif -.else -CFLAGS+= -DWITHOUT_KERBEROS +LIBADD= gssapi krb5 roken .endif CLEANFILES= gssd_svc.c gssd_xdr.c gssd.h diff --git a/usr.sbin/gssd/gssd.c b/usr.sbin/gssd/gssd.c --- a/usr.sbin/gssd/gssd.c +++ b/usr.sbin/gssd/gssd.c @@ -39,9 +39,7 @@ #include #include #include -#ifndef WITHOUT_KERBEROS #include -#endif #include #include #include @@ -53,6 +51,9 @@ #include #include #include +#ifdef MK_MITKRB5 +#include +#endif #include #include @@ -77,7 +78,6 @@ static char pref_realm[1024]; static int verbose; static int hostbased_initiator_cred; -#ifndef WITHOUT_KERBEROS /* 1.2.752.43.13.14 */ static gss_OID_desc gss_krb5_set_allowable_enctypes_x_desc = {6, (void *) "\x2a\x85\x70\x2b\x0d\x0e"}; @@ -87,16 +87,13 @@ {9, (void *) "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02" }; static gss_OID GSS_KRB5_MECH_OID_X = &gss_krb5_mech_oid_x_desc; -#endif static void gssd_load_mech(void); static int find_ccache_file(const char *, uid_t, char *); static int is_a_valid_tgt_cache(const char *, uid_t, int *, time_t *); static void gssd_verbose_out(const char *, ...); -#ifndef WITHOUT_KERBEROS static krb5_error_code gssd_get_cc_from_keytab(const char *); static OM_uint32 gssd_get_user_cred(OM_uint32 *, uid_t, gss_cred_id_t *); -#endif void gssd_terminate(int); extern void gssd_1(struct svc_req *rqstp, SVCXPRT *transp); @@ -128,32 +125,22 @@ debug_level++; break; case 'h': -#ifndef WITHOUT_KERBEROS /* * Enable use of a host based initiator credential * in the default keytab file. */ hostbased_initiator_cred = 1; -#else - errx(1, "This option not available when built" - " without MK_KERBEROS\n"); -#endif break; case 'v': verbose = 1; break; case 's': -#ifndef WITHOUT_KERBEROS /* * Set the directory search list. This enables use of * find_ccache_file() to search the directories for a * suitable credentials cache file. */ strlcpy(ccfile_dirlist, optarg, sizeof(ccfile_dirlist)); -#else - errx(1, "This option not available when built" - " without MK_KERBEROS\n"); -#endif break; case 'c': /* @@ -335,6 +322,7 @@ 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) { @@ -344,12 +332,10 @@ 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 && @@ -458,6 +444,35 @@ 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_lucid_v1_1_svc(init_sec_context_lucid_v1_args *argp, + init_sec_context_lucid_v1_res *result, struct svc_req *rqstp) +{ + + gssd_verbose_out("gssd_init_sec_context_lucid_v1: Heimdal\n"); + result->major_status = GSS_S_UNAVAILABLE; + return (TRUE); +} + +bool_t +gssd_accept_sec_context_lucid_v1_1_svc(accept_sec_context_lucid_v1_args *argp, + accept_sec_context_lucid_v1_res *result, struct svc_req *rqstp) +{ + + gssd_verbose_out("gssd_accept_sec_context_lucid_v1: 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) { @@ -508,6 +523,446 @@ 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: 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: MIT\n"); + result->major_status = GSS_S_UNAVAILABLE; + return (TRUE); +} + +bool_t +gssd_init_sec_context_lucid_v1_1_svc(init_sec_context_lucid_v1_args *argp, + init_sec_context_lucid_v1_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; + gss_buffer_desc principal_desc; + char enctype[sizeof(uint32_t)]; + int key_enctype; + OM_uint32 maj_stat; + + 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) { + /* + * Just to keep the bogus "elements" pointer + * from core dumping the daemon when linked to MIT + * libraries. For some reason, the "elements" pointer + * in actual_mech_type cannot be read. + */ + result->actual_mech_type = GSS_KRB5_MECH_OID_X; + } + + 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); + } + + 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_delete_resource(result->ctx); + if (result->major_status == GSS_S_COMPLETE && + lctx != NULL) { + result->lucid.initiate = lctx->initiate; + result->lucid.endtime = lctx->endtime; + result->lucid.send_seq = lctx->send_seq; + result->lucid.recv_seq = lctx->recv_seq; + result->lucid.protocol = lctx->protocol; + if (lctx->protocol == 0) { + result->lucid.rfc_sign = + lctx->rfc1964_kd.sign_alg; + result->lucid.rfc_seal = + lctx->rfc1964_kd.seal_alg; + result->lucid.ctx_type = + lctx->rfc1964_kd.ctx_key.type; + result->lucid.ctx_key.length = + lctx->rfc1964_kd.ctx_key.length; + result->lucid.ctx_key.value = + mem_alloc(result->lucid.ctx_key.length); + memcpy(result->lucid.ctx_key.value, + lctx->rfc1964_kd.ctx_key.data, + result->lucid.ctx_key.length); + } else if (lctx->protocol == 1) { + result->lucid.have_subkey = + lctx->cfx_kd.have_acceptor_subkey; + result->lucid.ctx_type = + lctx->cfx_kd.ctx_key.type; + result->lucid.ctx_key.length = + lctx->cfx_kd.ctx_key.length; + result->lucid.ctx_key.value = + mem_alloc(result->lucid.ctx_key.length); + memcpy(result->lucid.ctx_key.value, + lctx->cfx_kd.ctx_key.data, + result->lucid.ctx_key.length); + if (result->lucid.have_subkey != 0) { + result->lucid.subkey_type = + lctx->cfx_kd.acceptor_subkey.type; + result->lucid.subkey_key.length = + lctx->cfx_kd.acceptor_subkey.length; + result->lucid.subkey_key.value = + mem_alloc( + result->lucid.subkey_key.length); + memcpy(result->lucid.subkey_key.value, + lctx->cfx_kd.acceptor_subkey.data, + result->lucid.subkey_key.length); + } else { + result->lucid.subkey_type = 0; + result->lucid.subkey_key.length = 0; + result->lucid.subkey_key.value = NULL; + } + } + (void)gss_krb5_free_lucid_sec_context(&min_stat, + (void *)lctx); + } else { + gssd_verbose_out("gss_krb5_export_lucid_set_context" + " failed: major=0x%x minor=%d lctx=%p\n", + result->major_status, result->minor_status, lctx); + } + } + + return (TRUE); +} + +/* + * Internal function to acquire unix credentials. + */ +static OM_uint32 +_gss_get_unix_cred(OM_uint32 *minor_stat, gss_name_t name, gss_OID mech, + uid_t *uidp, gid_t *gidp, int *numgroups, gid_t *groups) +{ + OM_uint32 major_stat; + uid_t uid; + char buf[1024], *bufp; + struct passwd pwd, *pw; + size_t buflen; + int error; + static size_t buflen_hint = 1024; + + major_stat = gss_pname_to_uid(minor_stat, name, mech, &uid); + if (major_stat == GSS_S_COMPLETE) { + *uidp = uid; + buflen = buflen_hint; + for (;;) { + pw = NULL; + bufp = buf; + if (buflen > sizeof(buf)) + bufp = malloc(buflen); + if (bufp == NULL) + break; + error = getpwuid_r(uid, &pwd, bufp, buflen, + &pw); + if (error != ERANGE) + break; + if (buflen > sizeof(buf)) + free(bufp); + buflen += 1024; + if (buflen > buflen_hint) + buflen_hint = buflen; + } + if (pw) { + *gidp = pw->pw_gid; + getgrouplist(pw->pw_name, pw->pw_gid, + groups, numgroups); + } else { + major_stat = GSS_S_FAILURE; + gssd_verbose_out("get_unix_cred: cannot find" + " passwd entry\n"); + } + if (bufp != NULL && buflen > sizeof(buf)) + free(bufp); + } else if (major_stat != GSS_S_UNAVAILABLE) { + gssd_verbose_out("gssd_pname_to_uid: failed major=0x%x" + " minor=%d\n", major_stat, *minor_stat); + } + return (major_stat); +} + +bool_t +gssd_accept_sec_context_lucid_v1_1_svc(accept_sec_context_lucid_v1_args *argp, + accept_sec_context_lucid_v1_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; + OM_uint32 min_stat; + + 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; + + /* Get the lucid context stuff. */ + result->major_status = gss_krb5_export_lucid_sec_context( + &result->minor_status, &ctx, 1, (void *)&lctx); + gssd_delete_resource(result->ctx); + if (result->major_status == GSS_S_COMPLETE && + lctx != NULL) { + result->lucid.initiate = lctx->initiate; + result->lucid.endtime = lctx->endtime; + result->lucid.send_seq = lctx->send_seq; + result->lucid.recv_seq = lctx->recv_seq; + result->lucid.protocol = lctx->protocol; + if (lctx->protocol == 0) { + result->lucid.rfc_sign = + lctx->rfc1964_kd.sign_alg; + result->lucid.rfc_seal = + lctx->rfc1964_kd.seal_alg; + result->lucid.ctx_type = + lctx->rfc1964_kd.ctx_key.type; + result->lucid.ctx_key.length = + lctx->rfc1964_kd.ctx_key.length; + result->lucid.ctx_key.value = + mem_alloc(result->lucid.ctx_key.length); + memcpy(result->lucid.ctx_key.value, + lctx->rfc1964_kd.ctx_key.data, + result->lucid.ctx_key.length); + } else if (lctx->protocol == 1) { + result->lucid.have_subkey = + lctx->cfx_kd.have_acceptor_subkey; + result->lucid.ctx_type = + lctx->cfx_kd.ctx_key.type; + result->lucid.ctx_key.length = + lctx->cfx_kd.ctx_key.length; + result->lucid.ctx_key.value = + mem_alloc(result->lucid.ctx_key.length); + memcpy(result->lucid.ctx_key.value, + lctx->cfx_kd.ctx_key.data, + result->lucid.ctx_key.length); + if (result->lucid.have_subkey != 0) { + result->lucid.subkey_type = + lctx->cfx_kd.acceptor_subkey.type; + result->lucid.subkey_key.length = + lctx->cfx_kd.acceptor_subkey.length; + result->lucid.subkey_key.value = + mem_alloc( + result->lucid.subkey_key.length); + memcpy(result->lucid.subkey_key.value, + lctx->cfx_kd.acceptor_subkey.data, + result->lucid.subkey_key.length); + } else { + result->lucid.subkey_type = 0; + result->lucid.subkey_key.length = 0; + result->lucid.subkey_key.value = NULL; + } + } + (void)gss_krb5_free_lucid_sec_context(&min_stat, + (void *)lctx); + } else { + gssd_verbose_out("gss_krb5_export_lucid_set_context" + " failed: major=0x%x minor=%d lctx=%p\n", + result->major_status, result->minor_status, lctx); + } + + /* Now, get the exported name. */ + if (result->major_status == GSS_S_COMPLETE) { + result->major_status = gss_export_name( + &result->minor_status, src_name, + &result->exported_name); + gssd_verbose_out("gssd_accept_sec_context (name):" + " done major=0x%x minor=%d\n", + result->major_status, result->minor_status); + } + + /* Finally, get the unix credentials. */ + if (result->major_status == GSS_S_COMPLETE) { + gid_t groups[NGROUPS]; + int i, len = NGROUPS; + OM_uint32 major_stat, minor_stat; + + major_stat = _gss_get_unix_cred(&minor_stat, + src_name, result->mech_type, + &result->uid, &result->gid, &len, groups); + if (major_stat == GSS_S_COMPLETE) { + result->gidlist.gidlist_len = len; + result->gidlist.gidlist_val = + mem_alloc(len * sizeof(uint32_t)); + /* + * Just in case + * sizeof(gid_t) != sizeof(uint32_t). + */ + for (i = 0; i < len; i++) + result->gidlist.gidlist_val[i] = + groups[i]; + } else { + result->gid = 65534; + result->gidlist.gidlist_len = 0; + result->gidlist.gidlist_val = NULL; + gssd_verbose_out("gssd_pname_to_uid: mapped" + " to uid=%d, but no groups\n", + (int)result->uid); + } + } + } + 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) @@ -758,11 +1213,9 @@ gss_cred_id_t cred; char ccname[PATH_MAX + 5 + 1], *cp, *cp2; int gotone; -#ifndef WITHOUT_KERBEROS gss_buffer_desc namebuf; uint32_t minstat; krb5_error_code kret; -#endif memset(result, 0, sizeof(*result)); if (argp->desired_name) { @@ -775,7 +1228,6 @@ } } -#ifndef WITHOUT_KERBEROS if (hostbased_initiator_cred != 0 && argp->desired_name != 0 && argp->uid == 0 && argp->cred_usage == GSS_C_INITIATE) { /* This is a host based initiator name in the keytab file. */ @@ -808,9 +1260,7 @@ result->major_status = GSS_S_FAILURE; return (TRUE); } - } else -#endif /* !WITHOUT_KERBEROS */ - if (ccfile_dirlist[0] != '\0' && argp->desired_name == 0) { + } else if (ccfile_dirlist[0] != '\0' && argp->desired_name == 0) { /* * For the "-s" case and no name provided as an * argument, search the directory list for an appropriate @@ -1054,7 +1504,6 @@ is_a_valid_tgt_cache(const char *filepath, uid_t uid, int *retrating, time_t *retexptime) { -#ifndef WITHOUT_KERBEROS krb5_context context; krb5_principal princ; krb5_ccache ccache; @@ -1154,12 +1603,8 @@ *retexptime = exptime; } return (ret); -#else /* WITHOUT_KERBEROS */ - return (0); -#endif /* !WITHOUT_KERBEROS */ } -#ifndef WITHOUT_KERBEROS /* * This function attempts to do essentially a "kinit -k" for the principal * name provided as the argument, so that there will be a TGT in the @@ -1262,15 +1707,12 @@ gss_release_oid_set(&min_stat, &mechlist); return (maj_stat); } -#endif /* !WITHOUT_KERBEROS */ void gssd_terminate(int sig __unused) { -#ifndef WITHOUT_KERBEROS if (hostbased_initiator_cred != 0) unlink(GSSD_CREDENTIAL_CACHE_FILE); -#endif exit(0); }