int mix_dearmor(BUFFER *in, BUFFER *out) { BUFFER *line, *md; int tempbuf = 0; int err = 0; line = buf_new(); md = buf_new(); if (in == out) { tempbuf = 1; out = buf_new(); } do { err = buf_getline(in, line); if (err == -1) goto end; } while (!bufeq(line, begin_remailer)); do { /* skip lines before message digest */ if (buf_getline(in, md) == -1) break; } while (strlen(md->data) != 24); decode(in, out); err = buf_getline(in, line); if (err != 0 || !bufeq(line, end_remailer)) err = -1; else { digest_md5(out, line); encode(line, 0); if (!buf_eq(md, line)) err = -1; if (out->length != 20480) err = -1; } end: if (err == -1) errlog(NOTICE, "Malformatted message.\n"); if (tempbuf) { buf_move(in, out); buf_free(out); } buf_free(line); buf_free(md); return (err); }
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); }
int t1_getreply(BUFFER *msg, BUFFER *ek, int len) { BUFFER *key, *decrypt; int err = -1; int hop = 0; key = buf_new(); decrypt = buf_new(); do { t1_ek(key, ek, hop); buf_set(decrypt, msg); if (pgp_decrypt(decrypt, key, NULL, NULL, NULL) == 0 && decrypt->data != NULL) err = 0, buf_move(msg, decrypt); } while (hop++ < len); return (err); }
memi buf_remove(Buf *buffer, memi offset, memi size) { hale_assert(size <= buf_length(buffer)); hale_assert(offset <= buf_length(buffer)); hale_assert((offset + size) <= buf_length(buffer)); requirement_check_buf(buffer); ch8 *begin = buf_page_begin(buffer) + offset; ch8 *end = buf_page_begin(buffer) + offset + size; memi s; // No gap if (buffer->gap_end == buffer->gap_start) { buffer->gap_start = begin; buffer->gap_end = end; } // Before gap else if (begin <= buffer->gap_start && end <= buffer->gap_start) { // .xx..########### // vv^^ // ...############# // .xxx.#####..... // v--^ // ..#########..... s = buf_move(buffer, end, buffer->gap_start, begin); buffer->gap_start = begin + s; } // Around the gap else if (begin <= buffer->gap_start) { // ..[..]#####..... // ..#########..... // ..[...#####...].. // ..#############.. // ......[#####...].. // ......##########.. // ......#####[...].. // ......##########.. buffer->gap_end = hale_maximum(end + buf_gap(buffer), buffer->gap_end); // Must be done after calling `buf_gap`. Idiot. buffer->gap_start = begin; } // After the gap else if(begin > buffer->gap_start && end > buffer->gap_start) { // ......#####.[..].. // v----^ // .......#########.. begin += buf_gap(buffer); end += buf_gap(buffer); s = buf_move(buffer, buffer->gap_end, begin, buffer->gap_start); buffer->gap_start += s; buffer->gap_end = end; } hale_debug(buffer->debug_length -= size); requirement_check_buf(buffer); return size; }
void buf_insert(Buf *buffer, memi offset, const ch8 *data, memi size) { requirement_check_buf(buffer); // Are we making the gap larger? Do we need to? hale_assert_requirement(buffer->gap_end != buffer->gap_start); hale_assert_requirement(offset < buf_capacity); ch8 *at = buf_page_begin(buffer) + offset; if (at < buffer->gap_start) { // .|....#####..... // ^^^^-vvvv // .|#####......... // forward [at..gap_start] -> [(gap_end-(gap_start-at)) .. gap_end] // => [(at + gap) .. gap_end] buffer->gap_end -= buf_move(buffer, at, buffer->gap_start, at + buf_gap(buffer)); } else if (at > buffer->gap_start) { // .....#####....|. // vvvv-^^^^ // .........|#####. // backward [gap_end..at] -> [gap_start .. gap_start+(at-gap_end)] // [gap_start .. gap_start+at-gap_end] buffer->gap_end += buf_move(buffer, buffer->gap_end, at + buf_gap(buffer), buffer->gap_start); } // .|....#####..... // ++++ // .|++++#......... platform.copy_memory((void*)at, (void*)data, size); buffer->gap_start = at + size; if (((memi)at & ~buf_align_mask) != ((memi)buffer->gap_start & ~buf_align_mask)) { // We're using buffer->gap_start to tell where the buffer's page is at. // However when the buffer is filled, the buffer->gap_start might end // up at the end of the page, which is actually a pointer to the next // page (when masked out). // That only happens when the buffer is fully filled. Asserted below. hale_assert_requirement(buffer->gap_start == buffer->gap_end); // Therefore we're detecting this case and we move the gap to the // beginning of the buffer. buffer->gap_start = buffer->gap_end = (ch8*)((memi)at & ~buf_align_mask); } #if HALE_DEBUG buffer->debug_length += size; #endif requirement_check_buf(buffer); // BUF_DUMP(buffer); }
int pgpdb_getkey(int mode, int algo, int *sym, int *mdc, long *expires, BUFFER *key, BUFFER *userid, BUFFER *founduid, BUFFER *keyid, char *keyring, BUFFER *pass) /* FIXME: This could be changed to return the key with the latest expiration date if * a key is not unique */ { KEYRING *r; BUFFER *id, *thisid, *thiskey; int thisalgo, algofound = -1, needpass = 0; int found = 0; id = buf_new(); thisid = buf_new(); thiskey = buf_new(); if (keyring) r = pgpdb_open(keyring, pass, 0, PGP_TYPE_UNDEFINED); else switch (mode) { case PK_DECRYPT: case PK_SIGN: r = pgpdb_open(PGPREMSECRING, NULL, 0, PGP_TYPE_PRIVATE); break; case PK_ENCRYPT: case PK_VERIFY: r = pgpdb_open(PGPREMPUBASC, NULL, 0, PGP_TYPE_PUBLIC); if (r != NULL && r->filetype == -1) { pgpdb_close(r); r = pgpdb_open(PGPREMPUBRING, NULL, 0, PGP_TYPE_PUBLIC); } break; default: r = NULL; } if (r == NULL) goto end; for (;;) { /* repeat until success or end of key ring */ if (pgpdb_getnext(r, thiskey, keyid, userid) == -1) break; if (keyid) /* pgp_getkey has to chose subkey with given keyid */ buf_set(thisid, keyid); thisalgo = pgp_getkey(mode, algo, sym, mdc, expires, thiskey, thiskey, thisid, founduid, pass); if (thisalgo == PGP_PASS) needpass = 1; if (thisalgo > 0) { found++; if ((thisalgo == pgp_preferredalgo && algofound != pgp_preferredalgo && algofound > 0) || (thisalgo != pgp_preferredalgo && algofound == pgp_preferredalgo)) found--; /* ignore the non-preferred algorithm */ if (found <= 1 || (thisalgo == pgp_preferredalgo && algofound != pgp_preferredalgo && algofound > 0)) { algofound = thisalgo; if (key) buf_move(key, thiskey); buf_set(id, thisid); } } } pgpdb_close(r); end: if (found < 1) { if (needpass) errlog(DEBUGINFO, "Need passphrase!\n"); else if (!sym || *sym != PGP_K_IDEA) { /* kludge: try again with 3DES */ if (userid) errlog(NOTICE, "Key %b not found!\n", userid); else if (keyid && keyid->length > 7) errlog(NOTICE, "Key %02X%02X%02X%02X not found!\n", keyid->data[4], keyid->data[5], keyid->data[6], keyid->data[7]); } } if (found > 1) { if (userid) errlog(WARNING, "Key %b not unique!\n", userid); else if (keyid && keyid->length > 7) errlog(ERRORMSG, "Key %02X%02X%02X%02X not unique!\n", keyid->data[4], keyid->data[5], keyid->data[6], keyid->data[7]); else errlog(WARNING, "Key not unique!\n"); } if (found && keyid) /* return ID of found key */ buf_set(keyid, id); buf_free(thiskey); buf_free(thisid); buf_free(id); return (algofound); }
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); }
static void on_msg_recv_cb(wslay_event_context_ptr ev, const struct wslay_event_on_msg_recv_arg *arg, void *user_data) { struct transaction_t *txn = (struct transaction_t *) user_data; struct ws_context *ctx = (struct ws_context *) txn->ws_ctx; struct buf inbuf = BUF_INITIALIZER, outbuf = BUF_INITIALIZER; struct wslay_event_msg msgarg = { arg->opcode, NULL, 0 }; uint8_t rsv = WSLAY_RSV_NONE; double cmdtime, nettime; const char *err_msg; int r, err_code = 0; /* Place client request into a buf */ buf_init_ro(&inbuf, (const char *) arg->msg, arg->msg_length); /* Decompress request, if necessary */ if (wslay_get_rsv1(arg->rsv)) { /* Add trailing 4 bytes */ buf_appendmap(&inbuf, "\x00\x00\xff\xff", 4); r = zlib_decompress(txn, buf_base(&inbuf), buf_len(&inbuf)); if (r) { syslog(LOG_ERR, "on_msg_recv_cb(): zlib_decompress() failed"); err_code = WSLAY_CODE_PROTOCOL_ERROR; err_msg = DECOMP_FAILED_ERR; goto err; } buf_move(&inbuf, &txn->zbuf); } /* Log the uncompressed client request */ buf_truncate(&ctx->log, ctx->log_tail); buf_appendcstr(&ctx->log, " ("); if (txn->strm_ctx) { buf_printf(&ctx->log, "stream-id=%d; ", http2_get_streamid(txn->strm_ctx)); } buf_printf(&ctx->log, "opcode=%s; rsv=0x%x; length=%ld", wslay_str_opcode(arg->opcode), arg->rsv, arg->msg_length); switch (arg->opcode) { case WSLAY_CONNECTION_CLOSE: buf_printf(&ctx->log, "; status=%d; msg='%s'", arg->status_code, buf_len(&inbuf) ? buf_cstring(&inbuf)+2 : ""); txn->flags.conn = CONN_CLOSE; break; case WSLAY_TEXT_FRAME: case WSLAY_BINARY_FRAME: if (txn->conn->logfd != -1) { /* Telemetry logging */ struct iovec iov[2]; int niov = 0; assert(!buf_len(&txn->buf)); buf_printf(&txn->buf, "<%ld<", time(NULL)); /* timestamp */ WRITEV_ADD_TO_IOVEC(iov, niov, buf_base(&txn->buf), buf_len(&txn->buf)); WRITEV_ADD_TO_IOVEC(iov, niov, buf_base(&inbuf), buf_len(&inbuf)); writev(txn->conn->logfd, iov, niov); buf_reset(&txn->buf); } /* Process the request */ r = ctx->data_cb(&inbuf, &outbuf, &ctx->log, &ctx->cb_rock); if (r) { err_code = (r == HTTP_SERVER_ERROR ? WSLAY_CODE_INTERNAL_SERVER_ERROR : WSLAY_CODE_INVALID_FRAME_PAYLOAD_DATA); err_msg = error_message(r); goto err; } if (txn->conn->logfd != -1) { /* Telemetry logging */ struct iovec iov[2]; int niov = 0; assert(!buf_len(&txn->buf)); buf_printf(&txn->buf, ">%ld>", time(NULL)); /* timestamp */ WRITEV_ADD_TO_IOVEC(iov, niov, buf_base(&txn->buf), buf_len(&txn->buf)); WRITEV_ADD_TO_IOVEC(iov, niov, buf_base(&outbuf), buf_len(&outbuf)); writev(txn->conn->logfd, iov, niov); buf_reset(&txn->buf); } /* Compress the server response, if supported by the client */ if (ctx->ext & EXT_PMCE_DEFLATE) { r = zlib_compress(txn, ctx->pmce.deflate.no_context ? COMPRESS_START : 0, buf_base(&outbuf), buf_len(&outbuf)); if (r) { syslog(LOG_ERR, "on_msg_recv_cb(): zlib_compress() failed"); err_code = WSLAY_CODE_INTERNAL_SERVER_ERROR; err_msg = COMP_FAILED_ERR; goto err; } /* Trim the trailing 4 bytes */ buf_truncate(&txn->zbuf, buf_len(&txn->zbuf) - 4); buf_move(&outbuf, &txn->zbuf); rsv |= WSLAY_RSV1_BIT; } /* Queue the server response */ msgarg.msg = (const uint8_t *) buf_base(&outbuf); msgarg.msg_length = buf_len(&outbuf); wslay_event_queue_msg_ex(ev, &msgarg, rsv); /* Log the server response */ buf_printf(&ctx->log, ") => \"Success\" (opcode=%s; rsv=0x%x; length=%ld", wslay_str_opcode(msgarg.opcode), rsv, msgarg.msg_length); break; } err: if (err_code) { size_t err_msg_len = strlen(err_msg); syslog(LOG_DEBUG, "wslay_event_queue_close()"); wslay_event_queue_close(ev, err_code, (uint8_t *) err_msg, err_msg_len); /* Log the server response */ buf_printf(&ctx->log, ") => \"Fail\" (opcode=%s; rsv=0x%x; length=%ld" "; status=%d; msg='%s'", wslay_str_opcode(WSLAY_CONNECTION_CLOSE), rsv, err_msg_len, err_code, err_msg); } /* Add timing stats */ cmdtime_endtimer(&cmdtime, &nettime); buf_printf(&ctx->log, ") [timing: cmd=%f net=%f total=%f]", cmdtime, nettime, cmdtime + nettime); syslog(LOG_INFO, "%s", buf_cstring(&ctx->log)); buf_free(&inbuf); buf_free(&outbuf); }