Пример #1
0
static GMimeSignatureList *
pkcs7_verify (GMimeCryptoContext *context, GMimeDigestAlgo digest,
	      GMimeStream *istream, GMimeStream *sigstream,
	      GError **err)
{
#ifdef ENABLE_SMIME
	GMimePkcs7Context *ctx = (GMimePkcs7Context *) context;
	gpgme_data_t message, signature;
	Pkcs7Ctx *pkcs7 = ctx->priv;
	gpgme_error_t error;
	
	if ((error = gpgme_data_new_from_cbs (&message, &pkcs7_stream_funcs, istream)) != GPG_ERR_NO_ERROR) {
		g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open input stream"));
		return NULL;
	}
	
	/* if @sigstream is non-NULL, then it is a detached signature */
	if (sigstream != NULL) {
		if ((error = gpgme_data_new_from_cbs (&signature, &pkcs7_stream_funcs, sigstream)) != GPG_ERR_NO_ERROR) {
			g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open signature stream"));
			gpgme_data_release (message);
			return NULL;
		}
	} else {
		signature = NULL;
	}
	
	if ((error = gpgme_op_verify (pkcs7->ctx, signature, message, NULL)) != GPG_ERR_NO_ERROR) {
		g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not verify pkcs7 signature"));
		if (signature)
			gpgme_data_release (signature);
		gpgme_data_release (message);
		return NULL;
	}
	
	if (signature)
		gpgme_data_release (signature);
	
	if (message)
		gpgme_data_release (message);
	
	/* get/return the pkcs7 signatures */
	return pkcs7_get_signatures (pkcs7, TRUE);
#else
	g_set_error (err, GMIME_ERROR, GMIME_ERROR_NOT_SUPPORTED, _("S/MIME support is not enabled in this build"));
	
	return NULL;
#endif /* ENABLE_SMIME */
}
Пример #2
0
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 */
}
Пример #3
0
gpgme_data_t
seahorse_vfs_data_read_multi (const gchar **uris, GError **err)
{
    gpgme_error_t gerr;
    gpgme_data_t data;
    GList *datas = NULL;
    const gchar **u;
    
    for (u = uris; *u; u++) {
        if(!(*u)[0])
            continue;
        data = seahorse_vfs_data_create (*u, SEAHORSE_VFS_READ, err);
        if (!data)
            break;
        datas = g_list_prepend (datas, data);
    }
    
    /* Failed somewhere */
    if (!data) {
        multi_data_release (datas);
        return NULL;
    }
    
    datas = g_list_reverse (datas);
    gerr = gpgme_data_new_from_cbs (&data, &multi_data_cbs, datas);
    if (!GPG_IS_OK (gerr)) {
        seahorse_util_gpgme_to_error (gerr, err);
        multi_data_release (datas);
        return NULL;
    }

    return data;
}
Пример #4
0
/* Create a data on the given uri, remote uris get gnome-vfs backends,
 * local uris get normal file access. */
