/* ------------------ * check if a key is locally available * ------------------ */ int is_key_available(const char* fpr,int secret, int servermode, char** userid) { gpgme_error_t error; gpgme_ctx_t ctx; gpgme_key_t key; gpgme_key_t key_arr[2]; gpgme_keylist_mode_t current_keylist_mode; key_arr[0] = NULL; key_arr[1] = NULL; // connect to gpgme gpgme_check_version (NULL); error = gpgme_new(&ctx); if (error) { purple_debug_error(PLUGIN_ID,"gpgme_new failed: %s %s\n",gpgme_strsource (error), gpgme_strerror (error)); return FALSE; } // set to server search mode if servermode == TRUE if (servermode == TRUE) { purple_debug_info(PLUGIN_ID,"set keylist mode to server\n"); current_keylist_mode = gpgme_get_keylist_mode(ctx); gpgme_set_keylist_mode(ctx,(current_keylist_mode | GPGME_KEYLIST_MODE_EXTERN) &(~GPGME_KEYLIST_MODE_LOCAL)); } // get key by fingerprint error = gpgme_get_key(ctx,fpr,&key,secret); if (error || !key) { purple_debug_error(PLUGIN_ID,"gpgme_get_key failed: %s %s\n",gpgme_strsource (error), gpgme_strerror (error)); gpgme_release (ctx); return FALSE; } // if we have parameter, tell caller about userid if (userid != NULL) { *userid = g_strdup(key->uids->uid); } // import key key_arr[0] = key; error = gpgme_op_import_keys (ctx, key_arr); if (error) { purple_debug_error(PLUGIN_ID,"gpgme_op_import_keys failed: %s %s\n",gpgme_strsource (error), gpgme_strerror (error)); gpgme_release (ctx); return FALSE; } // close gpgme connection gpgme_release (ctx); // we got the key, YEAH :) return TRUE; }
int main(void) { gpgme_ctx_t ctx; gpgme_error_t err; int setup_res = setup(&ctx); if(setup_res) return setup_res; /* Change mode to list sigs and */ gpgme_keylist_mode_t mode = gpgme_get_keylist_mode(ctx); mode |= GPGME_KEYLIST_MODE_SIGS | GPGME_KEYLIST_MODE_SIG_NOTATIONS; err = gpgme_set_keylist_mode(ctx, mode); if (err != GPG_ERR_NO_ERROR) return 6; /* List all keys */ /* (context, pattern, secret_only) */ err = gpgme_op_keylist_start(ctx, NULL, 0); if (err != GPG_ERR_NO_ERROR) return 7; gpgme_key_t key; while ((err = gpgme_op_keylist_next(ctx, &key)) == GPG_ERR_NO_ERROR) { printf("Got a key\n"); printf ("%s:", key->subkeys->keyid); if (key->uids && key->uids->name) printf (" %s", key->uids->name); if (key->uids && key->uids->email) printf (" <%s>", key->uids->email); if (key->uids && key->uids->signatures) { printf("First signature: %s\n", key->uids->signatures->keyid); } putchar ('\n'); gpgme_key_release (key); } if (gpg_err_code(err) == GPG_ERR_EOF) { printf("%xu\n", err); printf("End of keylist.\n"); } else { print_gpg_error(err); return 8; } /* free context */ gpgme_release(ctx); return 0; }
/** * Search for a GPG key in a remote location. * This requires GPGME to call the gpg binary and have a keyserver previously * defined in a gpg.conf configuration file. * @param handle the context handle * @param fpr the fingerprint key ID to look up * @param pgpkey storage location for the given key if found * @return 1 on success, 0 on key not found, -1 on error */ static int key_search(alpm_handle_t *handle, const char *fpr, alpm_pgpkey_t *pgpkey) { gpgme_error_t gpg_err; gpgme_ctx_t ctx; gpgme_keylist_mode_t mode; gpgme_key_t key; int ret = -1; size_t fpr_len; char *full_fpr; /* gpg2 goes full retard here. For key searches ONLY, we need to prefix the * key fingerprint with 0x, or the lookup will fail. */ fpr_len = strlen(fpr); MALLOC(full_fpr, fpr_len + 3, RET_ERR(handle, ALPM_ERR_MEMORY, -1)); sprintf(full_fpr, "0x%s", fpr); memset(&ctx, 0, sizeof(ctx)); gpg_err = gpgme_new(&ctx); CHECK_ERR(); mode = gpgme_get_keylist_mode(ctx); /* using LOCAL and EXTERN together doesn't work for GPG 1.X. Ugh. */ mode &= ~GPGME_KEYLIST_MODE_LOCAL; mode |= GPGME_KEYLIST_MODE_EXTERN; gpg_err = gpgme_set_keylist_mode(ctx, mode); CHECK_ERR(); _alpm_log(handle, ALPM_LOG_DEBUG, "looking up key %s remotely\n", fpr); gpg_err = gpgme_get_key(ctx, full_fpr, &key, 0); if(gpg_err_code(gpg_err) == GPG_ERR_EOF) { _alpm_log(handle, ALPM_LOG_DEBUG, "key lookup failed, unknown key\n"); /* Try an alternate lookup using the 8 character fingerprint value, since * busted-ass keyservers can't support lookups using subkeys with the full * value as of now. This is why 2012 is not the year of PGP encryption. */ if(fpr_len > 8) { const char *short_fpr = memcpy(&full_fpr[fpr_len - 8], "0x", 2); _alpm_log(handle, ALPM_LOG_DEBUG, "looking up key %s remotely\n", short_fpr); gpg_err = gpgme_get_key(ctx, short_fpr, &key, 0); if(gpg_err_code(gpg_err) == GPG_ERR_EOF) { _alpm_log(handle, ALPM_LOG_DEBUG, "key lookup failed, unknown key\n"); ret = 0; } } else { ret = 0; } } CHECK_ERR(); /* should only get here if key actually exists */ pgpkey->data = key; if(key->subkeys->fpr) { pgpkey->fingerprint = key->subkeys->fpr; } else if(key->subkeys->keyid) { pgpkey->fingerprint = key->subkeys->keyid; } pgpkey->uid = key->uids->uid; pgpkey->name = key->uids->name; pgpkey->email = key->uids->email; pgpkey->created = key->subkeys->timestamp; pgpkey->expires = key->subkeys->expires; pgpkey->length = key->subkeys->length; pgpkey->revoked = key->subkeys->revoked; switch(key->subkeys->pubkey_algo) { case GPGME_PK_RSA: case GPGME_PK_RSA_E: case GPGME_PK_RSA_S: pgpkey->pubkey_algo = 'R'; break; case GPGME_PK_DSA: pgpkey->pubkey_algo = 'D'; break; case GPGME_PK_ELG_E: case GPGME_PK_ELG: case GPGME_PK_ECDSA: case GPGME_PK_ECDH: pgpkey->pubkey_algo = 'E'; break; } ret = 1; gpg_error: if(ret != 1) { _alpm_log(handle, ALPM_LOG_DEBUG, "gpg error: %s\n", gpgme_strerror(gpg_err)); } free(full_fpr); gpgme_release(ctx); return ret; }
SEXP R_gpg_keylist(SEXP filter, SEXP secret_only, SEXP local) { gpgme_keylist_mode_t mode = gpgme_get_keylist_mode(ctx); mode |= asLogical(local) ? GPGME_KEYLIST_MODE_LOCAL : GPGME_KEYLIST_MODE_EXTERN; mode |= GPGME_KEYLIST_MODE_SIGS; mode |= GPGME_KEYLIST_MODE_SIG_NOTATIONS; gpgme_set_keylist_mode (ctx, mode); gpgme_set_protocol (ctx, GPGME_PROTOCOL_OpenPGP); //gpgme_set_global_flag("auto-key-locate", "hkp://pgp.mit.edu"); bail(gpgme_op_keylist_start (ctx, CHAR(STRING_ELT(filter, 0)), asLogical(secret_only)), "starting keylist"); struct keylist *keys = (struct keylist *) malloc(sizeof(struct keylist)); struct keylist *head = keys; gpgme_error_t err; int count = 0; while(1){ err = gpgme_op_keylist_next (ctx, &(keys->key)); if(gpg_err_code (err) == GPG_ERR_EOF) break; bail(err, "getting next key"); keys->next = (struct keylist *) malloc(sizeof(struct keylist)); keys = keys->next; count++; } /* convert the linked list into vectors */ SEXP keyid = PROTECT(allocVector(STRSXP, count)); SEXP fpr = PROTECT(allocVector(STRSXP, count)); SEXP name = PROTECT(allocVector(STRSXP, count)); SEXP email = PROTECT(allocVector(STRSXP, count)); SEXP algo = PROTECT(allocVector(STRSXP, count)); SEXP timestamp = PROTECT(allocVector(INTSXP, count)); SEXP expires = PROTECT(allocVector(INTSXP, count)); gpgme_key_t key; for(int i = 0; i < count; i++){ key = head->key; SET_STRING_ELT(keyid, i, make_char(key->subkeys->keyid)); SET_STRING_ELT(fpr, i, make_char(key->subkeys->fpr)); SET_STRING_ELT(algo, i, make_char(gpgme_pubkey_algo_name(key->subkeys->pubkey_algo))); if(key->issuer_name) SET_STRING_ELT(fpr, i, make_char(key->issuer_name)); if(key->uids && key->uids->name) SET_STRING_ELT(name, i, make_char(key->uids->name)); if(key->uids && key->uids->email) SET_STRING_ELT(email, i, make_char(key->uids->email)); INTEGER(timestamp)[i] = (key->subkeys->timestamp > 0) ? key->subkeys->timestamp : NA_INTEGER; INTEGER(expires)[i] = (key->subkeys->expires > 0) ? key->subkeys->expires : NA_INTEGER; keys = head; head = head->next; gpgme_key_unref (key); free(keys); } SEXP result = PROTECT(allocVector(VECSXP, 7)); SET_VECTOR_ELT(result, 0, keyid); SET_VECTOR_ELT(result, 1, fpr); SET_VECTOR_ELT(result, 2, name); SET_VECTOR_ELT(result, 3, email); SET_VECTOR_ELT(result, 4, algo); SET_VECTOR_ELT(result, 5, timestamp); SET_VECTOR_ELT(result, 6, expires); UNPROTECT(8); return result; }
int main(void) { gpgme_ctx_t ctx; gpgme_error_t err; int setup_res = setup(&ctx); if(setup_res) return setup_res; /* Change mode to extern */ gpgme_keylist_mode_t mode = gpgme_get_keylist_mode(ctx); mode &= ~GPGME_KEYLIST_MODE_LOCAL; mode |= GPGME_KEYLIST_MODE_EXTERN; mode |= GPGME_KEYLIST_MODE_SIGS | GPGME_KEYLIST_MODE_SIG_NOTATIONS; err = gpgme_set_keylist_mode(ctx, mode); if (err != GPG_ERR_NO_ERROR) return 6; /* List all keys */ /* (context, pattern, secret_only) */ err = gpgme_op_keylist_start(ctx, "07E7871B", 0); if (err != GPG_ERR_NO_ERROR) return 7; gpgme_key_t key; size_t MAX_KEYS = 100; gpgme_key_t keyarray[MAX_KEYS+1]; // need a space for the NULL term size_t i = 0; while ((err = gpgme_op_keylist_next(ctx, &key)) == GPG_ERR_NO_ERROR) { printf("Got a key\n"); printf ("%s:", key->subkeys->keyid); if (key->uids && key->uids->name) printf (" %s", key->uids->name); if (key->uids && key->uids->email) printf (" <%s>", key->uids->email); if (key->uids && key->uids->signatures) { printf("First signature: %s\n", key->uids->signatures->keyid); } putchar ('\n'); if (i < MAX_KEYS) { keyarray[i++] = key; } else { printf("Too many keys, skipping a key\n"); } //gpgme_key_release (key); } if (gpg_err_code(err) == GPG_ERR_EOF) { printf("%xu\n", err); printf("End of keylist.\n"); } else { print_gpg_error(err); return 8; } // https://bugs.gnupg.org/gnupg/issue1670 printf("Attempting to import %lu keys\n", i); err = gpgme_op_import_keys(ctx, keyarray); if (err != GPG_ERR_NO_ERROR) return 9; gpgme_import_result_t impres = gpgme_op_import_result(ctx); if (!impres) return 10; print_import_result(impres); /* free keys */ for (i = 0; keyarray[i]; i++) gpgme_key_release(key); /* free context */ gpgme_release(ctx); return 0; }
static PyObject * pygpgme_context_get_keylist_mode(PyGpgmeContext *self) { return PyInt_FromLong(gpgme_get_keylist_mode(self->ctx)); }