Merge branch 'master' of https://github.com/openssh/openssh-portable into latestw

This commit is contained in:
Manoj Ampalam 2017-10-03 14:32:45 -07:00
commit 6fba3a2ae9
62 changed files with 3210 additions and 2196 deletions

2
.gitignore vendored
View File

@ -26,6 +26,8 @@ ssh-keyscan
ssh-keysign ssh-keysign
ssh-pkcs11-helper ssh-pkcs11-helper
sshd sshd
!regress/misc/fuzz-harness/Makefile
# Ignores in Windows fork # Ignores in Windows fork
/bin/x64/Debug /bin/x64/Debug
/contrib/win32/openssh/.vs/Win32-OpenSSH/v14 /contrib/win32/openssh/.vs/Win32-OpenSSH/v14

View File

@ -1,3 +1,5 @@
This file used to contain a description of the SSH agent protocol This file used to contain a description of the SSH agent protocol
implemented by OpenSSH. It has since been superseded by implemented by OpenSSH. It has since been superseded by an Internet-
https://tools.ietf.org/html/draft-miller-ssh-agent-00 draft that is available from:
https://tools.ietf.org/html/draft-miller-ssh-agent-02

2
README
View File

@ -1,4 +1,4 @@
See https://www.openssh.com/releasenotes.html#7.5p1 for the release notes. See https://www.openssh.com/releasenotes.html#7.6p1 for the release notes.
Please read https://www.openssh.com/report.html for bug reporting Please read https://www.openssh.com/report.html for bug reporting
instructions and note that we do not use Github for bug reporting or instructions and note that we do not use Github for bug reporting or

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth-options.c,v 1.73 2017/05/31 10:54:00 markus Exp $ */ /* $OpenBSD: auth-options.c,v 1.74 2017/09/12 06:32:07 djm Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -61,9 +61,13 @@ char *authorized_principals = NULL;
extern ServerOptions options; extern ServerOptions options;
/* XXX refactor to be stateless */
void void
auth_clear_options(void) auth_clear_options(void)
{ {
struct ssh *ssh = active_state; /* XXX */
no_agent_forwarding_flag = 0; no_agent_forwarding_flag = 0;
no_port_forwarding_flag = 0; no_port_forwarding_flag = 0;
no_pty_flag = 0; no_pty_flag = 0;
@ -81,7 +85,7 @@ auth_clear_options(void)
free(authorized_principals); free(authorized_principals);
authorized_principals = NULL; authorized_principals = NULL;
forced_tun_device = -1; forced_tun_device = -1;
channel_clear_permitted_opens(); channel_clear_permitted_opens(ssh);
} }
/* /*
@ -117,6 +121,7 @@ match_flag(const char *opt, int allow_negate, char **optsp, const char *msg)
/* /*
* return 1 if access is granted, 0 if not. * return 1 if access is granted, 0 if not.
* side effect: sets key option flags * side effect: sets key option flags
* XXX remove side effects; fill structure instead.
*/ */
int int
auth_parse_options(struct passwd *pw, char *opts, const char *file, auth_parse_options(struct passwd *pw, char *opts, const char *file,
@ -380,7 +385,7 @@ auth_parse_options(struct passwd *pw, char *opts, const char *file,
goto bad_option; goto bad_option;
} }
if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0) if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0)
channel_add_permitted_opens(host, port); channel_add_permitted_opens(ssh, host, port);
free(patterns); free(patterns);
goto next_option; goto next_option;
} }

3
auth.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth.c,v 1.123 2017/08/18 05:36:45 djm Exp $ */ /* $OpenBSD: auth.c,v 1.124 2017/09/12 06:32:07 djm Exp $ */
/* /*
* Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2000 Markus Friedl. All rights reserved.
* *
@ -592,6 +592,7 @@ getpwnamallow(const char *user)
ci->user = user; ci->user = user;
parse_server_match_config(&options, ci); parse_server_match_config(&options, ci);
log_change_level(options.log_level); log_change_level(options.log_level);
process_permitopen(ssh, &options);
#if defined(_AIX) && defined(HAVE_SETAUTHDB) #if defined(_AIX) && defined(HAVE_SETAUTHDB)
aix_setauthdb(user); aix_setauthdb(user);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: auth2-pubkey.c,v 1.70 2017/08/18 05:48:04 djm Exp $ */ /* $OpenBSD: auth2-pubkey.c,v 1.71 2017/09/07 23:48:09 djm Exp $ */
/* /*
* Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2000 Markus Friedl. All rights reserved.
* *
@ -482,7 +482,7 @@ check_authkeys_file(FILE *f, char *file, struct sshkey *key, struct passwd *pw)
char *cp, *key_options = NULL, *fp = NULL; char *cp, *key_options = NULL, *fp = NULL;
const char *reason = NULL; const char *reason = NULL;
/* Always consume entrire file */ /* Always consume entire file */
if (found_key) if (found_key)
continue; continue;
if (found != NULL) if (found != NULL)

