-/* $OpenBSD: channels.c,v 1.404 2021/01/27 09:26:53 djm Exp $ */
+/* $OpenBSD: channels.c,v 1.405 2021/02/15 20:43:15 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
static int
rdynamic_connect_finish(struct ssh *ssh, Channel *c)
{
+ struct ssh_channels *sc = ssh->chanctxt;
+ struct permission_set *pset = &sc->local_perms;
+ struct permission *perm;
struct channel_connect cctx;
+ u_int i, permit_adm = 1;
int sock;
+ if (pset->num_permitted_admin > 0) {
+ permit_adm = 0;
+ for (i = 0; i < pset->num_permitted_admin; i++) {
+ perm = &pset->permitted_admin[i];
+ if (open_match(perm, c->path, c->host_port)) {
+ permit_adm = 1;
+ break;
+ }
+ }
+ }
+ if (!permit_adm) {
+ debug_f("requested forward not permitted");
+ return -1;
+ }
+
memset(&cctx, 0, sizeof(cctx));
sock = connect_to_helper(ssh, c->path, c->host_port, SOCK_STREAM, NULL,
NULL, &cctx, NULL, NULL);
-/* $OpenBSD: readconf.c,v 1.350 2021/01/26 05:32:21 dtucker Exp $ */
+/* $OpenBSD: readconf.c,v 1.351 2021/02/15 20:43:15 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
oPasswordAuthentication,
oChallengeResponseAuthentication, oXAuthLocation,
oIdentityFile, oHostname, oPort, oRemoteForward, oLocalForward,
+ oPermitRemoteOpen,
oCertificateFile, oAddKeysToAgent, oIdentityAgent,
oUser, oEscapeChar, oProxyCommand,
oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
{ "macs", oMacs },
{ "remoteforward", oRemoteForward },
{ "localforward", oLocalForward },
+ { "permitremoteopen", oPermitRemoteOpen },
{ "user", oUser },
{ "host", oHost },
{ "match", oMatch },
{ NULL, oBadOption }
};
+static const char *lookup_opcode_name(OpCodes code);
const char *
kex_default_pk_alg(void)
const char *original_host, char *line, const char *filename,
int linenum, int *activep, int flags, int *want_final_pass, int depth)
{
- char *s, **charptr, *endofnumber, *keyword, *arg, *arg2;
+ char *s, **charptr, *endofnumber, *keyword, *arg, *arg2, *p, ch;
char **cpptr, ***cppptr, fwdarg[256];
- u_int i, *uintptr, max_entries = 0;
+ u_int i, *uintptr, uvalue, max_entries = 0;
int r, oactive, negated, opcode, *intptr, value, value2, cmdline = 0;
int remotefwd, dynamicfwd;
LogLevel *log_level_ptr;
}
break;
+ case oPermitRemoteOpen:
+ uintptr = &options->num_permitted_remote_opens;
+ cppptr = &options->permitted_remote_opens;
+ arg = strdelim(&s);
+ if (!arg || *arg == '\0')
+ fatal("%s line %d: missing %s specification",
+ filename, linenum, lookup_opcode_name(opcode));
+ uvalue = *uintptr; /* modified later */
+ if (strcmp(arg, "any") == 0 || strcmp(arg, "none") == 0) {
+ if (*activep && uvalue == 0) {
+ *uintptr = 1;
+ *cppptr = xcalloc(1, sizeof(**cppptr));
+ (*cppptr)[0] = xstrdup(arg);
+ }
+ break;
+ }
+ for (; arg != NULL && *arg != '\0'; arg = strdelim(&s)) {
+ arg2 = xstrdup(arg);
+ ch = '\0';
+ p = hpdelim2(&arg, &ch);
+ if (p == NULL || ch == '/') {
+ fatal("%s line %d: missing host in %s",
+ filename, linenum,
+ lookup_opcode_name(opcode));
+ }
+ p = cleanhostname(p);
+ /*
+ * don't want to use permitopen_port to avoid
+ * dependency on channels.[ch] here.
+ */
+ if (arg == NULL ||
+ (strcmp(arg, "*") != 0 && a2port(arg) <= 0)) {
+ fatal("%s line %d: bad port number in %s",
+ filename, linenum,
+ lookup_opcode_name(opcode));
+ }
+ if (*activep && uvalue == 0) {
+ opt_array_append(filename, linenum,
+ lookup_opcode_name(opcode),
+ cppptr, uintptr, arg2);
+ }
+ free(arg2);
+ }
+ break;
+
case oClearAllForwardings:
intptr = &options->clear_forwardings;
goto parse_flag;
options->num_local_forwards = 0;
options->remote_forwards = NULL;
options->num_remote_forwards = 0;
+ options->permitted_remote_opens = NULL;
+ options->num_permitted_remote_opens = 0;
options->log_facility = SYSLOG_FACILITY_NOT_SET;
options->log_level = SYSLOG_LEVEL_NOT_SET;
options->num_log_verbose = 0;
/* Special cases */
+ /* PermitRemoteOpen */
+ if (o->num_permitted_remote_opens == 0)
+ printf("%s any\n", lookup_opcode_name(oPermitRemoteOpen));
+ else
+ dump_cfg_strarray_oneline(oPermitRemoteOpen,
+ o->num_permitted_remote_opens, o->permitted_remote_opens);
+
/* AddKeysToAgent */
if (o->add_keys_to_agent_lifespan <= 0)
dump_cfg_fmtint(oAddKeysToAgent, o->add_keys_to_agent);
-/* $OpenBSD: readconf.h,v 1.139 2021/01/26 05:32:21 dtucker Exp $ */
+/* $OpenBSD: readconf.h,v 1.140 2021/02/15 20:43:15 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
struct Forward *remote_forwards;
int clear_forwardings;
+ /* Restrict remote dynamic forwarding */
+ char **permitted_remote_opens;
+ u_int num_permitted_remote_opens;
+
/* stdio forwarding (-W) host and port */
char *stdio_forward_host;
int stdio_forward_port;
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.\" $OpenBSD: ssh.1,v 1.418 2021/01/26 15:40:17 naddy Exp $
-.Dd $Mdocdate: January 26 2021 $
+.\" $OpenBSD: ssh.1,v 1.419 2021/02/15 20:43:15 markus Exp $
+.Dd $Mdocdate: February 15 2021 $
.Dt SSH 1
.Os
.Sh NAME
.It NumberOfPasswordPrompts
.It PasswordAuthentication
.It PermitLocalCommand
+.It PermitRemoteOpen
.It PKCS11Provider
.It Port
.It PreferredAuthentications
-/* $OpenBSD: ssh.c,v 1.550 2021/02/02 22:36:59 djm Exp $ */
+/* $OpenBSD: ssh.c,v 1.551 2021/02/15 20:43:15 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
channel_register_open_confirm(ssh, c->self, ssh_stdio_confirm, NULL);
}
+static void
+ssh_init_forward_permissions(struct ssh *ssh, const char *what, char **opens,
+ u_int num_opens)
+{
+ u_int i;
+ int port;
+ char *addr, *arg, *oarg, ch;
+ int where = FORWARD_LOCAL;
+
+ channel_clear_permission(ssh, FORWARD_ADM, where);
+ if (num_opens == 0)
+ return; /* permit any */
+
+ /* handle keywords: "any" / "none" */
+ if (num_opens == 1 && strcmp(opens[0], "any") == 0)
+ return;
+ if (num_opens == 1 && strcmp(opens[0], "none") == 0) {
+ channel_disable_admin(ssh, where);
+ return;
+ }
+ /* Otherwise treat it as a list of permitted host:port */
+ for (i = 0; i < num_opens; i++) {
+ oarg = arg = xstrdup(opens[i]);
+ ch = '\0';
+ addr = hpdelim2(&arg, &ch);
+ if (addr == NULL || ch == '/')
+ fatal_f("missing host in %s", what);
+ addr = cleanhostname(addr);
+ if (arg == NULL || ((port = permitopen_port(arg)) < 0))
+ fatal_f("bad port number in %s", what);
+ /* Send it to channels layer */
+ channel_add_permission(ssh, FORWARD_ADM,
+ where, addr, port);
+ free(oarg);
+ }
+}
+
static void
ssh_init_forwarding(struct ssh *ssh, char **ifname)
{
int success = 0;
int i;
+ ssh_init_forward_permissions(ssh, "permitremoteopen",
+ options.permitted_remote_opens,
+ options.num_permitted_remote_opens);
+
if (options.exit_on_forward_failure)
forward_confirms_pending = 0; /* track pending requests */
/* Initiate local TCP/IP port forwardings. */
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.\" $OpenBSD: ssh_config.5,v 1.346 2021/02/15 11:09:22 dlg Exp $
+.\" $OpenBSD: ssh_config.5,v 1.347 2021/02/15 20:43:15 markus Exp $
.Dd $Mdocdate: February 15 2021 $
.Dt SSH_CONFIG 5
.Os
or
.Cm no
(the default).
+.It Cm PermitRemoteOpen
+Specifies the destinations to which remote TCP port forwarding is permitted when
+.Cm RemoteForward
+is used as a SOCKS proxy.
+The forwarding specification must be one of the following forms:
+.Pp
+.Bl -item -offset indent -compact
+.It
+.Cm PermitRemoteOpen
+.Sm off
+.Ar host : port
+.Sm on
+.It
+.Cm PermitRemoteOpen
+.Sm off
+.Ar IPv4_addr : port
+.Sm on
+.It
+.Cm PermitRemoteOpen
+.Sm off
+.Ar \&[ IPv6_addr \&] : port
+.Sm on
+.El
+.Pp
+Multiple forwards may be specified by separating them with whitespace.
+An argument of
+.Cm any
+can be used to remove all restrictions and permit any forwarding requests.
+An argument of
+.Cm none
+can be used to prohibit all forwarding requests.
+The wildcard
+.Sq *
+can be used for host or port to allow all hosts or ports respectively.
+Otherwise, no pattern matching or address lookups are performed on supplied
+names.
.It Cm PKCS11Provider
Specifies which PKCS#11 provider to use or
.Cm none
or a Unix domain socket path,
otherwise if no destination argument is specified then the remote forwarding
will be established as a SOCKS proxy.
+When acting as a SOCKS proxy the destination of the connection can be
+restricted by
+.Cm PermitRemoteOpen .
.Pp
IPv6 addresses can be specified by enclosing addresses in square brackets.
Multiple forwardings may be specified, and additional