#!/usr/bin/perl -w
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 1, or (at your option)
#    any later version.
#   
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#

use strict;

my $i = 0;
my $passwd = "/etc/passwd";

print "Checking SSH userfiles for problems\n";
open (PASSWD, "<$passwd") or die ("Couldn't open $passwd for reading, perhaps you did something?\n");
flock (PASSWD, 2);
until (eof PASSWD) {
	my @line;
	if (@line = split (":", readline (*PASSWD))) {
		if (!($line[0] =~ /[#]/)) {
			determine_config($line[0], $line[2], $line[5]);
		}
	}
}
flock (PASSWD, 8);
close (PASSWD);
 

###############################################################
# cleanup: gets rid of any temporary files, via simple rm -Rf 
###############################################################
sub cleanup {
	my $t = $_[0];
	my $command = "rm -Rf $t";
	system($command);
}


###############################################################
# determine_config: goes through all the files in the dir 
# checks permissions, and reports.   
###############################################################
sub determine_config {

	my $user = $_[0];
	my $uid = $_[1];
	my $homedir = $_[2];
	my $ssh_dir = $homedir . "/.ssh";
	my @listing;
	
	#print "user: $user home: $homedir uid: $uid\n";	
	# take the configuration directory, get a listing of all the files for processing
	if (opendir (SSH, $ssh_dir)) {
		@listing = readdir (SSH);
		closedir (SSH);
	}
	else {
		print ("--INFO-- [sshc001i] $user does not have a .ssh directory\n");
	}

	# The following permission settings have been chosen for several reasons
	# 1) if a file is executable, it may be a script of some sort..better to be safe then sorry
	# 2) they are rather conservative so information leakage is minimized
	for ($i = 2; $i <= $#listing; $i++) {
		#print "Working on file $ssh_dir/$listing[$i]\n";
		my @file = stat ($ssh_dir . "/". $listing[$i]);
		if ($file[2] & 020) {
			print ("--FAIL-- [sshc001f] File $ssh_dir/$listing[$i] is group writable\n");
		}
		if ($file[2] & 002) {
			print ("--FAIL-- [sshc002f] File $ssh_dir/$listing[$i] is world writable\n");
		}
		if ($file[2] & 040) {
			print ("--FAIL-- [sshc003f] File $ssh_dir/$listing[$i] is world readable\n");
		}
		if ($file[2] & 004) {
			print ("--FAIL-- [sshc004f] File $ssh_dir/$listing[$i] is world readable\n");
		}
		if ($file[2] & 010) {
			print ("--WARN-- [sshc001w] File $ssh_dir/$listing[$i] is world executeable\n");
		}
		if ($file[2] & 001) {
			print ("--WARN-- [sshc002w] File $ssh_dir/$listing[$i] is world executeable\n");
		}
		if ($file[2] & 200) {
			if (!($listing[$i] =~ /[known]/) || !($listing[$i] =~ /[auth]/)) {
				print("--WARN-- [sshc003w] File $ssh_dir/$listing[$i] is user writable, and shouldn't be\n");
			}
		} 
		if ($file[2] & 100) {
			print ("--WARN-- [sshc003w] File $ssh_dir/$listing[$i] is user executable, and shouldn't be\n");
		}
		if ($file[2] & 000) {
                        print ("--WARN-- [sshc004w] File $ssh_dir/$listing[$i] has no perms\n");
                }
		if ($listing[$i] =~ /[known]/) {
			open (TEMP, "<$ssh_dir/$listing[$i]");
			flock (TEMP, 2);
			my @line;
			until (eof TEMP) {
				@line = split (" ", readline (*TEMP));
				print ("--INFO-- [sshc002i] $ssh_dir/$listing[$i] knows of host: $line[0]\n");
			}
			flock (TEMP, 8);
			close (TEMP);
		}
	}
}
