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>