[ossh patch] principal name/patterns in authorized_keys2

Nicolas Williams Nicolas.Williams at ubsw.com
Thu Aug 16 07:03:34 EST 2001


As you know, revoking RSA/DSA keys in an SSH environment requires
editing all authorized_keys and authorized_keys2 files that reference
those public keys. This is, well, difficult at best but certainly very
obnoxious, particularly in a large environment.

SSH key management is difficult. This patch simplifies key management
wherever GSS-API/Kerberos is used and is general enough to be used with
any authentication system that binds keys and names securely enough.

Other GSS-API mechanisms and Kerberos IV can be supported as well.

This patch adds support for referencing named keys (not SSH RSA/DSA,
but Kerberos) in authorized_keys2.

Here's some example authorized_keys2 entries:

ssh-ext-named:krb5 someuser at FOOBAR.COM
deny-access ssh-ext-named:krb5 loser at FOOBAR.COM

ssh-ext-name-pat:krb5 */superroot at FOOBAR.COM

command=/tools/inventory ssh-ext-name-pat:krb5 */inventory at FOOBAR.COM
command=/tools/audit ssh-ext-name-pat:krb5 */audit at FOOBAR.COM
...

What's cool about this is that administrators come and go, and so will
those */superroot at FOOBAR.COM Kerberos principals, but there's no need to
modify those authorized_keys2 files referencing those keys.

This patch (to OpenSSH 2.9p2) adds:

 - ssh-ext-named	key entry type for authorized_keys2 files
 - ssh-ext-name-pat	key entry type for authorized_keys2 files

 - deny-access		option for authorized_keys2 entries

 - SSH_AUTH_EXT_NAME		environment variable added by sshd
 - SSH_AUTH_EXT_NAME_TYPE	similar

