void command_report_error(buffer_t* out, const command_t* cmd, int error) { int do_eol = 1; if (NULL == out || NULL == cmd) return; switch (error) { case ENONE: buf_append(out, "OK"); break; case EIGNORE: do_eol = 0; break; case ENOCMD: buf_appendf(out, "ERR: No such command"); break; case ENOSESSION: buf_appendf(out, "ERR: Session not found"); break; case EUSAGE: command_usage(out, cmd); do_eol = 0; break; default: buf_appendf(out, "ERR: %s", strerror(error)); break; } if (do_eol) buf_append_eol(out); }
int cc_sys(buffer_t* out, command_t* cmd, uint8_t argc, char** argv) { db_connection* db; uint8_t num_db = 0, num_db_used = 0; if (NULL == out) return EFAULT; buf_appendf(out, "DB connections:\n"); for (db = db_connections; NULL != db; db = db->next) { num_db++; if (db->in_use) num_db_used++; buf_appendf(out, "%d\t%s\t%s\t%s%s", num_db, DB_CONNECTION_STATES[db->connection_state], db->in_use ? "in use" : "", db->in_transaction ? "(tran)\t" : "", db->has_result ? "result:\t" : "\n"); if (db->has_result) buf_appendf(out, "%d cols\t%d rows\n", db->num_cols, db->num_rows); } buf_appendf(out, "%d/%d connections available (DB reports %d/%d)\n", num_db - num_db_used, num_db, db_avail_connections, db_num_connections); return ENONE; }
static int os_buf_to_tmp_file_posix(Buf *contents, Buf *suffix, Buf *out_tmp_path) { const char *tmp_dir = getenv("TMPDIR"); if (!tmp_dir) { tmp_dir = P_tmpdir; } buf_resize(out_tmp_path, 0); buf_appendf(out_tmp_path, "%s/XXXXXX%s", tmp_dir, buf_ptr(suffix)); int fd = mkstemps(buf_ptr(out_tmp_path), buf_len(suffix)); if (fd < 0) { return ErrorFileSystem; } FILE *f = fdopen(fd, "wb"); if (!f) { zig_panic("fdopen failed"); } size_t amt_written = fwrite(buf_ptr(contents), 1, buf_len(contents), f); if (amt_written != (size_t)buf_len(contents)) zig_panic("write failed: %s", strerror(errno)); if (fclose(f)) zig_panic("close failed"); return 0; }
int cc_send(buffer_t* out, command_t* cmd, uint8_t argc, char** argv) { unsigned int session_id = 0; connection_t* c,* my_c; const char* nickname = NULL; char* endp = NULL,* msg; if (NULL == argv) return EFAULT; if (argc < 3) return EUSAGE; if (strcmp(argv[1], "-a")) { errno = 0; session_id = strtol(argv[1], &endp, 0); if (!session_id || errno || NULL == endp || '\0' != *endp) { nickname = argv[1]; session_id = 0; } } my_c = connect_findbybuffer(out); if (NULL == my_c) return EDOOFUS; if (!my_c->info.has_admin) return EACCES; argv += 2; msg = command_sjoin(" ", (const char**)argv); if (NULL == msg) return errno; for (c = connections; NULL != c; c = c->next) { if (session_id && c->info.connection_id != session_id) continue; if (NULL != nickname) if (NULL == c->info.nickname || strcmp(nickname, c->info.nickname)) continue; if (!session_id && c == my_c) continue; /* don't send to self, unless explicitly */ if (session_id) session_id = 0; /* mark as sent */ buf_appendf(c->out, "%s\n", msg); } if (session_id) return ENOSESSION; return ENONE; }
void errlog(int type, char *fmt,...) { va_list args; BUFFER *msg; FILE *e = NULL; time_t t; struct tm *tc; char line[LINELEN]; int p; char err[6][8] = {"", "Error", "Warning", "Notice", "Info", "Info"}; if ((VERBOSE == 0 && type != ERRORMSG) || (type == LOG && VERBOSE < 2) || (type == DEBUGINFO && VERBOSE < 3)) return; t = time(NULL); tc = localtime(&t); strftime(line, LINELEN, "[%Y-%m-%d %H:%M:%S] ", tc); msg = buf_new(); buf_appends(msg, line); p = msg->length; buf_appendf(msg, "%s: [%d] ", err[type], getpid()); va_start(args, fmt); buf_vappendf(msg, fmt, args); va_end(args); if (streq(ERRLOG, "stdout")) e = stdout; else if (streq(ERRLOG, "stderr")) e = stderr; if (e == NULL && (ERRLOG[0] == '\0' || (e = mix_openfile(ERRLOG, "a")) == NULL)) mix_status("%s", msg->data + p); else { buf_write(msg, e); if (e != stderr && e != stdout) { fclose(e); /* duplicate the error message on screen */ mix_status("%s", msg->data + p); } } buf_free(msg); }
int chain_select(int hop[], char *chainstr, int maxrem, REMAILER *remailer, int type, BUFFER *feedback) { /* hop[] is returned containing the chain as integers (0 means random like *) * chainstr is the input desired chain such as *,*,*,* * remailer is an input list of remailer details (see mix2_rlist()) */ int len = 0; int i, j, k; BUFFER *chain, *selected, *addr; chain = buf_new(); selected = buf_new(); addr = buf_new(); if (chainstr == NULL || chainstr[0] == '\0') buf_sets(chain, CHAIN); else buf_sets(chain, chainstr); /* put the chain backwards: final hop is in hop[0] */ for (i = chain->length; i >= 0; i--) if (i == 0 || chain->data[i - 1] == ',' || chain->data[i - 1] == ';' || chain->data[i - 1] == ':') { for (j = i; isspace(chain->data[j]);) /* ignore whitespace */ j++; if (chain->data[j] == '\0') break; if (chain->data[j] == '*') k = 0; #if 0 else if (isdigit(chain->data[j])) k = atoi(chain->data + j); #endif /* 0 */ else { buf_sets(selected, chain->data + j); rfc822_addr(selected, addr); buf_clear(selected); buf_getline(addr, selected); if (!selected->length) buf_sets(selected, chain->data + j); for (k = 0; k < maxrem; k++) if (((remailer[k].flags.mix && type == 0) || (remailer[k].flags.cpunk && type == 1) || (remailer[k].flags.newnym && type == 2)) && (streq(remailer[k].name, selected->data) || strieq(remailer[k].addr, selected->data) || (selected->data[0] == '@' && strifind(remailer[k].addr, selected->data)))) break; } if (k < 0 || k >= maxrem) { if (feedback != NULL) { buf_appendf(feedback, "No such remailer: %b", selected); buf_nl(feedback); } #if 0 k = 0; #else /* end of 0 */ len = -1; goto end; #endif /* else not 0 */ } hop[len++] = k; if (len >= 20) { /* array passed in is has length 20 */ if (feedback != NULL) { buf_appends(feedback, "Chain too long.\n"); } break; } if (i > 0) chain->data[i - 1] = '\0'; } end: buf_free(chain); buf_free(selected); buf_free(addr); return len; }
void menu_nym(char *nnym) { char nym[maxnym][LINELEN]; char pending[maxnym][LINELEN]; int c, i, num = 0, numpending = 0, select = -1; int edit = 0; BUFFER *nymlist; int s; int pass = 0; char reliability[9]; /* When printing information about a chain, this variable stores the reliability. */ nymlist = buf_new(); strcpy(nym[0], NONANON); strcatn(nym[0], " (", sizeof(nym[0])); strcatn(nym[0], NAME, sizeof(nym[0])); strcatn(nym[0], ")", sizeof(nym[0])); strcpy(nym[1], ANON); num = 2; if (nymlist_read(nymlist) == -1) { user_delpass(); mix_status(""); } else pass = 1; while (nymlist_get(nymlist, nym[num], NULL, NULL, NULL, NULL, NULL, &s) >= 0) { if (s == NYM_OK) { if (num < maxnym) num++; } else if (s == NYM_WAITING) { if (numpending < maxnym) strncpy(pending[numpending++], nym[num], LINELEN); } } buf_free(nymlist); nymselect: clear(); standout(); printw("Select nym:\n\n"); standend(); #ifdef USE_PGP if (pass) printw("c)reate new nym\ne)dit nym\nd)elete nym\n\n"); else printw("[nym passphrase is invalid]\n\n"); #endif /* USE_PGP */ for (i = 0; i < num; i++) printw("%d) %s\n", i, nym[i]); if (numpending > 0) { printw("\n\nWaiting for confirmation: "); for (i = 0; i < numpending; i++) printw("%s ", pending[i]); printw("\n"); } select: if (select != -1) printw("\r%d", select); else printw("\r \r"); refresh(); c = getch(); if (c == erasechar()) c = KEY_BACKSPACE; if (c >= '0' && c <= '9') { if (select == -1) select = c - '0'; else select = 10 * select + c - '0'; if (edit ? select == 0 || select >= num + numpending - 1 : select >= num) { beep(); select = -1; } refresh(); goto select; } else switch (c) { case KEY_BACKSPACE: select /= 10; if (select < 1) select = -1; goto select; case 'q': if (edit) { edit = 0; select = -1; goto nymselect; } break; #ifdef USE_PGP case 'e': if (pass) { if (edit || num + numpending < 3) { edit = 0; select = -1; goto nymselect; } else { clear(); standout(); printw("Edit nym:\n\n"); standend(); for (i = 2; i < num + numpending; i++) printw("%d) %s\n", i - 1, i < num ? nym[i] : pending[i - num]); printw("\n"); select = -1; edit = NYM_MODIFY; goto select; } } break; case 'd': if (pass) { if (edit || num + numpending < 3) { edit = 0; select = -1; goto nymselect; } else { clear(); standout(); printw("Delete nym:\n\n"); standend(); for (i = 2; i < num + numpending; i++) printw("%d) %s\n", i - 1, i < num ? nym[i] : pending[i - num]); printw("\n"); select = -1; edit = NYM_DELETE; goto select; } } break; case '\r': case '\n': if (select == -1 || (edit && select == 0)) { beep(); edit = 0; select = -1; goto nymselect; } if (!edit) { strncpy(nnym, nym[select], LINELEN); return; } /* fallthru */ case 'c': if (pass) { char nymserv[LINELEN] = "*"; char replyblock[5][CHAINMAX], dest[10][LINELEN]; int latent[5], desttype[5]; char mdest[LINELEN], pdest[LINELEN] = "alt.anonymous.messages", psub[LINELEN] = ""; int deflatent = 0, defdesttype = MSG_MAIL; char alias[LINELEN] = ""; BUFFER *name, *opt; char sendchain[CHAINMAX]; int sendnumcopies = 1, rnum = 1; int i; char line[LINELEN]; int acksend = 0, signsend = 0, fixedsize = 0, disable = 0, fingerkey = 1; name = buf_new(); opt = buf_new(); strncpy(sendchain, CHAIN, CHAINMAX); strncpy(mdest, ADDRESS, LINELEN); if (edit) strncpy(alias, select + 1 < num ? nym[select + 1] : pending[select + 1 - num], LINELEN); if (edit == NYM_MODIFY) { nymlist_getnym(alias, NULL, NULL, opt, name, NULL); acksend = bufifind(opt, "+acksend"); signsend = bufifind(opt, "+signsend"); fixedsize = bufifind(opt, "+fixedsize"); disable = bufifind(opt, "+disable"); fingerkey = bufifind(opt, "+fingerkey"); rnum = -1; } newnym: if (!edit) { clear(); standout(); printw("Create a nym:"); standend(); mvprintw(3, 0, "Alias address: "); echo(); wgetnstr(stdscr, alias, LINELEN); noecho(); if (alias[0] == '\0') goto end; for (i = 0; alias[i] > ' ' && alias[i] != '@'; i++) ; alias[i] = '\0'; if (i == 0) goto newnym; mvprintw(4, 0, "Pseudonym: "); echo(); wgetnstr(stdscr, line, LINELEN); noecho(); buf_sets(name, line); menu_chain(nymserv, 2, 0); } if (edit != NYM_DELETE) { for (i = 0; i < 5; i++) { desttype[i] = defdesttype; latent[i] = deflatent; dest[i][0] = '\0'; strcpy(replyblock[i], "*,*,*,*"); } if (rnum != -1) { menu_replychain(&defdesttype, &deflatent, mdest, pdest, psub, replyblock[0]); desttype[0] = defdesttype; latent[0] = deflatent; strncpy(dest[0], desttype[0] == MSG_POST ? pdest : mdest, LINELEN); } } redraw: clear(); standout(); switch (edit) { case NYM_DELETE: printw("Delete nym:"); break; case NYM_MODIFY: printw("Edit nym:"); break; default: printw("Create a nym:"); break; } standend(); loop: { if (!edit) { cl(2, 0); printw("Nym: a)lias address: %s", alias); cl(3, 0); printw(" nym s)erver: %s", nymserv); } if (edit != NYM_DELETE) { cl(4, 0); printw(" p)seudonym: %s", name->data); if (edit) mvprintw(6, 0, "Nym modification:"); else mvprintw(6, 0, "Nym creation:"); } cl(7, 0); chain_reliability(sendchain, 0, reliability); /* chaintype 0=mix */ printw(" c)hain to nym server: %-30s (reliability: %s)", sendchain, reliability); cl(8, 0); printw(" n)umber of redundant copies: %d", sendnumcopies); if (edit != NYM_DELETE) { mvprintw(10, 0, "Configuration:\n"); printw(" A)cknowledge sending: %s\n", acksend ? "yes" : "no"); printw(" S)erver signatures: %s\n", signsend ? "yes" : "no"); printw(" F)ixed size replies: %s\n", fixedsize ? "yes" : "no"); printw(" D)isable: %s\n", disable ? "yes" : "no"); printw(" Finger K)ey: %s\n", fingerkey ? "yes" : "no"); mvprintw(17, 0, "Reply chains:"); cl(18, 0); if (rnum == -1) printw(" create new r)eply block"); else { printw(" number of r)eply chains: %2d reliability", rnum); for (i = 0; i < rnum; i++) { cl(i + 19, 0); chain_reliability(replyblock[i], 1, reliability); /* 1=ek */ printw(" %d) %30s %-31s [%s]", i + 1, desttype[i] == MSG_NULL ? "(cover traffic)" : dest[i], replyblock[i], reliability); } } } move(LINES - 1, COLS - 1); refresh(); c = getch(); if (edit != NYM_DELETE && c >= '1' && c <= '9' && c - '1' < rnum) { menu_replychain(&defdesttype, &deflatent, mdest, pdest, psub, replyblock[c - '1']); desttype[c - '1'] = defdesttype; latent[c - '1'] = deflatent; strncpy(dest[c - '1'], desttype[c - '1'] == MSG_POST ? pdest : mdest, LINELEN); goto redraw; } switch (c) { case 'A': acksend = !acksend; goto redraw; case 'S': signsend = !signsend; goto redraw; case 'F': fixedsize = !fixedsize; goto redraw; case 'D': disable = !disable; goto redraw; case 'K': fingerkey = !fingerkey; goto redraw; case 'q': edit = 0; select = -1; goto nymselect; case '\014': goto redraw; case 'a': cl(2, 0); printw("Nym: a)lias address: "); echo(); wgetnstr(stdscr, alias, LINELEN); noecho(); for (i = 0; alias[i] > ' ' && alias[i] != '@'; i++) ; alias[i] = '\0'; if (i == 0) goto nymselect; goto redraw; case 'p': cl(4, 0); printw(" p)seudonym: "); echo(); wgetnstr(stdscr, line, LINELEN); noecho(); if (line[0] != '\0') buf_sets(name, line); goto redraw; case 'c': menu_chain(sendchain, 0, 0); goto redraw; case 'n': cl(8, 0); printw(" n)umber of redundant copies: "); echo(); wgetnstr(stdscr, line, LINELEN); noecho(); sendnumcopies = strtol(line, NULL, 10); if (sendnumcopies < 1 || sendnumcopies > 10) sendnumcopies = 1; goto redraw; case 'r': cl(18, 0); printw(" number of r)eply chains: "); echo(); wgetnstr(stdscr, line, LINELEN); noecho(); i = rnum; rnum = strtol(line, NULL, 10); if (rnum < 1) rnum = 1; if (rnum > 5) rnum = 5; for (; i < rnum; i++) if (dest[i][0] == '\0') { desttype[i] = defdesttype; latent[i] = deflatent; strncpy(dest[i], defdesttype == MSG_POST ? pdest : mdest, LINELEN); } goto redraw; case 's': menu_chain(nymserv, 2, 0); goto redraw; case '\n': case '\r': { BUFFER *chains; int err; if (rnum == -1) chains = NULL; else { chains = buf_new(); for (i = 0; i < rnum; i++) if (replyblock[i][0] != '\0') { if (desttype[i] == MSG_POST) buf_appendf(chains, "Subject: %s\n", psub); if (desttype[i] == MSG_MAIL) buf_appends(chains, "To: "); else if (desttype[i] == MSG_POST) buf_appends(chains, "Newsgroups: "); else buf_appends(chains, "Null:"); buf_appendf(chains, "%s\n", dest[i]); buf_appendf(chains, "Chain: %s\n", replyblock[i]); buf_appendf(chains, "Latency: %d\n\n", latent[i]); } } create: clear(); buf_setf(opt, " %cacksend %csignsend +cryptrecv %cfixedsize %cdisable %cfingerkey", acksend ? '+' : '-', signsend ? '+' : '-', fixedsize ? '+' : '-', disable ? '+' : '-', fingerkey ? '+' : '-'); if (edit) { mix_status("Preparing nymserver configuration message..."); err = nym_config(edit, alias, NULL, name, sendchain, sendnumcopies, chains, opt); } else { mix_status("Preparing nym creation request..."); err = nym_config(edit, alias, nymserv, name, sendchain, sendnumcopies, chains, opt); } if (err == -3) { beep(); mix_status("Bad passphrase!"); getch(); goto create; } if (err != 0) { mix_genericerror(); beep(); refresh(); } else { if (edit) mix_status("Nymserver configuration message completed."); else mix_status("Nym creation request completed."); } if (chains) buf_free(chains); goto end; } default: beep(); goto loop; } } end: buf_free(name); buf_free(opt); return; } #endif /* USE_PGP */ default: beep(); goto select; } }
int t1_encrypt(int type, BUFFER *message, char *chainstr, int latency, BUFFER *ek, BUFFER *feedback) { BUFFER *b, *rem, *dest, *line, *field, *content; REMAILER remailer[MAXREM]; int badchains[MAXREM][MAXREM]; int maxrem, chainlen = 0; int chain[20]; int hop; int hashmark = 0; int err = 0; b = buf_new(); rem = buf_new(); dest = buf_new(); line = buf_new(); field = buf_new(); content = buf_new(); maxrem = t1_rlist(remailer, badchains); if (maxrem < 1) { clienterr(feedback, "No remailer list!"); err = -1; goto end; } chainlen = chain_select(chain, chainstr, maxrem, remailer, 1, line); if (chainlen < 1) { if (line->length) clienterr(feedback, line->data); else clienterr(feedback, "Invalid remailer chain!"); err = -1; goto end; } if (chain[0] == 0) chain[0] = chain_randfinal(type, remailer, badchains, maxrem, 1, chain, chainlen, 0); if (chain[0] == -1) { clienterr(feedback, "Invalid remailer chain!"); err = -1; goto end; } if (chain_rand(remailer, badchains, maxrem, chain, chainlen, 1, 0) == -1) { clienterr(feedback, "No reliable remailers!"); err = -1; goto end; } while (buf_getheader(message, field, content) == 0) { hdr_encode(content, 0); if (type == MSG_POST && bufieq(field, "newsgroups") && remailer[chain[0]].flags.post) { buf_appendf(dest, "Anon-Post-To: %b\n", content); } else if (type == MSG_MAIL && bufieq(field, "to")) { buf_appendf(dest, "Anon-To: %b\n", content); } else { /* paste header */ if (type == MSG_POST && bufieq(field, "newsgroups")) buf_appendf(dest, "Anon-To: %s\n", MAILtoNEWS); if (hashmark == 0) { buf_appends(b, "##\n"); hashmark = 1; } buf_appendheader(b, field, content); } } buf_nl(b); buf_rest(b, message); buf_move(message, b); if (type != MSG_NULL && dest->length == 0) { clienterr(feedback, "No destination address!"); err = -1; goto end; } if (type == MSG_NULL) { buf_sets(dest, "Null:\n"); } for (hop = 0; hop < chainlen; hop++) { if (hop == 0) { buf_sets(b, "::\n"); buf_cat(b, dest); } else { buf_sets(b, "::\nAnon-To: "); buf_appends(b, remailer[chain[hop - 1]].addr); buf_nl(b); } if (remailer[chain[hop]].flags.latent && latency > 0) buf_appendf(b, "Latent-Time: +%d:00r\n", latency); if (ek && remailer[chain[hop]].flags.ek) { t1_ek(line, ek, hop); buf_appendf(b, "Encrypt-Key: %b\n", line); } buf_nl(b); buf_cat(b, message); #ifdef USE_PGP if (remailer[chain[hop]].flags.pgp) { buf_clear(message); buf_clear(rem); buf_setf(rem, "<%s>", remailer[chain[hop]].addr); err = pgp_encrypt(PGP_ENCRYPT | PGP_REMAIL | PGP_TEXT, b, rem, NULL, NULL, NULL, NULL); if (err < 0) { buf_setf(line, "No PGP key for remailer %s!\n", remailer[chain[hop]].name); clienterr(feedback, line->data); goto end; } buf_appends(message, "::\nEncrypted: PGP\n\n"); buf_cat(message, b); } else #endif /* USE_PGP */ { if (remailer[chain[hop]].flags.pgponly) { buf_setf(line, "PGP encryption needed for remailer %s!\n", remailer[chain[hop]].name); clienterr(feedback, line->data); goto end; } buf_move(message, b); } if (ek && remailer[chain[hop]].flags.ek) buf_appends(message, "\n**\n"); } buf_clear(b); if (chainlen == 0) { buf_appends(b, "::\n"); buf_cat(b, dest); } else { buf_appendf(b, "%s: %s\n", ek ? "::\nAnon-To" : "To", remailer[chain[chainlen - 1]].addr); } buf_nl(b); buf_cat(b, message); buf_move(message, b); end: buf_free(b); buf_free(rem); buf_free(dest); buf_free(line); buf_free(field); buf_free(content); return (err); }