/************************************************************************/
/* This is the main file for lsat					*/
/* It contains the main program and also does two checks of its own.    */
/* It gives the user some usage info (perhaps) and will check the 	*/
/* kernel version and release level of software running on the box.	*/
/*									*/
/* Current release is 0.1.1						*/
/* Project started on 04/01/2002					*/
/* homepage: http://www.dimlight.org/~number9/lsat 			*/
/* changelog: http://www.dimlight.org/~number9/lsat/changelog.html  	*/
/*									*/
/* This software Licensed under the GNU General Public License		*/
/* see the bottom of this lsatmain.c file for details.			*/
/*									*/
/* This program is _supposed_ to be modular in nature. That is to say:  */
/* all security checks are sub-functions called from this main prog.    */
/* As of now (release 0.1.1) the subfunctions can be called with 2	*/
/* parameters, the kernel level, and the release level. However, 	*/
/* the checkinetd.c program returns an integer dictating if inetd.conf  */
/* exists, and if it does another function hosts.c will check the 	*/
/* /etc/hosts.allow|deny files for existance, etc.			*/
/*									*/
/* I should not get in the habit of doing the above as it destroys the  */
/* modularity (sp?) of the program.					*/
/*									*/
/************************************************************************/	

/****************/
/* Includes	*/
/****************/
#include <stdio.h> /* fprintf,fgets,fputs,fopen,fclose,perror,sscanf */
#include <stdlib.h> /* the std stuff */
#include <string.h> /* strtok */
#include "lsatheader.h"

/********************************************************/
/* Usage function. Tell user command line options	*/
/********************************************************/
void usage()
{
	fprintf(stderr, "Usage is lsat [options]\n");
	fprintf(stderr, "Options:\n");
	fprintf(stderr, "		-v					verbose\n");
	fprintf(stderr, "		-o<filename>	Output file name\n");
	exit(8);
}

/***************************************************/
/* Check what version and kernel release we are at */
/***************************************************/
int versions(char release[], char kernel[])
{
	/* some local vars... */
	FILE *infile;
	char *ptr;
	char line[1024];
	char tempstring[50];
	int  linecount=0;
	int  field=0;
	int  i=0;
	/* open input file for read... 									*/
	infile = fopen("/tmp/templist.txt", "r");
	if (infile == NULL)
	{
		/* rhut-rho */
		perror("Can't open the file we just made!?!\n");
		perror("Giving up, check perms or something...\n");
		return(-1);
	}

	/* get a line from the file... it should contain only 2					*/
	/* 1st line is uname -a, so the third field is the kernel version 	*/
	/* 2nd line is (maybee) redhat-release. We want the number, which    */
	/* is the 5th element :)															*/
	while (fgets(line, sizeof(line), infile) != NULL)
	{
		/* (re)set field...	*/
		field=0;
		ptr = strtok(line, ", \"\n");
		if (ptr == NULL)
		{
			break;
		}
		/* not blank?? Do some stuff...			*/
		while (ptr != NULL)
		{
			/* if linecount == 0, get 3rd field */
			if (sscanf(ptr, "%s", &tempstring) < 1)
			{
				perror("sccanf bit the dust");
				return(-1);
			}
			if ((field == 2) && (linecount == 0))
			{
				for (i = 0; i < 50; i++)
				{
					kernel[i]=tempstring[i];
				}
			}
			if ((field == 4) && (linecount == 1))
			{
				for (i = 0; i < 50; i++)
				{
					release[i]=tempstring[i];
				}
			}
			ptr = strtok(NULL, ", \"\n");
			if (ptr == NULL)
			{
				/* freak out */
				break;
			}
			/* increment counter for the field we are reading */
			field++;
		} /* end while(ptr != NULL) */
		/* increment the line counter */
		linecount++;
	} /* end while (fgets...) */
	return(0);
}

