void crypto_asym::set_signatories(const std::vector<std::string> & signatories) { #if GPGME_SUPPORT gpgme_key_t *signatories_key = NULL; if(signatories.empty()) { gpgme_signers_clear(context); has_signatories = false; } else { build_key_list(signatories, signatories_key, true); try { gpgme_signers_clear(context); gpgme_key_t *ptr = signatories_key; gpgme_error_t err; if(ptr == NULL) throw SRC_BUG; // build_key_list failed while(*ptr != NULL) { err = gpgme_signers_add(context, *ptr); switch(gpgme_err_code(err)) { case GPG_ERR_NO_ERROR: break; default: throw Erange("crypto_asym::encrypt", string(gettext("Unexpected error reported by GPGME: ")) + tools_gpgme_strerror_r(err)); } ++ptr; } } catch(...) { release_key_list(signatories_key); gpgme_signers_clear(context); has_signatories = false; throw; } release_key_list(signatories_key); has_signatories = true; } #else throw Efeature("Asymetric Strong encryption algorithms using GPGME"); #endif }
int geanypg_sign_selection_dialog(encrypt_data * ed) { GtkWidget * dialog = gtk_dialog_new(); unsigned long idx; int response; GtkWidget * contentarea = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); GtkWidget * combobox = geanypg_combobox( geanypg_makelist(ed->skey_array, ed->nskeys, 0)); gtk_box_pack_start(GTK_BOX(contentarea), gtk_label_new(_("Choose a key to sign with:")), FALSE, FALSE, 5); gtk_box_pack_start(GTK_BOX(contentarea), combobox, TRUE, TRUE, 0); // add ok and cancel buttons gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_OK, GTK_RESPONSE_OK); gtk_dialog_add_button(GTK_DIALOG(dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL); gtk_widget_show_all(dialog); gtk_window_set_title(GTK_WINDOW(dialog), _("Select signer")); // make sure dialog is destroyed when user responds response = gtk_dialog_run(GTK_DIALOG(dialog)); if (response == GTK_RESPONSE_CANCEL) { gtk_widget_destroy(dialog); return 0; } idx = gtk_combo_box_get_active(GTK_COMBO_BOX(combobox)); gpgme_signers_clear(ed->ctx); if (idx < ed->nskeys) gpgme_signers_add(ed->ctx, ed->skey_array[idx]); gtk_widget_destroy(dialog); return 1; }
static int pygpgme_context_set_signers(PyGpgmeContext *self, PyObject *value) { PyObject *signers = NULL; int i, length, ret = 0; if (value == NULL) { PyErr_SetString(PyExc_AttributeError, "Can not delete attribute"); return -1; } signers = PySequence_Fast(value, "signers must be a sequence of keys"); if (!signers) { ret = -1; goto end; } gpgme_signers_clear(self->ctx); length = PySequence_Fast_GET_SIZE(signers); for (i = 0; i < length; i++) { PyObject *item = PySequence_Fast_GET_ITEM(signers, i); if (!PyObject_TypeCheck(item, &PyGpgmeKey_Type)) { PyErr_SetString(PyExc_TypeError, "signers must be a sequence of keys"); ret = -1; goto end; } gpgme_signers_add(self->ctx, ((PyGpgmeKey *)item)->key); } end: Py_XDECREF(signers); return ret; }
void GPGWrapper::deinit() { if (!initialized) return; gpgme_signers_clear(context); gpgme_release(context); }
/* * Setting the signers and the protocol for the context. The protocol * to use is derived from the keys. An errro will be displayed if the * selected keys are not all of one protocol. */ static gboolean set_signers (GpaFileSignOperation *op, GList *signers) { GList *cur; gpg_error_t err; gpgme_protocol_t protocol = GPGME_PROTOCOL_UNKNOWN; gpgme_signers_clear (GPA_OPERATION (op)->context->ctx); if (!signers) { /* Can't happen */ gpa_window_error (_("You didn't select any key for signing"), GPA_OPERATION (op)->window); return FALSE; } for (cur = signers; cur; cur = g_list_next (cur)) { gpgme_key_t key = cur->data; if (protocol == GPGME_PROTOCOL_UNKNOWN) protocol = key->protocol; else if (key->protocol != protocol) { /* Should not happen because the selection dialog should have not allowed to select different key types. */ gpa_window_error (_("The selected certificates are not all of the same type." " That is, you mixed OpenPGP and X.509 certificates." " Please make sure to select only certificates of the" " same type."), GPA_OPERATION (op)->window); return FALSE; } } gpgme_set_protocol (GPA_OPERATION (op)->context->ctx, protocol); for (cur = signers; cur; cur = g_list_next (cur)) { gpgme_key_t key = cur->data; err = gpgme_signers_add (GPA_OPERATION (op)->context->ctx, key); if (err) gpa_gpgme_error (err); } return TRUE; }
static gboolean encrypt_sign_start (SeahorseToolMode *mode, const gchar *uri, gpgme_data_t uridata, SeahorsePGPOperation *pop, GError **err) { gpgme_data_t cipher; gpgme_error_t gerr; gchar *touri; g_assert (mode->recipients && mode->recipients[0]); /* File to encrypt to */ touri = seahorse_util_add_suffix (uri, SEAHORSE_CRYPT_SUFFIX, _("Choose Encrypted File Name for '%s'")); if (!touri) return FALSE; /* Open necessary files, release these with the operation */ cipher = seahorse_vfs_data_create (touri, SEAHORSE_VFS_WRITE | SEAHORSE_VFS_DELAY, err); g_free (touri); if (!cipher) return FALSE; g_object_set_data_full (G_OBJECT (pop), "cipher-data", cipher, (GDestroyNotify)gpgme_data_release); gpgme_set_armor (pop->gctx, seahorse_gconf_get_boolean (ARMOR_KEY)); gpgme_set_textmode (pop->gctx, FALSE); /* Start actual encryption */ gpgme_signers_clear (pop->gctx); if (mode->signer) { gpgme_signers_add (pop->gctx, mode->signer); gerr = gpgme_op_encrypt_sign_start (pop->gctx, mode->recipients, GPGME_ENCRYPT_ALWAYS_TRUST, uridata, cipher); } else { gerr = gpgme_op_encrypt_start (pop->gctx, mode->recipients, GPGME_ENCRYPT_ALWAYS_TRUST, uridata, cipher); } if (gerr != 0) { seahorse_util_gpgme_to_error (gerr, err); return FALSE; } return TRUE; }
/* Sign this key with the given private key. */ gpg_error_t gpa_gpgme_edit_sign_start (GpaContext *ctx, gpgme_key_t key, gpgme_key_t secret_key, gboolean local) { struct edit_parms_s *parms = NULL; gpg_error_t err = gpg_error (GPG_ERR_NO_ERROR); gpgme_data_t out; err = gpgme_data_new (&out); if (gpg_err_code (err) != GPG_ERR_NO_ERROR) { return err; } gpgme_signers_clear (ctx->ctx); err = gpgme_signers_add (ctx->ctx, secret_key); if (gpg_err_code (err) != GPG_ERR_NO_ERROR) { return err; } parms = gpa_gpgme_edit_sign_parms_new (ctx, "0", local, out); err = gpgme_op_edit_start (ctx->ctx, key, edit_fnc, parms, out); return err; }
gboolean sgpgme_setup_signers(gpgme_ctx_t ctx, PrefsAccount *account, const gchar *from_addr) { GPGAccountConfig *config; const gchar *signer_addr = account->address; gpgme_signers_clear(ctx); if (from_addr) signer_addr = from_addr; config = prefs_gpg_account_get_config(account); switch(config->sign_key) { case SIGN_KEY_DEFAULT: debug_print("using default gnupg key\n"); break; case SIGN_KEY_BY_FROM: debug_print("using key for %s\n", signer_addr); break; case SIGN_KEY_CUSTOM: debug_print("using key for %s\n", config->sign_key_id); break; } if (config->sign_key != SIGN_KEY_DEFAULT) { const gchar *keyid; gpgme_key_t key, found_key; gpgme_error_t err; if (config->sign_key == SIGN_KEY_BY_FROM) keyid = signer_addr; else if (config->sign_key == SIGN_KEY_CUSTOM) keyid = config->sign_key_id; else goto bail; found_key = NULL; /* Look for any key, not just private ones, or GPGMe doesn't * correctly set the revoked flag. */ err = gpgme_op_keylist_start(ctx, keyid, 0); while ((err = gpgme_op_keylist_next(ctx, &key)) == 0) { if (key == NULL) continue; if (!key->can_sign) continue; if (key->protocol != gpgme_get_protocol(ctx)) { debug_print("skipping a key (wrong protocol %d)\n", key->protocol); gpgme_key_release(key); continue; } if (key->expired) { debug_print("skipping a key, expired"); gpgme_key_release(key); continue; } if (key->revoked) { debug_print("skipping a key, revoked"); gpgme_key_release(key); continue; } if (key->disabled) { debug_print("skipping a key, disabled"); gpgme_key_release(key); continue; } if (found_key != NULL) { gpgme_key_release(key); gpgme_op_keylist_end(ctx); g_warning("ambiguous specification of secret key '%s'\n", keyid); privacy_set_error(_("Secret key specification is ambiguous")); goto bail; } found_key = key; } gpgme_op_keylist_end(ctx); if (found_key == NULL) { g_warning("setup_signers start: %s", gpgme_strerror(err)); privacy_set_error(_("Secret key not found (%s)"), gpgme_strerror(err)); goto bail; } err = gpgme_signers_add(ctx, found_key); debug_print("got key (proto %d (pgp %d, smime %d).\n", found_key->protocol, GPGME_PROTOCOL_OpenPGP, GPGME_PROTOCOL_CMS); gpgme_key_release(found_key); if (err) { g_warning("error adding secret key: %s\n", gpgme_strerror(err)); privacy_set_error(_("Error setting secret key: %s"), gpgme_strerror(err)); goto bail; } } prefs_gpg_account_free_config(config); return TRUE; bail: prefs_gpg_account_free_config(config); return FALSE; }
/* ############################################################################# * * Description encrypt the given buffer and return the encrypted data with * an updated size information * Author Harry Brueckner * Date 2005-03-31 * Arguments char* buffer - buffer to encrypt * int size - size of the buffer * char** newbuffer - pointer to the new buffer which holds the * encrypted data * int* newsize - size of the returned buffer * PASSPHRASE_FN password_cb - callback function pointer used * to get the current passphrase * SHOWERROR_FN showerror_cb - callback function pointer used * to display errors * Return 0 if ok, otherwise 1 */ int gpgEncrypt(char* buffer, int size, char** newbuffer, int* newsize, PASSPHRASE_FN password_cb, SHOWERROR_FN showerror_cb) { gpgme_ctx_t context; gpgme_data_t input, output; gpgme_encrypt_result_t result; gpgme_error_t error; gpgme_key_t* key = NULL; gpgme_key_t tkey = NULL; gpgme_sign_result_t sign_result; int i, keys = 0, showerror = 1; char* agent; char* fpr; char* tmpbuffer = NULL; TRACE(99, "gpgEncrypt()", NULL); /* we set our passphrase callback function */ passphrase_callback = password_cb; /* we initialize the external size data */ newsize[0] = 0; error = gpgme_new(&context); if (!error) { gpgme_set_textmode(context, 1); gpgme_set_armor(context, 1); /* Flawfinder: ignore */ agent = getenv("GPG_AGENT_INFO"); if (!(agent && strchr(agent, ':'))) { retries = 0; gpgme_set_passphrase_cb(context, gpgRequestPassphrase, NULL); } } if (!error) { error = gpgme_data_new_from_mem(&input, buffer, size, 0); } if (!error) { error = gpgme_data_new(&output); } if (!error) { gpgme_signers_clear(context); } if (!error) { /* allocate the keys */ keys = keyCount(); key = memAlloc(__FILE__, __LINE__, sizeof(gpgme_key_t) * (keys + 1)); key[keys] = NULL; signers = 0; for (i = 0; i < keys && !error; i++) { /* add all keys */ fpr = gpgGetFingerprint(keyGet(i), LIST_SECRET); if (fpr) { error = gpgme_get_key(context, fpr, &tkey, LIST_SECRET); if (tkey -> secret); { error = gpgme_signers_add(context, tkey); signers++; } memFreeString(__FILE__, __LINE__, fpr); } fpr = gpgGetFingerprint(keyGet(i), LIST_ALL); if (fpr) { error = gpgme_get_key(context, fpr, &key[i], LIST_ALL); memFreeString(__FILE__, __LINE__, fpr); } } } if (signers > 1) { /* as soon as we get two signers, we must no longer cache anything */ config -> keeppassphrase = 0; clearPassphrase(1); } /* encrypt and sign the data */ if (!error) { error = gpgme_op_encrypt_sign(context, key, GPGME_ENCRYPT_ALWAYS_TRUST, input, output); } /* we don't need the passphrase any longer */ clearPassphrase(0); if (!error) { result = gpgme_op_encrypt_result(context); } if (!error && result -> invalid_recipients) { tmpbuffer = memAlloc(__FILE__, __LINE__, STDBUFFERLENGTH); snprintf(tmpbuffer, STDBUFFERLENGTH, _("Invalid recipient encountered: %s"), result -> invalid_recipients -> fpr); (showerror_cb)(_("GpgMe error"), tmpbuffer); memFree(__FILE__, __LINE__, tmpbuffer, STDBUFFERLENGTH); showerror = 0; error = 1; } if (!error) { sign_result = gpgme_op_sign_result(context); error = gpgCheckSignResult(showerror_cb, sign_result, GPGME_SIG_MODE_NORMAL); showerror = !error; } if (!error) { tmpbuffer = gpgData2Char(output, newsize); } /* free the keys again */ i = 0; while (key && keys && key[i]) { gpgme_key_unref(key[i++]); } memFree(__FILE__, __LINE__, key, sizeof(gpgme_key_t) * (keys + 1)); gpgme_data_release(input); gpgme_data_release(output); gpgme_release(context); *newbuffer = tmpbuffer; if (error) { if (showerror) { (showerror_cb)(_("GpgMe encrypt error"), gpgme_strerror(error)); } return 1; } else return 0; }
/* The main GPG encryption routine for libfko. */ int gpgme_encrypt(fko_ctx_t fko_ctx, unsigned char *indata, size_t in_len, const char *pw, unsigned char **out, size_t *out_len) { char *tmp_buf; int res; gpgme_ctx_t gpg_ctx = NULL; gpgme_data_t cipher = NULL; gpgme_data_t plaintext = NULL; gpgme_key_t key[2] = { NULL, NULL }; gpgme_error_t err; /* Initialize gpgme */ res = init_gpgme(fko_ctx); if(res != FKO_SUCCESS) return(res); gpg_ctx = fko_ctx->gpg_ctx; /* Initialize the plaintext data (place into gpgme_data object) */ err = gpgme_data_new_from_mem(&plaintext, (char*)indata, in_len, 1); if(gpg_err_code(err) != GPG_ERR_NO_ERROR) { gpgme_release(gpg_ctx); fko_ctx->gpg_ctx = NULL; fko_ctx->gpg_err = err; return(FKO_ERROR_GPGME_PLAINTEXT_DATA_OBJ); } /* Set protocol */ err = gpgme_set_protocol(gpg_ctx, GPGME_PROTOCOL_OpenPGP); if(gpg_err_code(err) != GPG_ERR_NO_ERROR) { gpgme_data_release(plaintext); gpgme_release(gpg_ctx); fko_ctx->gpg_ctx = NULL; fko_ctx->gpg_err = err; return(FKO_ERROR_GPGME_SET_PROTOCOL); } /* Set ascii-armor off (we will be base64-encoding the encrypted data * ourselves. */ gpgme_set_armor(gpg_ctx, 0); /* The gpgme_encrypt.... functions take a recipient key array, so we add * our single key here. */ key[0] = fko_ctx->recipient_key; /* Create the buffer for our encrypted data. */ err = gpgme_data_new(&cipher); if(gpg_err_code(err) != GPG_ERR_NO_ERROR) { gpgme_data_release(plaintext); gpgme_release(gpg_ctx); fko_ctx->gpg_ctx = NULL; fko_ctx->gpg_err = err; return(FKO_ERROR_GPGME_CIPHER_DATA_OBJ); } /* Here we add the signer to the gpgme context if there is one. */ if(fko_ctx->gpg_signer != NULL) { gpgme_signers_clear(gpg_ctx); err = gpgme_signers_add(gpg_ctx, fko_ctx->signer_key); if(gpg_err_code(err) != GPG_ERR_NO_ERROR) { gpgme_data_release(plaintext); gpgme_data_release(cipher); gpgme_release(gpg_ctx); fko_ctx->gpg_ctx = NULL; fko_ctx->gpg_err = err; return(FKO_ERROR_GPGME_ADD_SIGNER); } } /* Set the passphrase callback. */ gpgme_set_passphrase_cb(gpg_ctx, my_passphrase_cb, (void*)pw); /* Encrypt and sign (if a sig was provided) the SPA data. */ if(fko_ctx->gpg_signer == NULL) err = gpgme_op_encrypt( gpg_ctx, key, GPGME_ENCRYPT_ALWAYS_TRUST, plaintext, cipher ); else err = gpgme_op_encrypt_sign( gpg_ctx, key, GPGME_ENCRYPT_ALWAYS_TRUST, plaintext, cipher ); if(gpg_err_code(err) != GPG_ERR_NO_ERROR) { gpgme_data_release(plaintext); gpgme_data_release(cipher); gpgme_release(gpg_ctx); fko_ctx->gpg_ctx = NULL; fko_ctx->gpg_err = err; if(gpgme_err_code(err) == GPG_ERR_CANCELED) return(FKO_ERROR_GPGME_BAD_PASSPHRASE); return(FKO_ERROR_GPGME_ENCRYPT_SIGN); } /* Done with the plaintext. */ gpgme_data_release(plaintext); /* Get the encrypted data and its length from the gpgme data object. * BTW, this does free the memory used by cipher. */ tmp_buf = gpgme_data_release_and_get_mem(cipher, out_len); *out = malloc(*out_len); /* This is freed upon fko_ctx destruction. */ if(*out == NULL) res = FKO_ERROR_MEMORY_ALLOCATION; else { memcpy(*out, tmp_buf, *out_len); res = FKO_SUCCESS; } gpgme_free(tmp_buf); return(res); }
QString QalfCrypto::sign(QString &message, QString &key) { gpgme_key_t gpgkey ; gpgme_data_t signature ; gpgme_data_t msg ; gpgme_verify_result_t verification ; gpgme_signature_t signatures ; gpgme_error_t result ; char * buffer ; gpgme_set_passphrase_cb(context,&passphrase_callback,NULL) ; result = gpgme_set_protocol(context,GPGME_PROTOCOL_OpenPGP) ; Q_ASSERT(gpgme_err_code(result) == GPG_ERR_NO_ERROR) ; gpgme_set_armor(context,1) ; gpgme_set_textmode(context,1) ; gpgme_signers_clear(context) ; result = gpgme_set_keylist_mode(context,GPGME_KEYLIST_MODE_LOCAL) ; // retrieving key result = gpgme_get_key(context, key.toAscii().data(),&gpgkey,1) ; Q_ASSERT(result == GPG_ERR_NO_ERROR) ; Q_ASSERT(gpgkey != 0) ; // signing result = gpgme_signers_add(context,gpgkey) ; Q_ASSERT(result == GPG_ERR_NO_ERROR) ; result = gpgme_data_new(&signature); Q_ASSERT(result == GPG_ERR_NO_ERROR) ; int message_length = message.toAscii().size() ; char * message_char = (char *) calloc(message_length+1,sizeof(char)) ; memcpy(message_char,message.toAscii().data(),message_length) ; // printf("memcmp : %d\n",memcmp(message_char,"1fc36e1d41a93c1d79f6872198f426129320d287",message_length+1)) ; result = gpgme_data_new_from_mem(&msg,message_char,message_length,0) ; gpgme_data_seek(signature,0,SEEK_SET) ; gpgme_data_seek(msg,0,SEEK_SET) ; result = gpgme_op_sign(context, msg,signature, GPGME_SIG_MODE_DETACH) ; Q_ASSERT(gpgme_err_code(result) == GPG_ERR_NO_ERROR || gpgme_err_code(result) == GPG_ERR_BAD_PASSPHRASE || gpgme_err_code(result) == GPG_ERR_CANCELED) ; // gpgme_data_seek(signature,0,SEEK_SET) ; // gpgme_data_seek(msg,0,SEEK_SET) ; // // result = gpgme_op_verify (context, signature, msg , 0) ; // Q_ASSERT(gpgme_err_code(result) != GPG_ERR_INV_VALUE) ; // Q_ASSERT(gpgme_err_code(result) != GPG_ERR_NO_DATA) ; // Q_ASSERT(result == GPG_ERR_NO_ERROR) ; // // verification = gpgme_op_verify_result(context) ; // Q_ASSERT(verification != 0) ; // // signatures = verification->signatures ; // Q_ASSERT(verification->signatures != 0) ; // result = signatures->status ; // printf("status : %d\n",gpgme_err_code(result)) ; // printf("signature summary : %d\n",signatures->summary) ; // Q_ASSERT(signatures->summary == GPGME_SIGSUM_VALID | GPGME_SIGSUM_GREEN) ; // QString signatureStr ; buffer = (char *) calloc(2048,sizeof(char)) ; gpgme_data_seek(signature,0,SEEK_SET) ; gpgme_data_read(signature,buffer,2048) ; signatureStr += buffer ; qDebug() << "signature" << signatureStr ; gpgme_data_release(signature) ; gpgme_key_unref(gpgkey) ; gpgme_data_release(msg) ; return signatureStr ; }
gboolean sgpgme_setup_signers(gpgme_ctx_t ctx, PrefsAccount *account, const gchar *from_addr) { GPGAccountConfig *config; const gchar *signer_addr = account->address; gpgme_signers_clear(ctx); if (from_addr) signer_addr = from_addr; config = prefs_gpg_account_get_config(account); switch(config->sign_key) { case SIGN_KEY_DEFAULT: debug_print("using default gnupg key\n"); break; case SIGN_KEY_BY_FROM: debug_print("using key for %s\n", signer_addr); break; case SIGN_KEY_CUSTOM: debug_print("using key for %s\n", config->sign_key_id); break; } if (config->sign_key != SIGN_KEY_DEFAULT) { const gchar *keyid; gpgme_key_t key, key2; gpgme_error_t err; if (config->sign_key == SIGN_KEY_BY_FROM) keyid = signer_addr; else if (config->sign_key == SIGN_KEY_CUSTOM) keyid = config->sign_key_id; else goto bail; err = gpgme_op_keylist_start(ctx, keyid, 1); if (!err) { do { err = gpgme_op_keylist_next(ctx, &key); if (!err && key && key->protocol == gpgme_get_protocol(ctx) && !key->expired && !key->revoked && !key->disabled) break; if (!err && key && key->protocol != gpgme_get_protocol(ctx)) { debug_print("skipping a key (wrong protocol %d)\n", key->protocol); gpgme_key_release(key); } if (!err && key && (key->expired || key->revoked || key->disabled)) { debug_print("skipping a key"); if (key->expired) debug_print(" expired"); if (key->revoked) debug_print(" revoked"); if (key->disabled) debug_print(" disabled"); debug_print("\n"); gpgme_key_release(key); } } while (!err); } if (err) { g_warning("setup_signers start: %s", gpgme_strerror(err)); privacy_set_error(_("Secret key not found (%s)"), gpgme_strerror(err)); goto bail; } do { err = gpgme_op_keylist_next(ctx, &key2); if (!err && key2 && key2->protocol == gpgme_get_protocol(ctx) && !key2->expired && !key2->revoked && !key2->disabled) break; if (!err && key2 && key2->protocol != gpgme_get_protocol(ctx)) { debug_print("skipping a key (wrong protocol %d)\n", key2->protocol); gpgme_key_release(key2); } if (!err && key2 && (key2->expired || key2->revoked || key2->disabled)) { debug_print("skipping a key"); if (key2->expired) debug_print(" expired"); if (key2->revoked) debug_print(" revoked"); if (key2->disabled) debug_print(" disabled"); debug_print("\n"); gpgme_key_release(key2); } } while (!err); if (!err) { gpgme_key_release(key2); g_warning("ambiguous specification of secret key '%s'\n", keyid); privacy_set_error(_("Secret key specification is ambiguous")); goto bail; } gpgme_op_keylist_end(ctx); err = gpgme_signers_add(ctx, key); debug_print("got key (proto %d (pgp %d, smime %d).\n", key->protocol, GPGME_PROTOCOL_OpenPGP, GPGME_PROTOCOL_CMS); gpgme_key_release(key); if (err) { g_warning("error adding secret key: %s\n", gpgme_strerror(err)); privacy_set_error(_("Error setting secret key: %s"), gpgme_strerror(err)); goto bail; } } prefs_gpg_account_free_config(config); return TRUE; bail: prefs_gpg_account_free_config(config); return FALSE; }
/* ------------------ * sign a plain string with the key found with fingerprint fpr * FREE MEMORY AFTER USAGE OF RETURN VALUE! * ------------------ */ static char* sign(const char* plain_str,const char* fpr) { gpgme_error_t error; gpgme_ctx_t ctx; gpgme_key_t key; gpgme_data_t plain,sig; const int MAX_LEN = 10000; char *sig_str = NULL; char *sig_str_dup = NULL; size_t len = 0; // 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 NULL; } // get key by fingerprint error = gpgme_get_key(ctx,fpr,&key,1); 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 NULL; } // select signers gpgme_signers_clear(ctx); error = gpgme_signers_add (ctx,key); if (error) { purple_debug_error(PLUGIN_ID,"gpgme_signers_add failed: %s %s\n",gpgme_strsource (error), gpgme_strerror (error)); gpgme_release (ctx); return NULL; } // create data containers gpgme_data_new_from_mem (&plain, plain_str,strlen(plain_str),1); gpgme_data_new(&sig); // sign message, ascii armored gpgme_set_armor(ctx,1); error = gpgme_op_sign(ctx,plain,sig,GPGME_SIG_MODE_DETACH); if (error) { purple_debug_error(PLUGIN_ID,"gpgme_op_sign failed: %s %s\n",gpgme_strsource (error), gpgme_strerror (error)); gpgme_release (ctx); return NULL; } // release memory for data containers gpgme_data_release(plain); sig_str = gpgme_data_release_and_get_mem(sig,&len); if (sig_str != NULL) { sig_str[len] = 0; sig_str_dup = str_unarmor(sig_str); } gpgme_free(sig_str); // close gpgme connection gpgme_release (ctx); return sig_str_dup; }
char* p_gpg_sign(const char *const str, const char *const fp) { gpgme_ctx_t ctx; gpgme_error_t error = gpgme_new(&ctx); if (error) { log_error("GPG: Failed to create gpgme context. %s %s", gpgme_strsource(error), gpgme_strerror(error)); return NULL; } gpgme_set_passphrase_cb(ctx, (gpgme_passphrase_cb_t)_p_gpg_passphrase_cb, NULL); gpgme_key_t key = NULL; error = gpgme_get_key(ctx, fp, &key, 1); if (error || key == NULL) { log_error("GPG: Failed to get key. %s %s", gpgme_strsource(error), gpgme_strerror(error)); gpgme_release(ctx); return NULL; } gpgme_signers_clear(ctx); error = gpgme_signers_add(ctx, key); gpgme_key_unref(key); if (error) { log_error("GPG: Failed to load signer. %s %s", gpgme_strsource(error), gpgme_strerror(error)); gpgme_release(ctx); return NULL; } char *str_or_empty = NULL; if (str) { str_or_empty = strdup(str); } else { str_or_empty = strdup(""); } gpgme_data_t str_data; gpgme_data_new_from_mem(&str_data, str_or_empty, strlen(str_or_empty), 1); free(str_or_empty); gpgme_data_t signed_data; gpgme_data_new(&signed_data); gpgme_set_armor(ctx,1); error = gpgme_op_sign(ctx, str_data, signed_data, GPGME_SIG_MODE_DETACH); gpgme_data_release(str_data); gpgme_release(ctx); if (error) { log_error("GPG: Failed to sign string. %s %s", gpgme_strsource(error), gpgme_strerror(error)); gpgme_data_release(signed_data); return NULL; } char *result = NULL; size_t len = 0; char *signed_str = gpgme_data_release_and_get_mem(signed_data, &len); if (signed_str) { GString *signed_gstr = g_string_new(""); g_string_append_len(signed_gstr, signed_str, len); result = _remove_header_footer(signed_gstr->str, PGP_SIGNATURE_FOOTER); g_string_free(signed_gstr, TRUE); gpgme_free(signed_str); } if (passphrase_attempt) { passphrase = strdup(passphrase_attempt); } return result; }
gboolean pgpmime_sign(MimeInfo *mimeinfo, PrefsAccount *account, const gchar *from_addr) { MimeInfo *msgcontent, *sigmultipart, *newinfo; gchar *textstr, *micalg = NULL; FILE *fp; gchar *boundary = NULL; gchar *sigcontent; gpgme_ctx_t ctx; gpgme_data_t gpgtext, gpgsig; gpgme_error_t err; size_t len; struct passphrase_cb_info_s info; gpgme_sign_result_t result = NULL; gchar *test_msg; fp = my_tmpfile(); if (fp == NULL) { perror("my_tmpfile"); privacy_set_error(_("Couldn't create temporary file: %s"), g_strerror(errno)); return FALSE; } procmime_write_mimeinfo(mimeinfo, fp); rewind(fp); /* read temporary file into memory */ test_msg = file_read_stream_to_str(fp); claws_fclose(fp); memset (&info, 0, sizeof info); /* remove content node from message */ msgcontent = (MimeInfo *) mimeinfo->node->children->data; g_node_unlink(msgcontent->node); /* create temporary multipart for content */ sigmultipart = procmime_mimeinfo_new(); sigmultipart->type = MIMETYPE_MULTIPART; sigmultipart->subtype = g_strdup("signed"); do { g_free(boundary); boundary = generate_mime_boundary("Sig"); } while (strstr(test_msg, boundary) != NULL); g_free(test_msg); g_hash_table_insert(sigmultipart->typeparameters, g_strdup("boundary"), g_strdup(boundary)); g_hash_table_insert(sigmultipart->typeparameters, g_strdup("protocol"), g_strdup("application/pgp-signature")); g_node_append(sigmultipart->node, msgcontent->node); g_node_append(mimeinfo->node, sigmultipart->node); /* write message content to temporary file */ fp = my_tmpfile(); if (fp == NULL) { perror("my_tmpfile"); privacy_set_error(_("Couldn't create temporary file: %s"), g_strerror(errno)); return FALSE; } procmime_write_mimeinfo(sigmultipart, fp); rewind(fp); /* read temporary file into memory */ textstr = get_canonical_content(fp, boundary); g_free(boundary); claws_fclose(fp); gpgme_data_new_from_mem(&gpgtext, textstr, (size_t)strlen(textstr), 0); gpgme_data_new(&gpgsig); if ((err = gpgme_new(&ctx)) != GPG_ERR_NO_ERROR) { debug_print(("Couldn't initialize GPG context, %s\n"), gpgme_strerror(err)); privacy_set_error(_("Couldn't initialize GPG context, %s"), gpgme_strerror(err)); return FALSE; } gpgme_set_textmode(ctx, 1); gpgme_set_armor(ctx, 1); gpgme_signers_clear (ctx); if (!sgpgme_setup_signers(ctx, account, from_addr)) { gpgme_release(ctx); return FALSE; } prefs_gpg_enable_agent(prefs_gpg_get_config()->use_gpg_agent); if (g_getenv("GPG_AGENT_INFO") && prefs_gpg_get_config()->use_gpg_agent) { debug_print("GPG_AGENT_INFO environment defined, running without passphrase callback\n"); } else { info.c = ctx; gpgme_set_passphrase_cb (ctx, gpgmegtk_passphrase_cb, &info); } err = gpgme_op_sign(ctx, gpgtext, gpgsig, GPGME_SIG_MODE_DETACH); if (err != GPG_ERR_NO_ERROR) { if (err == GPG_ERR_CANCELED) { /* ignore cancelled signing */ privacy_reset_error(); debug_print("gpgme_op_sign cancelled\n"); } else { privacy_set_error(_("Data signing failed, %s"), gpgme_strerror(err)); debug_print("gpgme_op_sign error : %x\n", err); } gpgme_release(ctx); return FALSE; } result = gpgme_op_sign_result(ctx); if (result && result->signatures) { gpgme_new_signature_t sig = result->signatures; if (gpgme_get_protocol(ctx) == GPGME_PROTOCOL_OpenPGP) { gchar *down_algo = g_ascii_strdown(gpgme_hash_algo_name( result->signatures->hash_algo), -1); micalg = g_strdup_printf("pgp-%s", down_algo); g_free(down_algo); } else { micalg = g_strdup(gpgme_hash_algo_name( result->signatures->hash_algo)); } while (sig) { debug_print("valid signature: %s\n", sig->fpr); sig = sig->next; } } else if (result && result->invalid_signers) { gpgme_invalid_key_t invalid = result->invalid_signers; while (invalid) { g_warning("invalid signer: %s (%s)", invalid->fpr, gpgme_strerror(invalid->reason)); privacy_set_error(_("Data signing failed due to invalid signer: %s"), gpgme_strerror(invalid->reason)); invalid = invalid->next; } gpgme_release(ctx); return FALSE; } else { /* can't get result (maybe no signing key?) */ debug_print("gpgme_op_sign_result error\n"); privacy_set_error(_("Data signing failed, no results.")); gpgme_release(ctx); return FALSE; } sigcontent = sgpgme_data_release_and_get_mem(gpgsig, &len); gpgme_data_release(gpgtext); g_free(textstr); if (sigcontent == NULL || len <= 0) { g_warning("sgpgme_data_release_and_get_mem failed"); privacy_set_error(_("Data signing failed, no contents.")); g_free(micalg); g_free(sigcontent); return FALSE; } /* add signature */ g_hash_table_insert(sigmultipart->typeparameters, g_strdup("micalg"), micalg); newinfo = procmime_mimeinfo_new(); newinfo->type = MIMETYPE_APPLICATION; newinfo->subtype = g_strdup("pgp-signature"); newinfo->description = g_strdup(_("OpenPGP digital signature")); newinfo->content = MIMECONTENT_MEM; newinfo->data.mem = g_malloc(len + 1); g_memmove(newinfo->data.mem, sigcontent, len); newinfo->data.mem[len] = '\0'; g_node_append(sigmultipart->node, newinfo->node); g_free(sigcontent); gpgme_release(ctx); return TRUE; }