static int pgp_readkeyring(BUFFER *keys, char *filename) { FILE *keyfile; BUFFER *armored, *line, *tmp; int err = -1; if ((keyfile = mix_openfile(filename, "rb")) == NULL) return (err); armored = buf_new(); buf_read(armored, keyfile); fclose(keyfile); if (pgp_ispacket(armored)) { err = 0; buf_move(keys, armored); } else { line = buf_new(); tmp = buf_new(); while (1) { do if (buf_getline(armored, line) == -1) { goto end_greedy_dearmor; } while (!bufleft(line, begin_pgp)) ; buf_clear(tmp); buf_cat(tmp, line); buf_appends(tmp, "\n"); do { if (buf_getline(armored, line) == -1) { goto end_greedy_dearmor; } buf_cat(tmp, line); buf_appends(tmp, "\n"); } while (!bufleft(line, end_pgp)) ; if (pgp_dearmor(tmp, tmp) == 0) { err = ARMORED; buf_cat(keys, tmp); } } end_greedy_dearmor: buf_free(line); buf_free(tmp); } buf_free(armored); return (err); }
void clienterr(BUFFER *msgbuf, char *err) { if (msgbuf) { buf_sets(msgbuf, "Error: "); buf_appends(msgbuf, err); } else errlog(ERRORMSG, "%s\n", err); }
int pgp_latestkeys(BUFFER* outtxt, int algo) /* returns our latest key from pgpkey.txt in the buffer outtxt * with pgp key header, ascii armored * * Can probably be extended to do this for all keys if we pass * the keyring file and the userid * * IN: algo: PGP_ANY, PGP_ES_RSA, PGP_E_ELG, PGP_S_DSA * OUT: outtxt */ { int err = -1; long expires_found = 0, expires; BUFFER *key, *userid, *tmptxt; KEYRING *keys; key = buf_new(); userid = buf_new(); buf_sets(userid, REMAILERNAME); tmptxt = buf_new(); keys = pgpdb_open(PGPKEY, NULL, 0, PGP_TYPE_PUBLIC); if (keys != NULL) { while (pgpdb_getnext(keys, key, NULL, userid) != -1) { buf_clear(tmptxt); if (pgp_makekeyheader(PGP_PUBKEY, key, tmptxt, NULL, algo) == 0) { buf_rewind(key); pgp_getkey(PK_VERIFY, algo, NULL, NULL, &expires, key, NULL, NULL, NULL, NULL); if (expires == 0 || (expires_found <= expires)) { err = 0; buf_clear(outtxt); buf_appends(outtxt, "Type Bits/KeyID Date User ID\n"); buf_cat(outtxt, tmptxt); buf_nl(outtxt); pgp_armor(key, PGP_ARMOR_KEY); buf_cat(outtxt, key); buf_nl(outtxt); expires_found = expires; } } } pgpdb_close(keys); } buf_free(key); buf_free(userid); buf_free(tmptxt); return (err); }
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 menu_getuserpass(BUFFER *b, int mode) { #ifdef USE_NCURSES char p[LINELEN]; if (menu_initialized) { cl(LINES - 1, 10); if (mode == 0) printw("enter passphrase: "); else printw("re-enter passphrase: "); wgetnstr(stdscr, p, LINELEN); cl(LINES - 1, 10); refresh(); if (mode == 0) buf_appends(b, p); else return (bufeq(b, p)); return (0); } #endif /* USE_NCURSES */ return (-1); }
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; }
static enum rules_token lex_include_string(struct scanner *s, struct xkb_compose_table *table, union lvalue *val_out) { while (is_space(peek(s))) if (next(s) == '\n') return TOK_END_OF_LINE; s->token_line = s->line; s->token_column = s->column; s->buf_pos = 0; if (!chr(s, '\"')) { scanner_err(s, "include statement must be followed by a path"); return TOK_ERROR; } while (!eof(s) && !eol(s) && peek(s) != '\"') { if (chr(s, '%')) { if (chr(s, '%')) { buf_append(s, '%'); } else if (chr(s, 'H')) { const char *home = secure_getenv("HOME"); if (!home) { scanner_err(s, "%%H was used in an include statement, but the HOME environment variable is not set"); return TOK_ERROR; } if (!buf_appends(s, home)) { scanner_err(s, "include path after expanding %%H is too long"); return TOK_ERROR; } } else if (chr(s, 'L')) { char *path = get_locale_compose_file_path(table->locale); if (!path) { scanner_err(s, "failed to expand %%L to the locale Compose file"); return TOK_ERROR; } if (!buf_appends(s, path)) { free(path); scanner_err(s, "include path after expanding %%L is too long"); return TOK_ERROR; } free(path); } else if (chr(s, 'S')) { const char *xlocaledir = get_xlocaledir_path(); if (!buf_appends(s, xlocaledir)) { scanner_err(s, "include path after expanding %%S is too long"); return TOK_ERROR; } } else { scanner_err(s, "unknown %% format (%c) in include statement", peek(s)); return TOK_ERROR; } } else { buf_append(s, next(s)); } } if (!chr(s, '\"')) { scanner_err(s, "unterminated include statement"); return TOK_ERROR; } if (!buf_append(s, '\0')) { scanner_err(s, "include path is too long"); return TOK_ERROR; } val_out->string.str = s->buf; val_out->string.len = s->buf_pos; return TOK_INCLUDE_STRING; }
int v2body(BUFFER *body) { int i, n; BUFFER *to, *newsgroups; BUFFER *temp, *out; BUFFER *line; int type = MSG_MAIL; int subject = 0; line = buf_new(); to = buf_new(); newsgroups = buf_new(); temp = buf_new(); out = buf_new(); n = buf_getc(body); for (i = 0; i < n; i++) { buf_get(body, line, 80); buf_chop(line); if (bufileft(line, "null:")) goto end; if (bufileft(line, "post:")) { type = MSG_POST; if (line->length > 5) { int j = 5; while (j < line->length && isspace(line->data[j])) j++; if (newsgroups->length > 0) buf_appends(newsgroups, ","); buf_append(newsgroups, line->data + j, line->length - j); } } else { if (to->length > 0) buf_appends(to, ","); buf_cat(to, line); } } if (to->length > 0) { buf_appends(out, "To: "); buf_cat(out, to); buf_nl(out); } if (newsgroups->length > 0) { buf_appends(out, "Newsgroups: "); buf_cat(out, newsgroups); buf_nl(out); } n = buf_getc(body); for (i = 0; i < n; i++) { buf_get(body, line, 80); buf_chop(line); if (bufileft(line, "Subject:")) subject = 1; buf_cat(out, line); buf_nl(out); } buf_rest(temp, body); buf_uncompress(temp); buf_set(body, temp); buf_reset(temp); if (buf_lookahead(body, line) == 0 && isline(line, HASHMARK)) { buf_getline(body, line); while (buf_getline(body, line) == 0) { if (bufileft(line, "subject:")) subject = 1; buf_cat(out, line); buf_nl(out); } } if (type == MSG_POST && !subject) buf_appends(out, "Subject: (no subject)\n"); buf_nl(out); buf_rest(out, body); buf_reset(body); mix_pool(out, type, -1); end: buf_free(line); buf_free(to); buf_free(newsgroups); buf_free(temp); buf_free(out); return (0); }
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 pgp_keymgt(int force) { FILE *f = NULL; BUFFER *key, *keybak, *userid, *out, *outkey, *outtxt, *pass, *secout; KEYRING *keys; int err = 0, res, recreate_pubring = 0, dsa_ok = 0; #ifdef USE_IDEA int rsa_ok = 0; #endif /* USE_IDEA */ long expires; LOCK *seclock; key = buf_new(); out = buf_new(); keybak = buf_new(); secout = buf_new(); userid = buf_new(); buf_sets(userid, REMAILERNAME); pass = buf_new(); buf_sets(pass, PASSPHRASE); outtxt = buf_new(); outkey = buf_new(); /* We only want to build RSA keys if we also can do IDEA * This is to not lose any mail should users try our RSA key * with IDEA. */ #ifdef USE_IDEA /* FIXME: pgpdb_getky returns the expiration date from the last key in the keyring * which probably works most of the time if the keys are in the correct order * it doesn't return the latest expiration date (or 0) if the key in question * is before another matching key in the keyring tho */ res = pgpdb_getkey(PK_DECRYPT, PGP_ES_RSA, NULL, NULL, &expires, NULL, NULL, NULL, NULL, NULL, pass); if (force == 2 || res < 0 || (expires > 0 && expires - KEYOVERLAPPERIOD < time(NULL))) { rsa_ok = -1; pgp_keygen(PGP_ES_RSA, 0, userid, pass, PGPKEY, PGPREMSECRING, 0); }; if (force == 0 && (pgpdb_getkey(PK_ENCRYPT, PGP_ES_RSA, NULL, NULL, NULL, NULL, NULL, NULL, NULL, PGPKEY, NULL) < 0) && rsa_ok == 0) rsa_ok = 1; #endif /* USE_IDEA */ /* FIXME: pgpdb_getky returns the expiration date from the last key in the keyring * which probably works most of the time if the keys are in the correct order * it doesn't return the latest expiration date (or 0) if the key in question * is before another matching key in the keyring tho */ res = pgpdb_getkey(PK_DECRYPT, PGP_E_ELG, NULL, NULL, &expires, NULL, NULL, NULL, NULL, NULL, pass); if (force == 2 || res < 0 || (expires > 0 && expires - KEYOVERLAPPERIOD < time(NULL))) { dsa_ok = -1; pgp_keygen(PGP_E_ELG, 0, userid, pass, PGPKEY, PGPREMSECRING, 0); } if (force == 0 && (pgpdb_getkey(PK_ENCRYPT, PGP_E_ELG, NULL, NULL, NULL, NULL, NULL, NULL, NULL, PGPKEY, NULL) > 0) && dsa_ok == 0) dsa_ok = 1; /* No need to rewrite the files - we didn't change a thing */ if ( #ifdef USE_IDEA rsa_ok == 1 && #endif /* USE_IDEA */ dsa_ok == 1) goto end; /* write keys one key per armor to make hand editing easy and old PGP * versions happy */ err = -1; keys = pgpdb_open(PGPKEY, NULL, 0, PGP_TYPE_PUBLIC); if (keys == NULL) recreate_pubring = 1; else { while (pgpdb_getnext(keys, key, NULL, userid) != -1) { buf_clear(outtxt); if (pgp_makekeyheader(PGP_PUBKEY, key, outtxt, NULL, PGP_ANY) == 0) { err = 0; buf_appends(out, "Type Bits/KeyID Date User ID\n"); buf_cat(out, outtxt); buf_nl(out); pgp_armor(key, PGP_ARMOR_KEY); buf_cat(out, key); buf_nl(out); } } pgpdb_close(keys); } if (err != 0) recreate_pubring = 1; err = -1; keys = pgpdb_open(PGPREMSECRING, NULL, 0, PGP_TYPE_PRIVATE); if (keys == NULL) goto end; while (pgpdb_getnext(keys, key, NULL, userid) != -1) { buf_clear(outtxt); buf_clear(outkey); buf_clear(keybak); buf_cat(keybak, key); if (pgp_makekeyheader(PGP_SECKEY, key, outtxt, pass, PGP_ANY) == 0) { err = 0; buf_appends(secout, "Type Bits/KeyID Date User ID\n"); buf_cat(secout, outtxt); buf_nl(secout); pgp_armor(key, PGP_ARMOR_SECKEY); buf_cat(secout, key); buf_nl(secout); } buf_clear(outtxt); if (recreate_pubring && pgp_makepubkey(keybak, outtxt, outkey, pass, PGP_ANY) == 0) { buf_appends(out, "Type Bits/KeyID Date User ID\n"); buf_cat(out, outtxt); buf_nl(out); pgp_armor(outkey, PGP_ARMOR_KEY); buf_cat(out, outkey); buf_nl(out); } } pgpdb_close(keys); seclock = lockfile(PGPREMSECRING); if (err == 0 && (f = mix_openfile(PGPREMSECRING, "w")) != NULL) { buf_write(secout, f); fclose(f); } else err = -1; unlockfile(seclock); if (err == 0 && (f = mix_openfile(PGPKEY, "w")) != NULL) { buf_write(out, f); fclose(f); } else err = -1; end: buf_free(key); buf_free(keybak); buf_free(out); buf_free(userid); buf_free(pass); buf_free(outtxt); buf_free(outkey); buf_free(secout); return (err); }
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); }