View | Details | Raw Unified | Return to bug 1090 | Differences between
and this patch

Collapse All | Expand All

(-)clientloop.c (-18 / +42 lines)
Lines 164-169 struct confirm_ctx { Link Here
164
	char **env;
164
	char **env;
165
};
165
};
166
166
167
struct channel_reply_ctx {
168
	const char *request_type;
169
	int do_close;
170
};
171
167
/*XXX*/
172
/*XXX*/
168
extern Kex *xxx_kex;
173
extern Kex *xxx_kex;
169
174
Lines 636-645 client_process_net_input(fd_set *readset Link Here
636
}
641
}
637
642
638
static void
643
static void
639
client_subsystem_reply(int type, u_int32_t seq, void *ctxt)
644
client_handle_reply(int type, u_int32_t seq, void *ctxt, void *ex_ctx)
640
{
645
{
641
	int id;
646
	int id;
642
	Channel *c;
647
	Channel *c;
648
	struct channel_reply_ctx *cr = (struct channel_reply_ctx *)ex_ctx;
643
649
644
	id = packet_get_int();
650
	id = packet_get_int();
645
	packet_check_eom();
651
	packet_check_eom();
Lines 649-660 client_subsystem_reply(int type, u_int32 Link Here
649
		return;
655
		return;
650
	}
656
	}
651
657
652
	if (type == SSH2_MSG_CHANNEL_SUCCESS)
658
	if (type == SSH2_MSG_CHANNEL_SUCCESS) {
653
		debug2("Request suceeded on channel %d", id);
659
		debug2("%s request accepted on channel %d",
654
	else if (type == SSH2_MSG_CHANNEL_FAILURE) {
660
		    cr->request_type, id);
655
		error("Request failed on channel %d", id);
661
	} else if (type == SSH2_MSG_CHANNEL_FAILURE) {
656
		channel_free(c);
662
		error("%s request failed on channel %d",
663
		    cr->request_type, id);
664
		/* XXX return a nice error message to mux clients */
665
		if (cr->do_close) {
666
			chan_read_failed(c);
667
			chan_write_failed(c);
668
		}
657
	}
669
	}
670
	xfree(cr);
671
}
672
673
static void
674
client_expect_channel_reply(const char *request, int do_close)
675
{
676
	struct channel_reply_ctx *cr = xmalloc(sizeof(*cr));
677
678
	cr->request_type = request;
679
	cr->do_close = do_close;
680
	dispatch_expect_range(SSH2_MSG_CHANNEL_SUCCESS,
681
	    SSH2_MSG_CHANNEL_FAILURE, client_handle_reply, (void *)cr);
658
}
682
}
659
683
660
static void
684
static void
Lines 690-696 client_extra_session2_setup(int id, void Link Here
690
714
691
	client_session2_setup(id, cctx->want_tty, cctx->want_subsys,
715
	client_session2_setup(id, cctx->want_tty, cctx->want_subsys,
692
	    cctx->term, &cctx->tio, c->rfd, &cctx->cmd, cctx->env,
716
	    cctx->term, &cctx->tio, c->rfd, &cctx->cmd, cctx->env,
693
	    client_subsystem_reply);
717
	    client_handle_reply);
694
718
695
	c->confirm_ctx = NULL;
719
	c->confirm_ctx = NULL;
696
	buffer_free(&cctx->cmd);
720
	buffer_free(&cctx->cmd);
Lines 1947-1953 client_input_global_request(int type, u_ Link Here
1947
void
1971
void
1948
client_session2_setup(int id, int want_tty, int want_subsystem,
1972
client_session2_setup(int id, int want_tty, int want_subsystem,
1949
    const char *term, struct termios *tiop, int in_fd, Buffer *cmd, char **env,
1973
    const char *term, struct termios *tiop, int in_fd, Buffer *cmd, char **env,
1950
    dispatch_fn *subsys_repl)
1974
    dispatch_ex_fn *subsys_repl)
1951
{
1975
{
1952
	int len;
1976
	int len;
1953
	Channel *c = NULL;
1977
	Channel *c = NULL;
Lines 1965-1971 client_session2_setup(int id, int want_t Link Here
1965
		if (ioctl(in_fd, TIOCGWINSZ, &ws) < 0)
1989
		if (ioctl(in_fd, TIOCGWINSZ, &ws) < 0)
1966
			memset(&ws, 0, sizeof(ws));
1990
			memset(&ws, 0, sizeof(ws));
1967
1991
1968
		channel_request_start(id, "pty-req", 0);
1992
		channel_request_start(id, "pty-req", 1);
1993
		client_expect_channel_reply("PTY allocation", 0);
1969
		packet_put_cstring(term != NULL ? term : "");
1994
		packet_put_cstring(term != NULL ? term : "");
1970
		packet_put_int((u_int)ws.ws_col);
1995
		packet_put_int((u_int)ws.ws_col);
1971
		packet_put_int((u_int)ws.ws_row);
1996
		packet_put_int((u_int)ws.ws_row);
Lines 2021-2041 client_session2_setup(int id, int want_t Link Here
2021
			len = 900;
2046
			len = 900;
2022
		if (want_subsystem) {
2047
		if (want_subsystem) {
2023
			debug("Sending subsystem: %.*s", len, (u_char*)buffer_ptr(cmd));
2048
			debug("Sending subsystem: %.*s", len, (u_char*)buffer_ptr(cmd));
2024
			channel_request_start(id, "subsystem", subsys_repl != NULL);
2049
			channel_request_start(id, "subsystem",
2025
			if (subsys_repl != NULL) {
2050
			    subsys_repl != NULL);
2026
				/* register callback for reply */
2051
			if (subsys_repl != NULL)
2027
				/* XXX we assume that client_loop has already been called */
2052
				client_expect_channel_reply("subsystem", 1);
2028
				dispatch_set(SSH2_MSG_CHANNEL_FAILURE, subsys_repl);
2029
				dispatch_set(SSH2_MSG_CHANNEL_SUCCESS, subsys_repl);
2030
			}
2031
		} else {
2053
		} else {
2032
			debug("Sending command: %.*s", len, (u_char*)buffer_ptr(cmd));
2054
			debug("Sending command: %.*s", len, (u_char*)buffer_ptr(cmd));
2033
			channel_request_start(id, "exec", 0);
2055
			channel_request_start(id, "exec", 1);
2056
			client_expect_channel_reply("exec", 1);
2034
		}
2057
		}
2035
		packet_put_string(buffer_ptr(cmd), buffer_len(cmd));
2058
		packet_put_string(buffer_ptr(cmd), buffer_len(cmd));
2036
		packet_send();
2059
		packet_send();
2037
	} else {
2060
	} else {
2038
		channel_request_start(id, "shell", 0);
2061
		channel_request_start(id, "shell", 1);
2062
		client_expect_channel_reply("shell", 1);
2039
		packet_send();
2063
		packet_send();
2040
	}
2064
	}
2041
}
2065
}
(-)clientloop.h (-1 / +1 lines)
Lines 43-49 void client_x11_get_proto(const char *, Link Here
43
	    char **, char **);
43
	    char **, char **);
44
void	 client_global_request_reply_fwd(int, u_int32_t, void *);
44
void	 client_global_request_reply_fwd(int, u_int32_t, void *);
45
void	 client_session2_setup(int, int, int, const char *, struct termios *,
45
void	 client_session2_setup(int, int, int, const char *, struct termios *,
46
	    int, Buffer *, char **, dispatch_fn *);
46
	    int, Buffer *, char **, dispatch_ex_fn *);
47
int	 client_request_tun_fwd(int, int, int);
47
int	 client_request_tun_fwd(int, int, int);
48
48
49
/* Multiplexing protocol version */
49
/* Multiplexing protocol version */
(-)dispatch.c (-1 / +50 lines)
Lines 24-45 Link Here
24
 */
24
 */
25
25
26
#include <sys/types.h>
26
#include <sys/types.h>
27
#include <sys/queue.h>
27
28
28
#include <signal.h>
29
#include <signal.h>
29
#include <stdarg.h>
30
#include <stdarg.h>
31
#include <stdlib.h>
32
#include <string.h>
30
33
31
#include "ssh1.h"
34
#include "ssh1.h"
32
#include "ssh2.h"
35
#include "ssh2.h"
33
#include "log.h"
36
#include "log.h"
34
#include "dispatch.h"
37
#include "dispatch.h"
35
#include "packet.h"
38
#include "packet.h"
39
#include "xmalloc.h"
36
#include "compat.h"
40
#include "compat.h"
37
41
38
#define DISPATCH_MIN	0
42
#define DISPATCH_MIN	0
39
#define DISPATCH_MAX	255
43
#define DISPATCH_MAX	255
40
44
45
struct dispatch_expectation {
46
	int id_low, id_high;
47
	dispatch_ex_fn *cb;
48
	void *ex_ctx;
49
	TAILQ_ENTRY(dispatch_expectation) entry;
50
};
51
TAILQ_HEAD(dispatch_expectations, dispatch_expectation);
52
41
dispatch_fn *dispatch[DISPATCH_MAX];
53
dispatch_fn *dispatch[DISPATCH_MAX];
54
struct dispatch_expectations expected = TAILQ_HEAD_INITIALIZER(expected);
42
55
56
/* ARGSUSED */
43
void
57
void
44
dispatch_protocol_error(int type, u_int32_t seq, void *ctxt)
58
dispatch_protocol_error(int type, u_int32_t seq, void *ctxt)
45
{
59
{
Lines 51-56 dispatch_protocol_error(int type, u_int3 Link Here
51
	packet_send();
65
	packet_send();
52
	packet_write_wait();
66
	packet_write_wait();
53
}
67
}
68
69
/* ARGSUSED */
54
void
70
void
55
dispatch_protocol_ignore(int type, u_int32_t seq, void *ctxt)
71
dispatch_protocol_ignore(int type, u_int32_t seq, void *ctxt)
56
{
72
{
Lines 79-87 dispatch_set(int type, dispatch_fn *fn) Link Here
79
{
95
{
80
	dispatch[type] = fn;
96
	dispatch[type] = fn;
81
}
97
}
98
99
void
100
dispatch_expect_range(int id_low, int id_high, dispatch_ex_fn *cb, void *ex_ctx)
101
{
102
	struct dispatch_expectation *de;
103
104
	if (id_low > id_high)
105
		fatal("%s: id_low > id_high", __func__);
106
	de = xmalloc(sizeof(*de));
107
	de->id_low = id_low;
108
	de->id_high = id_high;
109
	de->cb = cb;
110
	de->ex_ctx = cb != NULL ? ex_ctx : NULL;
111
	TAILQ_INSERT_TAIL(&expected, de, entry);
112
}
113
114
void
115
dispatch_expect(int id, dispatch_ex_fn *cb, void *ex_ctx)
116
{
117
	dispatch_expect_range(id, id, cb, ex_ctx);
118
}
119
82
void
120
void
83
dispatch_run(int mode, volatile sig_atomic_t *done, void *ctxt)
121
dispatch_run(int mode, volatile sig_atomic_t *done, void *ctxt)
84
{
122
{
123
	struct dispatch_expectation *de;
124
85
	for (;;) {
125
	for (;;) {
86
		int type;
126
		int type;
87
		u_int32_t seqnr;
127
		u_int32_t seqnr;
Lines 93-99 dispatch_run(int mode, volatile sig_atom Link Here
93
			if (type == SSH_MSG_NONE)
133
			if (type == SSH_MSG_NONE)
94
				return;
134
				return;
95
		}
135
		}
96
		if (type > 0 && type < DISPATCH_MAX && dispatch[type] != NULL)
136
		/* Run any specific expected packets first */
137
		de = TAILQ_FIRST(&expected);
138
		if (de != NULL && de->id_low <= type && de->id_high >= type) {
139
			if (de->cb != NULL)
140
				de->cb(type, seqnr, ctxt, de->ex_ctx);
141
			TAILQ_REMOVE(&expected, de, entry);
142
			bzero(de, sizeof(*de));
143
			free(de);
144
		} else if (type > 0 && type < DISPATCH_MAX &&
145
		    dispatch[type] != NULL)
97
			(*dispatch[type])(type, seqnr, ctxt);
146
			(*dispatch[type])(type, seqnr, ctxt);
98
		else
147
		else
99
			packet_disconnect("protocol error: rcvd type %d", type);
148
			packet_disconnect("protocol error: rcvd type %d", type);
(-)dispatch.h (+3 lines)
Lines 29-38 enum { Link Here
29
};
29
};
30
30
31
typedef void dispatch_fn(int, u_int32_t, void *);
31
typedef void dispatch_fn(int, u_int32_t, void *);
32
typedef void dispatch_ex_fn(int, u_int32_t, void *, void *);
32
33
33
void	 dispatch_init(dispatch_fn *);
34
void	 dispatch_init(dispatch_fn *);
34
void	 dispatch_set(int, dispatch_fn *);
35
void	 dispatch_set(int, dispatch_fn *);
35
void	 dispatch_range(u_int, u_int, dispatch_fn *);
36
void	 dispatch_range(u_int, u_int, dispatch_fn *);
37
void	 dispatch_expect_range(int, int, dispatch_ex_fn *, void *);
38
void	 dispatch_expect(int, dispatch_ex_fn *, void *);
36
void	 dispatch_run(int, volatile sig_atomic_t *, void *);
39
void	 dispatch_run(int, volatile sig_atomic_t *, void *);
37
void	 dispatch_protocol_error(int, u_int32_t, void *);
40
void	 dispatch_protocol_error(int, u_int32_t, void *);
38
void	 dispatch_protocol_ignore(int, u_int32_t, void *);
41
void	 dispatch_protocol_ignore(int, u_int32_t, void *);
(-)monitor.c (-1 / +1 lines)
Lines 999-1005 mm_session_close(Session *s) Link Here
999
		debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ptyfd);
999
		debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ptyfd);
1000
		session_pty_cleanup2(s);
1000
		session_pty_cleanup2(s);
1001
	}
1001
	}
1002
	s->used = 0;
1002
	session_unused(s->self);
1003
}
1003
}
1004
1004
1005
int
1005
int
(-)monitor_wrap.c (-3 / +15 lines)
Lines 653-659 mm_pty_allocate(int *ptyfd, int *ttyfd, Link Here
653
{
653
{
654
	Buffer m;
654
	Buffer m;
655
	char *p, *msg;
655
	char *p, *msg;
656
	int success = 0;
656
	int success = 0, tmp1 = -1, tmp2 = -1;
657
658
	/* Kludge: ensure there are fds free to receive the pty/tty */
659
	if ((tmp1 = dup(pmonitor->m_recvfd)) == -1 ||
660
	    (tmp2 = dup(pmonitor->m_recvfd)) == -1) {
661
		error("%s: cannot allocate fds for pty", __func__);
662
		close(tmp1);
663
		close(tmp2);
664
		return 0;
665
	}
666
	close(tmp1);
667
	close(tmp2);
657
668
658
	buffer_init(&m);
669
	buffer_init(&m);
659
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTY, &m);
670
	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTY, &m);
Lines 698-705 mm_session_pty_cleanup2(Session *s) Link Here
698
	buffer_free(&m);
709
	buffer_free(&m);
699
710
700
	/* closed dup'ed master */
711
	/* closed dup'ed master */
701
	if (close(s->ptymaster) < 0)
712
	if (s->ptymaster != -1 && close(s->ptymaster) < 0)
702
		error("close(s->ptymaster): %s", strerror(errno));
713
		error("close(s->ptymaster/%d): %s",
714
		    s->ptymaster, strerror(errno));
703
715
704
	/* unlink pty from session */
716
	/* unlink pty from session */
705
	s->ttyfd = -1;
717
	s->ttyfd = -1;
(-)servconf.c (-5 / +14 lines)
Lines 105-110 initialize_server_options(ServerOptions Link Here
105
	options->max_startups_rate = -1;
105
	options->max_startups_rate = -1;
106
	options->max_startups = -1;
106
	options->max_startups = -1;
107
	options->max_authtries = -1;
107
	options->max_authtries = -1;
108
	options->max_sessions = -1;
108
	options->banner = NULL;
109
	options->banner = NULL;
109
	options->use_dns = -1;
110
	options->use_dns = -1;
110
	options->client_alive_interval = -1;
111
	options->client_alive_interval = -1;
Lines 221-226 fill_default_server_options(ServerOption Link Here
221
		options->max_startups_begin = options->max_startups;
222
		options->max_startups_begin = options->max_startups;
222
	if (options->max_authtries == -1)
223
	if (options->max_authtries == -1)
223
		options->max_authtries = DEFAULT_AUTH_FAIL_MAX;
224
		options->max_authtries = DEFAULT_AUTH_FAIL_MAX;
225
	if (options->max_sessions == -1)
226
		options->max_sessions = DEFAULT_SESSIONS_MAX;
224
	if (options->use_dns == -1)
227
	if (options->use_dns == -1)
225
		options->use_dns = 1;
228
		options->use_dns = 1;
226
	if (options->client_alive_interval == -1)
229
	if (options->client_alive_interval == -1)
Lines 262-268 typedef enum { Link Here
262
	sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
265
	sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
263
	sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
266
	sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
264
	sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem,
267
	sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem,
265
	sMaxStartups, sMaxAuthTries,
268
	sMaxStartups, sMaxAuthTries, sMaxSessions,
266
	sBanner, sUseDNS, sHostbasedAuthentication,
269
	sBanner, sUseDNS, sHostbasedAuthentication,
267
	sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
270
	sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
268
	sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
271
	sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
Lines 353-358 static struct { Link Here
353
	{ "subsystem", sSubsystem, SSHCFG_GLOBAL },
356
	{ "subsystem", sSubsystem, SSHCFG_GLOBAL },
354
	{ "maxstartups", sMaxStartups, SSHCFG_GLOBAL },
357
	{ "maxstartups", sMaxStartups, SSHCFG_GLOBAL },
355
	{ "maxauthtries", sMaxAuthTries, SSHCFG_GLOBAL },
358
	{ "maxauthtries", sMaxAuthTries, SSHCFG_GLOBAL },
359
	{ "maxsessions", sMaxSessions, SSHCFG_ALL },
356
	{ "banner", sBanner, SSHCFG_ALL },
360
	{ "banner", sBanner, SSHCFG_ALL },
357
	{ "usedns", sUseDNS, SSHCFG_GLOBAL },
361
	{ "usedns", sUseDNS, SSHCFG_GLOBAL },
358
	{ "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL },
362
	{ "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL },
Lines 647-653 process_server_config_line(ServerOptions Link Here
647
651
648
	case sServerKeyBits:
652
	case sServerKeyBits:
649
		intptr = &options->server_key_bits;
653
		intptr = &options->server_key_bits;
650
parse_int:
654
 parse_int:
651
		arg = strdelim(&cp);
655
		arg = strdelim(&cp);
652
		if (!arg || *arg == '\0')
656
		if (!arg || *arg == '\0')
653
			fatal("%s line %d: missing integer value.",
657
			fatal("%s line %d: missing integer value.",
Lines 659-665 parse_int: Link Here
659
663
660
	case sLoginGraceTime:
664
	case sLoginGraceTime:
661
		intptr = &options->login_grace_time;
665
		intptr = &options->login_grace_time;
662
parse_time:
666
 parse_time:
663
		arg = strdelim(&cp);
667
		arg = strdelim(&cp);
664
		if (!arg || *arg == '\0')
668
		if (!arg || *arg == '\0')
665
			fatal("%s line %d: missing time value.",
669
			fatal("%s line %d: missing time value.",
Lines 728-734 parse_time: Link Here
728
			fatal("%s line %d: too many host keys specified (max %d).",
732
			fatal("%s line %d: too many host keys specified (max %d).",
729
			    filename, linenum, MAX_HOSTKEYS);
733
			    filename, linenum, MAX_HOSTKEYS);
730
		charptr = &options->host_key_files[*intptr];
734
		charptr = &options->host_key_files[*intptr];
731
parse_filename:
735
 parse_filename:
732
		arg = strdelim(&cp);
736
		arg = strdelim(&cp);
733
		if (!arg || *arg == '\0')
737
		if (!arg || *arg == '\0')
734
			fatal("%s line %d: missing file name.",
738
			fatal("%s line %d: missing file name.",
Lines 771-777 parse_filename: Link Here
771
775
772
	case sIgnoreRhosts:
776
	case sIgnoreRhosts:
773
		intptr = &options->ignore_rhosts;
777
		intptr = &options->ignore_rhosts;
774
parse_flag:
778
 parse_flag:
775
		arg = strdelim(&cp);
779
		arg = strdelim(&cp);
776
		if (!arg || *arg == '\0')
780
		if (!arg || *arg == '\0')
777
			fatal("%s line %d: missing yes/no argument.",
781
			fatal("%s line %d: missing yes/no argument.",
Lines 1103-1108 parse_flag: Link Here
1103
		intptr = &options->max_authtries;
1107
		intptr = &options->max_authtries;
1104
		goto parse_int;
1108
		goto parse_int;
1105
1109
1110
	case sMaxSessions:
1111
		intptr = &options->max_sessions;
1112
		goto parse_int;
1113
1106
	case sBanner:
1114
	case sBanner:
1107
		charptr = &options->banner;
1115
		charptr = &options->banner;
1108
		goto parse_filename;
1116
		goto parse_filename;
Lines 1329-1334 copy_set_server_options(ServerOptions *d Link Here
1329
	M_CP_INTOPT(x11_display_offset);
1337
	M_CP_INTOPT(x11_display_offset);
1330
	M_CP_INTOPT(x11_forwarding);
1338
	M_CP_INTOPT(x11_forwarding);
1331
	M_CP_INTOPT(x11_use_localhost);
1339
	M_CP_INTOPT(x11_use_localhost);
1340
	M_CP_INTOPT(max_sessions);
1332
1341
1333
	M_CP_STROPT(banner);
1342
	M_CP_STROPT(banner);
1334
	if (preauth)
1343
	if (preauth)
(-)servconf.h (+2 lines)
Lines 35-40 Link Here
35
#define	PERMIT_YES		3
35
#define	PERMIT_YES		3
36
36
37
#define DEFAULT_AUTH_FAIL_MAX	6	/* Default for MaxAuthTries */
37
#define DEFAULT_AUTH_FAIL_MAX	6	/* Default for MaxAuthTries */
38
#define DEFAULT_SESSIONS_MAX	10	/* Default for MaxSessions */
38
39
39
/* Magic name for internal sftp-server */
40
/* Magic name for internal sftp-server */
40
#define INTERNAL_SFTP_NAME	"internal-sftp"
41
#define INTERNAL_SFTP_NAME	"internal-sftp"
Lines 122-127 typedef struct { Link Here
122
	int	max_startups_rate;
123
	int	max_startups_rate;
123
	int	max_startups;
124
	int	max_startups;
124
	int	max_authtries;
125
	int	max_authtries;
126
	int	max_sessions;
125
	char   *banner;			/* SSH-2 banner message */
127
	char   *banner;			/* SSH-2 banner message */
126
	int	use_dns;
128
	int	use_dns;
127
	int	client_alive_interval;	/*
129
	int	client_alive_interval;	/*
(-)session.c (-103 / +210 lines)
Lines 93-101 void session_set_fds(Session *, int, int Link Here
93
void	session_pty_cleanup(Session *);
93
void	session_pty_cleanup(Session *);
94
void	session_proctitle(Session *);
94
void	session_proctitle(Session *);
95
int	session_setup_x11fwd(Session *);
95
int	session_setup_x11fwd(Session *);
96
void	do_exec_pty(Session *, const char *);
96
int	do_exec_pty(Session *, const char *);
97
void	do_exec_no_pty(Session *, const char *);
97
int	do_exec_no_pty(Session *, const char *);
98
void	do_exec(Session *, const char *);
98
int	do_exec(Session *, const char *);
99
void	do_login(Session *, const char *);
99
void	do_login(Session *, const char *);
100
void	do_child(Session *, const char *);
100
void	do_child(Session *, const char *);
101
void	do_motd(void);
101
void	do_motd(void);
Lines 120-127 extern Buffer loginmsg; Link Here
120
const char *original_command = NULL;
120
const char *original_command = NULL;
121
121
122
/* data */
122
/* data */
123
#define MAX_SESSIONS 10
123
static int sessions_first_unused = -1;
124
Session	sessions[MAX_SESSIONS];
124
static int sessions_nalloc = 0;
125
static Session *sessions = NULL;
125
126
126
#define SUBSYSTEM_NONE		0
127
#define SUBSYSTEM_NONE		0
127
#define SUBSYSTEM_EXT		1
128
#define SUBSYSTEM_EXT		1
Lines 153-159 static int Link Here
153
auth_input_request_forwarding(struct passwd * pw)
154
auth_input_request_forwarding(struct passwd * pw)
154
{
155
{
155
	Channel *nc;
156
	Channel *nc;
156
	int sock;
157
	int sock = -1;
157
	struct sockaddr_un sunaddr;
158
	struct sockaddr_un sunaddr;
158
159
159
	if (auth_sock_name != NULL) {
160
	if (auth_sock_name != NULL) {
Lines 165-207 auth_input_request_forwarding(struct pas Link Here
165
	temporarily_use_uid(pw);
166
	temporarily_use_uid(pw);
166
167
167
	/* Allocate a buffer for the socket name, and format the name. */
168
	/* Allocate a buffer for the socket name, and format the name. */
168
	auth_sock_name = xmalloc(MAXPATHLEN);
169
	auth_sock_dir = xstrdup("/tmp/ssh-XXXXXXXXXX");
169
	auth_sock_dir = xmalloc(MAXPATHLEN);
170
	strlcpy(auth_sock_dir, "/tmp/ssh-XXXXXXXXXX", MAXPATHLEN);
171
170
172
	/* Create private directory for socket */
171
	/* Create private directory for socket */
173
	if (mkdtemp(auth_sock_dir) == NULL) {
172
	if (mkdtemp(auth_sock_dir) == NULL) {
174
		packet_send_debug("Agent forwarding disabled: "
173
		packet_send_debug("Agent forwarding disabled: "
175
		    "mkdtemp() failed: %.100s", strerror(errno));
174
		    "mkdtemp() failed: %.100s", strerror(errno));
176
		restore_uid();
175
		restore_uid();
177
		xfree(auth_sock_name);
178
		xfree(auth_sock_dir);
176
		xfree(auth_sock_dir);
179
		auth_sock_name = NULL;
180
		auth_sock_dir = NULL;
177
		auth_sock_dir = NULL;
181
		return 0;
178
		goto authsock_err;
182
	}
179
	}
183
	snprintf(auth_sock_name, MAXPATHLEN, "%s/agent.%ld",
180
184
		 auth_sock_dir, (long) getpid());
181
	auth_sock_name = xmalloc(MAXPATHLEN);
182
	xasprintf(&auth_sock_name, "%s/agent.%ld",
183
	    auth_sock_dir, (long) getpid());
185
184
186
	/* Create the socket. */
185
	/* Create the socket. */
187
	sock = socket(AF_UNIX, SOCK_STREAM, 0);
186
	sock = socket(AF_UNIX, SOCK_STREAM, 0);
188
	if (sock < 0)
187
	if (sock < 0) {
189
		packet_disconnect("socket: %.100s", strerror(errno));
188
		error("socket: %.100s", strerror(errno));
189
		restore_uid();
190
		goto authsock_err;
191
	}
190
192
191
	/* Bind it to the name. */
193
	/* Bind it to the name. */
192
	memset(&sunaddr, 0, sizeof(sunaddr));
194
	memset(&sunaddr, 0, sizeof(sunaddr));
193
	sunaddr.sun_family = AF_UNIX;
195
	sunaddr.sun_family = AF_UNIX;
194
	strlcpy(sunaddr.sun_path, auth_sock_name, sizeof(sunaddr.sun_path));
196
	strlcpy(sunaddr.sun_path, auth_sock_name, sizeof(sunaddr.sun_path));
195
197
196
	if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0)
198
	if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) {
197
		packet_disconnect("bind: %.100s", strerror(errno));
199
		error("bind: %.100s", strerror(errno));
200
		restore_uid();
201
		goto authsock_err;
202
	}
198
203
199
	/* Restore the privileged uid. */
204
	/* Restore the privileged uid. */
200
	restore_uid();
205
	restore_uid();
201
206
202
	/* Start listening on the socket. */
207
	/* Start listening on the socket. */
203
	if (listen(sock, SSH_LISTEN_BACKLOG) < 0)
208
	if (listen(sock, SSH_LISTEN_BACKLOG) < 0) {
204
		packet_disconnect("listen: %.100s", strerror(errno));
209
		error("listen: %.100s", strerror(errno));
210
		goto authsock_err;
211
	}
205
212
206
	/* Allocate a channel for the authentication agent socket. */
213
	/* Allocate a channel for the authentication agent socket. */
207
	nc = channel_new("auth socket",
214
	nc = channel_new("auth socket",
Lines 210-215 auth_input_request_forwarding(struct pas Link Here
210
	    0, "auth socket", 1);
217
	    0, "auth socket", 1);
211
	strlcpy(nc->path, auth_sock_name, sizeof(nc->path));
218
	strlcpy(nc->path, auth_sock_name, sizeof(nc->path));
212
	return 1;
219
	return 1;
220
221
 authsock_err:
222
	if (auth_sock_name != NULL)
223
		xfree(auth_sock_name);
224
	if (auth_sock_dir != NULL) {
225
		rmdir(auth_sock_dir);
226
		xfree(auth_sock_dir);
227
	}
228
	if (sock != -1)
229
		close(sock);
230
	auth_sock_name = NULL;
231
	auth_sock_dir = NULL;
232
	return 0;
213
}
233
}
214
234
215
static void
235
static void
Lines 358-364 do_authenticated1(Authctxt *authctxt) Link Here
358
			if (type == SSH_CMSG_EXEC_CMD) {
378
			if (type == SSH_CMSG_EXEC_CMD) {
359
				command = packet_get_string(&dlen);
379
				command = packet_get_string(&dlen);
360
				debug("Exec command '%.500s'", command);
380
				debug("Exec command '%.500s'", command);
361
				do_exec(s, command);
381
				if (do_exec(s, command) != 0)
382
					cleanup_exit(255);
362
				xfree(command);
383
				xfree(command);
363
			} else {
384
			} else {
364
				do_exec(s, NULL);
385
				do_exec(s, NULL);
Lines 391-418 do_authenticated1(Authctxt *authctxt) Link Here
391
 * will call do_child from the child, and server_loop from the parent after
412
 * will call do_child from the child, and server_loop from the parent after
392
 * setting up file descriptors and such.
413
 * setting up file descriptors and such.
393
 */
414
 */
394
void
415
int
395
do_exec_no_pty(Session *s, const char *command)
416
do_exec_no_pty(Session *s, const char *command)
396
{
417
{
397
	pid_t pid;
418
	pid_t pid;
398
399
	int inout[2], err[2];
419
	int inout[2], err[2];
420
400
	/* Uses socket pairs to communicate with the program. */
421
	/* Uses socket pairs to communicate with the program. */
401
	if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) < 0 ||
422
	if (socketpair(AF_UNIX, SOCK_STREAM, 0, inout) < 0) {
402
	    socketpair(AF_UNIX, SOCK_STREAM, 0, err) < 0)
423
		error("%s: socketpair #1: %.100s", __func__, strerror(errno));
403
		packet_disconnect("Could not create socket pairs: %.100s",
424
		return -1;
404
				  strerror(errno));
425
	}
426
	if (socketpair(AF_UNIX, SOCK_STREAM, 0, err) < 0) {
427
		error("%s: socketpair #2: %.100s", __func__, strerror(errno));
428
		close(inout[0]);
429
		close(inout[1]);
430
		return -1;
431
	}
432
405
	if (s == NULL)
433
	if (s == NULL)
406
		fatal("do_exec_no_pty: no session");
434
		fatal("do_exec_no_pty: no session");
407
435
408
	session_proctitle(s);
436
	session_proctitle(s);
409
437
410
	/* Fork the child. */
438
	/* Fork the child. */
411
	if ((pid = fork()) == 0) {
439
	switch ((pid = fork())) {
440
	case -1:
441
		error("%s: fork: %.100s", __func__, strerror(errno));
442
		close(inout[0]);
443
		close(inout[1]);
444
		close(err[0]);
445
		close(err[1]);
446
		return -1;
447
	case 0:
412
		is_child = 1;
448
		is_child = 1;
413
449
414
		/* Child.  Reinitialize the log since the pid has changed. */
450
		/* Child.  Reinitialize the log since the pid has changed. */
415
		log_init(__progname, options.log_level, options.log_facility, log_stderr);
451
		log_init(__progname, options.log_level,
452
		    options.log_facility, log_stderr);
416
453
417
		/*
454
		/*
418
		 * Create a new session and process group since the 4.4BSD
455
		 * Create a new session and process group since the 4.4BSD
Lines 430-436 do_exec_no_pty(Session *s, const char *c Link Here
430
		close(err[1]);
467
		close(err[1]);
431
		if (dup2(inout[0], 0) < 0)	/* stdin */
468
		if (dup2(inout[0], 0) < 0)	/* stdin */
432
			perror("dup2 stdin");
469
			perror("dup2 stdin");
433
		if (dup2(inout[0], 1) < 0)	/* stdout.  Note: same socket as stdin. */
470
		if (dup2(inout[0], 1) < 0)	/* stdout (same as stdin) */
434
			perror("dup2 stdout");
471
			perror("dup2 stdout");
435
		if (dup2(err[0], 2) < 0)	/* stderr */
472
		if (dup2(err[0], 2) < 0)	/* stderr */
436
			perror("dup2 stderr");
473
			perror("dup2 stderr");
Lines 438-446 do_exec_no_pty(Session *s, const char *c Link Here
438
		/* Do processing for the child (exec command etc). */
475
		/* Do processing for the child (exec command etc). */
439
		do_child(s, command);
476
		do_child(s, command);
440
		/* NOTREACHED */
477
		/* NOTREACHED */
478
	default:
479
		break;
441
	}
480
	}
442
	if (pid < 0)
481
443
		packet_disconnect("fork failed: %.100s", strerror(errno));
444
	s->pid = pid;
482
	s->pid = pid;
445
	/* Set interactive/non-interactive mode. */
483
	/* Set interactive/non-interactive mode. */
446
	packet_set_interactive(s->display != NULL);
484
	packet_set_interactive(s->display != NULL);
Lines 454-464 do_exec_no_pty(Session *s, const char *c Link Here
454
	 * handle the case that fdin and fdout are the same.
492
	 * handle the case that fdin and fdout are the same.
455
	 */
493
	 */
456
	if (compat20) {
494
	if (compat20) {
457
		session_set_fds(s, inout[1], inout[1], s->is_subsystem ? -1 : err[1]);
495
		session_set_fds(s, inout[1], inout[1],
496
		    s->is_subsystem ? -1 : err[1]);
497
		if (s->is_subsystem)
498
			close(err[1]);
458
	} else {
499
	} else {
459
		server_loop(pid, inout[1], inout[1], err[1]);
500
		server_loop(pid, inout[1], inout[1], err[1]);
460
		/* server_loop has closed inout[1] and err[1]. */
501
		/* server_loop has closed inout[1] and err[1]. */
461
	}
502
	}
503
	return 0;
462
}
504
}
463
505
464
/*
506
/*
Lines 467-473 do_exec_no_pty(Session *s, const char *c Link Here
467
 * setting up file descriptors, controlling tty, updating wtmp, utmp,
509
 * setting up file descriptors, controlling tty, updating wtmp, utmp,
468
 * lastlog, and other such operations.
510
 * lastlog, and other such operations.
469
 */
511
 */
470
void
512
int
471
do_exec_pty(Session *s, const char *command)
513
do_exec_pty(Session *s, const char *command)
472
{
514
{
473
	int fdout, ptyfd, ttyfd, ptymaster;
515
	int fdout, ptyfd, ttyfd, ptymaster;
Lines 478-489 do_exec_pty(Session *s, const char *comm Link Here
478
	ptyfd = s->ptyfd;
520
	ptyfd = s->ptyfd;
479
	ttyfd = s->ttyfd;
521
	ttyfd = s->ttyfd;
480
522
523
	/*
524
	 * Create another descriptor of the pty master side for use as the
525
	 * standard input.  We could use the original descriptor, but this
526
	 * simplifies code in server_loop.  The descriptor is bidirectional.
527
	 * Do this before forking (and cleanup in the child) so as to
528
	 * detect and gracefully fail out-of-fd conditions.
529
	 */
530
	if ((fdout = dup(ptyfd)) < 0) {
531
		error("%s: dup #1: %s", __func__, strerror(errno));
532
		close(ttyfd);
533
		close(ptyfd);
534
		return -1;
535
	}
536
	/* we keep a reference to the pty master */
537
	if ((ptymaster = dup(ptyfd)) < 0) {
538
		error("%s: dup #2: %s", __func__, strerror(errno));
539
		close(ttyfd);
540
		close(ptyfd);
541
		close(fdout);
542
		return -1;
543
	}
544
481
	/* Fork the child. */
545
	/* Fork the child. */
482
	if ((pid = fork()) == 0) {
546
	switch ((pid = fork())) {
547
	case -1:
548
		error("%s: fork: %.100s", __func__, strerror(errno));
549
		close(fdout);
550
		close(ptymaster);
551
		close(ttyfd);
552
		close(ptyfd);
553
		return -1;
554
	case 0:
483
		is_child = 1;
555
		is_child = 1;
484
556
557
		close(fdout);
558
		close(ptymaster);
559
485
		/* Child.  Reinitialize the log because the pid has changed. */
560
		/* Child.  Reinitialize the log because the pid has changed. */
486
		log_init(__progname, options.log_level, options.log_facility, log_stderr);
561
		log_init(__progname, options.log_level,
562
		    options.log_facility, log_stderr);
487
		/* Close the master side of the pseudo tty. */
563
		/* Close the master side of the pseudo tty. */
488
		close(ptyfd);
564
		close(ptyfd);
489
565
Lines 505-537 do_exec_pty(Session *s, const char *comm Link Here
505
		if (!(options.use_login && command == NULL))
581
		if (!(options.use_login && command == NULL))
506
			do_login(s, command);
582
			do_login(s, command);
507
583
508
		/* Do common processing for the child, such as execing the command. */
584
		/*
585
		 * Do common processing for the child, such as execing
586
		 * the command.
587
		 */
509
		do_child(s, command);
588
		do_child(s, command);
510
		/* NOTREACHED */
589
		/* NOTREACHED */
590
	default:
591
		break;
511
	}
592
	}
512
	if (pid < 0)
513
		packet_disconnect("fork failed: %.100s", strerror(errno));
514
	s->pid = pid;
593
	s->pid = pid;
515
594
516
	/* Parent.  Close the slave side of the pseudo tty. */
595
	/* Parent.  Close the slave side of the pseudo tty. */
517
	close(ttyfd);
596
	close(ttyfd);
518
597
519
	/*
520
	 * Create another descriptor of the pty master side for use as the
521
	 * standard input.  We could use the original descriptor, but this
522
	 * simplifies code in server_loop.  The descriptor is bidirectional.
523
	 */
524
	fdout = dup(ptyfd);
525
	if (fdout < 0)
526
		packet_disconnect("dup #1 failed: %.100s", strerror(errno));
527
528
	/* we keep a reference to the pty master */
529
	ptymaster = dup(ptyfd);
530
	if (ptymaster < 0)
531
		packet_disconnect("dup #2 failed: %.100s", strerror(errno));
532
	s->ptymaster = ptymaster;
533
534
	/* Enter interactive session. */
598
	/* Enter interactive session. */
599
	s->ptymaster = ptymaster;
535
	packet_set_interactive(1);
600
	packet_set_interactive(1);
536
	if (compat20) {
601
	if (compat20) {
537
		session_set_fds(s, ptyfd, fdout, -1);
602
		session_set_fds(s, ptyfd, fdout, -1);
Lines 539-553 do_exec_pty(Session *s, const char *comm Link Here
539
		server_loop(pid, ptyfd, fdout, -1);
604
		server_loop(pid, ptyfd, fdout, -1);
540
		/* server_loop _has_ closed ptyfd and fdout. */
605
		/* server_loop _has_ closed ptyfd and fdout. */
541
	}
606
	}
607
	return 0;
542
}
608
}
543
609
544
/*
610
/*
545
 * This is called to fork and execute a command.  If another command is
611
 * This is called to fork and execute a command.  If another command is
546
 * to be forced, execute that instead.
612
 * to be forced, execute that instead.
547
 */
613
 */
548
void
614
int
549
do_exec(Session *s, const char *command)
615
do_exec(Session *s, const char *command)
550
{
616
{
617
	int ret;
618
551
	if (options.adm_forced_command) {
619
	if (options.adm_forced_command) {
552
		original_command = command;
620
		original_command = command;
553
		command = options.adm_forced_command;
621
		command = options.adm_forced_command;
Lines 574-582 do_exec(Session *s, const char *command) Link Here
574
	}
642
	}
575
#endif
643
#endif
576
	if (s->ttyfd != -1)
644
	if (s->ttyfd != -1)
577
		do_exec_pty(s, command);
645
		ret = do_exec_pty(s, command);
578
	else
646
	else
579
		do_exec_no_pty(s, command);
647
		ret = do_exec_no_pty(s, command);
580
648
581
	original_command = NULL;
649
	original_command = NULL;
582
650
Lines 586-591 do_exec(Session *s, const char *command) Link Here
586
	 * multiple copies of the login messages.
654
	 * multiple copies of the login messages.
587
	 */
655
	 */
588
	buffer_clear(&loginmsg);
656
	buffer_clear(&loginmsg);
657
658
	return ret;
589
}
659
}
590
660
591
661
Lines 1291-1333 do_child(Session *s, const char *command Link Here
1291
	exit(1);
1361
	exit(1);
1292
}
1362
}
1293
1363
1364
void
1365
session_unused(int id)
1366
{
1367
	debug3("%s: session id %d unused", __func__, id);
1368
	if (id >= options.max_sessions ||
1369
	    id >= sessions_nalloc) {
1370
		fatal("%s: insane session id %d (max %d nalloc %d)",
1371
		    __func__, id, options.max_sessions, sessions_nalloc);
1372
	}
1373
	bzero(&sessions[id], sizeof(*sessions));
1374
	sessions[id].self = id;
1375
	sessions[id].used = 0;
1376
	sessions[id].chanid = -1;
1377
	sessions[id].ptyfd = -1;
1378
	sessions[id].ttyfd = -1;
1379
	sessions[id].ptymaster = -1;
1380
	sessions[id].x11_chanids = NULL;
1381
	sessions[id].next_unused = sessions_first_unused;
1382
	sessions_first_unused = id;
1383
}
1384
1294
Session *
1385
Session *
1295
session_new(void)
1386
session_new(void)
1296
{
1387
{
1297
	int i;
1388
	Session *s, *tmp;
1298
	static int did_init = 0;
1389
1299
	if (!did_init) {
1390
	if (sessions_first_unused == -1) {
1300
		debug("session_new: init");
1391
		if (sessions_nalloc >= options.max_sessions)
1301
		for (i = 0; i < MAX_SESSIONS; i++) {
1392
			return NULL;
1302
			sessions[i].used = 0;
1393
		debug2("%s: allocate (allocated %d max %d)",
1303
		}
1394
		    __func__, sessions_nalloc, options.max_sessions);
1304
		did_init = 1;
1395
		tmp = xrealloc(sessions, sessions_nalloc + 1,
1305
	}
1396
		    sizeof(*sessions));
1306
	for (i = 0; i < MAX_SESSIONS; i++) {
1397
		if (tmp == NULL) {
1307
		Session *s = &sessions[i];
1398
			error("%s: cannot allocate %d sessions",
1308
		if (! s->used) {
1399
			    __func__, sessions_nalloc + 1);
1309
			memset(s, 0, sizeof(*s));
1400
			return NULL;
1310
			s->chanid = -1;
1401
		}
1311
			s->ptyfd = -1;
1402
		sessions = tmp;
1312
			s->ttyfd = -1;
1403
		session_unused(sessions_nalloc++);
1313
			s->used = 1;
1404
	}
1314
			s->self = i;
1405
1315
			s->x11_chanids = NULL;
1406
	if (sessions_first_unused >= sessions_nalloc ||
1316
			debug("session_new: session %d", i);
1407
	    sessions_first_unused < 0) {
1317
			return s;
1408
		fatal("%s: insane first_unused %d max %d nalloc %d",
1318
		}
1409
		    __func__, sessions_first_unused, options.max_sessions,
1319
	}
1410
		    sessions_nalloc);
1320
	return NULL;
1411
	}
1412
1413
	s = &sessions[sessions_first_unused];
1414
	if (s->used) {
1415
		fatal("%s: session %d already used",
1416
		    __func__, sessions_first_unused);
1417
	}
1418
	sessions_first_unused = s->next_unused;
1419
	s->used = 1;
1420
	s->next_unused = -1;
1421
	debug("session_new: session %d", s->self);
1422
1423
	return s;
1321
}
1424
}
1322
1425
1323
static void
1426
static void
1324
session_dump(void)
1427
session_dump(void)
1325
{
1428
{
1326
	int i;
1429
	int i;
1327
	for (i = 0; i < MAX_SESSIONS; i++) {
1430
	for (i = 0; i < sessions_nalloc; i++) {
1328
		Session *s = &sessions[i];
1431
		Session *s = &sessions[i];
1329
		debug("dump: used %d session %d %p channel %d pid %ld",
1432
1433
		debug("dump: used %d next_unused %d session %d %p "
1434
		    "channel %d pid %ld",
1330
		    s->used,
1435
		    s->used,
1436
		    s->next_unused,
1331
		    s->self,
1437
		    s->self,
1332
		    s,
1438
		    s,
1333
		    s->chanid,
1439
		    s->chanid,
Lines 1357-1363 Session * Link Here
1357
session_by_tty(char *tty)
1463
session_by_tty(char *tty)
1358
{
1464
{
1359
	int i;
1465
	int i;
1360
	for (i = 0; i < MAX_SESSIONS; i++) {
1466
	for (i = 0; i < sessions_nalloc; i++) {
1361
		Session *s = &sessions[i];
1467
		Session *s = &sessions[i];
1362
		if (s->used && s->ttyfd != -1 && strcmp(s->tty, tty) == 0) {
1468
		if (s->used && s->ttyfd != -1 && strcmp(s->tty, tty) == 0) {
1363
			debug("session_by_tty: session %d tty %s", i, tty);
1469
			debug("session_by_tty: session %d tty %s", i, tty);
Lines 1373-1382 static Session * Link Here
1373
session_by_channel(int id)
1479
session_by_channel(int id)
1374
{
1480
{
1375
	int i;
1481
	int i;
1376
	for (i = 0; i < MAX_SESSIONS; i++) {
1482
	for (i = 0; i < sessions_nalloc; i++) {
1377
		Session *s = &sessions[i];
1483
		Session *s = &sessions[i];
1378
		if (s->used && s->chanid == id) {
1484
		if (s->used && s->chanid == id) {
1379
			debug("session_by_channel: session %d channel %d", i, id);
1485
			debug("session_by_channel: session %d channel %d",
1486
			    i, id);
1380
			return s;
1487
			return s;
1381
		}
1488
		}
1382
	}
1489
	}
Lines 1390-1396 session_by_x11_channel(int id) Link Here
1390
{
1497
{
1391
	int i, j;
1498
	int i, j;
1392
1499
1393
	for (i = 0; i < MAX_SESSIONS; i++) {
1500
	for (i = 0; i < sessions_nalloc; i++) {
1394
		Session *s = &sessions[i];
1501
		Session *s = &sessions[i];
1395
1502
1396
		if (s->x11_chanids == NULL || !s->used)
1503
		if (s->x11_chanids == NULL || !s->used)
Lines 1413-1419 session_by_pid(pid_t pid) Link Here
1413
{
1520
{
1414
	int i;
1521
	int i;
1415
	debug("session_by_pid: pid %ld", (long)pid);
1522
	debug("session_by_pid: pid %ld", (long)pid);
1416
	for (i = 0; i < MAX_SESSIONS; i++) {
1523
	for (i = 0; i < sessions_nalloc; i++) {
1417
		Session *s = &sessions[i];
1524
		Session *s = &sessions[i];
1418
		if (s->used && s->pid == pid)
1525
		if (s->used && s->pid == pid)
1419
			return s;
1526
			return s;
Lines 1469-1475 session_pty_req(Session *s) Link Here
1469
1576
1470
	/* Allocate a pty and open it. */
1577
	/* Allocate a pty and open it. */
1471
	debug("Allocating pty.");
1578
	debug("Allocating pty.");
1472
	if (!PRIVSEP(pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty)))) {
1579
	if (!PRIVSEP(pty_allocate(&s->ptyfd, &s->ttyfd, s->tty,
1580
	    sizeof(s->tty)))) {
1473
		if (s->term)
1581
		if (s->term)
1474
			xfree(s->term);
1582
			xfree(s->term);
1475
		s->term = NULL;
1583
		s->term = NULL;
Lines 1522-1529 session_subsystem_req(Session *s) Link Here
1522
				s->is_subsystem = SUBSYSTEM_EXT;
1630
				s->is_subsystem = SUBSYSTEM_EXT;
1523
			}
1631
			}
1524
			debug("subsystem: exec() %s", cmd);
1632
			debug("subsystem: exec() %s", cmd);
1525
			do_exec(s, cmd);
1633
			success = do_exec(s, cmd) == 0;
1526
			success = 1;
1527
			break;
1634
			break;
1528
		}
1635
		}
1529
	}
1636
	}
Lines 1566-1584 static int Link Here
1566
session_shell_req(Session *s)
1673
session_shell_req(Session *s)
1567
{
1674
{
1568
	packet_check_eom();
1675
	packet_check_eom();
1569
	do_exec(s, NULL);
1676
	return do_exec(s, NULL) == 0;
1570
	return 1;
1571
}
1677
}
1572
1678
1573
static int
1679
static int
1574
session_exec_req(Session *s)
1680
session_exec_req(Session *s)
1575
{
1681
{
1576
	u_int len;
1682
	u_int len, success;
1683
1577
	char *command = packet_get_string(&len);
1684
	char *command = packet_get_string(&len);
1578
	packet_check_eom();
1685
	packet_check_eom();
1579
	do_exec(s, command);
1686
	success = do_exec(s, command) == 0;
1580
	xfree(command);
1687
	xfree(command);
1581
	return 1;
1688
	return success;
1582
}
1689
}
1583
1690
1584
static int
1691
static int
Lines 1588-1595 session_break_req(Session *s) Link Here
1588
	packet_get_int();	/* ignored */
1695
	packet_get_int();	/* ignored */
1589
	packet_check_eom();
1696
	packet_check_eom();
1590
1697
1591
	if (s->ttyfd == -1 ||
1698
	if (s->ttyfd == -1 || tcsendbreak(s->ttyfd, 0) < 0)
1592
	    tcsendbreak(s->ttyfd, 0) < 0)
1593
		return 0;
1699
		return 0;
1594
	return 1;
1700
	return 1;
1595
}
1701
}
Lines 1736-1743 session_pty_cleanup2(Session *s) Link Here
1736
	 * the pty cleanup, so that another process doesn't get this pty
1842
	 * the pty cleanup, so that another process doesn't get this pty
1737
	 * while we're still cleaning up.
1843
	 * while we're still cleaning up.
1738
	 */
1844
	 */
1739
	if (close(s->ptymaster) < 0)
1845
	if (s->ptymaster != -1 && close(s->ptymaster) < 0)
1740
		error("close(s->ptymaster/%d): %s", s->ptymaster, strerror(errno));
1846
		error("close(s->ptymaster/%d): %s",
1847
		    s->ptymaster, strerror(errno));
1741
1848
1742
	/* unlink pty from session */
1849
	/* unlink pty from session */
1743
	s->ttyfd = -1;
1850
	s->ttyfd = -1;
Lines 1893-1899 session_close(Session *s) Link Here
1893
		xfree(s->auth_data);
2000
		xfree(s->auth_data);
1894
	if (s->auth_proto)
2001
	if (s->auth_proto)
1895
		xfree(s->auth_proto);
2002
		xfree(s->auth_proto);
1896
	s->used = 0;
1897
	if (s->env != NULL) {
2003
	if (s->env != NULL) {
1898
		for (i = 0; i < s->num_env; i++) {
2004
		for (i = 0; i < s->num_env; i++) {
1899
			xfree(s->env[i].name);
2005
			xfree(s->env[i].name);
Lines 1902-1907 session_close(Session *s) Link Here
1902
		xfree(s->env);
2008
		xfree(s->env);
1903
	}
2009
	}
1904
	session_proctitle(s);
2010
	session_proctitle(s);
2011
	session_unused(s->self);
1905
}
2012
}
1906
2013
1907
void
2014
void
Lines 1965-1971 void Link Here
1965
session_destroy_all(void (*closefunc)(Session *))
2072
session_destroy_all(void (*closefunc)(Session *))
1966
{
2073
{
1967
	int i;
2074
	int i;
1968
	for (i = 0; i < MAX_SESSIONS; i++) {
2075
	for (i = 0; i < sessions_nalloc; i++) {
1969
		Session *s = &sessions[i];
2076
		Session *s = &sessions[i];
1970
		if (s->used) {
2077
		if (s->used) {
1971
			if (closefunc != NULL)
2078
			if (closefunc != NULL)
Lines 1982-1988 session_tty_list(void) Link Here
1982
	static char buf[1024];
2089
	static char buf[1024];
1983
	int i;
2090
	int i;
1984
	buf[0] = '\0';
2091
	buf[0] = '\0';
1985
	for (i = 0; i < MAX_SESSIONS; i++) {
2092
	for (i = 0; i < sessions_nalloc; i++) {
1986
		Session *s = &sessions[i];
2093
		Session *s = &sessions[i];
1987
		if (s->used && s->ttyfd != -1) {
2094
		if (s->used && s->ttyfd != -1) {
1988
			if (buf[0] != '\0')
2095
			if (buf[0] != '\0')
(-)session.h (+2 lines)
Lines 31-36 typedef struct Session Session; Link Here
31
struct Session {
31
struct Session {
32
	int	used;
32
	int	used;
33
	int	self;
33
	int	self;
34
	int	next_unused;
34
	struct passwd *pw;
35
	struct passwd *pw;
35
	Authctxt *authctxt;
36
	Authctxt *authctxt;
36
	pid_t	pid;
37
	pid_t	pid;
Lines 65-70 void do_authenticated(Authctxt *); Link Here
65
void	 do_cleanup(Authctxt *);
66
void	 do_cleanup(Authctxt *);
66
67
67
int	 session_open(Authctxt *, int);
68
int	 session_open(Authctxt *, int);
69
void	 session_unused(int);
68
int	 session_input_channel_req(Channel *, const char *);
70
int	 session_input_channel_req(Channel *, const char *);
69
void	 session_close_by_pid(pid_t, int);
71
void	 session_close_by_pid(pid_t, int);
70
void	 session_close_by_channel(int, void *);
72
void	 session_close_by_channel(int, void *);
(-)ssh.c (-1 / +1 lines)
Lines 1019-1025 ssh_session(void) Link Here
1019
}
1019
}
1020
1020
1021
static void
1021
static void
1022
ssh_subsystem_reply(int type, u_int32_t seq, void *ctxt)
1022
ssh_subsystem_reply(int type, u_int32_t seq, void *ctxt, void *ex_ctx)
1023
{
1023
{
1024
	int id, len;
1024
	int id, len;
1025
1025
(-)sshd_config (+1 lines)
Lines 39-44 Protocol 2 Link Here
39
#PermitRootLogin yes
39
#PermitRootLogin yes
40
#StrictModes yes
40
#StrictModes yes
41
#MaxAuthTries 6
41
#MaxAuthTries 6
42
#MaxSessions 10
42
43
43
#RSAAuthentication yes
44
#RSAAuthentication yes
44
#PubkeyAuthentication yes
45
#PubkeyAuthentication yes
(-)sshd_config.5 (+3 lines)
Lines 585-590 connection. Link Here
585
Once the number of failures reaches half this value,
585
Once the number of failures reaches half this value,
586
additional failures are logged.
586
additional failures are logged.
587
The default is 6.
587
The default is 6.
588
.It Cm MaxSessions
589
Specifies the maximum number of open sessions permitted per network connection.
590
The default is 10.
588
.It Cm MaxStartups
591
.It Cm MaxStartups
589
Specifies the maximum number of concurrent unauthenticated connections to the
592
Specifies the maximum number of concurrent unauthenticated connections to the
590
SSH daemon.
593
SSH daemon.

Return to bug 1090