Merged in default test_diphoton
authorKrista Bennett <krista@pep-project.org>
Sun, 22 Oct 2017 16:52:57 +0200
branchtest_diphoton
changeset 21819545178b557c
parent 2172 572725ae6471
parent 2179 8745babd5d3f
child 2194 27024582896d
Merged in default
src/message_api.c
src/pEpEngine.c
src/pEp_internal.h
     1.1 --- a/src/message_api.c	Tue Oct 17 16:38:03 2017 +0200
     1.2 +++ b/src/message_api.c	Sun Oct 22 16:52:57 2017 +0200
     1.3 @@ -11,6 +11,7 @@
     1.4  #include <assert.h>
     1.5  #include <string.h>
     1.6  #include <stdlib.h>
     1.7 +#include <math.h>
     1.8  
     1.9  
    1.10  #ifndef _MIN
    1.11 @@ -30,7 +31,7 @@
    1.12              size += strlen(_kl->value);
    1.13          }
    1.14  
    1.15 -        char *result = calloc(1, size);
    1.16 +        char *result = calloc(size, 1);
    1.17          if (result == NULL)
    1.18              return NULL;
    1.19  
    1.20 @@ -231,7 +232,7 @@
    1.21      const size_t NL_LEN = 2;
    1.22          
    1.23      const size_t bufsize = PEP_MSG_WRAP_KEY_LEN + strlen(msg_wrap_info) + NL_LEN + strlen(longmsg) + 1;
    1.24 -    char * ptext = calloc(1, bufsize);
    1.25 +    char * ptext = calloc(bufsize, 1);
    1.26      assert(ptext);
    1.27      if (ptext == NULL)
    1.28          return NULL;
    1.29 @@ -270,7 +271,7 @@
    1.30      const size_t NL_LEN = 2;
    1.31  
    1.32      const size_t bufsize = PEP_SUBJ_KEY_LEN + strlen(shortmsg) + NL_LEN + strlen(longmsg) + 1;
    1.33 -    char * ptext = calloc(1, bufsize);
    1.34 +    char * ptext = calloc(bufsize, 1);
    1.35      assert(ptext);
    1.36      if (ptext == NULL)
    1.37          return NULL;
    1.38 @@ -303,6 +304,159 @@
    1.39      return PEP_STATUS_OK;
    1.40  }
    1.41  
    1.42 +unsigned long long get_bitmask(int num_bits) {
    1.43 +    if (num_bits <= 0)
    1.44 +        return 0;
    1.45 +        
    1.46 +    unsigned long long bitmask = 0;
    1.47 +    int i;
    1.48 +    for (i = 1; i < num_bits; i++) {
    1.49 +        bitmask = bitmask << 1;
    1.50 +        bitmask |= 1;
    1.51 +    }
    1.52 +    return bitmask;
    1.53 +}
    1.54 +
    1.55 +static char* get_base_36_rep(unsigned long long value, int num_sig_bits) {
    1.56 +        
    1.57 +    int bufsize = ceil(num_sig_bits / _pEp_log2_36) + 1;
    1.58 +    
    1.59 +    // based on
    1.60 +    // https://en.wikipedia.org/wiki/Base36#C_implementation
    1.61 +    // ok, we supposedly have a 64-bit kinda sorta random blob
    1.62 +    const char base_36_symbols[36] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    1.63 +
    1.64 +    char* retbuf = calloc(bufsize, 1); 
    1.65 +
    1.66 +    int i = bufsize - 1; // (end index)
    1.67 +
    1.68 +    while (i > 0) {
    1.69 +        retbuf[--i] = base_36_symbols[value % 36];
    1.70 +        value /= 36;
    1.71 +    }
    1.72 +
    1.73 +    return retbuf;
    1.74 +}
    1.75 +
    1.76 +
    1.77 +static char* message_id_prand_part(void) {
    1.78 +    // RAND modulus
    1.79 +    int num_bits = _pEp_rand_max_bits;
    1.80 +
    1.81 +    if (num_bits < 0)
    1.82 +        return NULL;
    1.83 +        
    1.84 +    const int DESIRED_BITS = 64;
    1.85 +
    1.86 +    num_bits = _MIN(num_bits, DESIRED_BITS);
    1.87 +    
    1.88 +    int i;
    1.89 +    
    1.90 +    // at least 64 bits
    1.91 +    unsigned long long bitmask = get_bitmask(num_bits);
    1.92 +    
    1.93 +    unsigned long long output_value = 0;
    1.94 +    
    1.95 +    i = DESIRED_BITS;
    1.96 +    
    1.97 +    int bitshift = 0;
    1.98 +    
    1.99 +    while (i > 0) {
   1.100 +        int randval = rand();
   1.101 +        unsigned long long temp_val = randval & bitmask;
   1.102 +
   1.103 +        output_value |= temp_val;
   1.104 +
   1.105 +        i -= num_bits; 
   1.106 +        
   1.107 +        bitshift = _MIN(num_bits, i);
   1.108 +        output_value <<= bitshift;        
   1.109 +        bitmask = get_bitmask(bitshift);
   1.110 +    }
   1.111 +
   1.112 +    return get_base_36_rep(output_value, DESIRED_BITS);
   1.113 +}
   1.114 +
   1.115 +static PEP_STATUS generate_message_id(message* msg) {
   1.116 +
   1.117 +    if (!msg || !msg->from || !msg->from->address)
   1.118 +        return PEP_ILLEGAL_VALUE;
   1.119 +
   1.120 +    char* time_prefix = NULL;
   1.121 +    char* random_id = NULL;
   1.122 +    char* retval = NULL;
   1.123 +    
   1.124 +    size_t buf_len = 2; // NUL + @
   1.125 +    
   1.126 +    char* from_addr = msg->from->address;
   1.127 +    char* domain_ptr = strstr(from_addr, "@");
   1.128 +    if (!domain_ptr || *(domain_ptr + 1) == '\0')
   1.129 +        domain_ptr = "localhost";
   1.130 +    else
   1.131 +        domain_ptr++;
   1.132 +
   1.133 +    buf_len += strlen(domain_ptr);
   1.134 +    
   1.135 +    if (msg->id)
   1.136 +        free(msg->id);
   1.137 +
   1.138 +    msg->id = NULL;
   1.139 +    
   1.140 +    time_t curr_time = time(NULL);
   1.141 +    
   1.142 +    time_prefix = get_base_36_rep(curr_time, ceil(log2(curr_time)));
   1.143 +
   1.144 +    if (!time_prefix)
   1.145 +        goto enomem;
   1.146 +    
   1.147 +    buf_len += strlen(time_prefix);
   1.148 +
   1.149 +    random_id = message_id_prand_part();
   1.150 +
   1.151 +    if (!random_id)
   1.152 +        goto enomem;
   1.153 +    
   1.154 +        
   1.155 +    buf_len += strlen(random_id);
   1.156 +    
   1.157 +    // make a new uuid - depending on rand() impl, time precision, etc,
   1.158 +    // we may still not be unique. We'd better make sure. So. 
   1.159 +    char new_uuid[37];
   1.160 +    pEpUUID uuid;
   1.161 +    uuid_generate_random(uuid);
   1.162 +    uuid_unparse_upper(uuid, new_uuid);
   1.163 +
   1.164 +    buf_len += strlen(new_uuid);
   1.165 +
   1.166 +    buf_len += 6; // "pEp" and 3 '.' chars
   1.167 +
   1.168 +    retval = calloc(buf_len, 1);
   1.169 +    
   1.170 +    if (!retval)
   1.171 +        goto enomem;
   1.172 +    
   1.173 +    strlcpy(retval, "pEp.", buf_len);
   1.174 +    strlcat(retval, time_prefix, buf_len);
   1.175 +    strlcat(retval, ".", buf_len);
   1.176 +    strlcat(retval, random_id, buf_len);
   1.177 +    strlcat(retval, ".", buf_len);
   1.178 +    strlcat(retval, new_uuid, buf_len);        
   1.179 +    strlcat(retval, "@", buf_len);    
   1.180 +    strlcat(retval, domain_ptr, buf_len);    
   1.181 +
   1.182 +    msg->id = retval;
   1.183 +    
   1.184 +    free(time_prefix);
   1.185 +    free(random_id);
   1.186 +    
   1.187 +    return PEP_STATUS_OK;
   1.188 +        
   1.189 +enomem:
   1.190 +    free(time_prefix);
   1.191 +    free(random_id);
   1.192 +    return PEP_OUT_OF_MEMORY;
   1.193 +}
   1.194 +
   1.195  /* 
   1.196     WARNING: For the moment, this only works for the first line of decrypted
   1.197     plaintext because we don't need more. IF WE DO, THIS MUST BE EXPANDED, or
   1.198 @@ -608,12 +762,24 @@
   1.199  static message* wrap_message_as_attachment(message* envelope, 
   1.200      message* attachment, bool keep_orig_subject) {
   1.201      
   1.202 +    if (!attachment)
   1.203 +        return NULL;
   1.204 +    
   1.205      message* _envelope = envelope;
   1.206  
   1.207 +    PEP_STATUS status = PEP_STATUS_OK;
   1.208 +
   1.209      replace_opt_field(attachment, "X-pEp-Version", PEP_VERSION);
   1.210  
   1.211      if (!_envelope) {
   1.212          _envelope = extract_minimal_envelope(attachment, PEP_dir_outgoing);
   1.213 +        status = generate_message_id(_envelope);
   1.214 +        
   1.215 +        if (status != PEP_STATUS_OK) {
   1.216 +            free(_envelope);
   1.217 +            return NULL;
   1.218 +        }
   1.219 +        
   1.220          attachment->longmsg = encapsulate_message_wrap_info("INNER", attachment->longmsg);
   1.221          _envelope->longmsg = encapsulate_message_wrap_info("OUTER", _envelope->longmsg);
   1.222      }
   1.223 @@ -622,8 +788,7 @@
   1.224      }
   1.225      char* message_text = NULL;
   1.226      /* Turn message into a MIME-blob */
   1.227 -    //attachment->enc_format = PEP_enc_none;
   1.228 -    PEP_STATUS status = mime_encode_message(attachment, false, &message_text);
   1.229 +    status = mime_encode_message(attachment, false, &message_text);
   1.230      
   1.231      if (status != PEP_STATUS_OK) {
   1.232          free(_envelope);
   1.233 @@ -1263,6 +1428,8 @@
   1.234          // FIXME - we need to deal with transport types (via flag)
   1.235          if ((max_comm_type | PEP_ct_confirmed) == PEP_ct_pEp) {
   1.236              _src = wrap_message_as_attachment(NULL, src, session->unencrypted_subject);
   1.237 +            if (!_src)
   1.238 +                goto pep_error;
   1.239          }
   1.240          else {
   1.241              // hide subject
   1.242 @@ -1317,8 +1484,8 @@
   1.243  
   1.244      if (msg) {
   1.245          decorate_message(msg, PEP_rating_undefined, NULL);
   1.246 -        if (src->id) {
   1.247 -            msg->id = strdup(src->id);
   1.248 +        if (_src->id) {
   1.249 +            msg->id = strdup(_src->id);
   1.250              assert(msg->id);
   1.251              if (msg->id == NULL)
   1.252                  goto enomem;
   1.253 @@ -1545,7 +1712,7 @@
   1.254      // Add space for the "--"
   1.255      size_t boundary_strlen = (end_boundary - start_boundary) + 2;
   1.256  
   1.257 -    signed_boundary = calloc(1, boundary_strlen + 1);
   1.258 +    signed_boundary = calloc(boundary_strlen + 1, 1);
   1.259      strlcpy(signed_boundary, "--", boundary_strlen + 1);
   1.260      strlcat(signed_boundary, start_boundary, boundary_strlen + 1);
   1.261  
   1.262 @@ -2329,7 +2496,6 @@
   1.263                  goto pep_error;
   1.264          }
   1.265          
   1.266 -        // copy message id to output message        
   1.267          if (src->id && src != msg) {
   1.268              msg->id = strdup(src->id);
   1.269              assert(msg->id);
   1.270 @@ -2635,7 +2801,7 @@
   1.271  
   1.272      max_len = (source1_len > source2_len ? source1_len : source2_len);
   1.273      
   1.274 -    char* XORed_fpr = (char*)(calloc(1,max_len + 1));
   1.275 +    char* XORed_fpr = (char*)(calloc(max_len + 1, 1));
   1.276      *(XORed_fpr + max_len) = '\0';
   1.277      char* result_curr = XORed_fpr + max_len - 1;
   1.278      char* source1_curr = source1 + source1_len - 1;
     2.1 --- a/src/pEpEngine.c	Tue Oct 17 16:38:03 2017 +0200
     2.2 +++ b/src/pEpEngine.c	Sun Oct 22 16:52:57 2017 +0200
     2.3 @@ -8,6 +8,9 @@
     2.4  #include "blacklist.h"
     2.5  #include "sync_fsm.h"
     2.6  
     2.7 +#include <time.h>
     2.8 +#include <stdlib.h>
     2.9 +
    2.10  static volatile int init_count = -1;
    2.11  
    2.12  // sql overloaded functions - modified from sqlite3.c
    2.13 @@ -270,7 +273,7 @@
    2.14      if (_count == 0)
    2.15          in_first = true;
    2.16      
    2.17 -    // Race contition mitigated by calling caveat starts here :
    2.18 +    // Race condition mitigated by calling caveat starts here :
    2.19      // If another call to init() preempts right now, then preemptive call
    2.20      // will have in_first false, will not create SQL tables, and following
    2.21      // calls relying on those tables will fail.
    2.22 @@ -324,6 +327,7 @@
    2.23  
    2.24      int_result = sqlite3_exec(
    2.25              _session->db,
    2.26 +            "PRAGMA locking_mode=NORMAL;\n"
    2.27              "PRAGMA journal_mode=WAL;\n",
    2.28              NULL,
    2.29              NULL,
    2.30 @@ -377,8 +381,8 @@
    2.31                  "create table if not exists log (\n"
    2.32                  "   timestamp integer default (datetime('now')),\n"
    2.33                  "   title text not null,\n"
    2.34 +                "   description text,\n"
    2.35                  "   entity text not null,\n"
    2.36 -                "   description text,\n"
    2.37                  "   comment text\n"
    2.38                  ");\n"
    2.39                  "create index if not exists log_timestamp on log (\n"
    2.40 @@ -571,6 +575,10 @@
    2.41              );
    2.42              assert(int_result == SQLITE_OK);
    2.43          }
    2.44 +        
    2.45 +        // We need to init a few globals for message id that we'd rather not
    2.46 +        // calculate more than once.
    2.47 +        _init_globals();
    2.48      }
    2.49  
    2.50      int_result = sqlite3_prepare_v2(_session->db, sql_log,
    2.51 @@ -784,6 +792,12 @@
    2.52      _session->sync_session = _session;
    2.53  
    2.54      *session = _session;
    2.55 +    
    2.56 +    // Note: Following statement is NOT for any cryptographic/secure functionality; it is
    2.57 +    //       ONLY used for some randomness in generated outer message ID, which are
    2.58 +    //       required by the RFC to be globally unique!
    2.59 +    srand(time(NULL));
    2.60 +    
    2.61      return PEP_STATUS_OK;
    2.62  
    2.63  enomem:
     3.1 --- a/src/pEp_internal.h	Tue Oct 17 16:38:03 2017 +0200
     3.2 +++ b/src/pEp_internal.h	Sun Oct 22 16:52:57 2017 +0200
     3.3 @@ -74,6 +74,7 @@
     3.4  #include <assert.h>
     3.5  #include <stdio.h>
     3.6  #include <ctype.h>
     3.7 +#include <math.h>
     3.8  
     3.9  #ifdef SQLITE3_FROM_OS
    3.10  #include <sqlite3.h>
    3.11 @@ -364,6 +365,17 @@
    3.12      return (char*)retval;
    3.13  }
    3.14  
    3.15 +// These are globals used in generating message IDs and should only be
    3.16 +// computed once, as they're either really constants or OS-dependent
    3.17 +
    3.18 +int _pEp_rand_max_bits;
    3.19 +double _pEp_log2_36;
    3.20 +
    3.21 +static inline void _init_globals() {
    3.22 +    _pEp_rand_max_bits = ceil(log2(RAND_MAX));
    3.23 +    _pEp_log2_36 = log2(36);
    3.24 +}
    3.25 +
    3.26  #ifdef DEBUG_ERRORSTACK
    3.27      PEP_STATUS session_add_error(PEP_SESSION session, const char* file, unsigned line, PEP_STATUS status);
    3.28      #define ADD_TO_LOG(status)   session_add_error(session, __FILE__, __LINE__, (status))
     4.1 --- a/test/Makefile	Tue Oct 17 16:38:03 2017 +0200
     4.2 +++ b/test/Makefile	Sun Oct 22 16:52:57 2017 +0200
     4.3 @@ -10,7 +10,7 @@
     4.4  TARGET=pEpEngineTest
     4.5  
     4.6  unexport GNUPGHOME
     4.7 -TEST_HOME=$(HERE)/test_home
     4.8 +TEST_HOME=$(HERE)test_home
     4.9  TEST_GNUPGHOME=$(TEST_HOME)/gnupg
    4.10  
    4.11  LDFLAGS+= $(ETPAN_LIB) -L../asn.1 -L../src