After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 545445 - SSH's "Offending key" message results in connection timeout
SSH's "Offending key" message results in connection timeout
Status: RESOLVED FIXED
Product: gvfs
Classification: Core
Component: sftp backend
0.2.x
Other All
: Normal major
: ---
Assigned To: gvfs-maint
gvfs-maint
: 312271 (view as bug list)
Depends on:
Blocks:
 
 
Reported: 2008-07-30 07:48 UTC by Thomas Perl
Modified: 2018-05-04 10:30 UTC
See Also:
GNOME target: ---
GNOME version: 2.21/2.22


Attachments
Patch (3.06 KB, patch)
2008-07-30 17:54 UTC, Carlos Garcia Campos
reviewed Details | Review
sftp: Handle host key / IP mismatch (7.02 KB, patch)
2015-03-13 23:33 UTC, Ross Lagerwall
none Details | Review
sftp: Be more robust when parsing login messages (1.10 KB, patch)
2015-03-13 23:33 UTC, Ross Lagerwall
none Details | Review
sftp: Ignore leading whitespace during login (1.01 KB, patch)
2015-03-14 14:51 UTC, Ross Lagerwall
committed Details | Review
sftp: Handle host key / IP mismatch (6.99 KB, patch)
2015-03-18 21:24 UTC, Ross Lagerwall
committed Details | Review
sftp: Be more robust when parsing login messages (1.09 KB, patch)
2015-03-18 21:24 UTC, Ross Lagerwall
committed Details | Review

Description Thomas Perl 2008-07-30 07:48:53 UTC
Please describe the problem:
On a small home network with a NAT router doing DHCP and multiple Linux machines with sshd running, I occassionally get into a situation where ssh has a problem connecting via ssh because host keys do not match for the IP (but for the host) or vice-versa. When manually connecting to such a server via "ssh" in the terminal, I get:

Warning: the RSA host key for 'serverhostname' differs from the key for the IP address 'XX.XX.XX.XX'
Offending key for IP in /home/username/.ssh/known_hosts:123
Matching host key in /home/username/.ssh/known_hosts:32
Are you sure you want to continue connecting (yes/no)?

I can then choose to accept the changed key or not. This should be handled in the sftp backend, too, by asking a question similiar to the case where no host key is saved locally ("The identify of the remote computer (...) is unknown[...]").

This should probably be handled with a similiar dialog to the handling for the string "The authenticity of host" in handle_login(), but stating that there is a new host key, but an old one matches (or something like that).

By looking at the source, I think this should be handled in "handle_login()" in "daemon/gvfsbackendsftp.c".

By the way: Maybe the host key verification failure should also be handled graphically, see http://www.linux-club.de/viewtopic.php?f=38&t=48887 for a sample message output of the "remote host identification has changed" warning.

