Page MenuHomeFreeBSD

D51731.id159929.diff
No OneTemporary

D51731.id159929.diff

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<NI_MAXHOST>;
};
+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 <dirent.h>
#include <err.h>
#include <errno.h>
-#ifndef WITHOUT_KERBEROS
#include <krb5.h>
-#endif
#include <netdb.h>
#include <pwd.h>
#include <signal.h>
@@ -53,6 +51,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>
@@ -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);
}

File Metadata

Mime Type
text/plain
Expires
Thu, Jul 23, 2:04 AM (6 h, 38 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35388235
Default Alt Text
D51731.id159929.diff (44 KB)

Event Timeline