summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSumit Bose <sbose@nb.localdomain>2008-09-17 20:43:35 +0200
committerSumit Bose <sbose@nb.localdomain>2008-09-17 20:43:35 +0200
commit575f23f9ca93b302cb487c037edcbb8bf7554437 (patch)
tree1a83800c45546e2a5ee660d92710cfd9d883c884
downloadipa_policy-575f23f9ca93b302cb487c037edcbb8bf7554437.tar.gz
ipa_policy-575f23f9ca93b302cb487c037edcbb8bf7554437.tar.xz
ipa_policy-575f23f9ca93b302cb487c037edcbb8bf7554437.zip
Initial Import
-rw-r--r--sudoers2xml214
1 files changed, 214 insertions, 0 deletions
diff --git a/sudoers2xml b/sudoers2xml
new file mode 100644
index 0000000..4ce9b18
--- /dev/null
+++ b/sudoers2xml
@@ -0,0 +1,214 @@
+#!/usr/bin/env perl
+use strict;
+use feature 'state';
+use Data::Dumper;
+#
+# Converts a sudoers file to LDIF format in prepration for loading into
+# the LDAP server.
+#
+# $Sudo: sudoers2ldif,v 1.2.2.1 2007/06/28 14:45:19 millert Exp $
+#
+
+# BUGS:
+# Does not yet handle multiple lines with : in them
+# Does not yet remove quotation marks from options
+# Does not yet escape + at the beginning of a dn
+# Does not yet handle line wraps correctly
+# Does not yet handle multiple roles with same name (needs tiebreaker)
+# Sudoers entries can have multiple Runas entries that override former ones,
+# with LDAP sudoRunas applies to all commands in a sudoRole
+
+my %UA;
+my %HA;
+my %CA;
+my %RA;
+##my $base=$ENV{SUDOERS_BASE} or die "$0: Container SUDOERS_BASE undefined\n";
+my @options=();
+
+my %user_group_namespaces=();
+$user_group_namespaces{'netgroup'}='xmlns="http://freeipa.org/xml/rng/netgroup/1.0"';
+$user_group_namespaces{'posixGroup'}='xmlns="http://freeipa.org/xml/rng/posixGroup/1.0"';
+$user_group_namespaces{'user'}='xmlns="http://freeipa.org/xml/rng/user/1.0"';
+my %user_group_attributename=();
+$user_group_attributename{'netgroup'}='groupnames';
+$user_group_attributename{'posixGroup'}='gids';
+$user_group_attributename{'user'}='uids';
+
+my $did_defaults=0;
+
+print '<?xml version="1.0" encoding="UTF-8"?>'."\n";
+print '<ipa xmlns="http://freeipa.org/xml/rng/ipa/1.0">'."\n";
+
+# parse sudoers one line at a time
+while (<>){
+
+ # remove comment
+ s/#.*//;
+
+ # line continuation
+ $_.=<> while s/\\\s*$//s;
+
+ # cleanup newline
+ chomp;
+
+ # ignore blank lines
+ next if /^\s*$/;
+
+ if (/^Defaults\s+/i) {
+ my $opt=$';
+ $opt=~s/\s+$//; # remove trailing whitespace
+ push @options,$opt;
+ } elsif (/^Defaults[:@>]/i) {
+ #ignore
+ my $opt=$';
+ } elsif (/^(\S+)\s+(.+)=\s*(.*)/) {
+
+ # Aliases or Definitions
+ my ($p1,$p2,$p3)=($1,$2,$3);
+ $p2=~s/\s+$//; # remove trailing whitespace
+ $p3=~s/\s+$//; # remove trailing whitespace
+
+ if ($p1 eq "User_Alias") {
+ $UA{$p2}=$p3;
+ } elsif ($p1 eq "Host_Alias") {
+ $HA{$p2}=$p3;
+ } elsif ($p1 eq "Cmnd_Alias") {
+ $CA{$p2}=$p3;
+ } elsif ($p1 eq "Runas_Alias") {
+ $RA{$p2}=$p3;
+ } else {
+ if (!$did_defaults++){
+ # do this once
+ ##print "dn: cn=defaults,$base\n";
+ ##print "objectClass: top\n";
+ ##print "objectClass: sudoRole\n";
+ ##print "cn: defaults\n";
+ ##print "description: Default sudoOption's go here\n";
+ ##print "sudoOption: $_\n" foreach @options;
+ print '<sudoOptions xmlns="http://freeipa.org/xml/rng/sudo/sudoOptions/1.0" ';
+ #print "$_ " foreach @options;
+ foreach ( split /,/, (join ',', @options) ) {
+ $_ =~ s/=(.*)/=\"$1\"/;
+ print "$_ ";
+ }
+ print "/>\n";
+ print "\n";
+ }
+ # Definition
+ my @users=split /\s*,\s*/,$p1;
+ my @hosts=split /\s*,\s*/,$p2;
+ $p3 =~ s/\\,/\\#/g;
+ my @cmds= split /\s*,\s*/,$p3;
+ s/\\#/,/g foreach @cmds;
+ @options=();
+ foreach my $user (expand(\%UA, @users)) {
+ my $type="user";
+ $type="posixGroup" if $user =~ s/^%//;
+ $type="netgroup" if $user =~ s/^\+//;
+ print "<$type $user_group_namespaces{$type} $user_group_attributename{$type}=\"$user\">\n";
+ tl(1);
+ # only "global" user options here!!!
+ #if (@options) {
+ # print tl() . '<sudoOptions xmlns="http://freeipa.org/xml/rng/sudo/sudoOptions/1.0"';
+ # print "$_ " foreach @options;
+ # print "/>\n";
+ #}
+ print tl() . '<sudoers xmlns="http://freeipa.org/xml/rng/sudo/sudoers/1.0">'."\n";
+ tl(1);
+#print Dumper(%CA, @cmds);
+ my @mycmds=@cmds;
+ #foreach my $command (expand(\%CA,@cmds)) {
+ foreach my $command (@mycmds) {
+ my $runas='';
+ if ( $command =~ s/^\(([^\)]+)\)\s*//) {
+ $runas .= "<runas>$_</runas>" foreach expand(\%RA, split(/,\s*/, $1));
+ }
+ foreach (expand(\%CA,$command)) {
+ my $tag='';
+ if (@options) {
+ $tag = '<tag>';
+ $tag .= "$_ " foreach @options;
+ $tag =~ s/ $/<\/tag>/;
+ }
+ print tl() . "<command><path>$_</path>$tag$runas</command>\n"
+ }
+ @options=();
+ }
+ tl(-1);
+ print tl() . "</sudoers>\n";
+ tl(-1);
+ ##print "dn: cn=$users[0],$base\n";
+ ##print "objectClass: top\n";
+ ##print "objectClass: sudoRole\n";
+ ##print "cn: $users[0]\n";
+ # will clobber options
+ ##print "sudoUser: $_\n" foreach expand(\%UA,@users);
+ ##print "sudoHost: $_\n" foreach expand(\%HA,@hosts);
+ ##my $runas = undef;
+ ##foreach (@cmds) {
+ ##if (s/^\(([^\)]+)\)\s*//) {
+ ##print "sudoRunas: $_\n" foreach expand(\%UA, split(/,\s*/, $1));
+ ##}
+ ##}
+ ##print "sudoCommand: $_\n" foreach expand(\%CA,@cmds);
+ ##print "sudoOption: $_\n" foreach @options;
+ print "</$type>\n";
+ print "\n";
+ }
+ }
+
+ } else {
+ print "parse error: $_\n";
+ }
+
+}
+print '</ipa>'."\n";
+
+#
+# recursively expand hash elements
+sub expand{
+ my $ref=shift;
+ my @a=();
+
+ # preen the line a little
+ foreach (@_){
+ # if NOPASSWD: directive found, mark entire entry as not requiring
+ s/NOPASSWD:\s*// && push @options,'NOPASSWD';
+ s/PASSWD:\s*// && push @options,'PASSWD';
+ s/NOEXEC:\s*// && push @options,"NOEXEC";
+ s/EXEC:\s*// && push @options,"EXEC";
+ s/SETENV:\s*// && push @options,"SETENV";
+ s/NOSETENV:\s*// && push @options,"NOSETENV";
+ s/\w+://; # silently remove other directives
+ s/\s+$//; # right trim
+ }
+
+ # do the expanding
+ #push @a,$ref->{$_} ? expand($ref,split /\s*,\s*/,$ref->{$_}):$_ foreach @_;
+ foreach (@_) {
+ if ( s/^!// ) {
+ my @dummy = $ref->{$_} ? expand($ref,split /\s*,\s*/,$ref->{$_}):$_;
+ s/^/!/ foreach @dummy;
+ push @a, @dummy;
+ } else {
+ push @a, $ref->{$_} ? expand($ref,split /\s*,\s*/,$ref->{$_}):$_;
+ }
+ }
+ @a;
+}
+
+sub tl {
+ my $d = @_?$_[0]:0;
+
+ state $tablevel=0;
+
+#print $d."\n";
+#print "t=" . $tablevel."\n";
+
+ $tablevel += $d;
+#print "t2=" . $tablevel."\n";
+ $tablevel=0 if ( $tablevel < 0 );
+#print "t3=" . $tablevel."\n";
+
+ return "\t" x $tablevel;
+}