diff options
author | markus@openbsd.org <markus@openbsd.org> | 2021-02-15 20:43:15 +0000 |
---|---|---|
committer | Darren Tucker <dtucker@dtucker.net> | 2021-02-17 15:03:41 +1100 |
commit | da0a9afcc446a30ca49dd216612c41ac3cb1f2d4 (patch) | |
tree | 59583623e3eacb7a9f7b511f2ed2e4da70f9e187 | |
parent | b696858a7f9db72a83d02cb6edaca4b30a91b386 (diff) | |
download | openssh-git-da0a9afcc446a30ca49dd216612c41ac3cb1f2d4.tar.gz |
upstream: ssh: add PermitRemoteOpen for remote dynamic forwarding
with SOCKS ok djm@, dtucker@
OpenBSD-Commit-ID: 64fe7b6360acc4ea56aa61b66498b5ecc0a96a7c
-rw-r--r-- | channels.c | 21 | ||||
-rw-r--r-- | readconf.c | 63 | ||||
-rw-r--r-- | readconf.h | 6 | ||||
-rw-r--r-- | ssh.1 | 5 | ||||
-rw-r--r-- | ssh.c | 43 | ||||
-rw-r--r-- | ssh_config.5 | 41 |
6 files changed, 170 insertions, 9 deletions
@@ -1,4 +1,4 @@ -/* $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 @@ -4478,9 +4478,28 @@ rdynamic_connect_prepare(struct ssh *ssh, char *ctype, char *rname) 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); @@ -1,4 +1,4 @@ -/* $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 @@ -147,6 +147,7 @@ typedef enum { oPasswordAuthentication, oChallengeResponseAuthentication, oXAuthLocation, oIdentityFile, oHostname, oPort, oRemoteForward, oLocalForward, + oPermitRemoteOpen, oCertificateFile, oAddKeysToAgent, oIdentityAgent, oUser, oEscapeChar, oProxyCommand, oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts, @@ -247,6 +248,7 @@ static struct { { "macs", oMacs }, { "remoteforward", oRemoteForward }, { "localforward", oLocalForward }, + { "permitremoteopen", oPermitRemoteOpen }, { "user", oUser }, { "host", oHost }, { "match", oMatch }, @@ -318,6 +320,7 @@ static struct { { NULL, oBadOption } }; +static const char *lookup_opcode_name(OpCodes code); const char * kex_default_pk_alg(void) @@ -912,9 +915,9 @@ process_config_line_depth(Options *options, struct passwd *pw, const char *host, 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; @@ -1482,6 +1485,51 @@ parse_pubkey_algos: } 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; @@ -2173,6 +2221,8 @@ initialize_options(Options * options) 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; @@ -3126,6 +3176,13 @@ dump_client_config(Options *o, const char *host) /* 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); @@ -1,4 +1,4 @@ -/* $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> @@ -110,6 +110,10 @@ typedef struct { 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; @@ -33,8 +33,8 @@ .\" (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 @@ -531,6 +531,7 @@ For full details of the options listed below, and their possible values, see .It NumberOfPasswordPrompts .It PasswordAuthentication .It PermitLocalCommand +.It PermitRemoteOpen .It PKCS11Provider .It Port .It PreferredAuthentications @@ -1,4 +1,4 @@ -/* $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 @@ -1875,11 +1875,52 @@ ssh_init_stdio_forwarding(struct ssh *ssh) } 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. */ diff --git a/ssh_config.5 b/ssh_config.5 index fb3a3a41..8764e87b 100644 --- a/ssh_config.5 +++ b/ssh_config.5 @@ -33,7 +33,7 @@ .\" (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 @@ -1290,6 +1290,42 @@ The argument must be 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 @@ -1484,6 +1520,9 @@ If forwarding to a specific destination then the second argument must be 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 |