util-linux.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* runuser(1) and su(1) -g/-G
@ 2012-09-04 15:18 Karel Zak
  2012-09-04 19:52 ` Pádraig Brady
  2012-09-05 12:38 ` Dave Reisner
  0 siblings, 2 replies; 10+ messages in thread
From: Karel Zak @ 2012-09-04 15:18 UTC (permalink / raw)
  To: util-linux; +Cc: Ludwig Nussel, Pádraig Brady


 Hi,

I did some changes to the su(1):

  - add --group= option to specify the primary group
  - add --supp-group= option to specify a supplemental group

the both options are based on Fedora runuser(1) patch and it's
available for root only (non-root cannot specify any groups).


I have also added new command runuser(1) -- it's completely based on
su(1) code. The difference is that runuser does not ask for password,
has to be executed by root and it uses different PAM configuration
(/etc/pam.d/runuser[-l]).

The changes should be available in v2.23 (or easily backported to
2.22, I'll do that for Fedora).

See master branch and "git whatchanged login-utils/".

    Karel

-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: runuser(1) and su(1) -g/-G
  2012-09-04 15:18 runuser(1) and su(1) -g/-G Karel Zak
@ 2012-09-04 19:52 ` Pádraig Brady
  2012-09-05  8:44   ` Karel Zak
  2012-09-05 12:38 ` Dave Reisner
  1 sibling, 1 reply; 10+ messages in thread
From: Pádraig Brady @ 2012-09-04 19:52 UTC (permalink / raw)
  To: Karel Zak; +Cc: util-linux, Ludwig Nussel

On 09/04/2012 04:18 PM, Karel Zak wrote:
>
>   Hi,
>
> I did some changes to the su(1):
>
>    - add --group= option to specify the primary group
>    - add --supp-group= option to specify a supplemental group
>
> the both options are based on Fedora runuser(1) patch and it's
> available for root only (non-root cannot specify any groups).
>
>
> I have also added new command runuser(1) -- it's completely based on
> su(1) code. The difference is that runuser does not ask for password,
> has to be executed by root and it uses different PAM configuration
> (/etc/pam.d/runuser[-l]).

Thanks for doing all that Karel.
I've not time to look now,
but will note that many were looking for
a lightweight option that didn't need PAM.
Perhaps PAM support could be easily compiled out?

cheers,
Pádraig.

>
> The changes should be available in v2.23 (or easily backported to
> 2.22, I'll do that for Fedora).
>
> See master branch and "git whatchanged login-utils/".
>
>      Karel
>


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: runuser(1) and su(1) -g/-G
  2012-09-04 19:52 ` Pádraig Brady
@ 2012-09-05  8:44   ` Karel Zak
  0 siblings, 0 replies; 10+ messages in thread
From: Karel Zak @ 2012-09-05  8:44 UTC (permalink / raw)
  To: Pádraig Brady; +Cc: util-linux, Ludwig Nussel

On Tue, Sep 04, 2012 at 08:52:14PM +0100, Pádraig Brady wrote:
> Thanks for doing all that Karel.
> I've not time to look now,
> but will note that many were looking for
> a lightweight option that didn't need PAM.

I know, it should be the second step.

> Perhaps PAM support could be easily compiled out?

Not yet. The patch will be pretty simple, all we need is to add
something like #ifdef BUILD_LIGHTWEIGHT_RUNUSER to
create_watching_parent() and authenticate(). 

Volunteers? (I'm going to spend this week with coverity scanner...)


Note that we will support PAM-only su(1), maintain alternative
authentication code in utils like su(1), login(1), ... is nonsense.

If you don't like modular PAM then you can rebuild libpam with
statically linked modules (result is still shared library, but without
dlopen()).

The command runuser(1) is different as there is no authentication at
all -- it's just wrapper around setuid/gid, and it uses PAM for
session setup only.

    Karel

-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: runuser(1) and su(1) -g/-G
  2012-09-04 15:18 runuser(1) and su(1) -g/-G Karel Zak
  2012-09-04 19:52 ` Pádraig Brady
@ 2012-09-05 12:38 ` Dave Reisner
  2012-09-05 21:28   ` Dave Reisner
  1 sibling, 1 reply; 10+ messages in thread
From: Dave Reisner @ 2012-09-05 12:38 UTC (permalink / raw)
  To: Karel Zak; +Cc: util-linux, Ludwig Nussel, Pádraig Brady

On Tue, Sep 04, 2012 at 05:18:43PM +0200, Karel Zak wrote:
> 
>  Hi,
> 
> I did some changes to the su(1):
> 
>   - add --group= option to specify the primary group
>   - add --supp-group= option to specify a supplemental group
> 
> the both options are based on Fedora runuser(1) patch and it's
> available for root only (non-root cannot specify any groups).
> 
> 
> I have also added new command runuser(1) -- it's completely based on
> su(1) code. The difference is that runuser does not ask for password,
> has to be executed by root and it uses different PAM configuration
> (/etc/pam.d/runuser[-l]).
> 
> The changes should be available in v2.23 (or easily backported to
> 2.22, I'll do that for Fedora).
> 
> See master branch and "git whatchanged login-utils/".
> 
>     Karel
> 

Hi Karel,

I think we're missing out on an opportunity with runuser. su insists on
starting a shell which, among other subtle problems, leads to the
largeer problem of quoting and escaping the command passed to the -c
flag. I think we should do something like this:

- separate out argument parsing to runuser and su
- remove most of the flags from runuser (-f, -c, -l, -, -s), add a -u
  flag (optional, for user)
- create a single common entry point for creating a session
- separate out the run command logic

With a name like runuser, I would expect that its purpose would be to
simply run commands (and not necessarily get a shell for a user, as is
done with su). runuser could take non-option arguments as argv for the
new command so that we'd have examples like this:

  runuser -u notroot vi /etc/fstab
  runuser notroot foocmd embedded '"quotes"'
  runuser -u notroot foocmd has args "with spaces" sometimes

If you still desperately want to abuse the command to create a shell for
a user, then you just do that:

  runuser -u notroot -- /bin/sh -

I can't make any guarantees that I'll be able to offers patches for this
myself, but I'll definitely be taking a look if I have some free time.
Just thought I'd bring up the idea, since it's always been a pet peeve
of mine to fix if ever there were an opportunity for a mulligan on su
(and this is it!).

Cheers,
Dave

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: runuser(1) and su(1) -g/-G
  2012-09-05 12:38 ` Dave Reisner
@ 2012-09-05 21:28   ` Dave Reisner
  2012-09-07 12:07     ` Karel Zak
  0 siblings, 1 reply; 10+ messages in thread
From: Dave Reisner @ 2012-09-05 21:28 UTC (permalink / raw)
  To: Karel Zak, util-linux, Ludwig Nussel, Pádraig Brady

On Wed, Sep 05, 2012 at 08:38:22AM -0400, Dave Reisner wrote:
> On Tue, Sep 04, 2012 at 05:18:43PM +0200, Karel Zak wrote:
> > 
> >  Hi,
> > 
> > I did some changes to the su(1):
> > 
> >   - add --group= option to specify the primary group
> >   - add --supp-group= option to specify a supplemental group
> > 
> > the both options are based on Fedora runuser(1) patch and it's
> > available for root only (non-root cannot specify any groups).
> > 
> > 
> > I have also added new command runuser(1) -- it's completely based on
> > su(1) code. The difference is that runuser does not ask for password,
> > has to be executed by root and it uses different PAM configuration
> > (/etc/pam.d/runuser[-l]).
> > 
> > The changes should be available in v2.23 (or easily backported to
> > 2.22, I'll do that for Fedora).
> > 
> > See master branch and "git whatchanged login-utils/".
> > 
> >     Karel
> > 
> 
> Hi Karel,
> 
> I think we're missing out on an opportunity with runuser. su insists on
> starting a shell which, among other subtle problems, leads to the
> largeer problem of quoting and escaping the command passed to the -c
> flag. I think we should do something like this:
> 
> - separate out argument parsing to runuser and su
> - remove most of the flags from runuser (-f, -c, -l, -, -s), add a -u
>   flag (optional, for user)
> - create a single common entry point for creating a session
> - separate out the run command logic
> 
> With a name like runuser, I would expect that its purpose would be to
> simply run commands (and not necessarily get a shell for a user, as is
> done with su). runuser could take non-option arguments as argv for the
> new command so that we'd have examples like this:
> 
>   runuser -u notroot vi /etc/fstab
>   runuser notroot foocmd embedded '"quotes"'
>   runuser -u notroot foocmd has args "with spaces" sometimes
> 
> If you still desperately want to abuse the command to create a shell for
> a user, then you just do that:
> 
>   runuser -u notroot -- /bin/sh -
> 
> I can't make any guarantees that I'll be able to offers patches for this
> myself, but I'll definitely be taking a look if I have some free time.
> Just thought I'd bring up the idea, since it's always been a pet peeve
> of mine to fix if ever there were an opportunity for a mulligan on su
> (and this is it!).
> 
> Cheers,
> Dave

Hrmm... I had no idea that runuser was an existing command in the RedHat
world, which makes my idea of a "mulligan" less feasible. Boo.


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: runuser(1) and su(1) -g/-G
  2012-09-05 21:28   ` Dave Reisner
@ 2012-09-07 12:07     ` Karel Zak
  2012-09-07 12:39       ` Pádraig Brady
  2012-09-07 12:47       ` Dave Reisner
  0 siblings, 2 replies; 10+ messages in thread
From: Karel Zak @ 2012-09-07 12:07 UTC (permalink / raw)
  To: util-linux, Ludwig Nussel, Pádraig Brady

On Wed, Sep 05, 2012 at 05:28:04PM -0400, Dave Reisner wrote:
> > I think we're missing out on an opportunity with runuser. su insists on
> > starting a shell which, among other subtle problems, leads to the
> > largeer problem of quoting and escaping the command passed to the -c
> > flag. I think we should do something like this:

 good point

> > - separate out argument parsing to runuser and su
> > - remove most of the flags from runuser (-f, -c, -l, -, -s), add a -u
> >   flag (optional, for user)
> > - create a single common entry point for creating a session
> > - separate out the run command logic

 well, we still need to initialize the session and it would be also
 to have independent PAM setting for "login-like-session" (-l - options).

> > With a name like runuser, I would expect that its purpose would be to
> > simply run commands (and not necessarily get a shell for a user, as is
> > done with su). runuser could take non-option arguments as argv for the
> > new command so that we'd have examples like this:
> > 
> >   runuser -u notroot vi /etc/fstab
> >   runuser notroot foocmd embedded '"quotes"'
> >   runuser -u notroot foocmd has args "with spaces" sometimes
> > 
> > If you still desperately want to abuse the command to create a shell for
> > a user, then you just do that:
> > 
> >   runuser -u notroot -- /bin/sh -

 well, but it will NOT use /etc/pam.d/runuser-l

 I agree that -f -s -c are unnecessary (and -c is wrong at all...). It
 would be probably better to support:

    runuser [-u] notroot [<command> [arg]]

 and if <command> is not specified then start a shell, and if -l is
 specified create a login-like session.

> Hrmm... I had no idea that runuser was an existing command in the RedHat
> world, which makes my idea of a "mulligan" less feasible. Boo.

 Well, that's question if we (upstream) have to care about one crazy
 distro specific command. Maybe we can introduce a new command (with a
 different name) and ignore the original runuser. For good reason the
 command has not been accepted by coreutils upstream.

 Any suggestion for the new name?

    runuid
    runid
    execuser

 I have no problem to revert the runuser patch, really ;-) It was
 probably too hasty decision to merge whole my su branch.

    Karel

-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: runuser(1) and su(1) -g/-G
  2012-09-07 12:07     ` Karel Zak
@ 2012-09-07 12:39       ` Pádraig Brady
  2012-09-07 13:09         ` Adam Sampson
  2012-09-13 10:12         ` Karel Zak
  2012-09-07 12:47       ` Dave Reisner
  1 sibling, 2 replies; 10+ messages in thread
From: Pádraig Brady @ 2012-09-07 12:39 UTC (permalink / raw)
  To: Karel Zak; +Cc: util-linux, Ludwig Nussel

On 09/07/2012 01:07 PM, Karel Zak wrote:
> On Wed, Sep 05, 2012 at 05:28:04PM -0400, Dave Reisner wrote:
>>> I think we're missing out on an opportunity with runuser. su insists on
>>> starting a shell which, among other subtle problems, leads to the
>>> largeer problem of quoting and escaping the command passed to the -c
>>> flag. I think we should do something like this:
>
>   good point
>
>>> - separate out argument parsing to runuser and su
>>> - remove most of the flags from runuser (-f, -c, -l, -, -s), add a -u
>>>    flag (optional, for user)
>>> - create a single common entry point for creating a session
>>> - separate out the run command logic
>
>   well, we still need to initialize the session and it would be also
>   to have independent PAM setting for "login-like-session" (-l - options).
>
>>> With a name like runuser, I would expect that its purpose would be to
>>> simply run commands (and not necessarily get a shell for a user, as is
>>> done with su). runuser could take non-option arguments as argv for the
>>> new command so that we'd have examples like this:
>>>
>>>    runuser -u notroot vi /etc/fstab
>>>    runuser notroot foocmd embedded '"quotes"'
>>>    runuser -u notroot foocmd has args "with spaces" sometimes
>>>
>>> If you still desperately want to abuse the command to create a shell for
>>> a user, then you just do that:
>>>
>>>    runuser -u notroot -- /bin/sh -
>
>   well, but it will NOT use /etc/pam.d/runuser-l
>
>   I agree that -f -s -c are unnecessary (and -c is wrong at all...). It
>   would be probably better to support:
>
>      runuser [-u] notroot [<command>  [arg]]
>
>   and if<command>  is not specified then start a shell, and if -l is
>   specified create a login-like session.
>
>> Hrmm... I had no idea that runuser was an existing command in the RedHat
>> world, which makes my idea of a "mulligan" less feasible. Boo.
>
>   Well, that's question if we (upstream) have to care about one crazy
>   distro specific command. Maybe we can introduce a new command (with a
>   different name) and ignore the original runuser. For good reason the
>   command has not been accepted by coreutils upstream.
>
>   Any suggestion for the new name?
>
>      runuid
>      runid
>      execuser
>
>   I have no problem to revert the runuser patch, really ;-) It was
>   probably too hasty decision to merge whole my su branch.
>
>      Karel
>

I'd not really studied the runuser interface to be honest,
and yes I agree that it's quite crufty.
Maybe we could keep the runuser name and say
the prefered form is to specify -u $USER, which
will _not_ start a shell. The old interface without
-u being retained for backwards compat?

For reference, I'm copying in below some info from the coreutils list
from when we were discussing the transition of su to util-linux,
which references other utils in this space.

==== info from coreutils ===

Note Fedora and Suse use su from coreutils
while debian use their own:
http://pkg-shadow.alioth.debian.org/

Note also Fedora has `runuser` which is based on su:
http://pkgs.fedoraproject.org/gitweb/?p=coreutils.git;a=blob;f=coreutils-8.7-runuser.patch;hb=HEAD

There was also a very related request for
`runuser` like functionality to be generally available:
http://bugs.gnu.org/8700

It's probably worth bringing runuser with su,
no matter where they end up. So with su being removed in favor
of the util-linux implementation, `runuser` is being implemented there too.
I.E. it will be available outside of redhat/fedora/centos/...
in util-linux >= 2.23, and so should address http://bugs.gnu.org/8700
[well maybe not given the above discussion]

Note from previous comments in this thread,
it seems like allowing runser to be built (as an option?)
without requiring PAM, would be useful.

For reference, here are utils with similar functionality:

chid,really
   Mentioned in feature request from debian
     http://bugs.gnu.org/8700

chroot --userspec=U:G --groups=G1,G2,G3 /
   since coreutils v7.4-16-gc45c51f
   beware of CVE-2005-4890

setuidgid
   coreutils internal only
   http://git.sv.gnu.org/gitweb/?p=coreutils.git;a=blob;f=src/setuidgid.c;hb=HEAD

sg from pwdutils
   http://pubs.opengroup.org/onlinepubs/9699919799/utilities/newgrp.html

sudo -u -g

runas from titantools


cheers,
Pádraig.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: runuser(1) and su(1) -g/-G
  2012-09-07 12:07     ` Karel Zak
  2012-09-07 12:39       ` Pádraig Brady
@ 2012-09-07 12:47       ` Dave Reisner
  1 sibling, 0 replies; 10+ messages in thread
From: Dave Reisner @ 2012-09-07 12:47 UTC (permalink / raw)
  To: Karel Zak; +Cc: util-linux, Ludwig Nussel, Pádraig Brady

On Fri, Sep 07, 2012 at 02:07:16PM +0200, Karel Zak wrote:
> On Wed, Sep 05, 2012 at 05:28:04PM -0400, Dave Reisner wrote:
> > > I think we're missing out on an opportunity with runuser. su insists on
> > > starting a shell which, among other subtle problems, leads to the
> > > largeer problem of quoting and escaping the command passed to the -c
> > > flag. I think we should do something like this:
> 
>  good point
> 
> > > - separate out argument parsing to runuser and su
> > > - remove most of the flags from runuser (-f, -c, -l, -, -s), add a -u
> > >   flag (optional, for user)
> > > - create a single common entry point for creating a session
> > > - separate out the run command logic
> 
>  well, we still need to initialize the session and it would be also
>  to have independent PAM setting for "login-like-session" (-l - options).
> 
> > > With a name like runuser, I would expect that its purpose would be to
> > > simply run commands (and not necessarily get a shell for a user, as is
> > > done with su). runuser could take non-option arguments as argv for the
> > > new command so that we'd have examples like this:
> > > 
> > >   runuser -u notroot vi /etc/fstab
> > >   runuser notroot foocmd embedded '"quotes"'
> > >   runuser -u notroot foocmd has args "with spaces" sometimes
> > > 
> > > If you still desperately want to abuse the command to create a shell for
> > > a user, then you just do that:
> > > 
> > >   runuser -u notroot -- /bin/sh -
> 
>  well, but it will NOT use /etc/pam.d/runuser-l
>
>  I agree that -f -s -c are unnecessary (and -c is wrong at all...). It
>  would be probably better to support:
> 
>     runuser [-u] notroot [<command> [arg]]
> 
>  and if <command> is not specified then start a shell, and if -l is
>  specified create a login-like session.

I like all this.

> 
> > Hrmm... I had no idea that runuser was an existing command in the RedHat
> > world, which makes my idea of a "mulligan" less feasible. Boo.
> 
>  Well, that's question if we (upstream) have to care about one crazy
>  distro specific command. Maybe we can introduce a new command (with a
>  different name) and ignore the original runuser. For good reason the
>  command has not been accepted by coreutils upstream.
> 
>  Any suggestion for the new name?
> 
>     runuid
>     runid
>     execuser

I'm digging deep, back to my windows admin days -- perhaps 'runas'?
Maybe something shorter? Could we use 'ru' (a step back!) for irony? ;P

>  I have no problem to revert the runuser patch, really ;-) It was
>  probably too hasty decision to merge whole my su branch.
> 
>     Karel
> 
> -- 
>  Karel Zak  <kzak@redhat.com>
>  http://karelzak.blogspot.com
> --
> To unsubscribe from this list: send the line "unsubscribe util-linux" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: runuser(1) and su(1) -g/-G
  2012-09-07 12:39       ` Pádraig Brady
@ 2012-09-07 13:09         ` Adam Sampson
  2012-09-13 10:12         ` Karel Zak
  1 sibling, 0 replies; 10+ messages in thread
From: Adam Sampson @ 2012-09-07 13:09 UTC (permalink / raw)
  To: Pádraig Brady; +Cc: Karel Zak, util-linux, Ludwig Nussel

Pádraig Brady <P@draigBrady.com> writes:

> setuidgid
>   coreutils internal only

The name setuidgid for this tool was introduced by daemontools, and
various other projects have have their own versions of it:

  http://cr.yp.to/daemontools/setuidgid.html
  http://www.skarnet.org/software/s6/s6-setuidgid.html
  http://b0llix.net/perp/site.cgi?page=runuid.8
  http://git.savannah.gnu.org/gitweb/?p=coreutils.git;a=blob;f=src/setuidgid.c
  http://offog.org/darcs/freedt/setuidgid.c

(It would often be helpful for the tool to do a bit more than just
setting the uid and gids -- e.g. setting $HOME...)

perp has a suite of "runtools" like this that do some sort of
environment setup before execing another program:

  http://b0llix.net/perp/site.cgi?page=manual

The most useful ones (for me!) have equivalents in util-linux already:

- runsession is setsid;

- runlimit is prlimit;

- runlock is flock -- but flock only has an su-style -c argument, so it
  would probably be worth fixing that at the same time as runuser?

Thanks,

-- 
Adam Sampson <ats@offog.org>                         <http://offog.org/>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: runuser(1) and su(1) -g/-G
  2012-09-07 12:39       ` Pádraig Brady
  2012-09-07 13:09         ` Adam Sampson
@ 2012-09-13 10:12         ` Karel Zak
  1 sibling, 0 replies; 10+ messages in thread
From: Karel Zak @ 2012-09-13 10:12 UTC (permalink / raw)
  To: Pádraig Brady; +Cc: util-linux, Ludwig Nussel

On Fri, Sep 07, 2012 at 01:39:49PM +0100, Pádraig Brady wrote:
> Maybe we could keep the runuser name and say
> the prefered form is to specify -u $USER, which
> will _not_ start a shell. The old interface without
> -u being retained for backwards compat?

Good idea. Implemented, see below. The su-like options -c/C, -l and -f
are mutually exclusive to -u.

(and sorry for coding style. I'm absolutely incompatible with the
 original code -- when all the changes will be in master branch we'll
 use indent to make it readable for lovers of the kernel-style ...)

    Karel

>From 6ec71facf066ade0c42b98b274d041c6e0ed6d8c Mon Sep 17 00:00:00 2001
From: Karel Zak <kzak@redhat.com>
Date: Thu, 13 Sep 2012 11:58:00 +0200
Subject: [PATCH] runuser: add -u to not execute shell

Signed-off-by: Karel Zak <kzak@redhat.com>
---
 login-utils/runuser.1   |   20 +++++---
 login-utils/su-common.c |  138 +++++++++++++++++++++++++++++++----------------
 login-utils/su.1        |    1 +
 3 files changed, 105 insertions(+), 54 deletions(-)

diff --git a/login-utils/runuser.1 b/login-utils/runuser.1
index 1f21408..9a00cb6 100644
--- a/login-utils/runuser.1
+++ b/login-utils/runuser.1
@@ -3,10 +3,21 @@
 runuser \- run a command with substitute user and group ID
 .SH SYNOPSIS
 .B runuser
-[options...] [\-] [user [args...]]
+[options] -u
+.IR user
+.IR "command " [ argument ...]
+.LP
+.B runuser
+[options] [-]
+[
+.IR "user " [ argument ...]
+]
 .SH DESCRIPTION
 .B runuser
 allows to run commands with substitute user and group ID.
+If the option \fB\-u\fR not given, fallback to
+.B su
+compatible semantic and shell is executed.
 The difference between the commands
 .B runuser
 and
@@ -37,12 +48,7 @@ and
 .B LOGNAME
 if the target
 .I user
-is not root).  It is recommended to always use the
-.B \-\-login
-option (instead it's shortcut
-.BR \- )
-to avoid side effects caused by mixing environments.
-.PP
+is not root).
 This version of
 .B runuser
 uses PAM for session management.
diff --git a/login-utils/su-common.c b/login-utils/su-common.c
index 23ad57d..c6f3389 100644
--- a/login-utils/su-common.c
+++ b/login-utils/su-common.c
@@ -543,7 +543,8 @@ modify_environment (const struct passwd *pw, const char *shell)
       if (term)
 	xsetenv ("TERM", term, 1);
       xsetenv ("HOME", pw->pw_dir, 1);
-      xsetenv ("SHELL", shell, 1);
+      if (shell)
+	xsetenv ("SHELL", shell, 1);
       xsetenv ("USER", pw->pw_name, 1);
       xsetenv ("LOGNAME", pw->pw_name, 1);
       set_path(pw);
@@ -555,7 +556,8 @@ modify_environment (const struct passwd *pw, const char *shell)
       if (change_environment)
         {
           xsetenv ("HOME", pw->pw_dir, 1);
-          xsetenv ("SHELL", shell, 1);
+	  if (shell)
+            xsetenv ("SHELL", shell, 1);
 	  if (getlogindefs_bool ("ALWAYS_SET_PATH", 0))
 	    set_path(pw);
 	  else
@@ -690,35 +692,47 @@ restricted_shell (const char *shell)
 static void __attribute__((__noreturn__))
 usage (int status)
 {
-  if (status != EXIT_SUCCESS)
-    fprintf (stderr, _("Try `%s --help' for more information.\n"),
-	     program_invocation_short_name);
-  else
-    {
-      fputs(USAGE_HEADER, stdout);
-      printf (_(" %s [options] [-] [USER [arg]...]\n"), program_invocation_short_name);
-      fputs (_("\n\
- Change the effective user id and group id to that of USER.\n\
- A mere - implies -l.   If USER not given, assume root.\n"), stdout);
-      fputs(USAGE_OPTIONS, stdout);
-      fputs (_("\
- -, -l, --login               make the shell a login shell\n\
- -c, --command <command>      pass a single command to the shell with -c\n\
- --session-command <command>  pass a single command to the shell with -c\n\
-                              and do not create a new session\n\
- -g --group=group             specify the primary group\n\
- -G --supp-group=group        specify a supplemental group\n\
- -f, --fast                   pass -f to the shell (for csh or tcsh)\n\
- -m, --preserve-environment   do not reset environment variables\n\
- -p                           same as -m\n\
- -s, --shell <shell>          run shell if /etc/shells allows it\n\
-"), stdout);
-
-      fputs(USAGE_SEPARATOR, stdout);
-      fputs(USAGE_HELP, stdout);
-      fputs(USAGE_VERSION, stdout);
-      printf(USAGE_MAN_TAIL("su(1)"));
-    }
+  if (su_mode == RUNUSER_MODE) {
+    fputs(USAGE_HEADER, stdout);
+    printf (_(" %s [options] -u <USER> COMMAND\n"), program_invocation_short_name);
+    printf (_(" %s [options] [-] [USER [arg]...]\n"), program_invocation_short_name);
+    fputs (_("\n"
+    "Run COMMAND with the effective <user> id and group id. If -u not\n"
+    "given, fallback to su(1) compatible semantic and shell is executed.\n"
+    "The options -l, -c, -f, -s are mutually exclusive to -u.\n"), stdout);
+
+    fputs(USAGE_OPTIONS, stdout);
+
+    fputs (_(
+    " -u, --user <user>               username\n"), stdout);
+
+  } else {
+    fputs(USAGE_HEADER, stdout);
+    printf (_(" %s [options] [-] [USER [arg]...]\n"), program_invocation_short_name);
+    fputs (_("\n"
+    "Change the effective user id and group id to that of USER.\n"
+    "A mere - implies -l.   If USER not given, assume root.\n"), stdout);
+
+    fputs(USAGE_OPTIONS, stdout);
+  }
+
+  fputs (_(
+    " -m, -p, --preserve-environment  do not reset environment variables\n"
+    " -g, --group <group>             specify the primary group\n"
+    " -G, --supp-group <group>        specify a supplemental group\n\n"), stdout);
+
+  fputs (_(
+    " -, -l, --login                  make the shell a login shell\n"
+    " -c, --command <command>         pass a single command to the shell with -c\n"
+    " --session-command <command>     pass a single command to the shell with -c\n"
+    "                                 and do not create a new session\n"
+    " -f, --fast                      pass -f to the shell (for csh or tcsh)\n"
+    " -s, --shell <shell>             run shell if /etc/shells allows it\n"), stdout);
+
+  fputs(USAGE_SEPARATOR, stdout);
+  fputs(USAGE_HELP, stdout);
+  fputs(USAGE_VERSION, stdout);
+  printf(USAGE_MAN_TAIL(su_mode == SU_MODE ? "su(1)" : "runuser(1)"));
   exit (status);
 }
 
