/****************************************/
/* This is the checkhostsfiles.c module */
/* for the lsat program. This module    */
/* reads the /etc/hosts.allow and       */
/* /etc/hosts.deny files.		*/
/* It checks for the existance of a 	*/
/* ALL:ALL line in deny, since we think */
/* that a good security policy would be */
/* only admit services we want and deny */
/* all others.				*/
/*					*/
/* See lsatmain.c for more details	*/
/****************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>

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

    int firstall=0; /* counter for target matches		*/
    int found=0;	/* found for target ALL:ALL		*/
    int field;	/* which field in a line we are on	*/
    int linecount;	/* line counter				*/
    int fileval=0;  /* return val         */
    char *ptr; 	/* plain ol' char pointer		*/
    char line[128];  /* for reading in a line from a file 	*/
    char tempstring[128]; /* temp char string		*/
    char target[4]="ALL"; /* what we are looking for 	*/
    FILE *outfile; /* file pointer for output file		*/
    FILE *fileptr;	/* file pointer for input file(s)	*/

    char *strptr = target;

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

    /* open the outfile for append	*/
    outfile = fopen(filename, "a");
    if (outfile == NULL)
    {
        perror("Error opening outfile!\n");
        perror("Check perms or something...\n");
        perror("Error was in module: checkhostfiles.\n");
        return(-1);
    }

    /* write a header for the outfile	*/
    fprintf(outfile, "\n");
    fprintf(outfile, "****************************************\n");

    if (verbose == 1)
    {
        printf("Checking list of entries in hosts.allow\n");
    }

    /* create a temp file for storage */
    if ((fileval = open("/tmp/greplist.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 checkhostsfiles...\n");
        exit(-1);
    }


    /* first off, get the entries in /etc/hosts.allow 	*/
    /* that are not comments...				*/
    /* note: grep returns
    *  0 on match
    *  1 on no match
    *  2 on system/file/read/other failure
    *  HOWEVER, -v inverts the sense of 0,1.
    */
    if (system("grep -v \\# /etc/hosts.allow >> /tmp/greplist.txt") == 2)
    {
        perror("Problem executing grep in module checkhostfiles\n");
        return(-1);
    }

    /* there should be no "ALL:ALL" in here! */
    /* check for it...			 */

    /* open the file...			 */
    fileptr = fopen("/tmp/greplist.txt", "r");
    if (fileptr == NULL)
    {
        perror("Error opening tmp file.\n");
        perror("Error was in checkhostsfiles module.\n");
        return(-1);
    }

    /* start getting lines from it		 */
    while (fgets(line, sizeof(line), fileptr) != NULL)
    {
        field=0;
        firstall=0;
        ptr = strtok(line, ", :\n");
        while (ptr != NULL)
        {
            /* note we want to check for:	*/
            /* a) any lines at all		*/
            /* b) ALL:ALL			*/
            /* c) <anything>:ALL		*/

            if (sscanf(ptr, "%s", &tempstring) < 1)
            {
                perror("sscanf bit the dust.\n");
                perror("Dust biting was in checkhostsfiles.\n");
                return(-1);
            }
            /* check for now */
            printf("%s\n", tempstring);
            if (field == 0)
            {
                if ((strstr(tempstring, strptr)) != NULL)
                {
                    /* found match, 1st field */
                    firstall = 1;
                }
            }
            if (field == 1)
            {
                if (((strstr(tempstring, strptr)) != NULL) &&  (firstall ==1))
                {
                    /* found match, 2nd filed */
                    fprintf(outfile, "ALL:ALL found in hosts.allow.\n");
                    fprintf(outfile, "Please delete that line!\n");
                    fprintf(outfile, "This is a major security risk!\n");
                    fprintf(outfile, "\n");
                }
                if (strstr(tempstring, target) != NULL)
                {
                    /* found match, 2nd filed, but not 1st. */
                    fprintf(outfile, "Found line in hosts.allow that is allowing ALL!\n");
                    fprintf(outfile, "Please delete that line.\n");
                    fprintf(outfile, "This is a major security risk!\n");
                    fprintf(outfile, "\n");
                }
            }
            ptr = strtok(NULL, ", :\n");
            if (ptr == NULL)
            {
                /* freak out */
                break;
            }
            field++;
        } /* end while(ptr!=NULL) */
    } /* end while(fgets...) */

    /* we have checked hosts.allow. Close open files */
    fclose(fileptr);
    /* rm the tempfile we were using		 */
    if ((system("rm -f /tmp/greplist.txt")) < 0)
    {
        /* rhut-rho... problems.. */
        perror("Can't rm tempfile...\n");
        perror("Permissions problem??\n");
        perror("Problem was in module: checkhostfiles.\n");
        return(-1);
    }

    if (verbose == 1)
    {
        printf("Checking entries in hosts.deny\n");
    }

    /* create a temp file for storage */
    if ((fileval = open("/tmp/greplist.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 checkhostsfiles...\n");
        exit(-1);
    }

    /* now then, get the entries in /etc/hosts.deny         */
    /* that are not comments...                             */
    /* note: grep returns
    *  0 on match
    *  1 on no match
    *  2 on system/file/read/other failure
    *  HOWEVER, -v inverts the sense of 0,1.
    */
    if (system("grep -v \\# /etc/hosts.deny >> /tmp/greplist.txt") == 2)
    {
        perror("Problem executing grep in checkhostfiles\n");
        return(-1);
    }

    /* two things to check for:		*/
    /* a) this file should not be empty	*/
    /* b) it should contain ALL:ALL		*/

    /* open the tempfile...			*/
    fileptr = fopen("/tmp/greplist.txt", "r");
    if (fileptr == NULL)
    {
        perror("Error opening tmp file.\n");
        perror("Error was in checkhostsfiles module.\n");
        return(-1);
    }

    /* start getting lines from this file	*/
    linecount=0;
    while (fgets(line, sizeof(line), fileptr) != NULL)
    {
        ptr = strtok(line, ", \n");
        while (ptr != NULL)
        {
            if (sscanf(line, "%s", &tempstring) < 1)
            {
                perror("sscanf bit the dust.\n");
                perror("Dust biting was in checkhostsfiles.\n");
                return(-1);
            }
            if ((strstr(tempstring, "ALL:ALL")) != NULL)
            {
                /* found match, good */
                found = 1;
            }
            ptr = strtok(NULL, ", \n");
            if (ptr == NULL)
            {
                break;
            }
        } /* end while (ptr != NULL) */
        linecount++;
    } /* end while(fgets...) */

    /* if found = 1, there is ALL:ALL */
    if (found == 1)
    {
        fprintf(outfile, "Found ALL:ALL in /etc/hosts.deny. Good.\n");
        fprintf(outfile, "\n");
    }
    if (found == 0)
    {
        fprintf(outfile, "Did not find a ALL:ALL line in /etc/hosts.deny.\n");
        fprintf(outfile, "Please place a line with the following in hosts.deny:\n");
        fprintf(outfile, "ALL:ALL\n");
        fprintf(outfile, "\nIf you need to allow services/hosts \n");
        fprintf(outfile, "do it in hosts.allow for each service/host.\n");
        fprintf(outfile, "\n");
    }
    /* print footer info into outfile... */
    fprintf(outfile, "****************************************\n");

    /* clean up */
    /* rm the tempfile we were using                 */
    if ((system("rm -f /tmp/greplist.txt")) < 0)
    {
        /* rhut-rho... problems.. */
        perror("Can't rm tempfile...\n");
        perror("Permissions problem??\n");
        return(-1);
    }
    fclose(outfile);

    if (verbose == 1)
    {
        printf("Finished module checkhostsfiles.\n");
    }

    return(0);
}
