diff options
author | jp161948 <none@none> | 2007-10-26 07:29:16 -0700 |
---|---|---|
committer | jp161948 <none@none> | 2007-10-26 07:29:16 -0700 |
commit | 9b03ea0f916d36e6ec001b90683afcaee8e29a40 (patch) | |
tree | c15358939ef4c4b1318e3f463c0482391fbfb094 /usr/src/cmd/ssh/libssh/common/readconf.c | |
parent | 6f1fe22336d824f58bda6680410a6b1c2a72ea2d (diff) | |
download | illumos-gate-9b03ea0f916d36e6ec001b90683afcaee8e29a40.tar.gz |
PSARC/2007/610 ssh(1) binding address for port forwarding
6506674 allow specific binding address to be used with -LRD options for ssh(1)
6619347 SunSSH is not fully compatible with RFC4254 with regard to port forwarding
Diffstat (limited to 'usr/src/cmd/ssh/libssh/common/readconf.c')
-rw-r--r-- | usr/src/cmd/ssh/libssh/common/readconf.c | 165 |
1 files changed, 126 insertions, 39 deletions
diff --git a/usr/src/cmd/ssh/libssh/common/readconf.c b/usr/src/cmd/ssh/libssh/common/readconf.c index e0d1ac2e71..86caa54913 100644 --- a/usr/src/cmd/ssh/libssh/common/readconf.c +++ b/usr/src/cmd/ssh/libssh/common/readconf.c @@ -230,21 +230,23 @@ static struct { */ void -add_local_forward(Options *options, u_short port, const char *host, - u_short host_port) +add_local_forward(Options *options, const Forward *newfwd) { Forward *fwd; #ifndef NO_IPPORT_RESERVED_CONCEPT extern uid_t original_real_uid; - if (port < IPPORT_RESERVED && original_real_uid != 0) + if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0) fatal("Privileged ports can only be forwarded by root."); #endif if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION) fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION); fwd = &options->local_forwards[options->num_local_forwards++]; - fwd->port = port; - fwd->host = xstrdup(host); - fwd->host_port = host_port; + + fwd->listen_host = (newfwd->listen_host == NULL) ? + NULL : xstrdup(newfwd->listen_host); + fwd->listen_port = newfwd->listen_port; + fwd->connect_host = xstrdup(newfwd->connect_host); + fwd->connect_port = newfwd->connect_port; } /* @@ -253,17 +255,19 @@ add_local_forward(Options *options, u_short port, const char *host, */ void -add_remote_forward(Options *options, u_short port, const char *host, - u_short host_port) +add_remote_forward(Options *options, const Forward *newfwd) { Forward *fwd; if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION) fatal("Too many remote forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION); fwd = &options->remote_forwards[options->num_remote_forwards++]; - fwd->port = port; - fwd->host = xstrdup(host); - fwd->host_port = host_port; + + fwd->listen_host = (newfwd->listen_host == NULL) ? + NULL : xstrdup(newfwd->listen_host); + fwd->listen_port = newfwd->listen_port; + fwd->connect_host = xstrdup(newfwd->connect_host); + fwd->connect_port = newfwd->connect_port; } static void @@ -271,11 +275,17 @@ clear_forwardings(Options *options) { int i; - for (i = 0; i < options->num_local_forwards; i++) - xfree(options->local_forwards[i].host); + for (i = 0; i < options->num_local_forwards; i++) { + if (options->local_forwards[i].listen_host != NULL) + xfree(options->local_forwards[i].listen_host); + xfree(options->local_forwards[i].connect_host); + } options->num_local_forwards = 0; - for (i = 0; i < options->num_remote_forwards; i++) - xfree(options->remote_forwards[i].host); + for (i = 0; i < options->num_remote_forwards; i++) { + if (options->remote_forwards[i].listen_host != NULL) + xfree(options->remote_forwards[i].listen_host); + xfree(options->remote_forwards[i].connect_host); + } options->num_remote_forwards = 0; } @@ -307,11 +317,10 @@ process_config_line(Options *options, const char *host, char *line, const char *filename, int linenum, int *activep) { - char buf[256], *s, *string, **charptr, *endofnumber, *keyword, *arg; + char *s, *string, **charptr, *endofnumber, *keyword, *arg, *arg2, fwdarg[256]; int opcode, *intptr, value, i; - u_short fwd_port, fwd_host_port; - char sfwd_host_port[6]; StoredOption *so; + Forward fwd; s = line; /* Get the keyword. (Each line is supposed to begin with a keyword). */ @@ -694,30 +703,26 @@ parse_int: case oLocalForward: case oRemoteForward: arg = strdelim(&s); - if (!arg || *arg == '\0') + if (arg == NULL || *arg == '\0') fatal("%.200s line %d: Missing port argument.", filename, linenum); - if ((fwd_port = a2port(arg)) == 0) - fatal("%.200s line %d: Bad listen port.", - filename, linenum); - arg = strdelim(&s); - if (!arg || *arg == '\0') - fatal("%.200s line %d: Missing second argument.", + arg2 = strdelim(&s); + if (arg2 == NULL || *arg2 == '\0') + fatal("%.200s line %d: Missing target argument.", filename, linenum); - if (sscanf(arg, "%255[^:]:%5[0-9]", buf, sfwd_host_port) != 2 && - sscanf(arg, "%255[^/]/%5[0-9]", buf, sfwd_host_port) != 2) + + /* construct a string for parse_forward */ + snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2); + + if (parse_forward(1, &fwd, fwdarg) == 0) fatal("%.200s line %d: Bad forwarding specification.", filename, linenum); - if ((fwd_host_port = a2port(sfwd_host_port)) == 0) - fatal("%.200s line %d: Bad forwarding port.", - filename, linenum); + if (*activep) { if (opcode == oLocalForward) - add_local_forward(options, fwd_port, buf, - fwd_host_port); + add_local_forward(options, &fwd); else if (opcode == oRemoteForward) - add_remote_forward(options, fwd_port, buf, - fwd_host_port); + add_remote_forward(options, &fwd); } break; @@ -726,12 +731,16 @@ parse_int: if (!arg || *arg == '\0') fatal("%.200s line %d: Missing port argument.", filename, linenum); - fwd_port = a2port(arg); - if (fwd_port == 0) - fatal("%.200s line %d: Badly formatted port number.", + + if (parse_forward(0, &fwd, arg) == 0) { + fatal("%.200s line %d: Bad dynamic forwarding specification.", filename, linenum); - if (*activep) - add_local_forward(options, fwd_port, "socks4", 0); + } + + if (*activep) { + fwd.connect_host = "socks"; + add_local_forward(options, &fwd); + } break; case oClearAllForwardings: @@ -1091,6 +1100,84 @@ fill_default_options(Options * options) } /* + * Parses a string containing a port forwarding specification of one of the + * two forms, short or long: + * + * [listenhost:]listenport + * [listenhost:]listenport:connecthost:connectport + * + * short forwarding specification is used for dynamic port forwarding and for + * port forwarding cancelation in process_cmdline(). The function returns number + * of arguments parsed or zero on any error. + */ +int +parse_forward(int long_form, Forward *fwd, const char *fwdspec) +{ + int i; + char *p, *cp, *fwdarg[5]; + + memset(fwd, '\0', sizeof(*fwd)); + + cp = p = xstrdup(fwdspec); + + /* skip leading spaces */ + while (isspace(*cp)) + cp++; + + for (i = 0; i < 5; ++i) + if ((fwdarg[i] = hpdelim(&cp)) == NULL) + break; + + if ((long_form == 0 && i > 2) || (long_form == 1 && i < 3) || (i == 5)) + goto fail_free; + + switch (i) { + case 0: + goto fail_free; + + case 1: + fwd->listen_host = NULL; + fwd->listen_port = a2port(fwdarg[0]); + break; + + case 2: + fwd->listen_host = xstrdup(cleanhostname(fwdarg[0])); + fwd->listen_port = a2port(fwdarg[1]); + break; + + case 3: + fwd->listen_host = NULL; + fwd->listen_port = a2port(fwdarg[0]); + fwd->connect_host = xstrdup(cleanhostname(fwdarg[1])); + fwd->connect_port = a2port(fwdarg[2]); + break; + + case 4: + fwd->listen_host = xstrdup(cleanhostname(fwdarg[0])); + fwd->listen_port = a2port(fwdarg[1]); + fwd->connect_host = xstrdup(cleanhostname(fwdarg[2])); + fwd->connect_port = a2port(fwdarg[3]); + break; + } + + xfree(p); + + if (fwd->listen_port == 0 || (fwd->connect_port == 0 && i > 2)) + goto fail_free; + + return (i); + + fail_free: + if (p != NULL) + xfree(p); + if (fwd->connect_host != NULL) + xfree(fwd->connect_host); + if (fwd->listen_host != NULL) + xfree(fwd->listen_host); + return (0); +} + +/* * Process previously stored unknown options. When this function is called we * already have IgnoreIfUnknown set so finally we can decide whether each * unknown option is to be ignored or not. |