Annotation of embedaddon/sudo/plugins/sudoers/sudoers2ldif, revision 1.1.1.1
1.1 misho 1: #!/usr/bin/env perl
2: use strict;
3:
4: #
5: # Converts a sudoers file to LDIF format in prepration for loading into
6: # the LDAP server.
7: #
8:
9: # BUGS:
10: # Does not yet handle multiple lines with : in them
11: # Does not yet remove quotation marks from options
12: # Does not yet escape + at the beginning of a dn
13: # Does not yet handle line wraps correctly
14: # Does not yet handle multiple roles with same name (needs tiebreaker)
15: #
16: # CAVEATS:
17: # Sudoers entries can have multiple RunAs entries that override former ones,
18: # with LDAP sudoRunAs{Group,User} applies to all commands in a sudoRole
19:
20: my %RA;
21: my %UA;
22: my %HA;
23: my %CA;
24: my $base=$ENV{SUDOERS_BASE} or die "$0: Container SUDOERS_BASE undefined\n";
25: my @options=();
26:
27: my $did_defaults=0;
28: my $order = 0;
29:
30: # parse sudoers one line at a time
31: while (<>){
32:
33: # remove comment
34: s/#.*//;
35:
36: # line continuation
37: $_.=<> while s/\\\s*$//s;
38:
39: # cleanup newline
40: chomp;
41:
42: # ignore blank lines
43: next if /^\s*$/;
44:
45: if (/^Defaults\s+/i) {
46: my $opt=$';
47: $opt=~s/\s+$//; # remove trailing whitespace
48: push @options,$opt;
49: } elsif (/^(\S+)\s+(.+)=\s*(.*)/) {
50:
51: # Aliases or Definitions
52: my ($p1,$p2,$p3)=($1,$2,$3);
53: $p2=~s/\s+$//; # remove trailing whitespace
54: $p3=~s/\s+$//; # remove trailing whitespace
55:
56: if ($p1 eq "User_Alias") {
57: $UA{$p2}=$p3;
58: } elsif ($p1 eq "Runas_Alias") {
59: $RA{$p2}=$p3;
60: } elsif ($p1 eq "Host_Alias") {
61: $HA{$p2}=$p3;
62: } elsif ($p1 eq "Cmnd_Alias") {
63: $CA{$p2}=$p3;
64: } else {
65: if (!$did_defaults++){
66: # do this once
67: print "dn: cn=defaults,$base\n";
68: print "objectClass: top\n";
69: print "objectClass: sudoRole\n";
70: print "cn: defaults\n";
71: print "description: Default sudoOption's go here\n";
72: print "sudoOption: $_\n" foreach @options;
73: printf "sudoOrder: %d\n", ++$order;
74: print "\n";
75: }
76: # Definition
77: my @users=split /\s*,\s*/,$p1;
78: my @hosts=split /\s*,\s*/,$p2;
79: my @cmds= split /\s*,\s*/,$p3;
80: @options=();
81: print "dn: cn=$users[0],$base\n";
82: print "objectClass: top\n";
83: print "objectClass: sudoRole\n";
84: print "cn: $users[0]\n";
85: # will clobber options
86: print "sudoUser: $_\n" foreach expand(\%UA,@users);
87: print "sudoHost: $_\n" foreach expand(\%HA,@hosts);
88: foreach (@cmds) {
89: if (s/^\(([^\)]+)\)\s*//) {
90: my @runas = split(/:\s*/, $1);
91: if (defined($runas[0])) {
92: print "sudoRunAsUser: $_\n" foreach expand(\%RA, split(/,\s*/, $runas[0]));
93: }
94: if (defined($runas[1])) {
95: print "sudoRunAsGroup: $_\n" foreach expand(\%RA, split(/,\s*/, $runas[1]));
96: }
97: }
98: }
99: print "sudoCommand: $_\n" foreach expand(\%CA,@cmds);
100: print "sudoOption: $_\n" foreach @options;
101: printf "sudoOrder: %d\n", ++$order;
102: print "\n";
103: }
104:
105: } else {
106: print "parse error: $_\n";
107: }
108:
109: }
110:
111: #
112: # recursively expand hash elements
113: sub expand{
114: my $ref=shift;
115: my @a=();
116:
117: # preen the line a little
118: foreach (@_){
119: # if NOPASSWD: directive found, mark entire entry as not requiring
120: s/NOPASSWD:\s*// && push @options,"!authenticate";
121: s/PASSWD:\s*// && push @options,"authenticate";
122: s/NOEXEC:\s*// && push @options,"noexec";
123: s/EXEC:\s*// && push @options,"!noexec";
124: s/SETENV:\s*// && push @options,"setenv";
125: s/NOSETENV:\s*// && push @options,"!setenv";
126: s/LOG_INPUT:\s*// && push @options,"log_input";
127: s/NOLOG_INPUT:\s*// && push @options,"!log_input";
128: s/LOG_OUTPUT:\s*// && push @options,"log_output";
129: s/NOLOG_OUTPUT:\s*// && push @options,"!log_output";
130: s/\w+://; # silently remove other directives
131: s/\s+$//; # right trim
132: }
133:
134: # do the expanding
135: push @a,$ref->{$_} ? expand($ref,split /\s*,\s*/,$ref->{$_}):$_ foreach @_;
136: @a;
137: }
138:
139:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>