All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] nfs-utils: Adds support for more encryption types.
@ 2010-04-14 19:18 steved
  2010-04-14 19:18 ` [PATCH 1/3] gssd: move function limit_krb5_enctypes into the exported functions area steved
                   ` (3 more replies)
  0 siblings, 4 replies; 10+ messages in thread
From: steved @ 2010-04-14 19:18 UTC (permalink / raw)
  To: linux-nfs

From: Steve Dickson <steved@redhat.com>

These three gssd patches added support for more DES and non-DES
encryption types. They were authored by Kevin Coffman and tested
by me on several recent kernels. 

Kevin Coffman (3):
  gssd: move function limit_krb5_enctypes into the exported functions area
  Try to use kernel function to determine supported Kerberos enctypes.
  Add support for non-DES encryption types.


 utils/gssd/context.h       |    6 ++-
 utils/gssd/context_lucid.c |  128 ++++++++++++++++++++++++++++++++++++-----
 utils/gssd/context_mit.c   |  136 +++++++++++++++++++++++++++++++++-----------
 utils/gssd/gssd_proc.c     |   81 ++++++++++++++++++++++++++-
 utils/gssd/krb5_util.c     |  121 +++++++++++++++++++++------------------
 5 files changed, 368 insertions(+), 104 deletions(-)


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/3] gssd: move function limit_krb5_enctypes into the exported functions area
  2010-04-14 19:18 [PATCH 0/3] nfs-utils: Adds support for more encryption types steved
@ 2010-04-14 19:18 ` steved
  2010-04-14 19:18 ` [PATCH 2/3] Try to use kernel function to determine supported Kerberos enctypes steved
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 10+ messages in thread
From: steved @ 2010-04-14 19:18 UTC (permalink / raw)
  To: linux-nfs

From: Kevin Coffman <kwc@citi.umich.edu>

cleanup: Move function limit_krb5_enctypes() from the section
containing static functions into the section containing
externally visible functions.

Signed-off-by: Steve Dickson <steved@redhat.com>
---
 utils/gssd/krb5_util.c |  109 ++++++++++++++++++++++++------------------------
 1 files changed, 54 insertions(+), 55 deletions(-)

diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c
index 1295f57..1c10bd4 100644
--- a/utils/gssd/krb5_util.c
+++ b/utils/gssd/krb5_util.c
@@ -292,61 +292,6 @@ gssd_find_existing_krb5_ccache(uid_t uid, char *dirname, struct dirent **d)
 	return err;
 }
 
-
-#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
-/*
- * this routine obtains a credentials handle via gss_acquire_cred()
- * then calls gss_krb5_set_allowable_enctypes() to limit the encryption
- * types negotiated.
- *
- * XXX Should call some function to determine the enctypes supported
- * by the kernel. (Only need to do that once!)
- *
- * Returns:
- *	0 => all went well
- *     -1 => there was an error
- */
-
-int
-limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid)
-{
-	u_int maj_stat, min_stat;
-	gss_cred_id_t credh;
-	gss_OID_set_desc  desired_mechs;
-	krb5_enctype enctypes[] = { ENCTYPE_DES_CBC_CRC,
-				    ENCTYPE_DES_CBC_MD5,
-				    ENCTYPE_DES_CBC_MD4 };
-	int num_enctypes = sizeof(enctypes) / sizeof(enctypes[0]);
-
-	/* We only care about getting a krb5 cred */
-	desired_mechs.count = 1;
-	desired_mechs.elements = &krb5oid;
-
-	maj_stat = gss_acquire_cred(&min_stat, NULL, 0,
-				    &desired_mechs, GSS_C_INITIATE,
-				    &credh, NULL, NULL);
-
-	if (maj_stat != GSS_S_COMPLETE) {
-		if (get_verbosity() > 0)
-			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) {
-		pgsserr("gss_set_allowable_enctypes",
-			maj_stat, min_stat, &krb5oid);
-		gss_release_cred(&min_stat, &credh);
-		return -1;
-	}
-	sec->cred = credh;
-
-	return 0;
-}
-#endif	/* HAVE_SET_ALLOWABLE_ENCTYPES */
-
 /*
  * Obtain credentials via a key in the keytab given
  * a keytab handle and a gssd_k5_kt_princ structure.
@@ -1304,3 +1249,57 @@ gssd_k5_get_default_realm(char **def_realm)
 
 	krb5_free_context(context);
 }
+
+#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
+/*
+ * this routine obtains a credentials handle via gss_acquire_cred()
+ * then calls gss_krb5_set_allowable_enctypes() to limit the encryption
+ * types negotiated.
+ *
+ * XXX Should call some function to determine the enctypes supported
+ * by the kernel. (Only need to do that once!)
+ *
+ * Returns:
+ *	0 => all went well
+ *     -1 => there was an error
+ */
+
+int
+limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid)
+{
+	u_int maj_stat, min_stat;
+	gss_cred_id_t credh;
+	gss_OID_set_desc  desired_mechs;
+	krb5_enctype enctypes[] = { ENCTYPE_DES_CBC_CRC,
+				    ENCTYPE_DES_CBC_MD5,
+				    ENCTYPE_DES_CBC_MD4 };
+	int num_enctypes = sizeof(enctypes) / sizeof(enctypes[0]);
+
+	/* We only care about getting a krb5 cred */
+	desired_mechs.count = 1;
+	desired_mechs.elements = &krb5oid;
+
+	maj_stat = gss_acquire_cred(&min_stat, NULL, 0,
+				    &desired_mechs, GSS_C_INITIATE,
+				    &credh, NULL, NULL);
+
+	if (maj_stat != GSS_S_COMPLETE) {
+		if (get_verbosity() > 0)
+			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) {
+		pgsserr("gss_set_allowable_enctypes",
+			maj_stat, min_stat, &krb5oid);
+		gss_release_cred(&min_stat, &credh);
+		return -1;
+	}
+	sec->cred = credh;
+
+	return 0;
+}
+#endif	/* HAVE_SET_ALLOWABLE_ENCTYPES */
-- 
1.6.6.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/3] Try to use kernel function to determine supported Kerberos enctypes.
  2010-04-14 19:18 [PATCH 0/3] nfs-utils: Adds support for more encryption types steved
  2010-04-14 19:18 ` [PATCH 1/3] gssd: move function limit_krb5_enctypes into the exported functions area steved
@ 2010-04-14 19:18 ` steved
  2010-04-14 19:58   ` Kevin Coffman
  2010-04-15 12:45   ` [PATCH 2/3] Try to use kernel function to determine supported Kerberos enctypes (Updated) Steve Dickson
  2010-04-14 19:18 ` [PATCH 3/3] Add support for non-DES encryption types steved
  2010-04-16 17:53 ` [PATCH 0/3] nfs-utils: Adds support for more " Steve Dickson
  3 siblings, 2 replies; 10+ messages in thread
From: steved @ 2010-04-14 19:18 UTC (permalink / raw)
  To: linux-nfs

From: Kevin Coffman <kwc@citi.umich.edu>

This patch replaces a hard-coded list with a function to obtain
the Kerberos encryption types that the kernel's rpcsec_gss code
can support.  Defaults to old behavior if kernel does not supply
information.

