/**************************************/
/* 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 */
#include <fcntl.h>

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 */
    /* 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 */
    if ((fileval = open("/tmp/templist.txt", O_RDWR | O_CREAT, 0600)) < 0)
    {
        perror("Could not make file w/perms 0600...\n");
        perror("Possible link attack while creating/opening file!\n");
        perror("Bailing in checkfiles...\n");
        exit(-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 */
    if ((fileval = open("/tmp/templist.txt", O_RDWR | O_CREAT, 0600)) < 0)
    {
        perror("Could not make file w/perms 0600...\n");
        perror("Possible link attack while creating/opening file!\n");
        perror("Bailing in checkfiles...\n");
        exit(-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 */
    if ((fileval = open("/tmp/templist.txt", O_RDWR | O_CREAT, 0600)) < 0)
    {
        perror("Could not make file w/perms 0600...\n");
        perror("Possible link attack while creating/opening file!\n");
        perror("Bailing in checkfiles...\n");
        exit(-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);
}

