Example #1
0
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);
}
Example #2
0
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);
}
Example #3
0
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);
}
Example #6
0
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);
}
Example #7
0
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);
}
Example #8
0
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);
}