1#!/bin/perl 2# 3# Hacked by Alan Stebbens <aks@sgi.com> to setuid to the username if 4# valid on this system. Written as a secure Perl script. To enable, 5# 6# chown root /usr/samba/bin/sambalp 7# chmod u+s,+x /usr/samba/bin/sambalp 8# 9# If setuidshells is not enabled on your system, you must also do this: 10# 11# systune -i 12# nosuidshells = 0 13# y 14# quit 15# 16# reboot 17# 18# This script will still work as a normal user; it will not try 19# to setuid in this case. 20# 21# If the "$PSFIX" variable is set below... 22# 23# Workaround Win95 printer driver/Impressario bug by removing 24# the PS check for available virtual memory. Note that this 25# bug appears to be in all Win95 print drivers that generate 26# PostScript; but is for certain there with a QMS-PS 810 (the 27# printer type I configure on the Win95-side for printing with 28# Samba). 29# 30# the perl script fixes 3 different bugs. 31# 1. remove the JCL statements added by some HP printer drivers to the 32# beginning of the postscript output. 33# 2. Fix a bug in output from word files with long filenames. A non-printing 34# character added to the end of the title comment by word is 35# removed. 36# 3. The VM fix described above. 37# 38# 39# Modified for Perl4 compatibility. 40# 41 42$PROG = "sambalp"; 43 44$PSFIX = 1; # set to 0 if you don't want to run 45 # the "psfix" portion 46 47# Untaint the PATH variable 48@PATH = split(' ',<<EOF); 49 /usr/sbin /usr/bsd /sbin /usr/bin /bin /usr/lib /usr/local/bin 50EOF 51$ENV{'PATH'} = join(':',@PATH); 52 53 print "$#ARGV ".scalar(@ARGV)."\n"; 54if (scalar(@ARGV) < 2) { 55 print STDERR "usage: $PROG printer file [user] [system]\n"; 56 exit; 57} 58 59$printer = $ARGV[0]; 60$file = $ARGV[1]; 61$user = $ARGV[2]; 62$system = $ARGV[3]; 63 64$user = "nobody" unless($user); 65$system = `hostname` unless($system); 66 67open(LPSTAT,"/usr/bin/lpstat -t|") || die("Can't get printer list.\n"); 68@printers = (); 69while (<LPSTAT>) { 70 next unless /^printer (\w+)/; 71 push(@printers,$1); 72} 73close LPSTAT; 74# Create a hash list 75@printers{@printers} = @printers; 76 77# Untaint the printer name 78if (defined($prtname = $printers{$printer})) { 79 $printer = $prtname; 80} else { 81 die("Unknown printer: \"$printer\"\n"); 82} 83 84if ($> == 0) { # are we root? 85 # yes -- then perform a taint checks and possibly do a suid check 86 87 # Untaint the file and system names (pretend to filter them) 88 $file = $file =~ /^(.*)/ ? $1 : die("Bad file: $file\n"); 89 $system = $system =~ /^(.*)/ ? $1 : die("Bad system: $system\n"); 90 91 # Get the valid users 92 setpwent; 93 %users = (); 94 while (@pwe = getpwent()) { 95 $uids{$pwe[0]} = $pwe[2]; 96 $users{$pwe[2]} = $pwe[0]; 97 } 98 endpwent(); 99 100 # Check out the user -- if the user is a real user on this system, 101 # then become that user so that the printer header page looks right 102 # otherwise, remain as the default user (probably "nobody"). 103 104 if (defined($uid = $uids{$user})) { 105 106 # before we change UID, we must ensure that the file is still 107 # readable after the UID change. 108 chown($uid, 9, $file); # make the file owned by the user 109 110 # Now, go ahead and become the user 111 $name = $users{$uid}; 112 $> = $uid; # become the user 113 $< = $uid; 114 } else { # do untaint filtering 115 $name = $user =~ /^(\w+)/ ? $1 : die("Bad user: $user\n"); 116 } 117} else { # otherwise, just be me 118 $name = $user; # whomever that is 119} 120 121$lpcommand = "/usr/bin/lp -c -d$printer -t'$name on $system'"; 122 123# This code is from the original "psfix" but it has been completely 124# rewritten for speed. 125 126if ($PSFIX) { # are we running a "psfix"? 127 open(FILE, $file) || die("Can't read $file: $!\n"); 128 open(LP, "|$lpcommand -") || die("Can't open pipe to \"lp\": $!\n"); 129 select(LP); 130 while (<FILE>) { # 131 $_ =~ s/^\004//; # strip any ctrl-d's 132 if (/^\e%/) { # get rid of any non-postscript commands 133 while (<FILE>) { # remove text until next %!PS 134 s/^\001M//; # lenmark driver prefixes Ctrl-A M to %!PS 135 last if /^%!PS/; 136 } 137 last if eof(FILE); 138 } elsif (/^%%Title:/) { # fix bug in long titles from MS Word 139 s/.\r$/\r/; # remove trailing character on the title 140 } elsif (/^\/VM\?/) { # remove VM test 141 print "/VM? { pop } bind def\r\n"; 142 while (<FILE>) { last if /def\r/; } 143 next; # don't print 144 } 145 print; 146 } 147 close FILE; 148 close LP; 149} else { # we're not running psfix? 150 system("$lpcommand $file"); 151} 152 153if ($file =~ m(^/)) { 154 # $file is a fully specified path 155 # Remove the file only if it lives in a directory ending in /tmp. 156 unlink($file) if ($file =~ m(/tmp/[^/]+$)); 157} else { 158 # $file is NOT a fully specified path 159 # Remove the file only if current directory ends in /tmp. 160 unlink($file) if (`pwd` =~ m(/tmp$)); 161} 162