Steps to reproduce:
1. Have to computers (or virtual machines, I'll call them computer X and computer Y) on the local network, each with their own sshd, a DIFFERENT hostname and a DIFFERENT host key.
2. Have to free IPs to assign to these machines (I'll call them IP A and IP B here)
3. Assign IP A to computer X and IP B to computer Y
4. Connect via ssh to X and Y and save the host keys for each of them
5. Assign IP B to computer X and IP A to computer Y
6. Try to connect to X (or Y) via gvfs' sftp backend


Actual results:
A timeout error occurs, looking as if the server went offline when in fact the ssh process is just waiting for an answer to the question "Offending key, Matching host key".

Expected results:
A GTK dialog box popping up and asking me if I want to continue connecting, and stating that the host key has changed (something like the dialog for the case where the host key is not known).

Does this happen every time?
Yes

Other information:
The current behaviour is misleading, because if the user does not know how to use the "ssh" command-line client, this effectively locks her out of a sftp connection and it's not possible to connect to such a server with changed host keys or IPs, even though it's possible to connect once with "ssh" and answer the question correctly. After having "fixed" the issue with "ssh", the sftp backend starts working again, because on subsequent connects, the question is not asked anymore.

It seems like you have to use the hostname for the machine to get this "Offending key" and "Matching key" messages. Plain IPs won't work (you'll get the "remote host identification has changed" warning).
Comment 1 Carlos Garcia Campos 2008-07-30 17:54:43 UTC
Created attachment 115578 [details] [review]
Patch

Hi Thomas, thank you very much for the detailed explanation. I don't have the network configuration needed to reproduce this problem, so I don't actually know whether the attached patch works or not. Could you confirm it please? We should probably add a better explanation of the problem in the dialog message too, but let's see if the patch is correct before.
Comment 2 Thomas Perl 2008-07-31 17:25:23 UTC
I've tested your patch and it works fine for the situation described. We just have to work on the wording.

Here's how you can test it too:

1.) Backup and move out of the way your ~/.ssh/known_hosts file
2.) Make sure you have HashKnownHosts set to "no" for this test in ~/.ssh/config
3.) Connect to one of your ssh accounts (use the DNS name), saving the host key
4.) Edit ~/.ssh/known_hosts like this:
    1.) Duplicate the single entry, so you have two equal lines
    2.) Remove the IP address from the first line
    3.) In the second line, replace the host key with another one (see below)
    4.) Try to connect via ssh, answer with "no" to the question
    5.) Connect via the gvfs backend to the same server, you see the dialog box
5.) Revert the HashKnownHosts setting in ~/.ssh/config to the previous setting
6.) Copy the backup of ~/.ssh/known_hosts back into its regular place

You can get another host key (which is invalid for your regular host) by trying to connect to a ssh server (like ssh gnome.org) and accepting the host key, which puts it into your known_hosts file where it can be copied and used.
Comment 3 Matthias Clasen 2008-08-16 00:21:08 UTC
Do you have a concrete proposal for better wording ? It looks ok to me...