Signed-off-by: Steve Dickson <steved@redhat.com>
---
 utils/gssd/gssd_proc.c |   81 +++++++++++++++++++++++++++++++++++++++++++++++-
 utils/gssd/krb5_util.c |   16 ++++++++-
 2 files changed, 94 insertions(+), 3 deletions(-)

diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c
index be4fb11..12e11d5 100644
--- a/utils/gssd/gssd_proc.c
+++ b/utils/gssd/gssd_proc.c
@@ -600,6 +600,67 @@ update_client_list(void)
 	return retval;
 }
 
+/* Encryption types supported by the kernel rpcsec_gss code */
+int num_krb5_enctypes = 0;
+krb5_enctype *krb5_enctypes = NULL;
+
+/*
+ * Parse the supported encryption type information
+ */
+static int
+parse_enctypes(char *enctypes)
+{
+	int n = 0;
+	char *curr, *comma;
+	int i;
+	static char *cached_types;
+
+	if (cached_types && strcmp(cached_types, enctypes) == 0)
+		return 0;
+	free(cached_types);
+
+	if (krb5_enctypes != NULL) {
+		free(krb5_enctypes);
+		krb5_enctypes = NULL;
+		num_krb5_enctypes = 0;
+	}
+
+	/* count the number of commas */
+	for (curr = enctypes; curr && *curr != '\0'; curr = ++comma) {
+		comma = strchr(curr, ',');
+		if (comma != NULL)
+			n++;
+		else
+			break;
+	}
+	/* If no more commas and we're not at the end, there's one more value */
+	if (*curr != '\0')
+		n++;
+
+	/* Empty string, return an error */
+	if (n == 0)
+		return ENOENT;
+
+	/* Allocate space for enctypes array */
+	if ((krb5_enctypes = (int *) calloc(n, sizeof(int))) == NULL) {
+		return ENOMEM;
+	}
+
+	/* Now parse each value into the array */
+	for (curr = enctypes, i = 0; curr && *curr != '\0'; curr = ++comma) {
+		krb5_enctypes[i++] = atoi(curr);
+		comma = strchr(curr, ',');
+		if (comma == NULL)
+			break;
+	}
+
+	num_krb5_enctypes = n;
+	if (cached_types = malloc(strlen(enctypes)+1))
+		strcpy(cached_types, enctypes);
+
+	return 0;
+}
+
 static int
 do_downcall(int k5_fd, uid_t uid, struct authgss_private_data *pd,
 	    gss_buffer_desc *context_token)
@@ -1128,11 +1189,12 @@ handle_gssd_upcall(struct clnt_info *clp)
 {
 	uid_t			uid;
 	char			*lbuf = NULL;
-	int			lbuflen = 0;
+	int			lbuflen = 0, code;
 	char			*p;
 	char			*mech = NULL;
 	char			*target = NULL;
 	char			*service = NULL;
+	char			*enctypes = NULL;
 
 	printerr(1, "handling gssd upcall (%s)\n", clp->dirname);
 
@@ -1176,6 +1238,23 @@ handle_gssd_upcall(struct clnt_info *clp)
 		goto out;
 	}
 
+	/* read supported encryption types if supplied */
+	if ((p = strstr(lbuf, "enctypes=")) != NULL) {
+		enctypes = malloc(lbuflen);
+		if (!enctypes)
+			goto out;
+		if (sscanf(p, "enctypes=%s", enctypes) != 1) {
+			printerr(0, "WARNING: handle_gssd_upcall: "
+				    "failed to parse target name "
+				    "in upcall string '%s'\n", lbuf);
+			goto out;
+		}
+		if (parse_enctypes(enctypes) != 0) {
+			printerr(0, "WARNING: handle_gssd_upcall: "
+				"parsing encryption types failed: errno %d\n", code);
+		}
+	}
+
 	/* read target name */
 	if ((p = strstr(lbuf, "target=")) != NULL) {
 		target = malloc(lbuflen);
diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c
index 1c10bd4..0f56b1d 100644
--- a/utils/gssd/krb5_util.c
+++ b/utils/gssd/krb5_util.c
@@ -1274,6 +1274,8 @@ limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid)
 				    ENCTYPE_DES_CBC_MD5,
 				    ENCTYPE_DES_CBC_MD4 };
 	int num_enctypes = sizeof(enctypes) / sizeof(enctypes[0]);
+	extern int num_krb5_enctypes;
+	extern krb5_enctype *krb5_enctypes;
 
 	/* We only care about getting a krb5 cred */
 	desired_mechs.count = 1;
@@ -1290,8 +1292,18 @@ limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid)
 		return -1;
 	}
 
-	maj_stat = gss_set_allowable_enctypes(&min_stat, credh, &krb5oid,
-					     num_enctypes, &enctypes);
+	/*
+	 * If we failed for any reason to produce global
+	 * list of supported enctypes, use local default here.
+	 */
+	if (krb5_enctypes == NULL)
+		maj_stat = gss_set_allowable_enctypes(&min_stat, credh,
+					&krb5oid, num_enctypes, &enctypes);
+	else
+		maj_stat = gss_set_allowable_enctypes(&min_stat, credh,
+					&krb5oid, num_krb5_enctypes,
+					krb5_enctypes);
+
 	if (maj_stat != GSS_S_COMPLETE) {
 		pgsserr("gss_set_allowable_enctypes",
 			maj_stat, min_stat, &krb5oid);
-- 
1.6.6.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 3/3] Add support for non-DES encryption types.
  2010-04-14 19:18 [PATCH 0/3] nfs-utils: Adds support for more encryption types steved
  2010-04-14 19:18 ` [PATCH 1/3] gssd: move function limit_krb5_enctypes into the exported functions area steved
  2010-04-14 19:18 ` [PATCH 2/3] Try to use kernel function to determine supported Kerberos enctypes steved
@ 2010-04-14 19:18 ` steved
  2010-04-16 17:53 ` [PATCH 0/3] nfs-utils: Adds support for more " Steve Dickson
  3 siblings, 0 replies; 10+ messages in thread
From: steved @ 2010-04-14 19:18 UTC (permalink / raw)
  To: linux-nfs

From: Kevin Coffman <kwc@citi.umich.edu>

Sends a new format of context information to the kernel.
(Requires kernel support to do anything useful.)

Signed-off-by: Steve Dickson <steved@redhat.com>
---
 utils/gssd/context.h       |    6 ++-
 utils/gssd/context_lucid.c |  128 ++++++++++++++++++++++++++++++++++++-----
 utils/gssd/context_mit.c   |  136 +++++++++++++++++++++++++++++++++-----------
 3 files changed, 222 insertions(+), 48 deletions(-)

diff --git a/utils/gssd/context.h b/utils/gssd/context.h
index be47f9c..c9cb0bd 100644
--- a/utils/gssd/context.h
+++ b/utils/gssd/context.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (c) 2004 The Regents of the University of Michigan.
+  Copyright (c) 2004,2008 The Regents of the University of Michigan.
   All rights reserved.
 
   Redistribution and use in source and binary forms, with or without
@@ -36,6 +36,10 @@
 /* Hopefully big enough to hold any serialized context */
 #define MAX_CTX_LEN 4096
 
+/* New context format flag values */
+#define KRB5_CTX_FLAG_INITIATOR         0x00000001
+#define KRB5_CTX_FLAG_CFX               0x00000002
+#define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY   0x00000004
 
 int serialize_context_for_kernel(gss_ctx_id_t ctx, gss_buffer_desc *buf,
 				 gss_OID mech, int32_t *endtime);