You'll need Simon Wilkinson's GSS-API patches for OpenSSH for this patch
to be much use, or add support for Kerberos IV key names (a trivial
patch, but I can't test it).

I really hope that this feature or a variation thereof will find its way
into OpenSSH. In conjunction with Kerberos (IV or V) it can be extremely
useful:

 - key management is simplified: key management is done at the KDC and
   there is no need to edit authorized_keys2 files all over to revoke
   keys!

 - authorized_keys2 is *much* more featureful than .klogin and .k5login
   are, regardless of Kerberos implementation source (KTH, Heimdal, MIT,
   SEAM, all implement pretty much the same all-or-nothing
   .klogin/.k5login functionality).

A similar patch of gss-serv.c:ssh_gssapi_gsi_userok() to support the
use of 'gsi' key names in authorized_keys2 would be trivial, but I
cannot test GSI.

A similar patch to auth-krb4.c:auth_krb4() to support the use of 'krb4'
key names would be trivial, but I cannot test such a patch.

A question, in my mind, is whether the krb4/gss:krb5/gss:gsi ssh_*userok()
code should require both, authorized_keys2 check *and* the underlying
mechanism userok() check to succeed, or either, or what. My patch to
gss-serv.c:ssh_gssapi_krb5_userok() requires either check to succeed.

Below you should find two versions of this patch, one against OpenSSH
2.9p2, the other against 2.9p2 + Simon Wilkinson's GSS-API patches (*).

NOTE: I did not strive too hard to keep to the code style of OpenSSH.
      Point me a the description of the OpenSSH code style and I'll
      modify my patch accordingly.

Files modified:

 - key.h
    - added KEY_NAME key type
    - added KEY_NAME_PAT key type
    - added name, name_len and name_type fields to the Key struct
	(I realize that the name_len field is useless, I may remove it)
    - added prototype for key_match()

 - key.c
    - added initialization/finalization of new Key fields to key_new()/key_free()
    - added named/pattern key type support to a variety of functions,
      including key_read() and key_write(), among others
    - added key_match() implementation

 - auth-options.h
    - added void auth_set_key_env(Key *) prototype

 - auth-options.c
    - added auth_set_key_env() implementation
    - modified auth_parse_options() to return (-1) when new deny-access
      option is encountered

 - auth-rsa.c
    - modified auth_parse_options() return value check according to the
      change made to auth_parse_options()

 - auth2.c
    - modified user_key_allowed() to:
       - try key_match() if key_equal() fails
       - check the result of auth_parse_options() for negative, 0, or
         positive values.
    - modified userauth_pubkey() to check for positive return value of
      user_key_allowed()

 - sshd.8
    - added documentation

 - gss-serv.c
    - modified ssh_gssapi_krb5_userok() to build a Key struct and 
      call user_key_allowed()
    - modified input_gssapi_token() and input_gssapi_exchange_complete()
      to log successful authentication correctly.

(*) You can get Simon Wilkinson's GSS-API patches for OpenSSH here:

	http://www.sxw.org.uk/computing/patches/openssh.html

There are four weaknesses with this patch that I am aware of currently:

 - while key names can be [double-]quoted, double-quotes in key names
   cannot be backslash-quoted

 - the name_len field added to the Key struct is unnecessary

 - there should be a way to limit the greediness of '*' in key name
   globs, with something like "*{/}" meaning "any number of characters
   upto a '/'"

 - the name_type of Key structs for Kerberos V principals should reflect
   the type of the Kerberos principal name (see RFC1510 and revisions)
   so that the name_type of ssh-ext-named/pattern authorized_keys2 entries
   should look something like: "krb5user", "krb5host", "krb5x500", etc...


Feedback would be greatly appreciated!

Nico

-DISCLAIMER: an automatically appended disclaimer may follow. By posting-
-to a public e-mail mailing list I hereby grant permission to distribute-
-and copy this message.-

********************************************************************************

Index: 2_9_p2.1/sshd.8
--- 2_9_p2.1/sshd.8 Thu, 03 May 2001 16:12:13 -0400 jd (OpenSSH/h/28_sshd.8 1.1 644)
+++ 2_9_p2_w_named_keys.2/sshd.8 Tue, 03 Jul 2001 14:20:28 -0400 willian (OpenSSH/h/28_sshd.8 1.1.1.1 644)
@@ -852,7 +852,8 @@
 .Pa $HOME/.ssh/authorized_keys2
 file lists the DSA and RSA keys that are
 permitted for public key authentication (PubkeyAuthentication)
-in protocol version 2.
+in protocol version 2. It can also list key names or key patterns
+for external authentication systems, such as krb4, krb5, gsi, etc...
 .Pp
 Each line of the file contains one
 key (empty lines and lines starting with a
@@ -873,7 +874,19 @@
 For protocol version 2 the keytype is
 .Dq ssh-dss
 or
-.Dq ssh-rsa .
+.Dq ssh-rsa
+or
+.Dq ssh-ext-named:<keytype>
+or
+.Dq ssh-ext-name-pat:<keytype> .
+.Pp
+Named keys and key name patterns follow the latter two, in double
+quotes if they contain whitespace. Named key types may include:
+.Dq krb4 ,
+.Dq krb5
+and/or
+.Dq gsi ,
+depending on what features are compiled in to OpenSSH.
 .Pp
 Note that lines in this file are usually several hundred bytes long
 (because of the size of the RSA key modulus).
@@ -930,6 +943,10 @@
 Environment variables set this way
 override other default environment values.
 Multiple options of this type are permitted.
+.It Cm deny-access
+This option ends authorized_keys2 processing if the key matches. This
+option is only really useful with named key and named key pattern
+entries.
 .It Cm no-port-forwarding
 Forbids TCP/IP forwarding when this key is used for authentication.
 Any port forward requests by the client will return an error.
Index: 2_9_p2.1/key.h
--- 2_9_p2.1/key.h Thu, 03 May 2001 16:12:13 -0400 jd (OpenSSH/j/7_key.h 1.1 644)
+++ 2_9_p2_w_named_keys.2/key.h Tue, 03 Jul 2001 13:57:30 -0400 willian (OpenSSH/j/7_key.h 1.1.1.1 644)
@@ -34,7 +34,9 @@
 	KEY_RSA1,
 	KEY_RSA,
 	KEY_DSA,
-	KEY_UNSPEC
+	KEY_UNSPEC,
+	KEY_NAME,
+	KEY_NAME_PAT
 };
 enum fp_type {
 	SSH_FP_SHA1,
@@ -48,12 +50,16 @@
 	int	type;
 	RSA	*rsa;
 	DSA	*dsa;
+	u_char	*name;
+	u_int	name_len;
+	char	*name_type;
 };
 
 Key	*key_new(int type);
 Key	*key_new_private(int type);
 void	key_free(Key *k);
 int	key_equal(Key *a, Key *b);
+int	key_match(Key *a, Key *b);
 char	*key_fingerprint(Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep);
 char	*key_type(Key *k);
 int	key_write(Key *key, FILE *f);
Index: 2_9_p2.1/key.c
--- 2_9_p2.1/key.c Thu, 03 May 2001 16:12:13 -0400 jd (OpenSSH/j/8_key.c 1.1 644)
+++ 2_9_p2_w_named_keys.2/key.c Tue, 03 Jul 2001 13:57:30 -0400 willian (OpenSSH/j/8_key.c 1.1.1.1 644)
@@ -56,6 +56,9 @@
 	k->type = type;
 	k->dsa = NULL;
 	k->rsa = NULL;
+	k->name = NULL;
+	k->name_len = 0;
+	k->name_type = NULL;
 	switch (k->type) {
 	case KEY_RSA1:
 	case KEY_RSA:
@@ -72,6 +75,8 @@
 		dsa->pub_key = BN_new();
 		k->dsa = dsa;
 		break;
+	case KEY_NAME:
+	case KEY_NAME_PAT:
 	case KEY_UNSPEC:
 		break;
 	default:
@@ -119,6 +124,14 @@
 			DSA_free(k->dsa);
 		k->dsa = NULL;
 		break;
+	case KEY_NAME:
+	case KEY_NAME_PAT:
+		if (k->name != NULL)
+			xfree(k->name);
+		k->name_len = 0;
+		if (k->name_type != NULL)
+			xfree(k->name_type);
+		break;
 	case KEY_UNSPEC:
 		break;
 	default:
@@ -130,8 +143,9 @@
 int
 key_equal(Key *a, Key *b)
 {
-	if (a == NULL || b == NULL || a->type != b->type)
+	if (a == NULL || b == NULL || a->type != b->type) {
 		return 0;
+	}
 	switch (a->type) {
 	case KEY_RSA1:
 	case KEY_RSA:
@@ -146,12 +160,67 @@
 		    BN_cmp(a->dsa->g, b->dsa->g) == 0 &&
 		    BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0;
 		break;
+	case KEY_NAME:
+		if ((a->name_type == NULL && b->name_type == NULL) ||
+		    (a->name_type == b->name_type))
+			return (a->name_len == b->name_len) &&
+			    (memcmp(a->name, b->name, a->name_len) == 0);
+		if (a->name_type == NULL || b->name_type == NULL)
+			return 0;
+		if (strcmp(a->name_type, b->name_type) == 0)
+			return (a->name_len == b->name_len) &&
+			    (memcmp(a->name, b->name, a->name_len) == 0);
+		break;
+	case KEY_NAME_PAT:
+		return 0;
+		break;
 	default:
 		fatal("key_equal: bad key type %d", a->type);
 		break;
 	}
 	return 0;
 }
+int
+key_match(Key *a, Key *b)
+{
+	debug3("key_match: trying to match %x and %x", a, b);
+	if (a == NULL || b == NULL)
+		return 0;
+
+	debug3("key_match: trying to match key types %d and %d -- KEY_NAME_PAT == %d", a->type, b->type, KEY_NAME_PAT);
+	/* One key must be a name pattern, the other must be a name */
+	if (!(a->type == KEY_NAME_PAT && b->type == KEY_NAME) &&
+	    !(b->type == KEY_NAME_PAT && a->type == KEY_NAME))
+		return 0;
+	
+	/* Both keys must have name types, or both must not */
+	/* or one key must have '*' as its name type        */
+	if ((a->name_type == NULL && b->name_type != NULL) ||
+	    (b->name_type == NULL && a->name_type != NULL)) {
+
+		debug3("key_match: foo");
+		if (a->name_type != NULL && *(a->name_type) != '*')
+			return 0;
+		if (b->name_type != NULL && *(b->name_type) != '*')
+			return 0;
+	}
+
+	/* Name type "*" matches any name type */
+	/* Otherwise name types must match */
+	if ((a->name_type != NULL && strcmp(a->name_type, b->name_type) != 0) &&
+	    (*(a->name_type) != '*' || *(b->name_type) != '*')) {
+		debug3("key_match: a->name_type == %s", a->name_type ? a->name_type : "");
+		debug3("key_match: b->name_type == %s", b->name_type ? b->name_type : "");
+		return 0;
+	    }
+
+	debug3("key_match: trying to match %s WITH %s", a->name, b->name);
+	if (a->type == KEY_NAME_PAT)
+		return match_pattern(b->name, a->name);
+	else
+		return match_pattern(a->name, b->name);
+}
+
 
 u_char*
 key_fingerprint_raw(Key *k, enum fp_type dgst_type, size_t *dgst_raw_length)
@@ -160,7 +229,7 @@
 	EVP_MD_CTX ctx;
 	u_char *blob = NULL;
 	u_char *retval = NULL;
-	int len = 0;
+	u_int len = 0;
 	int nlen, elen;
 
 	*dgst_raw_length = 0;
@@ -363,11 +432,12 @@
 {
 	Key *k;
 	int success = -1;
-	char *cp, *space;
+	char *cp, *space, *name_type;
 	int len, n, type;
 	u_int bits;
-	u_char *blob;
+	u_char *blob = NULL;
 
+	name_type = NULL;
 	cp = *cpp;
 
 	switch(ret->type) {
@@ -390,6 +460,8 @@
 	case KEY_UNSPEC:
 	case KEY_RSA:
 	case KEY_DSA:
+	case KEY_NAME:
+	case KEY_NAME_PAT:
 		space = strchr(cp, ' ');
 		if (space == NULL) {
 			debug3("key_read: no space");
@@ -397,6 +469,17 @@
 		}
 		*space = '\0';
 		type = key_type_from_name(cp);
+		if ((type == KEY_NAME) || (type == KEY_NAME_PAT)) {
+			char * colon = NULL;
+			
+			colon = strchr(cp, ':');
+
+			debug3("key_read: handling named key or pattern (%d), %s, colon at %x", type, cp, colon);
+			if (colon != NULL && *(++colon) != '\0') {
+				name_type = xstrdup(colon);
+			} else
+				name_type == NULL;
+		}
 		*space = ' ';
 		if (type == KEY_UNSPEC) {
 			debug3("key_read: no key found");
@@ -410,30 +493,80 @@
 		if (ret->type == KEY_UNSPEC) {
 			ret->type = type;
 		} else if (ret->type != type) {
-			/* is a key, but different type */
-			debug3("key_read: type mismatch");
-			return 0;
+			if (! ((ret->type == KEY_NAME) &&
+			       type ==  KEY_NAME_PAT)) {
+				/* is a key, but different type */
+				debug3("key_read: type mismatch");
+				return 0;
+			}
+			ret->type = type;
 		}
-		len = 2*strlen(cp);
-		blob = xmalloc(len);
-		n = uudecode(cp, blob, len);
-		if (n < 0) {
-			error("key_read: uudecode %s failed", cp);
-			return -1;
+		debug3("key_read: here -- ret->type == %d", ret->type);
+		if ((ret->type == KEY_NAME) || (ret->type == KEY_NAME_PAT)) {
+			char *quote, *newline;
+			debug3("key_read: reading named key %s", cp);
+			if (cp == NULL || *cp == '\0')
+				return 0;
+			if (*cp == '"') {
+				quote = strchr(++cp, '"');
+				if (quote == NULL) {
+					debug3("key_read: missing quote");
+					return 0;
+				}
+				*quote = '\0';
+			}
+			newline = strchr(cp, '\n');
+			if (newline != NULL)
+				*newline = '\0';
+			debug3("key_read: reading named key %s", cp);
+			k = key_new(ret->type);
+			k->name = (unsigned char *) xstrdup(cp);
+			k->name_len = strlen(cp);
+			k->name_type = name_type;
+			if (newline !=NULL)
+				*newline = '\n';
+			if (quote !=NULL)
+				*quote = '"';
+			debug3("key_read: read named key %s", k->name_type);
+		} else {
+			len = 2*strlen(cp);
+			blob = xmalloc(len);
+			n = uudecode(cp, blob, len);
+			if (n < 0) {
+				error("key_read: uudecode %s failed", cp);
+				return -1;
+			}
+			debug3("key_read: reading uuencoded key %s", blob);
+			k = key_from_blob(blob, n);
 		}
-		k = key_from_blob(blob, n);
 		if (k == NULL) {
 			error("key_read: key_from_blob %s failed", cp);
 			return -1;
 		}
-		xfree(blob);
+		if (blob != NULL)
+			xfree(blob);
 		if (k->type != type) {
-			error("key_read: type mismatch: encoding error");
-			key_free(k);
-			return -1;
+			if (! ((ret->type == KEY_NAME) &&
+			       type ==  KEY_NAME_PAT)) {
+				error("key_read: type mismatch: encoding error");
+				key_free(k);
+				return -1;
+			}
 		}
 /*XXXX*/
-		if (ret->type == KEY_RSA) {
+		if ((ret->type == KEY_NAME) || (ret->type == KEY_NAME_PAT)) {
+			/*
+			if (ret->name != NULL)
+				xfree(ret->name);
+			 */
+			ret->name = k->name;
+			ret->name_len = k->name_len;
+			ret->name_type = k->name_type;
+			k->name = NULL;
+			k->name_type = NULL;
+			k->name_len = 0;
+			success = 1;
+		} else if (ret->type == KEY_RSA) {
 			if (ret->rsa != NULL)
 				RSA_free(ret->rsa);
 			ret->rsa = k->rsa;
@@ -487,7 +620,7 @@
 		}
 	} else if ((key->type == KEY_DSA && key->dsa != NULL) ||
 	    (key->type == KEY_RSA && key->rsa != NULL)) {
-		int len, n;
+		u_int len, n;
 		u_char *blob, *uu;
 		key_to_blob(key, &blob, &len);
 		uu = xmalloc(2*len);
@@ -498,6 +631,14 @@
 		}
 		xfree(blob);
 		xfree(uu);
+	} else if (key->type == KEY_NAME && key->name != NULL &&
+		   key->name_len) {
+
+		fprintf(f, "%s ", key_ssh_name(key));
+		if (key->name_type != NULL)
+			fprintf(f, ":%s", key->name_type);
+		else
+			fprintf(f, " \"%.*s\"", key->name, key->name_len);
 	}
 	return success;
 }
@@ -514,6 +655,12 @@
 	case KEY_DSA:
 		return "DSA";
 		break;
+	case KEY_NAME:
+		return "Named";
+		break;
+	case KEY_NAME_PAT:
+		return "Name_Pattern";
+		break;
 	}
 	return "unknown";
 }
@@ -527,6 +674,12 @@
 	case KEY_DSA:
 		return "ssh-dss";
 		break;
+	case KEY_NAME:
+		return "ssh-ext-named";
+		break;
+	case KEY_NAME_PAT:
+		return "ssh-ext-name-pat";
+		break;
 	}
 	return "ssh-unknown";
 }
