/************************************************/
/* This checks inetd.conf for baddies...	*/
/* This function checks inetd.conf or xinetd.d  */
/* for unwanted services. It outputs the list   */
/* of all servies running (all are unwanted, 	*/
/* right?) to the outfile.			*/
/* If inetd.conf exists or if xinetd.d is 	*/
/* present it also returns a 1 to main to tell  */
/* main to run a check of /etc/hosts.deny.	*/
/*						*/
/* See lsatmain.c for more details...		*/
/************************************************/

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

int checkinetd(release, kernel, filename, verbose)
char release[50];
char kernel[50];
const char *const filename;
int verbose;
{

    char *ptr;
    char line[128];        /* temp line for reading   */
    char tempstring[128];    /* tempstring for inet     */
    char xinetdstring[7][128]; /* tempstring for xinetd entries */
    char Sunos[4]="Sun";    /* for comparison	   */
    char Linux[4]="Lin";    /* for comparison	   */
    char *sunptr=Sunos;     /* char pointer		   */
    char *lptr=Linux;	/* char pointer 	   */
    char myno[1][3]={"no"}; /* heh, no */
    int inetd = 0;		/* do we use inetd?        */
    int xinetd = 0;		/* do we use xinetd? 	   */
    int linecount, field;   /* some vars...		   */
    int emptyflag=1;	/* is inet an empty file?  */
    int inetexists=0;	/* does inet exist?	   */
    int fileval=0;		/* return val   */
    FILE *infile;  		/* tempfile file pointer   */
    FILE *inetfile;    		/* file pointer for checks */
    FILE *tmpfile;              /* file ptr for tempfile   */

    const char * tmp_file = "/tmp/lsat2.lsat"; /* temp file */

    const char * tempfile =NULL;
    const char * shellcode=NULL;
    const char * header   =NULL;

    if (verbose >= 0)
    {
        printf(" Running checkinetd module...\n");
    }


    /* ok, we also check here if we are on a Solaris */
    /* machine. It (AFAIK) still uses inetd.conf up  */
    /* to SunOS 5.8...				 */

    if (strstr(release, sunptr) != NULL)
    {
        inetd = 1;
    }
    /* check the release we are on */
    /* 4/4/2002 See changes in lsatmain.c on this... */
    /* assume kern 2.2.x/2.0.x uses /etc/inetd.conf  */
    if ((kernel[2]=='2') || (kernel[2]=='0'))
    {
        if (strstr(release, lptr) != NULL)
        {
            inetd = 1;
        }
    }
    else
    {
        /* we _should_ be on an xinetd type system */
        xinetd = 1;
    }


    if (inetd == 1) /* we are on a /etc/inetd.conf based system */
    {

        /* check to see if inetd.conf exists at all    */
        if ((inetfile=fopen("/etc/inetd.conf", "r"))!=NULL)
        {
            inetexists=1;
        }
        else
        {
            /* it does not exist */
            inetexists=0;
        }
        fclose(inetfile);
        if (inetexists == 1)
        {

            if (verbose > 0)
            {
                printf(" Checking entries in /etc/inetd.conf\n");
            }

            /* 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.
            */

            header = "inetd.conf entries:\n";
            tempfile = "/tmp/lsat1.lsat";
            shellcode = "grep -v \\# /etc/inetd.conf >/tmp/lsat1.lsat";
            if ((dostuff(tempfile, 0, shellcode, header)) < 0)
	    {
	        /* something went wrong */
		perror(" Creation of list failed.");
		return(-1);
	    }

	    /* now instead of reading the whole file and 	*/
            /* say looking for baddie servies, I consider	*/
            /* that all in there are evil. Merely tell the  */
            /* user what we have found that is open.        */
            /* perhaps also tell them to close them. :)     */

            /* note that if the file is empty, thats great. */
            /* it _should_ mean that they have commented    */
            /* out everything in /etc/inetd.conf		*/

            infile = fopen("/tmp/lsat1.lsat", "r");
            if (infile == NULL)
            {
                perror(" Error opening tmp file.\n");
                return(-1);
            }

            /* create another tmp file for entries... */
            if ((fileval = open(tmp_file, O_RDWR | O_CREAT, 0600)) < 0)
    	    {
                perror(" Could not create temporary file...\n");
                perror(" Possible link attack while creating/opening file!\n");
                exit(-1);
            }
            /* open it for append */
            tmpfile = fopen(tmp_file, "a");
            if (tmpfile == NULL)
	    {
		perror(" Error opening tmp file.\n");
		return(-1);
	    }

            while (fgets(line, sizeof(line), infile) != NULL)
            {
                field=0;
                ptr = strtok(line, ", \"\n");
                if (ptr == NULL)
                {
                    if (linecount == 0)
                    {
                        /* 1st line was empty, must have been */
                        /* an empty file. This _should_ be a  */
                        /* "good thing"....		      */
                        /* set flag, then break.	      */
                        emptyflag = 1;
                    }
                }
                linecount++;
                while (ptr != NULL)
                {
                    if (sscanf(ptr, "%s", tempstring) < 1)
                    {
                        perror(" sscanf bit the dust");
                        perror(" Dust biting was in checkinetd.\n");
                        return(-1);
                    }
                    /* note: we just need the 1st field... */
                    if (field == 0)
                    {
                        fprintf(tmpfile, "%s \n", tempstring);
                    }
                    ptr = strtok(NULL, ", \"\n");
                    if (ptr == NULL)
                    {
                        ;
                    }
                    field++;
                }
            } /* end while(fgets...) */
        } /* end if(inetexists == 1) */
        else
        {
            /* inetd.conf did not exist */
            inetexists=0;
        }
        /* close files in use, but not outfile  */
        fclose(infile);
        /* close the tmp file, do not rm it */
        fclose(tmpfile);
        /* rm tempfile since dostuff will be called */
	/* with the new tmpfile we created	*/
        remove(tempfile);


        /* call dostuff to append the new tmpfile */
	/* to the outfile.			*/
	if (emptyflag == 1)
	{
	    /* no baddies in inetd.conf */
	    header = "No non-essential items found in inetd.conf. Good.\n";
	}
	if (emptyflag == 0)
	{
	    /* found some lines not commented out... */
            header = "Please comment out all of these from inetd.conf.\n";
	}
	if ((dostuff(tmp_file, filename, 0, header)) < 0)
	{
	    /* something went wrong */
	    perror(" Creation of list failed.");
	    return(-1);
	}
    } /* end of RedHat 5.x, 6.x check portion */
    /* note that in the above dostuff it should	*/
    /* have removed the tempfile, so we will    */
    /* reuse it below for xinetd.d entries...   */



    /* if we are on RedHat 7.x we use xinetd.d/ files */
    if (xinetd == 1)
    {

        if (verbose > 0)
        {
            printf(" Checking entries in /etc/xinetd.d/\n");
        }

        /* init the linecount here   */
        linecount = 0;


        /* assume RedHat 7.x box */
        /* read through the files in /etc/xinetd.c and	*/
        /* check for ones that are not disabled.	*/
        tempfile = "/tmp/lsat3.lsat";
        shellcode = "grep disable /etc/xinetd.d/* >/tmp/lsat3.lsat";
        header = "xinetd.d entries:\n";
        if ((dostuff(tempfile, 0, shellcode, header)) < 0)
        {
	    /* something went wrong */
	    perror(" Creation of list failed.");
	    return(-1);
	}


        /* create another tmp file for entries... */
        if ((fileval = open(tmp_file, O_RDWR | O_CREAT, 0600)) < 0)
        {
            perror(" Could not create temporary file...\n");
            perror(" Possible link attack while creating/opening file!\n");
            exit(-1);
        }

        /* tmp file for entries from loop below */
        tmpfile = fopen(tmp_file, "a");
        if (tmpfile == NULL)
        {
            perror(" Error opening tmp file.");
            return(-1);
        }



        /* an entry should look like: 		*/
        /* /etc/xinetd.d/telnet: disable no 	*/
        /* so we will strtok on : and only take */
        /* the 1st element returned.		*/
 	
	/* open the file created w/dostuff	*/
	infile = fopen(tempfile, "r");
        if (infile == NULL)
        {
	     perror(" Error opening tempfile.");
		return(-1);
	}
	linecount = 0;
        while (fgets(line, sizeof(line), infile) != NULL)
        {
            field=0;
            ptr = strtok(line, ", :\n");
            linecount++;
            while (ptr != NULL)
            {
                if ((sscanf(ptr, "%s", xinetdstring[field])) < 1)
                {
                    perror(" sscanf bit the dust");
                    perror(" Dust biting was in checkinetd.\n");
                    return(-1);
                }
                /* print out the line if it is  */
                /* the first field		*/
                if ((field == 2) && (linecount != 0))
                {
                    if ((strcmp(myno[0], xinetdstring[3])) == 0)
		    {
			/* if we get here, must have had a disable = no */
			emptyflag = 0;
                    	fprintf(tmpfile, "%s\t%s", xinetdstring[0], xinetdstring[3]);
                    }
                }
                field++;
                ptr = strtok(NULL, ", :\n");
                if (ptr == NULL)
                {
                    ;
                }
            } /* end while (ptr != NULL) */
        } /* end while (fgets...) */
        
 	/* close the tmp file, do not rm it */
	fclose(tmpfile);
        /* close the infile, rm it. */
        fclose(infile);
        remove(tempfile);

        /* print some footer information */
        if (emptyflag == 1)
        {
            /* there were no disabled = no  lines */
            header = "No enabled xinetd.d services. Good.\n";
        }
        if (emptyflag == 0)
        {
            /* there are services in xinetd.d open */
            header = "It is strongly recommended that you set\ndisable = yes in the files in /etc/xinetd.d/\n";
        }
        if ((dostuff(tmp_file, filename, 0, header)) < 0)
	{
	    /* something went wrong */
	    perror(" Creation of list failed.");
	    return(-1);
	}
        /* clean up... */
    } /* end of RedHat 7.x check portion */

    if (verbose > 0) 
    {
        printf(" Finished module checkinetd.\n");
    }

    /* instead of just returning 0 here */
    /* we return inetextists... 	    */
    /* 0 for no existance, 1 if exists  */
    return(inetexists);
}
