From 91a55f28f35431f9000b95815c343b5a18fda712 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Tue, 23 Apr 2013 15:18:10 +1000 Subject: - markus@cvs.openbsd.org 2013/03/07 19:27:25 [auth.h auth2-chall.c auth2.c monitor.c sshd_config.5] add submethod support to AuthenticationMethods; ok and freedback djm@ --- auth.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'auth.h') diff --git a/auth.h b/auth.h index c6fe84722..7ff59f1ba 100644 --- a/auth.h +++ b/auth.h @@ -1,4 +1,4 @@ -/* $OpenBSD: auth.h,v 1.72 2012/12/02 20:34:09 djm Exp $ */ +/* $OpenBSD: auth.h,v 1.73 2013/03/07 19:27:25 markus Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -157,8 +157,9 @@ void userauth_send_banner(const char *); char *auth2_read_banner(void); int auth2_methods_valid(const char *, int); -int auth2_update_methods_lists(Authctxt *, const char *); +int auth2_update_methods_lists(Authctxt *, const char *, const char *); int auth2_setup_methods_lists(Authctxt *); +int auth2_method_allowed(Authctxt *, const char *, const char *); void privsep_challenge_enable(void); -- cgit v1.2.3 From 0acca3797d53d958d240c69a5f222f2aa8444858 Mon Sep 17 00:00:00 2001 From: Darren Tucker Date: Sun, 2 Jun 2013 07:41:51 +1000 Subject: - djm@cvs.openbsd.org 2013/05/19 02:42:42 [auth.h auth.c key.c monitor.c auth-rsa.c auth2.c auth1.c key.h] Standardise logging of supplemental information during userauth. Keys and ruser is now logged in the auth success/failure message alongside the local username, remote host/port and protocol in use. Certificates contents and CA are logged too. Pushing all logging onto a single line simplifies log analysis as it is no longer necessary to relate information scattered across multiple log entries. "I like it" markus@ --- ChangeLog | 9 +++++++++ auth-rsa.c | 16 ++++++++-------- auth.c | 30 ++++++++++++++++++++++++++---- auth.h | 10 +++++++--- auth1.c | 35 ++++++++++++++++------------------- auth2.c | 4 ++-- key.c | 4 ++-- key.h | 4 ++-- monitor.c | 9 ++++----- 9 files changed, 76 insertions(+), 45 deletions(-) (limited to 'auth.h') diff --git a/ChangeLog b/ChangeLog index c08e210be..d772486f5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -26,6 +26,15 @@ [auth2-pubkey.c] fix failure to recognise cert-authority keys if a key of a different type appeared in authorized_keys before it; ok markus@ + - djm@cvs.openbsd.org 2013/05/19 02:42:42 + [auth.h auth.c key.c monitor.c auth-rsa.c auth2.c auth1.c key.h] + Standardise logging of supplemental information during userauth. Keys + and ruser is now logged in the auth success/failure message alongside + the local username, remote host/port and protocol in use. Certificates + contents and CA are logged too. + Pushing all logging onto a single line simplifies log analysis as it is + no longer necessary to relate information scattered across multiple log + entries. "I like it" markus@ 20130529 - (dtucker) [configure.ac openbsd-compat/bsd-misc.h] bz#2087: Add a null diff --git a/auth-rsa.c b/auth-rsa.c index 748eaae09..92f0ad75c 100644 --- a/auth-rsa.c +++ b/auth-rsa.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth-rsa.c,v 1.82 2013/05/17 00:13:13 djm Exp $ */ +/* $OpenBSD: auth-rsa.c,v 1.83 2013/05/19 02:42:42 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -164,7 +164,7 @@ static int rsa_key_allowed_in_file(struct passwd *pw, char *file, const BIGNUM *client_n, Key **rkey) { - char line[SSH_MAX_PUBKEY_BYTES]; + char *fp, line[SSH_MAX_PUBKEY_BYTES]; int allowed = 0; u_int bits; FILE *f; @@ -232,6 +232,11 @@ rsa_key_allowed_in_file(struct passwd *pw, char *file, "actual %d vs. announced %d.", file, linenum, BN_num_bits(key->rsa->n), bits); + fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); + debug("matching key found: file %s, line %lu %s %s", + file, linenum, key_type(key), fp); + free(fp); + /* Never accept a revoked key */ if (auth_key_is_revoked(key)) break; @@ -298,7 +303,6 @@ int auth_rsa(Authctxt *authctxt, BIGNUM *client_n) { Key *key; - char *fp; struct passwd *pw = authctxt->pw; /* no user given */ @@ -328,11 +332,7 @@ auth_rsa(Authctxt *authctxt, BIGNUM *client_n) * options; this will be reset if the options cause the * authentication to be rejected. */ - fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); - verbose("Found matching %s key: %s", - key_type(key), fp); - free(fp); - key_free(key); + pubkey_auth_info(authctxt, key); packet_send_debug("RSA authentication accepted."); return (1); diff --git a/auth.c b/auth.c index ac126e6f3..9a36f1dac 100644 --- a/auth.c +++ b/auth.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth.c,v 1.102 2013/05/17 00:13:13 djm Exp $ */ +/* $OpenBSD: auth.c,v 1.103 2013/05/19 02:42:42 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -72,6 +72,7 @@ #include "authfile.h" #include "monitor_wrap.h" #include "krl.h" +#include "compat.h" /* import */ extern ServerOptions options; @@ -251,9 +252,26 @@ allowed_user(struct passwd * pw) return 1; } +void +auth_info(Authctxt *authctxt, const char *fmt, ...) +{ + va_list ap; + int i; + + free(authctxt->info); + authctxt->info = NULL; + + va_start(ap, fmt); + i = vasprintf(&authctxt->info, fmt, ap); + va_end(ap); + + if (i < 0 || authctxt->info == NULL) + fatal("vasprintf failed"); +} + void auth_log(Authctxt *authctxt, int authenticated, int partial, - const char *method, const char *submethod, const char *info) + const char *method, const char *submethod) { void (*authlog) (const char *fmt,...) = verbose; char *authmsg; @@ -275,7 +293,7 @@ auth_log(Authctxt *authctxt, int authenticated, int partial, else authmsg = authenticated ? "Accepted" : "Failed"; - authlog("%s %s%s%s for %s%.100s from %.200s port %d%s", + authlog("%s %s%s%s for %s%.100s from %.200s port %d %s%s%s", authmsg, method, submethod != NULL ? "/" : "", submethod == NULL ? "" : submethod, @@ -283,7 +301,11 @@ auth_log(Authctxt *authctxt, int authenticated, int partial, authctxt->user, get_remote_ipaddr(), get_remote_port(), - info); + compat20 ? "ssh2" : "ssh1", + authctxt->info != NULL ? ": " : "", + authctxt->info != NULL ? authctxt->info : ""); + free(authctxt->info); + authctxt->info = NULL; #ifdef CUSTOM_FAILED_LOGIN if (authenticated == 0 && !authctxt->postponed && diff --git a/auth.h b/auth.h index 7ff59f1ba..a406e1393 100644 --- a/auth.h +++ b/auth.h @@ -1,4 +1,4 @@ -/* $OpenBSD: auth.h,v 1.73 2013/03/07 19:27:25 markus Exp $ */ +/* $OpenBSD: auth.h,v 1.74 2013/05/19 02:42:42 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -60,6 +60,7 @@ struct Authctxt { struct passwd *pw; /* set if 'valid' */ char *style; void *kbdintctxt; + char *info; /* Extra info for next auth_log */ void *jpake_ctx; #ifdef BSD_AUTH auth_session_t *as; @@ -121,6 +122,7 @@ int auth_rsa_key_allowed(struct passwd *, BIGNUM *, Key **); int auth_rhosts_rsa_key_allowed(struct passwd *, char *, char *, Key *); int hostbased_key_allowed(struct passwd *, const char *, char *, Key *); int user_key_allowed(struct passwd *, Key *); +void pubkey_auth_info(Authctxt *, const Key *); struct stat; int auth_secure_path(const char *, struct stat *, const char *, uid_t, @@ -148,8 +150,10 @@ void disable_forwarding(void); void do_authentication(Authctxt *); void do_authentication2(Authctxt *); -void auth_log(Authctxt *, int, int, const char *, const char *, - const char *); +void auth_info(Authctxt *authctxt, const char *, ...) + __attribute__((__format__ (printf, 2, 3))) + __attribute__((__nonnull__ (2))); +void auth_log(Authctxt *, int, int, const char *, const char *); void userauth_finish(Authctxt *, int, const char *, const char *); int auth_root_allowed(const char *); diff --git a/auth1.c b/auth1.c index 238b3c9c3..3518fb1c6 100644 --- a/auth1.c +++ b/auth1.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth1.c,v 1.78 2013/05/17 00:13:13 djm Exp $ */ +/* $OpenBSD: auth1.c,v 1.79 2013/05/19 02:42:42 djm Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -45,11 +45,11 @@ extern ServerOptions options; extern Buffer loginmsg; -static int auth1_process_password(Authctxt *, char *, size_t); -static int auth1_process_rsa(Authctxt *, char *, size_t); -static int auth1_process_rhosts_rsa(Authctxt *, char *, size_t); -static int auth1_process_tis_challenge(Authctxt *, char *, size_t); -static int auth1_process_tis_response(Authctxt *, char *, size_t); +static int auth1_process_password(Authctxt *); +static int auth1_process_rsa(Authctxt *); +static int auth1_process_rhosts_rsa(Authctxt *); +static int auth1_process_tis_challenge(Authctxt *); +static int auth1_process_tis_response(Authctxt *); static char *client_user = NULL; /* Used to fill in remote user for PAM */ @@ -57,7 +57,7 @@ struct AuthMethod1 { int type; char *name; int *enabled; - int (*method)(Authctxt *, char *, size_t); ++ int (*method)(Authctxt *); }; const struct AuthMethod1 auth1_methods[] = { @@ -112,7 +112,7 @@ get_authname(int type) /*ARGSUSED*/ static int -auth1_process_password(Authctxt *authctxt, char *info, size_t infolen) +auth1_process_password(Authctxt *authctxt) { int authenticated = 0; char *password; @@ -137,7 +137,7 @@ auth1_process_password(Authctxt *authctxt, char *info, size_t infolen) /*ARGSUSED*/ static int -auth1_process_rsa(Authctxt *authctxt, char *info, size_t infolen) +auth1_process_rsa(Authctxt *authctxt) { int authenticated = 0; BIGNUM *n; @@ -155,7 +155,7 @@ auth1_process_rsa(Authctxt *authctxt, char *info, size_t infolen) /*ARGSUSED*/ static int -auth1_process_rhosts_rsa(Authctxt *authctxt, char *info, size_t infolen) +auth1_process_rhosts_rsa(Authctxt *authctxt) { int keybits, authenticated = 0; u_int bits; @@ -187,14 +187,14 @@ auth1_process_rhosts_rsa(Authctxt *authctxt, char *info, size_t infolen) client_host_key); key_free(client_host_key); - snprintf(info, infolen, " ruser %.100s", client_user); + auth_info(authctxt, "ruser %.100s", client_user); return (authenticated); } /*ARGSUSED*/ static int -auth1_process_tis_challenge(Authctxt *authctxt, char *info, size_t infolen) +auth1_process_tis_challenge(Authctxt *authctxt) { char *challenge; @@ -213,7 +213,7 @@ auth1_process_tis_challenge(Authctxt *authctxt, char *info, size_t infolen) /*ARGSUSED*/ static int -auth1_process_tis_response(Authctxt *authctxt, char *info, size_t infolen) +auth1_process_tis_response(Authctxt *authctxt) { int authenticated = 0; char *response; @@ -236,7 +236,6 @@ static void do_authloop(Authctxt *authctxt) { int authenticated = 0; - char info[1024]; int prev = 0, type = 0; const struct AuthMethod1 *meth; @@ -254,7 +253,7 @@ do_authloop(Authctxt *authctxt) #endif { auth_log(authctxt, 1, 0, "without authentication", - NULL, ""); + NULL); return; } } @@ -268,7 +267,6 @@ do_authloop(Authctxt *authctxt) /* default to fail */ authenticated = 0; - info[0] = '\0'; /* Get a packet from the client. */ prev = type; @@ -298,7 +296,7 @@ do_authloop(Authctxt *authctxt) goto skip; } - authenticated = meth->method(authctxt, info, sizeof(info)); + authenticated = meth->method(authctxt); if (authenticated == -1) continue; /* "postponed" */ @@ -353,8 +351,7 @@ do_authloop(Authctxt *authctxt) skip: /* Log before sending the reply */ - auth_log(authctxt, authenticated, 0, get_authname(type), - NULL, info); + auth_log(authctxt, authenticated, 0, get_authname(type), NULL); free(client_user); client_user = NULL; diff --git a/auth2.c b/auth2.c index 5f136ce09..f0cab8cc0 100644 --- a/auth2.c +++ b/auth2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2.c,v 1.128 2013/05/17 00:13:13 djm Exp $ */ +/* $OpenBSD: auth2.c,v 1.129 2013/05/19 02:42:42 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -326,7 +326,7 @@ userauth_finish(Authctxt *authctxt, int authenticated, const char *method, } /* Log before sending the reply */ - auth_log(authctxt, authenticated, partial, method, submethod, " ssh2"); + auth_log(authctxt, authenticated, partial, method, submethod); if (authctxt->postponed) return; diff --git a/key.c b/key.c index 8183ec90e..55ee78998 100644 --- a/key.c +++ b/key.c @@ -1,4 +1,4 @@ -/* $OpenBSD: key.c,v 1.103 2013/05/17 00:13:13 djm Exp $ */ +/* $OpenBSD: key.c,v 1.104 2013/05/19 02:42:42 djm Exp $ */ /* * read_bignum(): * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -569,7 +569,7 @@ key_fingerprint_randomart(u_char *dgst_raw, u_int dgst_raw_len, const Key *k) } char * -key_fingerprint(Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep) +key_fingerprint(const Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep) { char *retval = NULL; u_char *dgst_raw; diff --git a/key.h b/key.h index f2e058e9e..17358ae1f 100644 --- a/key.h +++ b/key.h @@ -1,4 +1,4 @@ -/* $OpenBSD: key.h,v 1.36 2013/04/19 01:06:50 djm Exp $ */ +/* $OpenBSD: key.h,v 1.37 2013/05/19 02:42:42 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -95,7 +95,7 @@ void key_free(Key *); Key *key_demote(const Key *); int key_equal_public(const Key *, const Key *); int key_equal(const Key *, const Key *); -char *key_fingerprint(Key *, enum fp_type, enum fp_rep); +char *key_fingerprint(const Key *, enum fp_type, enum fp_rep); u_char *key_fingerprint_raw(const Key *, enum fp_type, u_int *); const char *key_type(const Key *); const char *key_cert_type(const Key *); diff --git a/monitor.c b/monitor.c index 132f60df9..6acb20259 100644 --- a/monitor.c +++ b/monitor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.124 2013/05/17 00:13:13 djm Exp $ */ +/* $OpenBSD: monitor.c,v 1.125 2013/05/19 02:42:42 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -422,8 +422,7 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) } if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) { auth_log(authctxt, authenticated, partial, - auth_method, auth_submethod, - compat20 ? " ssh2" : ""); + auth_method, auth_submethod); if (!authenticated) authctxt->failures++; } @@ -1168,6 +1167,7 @@ mm_answer_keyallowed(int sock, Buffer *m) case MM_USERKEY: allowed = options.pubkey_authentication && user_key_allowed(authctxt->pw, key); + pubkey_auth_info(authctxt, key); auth_method = "publickey"; if (options.pubkey_authentication && allowed != 1) auth_clear_options(); @@ -1207,8 +1207,7 @@ mm_answer_keyallowed(int sock, Buffer *m) hostbased_chost = chost; } else { /* Log failed attempt */ - auth_log(authctxt, 0, 0, auth_method, NULL, - compat20 ? " ssh2" : ""); + auth_log(authctxt, 0, 0, auth_method, NULL); free(blob); free(cuser); free(chost); -- cgit v1.2.3 From 20bdcd72365e8b3d51261993928cc47c5f0d7c8a Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Thu, 18 Jul 2013 16:10:09 +1000 Subject: - djm@cvs.openbsd.org 2013/06/21 00:34:49 [auth-rsa.c auth.h auth2-hostbased.c auth2-pubkey.c monitor.c] for hostbased authentication, print the client host and user on the auth success/failure line; bz#2064, ok dtucker@ --- ChangeLog | 4 ++++ auth-rsa.c | 4 ++-- auth.h | 5 +++-- auth2-hostbased.c | 6 +++++- auth2-pubkey.c | 28 +++++++++++++++++++++------- monitor.c | 7 +++++-- 6 files changed, 40 insertions(+), 14 deletions(-) (limited to 'auth.h') diff --git a/ChangeLog b/ChangeLog index e0781041e..f8e2c6858 100644 --- a/ChangeLog +++ b/ChangeLog @@ -12,6 +12,10 @@ - markus@cvs.openbsd.org 2013/06/20 19:15:06 [krl.c] don't leak the rdata blob on errors; ok djm@ + - djm@cvs.openbsd.org 2013/06/21 00:34:49 + [auth-rsa.c auth.h auth2-hostbased.c auth2-pubkey.c monitor.c] + for hostbased authentication, print the client host and user on + the auth success/failure line; bz#2064, ok dtucker@ 20130702 - (dtucker) [contrib/cygwin/README contrib/cygwin/ssh-host-config diff --git a/auth-rsa.c b/auth-rsa.c index 92f0ad75c..b7a03fdc4 100644 --- a/auth-rsa.c +++ b/auth-rsa.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth-rsa.c,v 1.83 2013/05/19 02:42:42 djm Exp $ */ +/* $OpenBSD: auth-rsa.c,v 1.84 2013/06/21 00:34:49 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -332,7 +332,7 @@ auth_rsa(Authctxt *authctxt, BIGNUM *client_n) * options; this will be reset if the options cause the * authentication to be rejected. */ - pubkey_auth_info(authctxt, key); + pubkey_auth_info(authctxt, key, NULL); packet_send_debug("RSA authentication accepted."); return (1); diff --git a/auth.h b/auth.h index a406e1393..caf44adc0 100644 --- a/auth.h +++ b/auth.h @@ -1,4 +1,4 @@ -/* $OpenBSD: auth.h,v 1.74 2013/05/19 02:42:42 djm Exp $ */ +/* $OpenBSD: auth.h,v 1.75 2013/06/21 00:34:49 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -122,7 +122,8 @@ int auth_rsa_key_allowed(struct passwd *, BIGNUM *, Key **); int auth_rhosts_rsa_key_allowed(struct passwd *, char *, char *, Key *); int hostbased_key_allowed(struct passwd *, const char *, char *, Key *); int user_key_allowed(struct passwd *, Key *); -void pubkey_auth_info(Authctxt *, const Key *); +void pubkey_auth_info(Authctxt *, const Key *, const char *, ...) + __attribute__((__format__ (printf, 3, 4))); struct stat; int auth_secure_path(const char *, struct stat *, const char *, uid_t, diff --git a/auth2-hostbased.c b/auth2-hostbased.c index e6d05e261..a344dcc1f 100644 --- a/auth2-hostbased.c +++ b/auth2-hostbased.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-hostbased.c,v 1.15 2013/05/17 00:13:13 djm Exp $ */ +/* $OpenBSD: auth2-hostbased.c,v 1.16 2013/06/21 00:34:49 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -116,6 +116,10 @@ userauth_hostbased(Authctxt *authctxt) #ifdef DEBUG_PK buffer_dump(&b); #endif + + pubkey_auth_info(authctxt, key, + "client user \"%.100s\", client host \"%.100s\"", cuser, chost); + /* test for allowed key and correct signature */ authenticated = 0; if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) && diff --git a/auth2-pubkey.c b/auth2-pubkey.c index 45306f839..2b3ecb104 100644 --- a/auth2-pubkey.c +++ b/auth2-pubkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: auth2-pubkey.c,v 1.37 2013/05/19 02:38:28 djm Exp $ */ +/* $OpenBSD: auth2-pubkey.c,v 1.38 2013/06/21 00:34:49 djm Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. * @@ -147,7 +147,7 @@ userauth_pubkey(Authctxt *authctxt) #ifdef DEBUG_PK buffer_dump(&b); #endif - pubkey_auth_info(authctxt, key); + pubkey_auth_info(authctxt, key, NULL); /* test for correct signature */ authenticated = 0; @@ -190,23 +190,37 @@ done: } void -pubkey_auth_info(Authctxt *authctxt, const Key *key) +pubkey_auth_info(Authctxt *authctxt, const Key *key, const char *fmt, ...) { - char *fp; + char *fp, *extra; + va_list ap; + int i; + + extra = NULL; + if (fmt != NULL) { + va_start(ap, fmt); + i = vasprintf(&extra, fmt, ap); + va_end(ap); + if (i < 0 || extra == NULL) + fatal("%s: vasprintf failed", __func__); + } if (key_is_cert(key)) { fp = key_fingerprint(key->cert->signature_key, SSH_FP_MD5, SSH_FP_HEX); - auth_info(authctxt, "%s ID %s (serial %llu) CA %s %s", + auth_info(authctxt, "%s ID %s (serial %llu) CA %s %s%s%s", key_type(key), key->cert->key_id, (unsigned long long)key->cert->serial, - key_type(key->cert->signature_key), fp); + key_type(key->cert->signature_key), fp, + extra == NULL ? "" : ", ", extra == NULL ? "" : extra); free(fp); } else { fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); - auth_info(authctxt, "%s %s", key_type(key), fp); + auth_info(authctxt, "%s %s%s%s", key_type(key), fp, + extra == NULL ? "" : ", ", extra == NULL ? "" : extra); free(fp); } + free(extra); } static int diff --git a/monitor.c b/monitor.c index 7286126f5..0516f60a2 100644 --- a/monitor.c +++ b/monitor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.125 2013/05/19 02:42:42 djm Exp $ */ +/* $OpenBSD: monitor.c,v 1.126 2013/06/21 00:34:49 djm Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -1165,7 +1165,7 @@ mm_answer_keyallowed(int sock, Buffer *m) case MM_USERKEY: allowed = options.pubkey_authentication && user_key_allowed(authctxt->pw, key); - pubkey_auth_info(authctxt, key); + pubkey_auth_info(authctxt, key, NULL); auth_method = "publickey"; if (options.pubkey_authentication && allowed != 1) auth_clear_options(); @@ -1174,6 +1174,9 @@ mm_answer_keyallowed(int sock, Buffer *m) allowed = options.hostbased_authentication && hostbased_key_allowed(authctxt->pw, cuser, chost, key); + pubkey_auth_info(authctxt, key, + "client user \"%.100s\", client host \"%.100s\"", + cuser, chost); auth_method = "hostbased"; break; case MM_RSAHOSTKEY: -- cgit v1.2.3 From 85b45e09188e7a7fc8f0a900a4c6a0f04a5720a7 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Sat, 20 Jul 2013 13:21:52 +1000 Subject: - markus@cvs.openbsd.org 2013/07/19 07:37:48 [auth.h kex.h kexdhs.c kexecdhs.c kexgexs.c monitor.c servconf.c] [servconf.h session.c sshd.c sshd_config.5] add ssh-agent(1) support to sshd(8); allows encrypted hostkeys, or hostkeys on smartcards; most of the work by Zev Weiss; bz #1974 ok djm@ --- ChangeLog | 9 +++++++ auth.h | 4 ++- kex.h | 3 ++- kexdhs.c | 10 +++---- kexecdhs.c | 10 +++---- kexgexs.c | 11 +++----- monitor.c | 18 ++++++++++--- servconf.c | 18 +++++++++++-- servconf.h | 3 ++- session.c | 10 ++++++- sshd.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++------ sshd_config.5 | 16 ++++++++++-- 12 files changed, 153 insertions(+), 42 deletions(-) (limited to 'auth.h') diff --git a/ChangeLog b/ChangeLog index 9530ef55f..fd66fed6d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +20130720 + - (djm) OpenBSD CVS Sync + - markus@cvs.openbsd.org 2013/07/19 07:37:48 + [auth.h kex.h kexdhs.c kexecdhs.c kexgexs.c monitor.c servconf.c] + [servconf.h session.c sshd.c sshd_config.5] + add ssh-agent(1) support to sshd(8); allows encrypted hostkeys, + or hostkeys on smartcards; most of the work by Zev Weiss; bz #1974 + ok djm@ + 20130718 - (djm) OpenBSD CVS Sync - dtucker@cvs.openbsd.org 2013/06/10 19:19:44 diff --git a/auth.h b/auth.h index caf44adc0..80f089869 100644 --- a/auth.h +++ b/auth.h @@ -1,4 +1,4 @@ -/* $OpenBSD: auth.h,v 1.75 2013/06/21 00:34:49 djm Exp $ */ +/* $OpenBSD: auth.h,v 1.76 2013/07/19 07:37:48 markus Exp $ */ /* * Copyright (c) 2000 Markus Friedl. All rights reserved. @@ -198,10 +198,12 @@ check_key_in_hostfiles(struct passwd *, Key *, const char *, /* hostkey handling */ Key *get_hostkey_by_index(int); +Key *get_hostkey_public_by_index(int); Key *get_hostkey_public_by_type(int); Key *get_hostkey_private_by_type(int); int get_hostkey_index(Key *); int ssh1_session_key(BIGNUM *); +void sshd_hostkey_sign(Key *, Key *, u_char **, u_int *, u_char *, u_int); /* debug messages during authentication */ void auth_debug_add(const char *fmt,...) __attribute__((format(printf, 1, 2))); diff --git a/kex.h b/kex.h index 680264af2..9f1e1adb3 100644 --- a/kex.h +++ b/kex.h @@ -1,4 +1,4 @@ -/* $OpenBSD: kex.h,v 1.55 2013/04/19 01:06:50 djm Exp $ */ +/* $OpenBSD: kex.h,v 1.56 2013/07/19 07:37:48 markus Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -139,6 +139,7 @@ struct Kex { Key *(*load_host_public_key)(int); Key *(*load_host_private_key)(int); int (*host_key_index)(Key *); + void (*sign)(Key *, Key *, u_char **, u_int *, u_char *, u_int); void (*kex[KEX_MAX])(Kex *); }; diff --git a/kexdhs.c b/kexdhs.c index 15128632c..269d80900 100644 --- a/kexdhs.c +++ b/kexdhs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexdhs.c,v 1.13 2013/05/17 00:13:13 djm Exp $ */ +/* $OpenBSD: kexdhs.c,v 1.14 2013/07/19 07:37:48 markus Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * @@ -80,9 +80,6 @@ kexdh_server(Kex *kex) if (server_host_public == NULL) fatal("Unsupported hostkey type %d", kex->hostkey_type); server_host_private = kex->load_host_private_key(kex->hostkey_type); - if (server_host_private == NULL) - fatal("Missing private key for hostkey type %d", - kex->hostkey_type); /* key, cert */ if ((dh_client_pub = BN_new()) == NULL) @@ -144,9 +141,8 @@ kexdh_server(Kex *kex) } /* sign H */ - if (PRIVSEP(key_sign(server_host_private, &signature, &slen, hash, - hashlen)) < 0) - fatal("kexdh_server: key_sign failed"); + kex->sign(server_host_private, server_host_public, &signature, &slen, + hash, hashlen); /* destroy_sensitive_data(); */ diff --git a/kexecdhs.c b/kexecdhs.c index c42dcf448..3a580aacf 100644 --- a/kexecdhs.c +++ b/kexecdhs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexecdhs.c,v 1.4 2013/05/17 00:13:13 djm Exp $ */ +/* $OpenBSD: kexecdhs.c,v 1.5 2013/07/19 07:37:48 markus Exp $ */ /* * Copyright (c) 2001 Markus Friedl. All rights reserved. * Copyright (c) 2010 Damien Miller. All rights reserved. @@ -78,9 +78,6 @@ kexecdh_server(Kex *kex) if (server_host_public == NULL) fatal("Unsupported hostkey type %d", kex->hostkey_type); server_host_private = kex->load_host_private_key(kex->hostkey_type); - if (server_host_private == NULL) - fatal("Missing private key for hostkey type %d", - kex->hostkey_type); debug("expecting SSH2_MSG_KEX_ECDH_INIT"); packet_read_expect(SSH2_MSG_KEX_ECDH_INIT); @@ -139,9 +136,8 @@ kexecdh_server(Kex *kex) } /* sign H */ - if (PRIVSEP(key_sign(server_host_private, &signature, &slen, - hash, hashlen)) < 0) - fatal("kexdh_server: key_sign failed"); + kex->sign(server_host_private, server_host_public, &signature, &slen, + hash, hashlen); /* destroy_sensitive_data(); */ diff --git a/kexgexs.c b/kexgexs.c index a543dda82..4e473fc73 100644 --- a/kexgexs.c +++ b/kexgexs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kexgexs.c,v 1.15 2013/05/17 00:13:13 djm Exp $ */ +/* $OpenBSD: kexgexs.c,v 1.16 2013/07/19 07:37:48 markus Exp $ */ /* * Copyright (c) 2000 Niels Provos. All rights reserved. * Copyright (c) 2001 Markus Friedl. All rights reserved. @@ -68,10 +68,6 @@ kexgex_server(Kex *kex) if (server_host_public == NULL) fatal("Unsupported hostkey type %d", kex->hostkey_type); server_host_private = kex->load_host_private_key(kex->hostkey_type); - if (server_host_private == NULL) - fatal("Missing private key for hostkey type %d", - kex->hostkey_type); - type = packet_read(); switch (type) { @@ -187,9 +183,8 @@ kexgex_server(Kex *kex) } /* sign H */ - if (PRIVSEP(key_sign(server_host_private, &signature, &slen, hash, - hashlen)) < 0) - fatal("kexgex_server: key_sign failed"); + kex->sign(server_host_private, server_host_public, &signature, &slen, + hash, hashlen); /* destroy_sensitive_data(); */ diff --git a/monitor.c b/monitor.c index 0516f60a2..44dff98c9 100644 --- a/monitor.c +++ b/monitor.c @@ -1,4 +1,4 @@ -/* $OpenBSD: monitor.c,v 1.126 2013/06/21 00:34:49 djm Exp $ */ +/* $OpenBSD: monitor.c,v 1.127 2013/07/19 07:37:48 markus Exp $ */ /* * Copyright 2002 Niels Provos * Copyright 2002 Markus Friedl @@ -97,6 +97,7 @@ #include "ssh2.h" #include "jpake.h" #include "roaming.h" +#include "authfd.h" #ifdef GSSAPI static Gssctxt *gsscontext = NULL; @@ -686,6 +687,8 @@ mm_answer_moduli(int sock, Buffer *m) return (0); } +extern AuthenticationConnection *auth_conn; + int mm_answer_sign(int sock, Buffer *m) { @@ -714,10 +717,16 @@ mm_answer_sign(int sock, Buffer *m) memcpy(session_id2, p, session_id2_len); } - if ((key = get_hostkey_by_index(keyid)) == NULL) + if ((key = get_hostkey_by_index(keyid)) != NULL) { + if (key_sign(key, &signature, &siglen, p, datlen) < 0) + fatal("%s: key_sign failed", __func__); + } else if ((key = get_hostkey_public_by_index(keyid)) != NULL && + auth_conn != NULL) { + if (ssh_agent_sign(auth_conn, key, &signature, &siglen, p, + datlen) < 0) + fatal("%s: ssh_agent_sign failed", __func__); + } else fatal("%s: no hostkey from index %d", __func__, keyid); - if (key_sign(key, &signature, &siglen, p, datlen) < 0) - fatal("%s: key_sign failed", __func__); debug3("%s: signature %p(%u)", __func__, signature, siglen); @@ -1864,6 +1873,7 @@ mm_get_kex(Buffer *m) kex->load_host_public_key=&get_hostkey_public_by_type; kex->load_host_private_key=&get_hostkey_private_by_type; kex->host_key_index=&get_hostkey_index; + kex->sign = sshd_hostkey_sign; return (kex); } diff --git a/servconf.c b/servconf.c index 36b8efecf..747edde6c 100644 --- a/servconf.c +++ b/servconf.c @@ -1,5 +1,5 @@ -/* $OpenBSD: servconf.c,v 1.239 2013/05/17 00:13:14 djm Exp $ */ +/* $OpenBSD: servconf.c,v 1.240 2013/07/19 07:37:48 markus Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -79,6 +79,7 @@ initialize_server_options(ServerOptions *options) options->address_family = -1; options->num_host_key_files = 0; options->num_host_cert_files = 0; + options->host_key_agent = NULL; options->pid_file = NULL; options->server_key_bits = -1; options->login_grace_time = -1; @@ -344,7 +345,7 @@ typedef enum { sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, sKexAlgorithms, sIPQoS, sVersionAddendum, sAuthorizedKeysCommand, sAuthorizedKeysCommandUser, - sAuthenticationMethods, + sAuthenticationMethods, sHostKeyAgent, sDeprecated, sUnsupported } ServerOpCodes; @@ -369,6 +370,7 @@ static struct { { "port", sPort, SSHCFG_GLOBAL }, { "hostkey", sHostKeyFile, SSHCFG_GLOBAL }, { "hostdsakey", sHostKeyFile, SSHCFG_GLOBAL }, /* alias */ + { "hostkeyagent", sHostKeyAgent, SSHCFG_GLOBAL }, { "pidfile", sPidFile, SSHCFG_GLOBAL }, { "serverkeybits", sServerKeyBits, SSHCFG_GLOBAL }, { "logingracetime", sLoginGraceTime, SSHCFG_GLOBAL }, @@ -978,6 +980,17 @@ process_server_config_line(ServerOptions *options, char *line, } break; + case sHostKeyAgent: + charptr = &options->host_key_agent; + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: missing socket name.", + filename, linenum); + if (*activep && *charptr == NULL) + *charptr = !strcmp(arg, SSH_AUTHSOCKET_ENV_NAME) ? + xstrdup(arg) : derelativise_path(arg); + break; + case sHostCertificate: intptr = &options->num_host_cert_files; if (*intptr >= MAX_HOSTKEYS) @@ -2011,6 +2024,7 @@ dump_config(ServerOptions *o) dump_cfg_string(sVersionAddendum, o->version_addendum); dump_cfg_string(sAuthorizedKeysCommand, o->authorized_keys_command); dump_cfg_string(sAuthorizedKeysCommandUser, o->authorized_keys_command_user); + dump_cfg_string(sHostKeyAgent, o->host_key_agent); /* string arguments requiring a lookup */ dump_cfg_string(sLogLevel, log_level_name(o->log_level)); diff --git a/servconf.h b/servconf.h index fc051bd4b..98aad8ba2 100644 --- a/servconf.h +++ b/servconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: servconf.h,v 1.108 2013/05/16 04:09:14 dtucker Exp $ */ +/* $OpenBSD: servconf.h,v 1.109 2013/07/19 07:37:48 markus Exp $ */ /* * Author: Tatu Ylonen @@ -65,6 +65,7 @@ typedef struct { int num_host_key_files; /* Number of files for host keys. */ char *host_cert_files[MAX_HOSTCERTS]; /* Files containing host certs. */ int num_host_cert_files; /* Number of files for host certs. */ + char *host_key_agent; /* ssh-agent socket for host keys. */ char *pid_file; /* Where to put our pid */ int server_key_bits;/* Size of the server key. */ int login_grace_time; /* Disconnect if no auth in this time diff --git a/session.c b/session.c index 1424825ca..d4b57bdfb 100644 --- a/session.c +++ b/session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: session.c,v 1.265 2013/05/17 00:13:14 djm Exp $ */ +/* $OpenBSD: session.c,v 1.266 2013/07/19 07:37:48 markus Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -80,6 +80,7 @@ #include "hostfile.h" #include "auth.h" #include "auth-options.h" +#include "authfd.h" #include "pathnames.h" #include "log.h" #include "servconf.h" @@ -1589,6 +1590,13 @@ launch_login(struct passwd *pw, const char *hostname) static void child_close_fds(void) { + extern AuthenticationConnection *auth_conn; + + if (auth_conn) { + ssh_close_authentication_connection(auth_conn); + auth_conn = NULL; + } + if (packet_get_connection_in() == packet_get_connection_out()) close(packet_get_connection_in()); else { diff --git a/sshd.c b/sshd.c index 1306a62a7..174cc7a42 100644 --- a/sshd.c +++ b/sshd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshd.c,v 1.403 2013/06/05 02:27:50 dtucker Exp $ */ +/* $OpenBSD: sshd.c,v 1.404 2013/07/19 07:37:48 markus Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -106,6 +106,7 @@ #include "canohost.h" #include "hostfile.h" #include "auth.h" +#include "authfd.h" #include "misc.h" #include "msg.h" #include "dispatch.h" @@ -194,6 +195,10 @@ char *server_version_string = NULL; /* for rekeying XXX fixme */ Kex *xxx_kex; +/* Daemon's agent connection */ +AuthenticationConnection *auth_conn = NULL; +int have_agent = 0; + /* * Any really sensitive data in the application is contained in this * structure. The idea is that this structure could be locked into memory so @@ -206,6 +211,7 @@ struct { Key *server_key; /* ephemeral server key */ Key *ssh1_host_key; /* ssh1 host key */ Key **host_keys; /* all private host keys */ + Key **host_pubkeys; /* all public host keys */ Key **host_certificates; /* all public host certificates */ int have_ssh1_key; int have_ssh2_key; @@ -653,6 +659,8 @@ privsep_preauth(Authctxt *authctxt) debug2("Network child is on pid %ld", (long)pid); pmonitor->m_pid = pid; + if (have_agent) + auth_conn = ssh_get_authentication_connection(); if (box != NULL) ssh_sandbox_parent_preauth(box, pid); monitor_child_preauth(authctxt, pmonitor); @@ -766,6 +774,8 @@ list_hostkey_types(void) buffer_init(&b); for (i = 0; i < options.num_host_key_files; i++) { key = sensitive_data.host_keys[i]; + if (key == NULL) + key = sensitive_data.host_pubkeys[i]; if (key == NULL) continue; switch (key->type) { @@ -819,6 +829,8 @@ get_hostkey_by_type(int type, int need_private) break; default: key = sensitive_data.host_keys[i]; + if (key == NULL && !need_private) + key = sensitive_data.host_pubkeys[i]; break; } if (key != NULL && key->type == type) @@ -848,6 +860,14 @@ get_hostkey_by_index(int ind) return (sensitive_data.host_keys[ind]); } +Key * +get_hostkey_public_by_index(int ind) +{ + if (ind < 0 || ind >= options.num_host_key_files) + return (NULL); + return (sensitive_data.host_pubkeys[ind]); +} + int get_hostkey_index(Key *key) { @@ -860,6 +880,8 @@ get_hostkey_index(Key *key) } else { if (key == sensitive_data.host_keys[i]) return (i); + if (key == sensitive_data.host_pubkeys[i]) + return (i); } } return (-1); @@ -1344,6 +1366,8 @@ main(int ac, char **av) u_int64_t ibytes, obytes; mode_t new_umask; Key *key; + Key *pubkey; + int keytype; Authctxt *authctxt; struct connection_info *connection_info = get_connection_info(0, 0); @@ -1623,22 +1647,45 @@ main(int ac, char **av) } endpwent(); - /* load private host keys */ + /* load host keys */ sensitive_data.host_keys = xcalloc(options.num_host_key_files, sizeof(Key *)); - for (i = 0; i < options.num_host_key_files; i++) + sensitive_data.host_pubkeys = xcalloc(options.num_host_key_files, + sizeof(Key *)); + for (i = 0; i < options.num_host_key_files; i++) { sensitive_data.host_keys[i] = NULL; + sensitive_data.host_pubkeys[i] = NULL; + } + + if (options.host_key_agent) { + if (strcmp(options.host_key_agent, SSH_AUTHSOCKET_ENV_NAME)) + setenv(SSH_AUTHSOCKET_ENV_NAME, + options.host_key_agent, 1); + have_agent = ssh_agent_present(); + } for (i = 0; i < options.num_host_key_files; i++) { key = key_load_private(options.host_key_files[i], "", NULL); + pubkey = key_load_public(options.host_key_files[i], NULL); sensitive_data.host_keys[i] = key; - if (key == NULL) { + sensitive_data.host_pubkeys[i] = pubkey; + + if (key == NULL && pubkey != NULL && pubkey->type != KEY_RSA1 && + have_agent) { + debug("will rely on agent for hostkey %s", + options.host_key_files[i]); + keytype = pubkey->type; + } else if (key != NULL) { + keytype = key->type; + } else { error("Could not load host key: %s", options.host_key_files[i]); sensitive_data.host_keys[i] = NULL; + sensitive_data.host_pubkeys[i] = NULL; continue; } - switch (key->type) { + + switch (keytype) { case KEY_RSA1: sensitive_data.ssh1_host_key = key; sensitive_data.have_ssh1_key = 1; @@ -1649,8 +1696,8 @@ main(int ac, char **av) sensitive_data.have_ssh2_key = 1; break; } - debug("private host key: #%d type %d %s", i, key->type, - key_type(key)); + debug("private host key: #%d type %d %s", i, keytype, + key_type(key ? key : pubkey)); } if ((options.protocol & SSH_PROTO_1) && !sensitive_data.have_ssh1_key) { logit("Disabling protocol version 1. Could not load host key"); @@ -2020,9 +2067,11 @@ main(int ac, char **av) buffer_init(&loginmsg); auth_debug_reset(); - if (use_privsep) + if (use_privsep) { if (privsep_preauth(authctxt) == 1) goto authenticated; + } else if (compat20 && have_agent) + auth_conn = ssh_get_authentication_connection(); /* perform the key exchange */ /* authenticate user and start session */ @@ -2336,6 +2385,23 @@ do_ssh1_kex(void) packet_write_wait(); } +void +sshd_hostkey_sign(Key *privkey, Key *pubkey, u_char **signature, u_int *slen, + u_char *data, u_int dlen) +{ + if (privkey) { + if (PRIVSEP(key_sign(privkey, signature, slen, data, dlen) < 0)) + fatal("%s: key_sign failed", __func__); + } else if (use_privsep) { + if (mm_key_sign(pubkey, signature, slen, data, dlen) < 0) + fatal("%s: pubkey_sign failed", __func__); + } else { + if (ssh_agent_sign(auth_conn, pubkey, signature, slen, data, + dlen)) + fatal("%s: ssh_agent_sign failed", __func__); + } +} + /* * SSH2 key exchange: diffie-hellman-group1-sha1 */ @@ -2386,6 +2452,7 @@ do_ssh2_kex(void) kex->load_host_public_key=&get_hostkey_public_by_type; kex->load_host_private_key=&get_hostkey_private_by_type; kex->host_key_index=&get_hostkey_index; + kex->sign = sshd_hostkey_sign; xxx_kex = kex; diff --git a/sshd_config.5 b/sshd_config.5 index 3807c0f3c..3abac6c10 100644 --- a/sshd_config.5 +++ b/sshd_config.5 @@ -33,8 +33,8 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.\" $OpenBSD: sshd_config.5,v 1.161 2013/06/27 14:05:37 jmc Exp $ -.Dd $Mdocdate: June 27 2013 $ +.\" $OpenBSD: sshd_config.5,v 1.162 2013/07/19 07:37:48 markus Exp $ +.Dd $Mdocdate: July 19 2013 $ .Dt SSHD_CONFIG 5 .Os .Sh NAME @@ -546,6 +546,18 @@ keys are used for version 1 and or .Dq rsa are used for version 2 of the SSH protocol. +It is also possible to specify public host key files instead. +In this case operations on the private key will be delegated +to an +.Xr ssh-agent 1 . +.It Cm HostKeyAgent +Identifies the UNIX-domain socket used to communicate +with an agent that has access to the private host keys. +If +.Dq SSH_AUTH_SOCK +is specified, the location of the socket will be read from the +.Ev SSH_AUTH_SOCK +environment variable. .It Cm IgnoreRhosts Specifies that .Pa .rhosts -- cgit v1.2.3