Merged gnupg-2.1 in default. Also, for ENGINE-9, stripped unused get_resource function in message_api.c, producing warning with llvm toolchain
authorEdouard Tisserant <edouard@pep-project.org>
Thu, 20 Jul 2017 14:05:14 +0200
changeset 19313a52d0092cdc
parent 1919 335cdc692960
parent 1929 bad90979fd7e
child 1932 1bbe9e6435b7
Merged gnupg-2.1 in default. Also, for ENGINE-9, stripped unused get_resource function in message_api.c, producing warning with llvm toolchain
src/message_api.c
     1.1 --- a/src/message_api.c	Wed Jul 12 18:22:49 2017 +0200
     1.2 +++ b/src/message_api.c	Thu Jul 20 14:05:14 2017 +0200
     1.3 @@ -28,14 +28,6 @@
     1.4          return uri + 3;
     1.5  }
     1.6  
     1.7 -static char* get_resource(char* uri) {
     1.8 -    const char* resource_ptr = _get_resource_ptr_noown(uri);
     1.9 -    char* resource_str = NULL;
    1.10 -    if (resource_ptr)
    1.11 -        resource_str = strdup(resource_ptr);
    1.12 -    return resource_str;
    1.13 -}
    1.14 -
    1.15  static bool is_file_uri(char* str) {
    1.16      return(strncmp(str, "file://", 7) == 0);
    1.17  }
     2.1 --- a/src/pEpEngine.h	Wed Jul 12 18:22:49 2017 +0200
     2.2 +++ b/src/pEpEngine.h	Thu Jul 20 14:05:14 2017 +0200
     2.3 @@ -105,7 +105,9 @@
     2.4      PEP_ILLEGAL_VALUE                               = -4,
     2.5      PEP_BUFFER_TOO_SMALL                            = -3,
     2.6      PEP_OUT_OF_MEMORY                               = -2,
     2.7 -    PEP_UNKNOWN_ERROR                               = -1
     2.8 +    PEP_UNKNOWN_ERROR                               = -1,
     2.9 +    
    2.10 +    PEP_VERSION_MISMATCH                            = -7,
    2.11  } PEP_STATUS;
    2.12  
    2.13  
     3.1 --- a/src/pgp_gpg.c	Wed Jul 12 18:22:49 2017 +0200
     3.2 +++ b/src/pgp_gpg.c	Thu Jul 20 14:05:14 2017 +0200
     3.3 @@ -275,10 +275,30 @@
     3.4              "gpgme_signers_add");
     3.5          assert(gpg.gpgme_signers_add);
     3.6  
     3.7 +        gpg.gpgme_set_passphrase_cb
     3.8 +            = (gpgme_set_passphrase_cb_t) (intptr_t) dlsym(gpgme,
     3.9 +            "gpgme_set_passphrase_cb");
    3.10 +        assert(gpg.gpgme_set_passphrase_cb);
    3.11 +
    3.12          gpg.gpgme_get_key
    3.13              = (gpgme_get_key_t) (intptr_t) dlsym(gpgme, "gpgme_get_key");
    3.14          assert(gpg.gpgme_get_key);
    3.15 +        
    3.16 +        #ifdef GPGME_VERSION_NUMBER 
    3.17 +        #if (GPGME_VERSION_NUMBER >= 0x010700)
    3.18 +                gpg.gpgme_op_createkey
    3.19 +                    = (gpgme_op_createkey_t) (intptr_t) dlsym(gpgme,
    3.20 +                    "gpgme_op_createkey");
    3.21 +                assert(gpg.gpgme_op_createkey);
    3.22 +                
    3.23 +                gpg.gpgme_op_createsubkey
    3.24 +                    = (gpgme_op_createsubkey_t) (intptr_t) dlsym(gpgme,
    3.25 +                    "gpgme_op_createsubkey");
    3.26 +                assert(gpg.gpgme_op_createsubkey);
    3.27  
    3.28 +        #endif
    3.29 +        #endif
    3.30 +        
    3.31          gpg.gpgme_op_genkey
    3.32              = (gpgme_op_genkey_t) (intptr_t) dlsym(gpgme,
    3.33              "gpgme_op_genkey");
    3.34 @@ -1060,10 +1080,134 @@
    3.35          psize, ctext, csize, true);
    3.36  }
    3.37  
    3.38 +
    3.39 +static PEP_STATUS find_single_key(
    3.40 +        PEP_SESSION session,
    3.41 +        const char *fpr,
    3.42 +        gpgme_key_t *key
    3.43 +    )
    3.44 +{
    3.45 +    gpgme_error_t gpgme_error;
    3.46 +
    3.47 +    *key = NULL;
    3.48 +
    3.49 +//    gpgme_error = gpg.gpgme_op_keylist_start(session->ctx, fpr, 0);
    3.50 +
    3.51 +    gpgme_error = gpg.gpgme_get_key(session->ctx, fpr, key, 0);
    3.52 +
    3.53 +    gpgme_error = _GPGERR(gpgme_error);
    3.54 +    switch (gpgme_error) {
    3.55 +    case GPG_ERR_NO_ERROR:
    3.56 +        break;
    3.57 +    case GPG_ERR_INV_VALUE:
    3.58 +        assert(0);
    3.59 +        return PEP_UNKNOWN_ERROR;
    3.60 +    default:
    3.61 +        return PEP_GET_KEY_FAILED;
    3.62 +    };
    3.63 +
    3.64 +//    gpgme_error = gpg.gpgme_op_keylist_next(session->ctx, key);
    3.65 +//    gpgme_error = _GPGERR(gpgme_error);
    3.66 +//    assert(gpgme_error != GPG_ERR_INV_VALUE);
    3.67 +
    3.68 +//    gpg.gpgme_op_keylist_end(session->ctx);
    3.69 +
    3.70 +    return PEP_STATUS_OK;
    3.71 +}
    3.72 +
    3.73 +
    3.74 +static PEP_STATUS _pgp_createkey(PEP_SESSION session, pEp_identity *identity) {
    3.75 +    PEP_STATUS status = PEP_VERSION_MISMATCH;
    3.76 +
    3.77 +    if (identity && identity->address) {    
    3.78 +#ifdef GPGME_VERSION_NUMBER 
    3.79 +#if (GPGME_VERSION_NUMBER >= 0x010700)
    3.80 +        gpgme_error_t gpgme_error;
    3.81 +        int userid_size = strlen(identity->address) + 1;
    3.82 +        char* userid = (char*)(calloc(1, userid_size));
    3.83 +        if (!userid)
    3.84 +            return PEP_OUT_OF_MEMORY;
    3.85 +        strlcpy(userid, identity->address, userid_size);
    3.86 +        gpgme_error = gpg.gpgme_op_createkey(session->ctx, userid, "RSA", 
    3.87 +                                             0, 31536000, NULL, 
    3.88 +                                             GPGME_CREATE_NOPASSWD | GPGME_CREATE_FORCE);
    3.89 +        gpgme_error = _GPGERR(gpgme_error);
    3.90 +
    3.91 +        free(userid);
    3.92 +
    3.93 +        if (gpgme_error != GPG_ERR_NOT_SUPPORTED) {
    3.94 +            switch (gpgme_error) {
    3.95 +                case GPG_ERR_NO_ERROR:
    3.96 +                    break;		    
    3.97 +                case GPG_ERR_INV_VALUE:
    3.98 +                    return PEP_ILLEGAL_VALUE;
    3.99 +                case GPG_ERR_GENERAL:
   3.100 +                    return PEP_CANNOT_CREATE_KEY;
   3.101 +                default:
   3.102 +                    assert(0);
   3.103 +                    return PEP_UNKNOWN_ERROR;
   3.104 +            }        
   3.105 +
   3.106 +            /* This is the same regardless of whether we got it from genkey or createkey */
   3.107 +            gpgme_genkey_result_t gpgme_genkey_result = gpg.gpgme_op_genkey_result(session->ctx);
   3.108 +            assert(gpgme_genkey_result);
   3.109 +            assert(gpgme_genkey_result->fpr);
   3.110 +
   3.111 +            char* fpr = strdup(gpgme_genkey_result->fpr);
   3.112 +            gpgme_key_t key;
   3.113 +            PEP_STATUS key_status = find_single_key(session, fpr, &key);
   3.114 +            if (!key || key_status != PEP_STATUS_OK)
   3.115 +                return PEP_CANNOT_CREATE_KEY;
   3.116 +                                
   3.117 +            gpgme_error = gpg.gpgme_op_createsubkey(session->ctx, key, 
   3.118 +                                                    "RSA", 0, 
   3.119 +                                                    31536000, GPGME_CREATE_NOPASSWD 
   3.120 +                                                    | GPGME_CREATE_ENCR);
   3.121 +
   3.122 +            switch (gpgme_error) {
   3.123 +                case GPG_ERR_NO_ERROR:
   3.124 +                    break;		    
   3.125 +                case GPG_ERR_INV_VALUE:
   3.126 +                    return PEP_ILLEGAL_VALUE;
   3.127 +                case GPG_ERR_GENERAL:
   3.128 +                    return PEP_CANNOT_CREATE_KEY;
   3.129 +                default:
   3.130 +                    assert(0);
   3.131 +                    return PEP_UNKNOWN_ERROR;
   3.132 +            }        
   3.133 +            
   3.134 +            free(identity->fpr);
   3.135 +            identity->fpr = fpr;
   3.136 +            if (identity->fpr == NULL)
   3.137 +                return PEP_OUT_OF_MEMORY;
   3.138 +
   3.139 +//            gpg.gpgme_key_unref(key);
   3.140 +            
   3.141 +            status = pgp_replace_only_uid(session, fpr,
   3.142 +                        identity->username, identity->address);                       
   3.143 +        }
   3.144 +#endif
   3.145 +#endif
   3.146 +    }
   3.147 +    
   3.148 +    return status;
   3.149 +}
   3.150 +
   3.151  PEP_STATUS pgp_generate_keypair(
   3.152      PEP_SESSION session, pEp_identity *identity
   3.153      )
   3.154  {
   3.155 +    assert(session);
   3.156 +    assert(identity);
   3.157 +    assert(identity->address);
   3.158 +    assert(identity->fpr == NULL || identity->fpr[0] == 0);
   3.159 +    assert(identity->username);
   3.160 +
   3.161 +    PEP_STATUS status = _pgp_createkey(session, identity);
   3.162 +    
   3.163 +    if (status != PEP_VERSION_MISMATCH)
   3.164 +        return status;
   3.165 +        
   3.166      gpgme_error_t gpgme_error;
   3.167      char *parms;
   3.168      const char *template =
   3.169 @@ -1078,13 +1222,6 @@
   3.170          "Expire-Date: 1y\n"
   3.171          "</GnupgKeyParms>\n";
   3.172      int result;
   3.173 -    gpgme_genkey_result_t gpgme_genkey_result;
   3.174 -
   3.175 -    assert(session);
   3.176 -    assert(identity);
   3.177 -    assert(identity->address);
   3.178 -    assert(identity->fpr == NULL || identity->fpr[0] == 0);
   3.179 -    assert(identity->username);
   3.180  
   3.181      parms = calloc(1, PARMS_MAX);
   3.182      assert(parms);
   3.183 @@ -1115,7 +1252,7 @@
   3.184          return PEP_UNKNOWN_ERROR;
   3.185      }
   3.186  
   3.187 -    gpgme_genkey_result = gpg.gpgme_op_genkey_result(session->ctx);
   3.188 +    gpgme_genkey_result_t gpgme_genkey_result = gpg.gpgme_op_genkey_result(session->ctx);
   3.189      assert(gpgme_genkey_result);
   3.190      assert(gpgme_genkey_result->fpr);
   3.191  
   3.192 @@ -1755,37 +1892,297 @@
   3.193      return status;
   3.194  }
   3.195  
   3.196 -static PEP_STATUS find_single_key(
   3.197 -        PEP_SESSION session,
   3.198 -        const char *fpr,
   3.199 -        gpgme_key_t *key
   3.200 +
   3.201 +static ssize_t _nullwriter(
   3.202 +        void *_handle,
   3.203 +        const void *buffer,
   3.204 +        size_t size
   3.205      )
   3.206  {
   3.207 +    return size;
   3.208 +}
   3.209 +
   3.210 +typedef struct _replace_only_uid_state {
   3.211 +    enum {
   3.212 +        replace_uid_command = 0,
   3.213 +        replace_uid_realname,
   3.214 +        replace_uid_email,
   3.215 +        replace_uid_comment,
   3.216 +        replace_uid_adduid_ok,
   3.217 +        replace_uid_select_for_delete,
   3.218 +        replace_uid_delete,
   3.219 +        replace_uid_delete_confirm,
   3.220 +        replace_uid_select_for_trust,
   3.221 +        replace_uid_trust,
   3.222 +        replace_uid_trust_ultimate,
   3.223 +        replace_uid_trust_ultimate_confirm,
   3.224 +        replace_uid_quit,
   3.225 +        replace_uid_save_okay,
   3.226 +        replace_uid_exit,
   3.227 +        replace_uid_error = -1
   3.228 +    } state;
   3.229 +const char *realname;
   3.230 +const char *email;
   3.231 +} replace_only_uid_state;
   3.232 +
   3.233 +
   3.234 +static gpgme_error_t replace_only_uid_fsm(
   3.235 +    void *_handle,
   3.236 +    gpgme_status_code_t statuscode,
   3.237 +    const char *args,
   3.238 +    int fd
   3.239 +)
   3.240 +{
   3.241 +    replace_only_uid_state *handle = _handle;
   3.242 +        
   3.243 +    switch (handle->state) {
   3.244 +        case replace_uid_command:
   3.245 +            if (statuscode == GPGME_STATUS_GET_LINE) {
   3.246 +                assert(strcmp(args, "keyedit.prompt") == 0);
   3.247 +                if (strcmp(args, "keyedit.prompt")) {
   3.248 +                    handle->state = replace_uid_error;
   3.249 +                    return GPG_ERR_GENERAL;
   3.250 +                }
   3.251 +                gpg.gpgme_io_write(fd, "adduid\n", 7);
   3.252 +                handle->state = replace_uid_realname;
   3.253 +            }
   3.254 +            break;
   3.255 +            
   3.256 +        case replace_uid_realname:
   3.257 +            if (statuscode == GPGME_STATUS_GET_LINE) {
   3.258 +                assert(strcmp(args, "keygen.name") == 0);
   3.259 +                assert(handle->realname);
   3.260 +                if (strcmp(args, "keygen.name") || !handle->realname) {
   3.261 +                    handle->state = replace_uid_error;
   3.262 +                    return GPG_ERR_GENERAL;
   3.263 +                }
   3.264 +                size_t realname_strlen = strlen(handle->realname);
   3.265 +                char* realname = (char*)calloc(1, realname_strlen + 2); // \n + \0
   3.266 +                if (!realname) {
   3.267 +                    handle->state = replace_uid_error;
   3.268 +                    return GPG_ERR_ENOMEM;
   3.269 +                }
   3.270 +                strlcpy(realname, handle->realname, realname_strlen + 1);
   3.271 +                realname[realname_strlen] = '\n'; 
   3.272 +                gpg.gpgme_io_write(fd, realname, realname_strlen + 1);
   3.273 +                handle->state = replace_uid_email;
   3.274 +                free(realname);
   3.275 +            }
   3.276 +            break;
   3.277 +            
   3.278 +        case replace_uid_email:
   3.279 +            if (statuscode == GPGME_STATUS_GET_LINE) {
   3.280 +                assert(strcmp(args, "keygen.email") == 0);
   3.281 +                assert(handle->email);
   3.282 +                if (strcmp(args, "keygen.email") || !handle->email) {
   3.283 +                    handle->state = replace_uid_error;
   3.284 +                    return GPG_ERR_GENERAL;
   3.285 +                }
   3.286 +                size_t email_strlen = strlen(handle->email);
   3.287 +                char* email = (char*)calloc(1, email_strlen + 2); // \n + \0
   3.288 +                if (!email) {
   3.289 +                    handle->state = replace_uid_error;
   3.290 +                    return GPG_ERR_ENOMEM;
   3.291 +                }
   3.292 +                strlcpy(email, handle->email, email_strlen + 1);
   3.293 +                email[email_strlen] = '\n'; 
   3.294 +                gpg.gpgme_io_write(fd, email, email_strlen + 1);
   3.295 +                handle->state = replace_uid_comment;
   3.296 +                free(email);
   3.297 +            }
   3.298 +            break;
   3.299 +
   3.300 +        case replace_uid_comment:
   3.301 +            if (statuscode == GPGME_STATUS_GET_LINE) {
   3.302 +                assert(strcmp(args, "keygen.comment") == 0);
   3.303 +                if (strcmp(args, "keygen.comment") || !handle->email) {
   3.304 +                    handle->state = replace_uid_error;
   3.305 +                    return GPG_ERR_GENERAL;
   3.306 +                }
   3.307 +                gpg.gpgme_io_write(fd, "\n", 1);
   3.308 +                //handle->state = replace_uid_adduid_ok;
   3.309 +                handle->state = replace_uid_select_for_delete;
   3.310 +            }
   3.311 +            break;
   3.312 +/*
   3.313 +        case replace_uid_adduid_ok:
   3.314 +            if (statuscode == GPGME_STATUS_GET_LINE) {
   3.315 +                assert(strcmp(args, "keygen.userid.cmd") == 0);
   3.316 +                if (strcmp(args, "keygen.userid.cmd")) {
   3.317 +                    handle->state = replace_uid_error;
   3.318 +                    return GPG_ERR_GENERAL;
   3.319 +                }
   3.320 +                gpg.gpgme_io_write(fd, "O\n", 2);
   3.321 +                handle->state = replace_uid_select_for_delete;
   3.322 +            }
   3.323 +            break;
   3.324 +	    */
   3.325 +
   3.326 +        case replace_uid_select_for_delete:
   3.327 +            if (statuscode == GPGME_STATUS_GET_LINE) {
   3.328 +                assert(strcmp(args, "keyedit.prompt") == 0);
   3.329 +                if (strcmp(args, "keyedit.prompt")) {
   3.330 +                    handle->state = replace_uid_error;
   3.331 +                    return GPG_ERR_GENERAL;
   3.332 +                }
   3.333 +                gpg.gpgme_io_write(fd, "uid 1\n", 6);
   3.334 +                handle->state = replace_uid_delete;
   3.335 +            }
   3.336 +            break;
   3.337 +
   3.338 +        case replace_uid_delete:
   3.339 +            if (statuscode == GPGME_STATUS_GET_LINE) {
   3.340 +                assert(strcmp(args, "keyedit.prompt") == 0);
   3.341 +                if (strcmp(args, "keyedit.prompt")) {
   3.342 +                    handle->state = replace_uid_error;
   3.343 +                    return GPG_ERR_GENERAL;
   3.344 +                }
   3.345 +                gpg.gpgme_io_write(fd, "deluid\n", 7);
   3.346 +                handle->state = replace_uid_delete_confirm;
   3.347 +            }
   3.348 +            break;
   3.349 +
   3.350 +        case replace_uid_delete_confirm:
   3.351 +            if (statuscode == GPGME_STATUS_GET_BOOL) {
   3.352 +                assert(strcmp(args, "keyedit.remove.uid.okay") == 0);
   3.353 +                if (strcmp(args, "keyedit.remove.uid.okay")) {
   3.354 +                    handle->state = replace_uid_error;
   3.355 +                    return GPG_ERR_GENERAL;
   3.356 +                }
   3.357 +                gpg.gpgme_io_write(fd, "Y\n", 2);
   3.358 +                handle->state = replace_uid_select_for_trust;
   3.359 +            }
   3.360 +            break;
   3.361 +
   3.362 +        case replace_uid_select_for_trust:
   3.363 +            if (statuscode == GPGME_STATUS_GET_LINE) {
   3.364 +                assert(strcmp(args, "keyedit.prompt") == 0);
   3.365 +                if (strcmp(args, "keyedit.prompt")) {
   3.366 +                    handle->state = replace_uid_error;
   3.367 +                    return GPG_ERR_GENERAL;
   3.368 +                }
   3.369 +                gpg.gpgme_io_write(fd, "uid 1\n", 6);
   3.370 +                handle->state = replace_uid_trust;
   3.371 +            }
   3.372 +            break;
   3.373 +
   3.374 +        case replace_uid_trust:
   3.375 +            if (statuscode == GPGME_STATUS_GET_LINE) {
   3.376 +                assert(strcmp(args, "keyedit.prompt") == 0);
   3.377 +                if (strcmp(args, "keyedit.prompt")) {
   3.378 +                    handle->state = replace_uid_error;
   3.379 +                    return GPG_ERR_GENERAL;
   3.380 +                }
   3.381 +                gpg.gpgme_io_write(fd, "trust\n", 6);
   3.382 +                handle->state = replace_uid_trust_ultimate;
   3.383 +            }
   3.384 +            break;
   3.385 +
   3.386 +        case replace_uid_trust_ultimate:
   3.387 +            if (statuscode == GPGME_STATUS_GET_LINE) {
   3.388 +                assert(strcmp(args, "edit_ownertrust.value") == 0);
   3.389 +                if (strcmp(args, "edit_ownertrust.value")) {
   3.390 +                    handle->state = replace_uid_error;
   3.391 +                    return GPG_ERR_GENERAL;
   3.392 +                }
   3.393 +                gpg.gpgme_io_write(fd, "5\n", 2);
   3.394 +                handle->state = replace_uid_trust_ultimate_confirm;
   3.395 +            }
   3.396 +            break;
   3.397 +
   3.398 +        case replace_uid_trust_ultimate_confirm:
   3.399 +            if (statuscode == GPGME_STATUS_GET_BOOL) {
   3.400 +                assert(strcmp(args, "edit_ownertrust.set_ultimate.okay") == 0);
   3.401 +                if (strcmp(args, "edit_ownertrust.set_ultimate.okay")) {
   3.402 +                    handle->state = replace_uid_error;
   3.403 +                    return GPG_ERR_GENERAL;
   3.404 +                }
   3.405 +                gpg.gpgme_io_write(fd, "Y\n", 2);
   3.406 +                handle->state = replace_uid_quit;
   3.407 +            }
   3.408 +            break;
   3.409 +
   3.410 +        case replace_uid_quit:
   3.411 +            if (statuscode == GPGME_STATUS_GET_LINE) {
   3.412 +                assert(strcmp(args, "keyedit.prompt") == 0);
   3.413 +                if (strcmp(args, "keyedit.prompt")) {
   3.414 +                    handle->state = replace_uid_error;
   3.415 +                    return GPG_ERR_GENERAL;
   3.416 +                }
   3.417 +                gpg.gpgme_io_write(fd, "quit\n", 5);
   3.418 +                handle->state = replace_uid_save_okay;
   3.419 +            }
   3.420 +            break;
   3.421 +
   3.422 +        case replace_uid_save_okay:
   3.423 +            if (statuscode == GPGME_STATUS_GET_BOOL) {
   3.424 +                assert(strcmp(args, "keyedit.save.okay") == 0);
   3.425 +                if (strcmp(args, "keyedit.save.okay")) {
   3.426 +                    handle->state = replace_uid_error;
   3.427 +                    return GPG_ERR_GENERAL;
   3.428 +                }
   3.429 +                gpg.gpgme_io_write(fd, "Y\n", 2);
   3.430 +                handle->state = replace_uid_exit;
   3.431 +            }
   3.432 +            break;
   3.433 +
   3.434 +        case replace_uid_exit:
   3.435 +            break;
   3.436 +
   3.437 +        case replace_uid_error:
   3.438 +            return GPG_ERR_GENERAL;
   3.439 +            
   3.440 +        default:
   3.441 +            break;                
   3.442 +    }
   3.443 +    return GPG_ERR_NO_ERROR;
   3.444 +}
   3.445 +
   3.446 +PEP_STATUS pgp_replace_only_uid(
   3.447 +        PEP_SESSION session,
   3.448 +        const char* fpr,
   3.449 +        const char* realname,
   3.450 +        const char* email
   3.451 +    )
   3.452 +{
   3.453 +    PEP_STATUS status = PEP_STATUS_OK;
   3.454      gpgme_error_t gpgme_error;
   3.455 +    gpgme_key_t key;
   3.456 +    gpgme_data_t output;
   3.457 +    replace_only_uid_state handle;
   3.458  
   3.459 -    *key = NULL;
   3.460 +    assert(session);
   3.461 +    assert(fpr);
   3.462 +    assert(realname);
   3.463 +    assert(email);
   3.464 +    
   3.465 +    memset(&handle, 0, sizeof(replace_only_uid_state));
   3.466 +    handle.realname = realname;
   3.467 +    handle.email = email;
   3.468  
   3.469 -    gpgme_error = gpg.gpgme_op_keylist_start(session->ctx, fpr, 0);
   3.470 -    gpgme_error = _GPGERR(gpgme_error);
   3.471 -    switch (gpgme_error) {
   3.472 -    case GPG_ERR_NO_ERROR:
   3.473 -        break;
   3.474 -    case GPG_ERR_INV_VALUE:
   3.475 -        assert(0);
   3.476 -        return PEP_UNKNOWN_ERROR;
   3.477 -    default:
   3.478 -        return PEP_GET_KEY_FAILED;
   3.479 -    };
   3.480 +    status = find_single_key(session, fpr, &key);
   3.481 +    if (status != PEP_STATUS_OK)
   3.482 +        return status;
   3.483  
   3.484 -    gpgme_error = gpg.gpgme_op_keylist_next(session->ctx, key);
   3.485 -    gpgme_error = _GPGERR(gpgme_error);
   3.486 -    assert(gpgme_error != GPG_ERR_INV_VALUE);
   3.487 +    struct gpgme_data_cbs data_cbs;
   3.488 +    memset(&data_cbs, 0, sizeof(struct gpgme_data_cbs));
   3.489 +    data_cbs.write = _nullwriter;
   3.490 +    gpg.gpgme_data_new_from_cbs(&output, &data_cbs, &handle);
   3.491  
   3.492 -    gpg.gpgme_op_keylist_end(session->ctx);
   3.493 +    gpgme_error = gpg.gpgme_op_edit(session->ctx, key, replace_only_uid_fsm, &handle,
   3.494 +            output);
   3.495 +    assert(gpgme_error == GPG_ERR_NO_ERROR);
   3.496 +    if(gpgme_error != GPG_ERR_NO_ERROR) {
   3.497 +        status = PEP_CANNOT_EDIT_KEY;
   3.498 +    }
   3.499  
   3.500 -    return PEP_STATUS_OK;
   3.501 +    gpg.gpgme_data_release(output);
   3.502 +    gpg.gpgme_key_unref(key);
   3.503 +
   3.504 +    return status;
   3.505  }
   3.506  
   3.507 +
   3.508  typedef struct _renew_state {
   3.509      enum {
   3.510          renew_command = 0,
   3.511 @@ -1905,14 +2302,6 @@
   3.512      return GPG_ERR_NO_ERROR;
   3.513  }
   3.514  
   3.515 -static ssize_t _nullwriter(
   3.516 -        void *_handle,
   3.517 -        const void *buffer,
   3.518 -        size_t size
   3.519 -    )
   3.520 -{
   3.521 -    return size;
   3.522 -}
   3.523  
   3.524  PEP_STATUS pgp_renew_key(
   3.525          PEP_SESSION session,
     4.1 --- a/src/pgp_gpg.h	Wed Jul 12 18:22:49 2017 +0200
     4.2 +++ b/src/pgp_gpg.h	Thu Jul 20 14:05:14 2017 +0200
     4.3 @@ -105,4 +105,14 @@
     4.4  );
     4.5  
     4.6  PEP_STATUS pgp_binary(const char **path);
     4.7 +
     4.8 +/* Really only internal. */
     4.9 +PEP_STATUS pgp_replace_only_uid(
    4.10 +        PEP_SESSION session,
    4.11 +        const char* fpr,
    4.12 +        const char* realname,
    4.13 +        const char* email
    4.14 +    );
    4.15 +
    4.16 +
    4.17  #define PGP_BINARY_PATH pgp_binary
     5.1 --- a/src/pgp_gpg_internal.h	Wed Jul 12 18:22:49 2017 +0200
     5.2 +++ b/src/pgp_gpg_internal.h	Thu Jul 20 14:05:14 2017 +0200
     5.3 @@ -82,6 +82,22 @@
     5.4  typedef gpgme_ssize_t (*gpgme_io_write_t)(int fd, const void *buffer,
     5.5          size_t count);
     5.6  
     5.7 +#ifdef GPGME_VERSION_NUMBER 
     5.8 +#if (GPGME_VERSION_NUMBER >= 0x010700)
     5.9 +typedef gpgme_error_t(*gpgme_op_createkey_t)(gpgme_ctx_t CTX, 
    5.10 +    const char *USERID, const char *ALGO, unsigned long RESERVED, 
    5.11 +    unsigned long EXPIRES, gpgme_key_t EXTRAKEY, unsigned int FLAGS);
    5.12 +typedef gpgme_error_t(*gpgme_op_createsubkey_t)(gpgme_ctx_t ctx, 
    5.13 +    gpgme_key_t key, const char *algo, unsigned long reserved, 
    5.14 +    unsigned long expires, unsigned int flags);    
    5.15 +#endif
    5.16 +#endif
    5.17 +
    5.18 +
    5.19 +typedef gpgme_error_t(*gpgme_set_passphrase_cb_t)(gpgme_ctx_t ctx, 
    5.20 +		gpgme_passphrase_cb_t passfunc, void *hook_value);
    5.21 +
    5.22 +
    5.23  struct gpg_s {
    5.24      const char * version;
    5.25      gpgme_check_version_t gpgme_check;
    5.26 @@ -113,6 +129,12 @@
    5.27      gpgme_get_key_t gpgme_get_key;
    5.28      gpgme_op_genkey_t gpgme_op_genkey;
    5.29      gpgme_op_genkey_result_t gpgme_op_genkey_result;
    5.30 +#ifdef GPGME_VERSION_NUMBER 
    5.31 +#if (GPGME_VERSION_NUMBER >= 0x010700)    
    5.32 +    gpgme_op_createkey_t gpgme_op_createkey;
    5.33 +    gpgme_op_createsubkey_t gpgme_op_createsubkey;
    5.34 +#endif
    5.35 +#endif    
    5.36      gpgme_op_delete_t gpgme_op_delete;
    5.37      gpgme_op_import_t gpgme_op_import;
    5.38      gpgme_op_import_result_t gpgme_op_import_result;
    5.39 @@ -128,4 +150,6 @@
    5.40  	gpgme_key_release_t gpgme_key_release;
    5.41      gpgme_op_edit_t gpgme_op_edit;
    5.42      gpgme_io_write_t gpgme_io_write;
    5.43 +
    5.44 +    gpgme_set_passphrase_cb_t gpgme_set_passphrase_cb;
    5.45  };
     6.1 --- a/test/Makefile	Wed Jul 12 18:22:49 2017 +0200
     6.2 +++ b/test/Makefile	Thu Jul 20 14:05:14 2017 +0200
     6.3 @@ -39,6 +39,12 @@
     6.4  TEST_HOME_SKEL=$(TEST_HOME)_skel
     6.5  TEST_GNUPGHOME_SKEL=$(TEST_HOME)_skel/.gnupg
     6.6  
     6.7 +ifeq ($(shell which gpg2), )
     6.8 +    GPG_CMD = gpg
     6.9 +else
    6.10 +    GPG_CMD = gpg2
    6.11 +endif
    6.12 +
    6.13  ifeq ($(shell uname), Darwin)
    6.14      LIBPATH = DYLD_LIBRARY_PATH
    6.15      LLDB_BIN = /Applications/Xcode.app/Contents/Developer/usr/bin/lldb
    6.16 @@ -49,22 +55,12 @@
    6.17  
    6.18  TEST_CMD_PFX = $(LIBPATH)=$(HOME)/lib:../src HOME=$(TEST_HOME)
    6.19  
    6.20 -define killgpg =
    6.21 -endef
    6.22 -ifeq ("$(OPENPGP)","NETPGP")
    6.23 -    killgpg_if_using_it =
    6.24 -else
    6.25 -    killgpg_if_using_it = $(killgpg)
    6.26 -endif
    6.27 -
    6.28  test_home_skel:
    6.29 -	$(killgpg)
    6.30  	mkdir -p test_home_skel
    6.31 -	-cat 0x*.asc *_sec.asc | gpg2 --import --homedir $(TEST_GNUPGHOME_SKEL)
    6.32 -	$(killgpg)
    6.33 +	mkdir -p $(TEST_GNUPGHOME_SKEL)/private-keys-v1.d
    6.34 +	$(GPG_CMD) --import --batch --homedir $(TEST_GNUPGHOME_SKEL) 0x*.asc *_sec.asc
    6.35  
    6.36  test_home_: test_home_skel
    6.37 -	$(killgpg_if_using_it)
    6.38  	rm -rf test_home
    6.39  	cp -a test_home_skel test_home
    6.40  
     7.1 --- a/test/encrypt_missing_private_key_test.cc	Wed Jul 12 18:22:49 2017 +0200
     7.2 +++ b/test/encrypt_missing_private_key_test.cc	Thu Jul 20 14:05:14 2017 +0200
     7.3 @@ -45,10 +45,14 @@
     7.4                                                        PEP_OWN_USERID,
     7.5                                                        "Blacklist Self");
     7.6      blacklisted_identity->me = true;
     7.7 -    PEP_STATUS status8 = update_identity(session, blacklisted_identity);
     7.8 +    PEP_STATUS status8 = myself(session, blacklisted_identity);
     7.9 +    assert (status8 == PEP_STATUS_OK);
    7.10      PEP_STATUS status9 = blacklist_add(session, bl_fpr_1);
    7.11 +    assert (status9 == PEP_STATUS_OK);
    7.12      PEP_STATUS status10 = blacklist_is_listed(session, bl_fpr_1, &is_blacklisted);
    7.13 -    PEP_STATUS status11 = update_identity(session, blacklisted_identity);
    7.14 +    assert (status10 == PEP_STATUS_OK);
    7.15 +    PEP_STATUS status11 = myself(session, blacklisted_identity);
    7.16 +    assert (status11 == PEP_STATUS_OK);
    7.17  
    7.18      /* identity is blacklisted. Now let's try to encrypt a message. */
    7.19