[augeas-devel] Sudoers lens

Raphaël Pinson raphink at gmail.com
Tue Aug 12 07:59:03 UTC 2008


On Mon, Aug 11, 2008 at 11:31 PM, David Lutterkort <dlutter at redhat.com>wrote:

> On Mon, 2008-08-11 at 19:07 +0200, Raphaël Pinson wrote:
> > I've been trying to have a look at a lens for sudoers. I expected it
> > to be challenging, and so it is. Thankfully, man sudoers is one of the
> > best conffile docs ever.
>
> Very nice .. yeah, sudoers is a pretty complex file format. It might
> help if you cut&paste the grammar rules from the man page into a comment
> at the top of sudoers.aug. That will make it a little clearer what's
> going on - especially if you can explain where in the tree which parts
> of the file go.
>
> > Here is the code I have so far. It has a few major problems:
> > * augparse takes a few seconds to check it
>
> Yeah, the typechecker is pretty slow. From profiling data, most of the
> time is spent in typechecking concatenations - and most of the time for
> that is in computing the intersection of regular languages.
>
> > * it doesn't support "\" to continue a line. This is the biggest
> > issue, and I have no idea how to fix that in augeas.
>
> As long as continuation lines can't happen in the middle of an entry,
> and something must be present on the continued line, it should be
> possible. There's one wrinkle: backslashes get handled twice, once by
> the parser, and once by the regexp engine. Because of that, you need to
> write '\\\\' to get a single backslash into regexps.
>
> For example, /\\\\\n/ matches a backslash followed by a newline. To
> demonstrate handling of continuation lines, I just added a test
> tests/modules/pass_cont_lines.aug to the repo:
>
>        module Pass_cont_line =
>
>        (* Parse a list of words where the list can stretch over multiple
> lines.
>           Mostly there to demonstrate how to deal with continuation lines.
> *)
>
>        let list_elt = [ label "element" . store /[a-z]+/ ]
>
>        let ws_cont = /([ \t]+|[ \t]*\\\\\n[ \t]*)/
>
>        let sep = del ws_cont " "
>         let eol = del /[ \t]*\n/ "\n"
>
>         let list = list_elt . ( sep . list_elt )* . eol
>
>        let exp_tree = { "element" = "a" } { "element" = "b" }
>
>        test list get "a  b\n"      = exp_tree
>        test list get "a  \\\n b\n" = exp_tree
>        test list get "a\\\nb\n"    = exp_tree
>


Thanks for the tip, I'll be trying to add it to the lens.


Following on the spec issues... Here are my tests with sudoers:


 $ sudo tail /etc/sudoers -n 1
rpinson, %gdm localhost, lab64.echo-net.net     = (bb, root) NOPASSWD:
NOEXEC: /bin/test, /bin/test2, EXEC: /bin/toto, (www-data) /bin/titi :
LOCALNET = (gdm) /bin/test3

  $ sudo -l
User rpinson may run the following commands on this host:
    (bb, root) NOEXEC: NOPASSWD: /bin/test
    (bb, root) NOEXEC: NOPASSWD: /bin/test2
    (bb, root) NOPASSWD: /bin/toto
    (www-data) NOPASSWD: /bin/titi
    (gdm) /bin/test3


So it is clear that my representation is wrong. Obviously, sudo lists
settings by command, and Runas_User and Tag_Spec settings are properties of
the command and:
* Runas_User is inherited and overridden along the spec line, and its
default value is "root".
* tags are inherited and overridden along the spec line, and the defaults
are EXEC: PASSWD: SETENV:
* when a tag or Runas_User is changed, it affects all the commands
following, but the other parameters are kept as before.
* The colon ":" sign begins a new host group, and all the Runas_User and
tags are resetted. Only the users are kept.


So... I guess Augeas should describe the file without interpreting too much
the values. Something like :

{ "spec"
    { "user" = "rpinson" }
    { "user" = "%gmd" }
    { "host_group"
        { "host" = "localhost" }
        { "host" = "lab64.echo-net.net" }
        { "command" = "/bin/test"
            { "runas_user" = "bb" }
            { "runas_user" = "root" }
            { "tag" = "NOPASSWD" }
            { "tag" = "NOEXEC" } }
        { "command" = "/bin/test2" }
        { "command" = "/bin/toto"
            { "tag" = "EXEC" } }
        { "command" = "/bin/titi"
            { "runas_user" = "www-data" } } }
    { "host_group"
        { "host" = "LOCALNET" }
        { "command" = "/bin/test3"
            { "runas_user" = "gdm" } } } }


Of course, this representation doesn't show all the informations that sudo
-l would give. Just by reading this, we don't know that NOPASSWD and NOEXEC
apply to /bin/test2 and NOPASSWD applies to /bin/toto and /bin/titi, we're
only describing the file without trying to understand too much of the
meaning of it... This means that someone parsing the file using Augeas will
have to do this interpretation, i.e. parse all the commands within a
host_group and determine the overrides. The danger is that if I do something
like :

set /files/etc/sudoers/spec[last()]/host_group[1]/command[2]/tag =
"NOSETENV"

I might not realize that it will affect /bin/test2, /bin/toto and /bin/titi
all at once. One should be very careful when using such a lens!


Any thoughts are welcome on this!



Raphaël
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://listman.redhat.com/archives/augeas-devel/attachments/20080812/5f2fd958/attachment.htm>


More information about the augeas-devel mailing list