summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2013-07-20 13:21:52 +1000
committerDamien Miller <djm@mindrot.org>2013-07-20 13:21:52 +1000
commit85b45e09188e7a7fc8f0a900a4c6a0f04a5720a7 (patch)
tree575942d7e7a835c3b89b59eb0e9e0ecf34f1811b
parentd93340cbb6bc0fc0dbd4427e0cec6d994a494dd9 (diff)
- 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@
-rw-r--r--ChangeLog9
-rw-r--r--auth.h4
-rw-r--r--kex.h3
-rw-r--r--kexdhs.c10
-rw-r--r--kexecdhs.c10
-rw-r--r--kexgexs.c11
-rw-r--r--monitor.c18
-rw-r--r--servconf.c18
-rw-r--r--servconf.h3
-rw-r--r--session.c10
-rw-r--r--sshd.c83
-rw-r--r--sshd_config.516
12 files changed, 153 insertions, 42 deletions
diff --git a/ChangeLog b/ChangeLog
index 9530ef55f..fd66fed6d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
120130720
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
120130718 1020130718
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
diff --git a/auth.h b/auth.h
index caf44adc0..80f089869 100644
--- a/auth.h
+++ b/auth.h
@@ -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 */
200Key *get_hostkey_by_index(int); 200Key *get_hostkey_by_index(int);
201Key *get_hostkey_public_by_index(int);
201Key *get_hostkey_public_by_type(int); 202Key *get_hostkey_public_by_type(int);
202Key *get_hostkey_private_by_type(int); 203Key *get_hostkey_private_by_type(int);
203int get_hostkey_index(Key *); 204int get_hostkey_index(Key *);
204int ssh1_session_key(BIGNUM *); 205int ssh1_session_key(BIGNUM *);
206void 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 */
207void auth_debug_add(const char *fmt,...) __attribute__((format(printf, 1, 2))); 209void 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 @@
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
diff --git a/kexdhs.c b/kexdhs.c
index 15128632c..269d80900 100644
--- a/kexdhs.c
+++ b/kexdhs.c
@@ -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
diff --git a/kexgexs.c b/kexgexs.c
index a543dda82..4e473fc73 100644
--- a/kexgexs.c
+++ b/kexgexs.c
@@ -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
diff --git a/monitor.c b/monitor.c
index 0516f60a2..44dff98c9 100644
--- a/monitor.c
+++ b/monitor.c
@@ -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
102static Gssctxt *gsscontext = NULL; 103static Gssctxt *gsscontext = NULL;
@@ -686,6 +687,8 @@ mm_answer_moduli(int sock, Buffer *m)
686 return (0); 687 return (0);
687} 688}
688 689
690extern AuthenticationConnection *auth_conn;
691
689int 692int
690mm_answer_sign(int sock, Buffer *m) 693mm_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
diff --git a/session.c b/session.c
index 1424825ca..d4b57bdfb 100644
--- a/session.c
+++ b/session.c
@@ -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)
1589static void 1590static void
1590child_close_fds(void) 1591child_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 {
diff --git a/sshd.c b/sshd.c
index 1306a62a7..174cc7a42 100644
--- a/sshd.c
+++ b/sshd.c
@@ -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 */
195Kex *xxx_kex; 196Kex *xxx_kex;
196 197
198/* Daemon's agent connection */
199AuthenticationConnection *auth_conn = NULL;
200int 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
863Key *
864get_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
851int 871int
852get_hostkey_index(Key *key) 872get_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
2388void
2389sshd_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
546or 546or
547.Dq rsa 547.Dq rsa
548are used for version 2 of the SSH protocol. 548are used for version 2 of the SSH protocol.
549It is also possible to specify public host key files instead.
550In this case operations on the private key will be delegated
551to an
552.Xr ssh-agent 1 .
553.It Cm HostKeyAgent
554Identifies the UNIX-domain socket used to communicate
555with an agent that has access to the private host keys.
556If
557.Dq SSH_AUTH_SOCK
558is specified, the location of the socket will be read from the
559.Ev SSH_AUTH_SOCK
560environment variable.
549.It Cm IgnoreRhosts 561.It Cm IgnoreRhosts
550Specifies that 562Specifies that
551.Pa .rhosts 563.Pa .rhosts