ENGINE-222: this may need to be cleaned up, but this code now works for 2.1.13 plus - all tests pass, no password popups, key editing works, etc. Only delete prompts remain. gnupg-2.1
authorKrista Bennett <kgrothoff@pep-project.org>
Sun, 16 Jul 2017 20:00:33 +0200
branchgnupg-2.1
changeset 1926a6b1bf1c52a1
parent 1925 bee52dae2cb9
child 1927 635015dfafd5
ENGINE-222: this may need to be cleaned up, but this code now works for 2.1.13 plus - all tests pass, no password popups, key editing works, etc. Only delete prompts remain.
src/pgp_gpg.c
src/pgp_gpg_internal.h
     1.1 --- a/src/pgp_gpg.c	Sat Jul 15 00:11:53 2017 +0200
     1.2 +++ b/src/pgp_gpg.c	Sun Jul 16 20:00:33 2017 +0200
     1.3 @@ -275,6 +275,11 @@
     1.4              "gpgme_signers_add");
     1.5          assert(gpg.gpgme_signers_add);
     1.6  
     1.7 +        gpg.gpgme_set_passphrase_cb
     1.8 +            = (gpgme_set_passphrase_cb_t) (intptr_t) dlsym(gpgme,
     1.9 +            "gpgme_set_passphrase_cb");
    1.10 +        assert(gpg.gpgme_set_passphrase_cb);
    1.11 +
    1.12          gpg.gpgme_get_key
    1.13              = (gpgme_get_key_t) (intptr_t) dlsym(gpgme, "gpgme_get_key");
    1.14          assert(gpg.gpgme_get_key);
    1.15 @@ -1086,7 +1091,10 @@
    1.16  
    1.17      *key = NULL;
    1.18  
    1.19 -    gpgme_error = gpg.gpgme_op_keylist_start(session->ctx, fpr, 0);
    1.20 +//    gpgme_error = gpg.gpgme_op_keylist_start(session->ctx, fpr, 0);
    1.21 +
    1.22 +    gpgme_error = gpg.gpgme_get_key(session->ctx, fpr, key, 0);
    1.23 +
    1.24      gpgme_error = _GPGERR(gpgme_error);
    1.25      switch (gpgme_error) {
    1.26      case GPG_ERR_NO_ERROR:
    1.27 @@ -1098,11 +1106,11 @@
    1.28          return PEP_GET_KEY_FAILED;
    1.29      };
    1.30  
    1.31 -    gpgme_error = gpg.gpgme_op_keylist_next(session->ctx, key);
    1.32 -    gpgme_error = _GPGERR(gpgme_error);
    1.33 -    assert(gpgme_error != GPG_ERR_INV_VALUE);
    1.34 +//    gpgme_error = gpg.gpgme_op_keylist_next(session->ctx, key);
    1.35 +//    gpgme_error = _GPGERR(gpgme_error);
    1.36 +//    assert(gpgme_error != GPG_ERR_INV_VALUE);
    1.37  
    1.38 -    gpg.gpgme_op_keylist_end(session->ctx);
    1.39 +//    gpg.gpgme_op_keylist_end(session->ctx);
    1.40  
    1.41      return PEP_STATUS_OK;
    1.42  }
    1.43 @@ -1116,21 +1124,20 @@
    1.44  #if (GPGME_VERSION_NUMBER >= 0x010700)
    1.45          gpgme_error_t gpgme_error;
    1.46          /* "name <address>" adds 3 chars + NUL */
    1.47 -        int userid_size = strlen(identity->username) + strlen(identity->address) + 4;
    1.48 +        int userid_size = strlen(identity->address) + 1;
    1.49 +        /* int userid_size = strlen(identity->username) + strlen(identity->address) + 4; */
    1.50          char* userid = (char*)(calloc(1, userid_size));
    1.51          if (!userid)
    1.52              return PEP_OUT_OF_MEMORY;
    1.53          /* sprintf... so tempting... */    
    1.54 -        strlcpy(userid, identity->username, userid_size);
    1.55 -        strlcat(userid, " <", userid_size);
    1.56 -        strlcat(userid, identity->address, userid_size);
    1.57 -        strlcat(userid, ">", userid_size);
    1.58 +//        strlcpy(userid, identity->username, userid_size);
    1.59 +//        strlcat(userid, " <", userid_size);
    1.60 +        strlcpy(userid, identity->address, userid_size);
    1.61 +//        strlcat(userid, identity->address, userid_size);
    1.62 +//        strlcat(userid, ">", userid_size);
    1.63          gpgme_error = gpg.gpgme_op_createkey(session->ctx, userid, "RSA", 
    1.64                                               0, 31536000, NULL, 
    1.65 -                                             GPGME_CREATE_NOPASSWD | 
    1.66 -                                             GPGME_CREATE_SIGN |
    1.67 -                                             GPGME_CREATE_CERT |
    1.68 -                                             GPGME_CREATE_FORCE);
    1.69 +                                             GPGME_CREATE_NOPASSWD);
    1.70          gpgme_error = _GPGERR(gpgme_error);
    1.71  
    1.72          free(userid);
    1.73 @@ -1153,7 +1160,7 @@
    1.74              assert(gpgme_genkey_result);
    1.75              assert(gpgme_genkey_result->fpr);
    1.76  
    1.77 -            char* fpr = gpgme_genkey_result->fpr;
    1.78 +            char* fpr = strdup(gpgme_genkey_result->fpr);
    1.79              gpgme_key_t key;
    1.80              PEP_STATUS key_status = find_single_key(session, fpr, &key);
    1.81              if (!key || key_status != PEP_STATUS_OK)
    1.82 @@ -1177,14 +1184,14 @@
    1.83              }        
    1.84              
    1.85              free(identity->fpr);
    1.86 -            identity->fpr = strdup(fpr);
    1.87 +            identity->fpr = fpr;
    1.88              if (identity->fpr == NULL)
    1.89                  return PEP_OUT_OF_MEMORY;
    1.90  
    1.91 -            gpg.gpgme_key_unref(key);
    1.92 +//            gpg.gpgme_key_unref(key);
    1.93              
    1.94 -            status = pgp_replace_only_uid(session, identity->fpr,
    1.95 -                        identity->username, identity->address);                        
    1.96 +            status = pgp_replace_only_uid(session, fpr,
    1.97 +                        identity->username, identity->address);                       
    1.98          }
    1.99  #endif
   1.100  #endif
   1.101 @@ -1193,6 +1200,13 @@
   1.102      return status;
   1.103  }
   1.104  
   1.105 +static gpgme_error_t bypass_passphrase(void *hook, 
   1.106 +	const char *uid_hint, const char *passphrase_info, 
   1.107 +	int prev_was_bad, int fd) {
   1.108 +    gpg.gpgme_io_write(fd, "\n", 1);
   1.109 +    return GPG_ERR_NO_ERROR;
   1.110 +}
   1.111 +
   1.112  PEP_STATUS pgp_generate_keypair(
   1.113      PEP_SESSION session, pEp_identity *identity
   1.114      )
   1.115 @@ -1236,6 +1250,9 @@
   1.116          return PEP_BUFFER_TOO_SMALL;
   1.117      }
   1.118  
   1.119 +    /* if this is not implemented, we ignore the error and deal with the passphrase dialog */
   1.120 +    gpgme_error = gpg.gpgme_set_passphrase_cb(session->ctx, bypass_passphrase, NULL);
   1.121 +
   1.122      gpgme_error = gpg.gpgme_op_genkey(session->ctx, parms, NULL, NULL);
   1.123      gpgme_error = _GPGERR(gpgme_error);
   1.124      free(parms);
   1.125 @@ -1256,6 +1273,8 @@
   1.126      assert(gpgme_genkey_result);
   1.127      assert(gpgme_genkey_result->fpr);
   1.128  
   1.129 +    gpgme_error = gpg.gpgme_set_passphrase_cb(session->ctx, NULL, NULL);
   1.130 +
   1.131      free(identity->fpr);
   1.132      identity->fpr = strdup(gpgme_genkey_result->fpr);
   1.133      if (identity->fpr == NULL)
   1.134 @@ -1907,6 +1926,7 @@
   1.135          replace_uid_command = 0,
   1.136          replace_uid_realname,
   1.137          replace_uid_email,
   1.138 +        replace_uid_comment,
   1.139          replace_uid_adduid_ok,
   1.140          replace_uid_select_for_delete,
   1.141          replace_uid_delete,
   1.142 @@ -1924,6 +1944,7 @@
   1.143  const char *email;
   1.144  } replace_only_uid_state;
   1.145  
   1.146 +
   1.147  static gpgme_error_t replace_only_uid_fsm(
   1.148      void *_handle,
   1.149      gpgme_status_code_t statuscode,
   1.150 @@ -1960,7 +1981,7 @@
   1.151                      handle->state = replace_uid_error;
   1.152                      return GPG_ERR_ENOMEM;
   1.153                  }
   1.154 -                strlcpy(realname, handle->realname, realname_strlen);
   1.155 +                strlcpy(realname, handle->realname, realname_strlen + 1);
   1.156                  realname[realname_strlen] = '\n'; 
   1.157                  gpg.gpgme_io_write(fd, realname, realname_strlen + 1);
   1.158                  handle->state = replace_uid_email;
   1.159 @@ -1982,18 +2003,30 @@
   1.160                      handle->state = replace_uid_error;
   1.161                      return GPG_ERR_ENOMEM;
   1.162                  }
   1.163 -                strlcpy(email, handle->email, email_strlen);
   1.164 +                strlcpy(email, handle->email, email_strlen + 1);
   1.165                  email[email_strlen] = '\n'; 
   1.166                  gpg.gpgme_io_write(fd, email, email_strlen + 1);
   1.167 -                handle->state = replace_uid_adduid_ok;
   1.168 +                handle->state = replace_uid_comment;
   1.169                  free(email);
   1.170              }
   1.171              break;
   1.172  
   1.173 +        case replace_uid_comment:
   1.174 +            if (statuscode == GPGME_STATUS_GET_LINE) {
   1.175 +                assert(strcmp(args, "keygen.comment") == 0);
   1.176 +                if (strcmp(args, "keygen.comment") || !handle->email) {
   1.177 +                    handle->state = replace_uid_error;
   1.178 +                    return GPG_ERR_GENERAL;
   1.179 +                }
   1.180 +                gpg.gpgme_io_write(fd, "\n", 1);
   1.181 +                //handle->state = replace_uid_adduid_ok;
   1.182 +                handle->state = replace_uid_select_for_delete;
   1.183 +            }
   1.184 +            break;
   1.185 +/*
   1.186          case replace_uid_adduid_ok:
   1.187              if (statuscode == GPGME_STATUS_GET_LINE) {
   1.188                  assert(strcmp(args, "keygen.userid.cmd") == 0);
   1.189 -                assert(handle->email);
   1.190                  if (strcmp(args, "keygen.userid.cmd")) {
   1.191                      handle->state = replace_uid_error;
   1.192                      return GPG_ERR_GENERAL;
   1.193 @@ -2002,11 +2035,11 @@
   1.194                  handle->state = replace_uid_select_for_delete;
   1.195              }
   1.196              break;
   1.197 +	    */
   1.198  
   1.199          case replace_uid_select_for_delete:
   1.200              if (statuscode == GPGME_STATUS_GET_LINE) {
   1.201                  assert(strcmp(args, "keyedit.prompt") == 0);
   1.202 -                assert(handle->email);
   1.203                  if (strcmp(args, "keyedit.prompt")) {
   1.204                      handle->state = replace_uid_error;
   1.205                      return GPG_ERR_GENERAL;
   1.206 @@ -2019,7 +2052,6 @@
   1.207          case replace_uid_delete:
   1.208              if (statuscode == GPGME_STATUS_GET_LINE) {
   1.209                  assert(strcmp(args, "keyedit.prompt") == 0);
   1.210 -                assert(handle->email);
   1.211                  if (strcmp(args, "keyedit.prompt")) {
   1.212                      handle->state = replace_uid_error;
   1.213                      return GPG_ERR_GENERAL;
   1.214 @@ -2030,9 +2062,8 @@
   1.215              break;
   1.216  
   1.217          case replace_uid_delete_confirm:
   1.218 -            if (statuscode == GPGME_STATUS_GET_LINE) {
   1.219 +            if (statuscode == GPGME_STATUS_GET_BOOL) {
   1.220                  assert(strcmp(args, "keyedit.remove.uid.okay") == 0);
   1.221 -                assert(handle->email);
   1.222                  if (strcmp(args, "keyedit.remove.uid.okay")) {
   1.223                      handle->state = replace_uid_error;
   1.224                      return GPG_ERR_GENERAL;
   1.225 @@ -2045,12 +2076,11 @@
   1.226          case replace_uid_select_for_trust:
   1.227              if (statuscode == GPGME_STATUS_GET_LINE) {
   1.228                  assert(strcmp(args, "keyedit.prompt") == 0);
   1.229 -                assert(handle->email);
   1.230                  if (strcmp(args, "keyedit.prompt")) {
   1.231                      handle->state = replace_uid_error;
   1.232                      return GPG_ERR_GENERAL;
   1.233                  }
   1.234 -                gpg.gpgme_io_write(fd, "uid 1\n", 5);
   1.235 +                gpg.gpgme_io_write(fd, "uid 1\n", 6);
   1.236                  handle->state = replace_uid_trust;
   1.237              }
   1.238              break;
   1.239 @@ -2058,12 +2088,11 @@
   1.240          case replace_uid_trust:
   1.241              if (statuscode == GPGME_STATUS_GET_LINE) {
   1.242                  assert(strcmp(args, "keyedit.prompt") == 0);
   1.243 -                assert(handle->email);
   1.244                  if (strcmp(args, "keyedit.prompt")) {
   1.245                      handle->state = replace_uid_error;
   1.246                      return GPG_ERR_GENERAL;
   1.247                  }
   1.248 -                gpg.gpgme_io_write(fd, "trust\n", 5);
   1.249 +                gpg.gpgme_io_write(fd, "trust\n", 6);
   1.250                  handle->state = replace_uid_trust_ultimate;
   1.251              }
   1.252              break;
   1.253 @@ -2071,7 +2100,6 @@
   1.254          case replace_uid_trust_ultimate:
   1.255              if (statuscode == GPGME_STATUS_GET_LINE) {
   1.256                  assert(strcmp(args, "edit_ownertrust.value") == 0);
   1.257 -                assert(handle->email);
   1.258                  if (strcmp(args, "edit_ownertrust.value")) {
   1.259                      handle->state = replace_uid_error;
   1.260                      return GPG_ERR_GENERAL;
   1.261 @@ -2082,9 +2110,8 @@
   1.262              break;
   1.263  
   1.264          case replace_uid_trust_ultimate_confirm:
   1.265 -            if (statuscode == GPGME_STATUS_GET_LINE) {
   1.266 +            if (statuscode == GPGME_STATUS_GET_BOOL) {
   1.267                  assert(strcmp(args, "edit_ownertrust.set_ultimate.okay") == 0);
   1.268 -                assert(handle->email);
   1.269                  if (strcmp(args, "edit_ownertrust.set_ultimate.okay")) {
   1.270                      handle->state = replace_uid_error;
   1.271                      return GPG_ERR_GENERAL;
   1.272 @@ -2097,7 +2124,6 @@
   1.273          case replace_uid_quit:
   1.274              if (statuscode == GPGME_STATUS_GET_LINE) {
   1.275                  assert(strcmp(args, "keyedit.prompt") == 0);
   1.276 -                assert(handle->email);
   1.277                  if (strcmp(args, "keyedit.prompt")) {
   1.278                      handle->state = replace_uid_error;
   1.279                      return GPG_ERR_GENERAL;
   1.280 @@ -2108,9 +2134,8 @@
   1.281              break;
   1.282  
   1.283          case replace_uid_save_okay:
   1.284 -            if (statuscode == GPGME_STATUS_GET_LINE) {
   1.285 +            if (statuscode == GPGME_STATUS_GET_BOOL) {
   1.286                  assert(strcmp(args, "keyedit.save.okay") == 0);
   1.287 -                assert(handle->email);
   1.288                  if (strcmp(args, "keyedit.save.okay")) {
   1.289                      handle->state = replace_uid_error;
   1.290                      return GPG_ERR_GENERAL;
     2.1 --- a/src/pgp_gpg_internal.h	Sat Jul 15 00:11:53 2017 +0200
     2.2 +++ b/src/pgp_gpg_internal.h	Sun Jul 16 20:00:33 2017 +0200
     2.3 @@ -94,6 +94,10 @@
     2.4  #endif
     2.5  
     2.6  
     2.7 +typedef gpgme_error_t(*gpgme_set_passphrase_cb_t)(gpgme_ctx_t ctx, 
     2.8 +		gpgme_passphrase_cb_t passfunc, void *hook_value);
     2.9 +
    2.10 +
    2.11  struct gpg_s {
    2.12      const char * version;
    2.13      gpgme_check_version_t gpgme_check;
    2.14 @@ -146,4 +150,6 @@
    2.15  	gpgme_key_release_t gpgme_key_release;
    2.16      gpgme_op_edit_t gpgme_op_edit;
    2.17      gpgme_io_write_t gpgme_io_write;
    2.18 +
    2.19 +    gpgme_set_passphrase_cb_t gpgme_set_passphrase_cb;
    2.20  };