/****************************************/
/* This is the chekftpusers module for  */
/* the lsat program. It check the 	*/
/* /etc/ftpusers file and sees what 	*/
/* entries are NOT there that are in	*/
/* /etc/passwd.				*/
/*					*/
/* see lsatmain.c for more details	*/
/****************************************/

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

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

	char *passptr;		/* ptr to passwd line   */
	char *ftpptr;		/* ptr to ftpusers line */
	/* 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[60][40]; /*temparray. */
	char tempstring[60][40];	/* string to hold ftpusername */
	int i=0;		/* counter variable	*/
	int j=0;		/* counter variable  */
	int k=0;		/* counter variable  */
	int inlist=0;		/* flag for strcmp checks */
	int fileval; 		/* return val for mkstemp */
	int linecount=0;	/* line counter */


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


	/* init temparray */
	for (i=0; i<60; i++)
	{
		for (j=0; j<40; j++)
		{
			temparray[i][j]=0;
		}
	}


	/* "you may ask yourself, how do I work this?" */
	/*				Talking Heads  */
	/* This program will read the /etc/passwd file */
	/* and store the username in an array...       */
	/* It will then read the /etc/ftpusers file    */
	/* and see what entries are NOT in ftpusers.   */		


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


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

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

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

	/* check that /etc/ftpusers exists first */
        if ((system("cat /etc/ftpusers 1>/dev/null 2>/dev/null >/dev/null")) != 0)
        {
                /* ftpusers does not exist.             */
                /* this _could_ be ok for the user      */
                /* give a msg and leave the area.       */
		fprintf(outfile, "/etc/ftpusers does not exist.\n");
		fprintf(outfile, "This could be ok if you are not\n");
		fprintf(outfile, "running ftp or if your ftp daemon\n");
		fprintf(outfile, "does not use /etc/ftpuses.\n");
		fprintf(outfile, "Please triple check your configuration\n");
		fprintf(outfile, "and ensure you do not need /etc/ftpusers.\n\n");
		fprintf(outfile, "*****************************************\n");
		
		/* leave */
		return(0);
	}

	/* 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: checkftpusers\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 checkftpusers...\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 checkftpusers...\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  */

	/* reset counter */
	i = 0;
	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, "%s", temparray[i]) < 1)
			{
				perror("sscanf failed.\n");
				perror("Failure was in module: checkftpusers.\n");
				return(-1);
			}
			passptr = strtok(NULL, ", \n");
			if (passptr == NULL)
			{
				;
			}
		} /* end if (passptr != NULL) */
		/* inc the counter */
		i++;
	} /* end while (fgets...) */


	/* close the passfile */
	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 checkftpusers...\n");
                return(-1);
        }


	/* ok, we have all (we hope) entries from */
	/* /etc/passwd. Now read in /etc/ftpusers */
	/* and compare... I think just one at a   */
	/* time, 'non?				  */


	/* open /etc/ftpusers for read-only */
	ftpfile = fopen("/etc/ftpusers", "r");
	if (ftpfile == NULL)
	{
		perror("Can't open ftpusers!\n");
		perror("Check perms or checki f file exists.\n");
		perror("Recall this file should exist. :)\n");
		perror("Giving up in checkftpusers...\n");
		return(-1);
	}

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

	/* reset counter */
	j = 0;
	/* get a line from the ftpusers file */
	while (fgets(line, sizeof(line), ftpfile) != NULL)
        {
                ftpptr = strtok(line, ", \n");
                /* if not while. ftpusers = 1 entry per line */
                if (ftpptr != NULL)
                {
			if (sscanf(ftpptr, "%s", tempstring[linecount]) < 1)
                        {
                                perror("sscanf failed.\n");
                                perror("Failure was in module: checkftpusers.\n");
                                return(-1);
                        }
			ftpptr = strtok(NULL, ", \n");
                        if (ftpptr == NULL)
                        {
                                ;
                        }
                } /* end if (ftpptr != NULL) */
		/* inc the linec ounter */	
		linecount++;
        } /* end while (fgets...) */


	/* ok, now compare an entry in the userlist */
	/* we have against the entries in ftpusers  */
        for (j = 0; j < i; j++)
        {
		for (k=0; k < linecount; k++)
        	{
			if ((strcmp(temparray[j], tempstring[k])) == 0)
                	{
                		/* match */
				/* set flag that it is in list */
				inlist = 1;
				
                	}
		}
		/* flag was set on run? */
		/* no? then that entry was not in ftpusers list */
		if (inlist == 0)
		{
			fprintf(outfile, "%s\n", temparray[j]);
		}
		/* reset flag */
		inlist = 0;
        }


	/* print some footer information */	
	fprintf(outfile, "\nAbove accounts are NOT in /etc/ftpusers.\n");
	fprintf(outfile, "Ensure that above accounts are in /etc/ftpusers\n");	
	fprintf(outfile, "or that they _really_ do not need to be restricted.\n");
	fprintf(outfile, "****************************************\n");

	/* clean up... */
	fclose(outfile);
	fclose(ftpfile);

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