[sudo-workers] [PATCH] sudo/plugins/suoders/sudoers2ldif: Support #include and #includedir recursively
Natale Vinto
nvinto at redhat.com
Mon Oct 16 08:11:03 MDT 2017
Hello,
as said sometimes ago in the mailing list, I was wondering on how
better extend sudoers2ldif script, starting from supporting #include
and #includedir.
The idea is to look recursively for any #include and #includedir
directive in file parsed, and then parse it accordingly maintaining
the same behavior as now.
Thanks to dakkar [1], I could implement it through a callbacks
mechanism as shown in the proposed patch below.
What do you think?
Thanks,
Natale
[1] http://search.cpan.org/~dakkar/
diff -pru a/sudo/plugins/sudoers/sudoers2ldif
b/sudo/plugins/sudoers/sudoers2ldif
--- sudoers2ldif2 2017-10-11 12:10:13.603919900 +0200
+++ sudoers2ldif 2017-10-16 16:07:05.540025799 +0200
@@ -46,27 +46,31 @@ my $did_defaults=0;
my $order = 0;
my %seen_users;
-# parse sudoers one line at a time
-while (<>){
- # remove comment
- s/#.*//;
- # line continuation
- $_.=<> while s/\\\s*$//s;
+# Parsing is now through callbacks reading @ARGV or STDIN
+sub parse_sudoers_line{
+
+ my $line = shift;
+ # remove comment
+ $line =~ s/#.*//;
+
+
# cleanup newline
- chomp;
+ chomp $line;
+
+
+ return if $line =~ /^\s*$/;
- # ignore blank lines
- next if /^\s*$/;
- if (s/^Defaults\s+//) {
- s/\s+$//; # remove trailing whitespace
+ if ($line =~ s/^Defaults\s+//) {
+
+ $line =~ s/\s+$//; # remove trailing whitespace
# remove spaces between '!', '=', '+=' and '-='
- s/^(\S+)\s*([\+-]?=)\s*(\S.*)$/$1$2$3/ unless s/^!\s*(\S.*)$/!$1/;
- push @options, $_;
- } elsif (/^(\S+)\s+([^=]+)=\s*(.*)/) {
+ $line =~ s/^(\S+)\s*([\+-]?=)\s*(\S.*)$/$1$2$3/ unless $line =~
s/^!\s*(\S.*)$/!$1/;
+ push @options, $line;
+ } elsif ($line =~ /^(\S+)\s+([^=]+)=\s*(.*)/) {
# Aliases or Definitions
my ($p1,$p2,$p3)=($1,$2,$3);
$p2=~s/\s+$//; # remove trailing whitespace
@@ -132,7 +136,7 @@ while (<>){
print "\n";
}
} else {
- print "parse error: $_\n";
+ print STDERR "parse error: $line\n";
}
}
@@ -172,3 +176,70 @@ sub expand{
push @a,$ref->{$_} ? expand($ref,split /\s*,\s*/,$ref->{$_}):$_ foreach @_;
@a;
}
+
+
+# Recursively look for #include and #includedir directives
+sub scan_sudoers_fh {
+ my ($filehandle,$callback) = @_;
+
+ while (<$filehandle>) {
+ if (/^#include\s+(.+?)\s*$/){
+ my $inc = $1;
+ scan_sudoers_filename($inc,$callback);
+ }
+ elsif (/^#includedir\s+(.+?)\s*$/){
+ my $incdir = $1;
+ scan_sudoers_dirname($incdir,$callback);
+ }
+ else {
+ $callback->($_);
+ }
+ }
+}
+
+# Read from #include file
+sub scan_sudoers_filename {
+ my ($filename,$callback) = @_;
+ open my $fh, '<', $filename;
+ scan_sudoers_fh($fh,$callback);
+}
+
+# Read from #includedir directory
+sub scan_sudoers_dirname {
+ my ($dirname,$callback) = @_;
+ # qui puoi filtrare via i file che sudo ignorerebbe
+ scan_sudoers_filename($_,$callback)
+ for glob("$dirname/*");
+}
+
+# Returns a sub that reads lines until continuations,
+# then it invokes the callback that parses
+sub make_continuation_handler {
+ my ($callback) = @_;
+
+ my $buffer='';
+ return sub {
+ my ($line) = @_;
+
+ if ($line =~ s/\\\s*$//) {
+ # line continuation
+ $buffer .= $line;
+ }
+ else {
+ # parse all
+ $callback->($buffer.$line);
+ # empty buffer
+ $buffer='';
+ }
+
+ };
+}
+
+
+my $parser_cb = make_continuation_handler(\&parse_sudoers_line);
+if (@ARGV) {
+ scan_sudoers_filename($_,$parser_cb) for @ARGV;
+}
+else {
+ scan_sudoers_fh(\*STDIN,$parser_cb);
+}
More information about the sudo-workers
mailing list