Key fingerprint logging

Michal Kara lemming at netcentrum.cz
Wed Jan 30 01:40:54 EST 2002


  Hello there!

  I have made a patch against OpenSSH 3.0.2p1 which allows the fingerprint of
the accepted key to be printed in the log message. It works with SSH1-RSA and
SSH2 pubkey (DSA+RSA) authentication.

  This feature is controllable by the LogKeyFingerprint config option (turned
off by default).

							Michal Kara

-------------- next part --------------
diff -u5 openssh-3.0.2p1.orig/auth-rsa.c openssh-3.0.2p1/auth-rsa.c
--- openssh-3.0.2p1.orig/auth-rsa.c	Mon Aug  6 23:01:49 2001
+++ openssh-3.0.2p1/auth-rsa.c	Tue Jan 29 14:26:34 2002
@@ -118,11 +118,11 @@
  * 0 if the client could not be authenticated, and 1 if authentication was
  * successful.  This may exit if there is a serious protocol violation.
  */
 
 int
-auth_rsa(struct passwd *pw, BIGNUM *client_n)
+auth_rsa(struct passwd *pw, BIGNUM *client_n, char *info, int info_size)
 {
 	char line[8192], *file;
 	int authenticated;
 	u_int bits;
 	FILE *f;
@@ -179,11 +179,11 @@
 	 * found, perform a challenge-response dialog to verify that the
 	 * user really has the corresponding private key.
 	 */
 	while (fgets(line, sizeof(line), f)) {
 		char *cp;
-		char *options;
+		char *key_options;
 
 		linenum++;
 
 		/* Skip leading whitespace, empty and comment lines. */
 		for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
@@ -197,19 +197,19 @@
 		 * for now.  If there are no options, set the starting
 		 * address to NULL.
 		 */
 		if (*cp < '0' || *cp > '9') {
 			int quoted = 0;
-			options = cp;
+			key_options = cp;
 			for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
 				if (*cp == '\\' && cp[1] == '"')
 					cp++;	/* Skip both */
 				else if (*cp == '"')
 					quoted = !quoted;
 			}
 		} else
-			options = NULL;
+			key_options = NULL;
 
 		/* Parse the key from the line. */
 		if (!auth_rsa_read_key(&cp, &bits, pk->e, pk->n)) {
 			debug("%.100s, line %lu: non ssh1 key syntax",
 			    file, linenum);
@@ -230,11 +230,11 @@
 		/* We have found the desired key. */
 		/*
 		 * 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, key_options, file, linenum))
 			continue;
 
 		/* Perform the challenge-response dialog for this key. */
 		if (!auth_rsa_challenge_dialog(pk)) {
 			/* Wrong response. */
@@ -249,10 +249,19 @@
 		 * authentication to be rejected.
 		 * Break out of the loop if authentication was successful;
 		 * otherwise continue searching.
 		 */
 		authenticated = 1;
+
+		if (options.log_key_fingerprint == 1) {
+			Key *k = key_new(KEY_RSA);
+			RSA *old_rsa = k->rsa;
+			k->rsa = pk;
+			snprintf(info,info_size," fp %s",key_fingerprint(k,SSH_FP_MD5,SSH_FP_HEX));
+			k->rsa = old_rsa;
+			key_free(k);
+		}
 		break;
 	}
 
 	/* Restore the privileged uid. */
 	restore_uid();
diff -u5 openssh-3.0.2p1.orig/auth.h openssh-3.0.2p1/auth.h
--- openssh-3.0.2p1.orig/auth.h	Wed Jul  4 06:46:57 2001
+++ openssh-3.0.2p1/auth.h	Tue Jan 29 13:45:29 2002
@@ -91,11 +91,11 @@
 int
 auth_rhosts2(struct passwd *, const char *, const char *, const char *);
 
 int	 auth_rhosts_rsa(struct passwd *, const char *, RSA *);
 int      auth_password(Authctxt *, const char *);
-int      auth_rsa(struct passwd *, BIGNUM *);
+int      auth_rsa(struct passwd *, BIGNUM *, char *, int);
 int      auth_rsa_read_key(char **, u_int *, BIGNUM *, BIGNUM *);
 int      auth_rsa_challenge_dialog(RSA *);
 
 #ifdef KRB4
 #include <krb.h>
diff -u5 openssh-3.0.2p1.orig/auth1.c openssh-3.0.2p1/auth1.c
--- openssh-3.0.2p1.orig/auth1.c	Tue Nov 13 13:46:19 2001
+++ openssh-3.0.2p1/auth1.c	Tue Jan 29 13:40:20 2002
@@ -231,11 +231,11 @@
 			}
 			/* RSA authentication requested. */
 			n = BN_new();
 			packet_get_bignum(n, &nlen);
 			packet_integrity_check(plen, nlen, type);
-			authenticated = auth_rsa(pw, n);
+			authenticated = auth_rsa(pw, n, info, sizeof(info));
 			BN_clear_free(n);
 			break;
 
 		case SSH_CMSG_AUTH_PASSWORD:
 			if (!options.password_authentication) {
diff -u5 openssh-3.0.2p1.orig/auth2.c openssh-3.0.2p1/auth2.c
--- openssh-3.0.2p1.orig/auth2.c	Tue Nov 13 13:46:19 2001
+++ openssh-3.0.2p1/auth2.c	Tue Jan 29 15:21:58 2002
@@ -58,10 +58,14 @@
 extern int session_id2_len;
 
 static Authctxt	*x_authctxt = NULL;
 static int one = 1;
 
+static char real_info[1024] = " ssh2";
+static char *info = real_info + 5;
+static int info_size = sizeof(real_info)-5;
+
 typedef struct Authmethod Authmethod;
 struct Authmethod {
 	char	*name;
 	int	(*userauth)(Authctxt *authctxt);
 	int	*enabled;
@@ -261,11 +265,11 @@
 	    NULL))
 		authenticated = 0;
 #endif /* USE_PAM */
 
 	/* Log before sending the reply */
-	auth_log(authctxt, authenticated, method, " ssh2");
+	auth_log(authctxt, authenticated, method, real_info);
 
 	if (authctxt->postponed)
 		return;
 
 	/* XXX todo: check if multiple auth methods are needed */
@@ -475,12 +479,16 @@
 #ifdef DEBUG_PK
 			buffer_dump(&b);
 #endif
 			/* test for correct signature */
 			if (user_key_allowed(authctxt->pw, key) &&
-			    key_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1)
+			    key_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1) {
 				authenticated = 1;
+
+				if (options.log_key_fingerprint == 1)
+				    snprintf(info,info_size," fp %s",key_fingerprint(key,SSH_FP_MD5,SSH_FP_HEX));
+			}
 			buffer_clear(&b);
 			xfree(sig);
 		} else {
 			debug("test whether pkalg/pkblob are acceptable");
 			packet_done();
diff -u5 openssh-3.0.2p1.orig/servconf.c openssh-3.0.2p1/servconf.c
--- openssh-3.0.2p1.orig/servconf.c	Tue Nov 13 14:03:15 2001
+++ openssh-3.0.2p1/servconf.c	Tue Jan 29 14:23:41 2002
@@ -107,10 +107,11 @@
 	options->reverse_mapping_check = -1;
 	options->client_alive_interval = -1;
 	options->client_alive_count_max = -1;
 	options->authorized_keys_file = NULL;
 	options->authorized_keys_file2 = NULL;
+	options->log_key_fingerprint = -1;
 }
 
 void
 fill_default_server_options(ServerOptions *options)
 {
@@ -227,10 +228,12 @@
 		else
 			options->authorized_keys_file2 = _PATH_SSH_USER_PERMITTED_KEYS2;
 	}
 	if (options->authorized_keys_file == NULL)
 		options->authorized_keys_file = _PATH_SSH_USER_PERMITTED_KEYS;
