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

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

	char *ptr;
	char line[1024];        /* temp line for reading   */
	char tempstring[50];    /* tempstring for inet     */
	char Sunos[4]="Sun";    /* for comparison	   */
	char Linux[4]="Lin";    /* for comparison	   */
	char *sunptr=Sunos;     /* char pointer		   */
        char *lptr=Linux;	/* char pointer 	   */
	int inetd = 0;		/* do we use inetd?        */
	int xinetd = 0;		/* do we use xinetd? 	   */
	int linecount, field;   /* some vars...		   */
	int emptyflag=0;	/* is inet an empty file?  */
	int inetexists=0;	/* does inet exist?	   */
	FILE *infile;  		/* tempfile file pointer   */
	FILE *outfile; 		/* output file pointer     */
	FILE *inetfile;    		/* file pointer for checks */

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


	/* open the output file for append. */
	outfile = fopen(filename, "a");
	if (outfile == NULL)
	{
		perror("Error opening outfile.\n");
		perror("Check perms perhaps?\n");
		return(-1);
	}
	
	/* 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 == 1)
        		{
                		printf("Checking entries in /etc/inetd.conf\n");
        		}


			/* print some header info... */
			fprintf(outfile, "****************************************\n");
        		fprintf(outfile, "inetd.conf items not commented out:\n\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.
			*/
			if (system("grep -v \\# /etc/inetd.conf >> /tmp/greplist.txt") == 2)
			{
				perror("Problem executing grep in checkinetd\n");
				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/greplist.txt", "r");
			if (infile == 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;
						break;
					}
					/* otherwise just break... */
					break;
				}
				linecount++;
				while (ptr != NULL)
				{
					if (sscanf(ptr, "%s", &tempstring) < 1)
					{
						perror("sccanf bit the dust");
						return(-1);
					}
					/* note: we just need the 1st field... */
					if (field == 0)
					{
						fprintf(outfile, "%s \n", tempstring);
					}
					ptr = strtok(NULL, ", \"\n");
					if (ptr == NULL)
					{	
						/* freak out */
						break;
					}
					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);
        	if ((system("rm -f /tmp/greplist.txt")) < 0)
        	{
                	/* rhut-rho... problems.. */
                	perror("Can't rm tempfile...\n");
                	perror("Permissions problem??\n");
                	return(-1);
        	}

		/* print some footer information */
        	if (emptyflag == 1)
        	{
                	/* there were no non-commented inetd.conf lines */
                	fprintf(outfile, "\nNo non-essential items found in inetd.conf. Good.\n");
                	fprintf(outfile, "****************************************\n");
        	}
        	if (emptyflag == 0)
        	{
                	/* there were services in inetd.conf left open */
                	fprintf(outfile, "\nIt is strongly recommended that you comment out\n");
                	fprintf(outfile, "all of the above from your /etc/inetd.conf file.\n");
                	fprintf(outfile, "At the very least run tcpwrappers and edit your\n");
                	fprintf(outfile, "/etc/hosts.allow and /etc/hosts.deny files.\n");
                	fprintf(outfile, "\n");
                	fprintf(outfile, "****************************************\n");
        	}
	} /* end of RedHat 5.x, 6.x check portion */

	/* if we are on RedHat 7.x we use xinetd.d/ files */
	if (xinetd == 1)
	{
		
		if (verbose == 1)
        	{
                	printf("Checking entries in /etc/xinetd.d/\n");
        	}

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

		/* Note that the outfile should already be open */
		/* print some header info... */
                fprintf(outfile, "****************************************\n");
                fprintf(outfile, "xinetd.d items not disabled:\n\n");

		/* assume RedHat 7.x box */
		/* read through the files in /etc/xinetd.c and	*/
		/* check for ones that are not disabled.	*/
		if (system("grep disable /etc/xinetd.d/* |grep no >> /tmp/xinetd.txt") < 0)
		{
			perror("Problem executing ls??\n");
			return(-1);
		}
		
		/* open the file we just created */
		infile = fopen("/tmp/xinetd.txt", "r");
                if (infile == NULL)
                {
                        perror("Error opening tmp file.\n");
                        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.		*/
		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;
                                        break;
                                }
                                        /* otherwise just break... */
                                        break;
                        }
                        linecount++;
                       	while (ptr != NULL)
			{
				if ((sscanf(ptr, "%s", &tempstring)) < 1)
				{
					 perror("sccanf bit the dust");
                                         return(-1);
                                }
				/* print out the line if it is  */
				/* the first field		*/
				if ((field == 0) && (linecount != 0))
				{
					fprintf(outfile, "%s\n", tempstring);
			 	}
				field++;
				ptr = strtok(NULL, ", :\n");
				if (ptr == NULL)
                                {
                                	/* freak out */
                                        break;
                                }
			} /* end while (ptr != NULL) */
		} /* end while (fgets...) */

		/* print some footer information */
		if (emptyflag == 1)
		{
			/* there were no disabled = no  lines */
			fprintf(outfile, "\nNo enabled xinetd.d services. Good.\n");
			fprintf(outfile, "****************************************\n");
		}
		if (emptyflag == 0)
		{
			/* there are services in xinetd.d open */
			fprintf(outfile, "\nIt is strongly recommended that you set\n");
			fprintf(outfile, "disable = yes in the files in /etc/xinetd.d/\n");
			fprintf(outfile, "Be sure to read them and be sure you need to \n");
			fprintf(outfile, "enable those services. Also, double check your\n");
			fprintf(outfile, "/etc/hosts.allow and /etc/hosts.deny files\n");
			fprintf(outfile, "and make sure you are denying everyone and explicitly\n");
			fprintf(outfile, "allowing only the hosts you want.\n");
			fprintf(outfile, "Search http://www.cert.org for details on setup of hosts files.\n");
			fprintf(outfile, "\n");
			fprintf(outfile, "****************************************\n");
		}
		/* clean up... */
		fclose(infile);
		if ((system("rm -f /tmp/xinetd.txt")) < 0)
		{
			/* rhut-rho... problems.. */
			perror("Can't rm tempfile...\n");
			perror("Permissions problem??\n");
			return(-1);
		}
	} /* end of RedHat 7.x check portion */
	
	/* now we close the outfile... */
	fclose(outfile);

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

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