@@ -604,6 +757,16 @@
 		BN_copy(n->rsa->n, k->rsa->n);
 		BN_copy(n->rsa->e, k->rsa->e);
 		break;
+	case KEY_NAME:
+	case KEY_NAME_PAT:
+		n = key_new(k->type);
+		n->name_len = k->name_len;
+		n->name = xmalloc(k->name_len);
+		memcpy(n->name, k->name, n->name_len);
+		if (k->name_type) {
+			n->name_type = xstrdup(k->name_type);
+		}
+		break;
 	default:
 		fatal("key_from_private: unknown type %d", k->type);
 		break;
@@ -624,7 +787,16 @@
 		return KEY_RSA;
 	} else if (strcmp(name, "ssh-dss") == 0){
 		return KEY_DSA;
+	} else if (strcmp(name, "ssh-ext-named") == 0){
+		return KEY_NAME;
+	} else if (strncmp(name, "ssh-ext-named:", strlen("ssh-ext-named:")) == 0){
+		return KEY_NAME;
+	} else if (strcmp(name, "ssh-ext-name-pat") == 0){
+		return KEY_NAME_PAT;
+	} else if (strncmp(name, "ssh-ext-name-pat:", strlen("ssh-ext-name-pat:")) == 0){
+		return KEY_NAME_PAT;
 	}
