dpkg-statoverride.pl 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. #! /usr/bin/perl
  2. use POSIX;
  3. use POSIX qw(:errno_h :signal_h);
  4. $admindir= "/var/lib/dpkg"; # This line modified by Makefile
  5. $version= '1.3.0'; # This line modified by Makefile
  6. $verbose= 1;
  7. $doforce= 0;
  8. $doupdate= 0;
  9. $mode= "";
  10. sub UsageVersion {
  11. print STDERR <<EOF || &quit("failed to write usage: $!");
  12. Debian dpkg-statoverride $version.
  13. Copyright (C) 2000 Wichert Akkerman.
  14. This is free software; see the GNU General Public Licence version 2 or later
  15. for copying conditions. There is NO warranty.
  16. Usage:
  17. dpkg-statoverride [options] --add <owner> <group> <mode> <file>
  18. dpkg-statoverride [options] --import <package> <file>
  19. dpkg-statoverride [options] --remove <file>
  20. dpkg-statoverride [options] --list [<glob-pattern>]
  21. Options:
  22. --update immediately update file permissions
  23. --force force an action even if a sanity check fails
  24. --quiet quiet operation, minimal output
  25. --help print this help screen and exit
  26. --admindir <directory> set the directory with the statoverride file
  27. EOF
  28. }
  29. sub CheckModeConflict {
  30. return unless $mode;
  31. &badusage("two modes specified: $_ and --$mode");
  32. }
  33. while (@ARGV) {
  34. $_=shift(@ARGV);
  35. last if m/^--$/;
  36. if (!m/^-/) {
  37. unshift(@ARGV,$_); last;
  38. } elsif (m/^--help$/) {
  39. &UsageVersion; exit(0);
  40. } elsif (m/^--update$/) {
  41. $doupdate=1;
  42. } elsif (m/^--quiet$/) {
  43. $verbose=0;
  44. } elsif (m/^--force$/) {
  45. $doforce=1;
  46. } elsif (m/^--admindir$/) {
  47. @ARGV || &badusage("--admindir needs a directory argument");
  48. $admindir= shift(@ARGV);
  49. } elsif (m/^--add$/) {
  50. &CheckModeConflict;
  51. $mode= 'add';
  52. } elsif (m/^--remove$/) {
  53. &CheckModeConflict;
  54. $mode= 'remove';
  55. } elsif (m/^--list$/) {
  56. &CheckModeConflict;
  57. $mode= 'list';
  58. } elsif (m/^--import$/) {
  59. &CheckModeConflict;
  60. $mode= 'import';
  61. } else {
  62. &badusage("unknown option \`$_'");
  63. }
  64. }
  65. $dowrite=0;
  66. &badusage("no mode specified") unless $mode;
  67. &ReadOverrides;
  68. if ($mode eq "add") {
  69. @ARGV==4 || &badusage("--add needs four arguments");
  70. $user=$ARGV[0];
  71. if ($user =~ m/^#([0-9]+)$/) {
  72. $uid=$1;
  73. &badusage("illegal user $user") if ($uid<0);
  74. } else {
  75. (($name,$pw,$uid)=getpwnam($user)) || &badusage("non-existing user $user");
  76. }
  77. $group=$ARGV[1];
  78. if ($group =~ m/^#([0-9]+)$/) {
  79. $gid=$1;
  80. &badusage("illegal group $group") if ($gid<0);
  81. } else {
  82. (($name,$pw,$gid)=getgrnam($group)) || &badusage("non-existing group $group");
  83. }
  84. $mode= $ARGV[2];
  85. (($mode<0) or (oct($mode)>07777)) && &badusage("illegal mode $mode");
  86. $file= $ARGV[3];
  87. $file =~ m/\n/ && &badusage("file may not contain newlines");
  88. if (defined $owner{$file}) {
  89. print STDERR "An override for \"$file\" already exists, ";
  90. if ($doforce) {
  91. print STDERR "but --force specified so lets ignore it.\n";
  92. } else {
  93. print STDERR "aborting\n";
  94. exit(3);
  95. }
  96. }
  97. $owner{$file}=$user;
  98. $group{$file}=$group;
  99. $mode{$file}=$mode;
  100. $dowrite=1;
  101. if ($doupdate) {
  102. if (not -f $file) {
  103. print STDERR "waring: --update given but $file does not exist\n";
  104. } else {
  105. chmod (oct($mode),$file) || warn "failed to chmod $file: $!\n";
  106. chown ($uid,$gid,$file) || warn "failed to chown $file: $!\n";
  107. }
  108. }
  109. } elsif ($mode eq "remove") {
  110. @ARGV==1 || &badusage("--remove needs one arguments");
  111. $file=$ARGV[0];
  112. if (not defined $owner{$file}) {
  113. print STDERR "No override present.\n";
  114. exit(0);
  115. }
  116. delete $owner{$file};
  117. delete $group{$file};
  118. delete $mode{$file};
  119. $dowrite=1;
  120. print STDERR "warning: --update is useless for --remove\n" if ($doupdate);
  121. } elsif ($mode eq "import") {
  122. @ARGV==2 || &badusage("--import needs two arguments");
  123. $pkg=$ARGV[0];
  124. $file=$ARGV[1];
  125. if (defined $owner{$file}) {
  126. print STDERR "An override for \"$file\" already exists, ";
  127. if ($doforce) {
  128. print STDERR "but --force specified so lets ignore it.\n";
  129. } else {
  130. print STDERR "aborting\n";
  131. exit(3);
  132. }
  133. }
  134. open(SUIDCONF,"/etc/suid.conf") || &quit("error opening /etc/suid.conf");
  135. while (<SUIDCONF>) {
  136. next if (m/^\w*#/);
  137. chomp;
  138. ($sm_pkg,$sm_file,$sm_user,$sm_group)=split;
  139. next if ($sm_file ne $file);
  140. next if ($sm_pkg eq $pkg);
  141. $sm_user="#$sm_user" if ($sm_user =~ m/^\d*$/);
  142. $sm_group="#$sm_group" if ($sm_group =~ m/^\d*$/);
  143. $owner{$fm_file}=$sm_user;
  144. $group{$fm_file}=$sm_group;
  145. if ( -x "/usr/sbin/suidunregister") {
  146. @args = ("suidunregister", "$file");
  147. system(@args) == 0 || &quit("suidunregister failed");
  148. }
  149. $dowrite=1;
  150. last;
  151. }
  152. close(SUIDCONF);
  153. } elsif ($mode eq "list") {
  154. my (@list,@ilist,$pattern,$file);
  155. @ilist= @ARGV ? @ARGV : ('*');
  156. while (defined($_=shift(@ilist))) {
  157. s/\W/\\$&/g;
  158. s/\\\?/./g;
  159. s/\\\*/.*/g;
  160. push(@list,"^$_\$");
  161. }
  162. $pat= join('|',@list);
  163. for $file (keys %owner) {
  164. next unless ($file =~ m/$pat/o);
  165. print "$owner{$file} $group{$file} $mode{$file} $file\n";
  166. }
  167. }
  168. &WriteOverrides if ($dowrite);
  169. exit(0);
  170. sub ReadOverrides {
  171. open(SO,"$admindir/statoverride") || &quit("cannot open statoverride: $!");
  172. while (<SO>) {
  173. my ($owner,$group,$mode,$file);
  174. chomp;
  175. ($owner,$group,$mode,$file)=split(' ', $_, 4);
  176. die "Multiple overrides for \"$file\", aborting"
  177. if defined $owner{$file};
  178. $owner{$file}=$owner;
  179. $group{$file}=$group;
  180. $mode{$file}=$mode;
  181. }
  182. close(SO);
  183. }
  184. sub WriteOverrides {
  185. my ($file);
  186. open(SO,">$admindir/statoverride-new") || &quit("cannot open new statoverride file: $!");
  187. foreach $file (keys %owner) {
  188. print SO "$owner{$file} $group{$file} $mode{$file} $file\n";
  189. }
  190. close(SO);
  191. chmod(0644, "$admindir/statoverride-new");
  192. unlink("$admindir/statoverride-old") ||
  193. $! == ENOENT || &quit("error removing statoverride-old: $!");
  194. link("$admindir/statoverride","$admindir/statoverride-old") ||
  195. $! == ENOENT || &quit("error creating new statoverride-old: $!");
  196. rename("$admindir/statoverride-new","$admindir/statoverride")
  197. || &quit("error installing new statoverride: $!");
  198. }
  199. sub quit { print STDERR "dpkg-statoverride: @_\n"; exit(2); }
  200. sub badusage { print STDERR "dpkg-statoverride: @_\n\n"; print("You need --help.\n"); exit(2); }
  201. # vi: ts=8 sw=8 ai si cindent