Bugzilla – Attachment 2025 Details for
Bug 1513
CIDR address/masklen matching support for permitopen=
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Feature enhancement patch for permitopen - needs code review/testing/cleanup
openssh-5.8p1_permitopencidr.patch (text/plain), 16.78 KB, created by
RyanC
on 2011-03-29 08:49:02 AEDT
(
hide
)
Description:
Feature enhancement patch for permitopen - needs code review/testing/cleanup
Filename:
MIME Type:
Creator:
RyanC
Created:
2011-03-29 08:49:02 AEDT
Size:
16.78 KB
patch
obsolete
>diff -u openssh-5.8p1.orig/auth-options.c openssh-5.8p1/auth-options.c >--- openssh-5.8p1.orig/auth-options.c 2011-01-06 03:44:18.000000000 -0800 >+++ openssh-5.8p1/auth-options.c 2011-03-24 19:36:45.000000000 -0700 >@@ -280,12 +280,13 @@ > xfree(patterns); > /* Host name matches. */ > goto next_option; >- case -1: >+ case -2: > debug("%.100s, line %lu: invalid criteria", > file, linenum); > auth_debug_add("%.100s, line %lu: " > "invalid criteria", file, linenum); > /* FALLTHROUGH */ >+ case -1: > case 0: > xfree(patterns); > logit("Authentication tried for %.100s with " >@@ -303,7 +304,9 @@ > cp = "permitopen=\""; > if (strncasecmp(opts, cp, strlen(cp)) == 0) { > char *host, *p; >- int port; >+ char buf[512]; >+ int min_port; >+ int max_port; > char *patterns = xmalloc(strlen(opts) + 1); > > opts += strlen(cp); >@@ -341,16 +344,45 @@ > goto bad_option; > } > host = cleanhostname(host); >- if (p == NULL || (port = a2port(p)) <= 0) { >+ if (p == NULL) { > debug("%.100s, line %lu: Bad permitopen port " > "<%.100s>", file, linenum, p ? p : ""); > auth_debug_add("%.100s, line %lu: " > "Bad permitopen port", file, linenum); > xfree(patterns); > goto bad_option; >+ } else { >+ strncpy(buf, host, sizeof(buf) - 1); >+ /* >+ * After this hpdelim, if a cidr mask was specified, then >+ * host will contain the cidr mask and p will be the port >+ * if there wasn't a cidr mask, host will contain the port >+ * and p will be null. >+ */ >+ host = hpdelim(&p); >+ if (p == NULL && (a2portrange(host, &min_port, &max_port)) <= 0) { >+ debug("%.100s, line %lu: Bad permitopen port " >+ "<%.100s>", file, linenum, p ? p : ""); >+ auth_debug_add("%.100s, line %lu: " >+ "Bad permitopen port", file, linenum); >+ xfree(patterns); >+ goto bad_option; >+ } else if (p != NULL) { /* Both a CIDR mask and a port were specified */ >+ strncat(buf, "/", sizeof(buf) - strlen(buf) - 1); >+ if (strlen(host) + 1 > sizeof(buf) - strlen(host)) { // host contains a CIDR mask >+ debug("%.100s, line %lu: Bad permitopen port " >+ "<%.100s>", file, linenum, p ? p : ""); >+ auth_debug_add("%.100s, line %lu: " >+ "Bad permitopen port", file, linenum); >+ xfree(patterns); >+ goto bad_option; >+ } >+ strncat(buf, host, sizeof(buf) - strlen(buf) - 1); >+ a2portrange(p, &min_port, &max_port); // p has the port >+ } >+ if (options.allow_tcp_forwarding) >+ channel_add_permitted_opens(buf, min_port, max_port); > } >- if (options.allow_tcp_forwarding) >- channel_add_permitted_opens(host, port); > xfree(patterns); > goto next_option; > } >diff -u openssh-5.8p1.orig/channels.c openssh-5.8p1/channels.c >--- openssh-5.8p1.orig/channels.c 2010-11-30 17:02:35.000000000 -0800 >+++ openssh-5.8p1/channels.c 2011-03-24 19:41:56.000000000 -0700 >@@ -77,6 +77,7 @@ > #include "key.h" > #include "authfd.h" > #include "pathnames.h" >+#include "match.h" > > /* -- channel core */ > >@@ -109,7 +110,8 @@ > */ > typedef struct { > char *host_to_connect; /* Connect to 'host'. */ >- u_short port_to_connect; /* Connect to 'port'. */ >+ u_short min_port_to_connect; /* Connect to 'port' (minimum). */ >+ u_short max_port_to_connect; /* Connect to 'port' (maximum). */ > u_short listen_port; /* Remote side should listen port number. */ > } ForwardPermission; > >@@ -2906,7 +2908,8 @@ > permitted_opens = xrealloc(permitted_opens, > num_permitted_opens + 1, sizeof(*permitted_opens)); > permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host_to_connect); >- permitted_opens[num_permitted_opens].port_to_connect = port_to_connect; >+ permitted_opens[num_permitted_opens].min_port_to_connect = port_to_connect; >+ permitted_opens[num_permitted_opens].max_port_to_connect = port_to_connect; > permitted_opens[num_permitted_opens].listen_port = listen_port; > num_permitted_opens++; > } >@@ -2942,7 +2945,8 @@ > packet_send(); > > permitted_opens[i].listen_port = 0; >- permitted_opens[i].port_to_connect = 0; >+ permitted_opens[i].min_port_to_connect = 0; >+ permitted_opens[i].max_port_to_connect = 0; > xfree(permitted_opens[i].host_to_connect); > permitted_opens[i].host_to_connect = NULL; > } >@@ -3000,29 +3004,51 @@ > } > > void >-channel_add_permitted_opens(char *host, int port) >+channel_add_permitted_opens(char *host, int min_port, int max_port) > { >- debug("allow port forwarding to host %s port %d", host, port); >+ if (min_port == max_port) { >+ debug("allow port forwarding to host %s port %d", host, min_port); >+ } else { >+ if (min_port > max_port) { >+ // xor swap the ports >+ min_port ^= max_port; >+ max_port ^= min_port; >+ min_port ^= max_port; >+ } >+ debug("allow port forwarding to host %s ports %d through %d", host, min_port, max_port); >+ } > > permitted_opens = xrealloc(permitted_opens, > num_permitted_opens + 1, sizeof(*permitted_opens)); > permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host); >- permitted_opens[num_permitted_opens].port_to_connect = port; >+ permitted_opens[num_permitted_opens].min_port_to_connect = min_port; >+ permitted_opens[num_permitted_opens].min_port_to_connect = max_port; > num_permitted_opens++; > > all_opens_permitted = 0; > } > > int >-channel_add_adm_permitted_opens(char *host, int port) >+channel_add_adm_permitted_opens(char *host, int min_port, int max_port) > { >- debug("config allows port forwarding to host %s port %d", host, port); >+ if (min_port == max_port) { >+ debug("config allows port forwarding to host %s port %d", host, min_port); >+ } else { >+ if (min_port > max_port) { >+ // xor swap the ports >+ min_port ^= max_port; >+ max_port ^= min_port; >+ min_port ^= max_port; >+ } >+ debug("config allows port forwarding to host %s ports %d through %d", host, min_port, max_port); >+ } > > permitted_adm_opens = xrealloc(permitted_adm_opens, > num_adm_permitted_opens + 1, sizeof(*permitted_adm_opens)); > permitted_adm_opens[num_adm_permitted_opens].host_to_connect > = xstrdup(host); >- permitted_adm_opens[num_adm_permitted_opens].port_to_connect = port; >+ permitted_adm_opens[num_adm_permitted_opens].min_port_to_connect = min_port; >+ permitted_adm_opens[num_adm_permitted_opens].max_port_to_connect = max_port; > return ++num_adm_permitted_opens; > } > >@@ -3067,9 +3093,17 @@ > return; > } > for (i = 0; i < num_adm_permitted_opens; i++) >- if (permitted_adm_opens[i].host_to_connect != NULL) >- printf(" %s:%d", permitted_adm_opens[i].host_to_connect, >- permitted_adm_opens[i].port_to_connect); >+ if (permitted_adm_opens[i].host_to_connect != NULL) { >+ if (permitted_adm_opens[i].min_port_to_connect == >+ permitted_adm_opens[i].max_port_to_connect) { >+ printf(" %s:%d", permitted_adm_opens[i].host_to_connect, >+ permitted_adm_opens[i].min_port_to_connect); >+ } else { >+ printf(" %s:%d-%d", permitted_adm_opens[i].host_to_connect, >+ permitted_adm_opens[i].min_port_to_connect, >+ permitted_adm_opens[i].max_port_to_connect); >+ } >+ } > printf("\n"); > } > >@@ -3090,6 +3124,8 @@ > error("connect_next: getnameinfo failed"); > continue; > } >+ if (channel_is_connect_to_permitted(cctx) == 0) >+ continue; > if ((sock = socket(cctx->ai->ai_family, cctx->ai->ai_socktype, > cctx->ai->ai_protocol)) == -1) { > if (cctx->ai->ai_next == NULL) >@@ -3178,7 +3214,7 @@ > permitted_opens[i].listen_port == listen_port) { > return connect_to( > permitted_opens[i].host_to_connect, >- permitted_opens[i].port_to_connect, ctype, rname); >+ permitted_opens[i].min_port_to_connect, ctype, rname); > } > } > error("WARNING: Server requests forwarding for unknown listen_port %d", >@@ -3186,37 +3222,83 @@ > return NULL; > } > >-/* Check if connecting to that port is permitted and connect. */ >-Channel * >-channel_connect_to(const char *host, u_short port, char *ctype, char *rname) >+/* Check if connecting to that port is permitted */ >+int >+channel_is_connect_to_permitted(const struct channel_connect *cctx) > { >- int i, permit, permit_adm = 1; >+ int r, i, permit, permit_adm = 1; >+ char ipaddr[128]; // probably overkill size-wise >+ >+ /* Get an ip address string for match_host_and_ip */ >+ inet_ntop(cctx->ai->ai_family, &((const struct sockaddr_in *)cctx->ai->ai_addr)->sin_addr, ipaddr, cctx->ai->ai_addrlen); >+ >+ debug2("checking with ip %.100s for %.100s", ipaddr, cctx->host); > > permit = all_opens_permitted; > if (!permit) { >- for (i = 0; i < num_permitted_opens; i++) >+ for (i = 0; i < num_permitted_opens; i++) { >+ debug2("checking ports %d => %d <= %d", permitted_opens[i].min_port_to_connect, cctx->port, permitted_opens[i].max_port_to_connect); > if (permitted_opens[i].host_to_connect != NULL && >- permitted_opens[i].port_to_connect == port && >- strcmp(permitted_opens[i].host_to_connect, host) == 0) >- permit = 1; >+ permitted_opens[i].min_port_to_connect <= cctx->port && >+ permitted_opens[i].max_port_to_connect >= cctx->port) { >+ debug2("checking %.100s, %.100s, %.100s", cctx->host, ipaddr, permitted_opens[i].host_to_connect); >+ r = match_host_and_ip(cctx->host, ipaddr, permitted_opens[i].host_to_connect); >+ if (r == -1) { /* negated match - this attempt is blocked */ >+ debug2("denied %.100s:%d by %.100s:%d-%d", cctx->host, cctx->port, >+ permitted_opens[i].host_to_connect, >+ permitted_opens[i].min_port_to_connect, >+ permitted_opens[i].max_port_to_connect); >+ permit = 0; >+ break; >+ } else if (r == 1) { >+ debug2("permited %.100s:%d by %.100s:%d-%d", cctx->host, cctx->port, >+ permitted_opens[i].host_to_connect, >+ permitted_opens[i].min_port_to_connect, >+ permitted_opens[i].max_port_to_connect); >+ permit = 1; >+ } >+ } >+ } > } > > if (num_adm_permitted_opens > 0) { > permit_adm = 0; >- for (i = 0; i < num_adm_permitted_opens; i++) >+ for (i = 0; i < num_adm_permitted_opens; i++) { > if (permitted_adm_opens[i].host_to_connect != NULL && >- permitted_adm_opens[i].port_to_connect == port && >- strcmp(permitted_adm_opens[i].host_to_connect, host) >- == 0) >- permit_adm = 1; >+ permitted_adm_opens[i].min_port_to_connect <= cctx->port && >+ permitted_adm_opens[i].max_port_to_connect >= cctx->port) { >+ debug2("checking %.100s, %.100s, %.100s", cctx->host, ipaddr, permitted_adm_opens[i].host_to_connect); >+ r = match_host_and_ip(cctx->host, ipaddr, permitted_adm_opens[i].host_to_connect); >+ if (r == -1) { /* negated match - this attempt is blocked */ >+ debug2("server config denied %.100s:%d by %.100s:%d-%d", cctx->host, cctx->port, >+ permitted_adm_opens[i].host_to_connect, >+ permitted_adm_opens[i].min_port_to_connect, >+ permitted_adm_opens[i].max_port_to_connect); >+ permit_adm = 0; >+ break; >+ } else if (r == 1) { >+ debug2("server config permited %.100s:%d by %.100s:%d-%d", cctx->host, cctx->port, >+ permitted_adm_opens[i].host_to_connect, >+ permitted_adm_opens[i].min_port_to_connect, >+ permitted_adm_opens[i].max_port_to_connect); >+ permit_adm = 1; >+ } >+ } >+ } > } > > if (!permit || !permit_adm) { > logit("Received request to connect to host %.100s port %d, " >- "but the request was denied.", host, port); >- return NULL; >+ "but the request was denied.", cctx->host, cctx->port); >+ return 0; > } >- return connect_to(host, port, ctype, rname); >+ return 1; >+} >+/* Check if connecting to that port is permitted and connect. */ >+Channel * >+channel_connect_to(const char *host, u_short port, char *ctype, char *rname) >+{ >+ return connect_to(host, port, ctype, rname); /* XXX replace calls to channel_connect_to */ > } > > void >diff -u openssh-5.8p1.orig/channels.h openssh-5.8p1/channels.h >--- openssh-5.8p1.orig/channels.h 2010-05-20 21:57:10.000000000 -0700 >+++ openssh-5.8p1/channels.h 2011-03-24 17:00:32.000000000 -0700 >@@ -248,8 +248,9 @@ > /* tcp forwarding */ > void channel_set_af(int af); > void channel_permit_all_opens(void); >-void channel_add_permitted_opens(char *, int); >-int channel_add_adm_permitted_opens(char *, int); >+void channel_add_permitted_opens(char *, int, int); >+int channel_add_adm_permitted_opens(char *, int, int); >+int channel_is_connect_to_permitted(const struct channel_connect *); > void channel_clear_permitted_opens(void); > void channel_clear_adm_permitted_opens(void); > void channel_print_adm_permitted_opens(void); >Common subdirectories: openssh-5.8p1.orig/contrib and openssh-5.8p1/contrib >diff -u openssh-5.8p1.orig/match.c openssh-5.8p1/match.c >--- openssh-5.8p1.orig/match.c 2008-06-10 16:34:46.000000000 -0700 >+++ openssh-5.8p1/match.c 2011-03-24 19:34:58.000000000 -0700 >@@ -182,8 +182,8 @@ > } > > /* >- * returns 0 if we get a negative match for the hostname or the ip >- * or if we get no match at all. returns -1 on error, or 1 on >+ * returns -1 if we get a negative match for the hostname or the ip. >+ * returns 0 if we get no match at all. returns -2 on error, or 1 on > * successful match. > */ > int >@@ -193,14 +193,12 @@ > int mhost, mip; > > /* error in ipaddr match */ >- if ((mip = addr_match_list(ipaddr, patterns)) == -2) >- return -1; >- else if (mip == -1) /* negative ip address match */ >- return 0; >+ if ((mip = addr_match_list(ipaddr, patterns)) < 0) >+ return mip; > > /* negative hostname match */ >- if ((mhost = match_hostname(host, patterns, strlen(patterns))) == -1) >- return 0; >+ if ((mhost = match_hostname(host, patterns, strlen(patterns))) < 0) >+ return mhost; > /* no match at all */ > if (mhost == 0 && mip == 0) > return 0; >diff -u openssh-5.8p1.orig/misc.c openssh-5.8p1/misc.c >--- openssh-5.8p1.orig/misc.c 2011-01-12 17:21:36.000000000 -0800 >+++ openssh-5.8p1/misc.c 2011-03-23 18:15:27.000000000 -0700 >@@ -240,6 +240,47 @@ > return (int)port; > } > >+/* >+ * Convert ASCII string to a range of TCP/IP port numbers. >+ * Ports must be >=0 and <=65535. >+ * A single port will give itself as both the min and max >+ * A '*' will give a range of 0 to 65535 >+ * Return 2 if a range is found >+ * Return 1 if a single port is found >+ * Return -1 if invalid. >+ */ >+int >+a2portrange(const char *s, int *min_port, int *max_port) >+{ >+ char b1[16]; >+ char *b2; >+ b2 = b1; >+ strncpy(b1, s, sizeof(b1) - 1); >+ b1[sizeof(b1) - 1] = '\0'; >+ >+ if (!strcmp(b1, "*") || !strcmp(b1, "any")) { >+ *min_port = 1; >+ *max_port = 65535; >+ return 2; >+ } >+ >+ if ((b2 = strrchr(b1, '-')) != NULL) { >+ *b2 = '\0'; >+ b2++; >+ *min_port = a2port(b1); >+ *max_port = a2port(b2); >+ if (*min_port <= 0 || *max_port <= 0) >+ return -1; >+ return 2; >+ } >+ >+ *min_port = *max_port = a2port(b1); >+ if (*min_port <= 0) >+ return -1; >+ >+ return 1; >+} >+ > int > a2tun(const char *s, int *remote) > { >diff -u openssh-5.8p1.orig/misc.h openssh-5.8p1/misc.h >--- openssh-5.8p1.orig/misc.h 2010-11-30 16:50:35.000000000 -0800 >+++ openssh-5.8p1/misc.h 2011-03-23 18:04:47.000000000 -0700 >@@ -23,6 +23,7 @@ > int unset_nonblock(int); > void set_nodelay(int); > int a2port(const char *); >+int a2portrange(const char *, int *, int *); > int a2tun(const char *, int *); > char *put_host_port(const char *, u_short); > char *hpdelim(char **); >Common subdirectories: openssh-5.8p1.orig/openbsd-compat and openssh-5.8p1/openbsd-compat >Common subdirectories: openssh-5.8p1.orig/regress and openssh-5.8p1/regress >Common subdirectories: openssh-5.8p1.orig/scard and openssh-5.8p1/scard >diff -u openssh-5.8p1.orig/servconf.c openssh-5.8p1/servconf.c >--- openssh-5.8p1.orig/servconf.c 2010-11-19 20:19:38.000000000 -0800 >+++ openssh-5.8p1/servconf.c 2011-03-23 16:16:54.000000000 -0700 >@@ -681,11 +681,13 @@ > const char *host, const char *address) > { > char *cp, **charptr, *arg, *p; >+ char buf[512]; > int cmdline = 0, *intptr, value, value2, n; > SyslogFacility *log_facility_ptr; > LogLevel *log_level_ptr; > ServerOpCodes opcode; > int port; >+ int min_port, max_port; > u_int i, flags = 0; > size_t len; > >@@ -1344,12 +1346,28 @@ > fatal("%s line %d: missing host in PermitOpen", > filename, linenum); > p = cleanhostname(p); >- if (arg == NULL || (port = a2port(arg)) <= 0) >- fatal("%s line %d: bad port number in " >+ if (arg == NULL) { >+ fatal("%s line %d: missing port specification in " > "PermitOpen", filename, linenum); >- if (*activep && n == -1) >- options->num_permitted_opens = >- channel_add_adm_permitted_opens(p, port); >+ } else { >+ strncpy(buf, p, sizeof(buf) - 1); >+ p = hpdelim(&arg); >+ if (arg == NULL && (a2portrange(p, &min_port, &max_port)) <= 0) { >+ fatal("%s line %d: bad port specification in " >+ "PermitOpen", filename, linenum); >+ } else if (arg != NULL) { /* Both a CIDR mask and a port were specified */ >+ strncat(buf, "/", sizeof(buf) - strlen(buf) - 1); >+ if (strlen(p) + 1 > sizeof(buf) - strlen(p)) >+ fatal("%s line %d: argument too long in " >+ "PermitOpen", filename, linenum); >+ strncat(buf, p, sizeof(buf) - strlen(buf) - 1); >+ a2portrange(arg, &min_port, &max_port); >+ } >+ if (*activep) { >+ options->num_permitted_opens = >+ channel_add_adm_permitted_opens(buf, min_port, max_port); >+ } >+ } > } > break; >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 1513
: 2025