+
 	debug2("key_type_from_name: unknown key type '%s'", name);
 	return KEY_UNSPEC;
 }
Index: 2_9_p2.1/auth2.c
--- 2_9_p2.1/auth2.c Thu, 03 May 2001 16:12:13 -0400 jd (OpenSSH/k/6_auth2.c 1.1 644)
+++ 2_9_p2_w_named_keys.2/auth2.c Tue, 03 Jul 2001 13:57:30 -0400 willian (OpenSSH/k/6_auth2.c 1.1.1.1 644)
@@ -491,7 +491,7 @@
 			buffer_dump(&b);
 #endif
 			/* test for correct signature */
-			if (user_key_allowed(authctxt->pw, key) &&
+			if (user_key_allowed(authctxt->pw, key) > 0 &&
 			    key_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1)
 				authenticated = 1;
 			buffer_clear(&b);
@@ -508,7 +508,7 @@
 			 * if a user is not allowed to login. is this an
 			 * issue? -markus
 			 */
-			if (user_key_allowed(authctxt->pw, key)) {
+			if (user_key_allowed(authctxt->pw, key) > 0) {
 				packet_start(SSH2_MSG_USERAUTH_PK_OK);
 				packet_put_string(pkalg, alen);
 				packet_put_string(pkblob, blen);
@@ -768,19 +768,36 @@
 				continue;
 			}
 		}
-		if (key_equal(found, key) &&
-		    auth_parse_options(pw, options, file, linenum) == 1) {
-			found_key = 1;
-			debug("matching key found: file %s, line %ld",
-			    file, linenum);
+		if (key_equal(found, key)) {
+			found_key = auth_parse_options(pw, options, file, linenum);
+			if (found_key == 0)
+				continue;
+			break;
+		}
+		if (key_match(found, key)) {
+			found_key = auth_parse_options(pw, options, file, linenum);
+			if (found_key == 0)
+				continue;
+			/* Special treatment for key name patterns belongs here */
 			break;
 		}
 	}
+
+done:
 	restore_uid();
 	fclose(f);
 	key_free(found);
-	if (!found_key)
+	if (found_key > 0) {
+		debug("matching key found: file %s, line %ld",
+		    file, linenum);
+		auth_set_key_env(key);
+	}
+	if (found_key == 0)
 		debug2("key not found");
+	if (found_key < 0) {
+		debug("user_key_allowed: matching deny key found: "
+		      "file %s, line %ld", file, linenum);
+	}
 	return found_key;
 }
 
Index: 2_9_p2.1/auth-rsa.c
--- 2_9_p2.1/auth-rsa.c Thu, 03 May 2001 16:12:13 -0400 jd (OpenSSH/k/15_auth-rsa.c 1.1 644)
+++ 2_9_p2_w_named_keys.2/auth-rsa.c Tue, 03 Jul 2001 13:57:30 -0400 willian (OpenSSH/k/15_auth-rsa.c 1.1.1.1 644)
@@ -259,7 +259,7 @@
 		 * If our options do not allow this key to be used,
 		 * do not send challenge.
 		 */
-		if (!auth_parse_options(pw, options, file, linenum))
+		if (auth_parse_options(pw, options, file, linenum) < 1)
 			continue;
 
 		/* Perform the challenge-response dialog for this key. */
Index: 2_9_p2.1/auth-options.h
--- 2_9_p2.1/auth-options.h Thu, 03 May 2001 16:12:13 -0400 jd (OpenSSH/k/21_auth-optio 1.1 644)
+++ 2_9_p2_w_named_keys.2/auth-options.h Tue, 03 Jul 2001 13:57:30 -0400 willian (OpenSSH/k/21_auth-optio 1.1.1.1 644)
@@ -16,6 +16,8 @@
 #ifndef AUTH_OPTIONS_H
 #define AUTH_OPTIONS_H
 
+#include "key.h"
+
 /* Linked list of custom environment strings */
 struct envstring {
 	struct envstring *next;
@@ -37,6 +39,9 @@
 int
 auth_parse_options(struct passwd *pw, char *options, char *file,
     u_long linenum);
+
+void
+auth_set_key_env(Key *k);
 
 /* reset options flags */
 void	auth_clear_options(void);
Index: 2_9_p2.1/auth-options.c
--- 2_9_p2.1/auth-options.c Thu, 03 May 2001 16:12:13 -0400 jd (OpenSSH/k/22_auth-optio 1.1 644)
+++ 2_9_p2_w_named_keys.2/auth-options.c Tue, 03 Jul 2001 13:57:30 -0400 willian (OpenSSH/k/22_auth-optio 1.1.1.1 644)
@@ -55,8 +55,43 @@
 	channel_clear_permitted_opens();
 }
 
+void auth_set_key_env(Key *k)
+{
+	struct envstring *new_env;
+	char *s;
+	int len;
+
+	if (k->type != KEY_NAME)
+		return;
+
+	len = strlen("SSH_AUTH_EXT_NAME=");
+	len += k->name_len + 1;
+	s = xmalloc(len);
+	snprintf(s, len, "SSH_AUTH_EXT_NAME=%.*s", k->name_len, k->name);
+	debug3("auth_set_key_env: Adding to the environment: %.*s", len, s);
+	new_env = xmalloc(sizeof(struct envstring));
+	new_env->s = s;
+	new_env->next = custom_environment;
+	custom_environment = new_env;
+
+	if (k->name_type == NULL)
+		return;
+
+	len = strlen("SSH_AUTH_EXT_NAME_TYPE=");
+	len += strlen(k->name_type) + 1;
+	s = xmalloc(len);
+	snprintf(s, len, "SSH_AUTH_EXT_NAME_TYPE=%s", k->name_type);
+
+	new_env = xmalloc(sizeof(struct envstring));
+	new_env->s = s;
+	new_env->next = custom_environment;
+	custom_environment = new_env;
+
+	return;
+}
+
 /*
- * return 1 if access is granted, 0 if not.
+ * return 1 if access is granted, 0 if not, -1 if access explicitly denied
  * side effect: sets key option flags
  */
 int
