diff options
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | auth.h | 4 | ||||
-rw-r--r-- | kex.h | 3 | ||||
-rw-r--r-- | kexdhs.c | 10 | ||||
-rw-r--r-- | kexecdhs.c | 10 | ||||
-rw-r--r-- | kexgexs.c | 11 | ||||
-rw-r--r-- | monitor.c | 18 | ||||
-rw-r--r-- | servconf.c | 18 | ||||
-rw-r--r-- | servconf.h | 3 | ||||
-rw-r--r-- | session.c | 10 | ||||
-rw-r--r-- | sshd.c | 83 | ||||
-rw-r--r-- | sshd_config.5 | 16 |
12 files changed, 153 insertions, 42 deletions
@@ -1,3 +1,12 @@ | |||
1 | 20130720 | ||
2 | - (djm) OpenBSD CVS Sync | ||
3 | - markus@cvs.openbsd.org 2013/07/19 07:37:48 | ||
4 | [auth.h kex.h kexdhs.c kexecdhs.c kexgexs.c monitor.c servconf.c] | ||
5 | [servconf.h session.c sshd.c sshd_config.5] | ||
6 | add ssh-agent(1) support to sshd(8); allows encrypted hostkeys, | ||
7 | or hostkeys on smartcards; most of the work by Zev Weiss; bz #1974 | ||
8 | ok djm@ | ||
9 | |||
1 | 20130718 | 10 | 20130718 |
2 | - (djm) OpenBSD CVS Sync | 11 | - (djm) OpenBSD CVS Sync |
3 | - dtucker@cvs.openbsd.org 2013/06/10 19:19:44 | 12 | - dtucker@cvs.openbsd.org 2013/06/10 19:19:44 |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: auth.h,v 1.75 2013/06/21 00:34:49 djm Exp $ */ | 1 | /* $OpenBSD: auth.h,v 1.76 2013/07/19 07:37:48 markus Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 4 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
@@ -198,10 +198,12 @@ check_key_in_hostfiles(struct passwd *, Key *, const char *, | |||
198 | 198 | ||
199 | /* hostkey handling */ | 199 | /* hostkey handling */ |
200 | Key *get_hostkey_by_index(int); | 200 | Key *get_hostkey_by_index(int); |
201 | Key *get_hostkey_public_by_index(int); | ||
201 | Key *get_hostkey_public_by_type(int); | 202 | Key *get_hostkey_public_by_type(int); |
202 | Key *get_hostkey_private_by_type(int); | 203 | Key *get_hostkey_private_by_type(int); |
203 | int get_hostkey_index(Key *); | 204 | int get_hostkey_index(Key *); |
204 | int ssh1_session_key(BIGNUM *); | 205 | int ssh1_session_key(BIGNUM *); |
206 | void sshd_hostkey_sign(Key *, Key *, u_char **, u_int *, u_char *, u_int); | ||
205 | 207 | ||
206 | /* debug messages during authentication */ | 208 | /* debug messages during authentication */ |
207 | void auth_debug_add(const char *fmt,...) __attribute__((format(printf, 1, 2))); | 209 | void auth_debug_add(const char *fmt,...) __attribute__((format(printf, 1, 2))); |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: kex.h,v 1.55 2013/04/19 01:06:50 djm Exp $ */ | 1 | /* $OpenBSD: kex.h,v 1.56 2013/07/19 07:37:48 markus Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. | 4 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. |
@@ -139,6 +139,7 @@ struct Kex { | |||
139 | Key *(*load_host_public_key)(int); | 139 | Key *(*load_host_public_key)(int); |
140 | Key *(*load_host_private_key)(int); | 140 | Key *(*load_host_private_key)(int); |
141 | int (*host_key_index)(Key *); | 141 | int (*host_key_index)(Key *); |
142 | void (*sign)(Key *, Key *, u_char **, u_int *, u_char *, u_int); | ||
142 | void (*kex[KEX_MAX])(Kex *); | 143 | void (*kex[KEX_MAX])(Kex *); |
143 | }; | 144 | }; |
144 | 145 | ||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: kexdhs.c,v 1.13 2013/05/17 00:13:13 djm Exp $ */ | 1 | /* $OpenBSD: kexdhs.c,v 1.14 2013/07/19 07:37:48 markus Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2001 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2001 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -80,9 +80,6 @@ kexdh_server(Kex *kex) | |||
80 | if (server_host_public == NULL) | 80 | if (server_host_public == NULL) |
81 | fatal("Unsupported hostkey type %d", kex->hostkey_type); | 81 | fatal("Unsupported hostkey type %d", kex->hostkey_type); |
82 | server_host_private = kex->load_host_private_key(kex->hostkey_type); | 82 | server_host_private = kex->load_host_private_key(kex->hostkey_type); |
83 | if (server_host_private == NULL) | ||
84 | fatal("Missing private key for hostkey type %d", | ||
85 | kex->hostkey_type); | ||
86 | 83 | ||
87 | /* key, cert */ | 84 | /* key, cert */ |
88 | if ((dh_client_pub = BN_new()) == NULL) | 85 | if ((dh_client_pub = BN_new()) == NULL) |
@@ -144,9 +141,8 @@ kexdh_server(Kex *kex) | |||
144 | } | 141 | } |
145 | 142 | ||
146 | /* sign H */ | 143 | /* sign H */ |
147 | if (PRIVSEP(key_sign(server_host_private, &signature, &slen, hash, | 144 | kex->sign(server_host_private, server_host_public, &signature, &slen, |
148 | hashlen)) < 0) | 145 | hash, hashlen); |
149 | fatal("kexdh_server: key_sign failed"); | ||
150 | 146 | ||
151 | /* destroy_sensitive_data(); */ | 147 | /* destroy_sensitive_data(); */ |
152 | 148 | ||
diff --git a/kexecdhs.c b/kexecdhs.c index c42dcf448..3a580aacf 100644 --- a/kexecdhs.c +++ b/kexecdhs.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: kexecdhs.c,v 1.4 2013/05/17 00:13:13 djm Exp $ */ | 1 | /* $OpenBSD: kexecdhs.c,v 1.5 2013/07/19 07:37:48 markus Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2001 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2001 Markus Friedl. All rights reserved. |
4 | * Copyright (c) 2010 Damien Miller. All rights reserved. | 4 | * Copyright (c) 2010 Damien Miller. All rights reserved. |
@@ -78,9 +78,6 @@ kexecdh_server(Kex *kex) | |||
78 | if (server_host_public == NULL) | 78 | if (server_host_public == NULL) |
79 | fatal("Unsupported hostkey type %d", kex->hostkey_type); | 79 | fatal("Unsupported hostkey type %d", kex->hostkey_type); |
80 | server_host_private = kex->load_host_private_key(kex->hostkey_type); | 80 | server_host_private = kex->load_host_private_key(kex->hostkey_type); |
81 | if (server_host_private == NULL) | ||
82 | fatal("Missing private key for hostkey type %d", | ||
83 | kex->hostkey_type); | ||
84 | 81 | ||
85 | debug("expecting SSH2_MSG_KEX_ECDH_INIT"); | 82 | debug("expecting SSH2_MSG_KEX_ECDH_INIT"); |
86 | packet_read_expect(SSH2_MSG_KEX_ECDH_INIT); | 83 | packet_read_expect(SSH2_MSG_KEX_ECDH_INIT); |
@@ -139,9 +136,8 @@ kexecdh_server(Kex *kex) | |||
139 | } | 136 | } |
140 | 137 | ||
141 | /* sign H */ | 138 | /* sign H */ |
142 | if (PRIVSEP(key_sign(server_host_private, &signature, &slen, | 139 | kex->sign(server_host_private, server_host_public, &signature, &slen, |
143 | hash, hashlen)) < 0) | 140 | hash, hashlen); |
144 | fatal("kexdh_server: key_sign failed"); | ||
145 | 141 | ||
146 | /* destroy_sensitive_data(); */ | 142 | /* destroy_sensitive_data(); */ |
147 | 143 | ||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: kexgexs.c,v 1.15 2013/05/17 00:13:13 djm Exp $ */ | 1 | /* $OpenBSD: kexgexs.c,v 1.16 2013/07/19 07:37:48 markus Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Niels Provos. All rights reserved. | 3 | * Copyright (c) 2000 Niels Provos. All rights reserved. |
4 | * Copyright (c) 2001 Markus Friedl. All rights reserved. | 4 | * Copyright (c) 2001 Markus Friedl. All rights reserved. |
@@ -68,10 +68,6 @@ kexgex_server(Kex *kex) | |||
68 | if (server_host_public == NULL) | 68 | if (server_host_public == NULL) |
69 | fatal("Unsupported hostkey type %d", kex->hostkey_type); | 69 | fatal("Unsupported hostkey type %d", kex->hostkey_type); |
70 | server_host_private = kex->load_host_private_key(kex->hostkey_type); | 70 | server_host_private = kex->load_host_private_key(kex->hostkey_type); |
71 | if (server_host_private == NULL) | ||
72 | fatal("Missing private key for hostkey type %d", | ||
73 | kex->hostkey_type); | ||
74 | |||
75 | 71 | ||
76 | type = packet_read(); | 72 | type = packet_read(); |
77 | switch (type) { | 73 | switch (type) { |
@@ -187,9 +183,8 @@ kexgex_server(Kex *kex) | |||
187 | } | 183 | } |
188 | 184 | ||
189 | /* sign H */ | 185 | /* sign H */ |
190 | if (PRIVSEP(key_sign(server_host_private, &signature, &slen, hash, | 186 | kex->sign(server_host_private, server_host_public, &signature, &slen, |
191 | hashlen)) < 0) | 187 | hash, hashlen); |
192 | fatal("kexgex_server: key_sign failed"); | ||
193 | 188 | ||
194 | /* destroy_sensitive_data(); */ | 189 | /* destroy_sensitive_data(); */ |
195 | 190 | ||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: monitor.c,v 1.126 2013/06/21 00:34:49 djm Exp $ */ | 1 | /* $OpenBSD: monitor.c,v 1.127 2013/07/19 07:37:48 markus Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright 2002 Niels Provos <provos@citi.umich.edu> | 3 | * Copyright 2002 Niels Provos <provos@citi.umich.edu> |
4 | * Copyright 2002 Markus Friedl <markus@openbsd.org> | 4 | * Copyright 2002 Markus Friedl <markus@openbsd.org> |
@@ -97,6 +97,7 @@ | |||
97 | #include "ssh2.h" | 97 | #include "ssh2.h" |
98 | #include "jpake.h" | 98 | #include "jpake.h" |
99 | #include "roaming.h" | 99 | #include "roaming.h" |
100 | #include "authfd.h" | ||
100 | 101 | ||
101 | #ifdef GSSAPI | 102 | #ifdef GSSAPI |
102 | static Gssctxt *gsscontext = NULL; | 103 | static Gssctxt *gsscontext = NULL; |
@@ -686,6 +687,8 @@ mm_answer_moduli(int sock, Buffer *m) | |||
686 | return (0); | 687 | return (0); |
687 | } | 688 | } |
688 | 689 | ||
690 | extern AuthenticationConnection *auth_conn; | ||
691 | |||
689 | int | 692 | int |
690 | mm_answer_sign(int sock, Buffer *m) | 693 | mm_answer_sign(int sock, Buffer *m) |
691 | { | 694 | { |
@@ -714,10 +717,16 @@ mm_answer_sign(int sock, Buffer *m) | |||
714 | memcpy(session_id2, p, session_id2_len); | 717 | memcpy(session_id2, p, session_id2_len); |
715 | } | 718 | } |
716 | 719 | ||
717 | if ((key = get_hostkey_by_index(keyid)) == NULL) | 720 | if ((key = get_hostkey_by_index(keyid)) != NULL) { |
721 | if (key_sign(key, &signature, &siglen, p, datlen) < 0) | ||
722 | fatal("%s: key_sign failed", __func__); | ||
723 | } else if ((key = get_hostkey_public_by_index(keyid)) != NULL && | ||
724 | auth_conn != NULL) { | ||
725 | if (ssh_agent_sign(auth_conn, key, &signature, &siglen, p, | ||
726 | datlen) < 0) | ||
727 | fatal("%s: ssh_agent_sign failed", __func__); | ||
728 | } else | ||
718 | fatal("%s: no hostkey from index %d", __func__, keyid); | 729 | fatal("%s: no hostkey from index %d", __func__, keyid); |
719 | if (key_sign(key, &signature, &siglen, p, datlen) < 0) | ||
720 | fatal("%s: key_sign failed", __func__); | ||
721 | 730 | ||
722 | debug3("%s: signature %p(%u)", __func__, signature, siglen); | 731 | debug3("%s: signature %p(%u)", __func__, signature, siglen); |
723 | 732 | ||
@@ -1864,6 +1873,7 @@ mm_get_kex(Buffer *m) | |||
1864 | kex->load_host_public_key=&get_hostkey_public_by_type; | 1873 | kex->load_host_public_key=&get_hostkey_public_by_type; |
1865 | kex->load_host_private_key=&get_hostkey_private_by_type; | 1874 | kex->load_host_private_key=&get_hostkey_private_by_type; |
1866 | kex->host_key_index=&get_hostkey_index; | 1875 | kex->host_key_index=&get_hostkey_index; |
1876 | kex->sign = sshd_hostkey_sign; | ||
1867 | 1877 | ||
1868 | return (kex); | 1878 | return (kex); |
1869 | } | 1879 | } |
diff --git a/servconf.c b/servconf.c index 36b8efecf..747edde6c 100644 --- a/servconf.c +++ b/servconf.c | |||
@@ -1,5 +1,5 @@ | |||
1 | 1 | ||
2 | /* $OpenBSD: servconf.c,v 1.239 2013/05/17 00:13:14 djm Exp $ */ | 2 | /* $OpenBSD: servconf.c,v 1.240 2013/07/19 07:37:48 markus Exp $ */ |
3 | /* | 3 | /* |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
5 | * All rights reserved | 5 | * All rights reserved |
@@ -79,6 +79,7 @@ initialize_server_options(ServerOptions *options) | |||
79 | options->address_family = -1; | 79 | options->address_family = -1; |
80 | options->num_host_key_files = 0; | 80 | options->num_host_key_files = 0; |
81 | options->num_host_cert_files = 0; | 81 | options->num_host_cert_files = 0; |
82 | options->host_key_agent = NULL; | ||
82 | options->pid_file = NULL; | 83 | options->pid_file = NULL; |
83 | options->server_key_bits = -1; | 84 | options->server_key_bits = -1; |
84 | options->login_grace_time = -1; | 85 | options->login_grace_time = -1; |
@@ -344,7 +345,7 @@ typedef enum { | |||
344 | sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, | 345 | sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, |
345 | sKexAlgorithms, sIPQoS, sVersionAddendum, | 346 | sKexAlgorithms, sIPQoS, sVersionAddendum, |
346 | sAuthorizedKeysCommand, sAuthorizedKeysCommandUser, | 347 | sAuthorizedKeysCommand, sAuthorizedKeysCommandUser, |
347 | sAuthenticationMethods, | 348 | sAuthenticationMethods, sHostKeyAgent, |
348 | sDeprecated, sUnsupported | 349 | sDeprecated, sUnsupported |
349 | } ServerOpCodes; | 350 | } ServerOpCodes; |
350 | 351 | ||
@@ -369,6 +370,7 @@ static struct { | |||
369 | { "port", sPort, SSHCFG_GLOBAL }, | 370 | { "port", sPort, SSHCFG_GLOBAL }, |
370 | { "hostkey", sHostKeyFile, SSHCFG_GLOBAL }, | 371 | { "hostkey", sHostKeyFile, SSHCFG_GLOBAL }, |
371 | { "hostdsakey", sHostKeyFile, SSHCFG_GLOBAL }, /* alias */ | 372 | { "hostdsakey", sHostKeyFile, SSHCFG_GLOBAL }, /* alias */ |
373 | { "hostkeyagent", sHostKeyAgent, SSHCFG_GLOBAL }, | ||
372 | { "pidfile", sPidFile, SSHCFG_GLOBAL }, | 374 | { "pidfile", sPidFile, SSHCFG_GLOBAL }, |
373 | { "serverkeybits", sServerKeyBits, SSHCFG_GLOBAL }, | 375 | { "serverkeybits", sServerKeyBits, SSHCFG_GLOBAL }, |
374 | { "logingracetime", sLoginGraceTime, SSHCFG_GLOBAL }, | 376 | { "logingracetime", sLoginGraceTime, SSHCFG_GLOBAL }, |
@@ -978,6 +980,17 @@ process_server_config_line(ServerOptions *options, char *line, | |||
978 | } | 980 | } |
979 | break; | 981 | break; |
980 | 982 | ||
983 | case sHostKeyAgent: | ||
984 | charptr = &options->host_key_agent; | ||
985 | arg = strdelim(&cp); | ||
986 | if (!arg || *arg == '\0') | ||
987 | fatal("%s line %d: missing socket name.", | ||
988 | filename, linenum); | ||
989 | if (*activep && *charptr == NULL) | ||
990 | *charptr = !strcmp(arg, SSH_AUTHSOCKET_ENV_NAME) ? | ||
991 | xstrdup(arg) : derelativise_path(arg); | ||
992 | break; | ||
993 | |||
981 | case sHostCertificate: | 994 | case sHostCertificate: |
982 | intptr = &options->num_host_cert_files; | 995 | intptr = &options->num_host_cert_files; |
983 | if (*intptr >= MAX_HOSTKEYS) | 996 | if (*intptr >= MAX_HOSTKEYS) |
@@ -2011,6 +2024,7 @@ dump_config(ServerOptions *o) | |||
2011 | dump_cfg_string(sVersionAddendum, o->version_addendum); | 2024 | dump_cfg_string(sVersionAddendum, o->version_addendum); |
2012 | dump_cfg_string(sAuthorizedKeysCommand, o->authorized_keys_command); | 2025 | dump_cfg_string(sAuthorizedKeysCommand, o->authorized_keys_command); |
2013 | dump_cfg_string(sAuthorizedKeysCommandUser, o->authorized_keys_command_user); | 2026 | dump_cfg_string(sAuthorizedKeysCommandUser, o->authorized_keys_command_user); |
2027 | dump_cfg_string(sHostKeyAgent, o->host_key_agent); | ||
2014 | 2028 | ||
2015 | /* string arguments requiring a lookup */ | 2029 | /* string arguments requiring a lookup */ |
2016 | dump_cfg_string(sLogLevel, log_level_name(o->log_level)); | 2030 | 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 @@ | |||
1 | /* $OpenBSD: servconf.h,v 1.108 2013/05/16 04:09:14 dtucker Exp $ */ | 1 | /* $OpenBSD: servconf.h,v 1.109 2013/07/19 07:37:48 markus Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
@@ -65,6 +65,7 @@ typedef struct { | |||
65 | int num_host_key_files; /* Number of files for host keys. */ | 65 | int num_host_key_files; /* Number of files for host keys. */ |
66 | char *host_cert_files[MAX_HOSTCERTS]; /* Files containing host certs. */ | 66 | char *host_cert_files[MAX_HOSTCERTS]; /* Files containing host certs. */ |
67 | int num_host_cert_files; /* Number of files for host certs. */ | 67 | int num_host_cert_files; /* Number of files for host certs. */ |
68 | char *host_key_agent; /* ssh-agent socket for host keys. */ | ||
68 | char *pid_file; /* Where to put our pid */ | 69 | char *pid_file; /* Where to put our pid */ |
69 | int server_key_bits;/* Size of the server key. */ | 70 | int server_key_bits;/* Size of the server key. */ |
70 | int login_grace_time; /* Disconnect if no auth in this time | 71 | int login_grace_time; /* Disconnect if no auth in this time |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: session.c,v 1.265 2013/05/17 00:13:14 djm Exp $ */ | 1 | /* $OpenBSD: session.c,v 1.266 2013/07/19 07:37:48 markus Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 3 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
4 | * All rights reserved | 4 | * All rights reserved |
@@ -80,6 +80,7 @@ | |||
80 | #include "hostfile.h" | 80 | #include "hostfile.h" |
81 | #include "auth.h" | 81 | #include "auth.h" |
82 | #include "auth-options.h" | 82 | #include "auth-options.h" |
83 | #include "authfd.h" | ||
83 | #include "pathnames.h" | 84 | #include "pathnames.h" |
84 | #include "log.h" | 85 | #include "log.h" |
85 | #include "servconf.h" | 86 | #include "servconf.h" |
@@ -1589,6 +1590,13 @@ launch_login(struct passwd *pw, const char *hostname) | |||
1589 | static void | 1590 | static void |
1590 | child_close_fds(void) | 1591 | child_close_fds(void) |
1591 | { | 1592 | { |
1593 | extern AuthenticationConnection *auth_conn; | ||
1594 | |||
1595 | if (auth_conn) { | ||
1596 | ssh_close_authentication_connection(auth_conn); | ||
1597 | auth_conn = NULL; | ||
1598 | } | ||
1599 | |||
1592 | if (packet_get_connection_in() == packet_get_connection_out()) | 1600 | if (packet_get_connection_in() == packet_get_connection_out()) |
1593 | close(packet_get_connection_in()); | 1601 | close(packet_get_connection_in()); |
1594 | else { | 1602 | else { |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshd.c,v 1.403 2013/06/05 02:27:50 dtucker Exp $ */ | 1 | /* $OpenBSD: sshd.c,v 1.404 2013/07/19 07:37:48 markus Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -106,6 +106,7 @@ | |||
106 | #include "canohost.h" | 106 | #include "canohost.h" |
107 | #include "hostfile.h" | 107 | #include "hostfile.h" |
108 | #include "auth.h" | 108 | #include "auth.h" |
109 | #include "authfd.h" | ||
109 | #include "misc.h" | 110 | #include "misc.h" |
110 | #include "msg.h" | 111 | #include "msg.h" |
111 | #include "dispatch.h" | 112 | #include "dispatch.h" |
@@ -194,6 +195,10 @@ char *server_version_string = NULL; | |||
194 | /* for rekeying XXX fixme */ | 195 | /* for rekeying XXX fixme */ |
195 | Kex *xxx_kex; | 196 | Kex *xxx_kex; |
196 | 197 | ||
198 | /* Daemon's agent connection */ | ||
199 | AuthenticationConnection *auth_conn = NULL; | ||
200 | int have_agent = 0; | ||
201 | |||
197 | /* | 202 | /* |
198 | * Any really sensitive data in the application is contained in this | 203 | * Any really sensitive data in the application is contained in this |
199 | * structure. The idea is that this structure could be locked into memory so | 204 | * structure. The idea is that this structure could be locked into memory so |
@@ -206,6 +211,7 @@ struct { | |||
206 | Key *server_key; /* ephemeral server key */ | 211 | Key *server_key; /* ephemeral server key */ |
207 | Key *ssh1_host_key; /* ssh1 host key */ | 212 | Key *ssh1_host_key; /* ssh1 host key */ |
208 | Key **host_keys; /* all private host keys */ | 213 | Key **host_keys; /* all private host keys */ |
214 | Key **host_pubkeys; /* all public host keys */ | ||
209 | Key **host_certificates; /* all public host certificates */ | 215 | Key **host_certificates; /* all public host certificates */ |
210 | int have_ssh1_key; | 216 | int have_ssh1_key; |
211 | int have_ssh2_key; | 217 | int have_ssh2_key; |
@@ -653,6 +659,8 @@ privsep_preauth(Authctxt *authctxt) | |||
653 | debug2("Network child is on pid %ld", (long)pid); | 659 | debug2("Network child is on pid %ld", (long)pid); |
654 | 660 | ||
655 | pmonitor->m_pid = pid; | 661 | pmonitor->m_pid = pid; |
662 | if (have_agent) | ||
663 | auth_conn = ssh_get_authentication_connection(); | ||
656 | if (box != NULL) | 664 | if (box != NULL) |
657 | ssh_sandbox_parent_preauth(box, pid); | 665 | ssh_sandbox_parent_preauth(box, pid); |
658 | monitor_child_preauth(authctxt, pmonitor); | 666 | monitor_child_preauth(authctxt, pmonitor); |
@@ -767,6 +775,8 @@ list_hostkey_types(void) | |||
767 | for (i = 0; i < options.num_host_key_files; i++) { | 775 | for (i = 0; i < options.num_host_key_files; i++) { |
768 | key = sensitive_data.host_keys[i]; | 776 | key = sensitive_data.host_keys[i]; |
769 | if (key == NULL) | 777 | if (key == NULL) |
778 | key = sensitive_data.host_pubkeys[i]; | ||
779 | if (key == NULL) | ||
770 | continue; | 780 | continue; |
771 | switch (key->type) { | 781 | switch (key->type) { |
772 | case KEY_RSA: | 782 | case KEY_RSA: |
@@ -819,6 +829,8 @@ get_hostkey_by_type(int type, int need_private) | |||
819 | break; | 829 | break; |
820 | default: | 830 | default: |
821 | key = sensitive_data.host_keys[i]; | 831 | key = sensitive_data.host_keys[i]; |
832 | if (key == NULL && !need_private) | ||
833 | key = sensitive_data.host_pubkeys[i]; | ||
822 | break; | 834 | break; |
823 | } | 835 | } |
824 | if (key != NULL && key->type == type) | 836 | if (key != NULL && key->type == type) |
@@ -848,6 +860,14 @@ get_hostkey_by_index(int ind) | |||
848 | return (sensitive_data.host_keys[ind]); | 860 | return (sensitive_data.host_keys[ind]); |
849 | } | 861 | } |
850 | 862 | ||
863 | Key * | ||
864 | get_hostkey_public_by_index(int ind) | ||
865 | { | ||
866 | if (ind < 0 || ind >= options.num_host_key_files) | ||
867 | return (NULL); | ||
868 | return (sensitive_data.host_pubkeys[ind]); | ||
869 | } | ||
870 | |||
851 | int | 871 | int |
852 | get_hostkey_index(Key *key) | 872 | get_hostkey_index(Key *key) |
853 | { | 873 | { |
@@ -860,6 +880,8 @@ get_hostkey_index(Key *key) | |||
860 | } else { | 880 | } else { |
861 | if (key == sensitive_data.host_keys[i]) | 881 | if (key == sensitive_data.host_keys[i]) |
862 | return (i); | 882 | return (i); |
883 | if (key == sensitive_data.host_pubkeys[i]) | ||
884 | return (i); | ||
863 | } | 885 | } |
864 | } | 886 | } |
865 | return (-1); | 887 | return (-1); |
@@ -1344,6 +1366,8 @@ main(int ac, char **av) | |||
1344 | u_int64_t ibytes, obytes; | 1366 | u_int64_t ibytes, obytes; |
1345 | mode_t new_umask; | 1367 | mode_t new_umask; |
1346 | Key *key; | 1368 | Key *key; |
1369 | Key *pubkey; | ||
1370 | int keytype; | ||
1347 | Authctxt *authctxt; | 1371 | Authctxt *authctxt; |
1348 | struct connection_info *connection_info = get_connection_info(0, 0); | 1372 | struct connection_info *connection_info = get_connection_info(0, 0); |
1349 | 1373 | ||
@@ -1623,22 +1647,45 @@ main(int ac, char **av) | |||
1623 | } | 1647 | } |
1624 | endpwent(); | 1648 | endpwent(); |
1625 | 1649 | ||
1626 | /* load private host keys */ | 1650 | /* load host keys */ |
1627 | sensitive_data.host_keys = xcalloc(options.num_host_key_files, | 1651 | sensitive_data.host_keys = xcalloc(options.num_host_key_files, |
1628 | sizeof(Key *)); | 1652 | sizeof(Key *)); |
1629 | for (i = 0; i < options.num_host_key_files; i++) | 1653 | sensitive_data.host_pubkeys = xcalloc(options.num_host_key_files, |
1654 | sizeof(Key *)); | ||
1655 | for (i = 0; i < options.num_host_key_files; i++) { | ||
1630 | sensitive_data.host_keys[i] = NULL; | 1656 | sensitive_data.host_keys[i] = NULL; |
1657 | sensitive_data.host_pubkeys[i] = NULL; | ||
1658 | } | ||
1659 | |||
1660 | if (options.host_key_agent) { | ||
1661 | if (strcmp(options.host_key_agent, SSH_AUTHSOCKET_ENV_NAME)) | ||
1662 | setenv(SSH_AUTHSOCKET_ENV_NAME, | ||
1663 | options.host_key_agent, 1); | ||
1664 | have_agent = ssh_agent_present(); | ||
1665 | } | ||
1631 | 1666 | ||
1632 | for (i = 0; i < options.num_host_key_files; i++) { | 1667 | for (i = 0; i < options.num_host_key_files; i++) { |
1633 | key = key_load_private(options.host_key_files[i], "", NULL); | 1668 | key = key_load_private(options.host_key_files[i], "", NULL); |
1669 | pubkey = key_load_public(options.host_key_files[i], NULL); | ||
1634 | sensitive_data.host_keys[i] = key; | 1670 | sensitive_data.host_keys[i] = key; |
1635 | if (key == NULL) { | 1671 | sensitive_data.host_pubkeys[i] = pubkey; |
1672 | |||
1673 | if (key == NULL && pubkey != NULL && pubkey->type != KEY_RSA1 && | ||
1674 | have_agent) { | ||
1675 | debug("will rely on agent for hostkey %s", | ||
1676 | options.host_key_files[i]); | ||
1677 | keytype = pubkey->type; | ||
1678 | } else if (key != NULL) { | ||
1679 | keytype = key->type; | ||
1680 | } else { | ||
1636 | error("Could not load host key: %s", | 1681 | error("Could not load host key: %s", |
1637 | options.host_key_files[i]); | 1682 | options.host_key_files[i]); |
1638 | sensitive_data.host_keys[i] = NULL; | 1683 | sensitive_data.host_keys[i] = NULL; |
1684 | sensitive_data.host_pubkeys[i] = NULL; | ||
1639 | continue; | 1685 | continue; |
1640 | } | 1686 | } |
1641 | switch (key->type) { | 1687 | |
1688 | switch (keytype) { | ||
1642 | case KEY_RSA1: | 1689 | case KEY_RSA1: |
1643 | sensitive_data.ssh1_host_key = key; | 1690 | sensitive_data.ssh1_host_key = key; |
1644 | sensitive_data.have_ssh1_key = 1; | 1691 | sensitive_data.have_ssh1_key = 1; |
@@ -1649,8 +1696,8 @@ main(int ac, char **av) | |||
1649 | sensitive_data.have_ssh2_key = 1; | 1696 | sensitive_data.have_ssh2_key = 1; |
1650 | break; | 1697 | break; |
1651 | } | 1698 | } |
1652 | debug("private host key: #%d type %d %s", i, key->type, | 1699 | debug("private host key: #%d type %d %s", i, keytype, |
1653 | key_type(key)); | 1700 | key_type(key ? key : pubkey)); |
1654 | } | 1701 | } |
1655 | if ((options.protocol & SSH_PROTO_1) && !sensitive_data.have_ssh1_key) { | 1702 | if ((options.protocol & SSH_PROTO_1) && !sensitive_data.have_ssh1_key) { |
1656 | logit("Disabling protocol version 1. Could not load host key"); | 1703 | logit("Disabling protocol version 1. Could not load host key"); |
@@ -2020,9 +2067,11 @@ main(int ac, char **av) | |||
2020 | buffer_init(&loginmsg); | 2067 | buffer_init(&loginmsg); |
2021 | auth_debug_reset(); | 2068 | auth_debug_reset(); |
2022 | 2069 | ||
2023 | if (use_privsep) | 2070 | if (use_privsep) { |
2024 | if (privsep_preauth(authctxt) == 1) | 2071 | if (privsep_preauth(authctxt) == 1) |
2025 | goto authenticated; | 2072 | goto authenticated; |
2073 | } else if (compat20 && have_agent) | ||
2074 | auth_conn = ssh_get_authentication_connection(); | ||
2026 | 2075 | ||
2027 | /* perform the key exchange */ | 2076 | /* perform the key exchange */ |
2028 | /* authenticate user and start session */ | 2077 | /* authenticate user and start session */ |
@@ -2336,6 +2385,23 @@ do_ssh1_kex(void) | |||
2336 | packet_write_wait(); | 2385 | packet_write_wait(); |
2337 | } | 2386 | } |
2338 | 2387 | ||
2388 | void | ||
2389 | sshd_hostkey_sign(Key *privkey, Key *pubkey, u_char **signature, u_int *slen, | ||
2390 | u_char *data, u_int dlen) | ||
2391 | { | ||
2392 | if (privkey) { | ||
2393 | if (PRIVSEP(key_sign(privkey, signature, slen, data, dlen) < 0)) | ||
2394 | fatal("%s: key_sign failed", __func__); | ||
2395 | } else if (use_privsep) { | ||
2396 | if (mm_key_sign(pubkey, signature, slen, data, dlen) < 0) | ||
2397 | fatal("%s: pubkey_sign failed", __func__); | ||
2398 | } else { | ||
2399 | if (ssh_agent_sign(auth_conn, pubkey, signature, slen, data, | ||
2400 | dlen)) | ||
2401 | fatal("%s: ssh_agent_sign failed", __func__); | ||
2402 | } | ||
2403 | } | ||
2404 | |||
2339 | /* | 2405 | /* |
2340 | * SSH2 key exchange: diffie-hellman-group1-sha1 | 2406 | * SSH2 key exchange: diffie-hellman-group1-sha1 |
2341 | */ | 2407 | */ |
@@ -2386,6 +2452,7 @@ do_ssh2_kex(void) | |||
2386 | kex->load_host_public_key=&get_hostkey_public_by_type; | 2452 | kex->load_host_public_key=&get_hostkey_public_by_type; |
2387 | kex->load_host_private_key=&get_hostkey_private_by_type; | 2453 | kex->load_host_private_key=&get_hostkey_private_by_type; |
2388 | kex->host_key_index=&get_hostkey_index; | 2454 | kex->host_key_index=&get_hostkey_index; |
2455 | kex->sign = sshd_hostkey_sign; | ||
2389 | 2456 | ||
2390 | xxx_kex = kex; | 2457 | xxx_kex = kex; |
2391 | 2458 | ||
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 @@ | |||
33 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 33 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
34 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 34 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
35 | .\" | 35 | .\" |
36 | .\" $OpenBSD: sshd_config.5,v 1.161 2013/06/27 14:05:37 jmc Exp $ | 36 | .\" $OpenBSD: sshd_config.5,v 1.162 2013/07/19 07:37:48 markus Exp $ |
37 | .Dd $Mdocdate: June 27 2013 $ | 37 | .Dd $Mdocdate: July 19 2013 $ |
38 | .Dt SSHD_CONFIG 5 | 38 | .Dt SSHD_CONFIG 5 |
39 | .Os | 39 | .Os |
40 | .Sh NAME | 40 | .Sh NAME |
@@ -546,6 +546,18 @@ keys are used for version 1 and | |||
546 | or | 546 | or |
547 | .Dq rsa | 547 | .Dq rsa |
548 | are used for version 2 of the SSH protocol. | 548 | are used for version 2 of the SSH protocol. |
549 | It is also possible to specify public host key files instead. | ||
550 | In this case operations on the private key will be delegated | ||
551 | to an | ||
552 | .Xr ssh-agent 1 . | ||
553 | .It Cm HostKeyAgent | ||
554 | Identifies the UNIX-domain socket used to communicate | ||
555 | with an agent that has access to the private host keys. | ||
556 | If | ||
557 | .Dq SSH_AUTH_SOCK | ||
558 | is specified, the location of the socket will be read from the | ||
559 | .Ev SSH_AUTH_SOCK | ||
560 | environment variable. | ||
549 | .It Cm IgnoreRhosts | 561 | .It Cm IgnoreRhosts |
550 | Specifies that | 562 | Specifies that |
551 | .Pa .rhosts | 563 | .Pa .rhosts |