[sudo-workers] Fixes to sudoers2ldif

Aaron Peschel apeschel at zendesk.com
Tue Feb 2 12:21:10 MST 2016


* Fixes documented bug with duplicate role names.
* Parses assignments preceded by "Default" tag to eliminate whitespace.
  * (Not documented in script, but documented in this mail list.)
* Replaces leading tabs with spaces, for consistency.

--- sudo-1.8.15/plugins/sudoers/sudoers2ldif.orig       2015-10-31
16:34:59.000000000 -0700
+++ sudo-1.8.15/plugins/sudoers/sudoers2ldif    2016-02-02
11:12:33.000000000 -0800
@@ -27,11 +27,10 @@ use strict;
 #   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)
 #
 # CAVEATS:
 #   Sudoers entries can have multiple RunAs entries that override former ones,
-#      with LDAP sudoRunAs{Group,User} applies to all commands in a sudoRole
+#       with LDAP sudoRunAs{Group,User} applies to all commands in a sudoRole

 my %RA;
 my %UA;
@@ -42,6 +41,8 @@ my @options=();

 my $did_defaults=0;
 my $order = 0;
+my %seen_users;
+my $assignment= qr/^(\S+)\s+(.+)=\s*(.*)/;

 # parse sudoers one line at a time
 while (<>){
@@ -61,11 +62,14 @@ while (<>){
   if (/^Defaults\s+/i) {
     my $opt=$';
     $opt=~s/\s+$//; # remove trailing whitespace
-    push @options,$opt;
-  } elsif (/^(\S+)\s+([^=]+)=\s*(.*)/) {
+    if (/$assignment/) {
+        $opt = join('', parse_assignment($opt));
+    }
+    push @options, $opt;
+  } elsif (/$assignment/) {

     # Aliases or Definitions
-    my ($p1,$p2,$p3)=($1,$2,$3);
+    my ($p1,$p2,$p3)=parse_assignment($');
     $p2=~s/\s+$//; # remove trailing whitespace
     $p3=~s/\s+$//; # remove trailing whitespace

@@ -91,26 +95,33 @@ while (<>){
       }
       # Definition
       my @users=split /\s*,\s*/,$p1;
+      my $username = @users[0];
+      if ($seen_users{$username}) {
+          $seen_users{$username} += 1;
+          $username = sprintf("%s_%s", $username, $seen_users{$username});
+      } else {
+          $seen_users{$username} = 1;
+      }
       my @hosts=split /\s*,\s*/,$p2;
       my @cmds= split /\s*,\s*/,$p3;
       @options=();
-      print "dn: cn=$users[0],$base\n";
+      print "dn: cn=$username,$base\n";
       print "objectClass: top\n";
       print "objectClass: sudoRole\n";
-      print "cn: $users[0]\n";
+      print "cn: $username\n";
       # will clobber options
       print "sudoUser: $_\n"   foreach expand(\%UA, at users);
       print "sudoHost: $_\n"   foreach expand(\%HA, at hosts);
       foreach (@cmds) {
-       if (s/^\(([^\)]+)\)\s*//) {
-         my @runas = split(/:\s*/, $1);
-         if (defined($runas[0])) {
-           print "sudoRunAsUser: $_\n" foreach expand(\%RA,
split(/,\s*/, $runas[0]));
-         }
-         if (defined($runas[1])) {
-           print "sudoRunAsGroup: $_\n" foreach expand(\%RA,
split(/,\s*/, $runas[1]));
-         }
-       }
+        if (s/^\(([^\)]+)\)\s*//) {
+          my @runas = split(/:\s*/, $1);
+          if (defined($runas[0])) {
+            print "sudoRunAsUser: $_\n" foreach expand(\%RA,
split(/,\s*/, $runas[0]));
+          }
+          if (defined($runas[1])) {
+            print "sudoRunAsGroup: $_\n" foreach expand(\%RA,
split(/,\s*/, $runas[1]));
+          }
+        }
       }
       print "sudoCommand: $_\n" foreach expand(\%CA, at cmds);
       print "sudoOption: $_\n" foreach @options;
@@ -124,6 +135,12 @@ while (<>){

 }

+sub parse_assignment{
+    my $line=shift;
+    $line=~/$assignment/;
+    return ($1,$2,$3);
+}
+
 #
 # recursively expand hash elements
 sub expand{
-------------- next part --------------
A non-text attachment was scrubbed...
Name: sudoers2ldif.patch
Type: application/octet-stream
Size: 3247 bytes
Desc: not available
URL: <https://www.sudo.ws/pipermail/sudo-workers/attachments/20160202/3dc02e82/attachment.obj>


More information about the sudo-workers mailing list