@@ -72,6 +107,12 @@
 		return 1;
 
 	while (*opts && *opts != ' ' && *opts != '\t') {
+		cp = "deny-access";
+		if (strncasecmp(opts, cp, strlen(cp)) == 0) {
+			log("Authentication successful, but authorization denied");
+			packet_send_debug("Permission denied");
+			return -1;
+		}
 		cp = "no-port-forwarding";
 		if (strncasecmp(opts, cp, strlen(cp)) == 0) {
 			packet_send_debug("Port forwarding disabled.");

********************************************************************************

Index: 2_9_p2_w_gss_and_krb5.1/sshd.8
--- 2_9_p2_w_gss_and_krb5.1/sshd.8 Tue, 26 Jun 2001 16:27:13 -0400 willian (OpenSSH/h/28_sshd.8 1.2 644)
+++ 2_9_p2_w_gss_krb5_named_keys.6/sshd.8 Tue, 03 Jul 2001 14:20:01 -0400 willian (OpenSSH/h/28_sshd.8 1.3 644)
@@ -871,7 +871,8 @@
 .Pa $HOME/.ssh/authorized_keys2
 file lists the DSA and RSA keys that are
 permitted for public key authentication (PubkeyAuthentication)
-in protocol version 2.
+in protocol version 2. It can also list key names or key patterns
+for external authentication systems, such as krb4, krb5, gsi, etc...
 .Pp
 Each line of the file contains one
 key (empty lines and lines starting with a
@@ -892,7 +893,19 @@
 For protocol version 2 the keytype is
 .Dq ssh-dss
 or
-.Dq ssh-rsa .
+.Dq ssh-rsa
+or
+.Dq ssh-ext-named:<keytype>
+or
+.Dq ssh-ext-name-pat:<keytype> .
+.Pp
+Named keys and key name patterns follow the latter two, in double
+quotes if they contain whitespace. Named key types may include:
+.Dq krb4 ,
+.Dq krb5
+and/or
+.Dq gsi ,
+depending on what features are compiled in to OpenSSH.
 .Pp
 Note that lines in this file are usually several hundred bytes long
 (because of the size of the RSA key modulus).
@@ -949,6 +962,10 @@
 Environment variables set this way
 override other default environment values.
 Multiple options of this type are permitted.
+.It Cm deny-access
+This option ends authorized_keys2 processing if the key matches. This
+option is only really useful with named key and named key pattern
+entries.
 .It Cm no-port-forwarding
 Forbids TCP/IP forwarding when this key is used for authentication.
 Any port forward requests by the client will return an error.
Index: 2_9_p2_w_gss_and_krb5.1/key.h
--- 2_9_p2_w_gss_and_krb5.1/key.h Tue, 26 Jun 2001 16:27:13 -0400 willian (OpenSSH/j/7_key.h 1.2 644)
+++ 2_9_p2_w_gss_krb5_named_keys.6/key.h Tue, 03 Jul 2001 13:14:57 -0400 willian (OpenSSH/j/7_key.h 1.4 644)
@@ -35,7 +35,9 @@
 	KEY_RSA,
 	KEY_DSA,
 	KEY_NULL,
-	KEY_UNSPEC
+	KEY_UNSPEC,
+	KEY_NAME,
+	KEY_NAME_PAT
 };
 enum fp_type {
 	SSH_FP_SHA1,
@@ -49,12 +51,16 @@
 	int	type;
 	RSA	*rsa;
 	DSA	*dsa;
+	u_char	*name;
+	u_int	name_len;
+	char	*name_type;
 };
 
 Key	*key_new(int type);
 Key	*key_new_private(int type);
 void	key_free(Key *k);
 int	key_equal(Key *a, Key *b);
+int	key_match(Key *a, Key *b);
 char	*key_fingerprint(Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep);
 char	*key_type(Key *k);
 int	key_write(Key *key, FILE *f);
Index: 2_9_p2_w_gss_and_krb5.1/key.c
--- 2_9_p2_w_gss_and_krb5.1/key.c Tue, 26 Jun 2001 16:27:13 -0400 willian (OpenSSH/j/8_key.c 1.2 644)
+++ 2_9_p2_w_gss_krb5_named_keys.6/key.c Tue, 03 Jul 2001 14:23:39 -0400 willian (OpenSSH/j/8_key.c 1.6 644)
@@ -56,6 +56,9 @@
 	k->type = type;
 	k->dsa = NULL;
 	k->rsa = NULL;
+	k->name = NULL;
+	k->name_len = 0;
+	k->name_type = NULL;
 	switch (k->type) {
 	case KEY_RSA1:
 	case KEY_RSA:
@@ -72,6 +75,8 @@
 		dsa->pub_key = BN_new();
 		k->dsa = dsa;
 		break;
+	case KEY_NAME:
+	case KEY_NAME_PAT:
 	case KEY_UNSPEC:
 		break;
 	default:
@@ -119,6 +124,14 @@
 			DSA_free(k->dsa);
 		k->dsa = NULL;
 		break;
+	case KEY_NAME:
+	case KEY_NAME_PAT:
+		if (k->name != NULL)
+			xfree(k->name);
+		k->name_len = 0;
+		if (k->name_type != NULL)
+			xfree(k->name_type);
+		break;
 	case KEY_UNSPEC:
 		break;
 	default:
@@ -130,8 +143,9 @@
 int
 key_equal(Key *a, Key *b)
 {
-	if (a == NULL || b == NULL || a->type != b->type)
+	if (a == NULL || b == NULL || a->type != b->type) {
 		return 0;
+	}
 	switch (a->type) {
 	case KEY_RSA1:
 	case KEY_RSA:
@@ -146,12 +160,67 @@
 		    BN_cmp(a->dsa->g, b->dsa->g) == 0 &&
 		    BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0;
 		break;
+	case KEY_NAME:
+		if ((a->name_type == NULL && b->name_type == NULL) ||
+		    (a->name_type == b->name_type))
+			return (a->name_len == b->name_len) &&
+			    (memcmp(a->name, b->name, a->name_len) == 0);
+		if (a->name_type == NULL || b->name_type == NULL)
+			return 0;
+		if (strcmp(a->name_type, b->name_type) == 0)
+			return (a->name_len == b->name_len) &&
+			    (memcmp(a->name, b->name, a->name_len) == 0);
+		break;
+	case KEY_NAME_PAT:
+		return 0;
+		break;
 	default:
 		fatal("key_equal: bad key type %d", a->type);
 		break;
 	}
 	return 0;
 }
+int
+key_match(Key *a, Key *b)
+{
+	debug3("key_match: trying to match %x and %x", a, b);
+	if (a == NULL || b == NULL)
+		return 0;
+
+	debug3("key_match: trying to match key types %d and %d -- KEY_NAME_PAT == %d", a->type, b->type, KEY_NAME_PAT);
+	/* One key must be a name pattern, the other must be a name */
+	if (!(a->type == KEY_NAME_PAT && b->type == KEY_NAME) &&
+	    !(b->type == KEY_NAME_PAT && a->type == KEY_NAME))
+		return 0;
+	
+	/* Both keys must have name types, or both must not */
+	/* or one key must have '*' as its name type        */
+	if ((a->name_type == NULL && b->name_type != NULL) ||
+	    (b->name_type == NULL && a->name_type != NULL)) {
+
+		debug3("key_match: foo");
+		if (a->name_type != NULL && *(a->name_type) != '*')
+			return 0;
+		if (b->name_type != NULL && *(b->name_type) != '*')
+			return 0;
+	}
+
+	/* Name type "*" matches any name type */
+	/* Otherwise name types must match */
+	if ((a->name_type != NULL && strcmp(a->name_type, b->name_type) != 0) &&
+	    (*(a->name_type) != '*' || *(b->name_type) != '*')) {
+		debug3("key_match: a->name_type == %s", a->name_type ? a->name_type : "");
+		debug3("key_match: b->name_type == %s", b->name_type ? b->name_type : "");
+		return 0;
+	    }
+
+	debug3("key_match: trying to match %s WITH %s", a->name, b->name);
+	if (a->type == KEY_NAME_PAT)
+		return match_pattern(b->name, a->name);
+	else
+		return match_pattern(a->name, b->name);
+}
+
 
 u_char*
 key_fingerprint_raw(Key *k, enum fp_type dgst_type, size_t *dgst_raw_length)
@@ -160,7 +229,7 @@
 	EVP_MD_CTX ctx;
 	u_char *blob = NULL;
 	u_char *retval = NULL;
-	int len = 0;
+	u_int len = 0;
 	int nlen, elen;
 
 	*dgst_raw_length = 0;
@@ -363,11 +432,12 @@
 {
 	Key *k;
 	int success = -1;
-	char *cp, *space;
+	char *cp, *space, *name_type;
 	int len, n, type;
 	u_int bits;
-	u_char *blob;
+	u_char *blob = NULL;
 
+	name_type = NULL;
 	cp = *cpp;
 
 	switch(ret->type) {
@@ -390,6 +460,8 @@
 	case KEY_UNSPEC:
 	case KEY_RSA:
 	case KEY_DSA:
+	case KEY_NAME:
+	case KEY_NAME_PAT:
 		space = strchr(cp, ' ');
 		if (space == NULL) {
 			debug3("key_read: no space");
@@ -397,6 +469,17 @@
 		}
 		*space = '\0';
 		type = key_type_from_name(cp);
+		if ((type == KEY_NAME) || (type == KEY_NAME_PAT)) {
+			char * colon = NULL;
+			
+			colon = strchr(cp, ':');
+
+			debug3("key_read: handling named key or pattern (%d), %s, colon at %x", type, cp, colon);
+			if (colon != NULL && *(++colon) != '\0') {
+				name_type = xstrdup(colon);
+			} else
+				name_type == NULL;
+		}
 		*space = ' ';
 		if (type == KEY_UNSPEC) {
 			debug3("key_read: no key found");
@@ -410,30 +493,80 @@
 		if (ret->type == KEY_UNSPEC) {
 			ret->type = type;
 		} else if (ret->type != type) {
-			/* is a key, but different type */
-			debug3("key_read: type mismatch");
-			return 0;
+			if (! ((ret->type == KEY_NAME) &&
+			       type ==  KEY_NAME_PAT)) {
+				/* is a key, but different type */
+				debug3("key_read: type mismatch");
+				return 0;
+			}
+			ret->type = type;
 		}
-		len = 2*strlen(cp);
-		blob = xmalloc(len);
-		n = uudecode(cp, blob, len);
-		if (n < 0) {
-			error("key_read: uudecode %s failed", cp);
-			return -1;
+		debug3("key_read: here -- ret->type == %d", ret->type);
+		if ((ret->type == KEY_NAME) || (ret->type == KEY_NAME_PAT)) {
+			char *quote, *newline;
+			debug3("key_read: reading named key %s", cp);
+			if (cp == NULL || *cp == '\0')
+				return 0;
+			if (*cp == '"') {
+				quote = strchr(++cp, '"');
+				if (quote == NULL) {
+					debug3("key_read: missing quote");
+					return 0;
+				}
+				*quote = '\0';
+			}
+			newline = strchr(cp, '\n');
+			if (newline != NULL)
+				*newline = '\0';
+			debug3("key_read: reading named key %s", cp);
+			k = key_new(ret->type);
+			k->name = (unsigned char *) xstrdup(cp);
+			k->name_len = strlen(cp);
+			k->name_type = name_type;
+			if (newline !=NULL)
+				*newline = '\n';
+			if (quote !=NULL)
+				*quote = '"';
+			debug3("key_read: read named key %s", k->name_type);
+		} else {
+			len = 2*strlen(cp);
+			blob = xmalloc(len);
+			n = uudecode(cp, blob, len);
+			if (n < 0) {
+				error("key_read: uudecode %s failed", cp);
+				return -1;
+			}
+			debug3("key_read: reading uuencoded key %s", blob);
+			k = key_from_blob(blob, n);
 		}
-		k = key_from_blob(blob, n);
 		if (k == NULL) {
 			error("key_read: key_from_blob %s failed", cp);
 			return -1;
 		}
-		xfree(blob);
+		if (blob != NULL)
+			xfree(blob);
 		if (k->type != type) {
-			error("key_read: type mismatch: encoding error");
-			key_free(k);
-			return -1;
+			if (! ((ret->type == KEY_NAME) &&
+			       type ==  KEY_NAME_PAT)) {
+				error("key_read: type mismatch: encoding error");
+				key_free(k);
+				return -1;
+			}
 		}
 /*XXXX*/
-		if (ret->type == KEY_RSA) {
+		if ((ret->type == KEY_NAME) || (ret->type == KEY_NAME_PAT)) {
+			/*
+			if (ret->name != NULL)
+				xfree(ret->name);
+			 */
+			ret->name = k->name;
+			ret->name_len = k->name_len;
+			ret->name_type = k->name_type;
+			k->name = NULL;
+			k->name_type = NULL;
+			k->name_len = 0;
+			success = 1;
+		} else if (ret->type == KEY_RSA) {
 			if (ret->rsa != NULL)
 				RSA_free(ret->rsa);
 			ret->rsa = k->rsa;
@@ -487,7 +620,7 @@
 		}
 	} else if ((key->type == KEY_DSA && key->dsa != NULL) ||
 	    (key->type == KEY_RSA && key->rsa != NULL)) {
-		int len, n;
+		u_int len, n;
 		u_char *blob, *uu;
 		key_to_blob(key, &blob, &len);
 		uu = xmalloc(2*len);
@@ -498,6 +631,14 @@
 		}
 		xfree(blob);
 		xfree(uu);
+	} else if (key->type == KEY_NAME && key->name != NULL &&
+		   key->name_len) {
+
+		fprintf(f, "%s ", key_ssh_name(key));
+		if (key->name_type != NULL)
+			fprintf(f, ":%s", key->name_type);
+		else
+			fprintf(f, " \"%.*s\"", key->name, key->name_len);
 	}
 	return success;
 }
@@ -514,6 +655,12 @@
 	case KEY_DSA:
 		return "DSA";
 		break;
+	case KEY_NAME:
+		return "Named";
+		break;
+	case KEY_NAME_PAT:
+		return "Name_Pattern";
+		break;
 	}
 	return "unknown";
 }
@@ -527,6 +674,12 @@
 	case KEY_DSA:
 		return "ssh-dss";
 		break;
+	case KEY_NAME:
+		return "ssh-ext-named";
+		break;
+	case KEY_NAME_PAT:
+		return "ssh-ext-name-pat";
+		break;
 	}
 	return "ssh-unknown";
 }
@@ -604,6 +757,16 @@
 		BN_copy(n->rsa->n, k->rsa->n);
 		BN_copy(n->rsa->e, k->rsa->e);
 		break;
+	case KEY_NAME:
+	case KEY_NAME_PAT:
+		n = key_new(k->type);
+		n->name_len = k->name_len;
+		n->name = xmalloc(k->name_len);
+		memcpy(n->name, k->name, n->name_len);
+		if (k->name_type) {
+			n->name_type = xstrdup(k->name_type);
+		}
+		break;
 	default:
 		fatal("key_from_private: unknown type %d", k->type);
 		break;
@@ -624,6 +787,14 @@
 		return KEY_RSA;
 	} else if (strcmp(name, "ssh-dss") == 0){
 		return KEY_DSA;
+	} else if (strcmp(name, "ssh-ext-named") == 0){
+		return KEY_NAME;
+	} else if (strncmp(name, "ssh-ext-named:", strlen("ssh-ext-named:")) == 0){
+		return KEY_NAME;
+	} else if (strcmp(name, "ssh-ext-name-pat") == 0){
+		return KEY_NAME_PAT;
+	} else if (strncmp(name, "ssh-ext-name-pat:", strlen("ssh-ext-name-pat:")) == 0){
+		return KEY_NAME_PAT;
 	} else if (strcmp(name, "null") == 0){
 		return KEY_NULL;
 	}