static gpgme_data_t
create_vfs_data (GFile *file, guint mode, SeahorseVfsProgressCb progcb,
                 gpointer userdata, gpg_error_t* err) 
{
    gpgme_error_t gerr;
    gpgme_data_t ret = NULL;
    VfsAsyncHandle* handle = NULL;
    
    if (!err)
        err = &gerr;
    
    handle = vfs_data_open (file, mode & SEAHORSE_VFS_WRITE, 
                                  mode & SEAHORSE_VFS_DELAY);
    if (handle) {
        
        *err = gpgme_data_new_from_cbs (&ret, &vfs_data_cbs, handle);
        if (!GPG_IS_OK (*err)) {
            vfs_data_cbs.release (handle);
            ret = NULL;
        }
        
        handle->progcb = progcb;
        handle->userdata = userdata;
        handle->gdata = ret;
    }

    return ret;
}
Пример #5
0
static int
pkcs7_export_keys (GMimeCryptoContext *context, GPtrArray *keys, GMimeStream *ostream, GError **err)
{
#ifdef ENABLE_SMIME
	GMimePkcs7Context *ctx = (GMimePkcs7Context *) context;
	Pkcs7Ctx *pkcs7 = ctx->priv;
	gpgme_data_t keydata;
	gpgme_error_t error;
	guint i;
	
	if ((error = gpgme_data_new_from_cbs (&keydata, &pkcs7_stream_funcs, ostream)) != GPG_ERR_NO_ERROR) {
		g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open output stream"));
		return -1;
	}
	
	/* export the key(s) */
	for (i = 0; i < keys->len; i++) {
		if ((error = gpgme_op_export (pkcs7->ctx, keys->pdata[i], 0, keydata)) != GPG_ERR_NO_ERROR) {
			g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not export key data"));
			gpgme_data_release (keydata);
			return -1;
		}
	}
	
	gpgme_data_release (keydata);
	
	return 0;
#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 */
}
Пример #6
0
static int
pkcs7_import_keys (GMimeCryptoContext *context, GMimeStream *istream, GError **err)
{
#ifdef ENABLE_SMIME
	GMimePkcs7Context *ctx = (GMimePkcs7Context *) context;
	Pkcs7Ctx *pkcs7 = ctx->priv;
	gpgme_data_t keydata;
	gpgme_error_t error;
	
	if ((error = gpgme_data_new_from_cbs (&keydata, &pkcs7_stream_funcs, istream)) != GPG_ERR_NO_ERROR) {
		g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not open input stream"));
		return -1;
	}
	
	/* import the key(s) */
	if ((error = gpgme_op_import (pkcs7->ctx, keydata)) != GPG_ERR_NO_ERROR) {
		//printf ("import error (%d): %s\n", error & GPG_ERR_CODE_MASK, gpg_strerror (error));
		g_set_error (err, GMIME_GPGME_ERROR, error, _("Could not import key data"));
		gpgme_data_release (keydata);
		return -1;
	}
	
	gpgme_data_release (keydata);
	
	return 0;
#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 */
}
Пример #7
0
static GMimeDecryptResult *
pkcs7_decrypt (GMimeCryptoContext *context, GMimeStream *istream,
	       GMimeStream *ostream, GError **err)
{
#ifdef ENABLE_SMIME
	GMimePkcs7Context *ctx = (GMimePkcs7Context *) context;
	GMimeDecryptResult *result;
	Pkcs7Ctx *pkcs7 = ctx->priv;
	gpgme_decrypt_result_t res;
	gpgme_data_t input, output;
	gpgme_error_t error;
	
	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 NULL;
	}
	
	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 NULL;
	}
	
	/* decrypt the input stream */
	if ((error = gpgme_op_decrypt_verify (pkcs7->ctx, input, output)) != GPG_ERR_NO_ERROR) {
		g_set_error (err, GMIME_GPGME_ERROR, error, _("Decryption failed"));
		gpgme_data_release (output);
		gpgme_data_release (input);
		return NULL;
	}
	
	gpgme_data_release (output);
	gpgme_data_release (input);
	
	return pkcs7_get_decrypt_result (pkcs7);
#else
	g_set_error (err, GMIME_ERROR, GMIME_ERROR_NOT_SUPPORTED, _("S/MIME support is not enabled in this build"));
	
	return NULL;