diff --git a/utils/gssd/context_lucid.c b/utils/gssd/context_lucid.c
index 4a682ae..b87bf76 100644
--- a/utils/gssd/context_lucid.c
+++ b/utils/gssd/context_lucid.c
@@ -42,6 +42,7 @@
 #include <stdio.h>
 #include <syslog.h>
 #include <string.h>
+#include <errno.h>
 
 #include <gssapi/gssapi_krb5.h>
 
@@ -119,15 +120,13 @@ prepare_krb5_rfc1964_buffer(gss_krb5_lucid_context_v1_t *lctx,
 	 * Note that the rfc1964 version only supports DES enctypes.
 	 */
 	if (lctx->rfc1964_kd.ctx_key.type != 4) {
-		printerr(1, "prepare_krb5_rfc1964_buffer: "
-			    "overriding heimdal keytype (%d => %d)\n",
-			    lctx->rfc1964_kd.ctx_key.type, 4);
+		printerr(2, "%s: overriding heimdal keytype (%d => %d)\n",
+			 __FUNCTION__, lctx->rfc1964_kd.ctx_key.type, 4);
 		lctx->rfc1964_kd.ctx_key.type = 4;
 	}
 #endif
-	printerr(2, "prepare_krb5_rfc1964_buffer: serializing keys with "
-		 "enctype %d and length %d\n",
-		 lctx->rfc1964_kd.ctx_key.type,
+	printerr(2, "%s: serializing keys with enctype %d and length %d\n",
+		 __FUNCTION__, lctx->rfc1964_kd.ctx_key.type,
 		 lctx->rfc1964_kd.ctx_key.length);
 
 	/* derive the encryption key and copy it into buffer */
@@ -158,11 +157,100 @@ out_err:
 	return -1;
 }
 
+/* Flags for version 2 context flags */
+#define KRB5_CTX_FLAG_INITIATOR		0x00000001
+#define KRB5_CTX_FLAG_CFX		0x00000002
+#define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY	0x00000004
+
+/*
+ * Prepare a new-style buffer, as defined in rfc4121 (a.k.a. cfx),
+ * to send to the kernel for newer encryption types -- or for DES3.
+ *
+ * The new format is:
+ *
+ *	u32 flags;
+ *	#define KRB5_CTX_FLAG_INITIATOR		0x00000001
+ *	#define KRB5_CTX_FLAG_CFX		0x00000002
+ *	#define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY	0x00000004
+ *	s32 endtime;
+ *	u64 seq_send;
+ *	u32  enctype;			( encrption type of key )
+ *	raw key;			( raw key bytes (kernel will derive))
+ *
+ */
 static int
-prepare_krb5_rfc_cfx_buffer(gss_krb5_lucid_context_v1_t *lctx,
+prepare_krb5_rfc4121_buffer(gss_krb5_lucid_context_v1_t *lctx,
 	gss_buffer_desc *buf, int32_t *endtime)
 {
-	printerr(0, "ERROR: prepare_krb5_rfc_cfx_buffer: not implemented\n");
+	char *p, *end;
+	uint32_t v2_flags = 0;
+	uint32_t enctype;
+	uint32_t keysize;
+
+	if (!(buf->value = calloc(1, MAX_CTX_LEN)))
+		goto out_err;
+	p = buf->value;
+	end = buf->value + MAX_CTX_LEN;
+
+	/* Version 2 */
+	if (lctx->initiate)
+		v2_flags |= KRB5_CTX_FLAG_INITIATOR;
+	if (lctx->protocol != 0)
+		v2_flags |= KRB5_CTX_FLAG_CFX;
+	if (lctx->protocol != 0 && lctx->cfx_kd.have_acceptor_subkey == 1)
+		v2_flags |= KRB5_CTX_FLAG_ACCEPTOR_SUBKEY;
+
+	if (WRITE_BYTES(&p, end, v2_flags)) goto out_err;
+	if (WRITE_BYTES(&p, end, lctx->endtime)) goto out_err;
+	if (WRITE_BYTES(&p, end, lctx->send_seq)) goto out_err;
+
+	/* Protocol 0 here implies DES3 or RC4 */
+	printerr(2, "%s: protocol %d\n", __FUNCTION__, lctx->protocol);
+	if (lctx->protocol == 0) {
+		enctype = lctx->rfc1964_kd.ctx_key.type;
+		keysize = lctx->rfc1964_kd.ctx_key.length;
+	} else {
+		if (lctx->cfx_kd.have_acceptor_subkey) {
+			enctype = lctx->cfx_kd.acceptor_subkey.type;
+			keysize = lctx->cfx_kd.acceptor_subkey.length;
+		} else {
+			enctype = lctx->cfx_kd.ctx_key.type;
+			keysize = lctx->cfx_kd.ctx_key.length;
+		}
+	}
+	printerr(2, "%s: serializing key with enctype %d and size %d\n",
+		 __FUNCTION__, enctype, keysize);
+
+	if (WRITE_BYTES(&p, end, enctype)) goto out_err;
+
+	if (lctx->protocol == 0) {
+		if (write_bytes(&p, end, lctx->rfc1964_kd.ctx_key.data,
+				lctx->rfc1964_kd.ctx_key.length))
+			goto out_err;
+	} else {
+		if (lctx->cfx_kd.have_acceptor_subkey) {
+			if (write_bytes(&p, end,
+					lctx->cfx_kd.acceptor_subkey.data,
+					lctx->cfx_kd.acceptor_subkey.length))
+				goto out_err;
+		} else {
+			if (write_bytes(&p, end, lctx->cfx_kd.ctx_key.data,
+					lctx->cfx_kd.ctx_key.length))
+				goto out_err;
+		}
+	}
+
+	buf->length = p - (char *)buf->value;
+	return 0;
+
+out_err:
+	printerr(0, "ERROR: %s: failed serializing krb5 context for kernel\n",
+		 __FUNCTION__);
+	if (buf->value) {
+		free(buf->value);
+		buf->value = NULL;
+	}
+	buf->length = 0;
 	return -1;
 }
 
@@ -176,7 +264,7 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf, int32_t *endtime)
 	gss_krb5_lucid_context_v1_t *lctx = 0;
 	int retcode = 0;
 
-	printerr(2, "DEBUG: serialize_krb5_ctx: lucid version!\n");
+	printerr(2, "DEBUG: %s: lucid version!\n", __FUNCTION__);
 	maj_stat = gss_export_lucid_sec_context(&min_stat, &ctx,
 						1, &return_ctx);
 	if (maj_stat != GSS_S_COMPLETE) {
@@ -198,11 +286,20 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf, int32_t *endtime)
 		break;
 	}
 
-	/* Now lctx points to a lucid context that we can send down to kernel */
-	if (lctx->protocol == 0)
+	/*
+	 * Now lctx points to a lucid context that we can send down to kernel
+	 *
+	 * Note: we send down different information to the kernel depending
+	 * on the protocol version and the enctyption type.
+	 * For protocol version 0 with all enctypes besides DES3, we use
+	 * the original format.  For protocol version != 0 or DES3, we
+	 * send down the new style information.
+	 */
+
+	if (lctx->protocol == 0 && lctx->rfc1964_kd.ctx_key.type <= 4)
 		retcode = prepare_krb5_rfc1964_buffer(lctx, buf, endtime);
 	else