Index: 2_9_p2_w_gss_and_krb5.1/auth2.c
--- 2_9_p2_w_gss_and_krb5.1/auth2.c Tue, 26 Jun 2001 16:27:13 -0400 willian (OpenSSH/k/6_auth2.c 1.2 644)
+++ 2_9_p2_w_gss_krb5_named_keys.6/auth2.c Tue, 03 Jul 2001 13:14:57 -0400 willian (OpenSSH/k/6_auth2.c 1.3 644)
@@ -514,7 +514,7 @@
 			buffer_dump(&b);
 #endif
 			/* test for correct signature */
-			if (user_key_allowed(authctxt->pw, key) &&
+			if (user_key_allowed(authctxt->pw, key) > 0 &&
 			    key_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1)
 				authenticated = 1;
 			buffer_clear(&b);
@@ -531,7 +531,7 @@
 			 * if a user is not allowed to login. is this an
 			 * issue? -markus
 			 */
-			if (user_key_allowed(authctxt->pw, key)) {
+			if (user_key_allowed(authctxt->pw, key) > 0) {
 				packet_start(SSH2_MSG_USERAUTH_PK_OK);
 				packet_put_string(pkalg, alen);
 				packet_put_string(pkblob, blen);
@@ -791,19 +791,36 @@
 				continue;
 			}
 		}
-		if (key_equal(found, key) &&
-		    auth_parse_options(pw, options, file, linenum) == 1) {
-			found_key = 1;
-			debug("matching key found: file %s, line %ld",
-			    file, linenum);
+		if (key_equal(found, key)) {
+			found_key = auth_parse_options(pw, options, file, linenum);
+			if (found_key == 0)
+				continue;
+			break;
+		}
+		if (key_match(found, key)) {
+			found_key = auth_parse_options(pw, options, file, linenum);
+			if (found_key == 0)
+				continue;
+			/* Special treatment for key name patterns belongs here */
 			break;
 		}
 	}
+
+done:
 	restore_uid();
 	fclose(f);
 	key_free(found);
-	if (!found_key)
+	if (found_key > 0) {
+		debug("matching key found: file %s, line %ld",
+		    file, linenum);
+		auth_set_key_env(key);
+	}
+	if (found_key == 0)
 		debug2("key not found");
+	if (found_key < 0) {
+		debug("user_key_allowed: matching deny key found: "
+		      "file %s, line %ld", file, linenum);
+	}
 	return found_key;
 }
 
