summaryrefslogtreecommitdiff
path: root/usr/src/cmd/ssh/libssh/common/readconf.c
diff options
context:
space:
mode:
authorjp161948 <none@none>2007-10-26 07:29:16 -0700
committerjp161948 <none@none>2007-10-26 07:29:16 -0700
commit9b03ea0f916d36e6ec001b90683afcaee8e29a40 (patch)
treec15358939ef4c4b1318e3f463c0482391fbfb094 /usr/src/cmd/ssh/libssh/common/readconf.c
parent6f1fe22336d824f58bda6680410a6b1c2a72ea2d (diff)
downloadillumos-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.c165
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.