Esempio n. 1
0
/*
 * Set the node event status.
 */
int
mydb_setnodeeventstate(char *nodeid, char *eventtype)
{
	if (! mydb_update("update nodes set eventstate='%s' "
			  "where node_id='%s'",
			  eventtype, nodeid)) {
		error("setnodestatus: DB Error: %s/%s!", nodeid, eventtype);
		return 0;
	}
	return 1;
}
Esempio n. 2
0
int
main(int argc, char **argv)
{
	MYSQL_RES		*res;	
	MYSQL_ROW		row;
	int			tcpsock, ch;
	int			length, i;
	struct sockaddr_in	name;
	struct timeval		timeout;
	struct group		*group;
	struct sigaction	sa;
	sigset_t		actionsigmask;

	while ((ch = getopt(argc, argv, "dp:")) != -1)
		switch(ch) {
		case 'p':
			portnum = atoi(optarg);
			break;
		case 'd':
			debug++;
			break;
		case 'h':
		case '?':
		default:
			usage();
		}
	argc -= optind;
	argv += optind;

	if (argc)
		usage();

	openlog("capserver", LOG_PID, LOG_TESTBED);
	syslog(LOG_NOTICE, "daemon starting");

	if (!debug)
		(void)daemon(0, 0);

	if (!dbinit()) {
		syslog(LOG_ERR, "Could not connect to DB!");
		exit(1);
	}

	sigemptyset(&actionsigmask);
	sigaddset(&actionsigmask, SIGINT);
	sigaddset(&actionsigmask, SIGTERM);
	memset(&sa, 0, sizeof sa);
	sa.sa_handler = sigterm;
	sa.sa_mask = actionsigmask;
	sigaction(SIGINT, &sa, NULL);
	sigaction(SIGTERM, &sa, NULL);

	/*
	 * Grab the GID for the default group.
	 */
	if ((group = getgrnam(TBADMINGROUP)) == NULL) {
		syslog(LOG_ERR, "Getting GID for %s", TBADMINGROUP);
		exit(1);
	}
	admingid = group->gr_gid;

	/*
	 * Setup TCP socket
	 */

	/* Create socket from which to read. */
	tcpsock = socket(AF_INET, SOCK_STREAM, 0);
	if (tcpsock < 0) {
		syslog(LOG_ERR, "opening stream socket: %m");
		exit(1);
	}

	i = 1;
	if (setsockopt(tcpsock, SOL_SOCKET, SO_REUSEADDR,
		       (char *)&i, sizeof(i)) < 0)
		syslog(LOG_ERR, "control setsockopt: %m");;
	
	/* Create name. */
	name.sin_family = AF_INET;
	name.sin_addr.s_addr = INADDR_ANY;
	name.sin_port = htons((u_short) portnum);
	if (bind(tcpsock, (struct sockaddr *) &name, sizeof(name))) {
		syslog(LOG_ERR, "binding stream socket: %m");
		exit(1);
	}
	/* Find assigned port value and print it out. */
	length = sizeof(name);
	if (getsockname(tcpsock, (struct sockaddr *) &name, &length)) {
		syslog(LOG_ERR, "getting socket name: %m");
		exit(1);
	}
	if (listen(tcpsock, 40) < 0) {
		syslog(LOG_ERR, "listening on socket: %m");
		exit(1);
	}
	syslog(LOG_NOTICE, "listening on TCP port %d", ntohs(name.sin_port));

	if (!getuid()) {
		FILE	*fp;
		char    mybuf[BUFSIZ];
	    
		sprintf(mybuf, "%s/capserver.pid", _PATH_VARRUN);
		fp = fopen(mybuf, "w");
		if (fp != NULL) {
			fprintf(fp, "%d\n", getpid());
			(void) fclose(fp);
			Pidname = strdup(mybuf);
		}
	}

	while (1) {
		struct sockaddr_in client;
		int		   clientsock, length = sizeof(client);
		int		   cc, port;
		whoami_t	   whoami;
		unsigned char	   node_id[64];
		tipowner_t	   tipown;
		void		  *reply = &tipown;
		size_t		   reply_size = sizeof(tipown);

		if ((clientsock = accept(tcpsock,
					 (struct sockaddr *)&client,
					 &length)) < 0) {
			if (errno == ECONNABORTED) {
				syslog(LOG_ERR, "accept failed: %m; "
				       "continuing");
				continue;
			}
			syslog(LOG_ERR, "accept failed: %m; exiting");
			exit(1);
		}
		port = ntohs(client.sin_port);
		syslog(LOG_INFO, "%s connected from port %d",
		       inet_ntoa(client.sin_addr), port);

		/*
		 * Check port number of sender. Must be a reserved port.
		 */
		if (port >= IPPORT_RESERVED || port < IPPORT_RESERVED / 2) {
			syslog(LOG_ERR, "Illegal port! Ignoring.");
			goto done;
		}

		/*
		 * Set timeouts
		 */
		timeout.tv_sec  = 6;
		timeout.tv_usec = 0;
		
		if (setsockopt(clientsock, SOL_SOCKET, SO_RCVTIMEO,
			       &timeout, sizeof(timeout)) < 0) {
			syslog(LOG_ERR, "SO_RCVTIMEO failed: %m");
			goto done;
		}
		if (setsockopt(clientsock, SOL_SOCKET, SO_SNDTIMEO,
			       &timeout, sizeof(timeout)) < 0) {
			syslog(LOG_ERR, "SO_SNDTIMEO failed: %m");
			goto done;
		}
		
		/*
		 * Read in the whoami info.
		 */
		if ((cc = read(clientsock, &whoami, sizeof(whoami))) <= 0) {
			if (cc < 0)
				syslog(LOG_ERR, "Reading request: %m");
			syslog(LOG_ERR, "Connection aborted (read)");
			goto done;
		}
		if (cc != sizeof(whoami)) {
			syslog(LOG_ERR, "Wrong byte count (read)!");
			goto done;
		}

		/*
		 * Make sure there is an entry for this tipline in
		 * the DB. If not, we just drop the info with an error
		 * message in the log file. Local tip will still work but
		 * remote tip will not.
		 */
		res = mydb_query("select server,node_id,portnum from tiplines "
				 "where tipname='%s'",
				 3, whoami.name);
		if (!res) {
			syslog(LOG_ERR, "DB Error getting tiplines for %s!",
			       whoami.name);
			goto done;
		}
		if ((int)mysql_num_rows(res) == 0) {
			syslog(LOG_ERR, "No tipline info for %s!",
			       whoami.name);
			mysql_free_result(res);
			goto done;
		}
		row = mysql_fetch_row(res);
		strcpy(node_id, row[1]);
		port = -1;
		sscanf(row[2], "%d", &port);
		mysql_free_result(res);

		/*
		 * Figure out current owner. Might not be a reserved node,
		 * in which case set it to root/wheel by default. 
		 */
		res = mydb_query("select g.unix_gid from reserved as r "
				 "left join experiments as e on "
				 " r.pid=e.pid and r.eid=e.eid "
				 "left join groups as g on "
				 " g.pid=e.pid and g.gid=e.gid "
				 "where r.node_id='%s'",
				 1, node_id);

		if (!res) {
			syslog(LOG_ERR, "DB Error getting info for %s/%s!",
			       node_id, whoami.name);
			goto done;
		}
		if ((int)mysql_num_rows(res)) {
			row = mysql_fetch_row(res);

			tipown.uid = 0;
			if (row[0])
				tipown.gid = atoi(row[0]);
			else
				tipown.gid = admingid;
		}
		else {
			/*
			 * Default to root/root.
			 */
			tipown.uid = 0;
			tipown.gid = admingid;
		}
		mysql_free_result(res);

		if (whoami.portnum == -1) {
			reply = &port;
			reply_size = sizeof(port);
		}
		/*
		 * Update the DB.
		 */
		else if (! mydb_update("update tiplines set portnum=%d, "
				       "keylen=%d, keydata='%s' "
				       "where tipname='%s'", 
				       whoami.portnum,
				       whoami.key.keylen, whoami.key.key,
				       whoami.name)) {
			syslog(LOG_ERR, "DB Error updating tiplines for %s!",
			       whoami.name);
			goto done;
		}

		/*
		 * And now send the reply.
		 */
		if ((cc = write(clientsock, reply, reply_size)) <= 0) {
			if (cc < 0)
				syslog(LOG_ERR, "Writing reply: %m");
			syslog(LOG_ERR, "Connection aborted (write)");
			goto done;
		}
		if (cc != reply_size) {
			syslog(LOG_ERR, "Wrong byte count (write)!");
			goto done;
		}

		syslog(LOG_INFO,
		       "Tipline %s/%s, Port %d, Keylen %d, Key %s, Group %d\n",
		       node_id, whoami.name, whoami.portnum,
		       whoami.key.keylen, whoami.key.key, tipown.gid);
	done:
		close(clientsock);
	}
	close(tcpsock);
	syslog(LOG_NOTICE, "daemon terminating");
	cleanup();
	exit(0);
}
Esempio n. 3
0
/*
 * Set (or clear) event scheduler process ID. A zero is treated as
 * a request to clear it.
 *
 * NOTE: We want to fail if there is already a non-zero value in the DB
 * (although its okay to set it to zero no matter what). 
 */