-		retcode = prepare_krb5_rfc_cfx_buffer(lctx, buf, endtime);
+		retcode = prepare_krb5_rfc4121_buffer(lctx, buf, endtime);
 
 	maj_stat = gss_free_lucid_sec_context(&min_stat, ctx, return_ctx);
 	if (maj_stat != GSS_S_COMPLETE) {
@@ -212,8 +309,8 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf, int32_t *endtime)
 	}
 
 	if (retcode) {
-		printerr(1, "serialize_krb5_ctx: prepare_krb5_*_buffer "
-			 "failed (retcode = %d)\n", retcode);
+		printerr(1, "%s: prepare_krb5_*_buffer failed (retcode = %d)\n",
+			 __FUNCTION__, retcode);
 		goto out_err;
 	}
 
@@ -223,4 +320,7 @@ out_err:
 	printerr(0, "ERROR: failed serializing krb5 context for kernel\n");
 	return -1;
 }
+
+
+
 #endif /* HAVE_LUCID_CONTEXT_SUPPORT */
diff --git a/utils/gssd/context_mit.c b/utils/gssd/context_mit.c
index 709a903..f9cbb02 100644
--- a/utils/gssd/context_mit.c
+++ b/utils/gssd/context_mit.c
@@ -1,5 +1,5 @@
 /*
-  Copyright (c) 2004 The Regents of the University of Michigan.
+  Copyright (c) 2004-2006 The Regents of the University of Michigan.
   All rights reserved.
 
   Redistribution and use in source and binary forms, with or without
@@ -38,6 +38,7 @@
 #include <stdio.h>
 #include <syslog.h>
 #include <string.h>
+#include <errno.h>
 #include <gssapi/gssapi.h>
 #include <rpc/rpc.h>
 #include <rpc/auth_gss.h>
@@ -52,8 +53,7 @@
 /* XXX argggg, there's gotta be a better way than just duplicating this
  * whole struct.  Unfortunately, this is in a "private" header file,
  * so this is our best choice at this point :-/
- *
- * XXX Does this match the Heimdal definition?  */
+ */
 
 typedef struct _krb5_gss_ctx_id_rec {
    unsigned int initiate : 1;   /* nonzero if initiating, zero if accepting */
@@ -156,50 +156,120 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf, int32_t *endtime)
 {
 	krb5_gss_ctx_id_t kctx = ((gss_union_ctx_id_t)ctx)->internal_ctx_id;
 	char *p, *end;
-	static int constant_one = 1;
 	static int constant_zero = 0;
+	static int constant_one = 1;
+	static int constant_two = 2;
 	uint32_t word_seq_send;
+	u_int64_t seq_send_64bit;
+	uint32_t v2_flags = 0;
 
 	if (!(buf->value = calloc(1, MAX_CTX_LEN)))
 		goto out_err;
 	p = buf->value;
 	end = buf->value + MAX_CTX_LEN;
 
-	if (kctx->initiate) {
-		if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
-	}
-	else {
-		if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
-	}
-	if (kctx->seed_init) {
-		if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
-	}
-	else {
-		if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
-	}
-	if (write_bytes(&p, end, &kctx->seed, sizeof(kctx->seed)))
+	switch (kctx->enc->enctype) {
+	case ENCTYPE_DES_CBC_CRC:
+	case ENCTYPE_DES_CBC_MD4:
+	case ENCTYPE_DES_CBC_MD5:
+	case ENCTYPE_DES_CBC_RAW:
+		/* Old format of context to the kernel */
+		if (kctx->initiate) {
+			if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
+		}
+		else {
+			if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
+		}
+		if (kctx->seed_init) {
+			if (WRITE_BYTES(&p, end, constant_one)) goto out_err;
+		}
+		else {
+			if (WRITE_BYTES(&p, end, constant_zero)) goto out_err;
+		}
+		if (write_bytes(&p, end, &kctx->seed, sizeof(kctx->seed)))
+			goto out_err;
+		if (WRITE_BYTES(&p, end, kctx->signalg)) goto out_err;
+		if (WRITE_BYTES(&p, end, kctx->sealalg)) goto out_err;
+		if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err;
+		word_seq_send = kctx->seq_send;
+		if (WRITE_BYTES(&p, end, word_seq_send)) goto out_err;
+		if (write_oid(&p, end, kctx->mech_used)) goto out_err;
+
+		printerr(2, "serialize_krb5_ctx: serializing keys with "
+			 "enctype %d and length %d\n",
+			 kctx->enc->enctype, kctx->enc->length);
+
+		if (write_keyblock(&p, end, kctx->enc)) goto out_err;
+		if (write_keyblock(&p, end, kctx->seq)) goto out_err;
+		break;
+	case ENCTYPE_DES3_CBC_RAW:
+	case ENCTYPE_DES3_CBC_SHA1:
+	case ENCTYPE_ARCFOUR_HMAC:
+	case ENCTYPE_ARCFOUR_HMAC_EXP:
+	case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
+	case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
+		/* New format of context to the kernel */
+		/* u32 flags;
+		 * #define KRB5_CTX_FLAG_INITIATOR        0x00000001
+		 * #define KRB5_CTX_FLAG_CFX              0x00000002
+		 * #define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY  0x00000004
+		 * s32 endtime;
+		 * u64 seq_send;
+		 * u32  enctype;
+		 * rawkey data
+		 */
+
+		if (kctx->initiate)
+			v2_flags |= KRB5_CTX_FLAG_INITIATOR;
+		if (kctx->proto == 1)
+			v2_flags |= KRB5_CTX_FLAG_CFX;
+		if (kctx->have_acceptor_subkey)
+			v2_flags |= KRB5_CTX_FLAG_ACCEPTOR_SUBKEY;
+		if (WRITE_BYTES(&p, end, v2_flags)) goto out_err;
+		if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err;
+
+		seq_send_64bit = kctx->seq_send;
+		if (WRITE_BYTES(&p, end, seq_send_64bit)) goto out_err;
+
+		if (kctx->have_acceptor_subkey) {
+			if (WRITE_BYTES(&p, end, kctx->acceptor_subkey->enctype))
+				goto out_err;
+			printerr(2, "serialize_krb5_ctx: serializing subkey "
+				 "with enctype %d and size %d\n",
+				 kctx->acceptor_subkey->enctype,
+				 kctx->acceptor_subkey->length);
+
+			if (write_bytes(&p, end,
+					kctx->acceptor_subkey->contents,
+					kctx->acceptor_subkey->length))
+				goto out_err;
+		} else {
+			if (WRITE_BYTES(&p, end, kctx->enc->enctype))
+				goto out_err;
+			printerr(2, "serialize_krb5_ctx: serializing key "
+				 "with enctype %d and size %d\n",
+				 kctx->enc->enctype, kctx->enc->length);
+
+			if (write_bytes(&p, end, kctx->enc->contents,
+					kctx->enc->length))
+				goto out_err;
+		}
+		break;
+	default:
+		printerr(0, "ERROR: serialize_krb5_ctx: unsupported encryption "
+			 "algorithm %d\n", kctx->enc->enctype);
 		goto out_err;
-	if (WRITE_BYTES(&p, end, kctx->signalg)) goto out_err;
-	if (WRITE_BYTES(&p, end, kctx->sealalg)) goto out_err;
-	if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err;
-	if (endtime)
-		*endtime = kctx->endtime;
-	word_seq_send = kctx->seq_send;
-	if (WRITE_BYTES(&p, end, word_seq_send)) goto out_err;
-	if (write_oid(&p, end, kctx->mech_used)) goto out_err;
-
-	printerr(2, "serialize_krb5_ctx: serializing keys with "
-		 "enctype %d and length %d\n",
-		 kctx->enc->enctype, kctx->enc->length);
-
-	if (write_keyblock(&p, end, kctx->enc)) goto out_err;
-	if (write_keyblock(&p, end, kctx->seq)) goto out_err;
+	}
 
 	buf->length = p - (char *)buf->value;
 	return 0;
+
 out_err:
 	printerr(0, "ERROR: failed serializing krb5 context for kernel\n");
-	if (buf->value) free(buf->value);
+	if (buf->value) {
+		free(buf->value);
+	}
+	buf->value = NULL;
 	buf->length = 0;
 	return -1;
 }
