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