/* * 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; }
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); }
/* * 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; }
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; }