-- 
1.6.6.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/3] Try to use kernel function to determine supported Kerberos enctypes.
  2010-04-14 19:18 ` [PATCH 2/3] Try to use kernel function to determine supported Kerberos enctypes steved
@ 2010-04-14 19:58   ` Kevin Coffman
       [not found]     ` <z2j4d569c331004141258y2f16a82ga1aa7826d665b3a9-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
  2010-04-15 11:58     ` Steve Dickson
  2010-04-15 12:45   ` [PATCH 2/3] Try to use kernel function to determine supported Kerberos enctypes (Updated) Steve Dickson
  1 sibling, 2 replies; 10+ messages in thread
From: Kevin Coffman @ 2010-04-14 19:58 UTC (permalink / raw)
  To: steved; +Cc: linux-nfs

On Wed, Apr 14, 2010 at 3:18 PM,  <steved@redhat.com> wrote:
> From: Kevin Coffman <kwc@citi.umich.edu>
>
> This patch replaces a hard-coded list with a function to obtain
> the Kerberos encryption types that the kernel's rpcsec_gss code
> can support.  Defaults to old behavior if kernel does not supply
> information.
>
> Signed-off-by: Steve Dickson <steved@redhat.com>
> ---
>  utils/gssd/gssd_proc.c |   81 +++++++++++++++++++++++++++++++++++++++++++++++-
>  utils/gssd/krb5_util.c |   16 ++++++++-
>  2 files changed, 94 insertions(+), 3 deletions(-)
>
> diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c
> index be4fb11..12e11d5 100644
> --- a/utils/gssd/gssd_proc.c
> +++ b/utils/gssd/gssd_proc.c
> @@ -600,6 +600,67 @@ update_client_list(void)
>        return retval;
>  }
>
> +/* Encryption types supported by the kernel rpcsec_gss code */
> +int num_krb5_enctypes = 0;
> +krb5_enctype *krb5_enctypes = NULL;
> +
> +/*
> + * Parse the supported encryption type information
> + */
> +static int
> +parse_enctypes(char *enctypes)
> +{
> +       int n = 0;
> +       char *curr, *comma;
> +       int i;
> +       static char *cached_types;
> +
> +       if (cached_types && strcmp(cached_types, enctypes) == 0)
> +               return 0;
> +       free(cached_types);
> +
> +       if (krb5_enctypes != NULL) {
> +               free(krb5_enctypes);
> +               krb5_enctypes = NULL;
> +               num_krb5_enctypes = 0;
> +       }
> +
> +       /* count the number of commas */
> +       for (curr = enctypes; curr && *curr != '\0'; curr = ++comma) {
> +               comma = strchr(curr, ',');
> +               if (comma != NULL)
> +                       n++;
> +               else
> +                       break;
> +       }
> +       /* If no more commas and we're not at the end, there's one more value */
> +       if (*curr != '\0')
> +               n++;
> +
> +       /* Empty string, return an error */
> +       if (n == 0)
> +               return ENOENT;
> +
> +       /* Allocate space for enctypes array */
> +       if ((krb5_enctypes = (int *) calloc(n, sizeof(int))) == NULL) {
> +               return ENOMEM;
> +       }
> +
> +       /* Now parse each value into the array */
> +       for (curr = enctypes, i = 0; curr && *curr != '\0'; curr = ++comma) {
> +               krb5_enctypes[i++] = atoi(curr);
> +               comma = strchr(curr, ',');
> +               if (comma == NULL)
> +                       break;
> +       }
> +
> +       num_krb5_enctypes = n;
> +       if (cached_types = malloc(strlen(enctypes)+1))
> +               strcpy(cached_types, enctypes);
> +
> +       return 0;
> +}
> +
>  static int
>  do_downcall(int k5_fd, uid_t uid, struct authgss_private_data *pd,
>            gss_buffer_desc *context_token)
> @@ -1128,11 +1189,12 @@ handle_gssd_upcall(struct clnt_info *clp)
>  {
>        uid_t                   uid;
>        char                    *lbuf = NULL;
> -       int                     lbuflen = 0;
> +       int                     lbuflen = 0, code;
>        char                    *p;
>        char                    *mech = NULL;
>        char                    *target = NULL;
>        char                    *service = NULL;
> +       char                    *enctypes = NULL;
>
>        printerr(1, "handling gssd upcall (%s)\n", clp->dirname);
>
> @@ -1176,6 +1238,23 @@ handle_gssd_upcall(struct clnt_info *clp)
>                goto out;
>        }
>
> +       /* read supported encryption types if supplied */
> +       if ((p = strstr(lbuf, "enctypes=")) != NULL) {
> +               enctypes = malloc(lbuflen);
> +               if (!enctypes)
> +                       goto out;
> +               if (sscanf(p, "enctypes=%s", enctypes) != 1) {
> +                       printerr(0, "WARNING: handle_gssd_upcall: "
> +                                   "failed to parse target name "
> +                                   "in upcall string '%s'\n", lbuf);
> +                       goto out;
> +               }
> +               if (parse_enctypes(enctypes) != 0) {
> +                       printerr(0, "WARNING: handle_gssd_upcall: "
> +                               "parsing encryption types failed: errno %d\n", code);
> +               }
> +       }
> +
>        /* read target name */
>        if ((p = strstr(lbuf, "target=")) != NULL) {
>                target = malloc(lbuflen);
> diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c
> index 1c10bd4..0f56b1d 100644
> --- a/utils/gssd/krb5_util.c
> +++ b/utils/gssd/krb5_util.c
> @@ -1274,6 +1274,8 @@ limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid)
>                                    ENCTYPE_DES_CBC_MD5,
>                                    ENCTYPE_DES_CBC_MD4 };
>        int num_enctypes = sizeof(enctypes) / sizeof(enctypes[0]);
> +       extern int num_krb5_enctypes;
> +       extern krb5_enctype *krb5_enctypes;
>
>        /* We only care about getting a krb5 cred */
>        desired_mechs.count = 1;
> @@ -1290,8 +1292,18 @@ limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid)
>                return -1;
>        }
>
> -       maj_stat = gss_set_allowable_enctypes(&min_stat, credh, &krb5oid,
> -                                            num_enctypes, &enctypes);
> +       /*
> +        * If we failed for any reason to produce global
> +        * list of supported enctypes, use local default here.
> +        */
> +       if (krb5_enctypes == NULL)
> +               maj_stat = gss_set_allowable_enctypes(&min_stat, credh,
> +                                       &krb5oid, num_enctypes, &enctypes);
> +       else
> +               maj_stat = gss_set_allowable_enctypes(&min_stat, credh,
> +                                       &krb5oid, num_krb5_enctypes,
> +                                       krb5_enctypes);
> +
>        if (maj_stat != GSS_S_COMPLETE) {
>                pgsserr("gss_set_allowable_enctypes",
>                        maj_stat, min_stat, &krb5oid);
> --

Hi Steve,

The global krb5_enctypes array was used when the list was being read
once from a file.  With the list now coming up with each request in
the updated upcall, I think the list obtained in the upcall should be
added to the clnt_info structure and then passed to the
limit_krb5_enctypes function as a parameter.

K.C.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/3] Try to use kernel function to determine supported Kerberos enctypes.
       [not found]     ` <z2j4d569c331004141258y2f16a82ga1aa7826d665b3a9-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2010-04-14 20:05       ` Steve Dickson
  0 siblings, 0 replies; 10+ messages in thread
From: Steve Dickson @ 2010-04-14 20:05 UTC (permalink / raw)
  To: Kevin Coffman; +Cc: linux-nfs



On 04/14/2010 03:58 PM, Kevin Coffman wrote:
> On Wed, Apr 14, 2010 at 3:18 PM,  <steved@redhat.com> wrote:
>> From: Kevin Coffman <kwc@citi.umich.edu>
>>
>> This patch replaces a hard-coded list with a function to obtain
>> the Kerberos encryption types that the kernel's rpcsec_gss code
>> can support.  Defaults to old behavior if kernel does not supply
>> information.
>>
>> Signed-off-by: Steve Dickson <steved@redhat.com>
>> ---
>>  utils/gssd/gssd_proc.c |   81 +++++++++++++++++++++++++++++++++++++++++++++++-
>>  utils/gssd/krb5_util.c |   16 ++++++++-
>>  2 files changed, 94 insertions(+), 3 deletions(-)
>>
>> diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c
>> index be4fb11..12e11d5 100644
>> --- a/utils/gssd/gssd_proc.c
>> +++ b/utils/gssd/gssd_proc.c
>> @@ -600,6 +600,67 @@ update_client_list(void)
>>        return retval;
>>  }
>>
>> +/* Encryption types supported by the kernel rpcsec_gss code */
>> +int num_krb5_enctypes = 0;
>> +krb5_enctype *krb5_enctypes = NULL;
>> +
>> +/*
>> + * Parse the supported encryption type information
>> + */
>> +static int
>> +parse_enctypes(char *enctypes)
>> +{
>> +       int n = 0;
>> +       char *curr, *comma;
>> +       int i;
>> +       static char *cached_types;
>> +
>> +       if (cached_types && strcmp(cached_types, enctypes) == 0)
>> +               return 0;
>> +       free(cached_types);
>> +
>> +       if (krb5_enctypes != NULL) {
>> +               free(krb5_enctypes);
>> +               krb5_enctypes = NULL;
>> +               num_krb5_enctypes = 0;
>> +       }
>> +
>> +       /* count the number of commas */
>> +       for (curr = enctypes; curr && *curr != '\0'; curr = ++comma) {
>> +               comma = strchr(curr, ',');
>> +               if (comma != NULL)
>> +                       n++;
>> +               else
>> +                       break;
>> +       }
>> +       /* If no more commas and we're not at the end, there's one more value */
>> +       if (*curr != '\0')
>> +               n++;
>> +
>> +       /* Empty string, return an error */
>> +       if (n == 0)
>> +               return ENOENT;
>> +
>> +       /* Allocate space for enctypes array */
>> +       if ((krb5_enctypes = (int *) calloc(n, sizeof(int))) == NULL) {
>> +               return ENOMEM;
>> +       }
>> +
>> +       /* Now parse each value into the array */
>> +       for (curr = enctypes, i = 0; curr && *curr != '\0'; curr = ++comma) {
>> +               krb5_enctypes[i++] = atoi(curr);
>> +               comma = strchr(curr, ',');
>> +               if (comma == NULL)
>> +                       break;
>> +       }
>> +
>> +       num_krb5_enctypes = n;
>> +       if (cached_types = malloc(strlen(enctypes)+1))
>> +               strcpy(cached_types, enctypes);
>> +
>> +       return 0;
>> +}
>> +
>>  static int
>>  do_downcall(int k5_fd, uid_t uid, struct authgss_private_data *pd,
>>            gss_buffer_desc *context_token)
>> @@ -1128,11 +1189,12 @@ handle_gssd_upcall(struct clnt_info *clp)
>>  {
>>        uid_t                   uid;
>>        char                    *lbuf = NULL;
>> -       int                     lbuflen = 0;
>> +       int                     lbuflen = 0, code;
>>        char                    *p;
>>        char                    *mech = NULL;
>>        char                    *target = NULL;
>>        char                    *service = NULL;
>> +       char                    *enctypes = NULL;
>>
>>        printerr(1, "handling gssd upcall (%s)\n", clp->dirname);
>>
>> @@ -1176,6 +1238,23 @@ handle_gssd_upcall(struct clnt_info *clp)
>>                goto out;
>>        }
>>
>> +       /* read supported encryption types if supplied */
>> +       if ((p = strstr(lbuf, "enctypes=")) != NULL) {
>> +               enctypes = malloc(lbuflen);
>> +               if (!enctypes)
>> +                       goto out;
>> +               if (sscanf(p, "enctypes=%s", enctypes) != 1) {
>> +                       printerr(0, "WARNING: handle_gssd_upcall: "
>> +                                   "failed to parse target name "
>> +                                   "in upcall string '%s'\n", lbuf);
>> +                       goto out;
>> +               }
>> +               if (parse_enctypes(enctypes) != 0) {
>> +                       printerr(0, "WARNING: handle_gssd_upcall: "
>> +                               "parsing encryption types failed: errno %d\n", code);
>> +               }
>> +       }
>> +
>>        /* read target name */
>>        if ((p = strstr(lbuf, "target=")) != NULL) {
>>                target = malloc(lbuflen);
>> diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c
>> index 1c10bd4..0f56b1d 100644
>> --- a/utils/gssd/krb5_util.c
>> +++ b/utils/gssd/krb5_util.c
>> @@ -1274,6 +1274,8 @@ limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid)
>>                                    ENCTYPE_DES_CBC_MD5,
>>                                    ENCTYPE_DES_CBC_MD4 };
>>        int num_enctypes = sizeof(enctypes) / sizeof(enctypes[0]);
>> +       extern int num_krb5_enctypes;
>> +       extern krb5_enctype *krb5_enctypes;
>>
>>        /* We only care about getting a krb5 cred */
>>        desired_mechs.count = 1;
>> @@ -1290,8 +1292,18 @@ limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid)
>>                return -1;
>>        }
>>
>> -       maj_stat = gss_set_allowable_enctypes(&min_stat, credh, &krb5oid,
>> -                                            num_enctypes, &enctypes);
>> +       /*
>> +        * If we failed for any reason to produce global
>> +        * list of supported enctypes, use local default here.
>> +        */
>> +       if (krb5_enctypes == NULL)
>> +               maj_stat = gss_set_allowable_enctypes(&min_stat, credh,
>> +                                       &krb5oid, num_enctypes, &enctypes);
>> +       else
>> +               maj_stat = gss_set_allowable_enctypes(&min_stat, credh,
>> +                                       &krb5oid, num_krb5_enctypes,
>> +                                       krb5_enctypes);
>> +
>>        if (maj_stat != GSS_S_COMPLETE) {
>>                pgsserr("gss_set_allowable_enctypes",
>>                        maj_stat, min_stat, &krb5oid);
>> --
> 
> Hi Steve,
> 
> The global krb5_enctypes array was used when the list was being read
> once from a file.  With the list now coming up with each request in
> the updated upcall, I think the list obtained in the upcall should be
> added to the clnt_info structure and then passed to the
> limit_krb5_enctypes function as a parameter.
Six of one.... half a dozen of another... ;-)

But I do see there is a memory leak... I don't free the  enctypes
buffer in handle_gssd_upcall() :-\

I'll repost in a bit... 

steved.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/3] Try to use kernel function to determine supported Kerberos enctypes.
  2010-04-14 19:58   ` Kevin Coffman
       [not found]     ` <z2j4d569c331004141258y2f16a82ga1aa7826d665b3a9-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
@ 2010-04-15 11:58     ` Steve Dickson
  2010-04-15 13:25       ` Kevin Coffman
  1 sibling, 1 reply; 10+ messages in thread
From: Steve Dickson @ 2010-04-15 11:58 UTC (permalink / raw)
  To: Kevin Coffman; +Cc: linux-nfs

Hey Kevin,

On 04/14/2010 03:58 PM, Kevin Coffman wrote:
> 
> The global krb5_enctypes array was used when the list was being read
> once from a file.  With the list now coming up with each request in
> the updated upcall, I think the list obtained in the upcall should be
> added to the clnt_info structure and then passed to the
> limit_krb5_enctypes function as a parameter.
I took a look at move the krb5_enctypes array in to the clnt_info structure
and I'm thinking it might be better to keep it as global variable. 
Here is my reasoning... 

The "enctypes=" string that comes up in the upcall is basically a 
static string. Yeah I know it could change but that's highly unlikely
any time soon. So if we put the krb5_enctypes array in the clnt_info
structure we would have to parse that (static) string on *every* upcall,
since the clnt_info structures are dynamically allocated. So
parsing a static string on every upcall does not make sense to me.

Keeping the supported enctypes in a global variable allow us to
parse the string once and when it changes (which will never happen
dynamically). So if the first enctypes values are cached, all that
parsing become a simple strcmp()... ala:
 
+parse_enctypes(char *enctypes)
+{
+	int n = 0;
+	char *curr, *comma;
+	int i;
+	static char *cached_types;
+
+	if (cached_types && strcmp(cached_types, enctypes) == 0)
+		return 0;


Makes sense? Am I missing something??

steved.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 2/3] Try to use kernel function to determine supported Kerberos enctypes (Updated)
  2010-04-14 19:18 ` [PATCH 2/3] Try to use kernel function to determine supported Kerberos enctypes steved
  2010-04-14 19:58   ` Kevin Coffman
@ 2010-04-15 12:45   ` Steve Dickson
  1 sibling, 0 replies; 10+ messages in thread