#endif /* ENABLE_SMIME */
}
Пример #8
0
gpgme_data_t
seahorse_gpgme_data_input (GInputStream* input)
{
	gpgme_error_t gerr;
	gpgme_data_t ret = NULL;
	
	g_return_val_if_fail (G_IS_INPUT_STREAM (input), NULL);
	
	gerr = gpgme_data_new_from_cbs (&ret, &input_cbs, input);
	if (!GPG_IS_OK (gerr))
		return NULL;
	
	g_object_ref (input);
	return ret;
}
Пример #9
0
gpgme_data_t
seahorse_gpgme_data_output (GOutputStream* output)
{
	gpgme_error_t gerr;
	gpgme_data_t ret = NULL;

	g_return_val_if_fail (G_IS_OUTPUT_STREAM (output), NULL);
	
	gerr = gpgme_data_new_from_cbs (&ret, &output_cbs, output);
	if (!GPG_IS_OK (gerr))
		return NULL;
	
	g_object_ref (output);
	return ret;
}
Пример #10
0
GpgME::Data::Data( DataProvider * dp ) {
  d = new Private();
  d->ref();
  if ( !dp )
    return;
  if ( !dp->isSupported( DataProvider::Read ) )
    d->cbs.read = 0;
  if ( !dp->isSupported( DataProvider::Write ) )
    d->cbs.write = 0;
  if ( !dp->isSupported( DataProvider::Seek ) )
    d->cbs.seek = 0;
  if ( !dp->isSupported( DataProvider::Release ) )
    d->cbs.release = 0;
  const gpgme_error_t e = gpgme_data_new_from_cbs( &d->data, &d->cbs, dp );
  if ( e )
    d->data = 0;
#ifndef NDEBUG
  std::cerr << "GpgME::Data(): DataProvider supports: "
	    << ( d->cbs.read ? "read" : "no read" ) << ", "
	    << ( d->cbs.write ? "write" : "no write" ) << ", "
	    << ( d->cbs.seek ? "seek" : "no seek" ) << ", "
	    << ( d->cbs.release ? "release" : "no release" ) << std::endl;
#endif
}
Пример #11
0
/** \brief Decrypt data
 *
 * \param istream GMime input (encrypted) stream.
 * \param ostream GMime output (decrypted) stream.
 * \param protocol GpgME crypto protocol to use.
 * \param parent Parent window to be passed to the passphrase callback
 *        function.
 * \param error Filled with error information on error.
 * \return A new signature status object on success, or NULL on error.
 *
 * Decrypt and -if applicable- verify the signature of the passed data
 * stream.  If the input is not signed the returned signature status will
 * be GPG_ERR_NOT_SIGNED.
 */
GMimeGpgmeSigstat *
libbalsa_gpgme_decrypt(GMimeStream * crypted, GMimeStream * plain,
		       gpgme_protocol_t protocol, GtkWindow * parent,
		       GError ** error)
{
    gpgme_ctx_t ctx;
    gpgme_error_t err;
    gpgme_data_t plain_data;
    gpgme_data_t crypt_data;
    GMimeGpgmeSigstat *result;
    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(crypted), NULL);
    g_return_val_if_fail(GMIME_IS_STREAM(plain), NULL);
    g_return_val_if_fail(protocol == GPGME_PROTOCOL_OpenPGP ||
			 protocol == GPGME_PROTOCOL_CMS, NULL);

    /* create the GpgME context */
    if ((err =
	 gpgme_new_with_protocol(&ctx, protocol, parent,
				 error)) != GPG_ERR_NO_ERROR)
	return NULL;

    /* create the data streams */
    if ((err =
	 gpgme_data_new_from_cbs(&crypt_data, &cbs,
				 crypted)) != GPG_ERR_NO_ERROR) {
	g_set_error_from_gpgme(error, err,
			       _("could not get data from stream"));
	gpgme_release(ctx);
	return NULL;
    }
    if ((err =
	 gpgme_data_new_from_cbs(&plain_data, &cbs,
				 plain)) != GPG_ERR_NO_ERROR) {
	g_set_error_from_gpgme(error, err,
			       _("could not create new data object"));
	gpgme_data_release(crypt_data);
	gpgme_release(ctx);
	return NULL;
    }

    /* try to decrypt */
    if ((err =
	 gpgme_op_decrypt_verify(ctx, crypt_data,
				 plain_data)) != GPG_ERR_NO_ERROR) {
	g_set_error_from_gpgme(error, err, _("decryption failed"));
	result = NULL;
    } else {
	/* decryption successful, check for signature */
	result = g_mime_gpgme_sigstat_new_from_gpgme_ctx(ctx);
    }

    /* clean up */
    gpgme_data_release(plain_data);
    gpgme_data_release(crypt_data);
    gpgme_release(ctx);

    return result;
}
Пример #12
0
/** \brief Encrypt data
 *
 * \param recipients Array of User ID for which the matter shall be
 *        encrypted using their public keys.
 * \param sign_for User ID of the signer or NULL if the matter shall not be
 *        signed.  Note that combined signing and encryption is allowed \em
 *        only in OpenPGP single-part (i.e. RFC 2440) mode.
 * \param istream GMime input stream.
 * \param ostream GMime output stream.
 * \param protocol GpgME crypto protocol to use for encryption.
 * \param singlepart_mode TRUE indicates single-part mode (integrated
 *        signature), FALSE a detached signature.
 * \param trust_all_keys TRUE if all low-truct keys shall be accepted for
 *        encryption.  Otherwise, the function will use the global callback
 *        to ask the user whether a low-trust key shall be accepted.
 * \param parent Parent window to be passed to the callback functions.
 * \param error Filled with error information on error.
 * \return 0 on success, or -1 on error.
 *
 * Encrypt the passed matter and write the result to the output stream.
 * Combined signing and encryption is allowed for single-part OpenPGP mode
 * only.
 */
