[OpenAFS] Scripts for cleaning tokens/pags

System Administrator root@umr.edu
Thu, 14 Dec 2000 08:56:04 -0600


--X1bOJ3K7DJ5YkBrT
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

These are two scripts we use on machines with the following criteria:

a. Lots of authentications that involve tokens - this in our case does 
_NOT_ include POP and IMAP servers, those are krb5 only, and do not get 
tokens, however, they _DO_ include telnet logins, netatalk-afpd, and 
samba.

b. Setup such that tokens don't go away in general. In the case of telnet 
sessions, people often leave stuff running in background - having the 
tokens go away would cause a problem.

c. (HP-UX) Tokens are not owned by userids that don't match their afsid. 
(This is a limitation of HP-UX, I have no way of determining the pags 
that are in use by a process.) On linux, /proc can be used to determine all 
active pags from processes that are running.

----

For reference, if you run this script on a machine that is overly bogged 
down by pags currently - it will likely appear to lock up the machine for 
a few seconds as it collapses a huge in-kernel hash into a tiny one after 
you've cleared out all the old tokens. 

I'm sure someone could improve this immensely by triggering the unlog 
system call from perl directly instead of system("unlog");

---

The way the scripts work is, using kdump, they retrieve a list of all the 
pags in the kernel hash, they they attempt to determine which of those 
pags contain tokens that need to be kept. (In the case of the hpux10 
script, that means 'the userid associated with this afsid for this token 
has processes running on the machine.) (In the case of linux, that means 
'a process exists in this pag'.) it then loops through all those pags, 
putting the script into that pag temporarily (setgroups) and issuing unlog.

---

Note - this is necessary even on the most current afs for linux, as it 
still does not do garbage collection of tokens/pags. 

-- Nathan

--X1bOJ3K7DJ5YkBrT
Content-Type: application/x-perl
Content-Disposition: attachment; filename="clean-tokens-hpux10.pl"

#!/umr/bin/perl
$| = 1;

# 
# Input sources
#
$in_kdump = "/usr/afsws/etc/kdump -users|";
$in_ps = "/usr/bin/ps -ef|";

#
# Read in the kdump data
#
open(IN, $in_kdump);
print "Processing KDump: ";
$count = 0;
%pags = ();
%pags_per_uid = ();
while ( $line = <IN> )
{
	next if ( $line !~ /:/o );

	if ( $line =~ /uid=x(41[0-9a-fA-F]+),.* vid=([0-9]+)/o )
	{
		$pag = $1;
		$uid = $2;

		$pagnum = hex($pag) - hex("41000000");
		$pag2 = $pagnum % 16384;
		$pag1 = ($pagnum-$pag2)/16384;

		$pag1 += 33536;
		$pag2 += 32512;

		if ( $uid > 1 )
		{
			$pags{"$pag1:$pag2"} = $uid;
		}

#		if ( $count % 250 == 0 ) { print "." };
		$count++;
	}
}
print "$count active tokens.\n";
close(IN);

#
# Read in the ps data
#
open(IN, $in_ps);
print "Processing Users: ";
%uids = ();
$count = 0;
while ( chomp($line = <IN>) )
{
	$line =~ s/^ +//go;
	$line =~ s/ +.*//go;
	
	$uid = getpwnam($line);
	next if ($uid eq "");
	$uids{$uid} = 1;

#	if ( $count % 50 == 0 ) { print "." };
	$count++;
}
close(IN);
print "$count active user processes.\n";

#
# Clean pags
#
$cleaned = 0;
$skipped = 0;
$count = 0;
while ( ($pag,$uid) = each(%pags) )
{
	if ( $count % 100 == 0 )
	{
		print "Processed Tokens: $count\n";
	}
	$count++;
	if ( $uids{$uid} )
	{
#		print "-";
		$skipped++;
	}
	else
	{
		($pag1, $pag2) = split(/:/, $pag);
		$) = "0 $pag1 $pag2";
		system("/usr/afsws/bin/unlog");
		$cleaned++;
#		print "+";
	}
}
print "Cleaning Tokens: $skipped tokens skipped.\n";
print "Cleaning Tokens: $cleaned tokens unlogged.\n";

--X1bOJ3K7DJ5YkBrT
Content-Type: application/x-perl
Content-Disposition: attachment; filename="clean-tokens-redhat.pl"

#!/umr/bin/perl
$| = 1;

# 
# Input sources
#
$in_kdump = "/usr/afsws/etc/kdump -users|";
$in_ps = "/bin/ps -ef|";

#
# Read in the kdump data
#
open(IN, $in_kdump);
print "Processing KDump: ";
$count = 0;
%pags = ();
%pags_per_uid = ();
while ( $line = <IN> )
{
	next if ( $line !~ /:/o );

	if ( $line =~ /uid=x(41[0-9a-fA-F]+),.*vid=([0-9]+)/o )
	{
		$pag = $1;
		$uid = $2;

		$pagnum = hex($pag) - hex("41000000");
		$pag2 = $pagnum % 16384;
		$pag1 = ($pagnum-$pag2)/16384;

		$pag1 += 33536;
		$pag2 += 32512;

		if ( $uid > 0 )
		{
			$pags{"$pag1:$pag2"} = $uid;
			print "\t$pag1,$pag2\n";
		}

#		if ( $count % 250 == 0 ) { print "." };
		$count++;
	}
}
print "$count active tokens.\n";
close(IN);

#
# Read in the info about active processes, delete from
# %pags for each active
#
print "Scanning processes:\n";
opendir(DIR, "/proc");
while ( $file = readdir(DIR) )
{
	next if ( $file !~ /^[0-9]+$/o );
	print "\t$file: ";

	$groups = "";
	
	open(IN, "/proc/$file/status");
	while ( chomp($line = <IN>) )
	{
		if ( $line =~ /^Groups:(.*)$/o )
		{
			$groups = $1;
			last;
		}
	}
	close(IN);
	
	$groups =~ s/[\r\n\t ]+/ /gio;
	$groups =~ s/^ +//gio;
	$groups =~ s/ +$//gio;
	@groups = split(' ', $groups);

	$pag1 = $groups[0];
	$pag2 = $groups[1];
	
	if ( $pag1 >= 32512 && $pag2 >= 33536 )
	{
		print "$pag1,$pag2 ";
		if ( $pags{"$pag1:$pag2"} )
		{
			print "skipping pag\n";
			delete $pags{"$pag1:$pag2"};		
		}
		else
		{
			print "no active token\n";
		}
	}
	else
	{
		print "not active pag\n";
	}
}

closedir(DIR);

#
# Clean pags
#
$cleaned = 0;
$skipped = 0;
$count = 0;
while ( ($pag,$uid) = each(%pags) )
{
	if ( $count % 100 == 0 )
	{
		print "Processed Tokens: $count\n";
	}
	$count++;

	
	($pag1, $pag2) = split(/:/, $pag);
	$) = "0 $pag1 $pag2";
	system("/usr/afsws/bin/unlog");
	$cleaned++;

	print "\t$pag unlogged\n";
}
print "Cleaning Tokens: $cleaned tokens unlogged.\n";

--X1bOJ3K7DJ5YkBrT--