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