/**************************************/
/* This is the checkfiles module for  */
/* the lsatmain.c program. It checks  */
/* that /tmp and /var/tmp have the    */
/* sticky bit set. 		      */
/*                                    */
/* Future tests on dirs should be put */
/* in this file. I am working on it   */
/**************************************/

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

int checkfiles(filename, verbose)
const char *const filename;
int verbose;
{
	/* some local vars...		*/
	FILE *infile, *outfile;   /* infile/outfile pointers */
	char line[128];	 	 /* temp storage for reading a line */
	char chmod[12]="-rw-r--r--"; /* chmod 644 comparison string  */
	char rooted[2]="0";	  /* uid=0 comparison string	*/
	char *ptr;		  /* char ptr for strtok */
	int count = 0;		  /* general counter     */
	int Linecount = 0;	  /* line counter for file */
	int found = 0;		  /* var set if match found */
	int fileval = 0; 	  /* return val from mkstemp */
	/* note we make tempstring the same as line.  */
	/* this _should_ thwart most buffer overruns, */
	/* as we are doing a sizeof in fgets...	      */
	char tempstring[128];	  /* temp string for sscanf */


	if (verbose == 1)
	{
		printf("In checkfiles module...\n");
	}

	/* create a temp file for storage */
	fileval = mkstemp("/tmp/templist.txt");
        if (fileval < -1)
        {
                printf("Unable to create tempfile!?\n");
		printf("Problem was in module: checkfiles\n");
                return(-1);
        }

	/* make a list of the files */
	if ((system("ls -l / /var 1>/dev/null 2>/dev/null |grep tmp 1>/dev/null 2>/dev/null >/tmp/templist.txt")) < 0)
	{
		/* failure */
		perror("Error performing ls?\n");
		perror("Problem was in module: checkfiles\n");
		return(-1);
	}


	/* 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);
	}

	/* oopen output file for write, in cwd...						*/
	outfile = fopen(filename, "a");
	if (outfile == NULL)
	{
		/* rhut-rho */
		perror("Can't open output file!?!\n");
		perror("Giving up, check perms or something...\n");
		return(-1);
	}

	/* ok, first print out some header info to the file */
	fprintf(outfile, "****************************************\n");
	fprintf(outfile, "Check for non-sticky /tmp or /var/tmp:\n");


	if (verbose == 1)
	{
		printf("Checking for sticky bits...\n");
	}

	/* get a line from the file... */
	while (fgets(line, sizeof(line), infile) != NULL)
	{
		ptr = strtok(line, ", \n");
		while (ptr != NULL)
		{
			if (sscanf(ptr, "%s", &tempstring) < 1)
			{
				perror("sscanf bit the dust");
				return(-1);
			}
			if ((count == 0) && (Linecount == 0))
			{
				/* 1st line in file...  */
				/* note this is ls of / |grep tmp */
				if ((tempstring[9] != 't') || (tempstring[9] != 'T'))
				{
					/* sticky bit NOT set ! */
					found = 1;
					fprintf(outfile, "Sticky bit not set on /tmp.\n");
					fprintf(outfile, "Please set sticky bit on /tmp.\n");
				}
			}
			if ((count ==  0) && (Linecount == 1))
			{
				/* 2nd line in file */
				/* this is ls of /var |grep tmp */
				if ((tempstring[9] != 't') || (tempstring[9] != 'T'))
				{
					/* sticky bit NOT set! */
					found = 1;
					fprintf(outfile, "Sticky bit not set on /var/tmp.\n");
					fprintf(outfile, "Please set sticky bit on /var/tmp.\n");
				}
			}

			/* grab another token */
			ptr = strtok(NULL, ", \"\n");
			if (ptr == NULL)
			{
				;
			}
			/* inc counter...*/
			count++;
		} /* end of while(ptr != NULL), reset the counter */
		count=0;
		Linecount++;
	} /* end of while(fgets...) */

	/* print footer */
	if (found == 0)
	{
		/* no problems... */
		fprintf(outfile, "Sticky bits already set. Good.\n");
	}
	fprintf(outfile, "********************\n");



	/* second part... check utmp, wtmp, motd, mtab */
	/* for chmod 644. 									  */

	fprintf(outfile, "Checking files that should be chmod 644.\n\n");

	/* 1st close the infile...		*/
	fclose(infile);
	/* next rm the old templist...*/
	if ((system("rm -f /tmp/templist.txt")) < 0)
	{
			/* failure */
			perror("Error rm'ing tempfile...\n");
			perror("Error in module: checkfiles.\n");
			return(-1);
	}

	/* create a temp file for storage */
        fileval = mkstemp("/tmp/templist.txt");
        if (fileval < -1)
        {
                printf("Unable to create tempfile!?\n");
                printf("Problem was in module: checkfiles\n");
                return(-1);
        }

	/* if the system has any acceptable amount of 	*/
	/* ram subsequent calls to find should be fast	*/

	if ((system("find / -name utmp -exec ls -ln {} \\; 1>/dev/null 2>/dev/null >> /tmp/templist.txt")) < 0)
	{
		/* failure */
		perror("Error performing find.\n");
		perror("Error was in module checkfiles...\n");
		return(-1);
	}
	if ((system("find / -name wtmp -exec ls -ln {} \\; 1>/dev/null 2>/dev/null >> /tmp/templist.txt")) < 0)
	{
		/* failure */
		perror("Error performing find.\n");
		perror("Error was in module checkfiles...\n");
		return(-1);
	}
	if ((system("find / -name motd -exec ls -ln {} \\; 1>/dev/null 2>/dev/null >> /tmp/templist.txt")) < 0)
	{
		/* failure */
		perror("Error performing find.\n");
		perror("Error was in module checkfiles...\n");
		return(-1);
	}
	if ((system("find / -name mtab -exec ls -ln {} \\; 1>/dev/null 2>/dev/null >> /tmp/templist.txt")) < 0)
	{
		/* failure */
		perror("Error performing find.\n");
		perror("Error was in module checkfiles...\n");
		return(-1);
	}

	/* 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");
		perror("Problem was in module: checkfiles\n");
		return(-1);
	}

	if (verbose == 1)
	{
		printf("Checking files that should be chmod 644...\n");
	}

	/* get a line from the file... 	*/
	/* reset counters/flags 1st 		*/
	found = 0;
	count = 0;
	while (fgets(line, sizeof(line), infile) != NULL)
	{
		ptr = strtok(line, ", \n");
		while (ptr != NULL)
		{
			if (sscanf(ptr, "%s", &tempstring) < 1)
			{
				perror("sscanf bit the dust");	
				perror("Dust biting was in checkfiles.\n");
				return(-1);
			}
			/* this counts the fields we are on */
			count++;
			/* now check for chmod 644 		*/
			/* recall 644 is -rw-r--r-- :)	*/
			/* if count == 1 we should be at */
			/* the 1st field...					*/
			if (count == 1)
			{
				if ((strcmp(tempstring, chmod)) != 0)
				{
					/* not chmod 644 */
					/* grab the filename, which should be 		*/
					/* the 9th field on the line and print it	*/
					/* set flag to do this... */
					found = 1;
				}
			}
			if ((found == 1) && (count == 9))
			{
				/* we have a non-chmod 644 and we should 	*/
				/* be at the filename in the sscanf...		*/
				fprintf(outfile, "%s is not chmod 644.\n", tempstring);
				/* reset counters */
				found = 0;
				count = 0;
			}
			/* grab another token */
                        ptr = strtok(NULL, ", \"\n");
                        if (ptr == NULL)
                        {
                                ;
                        }
	  } /* end while (ptr != NULL) */
	  /* reset counters just to be sure... */
	  found = 0;
	  count = 0;
	} /* end while (fgets...) */

	/* print footer */
	fprintf(outfile, "Check above files for chmod 644.\n");
	fprintf(outfile, "********************\n");

	/* close input file before rm */
	fclose(infile);
	/* rm the templist... */
	if ((system("rm -f /tmp/templist.txt")) < 0)
	{
		/* failure */
		perror("Error rm'ing tempfile...\n");
		perror("Error in module: checkfiles.\n");
		return(-1);
	}

	/* finally, all dirs in the / should be owned by root */
	/* additionally, /usr/* should be owned by root, and	*/
	/* /var/tmp should be owned by root.						*/

	/* print header */
	fprintf(outfile, "Checking for root ownership of dirs.\n\n");

	
	/* create a temp file for storage */
        fileval = mkstemp("/tmp/templist.txt");
        if (fileval < -1)
        {
                printf("Unable to create tempfile!?\n");
                printf("Problem was in module: checkfiles\n");
                return(-1);
        }


	if ((system("ls -ln / |grep -v total 1>/dev/null 2>/dev/null >> /tmp/templist.txt")) < 0)
	{
		/* failure */
		perror("Error performing ls.\n");
		perror("Error was in module checkfiles...\n");
		return(-1);
	}

	if ((system("ls -ln /usr |grep -v total 1>/dev/null 2>/dev/null >> /tmp/templist.txt")) < 0)
	{
		/* failure */
		perror("Error performing ls.\n");
		perror("Error was in module checkfiles...\n");
		return(-1);
	}

	if ((system("ls -ln /var |grep -v total 1>/dev/null 2>/dev/null >> /tmp/templist.txt")) < 0)
	{
		/* failure */
		perror("Error performing ls.\n");
		perror("Error was in module checkfiles...\n");
		return(-1);
	}

	/* 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");
		perror("Error was in module: checkfiles.\n");
		return(-1);
	}

	if (verbose == 1)
	{
		printf("Checking files that should be owned by root...\n");
	}


	/* get a line from the file... 	*/
	/* reset counters/flags 1st 		*/
	found = 0;
	count = 0;
	while (fgets(line, sizeof(line), infile) != NULL)
	{
		ptr = strtok(line, ", \n");
		while (ptr != NULL)
		{
			if (sscanf(ptr, "%s", &tempstring) < 1)
			{
				perror("sscanf bit the dust");
				perror("Dust biting was in checkfiles.\n");
				return(-1);
			}
			/* this counts the fields we are on */
			count++;
			if (count == 3)
			{
				if ((strcmp(tempstring, rooted)) != 0)
				{
					/* file/dir not owned by root!				*/
					/* grab the filename, which should be 		*/
					/* the 9th field on the line and print it	*/
					/* set flag to do this... */
					found = 1;
				}
			}
			if ((found == 1) && (count == 9))
			{
				/* we have a non-rooted file...we should	*/
				/* be at the filename in the sscanf...		*/
				fprintf(outfile, "%s is not owned by root.\n", tempstring);
				/* reset counters */
				found = 0;
				count = 0;
			}
			/* grab another token */
			ptr = strtok(NULL, ", \"\n");
			if (ptr == NULL)
			{
				;
			}
		} /* end while (ptr != NULL) */
		/* reset counters just to be sure... */
		found = 0;
		count = 0;
	} /* end while (fgets...) */

	/* footer */
	fprintf(outfile, "Check above dirs to ensure root ownership.\n");
	fprintf(outfile, "****************************************\n");

	/* clean up		*/
	fclose(outfile);
	fclose(infile);

	if ((system("rm -f /tmp/templist.txt")) < 0)
		  {
					 /* failure */
					 perror("Error rm'ing tempfile...\n");
		perror("Error in checkfiles.\n");
					 return(-1);
		  }

	if (verbose == 1)
	{
		printf("Finished in checkfiles.\n");
	}

	return(0);
}

