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