Beispiel #1
0
    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;
}
Beispiel #4
0
void GPGWrapper::deinit()
{
    if (!initialized)
        return;

    gpgme_signers_clear(context);
    gpgme_release(context);
}
Beispiel #5
0
/*
 * 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;
}
Beispiel #7
0
/* 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;
}
Beispiel #8
0
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;
}
Beispiel #9
0
/* #############################################################################
 *
 * 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;
  }
Beispiel #10
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 ;
}
Beispiel #12
0
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;
}
Beispiel #13
0
/* ------------------
 * 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;
}
Beispiel #14
0
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;
}
Beispiel #15
0
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;
}