On Thu, May 04, 2017 at 09:37:59AM +1000, Adam Eijdenberg wrote:> Hi Devin, have you looked at using openssh certificates to help manage[...]> While the feature has been around for a while now (and is really > useful), there doesn't seem to be huge amount of documentation around > it. I found the following useful when getting a client of my runningYeah, when I wrote about it last year I didn't find many clients (just the openssh client) understood it: https://www.sweharris.org/post/2016-10-30-ssh-certs/ How many clients do work with CA signed keys? -- rgds Stephen
On Wed, 3 May 2017, Stephen Harris wrote:> On Thu, May 04, 2017 at 09:37:59AM +1000, Adam Eijdenberg wrote: > > Hi Devin, have you looked at using openssh certificates to help manage > [...] > > While the feature has been around for a while now (and is really > > useful), there doesn't seem to be huge amount of documentation around > > it. I found the following useful when getting a client of my running > > Yeah, when I wrote about it last year I didn't find many clients > (just the openssh client) understood it: > https://www.sweharris.org/post/2016-10-30-ssh-certs/Nice guide. You might want to mention hostname canonicalisation[1] in relation to host certs, it keeps things happy when users specify unqualified hostnames.> How many clients do work with CA signed keys?The Go x/crypto/ssh package supports OpenSSH certificates and offers a callback that's pretty easy to hook up with them. I don't know whether anybody is using it for that though. I do know of some of certified host keys in the wild with only OpenSSH as the client. -d [1] http://blog.djm.net.au/2014/01/hostname-canonicalisation-in-openssh.html
On May 3, 2017, at 5:44 PM, Stephen Harris <lists at spuddy.org> wrote:> On Thu, May 04, 2017 at 09:37:59AM +1000, Adam Eijdenberg wrote: >> Hi Devin, have you looked at using openssh certificates to help manage > [...] >> While the feature has been around for a while now (and is really >> useful), there doesn't seem to be huge amount of documentation around >> it. I found the following useful when getting a client of my running > > Yeah, when I wrote about it last year I didn't find many clients > (just the openssh client) understood it: > https://www.sweharris.org/post/2016-10-30-ssh-certs/ > > How many clients do work with CA signed keys?My AsyncSSH package for Python supports OpenSSH-format certificates. For more info, check out http://asyncssh.readthedocs.io <http://asyncssh.readthedocs.io/>. -- Ron Frederick ronf at timeheart.net
On Wed, May 3, 2017 at 6:01 PM, Damien Miller <djm at mindrot.org> wrote:> > > On Wed, 3 May 2017, Stephen Harris wrote: > >> On Thu, May 04, 2017 at 09:37:59AM +1000, Adam Eijdenberg wrote: >> > Hi Devin, have you looked at using openssh certificates to help manage >> [...] >> > While the feature has been around for a while now (and is really >> > useful), there doesn't seem to be huge amount of documentation around >> > it. I found the following useful when getting a client of my running >> >> Yeah, when I wrote about it last year I didn't find many clients >> (just the openssh client) understood it: >> https://www.sweharris.org/post/2016-10-30-ssh-certs/ > > Nice guide. You might want to mention hostname canonicalisation[1] in > relation to host certs, it keeps things happy when users specify > unqualified hostnames. > >> How many clients do work with CA signed keys? > > The Go x/crypto/ssh package supports OpenSSH certificates and offers > a callback that's pretty easy to hook up with them.and how> I don't know whether anybody is using it for that though.we use the go stuff to write certs to to an ssh-agent process, so it's still just an openssh client that's using the resulting cert/key the terminal emulation stuff scares me more than writing/maintaining an ssh ca, so I've never really tried to write a full openssh client replacement.> I do know of some of certified host keys in the wild with only OpenSSH > as the client. > > -d > > [1] http://blog.djm.net.au/2014/01/hostname-canonicalisation-in-openssh.html > _______________________________________________ > openssh-unix-dev mailing list > openssh-unix-dev at mindrot.org > https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev
Thank you to all that have replied so far, I appreciate your time. 1. For anyone who may be interested, I have attached our current patch. If others feel it helpful, feel free to use. It is released under the terms of the OpenSSH project. The intention of this patch is: a. This adds a permitgwport option for the authorized_keys file handling, allowing that file to control what ssh -R options a client may submit. b. This makes sshd require a permitopen option for any ports to be allowed. i.e. if no permitopen appears, then no ssh -L ports will be forwarded. c. This patch has been somewhat tested, but anyone that wants to use should review on their own. 2. Our thought is combining the AuthorizedKeysCommand with the key, and then gluing the port forward firewall rules our system builds. Our users are all AD so we have some extra items we want to do. Our problem isn?t lack of vision or understanding, it?s lack of time ? hence me trying to find and pay for smart people and their time! Thanks, Devin On 2017-05-03, 6:44 PM, "Stephen Harris" <lists at spuddy.org> wrote: On Thu, May 04, 2017 at 09:37:59AM +1000, Adam Eijdenberg wrote: > Hi Devin, have you looked at using openssh certificates to help manage [...] > While the feature has been around for a while now (and is really > useful), there doesn't seem to be huge amount of documentation around > it. I found the following useful when getting a client of my running Yeah, when I wrote about it last year I didn't find many clients (just the openssh client) understood it: https://www.sweharris.org/post/2016-10-30-ssh-certs/ How many clients do work with CA signed keys? -- rgds Stephen
Sorry to double post. I see the mailing list does not prefer attachments. permitgwport patch inline here, and changes behavior to require permitopen in an authorized_keys file, otherwise no ports may be opened (default deny). Thanks, Devin permitgwports-and-permitopen-mandatory-openssh-7.2p2.patch --- auth-options.c.orig 2016-05-02 11:25:41.420811342 -0600 +++ auth-options.c 2016-05-02 13:06:23.149347634 -0600 @@ -81,6 +81,7 @@ authorized_principals = NULL; forced_tun_device = -1; channel_clear_permitted_opens(); + channel_clear_permitted_gatewayports(); } /* @@ -326,6 +327,51 @@ /* deny access */ return 0; } + cp = "permitgwport=\""; + if (strncasecmp(opts, cp, strlen(cp)) == 0) { + char *p; + int port; + char *patterns = xmalloc(strlen(opts) + 1); + + opts += strlen(cp); + i = 0; + while (*opts) { + if (*opts == '"') + break; + if (*opts == '\\' && opts[1] == '"') { + opts += 2; + patterns[i++] = '"'; + continue; + } + patterns[i++] = *opts++; + } + if (!*opts) { + debug("%.100s, line %lu: missing end quote", + file, linenum); + auth_debug_add("%.100s, line %lu: missing " + "end quote", file, linenum); + free(patterns); + goto bad_option; + } + patterns[i] = '\0'; + opts++; + p = patterns; + port = a2port(p); + if (port <= 0 || port >= 65536) { + debug("%.100s, line %lu: Bad permitgwport " + "specification <%.100s>", file, linenum, + patterns); + auth_debug_add("%.100s, line %lu: " + "Bad permitgwport specification", file, + linenum); + free(patterns); + goto bad_option; + } + if ((options.allow_tcp_forwarding & FORWARD_REMOTE) != 0) + channel_add_permitted_gatewayports(port); + free(patterns); + goto next_option; + } cp = "permitopen=\""; if (strncasecmp(opts, cp, strlen(cp)) == 0) { char *host, *p; --- channels.c.orig 2016-05-02 11:18:46.095511183 -0600 +++ channels.c 2016-05-03 16:50:46.033883347 -0600 @@ -135,6 +135,12 @@ /* Number of permitted host/port pair in the array permitted by the admin. */ static int num_adm_permitted_opens = 0; +/* List of all permitted ports allowed to be gateway ports by the user */ +static int *permitted_gatewayports = NULL; + +/* Number of permitted ports allowed to be gateway ports by the user */ +static int num_permitted_gatewayports = 0; + /* special-case port number meaning allow any port */ #define FWD_PERMIT_ANY_PORT 0 @@ -3303,6 +3309,24 @@ return 1; } +int +gatewayport_permit(int requestedport) +{ + int i, permit = 0; + for (i = 0; i < num_permitted_gatewayports; i++) { + if (permitted_gatewayports[i] == requestedport) { + permit = 1; + break; + } + } + if (!permit) { + logit("Received request for gateway port %d, " + "but the request was denied.", requestedport); + return 0; + } + return 1; +} + /* * Note that in the listen host/port case * we don't support FWD_PERMIT_ANY_PORT and @@ -3482,8 +3506,8 @@ void channel_permit_all_opens(void) { - if (num_permitted_opens == 0) - all_opens_permitted = 1; + /* always require explicit permitopens */ + all_opens_permitted = 0; } void @@ -3503,6 +3527,16 @@ all_opens_permitted = 0; } +void +channel_add_permitted_gatewayports(int port) +{ + debug("allow gatewayport %d", port); + permitted_gatewayports = xreallocarray(permitted_gatewayports, + num_permitted_gatewayports + 1, sizeof(*permitted_gatewayports)); + permitted_gatewayports[num_permitted_gatewayports] = port; + num_permitted_gatewayports++; +} + /* * Update the listen port for a dynamic remote forward, after * the actual 'newport' has been allocated. If 'newport' < 0 is @@ -3577,6 +3611,14 @@ } void +channel_clear_permitted_gatewayports(void) +{ + free(permitted_gatewayports); + permitted_gatewayports = NULL; + num_permitted_gatewayports = 0; +} + +void channel_clear_adm_permitted_opens(void) { int i; --- channels.h.orig 2016-05-02 11:27:24.917708255 -0600 +++ channels.h 2016-05-02 18:55:21.789555565 -0600 @@ -261,10 +261,12 @@ void channel_set_af(int af); void channel_permit_all_opens(void); void channel_add_permitted_opens(char *, int); +void channel_add_permitted_gatewayports(int); int channel_add_adm_permitted_opens(char *, int); void channel_disable_adm_local_opens(void); void channel_update_permitted_opens(int, int); void channel_clear_permitted_opens(void); +void channel_clear_permitted_gatewayports(void); void channel_clear_adm_permitted_opens(void); void channel_print_adm_permitted_opens(void); int channel_input_port_forward_request(int, struct ForwardOptions *); @@ -281,6 +283,7 @@ int channel_cancel_rport_listener(struct Forward *); int channel_cancel_lport_listener(struct Forward *, int, struct ForwardOptions *); int permitopen_port(const char *); +int gatewayport_permit(int); /* x11 forwarding */ --- serverloop.c.orig 2016-05-02 17:15:09.745831104 -0600 +++ serverloop.c 2016-05-03 16:52:02.181666652 -0600 @@ -1240,6 +1240,7 @@ if ((options.allow_tcp_forwarding & FORWARD_REMOTE) == 0 || no_port_forwarding_flag || (!want_reply && fwd.listen_port == 0) + || !gatewayport_permit(fwd.listen_port) #ifndef NO_IPPORT_RESERVED_CONCEPT || (fwd.listen_port != 0 && fwd.listen_port < IPPORT_RESERVED && pw->pw_uid != 0)