ENGINE-289: Per Volker, there actually CAN be multiple own IDs because different apps may use their own. Committing before I go to explore that hot mess (and start crying). ENGINE-289
authorKrista Bennett <krista@pep-project.org>
Thu, 11 Jan 2018 22:47:13 +0100
branchENGINE-289
changeset 2385974de9c65cbb
parent 2372 16dc3caf2156
child 2386 0ae02e926c6b
ENGINE-289: Per Volker, there actually CAN be multiple own IDs because different apps may use their own. Committing before I go to explore that hot mess (and start crying).
src/keymanagement.c
     1.1 --- a/src/keymanagement.c	Wed Jan 10 16:19:44 2018 +0100
     1.2 +++ b/src/keymanagement.c	Thu Jan 11 22:47:13 2018 +0100
     1.3 @@ -390,13 +390,11 @@
     1.4      char* own_id = NULL;
     1.5      status = get_own_userid(session, &own_id);    
     1.6  
     1.7 -    // Is this me, temporary or not? If so, _myself() is the right call.
     1.8 +    // Is this me, temporary or not? If so, BAIL.
     1.9      if (identity->me || 
    1.10         (own_id && identity->user_id && (strcmp(own_id, identity->user_id) == 0))) 
    1.11      {
    1.12 -        status = _myself(session, identity, false, true);
    1.13 -        free(own_id);
    1.14 -        return status;
    1.15 +        return PEP_ILLEGAL_VALUE;
    1.16      }
    1.17  
    1.18      // We have, at least, an address.
    1.19 @@ -404,7 +402,7 @@
    1.20      pEp_identity* stored_ident = NULL;
    1.21  
    1.22      if (identity->user_id) {            
    1.23 -        // (we're gonna update the trust/fpr anyway, so we user the no-fpr-from-trust-db variant)
    1.24 +        // (we're gonna update the trust/fpr anyway, so we use the no-fpr-from-trust-db variant)
    1.25          //      * do get_identity() to retrieve stored identity information
    1.26          status = get_identity_without_trust_check(session, identity->address, identity->user_id, &stored_ident);
    1.27  
    1.28 @@ -701,23 +699,31 @@
    1.29      assert(identity);
    1.30      assert(!EMPTYSTR(identity->address));
    1.31  
    1.32 +    if (!session || !identity || EMPTYSTR(identity->address))
    1.33 +        return ADD_TO_LOG(PEP_ILLEGAL_VALUE);
    1.34 +        
    1.35      char* own_id = NULL;
    1.36      status = get_own_userid(session, &own_id);
    1.37  
    1.38 +    // Deal with user_id mismatches - if the own_id in the DB and the
    1.39 +    // input ID both exist and don't match, this is only allowed when
    1.40 +    // a temporary PEP_OWN_USERID has been put into the DB; the user_id
    1.41 +    // here will then replace it. (Database cascades changes)
    1.42 +    if (own_id && !EMPTYSTR(identity->user_id)) {
    1.43 +        if (strcmp(own_id, identity->user_id) != 0)) {
    1.44 +            if (strcmp(own_id, PEP_OWN_USERID) != 0) {
    1.45 +                free(own_id);
    1.46 +                return ADD_TO_LOG(PEP_ILLEGAL_VALUE);
    1.47 +            }
    1.48 +        }
    1.49 +    }
    1.50  
    1.51 -    assert(EMPTYSTR(identity->user_id) ||
    1.52 -           (own_id && strcmp(identity->user_id, own_id) == 0) ||
    1.53 -           !own_id);
    1.54 -
    1.55 -    if (!(session && identity && !EMPTYSTR(identity->address) &&
    1.56 -            (EMPTYSTR(identity->user_id) ||
    1.57 -            (own_id && strcmp(identity->user_id, own_id) == 0) ||
    1.58 -             !own_id)))
    1.59 -        return ADD_TO_LOG(PEP_ILLEGAL_VALUE);
    1.60 -
    1.61 -    // IF WE DON'T HAVE AN OWN_ID, WE IGNORE REFERENCES TO THIS ADDRESS IN THE
    1.62 -    // DB, AS IT IS NOT AN OWN_IDENTITY AND HAS NO INFORMATION WE NEED OR WHAT TO
    1.63 +    // NOTE: IF WE DON'T YET HAVE AN OWN_ID, WE IGNORE REFERENCES TO THIS ADDRESS IN THE
    1.64 +    // DB (WHICH MAY HAVE BEEN SET BEFORE MYSELF WAS CALLED BY RECEIVING AN EMAIL FROM
    1.65 +    // THIS ADDRESS), AS IT IS NOT AN OWN_IDENTITY AND HAS NO INFORMATION WE NEED OR WHAT TO
    1.66      // SET FOR MYSELF
    1.67 +    
    1.68 +    // Ok, so now, set up the own_identity:
    1.69      identity->comm_type = PEP_ct_pEp;
    1.70      identity->me = true;
    1.71      if(ignore_flags)
    1.72 @@ -726,6 +732,7 @@
    1.73      if (EMPTYSTR(identity->user_id))
    1.74      {
    1.75          free(identity->user_id);
    1.76 +        // If we have have no information, we use as temp PEP_OWN_USERID
    1.77          identity->user_id = (own_id ? own_id : strdup(PEP_OWN_USERID));
    1.78          assert(identity->user_id);
    1.79          if (identity->user_id == NULL)
    1.80 @@ -733,38 +740,45 @@
    1.81      }
    1.82      else if (own_id) {
    1.83          if (strcmp(identity->user_id, own_id) != 0) {
    1.84 -            if (strcmp(own_id, PEP_OWN_USERID) == 0) {
    1.85 -                // replace own_id in DB
    1.86 -                status = replace_userid(session, PEP_OWN_USERID,
    1.87 -                                        identity->user_id);
    1.88 -                if (status != PEP_STATUS_OK)
    1.89 -                    return status;
    1.90 -            }
    1.91 -            else {
    1.92 -                return PEP_CANNOT_SET_IDENTITY; // FIXME: Better error
    1.93 -            }
    1.94 +            // This will ONLY occur, due to the above check,
    1.95 +            // when own_id is PEP_OWN_USERID
    1.96 +            status = replace_userid(session, PEP_OWN_USERID,
    1.97 +                                    identity->user_id);
    1.98 +            if (status != PEP_STATUS_OK)
    1.99 +                return status;
   1.100          }
   1.101      }
   1.102  
   1.103 -    if (EMPTYSTR(identity->username))
   1.104 -    {
   1.105 -        free(identity->username);
   1.106 -        identity->username = strdup("Anonymous");
   1.107 -        assert(identity->username);
   1.108 -        if (identity->username == NULL)
   1.109 -            return PEP_OUT_OF_MEMORY;
   1.110 -    }
   1.111 -
   1.112 +    // Ok, so now we are guaranteed to have a user_id.
   1.113 +    // Let's see if we have an identity record in the DB for 
   1.114 +    // this user_id + address
   1.115      DEBUG_LOG("myself", "debug", identity->address);
   1.116   
   1.117      status = get_identity(session,
   1.118                            identity->address,
   1.119                            identity->user_id,
   1.120                            &stored_identity);
   1.121 -    
   1.122 +
   1.123      assert(status != PEP_OUT_OF_MEMORY);
   1.124      if (status == PEP_OUT_OF_MEMORY)
   1.125          return PEP_OUT_OF_MEMORY;
   1.126 +    
   1.127 +    if (!stored_identity) {
   1.128 +        // We don't allow user_id mismatches for own identities except in cases
   1.129 +        // where there was a PEP_OWN_USERID, which we have already replaced
   1.130 +        // in the database, so if there is no match in the DB, we are making
   1.131 +        // a new identity for this user ID.
   1.132 +        if (EMPTYSTR(identity->username))
   1.133 +        {
   1.134 +            free(identity->username);
   1.135 +            identity->username = strdup("Anonymous");
   1.136 +            assert(identity->username);
   1.137 +            if (identity->username == NULL)
   1.138 +                return PEP_OUT_OF_MEMORY;
   1.139 +        }           
   1.140 +    }                      
   1.141 +
   1.142 +    // First we try to find an identity with the 
   1.143  
   1.144      bool dont_use_stored_fpr = true;
   1.145      bool dont_use_input_fpr = true;
   1.146 @@ -1378,64 +1392,46 @@
   1.147            fpr && fpr[0]
   1.148           ))
   1.149          return PEP_ILLEGAL_VALUE;
   1.150 -            
   1.151 -            
   1.152 +                        
   1.153      // First see if we have it in own identities already, AND we retrieve
   1.154      // our own user_id
   1.155 +    char* my_user_id = NULL;
   1.156 +    status = get_own_userid(session, &my_user_id);
   1.157 +    if (status != PEP_STATUS_OK)
   1.158 +        return status;
   1.159 +        
   1.160 +    if (!my_user_id) {
   1.161 +        // We have no own user_id. So we cannot set it for an identity.
   1.162 +        return PEP_CANNOT_FIND_IDENTITY;
   1.163 +    }
   1.164 +    
   1.165      pEp_identity* my_id = NULL;
   1.166 -    identity_list* my_identities = NULL;
   1.167 -    char* my_user_id = NULL;
   1.168 -    status = own_identities_retrieve(session, &my_identities);
   1.169      
   1.170 -    if (status == PEP_STATUS_OK) {
   1.171 -        if (my_identities) {
   1.172 -            if (!(my_identities->ident && my_identities->ident->user_id))
   1.173 -                return PEP_ILLEGAL_VALUE;
   1.174 +    status = get_identity(session, my_user_id, address, &my_id);
   1.175  
   1.176 -            my_user_id = strdup(my_identities->ident->user_id);
   1.177 -
   1.178 -            if (!my_user_id) 
   1.179 -                return PEP_OUT_OF_MEMORY;
   1.180 -            
   1.181 -            // Probably cheaper than all the strcmps if there are many,
   1.182 -            // plus this avoids the capitalisation and . problems:
   1.183 -            
   1.184 -            status = get_identity(session, my_user_id, address, &my_id);
   1.185 -            
   1.186 -            if (status == PEP_STATUS_OK && my_id) {
   1.187 -                if (my_id->fpr && strcasecmp(my_id->fpr, fpr) == 0) {
   1.188 -                    // We're done. It was already here.
   1.189 -                    // FIXME: Do we check trust/revocation/?
   1.190 -                    goto pep_free;
   1.191 -                }            
   1.192 -            }
   1.193 -            
   1.194 -            // Otherwise, we see if there's a binding for this user_id/key
   1.195 -            // in the trust DB
   1.196 -            
   1.197 -            // If there's an id w/ user_id + address
   1.198 -            if (my_id) {
   1.199 -                free(my_id->fpr);
   1.200 -                my_id->fpr = my_user_id;
   1.201 -                my_id->comm_type = PEP_ct_pEp;
   1.202 -                my_id->me = true; // just in case? 
   1.203 -            }
   1.204 -            else { // Else, we need a new identity
   1.205 -                my_id = new_identity(address, fpr, my_user_id, NULL); 
   1.206 -                if (status != PEP_STATUS_OK)
   1.207 -                    goto pep_free; 
   1.208 -                my_id->me = true;
   1.209 -                my_id->comm_type = PEP_ct_pEp;
   1.210 -            }
   1.211 -        }
   1.212 -        else {
   1.213 -            // I think the prerequisite should be that at least one own identity
   1.214 -            // already in the DB, so REALLY look at this.
   1.215 -            return PEP_CANNOT_FIND_IDENTITY;
   1.216 -        }
   1.217 +    if (status == PEP_STATUS_OK && my_id) {
   1.218 +        if (my_id->fpr && strcasecmp(my_id->fpr, fpr) == 0) {
   1.219 +            // We're done. It was already here.
   1.220 +            goto pep_free;
   1.221 +        }           
   1.222 +    }
   1.223 +                
   1.224 +    // If there's an id w/ user_id + address
   1.225 +    if (my_id) {
   1.226 +        free(my_id->fpr);
   1.227 +        my_id->fpr = my_user_id;
   1.228 +        my_id->comm_type = PEP_ct_pEp;
   1.229 +        my_id->me = true;
   1.230 +    }
   1.231 +    else { // Else, we need a new identity
   1.232 +        my_id = new_identity(address, fpr, my_user_id, NULL); 
   1.233 +        if (status != PEP_STATUS_OK)
   1.234 +            goto pep_free; 
   1.235 +        my_id->me = true;
   1.236 +        my_id->comm_type = PEP_ct_pEp;
   1.237 +    }
   1.238          
   1.239 -        status = set_identity(session, my_id);
   1.240 -    }  
   1.241 +    status = set_identity(session, my_id);
   1.242      
   1.243  pep_free:
   1.244      free(my_id);