Index: 2_9_p2_w_gss_and_krb5.1/auth-rsa.c
--- 2_9_p2_w_gss_and_krb5.1/auth-rsa.c Thu, 03 May 2001 16:12:13 -0400 jd (OpenSSH/k/15_auth-rsa.c 1.1 644)
+++ 2_9_p2_w_gss_krb5_named_keys.6/auth-rsa.c Tue, 03 Jul 2001 13:14:57 -0400 willian (OpenSSH/k/15_auth-rsa.c 1.2 644)
@@ -259,7 +259,7 @@
 		 * If our options do not allow this key to be used,
 		 * do not send challenge.
 		 */
-		if (!auth_parse_options(pw, options, file, linenum))
+		if (auth_parse_options(pw, options, file, linenum) < 1)
 			continue;
 
 		/* Perform the challenge-response dialog for this key. */
Index: 2_9_p2_w_gss_and_krb5.1/auth-options.h
--- 2_9_p2_w_gss_and_krb5.1/auth-options.h Thu, 03 May 2001 16:12:13 -0400 jd (OpenSSH/k/21_auth-optio 1.1 644)
+++ 2_9_p2_w_gss_krb5_named_keys.6/auth-options.h Tue, 03 Jul 2001 13:14:57 -0400 willian (OpenSSH/k/21_auth-optio 1.2 644)
@@ -16,6 +16,8 @@
 #ifndef AUTH_OPTIONS_H
 #define AUTH_OPTIONS_H
 
+#include "key.h"
+
 /* Linked list of custom environment strings */
 struct envstring {
 	struct envstring *next;
@@ -37,6 +39,9 @@
 int
 auth_parse_options(struct passwd *pw, char *options, char *file,
     u_long linenum);
+
+void
+auth_set_key_env(Key *k);
 
 /* reset options flags */
 void	auth_clear_options(void);
Index: 2_9_p2_w_gss_and_krb5.1/auth-options.c
--- 2_9_p2_w_gss_and_krb5.1/auth-options.c Thu, 03 May 2001 16:12:13 -0400 jd (OpenSSH/k/22_auth-optio 1.1 644)
+++ 2_9_p2_w_gss_krb5_named_keys.6/auth-options.c Tue, 03 Jul 2001 13:14:57 -0400 willian (OpenSSH/k/22_auth-optio 1.2 644)
@@ -55,8 +55,43 @@
 	channel_clear_permitted_opens();
 }
 
