summaryrefslogtreecommitdiffstats
path: root/utils/gssd
diff options
context:
space:
mode:
Diffstat (limited to 'utils/gssd')
-rw-r--r--utils/gssd/context.c203
-rw-r--r--utils/gssd/gssd_proc.c96
-rw-r--r--utils/gssd/krb5_util.c10
3 files changed, 213 insertions, 96 deletions
diff --git a/utils/gssd/context.c b/utils/gssd/context.c
index 08979f3..8f2f359 100644
--- a/utils/gssd/context.c
+++ b/utils/gssd/context.c
@@ -42,6 +42,10 @@
#include "err_util.h"
#include "context.h"
+#ifdef HAVE_SPKM3_H
+#include <spkm3.h>
+#endif
+
/* spkm3 seems to actually want it this big, yipes. */
#define MAX_CTX_LEN 4096
@@ -133,49 +137,6 @@ typedef struct _krb5_gss_ctx_id_rec {
#endif /* KRB5_VERSION */
#endif /* HAVE_KRB5 */
-/* XXX We have the same issue as above. We can require SPKM-3 source
- * at the time we compile gssd, or copy the context structure definitions
- * here.
- */
-
-/* structure typedefs */
-
-typedef struct spkm3_ctx_id_t {
- int length;
- unsigned char *data;
-} spkm3_ctx_id,
- *spkm3_ctx_id_t;
-
-/* first pass at spkm3 context. will add a bunch of stuff .... */
-
-typedef struct spkm3_gss_ctx_id_desc_t {
- spkm3_ctx_id ctx_id; /* per spkm token contextid */
- int established;
- int qop; /* negotiated qop */
- gss_OID mech_used;
- OM_uint32 ret_flags;
- OM_uint32 req_flags;
- /* DH should be abstracted to an EVP_ struct able to hold
- * various kalg results */
- /* XXX The following is defined as "DH *dh" in the original
- * header we're gonna cheat and use "void *dh" here. */
- void *dh;
- gss_buffer_desc share_key;
- /* derived keys are result from applying the owf_alg to the
- * shared key - see spkm3_derive_supkey */
- gss_buffer_desc derived_conf_key;
- gss_buffer_desc derived_integ_key;
- /* openssl NID's of the negotiated algorithms */
- int keyestb_alg; /* key establishment */
- int owf_alg; /* one way function */
- int intg_alg; /* integrity */
- int conf_alg; /* privacy */
- /* der encoded REQ_TOKEN reqcontets and length */
- unsigned char *der_reqcontents;
- int der_req_len;
-} spkm3_gss_ctx_id_desc;
-
-
/* adapted from mit kerberos 5 ../lib/gssapi/mechglue/mglueP.h
* this is what gets passed around when the mechglue code is enabled : */
typedef struct gss_union_ctx_id_t {
@@ -292,6 +253,7 @@ prepare_krb5_rfc_cfx_buffer(gss_krb5_lucid_context_v1_t *lctx,
return -1;
}
+
static int
serialize_krb5_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf)
{
@@ -303,7 +265,7 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf)
printerr(2, "DEBUG: serialize_krb5_ctx: lucid version!\n");
maj_stat = gss_krb5_export_lucid_sec_context(&min_stat, &ctx,
- 1, &return_ctx);
+ 1, &return_ctx);
if (maj_stat != GSS_S_COMPLETE)
goto out_err;
@@ -392,63 +354,140 @@ out_err:
#endif /* HAVE_KRB5 */
-/* ANDROS: need to determine which fields of the spkm3_gss_ctx_id_desc_t
- * are needed in the kernel for get_mic, validate, wrap, unwrap, and destroy
- * and only export those fields to the kernel.
- */
+#ifdef HAVE_SPKM3_H
+/*
+ * Function: prepare_spkm3_ctx_buffer()
+ *
+ * Prepare spkm3 lucid context for the kernel
+ *
+ * buf->length should be:
+ *
+ * ctx_id 4 + 12
+ * qop 4
+ * mech_used 4 + 7
+ * ret_fl 4
+ * req_fl 4
+ * share 4 + key_len
+ * conf_alg 4 + oid_len
+ * d_conf_key 4 + key_len
+ * intg_alg 4 + oid_len
+ * d_intg_key 4 + key_len
+ * kyestb 4 + oid_len
+ * owl alg 4 + oid_len
+*/
static int
-serialize_spkm3_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf)
+prepare_spkm3_ctx_buffer(gss_spkm3_lucid_ctx_t *lctx, gss_buffer_desc *buf)
{
- spkm3_gss_ctx_id_desc *sctx = (spkm3_gss_ctx_id_desc *)ctx;
char *p, *end;
+ unsigned int buf_size = 0;
+
+ buf_size = lctx->ctx_id.length +
+ sizeof(lctx->ctx_id.length) + sizeof(lctx->qop) +
+ sizeof(lctx->mech_used.length) + lctx->mech_used.length +
+ sizeof(lctx->ret_flags) + sizeof(lctx->req_flags) +
+ sizeof(lctx->share_key.length) + lctx->share_key.length +
+ sizeof(lctx->conf_alg.length) + lctx->conf_alg.length +
+ sizeof(lctx->derived_conf_key.length) +
+ lctx->derived_conf_key.length +
+ sizeof(lctx->intg_alg.length) + lctx->intg_alg.length +
+ sizeof(lctx->derived_integ_key.length) +
+ lctx->derived_integ_key.length +
+ sizeof(lctx->keyestb_alg.length) + lctx->keyestb_alg.length +
+ sizeof(lctx->owf_alg.length) + lctx->owf_alg.length;
+
+ if (!(buf->value = calloc(1, buf_size)))
+ goto out_err;
+ p = buf->value;
+ end = buf->value + buf_size;
- printerr(1, "serialize_spkm3_ctx called\n");
+ if (write_buffer(&p, end, &lctx->ctx_id))
+ goto out_err;
- if (!(buf->value = calloc(1, MAX_CTX_LEN)))
+ if (WRITE_BYTES(&p, end, lctx->qop))
goto out_err;
- p = buf->value;
- end = buf->value + MAX_CTX_LEN;
-/* buf->length
-ctx_id 4 + 12
-qop 4
-mech_used 4 + 7
-ret_fl 4
-req_fl 4
-share 4 + 16
-conf_alg 4
-d_conf_key 4 + 0
-intg_alg 4
-d_intg_key 4 + 0
-kyestb 4
-owl alg 4
-*/
- if (write_buffer(&p, end, (gss_buffer_desc *)&sctx->ctx_id))
+
+ if (write_buffer(&p, end, &lctx->mech_used))
+ goto out_err;
+
+ if (WRITE_BYTES(&p, end, lctx->ret_flags))
+ goto out_err;
+
+ if (WRITE_BYTES(&p, end, lctx->req_flags))
+ goto out_err;
+
+ if (write_buffer(&p, end, &lctx->share_key))
+ goto out_err;
+
+ if (write_buffer(&p, end, &lctx->conf_alg))
goto out_err;
- if (WRITE_BYTES(&p, end, sctx->qop)) goto out_err;
- if (write_buffer(&p, end, (gss_buffer_desc *)sctx->mech_used)) goto out_err;
- if (WRITE_BYTES(&p, end, sctx->ret_flags)) goto out_err;
- if (WRITE_BYTES(&p, end, sctx->req_flags)) goto out_err;
- if (write_buffer(&p, end, &sctx->share_key))
+
+ if (write_buffer(&p, end, &lctx->derived_conf_key))
goto out_err;
- if (WRITE_BYTES(&p, end, sctx->conf_alg)) goto out_err;
- if (write_buffer(&p, end, &sctx->derived_conf_key))
+ if (write_buffer(&p, end, &lctx->intg_alg))
goto out_err;
- if (WRITE_BYTES(&p, end, sctx->intg_alg)) goto out_err;
- if (write_buffer(&p, end, &sctx->derived_integ_key))
+ if (write_buffer(&p, end, &lctx->derived_integ_key))
goto out_err;
- if (WRITE_BYTES(&p, end, sctx->keyestb_alg)) goto out_err;
- if (WRITE_BYTES(&p, end, sctx->owf_alg)) goto out_err;
+ if (write_buffer(&p, end, &lctx->keyestb_alg))
+ goto out_err;
+
+ if (write_buffer(&p, end, &lctx->owf_alg))
+ goto out_err;
buf->length = p - (char *)buf->value;
return 0;
out_err:
+ printerr(0, "ERROR: failed serializing spkm3 context for kernel\n");
if (buf->value) free(buf->value);
buf->length = 0;
+
+ return -1;
+}
+
+/* ANDROS: need to determine which fields of the spkm3_gss_ctx_id_desc_t
+ * are needed in the kernel for get_mic, validate, wrap, unwrap, and destroy
+ * and only export those fields to the kernel.
+ */
+static int
+serialize_spkm3_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf)
+{
+ OM_uint32 vers, ret, maj_stat, min_stat;
+ void *ret_ctx = 0;
+ gss_spkm3_lucid_ctx_t *lctx;
+
+ printerr(1, "serialize_spkm3_ctx called\n");
+
+ printerr(2, "DEBUG: serialize_spkm3_ctx: lucid version!\n");
+ maj_stat = gss_export_lucid_sec_context(&min_stat, ctx, 1, &ret_ctx);
+ if (maj_stat != GSS_S_COMPLETE)
+ goto out_err;
+
+ lctx = (gss_spkm3_lucid_ctx_t *)ret_ctx;
+
+ vers = lctx->version;
+ if (vers != 1) {
+ printerr(0, "ERROR: unsupported spkm3 context version %d\n",
+ vers);
+ goto out_err;
+ }
+ ret = prepare_spkm3_ctx_buffer(lctx, buf);
+
+ maj_stat = gss_free_lucid_sec_context(&min_stat, ctx, ret_ctx);
+
+ if (maj_stat != GSS_S_COMPLETE)
+ printerr(0, "WARN: failed to free lucid sec context\n");
+ if (ret)
+ goto out_err;
+ printerr(2, "DEBUG: serialize_spkm3_ctx: success\n");
+ return 0;
+
+out_err:
+ printerr(2, "DEBUG: serialize_spkm3_ctx: failed\n");
return -1;
}
+#endif /* HAVE_SPKM3_H */
int
serialize_context_for_kernel(gss_ctx_id_t ctx, gss_buffer_desc *buf)
@@ -457,8 +496,10 @@ serialize_context_for_kernel(gss_ctx_id_t ctx, gss_buffer_desc *buf)
if (g_OID_equal(&krb5oid, uctx->mech_type))
return serialize_krb5_ctx(uctx->internal_ctx_id, buf);
+#ifdef HAVE_SPKM3_H
else if (g_OID_equal(&spkm3oid, uctx->mech_type))
- return serialize_spkm3_ctx(uctx->internal_ctx_id, buf);
+ return serialize_spkm3_ctx(uctx, buf);
+#endif
else {
printerr(0, "ERROR: attempting to serialize context with "
"unknown mechanism oid\n");
diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c
index 788ecf1..78919b8 100644
--- a/utils/gssd/gssd_proc.c
+++ b/utils/gssd/gssd_proc.c
@@ -366,11 +366,16 @@ static int
do_downcall(int k5_fd, uid_t uid, struct authgss_private_data *pd,
gss_buffer_desc *context_token)
{
- char buf[2048];
- char *p = buf, *end = buf + 2048;
+ char *buf = NULL, *p = NULL, *end = NULL;
unsigned int timeout = 0; /* XXX decide on a reasonable value */
+ unsigned int buf_size = 0;
printerr(1, "doing downcall\n");
+ buf_size = sizeof(uid) + sizeof(timeout) + sizeof(pd->pd_seq_win) +
+ sizeof(pd->pd_ctx_hndl.length) + pd->pd_ctx_hndl.length +
+ sizeof(context_token->length) + context_token->length;
+ p = buf = malloc(buf_size);
+ end = buf + buf_size;
if (WRITE_BYTES(&p, end, uid)) goto out_err;
/* Not setting any timeout for now: */
@@ -380,8 +385,10 @@ do_downcall(int k5_fd, uid_t uid, struct authgss_private_data *pd,
if (write_buffer(&p, end, context_token)) goto out_err;
if (write(k5_fd, buf, p - buf) < p - buf) goto out_err;
+ if (buf) free(buf);
return 0;
out_err:
+ if (buf) free(buf);
printerr(0, "Failed to write downcall!\n");
return -1;
}
@@ -423,7 +430,12 @@ int create_auth_rpc_client(struct clnt_info *clp,
AUTH *auth = NULL;
uid_t save_uid = -1;
int retval = -1;
+ int errcode;
OM_uint32 min_stat;
+ char rpc_errmsg[1024];
+ int sockp = RPC_ANYSOCK;
+ int sendsz = 32768, recvsz = 32768;
+ struct addrinfo ai_hints, *a = NULL;
sec.qop = GSS_C_QOP_DEFAULT;
sec.svc = RPCSEC_GSS_SVC_NONE;
@@ -435,7 +447,10 @@ int create_auth_rpc_client(struct clnt_info *clp,
}
else if (authtype == AUTHTYPE_SPKM3) {
sec.mech = (gss_OID)&spkm3oid;
- sec.req_flags = GSS_C_ANON_FLAG;
+ /* XXX sec.req_flags = GSS_C_ANON_FLAG;
+ * Need a way to switch....
+ */
+ sec.req_flags = GSS_C_MUTUAL_FLAG;
}
else {
printerr(0, "ERROR: Invalid authentication type (%d) "
@@ -473,20 +488,82 @@ int create_auth_rpc_client(struct clnt_info *clp,
printerr(2, "creating %s client for server %s\n", clp->protocol,
clp->servername);
- if ((rpc_clnt = clnt_create(clp->servername, clp->prog, clp->vers,
- clp->protocol)) == NULL) {
- printerr(0, "WARNING: can't create rpc_clnt for server "
- "%s for user with uid %d\n",
- clp->servername, uid);
+
+ memset(&ai_hints, '\0', sizeof(ai_hints));
+ ai_hints.ai_family = PF_INET;
+ ai_hints.ai_flags |= AI_CANONNAME;
+ if ((strcmp(clp->protocol, "tcp")) == 0) {
+ ai_hints.ai_socktype = SOCK_STREAM;
+ ai_hints.ai_protocol = IPPROTO_TCP;
+ } else if ((strcmp(clp->protocol, "udp")) == 0) {
+ ai_hints.ai_socktype = SOCK_DGRAM;
+ ai_hints.ai_protocol = IPPROTO_UDP;
+ } else {
+ printerr(0, "WARNING: unrecognized protocol, '%s', requested "
+ "for connection to server %s for user with uid %d",
+ clp->protocol, clp->servername, uid);
+ goto out_fail;
+ }
+
+ errcode = getaddrinfo(clp->servername, "nfs",
+ &ai_hints, &a);
+ if (errcode) {
+ printerr(0, "WARNING: Error from getaddrinfo for server "
+ "'%s': %s", clp->servername, gai_strerror(errcode));
+ goto out_fail;
+ }
+
+ if (a == NULL) {
+ printerr(0, "WARNING: No address information found for "
+ "connection to server %s for user with uid %d",
+ clp->servername, uid);
+ goto out_fail;
+ }
+ if (a->ai_protocol == IPPROTO_TCP) {
+ if ((rpc_clnt = clnttcp_create(
+ (struct sockaddr_in *) a->ai_addr,
+ clp->prog, clp->vers, &sockp,
+ sendsz, recvsz)) == NULL) {
+ snprintf(rpc_errmsg, sizeof(rpc_errmsg),
+ "WARNING: can't create tcp rpc_clnt "
+ "for server %s for user with uid %d",
+ clp->servername, uid);
+ printerr(0, "%s\n",
+ clnt_spcreateerror(rpc_errmsg));
+ goto out_fail;
+ }
+ } else if (a->ai_protocol == IPPROTO_UDP) {
+ const struct timeval timeout = {5, 0};
+ if ((rpc_clnt = clntudp_bufcreate(
+ (struct sockaddr_in *) a->ai_addr,
+ clp->prog, clp->vers, timeout,
+ &sockp, sendsz, recvsz)) == NULL) {
+ snprintf(rpc_errmsg, sizeof(rpc_errmsg),
+ "WARNING: can't create udp rpc_clnt "
+ "for server %s for user with uid %d",
+ clp->servername, uid);
+ printerr(0, "%s\n",
+ clnt_spcreateerror(rpc_errmsg));
+ goto out_fail;
+ }
+ } else {
+ /* Shouldn't happen! */
+ printerr(0, "ERROR: requested protocol '%s', but "
+ "got addrinfo with protocol %d",
+ clp->protocol, a->ai_protocol);
goto out_fail;
}
+ /* We're done with this */
+ freeaddrinfo(a);
+ a = NULL;
printerr(2, "creating context with server %s\n", clp->servicename);
auth = authgss_create_default(rpc_clnt, clp->servicename, &sec);
if (!auth) {
/* Our caller should print appropriate message */
- printerr(2, "WARNING: Failed to create krb5 context for "
+ printerr(2, "WARNING: Failed to create %s context for "
"user with uid %d for server %s\n",
+ (authtype == AUTHTYPE_KRB5 ? "krb5":"spkm3"),
uid, clp->servername);
goto out_fail;
}
@@ -511,6 +588,7 @@ int create_auth_rpc_client(struct clnt_info *clp,
if (sec.cred != GSS_C_NO_CREDENTIAL)
gss_release_cred(&min_stat, &sec.cred);
if (rpc_clnt) clnt_destroy(rpc_clnt);
+ if (a != NULL) freeaddrinfo(a);
return retval;
}
diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c
index 353a93e..5f3e490 100644
--- a/utils/gssd/krb5_util.c
+++ b/utils/gssd/krb5_util.c
@@ -288,18 +288,16 @@ limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid)
&credh, NULL, NULL);
if (maj_stat != GSS_S_COMPLETE) {
- printerr(0, "WARNING: error from gss_acquire_cred "
- "for user with uid %d (%s)\n",
- uid, error_message(min_stat));
+ pgsserr("gss_acquire_cred",
+ maj_stat, min_stat, &krb5oid);
return -1;
}
maj_stat = gss_set_allowable_enctypes(&min_stat, credh, &krb5oid,
num_enctypes, &enctypes);
if (maj_stat != GSS_S_COMPLETE) {
- printerr(0, "WARNING: error from gss_set_allowable_enctypes "
- "for user with uid %d (%s)\n",
- uid, error_message(min_stat));
+ pgsserr("gss_set_allowable_enctypes",
+ maj_stat, min_stat, &krb5oid);
return -1;
}
sec->cred = credh;