From 16f151834e63d8df9f852b7e265f17c689553c35 Mon Sep 17 00:00:00 2001
From: Michael Weiser <weiser@science-computing.de>
Date: Mon, 16 Apr 2012 06:49:21 -0400
Subject: [PATCH] Add -l option to gssd to force legacy behaviour

Implement a new option -l to force gssd to ignore its kernel's crypto
capabilities and use just the Single DES legacy encryption types to be
compatible with old servers. This is only relevant if those servers have
strong keys in their keytab.

Signed-off-by: Steve Dickson <steved@redhat.com>
Tested-by: Michael Weiser <weiser@science-computing.de>
Signed-off-by: Petr Uzel <petr.uzel@suse.cz>
---
 utils/gssd/gssd.c      |   11 +++++++++--
 utils/gssd/gssd.man    |   26 +++++++++++++++++++++++++-
 utils/gssd/krb5_util.c |    6 +++++-
 utils/gssd/krb5_util.h |    1 +
 4 files changed, 40 insertions(+), 4 deletions(-)

Index: nfs-utils-1.2.3/utils/gssd/gssd.c
===================================================================
--- nfs-utils-1.2.3.orig/utils/gssd/gssd.c
+++ nfs-utils-1.2.3/utils/gssd/gssd.c
@@ -85,7 +85,7 @@ sig_hup(int signal)
 static void
 usage(char *progname)
 {
-	fprintf(stderr, "usage: %s [-f] [-M] [-n] [-v] [-r] [-D] [-p pipefsdir] [-k keytab] [-d ccachedir] [-t timeout] [-R preferred realm]\n",
+	fprintf(stderr, "usage: %s [-f] [-l] [-M] [-n] [-v] [-r] [-D] [-p pipefsdir] [-k keytab] [-d ccachedir] [-t timeout] [-R preferred realm]\n",
 		progname);
 	exit(1);
 }
@@ -102,7 +102,7 @@ main(int argc, char *argv[])
 	char *progname;
 
 	memset(ccachesearch, 0, sizeof(ccachesearch));
-	while ((opt = getopt(argc, argv, "DfvrmnMp:k:d:t:R:")) != -1) {
+	while ((opt = getopt(argc, argv, "DfvrlmnMp:k:d:t:R:")) != -1) {
 		switch (opt) {
 			case 'f':
 				fg = 1;
@@ -146,6 +146,13 @@ main(int argc, char *argv[])
 			case 'D':
 				avoid_dns = 0;
 				break;
+			case 'l':
+#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
+				limit_to_legacy_enctypes = 1;
+#else 
+				errx(1, "Setting encryption type not support by Kerberos libraries.");
+#endif
+				break;
 			default:
 				usage(argv[0]);
 				break;
Index: nfs-utils-1.2.3/utils/gssd/gssd.man
===================================================================
--- nfs-utils-1.2.3.orig/utils/gssd/gssd.man
+++ nfs-utils-1.2.3/utils/gssd/gssd.man
@@ -6,7 +6,7 @@
 .SH NAME
 rpc.gssd \- rpcsec_gss daemon
 .SH SYNOPSIS
-.B "rpc.gssd [-f] [-n] [-D] [-k keytab] [-p pipefsdir] [-v] [-r] [-d ccachedir]"
+.B "rpc.gssd [-f] [-n] [-D] [-k keytab] [-l] [-p pipefsdir] [-v] [-r] [-d ccachedir]"
 .SH DESCRIPTION
 The rpcsec_gss protocol gives a means of using the gss-api generic security
 api to provide security for protocols using rpc (in particular, nfs).  Before
@@ -65,6 +65,30 @@ for "machine credentials" is now:
 .br
   host/<anyname>@<REALM>
 .TP
+.B -l
+Tells
+.B rpc.gssd
+to limit session keys to Single DES even if the kernel supports stronger
+encryption types. Service ticket encryption is still governed by what
+the KDC believes the target server supports. This way the client can
+access a server that has strong keys in its keytab for ticket decryption
+but whose kernel only supports Single DES.
+.IP
+The alternative is to put only Single DES keys in the server's keytab
+and limit encryption types for its principal to Single DES on the KDC
+which will cause service tickets for this server to be encrypted using
+only Single DES and (as a side-effect) contain only Single DES session
+keys.
+.IP
+This legacy behaviour is only required for older servers
+(pre nfs-utils-1.2.4). If the server has a recent kernel, Kerberos
+implementation and nfs-utils it will work just fine with stronger
+encryption.
+.IP
+.B Note:
+This option is only available with Kerberos libraries that 
+support setable encryption types.
+.TP
 .B -p path
 Tells
 .B rpc.gssd
Index: nfs-utils-1.2.3/utils/gssd/krb5_util.c
===================================================================
--- nfs-utils-1.2.3.orig/utils/gssd/krb5_util.c
+++ nfs-utils-1.2.3/utils/gssd/krb5_util.c
@@ -129,6 +129,10 @@
 /* Global list of principals/cache file names for machine credentials */
 struct gssd_k5_kt_princ *gssd_k5_kt_princ_list = NULL;
 
+#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
+int limit_to_legacy_enctypes = 0;
+#endif
+
 /*==========================*/
 /*===  Internal routines ===*/
 /*==========================*/
@@ -1316,7 +1320,7 @@ limit_krb5_enctypes(struct rpc_gss_sec *
 	 * If we failed for any reason to produce global
 	 * list of supported enctypes, use local default here.
 	 */
-	if (krb5_enctypes == NULL)
+	if (krb5_enctypes == NULL || limit_to_legacy_enctypes)
 		maj_stat = gss_set_allowable_enctypes(&min_stat, credh,
 					&krb5oid, num_enctypes, enctypes);
 	else
Index: nfs-utils-1.2.3/utils/gssd/krb5_util.h
===================================================================
--- nfs-utils-1.2.3.orig/utils/gssd/krb5_util.h
+++ nfs-utils-1.2.3/utils/gssd/krb5_util.h
@@ -36,6 +36,7 @@ char *gssd_k5_err_msg(krb5_context conte
 void gssd_k5_get_default_realm(char **def_realm);
 
 #ifdef HAVE_SET_ALLOWABLE_ENCTYPES
+extern int limit_to_legacy_enctypes;
 int limit_krb5_enctypes(struct rpc_gss_sec *sec);
 #endif
 