On the patch, I note that hostname and ipaddress may be NULL if get_hostname_and_ipaddress_from_line fails. 
The g_strdup_printf call handles that for hostname, but not for ipaddress.
Comment 4 Thomas Perl 2008-08-17 13:25:18 UTC
I am ok with the wording, too, if nobody comes up with a better one (Carlos said in comment #1 that we should work on the wording).
Comment 5 Carlos Garcia Campos 2008-08-17 15:12:23 UTC
(In reply to comment #3)
> Do you have a concrete proposal for better wording ? It looks ok to me...
> 
> On the patch, I note that hostname and ipaddress may be NULL if
> get_hostname_and_ipaddress_from_line fails. 
> The g_strdup_printf call handles that for hostname, but not for ipaddress.
> 

Yes, the same happens with fingerprint when get_hostname_and_fingerprint_from_line() fails. I don't know what to use in both cases instead of the fingerprint and ipaddress. 

(In reply to comment #4)
> I am ok with the wording, too, if nobody comes up with a better one (Carlos
> said in comment #1 that we should work on the wording).
> 

It's ok for me too, I just thought someone might come up with a more user friendly message. 
Comment 6 Thomas Perl 2008-08-18 05:11:59 UTC
(In reply to comment #5)
> (In reply to comment #3)
> > On the patch, I note that hostname and ipaddress may be NULL if
> > get_hostname_and_ipaddress_from_line fails. 
> > The g_strdup_printf call handles that for hostname, but not for ipaddress.
> > 
> 
> Yes, the same happens with fingerprint when
> get_hostname_and_fingerprint_from_line() fails. I don't know what to use in
> both cases instead of the fingerprint and ipaddress. 

I couldn't find anything in GLib to do DNS lookups, so this might be what we want:

#include <netdb.h>
#include <arpa/inet.h>

[...]
char buf[16]; 

if(ipaddress == NULL) {
  struct hostent* h;
  h = gethostbyname(hostname ? hostname : op_backend->host);

  if(h != NULL) {
    ipaddress = g_strdup(inet_ntop(AF_INET, (struct in_addr *)h->h_addr, buf, 16));
  }

  if(ipaddress == NULL) {
    ipaddress = g_strdup(_("unknown"));
  }
}
[...]

(Source: http://beej.us/guide/bgnet/output/html/multipage/syscalls.html#dns and http://www.pronix.de/pronix-281.html)


Is there some helper function to easily get an IP address string from a hostname in GLib/gvfs already that I don't know about?

Maybe we should just fail and show an helpful error message ("Couldn't connect to host - please check SSH connection with a text-mode SSH client first.") so the user knows what to do in case ipaddress is NULL.
Comment 7 Tomas Bzatek 2010-02-19 17:24:21 UTC
I was just facing the same issue... pretty annoying.
Comment 8 Ross Lagerwall 2015-03-13 23:33:19 UTC
Created attachment 299366 [details] [review]
sftp: Handle host key / IP mismatch

Handle the following SSH login question by asking the user whether to
continue or not:

Warning: the ECDSA/RSA host key for 'hostname' differs from the key for the IP address '...'
Offending key for IP in /home/username/.ssh/known_hosts:???
Matching host key in /home/username/.ssh/known_hosts:???
Are you sure you want to continue connecting (yes/no)? yes

Based on a patch by Carlos Garcia Campos.
Comment 9 Ross Lagerwall 2015-03-13 23:33:25 UTC
Created attachment 299367 [details] [review]
sftp: Be more robust when parsing login messages

Handle the case when the fingerprint could not be parsed from SSH's
output.
Comment 10 Ross Lagerwall 2015-03-14 14:51:01 UTC
Created attachment 299404 [details] [review]
sftp: Ignore leading whitespace during login

If logging in without an agent, g_str_has_prefix (buffer, "Enter
passphrase for key") fails the second time around (e.g. if the first
entry was incorrect) because the buffer contains a leading newline: "
Enter passphrase for key '/home/user/.ssh/id_rsa': "
This makes the login process timeout.

To fix this, trim leading whitespace.
Comment 11 Ondrej Holy 2015-03-16 14:27:36 UTC
Review of attachment 299367 [details] [review]:

Looks good!
Comment 12 Ondrej Holy 2015-03-17 14:26:10 UTC
Review of attachment 299404 [details] [review]:

Looks good! 

(Do you have an idea how to disable the agent in GNOME?)
Comment 13 Ondrej Holy 2015-03-17 14:26:13 UTC
Review of attachment 299404 [details] [review]:

Looks good! 

(Do you have an idea how to disable the agent in GNOME?)
Comment 14 Ross Lagerwall 2015-03-17 14:52:03 UTC
(In reply to Ondrej Holy from comment #13)
> Review of attachment 299404 [details] [review] [review]:
> 
> Looks good! 
> 
> (Do you have an idea how to disable the agent in GNOME?)

You can grep for gnome-keyring through the dbus service files and comment it out so that it doesn't autostart then restart the session.
Comment 15 Matthias Clasen 2015-03-17 14:57:36 UTC
(In reply to Ross Lagerwall from comment #14)
> (In reply to Ondrej Holy from comment #13)
> > Review of attachment 299404 [details] [review] [review] [review]:
> > 
> > Looks good! 
> > 
> > (Do you have an idea how to disable the agent in GNOME?)
> 
> You can grep for gnome-keyring through the dbus service files and comment it
> out so that it doesn't autostart then restart the session.

Or you can just identify the appropriate gnome-keyring-... autostart file in /etc/xdg/autostart and remove it.
Comment 16 Ross Lagerwall 2015-03-17 15:36:33 UTC
(In reply to Matthias Clasen from comment #15)
> (In reply to Ross Lagerwall from comment #14)
> > (In reply to Ondrej Holy from comment #13)
> > > Review of attachment 299404 [details] [review] [review] [review] [review]:
> > > 
> > > Looks good! 
> > > 
> > > (Do you have an idea how to disable the agent in GNOME?)
> > 
> > You can grep for gnome-keyring through the dbus service files and comment it
> > out so that it doesn't autostart then restart the session.
> 
> Or you can just identify the appropriate gnome-keyring-... autostart file in
> /etc/xdg/autostart and remove it.

But it can still get get autostarted via dbus by programs (including gvfs) that try and use org.freedesktop.secrets or org.gnome.keyring.
Comment 17 Ondrej Holy 2015-03-17 15:45:38 UTC
Review of attachment 299366 [details] [review]:

Looks good, thanks, just...

::: daemon/gvfsbackendsftp.c
@@ +837,3 @@
+
+  /* Parse a line that looks like:
+   * Warning: the ECDSA/RSA host key for 'hostname' differs from the key for the IP address '...'

Maybe would be good to check that we really parsing this message...

@@ +871,3 @@
+
+static gboolean
+login_answer_yes_no (GMountSource *mount_source,

(Maybe would be useful to put something like this function inside e.g. gvfsdaemonutils.c...)

@@ +890,3 @@
+    {
+      g_set_error_literal (error,
+                           G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,

This isn't G_IO_ERROR_PERMISSION_DENIED, is it?

@@ +909,3 @@
+    {
+      g_set_error_literal (error,
+                           G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,

dtto

@@ +1231,3 @@
+                                       "contact the system administrator."),
+                                     hostname ? hostname : op_backend->host,
+                                     ip_address ? ip_address : _("unknown"));

"...for the IP address unknown..." seems to me like nonsense, wouldn't be better to just omit the address:
ip_address ? ip_address : ""
Comment 18 Ondrej Holy 2015-03-17 15:51:32 UTC
Review of attachment 299367 [details] [review]:

::: daemon/gvfsbackendsftp.c
@@ +1207,3 @@
 				       "contact the system administrator."),
+                                     hostname ? hostname : op_backend->host,
+                                     fingerprint ? fingerprint : _("unknown"));

I've just realized that this doesn't have to work for all translations correctly... Maybe would be good to add translators comments in which context this is used and what is the %s at least...
Comment 19 Ondrej Holy 2015-03-18 16:42:50 UTC
(In reply to Ross Lagerwall from comment #16)
> (In reply to Matthias Clasen from comment #15)
> > (In reply to Ross Lagerwall from comment #14)
> > > (In reply to Ondrej Holy from comment #13)
> > > > Review of attachment 299404 [details] [review] [review] [review] [review] [review]:
> > > > 
> > > > Looks good! 
> > > > 
> > > > (Do you have an idea how to disable the agent in GNOME?)
> > > 
> > > You can grep for gnome-keyring through the dbus service files and comment it
> > > out so that it doesn't autostart then restart the session.
> > 
> > Or you can just identify the appropriate gnome-keyring-... autostart file in
> > /etc/xdg/autostart and remove it.
> 
> But it can still get get autostarted via dbus by programs (including gvfs)
> that try and use org.freedesktop.secrets or org.gnome.keyring.

Thanks for the elaboration :-)
Comment 20 Ross Lagerwall 2015-03-18 21:24:09 UTC
Created attachment 299766 [details] [review]
sftp: Handle host key / IP mismatch

Handle the following SSH login question by asking the user whether to
continue or not:

Warning: the ECDSA/RSA host key for 'hostname' differs from the key for the IP address '...'
Offending key for IP in /home/username/.ssh/known_hosts:???
Matching host key in /home/username/.ssh/known_hosts:???
Are you sure you want to continue connecting (yes/no)? yes

Based on a patch by Carlos Garcia Campos.
Comment 21 Ross Lagerwall 2015-03-18 21:24:24 UTC
Created attachment 299767 [details] [review]
sftp: Be more robust when parsing login messages

Handle the case when the fingerprint could not be parsed from SSH's
output.
Comment 22 Ross Lagerwall 2015-03-18 21:31:51 UTC
(In reply to Ondrej Holy from comment #17)
> Review of attachment 299366 [details] [review] [review]:
> 
> Looks good, thanks, just...
> 
> ::: daemon/gvfsbackendsftp.c
> @@ +837,3 @@
> +
> +  /* Parse a line that looks like:
> +   * Warning: the ECDSA/RSA host key for 'hostname' differs from the key
> for the IP address '...'
> 
> Maybe would be good to check that we really parsing this message...

Well I already check that it mostly matches:
    else if (strstr (buffer, "differs from the key for the IP address"))
Checking further seems like more effort for little gain.

> 
> @@ +871,3 @@
> +
> +static gboolean
> +login_answer_yes_no (GMountSource *mount_source,
> 
> (Maybe would be useful to put something like this function inside e.g.
> gvfsdaemonutils.c...)

It's fairly specific to ssh at the moment so I'll leave it here for now.

> 
> @@ +890,3 @@
> +    {
> +      g_set_error_literal (error,
> +                           G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
> 
> This isn't G_IO_ERROR_PERMISSION_DENIED, is it?

This is what the original code had. I've changed it to G_IO_ERROR_FAILED.

> 
> @@ +909,3 @@
> +    {
> +      g_set_error_literal (error,
> +                           G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED,
> 
> dtto
> 
> @@ +1231,3 @@
> +                                       "contact the system administrator."),
> +                                     hostname ? hostname : op_backend->host,
> +                                     ip_address ? ip_address :
> _("unknown"));
> 
> "...for the IP address unknown..." seems to me like nonsense, wouldn't be
> better to just omit the address:
> ip_address ? ip_address : ""

I changed it to:
    The host key for “git.gnome.org” differs from the key for the IP address “???”
I think this OK, given that it is an unlikely error condition (and it doesn't require awkward translation...)


(In reply to Ondrej Holy from comment #18)
> Review of attachment 299367 [details] [review] [review]:
> 
> ::: daemon/gvfsbackendsftp.c
> @@ +1207,3 @@
>  				       "contact the system administrator."),
> +                                     hostname ? hostname : op_backend->host,
> +                                     fingerprint ? fingerprint :
> _("unknown"));
> 
> I've just realized that this doesn't have to work for all translations
> correctly... Maybe would be good to add translators comments in which
> context this is used and what is the %s at least...

I changed it to:
    Can't verify the identity of “git.gnome.org”.
    This happens when you log in to a computer the first time.

    The identity sent by the remote computer is “???”. If you want to be absolutely sure it is safe to continue, contact the system administrator.
I think this OK, given that it is an unlikely error condition (and it doesn't require awkward translation...)
Comment 23 Ondrej Holy 2015-04-07 10:56:46 UTC
Review of attachment 299767 [details] [review]:

Looks good!
Comment 24 Ondrej Holy 2015-04-07 11:29:23 UTC
Review of attachment 299766 [details] [review]:

Looks good, thanks, just formatting...

Please push after branched due to the new translations.

::: daemon/gvfsbackendsftp.c
@@ +840,3 @@
+   * First get the hostname.
+   */
+  startpos = strchr(buffer, '\'') + 1;

Missing space between function name and parenthesis.

@@ +844,3 @@
+    return FALSE;
+
+  endpos = strchr(startpos, '\'');

dtto

@@ +851,3 @@
+
+  /* Then get the ip address. */
+  startpos = strchr(endpos + 1, '\'') + 1;

dtto

@@ +858,3 @@
+    }
+
+  endpos = strchr(startpos, '\'');

dtto
Comment 25 Ross Lagerwall 2015-04-09 21:07:58 UTC
Pushed to master as ab4e591a40bbcd2d0e3b11e966fad42eaf259c28. Thanks for the reviews!
Comment 26 Ondrej Holy 2016-04-13 08:17:19 UTC
I realized that get_hostname_and_ip_address from attachment 299766 [details] [review] might cause segfault theoretically, so I pushed a fix for it, see commit 4a15698.
Comment 27 Ondrej Holy 2018-05-04 10:30:55 UTC
*** Bug 312271 has been marked as a duplicate of this bug. ***