src/keymanagement.c
author vb
Wed, 20 Aug 2014 20:20:07 +0200
changeset 22 e235409d570a
parent 21 89f925c7d5be
child 24 50887c6ab78f
permissions -rw-r--r--
bugfix: update_identity
     1 #ifndef WIN32 // UNIX
     2 #define _POSIX_C_SOURCE 200809L
     3 #else
     4 #include "platform_windows.h"
     5 #endif
     6 
     7 #include <string.h>
     8 #include <stdio.h>
     9 #include <stdlib.h>
    10 #include <assert.h>
    11 
    12 #define _EXPORT_PEP_ENGINE_DLL
    13 #include "pEpEngine.h"
    14 #include "keymanagement.h"
    15 
    16 #ifndef MIN
    17 #define MIN(A, B) ((B) > (A) ? (A) : (B))
    18 #endif
    19 
    20 #ifndef EMPTY
    21 #define EMPTY(STR) ((STR == NULL) || (STR)[0] == 0)
    22 #endif
    23 
    24 DYNAMIC_API PEP_STATUS update_identity(
    25         PEP_SESSION session, pEp_identity * identity
    26     )
    27 {
    28     pEp_identity *stored_identity;
    29     PEP_STATUS status;
    30 
    31     assert(session);
    32     assert(identity);
    33     assert(!EMPTY(identity->address));
    34 
    35     status = get_identity(session, identity->address, &stored_identity);
    36     assert(status != PEP_OUT_OF_MEMORY);
    37     if (status == PEP_OUT_OF_MEMORY)
    38         return PEP_OUT_OF_MEMORY;
    39 
    40     if (stored_identity) {
    41         PEP_comm_type _comm_type_key;
    42         status = get_key_rating(session, stored_identity->fpr, &_comm_type_key);
    43         assert(status != PEP_OUT_OF_MEMORY);
    44         if (status == PEP_OUT_OF_MEMORY)
    45             return PEP_OUT_OF_MEMORY;
    46 
    47         if (EMPTY(identity->user_id)) {
    48             free(identity->user_id);
    49             identity->user_id = strdup(stored_identity->user_id);
    50             if (identity->user_id == NULL)
    51                 return PEP_OUT_OF_MEMORY;
    52             identity->user_id_size = stored_identity->user_id_size;
    53         }
    54 
    55         if (EMPTY(identity->username)) {
    56             free(identity->username);
    57             identity->username = strdup(stored_identity->username);
    58             if (identity->username == NULL)
    59                 return PEP_OUT_OF_MEMORY;
    60             identity->username_size = stored_identity->username_size;
    61         }
    62 
    63         if (EMPTY(identity->fpr)) {
    64             identity->fpr = strdup(stored_identity->fpr);
    65             assert(identity->fpr);
    66             if (identity->fpr == NULL)
    67                 return PEP_OUT_OF_MEMORY;
    68             identity->fpr_size = stored_identity->address_size;
    69             if (_comm_type_key < PEP_ct_unconfirmed_encryption) {
    70                 identity->comm_type = _comm_type_key;
    71             }
    72             else {
    73                 identity->comm_type = stored_identity->comm_type;
    74             }
    75         }
    76         else /* !EMPTY(identity->fpr) */ {
    77             if (_comm_type_key != PEP_ct_unknown) {
    78                 if (_comm_type_key < PEP_ct_unconfirmed_encryption) {
    79                     identity->comm_type = _comm_type_key;
    80                 }
    81                 else if (identity->comm_type == PEP_ct_unknown) {
    82                     if (strcmp(identity->fpr, stored_identity->fpr) == 0) {
    83                         identity->comm_type = stored_identity->comm_type;
    84                     }
    85                     else {
    86                         status = get_trust(session, identity);
    87                         assert(status != PEP_OUT_OF_MEMORY);
    88                         if (status == PEP_OUT_OF_MEMORY)
    89                             return PEP_OUT_OF_MEMORY;
    90                     }
    91                 }
    92             }
    93             else
    94                 identity->comm_type = PEP_ct_unknown;
    95         }
    96 
    97         if (identity->lang[0] == 0) {
    98             identity->lang[0] = stored_identity->lang[0];
    99             identity->lang[1] = stored_identity->lang[1];
   100             identity->lang[2] = 0;
   101         }
   102     }
   103     else /* stored_identity == NULL */ {
   104         if (!EMPTY(identity->fpr)) {
   105             PEP_comm_type _comm_type_key;
   106 
   107             status = get_key_rating(session, identity->fpr, &_comm_type_key);
   108             assert(status != PEP_OUT_OF_MEMORY);
   109             if (status == PEP_OUT_OF_MEMORY)
   110                 return PEP_OUT_OF_MEMORY;
   111 
   112             identity->comm_type = _comm_type_key;
   113         }
   114         else /* EMPTY(identity->fpr) */ {
   115             PEP_STATUS status;
   116             stringlist_t *keylist;
   117             char *_fpr = NULL;
   118             identity->comm_type = PEP_ct_unknown;
   119 
   120             status = find_keys(session, identity->address, &keylist);
   121             assert(status != PEP_OUT_OF_MEMORY);
   122             if (status == PEP_OUT_OF_MEMORY)
   123                 return PEP_OUT_OF_MEMORY;
   124 
   125             stringlist_t *_keylist;
   126             for (_keylist = keylist; _keylist && _keylist->value; _keylist = _keylist->next) {
   127                 PEP_comm_type _comm_type_key;
   128 
   129                 status = get_key_rating(session, _keylist->value, &_comm_type_key);
   130                 assert(status != PEP_OUT_OF_MEMORY);
   131                 if (status == PEP_OUT_OF_MEMORY) {
   132                     free_stringlist(keylist);
   133                     return PEP_OUT_OF_MEMORY;
   134                 }
   135 
   136                 if (identity->comm_type == PEP_ct_unknown) {
   137                     if (_comm_type_key != PEP_ct_compromized && _comm_type_key != PEP_ct_unknown) {
   138                         identity->comm_type = _comm_type_key;
   139                         _fpr = _keylist->value;
   140                     }
   141                 }
   142                 else {
   143                     if (_comm_type_key != PEP_ct_compromized && _comm_type_key != PEP_ct_unknown) {
   144                         if (_comm_type_key > identity->comm_type) {
   145                             identity->comm_type = _comm_type_key;
   146                             _fpr = _keylist->value;
   147                         }
   148                     }
   149                 }
   150             }
   151 
   152             if (_fpr) {
   153                 free(identity->fpr);
   154 
   155                 identity->fpr = strdup(_fpr);
   156                 if (identity->fpr == NULL) {
   157                     free_stringlist(keylist);
   158                     return PEP_OUT_OF_MEMORY;
   159                 }
   160                 identity->fpr_size = strlen(identity->fpr);
   161             }
   162             free_stringlist(keylist);
   163         }
   164     }
   165 
   166     status = PEP_STATUS_OK;
   167 
   168     if (identity->comm_type != PEP_ct_unknown && !EMPTY(identity->user_id)) {
   169         assert(!EMPTY(identity->username)); // this should not happen
   170 
   171         if (EMPTY(identity->username)) { // mitigate
   172             free(identity->username);
   173             identity->username = strdup("anonymous");
   174             if (identity->username == NULL)
   175                 return PEP_OUT_OF_MEMORY;
   176             identity->username_size = 9;
   177         }
   178 
   179         status = set_identity(session, identity);
   180         assert(status == PEP_STATUS_OK);
   181     }
   182 
   183     return status;
   184 }
   185 
   186 DYNAMIC_API PEP_STATUS myself(PEP_SESSION session, pEp_identity * identity)
   187 {
   188     PEP_STATUS status;
   189     stringlist_t *keylist;
   190 
   191     assert(session);
   192     assert(identity);
   193     assert(identity->address);
   194     assert(identity->username);
   195     assert(identity->user_id);
   196 
   197     identity->comm_type = PEP_ct_pEp;
   198     identity->me = true;
   199 
   200     pEp_identity *_identity;
   201 
   202     log_event(session, "myself", "debug", identity->address, NULL);
   203     status = get_identity(session, identity->address, &_identity);
   204     assert(status != PEP_OUT_OF_MEMORY);
   205     if (status == PEP_OUT_OF_MEMORY)
   206         return PEP_OUT_OF_MEMORY;
   207 
   208     status = find_keys(session, identity->address, &keylist);
   209     assert(status != PEP_OUT_OF_MEMORY);
   210     if (status == PEP_OUT_OF_MEMORY)
   211         return PEP_OUT_OF_MEMORY;
   212 
   213     if (keylist == NULL || keylist->value == NULL) {
   214         log_event(session, "generating key pair", "debug", identity->address, NULL);
   215         status = generate_keypair(session, identity);
   216         assert(status != PEP_OUT_OF_MEMORY);
   217         if (status != PEP_STATUS_OK) {
   218             char buf[11];
   219             snprintf(buf, 11, "%d", status);
   220             log_event(session, "generating key pair failed", "debug", buf, NULL);
   221             return status;
   222         }
   223 
   224         status = find_keys(session, identity->address, &keylist);
   225         assert(status != PEP_OUT_OF_MEMORY);
   226         if (status == PEP_OUT_OF_MEMORY)
   227             return PEP_OUT_OF_MEMORY;
   228 
   229         assert(keylist);
   230     }
   231 
   232     if (identity->fpr)
   233         free(identity->fpr);
   234     identity->fpr = strdup(keylist->value);
   235     assert(identity->fpr);
   236     free_stringlist(keylist);
   237     if (identity->fpr == NULL)
   238         return PEP_OUT_OF_MEMORY;
   239     identity->fpr_size = strlen(identity->fpr);
   240 
   241     status = set_identity(session, identity);
   242     assert(status == PEP_STATUS_OK);
   243 
   244     return PEP_STATUS_OK;
   245 }
   246 
   247 DYNAMIC_API PEP_STATUS do_keymanagement(
   248         retrieve_next_identity_t retrieve_next_identity,
   249         void *management
   250     )
   251 {
   252     PEP_SESSION session;
   253     pEp_identity *identity;
   254     PEP_STATUS status = init(&session);
   255 
   256     assert(status == PEP_STATUS_OK);
   257     if (status != PEP_STATUS_OK)
   258         return status;
   259 
   260     log_event(session, "keymanagement thread started", "pEp engine", NULL, NULL);
   261 
   262     while (identity = retrieve_next_identity(management)) {
   263         assert(identity->address);
   264         log_event(session, "do_keymanagement", "debug", identity->address, NULL);
   265         if (identity->me) {
   266             status = myself(session, identity);
   267             assert(status != PEP_OUT_OF_MEMORY);
   268         } else {
   269             status = recv_key(session, identity->address);
   270             assert(status != PEP_OUT_OF_MEMORY);
   271         }
   272         free_identity(identity);
   273     }
   274 
   275     log_event(session, "keymanagement thread shutdown", "pEp engine", NULL, NULL);
   276 
   277     release(session);
   278     return PEP_STATUS_OK;
   279 }
   280