/****************************************/
/* This is the checkpasswd module for   */
/* the lsatmain.c program. It checks    */
/* the /etc/passwd file for entries...  */
/* makes sure only root is setuid 0     */
/* checks for accounts that should be   */
/* terminated.                          */
/*					*/
/* see lsatmain.c for more details	*/
/****************************************/

#include "lsatheader.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int checkpasswd(filename, verbose)
const char *const filename;
int verbose;
{

	char *passptr;		/* ptr to passwd file   */
	char *acctptr;		/* ptr to acctlist	*/
	/* note we use awk to get only the first entry in */
	/* the passwd list... we ass|u|me that a username */
	/* will be < 40 chars. :O   => line[40]	          */
	char line[40];	/* array for a line	*/
	char temparray[40][40]; /*temparray. */
	int i=0;				/* counter variable	*/
	int j=0;				/* counter variable  */
	int theuid;
	int field;			/* field counter	*/
	int fileval; 		/* return val for mkstemp */

	/* NOT a comprehensive list yet.	*/
	/* just making sure this works...	*/
	char acctlist[6][10] = {"sys", "uucp", "nuucp", "smtp", "listen", "nobody4"};
	/* num of entries in above list */
	int acctlistnum = 5;

	FILE *outfile;		/* output file pointer 	*/
	FILE *passfile;		/* file pointer to templist file */

	if (verbose == 1)
	{
		printf("Starting checkpasswd module...\n");
	}


	outfile=fopen(filename, "a");
	if (outfile == NULL)
	{
		perror("Can't open outfile!\n");
		perror("Check perms or something...\n");
		return(-1);
	}

	/* print some header info to the outfile...  */
	fprintf(outfile, "\n");
	fprintf(outfile, "****************************************\n");
	fprintf(outfile, "In /etc/passwd file:\n");
	fprintf(outfile, "\n");

	if (verbose == 1)
	{
		printf("Checking passwd file...\n");
	}


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

	/* ok, lets make one pass through the passwd   	*/
	/* note here we only pull the 1st field, which  */
	/* is the "account" name in /etc/passwd.    	*/

	if (system("cat /etc/passwd |awk -F\":\" 'length($1) > 0 {print $1}' 1>/dev/null 2>/dev/null >/tmp/sedlist.txt") < 0)
	{
		perror("Can't open /etc/passwd??\n");
		perror("I should be able to read this and\n");
		perror("it may be that you are not using shadow\n");
		perror("passwords. Check to see if you are.\n");
		perror("Giving up in checkpasswd...\n");
		return(-1);
	}

	/* open the newly created file */
	passfile=fopen("/tmp/sedlist.txt", "r");
	if (passfile == NULL)
	{
		perror("Can't open templist...\n");
		perror("Strange, we just created that file...\n");
		perror("Giving up in checkpasswd...\n");
		return(-1);
	}


	/* Note: IIRC, strtok can not be nested if you */
	/* are going to take another token on each one */
	/* i.e. in checkrpms.c it works since we only  */
	/* strtok once on the outside loop since we 	  */
	/* are guarenteed there is only one line in the*/
	/* file since that is how we created it. That  */
	/* is not the case here....			*/

	/* we therefore only grab one filed from the  	*/
	/* passwd file at a time and print that out.		*/
	/* here we are checking accounts on the system  */
	while (fgets(line, sizeof(line), passfile) != NULL)
	{
		field = 0;
		passptr = strtok(line, ", \n");
		/* if not while. we guarentee not more than */
		/* one entry per line with the cat - awk    */
		if (passptr != NULL)
		{
			if (sscanf(passptr, "%s", temparray[i]) < 1)
			{
				perror("sscanf failed.\n");
				perror("Failure was in module: checkpasswd.\n");
				return(-1);
			}
			i++;
			passptr = strtok(NULL, ", \n");
			if (passptr == NULL)
			{
				;
			}
		} /* end while (passptr != NULL) */
	} /* end while (fgets...) */

	/* in the temparray. we just need   */
	/* to compare that to the entries.. */

	for (i = 0; i < 40; i++)
	{
		for (j = 0; j < acctlistnum; j++)
		{
			if ((strcmp(temparray[i], acctlist[j])) == 0)
			{
				/* match */
				fprintf(outfile, "%s\n", temparray[i]);
			}
		}
	}

	/* print some footer information */
	fprintf(outfile, "Consider checking into the above accounts.\n");
	fprintf(outfile, "Remove any ones not needed.\n");
	fprintf(outfile, "********************\n");


	/* close input file */
	fclose(passfile);
	/* rm the input file */
	if (system("rm -f /tmp/sedlist.txt") < 0)
        {
                perror("Can't rm tempfile??\n");
                perror("Strange, we made the file...\n");
                perror("Giving up in checkpasswd...\n");
                return(-1);
        }

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


	/* check UID filed of passwd file... */

	if (system("cat /etc/passwd |awk -F\":\" 'length($3) > 0 {print $3}' 1>/dev/null 2>/dev/null >/tmp/sedlist.txt") < 0)
	{
		perror("Can't open /etc/passwd??\n");
		perror("I should be able to read this and\n");
		perror("it may be that you are not using shadow\n");
		perror("passwords. Check to see if you are.\n");
		perror("Giving up in checkpasswd...\n");
		return(-1);
	}

	/* open the newly created file */
	passfile=fopen("/tmp/sedlist.txt", "r");
	if (passfile == NULL)
	{
		perror("Can't open templist...\n");
		perror("Strange, we just created that file...\n");
		perror("Giving up in checkpasswd...\n");
		return(-1);
	}

	/* in here we grab one line at a time.		*/
	/* recall each line is a number. We need 	*/
	/* only make sure that all lines (!= 1)	*/
	/* are not == 0 (UID root)...					*/
	i = 0; /* reset counter, use it for line #*/
	while (fgets(line, sizeof(line), passfile) != NULL)
	{
		passptr = strtok(line, ", \n");
		/* if not while. we guarentee not more than */
		/* one entry per line with the cat - awk    */
		if (passptr != NULL)
		{
			if (sscanf(passptr, "%d", &theuid) < 1)
			{
				perror("sscanf failed.\n");
				perror("Errror was in module: checkpasswd.\n");
				return(-1);
			}
			if (i != 0)
			{
				if (theuid == 0)
				{
					/* Note here: temparray should still be 	*/
					/* filled with the system accounts.			*/
					/* we printed out the UID number in the	*/
					/* same order, so we should be ok... :)	*/
					fprintf(outfile, "%s has UID 0!\n", temparray[i]);
					fprintf(outfile, "Only root should have UID=0\n");
				}
			}
			passptr = strtok(NULL, ", \n");
			if (passptr == NULL)
			{
				;
			}
		}
		/* inc the line count */
		i++;
	}

	/* print some footer information */
	fprintf(outfile, "****************************************\n");

	/* clean up... */
	fclose(outfile);
	fclose(passfile);
	if (system("rm -f /tmp/sedlist.txt") < 0)
	{
		perror("Can't rm tempfile??\n");
		perror("Strange, we made the file...\n");
		perror("Giving up in checkpasswd...\n");
		return(-1);
	}

	if (verbose == 1)
	{
		printf("Finished in checkpasswd module.\n");
	}
	return(0);
}