From: Steve Dickson @ 2010-04-15 12:45 UTC (permalink / raw)
  To: linux-nfs

I did notice the following problems with this patch.
 
1) I was not freeing enctypes in handle_gssd_upcall()
  
diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c
index 50a27e4..12e11d5 100644
--- a/utils/gssd/gssd_proc.c
+++ b/utils/gssd/gssd_proc.c
@@ -1301,7 +1301,6 @@ handle_gssd_upcall(struct clnt_info *clp)
 out:
        free(lbuf);
        free(mech);
-       free(enctypes);
        free(target);
        free(service);
        return; 

 2) gss_set_allowable_enctypes last arugment is a void *
      not a void **

diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c
index dccbeb6..0f56b1d 100644
--- a/utils/gssd/krb5_util.c
+++ b/utils/gssd/krb5_util.c
@@ -1298,10 +1298,11 @@ limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid)
         */
        if (krb5_enctypes == NULL)
                maj_stat = gss_set_allowable_enctypes(&min_stat, credh,
-                                       &krb5oid, num_enctypes, enctypes);
+                                       &krb5oid, num_enctypes, &enctypes);
        else
                maj_stat = gss_set_allowable_enctypes(&min_stat, credh,
-                                       &krb5oid, num_krb5_enctypes, krb5_enctypes);
+                                       &krb5oid, num_krb5_enctypes,
+                                       krb5_enctypes);

