Exemplo n.º 1
0
int main(int argc, char *argv[])
{
	char *cfgfn = NULL, *statfn = NULL;
	int i;
	checkdef_t *walk;

#ifdef BIG_SECURITY_HOLE
	drop_root();
#else
	drop_root_and_removesuid(argv[0]);
#endif

	for (i=1; (i<argc); i++) {
		if (strcmp(argv[i], "--clock") == 0) {
			struct timeval tv;
			struct timezone tz;
			struct tm *tm;
			char timestr[50];

			gettimeofday(&tv, &tz);
			printf("epoch: %ld.%06ld\n", (long int)tv.tv_sec, (long int)tv.tv_usec);

			tm = localtime(&tv.tv_sec);
			strftime(timestr, sizeof(timestr), "local: %Y-%m-%d %H:%M:%S %Z", tm);
			printf("%s\n", timestr);

			tm = gmtime(&tv.tv_sec);
			strftime(timestr, sizeof(timestr), "UTC: %Y-%m-%d %H:%M:%S %Z", tm);
			printf("%s\n", timestr);
			return 0;
		}
		else if (i == 1) cfgfn = argv[i];
		else if (i == 2) statfn = argv[i];
	}

	if ((cfgfn == NULL) || (statfn == NULL)) return 1;

	if (loadconfig(cfgfn) != 0) return 1;
	loadlogstatus(statfn);

	for (walk = checklist; (walk); walk = walk->next) {
		char *data;
		checkdef_t *fwalk;

		switch (walk->checktype) {
		  case C_LOG:
			data = logdata(walk->filename, &walk->check.logcheck);
			fprintf(stdout, "[msgs:%s]\n", walk->filename);
			fprintf(stdout, "%s\n", data);

			/* See if there's a special "file:" entry for this logfile */
			for (fwalk = checklist; (fwalk && ((fwalk->checktype != C_FILE) || (strcmp(fwalk->filename, walk->filename) != 0))); fwalk = fwalk->next) ;
			if (fwalk == NULL) {
				/* No specific file: entry, so make sure the logfile metadata is available */
				fprintf(stdout, "[logfile:%s]\n", walk->filename);
				printfiledata(stdout, walk->filename, 0, 0, 0);
			}
			break;

		  case C_FILE:
			fprintf(stdout, "[file:%s]\n", walk->filename);
			printfiledata(stdout, walk->filename, 
					walk->check.filecheck.domd5, 
					walk->check.filecheck.dosha1,
					walk->check.filecheck.dormd160);
			break;

		  case C_DIR:
			fprintf(stdout, "[dir:%s]\n", walk->filename);
			printdirdata(stdout, walk->filename);
			break;

		  case C_COUNT:
			fprintf(stdout, "[linecount:%s]\n", walk->filename);
			printcountdata(stdout, walk);
			break;

		  case C_NONE:
			break;
		}
	}

	savelogstatus(statfn);

	return 0;
}
Exemplo n.º 2
0
int main(int argc, char *argv[])
{
	int argi;
	char *versionfn, *inprogressfn;
	FILE *versionfd, *tarpipefd;
	char version[1024];
	char *newversion = NULL;
	char *newverreq;
	char *updateparam = NULL;
	int  removeself = 0;
	int talkstat = 0;
	sendreturn_t *sres;

#ifdef BIG_SECURITY_HOLE
	/* Immediately drop all root privs, we'll regain them later when needed */
	drop_root();
#else
	/* We WILL not run as suid-root. */
	drop_root_and_removesuid(argv[0]);
#endif

	versionfn = (char *)malloc(strlen(xgetenv("XYMONHOME")) + strlen(CLIENTVERSIONFILE) + 2);
	sprintf(versionfn, "%s/%s", xgetenv("XYMONHOME"), CLIENTVERSIONFILE);
	inprogressfn = (char *)malloc(strlen(xgetenv("XYMONHOME")) + strlen(INPROGRESSFILE) + 2);
	sprintf(inprogressfn, "%s/%s", xgetenv("XYMONHOME"), INPROGRESSFILE);

	versionfd = fopen(versionfn, "r");
	if (versionfd) {
		char *p;
		if (fgets(version, sizeof(version), versionfd) == NULL) *version = '\0';
		p = strchr(version, '\n'); if (p) *p = '\0';
		fclose(versionfd);
	}
	else {
		*version = '\0';
	}

	if (chdir(xgetenv("XYMONHOME")) != 0) {
		errprintf("Cannot chdir to XYMONHOME\n");
		return 1;
	}

	for (argi=1; (argi < argc); argi++) {
		if (strcmp(argv[argi], "--level") == 0) {
			/* For checking what version we're at */
			printf("%s\n", version);
			return 0;
		}
		else if (strcmp(argv[argi], "--reexec") == 0) {
			/*
			 * First step of the update procedure.
			 *
			 * To avoid problems with unpacking a new clientupdate
			 * on top of the running one (some tar's will abort
			 * if they try this), copy ourself to a temp. file and
			 * re-exec it to carry out the update.
			 */
			char tmpfn[PATH_MAX];
			char *srcfn;
			FILE *tmpfd, *srcfd;
			unsigned char buf[8192];
			long n;
			struct stat st;
			int cperr;

			if (!updateparam) {
				errprintf("clientupdate --reexec called with no update version\n");
				return 1;
			}

			if ( (stat(inprogressfn, &st) == 0) && ((getcurrenttime(NULL) - st.st_mtime) < 3600) ) {
				errprintf("Found update in progress or failed update (started %ld minutes ago)\n",
					(long) (getcurrenttime(NULL)-st.st_mtime)/60);
				return 1;
			}
			unlink(inprogressfn);
			tmpfd = fopen(inprogressfn, "w"); if (tmpfd) fclose(tmpfd);

			/* Copy the executable */
			srcfn = argv[0];
			srcfd = fopen(srcfn, "r"); cperr = errno;

			sprintf(tmpfn, "%s/.update.%s.%ld.tmp", 
				xgetenv("XYMONTMP"), xgetenv("MACHINEDOTS"), (long)getcurrenttime(NULL));

			dbgprintf("Starting update by copying %s to %s\n", srcfn, tmpfn);

			unlink(tmpfn);	/* To avoid symlink attacks */
			if (srcfd) { tmpfd = fopen(tmpfn, "w"); cperr = errno; }

			if (!srcfd || !tmpfd) {
				errprintf("Cannot copy executable: %s\n", strerror(cperr));
				return 1;
			}

			while ((n = fread(buf, 1, sizeof(buf), srcfd)) > 0) fwrite(buf, 1, n, tmpfd);
			fclose(srcfd); fclose(tmpfd);

			/* Make sure the temp. binary has execute permissions set */
			chmod(tmpfn, S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP);

			/*
			 * Set the temp. executable suid-root, and exec() it.
			 * If get_root() fails (because clientupdate was installed
			 * without suid-root privs), just carry on and do what we
			 * can without root privs. (It basically just means that
			 * logfetch() and clientupdate() will continue to run without
			 * root privs).
			 */
#ifdef BIG_SECURITY_HOLE
			get_root();
			chown(tmpfn, 0, getgid());
			chmod(tmpfn, S_ISUID|S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP);
			drop_root();
#endif

			/* Run the temp. executable */
			dbgprintf("Running command '%s %s ..remove-self'\n", tmpfn, updateparam);
			execl(tmpfn, tmpfn, updateparam, "--remove-self", (char *)NULL);

			/* We should never go here */
			errprintf("exec() failed to launch update: %s\n", strerror(errno));
			return 1;
		}

		else if (strncmp(argv[argi], "--update=", 9) == 0) {
			newversion = strdup(argv[argi]+9);
			updateparam = argv[argi];
		}
		else if (strcmp(argv[argi], "--remove-self") == 0) {
			removeself = 1;
		}
		else if (strcmp(argv[argi], "--debug") == 0) {
			debug = 1;
		}

		else if (strcmp(argv[argi], "--suid-setup") == 0) {
			/*
			 * Final step of the update procedure.
			 *
			 * Become root to setup suid-root privs on utils that need it.
			 * Note: If get_root() fails, we're left with normal user privileges. That is
			 * OK, because that is how the client was installed originally, then.
			 */
#ifdef BIG_SECURITY_HOLE
			get_root();
			chown("bin/logfetch", 0, getgid());
			chmod("bin/logfetch", S_ISUID|S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP);
			drop_root();
#endif

			return 0;
		}
	}

	if (!newversion) {
		errprintf("No new version string!\n");
		cleanup(inprogressfn, (removeself ? argv[0] : NULL));
		return 1;
	}

	/* Update to version "newversion" */
	dbgprintf("Opening pipe to 'tar'\n");
	tarpipefd = popen("tar xf -", "w");
	if (tarpipefd == NULL) {
		errprintf("Cannot launch 'tar xf -': %s\n", strerror(errno));
		cleanup(inprogressfn, (removeself ? argv[0] : NULL));
		return 1;
	}

	sres = newsendreturnbuf(1, tarpipefd);
	newverreq = (char *)malloc(100+strlen(newversion));
	sprintf(newverreq, "download %s.tar", newversion);
	dbgprintf("Sending command to Xymon: %s\n", newverreq);
	if ((talkstat = sendmessage(newverreq, NULL, XYMON_TIMEOUT, sres)) != XYMONSEND_OK) {
		errprintf("Cannot fetch new client tarfile: Status %d\n", talkstat);
		cleanup(inprogressfn, (removeself ? argv[0] : NULL));
		freesendreturnbuf(sres);
		return 1;
	}
	else {
		dbgprintf("Download command completed OK\n");
		freesendreturnbuf(sres);
	}

	dbgprintf("Closing tar pipe\n");
	if ((talkstat = pclose(tarpipefd)) != 0) {
		errprintf("Upgrade failed, tar exited with status %d\n", talkstat);
		cleanup(inprogressfn, (removeself ? argv[0] : NULL));
		return 1;
	}
	else {
		dbgprintf("tar pipe exited with status 0 (OK)\n");
	}

	/* Create the new version file */
	dbgprintf("Creating new version file %s with version %s\n", versionfn, newversion);
	unlink(versionfn);
	versionfd = fopen(versionfn, "w");
	if (versionfd) {
		fprintf(versionfd, "%s", newversion);
		fclose(versionfd);
	}
	else {
		errprintf("Cannot create version file: %s\n", strerror(errno));
	}

	/* Make sure these have execute permissions */
	dbgprintf("Setting execute permissions on xymonclient.sh and clientupdate tools\n");
	chmod("bin/xymonclient.sh", S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP);
	chmod("bin/clientupdate", S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP);

	/*
	 * Become root to setup suid-root privs on the new clientupdate util.
	 * Note: If get_root() fails, we're left with normal user privileges. That is
	 * OK, because that is how the client was installed originally, then.
	 */
#ifdef BIG_SECURITY_HOLE
	get_root();
	chown("bin/clientupdate", 0, getgid());
	chmod("bin/clientupdate", S_ISUID|S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP);
	drop_root();
#endif

	dbgprintf("Cleaning up after update\n");
	cleanup(inprogressfn, (removeself ? argv[0] : NULL));

	/*
	 * Exec the new client-update utility to fix suid-root permissions on
	 * the new files.
	 */
	execl("bin/clientupdate", "bin/clientupdate", "--suid-setup", (char *)NULL);

	/* We should never go here */
	errprintf("exec() of clientupdate --suid-setup failed: %s\n", strerror(errno));

	return 0;
}