2903
channels.c

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/* $OpenBSD: channels.h,v 1.126 2017/05/30 14:23:52 markus Exp $ */ /* $OpenBSD: channels.h,v 1.130 2017/09/21 19:16:53 markus Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -57,23 +57,27 @@
#define SSH_CHANNEL_UNIX_LISTENER 18 /* Listening on a domain socket. */ #define SSH_CHANNEL_UNIX_LISTENER 18 /* Listening on a domain socket. */
#define SSH_CHANNEL_RUNIX_LISTENER 19 /* Listening to a R-style domain socket. */ #define SSH_CHANNEL_RUNIX_LISTENER 19 /* Listening to a R-style domain socket. */
#define SSH_CHANNEL_MUX_PROXY 20 /* proxy channel for mux-slave */ #define SSH_CHANNEL_MUX_PROXY 20 /* proxy channel for mux-slave */
#define SSH_CHANNEL_MAX_TYPE 21 #define SSH_CHANNEL_RDYNAMIC_OPEN 21 /* reverse SOCKS, parsing request */
#define SSH_CHANNEL_RDYNAMIC_FINISH 22 /* reverse SOCKS, finishing connect */
#define SSH_CHANNEL_MAX_TYPE 23
#define CHANNEL_CANCEL_PORT_STATIC -1 #define CHANNEL_CANCEL_PORT_STATIC -1
struct ssh; struct ssh;
struct Channel; struct Channel;
typedef struct Channel Channel; typedef struct Channel Channel;
struct fwd_perm_list;
typedef void channel_open_fn(int, int, void *); typedef void channel_open_fn(struct ssh *, int, int, void *);
typedef void channel_callback_fn(int, void *); typedef void channel_callback_fn(struct ssh *, int, void *);
typedef int channel_infilter_fn(struct Channel *, char *, int); typedef int channel_infilter_fn(struct ssh *, struct Channel *, char *, int);
typedef void channel_filter_cleanup_fn(int, void *); typedef void channel_filter_cleanup_fn(struct ssh *, int, void *);
typedef u_char *channel_outfilter_fn(struct Channel *, u_char **, u_int *); typedef u_char *channel_outfilter_fn(struct ssh *, struct Channel *,
u_char **, size_t *);
/* Channel success/failure callbacks */ /* Channel success/failure callbacks */
typedef void channel_confirm_cb(int, struct Channel *, void *); typedef void channel_confirm_cb(struct ssh *, int, struct Channel *, void *);
typedef void channel_confirm_abandon_cb(struct Channel *, void *); typedef void channel_confirm_abandon_cb(struct ssh *, struct Channel *, void *);
struct channel_confirm { struct channel_confirm {
TAILQ_ENTRY(channel_confirm) entry; TAILQ_ENTRY(channel_confirm) entry;
channel_confirm_cb *cb; channel_confirm_cb *cb;
@ -90,12 +94,14 @@ struct channel_connect {
}; };
/* Callbacks for mux channels back into client-specific code */ /* Callbacks for mux channels back into client-specific code */
typedef int mux_callback_fn(struct Channel *); typedef int mux_callback_fn(struct ssh *, struct Channel *);
struct Channel { struct Channel {
int type; /* channel type/state */ int type; /* channel type/state */
int self; /* my own channel identifier */ int self; /* my own channel identifier */
int remote_id; /* channel identifier for remote peer */ uint32_t remote_id; /* channel identifier for remote peer */
int have_remote_id; /* non-zero if remote_id is valid */
u_int istate; /* input from channel (state of receive half) */ u_int istate; /* input from channel (state of receive half) */
u_int ostate; /* output to channel (state of transmit half) */ u_int ostate; /* output to channel (state of transmit half) */
int flags; /* close sent/rcvd */ int flags; /* close sent/rcvd */
@ -116,11 +122,12 @@ struct Channel {
* to a matching pre-select handler. * to a matching pre-select handler.
* this way post-select handlers are not * this way post-select handlers are not
* accidentally called if a FD gets reused */ * accidentally called if a FD gets reused */
Buffer input; /* data read from socket, to be sent over struct sshbuf *input; /* data read from socket, to be sent over
* encrypted connection */ * encrypted connection */
Buffer output; /* data received over encrypted connection for struct sshbuf *output; /* data received over encrypted connection for
* send on socket */ * send on socket */
Buffer extended; struct sshbuf *extended;
char *path; char *path;
/* path for unix domain sockets, or host name for forwards */ /* path for unix domain sockets, or host name for forwards */
int listening_port; /* port being listened for forwards */ int listening_port; /* port being listened for forwards */
@ -156,6 +163,7 @@ struct Channel {
int datagram; int datagram;
/* non-blocking connect */ /* non-blocking connect */
/* XXX make this a pointer so the structure can be opaque */
struct channel_connect connect_ctx; struct channel_connect connect_ctx;
/* multiplexing protocol hook, called for each packet received */ /* multiplexing protocol hook, called for each packet received */
@ -195,44 +203,55 @@ struct Channel {
#define CHAN_EOF_RCVD 0x08 #define CHAN_EOF_RCVD 0x08
#define CHAN_LOCAL 0x10 #define CHAN_LOCAL 0x10
#define CHAN_RBUF 16*1024 /* Read buffer size */
#define CHAN_RBUF (16*1024)
/* Hard limit on number of channels */
#define CHANNELS_MAX_CHANNELS (16*1024)
/* check whether 'efd' is still in use */ /* check whether 'efd' is still in use */
#define CHANNEL_EFD_INPUT_ACTIVE(c) \ #define CHANNEL_EFD_INPUT_ACTIVE(c) \
(c->extended_usage == CHAN_EXTENDED_READ && \ (c->extended_usage == CHAN_EXTENDED_READ && \
(c->efd != -1 || \ (c->efd != -1 || \
buffer_len(&c->extended) > 0)) sshbuf_len(c->extended) > 0))
#define CHANNEL_EFD_OUTPUT_ACTIVE(c) \ #define CHANNEL_EFD_OUTPUT_ACTIVE(c) \
(c->extended_usage == CHAN_EXTENDED_WRITE && \ (c->extended_usage == CHAN_EXTENDED_WRITE && \
c->efd != -1 && (!(c->flags & (CHAN_EOF_RCVD|CHAN_CLOSE_RCVD)) || \ c->efd != -1 && (!(c->flags & (CHAN_EOF_RCVD|CHAN_CLOSE_RCVD)) || \
buffer_len(&c->extended) > 0)) sshbuf_len(c->extended) > 0))
/* Add channel management structures to SSH transport instance */
void channel_init_channels(struct ssh *ssh);
/* channel management */ /* channel management */
Channel *channel_by_id(int); Channel *channel_by_id(struct ssh *, int);
Channel *channel_by_remote_id(int); Channel *channel_by_remote_id(struct ssh *, u_int);
Channel *channel_lookup(int); Channel *channel_lookup(struct ssh *, int);
Channel *channel_new(char *, int, int, int, int, u_int, u_int, int, char *, int); Channel *channel_new(struct ssh *, char *, int, int, int, int,
void channel_set_fds(int, int, int, int, int, int, int, u_int); u_int, u_int, int, char *, int);
void channel_free(Channel *); void channel_set_fds(struct ssh *, int, int, int, int, int,
void channel_free_all(void); int, int, u_int);
void channel_stop_listening(void); void channel_free(struct ssh *, Channel *);
void channel_free_all(struct ssh *);
void channel_stop_listening(struct ssh *);
void channel_send_open(int); void channel_send_open(struct ssh *, int);
void channel_request_start(int, char *, int); void channel_request_start(struct ssh *, int, char *, int);
void channel_register_cleanup(int, channel_callback_fn *, int); void channel_register_cleanup(struct ssh *, int,
void channel_register_open_confirm(int, channel_open_fn *, void *); channel_callback_fn *, int);
void channel_register_filter(int, channel_infilter_fn *, void channel_register_open_confirm(struct ssh *, int,
channel_open_fn *, void *);
void channel_register_filter(struct ssh *, int, channel_infilter_fn *,
channel_outfilter_fn *, channel_filter_cleanup_fn *, void *); channel_outfilter_fn *, channel_filter_cleanup_fn *, void *);
void channel_register_status_confirm(int, channel_confirm_cb *, void channel_register_status_confirm(struct ssh *, int,
channel_confirm_abandon_cb *, void *); channel_confirm_cb *, channel_confirm_abandon_cb *, void *);
void channel_cancel_cleanup(int); void channel_cancel_cleanup(struct ssh *, int);
int channel_close_fd(int *); int channel_close_fd(struct ssh *, int *);
void channel_send_window_changes(void); void channel_send_window_changes(struct ssh *);
/* mux proxy support */ /* mux proxy support */
int channel_proxy_downstream(Channel *mc); int channel_proxy_downstream(struct ssh *, Channel *mc);
int channel_proxy_upstream(Channel *, int, u_int32_t, struct ssh *); int channel_proxy_upstream(Channel *, int, u_int32_t, struct ssh *);
/* protocol handler */ /* protocol handler */
@ -249,66 +268,72 @@ int channel_input_status_confirm(int, u_int32_t, struct ssh *);
/* file descriptor handling (read/write) */ /* file descriptor handling (read/write) */
void channel_prepare_select(fd_set **, fd_set **, int *, u_int*, void channel_prepare_select(struct ssh *, fd_set **, fd_set **, int *,
time_t*, int); u_int*, time_t*);
void channel_after_select(fd_set *, fd_set *); void channel_after_select(struct ssh *, fd_set *, fd_set *);
void channel_output_poll(void); void channel_output_poll(struct ssh *);
int channel_not_very_much_buffered_data(void); int channel_not_very_much_buffered_data(struct ssh *);
void channel_close_all(void); void channel_close_all(struct ssh *);
int channel_still_open(void); int channel_still_open(struct ssh *);
char *channel_open_message(void); char *channel_open_message(struct ssh *);
int channel_find_open(void); int channel_find_open(struct ssh *);
/* tcp forwarding */ /* tcp forwarding */
struct Forward; struct Forward;
struct ForwardOptions; struct ForwardOptions;
void channel_set_af(int af); void channel_set_af(struct ssh *, int af);
void channel_permit_all_opens(void); void channel_permit_all_opens(struct ssh *);
void channel_add_permitted_opens(char *, int); void channel_add_permitted_opens(struct ssh *, char *, int);
int channel_add_adm_permitted_opens(char *, int); int channel_add_adm_permitted_opens(struct ssh *, char *, int);
void channel_disable_adm_local_opens(void); void channel_copy_adm_permitted_opens(struct ssh *,
void channel_update_permitted_opens(int, int); const struct fwd_perm_list *);
void channel_clear_permitted_opens(void); void channel_disable_adm_local_opens(struct ssh *);
void channel_clear_adm_permitted_opens(void); void channel_update_permitted_opens(struct ssh *, int, int);
void channel_print_adm_permitted_opens(void); void channel_clear_permitted_opens(struct ssh *);
Channel *channel_connect_to_port(const char *, u_short, char *, char *, int *, void channel_clear_adm_permitted_opens(struct ssh *);
const char **); void channel_print_adm_permitted_opens(struct ssh *);
Channel *channel_connect_to_path(const char *, char *, char *); Channel *channel_connect_to_port(struct ssh *, const char *, u_short,
Channel *channel_connect_stdio_fwd(const char*, u_short, int, int); char *, char *, int *, const char **);
Channel *channel_connect_by_listen_address(const char *, u_short, Channel *channel_connect_to_path(struct ssh *, const char *, char *, char *);
Channel *channel_connect_stdio_fwd(struct ssh *, const char*,
u_short, int, int);
Channel *channel_connect_by_listen_address(struct ssh *, const char *,
u_short, char *, char *);
Channel *channel_connect_by_listen_path(struct ssh *, const char *,
char *, char *); char *, char *);
Channel *channel_connect_by_listen_path(const char *, char *, char *); int channel_request_remote_forwarding(struct ssh *, struct Forward *);
int channel_request_remote_forwarding(struct Forward *); int channel_setup_local_fwd_listener(struct ssh *, struct Forward *,
int channel_setup_local_fwd_listener(struct Forward *, struct ForwardOptions *); struct ForwardOptions *);
int channel_request_rforward_cancel(struct Forward *); int channel_request_rforward_cancel(struct ssh *, struct Forward *);
int channel_setup_remote_fwd_listener(struct Forward *, int *, struct ForwardOptions *); int channel_setup_remote_fwd_listener(struct ssh *, struct Forward *,
int channel_cancel_rport_listener(struct Forward *); int *, struct ForwardOptions *);
int channel_cancel_lport_listener(struct Forward *, int, struct ForwardOptions *); int channel_cancel_rport_listener(struct ssh *, struct Forward *);
int channel_cancel_lport_listener(struct ssh *, struct Forward *,
int, struct ForwardOptions *);
int permitopen_port(const char *); int permitopen_port(const char *);
/* x11 forwarding */ /* x11 forwarding */
void channel_set_x11_refuse_time(u_int); void channel_set_x11_refuse_time(struct ssh *, u_int);
int x11_connect_display(void); int x11_connect_display(struct ssh *);
int x11_create_display_inet(int, int, int, u_int *, int **); int x11_create_display_inet(struct ssh *, int, int, int, u_int *, int **);
void x11_request_forwarding_with_spoofing(int, const char *, const char *, void x11_request_forwarding_with_spoofing(struct ssh *, int,
const char *, int); const char *, const char *, const char *, int);
/* channel close */ /* channel close */
int chan_is_dead(Channel *, int); int chan_is_dead(struct ssh *, Channel *, int);
void chan_mark_dead(Channel *); void chan_mark_dead(struct ssh *, Channel *);
/* channel events */ /* channel events */
void chan_rcvd_oclose(Channel *); void chan_rcvd_oclose(struct ssh *, Channel *);
void chan_rcvd_eow(Channel *); /* SSH2-only */ void chan_rcvd_eow(struct ssh *, Channel *);
void chan_read_failed(Channel *); void chan_read_failed(struct ssh *, Channel *);
void chan_ibuf_empty(Channel *); void chan_ibuf_empty(struct ssh *, Channel *);
void chan_rcvd_ieof(struct ssh *, Channel *);
void chan_rcvd_ieof(Channel *); void chan_write_failed(struct ssh *, Channel *);
void chan_write_failed(Channel *); void chan_obuf_empty(struct ssh *, Channel *);
void chan_obuf_empty(Channel *);
#endif #endif

View File

@ -1,4 +1,4 @@
/* $OpenBSD: clientloop.c,v 1.301 2017/07/14 03:18:21 dtucker Exp $ */ /* $OpenBSD: clientloop.c,v 1.305 2017/09/19 04:24:22 djm Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -177,6 +177,7 @@ struct channel_reply_ctx {
}; };
/* Global request success/failure callbacks */ /* Global request success/failure callbacks */
/* XXX move to struct ssh? */
struct global_confirm { struct global_confirm {
TAILQ_ENTRY(global_confirm) entry; TAILQ_ENTRY(global_confirm) entry;
global_confirm_cb *cb; global_confirm_cb *cb;
@ -244,13 +245,13 @@ get_current_time(void)
* control master process, or if there is no ControlPersist timeout. * control master process, or if there is no ControlPersist timeout.
*/ */
static void static void
set_control_persist_exit_time(void) set_control_persist_exit_time(struct ssh *ssh)
{ {
if (muxserver_sock == -1 || !options.control_persist if (muxserver_sock == -1 || !options.control_persist
|| options.control_persist_timeout == 0) { || options.control_persist_timeout == 0) {
/* not using a ControlPersist timeout */ /* not using a ControlPersist timeout */
control_persist_exit_time = 0; control_persist_exit_time = 0;
} else if (channel_still_open()) { } else if (channel_still_open(ssh)) {
/* some client connections are still open */ /* some client connections are still open */
if (control_persist_exit_time > 0) if (control_persist_exit_time > 0)
debug2("%s: cancel scheduled exit", __func__); debug2("%s: cancel scheduled exit", __func__);
@ -288,8 +289,9 @@ client_x11_display_valid(const char *display)
#define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1" #define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1"
#define X11_TIMEOUT_SLACK 60 #define X11_TIMEOUT_SLACK 60
int int
client_x11_get_proto(const char *display, const char *xauth_path, client_x11_get_proto(struct ssh *ssh, const char *display,
u_int trusted, u_int timeout, char **_proto, char **_data) const char *xauth_path, u_int trusted, u_int timeout,
char **_proto, char **_data)
{ {
char cmd[1024], line[512], xdisplay[512]; char cmd[1024], line[512], xdisplay[512];
char xauthfile[PATH_MAX], xauthdir[PATH_MAX]; char xauthfile[PATH_MAX], xauthdir[PATH_MAX];
@ -373,7 +375,8 @@ client_x11_get_proto(const char *display, const char *xauth_path,
x11_refuse_time = UINT_MAX; x11_refuse_time = UINT_MAX;
else else
x11_refuse_time = now + timeout; x11_refuse_time = now + timeout;
channel_set_x11_refuse_time(x11_refuse_time); channel_set_x11_refuse_time(ssh,
x11_refuse_time);
} }
if (system(cmd) == 0) if (system(cmd) == 0)
generated = 1; generated = 1;
@ -446,7 +449,7 @@ client_x11_get_proto(const char *display, const char *xauth_path,
*/ */
static void static void
client_check_window_change(void) client_check_window_change(struct ssh *ssh)
{ {
if (!received_window_change_signal) if (!received_window_change_signal)
return; return;
@ -455,7 +458,7 @@ client_check_window_change(void)
debug2("%s: changed", __func__); debug2("%s: changed", __func__);
channel_send_window_changes(); channel_send_window_changes(ssh);
} }
static int static int
@ -466,7 +469,7 @@ client_global_request_reply(int type, u_int32_t seq, struct ssh *ssh)
if ((gc = TAILQ_FIRST(&global_confirms)) == NULL) if ((gc = TAILQ_FIRST(&global_confirms)) == NULL)
return 0; return 0;
if (gc->cb != NULL) if (gc->cb != NULL)
gc->cb(type, seq, gc->ctx); gc->cb(ssh, type, seq, gc->ctx);
if (--gc->ref_count <= 0) { if (--gc->ref_count <= 0) {
TAILQ_REMOVE(&global_confirms, gc, entry); TAILQ_REMOVE(&global_confirms, gc, entry);
explicit_bzero(gc, sizeof(*gc)); explicit_bzero(gc, sizeof(*gc));
@ -497,7 +500,8 @@ server_alive_check(void)
* one of the file descriptors). * one of the file descriptors).
*/ */
static void static void
client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, client_wait_until_can_do_something(struct ssh *ssh,
fd_set **readsetp, fd_set **writesetp,
int *maxfdp, u_int *nallocp, int rekeying) int *maxfdp, u_int *nallocp, int rekeying)
{ {
struct timeval tv, *tvp; struct timeval tv, *tvp;
@ -506,11 +510,11 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
int ret; int ret;
/* Add any selections by the channel mechanism. */ /* Add any selections by the channel mechanism. */
channel_prepare_select(readsetp, writesetp, maxfdp, nallocp, channel_prepare_select(active_state, readsetp, writesetp, maxfdp,
&minwait_secs, rekeying); nallocp, &minwait_secs);
/* channel_prepare_select could have closed the last channel */ /* channel_prepare_select could have closed the last channel */
if (session_closed && !channel_still_open() && if (session_closed && !channel_still_open(ssh) &&
!packet_have_data_to_write()) { !packet_have_data_to_write()) {
/* clear mask since we did not call select() */ /* clear mask since we did not call select() */
memset(*readsetp, 0, *nallocp); memset(*readsetp, 0, *nallocp);
@ -537,7 +541,7 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp,
} }
if (options.rekey_interval > 0 && !rekeying) if (options.rekey_interval > 0 && !rekeying)
timeout_secs = MINIMUM(timeout_secs, packet_get_rekey_timeout()); timeout_secs = MINIMUM(timeout_secs, packet_get_rekey_timeout());
set_control_persist_exit_time(); set_control_persist_exit_time(ssh);
if (control_persist_exit_time > 0) { if (control_persist_exit_time > 0) {
timeout_secs = MINIMUM(timeout_secs, timeout_secs = MINIMUM(timeout_secs,
control_persist_exit_time - now); control_persist_exit_time - now);
@ -596,13 +600,9 @@ client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr)
leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
/* sshbuf_reset(bin);
* Free (and clear) the buffer to reduce the amount of data that gets sshbuf_reset(bout);
* written to swap. sshbuf_reset(berr);
*/
buffer_free(bin);
buffer_free(bout);
buffer_free(berr);
/* Send the suspend signal to the program itself. */ /* Send the suspend signal to the program itself. */
kill(getpid(), SIGTSTP); kill(getpid(), SIGTSTP);
@ -610,11 +610,6 @@ client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr)
/* Reset window sizes in case they have changed */ /* Reset window sizes in case they have changed */
received_window_change_signal = 1; received_window_change_signal = 1;
/* OK, we have been continued by the user. Reinitialize buffers. */
buffer_init(bin);
buffer_init(bout);
buffer_init(berr);
enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE); enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
} }
@ -668,7 +663,7 @@ client_process_net_input(fd_set *readset)
} }
static void static void
client_status_confirm(int type, Channel *c, void *ctx) client_status_confirm(struct ssh *ssh, int type, Channel *c, void *ctx)
{ {
struct channel_reply_ctx *cr = (struct channel_reply_ctx *)ctx; struct channel_reply_ctx *cr = (struct channel_reply_ctx *)ctx;
char errmsg[256]; char errmsg[256];
@ -707,8 +702,7 @@ client_status_confirm(int type, Channel *c, void *ctx)
* their stderr. * their stderr.
*/ */
if (tochan) { if (tochan) {
buffer_append(&c->extended, errmsg, buffer_append(c->extended, errmsg, strlen(errmsg));
strlen(errmsg));
} else } else
error("%s", errmsg); error("%s", errmsg);
if (cr->action == CONFIRM_TTY) { if (cr->action == CONFIRM_TTY) {
@ -719,23 +713,23 @@ client_status_confirm(int type, Channel *c, void *ctx)
if (c->self == session_ident) if (c->self == session_ident)
leave_raw_mode(0); leave_raw_mode(0);
else else
mux_tty_alloc_failed(c); mux_tty_alloc_failed(ssh, c);
} else if (cr->action == CONFIRM_CLOSE) { } else if (cr->action == CONFIRM_CLOSE) {
chan_read_failed(c); chan_read_failed(ssh, c);
chan_write_failed(c); chan_write_failed(ssh, c);
} }
} }
free(cr); free(cr);
} }
static void static void
client_abandon_status_confirm(Channel *c, void *ctx) client_abandon_status_confirm(struct ssh *ssh, Channel *c, void *ctx)
{ {
free(ctx); free(ctx);
} }
void void
client_expect_confirm(int id, const char *request, client_expect_confirm(struct ssh *ssh, int id, const char *request,
enum confirm_action action) enum confirm_action action)
{ {
struct channel_reply_ctx *cr = xcalloc(1, sizeof(*cr)); struct channel_reply_ctx *cr = xcalloc(1, sizeof(*cr));
@ -743,7 +737,7 @@ client_expect_confirm(int id, const char *request,
cr->request_type = request; cr->request_type = request;
cr->action = action; cr->action = action;
channel_register_status_confirm(id, client_status_confirm, channel_register_status_confirm(ssh, id, client_status_confirm,
client_abandon_status_confirm, cr); client_abandon_status_confirm, cr);
} }
@ -769,7 +763,7 @@ client_register_global_confirm(global_confirm_cb *cb, void *ctx)
} }
static void static void
process_cmdline(void) process_cmdline(struct ssh *ssh)
{ {
void (*handler)(int); void (*handler)(int);
char *s, *cmd; char *s, *cmd;
@ -843,12 +837,12 @@ process_cmdline(void)
goto out; goto out;
} }
if (remote) if (remote)
ok = channel_request_rforward_cancel(&fwd) == 0; ok = channel_request_rforward_cancel(ssh, &fwd) == 0;
else if (dynamic) else if (dynamic)
ok = channel_cancel_lport_listener(&fwd, ok = channel_cancel_lport_listener(ssh, &fwd,
0, &options.fwd_opts) > 0; 0, &options.fwd_opts) > 0;
else else
ok = channel_cancel_lport_listener(&fwd, ok = channel_cancel_lport_listener(ssh, &fwd,
CHANNEL_CANCEL_PORT_STATIC, CHANNEL_CANCEL_PORT_STATIC,
&options.fwd_opts) > 0; &options.fwd_opts) > 0;
if (!ok) { if (!ok) {
@ -862,13 +856,13 @@ process_cmdline(void)
goto out; goto out;
} }
if (local || dynamic) { if (local || dynamic) {
if (!channel_setup_local_fwd_listener(&fwd, if (!channel_setup_local_fwd_listener(ssh, &fwd,
&options.fwd_opts)) { &options.fwd_opts)) {
logit("Port forwarding failed."); logit("Port forwarding failed.");
goto out; goto out;
} }
} else { } else {
if (channel_request_remote_forwarding(&fwd) < 0) { if (channel_request_remote_forwarding(ssh, &fwd) < 0) {
logit("Port forwarding failed."); logit("Port forwarding failed.");
goto out; goto out;
} }
@ -945,7 +939,8 @@ print_escape_help(Buffer *b, int escape_char, int mux_client, int using_stderr)
* Process the characters one by one. * Process the characters one by one.
*/ */
static int static int
process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, process_escapes(struct ssh *ssh, Channel *c,
Buffer *bin, Buffer *bout, Buffer *berr,
char *buf, int len) char *buf, int len)
{ {
char string[1024]; char string[1024];
@ -981,13 +976,15 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
buffer_append(berr, string, strlen(string)); buffer_append(berr, string, strlen(string));
if (c && c->ctl_chan != -1) { if (c && c->ctl_chan != -1) {
chan_read_failed(c); chan_read_failed(ssh, c);
chan_write_failed(c); chan_write_failed(ssh, c);
if (c->detach_user) if (c->detach_user) {
c->detach_user(c->self, NULL); c->detach_user(ssh,
c->self, NULL);
}
c->type = SSH_CHANNEL_ABANDONED; c->type = SSH_CHANNEL_ABANDONED;
buffer_clear(&c->input); buffer_clear(c->input);
chan_ibuf_empty(c); chan_ibuf_empty(ssh, c);
return 0; return 0;
} else } else
quit_pending = 1; quit_pending = 1;
@ -1025,7 +1022,7 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
snprintf(string, sizeof string, snprintf(string, sizeof string,
"%cB\r\n", efc->escape_char); "%cB\r\n", efc->escape_char);
buffer_append(berr, string, strlen(string)); buffer_append(berr, string, strlen(string));
channel_request_start(c->self, "break", 0); channel_request_start(ssh, c->self, "break", 0);
packet_put_int(1000); packet_put_int(1000);
packet_send(); packet_send();
continue; continue;
@ -1080,7 +1077,7 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
options.request_tty == REQUEST_TTY_FORCE); options.request_tty == REQUEST_TTY_FORCE);
/* Stop listening for new connections. */ /* Stop listening for new connections. */
channel_stop_listening(); channel_stop_listening(ssh);
snprintf(string, sizeof string, snprintf(string, sizeof string,
"%c& [backgrounded]\n", efc->escape_char); "%c& [backgrounded]\n", efc->escape_char);
@ -1111,7 +1108,7 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
snprintf(string, sizeof string, "%c#\r\n", snprintf(string, sizeof string, "%c#\r\n",
efc->escape_char); efc->escape_char);
buffer_append(berr, string, strlen(string)); buffer_append(berr, string, strlen(string));
s = channel_open_message(); s = channel_open_message(ssh);
buffer_append(berr, s, strlen(s)); buffer_append(berr, s, strlen(s));
free(s); free(s);
continue; continue;
@ -1119,7 +1116,7 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
case 'C': case 'C':
if (c && c->ctl_chan != -1) if (c && c->ctl_chan != -1)
goto noescape; goto noescape;
process_cmdline(); process_cmdline(ssh);
continue; continue;
default: default:
@ -1190,25 +1187,25 @@ client_new_escape_filter_ctx(int escape_char)
/* Free the escape filter context on channel free */ /* Free the escape filter context on channel free */
void void
client_filter_cleanup(int cid, void *ctx) client_filter_cleanup(struct ssh *ssh, int cid, void *ctx)
{ {
free(ctx); free(ctx);
} }
int int
client_simple_escape_filter(Channel *c, char *buf, int len) client_simple_escape_filter(struct ssh *ssh, Channel *c, char *buf, int len)
{ {
if (c->extended_usage != CHAN_EXTENDED_WRITE) if (c->extended_usage != CHAN_EXTENDED_WRITE)
return 0; return 0;
return process_escapes(c, &c->input, &c->output, &c->extended, return process_escapes(ssh, c, c->input, c->output, c->extended,
buf, len); buf, len);
} }
static void static void
client_channel_closed(int id, void *arg) client_channel_closed(struct ssh *ssh, int id, void *arg)
{ {
channel_cancel_cleanup(id); channel_cancel_cleanup(ssh, id);
session_closed = 1; session_closed = 1;
leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
} }
@ -1219,9 +1216,9 @@ client_channel_closed(int id, void *arg)
* remote host. If escape_char != SSH_ESCAPECHAR_NONE, it is the character * remote host. If escape_char != SSH_ESCAPECHAR_NONE, it is the character
* used as an escape character for terminating or suspending the session. * used as an escape character for terminating or suspending the session.
*/ */
int int
client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) client_loop(struct ssh *ssh, int have_pty, int escape_char_arg,
int ssh2_chan_id)
{ {
fd_set *readset = NULL, *writeset = NULL; fd_set *readset = NULL, *writeset = NULL;
double start_time, total_time; double start_time, total_time;
@ -1299,13 +1296,13 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
session_ident = ssh2_chan_id; session_ident = ssh2_chan_id;
if (session_ident != -1) { if (session_ident != -1) {
if (escape_char_arg != SSH_ESCAPECHAR_NONE) { if (escape_char_arg != SSH_ESCAPECHAR_NONE) {
channel_register_filter(session_ident, channel_register_filter(ssh, session_ident,
client_simple_escape_filter, NULL, client_simple_escape_filter, NULL,
client_filter_cleanup, client_filter_cleanup,
client_new_escape_filter_ctx( client_new_escape_filter_ctx(
escape_char_arg)); escape_char_arg));
} }
channel_register_cleanup(session_ident, channel_register_cleanup(ssh, session_ident,
client_channel_closed, 0); client_channel_closed, 0);
} }
@ -1315,15 +1312,15 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
/* Process buffered packets sent by the server. */ /* Process buffered packets sent by the server. */
client_process_buffered_input_packets(); client_process_buffered_input_packets();
if (session_closed && !channel_still_open()) if (session_closed && !channel_still_open(ssh))
break; break;
if (ssh_packet_is_rekeying(active_state)) { if (ssh_packet_is_rekeying(ssh)) {
debug("rekeying in progress"); debug("rekeying in progress");
} else if (need_rekeying) { } else if (need_rekeying) {
/* manual rekey request */ /* manual rekey request */
debug("need rekeying"); debug("need rekeying");
if ((r = kex_start_rekex(active_state)) != 0) if ((r = kex_start_rekex(ssh)) != 0)
fatal("%s: kex_start_rekex: %s", __func__, fatal("%s: kex_start_rekex: %s", __func__,
ssh_err(r)); ssh_err(r));
need_rekeying = 0; need_rekeying = 0;
@ -1333,13 +1330,13 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
* enqueue them for sending to the server. * enqueue them for sending to the server.
*/ */
if (packet_not_very_much_data_to_write()) if (packet_not_very_much_data_to_write())
channel_output_poll(); channel_output_poll(ssh);
/* /*
* Check if the window size has changed, and buffer a * Check if the window size has changed, and buffer a
* message about it to the server if so. * message about it to the server if so.
*/ */
client_check_window_change(); client_check_window_change(ssh);
if (quit_pending) if (quit_pending)
break; break;
@ -1349,15 +1346,15 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
* available on one of the descriptors). * available on one of the descriptors).
*/ */
max_fd2 = max_fd; max_fd2 = max_fd;
client_wait_until_can_do_something(&readset, &writeset, client_wait_until_can_do_something(ssh, &readset, &writeset,
&max_fd2, &nalloc, ssh_packet_is_rekeying(active_state)); &max_fd2, &nalloc, ssh_packet_is_rekeying(ssh));
if (quit_pending) if (quit_pending)
break; break;
/* Do channel operations unless rekeying in progress. */ /* Do channel operations unless rekeying in progress. */
if (!ssh_packet_is_rekeying(active_state)) if (!ssh_packet_is_rekeying(ssh))
channel_after_select(readset, writeset); channel_after_select(ssh, readset, writeset);
/* Buffer input from the connection. */ /* Buffer input from the connection. */
client_process_net_input(readset); client_process_net_input(readset);
@ -1399,7 +1396,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
packet_send(); packet_send();
packet_write_wait(); packet_write_wait();
channel_free_all(); channel_free_all(ssh);
if (have_pty) if (have_pty)
leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
@ -1467,8 +1464,8 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
/*********/ /*********/
static Channel * static Channel *
client_request_forwarded_tcpip(const char *request_type, int rchan, client_request_forwarded_tcpip(struct ssh *ssh, const char *request_type,
u_int rwindow, u_int rmaxpack) int rchan, u_int rwindow, u_int rmaxpack)
{ {
Channel *c = NULL; Channel *c = NULL;
struct sshbuf *b = NULL; struct sshbuf *b = NULL;
@ -1486,7 +1483,7 @@ client_request_forwarded_tcpip(const char *request_type, int rchan,
debug("%s: listen %s port %d, originator %s port %d", __func__, debug("%s: listen %s port %d, originator %s port %d", __func__,
listen_address, listen_port, originator_address, originator_port); listen_address, listen_port, originator_address, originator_port);
c = channel_connect_by_listen_address(listen_address, listen_port, c = channel_connect_by_listen_address(ssh, listen_address, listen_port,
"forwarded-tcpip", originator_address); "forwarded-tcpip", originator_address);
if (c != NULL && c->type == SSH_CHANNEL_MUX_CLIENT) { if (c != NULL && c->type == SSH_CHANNEL_MUX_CLIENT) {
@ -1505,7 +1502,7 @@ client_request_forwarded_tcpip(const char *request_type, int rchan,
(r = sshbuf_put_u32(b, listen_port)) != 0 || (r = sshbuf_put_u32(b, listen_port)) != 0 ||
(r = sshbuf_put_cstring(b, originator_address)) != 0 || (r = sshbuf_put_cstring(b, originator_address)) != 0 ||
(r = sshbuf_put_u32(b, originator_port)) != 0 || (r = sshbuf_put_u32(b, originator_port)) != 0 ||
(r = sshbuf_put_stringb(&c->output, b)) != 0) { (r = sshbuf_put_stringb(c->output, b)) != 0) {
error("%s: compose for muxclient %s", __func__, error("%s: compose for muxclient %s", __func__,
ssh_err(r)); ssh_err(r));
goto out; goto out;
@ -1520,7 +1517,8 @@ client_request_forwarded_tcpip(const char *request_type, int rchan,
} }
static Channel * static Channel *
client_request_forwarded_streamlocal(const char *request_type, int rchan) client_request_forwarded_streamlocal(struct ssh *ssh,
const char *request_type, int rchan)
{ {
Channel *c = NULL; Channel *c = NULL;
char *listen_path; char *listen_path;
@ -1534,14 +1532,14 @@ client_request_forwarded_streamlocal(const char *request_type, int rchan)
debug("%s: %s", __func__, listen_path); debug("%s: %s", __func__, listen_path);
c = channel_connect_by_listen_path(listen_path, c = channel_connect_by_listen_path(ssh, listen_path,
"forwarded-streamlocal@openssh.com", "forwarded-streamlocal"); "forwarded-streamlocal@openssh.com", "forwarded-streamlocal");
free(listen_path); free(listen_path);
return c; return c;
} }
static Channel * static Channel *
client_request_x11(const char *request_type, int rchan) client_request_x11(struct ssh *ssh, const char *request_type, int rchan)
{ {
Channel *c = NULL; Channel *c = NULL;
char *originator; char *originator;
@ -1571,10 +1569,10 @@ client_request_x11(const char *request_type, int rchan)
debug("client_request_x11: request from %s %d", originator, debug("client_request_x11: request from %s %d", originator,
originator_port); originator_port);
free(originator); free(originator);
sock = x11_connect_display(); sock = x11_connect_display(ssh);
if (sock < 0) if (sock < 0)
return NULL; return NULL;
c = channel_new("x11", c = channel_new(ssh, "x11",
SSH_CHANNEL_X11_OPEN, sock, sock, -1, SSH_CHANNEL_X11_OPEN, sock, sock, -1,
CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, "x11", 1); CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, "x11", 1);
c->force_drain = 1; c->force_drain = 1;
@ -1582,7 +1580,7 @@ client_request_x11(const char *request_type, int rchan)
} }
static Channel * static Channel *
client_request_agent(const char *request_type, int rchan) client_request_agent(struct ssh *ssh, const char *request_type, int rchan)
{ {
Channel *c = NULL; Channel *c = NULL;
int r, sock; int r, sock;
@ -1599,7 +1597,7 @@ client_request_agent(const char *request_type, int rchan)
__func__, ssh_err(r)); __func__, ssh_err(r));
return NULL; return NULL;
} }
c = channel_new("authentication agent connection", c = channel_new(ssh, "authentication agent connection",
SSH_CHANNEL_OPEN, sock, sock, -1, SSH_CHANNEL_OPEN, sock, sock, -1,
CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0,
"authentication agent connection", 1); "authentication agent connection", 1);
@ -1608,7 +1606,8 @@ client_request_agent(const char *request_type, int rchan)
} }
int int
client_request_tun_fwd(int tun_mode, int local_tun, int remote_tun) client_request_tun_fwd(struct ssh *ssh, int tun_mode,
int local_tun, int remote_tun)
{ {
Channel *c; Channel *c;
int fd; int fd;
@ -1624,13 +1623,13 @@ client_request_tun_fwd(int tun_mode, int local_tun, int remote_tun)
return -1; return -1;
} }
c = channel_new("tun", SSH_CHANNEL_OPENING, fd, fd, -1, c = channel_new(ssh, "tun", SSH_CHANNEL_OPENING, fd, fd, -1,
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1);
c->datagram = 1; c->datagram = 1;
#if defined(SSH_TUN_FILTER) #if defined(SSH_TUN_FILTER)
if (options.tun_open == SSH_TUNMODE_POINTOPOINT) if (options.tun_open == SSH_TUNMODE_POINTOPOINT)
channel_register_filter(c->self, sys_tun_infilter, channel_register_filter(ssh, c->self, sys_tun_infilter,
sys_tun_outfilter, NULL, NULL); sys_tun_outfilter, NULL, NULL);
#endif #endif
@ -1664,20 +1663,21 @@ client_input_channel_open(int type, u_int32_t seq, struct ssh *ssh)
ctype, rchan, rwindow, rmaxpack); ctype, rchan, rwindow, rmaxpack);
if (strcmp(ctype, "forwarded-tcpip") == 0) { if (strcmp(ctype, "forwarded-tcpip") == 0) {
c = client_request_forwarded_tcpip(ctype, rchan, rwindow, c = client_request_forwarded_tcpip(ssh, ctype, rchan, rwindow,
rmaxpack); rmaxpack);
} else if (strcmp(ctype, "forwarded-streamlocal@openssh.com") == 0) { } else if (strcmp(ctype, "forwarded-streamlocal@openssh.com") == 0) {
c = client_request_forwarded_streamlocal(ctype, rchan); c = client_request_forwarded_streamlocal(ssh, ctype, rchan);
} else if (strcmp(ctype, "x11") == 0) { } else if (strcmp(ctype, "x11") == 0) {
c = client_request_x11(ctype, rchan); c = client_request_x11(ssh, ctype, rchan);
} else if (strcmp(ctype, "auth-agent@openssh.com") == 0) { } else if (strcmp(ctype, "auth-agent@openssh.com") == 0) {
c = client_request_agent(ctype, rchan); c = client_request_agent(ssh, ctype, rchan);
} }
if (c != NULL && c->type == SSH_CHANNEL_MUX_CLIENT) { if (c != NULL && c->type == SSH_CHANNEL_MUX_CLIENT) {
debug3("proxied to downstream: %s", ctype); debug3("proxied to downstream: %s", ctype);
} else if (c != NULL) { } else if (c != NULL) {
debug("confirm %s", ctype); debug("confirm %s", ctype);
c->remote_id = rchan; c->remote_id = rchan;
c->have_remote_id = 1;
c->remote_window = rwindow; c->remote_window = rwindow;
c->remote_maxpacket = rmaxpack; c->remote_maxpacket = rmaxpack;
if (c->type != SSH_CHANNEL_CONNECTING) { if (c->type != SSH_CHANNEL_CONNECTING) {
@ -1711,7 +1711,7 @@ client_input_channel_req(int type, u_int32_t seq, struct ssh *ssh)
char *rtype; char *rtype;
id = packet_get_int(); id = packet_get_int();
c = channel_lookup(id); c = channel_lookup(ssh, id);
if (channel_proxy_upstream(c, type, seq, ssh)) if (channel_proxy_upstream(c, type, seq, ssh))
return 0; return 0;
rtype = packet_get_string(NULL); rtype = packet_get_string(NULL);
@ -1727,11 +1727,11 @@ client_input_channel_req(int type, u_int32_t seq, struct ssh *ssh)
"unknown channel", id); "unknown channel", id);
} else if (strcmp(rtype, "eow@openssh.com") == 0) { } else if (strcmp(rtype, "eow@openssh.com") == 0) {
packet_check_eom(); packet_check_eom();
chan_rcvd_eow(c); chan_rcvd_eow(ssh, c);
} else if (strcmp(rtype, "exit-status") == 0) { } else if (strcmp(rtype, "exit-status") == 0) {
exitval = packet_get_int(); exitval = packet_get_int();
if (c->ctl_chan != -1) { if (c->ctl_chan != -1) {
mux_exit_message(c, exitval); mux_exit_message(ssh, c, exitval);
success = 1; success = 1;
} else if (id == session_ident) { } else if (id == session_ident) {
/* Record exit value of local session */ /* Record exit value of local session */
@ -1745,6 +1745,9 @@ client_input_channel_req(int type, u_int32_t seq, struct ssh *ssh)
packet_check_eom(); packet_check_eom();
} }
if (reply && c != NULL && !(c->flags & CHAN_CLOSE_SENT)) { if (reply && c != NULL && !(c->flags & CHAN_CLOSE_SENT)) {
if (!c->have_remote_id)
fatal("%s: channel %d: no remote_id",
__func__, c->self);
packet_start(success ? packet_start(success ?
SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE); SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE);
packet_put_int(c->remote_id); packet_put_int(c->remote_id);
@ -1899,9 +1902,9 @@ update_known_hosts(struct hostkeys_update_ctx *ctx)
} }
static void static void
client_global_hostkeys_private_confirm(int type, u_int32_t seq, void *_ctx) client_global_hostkeys_private_confirm(struct ssh *ssh, int type,
u_int32_t seq, void *_ctx)
{ {
struct ssh *ssh = active_state; /* XXX */
struct hostkeys_update_ctx *ctx = (struct hostkeys_update_ctx *)_ctx; struct hostkeys_update_ctx *ctx = (struct hostkeys_update_ctx *)_ctx;
size_t i, ndone; size_t i, ndone;
struct sshbuf *signdata; struct sshbuf *signdata;
@ -2165,7 +2168,7 @@ client_input_global_request(int type, u_int32_t seq, struct ssh *ssh)
} }
void void
client_session2_setup(int id, int want_tty, int want_subsystem, client_session2_setup(struct ssh *ssh, int id, int want_tty, int want_subsystem,
const char *term, struct termios *tiop, int in_fd, Buffer *cmd, char **env) const char *term, struct termios *tiop, int in_fd, Buffer *cmd, char **env)
{ {
int len; int len;
@ -2173,8 +2176,8 @@ client_session2_setup(int id, int want_tty, int want_subsystem,
debug2("%s: id %d", __func__, id); debug2("%s: id %d", __func__, id);
if ((c = channel_lookup(id)) == NULL) if ((c = channel_lookup(ssh, id)) == NULL)
fatal("client_session2_setup: channel %d: unknown channel", id); fatal("%s: channel %d: unknown channel", __func__, id);
packet_set_interactive(want_tty, packet_set_interactive(want_tty,
options.ip_qos_interactive, options.ip_qos_bulk); options.ip_qos_interactive, options.ip_qos_bulk);
@ -2186,8 +2189,8 @@ client_session2_setup(int id, int want_tty, int want_subsystem,
if (ioctl(in_fd, TIOCGWINSZ, &ws) < 0) if (ioctl(in_fd, TIOCGWINSZ, &ws) < 0)
memset(&ws, 0, sizeof(ws)); memset(&ws, 0, sizeof(ws));
channel_request_start(id, "pty-req", 1); channel_request_start(ssh, id, "pty-req", 1);
client_expect_confirm(id, "PTY allocation", CONFIRM_TTY); client_expect_confirm(ssh, id, "PTY allocation", CONFIRM_TTY);
packet_put_cstring(term != NULL ? term : ""); packet_put_cstring(term != NULL ? term : "");
packet_put_int((u_int)ws.ws_col); packet_put_int((u_int)ws.ws_col);
packet_put_int((u_int)ws.ws_row); packet_put_int((u_int)ws.ws_row);
@ -2230,7 +2233,7 @@ client_session2_setup(int id, int want_tty, int want_subsystem,
} }
debug("Sending env %s = %s", name, val); debug("Sending env %s = %s", name, val);
channel_request_start(id, "env", 0); channel_request_start(ssh, id, "env", 0);
packet_put_cstring(name); packet_put_cstring(name);
packet_put_cstring(val); packet_put_cstring(val);
packet_send(); packet_send();
@ -2245,19 +2248,20 @@ client_session2_setup(int id, int want_tty, int want_subsystem,
if (want_subsystem) { if (want_subsystem) {
debug("Sending subsystem: %.*s", debug("Sending subsystem: %.*s",
len, (u_char*)buffer_ptr(cmd)); len, (u_char*)buffer_ptr(cmd));
channel_request_start(id, "subsystem", 1); channel_request_start(ssh, id, "subsystem", 1);
client_expect_confirm(id, "subsystem", CONFIRM_CLOSE); client_expect_confirm(ssh, id, "subsystem",
CONFIRM_CLOSE);
} else { } else {
debug("Sending command: %.*s", debug("Sending command: %.*s",
len, (u_char*)buffer_ptr(cmd)); len, (u_char*)buffer_ptr(cmd));
channel_request_start(id, "exec", 1); channel_request_start(ssh, id, "exec", 1);
client_expect_confirm(id, "exec", CONFIRM_CLOSE); client_expect_confirm(ssh, id, "exec", CONFIRM_CLOSE);
} }
packet_put_string(buffer_ptr(cmd), buffer_len(cmd)); packet_put_string(buffer_ptr(cmd), buffer_len(cmd));
packet_send(); packet_send();
} else { } else {
channel_request_start(id, "shell", 1); channel_request_start(ssh, id, "shell", 1);
client_expect_confirm(id, "shell", CONFIRM_CLOSE); client_expect_confirm(ssh, id, "shell", CONFIRM_CLOSE);
packet_send(); packet_send();
} }
} }

View File

@ -1,4 +1,4 @@
/* $OpenBSD: clientloop.h,v 1.33 2016/09/30 09:19:13 markus Exp $ */ /* $OpenBSD: clientloop.h,v 1.34 2017/09/12 06:32:07 djm Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -37,28 +37,31 @@
#include <termios.h> #include <termios.h>
struct ssh;
/* Client side main loop for the interactive session. */ /* Client side main loop for the interactive session. */
int client_loop(int, int, int); int client_loop(struct ssh *, int, int, int);
int client_x11_get_proto(const char *, const char *, u_int, u_int, int client_x11_get_proto(struct ssh *, const char *, const char *,
char **, char **); u_int, u_int, char **, char **);
void client_global_request_reply_fwd(int, u_int32_t, void *); void client_global_request_reply_fwd(int, u_int32_t, void *);
void client_session2_setup(int, int, int, const char *, struct termios *, void client_session2_setup(struct ssh *, int, int, int,
int, Buffer *, char **); const char *, struct termios *, int, Buffer *, char **);
int client_request_tun_fwd(int, int, int); int client_request_tun_fwd(struct ssh *, int, int, int);
void client_stop_mux(void); void client_stop_mux(void);
/* Escape filter for protocol 2 sessions */ /* Escape filter for protocol 2 sessions */
void *client_new_escape_filter_ctx(int); void *client_new_escape_filter_ctx(int);
void client_filter_cleanup(int, void *); void client_filter_cleanup(struct ssh *, int, void *);
int client_simple_escape_filter(Channel *, char *, int); int client_simple_escape_filter(struct ssh *, Channel *, char *, int);
/* Global request confirmation callbacks */ /* Global request confirmation callbacks */
typedef void global_confirm_cb(int, u_int32_t seq, void *); typedef void global_confirm_cb(struct ssh *, int, u_int32_t, void *);
void client_register_global_confirm(global_confirm_cb *, void *); void client_register_global_confirm(global_confirm_cb *, void *);
/* Channel request confirmation callbacks */ /* Channel request confirmation callbacks */
enum confirm_action { CONFIRM_WARN = 0, CONFIRM_CLOSE, CONFIRM_TTY }; enum confirm_action { CONFIRM_WARN = 0, CONFIRM_CLOSE, CONFIRM_TTY };
void client_expect_confirm(int, const char *, enum confirm_action); void client_expect_confirm(struct ssh *, int, const char *,
enum confirm_action);
/* Multiplexing protocol version */ /* Multiplexing protocol version */
#define SSHMUX_VER 4 #define SSHMUX_VER 4
@ -73,8 +76,8 @@ void client_expect_confirm(int, const char *, enum confirm_action);
#define SSHMUX_COMMAND_CANCEL_FWD 7 /* Cancel forwarding(s) */ #define SSHMUX_COMMAND_CANCEL_FWD 7 /* Cancel forwarding(s) */
#define SSHMUX_COMMAND_PROXY 8 /* Open new connection */ #define SSHMUX_COMMAND_PROXY 8 /* Open new connection */
void muxserver_listen(void); void muxserver_listen(struct ssh *);
int muxclient(const char *); int muxclient(const char *);
void mux_exit_message(Channel *, int); void mux_exit_message(struct ssh *, Channel *, int);
void mux_tty_alloc_failed(Channel *); void mux_tty_alloc_failed(struct ssh *ssh, Channel *);

View File

@ -163,8 +163,8 @@ if test "$GCC" = "yes" || test "$GCC" = "egcs"; then
OSSH_CHECK_CFLAG_COMPILE([-Wpointer-sign], [-Wno-pointer-sign]) OSSH_CHECK_CFLAG_COMPILE([-Wpointer-sign], [-Wno-pointer-sign])
OSSH_CHECK_CFLAG_COMPILE([-Wunused-result], [-Wno-unused-result]) OSSH_CHECK_CFLAG_COMPILE([-Wunused-result], [-Wno-unused-result])
OSSH_CHECK_CFLAG_COMPILE([-fno-strict-aliasing]) OSSH_CHECK_CFLAG_COMPILE([-fno-strict-aliasing])
OSSH_CHECK_CFLAG_COMPILE([-D_FORTIFY_SOURCE=2])
if test "x$use_toolchain_hardening" = "x1"; then if test "x$use_toolchain_hardening" = "x1"; then
OSSH_CHECK_CFLAG_COMPILE([-D_FORTIFY_SOURCE=2])
OSSH_CHECK_LDFLAG_LINK([-Wl,-z,relro]) OSSH_CHECK_LDFLAG_LINK([-Wl,-z,relro])
OSSH_CHECK_LDFLAG_LINK([-Wl,-z,now]) OSSH_CHECK_LDFLAG_LINK([-Wl,-z,now])
OSSH_CHECK_LDFLAG_LINK([-Wl,-z,noexecstack]) OSSH_CHECK_LDFLAG_LINK([-Wl,-z,noexecstack])
@ -289,6 +289,16 @@ AC_ARG_WITH([cflags],
fi fi
] ]
) )
AC_ARG_WITH([cflags-after],
[ --with-cflags-after Specify additional flags to pass to compiler after configure],
[
if test -n "$withval" && test "x$withval" != "xno" && \
test "x${withval}" != "xyes"; then
CFLAGS_AFTER="$withval"
fi
]
)
AC_ARG_WITH([cppflags], AC_ARG_WITH([cppflags],
[ --with-cppflags Specify additional flags to pass to preprocessor] , [ --with-cppflags Specify additional flags to pass to preprocessor] ,
[ [
@ -307,6 +317,15 @@ AC_ARG_WITH([ldflags],
fi fi
] ]
) )
AC_ARG_WITH([ldflags-after],
[ --with-ldflags-after Specify additional flags to pass to linker after configure],
[
if test -n "$withval" && test "x$withval" != "xno" && \
test "x${withval}" != "xyes"; then
LDFLAGS_AFTER="$withval"
fi
]
)
AC_ARG_WITH([libs], AC_ARG_WITH([libs],
[ --with-libs Specify additional libraries to link with], [ --with-libs Specify additional libraries to link with],
[ [
@ -370,7 +389,6 @@ AC_CHECK_HEADERS([ \
sys/audit.h \ sys/audit.h \
sys/bitypes.h \ sys/bitypes.h \
sys/bsdtty.h \ sys/bsdtty.h \
sys/capability.h \
sys/cdefs.h \ sys/cdefs.h \
sys/dir.h \ sys/dir.h \
sys/mman.h \ sys/mman.h \
@ -402,6 +420,13 @@ AC_CHECK_HEADERS([ \
wchar.h \ wchar.h \
]) ])
# sys/capsicum.h requires sys/types.h
AC_CHECK_HEADERS([sys/capsicum.h], [], [], [
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
])
# lastlog.h requires sys/time.h to be included first on Solaris # lastlog.h requires sys/time.h to be included first on Solaris
AC_CHECK_HEADERS([lastlog.h], [], [], [ AC_CHECK_HEADERS([lastlog.h], [], [], [
#ifdef HAVE_SYS_TIME_H #ifdef HAVE_SYS_TIME_H
@ -1306,7 +1331,17 @@ AC_CHECK_FUNCS([fmt_scaled scan_scaled login logout openpty updwtmp logwtmp])
AC_SEARCH_LIBS([inet_ntop], [resolv nsl]) AC_SEARCH_LIBS([inet_ntop], [resolv nsl])
AC_SEARCH_LIBS([gethostbyname], [resolv nsl]) AC_SEARCH_LIBS([gethostbyname], [resolv nsl])
# "Particular Function Checks"
# see https://www.gnu.org/software/autoconf/manual/autoconf-2.69/html_node/Particular-Functions.html
AC_FUNC_STRFTIME AC_FUNC_STRFTIME
AC_FUNC_MALLOC
AC_FUNC_REALLOC
# autoconf doesn't have AC_FUNC_CALLOC so fake it if malloc returns NULL;
if test "x$ac_cv_func_malloc_0_nonnull" != "xyes"; then
AC_DEFINE(HAVE_CALLOC, 0, [calloc(x, 0) returns NULL])
AC_DEFINE(calloc, rpl_calloc,
[Define to rpl_calloc if the replacement function should be used.])
fi
# Check for ALTDIRFUNC glob() extension # Check for ALTDIRFUNC glob() extension
AC_MSG_CHECKING([for GLOB_ALTDIRFUNC support]) AC_MSG_CHECKING([for GLOB_ALTDIRFUNC support])
@ -1671,6 +1706,7 @@ AC_CHECK_FUNCS([ \
fchmod \ fchmod \
fchown \ fchown \
freeaddrinfo \ freeaddrinfo \
freezero \
fstatfs \ fstatfs \
fstatvfs \ fstatvfs \
futimes \ futimes \
@ -1744,6 +1780,7 @@ AC_CHECK_FUNCS([ \
strnlen \ strnlen \
strnvis \ strnvis \
strptime \ strptime \
strsignal \
strtonum \ strtonum \
strtoll \ strtoll \
strtoul \ strtoul \
@ -2512,7 +2549,11 @@ if test "x$openssl" = "xyes" ; then
10000*|0*) 10000*|0*)
AC_MSG_ERROR([OpenSSL >= 1.0.1 required (have "$ssl_library_ver")]) AC_MSG_ERROR([OpenSSL >= 1.0.1 required (have "$ssl_library_ver")])
;; ;;
*) ;; 100*) ;; # 1.0.x
200*) ;; # LibreSSL
*)
AC_MSG_ERROR([OpenSSL >= 1.1.0 is not yet supported (have "$ssl_library_ver")])
;;
esac esac
AC_MSG_RESULT([$ssl_library_ver]) AC_MSG_RESULT([$ssl_library_ver])
], ],
@ -3256,10 +3297,10 @@ elif test "x$sandbox_arg" = "xseccomp_filter" || \
AC_DEFINE([SANDBOX_SECCOMP_FILTER], [1], [Sandbox using seccomp filter]) AC_DEFINE([SANDBOX_SECCOMP_FILTER], [1], [Sandbox using seccomp filter])
elif test "x$sandbox_arg" = "xcapsicum" || \ elif test "x$sandbox_arg" = "xcapsicum" || \
( test -z "$sandbox_arg" && \ ( test -z "$sandbox_arg" && \
test "x$ac_cv_header_sys_capability_h" = "xyes" && \ test "x$ac_cv_header_sys_capsicum_h" = "xyes" && \
test "x$ac_cv_func_cap_rights_limit" = "xyes") ; then test "x$ac_cv_func_cap_rights_limit" = "xyes") ; then
test "x$ac_cv_header_sys_capability_h" != "xyes" && \ test "x$ac_cv_header_sys_capsicum_h" != "xyes" && \
AC_MSG_ERROR([capsicum sandbox requires sys/capability.h header]) AC_MSG_ERROR([capsicum sandbox requires sys/capsicum.h header])
test "x$ac_cv_func_cap_rights_limit" != "xyes" && \ test "x$ac_cv_func_cap_rights_limit" != "xyes" && \
AC_MSG_ERROR([capsicum sandbox requires cap_rights_limit function]) AC_MSG_ERROR([capsicum sandbox requires cap_rights_limit function])
SANDBOX_STYLE="capsicum" SANDBOX_STYLE="capsicum"
@ -5016,6 +5057,9 @@ AC_SUBST([TEST_SSH_UTF8], [$TEST_SSH_UTF8])
AC_SUBST([TEST_MALLOC_OPTIONS], [$TEST_MALLOC_OPTIONS]) AC_SUBST([TEST_MALLOC_OPTIONS], [$TEST_MALLOC_OPTIONS])
AC_SUBST([UNSUPPORTED_ALGORITHMS], [$unsupported_algorithms]) AC_SUBST([UNSUPPORTED_ALGORITHMS], [$unsupported_algorithms])
CFLAGS="${CFLAGS} ${CFLAGS_AFTER}"
LDFLAGS="${LDFLAGS} ${LDFLAGS_AFTER}"
AC_EXEEXT AC_EXEEXT
AC_CONFIG_FILES([Makefile buildpkg.sh opensshd.init openssh.xml \ AC_CONFIG_FILES([Makefile buildpkg.sh opensshd.init openssh.xml \
openbsd-compat/Makefile openbsd-compat/regress/Makefile \ openbsd-compat/Makefile openbsd-compat/regress/Makefile \

View File

@ -1,4 +1,4 @@
%define ver 7.5p1 %define ver 7.6p1
%define rel 1 %define rel 1
# OpenSSH privilege separation requires a user & group ID # OpenSSH privilege separation requires a user & group ID

View File

@ -1,6 +1,6 @@
#!/bin/sh #!/bin/sh
# Copyright (c) 1999-2013 Philip Hands <phil@hands.com> # Copyright (c) 1999-2016 Philip Hands <phil@hands.com>
# 2013 Martin Kletzander <mkletzan@redhat.com> # 2013 Martin Kletzander <mkletzan@redhat.com>
# 2010 Adeodato =?iso-8859-1?Q?Sim=F3?= <asp16@alu.ua.es> # 2010 Adeodato =?iso-8859-1?Q?Sim=F3?= <asp16@alu.ua.es>
# 2010 Eric Moret <eric.moret@gmail.com> # 2010 Eric Moret <eric.moret@gmail.com>
@ -56,7 +56,8 @@ then
fi fi
fi fi
DEFAULT_PUB_ID_FILE="$HOME/$(cd "$HOME" ; ls -t .ssh/id*.pub 2>/dev/null | grep -v -- '-cert.pub$' | head -n 1)" most_recent_id="$(cd "$HOME" ; ls -t .ssh/id*.pub 2>/dev/null | grep -v -- '-cert.pub$' | head -n 1)"
DEFAULT_PUB_ID_FILE="${most_recent_id:+$HOME/}$most_recent_id"
usage () { usage () {
printf 'Usage: %s [-h|-?|-f|-n] [-i [identity_file]] [-p port] [[-o <ssh -o options>] ...] [user@]hostname\n' "$0" >&2 printf 'Usage: %s [-h|-?|-f|-n] [-i [identity_file]] [-p port] [[-o <ssh -o options>] ...] [user@]hostname\n' "$0" >&2
@ -74,6 +75,11 @@ quote() {
use_id_file() { use_id_file() {
local L_ID_FILE="$1" local L_ID_FILE="$1"
if [ -z "$L_ID_FILE" ] ; then
printf "%s: ERROR: no ID file found\n" "$0"
exit 1
fi
if expr "$L_ID_FILE" : ".*\.pub$" >/dev/null ; then if expr "$L_ID_FILE" : ".*\.pub$" >/dev/null ; then
PUB_ID_FILE="$L_ID_FILE" PUB_ID_FILE="$L_ID_FILE"
else else
@ -287,9 +293,10 @@ case "$REMOTE_VERSION" in
*) *)
# Assuming that the remote host treats ~/.ssh/authorized_keys as one might expect # Assuming that the remote host treats ~/.ssh/authorized_keys as one might expect
populate_new_ids 0 populate_new_ids 0
# in ssh below - to defend against quirky remote shells: use 'exec sh -c' to get POSIX; 'cd' to be at $HOME; and all on one line, because tcsh. # in ssh below - to defend against quirky remote shells: use 'exec sh -c' to get POSIX;
# 'cd' to be at $HOME; add a newline if it's missing; and all on one line, because tcsh.
[ "$DRY_RUN" ] || printf '%s\n' "$NEW_IDS" | \ [ "$DRY_RUN" ] || printf '%s\n' "$NEW_IDS" | \
ssh "$@" "exec sh -c 'cd ; umask 077 ; mkdir -p .ssh && cat >> .ssh/authorized_keys || exit 1 ; if type restorecon >/dev/null 2>&1 ; then restorecon -F .ssh .ssh/authorized_keys ; fi'" \ ssh "$@" "exec sh -c 'cd ; umask 077 ; mkdir -p .ssh && { [ -z "'`tail -1c .ssh/authorized_keys 2>/dev/null`'" ] || echo >> .ssh/authorized_keys ; } && cat >> .ssh/authorized_keys || exit 1 ; if type restorecon >/dev/null 2>&1 ; then restorecon -F .ssh .ssh/authorized_keys ; fi'" \
|| exit 1 || exit 1
ADDED=$(printf '%s\n' "$NEW_IDS" | wc -l) ADDED=$(printf '%s\n' "$NEW_IDS" | wc -l)
;; ;;

View File

@ -13,7 +13,7 @@
Summary: OpenSSH, a free Secure Shell (SSH) protocol implementation Summary: OpenSSH, a free Secure Shell (SSH) protocol implementation
Name: openssh Name: openssh
Version: 7.5p1 Version: 7.6p1
URL: https://www.openssh.com/ URL: https://www.openssh.com/
Release: 1 Release: 1
Source0: openssh-%{version}.tar.gz Source0: openssh-%{version}.tar.gz

2
dns.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: dns.c,v 1.35 2015/08/20 22:32:42 deraadt Exp $ */ /* $OpenBSD: dns.c,v 1.37 2017/09/14 04:32:21 djm Exp $ */
/* /*
* Copyright (c) 2003 Wesley Griffin. All rights reserved. * Copyright (c) 2003 Wesley Griffin. All rights reserved.

2
dns.h
View File

@ -1,4 +1,4 @@
/* $OpenBSD: dns.h,v 1.15 2015/05/08 06:45:13 djm Exp $ */ /* $OpenBSD: dns.h,v 1.17 2017/09/14 04:32:21 djm Exp $ */
/* /*
* Copyright (c) 2003 Wesley Griffin. All rights reserved. * Copyright (c) 2003 Wesley Griffin. All rights reserved.

View File

@ -1,4 +1,4 @@
/* $OpenBSD: monitor.c,v 1.172 2017/06/24 06:34:38 djm Exp $ */ /* $OpenBSD: monitor.c,v 1.174 2017/10/02 19:33:20 djm Exp $ */
/* /*
* Copyright 2002 Niels Provos <provos@citi.umich.edu> * Copyright 2002 Niels Provos <provos@citi.umich.edu>
* Copyright 2002 Markus Friedl <markus@openbsd.org> * Copyright 2002 Markus Friedl <markus@openbsd.org>
@ -760,10 +760,12 @@ mm_answer_pwnamallow(int sock, Buffer *m)
for (i = 0; i < options.nx; i++) \ for (i = 0; i < options.nx; i++) \
buffer_put_cstring(m, options.x[i]); \ buffer_put_cstring(m, options.x[i]); \
} while (0) } while (0)
#define M_CP_STRARRAYOPT_ALLOC(x, nx) M_CP_STRARRAYOPT(x, nx)
/* See comment in servconf.h */ /* See comment in servconf.h */
COPY_MATCH_STRING_OPTS(); COPY_MATCH_STRING_OPTS();
#undef M_CP_STROPT #undef M_CP_STROPT
#undef M_CP_STRARRAYOPT #undef M_CP_STRARRAYOPT
#undef M_CP_STRARRAYOPT_ALLOC
/* Create valid auth method lists */ /* Create valid auth method lists */
if (auth2_setup_methods_lists(authctxt) != 0) { if (auth2_setup_methods_lists(authctxt) != 0) {
@ -1519,13 +1521,14 @@ mm_answer_pty_cleanup(int sock, Buffer *m)
int int
mm_answer_term(int sock, Buffer *req) mm_answer_term(int sock, Buffer *req)
{ {
struct ssh *ssh = active_state; /* XXX */
extern struct monitor *pmonitor; extern struct monitor *pmonitor;
int res, status; int res, status;
debug3("%s: tearing down sessions", __func__); debug3("%s: tearing down sessions", __func__);
/* The child is terminating */ /* The child is terminating */
session_destroy_all(&mm_session_close); session_destroy_all(ssh, &mm_session_close);
#ifdef USE_PAM #ifdef USE_PAM
if (options.use_pam) if (options.use_pam)

View File

@ -1,4 +1,4 @@
/* $OpenBSD: monitor_wrap.c,v 1.92 2017/05/30 14:10:53 markus Exp $ */ /* $OpenBSD: monitor_wrap.c,v 1.94 2017/10/02 19:33:20 djm Exp $ */
/* /*
* Copyright 2002 Niels Provos <provos@citi.umich.edu> * Copyright 2002 Niels Provos <provos@citi.umich.edu>
* Copyright 2002 Markus Friedl <markus@openbsd.org> * Copyright 2002 Markus Friedl <markus@openbsd.org>
@ -242,6 +242,7 @@ mm_key_sign(struct sshkey *key, u_char **sigp, u_int *lenp,
struct passwd * struct passwd *
mm_getpwnamallow(const char *username) mm_getpwnamallow(const char *username)
{ {
struct ssh *ssh = active_state; /* XXX */
Buffer m; Buffer m;
struct passwd *pw; struct passwd *pw;
u_int len, i; u_int len, i;
@ -289,13 +290,20 @@ out:
for (i = 0; i < newopts->nx; i++) \ for (i = 0; i < newopts->nx; i++) \
newopts->x[i] = buffer_get_string(&m, NULL); \ newopts->x[i] = buffer_get_string(&m, NULL); \
} while (0) } while (0)
#define M_CP_STRARRAYOPT_ALLOC(x, nx) do { \
newopts->x = newopts->nx == 0 ? \
NULL : xcalloc(newopts->nx, sizeof(*newopts->x)); \
M_CP_STRARRAYOPT(x, nx); \
} while (0)
/* See comment in servconf.h */ /* See comment in servconf.h */
COPY_MATCH_STRING_OPTS(); COPY_MATCH_STRING_OPTS();
#undef M_CP_STROPT #undef M_CP_STROPT
#undef M_CP_STRARRAYOPT #undef M_CP_STRARRAYOPT
#undef M_CP_STRARRAYOPT_ALLOC
copy_set_server_options(&options, newopts, 1); copy_set_server_options(&options, newopts, 1);
log_change_level(options.log_level); log_change_level(options.log_level);
process_permitopen(ssh, &options);
free(newopts); free(newopts);
buffer_free(&m); buffer_free(&m);

209
mux.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: mux.c,v 1.65 2017/06/09 06:47:13 djm Exp $ */ /* $OpenBSD: mux.c,v 1.69 2017/09/20 05:19:00 dtucker Exp $ */
/* /*
* Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org> * Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org>
* *
@ -161,22 +161,32 @@ struct mux_master_state {
#define MUX_FWD_REMOTE 2 #define MUX_FWD_REMOTE 2
#define MUX_FWD_DYNAMIC 3 #define MUX_FWD_DYNAMIC 3
static void mux_session_confirm(int, int, void *); static void mux_session_confirm(struct ssh *, int, int, void *);
static void mux_stdio_confirm(int, int, void *); static void mux_stdio_confirm(struct ssh *, int, int, void *);
static int process_mux_master_hello(u_int, Channel *, Buffer *, Buffer *); static int process_mux_master_hello(struct ssh *, u_int,
static int process_mux_new_session(u_int, Channel *, Buffer *, Buffer *); Channel *, struct sshbuf *, struct sshbuf *);
static int process_mux_alive_check(u_int, Channel *, Buffer *, Buffer *); static int process_mux_new_session(struct ssh *, u_int,
static int process_mux_terminate(u_int, Channel *, Buffer *, Buffer *); Channel *, struct sshbuf *, struct sshbuf *);
static int process_mux_open_fwd(u_int, Channel *, Buffer *, Buffer *); static int process_mux_alive_check(struct ssh *, u_int,
static int process_mux_close_fwd(u_int, Channel *, Buffer *, Buffer *); Channel *, struct sshbuf *, struct sshbuf *);
static int process_mux_stdio_fwd(u_int, Channel *, Buffer *, Buffer *); static int process_mux_terminate(struct ssh *, u_int,
static int process_mux_stop_listening(u_int, Channel *, Buffer *, Buffer *); Channel *, struct sshbuf *, struct sshbuf *);
static int process_mux_proxy(u_int, Channel *, Buffer *, Buffer *); static int process_mux_open_fwd(struct ssh *, u_int,
Channel *, struct sshbuf *, struct sshbuf *);
static int process_mux_close_fwd(struct ssh *, u_int,
Channel *, struct sshbuf *, struct sshbuf *);
static int process_mux_stdio_fwd(struct ssh *, u_int,
Channel *, struct sshbuf *, struct sshbuf *);
static int process_mux_stop_listening(struct ssh *, u_int,
Channel *, struct sshbuf *, struct sshbuf *);
static int process_mux_proxy(struct ssh *, u_int,
Channel *, struct sshbuf *, struct sshbuf *);
static const struct { static const struct {
u_int type; u_int type;
int (*handler)(u_int, Channel *, Buffer *, Buffer *); int (*handler)(struct ssh *, u_int, Channel *,
struct sshbuf *, struct sshbuf *);
} mux_master_handlers[] = { } mux_master_handlers[] = {
{ MUX_MSG_HELLO, process_mux_master_hello }, { MUX_MSG_HELLO, process_mux_master_hello },
{ MUX_C_NEW_SESSION, process_mux_new_session }, { MUX_C_NEW_SESSION, process_mux_new_session },
@ -193,52 +203,54 @@ static const struct {
/* Cleanup callback fired on closure of mux slave _session_ channel */ /* Cleanup callback fired on closure of mux slave _session_ channel */
/* ARGSUSED */ /* ARGSUSED */
static void static void
mux_master_session_cleanup_cb(int cid, void *unused) mux_master_session_cleanup_cb(struct ssh *ssh, int cid, void *unused)
{ {
Channel *cc, *c = channel_by_id(cid); Channel *cc, *c = channel_by_id(ssh, cid);
debug3("%s: entering for channel %d", __func__, cid); debug3("%s: entering for channel %d", __func__, cid);
if (c == NULL) if (c == NULL)
fatal("%s: channel_by_id(%i) == NULL", __func__, cid); fatal("%s: channel_by_id(%i) == NULL", __func__, cid);
if (c->ctl_chan != -1) { if (c->ctl_chan != -1) {
if ((cc = channel_by_id(c->ctl_chan)) == NULL) if ((cc = channel_by_id(ssh, c->ctl_chan)) == NULL)
fatal("%s: channel %d missing control channel %d", fatal("%s: channel %d missing control channel %d",
__func__, c->self, c->ctl_chan); __func__, c->self, c->ctl_chan);
c->ctl_chan = -1; c->ctl_chan = -1;
cc->remote_id = -1; cc->remote_id = 0;
chan_rcvd_oclose(cc); cc->have_remote_id = 0;
chan_rcvd_oclose(ssh, cc);
} }
channel_cancel_cleanup(c->self); channel_cancel_cleanup(ssh, c->self);
} }
/* Cleanup callback fired on closure of mux slave _control_ channel */ /* Cleanup callback fired on closure of mux slave _control_ channel */
/* ARGSUSED */ /* ARGSUSED */
static void static void
mux_master_control_cleanup_cb(int cid, void *unused) mux_master_control_cleanup_cb(struct ssh *ssh, int cid, void *unused)
{ {
Channel *sc, *c = channel_by_id(cid); Channel *sc, *c = channel_by_id(ssh, cid);
debug3("%s: entering for channel %d", __func__, cid); debug3("%s: entering for channel %d", __func__, cid);
if (c == NULL) if (c == NULL)
fatal("%s: channel_by_id(%i) == NULL", __func__, cid); fatal("%s: channel_by_id(%i) == NULL", __func__, cid);
if (c->remote_id != -1) { if (c->have_remote_id) {
if ((sc = channel_by_id(c->remote_id)) == NULL) if ((sc = channel_by_id(ssh, c->remote_id)) == NULL)
fatal("%s: channel %d missing session channel %d", fatal("%s: channel %d missing session channel %u",
__func__, c->self, c->remote_id); __func__, c->self, c->remote_id);
c->remote_id = -1; c->remote_id = 0;
c->have_remote_id = 0;
sc->ctl_chan = -1; sc->ctl_chan = -1;
if (sc->type != SSH_CHANNEL_OPEN && if (sc->type != SSH_CHANNEL_OPEN &&
sc->type != SSH_CHANNEL_OPENING) { sc->type != SSH_CHANNEL_OPENING) {
debug2("%s: channel %d: not open", __func__, sc->self); debug2("%s: channel %d: not open", __func__, sc->self);
chan_mark_dead(sc); chan_mark_dead(ssh, sc);
} else { } else {
if (sc->istate == CHAN_INPUT_OPEN) if (sc->istate == CHAN_INPUT_OPEN)
chan_read_failed(sc); chan_read_failed(ssh, sc);
if (sc->ostate == CHAN_OUTPUT_OPEN) if (sc->ostate == CHAN_OUTPUT_OPEN)
chan_write_failed(sc); chan_write_failed(ssh, sc);
} }
} }
channel_cancel_cleanup(c->self); channel_cancel_cleanup(ssh, c->self);
} }
/* Check mux client environment variables before passing them to mux master. */ /* Check mux client environment variables before passing them to mux master. */
@ -266,7 +278,8 @@ env_permitted(char *env)
/* Mux master protocol message handlers */ /* Mux master protocol message handlers */
static int static int
process_mux_master_hello(u_int rid, Channel *c, Buffer *m, Buffer *r) process_mux_master_hello(struct ssh *ssh, u_int rid,
Channel *c, Buffer *m, Buffer *r)
{ {
u_int ver; u_int ver;
struct mux_master_state *state = (struct mux_master_state *)c->mux_ctx; struct mux_master_state *state = (struct mux_master_state *)c->mux_ctx;
@ -308,7 +321,8 @@ process_mux_master_hello(u_int rid, Channel *c, Buffer *m, Buffer *r)
} }
static int static int
process_mux_new_session(u_int rid, Channel *c, Buffer *m, Buffer *r) process_mux_new_session(struct ssh *ssh, u_int rid,
Channel *c, Buffer *m, Buffer *r)
{ {
Channel *nc; Channel *nc;
struct mux_session_confirm_ctx *cctx; struct mux_session_confirm_ctx *cctx;
@ -401,7 +415,7 @@ process_mux_new_session(u_int rid, Channel *c, Buffer *m, Buffer *r)
new_fd[0], new_fd[1], new_fd[2]); new_fd[0], new_fd[1], new_fd[2]);
/* XXX support multiple child sessions in future */ /* XXX support multiple child sessions in future */
if (c->remote_id != -1) { if (c->have_remote_id) {
debug2("%s: session already open", __func__); debug2("%s: session already open", __func__);
/* prepare reply */ /* prepare reply */
buffer_put_int(r, MUX_S_FAILURE); buffer_put_int(r, MUX_S_FAILURE);
@ -453,15 +467,16 @@ process_mux_new_session(u_int rid, Channel *c, Buffer *m, Buffer *r)
packetmax >>= 1; packetmax >>= 1;
} }
nc = channel_new("session", SSH_CHANNEL_OPENING, nc = channel_new(ssh, "session", SSH_CHANNEL_OPENING,
new_fd[0], new_fd[1], new_fd[2], window, packetmax, new_fd[0], new_fd[1], new_fd[2], window, packetmax,
CHAN_EXTENDED_WRITE, "client-session", /*nonblock*/0); CHAN_EXTENDED_WRITE, "client-session", /*nonblock*/0);
nc->ctl_chan = c->self; /* link session -> control channel */ nc->ctl_chan = c->self; /* link session -> control channel */
c->remote_id = nc->self; /* link control -> session channel */ c->remote_id = nc->self; /* link control -> session channel */
c->have_remote_id = 1;
if (cctx->want_tty && escape_char != 0xffffffff) { if (cctx->want_tty && escape_char != 0xffffffff) {
channel_register_filter(nc->self, channel_register_filter(ssh, nc->self,
client_simple_escape_filter, NULL, client_simple_escape_filter, NULL,
client_filter_cleanup, client_filter_cleanup,
client_new_escape_filter_ctx((int)escape_char)); client_new_escape_filter_ctx((int)escape_char));
@ -470,17 +485,19 @@ process_mux_new_session(u_int rid, Channel *c, Buffer *m, Buffer *r)
debug2("%s: channel_new: %d linked to control channel %d", debug2("%s: channel_new: %d linked to control channel %d",
__func__, nc->self, nc->ctl_chan); __func__, nc->self, nc->ctl_chan);
channel_send_open(nc->self); channel_send_open(ssh, nc->self);
channel_register_open_confirm(nc->self, mux_session_confirm, cctx); channel_register_open_confirm(ssh, nc->self, mux_session_confirm, cctx);
c->mux_pause = 1; /* stop handling messages until open_confirm done */ c->mux_pause = 1; /* stop handling messages until open_confirm done */
channel_register_cleanup(nc->self, mux_master_session_cleanup_cb, 1); channel_register_cleanup(ssh, nc->self,
mux_master_session_cleanup_cb, 1);
/* reply is deferred, sent by mux_session_confirm */ /* reply is deferred, sent by mux_session_confirm */
return 0; return 0;
} }
static int static int
process_mux_alive_check(u_int rid, Channel *c, Buffer *m, Buffer *r) process_mux_alive_check(struct ssh *ssh, u_int rid,
Channel *c, Buffer *m, Buffer *r)
{ {
debug2("%s: channel %d: alive check", __func__, c->self); debug2("%s: channel %d: alive check", __func__, c->self);
@ -493,7 +510,8 @@ process_mux_alive_check(u_int rid, Channel *c, Buffer *m, Buffer *r)
} }
static int static int
process_mux_terminate(u_int rid, Channel *c, Buffer *m, Buffer *r) process_mux_terminate(struct ssh *ssh, u_int rid,
Channel *c, Buffer *m, Buffer *r)
{ {
debug2("%s: channel %d: terminate request", __func__, c->self); debug2("%s: channel %d: terminate request", __func__, c->self);
@ -582,7 +600,7 @@ compare_forward(struct Forward *a, struct Forward *b)
} }
static void static void
mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) mux_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt)
{ {
struct mux_channel_confirm_ctx *fctx = ctxt; struct mux_channel_confirm_ctx *fctx = ctxt;
char *failmsg = NULL; char *failmsg = NULL;
@ -590,7 +608,7 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
Channel *c; Channel *c;
Buffer out; Buffer out;
if ((c = channel_by_id(fctx->cid)) == NULL) { if ((c = channel_by_id(ssh, fctx->cid)) == NULL) {
/* no channel for reply */ /* no channel for reply */
error("%s: unknown channel", __func__); error("%s: unknown channel", __func__);
return; return;
@ -616,7 +634,7 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
buffer_put_int(&out, MUX_S_REMOTE_PORT); buffer_put_int(&out, MUX_S_REMOTE_PORT);
buffer_put_int(&out, fctx->rid); buffer_put_int(&out, fctx->rid);
buffer_put_int(&out, rfwd->allocated_port); buffer_put_int(&out, rfwd->allocated_port);
channel_update_permitted_opens(rfwd->handle, channel_update_permitted_opens(ssh, rfwd->handle,
rfwd->allocated_port); rfwd->allocated_port);
} else { } else {
buffer_put_int(&out, MUX_S_OK); buffer_put_int(&out, MUX_S_OK);
@ -625,7 +643,7 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
goto out; goto out;
} else { } else {
if (rfwd->listen_port == 0) if (rfwd->listen_port == 0)
channel_update_permitted_opens(rfwd->handle, -1); channel_update_permitted_opens(ssh, rfwd->handle, -1);
if (rfwd->listen_path != NULL) if (rfwd->listen_path != NULL)
xasprintf(&failmsg, "remote port forwarding failed for " xasprintf(&failmsg, "remote port forwarding failed for "
"listen path %s", rfwd->listen_path); "listen path %s", rfwd->listen_path);
@ -651,7 +669,7 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
buffer_put_cstring(&out, failmsg); buffer_put_cstring(&out, failmsg);
free(failmsg); free(failmsg);
out: out:
buffer_put_string(&c->output, buffer_ptr(&out), buffer_len(&out)); buffer_put_string(c->output, buffer_ptr(&out), buffer_len(&out));
buffer_free(&out); buffer_free(&out);
if (c->mux_pause <= 0) if (c->mux_pause <= 0)
fatal("%s: mux_pause %d", __func__, c->mux_pause); fatal("%s: mux_pause %d", __func__, c->mux_pause);
@ -659,7 +677,8 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
} }
static int static int
process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) process_mux_open_fwd(struct ssh *ssh, u_int rid,
Channel *c, Buffer *m, Buffer *r)
{ {
struct Forward fwd; struct Forward fwd;
char *fwd_desc = NULL; char *fwd_desc = NULL;
@ -727,13 +746,16 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
fwd.listen_port); fwd.listen_port);
goto invalid; goto invalid;
} }
if ((fwd.connect_port != PORT_STREAMLOCAL && fwd.connect_port >= 65536) if ((fwd.connect_port != PORT_STREAMLOCAL &&
|| (ftype != MUX_FWD_DYNAMIC && ftype != MUX_FWD_REMOTE && fwd.connect_port == 0)) { fwd.connect_port >= 65536) ||
(ftype != MUX_FWD_DYNAMIC && ftype != MUX_FWD_REMOTE &&
fwd.connect_port == 0)) {
logit("%s: invalid connect port %u", __func__, logit("%s: invalid connect port %u", __func__,
fwd.connect_port); fwd.connect_port);
goto invalid; goto invalid;
} }
if (ftype != MUX_FWD_DYNAMIC && fwd.connect_host == NULL && fwd.connect_path == NULL) { if (ftype != MUX_FWD_DYNAMIC && fwd.connect_host == NULL &&
fwd.connect_path == NULL) {
logit("%s: missing connect host", __func__); logit("%s: missing connect host", __func__);
goto invalid; goto invalid;
} }
@ -784,7 +806,7 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
} }
if (ftype == MUX_FWD_LOCAL || ftype == MUX_FWD_DYNAMIC) { if (ftype == MUX_FWD_LOCAL || ftype == MUX_FWD_DYNAMIC) {
if (!channel_setup_local_fwd_listener(&fwd, if (!channel_setup_local_fwd_listener(ssh, &fwd,
&options.fwd_opts)) { &options.fwd_opts)) {
fail: fail:
logit("slave-requested %s failed", fwd_desc); logit("slave-requested %s failed", fwd_desc);
@ -798,7 +820,7 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
} else { } else {
struct mux_channel_confirm_ctx *fctx; struct mux_channel_confirm_ctx *fctx;
fwd.handle = channel_request_remote_forwarding(&fwd); fwd.handle = channel_request_remote_forwarding(ssh, &fwd);
if (fwd.handle < 0) if (fwd.handle < 0)
goto fail; goto fail;
add_remote_forward(&options, &fwd); add_remote_forward(&options, &fwd);
@ -827,7 +849,8 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
} }
static int static int
process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) process_mux_close_fwd(struct ssh *ssh, u_int rid,
Channel *c, Buffer *m, Buffer *r)
{ {
struct Forward fwd, *found_fwd; struct Forward fwd, *found_fwd;
char *fwd_desc = NULL; char *fwd_desc = NULL;
@ -908,11 +931,11 @@ process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
* However, for dynamic allocated listen ports we need * However, for dynamic allocated listen ports we need
* to use the actual listen port. * to use the actual listen port.
*/ */
if (channel_request_rforward_cancel(found_fwd) == -1) if (channel_request_rforward_cancel(ssh, found_fwd) == -1)
error_reason = "port not in permitted opens"; error_reason = "port not in permitted opens";
} else { /* local and dynamic forwards */ } else { /* local and dynamic forwards */
/* Ditto */ /* Ditto */
if (channel_cancel_lport_listener(&fwd, fwd.connect_port, if (channel_cancel_lport_listener(ssh, &fwd, fwd.connect_port,
&options.fwd_opts) == -1) &options.fwd_opts) == -1)
error_reason = "port not found"; error_reason = "port not found";
} }
@ -942,7 +965,8 @@ process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
} }
static int static int
process_mux_stdio_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) process_mux_stdio_fwd(struct ssh *ssh, u_int rid,
Channel *c, Buffer *m, Buffer *r)
{ {
Channel *nc; Channel *nc;
char *reserved, *chost; char *reserved, *chost;
@ -986,7 +1010,7 @@ process_mux_stdio_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
new_fd[0], new_fd[1]); new_fd[0], new_fd[1]);
/* XXX support multiple child sessions in future */ /* XXX support multiple child sessions in future */
if (c->remote_id != -1) { if (c->have_remote_id) {
debug2("%s: session already open", __func__); debug2("%s: session already open", __func__);
/* prepare reply */ /* prepare reply */
buffer_put_int(r, MUX_S_FAILURE); buffer_put_int(r, MUX_S_FAILURE);
@ -1018,19 +1042,21 @@ process_mux_stdio_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
if (!isatty(new_fd[1])) if (!isatty(new_fd[1]))
set_nonblock(new_fd[1]); set_nonblock(new_fd[1]);
nc = channel_connect_stdio_fwd(chost, cport, new_fd[0], new_fd[1]); nc = channel_connect_stdio_fwd(ssh, chost, cport, new_fd[0], new_fd[1]);
nc->ctl_chan = c->self; /* link session -> control channel */ nc->ctl_chan = c->self; /* link session -> control channel */
c->remote_id = nc->self; /* link control -> session channel */ c->remote_id = nc->self; /* link control -> session channel */
c->have_remote_id = 1;
debug2("%s: channel_new: %d linked to control channel %d", debug2("%s: channel_new: %d linked to control channel %d",
__func__, nc->self, nc->ctl_chan); __func__, nc->self, nc->ctl_chan);
channel_register_cleanup(nc->self, mux_master_session_cleanup_cb, 1); channel_register_cleanup(ssh, nc->self,
mux_master_session_cleanup_cb, 1);
cctx = xcalloc(1, sizeof(*cctx)); cctx = xcalloc(1, sizeof(*cctx));
cctx->rid = rid; cctx->rid = rid;
channel_register_open_confirm(nc->self, mux_stdio_confirm, cctx); channel_register_open_confirm(ssh, nc->self, mux_stdio_confirm, cctx);
c->mux_pause = 1; /* stop handling messages until open_confirm done */ c->mux_pause = 1; /* stop handling messages until open_confirm done */
/* reply is deferred, sent by mux_session_confirm */ /* reply is deferred, sent by mux_session_confirm */
@ -1039,7 +1065,7 @@ process_mux_stdio_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
/* Callback on open confirmation in mux master for a mux stdio fwd session. */ /* Callback on open confirmation in mux master for a mux stdio fwd session. */
static void static void
mux_stdio_confirm(int id, int success, void *arg) mux_stdio_confirm(struct ssh *ssh, int id, int success, void *arg)
{ {
struct mux_stdio_confirm_ctx *cctx = arg; struct mux_stdio_confirm_ctx *cctx = arg;
Channel *c, *cc; Channel *c, *cc;
@ -1047,9 +1073,9 @@ mux_stdio_confirm(int id, int success, void *arg)
if (cctx == NULL) if (cctx == NULL)
fatal("%s: cctx == NULL", __func__); fatal("%s: cctx == NULL", __func__);
if ((c = channel_by_id(id)) == NULL) if ((c = channel_by_id(ssh, id)) == NULL)
fatal("%s: no channel for id %d", __func__, id); fatal("%s: no channel for id %d", __func__, id);
if ((cc = channel_by_id(c->ctl_chan)) == NULL) if ((cc = channel_by_id(ssh, c->ctl_chan)) == NULL)
fatal("%s: channel %d lacks control channel %d", __func__, fatal("%s: channel %d lacks control channel %d", __func__,
id, c->ctl_chan); id, c->ctl_chan);
@ -1072,7 +1098,7 @@ mux_stdio_confirm(int id, int success, void *arg)
done: done:
/* Send reply */ /* Send reply */
buffer_put_string(&cc->output, buffer_ptr(&reply), buffer_len(&reply)); buffer_put_string(cc->output, buffer_ptr(&reply), buffer_len(&reply));
buffer_free(&reply); buffer_free(&reply);
if (cc->mux_pause <= 0) if (cc->mux_pause <= 0)
@ -1083,7 +1109,8 @@ mux_stdio_confirm(int id, int success, void *arg)
} }
static int static int
process_mux_stop_listening(u_int rid, Channel *c, Buffer *m, Buffer *r) process_mux_stop_listening(struct ssh *ssh, u_int rid,
Channel *c, Buffer *m, Buffer *r)
{ {
debug("%s: channel %d: stop listening", __func__, c->self); debug("%s: channel %d: stop listening", __func__, c->self);
@ -1100,7 +1127,7 @@ process_mux_stop_listening(u_int rid, Channel *c, Buffer *m, Buffer *r)
} }
if (mux_listener_channel != NULL) { if (mux_listener_channel != NULL) {
channel_free(mux_listener_channel); channel_free(ssh, mux_listener_channel);
client_stop_mux(); client_stop_mux();
free(options.control_path); free(options.control_path);
options.control_path = NULL; options.control_path = NULL;
@ -1116,7 +1143,8 @@ process_mux_stop_listening(u_int rid, Channel *c, Buffer *m, Buffer *r)
} }
static int static int
process_mux_proxy(u_int rid, Channel *c, Buffer *m, Buffer *r) process_mux_proxy(struct ssh *ssh, u_int rid,
Channel *c, Buffer *m, Buffer *r)
{ {
debug("%s: channel %d: proxy request", __func__, c->self); debug("%s: channel %d: proxy request", __func__, c->self);
@ -1129,7 +1157,7 @@ process_mux_proxy(u_int rid, Channel *c, Buffer *m, Buffer *r)
/* Channel callbacks fired on read/write from mux slave fd */ /* Channel callbacks fired on read/write from mux slave fd */
static int static int
mux_master_read_cb(Channel *c) mux_master_read_cb(struct ssh *ssh, Channel *c)
{ {
struct mux_master_state *state = (struct mux_master_state *)c->mux_ctx; struct mux_master_state *state = (struct mux_master_state *)c->mux_ctx;
Buffer in, out; Buffer in, out;
@ -1141,7 +1169,7 @@ mux_master_read_cb(Channel *c)
if (c->mux_ctx == NULL) { if (c->mux_ctx == NULL) {
state = xcalloc(1, sizeof(*state)); state = xcalloc(1, sizeof(*state));
c->mux_ctx = state; c->mux_ctx = state;
channel_register_cleanup(c->self, channel_register_cleanup(ssh, c->self,
mux_master_control_cleanup_cb, 0); mux_master_control_cleanup_cb, 0);
/* Send hello */ /* Send hello */
@ -1149,7 +1177,7 @@ mux_master_read_cb(Channel *c)
buffer_put_int(&out, MUX_MSG_HELLO); buffer_put_int(&out, MUX_MSG_HELLO);
buffer_put_int(&out, SSHMUX_VER); buffer_put_int(&out, SSHMUX_VER);
/* no extensions */ /* no extensions */
buffer_put_string(&c->output, buffer_ptr(&out), buffer_put_string(c->output, buffer_ptr(&out),
buffer_len(&out)); buffer_len(&out));
buffer_free(&out); buffer_free(&out);
debug3("%s: channel %d: hello sent", __func__, c->self); debug3("%s: channel %d: hello sent", __func__, c->self);
@ -1160,7 +1188,7 @@ mux_master_read_cb(Channel *c)
buffer_init(&out); buffer_init(&out);
/* Channel code ensures that we receive whole packets */ /* Channel code ensures that we receive whole packets */
if ((ptr = buffer_get_string_ptr_ret(&c->input, &have)) == NULL) { if ((ptr = buffer_get_string_ptr_ret(c->input, &have)) == NULL) {
malf: malf:
error("%s: malformed message", __func__); error("%s: malformed message", __func__);
goto out; goto out;
@ -1186,7 +1214,8 @@ mux_master_read_cb(Channel *c)
for (i = 0; mux_master_handlers[i].handler != NULL; i++) { for (i = 0; mux_master_handlers[i].handler != NULL; i++) {
if (type == mux_master_handlers[i].type) { if (type == mux_master_handlers[i].type) {
ret = mux_master_handlers[i].handler(rid, c, &in, &out); ret = mux_master_handlers[i].handler(ssh, rid,
c, &in, &out);
break; break;
} }
} }
@ -1199,7 +1228,7 @@ mux_master_read_cb(Channel *c)
} }
/* Enqueue reply packet */ /* Enqueue reply packet */
if (buffer_len(&out) != 0) { if (buffer_len(&out) != 0) {
buffer_put_string(&c->output, buffer_ptr(&out), buffer_put_string(c->output, buffer_ptr(&out),
buffer_len(&out)); buffer_len(&out));
} }
out: out:
@ -1209,7 +1238,7 @@ mux_master_read_cb(Channel *c)
} }
void void
mux_exit_message(Channel *c, int exitval) mux_exit_message(struct ssh *ssh, Channel *c, int exitval)
{ {
Buffer m; Buffer m;
Channel *mux_chan; Channel *mux_chan;
@ -1217,7 +1246,7 @@ mux_exit_message(Channel *c, int exitval)
debug3("%s: channel %d: exit message, exitval %d", __func__, c->self, debug3("%s: channel %d: exit message, exitval %d", __func__, c->self,
exitval); exitval);
if ((mux_chan = channel_by_id(c->ctl_chan)) == NULL) if ((mux_chan = channel_by_id(ssh, c->ctl_chan)) == NULL)
fatal("%s: channel %d missing mux channel %d", fatal("%s: channel %d missing mux channel %d",
__func__, c->self, c->ctl_chan); __func__, c->self, c->ctl_chan);
@ -1227,19 +1256,19 @@ mux_exit_message(Channel *c, int exitval)
buffer_put_int(&m, c->self); buffer_put_int(&m, c->self);
buffer_put_int(&m, exitval); buffer_put_int(&m, exitval);
buffer_put_string(&mux_chan->output, buffer_ptr(&m), buffer_len(&m)); buffer_put_string(mux_chan->output, buffer_ptr(&m), buffer_len(&m));
buffer_free(&m); buffer_free(&m);
} }
void void
mux_tty_alloc_failed(Channel *c) mux_tty_alloc_failed(struct ssh *ssh, Channel *c)
{ {
Buffer m; Buffer m;
Channel *mux_chan; Channel *mux_chan;
debug3("%s: channel %d: TTY alloc failed", __func__, c->self); debug3("%s: channel %d: TTY alloc failed", __func__, c->self);
if ((mux_chan = channel_by_id(c->ctl_chan)) == NULL) if ((mux_chan = channel_by_id(ssh, c->ctl_chan)) == NULL)
fatal("%s: channel %d missing mux channel %d", fatal("%s: channel %d missing mux channel %d",
__func__, c->self, c->ctl_chan); __func__, c->self, c->ctl_chan);
@ -1248,13 +1277,13 @@ mux_tty_alloc_failed(Channel *c)
buffer_put_int(&m, MUX_S_TTY_ALLOC_FAIL); buffer_put_int(&m, MUX_S_TTY_ALLOC_FAIL);
buffer_put_int(&m, c->self); buffer_put_int(&m, c->self);
buffer_put_string(&mux_chan->output, buffer_ptr(&m), buffer_len(&m)); buffer_put_string(mux_chan->output, buffer_ptr(&m), buffer_len(&m));
buffer_free(&m); buffer_free(&m);
} }
/* Prepare a mux master to listen on a Unix domain socket. */ /* Prepare a mux master to listen on a Unix domain socket. */
void void
muxserver_listen(void) muxserver_listen(struct ssh *ssh)
{ {
mode_t old_umask; mode_t old_umask;
char *orig_control_path = options.control_path; char *orig_control_path = options.control_path;
@ -1327,7 +1356,7 @@ muxserver_listen(void)
set_nonblock(muxserver_sock); set_nonblock(muxserver_sock);
mux_listener_channel = channel_new("mux listener", mux_listener_channel = channel_new(ssh, "mux listener",
SSH_CHANNEL_MUX_LISTENER, muxserver_sock, muxserver_sock, -1, SSH_CHANNEL_MUX_LISTENER, muxserver_sock, muxserver_sock, -1,
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
0, options.control_path, 1); 0, options.control_path, 1);
@ -1338,7 +1367,7 @@ muxserver_listen(void)
/* Callback on open confirmation in mux master for a mux client session. */ /* Callback on open confirmation in mux master for a mux client session. */
static void static void
mux_session_confirm(int id, int success, void *arg) mux_session_confirm(struct ssh *ssh, int id, int success, void *arg)
{ {
struct mux_session_confirm_ctx *cctx = arg; struct mux_session_confirm_ctx *cctx = arg;
const char *display; const char *display;
@ -1348,9 +1377,9 @@ mux_session_confirm(int id, int success, void *arg)
if (cctx == NULL) if (cctx == NULL)
fatal("%s: cctx == NULL", __func__); fatal("%s: cctx == NULL", __func__);
if ((c = channel_by_id(id)) == NULL) if ((c = channel_by_id(ssh, id)) == NULL)
fatal("%s: no channel for id %d", __func__, id); fatal("%s: no channel for id %d", __func__, id);
if ((cc = channel_by_id(c->ctl_chan)) == NULL) if ((cc = channel_by_id(ssh, c->ctl_chan)) == NULL)
fatal("%s: channel %d lacks control channel %d", __func__, fatal("%s: channel %d lacks control channel %d", __func__,
id, c->ctl_chan); id, c->ctl_chan);
@ -1369,27 +1398,27 @@ mux_session_confirm(int id, int success, void *arg)
char *proto, *data; char *proto, *data;
/* Get reasonable local authentication information. */ /* Get reasonable local authentication information. */
if (client_x11_get_proto(display, options.xauth_location, if (client_x11_get_proto(ssh, display, options.xauth_location,
options.forward_x11_trusted, options.forward_x11_timeout, options.forward_x11_trusted, options.forward_x11_timeout,
&proto, &data) == 0) { &proto, &data) == 0) {
/* Request forwarding with authentication spoofing. */ /* Request forwarding with authentication spoofing. */
debug("Requesting X11 forwarding with authentication " debug("Requesting X11 forwarding with authentication "
"spoofing."); "spoofing.");
x11_request_forwarding_with_spoofing(id, display, proto, x11_request_forwarding_with_spoofing(ssh, id,
data, 1); display, proto, data, 1);
/* XXX exit_on_forward_failure */ /* XXX exit_on_forward_failure */
client_expect_confirm(id, "X11 forwarding", client_expect_confirm(ssh, id, "X11 forwarding",
CONFIRM_WARN); CONFIRM_WARN);
} }
} }
if (cctx->want_agent_fwd && options.forward_agent) { if (cctx->want_agent_fwd && options.forward_agent) {
debug("Requesting authentication agent forwarding."); debug("Requesting authentication agent forwarding.");
channel_request_start(id, "auth-agent-req@openssh.com", 0); channel_request_start(ssh, id, "auth-agent-req@openssh.com", 0);
packet_send(); packet_send();
} }
client_session2_setup(id, cctx->want_tty, cctx->want_subsys, client_session2_setup(ssh, id, cctx->want_tty, cctx->want_subsys,
cctx->term, &cctx->tio, c->rfd, &cctx->cmd, cctx->env); cctx->term, &cctx->tio, c->rfd, &cctx->cmd, cctx->env);
debug3("%s: sending success reply", __func__); debug3("%s: sending success reply", __func__);
@ -1401,7 +1430,7 @@ mux_session_confirm(int id, int success, void *arg)
done: done:
/* Send reply */ /* Send reply */
buffer_put_string(&cc->output, buffer_ptr(&reply), buffer_len(&reply)); buffer_put_string(cc->output, buffer_ptr(&reply), buffer_len(&reply));
buffer_free(&reply); buffer_free(&reply);
if (cc->mux_pause <= 0) if (cc->mux_pause <= 0)
@ -1972,7 +2001,7 @@ mux_client_request_session(int fd)
leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
if (muxclient_terminate) { if (muxclient_terminate) {
debug2("Exiting on signal %d", muxclient_terminate); debug2("Exiting on signal: %s", strsignal(muxclient_terminate));
exitval = 255; exitval = 255;
} else if (!exitval_seen) { } else if (!exitval_seen) {
debug2("Control master terminated unexpectedly"); debug2("Control master terminated unexpectedly");

122
nchan.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: nchan.c,v 1.65 2017/04/30 23:28:42 djm Exp $ */ /* $OpenBSD: nchan.c,v 1.67 2017/09/12 06:35:32 djm Exp $ */
/* /*
* Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved.
* *
@ -34,7 +34,8 @@
#include "openbsd-compat/sys-queue.h" #include "openbsd-compat/sys-queue.h"
#include "ssh2.h" #include "ssh2.h"
#include "buffer.h" #include "sshbuf.h"
#include "ssherr.h"
#include "packet.h" #include "packet.h"
#include "channels.h" #include "channels.h"
#include "compat.h" #include "compat.h"
@ -73,15 +74,15 @@
/* /*
* ACTIONS: should never update the channel states * ACTIONS: should never update the channel states
*/ */
static void chan_send_eof2(Channel *); static void chan_send_eof2(struct ssh *, Channel *);
static void chan_send_eow2(Channel *); static void chan_send_eow2(struct ssh *, Channel *);
/* helper */ /* helper */
static void chan_shutdown_write(Channel *); static void chan_shutdown_write(struct ssh *, Channel *);
static void chan_shutdown_read(Channel *); static void chan_shutdown_read(struct ssh *, Channel *);
static char *ostates[] = { "open", "drain", "wait_ieof", "closed" }; static const char *ostates[] = { "open", "drain", "wait_ieof", "closed" };
static char *istates[] = { "open", "drain", "wait_oclose", "closed" }; static const char *istates[] = { "open", "drain", "wait_oclose", "closed" };
static void static void
chan_set_istate(Channel *c, u_int next) chan_set_istate(Channel *c, u_int next)
@ -104,12 +105,12 @@ chan_set_ostate(Channel *c, u_int next)
} }
void void
chan_read_failed(Channel *c) chan_read_failed(struct ssh *ssh, Channel *c)
{ {
debug2("channel %d: read failed", c->self); debug2("channel %d: read failed", c->self);
switch (c->istate) { switch (c->istate) {
case CHAN_INPUT_OPEN: case CHAN_INPUT_OPEN:
chan_shutdown_read(c); chan_shutdown_read(ssh, c);
chan_set_istate(c, CHAN_INPUT_WAIT_DRAIN); chan_set_istate(c, CHAN_INPUT_WAIT_DRAIN);
break; break;
default: default:
@ -120,10 +121,10 @@ chan_read_failed(Channel *c)
} }
void void
chan_ibuf_empty(Channel *c) chan_ibuf_empty(struct ssh *ssh, Channel *c)
{ {
debug2("channel %d: ibuf empty", c->self); debug2("channel %d: ibuf empty", c->self);
if (buffer_len(&c->input)) { if (sshbuf_len(c->input)) {
error("channel %d: chan_ibuf_empty for non empty buffer", error("channel %d: chan_ibuf_empty for non empty buffer",
c->self); c->self);
return; return;
@ -131,7 +132,7 @@ chan_ibuf_empty(Channel *c)
switch (c->istate) { switch (c->istate) {
case CHAN_INPUT_WAIT_DRAIN: case CHAN_INPUT_WAIT_DRAIN:
if (!(c->flags & (CHAN_CLOSE_SENT|CHAN_LOCAL))) if (!(c->flags & (CHAN_CLOSE_SENT|CHAN_LOCAL)))
chan_send_eof2(c); chan_send_eof2(ssh, c);
chan_set_istate(c, CHAN_INPUT_CLOSED); chan_set_istate(c, CHAN_INPUT_CLOSED);
break; break;
default: default:
@ -142,17 +143,17 @@ chan_ibuf_empty(Channel *c)
} }
void void
chan_obuf_empty(Channel *c) chan_obuf_empty(struct ssh *ssh, Channel *c)
{ {
debug2("channel %d: obuf empty", c->self); debug2("channel %d: obuf empty", c->self);
if (buffer_len(&c->output)) { if (sshbuf_len(c->output)) {
error("channel %d: chan_obuf_empty for non empty buffer", error("channel %d: chan_obuf_empty for non empty buffer",
c->self); c->self);
return; return;
} }
switch (c->ostate) { switch (c->ostate) {
case CHAN_OUTPUT_WAIT_DRAIN: case CHAN_OUTPUT_WAIT_DRAIN:
chan_shutdown_write(c); chan_shutdown_write(ssh, c);
chan_set_ostate(c, CHAN_OUTPUT_CLOSED); chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
break; break;
default: default:
@ -163,26 +164,32 @@ chan_obuf_empty(Channel *c)
} }
void void
chan_rcvd_eow(Channel *c) chan_rcvd_eow(struct ssh *ssh, Channel *c)
{ {
debug2("channel %d: rcvd eow", c->self); debug2("channel %d: rcvd eow", c->self);
switch (c->istate) { switch (c->istate) {
case CHAN_INPUT_OPEN: case CHAN_INPUT_OPEN:
chan_shutdown_read(c); chan_shutdown_read(ssh, c);
chan_set_istate(c, CHAN_INPUT_CLOSED); chan_set_istate(c, CHAN_INPUT_CLOSED);
break; break;
} }
} }
static void static void
chan_send_eof2(Channel *c) chan_send_eof2(struct ssh *ssh, Channel *c)
{ {
int r;
debug2("channel %d: send eof", c->self); debug2("channel %d: send eof", c->self);
switch (c->istate) { switch (c->istate) {
case CHAN_INPUT_WAIT_DRAIN: case CHAN_INPUT_WAIT_DRAIN:
packet_start(SSH2_MSG_CHANNEL_EOF); if (!c->have_remote_id)
packet_put_int(c->remote_id); fatal("%s: channel %d: no remote_id",
packet_send(); __func__, c->self);
if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_EOF)) != 0 ||
(r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
fatal("%s: send CHANNEL_EOF: %s", __func__, ssh_err(r));
c->flags |= CHAN_EOF_SENT; c->flags |= CHAN_EOF_SENT;
break; break;
default: default:
@ -193,8 +200,10 @@ chan_send_eof2(Channel *c)
} }
static void static void
chan_send_close2(Channel *c) chan_send_close2(struct ssh *ssh, Channel *c)
{ {
int r;
debug2("channel %d: send close", c->self); debug2("channel %d: send close", c->self);
if (c->ostate != CHAN_OUTPUT_CLOSED || if (c->ostate != CHAN_OUTPUT_CLOSED ||
c->istate != CHAN_INPUT_CLOSED) { c->istate != CHAN_INPUT_CLOSED) {
@ -203,16 +212,22 @@ chan_send_close2(Channel *c)
} else if (c->flags & CHAN_CLOSE_SENT) { } else if (c->flags & CHAN_CLOSE_SENT) {
error("channel %d: already sent close", c->self); error("channel %d: already sent close", c->self);
} else { } else {
packet_start(SSH2_MSG_CHANNEL_CLOSE); if (!c->have_remote_id)
packet_put_int(c->remote_id); fatal("%s: channel %d: no remote_id",
packet_send(); __func__, c->self);
if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_CLOSE)) != 0 ||
(r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
fatal("%s: send CHANNEL_EOF: %s", __func__, ssh_err(r));
c->flags |= CHAN_CLOSE_SENT; c->flags |= CHAN_CLOSE_SENT;
} }
} }
static void static void
chan_send_eow2(Channel *c) chan_send_eow2(struct ssh *ssh, Channel *c)
{ {
int r;
debug2("channel %d: send eow", c->self); debug2("channel %d: send eow", c->self);
if (c->ostate == CHAN_OUTPUT_CLOSED) { if (c->ostate == CHAN_OUTPUT_CLOSED) {
error("channel %d: must not sent eow on closed output", error("channel %d: must not sent eow on closed output",
@ -221,30 +236,33 @@ chan_send_eow2(Channel *c)
} }
if (!(datafellows & SSH_NEW_OPENSSH)) if (!(datafellows & SSH_NEW_OPENSSH))
return; return;
packet_start(SSH2_MSG_CHANNEL_REQUEST); if (!c->have_remote_id)
packet_put_int(c->remote_id); fatal("%s: channel %d: no remote_id", __func__, c->self);
packet_put_cstring("eow@openssh.com"); if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_REQUEST)) != 0 ||
packet_put_char(0); (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||
packet_send(); (r = sshpkt_put_cstring(ssh, "eow@openssh.com")) != 0 ||
(r = sshpkt_put_u8(ssh, 0)) != 0 ||
(r = sshpkt_send(ssh)) != 0)
fatal("%s: send CHANNEL_EOF: %s", __func__, ssh_err(r));
} }
/* shared */ /* shared */
void void
chan_rcvd_ieof(Channel *c) chan_rcvd_ieof(struct ssh *ssh, Channel *c)
{ {
debug2("channel %d: rcvd eof", c->self); debug2("channel %d: rcvd eof", c->self);
c->flags |= CHAN_EOF_RCVD; c->flags |= CHAN_EOF_RCVD;
if (c->ostate == CHAN_OUTPUT_OPEN) if (c->ostate == CHAN_OUTPUT_OPEN)
chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN); chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN);
if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN && if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN &&
buffer_len(&c->output) == 0 && sshbuf_len(c->output) == 0 &&
!CHANNEL_EFD_OUTPUT_ACTIVE(c)) !CHANNEL_EFD_OUTPUT_ACTIVE(c))
chan_obuf_empty(c); chan_obuf_empty(ssh, c);
} }
void void
chan_rcvd_oclose(Channel *c) chan_rcvd_oclose(struct ssh *ssh, Channel *c)
{ {
debug2("channel %d: rcvd close", c->self); debug2("channel %d: rcvd close", c->self);
if (!(c->flags & CHAN_LOCAL)) { if (!(c->flags & CHAN_LOCAL)) {
@ -270,27 +288,27 @@ chan_rcvd_oclose(Channel *c)
} }
switch (c->istate) { switch (c->istate) {
case CHAN_INPUT_OPEN: case CHAN_INPUT_OPEN:
chan_shutdown_read(c); chan_shutdown_read(ssh, c);
chan_set_istate(c, CHAN_INPUT_CLOSED); chan_set_istate(c, CHAN_INPUT_CLOSED);
break; break;
case CHAN_INPUT_WAIT_DRAIN: case CHAN_INPUT_WAIT_DRAIN:
if (!(c->flags & CHAN_LOCAL)) if (!(c->flags & CHAN_LOCAL))
chan_send_eof2(c); chan_send_eof2(ssh, c);
chan_set_istate(c, CHAN_INPUT_CLOSED); chan_set_istate(c, CHAN_INPUT_CLOSED);
break; break;
} }
} }
void void
chan_write_failed(Channel *c) chan_write_failed(struct ssh *ssh, Channel *c)
{ {
debug2("channel %d: write failed", c->self); debug2("channel %d: write failed", c->self);
switch (c->ostate) { switch (c->ostate) {
case CHAN_OUTPUT_OPEN: case CHAN_OUTPUT_OPEN:
case CHAN_OUTPUT_WAIT_DRAIN: case CHAN_OUTPUT_WAIT_DRAIN:
chan_shutdown_write(c); chan_shutdown_write(ssh, c);
if (strcmp(c->ctype, "session") == 0) if (strcmp(c->ctype, "session") == 0)
chan_send_eow2(c); chan_send_eow2(ssh, c);
chan_set_ostate(c, CHAN_OUTPUT_CLOSED); chan_set_ostate(c, CHAN_OUTPUT_CLOSED);
break; break;
default: default:
@ -301,13 +319,13 @@ chan_write_failed(Channel *c)
} }
void void
chan_mark_dead(Channel *c) chan_mark_dead(struct ssh *ssh, Channel *c)
{ {
c->type = SSH_CHANNEL_ZOMBIE; c->type = SSH_CHANNEL_ZOMBIE;
} }
int int
chan_is_dead(Channel *c, int do_send) chan_is_dead(struct ssh *ssh, Channel *c, int do_send)
{ {
if (c->type == SSH_CHANNEL_ZOMBIE) { if (c->type == SSH_CHANNEL_ZOMBIE) {
debug2("channel %d: zombie", c->self); debug2("channel %d: zombie", c->self);
@ -318,9 +336,9 @@ chan_is_dead(Channel *c, int do_send)
if ((datafellows & SSH_BUG_EXTEOF) && if ((datafellows & SSH_BUG_EXTEOF) &&
c->extended_usage == CHAN_EXTENDED_WRITE && c->extended_usage == CHAN_EXTENDED_WRITE &&
c->efd != -1 && c->efd != -1 &&
buffer_len(&c->extended) > 0) { sshbuf_len(c->extended) > 0) {
debug2("channel %d: active efd: %d len %d", debug2("channel %d: active efd: %d len %zu",
c->self, c->efd, buffer_len(&c->extended)); c->self, c->efd, sshbuf_len(c->extended));
return 0; return 0;
} }
if (c->flags & CHAN_LOCAL) { if (c->flags & CHAN_LOCAL) {
@ -329,7 +347,7 @@ chan_is_dead(Channel *c, int do_send)
} }
if (!(c->flags & CHAN_CLOSE_SENT)) { if (!(c->flags & CHAN_CLOSE_SENT)) {
if (do_send) { if (do_send) {
chan_send_close2(c); chan_send_close2(ssh, c);
} else { } else {
/* channel would be dead if we sent a close */ /* channel would be dead if we sent a close */
if (c->flags & CHAN_CLOSE_RCVD) { if (c->flags & CHAN_CLOSE_RCVD) {
@ -349,9 +367,9 @@ chan_is_dead(Channel *c, int do_send)
/* helper */ /* helper */
static void static void
chan_shutdown_write(Channel *c) chan_shutdown_write(struct ssh *ssh, Channel *c)
{ {
buffer_clear(&c->output); sshbuf_reset(c->output);
if (c->type == SSH_CHANNEL_LARVAL) if (c->type == SSH_CHANNEL_LARVAL)
return; return;
/* shutdown failure is allowed if write failed already */ /* shutdown failure is allowed if write failed already */
@ -362,7 +380,7 @@ chan_shutdown_write(Channel *c)
"shutdown() failed for fd %d: %.100s", "shutdown() failed for fd %d: %.100s",
c->self, c->sock, strerror(errno)); c->self, c->sock, strerror(errno));
} else { } else {
if (channel_close_fd(&c->wfd) < 0) if (channel_close_fd(ssh, &c->wfd) < 0)
logit("channel %d: chan_shutdown_write: " logit("channel %d: chan_shutdown_write: "
"close() failed for fd %d: %.100s", "close() failed for fd %d: %.100s",
c->self, c->wfd, strerror(errno)); c->self, c->wfd, strerror(errno));
@ -370,7 +388,7 @@ chan_shutdown_write(Channel *c)
} }
static void static void
chan_shutdown_read(Channel *c) chan_shutdown_read(struct ssh *ssh, Channel *c)
{ {
if (c->type == SSH_CHANNEL_LARVAL) if (c->type == SSH_CHANNEL_LARVAL)
return; return;
@ -388,7 +406,7 @@ chan_shutdown_read(Channel *c)
c->self, c->sock, c->istate, c->ostate, c->self, c->sock, c->istate, c->ostate,
strerror(errno)); strerror(errno));
} else { } else {
if (channel_close_fd(&c->rfd) < 0) if (channel_close_fd(ssh, &c->rfd) < 0)
logit("channel %d: chan_shutdown_read: " logit("channel %d: chan_shutdown_read: "
"close() failed for fd %d: %.100s", "close() failed for fd %d: %.100s",
c->self, c->rfd, strerror(errno)); c->self, c->rfd, strerror(errno));

View File

@ -16,9 +16,9 @@ RANLIB=@RANLIB@
INSTALL=@INSTALL@ INSTALL=@INSTALL@
LDFLAGS=-L. @LDFLAGS@ LDFLAGS=-L. @LDFLAGS@
OPENBSD=base64.o basename.o bcrypt_pbkdf.o bindresvport.o blowfish.o daemon.o dirname.o fmt_scaled.o getcwd.o getgrouplist.o getopt_long.o getrrsetbyname.o glob.o inet_aton.o inet_ntoa.o inet_ntop.o mktemp.o pwcache.o readpassphrase.o reallocarray.o realpath.o recallocarray.o rresvport.o setenv.o setproctitle.o sha1.o sha2.o rmd160.o md5.o sigact.o strcasestr.o strlcat.o strlcpy.o strmode.o strnlen.o strptime.o strsep.o strtonum.o strtoll.o strtoul.o strtoull.o timingsafe_bcmp.o vis.o blowfish.o bcrypt_pbkdf.o explicit_bzero.o OPENBSD=base64.o basename.o bcrypt_pbkdf.o bindresvport.o blowfish.o daemon.o dirname.o fmt_scaled.o getcwd.o getgrouplist.o getopt_long.o getrrsetbyname.o glob.o inet_aton.o inet_ntoa.o inet_ntop.o mktemp.o pwcache.o readpassphrase.o reallocarray.o realpath.o recallocarray.o rresvport.o setenv.o setproctitle.o sha1.o sha2.o rmd160.o md5.o sigact.o strcasestr.o strlcat.o strlcpy.o strmode.o strnlen.o strptime.o strsep.o strtonum.o strtoll.o strtoul.o strtoull.o timingsafe_bcmp.o vis.o blowfish.o bcrypt_pbkdf.o explicit_bzero.o freezero.o
COMPAT=arc4random.o bsd-asprintf.o bsd-closefrom.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o getrrsetbyname-ldns.o bsd-err.o bsd-getpagesize.o bsd-misc.o bsd-nextstep.o bsd-openpty.o bsd-poll.o bsd-setres_id.o bsd-snprintf.o bsd-statvfs.o bsd-waitpid.o fake-rfc2553.o openssl-compat.o xcrypt.o kludge-fd_set.o COMPAT=arc4random.o bsd-asprintf.o bsd-closefrom.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o getrrsetbyname-ldns.o bsd-err.o bsd-getpagesize.o bsd-misc.o bsd-nextstep.o bsd-openpty.o bsd-poll.o bsd-malloc.o bsd-setres_id.o bsd-snprintf.o bsd-statvfs.o bsd-waitpid.o fake-rfc2553.o openssl-compat.o xcrypt.o kludge-fd_set.o
PORTS=port-aix.o port-irix.o port-linux.o port-solaris.o port-tun.o port-uw.o PORTS=port-aix.o port-irix.o port-linux.o port-solaris.o port-tun.o port-uw.o

View File

@ -0,0 +1,55 @@
/*
* Copyright (c) 2017 Darren Tucker (dtucker at zip com au).
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "config.h"
#undef malloc
#undef calloc
#undef realloc
#include <sys/types.h>
#include <stdlib.h>
#if defined(HAVE_MALLOC) && HAVE_MALLOC == 0
void *
rpl_malloc(size_t size)
{
if (size == 0)
size = 1;
return malloc(size);
}
#endif
#if defined(HAVE_CALLOC) && HAVE_CALLOC == 0
void *
rpl_calloc(size_t nmemb, size_t size)
{
if (nmemb == 0)
nmemb = 1;
if (size == 0)
size = 1;
return calloc(nmemb, size);
}
#endif
#if defined (HAVE_REALLOC) && HAVE_REALLOC == 0
void *
rpl_realloc(void *ptr, size_t size)
{
if (size == 0)
size = 1;
return realloc(ptr, size);
}
#endif

View File

@ -104,6 +104,16 @@ const char *strerror(int e)
} }
#endif #endif
#if !defined(HAVE_STRSIGNAL)
char *strsignal(int sig)
{
static char buf[16];
(void)snprintf(buf, sizeof(buf), "%d", sig);
return buf;
}
#endif
#ifndef HAVE_UTIMES #ifndef HAVE_UTIMES
int utimes(char *filename, struct timeval *tvp) int utimes(char *filename, struct timeval *tvp)
{ {

View File

@ -49,6 +49,10 @@ int setegid(uid_t);
const char *strerror(int); const char *strerror(int);
#endif #endif
#if !defined(HAVE_STRSIGNAL)
char *strsignal(int);
#endif
#if !defined(HAVE_SETLINEBUF) #if !defined(HAVE_SETLINEBUF)
#define setlinebuf(a) (setvbuf((a), NULL, _IOLBF, 0)) #define setlinebuf(a) (setvbuf((a), NULL, _IOLBF, 0))
#endif #endif

29
openbsd-compat/freezero.c Normal file
View File

@ -0,0 +1,29 @@
/*
* Copyright (c) 2008, 2010, 2011, 2016 Otto Moerbeek <otto@drijf.net>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "includes.h"
#ifndef HAVE_FREEZERO
void
freezero(void *ptr, size_t sz)
{
explicit_bzero(ptr, sz);
free(ptr);
}
#endif /* HAVE_FREEZERO */

View File

@ -307,6 +307,10 @@ int bcrypt_pbkdf(const char *, size_t, const u_int8_t *, size_t,
void explicit_bzero(void *p, size_t n); void explicit_bzero(void *p, size_t n);
#endif #endif
#ifndef HAVE_FREEZERO
void freezero(void *, size_t);
#endif
char *xcrypt(const char *password, const char *salt); char *xcrypt(const char *password, const char *salt);
char *shadow_pw(struct passwd *pw); char *shadow_pw(struct passwd *pw);

View File

@ -207,7 +207,7 @@ sys_tun_open(int tun, int mode)
#define OPENBSD_AF_INET6 24 #define OPENBSD_AF_INET6 24
int int
sys_tun_infilter(struct Channel *c, char *buf, int _len) sys_tun_infilter(struct ssh *ssh, struct Channel *c, char *buf, int _len)
{ {
int r; int r;
size_t len; size_t len;
@ -245,24 +245,22 @@ sys_tun_infilter(struct Channel *c, char *buf, int _len)
POKE_U32(buf, af == AF_INET6 ? OPENBSD_AF_INET6 : OPENBSD_AF_INET); POKE_U32(buf, af == AF_INET6 ? OPENBSD_AF_INET6 : OPENBSD_AF_INET);
#endif #endif
if ((r = sshbuf_put_string(&c->input, ptr, len)) != 0) if ((r = sshbuf_put_string(c->input, ptr, len)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r)); fatal("%s: buffer error: %s", __func__, ssh_err(r));
return (0); return (0);
} }
u_char * u_char *
sys_tun_outfilter(struct Channel *c, u_char **data, u_int *dlen) sys_tun_outfilter(struct ssh *ssh, struct Channel *c,
u_char **data, size_t *dlen)
{ {
u_char *buf; u_char *buf;
u_int32_t af; u_int32_t af;
int r; int r;
size_t xxx_dlen;
/* XXX new API is incompatible with this signature. */ /* XXX new API is incompatible with this signature. */
if ((r = sshbuf_get_string(&c->output, data, &xxx_dlen)) != 0) if ((r = sshbuf_get_string(c->output, data, dlen)) != 0)
fatal("%s: buffer error: %s", __func__, ssh_err(r)); fatal("%s: buffer error: %s", __func__, ssh_err(r));
if (dlen != NULL)
*dlen = xxx_dlen;
if (*dlen < sizeof(af)) if (*dlen < sizeof(af))
return (NULL); return (NULL);
buf = *data; buf = *data;

View File

@ -18,6 +18,7 @@
#define _PORT_TUN_H #define _PORT_TUN_H
struct Channel; struct Channel;
struct ssh;
#if defined(SSH_TUN_LINUX) || defined(SSH_TUN_FREEBSD) #if defined(SSH_TUN_LINUX) || defined(SSH_TUN_FREEBSD)
# define CUSTOM_SYS_TUN_OPEN # define CUSTOM_SYS_TUN_OPEN
@ -26,8 +27,8 @@ int sys_tun_open(int, int);
#if defined(SSH_TUN_COMPAT_AF) || defined(SSH_TUN_PREPEND_AF) #if defined(SSH_TUN_COMPAT_AF) || defined(SSH_TUN_PREPEND_AF)
# define SSH_TUN_FILTER # define SSH_TUN_FILTER
int sys_tun_infilter(struct Channel *, char *, int); int sys_tun_infilter(struct ssh *, struct Channel *, char *, int);
u_char *sys_tun_outfilter(struct Channel *, u_char **, u_int *); u_char *sys_tun_outfilter(struct ssh *, struct Channel *, u_char **, size_t *);
#endif #endif
#endif #endif

View File

@ -1,4 +1,4 @@
/* $OpenBSD: packet.c,v 1.263 2017/07/23 23:37:02 djm Exp $ */ /* $OpenBSD: packet.c,v 1.264 2017/09/12 06:32:07 djm Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -2090,35 +2090,6 @@ ssh_packet_get_maxsize(struct ssh *ssh)
return ssh->state->max_packet_size; return ssh->state->max_packet_size;
} }
/*
* 9.2. Ignored Data Message
*
* byte SSH_MSG_IGNORE
* string data
*
* All implementations MUST understand (and ignore) this message at any
* time (after receiving the protocol version). No implementation is
* required to send them. This message can be used as an additional
* protection measure against advanced traffic analysis techniques.
*/
void
ssh_packet_send_ignore(struct ssh *ssh, int nbytes)
{
u_int32_t rnd = 0;
int r, i;
if ((r = sshpkt_start(ssh, SSH2_MSG_IGNORE)) != 0 ||
(r = sshpkt_put_u32(ssh, nbytes)) != 0)
fatal("%s: %s", __func__, ssh_err(r));
for (i = 0; i < nbytes; i++) {
if (i % 4 == 0)
rnd = arc4random();
if ((r = sshpkt_put_u8(ssh, (u_char)rnd & 0xff)) != 0)
fatal("%s: %s", __func__, ssh_err(r));
rnd >>= 8;
}
}
void void
ssh_packet_set_rekey_limits(struct ssh *ssh, u_int64_t bytes, u_int32_t seconds) ssh_packet_set_rekey_limits(struct ssh *ssh, u_int64_t bytes, u_int32_t seconds)
{ {
@ -2538,6 +2509,12 @@ sshpkt_get_string_direct(struct ssh *ssh, const u_char **valp, size_t *lenp)
return sshbuf_get_string_direct(ssh->state->incoming_packet, valp, lenp); return sshbuf_get_string_direct(ssh->state->incoming_packet, valp, lenp);
} }
int
sshpkt_peek_string_direct(struct ssh *ssh, const u_char **valp, size_t *lenp)
{
return sshbuf_peek_string_direct(ssh->state->incoming_packet, valp, lenp);
}
int int
sshpkt_get_cstring(struct ssh *ssh, char **valp, size_t *lenp) sshpkt_get_cstring(struct ssh *ssh, char **valp, size_t *lenp)
{ {
@ -2621,6 +2598,37 @@ ssh_packet_send_mux(struct ssh *ssh)
return 0; return 0;
} }
/*
* 9.2. Ignored Data Message
*
* byte SSH_MSG_IGNORE
* string data
*
* All implementations MUST understand (and ignore) this message at any
* time (after receiving the protocol version). No implementation is
* required to send them. This message can be used as an additional
* protection measure against advanced traffic analysis techniques.
*/
int
sshpkt_msg_ignore(struct ssh *ssh, u_int nbytes)
{
u_int32_t rnd = 0;
int r;
u_int i;
if ((r = sshpkt_start(ssh, SSH2_MSG_IGNORE)) != 0 ||
(r = sshpkt_put_u32(ssh, nbytes)) != 0)
return r;
for (i = 0; i < nbytes; i++) {
if (i % 4 == 0)
rnd = arc4random();
if ((r = sshpkt_put_u8(ssh, (u_char)rnd & 0xff)) != 0)
return r;
rnd >>= 8;
}
return 0;
}
/* send it */ /* send it */
int int

View File

@ -1,4 +1,4 @@
/* $OpenBSD: packet.h,v 1.81 2017/05/31 08:09:45 markus Exp $ */ /* $OpenBSD: packet.h,v 1.82 2017/09/12 06:32:07 djm Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -80,6 +80,9 @@ struct ssh {
/* Client/Server authentication context */ /* Client/Server authentication context */
void *authctxt; void *authctxt;
/* Channels context */
struct ssh_channels *chanctxt;
/* APP data */ /* APP data */
void *app_data; void *app_data;
}; };
@ -143,7 +146,6 @@ int ssh_packet_not_very_much_data_to_write(struct ssh *);
int ssh_packet_connection_is_on_socket(struct ssh *); int ssh_packet_connection_is_on_socket(struct ssh *);
int ssh_packet_remaining(struct ssh *); int ssh_packet_remaining(struct ssh *);
void ssh_packet_send_ignore(struct ssh *, int);
void tty_make_modes(int, struct termios *); void tty_make_modes(int, struct termios *);
void tty_parse_modes(int, int *); void tty_parse_modes(int, int *);
@ -174,6 +176,7 @@ int sshpkt_disconnect(struct ssh *, const char *fmt, ...)
__attribute__((format(printf, 2, 3))); __attribute__((format(printf, 2, 3)));
int sshpkt_add_padding(struct ssh *, u_char); int sshpkt_add_padding(struct ssh *, u_char);
void sshpkt_fatal(struct ssh *ssh, const char *tag, int r); void sshpkt_fatal(struct ssh *ssh, const char *tag, int r);
int sshpkt_msg_ignore(struct ssh *, u_int);
int sshpkt_put(struct ssh *ssh, const void *v, size_t len); int sshpkt_put(struct ssh *ssh, const void *v, size_t len);
int sshpkt_putb(struct ssh *ssh, const struct sshbuf *b); int sshpkt_putb(struct ssh *ssh, const struct sshbuf *b);
@ -192,6 +195,7 @@ int sshpkt_get_u32(struct ssh *ssh, u_int32_t *valp);
int sshpkt_get_u64(struct ssh *ssh, u_int64_t *valp); int sshpkt_get_u64(struct ssh *ssh, u_int64_t *valp);
int sshpkt_get_string(struct ssh *ssh, u_char **valp, size_t *lenp); int sshpkt_get_string(struct ssh *ssh, u_char **valp, size_t *lenp);
int sshpkt_get_string_direct(struct ssh *ssh, const u_char **valp, size_t *lenp); int sshpkt_get_string_direct(struct ssh *ssh, const u_char **valp, size_t *lenp);
int sshpkt_peek_string_direct(struct ssh *ssh, const u_char **valp, size_t *lenp);
int sshpkt_get_cstring(struct ssh *ssh, char **valp, size_t *lenp); int sshpkt_get_cstring(struct ssh *ssh, char **valp, size_t *lenp);
int sshpkt_get_ec(struct ssh *ssh, EC_POINT *v, const EC_GROUP *g); int sshpkt_get_ec(struct ssh *ssh, EC_POINT *v, const EC_GROUP *g);
int sshpkt_get_bignum2(struct ssh *ssh, BIGNUM *v); int sshpkt_get_bignum2(struct ssh *ssh, BIGNUM *v);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: readconf.c,v 1.277 2017/05/30 18:58:37 bluhm Exp $ */ /* $OpenBSD: readconf.c,v 1.279 2017/09/21 19:16:53 markus Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -757,6 +757,16 @@ static const struct multistate multistate_yesnoask[] = {
{ "ask", 2 }, { "ask", 2 },
{ NULL, -1 } { NULL, -1 }
}; };
static const struct multistate multistate_strict_hostkey[] = {
{ "true", SSH_STRICT_HOSTKEY_YES },
{ "false", SSH_STRICT_HOSTKEY_OFF },
{ "yes", SSH_STRICT_HOSTKEY_YES },
{ "no", SSH_STRICT_HOSTKEY_OFF },
{ "ask", SSH_STRICT_HOSTKEY_ASK },
{ "off", SSH_STRICT_HOSTKEY_OFF },
{ "accept-new", SSH_STRICT_HOSTKEY_NEW },
{ NULL, -1 }
};
static const struct multistate multistate_yesnoaskconfirm[] = { static const struct multistate multistate_yesnoaskconfirm[] = {
{ "true", 1 }, { "true", 1 },
{ "false", 0 }, { "false", 0 },
@ -832,6 +842,7 @@ process_config_line_depth(Options *options, struct passwd *pw, const char *host,
char **cpptr, fwdarg[256]; char **cpptr, fwdarg[256];
u_int i, *uintptr, max_entries = 0; u_int i, *uintptr, max_entries = 0;
int r, oactive, negated, opcode, *intptr, value, value2, cmdline = 0; int r, oactive, negated, opcode, *intptr, value, value2, cmdline = 0;
int remotefwd, dynamicfwd;
LogLevel *log_level_ptr; LogLevel *log_level_ptr;
SyslogFacility *log_facility_ptr; SyslogFacility *log_facility_ptr;
long long val64; long long val64;
@ -990,7 +1001,7 @@ parse_time:
case oStrictHostKeyChecking: case oStrictHostKeyChecking:
intptr = &options->strict_host_key_checking; intptr = &options->strict_host_key_checking;
multistate_ptr = multistate_yesnoask; multistate_ptr = multistate_strict_hostkey;
goto parse_multistate; goto parse_multistate;
case oCompression: case oCompression:
@ -1251,31 +1262,36 @@ parse_keytypes:
fatal("%.200s line %d: Missing port argument.", fatal("%.200s line %d: Missing port argument.",
filename, linenum); filename, linenum);
if (opcode == oLocalForward || remotefwd = (opcode == oRemoteForward);
opcode == oRemoteForward) { dynamicfwd = (opcode == oDynamicForward);
if (!dynamicfwd) {
arg2 = strdelim(&s); arg2 = strdelim(&s);
if (arg2 == NULL || *arg2 == '\0') if (arg2 == NULL || *arg2 == '\0') {
fatal("%.200s line %d: Missing target argument.", if (remotefwd)
filename, linenum); dynamicfwd = 1;
else
fatal("%.200s line %d: Missing target "
"argument.", filename, linenum);
} else {
/* construct a string for parse_forward */ /* construct a string for parse_forward */
snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2); snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg,
} else if (opcode == oDynamicForward) { arg2);
strlcpy(fwdarg, arg, sizeof(fwdarg));
} }
}
if (dynamicfwd)
strlcpy(fwdarg, arg, sizeof(fwdarg));
if (parse_forward(&fwd, fwdarg, if (parse_forward(&fwd, fwdarg, dynamicfwd, remotefwd) == 0)
opcode == oDynamicForward ? 1 : 0,
opcode == oRemoteForward ? 1 : 0) == 0)
fatal("%.200s line %d: Bad forwarding specification.", fatal("%.200s line %d: Bad forwarding specification.",
filename, linenum); filename, linenum);
if (*activep) { if (*activep) {
if (opcode == oLocalForward || if (remotefwd) {
opcode == oDynamicForward)
add_local_forward(options, &fwd);
else if (opcode == oRemoteForward)
add_remote_forward(options, &fwd); add_remote_forward(options, &fwd);
} else {
add_local_forward(options, &fwd);
}
} }
break; break;
@ -1944,7 +1960,7 @@ fill_default_options(Options * options)
if (options->check_host_ip == -1) if (options->check_host_ip == -1)
options->check_host_ip = 1; options->check_host_ip = 1;
if (options->strict_host_key_checking == -1) if (options->strict_host_key_checking == -1)
options->strict_host_key_checking = 2; /* 2 is default */ options->strict_host_key_checking = SSH_STRICT_HOSTKEY_ASK;
if (options->compression == -1) if (options->compression == -1)
options->compression = 0; options->compression = 0;
if (options->tcp_keep_alive == -1) if (options->tcp_keep_alive == -1)
@ -2346,9 +2362,10 @@ fmt_intarg(OpCodes code, int val)
case oAddressFamily: case oAddressFamily:
return fmt_multistate_int(val, multistate_addressfamily); return fmt_multistate_int(val, multistate_addressfamily);
case oVerifyHostKeyDNS: case oVerifyHostKeyDNS:
case oStrictHostKeyChecking:
case oUpdateHostkeys: case oUpdateHostkeys:
return fmt_multistate_int(val, multistate_yesnoask); return fmt_multistate_int(val, multistate_yesnoask);
case oStrictHostKeyChecking:
return fmt_multistate_int(val, multistate_strict_hostkey);
case oControlMaster: case oControlMaster:
return fmt_multistate_int(val, multistate_controlmaster); return fmt_multistate_int(val, multistate_controlmaster);
case oTunnel: case oTunnel:

View File

@ -1,4 +1,4 @@
/* $OpenBSD: readconf.h,v 1.122 2017/05/30 18:58:37 bluhm Exp $ */ /* $OpenBSD: readconf.h,v 1.123 2017/09/03 23:33:13 djm Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -190,6 +190,11 @@ typedef struct {
#define SSH_UPDATE_HOSTKEYS_YES 1 #define SSH_UPDATE_HOSTKEYS_YES 1
#define SSH_UPDATE_HOSTKEYS_ASK 2 #define SSH_UPDATE_HOSTKEYS_ASK 2
#define SSH_STRICT_HOSTKEY_OFF 0
#define SSH_STRICT_HOSTKEY_NEW 1
#define SSH_STRICT_HOSTKEY_YES 2
#define SSH_STRICT_HOSTKEY_ASK 3
void initialize_options(Options *); void initialize_options(Options *);
void fill_default_options(Options *); void fill_default_options(Options *);
void fill_default_options_for_canonicalization(Options *); void fill_default_options_for_canonicalization(Options *);

View File

@ -1,4 +1,4 @@
# $OpenBSD: agent-getpeereid.sh,v 1.8 2017/01/06 02:51:16 djm Exp $ # $OpenBSD: agent-getpeereid.sh,v 1.9 2017/09/13 14:58:26 bluhm Exp $
# Placed in the Public Domain. # Placed in the Public Domain.
tid="disallow agent attach from other uid" tid="disallow agent attach from other uid"

View File

@ -1,4 +1,4 @@
# $OpenBSD: dynamic-forward.sh,v 1.12 2017/04/30 23:34:55 djm Exp $ # $OpenBSD: dynamic-forward.sh,v 1.13 2017/09/21 19:18:12 markus Exp $
# Placed in the Public Domain. # Placed in the Public Domain.
tid="dynamic forwarding" tid="dynamic forwarding"
@ -17,33 +17,34 @@ trace "will use ProxyCommand $proxycmd"
start_sshd start_sshd
for p in ${SSH_PROTOCOLS}; do for d in D R; do
n=0 n=0
error="1" error="1"
trace "start dynamic forwarding, fork to background" trace "start dynamic forwarding, fork to background"
while [ "$error" -ne 0 -a "$n" -lt 3 ]; do while [ "$error" -ne 0 -a "$n" -lt 3 ]; do
n=`expr $n + 1` n=`expr $n + 1`
${SSH} -$p -F $OBJ/ssh_config -f -D $FWDPORT -q \ ${SSH} -F $OBJ/ssh_config -f -$d $FWDPORT -q \
-oExitOnForwardFailure=yes somehost exec sh -c \ -oExitOnForwardFailure=yes somehost exec sh -c \
\'"echo \$\$ > $OBJ/remote_pid; exec sleep 444"\' \'"echo \$\$ > $OBJ/remote_pid; exec sleep 444"\'
error=$? error=$?
if [ "$error" -ne 0 ]; then if [ "$error" -ne 0 ]; then
trace "forward failed proto $p attempt $n err $error" trace "forward failed attempt $n err $error"
sleep $n sleep $n
fi fi
done done
if [ "$error" -ne 0 ]; then if [ "$error" -ne 0 ]; then
fatal "failed to start dynamic forwarding proto $p" fatal "failed to start dynamic forwarding"
fi fi
for s in 4 5; do for s in 4 5; do
for h in 127.0.0.1 localhost; do for h in 127.0.0.1 localhost; do
trace "testing ssh protocol $p socks version $s host $h" trace "testing ssh socks version $s host $h (-$d)"
${SSH} -F $OBJ/ssh_config \ ${SSH} -F $OBJ/ssh_config \
-o "ProxyCommand ${proxycmd}${s} $h $PORT" \ -o "ProxyCommand ${proxycmd}${s} $h $PORT" \
somehost cat $DATA > $OBJ/ls.copy somehost cat ${DATA} > ${COPY}
test -f $OBJ/ls.copy || fail "failed copy $DATA" test -f ${COPY} || fail "failed copy ${DATA}"
cmp $DATA $OBJ/ls.copy || fail "corrupted copy of $DATA" cmp ${DATA} ${COPY} || fail "corrupted copy of ${DATA}"
done done
done done
@ -56,4 +57,5 @@ for p in ${SSH_PROTOCOLS}; do
else else
fail "no pid file: $OBJ/remote_pid" fail "no pid file: $OBJ/remote_pid"
fi fi
done done

View File

@ -1,4 +1,4 @@
# $OpenBSD: login-timeout.sh,v 1.8 2016/12/16 01:06:27 dtucker Exp $ # $OpenBSD: login-timeout.sh,v 1.9 2017/08/07 00:53:51 dtucker Exp $
# Placed in the Public Domain. # Placed in the Public Domain.
tid="connect after login grace timeout" tid="connect after login grace timeout"
@ -14,19 +14,5 @@ start_sshd
sleep 15 sleep 15
${SSH} -F $OBJ/ssh_config somehost true ${SSH} -F $OBJ/ssh_config somehost true
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
fail "ssh connect after login grace timeout failed with privsep" fail "ssh connect after login grace timeout failed"
fi
stop_sshd
trace "test login grace without privsep"
echo "UsePrivilegeSeparation no" >> $OBJ/sshd_config
start_sshd
sleep 1
(echo SSH-2.0-fake; sleep 60) | telnet 127.0.0.1 ${PORT} >/dev/null 2>&1 &
sleep 15
${SSH} -F $OBJ/ssh_config somehost true
if [ $? -ne 0 ]; then
fail "ssh connect after login grace timeout failed without privsep"
fi fi

View File

@ -0,0 +1,22 @@
# NB. libssh and libopenbsd-compat should be built with the same sanitizer opts.
CXX=clang++-3.9
FUZZ_FLAGS=-fsanitize=address,undefined -fsanitize-coverage=edge
FUZZ_LIBS=-lFuzzer
CXXFLAGS=-O2 -g -Wall -Wextra -I ../../.. $(FUZZ_FLAGS)
LDFLAGS=-L ../../.. -L ../../../openbsd-compat -g $(FUZZ_FLAGS)
LIBS=-lssh -lopenbsd-compat -lcrypto $(FUZZ_LIBS)
all: pubkey_fuzz sig_fuzz
.cc.o:
$(CXX) $(CXXFLAGS) -c $< -o $@
pubkey_fuzz: pubkey_fuzz.o
$(CXX) -o $@ pubkey_fuzz.o $(LDFLAGS) $(LIBS)
sig_fuzz: sig_fuzz.o
$(CXX) -o $@ sig_fuzz.o $(LDFLAGS) $(LIBS)
clean:
-rm -f *.o pubkey_fuzz sig_fuzz

View File

@ -0,0 +1 @@
This directory contains fuzzing harnesses for use with clang's libfuzzer.

View File

@ -0,0 +1,18 @@
#include <stddef.h>
#include <stdio.h>
#include <stdint.h>
extern "C" {
#include "sshkey.h"
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{
struct sshkey *k = NULL;
int r = sshkey_from_blob(data, size, &k);
if (r == 0) sshkey_free(k);
return 0;
}
} // extern

View File

@ -0,0 +1,50 @@
// cc_fuzz_target test for public key parsing.
#include <stddef.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
extern "C" {
#include "includes.h"
#include "sshkey.h"
#include "ssherr.h"
static struct sshkey *generate_or_die(int type, unsigned bits) {
int r;
struct sshkey *ret;
if ((r = sshkey_generate(type, bits, &ret)) != 0) {
fprintf(stderr, "generate(%d, %u): %s", type, bits, ssh_err(r));
abort();
}
return ret;
}
int LLVMFuzzerTestOneInput(const uint8_t* sig, size_t slen)
{
#ifdef WITH_OPENSSL
static struct sshkey *rsa = generate_or_die(KEY_RSA, 2048);
static struct sshkey *dsa = generate_or_die(KEY_DSA, 1024);
static struct sshkey *ecdsa256 = generate_or_die(KEY_ECDSA, 256);
static struct sshkey *ecdsa384 = generate_or_die(KEY_ECDSA, 384);
static struct sshkey *ecdsa521 = generate_or_die(KEY_ECDSA, 521);
#endif
static struct sshkey *ed25519 = generate_or_die(KEY_ED25519, 0);
static const char *data = "If everyone started announcing his nose had "
"run away, I dont know how it would all end";
static const size_t dlen = strlen(data);
#ifdef WITH_OPENSSL
sshkey_verify(rsa, sig, slen, (const u_char *)data, dlen, 0);
sshkey_verify(dsa, sig, slen, (const u_char *)data, dlen, 0);
sshkey_verify(ecdsa256, sig, slen, (const u_char *)data, dlen, 0);
sshkey_verify(ecdsa384, sig, slen, (const u_char *)data, dlen, 0);
sshkey_verify(ecdsa521, sig, slen, (const u_char *)data, dlen, 0);
#endif
sshkey_verify(ed25519, sig, slen, (const u_char *)data, dlen, 0);
return 0;
}
} // extern

View File

@ -1,4 +1,4 @@
# $OpenBSD: reexec.sh,v 1.11 2017/04/30 23:34:55 djm Exp $ # $OpenBSD: reexec.sh,v 1.12 2017/08/07 03:52:55 dtucker Exp $
# Placed in the Public Domain. # Placed in the Public Domain.
tid="reexec tests" tid="reexec tests"
@ -51,17 +51,4 @@ rm -f $SSHD_COPY
copy_tests copy_tests
stop_sshd stop_sshd
verbose "test reexec fallback without privsep"
cp $OBJ/sshd_config.orig $OBJ/sshd_config
echo "UsePrivilegeSeparation=no" >> $OBJ/sshd_config
start_sshd_copy
rm -f $SSHD_COPY
copy_tests
stop_sshd
fi fi

View File

@ -1,4 +1,4 @@
# $OpenBSD: test-exec.sh,v 1.60 2017/04/30 23:34:55 djm Exp $ # $OpenBSD: test-exec.sh,v 1.61 2017/07/28 10:32:08 dtucker Exp $
# Placed in the Public Domain. # Placed in the Public Domain.
#SUDO=sudo #SUDO=sudo
@ -304,8 +304,15 @@ stop_sshd ()
i=`expr $i + 1` i=`expr $i + 1`
sleep $i sleep $i
done done
test -f $PIDFILE && \ if test -f $PIDFILE; then
fatal "sshd didn't exit port $PORT pid $pid" if $SUDO kill -0 $pid; then
echo "sshd didn't exit " \
"port $PORT pid $pid"
else
echo "sshd died without cleanup"
fi
exit 1
fi
fi fi
fi fi
fi fi

View File

@ -22,7 +22,7 @@
#include <sys/param.h> #include <sys/param.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/resource.h> #include <sys/resource.h>
#include <sys/capability.h> #include <sys/capsicum.h>
#include <errno.h> #include <errno.h>
#include <stdarg.h> #include <stdarg.h>

View File

@ -1,5 +1,5 @@
/* $OpenBSD: servconf.c,v 1.309 2017/06/24 06:34:38 djm Exp $ */ /* $OpenBSD: servconf.c,v 1.312 2017/10/02 19:33:20 djm Exp $ */
/* /*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved * All rights reserved
@ -149,7 +149,7 @@ initialize_server_options(ServerOptions *options)
options->num_authkeys_files = 0; options->num_authkeys_files = 0;
options->num_accept_env = 0; options->num_accept_env = 0;
options->permit_tun = -1; options->permit_tun = -1;
options->num_permitted_opens = -1; options->permitted_opens = NULL;
options->adm_forced_command = NULL; options->adm_forced_command = NULL;
options->chroot_directory = NULL; options->chroot_directory = NULL;
options->authorized_keys_command = NULL; options->authorized_keys_command = NULL;
@ -703,6 +703,44 @@ process_queued_listen_addrs(ServerOptions *options)
options->num_queued_listens = 0; options->num_queued_listens = 0;
} }
/*
* Inform channels layer of permitopen options from configuration.
*/
void
process_permitopen(struct ssh *ssh, ServerOptions *options)
{
u_int i;
int port;
char *host, *arg, *oarg;
channel_clear_adm_permitted_opens(ssh);
if (options->num_permitted_opens == 0)
return; /* permit any */
/* handle keywords: "any" / "none" */
if (options->num_permitted_opens == 1 &&
strcmp(options->permitted_opens[0], "any") == 0)
return;
if (options->num_permitted_opens == 1 &&
strcmp(options->permitted_opens[0], "none") == 0) {
channel_disable_adm_local_opens(ssh);
return;
}
/* Otherwise treat it as a list of permitted host:port */
for (i = 0; i < options->num_permitted_opens; i++) {
oarg = arg = xstrdup(options->permitted_opens[i]);
host = hpdelim(&arg);
if (host == NULL)
fatal("%s: missing host in PermitOpen", __func__);
host = cleanhostname(host);
if (arg == NULL || ((port = permitopen_port(arg)) < 0))
fatal("%s: bad port number in PermitOpen", __func__);
/* Send it to channels layer */
channel_add_adm_permitted_opens(ssh, host, port);
free(oarg);
}
}
struct connection_info * struct connection_info *
get_connection_info(int populate, int use_dns) get_connection_info(int populate, int use_dns)
{ {
@ -960,7 +998,7 @@ process_server_config_line(ServerOptions *options, char *line,
const char *filename, int linenum, int *activep, const char *filename, int linenum, int *activep,
struct connection_info *connectinfo) struct connection_info *connectinfo)
{ {
char *cp, **charptr, *arg, *p; char *cp, **charptr, *arg, *arg2, *p;
int cmdline = 0, *intptr, value, value2, n, port; int cmdline = 0, *intptr, value, value2, n, port;
SyslogFacility *log_facility_ptr; SyslogFacility *log_facility_ptr;
LogLevel *log_level_ptr; LogLevel *log_level_ptr;
@ -1631,24 +1669,18 @@ process_server_config_line(ServerOptions *options, char *line,
if (!arg || *arg == '\0') if (!arg || *arg == '\0')
fatal("%s line %d: missing PermitOpen specification", fatal("%s line %d: missing PermitOpen specification",
filename, linenum); filename, linenum);
n = options->num_permitted_opens; /* modified later */ i = options->num_permitted_opens; /* modified later */
if (strcmp(arg, "any") == 0) { if (strcmp(arg, "any") == 0 || strcmp(arg, "none") == 0) {
if (*activep && n == -1) { if (*activep && i == 0) {
channel_clear_adm_permitted_opens();
options->num_permitted_opens = 0;
}
break;
}
if (strcmp(arg, "none") == 0) {
if (*activep && n == -1) {
options->num_permitted_opens = 1; options->num_permitted_opens = 1;
channel_disable_adm_local_opens(); options->permitted_opens = xcalloc(1,
sizeof(*options->permitted_opens));
options->permitted_opens[0] = xstrdup(arg);
} }
break; break;
} }
if (*activep && n == -1)
channel_clear_adm_permitted_opens();
for (; arg != NULL && *arg != '\0'; arg = strdelim(&cp)) { for (; arg != NULL && *arg != '\0'; arg = strdelim(&cp)) {
arg2 = xstrdup(arg);
p = hpdelim(&arg); p = hpdelim(&arg);
if (p == NULL) if (p == NULL)
fatal("%s line %d: missing host in PermitOpen", fatal("%s line %d: missing host in PermitOpen",
@ -1657,9 +1689,16 @@ process_server_config_line(ServerOptions *options, char *line,
if (arg == NULL || ((port = permitopen_port(arg)) < 0)) if (arg == NULL || ((port = permitopen_port(arg)) < 0))
fatal("%s line %d: bad port number in " fatal("%s line %d: bad port number in "
"PermitOpen", filename, linenum); "PermitOpen", filename, linenum);
if (*activep && n == -1) if (*activep && i == 0) {
options->num_permitted_opens = options->permitted_opens = xrecallocarray(
channel_add_adm_permitted_opens(p, port); options->permitted_opens,
options->num_permitted_opens,
options->num_permitted_opens + 1,
sizeof(*options->permitted_opens));
i = options->num_permitted_opens++;
options->permitted_opens[i] = arg2;
} else
free(arg2);
} }
break; break;
@ -2030,6 +2069,13 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
dst->n[dst->num_n] = xstrdup(src->n[dst->num_n]); \ dst->n[dst->num_n] = xstrdup(src->n[dst->num_n]); \
} \ } \
} while(0) } while(0)
#define M_CP_STRARRAYOPT_ALLOC(n, num_n) do { \
if (src->num_n != 0) { \
dst->n = xcalloc(src->num_n, sizeof(*dst->n)); \
M_CP_STRARRAYOPT(n, num_n); \
dst->num_n = src->num_n; \
} \
} while(0)
/* See comment in servconf.h */ /* See comment in servconf.h */
COPY_MATCH_STRING_OPTS(); COPY_MATCH_STRING_OPTS();
@ -2060,6 +2106,7 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
#undef M_CP_INTOPT #undef M_CP_INTOPT
#undef M_CP_STROPT #undef M_CP_STROPT
#undef M_CP_STRARRAYOPT #undef M_CP_STRARRAYOPT
#undef M_CP_STRARRAYOPT_ALLOC
void void
parse_server_config(ServerOptions *options, const char *filename, Buffer *conf, parse_server_config(ServerOptions *options, const char *filename, Buffer *conf,
@ -2384,5 +2431,12 @@ dump_config(ServerOptions *o)
printf("rekeylimit %llu %d\n", (unsigned long long)o->rekey_limit, printf("rekeylimit %llu %d\n", (unsigned long long)o->rekey_limit,
o->rekey_interval); o->rekey_interval);
channel_print_adm_permitted_opens(); printf("permitopen");
if (o->num_permitted_opens == 0)
printf(" any");
else {
for (i = 0; i < o->num_permitted_opens; i++)
printf(" %s", o->permitted_opens[i]);
}
printf("\n");
} }

View File

@ -1,4 +1,4 @@
/* $OpenBSD: servconf.h,v 1.124 2017/06/24 06:34:38 djm Exp $ */ /* $OpenBSD: servconf.h,v 1.126 2017/10/02 19:33:20 djm Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -48,12 +48,19 @@
#define FORWARD_LOCAL (1<<1) #define FORWARD_LOCAL (1<<1)
#define FORWARD_ALLOW (FORWARD_REMOTE|FORWARD_LOCAL) #define FORWARD_ALLOW (FORWARD_REMOTE|FORWARD_LOCAL)
/* PermitOpen */
#define PERMITOPEN_ANY 0
#define PERMITOPEN_NONE -2
#define DEFAULT_AUTH_FAIL_MAX 6 /* Default for MaxAuthTries */ #define DEFAULT_AUTH_FAIL_MAX 6 /* Default for MaxAuthTries */
#define DEFAULT_SESSIONS_MAX 10 /* Default for MaxSessions */ #define DEFAULT_SESSIONS_MAX 10 /* Default for MaxSessions */
/* Magic name for internal sftp-server */ /* Magic name for internal sftp-server */
#define INTERNAL_SFTP_NAME "internal-sftp" #define INTERNAL_SFTP_NAME "internal-sftp"
struct ssh;
struct fwd_perm_list;
typedef struct { typedef struct {
u_int num_ports; u_int num_ports;
u_int ports_from_cmdline; u_int ports_from_cmdline;
@ -169,7 +176,8 @@ typedef struct {
int permit_tun; int permit_tun;
int num_permitted_opens; char **permitted_opens;
u_int num_permitted_opens; /* May also be one of PERMITOPEN_* */
char *chroot_directory; char *chroot_directory;
char *revoked_keys_file; char *revoked_keys_file;
@ -229,6 +237,7 @@ struct connection_info {
M_CP_STRARRAYOPT(deny_groups, num_deny_groups); \ M_CP_STRARRAYOPT(deny_groups, num_deny_groups); \
M_CP_STRARRAYOPT(accept_env, num_accept_env); \ M_CP_STRARRAYOPT(accept_env, num_accept_env); \
M_CP_STRARRAYOPT(auth_methods, num_auth_methods); \ M_CP_STRARRAYOPT(auth_methods, num_auth_methods); \
M_CP_STRARRAYOPT_ALLOC(permitted_opens, num_permitted_opens); \
} while (0) } while (0)
struct connection_info *get_connection_info(int, int); struct connection_info *get_connection_info(int, int);
@ -236,6 +245,7 @@ void initialize_server_options(ServerOptions *);
void fill_default_server_options(ServerOptions *); void fill_default_server_options(ServerOptions *);
int process_server_config_line(ServerOptions *, char *, const char *, int, int process_server_config_line(ServerOptions *, char *, const char *, int,
int *, struct connection_info *); int *, struct connection_info *);
void process_permitopen(struct ssh *ssh, ServerOptions *options);
void load_server_config(const char *, Buffer *); void load_server_config(const char *, Buffer *);
void parse_server_config(ServerOptions *, const char *, Buffer *, void parse_server_config(ServerOptions *, const char *, Buffer *,
struct connection_info *); struct connection_info *);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: serverloop.c,v 1.195 2017/08/11 04:16:35 dtucker Exp $ */ /* $OpenBSD: serverloop.c,v 1.198 2017/09/12 06:35:32 djm Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -165,7 +165,7 @@ sigterm_handler(int sig)
} }
static void static void
client_alive_check(void) client_alive_check(struct ssh *ssh)
{ {
int channel_id; int channel_id;
@ -179,12 +179,13 @@ client_alive_check(void)
* send a bogus global/channel request with "wantreply", * send a bogus global/channel request with "wantreply",
* we should get back a failure * we should get back a failure
*/ */
if ((channel_id = channel_find_open()) == -1) { if ((channel_id = channel_find_open(ssh)) == -1) {
packet_start(SSH2_MSG_GLOBAL_REQUEST); packet_start(SSH2_MSG_GLOBAL_REQUEST);
packet_put_cstring("keepalive@openssh.com"); packet_put_cstring("keepalive@openssh.com");
packet_put_char(1); /* boolean: want reply */ packet_put_char(1); /* boolean: want reply */
} else { } else {
channel_request_start(channel_id, "keepalive@openssh.com", 1); channel_request_start(ssh, channel_id,
"keepalive@openssh.com", 1);
} }
packet_send(); packet_send();
} }
@ -196,7 +197,8 @@ client_alive_check(void)
* for the duration of the wait (0 = infinite). * for the duration of the wait (0 = infinite).
*/ */
static void static void
wait_until_can_do_something(int connection_in, int connection_out, wait_until_can_do_something(struct ssh *ssh,
int connection_in, int connection_out,
fd_set **readsetp, fd_set **writesetp, int *maxfdp, fd_set **readsetp, fd_set **writesetp, int *maxfdp,
u_int *nallocp, u_int64_t max_time_ms) u_int *nallocp, u_int64_t max_time_ms)
{ {
@ -207,8 +209,8 @@ wait_until_can_do_something(int connection_in, int connection_out,
static time_t last_client_time; static time_t last_client_time;
/* Allocate and update select() masks for channel descriptors. */ /* Allocate and update select() masks for channel descriptors. */
channel_prepare_select(readsetp, writesetp, maxfdp, nallocp, channel_prepare_select(ssh, readsetp, writesetp, maxfdp,
&minwait_secs, 0); nallocp, &minwait_secs);
/* XXX need proper deadline system for rekey/client alive */ /* XXX need proper deadline system for rekey/client alive */
if (minwait_secs != 0) if (minwait_secs != 0)
@ -273,12 +275,12 @@ wait_until_can_do_something(int connection_in, int connection_out,
time_t now = monotime(); time_t now = monotime();
if (ret == 0) { /* timeout */ if (ret == 0) { /* timeout */
client_alive_check(); client_alive_check(ssh);
} else if (FD_ISSET(connection_in, *readsetp)) { } else if (FD_ISSET(connection_in, *readsetp)) {
last_client_time = now; last_client_time = now;
} else if (last_client_time != 0 && last_client_time + } else if (last_client_time != 0 && last_client_time +
options.client_alive_interval <= now) { options.client_alive_interval <= now) {
client_alive_check(); client_alive_check(ssh);
last_client_time = now; last_client_time = now;
} }
} }
@ -291,9 +293,8 @@ wait_until_can_do_something(int connection_in, int connection_out,
* in buffers and processed later. * in buffers and processed later.
*/ */
static int static int
process_input(fd_set *readset, int connection_in) process_input(struct ssh *ssh, fd_set *readset, int connection_in)
{ {
struct ssh *ssh = active_state; /* XXX */
int len; int len;
char buf[16384]; char buf[16384];
@ -333,13 +334,13 @@ process_output(fd_set *writeset, int connection_out)
} }
static void static void
process_buffered_input_packets(void) process_buffered_input_packets(struct ssh *ssh)
{ {
ssh_dispatch_run_fatal(active_state, DISPATCH_NONBLOCK, NULL); ssh_dispatch_run_fatal(ssh, DISPATCH_NONBLOCK, NULL);
} }
static void static void
collect_children(void) collect_children(struct ssh *ssh)
{ {
pid_t pid; pid_t pid;
sigset_t oset, nset; sigset_t oset, nset;
@ -354,14 +355,14 @@ collect_children(void)
while ((pid = waitpid(-1, &status, WNOHANG)) > 0 || while ((pid = waitpid(-1, &status, WNOHANG)) > 0 ||
(pid < 0 && errno == EINTR)) (pid < 0 && errno == EINTR))
if (pid > 0) if (pid > 0)
session_close_by_pid(pid, status); session_close_by_pid(ssh, pid, status);
child_terminated = 0; child_terminated = 0;
} }
sigprocmask(SIG_SETMASK, &oset, NULL); sigprocmask(SIG_SETMASK, &oset, NULL);
} }
void void
server_loop2(Authctxt *authctxt) server_loop2(struct ssh *ssh, Authctxt *authctxt)
{ {
fd_set *readset = NULL, *writeset = NULL; fd_set *readset = NULL, *writeset = NULL;
int max_fd; int max_fd;
@ -389,18 +390,17 @@ server_loop2(Authctxt *authctxt)
server_init_dispatch(); server_init_dispatch();
for (;;) { for (;;) {
process_buffered_input_packets(); process_buffered_input_packets(ssh);
if (!ssh_packet_is_rekeying(active_state) && if (!ssh_packet_is_rekeying(ssh) &&
packet_not_very_much_data_to_write()) packet_not_very_much_data_to_write())
channel_output_poll(); channel_output_poll(ssh);
if (options.rekey_interval > 0 && if (options.rekey_interval > 0 && !ssh_packet_is_rekeying(ssh))
!ssh_packet_is_rekeying(active_state))
rekey_timeout_ms = packet_get_rekey_timeout() * 1000; rekey_timeout_ms = packet_get_rekey_timeout() * 1000;
else else
rekey_timeout_ms = 0; rekey_timeout_ms = 0;
wait_until_can_do_something(connection_in, connection_out, wait_until_can_do_something(ssh, connection_in, connection_out,
&readset, &writeset, &max_fd, &nalloc, rekey_timeout_ms); &readset, &writeset, &max_fd, &nalloc, rekey_timeout_ms);
if (received_sigterm) { if (received_sigterm) {
@ -409,23 +409,23 @@ server_loop2(Authctxt *authctxt)
cleanup_exit(255); cleanup_exit(255);
} }
collect_children(); collect_children(ssh);
if (!ssh_packet_is_rekeying(active_state)) if (!ssh_packet_is_rekeying(ssh))
channel_after_select(readset, writeset); channel_after_select(ssh, readset, writeset);
if (process_input(readset, connection_in) < 0) if (process_input(ssh, readset, connection_in) < 0)
break; break;
process_output(writeset, connection_out); process_output(writeset, connection_out);
} }
collect_children(); collect_children(ssh);
free(readset); free(readset);
free(writeset); free(writeset);
/* free all channels, no more reads and writes */ /* free all channels, no more reads and writes */
channel_free_all(); channel_free_all(ssh);
/* free remaining sessions, e.g. remove wtmp entries */ /* free remaining sessions, e.g. remove wtmp entries */
session_destroy_all(NULL); session_destroy_all(ssh, NULL);
} }
static int static int
@ -442,7 +442,7 @@ server_input_keep_alive(int type, u_int32_t seq, struct ssh *ssh)
} }
static Channel * static Channel *
server_request_direct_tcpip(int *reason, const char **errmsg) server_request_direct_tcpip(struct ssh *ssh, int *reason, const char **errmsg)
{ {
Channel *c = NULL; Channel *c = NULL;
char *target, *originator; char *target, *originator;
@ -460,7 +460,7 @@ server_request_direct_tcpip(int *reason, const char **errmsg)
/* XXX fine grained permissions */ /* XXX fine grained permissions */
if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0 && if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0 &&
!no_port_forwarding_flag && !options.disable_forwarding) { !no_port_forwarding_flag && !options.disable_forwarding) {
c = channel_connect_to_port(target, target_port, c = channel_connect_to_port(ssh, target, target_port,
"direct-tcpip", "direct-tcpip", reason, errmsg); "direct-tcpip", "direct-tcpip", reason, errmsg);
} else { } else {
logit("refused local port forward: " logit("refused local port forward: "
@ -477,7 +477,7 @@ server_request_direct_tcpip(int *reason, const char **errmsg)
} }
static Channel * static Channel *
server_request_direct_streamlocal(void) server_request_direct_streamlocal(struct ssh *ssh)
{ {
Channel *c = NULL; Channel *c = NULL;
char *target, *originator; char *target, *originator;
@ -499,7 +499,7 @@ server_request_direct_streamlocal(void)
if ((options.allow_streamlocal_forwarding & FORWARD_LOCAL) != 0 && if ((options.allow_streamlocal_forwarding & FORWARD_LOCAL) != 0 &&
!no_port_forwarding_flag && !options.disable_forwarding && !no_port_forwarding_flag && !options.disable_forwarding &&
(pw->pw_uid == 0 || use_privsep)) { (pw->pw_uid == 0 || use_privsep)) {
c = channel_connect_to_path(target, c = channel_connect_to_path(ssh, target,
"direct-streamlocal@openssh.com", "direct-streamlocal"); "direct-streamlocal@openssh.com", "direct-streamlocal");
} else { } else {
logit("refused streamlocal port forward: " logit("refused streamlocal port forward: "
@ -514,7 +514,7 @@ server_request_direct_streamlocal(void)
} }
static Channel * static Channel *
server_request_tun(void) server_request_tun(struct ssh *ssh)
{ {
Channel *c = NULL; Channel *c = NULL;
int mode, tun; int mode, tun;
@ -544,12 +544,12 @@ server_request_tun(void)
sock = tun_open(tun, mode); sock = tun_open(tun, mode);
if (sock < 0) if (sock < 0)
goto done; goto done;
c = channel_new("tun", SSH_CHANNEL_OPEN, sock, sock, -1, c = channel_new(ssh, "tun", SSH_CHANNEL_OPEN, sock, sock, -1,
CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1);
c->datagram = 1; c->datagram = 1;
#if defined(SSH_TUN_FILTER) #if defined(SSH_TUN_FILTER)
if (mode == SSH_TUNMODE_POINTOPOINT) if (mode == SSH_TUNMODE_POINTOPOINT)
channel_register_filter(c->self, sys_tun_infilter, channel_register_filter(ssh, c->self, sys_tun_infilter,
sys_tun_outfilter, NULL, NULL); sys_tun_outfilter, NULL, NULL);
#endif #endif
@ -560,7 +560,7 @@ server_request_tun(void)
} }
static Channel * static Channel *
server_request_session(void) server_request_session(struct ssh *ssh)
{ {
Channel *c; Channel *c;
@ -578,15 +578,15 @@ server_request_session(void)
* SSH_CHANNEL_LARVAL. Additionally, a callback for handling all * SSH_CHANNEL_LARVAL. Additionally, a callback for handling all
* CHANNEL_REQUEST messages is registered. * CHANNEL_REQUEST messages is registered.
*/ */
c = channel_new("session", SSH_CHANNEL_LARVAL, c = channel_new(ssh, "session", SSH_CHANNEL_LARVAL,
-1, -1, -1, /*window size*/0, CHAN_SES_PACKET_DEFAULT, -1, -1, -1, /*window size*/0, CHAN_SES_PACKET_DEFAULT,
0, "server-session", 1); 0, "server-session", 1);
if (session_open(the_authctxt, c->self) != 1) { if (session_open(the_authctxt, c->self) != 1) {
debug("session open failed, free channel %d", c->self); debug("session open failed, free channel %d", c->self);
channel_free(c); channel_free(ssh, c);
return NULL; return NULL;
} }
channel_register_cleanup(c->self, session_close_by_channel, 0); channel_register_cleanup(ssh, c->self, session_close_by_channel, 0);
return c; return c;
} }
@ -608,17 +608,18 @@ server_input_channel_open(int type, u_int32_t seq, struct ssh *ssh)
ctype, rchan, rwindow, rmaxpack); ctype, rchan, rwindow, rmaxpack);
if (strcmp(ctype, "session") == 0) { if (strcmp(ctype, "session") == 0) {
c = server_request_session(); c = server_request_session(ssh);
} else if (strcmp(ctype, "direct-tcpip") == 0) { } else if (strcmp(ctype, "direct-tcpip") == 0) {
c = server_request_direct_tcpip(&reason, &errmsg); c = server_request_direct_tcpip(ssh, &reason, &errmsg);
} else if (strcmp(ctype, "direct-streamlocal@openssh.com") == 0) { } else if (strcmp(ctype, "direct-streamlocal@openssh.com") == 0) {
c = server_request_direct_streamlocal(); c = server_request_direct_streamlocal(ssh);
} else if (strcmp(ctype, "tun@openssh.com") == 0) { } else if (strcmp(ctype, "tun@openssh.com") == 0) {
c = server_request_tun(); c = server_request_tun(ssh);
} }
if (c != NULL) { if (c != NULL) {
debug("server_input_channel_open: confirm %s", ctype); debug("server_input_channel_open: confirm %s", ctype);
c->remote_id = rchan; c->remote_id = rchan;
c->have_remote_id = 1;
c->remote_window = rwindow; c->remote_window = rwindow;
c->remote_maxpacket = rmaxpack; c->remote_maxpacket = rmaxpack;
if (c->type != SSH_CHANNEL_CONNECTING) { if (c->type != SSH_CHANNEL_CONNECTING) {
@ -645,9 +646,8 @@ server_input_channel_open(int type, u_int32_t seq, struct ssh *ssh)
} }
static int static int
server_input_hostkeys_prove(struct sshbuf **respp) server_input_hostkeys_prove(struct ssh *ssh, struct sshbuf **respp)
{ {
struct ssh *ssh = active_state; /* XXX */
struct sshbuf *resp = NULL; struct sshbuf *resp = NULL;
struct sshbuf *sigbuf = NULL; struct sshbuf *sigbuf = NULL;
struct sshkey *key = NULL, *key_pub = NULL, *key_prv = NULL; struct sshkey *key = NULL, *key_pub = NULL, *key_prv = NULL;
@ -750,7 +750,7 @@ server_input_global_request(int type, u_int32_t seq, struct ssh *ssh)
packet_send_debug("Server has disabled port forwarding."); packet_send_debug("Server has disabled port forwarding.");
} else { } else {
/* Start listening on the port */ /* Start listening on the port */
success = channel_setup_remote_fwd_listener(&fwd, success = channel_setup_remote_fwd_listener(ssh, &fwd,
&allocated_listen_port, &options.fwd_opts); &allocated_listen_port, &options.fwd_opts);
} }
free(fwd.listen_host); free(fwd.listen_host);
@ -768,7 +768,7 @@ server_input_global_request(int type, u_int32_t seq, struct ssh *ssh)
debug("%s: cancel-tcpip-forward addr %s port %d", __func__, debug("%s: cancel-tcpip-forward addr %s port %d", __func__,
fwd.listen_host, fwd.listen_port); fwd.listen_host, fwd.listen_port);
success = channel_cancel_rport_listener(&fwd); success = channel_cancel_rport_listener(ssh, &fwd);
free(fwd.listen_host); free(fwd.listen_host);
} else if (strcmp(rtype, "streamlocal-forward@openssh.com") == 0) { } else if (strcmp(rtype, "streamlocal-forward@openssh.com") == 0) {
struct Forward fwd; struct Forward fwd;
@ -787,7 +787,7 @@ server_input_global_request(int type, u_int32_t seq, struct ssh *ssh)
"streamlocal forwarding."); "streamlocal forwarding.");
} else { } else {
/* Start listening on the socket */ /* Start listening on the socket */
success = channel_setup_remote_fwd_listener( success = channel_setup_remote_fwd_listener(ssh,
&fwd, NULL, &options.fwd_opts); &fwd, NULL, &options.fwd_opts);
} }
free(fwd.listen_path); free(fwd.listen_path);
@ -799,19 +799,19 @@ server_input_global_request(int type, u_int32_t seq, struct ssh *ssh)
debug("%s: cancel-streamlocal-forward path %s", __func__, debug("%s: cancel-streamlocal-forward path %s", __func__,
fwd.listen_path); fwd.listen_path);
success = channel_cancel_rport_listener(&fwd); success = channel_cancel_rport_listener(ssh, &fwd);
free(fwd.listen_path); free(fwd.listen_path);
} else if (strcmp(rtype, "no-more-sessions@openssh.com") == 0) { } else if (strcmp(rtype, "no-more-sessions@openssh.com") == 0) {
no_more_sessions = 1; no_more_sessions = 1;
success = 1; success = 1;
} else if (strcmp(rtype, "hostkeys-prove-00@openssh.com") == 0) { } else if (strcmp(rtype, "hostkeys-prove-00@openssh.com") == 0) {
success = server_input_hostkeys_prove(&resp); success = server_input_hostkeys_prove(ssh, &resp);
} }
if (want_reply) { if (want_reply) {
packet_start(success ? packet_start(success ?
SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE); SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE);
if (success && resp != NULL) if (success && resp != NULL)
ssh_packet_put_raw(active_state, sshbuf_ptr(resp), ssh_packet_put_raw(ssh, sshbuf_ptr(resp),
sshbuf_len(resp)); sshbuf_len(resp));
packet_send(); packet_send();
packet_write_wait(); packet_write_wait();
@ -835,16 +835,19 @@ server_input_channel_req(int type, u_int32_t seq, struct ssh *ssh)
debug("server_input_channel_req: channel %d request %s reply %d", debug("server_input_channel_req: channel %d request %s reply %d",
id, rtype, reply); id, rtype, reply);
if ((c = channel_lookup(id)) == NULL) if ((c = channel_lookup(ssh, id)) == NULL)
packet_disconnect("server_input_channel_req: " packet_disconnect("server_input_channel_req: "
"unknown channel %d", id); "unknown channel %d", id);
if (!strcmp(rtype, "eow@openssh.com")) { if (!strcmp(rtype, "eow@openssh.com")) {
packet_check_eom(); packet_check_eom();
chan_rcvd_eow(c); chan_rcvd_eow(ssh, c);
} else if ((c->type == SSH_CHANNEL_LARVAL || } else if ((c->type == SSH_CHANNEL_LARVAL ||
c->type == SSH_CHANNEL_OPEN) && strcmp(c->ctype, "session") == 0) c->type == SSH_CHANNEL_OPEN) && strcmp(c->ctype, "session") == 0)
success = session_input_channel_req(c, rtype); success = session_input_channel_req(ssh, c, rtype);
if (reply && !(c->flags & CHAN_CLOSE_SENT)) { if (reply && !(c->flags & CHAN_CLOSE_SENT)) {
if (!c->have_remote_id)
fatal("%s: channel %d: no remote_id",
__func__, c->self);
packet_start(success ? packet_start(success ?
SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE); SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE);
packet_put_int(c->remote_id); packet_put_int(c->remote_id);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: serverloop.h,v 1.7 2016/08/13 17:47:41 markus Exp $ */ /* $OpenBSD: serverloop.h,v 1.8 2017/09/12 06:32:07 djm Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -21,6 +21,8 @@
#ifndef SERVERLOOP_H #ifndef SERVERLOOP_H
#define SERVERLOOP_H #define SERVERLOOP_H
void server_loop2(Authctxt *); struct ssh;
void server_loop2(struct ssh *, Authctxt *);
#endif #endif

223
session.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: session.c,v 1.291 2017/08/18 05:36:45 djm Exp $ */ /* $OpenBSD: session.c,v 1.292 2017/09/12 06:32:07 djm Exp $ */
/* /*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved * All rights reserved
@ -113,24 +113,24 @@
/* func */ /* func */
Session *session_new(void); Session *session_new(void);
void session_set_fds(Session *, int, int, int, int, int); void session_set_fds(struct ssh *, Session *, int, int, int, int, int);
void session_pty_cleanup(Session *); void session_pty_cleanup(Session *);
void session_proctitle(Session *); void session_proctitle(Session *);
int session_setup_x11fwd(Session *); int session_setup_x11fwd(struct ssh *, Session *);
int do_exec_pty(Session *, const char *); int do_exec_pty(struct ssh *, Session *, const char *);
int do_exec_no_pty(Session *, const char *); int do_exec_no_pty(struct ssh *, Session *, const char *);
int do_exec(Session *, const char *); int do_exec(struct ssh *, Session *, const char *);
void do_login(Session *, const char *); void do_login(struct ssh *, Session *, const char *);
void do_child(struct ssh *, Session *, const char *);
#ifdef LOGIN_NEEDS_UTMPX #ifdef LOGIN_NEEDS_UTMPX
static void do_pre_login(Session *s); static void do_pre_login(Session *s);
#endif #endif
void do_child(Session *, const char *);
void do_motd(void); void do_motd(void);
int check_quietlogin(Session *, const char *); int check_quietlogin(Session *, const char *);
static void do_authenticated2(Authctxt *); static void do_authenticated2(struct ssh *, Authctxt *);
static int session_pty_req(Session *); static int session_pty_req(struct ssh *, Session *);
/* import */ /* import */
extern ServerOptions options; extern ServerOptions options;
@ -183,7 +183,7 @@ auth_sock_cleanup_proc(struct passwd *pw)
} }
static int static int
auth_input_request_forwarding(struct passwd * pw) auth_input_request_forwarding(struct ssh *ssh, struct passwd * pw)
{ {
#ifdef WINDOWS #ifdef WINDOWS
packet_send_debug("Agent forwarding not supported in Windows yet"); packet_send_debug("Agent forwarding not supported in Windows yet");
@ -227,7 +227,7 @@ auth_input_request_forwarding(struct passwd * pw)
goto authsock_err; goto authsock_err;
/* Allocate a channel for the authentication agent socket. */ /* Allocate a channel for the authentication agent socket. */
nc = channel_new("auth socket", nc = channel_new(ssh, "auth socket",
SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1, SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1,
CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,
0, "auth socket", 1); 0, "auth socket", 1);
@ -293,7 +293,7 @@ prepare_auth_info_file(struct passwd *pw, struct sshbuf *info)
} }
void void
do_authenticated(Authctxt *authctxt) do_authenticated(struct ssh *ssh, Authctxt *authctxt)
{ {
setproctitle("%s", authctxt->pw->pw_name); setproctitle("%s", authctxt->pw->pw_name);
@ -301,17 +301,17 @@ do_authenticated(Authctxt *authctxt)
/* XXX - streamlocal? */ /* XXX - streamlocal? */
if (no_port_forwarding_flag || options.disable_forwarding || if (no_port_forwarding_flag || options.disable_forwarding ||
(options.allow_tcp_forwarding & FORWARD_LOCAL) == 0) (options.allow_tcp_forwarding & FORWARD_LOCAL) == 0)
channel_disable_adm_local_opens(); channel_disable_adm_local_opens(ssh);
else else
channel_permit_all_opens(); channel_permit_all_opens(ssh);
auth_debug_send(); auth_debug_send();
prepare_auth_info_file(authctxt->pw, authctxt->session_info); prepare_auth_info_file(authctxt->pw, authctxt->session_info);
do_authenticated2(authctxt); do_authenticated2(ssh, authctxt);
do_cleanup(authctxt); do_cleanup(ssh, authctxt);
} }
/* Check untrusted xauth strings for metacharacters */ /* Check untrusted xauth strings for metacharacters */
@ -608,7 +608,7 @@ do_exec_pty(Session *s, const char *command) {
* setting up file descriptors and such. * setting up file descriptors and such.
*/ */
int int
do_exec_no_pty(Session *s, const char *command) do_exec_no_pty(struct ssh *ssh, Session *s, const char *command)
{ {
pid_t pid; pid_t pid;
@ -733,7 +733,7 @@ do_exec_no_pty(Session *s, const char *command)
#endif #endif
/* Do processing for the child (exec command etc). */ /* Do processing for the child (exec command etc). */
do_child(s, command); do_child(ssh, s, command);
/* NOTREACHED */ /* NOTREACHED */
default: default:
break; break;
@ -764,7 +764,7 @@ do_exec_no_pty(Session *s, const char *command)
close(pout[1]); close(pout[1]);
close(perr[1]); close(perr[1]);
session_set_fds(s, pin[1], pout[0], perr[0], session_set_fds(ssh, s, pin[1], pout[0], perr[0],
s->is_subsystem, 0); s->is_subsystem, 0);
#else #else
/* We are the parent. Close the child sides of the socket pairs. */ /* We are the parent. Close the child sides of the socket pairs. */
@ -788,7 +788,7 @@ do_exec_no_pty(Session *s, const char *command)
* lastlog, and other such operations. * lastlog, and other such operations.
*/ */
int int
do_exec_pty(Session *s, const char *command) do_exec_pty(struct ssh *ssh, Session *s, const char *command)
{ {
int fdout, ptyfd, ttyfd, ptymaster; int fdout, ptyfd, ttyfd, ptymaster;
pid_t pid; pid_t pid;
@ -857,13 +857,13 @@ do_exec_pty(Session *s, const char *command)
cray_init_job(s->pw); /* set up cray jid and tmpdir */ cray_init_job(s->pw); /* set up cray jid and tmpdir */
#endif /* _UNICOS */ #endif /* _UNICOS */
#ifndef HAVE_OSF_SIA #ifndef HAVE_OSF_SIA
do_login(s, command); do_login(ssh, s, command);
#endif #endif
/* /*
* Do common processing for the child, such as execing * Do common processing for the child, such as execing
* the command. * the command.
*/ */
do_child(s, command); do_child(ssh, s, command);
/* NOTREACHED */ /* NOTREACHED */
default: default:
break; break;
@ -885,7 +885,7 @@ do_exec_pty(Session *s, const char *command)
s->ptymaster = ptymaster; s->ptymaster = ptymaster;
packet_set_interactive(1, packet_set_interactive(1,
options.ip_qos_interactive, options.ip_qos_bulk); options.ip_qos_interactive, options.ip_qos_bulk);
session_set_fds(s, ptyfd, fdout, -1, 1, 1); session_set_fds(ssh, s, ptyfd, fdout, -1, 1, 1);
return 0; return 0;
} }
#endif /* !WINDOWS */ #endif /* !WINDOWS */
@ -924,9 +924,8 @@ do_pre_login(Session *s)
* to be forced, execute that instead. * to be forced, execute that instead.
*/ */
int int
do_exec(Session *s, const char *command) do_exec(struct ssh *ssh, Session *s, const char *command)
{ {
struct ssh *ssh = active_state; /* XXX */
int ret; int ret;
const char *forced = NULL, *tty = NULL; const char *forced = NULL, *tty = NULL;
char session_type[1024]; char session_type[1024];
@ -985,9 +984,9 @@ do_exec(Session *s, const char *command)
} }
#endif #endif
if (s->ttyfd != -1) if (s->ttyfd != -1)
ret = do_exec_pty(s, command); ret = do_exec_pty(ssh, s, command);
else else
ret = do_exec_no_pty(s, command); ret = do_exec_no_pty(ssh, s, command);
original_command = NULL; original_command = NULL;
@ -1003,9 +1002,8 @@ do_exec(Session *s, const char *command)
/* administrative, login(1)-like work */ /* administrative, login(1)-like work */
void void
do_login(Session *s, const char *command) do_login(struct ssh *ssh, Session *s, const char *command)
{ {
struct ssh *ssh = active_state; /* XXX */
socklen_t fromlen; socklen_t fromlen;
struct sockaddr_storage from; struct sockaddr_storage from;
struct passwd * pw = s->pw; struct passwd * pw = s->pw;
@ -1238,9 +1236,8 @@ copy_environment(char **source, char ***env, u_int *envsize)
} }
static char ** static char **
do_setup_env(Session *s, const char *shell) do_setup_env(struct ssh *ssh, Session *s, const char *shell)
{ {
struct ssh *ssh = active_state; /* XXX */
char buf[256]; char buf[256];
u_int i, envsize; u_int i, envsize;
char **env, *laddr; char **env, *laddr;
@ -1699,7 +1696,7 @@ do_pwchange(Session *s)
} }
static void static void
child_close_fds(void) child_close_fds(struct ssh *ssh)
{ {
extern int auth_sock; extern int auth_sock;
@ -1719,7 +1716,7 @@ child_close_fds(void)
* open in the parent. * open in the parent.
*/ */
/* XXX better use close-on-exec? -markus */ /* XXX better use close-on-exec? -markus */
channel_close_all(); channel_close_all(ssh);
/* /*
* Close any extra file descriptors. Note that there may still be * Close any extra file descriptors. Note that there may still be
@ -1743,7 +1740,7 @@ child_close_fds(void)
*/ */
#define ARGV_MAX 10 #define ARGV_MAX 10
void void
do_child(Session *s, const char *command) do_child(struct ssh *ssh, Session *s, const char *command)
{ {
#ifdef WINDOWS #ifdef WINDOWS
/*not called for Windows */ /*not called for Windows */
@ -1763,7 +1760,7 @@ do_child(Session *s, const char *command)
/* Force a password change */ /* Force a password change */
if (s->authctxt->force_pwchange) { if (s->authctxt->force_pwchange) {
do_setusercontext(pw); do_setusercontext(pw);
child_close_fds(); child_close_fds(ssh);
do_pwchange(s); do_pwchange(s);
exit(1); exit(1);
} }
@ -1812,7 +1809,7 @@ do_child(Session *s, const char *command)
* Make sure $SHELL points to the shell from the password file, * Make sure $SHELL points to the shell from the password file,
* even if shell is overridden from login.conf * even if shell is overridden from login.conf
*/ */
env = do_setup_env(s, shell); env = do_setup_env(ssh, s, shell);
#ifdef HAVE_LOGIN_CAP #ifdef HAVE_LOGIN_CAP
shell = login_getcapstr(lc, "shell", (char *)shell, (char *)shell); shell = login_getcapstr(lc, "shell", (char *)shell, (char *)shell);
@ -1825,7 +1822,7 @@ do_child(Session *s, const char *command)
* closed before building the environment, as we call * closed before building the environment, as we call
* ssh_remote_ipaddr there. * ssh_remote_ipaddr there.
*/ */
child_close_fds(); child_close_fds(ssh);
/* /*
* Must take new environment into use so that .ssh/rc, * Must take new environment into use so that .ssh/rc,
@ -2123,7 +2120,7 @@ session_by_pid(pid_t pid)
} }
static int static int
session_window_change_req(Session *s) session_window_change_req(struct ssh *ssh, Session *s)
{ {
s->col = packet_get_int(); s->col = packet_get_int();
s->row = packet_get_int(); s->row = packet_get_int();
@ -2135,7 +2132,7 @@ session_window_change_req(Session *s)
} }
static int static int
session_pty_req(Session *s) session_pty_req(struct ssh *ssh, Session *s)
{ {
u_int len; u_int len;
int n_bytes; int n_bytes;
@ -2188,7 +2185,7 @@ session_pty_req(Session *s)
} }
static int static int
session_subsystem_req(Session *s) session_subsystem_req(struct ssh *ssh, Session *s)
{ {
struct stat st; struct stat st;
u_int len; u_int len;
@ -2215,7 +2212,7 @@ session_subsystem_req(Session *s)
s->is_subsystem = SUBSYSTEM_EXT; s->is_subsystem = SUBSYSTEM_EXT;
debug("subsystem: exec() %s", cmd); debug("subsystem: exec() %s", cmd);
} }
success = do_exec(s, cmd) == 0; success = do_exec(ssh, s, cmd) == 0;
break; break;
} }
} }
@ -2228,7 +2225,7 @@ session_subsystem_req(Session *s)
} }
static int static int
session_x11_req(Session *s) session_x11_req(struct ssh *ssh, Session *s)
{ {
int success; int success;
@ -2245,7 +2242,7 @@ session_x11_req(Session *s)
if (xauth_valid_string(s->auth_proto) && if (xauth_valid_string(s->auth_proto) &&
xauth_valid_string(s->auth_data)) xauth_valid_string(s->auth_data))
success = session_setup_x11fwd(s); success = session_setup_x11fwd(ssh, s);
else { else {
success = 0; success = 0;
error("Invalid X11 forwarding data"); error("Invalid X11 forwarding data");
@ -2260,26 +2257,26 @@ session_x11_req(Session *s)
} }
static int static int
session_shell_req(Session *s) session_shell_req(struct ssh *ssh, Session *s)
{ {
packet_check_eom(); packet_check_eom();
return do_exec(s, NULL) == 0; return do_exec(ssh, s, NULL) == 0;
} }
static int static int
session_exec_req(Session *s) session_exec_req(struct ssh *ssh, Session *s)
{ {
u_int len, success; u_int len, success;
char *command = packet_get_string(&len); char *command = packet_get_string(&len);
packet_check_eom(); packet_check_eom();
success = do_exec(s, command) == 0; success = do_exec(ssh, s, command) == 0;
free(command); free(command);
return success; return success;
} }
static int static int
session_break_req(Session *s) session_break_req(struct ssh *ssh, Session *s)
{ {
packet_get_int(); /* ignored */ packet_get_int(); /* ignored */
@ -2291,7 +2288,7 @@ session_break_req(Session *s)
} }
static int static int
session_env_req(Session *s) session_env_req(struct ssh *ssh, Session *s)
{ {
char *name, *val; char *name, *val;
u_int name_len, val_len, i; u_int name_len, val_len, i;
@ -2326,7 +2323,7 @@ session_env_req(Session *s)
} }
static int static int
session_auth_agent_req(Session *s) session_auth_agent_req(struct ssh *ssh, Session *s)
{ {
static int called = 0; static int called = 0;
packet_check_eom(); packet_check_eom();
@ -2338,22 +2335,21 @@ session_auth_agent_req(Session *s)
return 0; return 0;
} else { } else {
called = 1; called = 1;
return auth_input_request_forwarding(s->pw); return auth_input_request_forwarding(ssh, s->pw);
} }
} }
int int
session_input_channel_req(Channel *c, const char *rtype) session_input_channel_req(struct ssh *ssh, Channel *c, const char *rtype)
{ {
int success = 0; int success = 0;
Session *s; Session *s;
if ((s = session_by_channel(c->self)) == NULL) { if ((s = session_by_channel(c->self)) == NULL) {
logit("session_input_channel_req: no session %d req %.100s", logit("%s: no session %d req %.100s", __func__, c->self, rtype);
c->self, rtype);
return 0; return 0;
} }
debug("session_input_channel_req: session %d req %s", s->self, rtype); debug("%s: session %d req %s", __func__, s->self, rtype);
/* /*
* a session is in LARVAL state until a shell, a command * a session is in LARVAL state until a shell, a command
@ -2361,33 +2357,33 @@ session_input_channel_req(Channel *c, const char *rtype)
*/ */
if (c->type == SSH_CHANNEL_LARVAL) { if (c->type == SSH_CHANNEL_LARVAL) {
if (strcmp(rtype, "shell") == 0) { if (strcmp(rtype, "shell") == 0) {
success = session_shell_req(s); success = session_shell_req(ssh, s);
} else if (strcmp(rtype, "exec") == 0) { } else if (strcmp(rtype, "exec") == 0) {
success = session_exec_req(s); success = session_exec_req(ssh, s);
} else if (strcmp(rtype, "pty-req") == 0) { } else if (strcmp(rtype, "pty-req") == 0) {
success = session_pty_req(s); success = session_pty_req(ssh, s);
} else if (strcmp(rtype, "x11-req") == 0) { } else if (strcmp(rtype, "x11-req") == 0) {
success = session_x11_req(s); success = session_x11_req(ssh, s);
} else if (strcmp(rtype, "auth-agent-req@openssh.com") == 0) { } else if (strcmp(rtype, "auth-agent-req@openssh.com") == 0) {
success = session_auth_agent_req(s); success = session_auth_agent_req(ssh, s);
} else if (strcmp(rtype, "subsystem") == 0) { } else if (strcmp(rtype, "subsystem") == 0) {
success = session_subsystem_req(s); success = session_subsystem_req(ssh, s);
} else if (strcmp(rtype, "env") == 0) { } else if (strcmp(rtype, "env") == 0) {
success = session_env_req(s); success = session_env_req(ssh, s);
} }
} }
if (strcmp(rtype, "window-change") == 0) { if (strcmp(rtype, "window-change") == 0) {
success = session_window_change_req(s); success = session_window_change_req(ssh, s);
} else if (strcmp(rtype, "break") == 0) { } else if (strcmp(rtype, "break") == 0) {
success = session_break_req(s); success = session_break_req(ssh, s);
} }
return success; return success;
} }
void void
session_set_fds(Session *s, int fdin, int fdout, int fderr, int ignore_fderr, session_set_fds(struct ssh *ssh, Session *s,
int is_tty) int fdin, int fdout, int fderr, int ignore_fderr, int is_tty)
{ {
/* /*
* now that have a child and a pipe to the child, * now that have a child and a pipe to the child,
@ -2395,7 +2391,7 @@ session_set_fds(Session *s, int fdin, int fdout, int fderr, int ignore_fderr,
*/ */
if (s->chanid == -1) if (s->chanid == -1)
fatal("no channel for session %d", s->self); fatal("no channel for session %d", s->self);
channel_set_fds(s->chanid, channel_set_fds(ssh, s->chanid,
fdout, fdin, fderr, fdout, fdin, fderr,
ignore_fderr ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ, ignore_fderr ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ,
1, is_tty, CHAN_SES_WINDOW_DEFAULT); 1, is_tty, CHAN_SES_WINDOW_DEFAULT);
@ -2466,40 +2462,40 @@ sig2name(int sig)
} }
static void static void
session_close_x11(int id) session_close_x11(struct ssh *ssh, int id)
{ {
Channel *c; Channel *c;
if ((c = channel_by_id(id)) == NULL) { if ((c = channel_by_id(ssh, id)) == NULL) {
debug("session_close_x11: x11 channel %d missing", id); debug("%s: x11 channel %d missing", __func__, id);
} else { } else {
/* Detach X11 listener */ /* Detach X11 listener */
debug("session_close_x11: detach x11 channel %d", id); debug("%s: detach x11 channel %d", __func__, id);
channel_cancel_cleanup(id); channel_cancel_cleanup(ssh, id);
if (c->ostate != CHAN_OUTPUT_CLOSED) if (c->ostate != CHAN_OUTPUT_CLOSED)
chan_mark_dead(c); chan_mark_dead(ssh, c);
} }
} }
static void static void
session_close_single_x11(int id, void *arg) session_close_single_x11(struct ssh *ssh, int id, void *arg)
{ {
Session *s; Session *s;
u_int i; u_int i;
debug3("session_close_single_x11: channel %d", id); debug3("%s: channel %d", __func__, id);
channel_cancel_cleanup(id); channel_cancel_cleanup(ssh, id);
if ((s = session_by_x11_channel(id)) == NULL) if ((s = session_by_x11_channel(id)) == NULL)
fatal("session_close_single_x11: no x11 channel %d", id); fatal("%s: no x11 channel %d", __func__, id);
for (i = 0; s->x11_chanids[i] != -1; i++) { for (i = 0; s->x11_chanids[i] != -1; i++) {
debug("session_close_single_x11: session %d: " debug("%s: session %d: closing channel %d",
"closing channel %d", s->self, s->x11_chanids[i]); __func__, s->self, s->x11_chanids[i]);
/* /*
* The channel "id" is already closing, but make sure we * The channel "id" is already closing, but make sure we
* close all of its siblings. * close all of its siblings.
*/ */
if (s->x11_chanids[i] != id) if (s->x11_chanids[i] != id)
session_close_x11(s->x11_chanids[i]); session_close_x11(ssh, s->x11_chanids[i]);
} }
free(s->x11_chanids); free(s->x11_chanids);
s->x11_chanids = NULL; s->x11_chanids = NULL;
@ -2514,22 +2510,22 @@ session_close_single_x11(int id, void *arg)
} }
static void static void
session_exit_message(Session *s, int status) session_exit_message(struct ssh *ssh, Session *s, int status)
{ {
Channel *c; Channel *c;
if ((c = channel_lookup(s->chanid)) == NULL) if ((c = channel_lookup(ssh, s->chanid)) == NULL)
fatal("session_exit_message: session %d: no channel %d", fatal("%s: session %d: no channel %d",
s->self, s->chanid); __func__, s->self, s->chanid);
debug("session_exit_message: session %d channel %d pid %ld", debug("%s: session %d channel %d pid %ld",
s->self, s->chanid, (long)s->pid); __func__, s->self, s->chanid, (long)s->pid);
if (WIFEXITED(status)) { if (WIFEXITED(status)) {
channel_request_start(s->chanid, "exit-status", 0); channel_request_start(ssh, s->chanid, "exit-status", 0);
packet_put_int(WEXITSTATUS(status)); packet_put_int(WEXITSTATUS(status));
packet_send(); packet_send();
} else if (WIFSIGNALED(status)) { } else if (WIFSIGNALED(status)) {
channel_request_start(s->chanid, "exit-signal", 0); channel_request_start(ssh, s->chanid, "exit-signal", 0);
packet_put_cstring(sig2name(WTERMSIG(status))); packet_put_cstring(sig2name(WTERMSIG(status)));
#ifdef WCOREDUMP #ifdef WCOREDUMP
packet_put_char(WCOREDUMP(status)? 1 : 0); packet_put_char(WCOREDUMP(status)? 1 : 0);
@ -2545,14 +2541,14 @@ session_exit_message(Session *s, int status)
} }
/* disconnect channel */ /* disconnect channel */
debug("session_exit_message: release channel %d", s->chanid); debug("%s: release channel %d", __func__, s->chanid);
/* /*
* Adjust cleanup callback attachment to send close messages when * Adjust cleanup callback attachment to send close messages when
* the channel gets EOF. The session will be then be closed * the channel gets EOF. The session will be then be closed
* by session_close_by_channel when the childs close their fds. * by session_close_by_channel when the childs close their fds.
*/ */
channel_register_cleanup(c->self, session_close_by_channel, 1); channel_register_cleanup(ssh, c->self, session_close_by_channel, 1);
/* /*
* emulate a write failure with 'chan_write_failed', nobody will be * emulate a write failure with 'chan_write_failed', nobody will be
@ -2561,13 +2557,12 @@ session_exit_message(Session *s, int status)
* be some more data waiting in the pipe. * be some more data waiting in the pipe.
*/ */
if (c->ostate != CHAN_OUTPUT_CLOSED) if (c->ostate != CHAN_OUTPUT_CLOSED)
chan_write_failed(c); chan_write_failed(ssh, c);
} }
void void
session_close(Session *s) session_close(struct ssh *ssh, Session *s)
{ {
struct ssh *ssh = active_state; /* XXX */
u_int i; u_int i;
verbose("Close session: user %s from %.200s port %d id %d", verbose("Close session: user %s from %.200s port %d id %d",
@ -2597,16 +2592,15 @@ session_close(Session *s)
} }
void void
session_close_by_pid(pid_t pid, int status) session_close_by_pid(struct ssh *ssh, pid_t pid, int status)
{ {
Session *s = session_by_pid(pid); Session *s = session_by_pid(pid);
if (s == NULL) { if (s == NULL) {
debug("session_close_by_pid: no session for pid %ld", debug("%s: no session for pid %ld", __func__, (long)pid);
(long)pid);
return; return;
} }
if (s->chanid != -1) if (s->chanid != -1)
session_exit_message(s, status); session_exit_message(ssh, s, status);
if (s->ttyfd != -1) if (s->ttyfd != -1)
session_pty_cleanup(s); session_pty_cleanup(s);
s->pid = 0; s->pid = 0;
@ -2617,19 +2611,18 @@ session_close_by_pid(pid_t pid, int status)
* the session 'child' itself dies * the session 'child' itself dies
*/ */
void void
session_close_by_channel(int id, void *arg) session_close_by_channel(struct ssh *ssh, int id, void *arg)
{ {
Session *s = session_by_channel(id); Session *s = session_by_channel(id);
u_int i; u_int i;
if (s == NULL) { if (s == NULL) {
debug("session_close_by_channel: no session for id %d", id); debug("%s: no session for id %d", __func__, id);
return; return;
} }
debug("session_close_by_channel: channel %d child %ld", debug("%s: channel %d child %ld", __func__, id, (long)s->pid);
id, (long)s->pid);
if (s->pid != 0) { if (s->pid != 0) {
debug("session_close_by_channel: channel %d: has child", id); debug("%s: channel %d: has child", __func__, id);
/* /*
* delay detach of session, but release pty, since * delay detach of session, but release pty, since
* the fd's to the child are already closed * the fd's to the child are already closed
@ -2639,22 +2632,22 @@ session_close_by_channel(int id, void *arg)
return; return;
} }
/* detach by removing callback */ /* detach by removing callback */
channel_cancel_cleanup(s->chanid); channel_cancel_cleanup(ssh, s->chanid);
/* Close any X11 listeners associated with this session */ /* Close any X11 listeners associated with this session */
if (s->x11_chanids != NULL) { if (s->x11_chanids != NULL) {
for (i = 0; s->x11_chanids[i] != -1; i++) { for (i = 0; s->x11_chanids[i] != -1; i++) {
session_close_x11(s->x11_chanids[i]); session_close_x11(ssh, s->x11_chanids[i]);
s->x11_chanids[i] = -1; s->x11_chanids[i] = -1;
} }
} }
s->chanid = -1; s->chanid = -1;
session_close(s); session_close(ssh, s);
} }
void void
session_destroy_all(void (*closefunc)(Session *)) session_destroy_all(struct ssh *ssh, void (*closefunc)(Session *))
{ {
int i; int i;
for (i = 0; i < sessions_nalloc; i++) { for (i = 0; i < sessions_nalloc; i++) {
@ -2663,7 +2656,7 @@ session_destroy_all(void (*closefunc)(Session *))
if (closefunc != NULL) if (closefunc != NULL)
closefunc(s); closefunc(s);
else else
session_close(s); session_close(ssh, s);
} }
} }
} }
@ -2706,7 +2699,7 @@ session_proctitle(Session *s)
} }
int int
session_setup_x11fwd(Session *s) session_setup_x11fwd(struct ssh *ssh, Session *s)
{ {
struct stat st; struct stat st;
char display[512], auth_display[512]; char display[512], auth_display[512];
@ -2730,14 +2723,14 @@ session_setup_x11fwd(Session *s)
debug("X11 display already set."); debug("X11 display already set.");
return 0; return 0;
} }
if (x11_create_display_inet(options.x11_display_offset, if (x11_create_display_inet(ssh, options.x11_display_offset,
options.x11_use_localhost, s->single_connection, options.x11_use_localhost, s->single_connection,
&s->display_number, &s->x11_chanids) == -1) { &s->display_number, &s->x11_chanids) == -1) {
debug("x11_create_display_inet failed."); debug("x11_create_display_inet failed.");
return 0; return 0;
} }
for (i = 0; s->x11_chanids[i] != -1; i++) { for (i = 0; s->x11_chanids[i] != -1; i++) {
channel_register_cleanup(s->x11_chanids[i], channel_register_cleanup(ssh, s->x11_chanids[i],
session_close_single_x11, 0); session_close_single_x11, 0);
} }
@ -2782,13 +2775,13 @@ session_setup_x11fwd(Session *s)
} }
static void static void
do_authenticated2(Authctxt *authctxt) do_authenticated2(struct ssh *ssh, Authctxt *authctxt)
{ {
server_loop2(authctxt); server_loop2(ssh, authctxt);
} }
void void
do_cleanup(Authctxt *authctxt) do_cleanup(struct ssh *ssh, Authctxt *authctxt)
{ {
static int called = 0; static int called = 0;
@ -2844,7 +2837,7 @@ do_cleanup(Authctxt *authctxt)
* or if running in monitor. * or if running in monitor.
*/ */
if (!use_privsep || mm_is_monitor()) if (!use_privsep || mm_is_monitor())
session_destroy_all(session_pty_cleanup2); session_destroy_all(ssh, session_pty_cleanup2);
} }
/* Return a name for the remote host that fits inside utmp_size */ /* Return a name for the remote host that fits inside utmp_size */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: session.h,v 1.34 2017/08/18 05:36:45 djm Exp $ */ /* $OpenBSD: session.h,v 1.35 2017/09/12 06:32:07 djm Exp $ */
/* /*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@ -62,20 +62,20 @@ struct Session {
} *env; } *env;
}; };
void do_authenticated(Authctxt *); void do_authenticated(struct ssh *, Authctxt *);
void do_cleanup(Authctxt *); void do_cleanup(struct ssh *, Authctxt *);
int session_open(Authctxt *, int); int session_open(Authctxt *, int);
void session_unused(int); void session_unused(int);
int session_input_channel_req(Channel *, const char *); int session_input_channel_req(struct ssh *, Channel *, const char *);
void session_close_by_pid(pid_t, int); void session_close_by_pid(struct ssh *ssh, pid_t, int);
void session_close_by_channel(int, void *); void session_close_by_channel(struct ssh *, int, void *);
void session_destroy_all(void (*)(Session *)); void session_destroy_all(struct ssh *, void (*)(Session *));
void session_pty_cleanup2(Session *); void session_pty_cleanup2(Session *);
Session *session_new(void); Session *session_new(void);
Session *session_by_tty(char *); Session *session_by_tty(char *);
void session_close(Session *); void session_close(struct ssh *, Session *);
void do_setusercontext(struct passwd *); void do_setusercontext(struct passwd *);
const char *session_get_remote_name_or_ip(struct ssh *, u_int, int); const char *session_get_remote_name_or_ip(struct ssh *, u_int, int);

View File

@ -1,4 +1,4 @@
.\" $OpenBSD: ssh-add.1,v 1.64 2017/05/05 10:41:58 naddy Exp $ .\" $OpenBSD: ssh-add.1,v 1.66 2017/08/29 13:05:58 jmc Exp $
.\" .\"
.\" Author: Tatu Ylonen <ylo@cs.hut.fi> .\" Author: Tatu Ylonen <ylo@cs.hut.fi>
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland .\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -35,7 +35,7 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\" .\"
.Dd $Mdocdate: May 5 2017 $ .Dd $Mdocdate: August 29 2017 $
.Dt SSH-ADD 1 .Dt SSH-ADD 1
.Os .Os
.Sh NAME .Sh NAME
@ -43,7 +43,7 @@
.Nd adds private key identities to the authentication agent .Nd adds private key identities to the authentication agent
.Sh SYNOPSIS .Sh SYNOPSIS
.Nm ssh-add .Nm ssh-add
.Op Fl cDdkLlXx .Op Fl cDdkLlqXx
.Op Fl E Ar fingerprint_hash .Op Fl E Ar fingerprint_hash
.Op Fl t Ar life .Op Fl t Ar life
.Op Ar .Op Ar
@ -126,6 +126,8 @@ Lists public key parameters of all identities currently represented
by the agent. by the agent.
.It Fl l .It Fl l
Lists fingerprints of all identities currently represented by the agent. Lists fingerprints of all identities currently represented by the agent.
.It Fl q
Be quiet after a successful operation.
.It Fl s Ar pkcs11 .It Fl s Ar pkcs11
Add keys provided by the PKCS#11 shared library Add keys provided by the PKCS#11 shared library
.Ar pkcs11 . .Ar pkcs11 .

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh-add.c,v 1.133 2017/07/01 13:50:45 djm Exp $ */ /* $OpenBSD: ssh-add.c,v 1.134 2017/08/29 09:42:29 dlg Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -102,7 +102,7 @@ clear_pass(void)
} }
static int static int
delete_file(int agent_fd, const char *filename, int key_only) delete_file(int agent_fd, const char *filename, int key_only, int qflag)
{ {
struct sshkey *public, *cert = NULL; struct sshkey *public, *cert = NULL;
char *certpath = NULL, *comment = NULL; char *certpath = NULL, *comment = NULL;
@ -113,7 +113,10 @@ delete_file(int agent_fd, const char *filename, int key_only)
return -1; return -1;
} }
if ((r = ssh_remove_identity(agent_fd, public)) == 0) { if ((r = ssh_remove_identity(agent_fd, public)) == 0) {
fprintf(stderr, "Identity removed: %s (%s)\n", filename, comment); if (!qflag) {
fprintf(stderr, "Identity removed: %s (%s)\n",
filename, comment);
}
ret = 0; ret = 0;
} else } else
fprintf(stderr, "Could not remove identity \"%s\": %s\n", fprintf(stderr, "Could not remove identity \"%s\": %s\n",
@ -138,8 +141,10 @@ delete_file(int agent_fd, const char *filename, int key_only)
certpath, filename); certpath, filename);
if ((r = ssh_remove_identity(agent_fd, cert)) == 0) { if ((r = ssh_remove_identity(agent_fd, cert)) == 0) {
fprintf(stderr, "Identity removed: %s (%s)\n", certpath, if (!qflag) {
comment); fprintf(stderr, "Identity removed: %s (%s)\n",
certpath, comment);
}
ret = 0; ret = 0;
} else } else
fprintf(stderr, "Could not remove identity \"%s\": %s\n", fprintf(stderr, "Could not remove identity \"%s\": %s\n",
@ -179,7 +184,7 @@ delete_all(int agent_fd)
} }
static int static int
add_file(int agent_fd, const char *filename, int key_only) add_file(int agent_fd, const char *filename, int key_only, int qflag)
{ {
struct sshkey *private, *cert; struct sshkey *private, *cert;
char *comment = NULL; char *comment = NULL;
@ -427,13 +432,13 @@ lock_agent(int agent_fd, int lock)
} }
static int static int
do_file(int agent_fd, int deleting, int key_only, char *file) do_file(int agent_fd, int deleting, int key_only, char *file, int qflag)
{ {
if (deleting) { if (deleting) {
if (delete_file(agent_fd, file, key_only) == -1) if (delete_file(agent_fd, file, key_only, qflag) == -1)
return -1; return -1;
} else { } else {
if (add_file(agent_fd, file, key_only) == -1) if (add_file(agent_fd, file, key_only, qflag) == -1)
return -1; return -1;
} }
return 0; return 0;
@ -456,6 +461,7 @@ usage(void)
fprintf(stderr, " -X Unlock agent.\n"); fprintf(stderr, " -X Unlock agent.\n");
fprintf(stderr, " -s pkcs11 Add keys from PKCS#11 provider.\n"); fprintf(stderr, " -s pkcs11 Add keys from PKCS#11 provider.\n");
fprintf(stderr, " -e pkcs11 Remove keys provided by PKCS#11 provider.\n"); fprintf(stderr, " -e pkcs11 Remove keys provided by PKCS#11 provider.\n");
fprintf(stderr, " -q Be quiet after a successful operation.\n");
} }
int int
@ -466,7 +472,7 @@ main(int argc, char **argv)
int agent_fd; int agent_fd;
char *pkcs11provider = NULL; char *pkcs11provider = NULL;
int r, i, ch, deleting = 0, ret = 0, key_only = 0; int r, i, ch, deleting = 0, ret = 0, key_only = 0;
int xflag = 0, lflag = 0, Dflag = 0; int xflag = 0, lflag = 0, Dflag = 0, qflag = 0;
ssh_malloc_init(); /* must be called before any mallocs */ ssh_malloc_init(); /* must be called before any mallocs */
/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
@ -494,7 +500,7 @@ main(int argc, char **argv)
exit(2); exit(2);
} }
while ((ch = getopt(argc, argv, "klLcdDxXE:e:s:t:")) != -1) { while ((ch = getopt(argc, argv, "klLcdDxXE:e:qs:t:")) != -1) {
switch (ch) { switch (ch) {
case 'E': case 'E':
fingerprint_hash = ssh_digest_alg_by_name(optarg); fingerprint_hash = ssh_digest_alg_by_name(optarg);
@ -539,6 +545,9 @@ main(int argc, char **argv)
goto done; goto done;
} }
break; break;
case 'q':
qflag = 1;
break;
default: default:
usage(); usage();
ret = 1; ret = 1;
@ -587,7 +596,8 @@ main(int argc, char **argv)
default_files[i]); default_files[i]);
if (stat(buf, &st) < 0) if (stat(buf, &st) < 0)
continue; continue;
if (do_file(agent_fd, deleting, key_only, buf) == -1) if (do_file(agent_fd, deleting, key_only, buf,
qflag) == -1)
ret = 1; ret = 1;
else else
count++; count++;
@ -597,7 +607,7 @@ main(int argc, char **argv)
} else { } else {
for (i = 0; i < argc; i++) { for (i = 0; i < argc; i++) {
if (do_file(agent_fd, deleting, key_only, if (do_file(agent_fd, deleting, key_only,
argv[i]) == -1) argv[i], qflag) == -1)
ret = 1; ret = 1;
} }
} }

21
ssh.1
View File

@ -33,8 +33,8 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\" .\"
.\" $OpenBSD: ssh.1,v 1.383 2017/06/09 06:43:01 djm Exp $ .\" $OpenBSD: ssh.1,v 1.384 2017/09/21 19:16:53 markus Exp $
.Dd $Mdocdate: June 9 2017 $ .Dd $Mdocdate: September 21 2017 $
.Dt SSH 1 .Dt SSH 1
.Os .Os
.Sh NAME .Sh NAME
@ -592,21 +592,30 @@ Causes most warning and diagnostic messages to be suppressed.
.Ar remote_socket : local_socket .Ar remote_socket : local_socket
.Sm on .Sm on
.Xc .Xc
.It Fl R Xo
.Sm off
.Oo Ar bind_address : Oc
.Ar port
.Sm on
.Xc
Specifies that connections to the given TCP port or Unix socket on the remote Specifies that connections to the given TCP port or Unix socket on the remote
(server) host are to be forwarded to the given host and port, or Unix socket, (server) host are to be forwarded to the local side.
on the local side. .Pp
This works by allocating a socket to listen to either a TCP This works by allocating a socket to listen to either a TCP
.Ar port .Ar port
or to a Unix socket on the remote side. or to a Unix socket on the remote side.
Whenever a connection is made to this port or Unix socket, the Whenever a connection is made to this port or Unix socket, the
connection is forwarded over the secure channel, and a connection connection is forwarded over the secure channel, and a connection
is made to either is made from the local machine to either an explicit destination specified by
.Ar host .Ar host
port port
.Ar hostport , .Ar hostport ,
or or
.Ar local_socket , .Ar local_socket ,
from the local machine. or, if no explicit destination was specified,
.Nm
will act as a SOCKS 4/5 proxy and forward connections to the destinations
requested by the remote SOCKS client.
.Pp .Pp
Port forwardings can also be specified in the configuration file. Port forwardings can also be specified in the configuration file.
Privileged ports can be forwarded only when Privileged ports can be forwarded only when

91
ssh.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh.c,v 1.462 2017/08/12 06:46:01 djm Exp $ */ /* $OpenBSD: ssh.c,v 1.464 2017/09/21 19:16:53 markus Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -208,7 +208,7 @@ usage(void)
exit(255); exit(255);
} }
static int ssh_session2(void); static int ssh_session2(struct ssh *);
static void load_public_identity_files(void); static void load_public_identity_files(void);
static void main_sigchld_handler(int); static void main_sigchld_handler(int);
@ -596,6 +596,14 @@ main(int ac, char **av)
*/ */
initialize_options(&options); initialize_options(&options);
/*
* Prepare main ssh transport/connection structures
*/
if ((ssh = ssh_alloc_session_state()) == NULL)
fatal("Couldn't allocate session state");
channel_init_channels(ssh);
active_state = ssh; /* XXX legacy API compat */
/* Parse command-line arguments. */ /* Parse command-line arguments. */
host = NULL; host = NULL;
use_syslog = 0; use_syslog = 0;
@ -860,7 +868,8 @@ main(int ac, char **av)
break; break;
case 'R': case 'R':
if (parse_forward(&fwd, optarg, 0, 1)) { if (parse_forward(&fwd, optarg, 0, 1) ||
parse_forward(&fwd, optarg, 1, 1)) {
add_remote_forward(&options, &fwd); add_remote_forward(&options, &fwd);
} else { } else {
fprintf(stderr, fprintf(stderr,
@ -1108,7 +1117,7 @@ main(int ac, char **av)
if (options.port == 0) if (options.port == 0)
options.port = default_ssh_port(); options.port = default_ssh_port();
channel_set_af(options.address_family); channel_set_af(ssh, options.address_family);
/* Tidy and check options */ /* Tidy and check options */
if (options.host_key_alias != NULL) if (options.host_key_alias != NULL)
@ -1253,8 +1262,7 @@ main(int ac, char **av)
if (options.control_path != NULL) { if (options.control_path != NULL) {
int sock; int sock;
if ((sock = muxclient(options.control_path)) >= 0) { if ((sock = muxclient(options.control_path)) >= 0) {
packet_set_connection(sock, sock); ssh_packet_set_connection(ssh, sock, sock);
ssh = active_state; /* XXX */
packet_set_mux(); packet_set_mux();
goto skip_connect; goto skip_connect;
} }
@ -1274,7 +1282,7 @@ main(int ac, char **av)
timeout_ms = options.connection_timeout * 1000; timeout_ms = options.connection_timeout * 1000;
/* Open a connection to the remote host. */ /* Open a connection to the remote host. */
if (ssh_connect(host, addrs, &hostaddr, options.port, if (ssh_connect(ssh, host, addrs, &hostaddr, options.port,
options.address_family, options.connection_attempts, options.address_family, options.connection_attempts,
&timeout_ms, options.tcp_keep_alive, &timeout_ms, options.tcp_keep_alive,
options.use_privileged_port) != 0) options.use_privileged_port) != 0)
@ -1457,7 +1465,7 @@ main(int ac, char **av)
} }
skip_connect: skip_connect:
exit_status = ssh_session2(); exit_status = ssh_session2(ssh);
packet_close(); packet_close();
if (options.control_path != NULL && muxserver_sock != -1) if (options.control_path != NULL && muxserver_sock != -1)
@ -1539,7 +1547,7 @@ fork_postauth(void)
/* Callback for remote forward global requests */ /* Callback for remote forward global requests */
static void static void
ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) ssh_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt)
{ {
struct Forward *rfwd = (struct Forward *)ctxt; struct Forward *rfwd = (struct Forward *)ctxt;
@ -1557,10 +1565,10 @@ ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
logit("Allocated port %u for remote forward to %s:%d", logit("Allocated port %u for remote forward to %s:%d",
rfwd->allocated_port, rfwd->allocated_port,
rfwd->connect_host, rfwd->connect_port); rfwd->connect_host, rfwd->connect_port);
channel_update_permitted_opens(rfwd->handle, channel_update_permitted_opens(ssh,
rfwd->allocated_port); rfwd->handle, rfwd->allocated_port);
} else { } else {
channel_update_permitted_opens(rfwd->handle, -1); channel_update_permitted_opens(ssh, rfwd->handle, -1);
} }
} }
@ -1589,21 +1597,21 @@ ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
} }
static void static void
client_cleanup_stdio_fwd(int id, void *arg) client_cleanup_stdio_fwd(struct ssh *ssh, int id, void *arg)
{ {
debug("stdio forwarding: done"); debug("stdio forwarding: done");
cleanup_exit(0); cleanup_exit(0);
} }
static void static void
ssh_stdio_confirm(int id, int success, void *arg) ssh_stdio_confirm(struct ssh *ssh, int id, int success, void *arg)
{ {
if (!success) if (!success)
fatal("stdio forwarding failed"); fatal("stdio forwarding failed");
} }
static void static void
ssh_init_stdio_forwarding(void) ssh_init_stdio_forwarding(struct ssh *ssh)
{ {
Channel *c; Channel *c;
int in, out; int in, out;
@ -1617,15 +1625,15 @@ ssh_init_stdio_forwarding(void)
if ((in = dup(STDIN_FILENO)) < 0 || if ((in = dup(STDIN_FILENO)) < 0 ||
(out = dup(STDOUT_FILENO)) < 0) (out = dup(STDOUT_FILENO)) < 0)
fatal("channel_connect_stdio_fwd: dup() in/out failed"); fatal("channel_connect_stdio_fwd: dup() in/out failed");
if ((c = channel_connect_stdio_fwd(options.stdio_forward_host, if ((c = channel_connect_stdio_fwd(ssh, options.stdio_forward_host,
options.stdio_forward_port, in, out)) == NULL) options.stdio_forward_port, in, out)) == NULL)
fatal("%s: channel_connect_stdio_fwd failed", __func__); fatal("%s: channel_connect_stdio_fwd failed", __func__);
channel_register_cleanup(c->self, client_cleanup_stdio_fwd, 0); channel_register_cleanup(ssh, c->self, client_cleanup_stdio_fwd, 0);
channel_register_open_confirm(c->self, ssh_stdio_confirm, NULL); channel_register_open_confirm(ssh, c->self, ssh_stdio_confirm, NULL);
} }
static void static void
ssh_init_forwarding(void) ssh_init_forwarding(struct ssh *ssh)
{ {
int success = 0; int success = 0;
int i; int i;
@ -1644,7 +1652,7 @@ ssh_init_forwarding(void)
options.local_forwards[i].connect_path : options.local_forwards[i].connect_path :
options.local_forwards[i].connect_host, options.local_forwards[i].connect_host,
options.local_forwards[i].connect_port); options.local_forwards[i].connect_port);
success += channel_setup_local_fwd_listener( success += channel_setup_local_fwd_listener(ssh,
&options.local_forwards[i], &options.fwd_opts); &options.local_forwards[i], &options.fwd_opts);
} }
if (i > 0 && success != i && options.exit_on_forward_failure) if (i > 0 && success != i && options.exit_on_forward_failure)
@ -1666,7 +1674,7 @@ ssh_init_forwarding(void)
options.remote_forwards[i].connect_host, options.remote_forwards[i].connect_host,
options.remote_forwards[i].connect_port); options.remote_forwards[i].connect_port);
options.remote_forwards[i].handle = options.remote_forwards[i].handle =
channel_request_remote_forwarding( channel_request_remote_forwarding(ssh,
&options.remote_forwards[i]); &options.remote_forwards[i]);
if (options.remote_forwards[i].handle < 0) { if (options.remote_forwards[i].handle < 0) {
if (options.exit_on_forward_failure) if (options.exit_on_forward_failure)
@ -1675,14 +1683,15 @@ ssh_init_forwarding(void)
logit("Warning: Could not request remote " logit("Warning: Could not request remote "
"forwarding."); "forwarding.");
} else { } else {
client_register_global_confirm(ssh_confirm_remote_forward, client_register_global_confirm(
ssh_confirm_remote_forward,
&options.remote_forwards[i]); &options.remote_forwards[i]);
} }
} }
/* Initiate tunnel forwarding. */ /* Initiate tunnel forwarding. */
if (options.tun_open != SSH_TUNMODE_NO) { if (options.tun_open != SSH_TUNMODE_NO) {
if (client_request_tun_fwd(options.tun_open, if (client_request_tun_fwd(ssh, options.tun_open,
options.tun_local, options.tun_remote) == -1) { options.tun_local, options.tun_remote) == -1) {
if (options.exit_on_forward_failure) if (options.exit_on_forward_failure)
fatal("Could not request tunnel forwarding."); fatal("Could not request tunnel forwarding.");
@ -1709,7 +1718,7 @@ check_agent_present(void)
} }
static void static void
ssh_session2_setup(int id, int success, void *arg) ssh_session2_setup(struct ssh *ssh, int id, int success, void *arg)
{ {
extern char **environ; extern char **environ;
const char *display; const char *display;
@ -1722,15 +1731,15 @@ ssh_session2_setup(int id, int success, void *arg)
display = getenv("DISPLAY"); display = getenv("DISPLAY");
if (display == NULL && options.forward_x11) if (display == NULL && options.forward_x11)
debug("X11 forwarding requested but DISPLAY not set"); debug("X11 forwarding requested but DISPLAY not set");
if (options.forward_x11 && client_x11_get_proto(display, if (options.forward_x11 && client_x11_get_proto(ssh, display,
options.xauth_location, options.forward_x11_trusted, options.xauth_location, options.forward_x11_trusted,
options.forward_x11_timeout, &proto, &data) == 0) { options.forward_x11_timeout, &proto, &data) == 0) {
/* Request forwarding with authentication spoofing. */ /* Request forwarding with authentication spoofing. */
debug("Requesting X11 forwarding with authentication " debug("Requesting X11 forwarding with authentication "
"spoofing."); "spoofing.");
x11_request_forwarding_with_spoofing(id, display, proto, x11_request_forwarding_with_spoofing(ssh, id, display, proto,
data, 1); data, 1);
client_expect_confirm(id, "X11 forwarding", CONFIRM_WARN); client_expect_confirm(ssh, id, "X11 forwarding", CONFIRM_WARN);
/* XXX exit_on_forward_failure */ /* XXX exit_on_forward_failure */
interactive = 1; interactive = 1;
} }
@ -1738,7 +1747,7 @@ ssh_session2_setup(int id, int success, void *arg)
check_agent_present(); check_agent_present();
if (options.forward_agent) { if (options.forward_agent) {
debug("Requesting authentication agent forwarding."); debug("Requesting authentication agent forwarding.");
channel_request_start(id, "auth-agent-req@openssh.com", 0); channel_request_start(ssh, id, "auth-agent-req@openssh.com", 0);
packet_send(); packet_send();
} }
@ -1746,13 +1755,13 @@ ssh_session2_setup(int id, int success, void *arg)
packet_set_interactive(interactive, packet_set_interactive(interactive,
options.ip_qos_interactive, options.ip_qos_bulk); options.ip_qos_interactive, options.ip_qos_bulk);
client_session2_setup(id, tty_flag, subsystem_flag, getenv("TERM"), client_session2_setup(ssh, id, tty_flag, subsystem_flag, getenv("TERM"),
NULL, fileno(stdin), &command, environ); NULL, fileno(stdin), &command, environ);
} }
/* open new channel for a session */ /* open new channel for a session */
static int static int
ssh_session2_open(void) ssh_session2_open(struct ssh *ssh)
{ {
Channel *c; Channel *c;
int window, packetmax, in, out, err; int window, packetmax, in, out, err;
@ -1782,34 +1791,34 @@ ssh_session2_open(void)
window >>= 1; window >>= 1;
packetmax >>= 1; packetmax >>= 1;
} }
c = channel_new( c = channel_new(ssh,
"session", SSH_CHANNEL_OPENING, in, out, err, "session", SSH_CHANNEL_OPENING, in, out, err,
window, packetmax, CHAN_EXTENDED_WRITE, window, packetmax, CHAN_EXTENDED_WRITE,
"client-session", /*nonblock*/0); "client-session", /*nonblock*/0);
debug3("ssh_session2_open: channel_new: %d", c->self); debug3("%s: channel_new: %d", __func__, c->self);
channel_send_open(c->self); channel_send_open(ssh, c->self);
if (!no_shell_flag) if (!no_shell_flag)
channel_register_open_confirm(c->self, channel_register_open_confirm(ssh, c->self,
ssh_session2_setup, NULL); ssh_session2_setup, NULL);
return c->self; return c->self;
} }
static int static int
ssh_session2(void) ssh_session2(struct ssh *ssh)
{ {
int id = -1; int id = -1;
/* XXX should be pre-session */ /* XXX should be pre-session */
if (!options.control_persist) if (!options.control_persist)
ssh_init_stdio_forwarding(); ssh_init_stdio_forwarding(ssh);
ssh_init_forwarding(); ssh_init_forwarding(ssh);
/* Start listening for multiplex clients */ /* Start listening for multiplex clients */
if (!packet_get_mux()) if (!packet_get_mux())
muxserver_listen(); muxserver_listen(ssh);
/* /*
* If we are in control persist mode and have a working mux listen * If we are in control persist mode and have a working mux listen
@ -1837,10 +1846,10 @@ ssh_session2(void)
* stdio forward setup that we skipped earlier. * stdio forward setup that we skipped earlier.
*/ */
if (options.control_persist && muxserver_sock == -1) if (options.control_persist && muxserver_sock == -1)
ssh_init_stdio_forwarding(); ssh_init_stdio_forwarding(ssh);
if (!no_shell_flag || (datafellows & SSH_BUG_DUMMYCHAN)) if (!no_shell_flag || (datafellows & SSH_BUG_DUMMYCHAN))
id = ssh_session2_open(); id = ssh_session2_open(ssh);
else { else {
packet_set_interactive( packet_set_interactive(
options.control_master == SSHCTL_MASTER_NO, options.control_master == SSHCTL_MASTER_NO,
@ -1875,7 +1884,7 @@ ssh_session2(void)
fork_postauth(); fork_postauth();
} }
return client_loop(tty_flag, tty_flag ? return client_loop(ssh, tty_flag, tty_flag ?
options.escape_char : SSH_ESCAPECHAR_NONE, id); options.escape_char : SSH_ESCAPECHAR_NONE, id);
} }

View File

@ -33,8 +33,8 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\" .\"
.\" $OpenBSD: ssh_config.5,v 1.253 2017/07/23 23:37:02 djm Exp $ .\" $OpenBSD: ssh_config.5,v 1.256 2017/09/21 19:16:53 markus Exp $
.Dd $Mdocdate: July 23 2017 $ .Dd $Mdocdate: September 21 2017 $
.Dt SSH_CONFIG 5 .Dt SSH_CONFIG 5
.Os .Os
.Sh NAME .Sh NAME
@ -1298,13 +1298,19 @@ accept the tokens described in the
section. section.
.It Cm RemoteForward .It Cm RemoteForward
Specifies that a TCP port on the remote machine be forwarded over Specifies that a TCP port on the remote machine be forwarded over
the secure channel to the specified host and port from the local machine. the secure channel.
The remote port may either be fowarded to a specified host and port
from the local machine, or may act as a SOCKS 4/5 proxy that allows a remote
client to connect to arbitrary destinations from the local machine.
The first argument must be The first argument must be
.Sm off .Sm off
.Oo Ar bind_address : Oc Ar port .Oo Ar bind_address : Oc Ar port
.Sm on .Sm on
and the second argument must be If forwarding to a specific destination then the second argument must be
.Ar host : Ns Ar hostport . .Ar host : Ns Ar hostport ,
otherwise if no destination argument is specified then the remote forwarding
will be established as a SOCKS proxy.
.Pp
IPv6 addresses can be specified by enclosing addresses in square brackets. IPv6 addresses can be specified by enclosing addresses in square brackets.
Multiple forwardings may be specified, and additional Multiple forwardings may be specified, and additional
forwardings can be given on the command line. forwardings can be given on the command line.
@ -1458,10 +1464,19 @@ file is poorly maintained or when connections to new hosts are
frequently made. frequently made.
This option forces the user to manually This option forces the user to manually
add all new hosts. add all new hosts.
.Pp
If this flag is set to If this flag is set to
.Cm no , .Dq accept-new
ssh will automatically add new host keys to the then ssh will automatically add new host keys to the user
user known hosts files. known hosts files, but will not permit connections to hosts with
changed host keys.
If this flag is set to
.Dq no
or
.Dq off ,
ssh will automatically add new host keys to the user known hosts files
and allow connections to hosts with changed hostkeys to proceed,
subject to some restrictions.
If this flag is set to If this flag is set to
.Cm ask .Cm ask
(the default), (the default),

View File

@ -1,4 +1,4 @@
/* $OpenBSD: sshbuf.h,v 1.8 2016/11/25 23:22:04 djm Exp $ */ /* $OpenBSD: sshbuf.h,v 1.9 2017/09/12 06:32:07 djm Exp $ */
/* /*
* Copyright (c) 2011 Damien Miller * Copyright (c) 2011 Damien Miller
* *
@ -211,6 +211,7 @@ int sshbuf_get_string_direct(struct sshbuf *buf, const u_char **valp,
/* Another variant: "peeks" into the buffer without modifying it */ /* Another variant: "peeks" into the buffer without modifying it */
int sshbuf_peek_string_direct(const struct sshbuf *buf, const u_char **valp, int sshbuf_peek_string_direct(const struct sshbuf *buf, const u_char **valp,
size_t *lenp); size_t *lenp);
/* XXX peek_u8 / peek_u32 */
/* /*
* Functions to extract or store SSH wire encoded bignums and elliptic * Functions to extract or store SSH wire encoded bignums and elliptic

View File

@ -1,4 +1,4 @@
/* $OpenBSD: sshconnect.c,v 1.283 2017/07/01 13:50:45 djm Exp $ */ /* $OpenBSD: sshconnect.c,v 1.287 2017/09/14 04:32:21 djm Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -104,7 +104,7 @@ expand_proxy_command(const char *proxy_command, const char *user,
* a connected fd back to us. * a connected fd back to us.
*/ */
static int static int
ssh_proxy_fdpass_connect(const char *host, u_short port, ssh_proxy_fdpass_connect(struct ssh *ssh, const char *host, u_short port,
const char *proxy_command) const char *proxy_command)
{ {
#ifdef WINDOWS #ifdef WINDOWS
@ -185,7 +185,8 @@ ssh_proxy_fdpass_connect(const char *host, u_short port,
fatal("Couldn't wait for child: %s", strerror(errno)); fatal("Couldn't wait for child: %s", strerror(errno));
/* Set the connection file descriptors. */ /* Set the connection file descriptors. */
packet_set_connection(sock, sock); if (ssh_packet_set_connection(ssh, sock, sock) == NULL)
return -1; /* ssh_packet_set_connection logs error */
return 0; return 0;
#endif /* !WINDOWS */ #endif /* !WINDOWS */
@ -195,7 +196,8 @@ ssh_proxy_fdpass_connect(const char *host, u_short port,
* Connect to the given ssh server using a proxy command. * Connect to the given ssh server using a proxy command.
*/ */
static int static int
ssh_proxy_connect(const char *host, u_short port, const char *proxy_command) ssh_proxy_connect(struct ssh *ssh, const char *host, u_short port,
const char *proxy_command)
{ {
#ifdef WINDOWS #ifdef WINDOWS
fatal("Proxy connect is not supported in Windows yet"); fatal("Proxy connect is not supported in Windows yet");
@ -266,9 +268,9 @@ ssh_proxy_connect(const char *host, u_short port, const char *proxy_command)
free(command_string); free(command_string);
/* Set the connection file descriptors. */ /* Set the connection file descriptors. */
packet_set_connection(pout[0], pin[1]); if (ssh_packet_set_connection(ssh, pout[0], pin[1]) == NULL)
return -1; /* ssh_packet_set_connection logs error */
/* Indicate OK return */
return 0; return 0;
#endif /* !WINDOWS */ #endif /* !WINDOWS */
} }
@ -425,7 +427,7 @@ timeout_connect(int sockfd, const struct sockaddr *serv_addr,
* the daemon. * the daemon.
*/ */
static int static int
ssh_connect_direct(const char *host, struct addrinfo *aitop, ssh_connect_direct(struct ssh *ssh, const char *host, struct addrinfo *aitop,
struct sockaddr_storage *hostaddr, u_short port, int family, struct sockaddr_storage *hostaddr, u_short port, int family,
int connection_attempts, int *timeout_ms, int want_keepalive, int needpriv) int connection_attempts, int *timeout_ms, int want_keepalive, int needpriv)
{ {
@ -499,27 +501,31 @@ ssh_connect_direct(const char *host, struct addrinfo *aitop,
error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno)); error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno));
/* Set the connection. */ /* Set the connection. */
packet_set_connection(sock, sock); if (ssh_packet_set_connection(ssh, sock, sock) == NULL)
return -1; /* ssh_packet_set_connection logs error */
return 0; return 0;
} }
int int
ssh_connect(const char *host, struct addrinfo *addrs, ssh_connect(struct ssh *ssh, const char *host, struct addrinfo *addrs,
struct sockaddr_storage *hostaddr, u_short port, int family, struct sockaddr_storage *hostaddr, u_short port, int family,
int connection_attempts, int *timeout_ms, int want_keepalive, int needpriv) int connection_attempts, int *timeout_ms, int want_keepalive, int needpriv)
{ {
if (options.proxy_command == NULL) { if (options.proxy_command == NULL) {
return ssh_connect_direct(host, addrs, hostaddr, port, family, return ssh_connect_direct(ssh, host, addrs, hostaddr, port,
connection_attempts, timeout_ms, want_keepalive, needpriv); family, connection_attempts, timeout_ms, want_keepalive,
needpriv);
} else if (strcmp(options.proxy_command, "-") == 0) { } else if (strcmp(options.proxy_command, "-") == 0) {
packet_set_connection(STDIN_FILENO, STDOUT_FILENO); if ((ssh_packet_set_connection(ssh,
return 0; /* Always succeeds */ STDIN_FILENO, STDOUT_FILENO)) == NULL)
return -1; /* ssh_packet_set_connection logs error */
return 0;
} else if (options.proxy_use_fdpass) { } else if (options.proxy_use_fdpass) {
return ssh_proxy_fdpass_connect(host, port, return ssh_proxy_fdpass_connect(ssh, host, port,
options.proxy_command); options.proxy_command);
} }
return ssh_proxy_connect(host, port, options.proxy_command); return ssh_proxy_connect(ssh, host, port, options.proxy_command);
} }
static void static void
@ -896,7 +902,8 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
if (readonly || want_cert) if (readonly || want_cert)
goto fail; goto fail;
/* The host is new. */ /* The host is new. */
if (options.strict_host_key_checking == 1) { if (options.strict_host_key_checking ==
SSH_STRICT_HOSTKEY_YES) {
/* /*
* User has requested strict host key checking. We * User has requested strict host key checking. We
* will not add the host key automatically. The only * will not add the host key automatically. The only
@ -905,7 +912,8 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
error("No %s host key is known for %.200s and you " error("No %s host key is known for %.200s and you "
"have requested strict checking.", type, host); "have requested strict checking.", type, host);
goto fail; goto fail;
} else if (options.strict_host_key_checking == 2) { } else if (options.strict_host_key_checking ==
SSH_STRICT_HOSTKEY_ASK) {
char msg1[1024], msg2[1024]; char msg1[1024], msg2[1024];
if (show_other_keys(host_hostkeys, host_key)) if (show_other_keys(host_hostkeys, host_key))
@ -949,8 +957,8 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
hostkey_trusted = 1; /* user explicitly confirmed */ hostkey_trusted = 1; /* user explicitly confirmed */
} }
/* /*
* If not in strict mode, add the key automatically to the * If in "new" or "off" strict mode, add the key automatically
* local known_hosts file. * to the local known_hosts file.
*/ */
if (options.check_host_ip && ip_status == HOST_NEW) { if (options.check_host_ip && ip_status == HOST_NEW) {
snprintf(hostline, sizeof(hostline), "%s,%s", host, ip); snprintf(hostline, sizeof(hostline), "%s,%s", host, ip);
@ -992,7 +1000,8 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
* If strict host key checking is in use, the user will have * If strict host key checking is in use, the user will have
* to edit the key manually and we can only abort. * to edit the key manually and we can only abort.
*/ */
if (options.strict_host_key_checking) { if (options.strict_host_key_checking !=
SSH_STRICT_HOSTKEY_OFF) {
error("%s host key for %.200s was revoked and you have " error("%s host key for %.200s was revoked and you have "
"requested strict checking.", type, host); "requested strict checking.", type, host);
goto fail; goto fail;
@ -1045,7 +1054,8 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
* If strict host key checking is in use, the user will have * If strict host key checking is in use, the user will have
* to edit the key manually and we can only abort. * to edit the key manually and we can only abort.
*/ */
if (options.strict_host_key_checking) { if (options.strict_host_key_checking !=
SSH_STRICT_HOSTKEY_OFF) {
error("%s host key for %.200s has changed and you have " error("%s host key for %.200s has changed and you have "
"requested strict checking.", type, host); "requested strict checking.", type, host);
goto fail; goto fail;
@ -1132,15 +1142,17 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
"\nMatching host key in %s:%lu", "\nMatching host key in %s:%lu",
host_found->file, host_found->line); host_found->file, host_found->line);
} }
if (options.strict_host_key_checking == 1) { if (options.strict_host_key_checking ==
logit("%s", msg); SSH_STRICT_HOSTKEY_ASK) {
error("Exiting, you have requested strict checking.");
goto fail;
} else if (options.strict_host_key_checking == 2) {
strlcat(msg, "\nAre you sure you want " strlcat(msg, "\nAre you sure you want "
"to continue connecting (yes/no)? ", sizeof(msg)); "to continue connecting (yes/no)? ", sizeof(msg));
if (!confirm(msg)) if (!confirm(msg))
goto fail; goto fail;
} else if (options.strict_host_key_checking !=
SSH_STRICT_HOSTKEY_OFF) {
logit("%s", msg);
error("Exiting, you have requested strict checking.");
goto fail;
} else { } else {
logit("%s", msg); logit("%s", msg);
} }

View File

@ -1,4 +1,4 @@
/* $OpenBSD: sshconnect.h,v 1.30 2017/05/30 08:52:19 markus Exp $ */ /* $OpenBSD: sshconnect.h,v 1.31 2017/09/12 06:32:07 djm Exp $ */
/* /*
* Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2000 Markus Friedl. All rights reserved.
@ -32,8 +32,10 @@ struct Sensitive {
}; };
struct addrinfo; struct addrinfo;
int ssh_connect(const char *, struct addrinfo *, struct sockaddr_storage *, struct ssh;
u_short, int, int, int *, int, int);
int ssh_connect(struct ssh *, const char *, struct addrinfo *,
struct sockaddr_storage *, u_short, int, int, int *, int, int);
void ssh_kill_proxy_command(void); void ssh_kill_proxy_command(void);
void ssh_login(Sensitive *, const char *, struct sockaddr *, u_short, void ssh_login(Sensitive *, const char *, struct sockaddr *, u_short,

View File

@ -1,4 +1,4 @@
/* $OpenBSD: sshconnect2.c,v 1.265 2017/08/11 04:47:12 djm Exp $ */ /* $OpenBSD: sshconnect2.c,v 1.266 2017/08/27 00:38:41 dtucker Exp $ */
/* /*
* Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2000 Markus Friedl. All rights reserved.
* Copyright (c) 2008 Damien Miller. All rights reserved. * Copyright (c) 2008 Damien Miller. All rights reserved.
@ -900,7 +900,7 @@ int
userauth_passwd(Authctxt *authctxt) userauth_passwd(Authctxt *authctxt)
{ {
static int attempt = 0; static int attempt = 0;
char prompt[150]; char prompt[256];
char *password; char *password;
const char *host = options.host_key_alias ? options.host_key_alias : const char *host = options.host_key_alias ? options.host_key_alias :
authctxt->host; authctxt->host;
@ -940,7 +940,7 @@ input_userauth_passwd_changereq(int type, u_int32_t seqnr, struct ssh *ssh)
{ {
Authctxt *authctxt = ssh->authctxt; Authctxt *authctxt = ssh->authctxt;
char *info, *lang, *password = NULL, *retype = NULL; char *info, *lang, *password = NULL, *retype = NULL;
char prompt[150]; char prompt[256];
const char *host; const char *host;
debug2("input_userauth_passwd_changereq"); debug2("input_userauth_passwd_changereq");

19
sshd.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: sshd.c,v 1.491 2017/07/01 13:50:45 djm Exp $ */ /* $OpenBSD: sshd.c,v 1.492 2017/09/12 06:32:07 djm Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -1714,9 +1714,6 @@ main(int ac, char **av)
"enabled authentication methods"); "enabled authentication methods");
} }
/* set default channel AF */
channel_set_af(options.address_family);
/* Check that there are no remaining arguments. */ /* Check that there are no remaining arguments. */
if (optind < ac) { if (optind < ac) {
fprintf(stderr, "Extra argument %s.\n", av[optind]); fprintf(stderr, "Extra argument %s.\n", av[optind]);
@ -2075,8 +2072,14 @@ main(int ac, char **av)
packet_set_connection(sock_in, sock_out); packet_set_connection(sock_in, sock_out);
packet_set_server(); packet_set_server();
ssh = active_state; /* XXX */ ssh = active_state; /* XXX */
check_ip_options(ssh); check_ip_options(ssh);
/* Prepare the channels layer */
channel_init_channels(ssh);
channel_set_af(ssh, options.address_family);
process_permitopen(ssh, &options);
/* Set SO_KEEPALIVE if requested. */ /* Set SO_KEEPALIVE if requested. */
if (options.tcp_keep_alive && packet_connection_is_on_socket() && if (options.tcp_keep_alive && packet_connection_is_on_socket() &&
setsockopt(sock_in, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) < 0) setsockopt(sock_in, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) < 0)
@ -2200,10 +2203,10 @@ main(int ac, char **av)
options.client_alive_count_max); options.client_alive_count_max);
/* Try to send all our hostkeys to the client */ /* Try to send all our hostkeys to the client */
notify_hostkeys(active_state); notify_hostkeys(ssh);
/* Start session. */ /* Start session. */
do_authenticated(authctxt); do_authenticated(ssh, authctxt);
/* The connection has been terminated. */ /* The connection has been terminated. */
packet_get_bytes(&ibytes, &obytes); packet_get_bytes(&ibytes, &obytes);
@ -2331,8 +2334,10 @@ do_ssh2_kex(void)
void void
cleanup_exit(int i) cleanup_exit(int i)
{ {
struct ssh *ssh = active_state; /* XXX */
if (the_authctxt) { if (the_authctxt) {
do_cleanup(the_authctxt); do_cleanup(ssh, the_authctxt);
if (use_privsep && privsep_is_preauth && if (use_privsep && privsep_is_preauth &&
pmonitor != NULL && pmonitor->m_pid > 1) { pmonitor != NULL && pmonitor->m_pid > 1) {
debug("Killing privsep child %d", pmonitor->m_pid); debug("Killing privsep child %d", pmonitor->m_pid);

View File

@ -33,8 +33,8 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\" .\"
.\" $OpenBSD: sshd_config.5,v 1.250 2017/07/23 23:37:02 djm Exp $ .\" $OpenBSD: sshd_config.5,v 1.253 2017/09/27 06:45:53 jmc Exp $
.Dd $Mdocdate: July 23 2017 $ .Dd $Mdocdate: September 27 2017 $
.Dt SSHD_CONFIG 5 .Dt SSHD_CONFIG 5
.Os .Os
.Sh NAME .Sh NAME
@ -223,6 +223,18 @@ requires successful authentication using two different public keys.
.Pp .Pp
Note that each authentication method listed should also be explicitly enabled Note that each authentication method listed should also be explicitly enabled
in the configuration. in the configuration.
.Pp
The available authentication methods are:
.Qq gssapi-with-mic ,
.Qq hostbased ,
.Qq keyboard-interactive ,
.Qq none
(used for access to password-less accounts when
.Cm PermitEmptyPassword
is enabled),
.Qq password
and
.Qq publickey .
.It Cm AuthorizedKeysCommand .It Cm AuthorizedKeysCommand
Specifies a program to be used to look up the user's public keys. Specifies a program to be used to look up the user's public keys.
The program must be owned by root, not writable by group or others and The program must be owned by root, not writable by group or others and
@ -563,11 +575,13 @@ TCP and StreamLocal.
This option overrides all other forwarding-related options and may This option overrides all other forwarding-related options and may
simplify restricted configurations. simplify restricted configurations.
.It Cm ExposeAuthInfo .It Cm ExposeAuthInfo
Enables writing a file containing a list of authentication methods and Writes a temporary file containing a list of authentication methods and
public credentials (e.g. keys) used to authenticate the user. public credentials (e.g. keys) used to authenticate the user.
The location of the file is exposed to the user session through the The location of the file is exposed to the user session through the
.Ev SSH_USER_AUTH .Ev SSH_USER_AUTH
environment variable. environment variable.
The default is
.Cm no .
.It Cm FingerprintHash .It Cm FingerprintHash
Specifies the hash algorithm used when logging key fingerprints. Specifies the hash algorithm used when logging key fingerprints.
Valid options are: Valid options are:

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssherr.c,v 1.6 2017/05/07 23:15:59 djm Exp $ */ /* $OpenBSD: ssherr.c,v 1.7 2017/09/12 06:32:08 djm Exp $ */
/* /*
* Copyright (c) 2011 Damien Miller * Copyright (c) 2011 Damien Miller
* *
@ -137,6 +137,8 @@ ssh_err(int n)
return "Protocol error"; return "Protocol error";
case SSH_ERR_KEY_LENGTH: case SSH_ERR_KEY_LENGTH:
return "Invalid key length"; return "Invalid key length";
case SSH_ERR_NUMBER_TOO_LARGE:
return "number is too large";
default: default:
return "unknown error"; return "unknown error";
} }

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssherr.h,v 1.4 2017/05/07 23:15:59 djm Exp $ */ /* $OpenBSD: ssherr.h,v 1.5 2017/09/12 06:32:08 djm Exp $ */
/* /*
* Copyright (c) 2011 Damien Miller * Copyright (c) 2011 Damien Miller
* *
@ -78,6 +78,7 @@
#define SSH_ERR_CONN_CORRUPT -54 #define SSH_ERR_CONN_CORRUPT -54
#define SSH_ERR_PROTOCOL_ERROR -55 #define SSH_ERR_PROTOCOL_ERROR -55
#define SSH_ERR_KEY_LENGTH -56 #define SSH_ERR_KEY_LENGTH -56
#define SSH_ERR_NUMBER_TOO_LARGE -57
/* Translate a numeric error code to a human-readable error string */ /* Translate a numeric error code to a human-readable error string */
const char *ssh_err(int n); const char *ssh_err(int n);

View File

@ -1,6 +1,6 @@
/* $OpenBSD: version.h,v 1.79 2017/03/20 01:18:59 djm Exp $ */ /* $OpenBSD: version.h,v 1.80 2017/09/30 22:26:33 djm Exp $ */
#define SSH_VERSION "OpenSSH_7.5" #define SSH_VERSION "OpenSSH_7.6"
#define SSH_PORTABLE "p1" #define SSH_PORTABLE "p1"
#define SSH_RELEASE SSH_VERSION SSH_PORTABLE #define SSH_RELEASE SSH_VERSION SSH_PORTABLE