Here is the entire updated patch...


Author: Kevin Coffman <kwc@citi.umich.edu>
Date:   Thu Apr 15 08:10:07 2010 -0400

    gssd: move function limit_krb5_enctypes into the exported functions area
    
    cleanup: Move function limit_krb5_enctypes() from the section
    containing static functions into the section containing
    externally visible functions.
    
    Signed-off-by: Steve Dickson <steved@redhat.com>

diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c
index be4fb11..50a27e4 100644
--- a/utils/gssd/gssd_proc.c
+++ b/utils/gssd/gssd_proc.c
@@ -600,6 +600,67 @@ update_client_list(void)
 	return retval;
 }
 
+/* Encryption types supported by the kernel rpcsec_gss code */
+int num_krb5_enctypes = 0;
+krb5_enctype *krb5_enctypes = NULL;
+
+/*
+ * Parse the supported encryption type information
+ */
+static int
+parse_enctypes(char *enctypes)
+{
+	int n = 0;
+	char *curr, *comma;
+	int i;
+	static char *cached_types;
+
+	if (cached_types && strcmp(cached_types, enctypes) == 0)
+		return 0;
+	free(cached_types);
+
+	if (krb5_enctypes != NULL) {
+		free(krb5_enctypes);
+		krb5_enctypes = NULL;
+		num_krb5_enctypes = 0;
+	}
+
+	/* count the number of commas */
+	for (curr = enctypes; curr && *curr != '\0'; curr = ++comma) {
+		comma = strchr(curr, ',');
+		if (comma != NULL)
+			n++;
+		else
+			break;
+	}
+	/* If no more commas and we're not at the end, there's one more value */
+	if (*curr != '\0')
+		n++;
+
+	/* Empty string, return an error */
+	if (n == 0)
+		return ENOENT;
+
+	/* Allocate space for enctypes array */
+	if ((krb5_enctypes = (int *) calloc(n, sizeof(int))) == NULL) {
+		return ENOMEM;
+	}
+
+	/* Now parse each value into the array */
+	for (curr = enctypes, i = 0; curr && *curr != '\0'; curr = ++comma) {
+		krb5_enctypes[i++] = atoi(curr);
+		comma = strchr(curr, ',');
+		if (comma == NULL)
+			break;
+	}
+
+	num_krb5_enctypes = n;
+	if (cached_types = malloc(strlen(enctypes)+1))
+		strcpy(cached_types, enctypes);
+
+	return 0;
+}
+
 static int
 do_downcall(int k5_fd, uid_t uid, struct authgss_private_data *pd,
 	    gss_buffer_desc *context_token)