+	if (options->log_key_fingerprint == -1)
+		options->log_key_fingerprint = 0;
 }
 
 /* Keyword tokens. */
 typedef enum {
 	sBadOption,		/* == unknown option */
@@ -259,11 +262,11 @@
 	sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
 	sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, sMaxStartups,
 	sBanner, sReverseMappingCheck, sHostbasedAuthentication,
 	sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, 
 	sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
-	sDeprecated 
+	sDeprecated, sLogKeyFingerprint
 } ServerOpCodes;
 
 /* Textual representation of the tokens. */
 static struct {
 	const char *name;
@@ -332,10 +335,11 @@
 	{ "reversemappingcheck", sReverseMappingCheck },
 	{ "clientaliveinterval", sClientAliveInterval },
 	{ "clientalivecountmax", sClientAliveCountMax },
 	{ "authorizedkeysfile", sAuthorizedKeysFile },
 	{ "authorizedkeysfile2", sAuthorizedKeysFile2 },
+	{ "logkeyfingerprint", sLogKeyFingerprint },
 	{ NULL, 0 }
 };
 
 /*
  * Returns the number of the token pointed to by cp or sBadOption.
@@ -863,10 +867,14 @@
 			log("%s line %d: Deprecated option %s",
 			    filename, linenum, arg);
 			while(arg)
 			    arg = strdelim(&cp);
 			break;
+
+		case sLogKeyFingerprint:
+			intptr = &options->log_key_fingerprint;
+			goto parse_flag;
 
 		default:
 			fatal("%s line %d: Missing handler for opcode %s (%d)",
 			    filename, linenum, arg, opcode);
 		}
diff -u5 openssh-3.0.2p1.orig/servconf.h openssh-3.0.2p1/servconf.h
--- openssh-3.0.2p1.orig/servconf.h	Wed Sep 12 18:40:06 2001
+++ openssh-3.0.2p1/servconf.h	Tue Jan 29 15:19:29 2002
@@ -128,10 +128,12 @@
 
 	char   *authorized_keys_file;	/* File containing public keys */
 	char   *authorized_keys_file2;
 	int	pam_authentication_via_kbd_int;
 
+	int	log_key_fingerprint;
+
 }       ServerOptions;
 
 void	 initialize_server_options(ServerOptions *);
 void	 read_server_config(ServerOptions *, const char *);
 void	 fill_default_server_options(ServerOptions *);
diff -u5 openssh-3.0.2p1.orig/sshd.8 openssh-3.0.2p1/sshd.8
--- openssh-3.0.2p1.orig/sshd.8	Sun Dec  2 00:37:08 2001
+++ openssh-3.0.2p1/sshd.8	Tue Jan 29 15:12:08 2002
@@ -606,10 +606,15 @@
 .It Cm LoginGraceTime
 The server disconnects after this time if the user has not
 successfully logged in.
 If the value is 0, there is no time limit.
 The default is 600 (seconds).
+.It Cm LogKeyFingerprint
+Specifies whether to log key fingerprint after successful
+publickey authentication.
+The default is
+.Dq no .
 .It Cm LogLevel
 Gives the verbosity level that is used when logging messages from
 .Nm sshd .
 The possible values are:
 QUIET, FATAL, ERROR, INFO, VERBOSE and DEBUG.


More information about the openssh-unix-dev mailing list