int main (int argc, char *argv[]) { gpgme_ctx_t ctx; gpgme_error_t err; gpgme_data_t in, out; gpgme_sign_result_t result; init_gpgme (GPGME_PROTOCOL_CMS); err = gpgme_new (&ctx); fail_if_err (err); gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS); gpgme_set_textmode (ctx, 1); gpgme_set_armor (ctx, 1); err = gpgme_data_new_from_mem (&in, "Hallo Leute!\n", 13, 0); fail_if_err (err); /* First a normal signature. */ err = gpgme_data_new (&out); fail_if_err (err); err = gpgme_op_sign (ctx, in, out, GPGME_SIG_MODE_NORMAL); fail_if_err (err); result = gpgme_op_sign_result (ctx); check_result (result, GPGME_SIG_MODE_NORMAL); print_data (out); gpgme_data_release (out); /* Now a detached signature. */ gpgme_data_seek (in, 0, SEEK_SET); err = gpgme_data_new (&out); fail_if_err (err); err = gpgme_op_sign (ctx, in, out, GPGME_SIG_MODE_DETACH); fail_if_err (err); result = gpgme_op_sign_result (ctx); check_result (result, GPGME_SIG_MODE_DETACH); print_data (out); gpgme_data_release (out); gpgme_data_release (in); gpgme_release (ctx); return 0; }
GpgME::SigningResult::SigningResult(gpgme_ctx_t ctx, int error) : GpgME::Result(error), d(0) { if(error || !ctx) return; gpgme_sign_result_t res = gpgme_op_sign_result(ctx); if(!res) return; d = new Private(res); d->ref(); }
static int pkcs7_sign (GMimeCryptoContext *context, const char *userid, GMimeDigestAlgo digest, GMimeStream *istream, GMimeStream *ostream, GError **err) { #ifdef ENABLE_SMIME GMimePkcs7Context *ctx = (GMimePkcs7Context *) context; Pkcs7Ctx *pkcs7 = ctx->priv; gpgme_sign_result_t result; gpgme_data_t input, output; gpgme_error_t error; if (!pkcs7_add_signer (pkcs7, userid, err)) return -1; gpgme_set_armor (pkcs7->ctx, FALSE); if ((error = gpgme_data_new_from_cbs (&input, &pkcs7_stream_funcs, istream)) != GPG_ERR_NO_ERROR) { g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open input stream")); return -1; } if ((error = gpgme_data_new_from_cbs (&output, &pkcs7_stream_funcs, ostream)) != GPG_ERR_NO_ERROR) { g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open output stream")); gpgme_data_release (input); return -1; } /* sign the input stream */ if ((error = gpgme_op_sign (pkcs7->ctx, input, output, GPGME_SIG_MODE_DETACH)) != GPG_ERR_NO_ERROR) { g_set_error (err, GMIME_GPGME_ERROR, error, _("Signing failed")); gpgme_data_release (output); gpgme_data_release (input); return -1; } gpgme_data_release (output); gpgme_data_release (input); /* return the digest algorithm used for signing */ result = gpgme_op_sign_result (pkcs7->ctx); return pkcs7_digest_id (context, gpgme_hash_algo_name (result->signatures->hash_algo)); #else g_set_error (err, GMIME_ERROR, GMIME_ERROR_NOT_SUPPORTED, _("S/MIME support is not enabled in this build")); return -1; #endif /* ENABLE_SMIME */ }
/* ############################################################################# * * 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; }
static gboolean pgpinline_sign(MimeInfo *mimeinfo, PrefsAccount *account, const gchar *from_addr) { MimeInfo *msgcontent; gchar *textstr, *tmp; FILE *fp; gchar *sigcontent; gpgme_ctx_t ctx; gpgme_data_t gpgtext, gpgsig; size_t len; gpgme_error_t err; struct passphrase_cb_info_s info; gpgme_sign_result_t result = NULL; memset (&info, 0, sizeof info); /* get content node from message */ msgcontent = (MimeInfo *) mimeinfo->node->children->data; if (msgcontent->type == MIMETYPE_MULTIPART) { if (!msgcontent->node->children) { debug_print("msgcontent->node->children NULL, bailing\n"); privacy_set_error(_("Malformed message")); return FALSE; } msgcontent = (MimeInfo *) msgcontent->node->children->data; } /* get rid of quoted-printable or anything */ procmime_decode_content(msgcontent); fp = my_tmpfile(); if (fp == NULL) { perror("my_tmpfile"); privacy_set_error(_("Couldn't create temporary file.")); return FALSE; } procmime_write_mimeinfo(msgcontent, fp); rewind(fp); /* read temporary file into memory */ textstr = fp_read_noconv(fp); 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"), 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); 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 (!getenv("GPG_AGENT_INFO") || !prefs_gpg_get_config()->use_gpg_agent) { info.c = ctx; gpgme_set_passphrase_cb (ctx, gpgmegtk_passphrase_cb, &info); } err = gpgme_op_sign(ctx, gpgtext, gpgsig, GPGME_SIG_MODE_CLEAR); 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; 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); if (sigcontent == NULL || len <= 0) { g_warning("sgpgme_data_release_and_get_mem failed"); privacy_set_error(_("Data signing failed, no contents.")); gpgme_data_release(gpgtext); g_free(textstr); g_free(sigcontent); gpgme_release(ctx); return FALSE; } tmp = g_malloc(len+1); g_memmove(tmp, sigcontent, len+1); tmp[len] = '\0'; gpgme_data_release(gpgtext); g_free(textstr); g_free(sigcontent); if (msgcontent->content == MIMECONTENT_FILE && msgcontent->data.filename != NULL) { if (msgcontent->tmp == TRUE) claws_unlink(msgcontent->data.filename); g_free(msgcontent->data.filename); } msgcontent->data.mem = g_strdup(tmp); msgcontent->content = MIMECONTENT_MEM; g_free(tmp); /* avoid all sorts of clear-signing problems with non ascii * chars */ procmime_encode_content(msgcontent, ENC_BASE64); gpgme_release(ctx); return TRUE; }
/** \brief Sign data * * \param userid User ID of the signer. * \param istream GMime input stream. * \param ostream GMime output stream. * \param protocol GpgME crypto protocol of the signature. * \param singlepart_mode TRUE indicates single-part mode (integrated * signature), FALSE a detached signature. * \param parent Parent window to be passed to the passphrase callback * function. * \param error Filled with error information on error. * \return The hash algorithm used for creating the signature, or * GPGME_MD_NONE on error. * * Sign the passed matter and write the detached signature or the signed * input and the signature, respectively, to the output stream. The global * callback to read the passphrase for the user's private key will be * called by GpgME if no GPG Agent is running. */ gpgme_hash_algo_t libbalsa_gpgme_sign(const gchar * userid, GMimeStream * istream, GMimeStream * ostream, gpgme_protocol_t protocol, gboolean singlepart_mode, GtkWindow * parent, GError ** error) { gpgme_error_t err; gpgme_ctx_t ctx; gpgme_sig_mode_t sig_mode; gpgme_data_t in; gpgme_data_t out; gpgme_hash_algo_t hash_algo; struct gpgme_data_cbs cbs = { (gpgme_data_read_cb_t) g_mime_gpgme_stream_rd, /* read method */ (gpgme_data_write_cb_t) g_mime_gpgme_stream_wr, /* write method */ NULL, /* seek method */ cb_data_release /* release method */ }; /* paranoia checks */ g_return_val_if_fail(GMIME_IS_STREAM(istream), GPGME_MD_NONE); g_return_val_if_fail(GMIME_IS_STREAM(ostream), GPGME_MD_NONE); g_return_val_if_fail(protocol == GPGME_PROTOCOL_OpenPGP || protocol == GPGME_PROTOCOL_CMS, GPGME_MD_NONE); /* create the GpgME context */ if ((err = gpgme_new_with_protocol(&ctx, protocol, parent, error)) != GPG_ERR_NO_ERROR) return GPGME_MD_NONE; /* set the signature mode */ if (singlepart_mode) { if (protocol == GPGME_PROTOCOL_OpenPGP) sig_mode = GPGME_SIG_MODE_CLEAR; else sig_mode = GPGME_SIG_MODE_NORMAL; } else sig_mode = GPGME_SIG_MODE_DETACH; /* find the secret key for the "sign_for" address */ if (!gpgme_add_signer(ctx, userid, parent, error)) { gpgme_release(ctx); return GPGME_MD_NONE; } /* OpenPGP signatures are ASCII armored */ gpgme_set_armor(ctx, protocol == GPGME_PROTOCOL_OpenPGP); /* create gpgme data objects */ if ((err = gpgme_data_new_from_cbs(&in, &cbs, istream)) != GPG_ERR_NO_ERROR) { g_set_error_from_gpgme(error, err, _("could not get data from stream")); gpgme_release(ctx); return GPGME_MD_NONE; } if ((err = gpgme_data_new_from_cbs(&out, &cbs, ostream)) != GPG_ERR_NO_ERROR) { g_set_error_from_gpgme(error, err, _("could not create new data object")); gpgme_data_release(in); gpgme_release(ctx); return GPGME_MD_NONE; } /* sign and get the used hash algorithm */ err = gpgme_op_sign(ctx, in, out, sig_mode); if (err != GPG_ERR_NO_ERROR) { g_set_error_from_gpgme(error, err, _("signing failed")); hash_algo = GPGME_MD_NONE; } else hash_algo = gpgme_op_sign_result(ctx)->signatures->hash_algo; /* clean up */ gpgme_data_release(in); gpgme_data_release(out); gpgme_release(ctx); return hash_algo; }
gpointer sign_file (const gchar *input_file_path, const gchar *fpr) { gpgme_error_t error; gpgme_ctx_t context; gpgme_key_t signing_key; gpgme_data_t clear_text, signed_text; gpgme_sign_result_t result; gchar *buffer; gssize nbytes; error = gpgme_new (&context); if (error) { g_printerr ("%s:%d: %s: %s\n", __FILE__, __LINE__, gpgme_strsource (error), gpgme_strerror (error)); return GPGME_ERROR; } gpgme_set_armor (context, 0); error = gpgme_engine_check_version (GPGME_PROTOCOL_OpenPGP); if (error) { g_printerr ("%s:%d: %s: %s\n", __FILE__, __LINE__, gpgme_strsource (error), gpgme_strerror (error)); gpgme_release (context); return GPGME_ERROR; } const char *keyring_dir = gpgme_get_dirinfo ("homedir"); error = gpgme_ctx_set_engine_info (context, GPGME_PROTOCOL_OpenPGP, NULL, keyring_dir); if (error) { g_printerr ("%s:%d: %s: %s\n", __FILE__, __LINE__, gpgme_strsource (error), gpgme_strerror (error)); gpgme_release (context); return GPGME_ERROR; } error = gpgme_get_key (context, fpr, &signing_key, 1); if (error) { g_printerr ("%s:%d: %s: %s\n", __FILE__, __LINE__, gpgme_strsource (error), gpgme_strerror (error)); gpgme_release (context); return GPGME_ERROR; } error = gpgme_signers_add (context, signing_key); if (error) { g_printerr ("%s:%d: %s: %s\n", __FILE__, __LINE__, gpgme_strsource (error), gpgme_strerror (error)); cleanup (NULL, NULL, NULL, NULL, &signing_key, &context); return GPGME_ERROR; } FILE *infp = g_fopen (input_file_path, "r"); if (infp == NULL) { g_printerr ("Couldn't open input file\n"); cleanup (NULL, NULL, NULL, NULL, &signing_key, &context); return FILE_OPEN_ERROR; } error = gpgme_data_new_from_stream (&clear_text, infp); if (error) { g_printerr ("%s:%d: %s: %s\n", __FILE__, __LINE__, gpgme_strsource (error), gpgme_strerror (error)); cleanup (infp, NULL, NULL, NULL, &signing_key, &context); return GPGME_ERROR; } error = gpgme_data_new (&signed_text); if (error) { g_printerr ("%s:%d: %s: %s\n", __FILE__, __LINE__, gpgme_strsource (error), gpgme_strerror (error)); cleanup (infp, NULL, NULL, NULL, &signing_key, &context); return GPGME_ERROR; } error = gpgme_op_sign (context, clear_text, signed_text, GPGME_SIG_MODE_DETACH); if (error) { g_printerr ("%s:%d: %s: %s\n", __FILE__, __LINE__, gpgme_strsource (error), gpgme_strerror (error)); cleanup (infp, NULL, NULL, NULL, &signing_key, &context); return GPGME_ERROR; } result = gpgme_op_sign_result (context); if (result->invalid_signers) { g_printerr ("Invalid signer found: %s\n", result->invalid_signers->fpr); cleanup (infp, NULL, NULL, NULL, &signing_key, &context); return GPGME_ERROR; } if (!result->signatures || result->signatures->next) { g_printerr ("Unexpected number of signatures created\n"); cleanup (infp, NULL, NULL, NULL, &signing_key, &context); return GPGME_ERROR; } error = gpgme_data_seek (signed_text, 0, SEEK_SET); if (error) { g_printerr ("%s:%d: %s: %s\n", __FILE__, __LINE__, gpgme_strsource (error), gpgme_strerror (error)); cleanup (infp, NULL, NULL, NULL, &signing_key, &context); return GPGME_ERROR; } buffer = g_try_malloc0 (SIG_MAXLEN); if (buffer == NULL) { g_printerr ("Couldn't allocate memory\n"); cleanup (infp, NULL, NULL, NULL, &signing_key, &context); return MEMORY_ALLOCATION_ERROR; } nbytes = gpgme_data_read (signed_text, buffer, SIG_MAXLEN); if (nbytes == -1) { g_printerr ("Error while reading data\n"); cleanup (infp, NULL, NULL, NULL, &signing_key, &context); return GPGME_ERROR; } GError *gerr = NULL; gchar *output_file_path = g_strconcat (input_file_path, ".sig", NULL); GFile *fpout = g_file_new_for_path (output_file_path); GFileOutputStream *ostream = g_file_append_to (fpout, G_FILE_CREATE_REPLACE_DESTINATION, NULL, &gerr); if (gerr != NULL) { g_printerr ("Couldn't open output file for writing\n"); cleanup (infp, fpout, NULL, output_file_path, &signing_key, &context); return FILE_OPEN_ERROR; } gssize wbytes = g_output_stream_write (G_OUTPUT_STREAM (ostream), buffer, nbytes, NULL, &gerr); if (wbytes == -1) { g_printerr ("Couldn't write the request number of bytes (%s)\n", gerr->message); cleanup (infp, fpout, ostream, output_file_path, &signing_key, &context); return FILE_WRITE_ERROR; } cleanup (infp, fpout, ostream, output_file_path, &signing_key, &context); return SIGN_OK; }
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; }
static PyObject * pygpgme_context_sign(PyGpgmeContext *self, PyObject *args) { PyObject *py_plain, *py_sig; gpgme_data_t plain, sig; int sig_mode = GPGME_SIG_MODE_NORMAL; gpgme_error_t err; gpgme_sign_result_t result; if (!PyArg_ParseTuple(args, "OO|i", &py_plain, &py_sig, &sig_mode)) return NULL; if (pygpgme_data_new(&plain, py_plain)) return NULL; if (pygpgme_data_new(&sig, py_sig)) { gpgme_data_release(plain); return NULL; } Py_BEGIN_ALLOW_THREADS; err = gpgme_op_sign(self->ctx, plain, sig, sig_mode); Py_END_ALLOW_THREADS; gpgme_data_release(plain); gpgme_data_release(sig); result = gpgme_op_sign_result(self->ctx); /* annotate exception */ if (pygpgme_check_error(err)) { PyObject *err_type, *err_value, *err_traceback; PyObject *list; gpgme_invalid_key_t key; PyErr_Fetch(&err_type, &err_value, &err_traceback); PyErr_NormalizeException(&err_type, &err_value, &err_traceback); if (result == NULL) goto end; if (!PyErr_GivenExceptionMatches(err_type, pygpgme_error)) goto end; list = PyList_New(0); for (key = result->invalid_signers; key != NULL; key = key->next) { PyObject *item, *py_fpr, *err; if (key->fpr) py_fpr = PyUnicode_DecodeASCII(key->fpr, strlen(key->fpr), "replace"); else { py_fpr = Py_None; Py_INCREF(py_fpr); } err = pygpgme_error_object(key->reason); item = Py_BuildValue("(NN)", py_fpr, err); PyList_Append(list, item); Py_DECREF(item); } PyObject_SetAttrString(err_value, "invalid_signers", list); Py_DECREF(list); list = pygpgme_newsiglist_new(result->signatures); PyObject_SetAttrString(err_value, "signatures", list); Py_DECREF(list); end: PyErr_Restore(err_type, err_value, err_traceback); return NULL; } if (result) return pygpgme_newsiglist_new(result->signatures); else return PyList_New(0); }
static PyObject * pygpgme_context_encrypt_sign(PyGpgmeContext *self, PyObject *args) { PyObject *py_recp, *py_plain, *py_cipher, *recp_seq = NULL, *result = NULL; int flags, i, length; gpgme_key_t *recp = NULL; gpgme_data_t plain = NULL, cipher = NULL; gpgme_error_t err; gpgme_sign_result_t sign_result; if (!PyArg_ParseTuple(args, "OiOO", &py_recp, &flags, &py_plain, &py_cipher)) goto end; recp_seq = PySequence_Fast(py_recp, "first argument must be a sequence"); if (recp_seq == NULL) goto end; length = PySequence_Fast_GET_SIZE(recp_seq); recp = malloc((length + 1) * sizeof (gpgme_key_t)); for (i = 0; i < length; i++) { PyObject *item = PySequence_Fast_GET_ITEM(recp_seq, i); if (!PyObject_TypeCheck(item, &PyGpgmeKey_Type)) { PyErr_SetString(PyExc_TypeError, "items in first argument " "must be gpgme.Key objects"); goto end; } recp[i] = ((PyGpgmeKey *)item)->key; } recp[i] = NULL; if (pygpgme_data_new(&plain, py_plain)) goto end; if (pygpgme_data_new(&cipher, py_cipher)) goto end; Py_BEGIN_ALLOW_THREADS; err = gpgme_op_encrypt_sign(self->ctx, recp, flags, plain, cipher); Py_END_ALLOW_THREADS; sign_result = gpgme_op_sign_result(self->ctx); /* annotate exception */ if (pygpgme_check_error(err)) { PyObject *err_type, *err_value, *err_traceback; PyObject *list; gpgme_invalid_key_t key; decode_encrypt_result(self); PyErr_Fetch(&err_type, &err_value, &err_traceback); PyErr_NormalizeException(&err_type, &err_value, &err_traceback); if (sign_result == NULL) goto error_end; if (!PyErr_GivenExceptionMatches(err_type, pygpgme_error)) goto error_end; list = PyList_New(0); for (key = sign_result->invalid_signers; key != NULL; key = key->next) { PyObject *item, *py_fpr, *err; if (key->fpr) py_fpr = PyUnicode_DecodeASCII(key->fpr, strlen(key->fpr), "replace"); else { py_fpr = Py_None; Py_INCREF(py_fpr); } err = pygpgme_error_object(key->reason); item = Py_BuildValue("(NN)", py_fpr, err); PyList_Append(list, item); Py_DECREF(item); } PyObject_SetAttrString(err_value, "invalid_signers", list); Py_DECREF(list); list = pygpgme_newsiglist_new(sign_result->signatures); PyObject_SetAttrString(err_value, "signatures", list); Py_DECREF(list); error_end: PyErr_Restore(err_type, err_value, err_traceback); goto end; } if (sign_result) result = pygpgme_newsiglist_new(sign_result->signatures); else result = PyList_New(0); end: if (recp != NULL) free(recp); Py_XDECREF(recp_seq); if (plain != NULL) gpgme_data_release(plain); if (cipher != NULL) gpgme_data_release(cipher); return result; }