/* $OpenBSD: sshconnect.c,v 1.191 2006/07/12 22:28:52 stevesk Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Code to connect to a remote host, and to perform the client side of the
* login (authentication) dialog.
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*/
#include "includes.h"
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <ctype.h>
#include <errno.h>
#if defined(HAVE_NETDB_H)
# include <netdb.h>
#endif
#ifdef HAVE_PATHS_H
#include <paths.h>
#endif
#include <pwd.h>
#include "ssh.h"
#include "xmalloc.h"
#include "rsa.h"
#include "buffer.h"
#include "packet.h"
#include "uidswap.h"
#include "compat.h"
#include "key.h"
#include "sshconnect.h"
#include "hostfile.h"
#include "log.h"
#include "readconf.h"
#include "atomicio.h"
#include "misc.h"
#include "dns.h"
#include "version.h"
char *client_version_string = NULL;
char *server_version_string = NULL;
static int matching_host_key_dns = 0;
/* import */
extern Options options;
extern char *__progname;
extern uid_t original_real_uid;
extern uid_t original_effective_uid;
extern pid_t proxy_command_pid;
#ifndef INET6_ADDRSTRLEN /* for non IPv6 machines */
#define INET6_ADDRSTRLEN 46
#endif
static int show_other_keys(const char *, Key *);
static void warn_changed_key(Key *);
/*
* Connect to the given ssh server using a proxy command.
*/
static int
ssh_proxy_connect(const char *host, u_short port, const char *proxy_command)
{
char *command_string, *tmp;
int pin[2], pout[2];
pid_t pid;
char strport[NI_MAXSERV];
/* Convert the port number into a string. */
snprintf(strport, sizeof strport, "%hu", port);
/*
* Build the final command string in the buffer by making the
* appropriate substitutions to the given proxy command.
*
* Use "exec" to avoid "sh -c" processes on some platforms
* (e.g. Solaris)
*/
xasprintf(&tmp, "exec %s", proxy_command);
command_string = percent_expand(tmp, "h", host,
"p", strport, (char *)NULL);
xfree(tmp);
/* Create pipes for communicating with the proxy. */
if (pipe(pin) < 0 || pipe(pout) < 0)
fatal("Could not create pipes to communicate with the proxy: %.100s",
strerror(errno));
debug("Executing proxy command: %.500s", command_string);
/* Fork and execute the proxy command. */
if ((pid = fork()) == 0) {
char *argv[10];
/* Child. Permanently give up superuser privileges. */
permanently_drop_suid(original_real_uid);
/* Redirect stdin and stdout. */
close(pin[1]);
if (pin[0] != 0) {
if (dup2(pin[0], 0) < 0)
perror("dup2 stdin");
close(pin[0]);
}
close(pout[0]);
if (dup2(pout[1], 1) < 0)
perror("dup2 stdout");
/* Cannot be 1 because pin allocated two descriptors. */
close(pout[1]);
/* Stderr is left as it is so that error messages get
printed on the user's terminal. */
argv[0] = _PATH_BSHELL;
argv[1] = "-c";
argv[2] = command_string;
argv[3] = NULL;
/* Execute the proxy command. Note that we gave up any
extra privileges above. */
execv(argv[0], argv);
perror(argv[0]);
exit(1);
}
/* Parent. */
if (pid < 0)
fatal("fork failed: %.100s", strerror(errno));