ENGINE-288: now generating exciting (and different) message IDs for the external envelope when sending a 2.0 message

doc_update_sequoia
Krista Bennett 6 years ago
parent db4fc6e3d8
commit 2cdb226e0f

@ -11,6 +11,7 @@
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#ifndef _MIN
@ -30,7 +31,7 @@ static char * keylist_to_string(const stringlist_t *keylist)
size += strlen(_kl->value);
}
char *result = calloc(1, size);
char *result = calloc(size, 1);
if (result == NULL)
return NULL;
@ -231,7 +232,7 @@ static char * encapsulate_message_wrap_info(const char *msg_wrap_info, const cha
const size_t NL_LEN = 2;
const size_t bufsize = PEP_MSG_WRAP_KEY_LEN + strlen(msg_wrap_info) + NL_LEN + strlen(longmsg) + 1;
char * ptext = calloc(1, bufsize);
char * ptext = calloc(bufsize, 1);
assert(ptext);
if (ptext == NULL)
return NULL;
@ -270,7 +271,7 @@ static char * combine_short_and_long(const char *shortmsg, const char *longmsg)
const size_t NL_LEN = 2;
const size_t bufsize = PEP_SUBJ_KEY_LEN + strlen(shortmsg) + NL_LEN + strlen(longmsg) + 1;
char * ptext = calloc(1, bufsize);
char * ptext = calloc(bufsize, 1);
assert(ptext);
if (ptext == NULL)
return NULL;
@ -303,6 +304,159 @@ static PEP_STATUS replace_subject(message* msg) {
return PEP_STATUS_OK;
}
unsigned long long get_bitmask(int num_bits) {
if (num_bits <= 0)
return 0;
unsigned long long bitmask = 0;
int i;
for (i = 1; i < num_bits; i++) {
bitmask = bitmask << 1;
bitmask |= 1;
}
return bitmask;
}
static char* get_base_36_rep(unsigned long long value, int num_sig_bits) {
int bufsize = ceil(num_sig_bits / _pEp_log2_36) + 1;
// based on
// https://en.wikipedia.org/wiki/Base36#C_implementation
// ok, we supposedly have a 64-bit kinda sorta random blob
const char base_36_symbols[36] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char* retbuf = calloc(bufsize, 1);
int i = bufsize - 1; // (end index)
while (i > 0) {
retbuf[--i] = base_36_symbols[value % 36];
value /= 36;
}
return retbuf;
}
static char* message_id_prand_part(void) {
// RAND modulus
int num_bits = _pEp_rand_max_bits;
if (num_bits < 0)
return NULL;
const int DESIRED_BITS = 64;
num_bits = _MIN(num_bits, DESIRED_BITS);
int i;
// at least 64 bits
unsigned long long bitmask = get_bitmask(num_bits);
unsigned long long output_value = 0;
i = DESIRED_BITS;
int bitshift = 0;
while (i > 0) {
int randval = rand();
unsigned long long temp_val = randval & bitmask;
output_value |= temp_val;
i -= num_bits;
bitshift = _MIN(num_bits, i);
output_value <<= bitshift;
bitmask = get_bitmask(bitshift);
}
return get_base_36_rep(output_value, DESIRED_BITS);
}
static PEP_STATUS generate_message_id(message* msg) {
if (!msg || !msg->from || !msg->from->address)
return PEP_ILLEGAL_VALUE;
char* time_prefix = NULL;
char* random_id = NULL;
char* retval = NULL;
size_t buf_len = 2; // NUL + @
char* from_addr = msg->from->address;
char* domain_ptr = strstr(from_addr, "@");
if (!domain_ptr || *(domain_ptr + 1) == '\0')
domain_ptr = "localhost";
else
domain_ptr++;
buf_len += strlen(domain_ptr);
if (msg->id)
free(msg->id);
msg->id = NULL;
time_t curr_time = time(NULL);
time_prefix = get_base_36_rep(curr_time, ceil(log2(curr_time)));
if (!time_prefix)
goto enomem;
buf_len += strlen(time_prefix);
random_id = message_id_prand_part();
if (!random_id)
goto enomem;
buf_len += strlen(random_id);
// make a new uuid - depending on rand() impl, time precision, etc,
// we may still not be unique. We'd better make sure. So.
char new_uuid[37];
pEpUUID uuid;
uuid_generate_random(uuid);
uuid_unparse_upper(uuid, new_uuid);
buf_len += strlen(new_uuid);
buf_len += 6; // "pEp" and 3 '.' chars
retval = calloc(buf_len, 1);
if (!retval)
goto enomem;
strlcpy(retval, "pEp.", buf_len);
strlcat(retval, time_prefix, buf_len);
strlcat(retval, ".", buf_len);
strlcat(retval, random_id, buf_len);
strlcat(retval, ".", buf_len);
strlcat(retval, new_uuid, buf_len);
strlcat(retval, "@", buf_len);
strlcat(retval, domain_ptr, buf_len);
msg->id = retval;
free(time_prefix);
free(random_id);
return PEP_STATUS_OK;
enomem:
free(time_prefix);
free(random_id);
return PEP_OUT_OF_MEMORY;
}
/*
WARNING: For the moment, this only works for the first line of decrypted
plaintext because we don't need more. IF WE DO, THIS MUST BE EXPANDED, or
@ -608,12 +762,24 @@ enomem:
static message* wrap_message_as_attachment(message* envelope,
message* attachment, bool keep_orig_subject) {
if (!attachment)
return NULL;
message* _envelope = envelope;
PEP_STATUS status = PEP_STATUS_OK;
replace_opt_field(attachment, "X-pEp-Version", PEP_VERSION);
if (!_envelope) {
_envelope = extract_minimal_envelope(attachment, PEP_dir_outgoing);
status = generate_message_id(_envelope);
if (status != PEP_STATUS_OK) {
free(_envelope);
return NULL;
}
attachment->longmsg = encapsulate_message_wrap_info("INNER", attachment->longmsg);
_envelope->longmsg = encapsulate_message_wrap_info("OUTER", _envelope->longmsg);
}
@ -622,8 +788,7 @@ static message* wrap_message_as_attachment(message* envelope,
}
char* message_text = NULL;
/* Turn message into a MIME-blob */
//attachment->enc_format = PEP_enc_none;
PEP_STATUS status = mime_encode_message(attachment, false, &message_text);
status = mime_encode_message(attachment, false, &message_text);
if (status != PEP_STATUS_OK) {
free(_envelope);
@ -1263,6 +1428,8 @@ DYNAMIC_API PEP_STATUS encrypt_message(
// FIXME - we need to deal with transport types (via flag)
if ((max_comm_type | PEP_ct_confirmed) == PEP_ct_pEp) {
_src = wrap_message_as_attachment(NULL, src, session->unencrypted_subject);
if (!_src)
goto pep_error;
}
else {
// hide subject
@ -1317,8 +1484,8 @@ DYNAMIC_API PEP_STATUS encrypt_message(
if (msg) {
decorate_message(msg, PEP_rating_undefined, NULL);
if (src->id) {
msg->id = strdup(src->id);
if (_src->id) {
msg->id = strdup(_src->id);
assert(msg->id);
if (msg->id == NULL)
goto enomem;
@ -1545,7 +1712,7 @@ static PEP_STATUS _get_signed_text(const char* ptext, const size_t psize,
// Add space for the "--"
size_t boundary_strlen = (end_boundary - start_boundary) + 2;
signed_boundary = calloc(1, boundary_strlen + 1);
signed_boundary = calloc(boundary_strlen + 1, 1);
strlcpy(signed_boundary, "--", boundary_strlen + 1);
strlcat(signed_boundary, start_boundary, boundary_strlen + 1);
@ -2329,7 +2496,6 @@ DYNAMIC_API PEP_STATUS _decrypt_message(
goto pep_error;
}
// copy message id to output message
if (src->id && src != msg) {
msg->id = strdup(src->id);
assert(msg->id);
@ -2635,7 +2801,7 @@ DYNAMIC_API PEP_STATUS get_trustwords(
max_len = (source1_len > source2_len ? source1_len : source2_len);
char* XORed_fpr = (char*)(calloc(1,max_len + 1));
char* XORed_fpr = (char*)(calloc(max_len + 1, 1));
*(XORed_fpr + max_len) = '\0';
char* result_curr = XORed_fpr + max_len - 1;
char* source1_curr = source1 + source1_len - 1;

@ -8,6 +8,9 @@
#include "blacklist.h"
#include "sync_fsm.h"
#include <time.h>
#include <stdlib.h>
static volatile int init_count = -1;
// sql overloaded functions - modified from sqlite3.c
@ -270,7 +273,7 @@ DYNAMIC_API PEP_STATUS init(PEP_SESSION *session)
if (_count == 0)
in_first = true;
// Race contition mitigated by calling caveat starts here :
// Race condition mitigated by calling caveat starts here :
// If another call to init() preempts right now, then preemptive call
// will have in_first false, will not create SQL tables, and following
// calls relying on those tables will fail.
@ -378,8 +381,8 @@ DYNAMIC_API PEP_STATUS init(PEP_SESSION *session)
"create table if not exists log (\n"
" timestamp integer default (datetime('now')),\n"
" title text not null,\n"
" entity text not null,\n"
" description text,\n"
" entity text not null,\n"
" comment text\n"
");\n"
"create index if not exists log_timestamp on log (\n"
@ -572,6 +575,10 @@ DYNAMIC_API PEP_STATUS init(PEP_SESSION *session)
);
assert(int_result == SQLITE_OK);
}
// We need to init a few globals for message id that we'd rather not
// calculate more than once.
_init_globals();
}
int_result = sqlite3_prepare_v2(_session->db, sql_log,
@ -785,6 +792,12 @@ DYNAMIC_API PEP_STATUS init(PEP_SESSION *session)
_session->sync_session = _session;
*session = _session;
// Note: Following statement is NOT for any cryptographic/secure functionality; it is
// ONLY used for some randomness in generated outer message ID, which are
// required by the RFC to be globally unique!
srand(time(NULL));
return PEP_STATUS_OK;
enomem:

@ -74,6 +74,7 @@
#include <assert.h>
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#ifdef SQLITE3_FROM_OS
#include <sqlite3.h>
@ -364,6 +365,17 @@ static inline char* _pep_subj_copy() {
return (char*)retval;
}
// These are globals used in generating message IDs and should only be
// computed once, as they're either really constants or OS-dependent
int _pEp_rand_max_bits;
double _pEp_log2_36;
static inline void _init_globals() {
_pEp_rand_max_bits = ceil(log2(RAND_MAX));
_pEp_log2_36 = log2(36);
}
#ifdef DEBUG_ERRORSTACK
PEP_STATUS session_add_error(PEP_SESSION session, const char* file, unsigned line, PEP_STATUS status);
#define ADD_TO_LOG(status) session_add_error(session, __FILE__, __LINE__, (status))

Loading…
Cancel
Save