Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F163319839
D51731.id159929.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
44 KB
Referenced Files
None
Subscribers
None
D51731.id159929.diff
View Options
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
Details
Attached
Mime Type
text/plain
Expires
Thu, Jul 23, 2:04 AM (12 h, 15 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35388235
Default Alt Text
D51731.id159929.diff (44 KB)
Attached To
Mode
D51731: kgssapi: Fix the kgssapi so that it can use MIT Kerberos
Attached
Detach File
Event Timeline
Log In to Comment