Annotation of loncom/lcnfsoff, revision 1.2
1.1 harris41 1: #!/usr/bin/perl
2:
3: use strict;
4:
5: # This script is a setuid script (chmod 6755; chown root:root).
6: # It disables nfs/portmap services for a specific user at
7: # a specific ip address.
8:
9: # Exit codes. 0=ok. Higher than 0 means something went wrong.
10:
11: # Usage within code
12: #
13: # $exitcode=system("/home/httpd/perl/lcnfsoff","NAME","IPADDRESS")/256;
14: # print "uh-oh" if $exitcode;
15:
16: # Security
17: $ENV{'PATH'}=""; # Nullify path information.
18: $ENV{'BASH_ENV'}=""; # Nullify shell environment information.
19:
20: # Do not print error messages if there are command-line arguments
21: my $noprint=0;
22: if (@ARGV) {
23: $noprint=1;
24: }
25:
26: # Read in /etc/passwd, and make sure this process is running from user=www
27: open (IN, "</etc/passwd");
28: my @lines=<IN>;
29: close IN;
30: my $wwwid;
31: for my $l (@lines) {
32: chop $l;
33: my @F=split(/\:/,$l);
34: if ($F[0] eq 'www') {$wwwid=$F[2];}
35: }
36: if ($wwwid!=$<) {
37: print("User ID mismatch. This program must be run as user 'www'\n") unless $noprint;
38: exit 1;
39: }
40: &disable_root_capability;
41:
42: # Handle case of another lcnfs process
43: unless (&try_to_lock("/tmp/lock_lcnfs")) {
44: print "Error. Too many other simultaneous nfs change requests being made.\n" unless $noprint;
45: exit 4;
46: }
47: # Gather input. Should be 2 values (user name, numeric ip address).
48: my @input;
49: if (@ARGV==3) {
50: @input=@ARGV;
51: }
52: elsif (@ARGV) {
53: print("Error. This program needs 2 command-line arguments (username, numeric ip address).\n") unless $noprint;
54: unlink('/tmp/lock_lcnfs');
55: exit 2;
56: }
57: else {
58: @input=<>;
59: if (@input!=2) {
60: print("Error. Two lines should be entered into standard input.\n") unless $noprint;
61: unlink('/tmp/lock_lcnfs');
62: exit 3;
63: }
64: map {chop} @input;
65: }
66:
67: my ($username,$ipaddress)=@input;
68: $username=~/^(\w+)$/;
69: my $safeusername=$1;
70: if ($username ne $safeusername) {
71: print "Error. The user name specified has invalid characters.\n";
72: unlink('/tmp/lock_lcnfs');
73: exit 9;
74: }
75:
76: $ipaddress=~/^([\w|\.]*)$/;
77: my $safeipaddress=$1;
78: if ($ipaddress ne $safeipaddress) {
79: print "Error. The IP address must be numeric and of the form ##.##.##.##.\n";
80: unlink('/tmp/lock_lcnfs');
81: exit 8;
82: }
83:
84: &enable_root_capability;
85: # Remove entry from /etc/exports
86: my $exports=`/bin/cat /etc/exports`;
87: $exports=~s/\/home\/${safeusername}\s*${safeipaddress}.*?\n//g;
88: # Resynchronize /etc/exports file
89: open (OUT,">/etc/exports");
90: print OUT $exports;
91: close OUT;
92: system('/usr/sbin/exportfs','-r');
93:
94: # Remove entry from /etc/hosts.allow
95: my $hostsallow=`/bin/cat /etc/hosts.allow`;
96: $hostsallow=~s/\# $safeusername\nportmap: $safeipaddress\n//g;
97: open (OUT,">/etc/hosts.allow");
98: print OUT $hostsallow;
99: close OUT;
100:
101: &disable_root_capability;
102: unlink('/tmp/lock_lcnfs');
103: exit 0;
104:
105: # ----------------------------------------------------------- have setuid script run as root
106: sub enable_root_capability {
107: if ($wwwid==$>) {
108: ($<,$>)=($>,$<);
109: ($(,$))=($),$();
110: }
111: else {
112: # root capability is already enabled
113: }
114: return $>;
115: }
116:
117: # ----------------------------------------------------------- have setuid script run as www
118: sub disable_root_capability {
119: if ($wwwid==$<) {
120: ($<,$>)=($>,$<);
121: ($(,$))=($),$();
122: }
123: else {
124: # root capability is already disabled
125: }
126: }
127:
128: # ----------------------------------- make sure that another lcnfs process isn't running
129: sub try_to_lock {
130: my ($lockfile)=@_;
131: my $currentpid;
132: my $lastpid;
133: # Do not manipulate lock file as root
134: if ($>==0) {
135: return 0;
136: }
137: # Try to generate lock file.
138: # Wait 3 seconds. If same process id is in
139: # lock file, then assume lock file is stale, and
140: # go ahead. If process id's fluctuate, try
141: # for a maximum of 10 times.
142: for (0..10) {
143: if (-e $lockfile) {
144: open(LOCK,"<$lockfile");
145: $currentpid=<LOCK>;
146: close LOCK;
147: if ($currentpid==$lastpid) {
148: last;
149: }
150: sleep 3;
151: $lastpid=$currentpid;
152: }
153: else {
154: last;
155: }
156: if ($_==10) {
157: return 0;
158: }
159: }
160: open(LOCK,">$lockfile");
161: print LOCK $$;
162: close LOCK;
163: return 1;
164: }
165:
166:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>