Re: ssh agent authentication for doas
On 27 Jul 2015, at 1:57 am, Ted Unangst t...@tedunangst.com wrote: David Gwynne wrote: this is rough, but enough to start a discussion. this lets doas authenticate a user by talking to their ssh agent by specifying 'ssh-agent' on a permit line in the config. if agent auth fails, doas falls back to bsd auth (ie, password auth). to minimise the amount of code needed in doas, most of the heavy lifting is handed off to two external programs. ehhh... woah, this is getting complicated fast. the first is a program that fetches a users keys. it has to be provided by the system administrator. at work i have an AuthorizedKeysCommand thing that fetches keys from active directory (ie, an ldap) so users can do key based auth and it sounds like you will be the only user... If we add this, we would need to document it. And worse, users would need to read it. And it would sound cool, but then they'd struggle to set it up and get frustrated. It is, in short, an attractive nuisance. If bsd auth does not suit your needs, then I think that should be the place to focus your efforts. aww, the burn :( im pretty sure im not the only user of authorizedkeyscommand. it sort of came via redhat, and i think sunssh on solaris has a similar capability via weird shared libs. presumably people who run more than a couple of machines at home find this stuff useful. more importantly to me, i also got a private reply to my diff from someone who seemed keen on this on openbsd as they are current users of http://pamsshagentauth.sourceforge.net/ on other platforms. they also asked if id seen https://www.usenix.org/legacy/event/lisa08/tech/full_papers/burnside/burnside_html/index.html. the link above is pretty depressing for two reasons. we could have had this functionality in place nearly 20 years ago, and between 98 when that paper was written and 2000 when bsd_auth seems to have been brought into the openbsd tree, the environment masking was put in place that gets in the way of me implementing a bsd_auth ssh agent login script. just so im clear, we're not arguing about the general usefulness of being able to use an ssh agent for auth with doas? just how my diff did it? id like to be able to do it cos it would give us an alternative to implementing tickets to mitigate password requests. if the preference is to do it via bsd_auth instead of hardcoding it in doas, can i have a suggestion on what the least damaging way of implementing it would be? the easiest change would be to for bsd_auth to unconditionally copy SSH_AUTH_SOCK into the environment it calls the login script with. that could also be considered quite damaging though :( maybe whitelisting env vars in login.conf that can be passed to a login script by bsd_auth? dlg
Re: ssh agent authentication for doas
2015-07-26 13:06 GMT+03:00 David Gwynne da...@gwynne.id.au: On 26 Jul 2015, at 7:41 pm, Vadim Zhukov persg...@gmail.com wrote: 2015-07-26 12:19 GMT+03:00 David Gwynne da...@gwynne.id.au: On 26 Jul 2015, at 7:07 pm, Nicholas Marriott nicholas.marri...@gmail.com wrote: Hi I can't say I know a lot about bsdauth so maybe this is a stupid question, but could this work as a login_* authentication method instead of doas doing it? i had a look at that. the biggest technical problem is that the bsd_auth framework filters all environment variables from the caller before calling the actual auth handler. if i wrote a login_sshagent thing for bsdauth, i cant get at the SSH_AUTH_SOCK env var to be able to talk to the agent. doas (and other programs) would have to be modified to explicitly pass the sockets location as an argument somehow. threading that needle doesnt look like much fun. it was pointed out to me that this isnt that useful anywhere except for doas and sudo, so generalising it has limited benefit. most bsd_auth uses are to authenticate remote users, you dont have a local agent socket to connect to in that situation. Probably a stupid question, but I see the auth_setoption() function that allows to pass parameters to the login script. Can't it be used? yes, that's what i alluded to above. doas would have to be modified to manage the bsd auth session itself rather than simply calling auth_userokay. it would have to check or specify the auth style and provide the extra information as you suggested. getting the list of authorized_keys would have to be rethought too. im still not sure what the general benefit is though. what else could sanely make use of an sshagent bsdauth backend apart from doas? the only thing i can think of is sudo, and it would need to be modified like i described above for doas too. without modification and code specific for this backend, bsd_auth users can't take advantage of it. Now I got it, thank you for explanation. I try to find a reliable and non-intrusive solution but can't, too. :( -- WBR, Vadim Zhukov
Re: ssh agent authentication for doas
Fair enough, thanks. On Sun, Jul 26, 2015 at 07:19:06PM +1000, David Gwynne wrote: On 26 Jul 2015, at 7:07 pm, Nicholas Marriott nicholas.marri...@gmail.com wrote: Hi I can't say I know a lot about bsdauth so maybe this is a stupid question, but could this work as a login_* authentication method instead of doas doing it? i had a look at that. the biggest technical problem is that the bsd_auth framework filters all environment variables from the caller before calling the actual auth handler. if i wrote a login_sshagent thing for bsdauth, i cant get at the SSH_AUTH_SOCK env var to be able to talk to the agent. doas (and other programs) would have to be modified to explicitly pass the sockets location as an argument somehow. threading that needle doesnt look like much fun. it was pointed out to me that this isnt that useful anywhere except for doas and sudo, so generalising it has limited benefit. most bsd_auth uses are to authenticate remote users, you dont have a local agent socket to connect to in that situation. cheers, dlg On Sun, Jul 26, 2015 at 06:43:57PM +1000, David Gwynne wrote: this is rough, but enough to start a discussion. this lets doas authenticate a user by talking to their ssh agent by specifying 'ssh-agent' on a permit line in the config. if agent auth fails, doas falls back to bsd auth (ie, password auth). to minimise the amount of code needed in doas, most of the heavy lifting is handed off to two external programs. the first is a program that fetches a users keys. it has to be provided by the system administrator. doas does not look at ~/.ssh/authorized_keys because that would allow someone on an unattended shell to modify the current users keys file to gain whatever privs theyve been granted by doas. instead, it followes the semantics of sshds AuthorizedKeysCommand handler. at work i have an AuthorizedKeysCommand thing that fetches keys from active directory (ie, an ldap) so users can do key based auth on all our machines instead of just the ones we nfs export their homedirs to. doas can use the same backend to fetch the set of keys the system trusts to auth that user. alternatively, a machine could have a set of trusted keys for its users that is read from /etc or such. the second program is /usr/libexec/doas.sshagent. my implementation reuses a lot of ssh code and links to libssh.a, so ive currently got it in src/usr.bin/ssh/doas.sshagent. it basically reads authorized_keys from stdin and attempts to use them against the users ssh agent. if one of the provided keys works, it exits with code 0. if auth fails, it exits with code 8. every other code is considered an error. the code in doas basically creates a pipe to join the stdout of the authorized_keys command to the stdin of doas.sshagent, and then waits for the latter to exit with a useful code. this way avoids having to add a bunch of buffering, string parsing, and crypto to doas itself. the doas.sshagent code contains that on its behalf. anyway, the code is rough, i only just got it all hanging together. thoughts? Index: doas/Makefile === RCS file: /cvs/src/usr.bin/doas/Makefile,v retrieving revision 1.1 diff -u -p -r1.1 Makefile --- doas/Makefile 16 Jul 2015 20:44:21 - 1.1 +++ doas/Makefile 26 Jul 2015 04:39:17 - @@ -8,7 +8,6 @@ MAN= doas.1 doas.conf.5 BINOWN= root BINMODE=4555 -CFLAGS+= -I${.CURDIR} COPTS+=-Wall .include bsd.prog.mk Index: doas/doas.c === RCS file: /cvs/src/usr.bin/doas/doas.c,v retrieving revision 1.21 diff -u -p -r1.21 doas.c --- doas/doas.c24 Jul 2015 06:36:42 - 1.21 +++ doas/doas.c26 Jul 2015 04:39:17 - @@ -17,6 +17,7 @@ #include sys/types.h #include sys/stat.h +#include sys/wait.h #include limits.h #include login_cap.h @@ -26,6 +27,8 @@ #include stdlib.h #include err.h #include unistd.h +#include fcntl.h +#include signal.h #include pwd.h #include grp.h #include syslog.h @@ -33,6 +36,8 @@ #include doas.h +static int ssh_agent(const char *, uid_t, gid_t); + static void __dead usage(void) { @@ -291,7 +296,7 @@ main(int argc, char **argv, char **envp) struct rule *rule; uid_t uid; uid_t target = 0; - gid_t groups[NGROUPS_MAX + 1]; + gid_t groups[NGROUPS_MAX + 1], gid; int ngroups; int i, ch; int sflag = 0; @@ -331,7 +336,7 @@ main(int argc, char **argv, char **envp) ngroups = getgroups(NGROUPS_MAX, groups); if (ngroups == -1) err(1, can't get groups); - groups[ngroups++] = getgid(); + groups[ngroups++] = gid = getgid(); if (sflag) { sh = getenv(SHELL); @@ -360,13 +365,23 @@
Re: ssh agent authentication for doas
On 26 Jul 2015, at 7:07 pm, Nicholas Marriott nicholas.marri...@gmail.com wrote: Hi I can't say I know a lot about bsdauth so maybe this is a stupid question, but could this work as a login_* authentication method instead of doas doing it? i had a look at that. the biggest technical problem is that the bsd_auth framework filters all environment variables from the caller before calling the actual auth handler. if i wrote a login_sshagent thing for bsdauth, i cant get at the SSH_AUTH_SOCK env var to be able to talk to the agent. doas (and other programs) would have to be modified to explicitly pass the sockets location as an argument somehow. threading that needle doesnt look like much fun. it was pointed out to me that this isnt that useful anywhere except for doas and sudo, so generalising it has limited benefit. most bsd_auth uses are to authenticate remote users, you dont have a local agent socket to connect to in that situation. cheers, dlg On Sun, Jul 26, 2015 at 06:43:57PM +1000, David Gwynne wrote: this is rough, but enough to start a discussion. this lets doas authenticate a user by talking to their ssh agent by specifying 'ssh-agent' on a permit line in the config. if agent auth fails, doas falls back to bsd auth (ie, password auth). to minimise the amount of code needed in doas, most of the heavy lifting is handed off to two external programs. the first is a program that fetches a users keys. it has to be provided by the system administrator. doas does not look at ~/.ssh/authorized_keys because that would allow someone on an unattended shell to modify the current users keys file to gain whatever privs theyve been granted by doas. instead, it followes the semantics of sshds AuthorizedKeysCommand handler. at work i have an AuthorizedKeysCommand thing that fetches keys from active directory (ie, an ldap) so users can do key based auth on all our machines instead of just the ones we nfs export their homedirs to. doas can use the same backend to fetch the set of keys the system trusts to auth that user. alternatively, a machine could have a set of trusted keys for its users that is read from /etc or such. the second program is /usr/libexec/doas.sshagent. my implementation reuses a lot of ssh code and links to libssh.a, so ive currently got it in src/usr.bin/ssh/doas.sshagent. it basically reads authorized_keys from stdin and attempts to use them against the users ssh agent. if one of the provided keys works, it exits with code 0. if auth fails, it exits with code 8. every other code is considered an error. the code in doas basically creates a pipe to join the stdout of the authorized_keys command to the stdin of doas.sshagent, and then waits for the latter to exit with a useful code. this way avoids having to add a bunch of buffering, string parsing, and crypto to doas itself. the doas.sshagent code contains that on its behalf. anyway, the code is rough, i only just got it all hanging together. thoughts? Index: doas/Makefile === RCS file: /cvs/src/usr.bin/doas/Makefile,v retrieving revision 1.1 diff -u -p -r1.1 Makefile --- doas/Makefile16 Jul 2015 20:44:21 - 1.1 +++ doas/Makefile26 Jul 2015 04:39:17 - @@ -8,7 +8,6 @@ MAN= doas.1 doas.conf.5 BINOWN= root BINMODE=4555 -CFLAGS+= -I${.CURDIR} COPTS+= -Wall .include bsd.prog.mk Index: doas/doas.c === RCS file: /cvs/src/usr.bin/doas/doas.c,v retrieving revision 1.21 diff -u -p -r1.21 doas.c --- doas/doas.c 24 Jul 2015 06:36:42 - 1.21 +++ doas/doas.c 26 Jul 2015 04:39:17 - @@ -17,6 +17,7 @@ #include sys/types.h #include sys/stat.h +#include sys/wait.h #include limits.h #include login_cap.h @@ -26,6 +27,8 @@ #include stdlib.h #include err.h #include unistd.h +#include fcntl.h +#include signal.h #include pwd.h #include grp.h #include syslog.h @@ -33,6 +36,8 @@ #include doas.h +static int ssh_agent(const char *, uid_t, gid_t); + static void __dead usage(void) { @@ -291,7 +296,7 @@ main(int argc, char **argv, char **envp) struct rule *rule; uid_t uid; uid_t target = 0; -gid_t groups[NGROUPS_MAX + 1]; +gid_t groups[NGROUPS_MAX + 1], gid; int ngroups; int i, ch; int sflag = 0; @@ -331,7 +336,7 @@ main(int argc, char **argv, char **envp) ngroups = getgroups(NGROUPS_MAX, groups); if (ngroups == -1) err(1, can't get groups); -groups[ngroups++] = getgid(); +groups[ngroups++] = gid = getgid(); if (sflag) { sh = getenv(SHELL); @@ -360,13 +365,23 @@ main(int argc, char **argv, char **envp) fail(); } -if (!(rule-options NOPASS)) { +switch (rule-options AUTHMASK) { +case NOPASS: +break; +case
Re: ssh agent authentication for doas
2015-07-26 12:19 GMT+03:00 David Gwynne da...@gwynne.id.au: On 26 Jul 2015, at 7:07 pm, Nicholas Marriott nicholas.marri...@gmail.com wrote: Hi I can't say I know a lot about bsdauth so maybe this is a stupid question, but could this work as a login_* authentication method instead of doas doing it? i had a look at that. the biggest technical problem is that the bsd_auth framework filters all environment variables from the caller before calling the actual auth handler. if i wrote a login_sshagent thing for bsdauth, i cant get at the SSH_AUTH_SOCK env var to be able to talk to the agent. doas (and other programs) would have to be modified to explicitly pass the sockets location as an argument somehow. threading that needle doesnt look like much fun. it was pointed out to me that this isnt that useful anywhere except for doas and sudo, so generalising it has limited benefit. most bsd_auth uses are to authenticate remote users, you dont have a local agent socket to connect to in that situation. Probably a stupid question, but I see the auth_setoption() function that allows to pass parameters to the login script. Can't it be used? -- WBR, Vadim Zhukov
Re: ssh agent authentication for doas
On 26 Jul 2015, at 7:41 pm, Vadim Zhukov persg...@gmail.com wrote: 2015-07-26 12:19 GMT+03:00 David Gwynne da...@gwynne.id.au: On 26 Jul 2015, at 7:07 pm, Nicholas Marriott nicholas.marri...@gmail.com wrote: Hi I can't say I know a lot about bsdauth so maybe this is a stupid question, but could this work as a login_* authentication method instead of doas doing it? i had a look at that. the biggest technical problem is that the bsd_auth framework filters all environment variables from the caller before calling the actual auth handler. if i wrote a login_sshagent thing for bsdauth, i cant get at the SSH_AUTH_SOCK env var to be able to talk to the agent. doas (and other programs) would have to be modified to explicitly pass the sockets location as an argument somehow. threading that needle doesnt look like much fun. it was pointed out to me that this isnt that useful anywhere except for doas and sudo, so generalising it has limited benefit. most bsd_auth uses are to authenticate remote users, you dont have a local agent socket to connect to in that situation. Probably a stupid question, but I see the auth_setoption() function that allows to pass parameters to the login script. Can't it be used? yes, that's what i alluded to above. doas would have to be modified to manage the bsd auth session itself rather than simply calling auth_userokay. it would have to check or specify the auth style and provide the extra information as you suggested. getting the list of authorized_keys would have to be rethought too. im still not sure what the general benefit is though. what else could sanely make use of an sshagent bsdauth backend apart from doas? the only thing i can think of is sudo, and it would need to be modified like i described above for doas too. without modification and code specific for this backend, bsd_auth users can't take advantage of it. dlg -- WBR, Vadim Zhukov
Re: ssh agent authentication for doas
Hi I can't say I know a lot about bsdauth so maybe this is a stupid question, but could this work as a login_* authentication method instead of doas doing it? On Sun, Jul 26, 2015 at 06:43:57PM +1000, David Gwynne wrote: this is rough, but enough to start a discussion. this lets doas authenticate a user by talking to their ssh agent by specifying 'ssh-agent' on a permit line in the config. if agent auth fails, doas falls back to bsd auth (ie, password auth). to minimise the amount of code needed in doas, most of the heavy lifting is handed off to two external programs. the first is a program that fetches a users keys. it has to be provided by the system administrator. doas does not look at ~/.ssh/authorized_keys because that would allow someone on an unattended shell to modify the current users keys file to gain whatever privs theyve been granted by doas. instead, it followes the semantics of sshds AuthorizedKeysCommand handler. at work i have an AuthorizedKeysCommand thing that fetches keys from active directory (ie, an ldap) so users can do key based auth on all our machines instead of just the ones we nfs export their homedirs to. doas can use the same backend to fetch the set of keys the system trusts to auth that user. alternatively, a machine could have a set of trusted keys for its users that is read from /etc or such. the second program is /usr/libexec/doas.sshagent. my implementation reuses a lot of ssh code and links to libssh.a, so ive currently got it in src/usr.bin/ssh/doas.sshagent. it basically reads authorized_keys from stdin and attempts to use them against the users ssh agent. if one of the provided keys works, it exits with code 0. if auth fails, it exits with code 8. every other code is considered an error. the code in doas basically creates a pipe to join the stdout of the authorized_keys command to the stdin of doas.sshagent, and then waits for the latter to exit with a useful code. this way avoids having to add a bunch of buffering, string parsing, and crypto to doas itself. the doas.sshagent code contains that on its behalf. anyway, the code is rough, i only just got it all hanging together. thoughts? Index: doas/Makefile === RCS file: /cvs/src/usr.bin/doas/Makefile,v retrieving revision 1.1 diff -u -p -r1.1 Makefile --- doas/Makefile 16 Jul 2015 20:44:21 - 1.1 +++ doas/Makefile 26 Jul 2015 04:39:17 - @@ -8,7 +8,6 @@ MAN= doas.1 doas.conf.5 BINOWN= root BINMODE=4555 -CFLAGS+= -I${.CURDIR} COPTS+= -Wall .include bsd.prog.mk Index: doas/doas.c === RCS file: /cvs/src/usr.bin/doas/doas.c,v retrieving revision 1.21 diff -u -p -r1.21 doas.c --- doas/doas.c 24 Jul 2015 06:36:42 - 1.21 +++ doas/doas.c 26 Jul 2015 04:39:17 - @@ -17,6 +17,7 @@ #include sys/types.h #include sys/stat.h +#include sys/wait.h #include limits.h #include login_cap.h @@ -26,6 +27,8 @@ #include stdlib.h #include err.h #include unistd.h +#include fcntl.h +#include signal.h #include pwd.h #include grp.h #include syslog.h @@ -33,6 +36,8 @@ #include doas.h +static int ssh_agent(const char *, uid_t, gid_t); + static void __dead usage(void) { @@ -291,7 +296,7 @@ main(int argc, char **argv, char **envp) struct rule *rule; uid_t uid; uid_t target = 0; - gid_t groups[NGROUPS_MAX + 1]; + gid_t groups[NGROUPS_MAX + 1], gid; int ngroups; int i, ch; int sflag = 0; @@ -331,7 +336,7 @@ main(int argc, char **argv, char **envp) ngroups = getgroups(NGROUPS_MAX, groups); if (ngroups == -1) err(1, can't get groups); - groups[ngroups++] = getgid(); + groups[ngroups++] = gid = getgid(); if (sflag) { sh = getenv(SHELL); @@ -360,13 +365,23 @@ main(int argc, char **argv, char **envp) fail(); } - if (!(rule-options NOPASS)) { + switch (rule-options AUTHMASK) { + case NOPASS: + break; + case SSHAGENT: + if (ssh_agent(myname, uid, gid) == 0) + break; + + /* FALLTHROUGH */ + case PASSAUTH: if (!auth_userokay(myname, NULL, NULL, NULL)) { syslog(LOG_AUTHPRIV | LOG_NOTICE, failed password for %s, myname); fail(); } + break; } + envp = copyenv((const char **)envp, rule); pw = getpwuid(target); @@ -385,4 +400,136 @@ main(int argc, char **argv, char **envp) if (errno == ENOENT) errx(1, %s: command not found, cmd); err(1, %s, cmd); +} + +char *keycmd = /etc/doas/sshkeys; +char *keyuser = _doas; +char *agentcmd =
Re: ssh agent authentication for doas
David Gwynne wrote: this is rough, but enough to start a discussion. this lets doas authenticate a user by talking to their ssh agent by specifying 'ssh-agent' on a permit line in the config. if agent auth fails, doas falls back to bsd auth (ie, password auth). to minimise the amount of code needed in doas, most of the heavy lifting is handed off to two external programs. ehhh... woah, this is getting complicated fast. the first is a program that fetches a users keys. it has to be provided by the system administrator. at work i have an AuthorizedKeysCommand thing that fetches keys from active directory (ie, an ldap) so users can do key based auth and it sounds like you will be the only user... If we add this, we would need to document it. And worse, users would need to read it. And it would sound cool, but then they'd struggle to set it up and get frustrated. It is, in short, an attractive nuisance. If bsd auth does not suit your needs, then I think that should be the place to focus your efforts.