@@ -754,7 +768,7 @@ int
 su_main (int argc, char **argv, int mode)
 {
   int optc;
-  const char *new_user = DEFAULT_USER;
+  const char *new_user = DEFAULT_USER, *runuser_user = NULL;
   char *command = NULL;
   int request_same_session = 0;
   char *shell = NULL;
@@ -774,6 +788,7 @@ su_main (int argc, char **argv, int mode)
     {"shell", required_argument, NULL, 's'},
     {"group", required_argument, NULL, 'g'},
     {"supp-group", required_argument, NULL, 'G'},
+    {"user", required_argument, NULL, 'u'},		/* runuser only */
     {"help", no_argument, 0, 'h'},
     {"version", no_argument, 0, 'V'},
     {NULL, 0, NULL, 0}
@@ -789,7 +804,7 @@ su_main (int argc, char **argv, int mode)
   simulate_login = false;
   change_environment = true;
 
-  while ((optc = getopt_long (argc, argv, "c:fg:G:lmps:hV", longopts, NULL)) != -1)
+  while ((optc = getopt_long (argc, argv, "+c:fg:G:lmps:u:hV", longopts, NULL)) != -1)
     {
       switch (optc)
 	{
@@ -839,6 +854,12 @@ su_main (int argc, char **argv, int mode)
 	  shell = optarg;
 	  break;
 
+	case 'u':
+	  if (su_mode != RUNUSER_MODE)
+	    usage (EXIT_FAILURE);
+	  runuser_user = optarg;
+	  break;
+
 	case 'h':
 	  usage(0);
 
@@ -858,8 +879,21 @@ su_main (int argc, char **argv, int mode)
       simulate_login = true;
       ++optind;
     }
-  if (optind < argc)
+
+  /* if not "-u <user>" specified then fallback to classic su(1) */
+  if (!runuser_user && optind < argc)
     new_user = argv[optind++];
+  else {
+      /* runuser -u <command> */
+    new_user = runuser_user;
+    if (shell || fast_startup || command || simulate_login) {
+      errx(EXIT_FAILURE,
+	   _("options --{shell,fast,command,session-command,login} and "
+	     "--user are mutually exclusive."));
+    }
+    if (optind == argc)
+      errx(EXIT_FAILURE, _("COMMAND not specified."));
+  }
 
   if ((num_supp_groups || use_gid) && restricted)
     errx(EXIT_FAILURE, _("only root can specify alternative groups"));
@@ -903,18 +937,23 @@ su_main (int argc, char **argv, int mode)
   if (request_same_session || !command || !pw->pw_uid)
     same_session = 1;
 
-  if (!shell && !change_environment)
-    shell = getenv ("SHELL");
-  if (shell && getuid () != 0 && restricted_shell (pw->pw_shell))
-    {
-      /* The user being su'd to has a nonstandard shell, and so is
-	 probably a uucp account or has restricted access.  Don't
-	 compromise the account by allowing access with a standard
-	 shell.  */
-      warnx (_("using restricted shell %s"), pw->pw_shell);
-      shell = NULL;
-    }
-  shell = xstrdup (shell ? shell : pw->pw_shell);
+  /* initialize shell variable only if "-u <user>" not specified */
+  if (runuser_user) {
+    shell = NULL;
+  } else {
+    if (!shell && !change_environment)
+      shell = getenv ("SHELL");
+    if (shell && getuid () != 0 && restricted_shell (pw->pw_shell))
+      {
+	/* The user being su'd to has a nonstandard shell, and so is
+	   probably a uucp account or has restricted access.  Don't
+	   compromise the account by allowing access with a standard
+	   shell.  */
+	warnx (_("using restricted shell %s"), pw->pw_shell);
+	shell = NULL;
+      }
+    shell = xstrdup (shell ? shell : pw->pw_shell);
+  }
 
   init_groups (pw, groups, num_supp_groups);
 
@@ -933,7 +972,12 @@ su_main (int argc, char **argv, int mode)
   if (simulate_login && chdir (pw->pw_dir) != 0)
     warn (_("warning: cannot change directory to %s"), pw->pw_dir);
 
-  run_shell (shell, command, argv + optind, max (0, argc - optind));
+  if (shell)
+    run_shell (shell, command, argv + optind, max (0, argc - optind));
+  else {
+    execvp(argv[optind], &argv[optind]);
+    err(EXIT_FAILURE, _("executing %s failed"), argv[optind]);
+  }
 }
 
 // vim: sw=2 cinoptions=>4,n-2,{2,^-2,\:2,=2,g0,h2,p5,t0,+2,(0,u0,w1,m1
diff --git a/login-utils/su.1 b/login-utils/su.1
index 59e1731..c82b941 100644
--- a/login-utils/su.1
+++ b/login-utils/su.1
@@ -216,6 +216,7 @@ command specific logindef config file
 global logindef config file
 .PD 1
 .SH "SEE ALSO"
+.BR runuser (8),
 .BR pam (8),
 .BR shells (5),
 .BR login.defs (5)
-- 
1.7.7.6


^ permalink raw reply related	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2012-09-13 10:12 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-09-04 15:18 runuser(1) and su(1) -g/-G Karel Zak
2012-09-04 19:52 ` Pádraig Brady
2012-09-05  8:44   ` Karel Zak
2012-09-05 12:38 ` Dave Reisner
2012-09-05 21:28   ` Dave Reisner
2012-09-07 12:07     ` Karel Zak
2012-09-07 12:39       ` Pádraig Brady
2012-09-07 13:09         ` Adam Sampson
2012-09-13 10:12         ` Karel Zak
2012-09-07 12:47       ` Dave Reisner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).