repair_obsolete_profiles 6.93 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
#!/usr/bin/perl -wi
# automatically repair apparmor profiles that have had their supporting
# infrastructure refactored out from underneath them

# note -i in shebang line -- this program will modify in-place
# profiles or #include chunks specified on the command line without
# backups. Please make some yourself and inspect the changes made by
# this tool to ensure they look correct.

# It'll try to fix up #include files (supplied by SUSE/Immunix) that have
# moved; it will also inspect many #include files that exist solely
# for netdomain rule separation, and either remove the #include line
# from profiles/includes or suck in the contents of the specific file,
# depending if there was any non-netdomain content.

# If you haven't modified any of the files listed in the @useless array,
# you probably don't have to concern yourself with the complicated part
# of the previous paragraph. If you did modify any of those files, this
# tool will inspect those for changes, try to update any lines in those
# files for correctness, and insert those lines directly into the
# referencing profiles.

our %count_cache;

# count the number of 'interesting' lines in the file
sub numlines ($) {
  my $name = $_[0];

  return $count_cache{$name} if $count_cache{$name};

  open FH, $name or return 1; # can't tell -> not empty

  my $linecount=0;
  while(<FH>) {
    if (m/^[^#]*#include/) {
      $linecount++;
    } elsif (m/^\s*#/) {
      # just a comment, skip it
    } elsif (m/\s*tcp_/) {
      # netdomain rules are unenforced, skip it
    } elsif (m/\s*udp_/) {
      # netdomain rules are unenforced, skip it
    } elsif (m/\S+/) {
      $linecount++;
    }
  }
  close FH;

  $count_cache{$name} = $linecount;

  return $linecount;
}

# given a single line from a profile, perform some search/replace
# operations to reflect new locations for old files.
#
# change #include lines that reference files in the @useless array:
# don't print the #include any more, and either suck in the contents of
# the referenced file (calling itself recursively to fix up _those_
# files) or just leave well enough alone, if the file had no
# 'interesting' lines as defined above.

%transforms = (
  # renamed around SuSE 9.3
  "abstractions/kde3"            => "abstractions/kde",
  "abstractions/user-GTK"        => "abstractions/gnome",
  "abstractions/user-Xauthority" => "abstractions/X",
  
  # user-custom -> program-chunks around SHASS 1.1, but these changed dirs
  "user-custom/fonts"           => "abstractions/fonts",
  "user-custom/kde3"            => "abstractions/kde",
  "user-custom/user-GTK"        => "abstractions/gnome",
  "user-custom/user-mail"       => "abstractions/user-mail",
  "user-custom/user-manpages"   => "abstractions/user-manpages",
  "user-custom/user-Xauthority" => "abstractions/X",
  "user-custom/user-tmp"        => "abstractions/user-tmp",
  
  # try to forget the -files
  "program-chunks/base-files"          => "abstractions/base",
  "program-chunks/nameservice-files"   => "abstractions/nameservice",
  "immunix-standard/base-files"        => "abstractions/base",
  "immunix-standard/nameservice-files" => "abstractions/nameservice",
  
  # immunix-standard -> program-chunks
  "immunix-standard/postfix-bounce"     => "program-chunks/postfix-bounce",
  "immunix-standard/postfix-cleanup"    => "program-chunks/postfix-cleanup",
  "immunix-standard/postfix-common"     => "program-chunks/postfix-common",
  "immunix-standard/postfix-flush"      => "program-chunks/postfix-flush",
  "immunix-standard/postfix-local"      => "program-chunks/postfix-local",
  "immunix-standard/postfix-master"     => "program-chunks/postfix-master",
  "immunix-standard/postfix-nqmgr"      => "program-chunks/postfix-nqmgr",
  "immunix-standard/postfix-pickup"     => "program-chunks/postfix-pickup",
  "immunix-standard/postfix-proxymap"   => "program-chunks/postfix-proxymap",
  "immunix-standard/postfix-qmgr"       => "program-chunks/postfix-qmgr",
  "immunix-standard/postfix-showq"      => "program-chunks/postfix-showq",
  "immunix-standard/postfix-smtp"       => "program-chunks/postfix-smtp",
  "immunix-standard/postfix-smtpd"      => "program-chunks/postfix-smtpd",
  "immunix-standard/postfix-trivial-rewrite" => "program-chunks/postfix-trivial-rewrite",
  "immunix-standard/apache-default-uri" => "program-chunks/apache-default-uri",
  "immunix-standard/at"                 => "program-chunks/at",
);

# chunks that immunix tools never populated -- lets remove the ones that
# don't have any useful information
my @useless = qw{
  program-chunks/base-nd
  program-chunks/portmap-nd
  program-chunks/postfix-local-nd
  program-chunks/postfix-master-nd
  program-chunks/postfix-proxymap-nd
  program-chunks/postfix-smtpd-nd
  program-chunks/postfix-smtp-nd
  user-custom/base-nd
  user-custom/portmap-nd
  user-custom/postfix-local-nd
  user-custom/postfix-master-nd
  user-custom/postfix-proxymap-nd
  user-custom/postfix-smtpd-nd
  user-custom/postfix-smtp-nd
  immunix-standard/base-nd
  immunix-standard/portmap-nd
  immunix-standard/postfix-local-nd
  immunix-standard/postfix-master-nd
  immunix-standard/postfix-proxymap-nd
  immunix-standard/postfix-smtpd-nd
  immunix-standard/postfix-smtp-nd
  program-chunks/at
  program-chunks/fam
  program-chunks/httpd
  program-chunks/identd
  program-chunks/imapd
  program-chunks/ipop2d
  program-chunks/ipop3d
  program-chunks/lpd
  program-chunks/mutt
  program-chunks/named
  program-chunks/nmbd
  program-chunks/ntalkd
  program-chunks/ntpd
  program-chunks/postgres
  program-chunks/rpc.lockd
  program-chunks/rpc.nfsd
  program-chunks/rpc.statd
  program-chunks/samba
  program-chunks/sendmail.sendmail
  program-chunks/shells
  program-chunks/slocate
  program-chunks/snmpd
  program-chunks/spamc
  program-chunks/sshd
  program-chunks/swat
  program-chunks/syslogd
  program-chunks/talk
  program-chunks/xfs
};

# create an alternation to speed up the regexp below
my $useless = join('|', @useless);

sub fixup ($) {
  $line = $_[0];

  $line =~ s/#include\s+<([^>]+)>/$i = (exists $transforms{$1}) ? $transforms{$1} : "$1"; "#include <$i>"/e;

  if ($line =~ m/\s*#include\s+<($useless)>/) {
    my $file = $1;
    if (numlines("/etc/subdomain.d/$file") > 0) {
      my $succ = open INC, "/etc/subdomain.d/$file";
      if (not $succ) {
        print STDERR "Error opening /etc/subdomain.d/$file\n";
      } else {
        while(my $included_line = <INC>) {
          print fixup_loop($included_line);
        }
        close INC;
      }
    }
    $line = ""; # this line has been handled by the file
  }

  return $line;
}

# call fixup on a single entry repeatedly -- this way, we can encode
# 'small' changes in the fixup routine when they are made, rather than
# encoding all possible starting points and which specific end point
# they should go to.
sub fixup_loop ($) {
  my $line = $_[0];
  my $saved;
  do {
    $saved = $line;
    $line = fixup($saved);
  } until ($line eq $saved);
  return $line;
}

# main entry point; fix each line in every file in argv.
while(<>) {
  print fixup_loop($_);
}