<div dir="ltr"><br><br><div class="gmail_quote">On Mon, Aug 11, 2008 at 11:31 PM, David Lutterkort <span dir="ltr"><<a href="mailto:dlutter@redhat.com">dlutter@redhat.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<div class="Ih2E3d">On Mon, 2008-08-11 at 19:07 +0200, Raphaël Pinson wrote:<br>
> I've been trying to have a look at a lens for sudoers. I expected it<br>
> to be challenging, and so it is. Thankfully, man sudoers is one of the<br>
> best conffile docs ever.<br>
<br>
</div>Very nice .. yeah, sudoers is a pretty complex file format. It might<br>
help if you cut&paste the grammar rules from the man page into a comment<br>
at the top of sudoers.aug. That will make it a little clearer what's<br>
going on - especially if you can explain where in the tree which parts<br>
of the file go.<br>
<div class="Ih2E3d"><br>
> Here is the code I have so far. It has a few major problems:<br>
> * augparse takes a few seconds to check it<br>
<br>
</div>Yeah, the typechecker is pretty slow. From profiling data, most of the<br>
time is spent in typechecking concatenations - and most of the time for<br>
that is in computing the intersection of regular languages.<br>
<div class="Ih2E3d"><br>
> * it doesn't support "\" to continue a line. This is the biggest<br>
> issue, and I have no idea how to fix that in augeas.<br>
<br>
</div>As long as continuation lines can't happen in the middle of an entry,<br>
and something must be present on the continued line, it should be<br>
possible. There's one wrinkle: backslashes get handled twice, once by<br>
the parser, and once by the regexp engine. Because of that, you need to<br>
write '\\\\' to get a single backslash into regexps.<br>
<br>
For example, /\\\\\n/ matches a backslash followed by a newline. To<br>
demonstrate handling of continuation lines, I just added a test<br>
tests/modules/pass_cont_lines.aug to the repo:<br>
<br>
        module Pass_cont_line =<br>
<br>
        (* Parse a list of words where the list can stretch over multiple lines.<br>
           Mostly there to demonstrate how to deal with continuation lines. *)<br>
<br>
        let list_elt = [ label "element" . store /[a-z]+/ ]<br>
<br>
        let ws_cont = /([ \t]+|[ \t]*\\\\\n[ \t]*)/<br>
<br>
        let sep = del ws_cont " "<br>
<div class="Ih2E3d">        let eol = del /[ \t]*\n/ "\n"<br>
<br>
</div>        let list = list_elt . ( sep . list_elt )* . eol<br>
<br>
        let exp_tree = { "element" = "a" } { "element" = "b" }<br>
<br>
        test list get "a  b\n"      = exp_tree<br>
        test list get "a  \\\n b\n" = exp_tree<br>
        test list get "a\\\nb\n"    = exp_tree<br>
<font color="#888888"></font></blockquote><div><br><br>Thanks for the tip, I'll be trying to add it to the lens.<br><br><br>Following on the spec issues... Here are my tests with sudoers:<br><br><br> $ sudo tail /etc/sudoers -n 1<br>
rpinson, %gdm localhost, <a href="http://lab64.echo-net.net">lab64.echo-net.net</a>     = (bb, root) NOPASSWD: NOEXEC: /bin/test, /bin/test2, EXEC: /bin/toto, (www-data) /bin/titi : LOCALNET = (gdm) /bin/test3<br><br>  $ sudo -l<br>
User rpinson may run the following commands on this host:<br>    (bb, root) NOEXEC: NOPASSWD: /bin/test<br>    (bb, root) NOEXEC: NOPASSWD: /bin/test2<br>    (bb, root) NOPASSWD: /bin/toto<br>    (www-data) NOPASSWD: /bin/titi<br>
    (gdm) /bin/test3<br><br><br></div></div>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:<br>* Runas_User is inherited and overridden along the spec line, and its default value is "root".<br>
* tags are inherited and overridden along the spec line, and the defaults are EXEC: PASSWD: SETENV:<br>* when a tag or Runas_User is changed, it affects all the commands following, but the other parameters are kept as before.<br>
* The colon ":" sign begins a new host group, and all the Runas_User and tags are resetted. Only the users are kept.<br><br><br>So... I guess Augeas should describe the file without interpreting too much the values. Something like :<br>
<br>{ "spec"<br>    { "user" = "rpinson" }<br>    { "user" = "%gmd" }<br>    { "host_group"<br>        { "host" = "localhost" }<br>        { "host" = "<a href="http://lab64.echo-net.net">lab64.echo-net.net</a>" }<br>
        { "command" = "/bin/test"<br>            { "runas_user" = "bb" }<br>            { "runas_user" = "root" }<br>            { "tag" = "NOPASSWD" }<br>
            { "tag" = "NOEXEC" } }<br>        { "command" = "/bin/test2" }<br>        { "command" = "/bin/toto"<br>            { "tag" = "EXEC" } }<br>
        { "command" = "/bin/titi"<br>            { "runas_user" = "www-data" } } }<br>    { "host_group"<br>        { "host" = "LOCALNET" }<br>        { "command" = "/bin/test3"<br>
            { "runas_user" = "gdm" } } } }<br><br><br>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 :<br>
<br>set /files/etc/sudoers/spec[last()]/host_group[1]/command[2]/tag = "NOSETENV"<br><br>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!<br>
<br><br>Any thoughts are welcome on this!<br><br><br><br>Raphaël<br><br><br><br><br><br></div>