@@ -1128,11 +1189,12 @@ handle_gssd_upcall(struct clnt_info *clp)
 {
 	uid_t			uid;
 	char			*lbuf = NULL;
-	int			lbuflen = 0;
+	int			lbuflen = 0, code;
 	char			*p;
 	char			*mech = NULL;
 	char			*target = NULL;
 	char			*service = NULL;
+	char			*enctypes = NULL;
 
 	printerr(1, "handling gssd upcall (%s)\n", clp->dirname);
 
@@ -1176,6 +1238,23 @@ handle_gssd_upcall(struct clnt_info *clp)
 		goto out;
 	}
 
+	/* read supported encryption types if supplied */
+	if ((p = strstr(lbuf, "enctypes=")) != NULL) {
+		enctypes = malloc(lbuflen);
+		if (!enctypes)
+			goto out;
+		if (sscanf(p, "enctypes=%s", enctypes) != 1) {
+			printerr(0, "WARNING: handle_gssd_upcall: "
+				    "failed to parse target name "
+				    "in upcall string '%s'\n", lbuf);
+			goto out;
+		}
+		if (parse_enctypes(enctypes) != 0) {
+			printerr(0, "WARNING: handle_gssd_upcall: "
+				"parsing encryption types failed: errno %d\n", code);
+		}
+	}
+
 	/* read target name */
 	if ((p = strstr(lbuf, "target=")) != NULL) {
 		target = malloc(lbuflen);
@@ -1222,6 +1301,7 @@ handle_gssd_upcall(struct clnt_info *clp)
 out:
 	free(lbuf);
 	free(mech);
+	free(enctypes);
 	free(target);
 	free(service);
 	return;	
diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c
index 1c10bd4..dccbeb6 100644
--- a/utils/gssd/krb5_util.c
+++ b/utils/gssd/krb5_util.c
@@ -1274,6 +1274,8 @@ limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid)
 				    ENCTYPE_DES_CBC_MD5,
 				    ENCTYPE_DES_CBC_MD4 };
 	int num_enctypes = sizeof(enctypes) / sizeof(enctypes[0]);
+	extern int num_krb5_enctypes;
+	extern krb5_enctype *krb5_enctypes;
 
 	/* We only care about getting a krb5 cred */
 	desired_mechs.count = 1;
@@ -1290,8 +1292,17 @@ limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid)
 		return -1;
 	}
 
-	maj_stat = gss_set_allowable_enctypes(&min_stat, credh, &krb5oid,
-					     num_enctypes, &enctypes);
+	/*
+	 * If we failed for any reason to produce global
+	 * list of supported enctypes, use local default here.
+	 */
+	if (krb5_enctypes == NULL)
+		maj_stat = gss_set_allowable_enctypes(&min_stat, credh,
+					&krb5oid, num_enctypes, enctypes);
+	else
+		maj_stat = gss_set_allowable_enctypes(&min_stat, credh,
+					&krb5oid, num_krb5_enctypes, krb5_enctypes);
+
 	if (maj_stat != GSS_S_COMPLETE) {
 		pgsserr("gss_set_allowable_enctypes",
 			maj_stat, min_stat, &krb5oid);


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 2/3] Try to use kernel function to determine supported Kerberos enctypes.
  2010-04-15 11:58     ` Steve Dickson
@ 2010-04-15 13:25       ` Kevin Coffman
  0 siblings, 0 replies; 10+ messages in thread
From: Kevin Coffman @ 2010-04-15 13:25 UTC (permalink / raw)
  To: Steve Dickson; +Cc: linux-nfs

On Thu, Apr 15, 2010 at 7:58 AM, Steve Dickson <SteveD@redhat.com> wrote:
> Hey Kevin,
>
> On 04/14/2010 03:58 PM, Kevin Coffman wrote:
>>
>> The global krb5_enctypes array was used when the list was being read
>> once from a file.  With the list now coming up with each request in
>> the updated upcall, I think the list obtained in the upcall should be
>> added to the clnt_info structure and then passed to the
>> limit_krb5_enctypes function as a parameter.
> I took a look at move the krb5_enctypes array in to the clnt_info structure
> and I'm thinking it might be better to keep it as global variable.
> Here is my reasoning...
>
> The "enctypes=" string that comes up in the upcall is basically a
> static string. Yeah I know it could change but that's highly unlikely
> any time soon. So if we put the krb5_enctypes array in the clnt_info
> structure we would have to parse that (static) string on *every* upcall,
> since the clnt_info structures are dynamically allocated. So
> parsing a static string on every upcall does not make sense to me.
>
> Keeping the supported enctypes in a global variable allow us to
> parse the string once and when it changes (which will never happen
> dynamically). So if the first enctypes values are cached, all that
> parsing become a simple strcmp()... ala:
>
> +parse_enctypes(char *enctypes)
> +{
> +       int n = 0;
> +       char *curr, *comma;
> +       int i;
> +       static char *cached_types;
> +
> +       if (cached_types && strcmp(cached_types, enctypes) == 0)
> +               return 0;
>
>
> Makes sense? Am I missing something??
>
> steved.

I originally missed the addition of cached_types.  I guess this is fine.

K.C.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/3] nfs-utils: Adds support for more encryption types.
  2010-04-14 19:18 [PATCH 0/3] nfs-utils: Adds support for more encryption types steved
                   ` (2 preceding siblings ...)
  2010-04-14 19:18 ` [PATCH 3/3] Add support for non-DES encryption types steved
@ 2010-04-16 17:53 ` Steve Dickson
  3 siblings, 0 replies; 10+ messages in thread
From: Steve Dickson @ 2010-04-16 17:53 UTC (permalink / raw)
  To: linux-nfs



On 04/14/2010 03:18 PM, steved@redhat.com wrote:
> From: Steve Dickson <steved@redhat.com>
> 
> These three gssd patches added support for more DES and non-DES
> encryption types. They were authored by Kevin Coffman and tested
> by me on several recent kernels. 
> 
> Kevin Coffman (3):
>   gssd: move function limit_krb5_enctypes into the exported functions area
>   Try to use kernel function to determine supported Kerberos enctypes.
>   Add support for non-DES encryption types.
Committed and pushed...

steved.

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2010-04-16 17:53 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-04-14 19:18 [PATCH 0/3] nfs-utils: Adds support for more encryption types steved
2010-04-14 19:18 ` [PATCH 1/3] gssd: move function limit_krb5_enctypes into the exported functions area steved
2010-04-14 19:18 ` [PATCH 2/3] Try to use kernel function to determine supported Kerberos enctypes steved
2010-04-14 19:58   ` Kevin Coffman
     [not found]     ` <z2j4d569c331004141258y2f16a82ga1aa7826d665b3a9-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2010-04-14 20:05       ` Steve Dickson
2010-04-15 11:58     ` Steve Dickson
2010-04-15 13:25       ` Kevin Coffman
2010-04-15 12:45   ` [PATCH 2/3] Try to use kernel function to determine supported Kerberos enctypes (Updated) Steve Dickson
2010-04-14 19:18 ` [PATCH 3/3] Add support for non-DES encryption types steved
2010-04-16 17:53 ` [PATCH 0/3] nfs-utils: Adds support for more " Steve Dickson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.