static void report(const char* id, const char* msg) { wrap_str(str_copyb(&tmp, id, strlen(id) + 1)); wrap_str(str_cats(&tmp, msg)); if (!sendpacket(1, &tmp)) exit(111); }
static void failsys(const char* id, const char* msg) { wrap_str(str_copyb(&tmp, id, strlen(id) + 1)); wrap_str(str_cats(&tmp, msg)); wrap_str(str_cats(&tmp, ": ")); wrap_str(str_cats(&tmp, strerror(errno))); if (!sendpacket(1, &tmp)) exit(111); }
static void make_prq(void) { brandom_fill(nonce, sizeof nonce); pkt_start(&packet, PRQ1); pkt_add_b(&packet, nonce, sizeof nonce); pkt_add_s1c(&packet, AUTHENTICATOR_NAME); wrap_str(str_copys(&keyex_name, nistp224_cb.name)); if (keylist_get(&shared_secrets, &curve25519_cb) != 0) { wrap_str(str_catc(&keyex_name, 0)); wrap_str(str_cats(&keyex_name, curve25519_cb.name)); } pkt_add_s1(&packet, &keyex_name); pkt_add_s1c(&packet, KEYHASH_NAME); pkt_add_s1c(&packet, ENCRYPTOR_NAME); pkt_add_s1c(&packet, "null"); }
static void init_slots(void) { int slot; for (slot = 0; slot < SLOT_MAX; ++slot) { slots[slot].pid = 0; slots[slot].tmpfd = -1; wrap_str(str_ready(&slots[slot].id, 16)); } }
static void handle_packet(struct connection* c) { str* packet; const char* id; const char* runas; const char* command; const char* envstart; long slot; unsigned int i; struct passwd* pw; packet = &c->packet; id = packet->s; if (*id == NUL) FAIL(id, "DInvalid ID"); if ((slot = pick_slot()) < 0) FAIL(id, "DCould not allocate a slot"); wrap_str(str_copys(&slots[slot].id, id)); if ((i = str_findfirst(packet, NUL) + 1) >= packet->len) FAIL(id, "DInvalid packet"); runas = packet->s + i; if (*runas == NUL || (pw = getpwnam(runas)) == 0) FAIL(id, "DInvalid username"); if ((i = str_findnext(packet, NUL, i) + 1) >= packet->len) FAIL(id, "DInvalid packet"); command = packet->s + i; if ((i = str_findnext(packet, NUL, i) + 1) >= packet->len) envstart = 0; else { envstart = packet->s + i; wrap_str(str_catc(packet, 0)); } if (!init_slot(slot, pw)) FAIL(id, "ZOut of memory"); start_slot(slot, command, envstart); }
static void load_keys(const char* server) { str path = {0,0,0}; wrap_str(str_copy4s(&path, keydir, "/servers/", server, ".")); if (!keylist_load_multi(&server_publics, path.s, 0) && !keylist_load_multi(&server_publics, "server.", 0)) die1sys(1, "Could not load server keys"); if (!keylist_load_multi(&client_secrets, "", 0)) { wrap_str(str_copy2s(&path, keydir, "/")); if (!keylist_load_multi(&client_secrets, path.s, 0)) die1sys(1, "Could not load sender keys"); } if (!keylist_exchange_all(&shared_secrets, &server_publics, &client_secrets)) die1(1, "No server keys matched any sender keys"); str_free(&path); }
static void end_slot(int slot, int status) { struct stat st; slots[slot].pid = 0; --slots_used; if (slots[slot].sending_email) { slots[slot].sending_email = 0; if (status) report_slot(slot, "ZJob complete, sending email failed"); else report_slot(slot, "KJob complete, email sent"); } else { /* No header, no possible way to send email. */ if (slots[slot].headerlen == 0) report_slot(slot, "KJob complete, no MAILTO"); else { /* If the job crashed, make sure it is noted. */ if (WIFSIGNALED(status)) { debugf(DEBUG_EXEC, "{slot }d{ Job was killed by signal #}d", slot, WTERMSIG(status)); wrap_str(str_copys(&tmp, "\n\nJob was killed by signal #")); wrap_str(str_cati(&tmp, WTERMSIG(status))); wrap_str(str_catc(&tmp, '\n')); write(slots[slot].tmpfd, tmp.s, tmp.len); } if (fstat(slots[slot].tmpfd, &st) == -1) failsys_slot(slot, "ZCould not fstat"); else if (st.st_size > slots[slot].headerlen) send_email(slot); else report_slot(slot, "KJob complete, no mail sent"); } /* To simplify the procedure, close the temporary file early. * The email sender still has it open, and will effect the final * deletion of the file when it completes. */ if (slots[slot].tmpfd != devnull) close(slots[slot].tmpfd); slots[slot].tmpfd = -1; } }
const char* getprotoenv(const char* name) { static str fullname; const char* env; if (proto == 0) if ((proto = getenv("PROTO")) == 0) proto = "TCP"; if (name == 0 || *name == 0) return proto; wrap_str(str_copy2s(&fullname, proto, name)); if ((env = getenv(fullname.s)) != 0 && env[0] == 0) env = 0; return env; }
static void start_slot(int slot, const char* command, const char* envstart) { static str env; char* period; int fd; char hostname[256]; const char* mailto; const struct passwd* pw = &slots[slot].pw; const char* shell; msg5("(", pw->pw_name, ") CMD (", command, ")"); env.len = 0; wrap_str(envstr_set(&env, "PATH", path, 1)); if (envstart) wrap_str(envstr_from_string(&env, envstart, 1)); wrap_str(envstr_set(&env, "HOME", pw->pw_dir, 1)); wrap_str(envstr_set(&env, "USER", pw->pw_name, 1)); wrap_str(envstr_set(&env, "LOGNAME", pw->pw_name, 1)); if ((shell = envstr_get(&env, "SHELL")) == 0) shell = "/bin/sh"; if ((mailto = envstr_get(&env, "MAILTO")) == 0) mailto = pw->pw_name; if (*mailto == 0) { fd = devnull; slots[slot].headerlen = 0; } else { if ((fd = path_mktemp(tmpprefix, &tmp)) == -1) { failsys_slot(slot, "ZCould not create temporary file"); return; } unlink(tmp.s); cloexec_on(fd); gethostname(hostname, sizeof hostname); wrap_str(str_copyns(&tmp, 6, "To: <", mailto, ">\n", "From: Cron Daemon <root@", hostname, ">\n")); if ((period = strchr(hostname, '.')) != 0) *period = 0; wrap_str(str_catns(&tmp, 7, "Subject: Cron <", pw->pw_name, "@", hostname, "> ", command, "\n\n")); slots[slot].headerlen = tmp.len; if (write(fd, tmp.s, tmp.len) != (long)tmp.len) { close(fd); fd = -1; report_slot(slot, "ZCould not write message header"); return; } } shell_argv[shell_argc+0] = shell; shell_argv[shell_argc+1] = "-c"; shell_argv[shell_argc+2] = command; debugf(DEBUG_EXEC, "{slot }d{ starting: }s", slot, command); if (!forkexec_slot(slot, devnull, fd, shell_argv, &env)) { if (fd != devnull) close(fd); fd = -1; } slots[slot].sending_email = 0; slots[slot].tmpfd = fd; }
void ministat2(const char* base, const char* entry, struct ministat* s) { static str path; wrap_str(str_copy3s(&path, base, "/", entry)); ministat(path.s, s); }