int
libbalsa_gpgme_encrypt(GPtrArray * recipients, const char *sign_for,
		       GMimeStream * istream, GMimeStream * ostream,
		       gpgme_protocol_t protocol, gboolean singlepart_mode,
		       gboolean trust_all_keys, GtkWindow * parent,
		       GError ** error)
{
    gpgme_ctx_t ctx;
    gpgme_error_t err;
    gpgme_key_t *rcpt_keys;
    gpgme_data_t plain;
    gpgme_data_t crypt;
    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(recipients != NULL, -1);
    g_return_val_if_fail(GMIME_IS_STREAM(istream), -1);
    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, -1);

    /* create the GpgME context */
    if ((err =
	 gpgme_new_with_protocol(&ctx, protocol, parent,
				 error)) != GPG_ERR_NO_ERROR)
	return -1;

    /* sign & encrypt is valid only for single-part OpenPGP */
    if (sign_for != NULL
	&& (!singlepart_mode || protocol != GPGME_PROTOCOL_OpenPGP)) {
	if (error)
	    g_set_error(error, GPGME_ERROR_QUARK, GPG_ERR_INV_ENGINE,
			_
			("combined signing and encryption is defined only for RFC 2440"));
	gpgme_release(ctx);
	return -1;
    }

    /* if requested, find the secret key for "userid" */
    if (sign_for && !gpgme_add_signer(ctx, sign_for, parent, error)) {
	gpgme_release(ctx);
	return -1;
    }

    /* build the list of recipients */
    if (!
	(rcpt_keys =
	 gpgme_build_recipients(ctx, recipients, trust_all_keys, parent,
				error))) {
	gpgme_release(ctx);
	return -1;
    }

    /* create the data objects */
    if (protocol == GPGME_PROTOCOL_OpenPGP) {
	gpgme_set_armor(ctx, 1);
	gpgme_set_textmode(ctx, singlepart_mode);
    } else {
	gpgme_set_armor(ctx, 0);
	gpgme_set_textmode(ctx, 0);
    }
    if ((err =
	 gpgme_data_new_from_cbs(&plain, &cbs,
				 istream)) != GPG_ERR_NO_ERROR) {
	g_set_error_from_gpgme(error, err,
			       _("could not get data from stream"));
	release_keylist(rcpt_keys);
	gpgme_release(ctx);
	return -1;
    }
    if ((err =
	 gpgme_data_new_from_cbs(&crypt, &cbs,
				 ostream)) != GPG_ERR_NO_ERROR) {
	g_set_error_from_gpgme(error, err,
			       _("could not create new data object"));
	release_keylist(rcpt_keys);
	gpgme_data_release(plain);
	gpgme_release(ctx);
	return -1;
    }

    /* do the encrypt or sign and encrypt operation
     * Note: we set "always trust" here, as if we detected an untrusted key
     * earlier, the user already accepted it */
    if (sign_for)
	err =
	    gpgme_op_encrypt_sign(ctx, rcpt_keys,
				  GPGME_ENCRYPT_ALWAYS_TRUST, plain,
				  crypt);
    else
	err =
	    gpgme_op_encrypt(ctx, rcpt_keys, GPGME_ENCRYPT_ALWAYS_TRUST,
			     plain, crypt);

    release_keylist(rcpt_keys);
    gpgme_data_release(plain);
    gpgme_data_release(crypt);
    gpgme_release(ctx);
    if (err != GPG_ERR_NO_ERROR) {
	if (sign_for)
	    g_set_error_from_gpgme(error, err,
				   _("signing and encryption failed"));
	else
	    g_set_error_from_gpgme(error, err, _("encryption failed"));
	return -1;
    } else
	return 0;
}
Пример #13
0
/** \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;
}
Пример #14
0
/** \brief Verify a signature
 *
 * \param content GMime stream of the signed matter.
 * \param sig_plain GMime signature stream for a detached signature, or the
 *        output stream for the checked matter in single-part mode.
 * \param protocol GpgME crypto protocol of the signature.
 * \param singlepart_mode TRUE indicates single-part mode (i.e. sig_plain
 *        an output stream).
 * \param error Filled with error information on error.
 * \return A new signature status object on success, or NULL on error.
 *
 * Verify a signature by calling GpgME on the passed streams, and create a
 * new signature object on success.
 */
