Annotation of src/usr.bin/sudo/sudoers2ldif, Revision 1.2
1.1 millert 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: #
1.2 ! millert 8: # $Sudo: sudoers2ldif,v 1.2.2.1 2007/06/28 14:45:19 millert Exp $
1.1 millert 9: #
10:
11: # BUGS:
12: # Does not yet handle multiple lines with : in them
13: # Does not yet remove quotation marks from options
14: # Does not yet escape + at the beginning of a dn
15: # Does not yet handle line wraps correctly
16: # Does not yet handle multiple roles with same name (needs tiebreaker)
1.2 ! millert 17: # Sudoers entries can have multiple Runas entries that override former ones,
! 18: # with LDAP sudoRunas applies to all commands in a sudoRole
1.1 millert 19:
20: my %UA;
21: my %HA;
22: my %CA;
23: my $base=$ENV{SUDOERS_BASE} or die "$0: Container SUDOERS_BASE undefined\n";
24: my @options=();
25:
26: my $did_defaults=0;
27:
28: # parse sudoers one line at a time
29: while (<>){
30:
31: # remove comment
32: s/#.*//;
33:
34: # line continuation
35: $_.=<> while s/\\\s*$//s;
36:
37: # cleanup newline
38: chomp;
39:
40: # ignore blank lines
41: next if /^\s*$/;
42:
43: if (/^Defaults\s+/i) {
44: my $opt=$';
45: $opt=~s/\s+$//; # remove trailing whitespace
46: push @options,$opt;
47: } elsif (/^(\S+)\s+(.+)=\s*(.*)/) {
48:
49: # Aliases or Definitions
50: my ($p1,$p2,$p3)=($1,$2,$3);
51: $p2=~s/\s+$//; # remove trailing whitespace
52: $p3=~s/\s+$//; # remove trailing whitespace
53:
54: if ($p1 eq "User_Alias") {
55: $UA{$p2}=$p3;
56: } elsif ($p1 eq "Host_Alias") {
57: $HA{$p2}=$p3;
58: } elsif ($p1 eq "Cmnd_Alias") {
59: $CA{$p2}=$p3;
60: } else {
61: if (!$did_defaults++){
62: # do this once
63: print "dn: cn=defaults,$base\n";
64: print "objectClass: top\n";
65: print "objectClass: sudoRole\n";
66: print "cn: defaults\n";
67: print "description: Default sudoOption's go here\n";
68: print "sudoOption: $_\n" foreach @options;
69: print "\n";
70: }
71: # Definition
72: my @users=split /\s*,\s*/,$p1;
73: my @hosts=split /\s*,\s*/,$p2;
74: my @cmds= split /\s*,\s*/,$p3;
75: @options=();
76: print "dn: cn=$users[0],$base\n";
77: print "objectClass: top\n";
78: print "objectClass: sudoRole\n";
79: print "cn: $users[0]\n";
80: # will clobber options
81: print "sudoUser: $_\n" foreach expand(\%UA,@users);
82: print "sudoHost: $_\n" foreach expand(\%HA,@hosts);
1.2 ! millert 83: my $runas = undef;
! 84: foreach (@cmds) {
! 85: if (s/^\(([^\)]+)\)\s*//) {
! 86: print "sudoRunas: $_\n" foreach expand(\%UA, split(/,\s*/, $1));
! 87: }
! 88: }
1.1 millert 89: print "sudoCommand: $_\n" foreach expand(\%CA,@cmds);
90: print "sudoOption: $_\n" foreach @options;
91: print "\n";
92: }
93:
94: } else {
95: print "parse error: $_\n";
96: }
97:
98: }
99:
100: #
101: # recursively expand hash elements
102: sub expand{
103: my $ref=shift;
104: my @a=();
105:
106: # preen the line a little
107: foreach (@_){
108: # if NOPASSWD: directive found, mark entire entry as not requiring
109: s/NOPASSWD:\s*// && push @options,"!authenticate";
110: s/PASSWD:\s*// && push @options,"authenticate";
111: s/NOEXEC:\s*// && push @options,"noexec";
112: s/EXEC:\s*// && push @options,"!noexec";
1.2 ! millert 113: s/SETENV:\s*// && push @options,"setenv";
! 114: s/NOSETENV:\s*// && push @options,"!setenv";
1.1 millert 115: s/\w+://; # silently remove other directives
116: s/\s+$//; # right trim
117: }
118:
119: # do the expanding
120: push @a,$ref->{$_} ? expand($ref,split /\s*,\s*/,$ref->{$_}):$_ foreach @_;
121: @a;
122: }
123:
124: