Re: ssh agent authentication for doas

2015-07-27 Thread David Gwynne

 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 Thread Vadim Zhukov
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

2015-07-26 Thread Nicholas Marriott
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

2015-07-26 Thread David Gwynne

 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 Thread Vadim Zhukov
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

2015-07-26 Thread David Gwynne

 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

2015-07-26 Thread Nicholas Marriott
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

2015-07-26 Thread Ted Unangst
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.