+void auth_set_key_env(Key *k)
+{
+	struct envstring *new_env;
+	char *s;
+	int len;
+
+	if (k->type != KEY_NAME)
+		return;
+
+	len = strlen("SSH_AUTH_EXT_NAME=");
+	len += k->name_len + 1;
+	s = xmalloc(len);
+	snprintf(s, len, "SSH_AUTH_EXT_NAME=%.*s", k->name_len, k->name);
+	debug3("auth_set_key_env: Adding to the environment: %.*s", len, s);
+	new_env = xmalloc(sizeof(struct envstring));
+	new_env->s = s;
+	new_env->next = custom_environment;
+	custom_environment = new_env;
+
+	if (k->name_type == NULL)
+		return;
+
+	len = strlen("SSH_AUTH_EXT_NAME_TYPE=");
+	len += strlen(k->name_type) + 1;
+	s = xmalloc(len);
+	snprintf(s, len, "SSH_AUTH_EXT_NAME_TYPE=%s", k->name_type);
+
+	new_env = xmalloc(sizeof(struct envstring));
+	new_env->s = s;
+	new_env->next = custom_environment;
+	custom_environment = new_env;
+
+	return;
+}
+
 /*
- * return 1 if access is granted, 0 if not.
+ * return 1 if access is granted, 0 if not, -1 if access explicitly denied
  * side effect: sets key option flags
  */
 int
@@ -72,6 +107,12 @@
 		return 1;
 
 	while (*opts && *opts != ' ' && *opts != '\t') {
+		cp = "deny-access";
+		if (strncasecmp(opts, cp, strlen(cp)) == 0) {
+			log("Authentication successful, but authorization denied");
+			packet_send_debug("Permission denied");
+			return -1;
+		}
 		cp = "no-port-forwarding";
 		if (strncasecmp(opts, cp, strlen(cp)) == 0) {
 			packet_send_debug("Port forwarding disabled.");
Index: 2_9_p2_w_gss_and_krb5.1/gss-serv.c
--- 2_9_p2_w_gss_and_krb5.1/gss-serv.c Tue, 26 Jun 2001 16:27:13 -0400 willian (OpenSSH/l/25_gss-serv.c 1.1 644)
+++ 2_9_p2_w_gss_krb5_named_keys.6/gss-serv.c Thu, 05 Jul 2001 18:25:48 -0400 willian (OpenSSH/l/25_gss-serv.c 1.5 644)
@@ -127,24 +127,45 @@
 int
 ssh_gssapi_krb5_userok(char *name) {
 	krb5_principal princ;
-	int retval;
+	int retval, retval2;
+	Key k;
 
 	if (ssh_gssapi_krb5_init() == 0)
 		return 0;
 		
+	k.type = KEY_NAME;
+	k.name = gssapi_client_name.value;
+	k.name_len = strlen(gssapi_client_name.value);
+	k.name_type = "krb5";
+
+	debug3("ssh_gssapi_krb5_userok:");
+	debug3("ssh_gssapi_krb5_userok: %s", k.name_type);
+
 	if ((retval=krb5_parse_name(krb_context, gssapi_client_name.value, 
 				    &princ))) {
 		log("krb5_parse_name(): %.100s", 
 			krb5_get_err_text(krb_context,retval));
 		return 0;
 	}
+
+	retval2 = user_key_allowed(getpwnam(name), &k);
+	if (retval2 < 0) {
+		krb5_free_principal(krb_context, princ);
+		return 0;
+	}
+
 	if (krb5_kuserok(krb_context, princ, name))
 		retval = 1;
 	else
 		retval = 0;
 	
+	if (retval2 > 0)
+		log("Authorized to %s, krb5 principal %s (authorized_keys2)", name, gssapi_client_name.value);
+	else if (retval > 0)
+		log("Authorized to %s, krb5 principal %s (.k5login)", name, gssapi_client_name.value);
+
 	krb5_free_principal(krb_context, princ);
-	return retval;
+	return retval | retval2;
 }
 	
 /* Make sure that this is called _after_ we've setuid to the user */
@@ -524,8 +545,8 @@
 	
 	if (GSS_ERROR(maj_status)) {
 		/* Failure <sniff> */
-		auth_log(authctxt, 0, "gssapi", " ssh2");
 		authctxt->postponed = 0;
+		auth_log(authctxt, 0, "gssapi", " ssh2");
 		dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
 		userauth_reply(authctxt, 0);
 	}
@@ -563,6 +584,8 @@
 	OM_uint32 maj_status, min_status;
 	int authenticated;
 	gss_buffer_desc gssbuf,msg_tok;
+	char *info;
+	int info_len;
 	
 	if (authctxt == NULL || authctxt->methoddata == NULL)
 		fatal("No authentication or GSSAPI context");
@@ -598,8 +621,24 @@
         	packet_write_wait();
         }
 
-	auth_log(authctxt, authenticated, "gssapi", " ssh2");
+	switch (gssapi_client_type) {
+#ifdef	KRB5
+	case GSS_KERBEROS:
+		info_len = strlen(gssapi_client_name.value) + strlen("krb5") + 2 + 1;
+		info = xmalloc(info_len);
+		(void) snprintf(info, info_len, " %s:%s", "krb5", gssapi_client_name.value);
+		break;
+#endif	/* KRB5 */
+#ifdef	GSI
+	case GSS_GSI:
+		info_len = strlen(gssapi_client_name.value) + strlen("gsi") + 2 + 1;
+		info = xmalloc(info_len);
+		(void) snprintf(info, info_len, " %s:%s", "gsi", gssapi_client_name.value);
+		break;
+#endif	/* GSI */
+	}
 	authctxt->postponed = 0;
+	auth_log(authctxt, authenticated, "gssapi", info);
 	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
 	dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
 	userauth_reply(authctxt, authenticated);

********************************************************************************

Visit our website at http://www.ubswarburg.com

This message contains confidential information and is intended only 
for the individual named.  If you are not the named addressee you 
should not disseminate, distribute or copy this e-mail.  Please 
notify the sender immediately by e-mail if you have received this 
e-mail by mistake and delete this e-mail from your system.

E-mail transmission cannot be guaranteed to be secure or error-free 
as information could be intercepted, corrupted, lost, destroyed, 
arrive late or incomplete, or contain viruses.  The sender therefore 
does not accept liability for any errors or omissions in the contents 
of this message which arise as a result of e-mail transmission.  If 
verification is required please request a hard-copy version.  This 
message is provided for informational purposes and should not be 
construed as a solicitation or offer to buy or sell any securities or 
related financial instruments.




More information about the openssh-unix-dev mailing list