int
mydb_seteventschedulerpid(char *pid, char *eid, int processid)
{
	MYSQL_RES	*res;
	MYSQL_ROW	row;
	int		retval = 1;

	if (! processid) {
		if (! mydb_update("update experiments set event_sched_pid=0 "
				  "where pid='%s' and eid='%s'",
				  pid, eid)) {
			error("seteventschedulerpid: DB Error(0): %s/%s!",
			      pid, eid);
			return 0;
		}
		return 1;
	}

	if (! mydb_update("lock tables experiments write")) {
		error("seteventschedulerpid: DB Error: locking table!");
		return 0;
	}

	res = mydb_query("select event_sched_pid from experiments "
			 "where pid='%s' and eid='%s'",
			 1, pid, eid);
	
	if (!res) {
		error("seteventschedulerpid: DB Error(1): %s/%s", pid, eid);
		return 0;
	}
	if (! mysql_num_rows(res)) {
		error("seteventschedulerpid: No such experiment: %s/%s",
		      pid, eid);
		retval = 0;
		goto done;
	}
	row = mysql_fetch_row(res);
	
	if (!row[0] || !row[0][0]) {
		error("seteventschedulerpid: Bad value for procid: %s/%s",
		      pid, eid);
		retval = 0;
		goto done;
	}
	if (atoi(row[0]) != 0) {
		info("seteventschedulerpid: A scheduler is running: %s/%s",
		     pid, eid);
		retval = 0;
		goto done;
	}
	if (! mydb_update("update experiments set event_sched_pid=%d "
			  "where pid='%s' and eid='%s'",
			  processid, pid, eid)) {
		error("seteventschedulerpid: DB Error(2): %s/%s!", pid, eid);
		retval = 0;
		goto done;
	}
	retval = 1;
  done:	
	if (! mydb_update("unlock tables")) {
		error("seteventschedulerpid: DB Error: unlocking table!");
		return 0;
	}
	mysql_free_result(res);
	return retval;
}
Esempio n. 4
0
static int
doit(gzFile *infp)
{
	int		i, skip = 0;
	time_t		curtime, ll_time;
	char		*user, node[TBDB_FLEN_NODEID * 2], prog[128];
	char		buf[BUFSIZ], *bp, uid_idx[128], tmp[BUFSIZ];
	struct tm	tm;
	MYSQL_RES	*dbres;
	MYSQL_ROW	dbrow;
	
	while (1) {
		if (gzgets(infp, buf, BUFSIZ) == NULL)
			break;

		/*
		 * If the line does not contain a newline, then we skip it
		 * and try to sync up again. We consider ourselves synced
		 * when the buffer contains a newline in it.
		 */
		if (buf[strlen(buf) - 1] != '\n') {
			skip = 1;
			continue;
		}
		if (skip) {
			skip = 0;
			continue;
 		}

		/*
		 * Thank dog for strptime! Convert the syslog timestamp
		 * into a tm, and then into regular unix time.
		 */
		time(&curtime);
		localtime_r(&curtime, &tm);
		if ((bp = strptime(buf, "%b %e %T", &tm)) == NULL) {
			continue;
		}
		ll_time = mktime(&tm);

		/*
		 * If the constructed time is in the future, then we have
		 * year off by one (cause we are possibly looking at files
		 * created in the previous year). Set the year back by one,
		 * and redo.
		 */
		if (ll_time > curtime) {
			tm.tm_year--;
			ll_time = mktime(&tm);
		}

		/*
		 * Scanf the next part, which looks like:
		 *
		 *	node progname[pid]:
		 *
		 * Ensure we match the proper number of items.
		 */
		bzero(node, sizeof(node));
		if ((sscanf(bp, "%s %s:", node, prog) != 2))
			continue;

		/*
		 * Only sshd matters to us.
		 */
		if (strncmp(prog, SSHD, strlen(SSHD)))
			continue;

		/*
		 * Okay, these kinds of strings matter.
		 *
		 *	FreeBSD:	"Accepted rsa for USER" 
		 *	Linux 6.2:	"log: RSA authentication for USER"
		 *	Linux 7.1:	"session opened for user USER"
		 *      (several ssh2): "Accepted publickey for USER"
		 *      (several ssh2): "Accepted password for USER"
		 *      (several ssh2): "Accepted keyboard-interactive for USER"
		 */
#define L1	"Accepted rsa for "
#define L2	"session opened for user "
#define L3	"log: RSA authentication for "
#define L4	"Accepted publickey for "
#define L5	"Accepted password for "
#define L6	"Accepted keyboard-interactive for "
		
		/* Skip to end of program[pid]: and trailing space */
		bp = strchr(bp, ':');
		bp += 2;

		if (strncmp(bp, L1, strlen(L1)) == 0) {
		  /*fprintf(stdout,"Hit L1: ");*/
			bp += strlen(L1);
		}
		else if (strncmp(bp, L2, strlen(L2)) == 0) {
		  /*fprintf(stdout,"Hit L2: ");*/
			bp += strlen(L2);
		}
		else if (strncmp(bp, L3, strlen(L3)) == 0) {
		  /*fprintf(stdout,"Hit L3: ");*/
			bp += strlen(L3);
		}
		else if (strncmp(bp, L4, strlen(L4)) == 0) {
		  /*fprintf(stdout,"Hit L4: ");*/
			bp += strlen(L4);
		}
		else if (strncmp(bp, L5, strlen(L5)) == 0) {
		  /*fprintf(stdout,"Hit L5: ");*/
			bp += strlen(L5);
		}
		else if (strncmp(bp, L6, strlen(L6)) == 0) {
		  /*fprintf(stdout,"Hit L6: ");*/
			bp += strlen(L6);
		}
		else {
			continue;
		}

		/*
		 * The login name is the next token.
		 */
		if (! (user = strsep(&bp, " ")))
			continue;
		/*fprintf(stdout,"%s on %s\n",user,node);*/

		/* We do not care about ROOT logins. */
		if (strcasecmp(user, "ROOT") == 0)
			continue;

		dbres = mydb_query("select uid_idx from users where uid='%s' "
				   "and status!='archived' and status!='nonlocal'",
				   1, user);

		if (!dbres) {
			syslog(LOG_ERR, "DB error getting user %s", user);
			continue;
		}

		if (!mysql_num_rows(dbres)) {
			syslog(LOG_INFO, "No DB record for user %s", user);
			mysql_free_result(dbres);
			continue;
		}
		dbrow = mysql_fetch_row(dbres);
		strncpy(uid_idx, dbrow[0], sizeof(uid_idx));
		mysql_free_result(dbres);

		/*
		 * Safety first. 
		 */
		mydb_escape_string(tmp, uid_idx, strlen(uid_idx));
		strcpy(uid_idx, tmp);
		mydb_escape_string(tmp, node, strlen(node));
		strcpy(node, tmp);

		if (mydb_update("replace into uidnodelastlogin "
				"(uid, uid_idx, node_id, date, time) "
				"values ('%s', '%s', '%s', "
				"        FROM_UNIXTIME(%ld, '%%Y-%%m-%%d'), "
				"        FROM_UNIXTIME(%ld, '%%T')) ",
				user, uid_idx, node, ll_time, ll_time) == 0)
			break;

		if (strncmp(node, opshostname, strlen(node)) == 0 ||
		    strncmp(node, "ops", strlen(node)) == 0) {
			if (mydb_update("replace into userslastlogin "
					"(uid, uid_idx, date, time) "
					"values ('%s', '%s', "
					"  FROM_UNIXTIME(%ld, '%%Y-%%m-%%d'), "
					"  FROM_UNIXTIME(%ld, '%%T')) ",
					user, uid_idx, ll_time, ll_time) == 0)
				break;
		}
		else {
			if (mydb_update("replace into nodeuidlastlogin "
					"(node_id, uid_idx, uid, date, time) "
					"values ('%s', '%s', '%s', "
					"  FROM_UNIXTIME(%ld, '%%Y-%%m-%%d'), "
					"  FROM_UNIXTIME(%ld, '%%T')) ",
					node, uid_idx, user, ll_time, ll_time) == 0)
				break;
		}
	}
	return 0;
}