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