SYNC added fpr/address spoofing protection
authorEdouard Tisserant <edouard@pep-project.org>
Thu, 05 Jan 2017 13:07:31 +0100
changeset 152148efea61cfcd
parent 1518 eb19ed33384a
child 1522 57c2dbcb70dd
SYNC added fpr/address spoofing protection
src/pEp_internal.h
src/sync_impl.c
     1.1 --- a/src/pEp_internal.h	Fri Dec 30 02:13:13 2016 +0100
     1.2 +++ b/src/pEp_internal.h	Thu Jan 05 13:07:31 2017 +0100
     1.3 @@ -54,6 +54,7 @@
     1.4  #include <string.h>
     1.5  #include <assert.h>
     1.6  #include <stdio.h>
     1.7 +#include <ctype.h>
     1.8  
     1.9  #include "sqlite3.h"
    1.10  
    1.11 @@ -170,3 +171,43 @@
    1.12      log_event(session, (TITLE), (ENTITY), (DESC), "debug");
    1.13  #endif
    1.14  
    1.15 +// Space tolerant and case insensitive fingerprint string compare
    1.16 +static inline int _same_fpr(
    1.17 +        const char* fpra,
    1.18 +        size_t fpras,
    1.19 +        const char* fprb,
    1.20 +        size_t fprbs
    1.21 +    )
    1.22 +{
    1.23 +    size_t ai = 0;
    1.24 +    size_t bi = 0;
    1.25 +    
    1.26 +    do
    1.27 +    {
    1.28 +        if(fpra[ai] == 0 || fprb[bi] == 0)
    1.29 +        {
    1.30 +            return 0;
    1.31 +        }
    1.32 +        else if(fpra[ai] == ' ')
    1.33 +        {
    1.34 +            ai++;
    1.35 +        }
    1.36 +        else if(fprb[bi] == ' ')
    1.37 +        {
    1.38 +            bi++;
    1.39 +        }
    1.40 +        else if(toupper(fpra[ai]) == toupper(fprb[bi]))
    1.41 +        {
    1.42 +            ai++;
    1.43 +            bi++;
    1.44 +        }
    1.45 +        else
    1.46 +        {
    1.47 +            return 0;
    1.48 +        }
    1.49 +        
    1.50 +    }
    1.51 +    while(ai < fpras && bi < fprbs);
    1.52 +    
    1.53 +    return ai == fpras && bi == fprbs;
    1.54 +}
     2.1 --- a/src/sync_impl.c	Fri Dec 30 02:13:13 2016 +0100
     2.2 +++ b/src/sync_impl.c	Thu Jan 05 13:07:31 2017 +0100
     2.3 @@ -288,6 +288,47 @@
     2.4                      return PEP_OUT_OF_MEMORY;
     2.5                  }
     2.6  
     2.7 +                // detect and mitigate address spoofing
     2.8 +                Identity check_me = NULL;
     2.9 +                const char* null_terminated_address = 
    2.10 +                    strndup((char *) msg->header.me.address->buf,
    2.11 +                            msg->header.me.address->size);
    2.12 +
    2.13 +                status = get_identity(session, 
    2.14 +                                      null_terminated_address, 
    2.15 +                                      PEP_OWN_USERID, 
    2.16 +                                      &check_me);
    2.17 +
    2.18 +                if (status == PEP_OUT_OF_MEMORY)
    2.19 +                    goto free_all;
    2.20 +
    2.21 +                free_identity(check_me);
    2.22 +
    2.23 +                bool not_own_address = status != PEP_STATUS_OK;
    2.24 +                status = PEP_STATUS_OK;
    2.25 +
    2.26 +                if (not_own_address || 
    2.27 +                    strncmp(src->from->address,
    2.28 +                            (char *) msg->header.me.address->buf,
    2.29 +                            msg->header.me.address->size) != 0 ||
    2.30 +                    strncmp(src->to->ident->address,
    2.31 +                            (char *) msg->header.me.address->buf,
    2.32 +                            msg->header.me.address->size) != 0) {
    2.33 +                    consume = true;
    2.34 +                    goto free_all;
    2.35 +                }
    2.36 +
    2.37 +                // if encrypted, ensure that header.me.fpr match signer's fpr
    2.38 +                if (rating >= PEP_rating_reliable && (
    2.39 +                        !keylist ||
    2.40 +                        !_same_fpr((char *) msg->header.me.fpr.buf,
    2.41 +                                   msg->header.me.fpr.size,
    2.42 +                                   keylist->value,
    2.43 +                                   strlen(keylist->value)))) {
    2.44 +                    consume = true;
    2.45 +                    goto free_all;
    2.46 +                }
    2.47 +
    2.48                  // check message expiry 
    2.49                  if(src->recv) {
    2.50                      time_t expiry = timegm(src->recv) + SYNC_MSG_EXPIRE_TIME;