GMimeGpgmeSigstat *
libbalsa_gpgme_verify(GMimeStream * content, GMimeStream * sig_plain,
		      gpgme_protocol_t protocol, gboolean singlepart_mode,
		      GError ** error)
{
    gpgme_error_t err;
    gpgme_ctx_t ctx;
    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 */
    };
    gpgme_data_t cont_data;
    gpgme_data_t sig_plain_data;
    GMimeGpgmeSigstat *result;

    /* paranoia checks */
    g_return_val_if_fail(GMIME_IS_STREAM(content), NULL);
    g_return_val_if_fail(GMIME_IS_STREAM(sig_plain), NULL);
    g_return_val_if_fail(protocol == GPGME_PROTOCOL_OpenPGP ||
			 protocol == GPGME_PROTOCOL_CMS, NULL);

    /* create the GpgME context */
    if ((err =
	 gpgme_new_with_protocol(&ctx, protocol, NULL,
				 error)) != GPG_ERR_NO_ERROR)
	return NULL;

    /* create the message stream */
    if ((err =
	 gpgme_data_new_from_cbs(&cont_data, &cbs,
				 content)) != GPG_ERR_NO_ERROR) {
	g_set_error_from_gpgme(error, err,
			       _("could not get data from stream"));
	gpgme_release(ctx);
	return NULL;
    }

    /* create data object for the detached signature stream or the
     * "decrypted" plaintext */
    if ((err =
	 gpgme_data_new_from_cbs(&sig_plain_data, &cbs,
				 sig_plain)) != GPG_ERR_NO_ERROR) {
	g_set_error_from_gpgme(error, err,
			       _("could not get data from stream"));
	gpgme_data_release(cont_data);
	gpgme_release(ctx);
	return NULL;
    }

    /* verify the signature */
    if (singlepart_mode)
	err = gpgme_op_verify(ctx, cont_data, NULL, sig_plain_data);
    else
	err = gpgme_op_verify(ctx, sig_plain_data, cont_data, NULL);
    if (err != GPG_ERR_NO_ERROR) {
	g_set_error_from_gpgme(error, err,
			       _("signature verification failed"));
	result = g_mime_gpgme_sigstat_new();
	result->status = err;
	result->protocol = gpgme_get_protocol(ctx);
    } else
	result = g_mime_gpgme_sigstat_new_from_gpgme_ctx(ctx);

    /* release gmgme data buffers, destroy the context and return the
     * signature object */
    gpgme_data_release(cont_data);
    gpgme_data_release(sig_plain_data);
    gpgme_release(ctx);
    return result;
}
Пример #15
0
int 
main (int argc, char *argv[])
{
  gpgme_ctx_t ctx;
  gpgme_error_t err;
  struct gpgme_data_cbs cbs;
  gpgme_data_t in, out;
  gpgme_key_t key[3] = { NULL, NULL, NULL };
  gpgme_encrypt_result_t result;
  size_t nbytes;
  struct cb_parms parms;

  if (argc > 1)
    nbytes = atoi (argv[1]);
  else
    nbytes = 100000;

  init_gpgme (GPGME_PROTOCOL_OpenPGP);
    
  memset (&cbs, 0, sizeof cbs);
  cbs.read = read_cb;
  cbs.write = write_cb;
  memset (&parms, 0, sizeof parms);
  parms.bytes_to_send = nbytes;

  err = gpgme_new (&ctx);
  fail_if_err (err);
  gpgme_set_armor (ctx, 0);

  /* Install a progress handler to enforce a bit of more work to the
     gpgme i/o system. */
  gpgme_set_progress_cb (ctx, progress_cb, NULL);

  err = gpgme_data_new_from_cbs (&in, &cbs, &parms);
  fail_if_err (err);

  err = gpgme_data_new_from_cbs (&out, &cbs, &parms);
  fail_if_err (err);

  err = gpgme_get_key (ctx, "A0FF4590BB6122EDEF6E3C542D727CC768697734",
		       &key[0], 0);
  fail_if_err (err);
  err = gpgme_get_key (ctx, "D695676BDCEDCC2CDD6152BCFE180B1DA9E3B0B2",
		       &key[1], 0);
  fail_if_err (err);

  err = gpgme_op_encrypt (ctx, key, GPGME_ENCRYPT_ALWAYS_TRUST, in, out);
  fail_if_err (err);
  result = gpgme_op_encrypt_result (ctx);
  if (result->invalid_recipients)
    {
      fprintf (stderr, "Invalid recipient encountered: %s\n",
	       result->invalid_recipients->fpr);
      exit (1);
    }
  printf ("plaintext=%u bytes, ciphertext=%u bytes\n", 
          (unsigned int)nbytes, (unsigned int)parms.bytes_received);

  gpgme_key_unref (key[0]);
  gpgme_key_unref (key[1]);
  gpgme_data_release (in);
  gpgme_data_release (out);
  gpgme_release (ctx);
  return 0;
}
Пример #16
0
static int
pkcs7_encrypt (GMimeCryptoContext *context, gboolean sign, const char *userid,
	       GMimeDigestAlgo digest, GPtrArray *recipients, GMimeStream *istream,
	       GMimeStream *ostream, GError **err)
{
#ifdef ENABLE_SMIME
	GMimePkcs7Context *ctx = (GMimePkcs7Context *) context;
	Pkcs7Ctx *pkcs7 = ctx->priv;
	gpgme_data_t input, output;
	gpgme_error_t error;
	gpgme_key_t *rcpts;
	gpgme_key_t key;
	guint i;
	
	if (sign) {
		g_set_error (err, GMIME_ERROR, GMIME_ERROR_NOT_SUPPORTED,
			     _("Cannot sign and encrypt a stream at the same time using pkcs7"));
		return -1;
	}
	
	/* create an array of recipient keys for GpgMe */
	rcpts = g_new0 (gpgme_key_t, recipients->len + 1);
	for (i = 0; i < recipients->len; i++) {
		if (!(key = pkcs7_get_key_by_name (pkcs7, recipients->pdata[i], FALSE, err))) {
			key_list_free (rcpts);
			return -1;
		}
		
		rcpts[i] = key;
	}
	
	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"));
		key_list_free (rcpts);
		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);
		key_list_free (rcpts);
		return -1;
	}
	
	/* encrypt the input stream */
	error = gpgme_op_encrypt (pkcs7->ctx, rcpts, GPGME_ENCRYPT_ALWAYS_TRUST, input, output);
	gpgme_data_release (output);
	gpgme_data_release (input);
	key_list_free (rcpts);
	
	if (error != GPG_ERR_NO_ERROR) {
		g_set_error (err, GMIME_GPGME_ERROR, error, _("Encryption failed"));
		return -1;
	}
	
	return 0;
#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 */
}