/****************************************************************/
/* Main <smile> All sub-programs/functions should be called 	*/
/* from here. Note: they should also be listed in lsatheader.h  */
/****************************************************************/
int main(int argc, char *argv[])
{
	int retval=0;     /* a return value indicator		*/
	int verbose=0;    /* for verbosity			*/
	int inetexists=0; /* if inetd.conf exists, this is 1 	*/
	char release[50]; /* array for release level		*/
	char kernel[50];  /* what kernel user is running	*/
	char *out_file="lsat.out";  /* output filename if none given	*/
	FILE *tempptr;    /* a temp file pointer		*/

	/* some options that are not yet implimented :) */
	while ((argc > 1) && (argv[1][0]=='-'))
	{
		/* argv[1][1] is 1st option char */
		switch (argv[1][1])
		{
			case 'v':
				verbose = 1;
				break;

			/* outfile 					*/
			/* -o<name> is format 	*/

			case 'o':
				out_file = &argv[1][2];
				break;

			default:
				printf("Bad option %s\n", argv[1]);
				usage();
		}
		++argv;
		--argc;
	}

	/* First off, get the uname and redhat-release, if there 	*/
	/* is one...							*/
	/* this is silly, I should know how to do this more easily 	*/

	if ( (system("uname -a >> /tmp/templist.txt")) < 0)
	{
		/* rhut-rho...something bad happened. 			*/
		perror("Problem executing pwd...\n");
		return(0);
	}
	if ( (system("cat /etc/redhat-release >> /tmp/templist.txt")) < 0)
	{
		/* Hrm, perhaps we are not on a redhat system		*/
		/* we will do something else to fix that later on  */
		;
	}

	/* read that in, check kernel version and if we are	*/
	/* on a redhat box, the redhat-release...		*/
	retval = versions(release, kernel);
	if (retval < 0)
	{
		/* something went wrong... 			*/
		perror("Problem in versions function.\n");
		return(0);
	}

	if ( (system("rm -f /tmp/templist.txt")) < 0)
	{
		/* rhut-rho...something bad happened.		*/
		perror("Problem rm'ing tempfile...\n");
		return(0);
	}

	/* secondly, check to see if lsat.out exists.   */
	/* if it does, call it lsat.old and rm lsat.out	*/

	tempptr = fopen(out_file, "r");
	if (tempptr == NULL)
	{
		/* great the outfile does not exist */
		/* do nothing... <smile>	    */
		;		
	}
	else
	{
		/* the outfile exists. lets not     */
		/* append to it, but back it up     */
		fclose(tempptr);
		if ((system("mv -f lsat.out lsat.old")) < 0)
		{
			/* rhut-rho... problems... */
			perror("Problem backing up lsat.out file.\n");
			perror("Check perms on the cwd please...\n");
			return(-1);
		}
	}

	/* run checkrpms */
	retval = 0;
	retval = checkrpms(release, kernel, out_file);
	if (retval < 0)
	{
		/* something went wrong...                      */
                perror("Problem in checkrpms module.\n");
		perror("You should have seen errors...\n");
                return(0);
	}

	/* run checkinetd */
	/* if hosts exists run checkhostsfiles */
	inetexists = checkinetd(release, out_file);
	/* if inetexists == 1, it does!				*/
	/* if inetexists == 0, it does not...			*/
	/* if inetexists == -1, we had some problems.		*/
	if (inetexists == 1)
	{
		checkhostsfiles(out_file);
	}
	if (inetexists == 0)
	{
		/* do nothing... */
		;
	}
	if (inetexists == -1)
	{
		/* there was a problem. User should have seen	*/
		/* messages from checkinetd program.		*/
		/* do nothing here and continue...		*/
		;
	}

	/* check for setuid/setgid files */
	retval = 0;
	retval = checkset(out_file);
	if (retval < 0)
        {
                /* something went wrong...                      */
                perror("Problem in checkset module.\n");
                perror("You should have seen errors...\n");
                return(0);
        }


	/* check for world writable files/directories */
	retval = 0;
	retval = checkwrite(out_file);
	if (retval < 0)
        {
                /* something went wrong...                      */
                perror("Problem in checkwrite module.\n");
                perror("You should have seen errors...\n");
                return(0);
        }

	/* check for .exrc and .forward files */
	retval = 0;
	retval = checkdotfiles(out_file);
	if (retval < 0)
	{
		/* something went wrong...                      */
                perror("Problem in checkwrite module.\n");
                perror("You should have seen errors...\n");
                return(0);
        }

	/* tell the user we are finished and where the output is */
	printf("Finished.\n");
	printf("Check lsat.out for details.\n");
	return(0);
}


/**********************************************************************
Copyright (C) 2002 Robert Minvielle (number9)

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 2
of the License, 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.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
**********************************************************************/
