-/* $OpenBSD: ssh.c,v 1.290 2006/07/26 13:57:17 stevesk Exp $ */
+/* $OpenBSD: ssh.c,v 1.300 2007/06/14 22:48:05 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
#endif
#include <pwd.h>
#include <signal.h>
+#include <stdarg.h>
#include <stddef.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
#include <openssl/evp.h>
#include <openssl/err.h>
+#include "xmalloc.h"
#include "ssh.h"
#include "ssh1.h"
#include "ssh2.h"
#include "compat.h"
#include "cipher.h"
-#include "xmalloc.h"
#include "packet.h"
#include "buffer.h"
-#include "bufaux.h"
#include "channels.h"
#include "key.h"
#include "authfd.h"
usage(void)
{
fprintf(stderr,
-"usage: ssh [-1246AaCfgkMNnqsTtVvXxY] [-b bind_address] [-c cipher_spec]\n"
+"usage: ssh [-1246AaCfgKkMNnqsTtVvXxY] [-b bind_address] [-c cipher_spec]\n"
" [-D [bind_address:]port] [-e escape_char] [-F configfile]\n"
" [-i identity_file] [-L [bind_address:]port:host:hostport]\n"
" [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]\n"
again:
while ((opt = getopt(ac, av,
- "1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:I:L:MNO:PR:S:TVw:XY")) != -1) {
+ "1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:I:KL:MNO:PR:S:TVw:XY")) != -1) {
switch (opt) {
case '1':
options.protocol = SSH_PROTO_1;
case 'k':
options.gss_deleg_creds = 0;
break;
+ case 'K':
+ options.gss_authentication = 1;
+ options.gss_deleg_creds = 1;
+ break;
case 'i':
if (stat(optarg, &st) < 0) {
fprintf(stderr, "Warning: Identity file %s "
if (!read_config_file(config, host, &options, 0))
fatal("Can't open user config file %.100s: "
"%.100s", config, strerror(errno));
- } else {
+ } else {
snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir,
_PATH_SSH_USER_CONFFILE);
(void)read_config_file(buf, host, &options, 1);
if (options.smartcard_device != NULL &&
options.num_identity_files < SSH_MAX_IDENTITY_FILES &&
- (keys = sc_get_keys(options.smartcard_device, NULL)) != NULL ) {
+ (keys = sc_get_keys(options.smartcard_device, NULL)) != NULL) {
int count = 0;
for (i = 0; keys[i] != NULL; i++) {
count++;
cp = tilde_expand_filename(options.identity_files[i],
original_real_uid);
filename = percent_expand(cp, "d", pw->pw_dir,
- "u", pw->pw_name, "l", thishost, "h", host,
+ "u", pw->pw_name, "l", thishost, "h", host,
"r", options.user, (char *)NULL);
xfree(cp);
public = key_load_public(filename, NULL);
control_client(const char *path)
{
struct sockaddr_un addr;
- int i, r, fd, sock, exitval, num_env, addr_len;
+ int i, r, fd, sock, exitval[2], num_env, addr_len;
Buffer m;
char *term;
extern char **environ;
if (tty_flag)
enter_raw_mode();
- /* Stick around until the controlee closes the client_fd */
- exitval = 0;
- for (;!control_client_terminate;) {
- r = read(sock, &exitval, sizeof(exitval));
+ /*
+ * Stick around until the controlee closes the client_fd.
+ * Before it does, it is expected to write this process' exit
+ * value (one int). This process must read the value and wait for
+ * the closure of the client_fd; if this one closes early, the
+ * multiplex master will terminate early too (possibly losing data).
+ */
+ exitval[0] = 0;
+ for (i = 0; !control_client_terminate && i < (int)sizeof(exitval);) {
+ r = read(sock, (char *)exitval + i, sizeof(exitval) - i);
if (r == 0) {
debug2("Received EOF from master");
break;
}
- if (r > 0)
- debug2("Received exit status from master %d", exitval);
- if (r == -1 && errno != EINTR)
+ if (r == -1) {
+ if (errno == EINTR)
+ continue;
fatal("%s: read %s", __func__, strerror(errno));
+ }
+ i += r;
}
- if (control_client_terminate)
- debug2("Exiting on signal %d", control_client_terminate);
-
close(sock);
-
leave_raw_mode();
+ if (i > (int)sizeof(int))
+ fatal("%s: master returned too much data (%d > %lu)",
+ __func__, i, sizeof(int));
+ if (control_client_terminate) {
+ debug2("Exiting on signal %d", control_client_terminate);
+ exitval[0] = 255;
+ } else if (i < (int)sizeof(int)) {
+ debug2("Control master terminated unexpectedly");
+ exitval[0] = 255;
+ } else
+ debug2("Received exit status from master %d", exitval[0]);
if (tty_flag && options.log_level != SYSLOG_LEVEL_QUIET)
- fprintf(stderr, "Connection to master closed.\r\n");
+ fprintf(stderr, "Shared connection to %s closed.\r\n", host);
- exit(exitval);
+ exit(exitval[0]);
}