summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--kex.h4
-rw-r--r--kexdh.c9
-rw-r--r--kexgex.c9
-rw-r--r--pathnames.h4
-rw-r--r--readconf.c6
-rw-r--r--servconf.h2
-rw-r--r--ssh.151
-rw-r--r--sshconnect.c147
-rw-r--r--sshconnect.h6
-rw-r--r--sshconnect1.c6
-rw-r--r--sshconnect2.c10
-rw-r--r--sshd.820
13 files changed, 158 insertions, 123 deletions
diff --git a/ChangeLog b/ChangeLog
index 84917fb26..f3a7da695 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -46,6 +46,11 @@
46 - deraadt@cvs.openbsd.org 2001/06/23 02:33:05 46 - deraadt@cvs.openbsd.org 2001/06/23 02:33:05
47 [sftp.1 sftp-server.8 ssh-keygen.1] 47 [sftp.1 sftp-server.8 ssh-keygen.1]
48 join .%A entries; most by bk@rt.fm 48 join .%A entries; most by bk@rt.fm
49 - markus@cvs.openbsd.org 2001/06/23 02:34:33
50 [kexdh.c kexgex.c kex.h pathnames.h readconf.c servconf.h ssh.1
51 sshconnect1.c sshconnect2.c sshconnect.c sshconnect.h sshd.8]
52 get rid of known_hosts2, use it for hostkey lookup, but do not
53 modify.
49 54
5020010622 5520010622
51 - (stevesk) handle systems without pw_expire and pw_change. 56 - (stevesk) handle systems without pw_expire and pw_change.
@@ -5730,4 +5735,4 @@
5730 - Wrote replacements for strlcpy and mkdtemp 5735 - Wrote replacements for strlcpy and mkdtemp
5731 - Released 1.0pre1 5736 - Released 1.0pre1
5732 5737
5733$Id: ChangeLog,v 1.1308 2001/06/25 04:32:38 mouring Exp $ 5738$Id: ChangeLog,v 1.1309 2001/06/25 04:37:41 mouring Exp $
diff --git a/kex.h b/kex.h
index 8758804c5..eca36b36a 100644
--- a/kex.h
+++ b/kex.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: kex.h,v 1.22 2001/04/04 20:25:37 markus Exp $ */ 1/* $OpenBSD: kex.h,v 1.23 2001/06/23 02:34:28 markus Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000 Markus Friedl. All rights reserved. 4 * Copyright (c) 2000 Markus Friedl. All rights reserved.
@@ -107,7 +107,7 @@ struct Kex {
107 int flags; 107 int flags;
108 char *client_version_string; 108 char *client_version_string;
109 char *server_version_string; 109 char *server_version_string;
110 int (*check_host_key)(Key *hostkey); 110 int (*verify_host_key)(Key *hostkey);
111 Key *(*load_host_key)(int type); 111 Key *(*load_host_key)(int type);
112}; 112};
113 113
diff --git a/kexdh.c b/kexdh.c
index 40eccf6c2..d7f90b756 100644
--- a/kexdh.c
+++ b/kexdh.c
@@ -23,7 +23,7 @@
23 */ 23 */
24 24
25#include "includes.h" 25#include "includes.h"
26RCSID("$OpenBSD: kexdh.c,v 1.4 2001/06/07 20:23:04 markus Exp $"); 26RCSID("$OpenBSD: kexdh.c,v 1.5 2001/06/23 02:34:29 markus Exp $");
27 27
28#include <openssl/crypto.h> 28#include <openssl/crypto.h>
29#include <openssl/bn.h> 29#include <openssl/bn.h>
@@ -123,9 +123,10 @@ kexdh_client(Kex *kex)
123 if (server_host_key == NULL) 123 if (server_host_key == NULL)
124 fatal("cannot decode server_host_key_blob"); 124 fatal("cannot decode server_host_key_blob");
125 125
126 if (kex->check_host_key == NULL) 126 if (kex->verify_host_key == NULL)
127 fatal("cannot check server_host_key"); 127 fatal("cannot verify server_host_key");
128 kex->check_host_key(server_host_key); 128 if (kex->verify_host_key(server_host_key) == -1)
129 fatal("server_host_key verification failed");
129 130
130 /* DH paramter f, server public DH key */ 131 /* DH paramter f, server public DH key */
131 dh_server_pub = BN_new(); 132 dh_server_pub = BN_new();
diff --git a/kexgex.c b/kexgex.c
index f21f310ee..01b86d903 100644
--- a/kexgex.c
+++ b/kexgex.c
@@ -24,7 +24,7 @@
24 */ 24 */
25 25
26#include "includes.h" 26#include "includes.h"
27RCSID("$OpenBSD: kexgex.c,v 1.6 2001/06/07 20:23:04 markus Exp $"); 27RCSID("$OpenBSD: kexgex.c,v 1.7 2001/06/23 02:34:29 markus Exp $");
28 28
29#include <openssl/bn.h> 29#include <openssl/bn.h>
30 30
@@ -177,9 +177,10 @@ kexgex_client(Kex *kex)
177 if (server_host_key == NULL) 177 if (server_host_key == NULL)
178 fatal("cannot decode server_host_key_blob"); 178 fatal("cannot decode server_host_key_blob");
179 179
180 if (kex->check_host_key == NULL) 180 if (kex->verify_host_key == NULL)
181 fatal("cannot check server_host_key"); 181 fatal("cannot verify server_host_key");
182 kex->check_host_key(server_host_key); 182 if (kex->verify_host_key(server_host_key) == -1)
183 fatal("server_host_key verification failed");
183 184
184 /* DH paramter f, server public DH key */ 185 /* DH paramter f, server public DH key */
185 dh_server_pub = BN_new(); 186 dh_server_pub = BN_new();
diff --git a/pathnames.h b/pathnames.h
index 014f62b3e..54c2c1319 100644
--- a/pathnames.h
+++ b/pathnames.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: pathnames.h,v 1.8 2001/06/22 21:55:49 markus Exp $ */ 1/* $OpenBSD: pathnames.h,v 1.9 2001/06/23 02:34:30 markus Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -25,6 +25,7 @@
25 * world-readable. 25 * world-readable.
26 */ 26 */
27#define _PATH_SSH_SYSTEM_HOSTFILE ETCDIR "/ssh_known_hosts" 27#define _PATH_SSH_SYSTEM_HOSTFILE ETCDIR "/ssh_known_hosts"
28/* backward compat for protocol 2 */
28#define _PATH_SSH_SYSTEM_HOSTFILE2 ETCDIR "/ssh_known_hosts2" 29#define _PATH_SSH_SYSTEM_HOSTFILE2 ETCDIR "/ssh_known_hosts2"
29 30
30/* 31/*
@@ -62,6 +63,7 @@
62 * contain anything particularly secret. 63 * contain anything particularly secret.
63 */ 64 */
64#define _PATH_SSH_USER_HOSTFILE "~/.ssh/known_hosts" 65#define _PATH_SSH_USER_HOSTFILE "~/.ssh/known_hosts"
66/* backward compat for protocol 2 */
65#define _PATH_SSH_USER_HOSTFILE2 "~/.ssh/known_hosts2" 67#define _PATH_SSH_USER_HOSTFILE2 "~/.ssh/known_hosts2"
66 68
67/* 69/*
diff --git a/readconf.c b/readconf.c
index 7ecbe96b7..3c4d12662 100644
--- a/readconf.c
+++ b/readconf.c
@@ -12,7 +12,7 @@
12 */ 12 */
13 13
14#include "includes.h" 14#include "includes.h"
15RCSID("$OpenBSD: readconf.c,v 1.80 2001/06/08 15:25:40 markus Exp $"); 15RCSID("$OpenBSD: readconf.c,v 1.81 2001/06/23 02:34:30 markus Exp $");
16 16
17#include "ssh.h" 17#include "ssh.h"
18#include "xmalloc.h" 18#include "xmalloc.h"
@@ -162,9 +162,9 @@ static struct {
162 { "host", oHost }, 162 { "host", oHost },
163 { "escapechar", oEscapeChar }, 163 { "escapechar", oEscapeChar },
164 { "globalknownhostsfile", oGlobalKnownHostsFile }, 164 { "globalknownhostsfile", oGlobalKnownHostsFile },
165 { "userknownhostsfile", oUserKnownHostsFile }, 165 { "userknownhostsfile", oUserKnownHostsFile }, /* obsolete */
166 { "globalknownhostsfile2", oGlobalKnownHostsFile2 }, 166 { "globalknownhostsfile2", oGlobalKnownHostsFile2 },
167 { "userknownhostsfile2", oUserKnownHostsFile2 }, 167 { "userknownhostsfile2", oUserKnownHostsFile2 }, /* obsolete */
168 { "connectionattempts", oConnectionAttempts }, 168 { "connectionattempts", oConnectionAttempts },
169 { "batchmode", oBatchMode }, 169 { "batchmode", oBatchMode },
170 { "checkhostip", oCheckHostIP }, 170 { "checkhostip", oCheckHostIP },
diff --git a/servconf.h b/servconf.h
index 2bf19fb3b..6256c3a37 100644
--- a/servconf.h
+++ b/servconf.h
@@ -11,7 +11,7 @@
11 * called by a name other than "ssh" or "Secure Shell". 11 * called by a name other than "ssh" or "Secure Shell".
12 */ 12 */
13 13
14/* RCSID("$OpenBSD: servconf.h,v 1.43 2001/05/20 17:20:35 markus Exp $"); */ 14/* RCSID("$OpenBSD: servconf.h,v 1.44 2001/06/23 02:34:31 markus Exp $"); */
15 15
16#ifndef SERVCONF_H 16#ifndef SERVCONF_H
17#define SERVCONF_H 17#define SERVCONF_H
diff --git a/ssh.1 b/ssh.1
index 99371f5ce..94a22f1e4 100644
--- a/ssh.1
+++ b/ssh.1
@@ -34,7 +34,7 @@
34.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 34.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36.\" 36.\"
37.\" $OpenBSD: ssh.1,v 1.115 2001/06/22 21:55:49 markus Exp $ 37.\" $OpenBSD: ssh.1,v 1.116 2001/06/23 02:34:31 markus Exp $
38.Dd September 25, 1999 38.Dd September 25, 1999
39.Dt SSH 1 39.Dt SSH 1
40.Os 40.Os
@@ -361,17 +361,12 @@ electronic purse; another is going through firewalls.
361.Nm 361.Nm
362automatically maintains and checks a database containing 362automatically maintains and checks a database containing
363identifications for all hosts it has ever been used with. 363identifications for all hosts it has ever been used with.
364RSA host keys are stored in 364Host keys are stored in
365.Pa $HOME/.ssh/known_hosts 365.Pa $HOME/.ssh/known_hosts
366and
367host keys used in the protocol version 2 are stored in
368.Pa $HOME/.ssh/known_hosts2
369in the user's home directory. 366in the user's home directory.
370Additionally, the files 367Additionally, the file
371.Pa /etc/ssh_known_hosts 368.Pa /etc/ssh_known_hosts
372and 369is automatically checked for known hosts.
373.Pa /etc/ssh_known_hosts2
374are automatically checked for known hosts.
375Any new hosts are automatically added to the user's file. 370Any new hosts are automatically added to the user's file.
376If a host's identification 371If a host's identification
377ever changes, 372ever changes,
@@ -797,13 +792,9 @@ or
797The default is 792The default is
798.Dq no . 793.Dq no .
799.It Cm GlobalKnownHostsFile 794.It Cm GlobalKnownHostsFile
800Specifies a file to use for the protocol version 1 global 795Specifies a file to use for the global
801host key database instead of 796host key database instead of
802.Pa /etc/ssh_known_hosts . 797.Pa /etc/ssh_known_hosts .
803.It Cm GlobalKnownHostsFile2
804Specifies a file to use for the protocol version 2 global
805host key database instead of
806.Pa /etc/ssh_known_hosts2 .
807.It Cm HostbasedAuthentication 798.It Cm HostbasedAuthentication
808Specifies whether to try rhosts based authentication with public key 799Specifies whether to try rhosts based authentication with public key
809authentication. 800authentication.
@@ -1036,14 +1027,10 @@ If this flag is set to
1036.Nm 1027.Nm
1037will never automatically add host keys to the 1028will never automatically add host keys to the
1038.Pa $HOME/.ssh/known_hosts 1029.Pa $HOME/.ssh/known_hosts
1039and 1030file, and refuses to connect to hosts whose host key has changed.
1040.Pa $HOME/.ssh/known_hosts2
1041files, and refuses to connect to hosts whose host key has changed.
1042This provides maximum protection against trojan horse attacks. 1031This provides maximum protection against trojan horse attacks.
1043However, it can be somewhat annoying if you don't have good 1032However, it can be somewhat annoying if you don't have good
1044.Pa /etc/ssh_known_hosts 1033.Pa /etc/ssh_known_hosts
1045and
1046.Pa /etc/ssh_known_hosts2
1047files installed and frequently 1034files installed and frequently
1048connect to new hosts. 1035connect to new hosts.
1049This option forces the user to manually 1036This option forces the user to manually
@@ -1090,13 +1077,9 @@ This can be useful if you have a different user name on different machines.
1090This saves the trouble of 1077This saves the trouble of
1091having to remember to give the user name on the command line. 1078having to remember to give the user name on the command line.
1092.It Cm UserKnownHostsFile 1079.It Cm UserKnownHostsFile
1093Specifies a file to use for the protocol version 1 user 1080Specifies a file to use for the user
1094host key database instead of 1081host key database instead of
1095.Pa $HOME/.ssh/known_hosts . 1082.Pa $HOME/.ssh/known_hosts .
1096.It Cm UserKnownHostsFile2
1097Specifies a file to use for the protocol version 2 user
1098host key database instead of
1099.Pa $HOME/.ssh/known_hosts2 .
1100.It Cm UseRsh 1083.It Cm UseRsh
1101Specifies that rlogin/rsh should be used for this host. 1084Specifies that rlogin/rsh should be used for this host.
1102It is possible that the host does not at all support the 1085It is possible that the host does not at all support the
@@ -1189,13 +1172,10 @@ and adds lines of the format
1189to the environment. 1172to the environment.
1190.Sh FILES 1173.Sh FILES
1191.Bl -tag -width Ds 1174.Bl -tag -width Ds
1192.It Pa $HOME/.ssh/known_hosts, $HOME/.ssh/known_hosts2 1175.It Pa $HOME/.ssh/known_hosts
1193Records host keys for all hosts the user has logged into (that are not 1176Records host keys for all hosts the user has logged into (that are not
1194in 1177in
1195.Pa /etc/ssh_known_hosts 1178.Pa /etc/ssh_known_hosts .
1196for protocol version 1 or
1197.Pa /etc/ssh_known_hosts2
1198for protocol version 2).
1199See 1179See
1200.Xr sshd 8 . 1180.Xr sshd 8 .
1201.It Pa $HOME/.ssh/identity, $HOME/.ssh/id_dsa, $HOME/.ssh/id_rsa 1181.It Pa $HOME/.ssh/identity, $HOME/.ssh/id_dsa, $HOME/.ssh/id_rsa
@@ -1246,22 +1226,19 @@ Lists the public keys (RSA/DSA) that can be used for logging in as this user.
1246The format of this file is described in the 1226The format of this file is described in the
1247.Xr sshd 8 1227.Xr sshd 8
1248manual page. 1228manual page.
1229In the simplest form the format is the same as the .pub
1230identity files.
1249This file is not highly sensitive, but the recommended 1231This file is not highly sensitive, but the recommended
1250permissions are read/write for the user, and not accessible by others. 1232permissions are read/write for the user, and not accessible by others.
1251.It Pa /etc/ssh_known_hosts, /etc/ssh_known_hosts2 1233.It Pa /etc/ssh_known_hosts
1252Systemwide list of known host keys. 1234Systemwide list of known host keys.
1253.Pa /etc/ssh_known_hosts 1235This file should be prepared by the
1254contains RSA and
1255.Pa /etc/ssh_known_hosts2
1256contains RSA or DSA keys for protocol version 2.
1257These files should be prepared by the
1258system administrator to contain the public host keys of all machines in the 1236system administrator to contain the public host keys of all machines in the
1259organization. 1237organization.
1260This file should be world-readable. 1238This file should be world-readable.
1261This file contains 1239This file contains
1262public keys, one per line, in the following format (fields separated 1240public keys, one per line, in the following format (fields separated
1263by spaces): system name, number of bits in modulus, public exponent, 1241by spaces): system name, public key and optional comment field.
1264modulus, and optional comment field.
1265When different names are used 1242When different names are used
1266for the same machine, all such names should be listed, separated by 1243for the same machine, all such names should be listed, separated by
1267commas. 1244commas.
diff --git a/sshconnect.c b/sshconnect.c
index bafdec95a..1766de0c3 100644
--- a/sshconnect.c
+++ b/sshconnect.c
@@ -13,7 +13,7 @@
13 */ 13 */
14 14
15#include "includes.h" 15#include "includes.h"
16RCSID("$OpenBSD: sshconnect.c,v 1.107 2001/06/07 20:23:05 markus Exp $"); 16RCSID("$OpenBSD: sshconnect.c,v 1.108 2001/06/23 02:34:31 markus Exp $");
17 17
18#include <openssl/bn.h> 18#include <openssl/bn.h>
19 19
@@ -467,7 +467,10 @@ read_yes_or_no(const char *prompt, int defval)
467 while (1) { 467 while (1) {
468 fprintf(stderr, "%s", prompt); 468 fprintf(stderr, "%s", prompt);
469 if (fgets(buf, sizeof(buf), f) == NULL) { 469 if (fgets(buf, sizeof(buf), f) == NULL) {
470 /* Print a newline (the prompt probably didn\'t have one). */ 470 /*
471 * Print a newline (the prompt probably didn\'t have
472 * one).
473 */
471 fprintf(stderr, "\n"); 474 fprintf(stderr, "\n");
472 strlcpy(buf, "no", sizeof buf); 475 strlcpy(buf, "no", sizeof buf);
473 } 476 }
@@ -493,12 +496,13 @@ read_yes_or_no(const char *prompt, int defval)
493} 496}
494 497
495/* 498/*
496 * check whether the supplied host key is valid, return only if ok. 499 * check whether the supplied host key is valid, return -1 if the key
500 * is not valid. the user_hostfile will not be updated if 'readonly' is true.
497 */ 501 */
498 502
499void 503int
500check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key, 504check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
501 const char *user_hostfile, const char *system_hostfile) 505 int readonly, const char *user_hostfile, const char *system_hostfile)
502{ 506{
503 Key *file_key; 507 Key *file_key;
504 char *type = key_type(host_key); 508 char *type = key_type(host_key);
@@ -523,11 +527,13 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
523 /** hostaddr == 0! */ 527 /** hostaddr == 0! */
524 switch (hostaddr->sa_family) { 528 switch (hostaddr->sa_family) {
525 case AF_INET: 529 case AF_INET:
526 local = (ntohl(((struct sockaddr_in *)hostaddr)->sin_addr.s_addr) >> 24) == IN_LOOPBACKNET; 530 local = (ntohl(((struct sockaddr_in *)hostaddr)->
531 sin_addr.s_addr) >> 24) == IN_LOOPBACKNET;
527 salen = sizeof(struct sockaddr_in); 532 salen = sizeof(struct sockaddr_in);
528 break; 533 break;
529 case AF_INET6: 534 case AF_INET6:
530 local = IN6_IS_ADDR_LOOPBACK(&(((struct sockaddr_in6 *)hostaddr)->sin6_addr)); 535 local = IN6_IS_ADDR_LOOPBACK(
536 &(((struct sockaddr_in6 *)hostaddr)->sin6_addr));
531 salen = sizeof(struct sockaddr_in6); 537 salen = sizeof(struct sockaddr_in6);
532 break; 538 break;
533 default: 539 default:
@@ -538,7 +544,7 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
538 if (local && options.host_key_alias == NULL) { 544 if (local && options.host_key_alias == NULL) {
539 debug("Forcing accepting of host key for " 545 debug("Forcing accepting of host key for "
540 "loopback/localhost."); 546 "loopback/localhost.");
541 return; 547 return 0;
542 } 548 }
543 549
544 /* 550 /*
@@ -582,10 +588,12 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
582 * hosts or in the systemwide list. 588 * hosts or in the systemwide list.
583 */ 589 */
584 host_file = user_hostfile; 590 host_file = user_hostfile;
585 host_status = check_host_in_hostfile(host_file, host, host_key, file_key, &host_line); 591 host_status = check_host_in_hostfile(host_file, host, host_key,
592 file_key, &host_line);
586 if (host_status == HOST_NEW) { 593 if (host_status == HOST_NEW) {
587 host_file = system_hostfile; 594 host_file = system_hostfile;
588 host_status = check_host_in_hostfile(host_file, host, host_key, file_key, &host_line); 595 host_status = check_host_in_hostfile(host_file, host, host_key,
596 file_key, &host_line);
589 } 597 }
590 /* 598 /*
591 * Also perform check for the ip address, skip the check if we are 599 * Also perform check for the ip address, skip the check if we are
@@ -595,10 +603,12 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
595 Key *ip_key = key_new(host_key->type); 603 Key *ip_key = key_new(host_key->type);
596 604
597 ip_file = user_hostfile; 605 ip_file = user_hostfile;
598 ip_status = check_host_in_hostfile(ip_file, ip, host_key, ip_key, &ip_line); 606 ip_status = check_host_in_hostfile(ip_file, ip, host_key,
607 ip_key, &ip_line);
599 if (ip_status == HOST_NEW) { 608 if (ip_status == HOST_NEW) {
600 ip_file = system_hostfile; 609 ip_file = system_hostfile;
601 ip_status = check_host_in_hostfile(ip_file, ip, host_key, ip_key, &ip_line); 610 ip_status = check_host_in_hostfile(ip_file, ip,
611 host_key, ip_key, &ip_line);
602 } 612 }
603 if (host_status == HOST_CHANGED && 613 if (host_status == HOST_CHANGED &&
604 (ip_status != HOST_CHANGED || !key_equal(ip_key, file_key))) 614 (ip_status != HOST_CHANGED || !key_equal(ip_key, file_key)))
@@ -617,32 +627,49 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
617 host, type); 627 host, type);
618 debug("Found key in %s:%d", host_file, host_line); 628 debug("Found key in %s:%d", host_file, host_line);
619 if (options.check_host_ip && ip_status == HOST_NEW) { 629 if (options.check_host_ip && ip_status == HOST_NEW) {
620 if (!add_host_to_hostfile(user_hostfile, ip, host_key)) 630 if (readonly)
621 log("Failed to add the %s host key for IP address '%.128s' to the list of known hosts (%.30s).", 631 log("%s host key for IP address "
622 type, ip, user_hostfile); 632 "'%.128s' not in list of known hosts.",
623 else
624 log("Warning: Permanently added the %s host key for IP address '%.128s' to the list of known hosts.",
625 type, ip); 633 type, ip);
634 else if (!add_host_to_hostfile(user_hostfile, ip,
635 host_key))
636 log("Failed to add the %s host key for IP "
637 "address '%.128s' to the list of known "
638 "hosts (%.30s).", type, ip, user_hostfile);
639 else
640 log("Warning: Permanently added the %s host "
641 "key for IP address '%.128s' to the list "
642 "of known hosts.", type, ip);
626 } 643 }
627 break; 644 break;
628 case HOST_NEW: 645 case HOST_NEW:
646 if (readonly)
647 goto fail;
629 /* The host is new. */ 648 /* The host is new. */
630 if (options.strict_host_key_checking == 1) { 649 if (options.strict_host_key_checking == 1) {
631 /* User has requested strict host key checking. We will not add the host key 650 /*
632 automatically. The only alternative left is to abort. */ 651 * User has requested strict host key checking. We
633 fatal("No %s host key is known for %.200s and you have requested strict checking.", type, host); 652 * will not add the host key automatically. The only
653 * alternative left is to abort.
654 */
655 error("No %s host key is known for %.200s and you "
656 "have requested strict checking.", type, host);
657 goto fail;
634 } else if (options.strict_host_key_checking == 2) { 658 } else if (options.strict_host_key_checking == 2) {
635 /* The default */ 659 /* The default */
636 char prompt[1024]; 660 char prompt[1024];
637 fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); 661 fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
638 snprintf(prompt, sizeof(prompt), 662 snprintf(prompt, sizeof(prompt),
639 "The authenticity of host '%.200s (%s)' can't be established.\n" 663 "The authenticity of host '%.200s (%s)' can't be "
664 "established.\n"
640 "%s key fingerprint is %s.\n" 665 "%s key fingerprint is %s.\n"
641 "Are you sure you want to continue connecting (yes/no)? ", 666 "Are you sure you want to continue connecting "
642 host, ip, type, fp); 667 "(yes/no)? ", host, ip, type, fp);
643 xfree(fp); 668 xfree(fp);
644 if (!read_yes_or_no(prompt, -1)) 669 if (!read_yes_or_no(prompt, -1)) {
645 fatal("Aborted by user!"); 670 log("Aborted by user!");
671 goto fail;
672 }
646 } 673 }
647 if (options.check_host_ip && ip_status == HOST_NEW) { 674 if (options.check_host_ip && ip_status == HOST_NEW) {
648 snprintf(hostline, sizeof(hostline), "%s,%s", host, ip); 675 snprintf(hostline, sizeof(hostline), "%s,%s", host, ip);
@@ -650,13 +677,16 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
650 } else 677 } else
651 hostp = host; 678 hostp = host;
652 679
653 /* If not in strict mode, add the key automatically to the local known_hosts file. */ 680 /*
681 * If not in strict mode, add the key automatically to the
682 * local known_hosts file.
683 */
654 if (!add_host_to_hostfile(user_hostfile, hostp, host_key)) 684 if (!add_host_to_hostfile(user_hostfile, hostp, host_key))
655 log("Failed to add the host to the list of known hosts (%.500s).", 685 log("Failed to add the host to the list of known "
656 user_hostfile); 686 "hosts (%.500s).", user_hostfile);
657 else 687 else
658 log("Warning: Permanently added '%.200s' (%s) to the list of known hosts.", 688 log("Warning: Permanently added '%.200s' (%s) to the "
659 hostp, type); 689 "list of known hosts.", hostp, type);
660 break; 690 break;
661 case HOST_CHANGED: 691 case HOST_CHANGED:
662 if (options.check_host_ip && host_ip_differ) { 692 if (options.check_host_ip && host_ip_differ) {
@@ -698,8 +728,11 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
698 * If strict host key checking is in use, the user will have 728 * If strict host key checking is in use, the user will have
699 * to edit the key manually and we can only abort. 729 * to edit the key manually and we can only abort.
700 */ 730 */
701 if (options.strict_host_key_checking) 731 if (options.strict_host_key_checking) {
702 fatal("%s host key for %.200s has changed and you have requested strict checking.", type, host); 732 error("%s host key for %.200s has changed and you have "
733 "requested strict checking.", type, host);
734 goto fail;
735 }
703 736
704 /* 737 /*
705 * If strict host key checking has not been requested, allow 738 * If strict host key checking has not been requested, allow
@@ -707,20 +740,26 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
707 * agent forwarding. 740 * agent forwarding.
708 */ 741 */
709 if (options.password_authentication) { 742 if (options.password_authentication) {
710 error("Password authentication is disabled to avoid trojan horses."); 743 error("Password authentication is disabled to avoid "
744 "man-in-the-middle attacks.");
711 options.password_authentication = 0; 745 options.password_authentication = 0;
712 } 746 }
713 if (options.forward_agent) { 747 if (options.forward_agent) {
714 error("Agent forwarding is disabled to avoid trojan horses."); 748 error("Agent forwarding is disabled to avoid "
749 "man-in-the-middle attacks.");
715 options.forward_agent = 0; 750 options.forward_agent = 0;
716 } 751 }
717 if (options.forward_x11) { 752 if (options.forward_x11) {
718 error("X11 forwarding is disabled to avoid trojan horses."); 753 error("X11 forwarding is disabled to avoid "
754 "man-in-the-middle attacks.");
719 options.forward_x11 = 0; 755 options.forward_x11 = 0;
720 } 756 }
721 if (options.num_local_forwards > 0 || options.num_remote_forwards > 0) { 757 if (options.num_local_forwards > 0 ||
722 error("Port forwarding is disabled to avoid trojan horses."); 758 options.num_remote_forwards > 0) {
723 options.num_local_forwards = options.num_remote_forwards = 0; 759 error("Port forwarding is disabled to avoid "
760 "man-in-the-middle attacks.");
761 options.num_local_forwards =
762 options.num_remote_forwards = 0;
724 } 763 }
725 /* 764 /*
726 * XXX Should permit the user to change to use the new id. 765 * XXX Should permit the user to change to use the new id.
@@ -741,15 +780,39 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
741 log("Matching host key in %s:%d", host_file, host_line); 780 log("Matching host key in %s:%d", host_file, host_line);
742 log("Offending key for IP in %s:%d", ip_file, ip_line); 781 log("Offending key for IP in %s:%d", ip_file, ip_line);
743 if (options.strict_host_key_checking == 1) { 782 if (options.strict_host_key_checking == 1) {
744 fatal("Exiting, you have requested strict checking."); 783 error("Exiting, you have requested strict checking.");
784 goto fail;
745 } else if (options.strict_host_key_checking == 2) { 785 } else if (options.strict_host_key_checking == 2) {
746 if (!read_yes_or_no("Are you sure you want " \ 786 if (!read_yes_or_no("Are you sure you want "
747 "to continue connecting (yes/no)? ", -1)) 787 "to continue connecting (yes/no)? ", -1)) {
748 fatal("Aborted by user!"); 788 log("Aborted by user!");
789 goto fail;
790 }
749 } 791 }
750 } 792 }
751 793
752 xfree(ip); 794 xfree(ip);
795 return 0;
796
797fail:
798 xfree(ip);
799 return -1;
800}
801
802int
803verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
804{
805 struct stat st;
806
807 /* return ok if the key can be found in an old keyfile */
808 if (stat(options.system_hostfile2, &st) == 0 ||
809 stat(options.user_hostfile2, &st) == 0) {
810 if (check_host_key(host, hostaddr, host_key, /*readonly*/ 1,
811 options.user_hostfile2, options.system_hostfile2) == 0)
812 return 0;
813 }
814 return check_host_key(host, hostaddr, host_key, /*readonly*/ 0,
815 options.user_hostfile, options.system_hostfile);
753} 816}
754 817
755/* 818/*
diff --git a/sshconnect.h b/sshconnect.h
index 661040185..1aa892f7e 100644
--- a/sshconnect.h
+++ b/sshconnect.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshconnect.h,v 1.9 2001/04/12 19:15:25 markus Exp $ */ 1/* $OpenBSD: sshconnect.h,v 1.10 2001/06/23 02:34:32 markus Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000 Markus Friedl. All rights reserved. 4 * Copyright (c) 2000 Markus Friedl. All rights reserved.
@@ -36,9 +36,7 @@ void
36ssh_login(Key **keys, int nkeys, const char *orighost, 36ssh_login(Key **keys, int nkeys, const char *orighost,
37 struct sockaddr *hostaddr, struct passwd *pw); 37 struct sockaddr *hostaddr, struct passwd *pw);
38 38
39void 39int verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key);
40check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
41 const char *user_hostfile, const char *system_hostfile);
42 40
43void ssh_kex(char *host, struct sockaddr *hostaddr); 41void ssh_kex(char *host, struct sockaddr *hostaddr);
44void ssh_kex2(char *host, struct sockaddr *hostaddr); 42void ssh_kex2(char *host, struct sockaddr *hostaddr);
diff --git a/sshconnect1.c b/sshconnect1.c
index c20613571..4c469c20d 100644
--- a/sshconnect1.c
+++ b/sshconnect1.c
@@ -13,7 +13,7 @@
13 */ 13 */
14 14
15#include "includes.h" 15#include "includes.h"
16RCSID("$OpenBSD: sshconnect1.c,v 1.33 2001/06/07 20:23:05 markus Exp $"); 16RCSID("$OpenBSD: sshconnect1.c,v 1.34 2001/06/23 02:34:32 markus Exp $");
17 17
18#include <openssl/bn.h> 18#include <openssl/bn.h>
19#include <openssl/evp.h> 19#include <openssl/evp.h>
@@ -784,8 +784,8 @@ ssh_kex(char *host, struct sockaddr *hostaddr)
784 SSH_SMSG_PUBLIC_KEY); 784 SSH_SMSG_PUBLIC_KEY);
785 k.type = KEY_RSA1; 785 k.type = KEY_RSA1;
786 k.rsa = host_key; 786 k.rsa = host_key;
787 check_host_key(host, hostaddr, &k, 787 if (verify_host_key(host, hostaddr, &k) == -1)
788 options.user_hostfile, options.system_hostfile); 788 fatal("host_key verification failed");
789 789
790 client_flags = SSH_PROTOFLAG_SCREEN_NUMBER | SSH_PROTOFLAG_HOST_IN_FWD_OPEN; 790 client_flags = SSH_PROTOFLAG_SCREEN_NUMBER | SSH_PROTOFLAG_HOST_IN_FWD_OPEN;
791 791
diff --git a/sshconnect2.c b/sshconnect2.c
index 5b354010d..e2d64d7b1 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -23,7 +23,7 @@
23 */ 23 */
24 24
25#include "includes.h" 25#include "includes.h"
26RCSID("$OpenBSD: sshconnect2.c,v 1.74 2001/05/19 16:32:16 markus Exp $"); 26RCSID("$OpenBSD: sshconnect2.c,v 1.75 2001/06/23 02:34:33 markus Exp $");
27 27
28#include <openssl/bn.h> 28#include <openssl/bn.h>
29#include <openssl/md5.h> 29#include <openssl/md5.h>
@@ -73,10 +73,10 @@ struct sockaddr *xxx_hostaddr;
73Kex *xxx_kex = NULL; 73Kex *xxx_kex = NULL;
74 74
75int 75int
76check_host_key_callback(Key *hostkey) 76verify_host_key_callback(Key *hostkey)
77{ 77{
78 check_host_key(xxx_host, xxx_hostaddr, hostkey, 78 if (verify_host_key(xxx_host, xxx_hostaddr, hostkey) == -1)
79 options.user_hostfile2, options.system_hostfile2); 79 fatal("verify_host_key failed");
80 return 0; 80 return 0;
81} 81}
82 82
@@ -119,7 +119,7 @@ ssh_kex2(char *host, struct sockaddr *hostaddr)
119 kex = kex_setup(myproposal); 119 kex = kex_setup(myproposal);
120 kex->client_version_string=client_version_string; 120 kex->client_version_string=client_version_string;
121 kex->server_version_string=server_version_string; 121 kex->server_version_string=server_version_string;
122 kex->check_host_key=&check_host_key_callback; 122 kex->verify_host_key=&verify_host_key_callback;
123 123
124 xxx_kex = kex; 124 xxx_kex = kex;
125 125
diff --git a/sshd.8 b/sshd.8
index b6ac3d40a..918e9ce57 100644
--- a/sshd.8
+++ b/sshd.8
@@ -34,7 +34,7 @@
34.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 34.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36.\" 36.\"
37.\" $OpenBSD: sshd.8,v 1.130 2001/06/22 21:55:50 markus Exp $ 37.\" $OpenBSD: sshd.8,v 1.131 2001/06/23 02:34:33 markus Exp $
38.Dd September 25, 1999 38.Dd September 25, 1999
39.Dt SSHD 8 39.Dt SSHD 8
40.Os 40.Os
@@ -1025,10 +1025,8 @@ permitopen="10.2.1.55:80",permitopen="10.2.1.56:25" 1024 33 23.\|.\|.\|2323
1025.Sh SSH_KNOWN_HOSTS FILE FORMAT 1025.Sh SSH_KNOWN_HOSTS FILE FORMAT
1026The 1026The
1027.Pa /etc/ssh_known_hosts , 1027.Pa /etc/ssh_known_hosts ,
1028.Pa /etc/ssh_known_hosts2 ,
1029.Pa $HOME/.ssh/known_hosts ,
1030and 1028and
1031.Pa $HOME/.ssh/known_hosts2 1029.Pa $HOME/.ssh/known_hosts
1032files contain host public keys for all known hosts. 1030files contain host public keys for all known hosts.
1033The global file should 1031The global file should
1034be prepared by the administrator (optional), and the per-user file is 1032be prepared by the administrator (optional), and the per-user file is
@@ -1129,7 +1127,8 @@ files into this file, as described in
1129.Xr ssh-keygen 1 . 1127.Xr ssh-keygen 1 .
1130.It Pa "/etc/ssh_known_hosts" and "$HOME/.ssh/known_hosts" 1128.It Pa "/etc/ssh_known_hosts" and "$HOME/.ssh/known_hosts"
1131These files are consulted when using rhosts with RSA host 1129These files are consulted when using rhosts with RSA host
1132authentication to check the public key of the host. 1130authentication or protocol version 2 hostbased authentication
1131to check the public key of the host.
1133The key must be listed in one of these files to be accepted. 1132The key must be listed in one of these files to be accepted.
1134The client uses the same files 1133The client uses the same files
1135to verify that it is connecting to the correct remote host. 1134to verify that it is connecting to the correct remote host.
@@ -1138,17 +1137,6 @@ These files should be writable only by root/the owner.
1138should be world-readable, and 1137should be world-readable, and
1139.Pa $HOME/.ssh/known_hosts 1138.Pa $HOME/.ssh/known_hosts
1140can but need not be world-readable. 1139can but need not be world-readable.
1141.It Pa "/etc/ssh_known_hosts2" and "$HOME/.ssh/known_hosts2"
1142These files are consulted when using protocol version 2 hostbased
1143authentication to check the public key of the host.
1144The key must be listed in one of these files to be accepted.
1145The client uses the same files
1146to verify that it is connecting to the correct remote host.
1147These files should be writable only by root/the owner.
1148.Pa /etc/ssh_known_hosts2
1149should be world-readable, and
1150.Pa $HOME/.ssh/known_hosts2
1151can but need not be world-readable.
1152.It Pa /etc/nologin 1140.It Pa /etc/nologin
1153If this file exists, 1141If this file exists,
1154.Nm 1142.Nm