-/* $OpenBSD: sshconnect.c,v 1.182 2006/05/17 12:43:34 markus Exp $ */
+/* $OpenBSD: sshconnect.c,v 1.199 2006/08/03 03:34:42 deraadt Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
+#include <sys/socket.h>
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+
+#include <netinet/in.h>
#include <ctype.h>
+#include <errno.h>
+#include <netdb.h>
#ifdef HAVE_PATHS_H
#include <paths.h>
#endif
+#include <pwd.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
-#include "ssh.h"
#include "xmalloc.h"
+#include "key.h"
+#include "hostfile.h"
+#include "ssh.h"
#include "rsa.h"
#include "buffer.h"
#include "packet.h"
#include "atomicio.h"
#include "misc.h"
#include "dns.h"
+#include "version.h"
char *client_version_string = NULL;
char *server_version_string = NULL;
char *argv[10];
/* Child. Permanently give up superuser privileges. */
- seteuid(original_real_uid);
- setuid(original_real_uid);
+ permanently_drop_suid(original_real_uid);
/* Redirect stdin and stdout. */
close(pin[1]);
int connection_in = packet_get_connection_in();
int connection_out = packet_get_connection_out();
int minor1 = PROTOCOL_MINOR_1;
- u_int i;
+ u_int i, n;
/* Read other side's version identification. */
- for (;;) {
+ for (n = 0;;) {
for (i = 0; i < sizeof(buf) - 1; i++) {
size_t len = atomicio(read, connection_in, &buf[i], 1);
buf[i + 1] = 0;
break;
}
+ if (++n > 65536)
+ fatal("ssh_exchange_identification: No banner received");
}
buf[sizeof(buf) - 1] = 0;
if (strncmp(buf, "SSH-", 4) == 0)
* check whether the supplied host key is valid, return -1 if the key
* is not valid. the user_hostfile will not be updated if 'readonly' is true.
*/
+#define RDRW 0
+#define RDONLY 1
+#define ROQUIET 2
static int
-check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
- int readonly, const char *user_hostfile, const char *system_hostfile)
+check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
+ Key *host_key, int readonly, const char *user_hostfile,
+ const char *system_hostfile)
{
Key *file_key;
const char *type = key_type(host_key);
- char *ip = NULL;
+ char *ip = NULL, *host = NULL;
char hostline[1000], *hostp, *fp;
HostStatus host_status;
HostStatus ip_status;
if (getnameinfo(hostaddr, salen, ntop, sizeof(ntop),
NULL, 0, NI_NUMERICHOST) != 0)
fatal("check_host_key: getnameinfo failed");
- ip = xstrdup(ntop);
+ ip = put_host_port(ntop, port);
} else {
ip = xstrdup("<no hostip for proxy command>");
}
* Turn off check_host_ip if the connection is to localhost, via proxy
* command or if we don't have a hostname to compare with
*/
- if (options.check_host_ip &&
- (local || strcmp(host, ip) == 0 || options.proxy_command != NULL))
+ if (options.check_host_ip && (local ||
+ strcmp(hostname, ip) == 0 || options.proxy_command != NULL))
options.check_host_ip = 0;
/*
- * Allow the user to record the key under a different name. This is
- * useful for ssh tunneling over forwarded connections or if you run
- * multiple sshd's on different ports on the same machine.
+ * Allow the user to record the key under a different name or
+ * differentiate a non-standard port. This is useful for ssh
+ * tunneling over forwarded connections or if you run multiple
+ * sshd's on different ports on the same machine.
*/
if (options.host_key_alias != NULL) {
- host = options.host_key_alias;
+ host = xstrdup(options.host_key_alias);
debug("using hostkeyalias: %s", host);
+ } else {
+ host = put_host_port(hostname, port);
}
/*
}
break;
case HOST_NEW:
+ if (options.host_key_alias == NULL && port != 0 &&
+ port != SSH_DEFAULT_PORT) {
+ debug("checking without port identifier");
+ if (check_host_key(hostname, hostaddr, 0, host_key, 2,
+ user_hostfile, system_hostfile) == 0) {
+ debug("found matching key w/out port");
+ break;
+ }
+ }
if (readonly)
goto fail;
/* The host is new. */
"list of known hosts.", hostp, type);
break;
case HOST_CHANGED:
+ if (readonly == ROQUIET)
+ goto fail;
if (options.check_host_ip && host_ip_differ) {
char *key_msg;
if (ip_status == HOST_NEW)
/*
* If strict host key checking has not been requested, allow
* the connection but without MITM-able authentication or
- * agent forwarding.
+ * forwarding.
*/
if (options.password_authentication) {
error("Password authentication is disabled to avoid "
options.num_local_forwards =
options.num_remote_forwards = 0;
}
+ if (options.tun_open != SSH_TUNMODE_NO) {
+ error("Tunnel forwarding is disabled to avoid "
+ "man-in-the-middle attacks.");
+ options.tun_open = SSH_TUNMODE_NO;
+ }
/*
* XXX Should permit the user to change to use the new id.
* This could be done by converting the host key to an
}
xfree(ip);
+ xfree(host);
return 0;
fail:
xfree(ip);
+ xfree(host);
return -1;
}
/* return ok if the key can be found in an old keyfile */
if (stat(options.system_hostfile2, &st) == 0 ||
stat(options.user_hostfile2, &st) == 0) {
- if (check_host_key(host, hostaddr, host_key, /*readonly*/ 1,
- options.user_hostfile2, options.system_hostfile2) == 0)
+ if (check_host_key(host, hostaddr, options.port, host_key,
+ RDONLY, options.user_hostfile2,
+ options.system_hostfile2) == 0)
return 0;
}
- return check_host_key(host, hostaddr, host_key, /*readonly*/ 0,
- options.user_hostfile, options.system_hostfile);
+ return check_host_key(host, hostaddr, options.port, host_key,
+ RDRW, options.user_hostfile, options.system_hostfile);
}
/*