Example #1
0
/*
int main(int argc, char** argv)
{
	gpgme_ctx_t ctx;
	gpgme_error_t err;
	init_gpgme(GPGME_PROTOCOL_OpenPGP);
	err = gpgme_new(&ctx);
	check_errors(err,"error with gpgme_new");
	verify_signature(ctx,"signature.c.sig","signature.c");
	
	return 0;
}
*/
bool verify_signature(gpgme_ctx_t ctx, char* sig_path,char* file_path)
{
	gpgme_error_t err;
	FILE* fp_sig = NULL;
	FILE* fp_msg = NULL;
	gpgme_data_t sig = NULL;
	gpgme_data_t msg = NULL;
	gpgme_verify_result_t result;
	fp_sig = fopen(sig_path,"rb");	//open file with signature
	if(!fp_sig)
	{
		err = gpg_error_from_syserror();
		fprintf (stderr, PGM ": can't open `%s': %s\n", sig_path, gpg_strerror(err));
		return false;
	}
	fp_msg = fopen(file_path,"rb");	//open file which want to check
	if(!fp_msg)
	{
		err = gpg_error_from_syserror();
		fprintf(stderr,PGM ": cant open `%s`: %s\n", file_path, gpg_strerror(err));
		return false;
	}
	err = gpgme_data_new_from_stream(&sig,fp_sig);	//write to gpgme_data object from fp_sig stream(signature)
	if(err)
	{
		fprintf (stderr, PGM ": error allocating data object: %s\n",gpg_strerror (err));
		return false;
	}
	if(fp_msg)
	{
		err = gpgme_data_new_from_stream(&msg,fp_msg);	//write to gpgme_data object from fp_msg(file)
		if(err)
		{
			fprintf(stderr,PGM ": error allocation data object: %s\n",gpg_strerror(err));
			return false;
		}
	}
	err = gpgme_op_verify(ctx,sig,msg,NULL);	//verify signature
	check_errors(err,"error with verify");
	result = gpgme_op_verify_result(ctx);		//get result of checking signature
	if(result)
	{
		print_result_of_checking(result);		//printf checking information
	}
	fclose(fp_sig);
	fclose(fp_msg);
	gpgme_data_release (msg);
	gpgme_data_release (sig);		
	return true;
}
Example #2
0
static void geanypg_encrypt(encrypt_data * ed, gpgme_key_t * recp, int sign, int flags)
{   /* FACTORIZE */
    gpgme_data_t plain, cipher;
    gpgme_error_t err;
    FILE * tempfile;
    tempfile = tmpfile();
    if (!(tempfile))
    {
        g_warning("%s: %s.", _("couldn't create tempfile"), strerror(errno));
        return ;
    }
    gpgme_data_new_from_stream(&cipher, tempfile);
    gpgme_data_set_encoding(cipher, GPGME_DATA_ENCODING_ARMOR);

    geanypg_load_buffer(&plain);

    /* do the actual encryption */
    if (sign)
        err = gpgme_op_encrypt_sign(ed->ctx, recp, flags, plain, cipher);
    else
        err = gpgme_op_encrypt(ed->ctx, recp, flags, plain, cipher);
    if (err != GPG_ERR_NO_ERROR && gpgme_err_code(err) != GPG_ERR_CANCELED)
        geanypg_show_err_msg(err);
    else if(gpgme_err_code(err) != GPG_ERR_CANCELED)
    {
        rewind(tempfile);
        geanypg_write_file(tempfile);
    }

    fclose(tempfile);
    /* release buffers */
    gpgme_data_release(plain);
    gpgme_data_release(cipher);
}
Example #3
0
File: filetype.c Project: gpg/gpa
/* Return true if the file FNAME looks like an CMS file.  There is no
   error return, just a best effort try to identify CMS in a file with
   a CMS object.  */
int
is_cms_file (const char *fname)
{
#ifdef HAVE_GPGME_DATA_IDENTIFY
  FILE *fp;
  gpgme_data_t dh;
  gpgme_data_type_t dt;

  fp = fopen (fname, "rb");
  if (!fp)
    return 0; /* Not found - can't be a CMS file.  */
  if (gpgme_data_new_from_stream (&dh, fp))
    {
      fclose (fp);
      return 0;
    }
  dt = gpgme_data_identify (dh, 0);
  gpgme_data_release (dh);
  fclose (fp);
  switch (dt)
    {
    case GPGME_DATA_TYPE_CMS_SIGNED:
    case GPGME_DATA_TYPE_CMS_ENCRYPTED:
    case GPGME_DATA_TYPE_CMS_OTHER:
    case GPGME_DATA_TYPE_X509_CERT:
    case GPGME_DATA_TYPE_PKCS12:
      return 1;
    default:
      return 0;
    }
#else
  int result;
  FILE *fp;
  char *data;
  size_t datalen;

  fp = fopen (fname, "rb");
  if (!fp)
    return 0; /* Not found - can't be a CMS file.  */

  data = malloc (CMS_BUFFER_SIZE);
  if (!data)
    {
      fclose (fp);
      return 0; /* Oops */
    }

  datalen = fread (data, 1, CMS_BUFFER_SIZE - 1, fp);
  data[datalen] = 0;
  fclose (fp);

  result = detect_cms (data, datalen);
  free (data);
  return result;
#endif
}
Example #4
0
char checkSignature(char *path, struct memory_identifier *memory)
{

    gpgme_ctx_t context;
    gpgme_error_t err;
    gpgme_data_t signature, iso;

    FILE *file = fopen(path, "r");

    if (file == NULL) {
        fprintf(stderr, "File %s not found!\n", path);
        fatal("Unable to open file!\n");
    }

    gpgme_check_version(NULL);

    err = gpgme_new(&context);

    switch (err) {

    case GPG_ERR_NO_ERROR:
        break;

    case GPG_ERR_ENOMEM:
        fatal("There is not enough memory available to initialize gpgme. Aborting...\n");

    default:
        break;

    }

    gpgme_set_protocol(context, GPGME_PROTOCOL_OpenPGP);
    err = gpgme_data_new_from_stream(&iso, file);

    if (err == GPG_ERR_ENOMEM)
        fatal("There was not enough memory to crate a new data buffer for gpgme. Aborting...\n");

    err = gpgme_ctx_set_engine_info(context, GPGME_PROTOCOL_OpenPGP, "/usr/bin/gpg",
                                    "/etc/pacman.d/gnupg/");
    if (err != GPG_ERR_NO_ERROR) {
        printf("Something went wrong while setting the engine info.\n");
        return 1;
    }

    err = gpgme_data_new_from_mem(&signature, memory->chunk, memory->length, 1);

    if (err == GPG_ERR_ENOMEM)
        fatal("There was not enough memory to crate a new data buffer for gpgme. Aborting...\n");

    err = gpgme_op_verify(context, signature, iso, NULL);

    if (err == GPG_ERR_NO_ERROR)
        return 0;
    else
        return 1;
}
Example #5
0
/**
 * Check the PGP signature for the given file path.
 * If base64_sig is provided, it will be used as the signature data after
 * decoding. If base64_sig is NULL, expect a signature file next to path
 * (e.g. "%s.sig").
 *
 * The return value will be 0 if nothing abnormal happened during the signature
 * check, and -1 if an error occurred while checking signatures or if a
 * signature could not be found; pm_errno will be set. Note that "abnormal"
 * does not include a failed signature; the value in siglist should be checked
 * to determine if the signature(s) are good.
 * @param handle the context handle
 * @param path the full path to a file
 * @param base64_sig optional PGP signature data in base64 encoding
 * @param siglist a pointer to storage for signature results
 * @return 0 in normal cases, -1 if the something failed in the check process
 */
int _alpm_gpgme_checksig(alpm_handle_t *handle, const char *path,
		const char *base64_sig, alpm_siglist_t *siglist)
{
	int ret = -1, sigcount;
	gpgme_error_t gpg_err = 0;
	gpgme_ctx_t ctx;
	gpgme_data_t filedata, sigdata;
	gpgme_verify_result_t verify_result;
	gpgme_signature_t gpgsig;
	char *sigpath = NULL;
	unsigned char *decoded_sigdata = NULL;
	FILE *file = NULL, *sigfile = NULL;

	if(!path || _alpm_access(handle, NULL, path, R_OK) != 0) {
		RET_ERR(handle, ALPM_ERR_NOT_A_FILE, -1);
	}

	if(!siglist) {
		RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1);
	}
	siglist->count = 0;

	if(!base64_sig) {
		sigpath = _alpm_sigpath(handle, path);
		if(_alpm_access(handle, NULL, sigpath, R_OK) != 0
				|| (sigfile = fopen(sigpath, "rb")) == NULL) {
			_alpm_log(handle, ALPM_LOG_DEBUG, "sig path %s could not be opened\n",
					sigpath);
			handle->pm_errno = ALPM_ERR_SIG_MISSING;
			goto error;
		}
	}

	/* does the file we are verifying exist? */
	file = fopen(path, "rb");
	if(file == NULL) {
		handle->pm_errno = ALPM_ERR_NOT_A_FILE;
		goto error;
	}

	if(init_gpgme(handle)) {
		/* pm_errno was set in gpgme_init() */
		goto error;
	}

	_alpm_log(handle, ALPM_LOG_DEBUG, "checking signature for %s\n", path);

	memset(&ctx, 0, sizeof(ctx));
	memset(&sigdata, 0, sizeof(sigdata));
	memset(&filedata, 0, sizeof(filedata));

	gpg_err = gpgme_new(&ctx);
	CHECK_ERR();

	/* create our necessary data objects to verify the signature */
	gpg_err = gpgme_data_new_from_stream(&filedata, file);
	CHECK_ERR();

	/* next create data object for the signature */
	if(base64_sig) {
		/* memory-based, we loaded it from a sync DB */
		size_t data_len;
		int decode_ret = alpm_decode_signature(base64_sig,
				&decoded_sigdata, &data_len);
		if(decode_ret) {
			handle->pm_errno = ALPM_ERR_SIG_INVALID;
			goto gpg_error;
		}
		gpg_err = gpgme_data_new_from_mem(&sigdata,
				(char *)decoded_sigdata, data_len, 0);
	} else {
		/* file-based, it is on disk */
		gpg_err = gpgme_data_new_from_stream(&sigdata, sigfile);
	}
	CHECK_ERR();

	/* here's where the magic happens */
	gpg_err = gpgme_op_verify(ctx, sigdata, filedata, NULL);
	CHECK_ERR();
	verify_result = gpgme_op_verify_result(ctx);
	CHECK_ERR();
	if(!verify_result || !verify_result->signatures) {
		_alpm_log(handle, ALPM_LOG_DEBUG, "no signatures returned\n");
		handle->pm_errno = ALPM_ERR_SIG_MISSING;
		goto gpg_error;
	}
	for(gpgsig = verify_result->signatures, sigcount = 0;
			gpgsig; gpgsig = gpgsig->next, sigcount++);
	_alpm_log(handle, ALPM_LOG_DEBUG, "%d signatures returned\n", sigcount);

	CALLOC(siglist->results, sigcount, sizeof(alpm_sigresult_t),
			handle->pm_errno = ALPM_ERR_MEMORY; goto gpg_error);
	siglist->count = sigcount;

	for(gpgsig = verify_result->signatures, sigcount = 0; gpgsig;
			gpgsig = gpgsig->next, sigcount++) {
		alpm_list_t *summary_list, *summary;
		alpm_sigstatus_t status;
		alpm_sigvalidity_t validity;
		gpgme_key_t key;
		alpm_sigresult_t *result;

		_alpm_log(handle, ALPM_LOG_DEBUG, "fingerprint: %s\n", gpgsig->fpr);
		summary_list = list_sigsum(gpgsig->summary);
		for(summary = summary_list; summary; summary = summary->next) {
			_alpm_log(handle, ALPM_LOG_DEBUG, "summary: %s\n", (const char *)summary->data);
		}
		alpm_list_free(summary_list);
		_alpm_log(handle, ALPM_LOG_DEBUG, "status: %s\n", gpgme_strerror(gpgsig->status));
		_alpm_log(handle, ALPM_LOG_DEBUG, "timestamp: %lu\n", gpgsig->timestamp);

		if((time_t)gpgsig->timestamp > time(NULL)) {
			_alpm_log(handle, ALPM_LOG_DEBUG,
					"signature timestamp is greater than system time.\n");
		}

		_alpm_log(handle, ALPM_LOG_DEBUG, "exp_timestamp: %lu\n", gpgsig->exp_timestamp);
		_alpm_log(handle, ALPM_LOG_DEBUG, "validity: %s; reason: %s\n",
				string_validity(gpgsig->validity),
				gpgme_strerror(gpgsig->validity_reason));

		result = siglist->results + sigcount;
		gpg_err = gpgme_get_key(ctx, gpgsig->fpr, &key, 0);
		if(gpg_err_code(gpg_err) == GPG_ERR_EOF) {
			_alpm_log(handle, ALPM_LOG_DEBUG, "key lookup failed, unknown key\n");
			gpg_err = GPG_ERR_NO_ERROR;
			/* we dupe the fpr in this case since we have no key to point at */
			STRDUP(result->key.fingerprint, gpgsig->fpr,
					handle->pm_errno = ALPM_ERR_MEMORY; goto gpg_error);
		} else {
Example #6
0
GpgME::Data::Data( FILE * fp ) {
  gpgme_data_t data;
  const gpgme_error_t e = gpgme_data_new_from_stream( &data, fp );
  d = new Private( e ? 0 : data );
  d->ref();
}
Example #7
0
gpointer
verify_signature (const gchar *detached_signature_path, const gchar *signed_file_path)
{
    init_gpgme ();
    gpgme_ctx_t ctx;
    gpgme_signature_t sig;
    gpgme_data_t signature_data, signed_data;

    gpgme_error_t error = gpgme_new (&ctx);
    if (error) {
        g_printerr ("%s:%d: %s: %s\n", __FILE__, __LINE__, gpgme_strsource (error), gpgme_strerror (error));
        return GPGME_ERROR;
    }

    gpgme_set_armor (ctx, 1);

    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 (ctx);
        return GPGME_ERROR;
    }

    const char *keyring_dir = gpgme_get_dirinfo ("homedir");
    error = gpgme_ctx_set_engine_info (ctx, 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 (ctx);
        return GPGME_ERROR;
    }

    FILE *sig_fp = g_fopen (detached_signature_path, "r");
    FILE *sig_data_fp = g_fopen (signed_file_path, "r");
    if (sig_fp == NULL || sig_data_fp == NULL) {
        g_printerr ("Couldn't open input file\n");
        gpgme_release (ctx);
        return FILE_OPEN_ERROR;
    }

    error = gpgme_data_new_from_stream (&signature_data, sig_fp);
    if (error) {
        g_printerr ("%s:%d: %s: %s\n", __FILE__, __LINE__, gpgme_strsource (error), gpgme_strerror (error));
        fclose (sig_fp);
        fclose (sig_data_fp);
        gpgme_release (ctx);
        return GPGME_ERROR;
    }

    error = gpgme_data_new_from_stream (&signed_data, sig_data_fp);
    if (error) {
        g_printerr ("%s:%d: %s: %s\n", __FILE__, __LINE__, gpgme_strsource (error), gpgme_strerror (error));
        fclose (sig_fp);
        fclose (sig_data_fp);
        gpgme_release (ctx);
        gpgme_data_release (signature_data);
        return GPGME_ERROR;
    }

    error = gpgme_op_verify (ctx, signature_data, signed_data, NULL);

    gpgme_data_release (signature_data);
    gpgme_data_release (signed_data);

    fclose (sig_fp);
    fclose (sig_data_fp);

    if (error != GPG_ERR_NO_ERROR) {
        g_printerr ("%s:%d: %s: %s\n", __FILE__, __LINE__, gpgme_strsource (error), gpgme_strerror (error));
        gpgme_release (ctx);
        return GPGME_ERROR;
    }

    gpgme_verify_result_t result = gpgme_op_verify_result (ctx);
    if (!result) {
        g_printerr ("%s:%d: %s: %s\n", __FILE__, __LINE__, gpgme_strsource (error), gpgme_strerror (error));
        gpgme_release (ctx);
        return GPGME_ERROR;
    }

    sig = result->signatures;
    if (!sig) {
        gpgme_release (ctx);
        return NO_GPG_KEYS_AVAILABLE;
    }

    for (; sig; sig = sig->next) {
        if ((sig->summary & GPGME_SIGSUM_VALID) || (sig->summary & GPGME_SIGSUM_GREEN)) {
            gpgme_release (ctx);
            return SIGNATURE_OK;
        }
        else if (sig->summary == 0 && sig->status == GPG_ERR_NO_ERROR) {  // Valid but key is not certified with a trusted signature
            gpgme_release (ctx);
            return SIGNATURE_OK_KEY_NOT_TRUSTED;
        }
    }

    gpgme_release (ctx);
    return BAD_SIGNATURE;
}
Example #8
0
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;
}
Example #9
0
/**
 * Check the PGP signature for the given file path.
 * If base64_sig is provided, it will be used as the signature data after
 * decoding. If base64_sig is NULL, expect a signature file next to path
 * (e.g. "%s.sig").
 *
 * The return value will be 0 if nothing abnormal happened during the signature
 * check, and -1 if an error occurred while checking signatures or if a
 * signature could not be found; pm_errno will be set. Note that "abnormal"
 * does not include a failed signature; the value in #result should be checked
 * to determine if the signature(s) are good.
 * @param handle the context handle
 * @param path the full path to a file
 * @param base64_sig optional PGP signature data in base64 encoding
 * @result
 * @return 0 in normal cases, -1 if the something failed in the check process
 */
int _alpm_gpgme_checksig(alpm_handle_t *handle, const char *path,
		const char *base64_sig, alpm_sigresult_t *result)
{
	int ret = -1, sigcount;
	gpgme_error_t err;
	gpgme_ctx_t ctx;
	gpgme_data_t filedata, sigdata;
	gpgme_verify_result_t verify_result;
	gpgme_signature_t gpgsig;
	char *sigpath = NULL;
	unsigned char *decoded_sigdata = NULL;
	FILE *file = NULL, *sigfile = NULL;

	if(!path || access(path, R_OK) != 0) {
		RET_ERR(handle, ALPM_ERR_NOT_A_FILE, -1);
	}

	if(!result) {
		RET_ERR(handle, ALPM_ERR_WRONG_ARGS, -1);
	}
	result->count = 0;

	if(!base64_sig) {
		size_t len = strlen(path) + 5;
		CALLOC(sigpath, len, sizeof(char), RET_ERR(handle, ALPM_ERR_MEMORY, -1));
		snprintf(sigpath, len, "%s.sig", path);

		if(!access(sigpath, R_OK) == 0) {
			/* sigcount is 0 */
		}
	}

	if(init_gpgme(handle)) {
		/* pm_errno was set in gpgme_init() */
		return -1;
	}

	_alpm_log(handle, ALPM_LOG_DEBUG, "checking signature for %s\n", path);

	memset(&ctx, 0, sizeof(ctx));
	memset(&sigdata, 0, sizeof(sigdata));
	memset(&filedata, 0, sizeof(filedata));

	err = gpgme_new(&ctx);
	CHECK_ERR();

	/* create our necessary data objects to verify the signature */
	file = fopen(path, "rb");
	if(file == NULL) {
		handle->pm_errno = ALPM_ERR_NOT_A_FILE;
		goto error;
	}
	err = gpgme_data_new_from_stream(&filedata, file);
	CHECK_ERR();

	/* next create data object for the signature */
	if(base64_sig) {
		/* memory-based, we loaded it from a sync DB */
		int data_len;
		int decode_ret = decode_signature(base64_sig,
				&decoded_sigdata, &data_len);
		if(decode_ret) {
			handle->pm_errno = ALPM_ERR_SIG_INVALID;
			goto error;
		}
		err = gpgme_data_new_from_mem(&sigdata,
				(char *)decoded_sigdata, data_len, 0);
	} else {
		/* file-based, it is on disk */
		sigfile = fopen(sigpath, "rb");
		if(sigfile == NULL) {
			handle->pm_errno = ALPM_ERR_SIG_MISSING;
			goto error;
		}
		err = gpgme_data_new_from_stream(&sigdata, sigfile);
	}
	CHECK_ERR();

	/* here's where the magic happens */
	err = gpgme_op_verify(ctx, sigdata, filedata, NULL);
	CHECK_ERR();
	verify_result = gpgme_op_verify_result(ctx);
	CHECK_ERR();
	if(!verify_result || !verify_result->signatures) {
		_alpm_log(handle, ALPM_LOG_DEBUG, "no signatures returned\n");
		handle->pm_errno = ALPM_ERR_SIG_MISSING;
		goto error;
	}
	for(gpgsig = verify_result->signatures, sigcount = 0;
			gpgsig; gpgsig = gpgsig->next, sigcount++);
	_alpm_log(handle, ALPM_LOG_DEBUG, "%d signatures returned\n", sigcount);

	result->status = calloc(sigcount, sizeof(alpm_sigstatus_t));
	result->uid = calloc(sigcount, sizeof(char*));
	if(!result->status || !result->uid) {
		handle->pm_errno = ALPM_ERR_MEMORY;
		goto error;
	}
	result->count = sigcount;

	for(gpgsig = verify_result->signatures, sigcount = 0; gpgsig;
			gpgsig = gpgsig->next, sigcount++) {
		alpm_list_t *summary_list, *summary;
		alpm_sigstatus_t status;
		gpgme_key_t key;

		_alpm_log(handle, ALPM_LOG_DEBUG, "fingerprint: %s\n", gpgsig->fpr);
		summary_list = list_sigsum(gpgsig->summary);
		for(summary = summary_list; summary; summary = summary->next) {
			_alpm_log(handle, ALPM_LOG_DEBUG, "summary: %s\n", (const char *)summary->data);
		}
		alpm_list_free(summary_list);
		_alpm_log(handle, ALPM_LOG_DEBUG, "status: %s\n", gpgme_strerror(gpgsig->status));
		_alpm_log(handle, ALPM_LOG_DEBUG, "timestamp: %lu\n", gpgsig->timestamp);
		_alpm_log(handle, ALPM_LOG_DEBUG, "exp_timestamp: %lu\n", gpgsig->exp_timestamp);
		_alpm_log(handle, ALPM_LOG_DEBUG, "validity: %s; reason: %s\n",
				string_validity(gpgsig->validity),
				gpgme_strerror(gpgsig->validity_reason));

		err = gpgme_get_key(ctx, gpgsig->fpr, &key, 0);
		if(gpg_err_code(err) == GPG_ERR_EOF) {
			_alpm_log(handle, ALPM_LOG_DEBUG, "key lookup failed, unknown key\n");
			err = GPG_ERR_NO_ERROR;
		} else {
			CHECK_ERR();
			if(key->uids) {
				const char *uid = key->uids->uid;
				STRDUP(result->uid[sigcount], uid,
						handle->pm_errno = ALPM_ERR_MEMORY; goto error);
				_alpm_log(handle, ALPM_LOG_DEBUG, "key user: %s\n", uid);
			}
			gpgme_key_unref(key);
		}

		if(gpgsig->summary & GPGME_SIGSUM_VALID) {
			/* definite good signature */
			_alpm_log(handle, ALPM_LOG_DEBUG, "result: valid signature\n");
			status = ALPM_SIGSTATUS_VALID;
		} else if(gpgsig->summary & GPGME_SIGSUM_GREEN) {
			/* good signature */
			_alpm_log(handle, ALPM_LOG_DEBUG, "result: green signature\n");
			status = ALPM_SIGSTATUS_VALID;
		} else if(gpgsig->summary & GPGME_SIGSUM_RED) {
			/* definite bad signature, error */
			_alpm_log(handle, ALPM_LOG_DEBUG, "result: red signature\n");
			status = ALPM_SIGSTATUS_BAD;
		} else if(gpgsig->summary & GPGME_SIGSUM_KEY_MISSING) {
			_alpm_log(handle, ALPM_LOG_DEBUG, "result: signature from unknown key\n");
			status = ALPM_SIGSTATUS_UNKNOWN;
		} else if(gpgsig->summary & GPGME_SIGSUM_KEY_EXPIRED) {
			_alpm_log(handle, ALPM_LOG_DEBUG, "result: key expired\n");
			status = ALPM_SIGSTATUS_BAD;
		} else if(gpgsig->summary & GPGME_SIGSUM_SIG_EXPIRED) {
			_alpm_log(handle, ALPM_LOG_DEBUG, "result: signature expired\n");
			status = ALPM_SIGSTATUS_BAD;
		} else {
			/* we'll capture everything else here */
			_alpm_log(handle, ALPM_LOG_DEBUG, "result: invalid signature\n");
			status = ALPM_SIGSTATUS_BAD;
		}

		result->status[sigcount] = status;
	}

	ret = 0;

error:
	gpgme_data_release(sigdata);
	gpgme_data_release(filedata);
	gpgme_release(ctx);
	if(sigfile) {
		fclose(sigfile);
	}
	if(file) {
		fclose(file);
	}
	FREE(sigpath);
	FREE(decoded_sigdata);
	if(gpg_err_code(err) != GPG_ERR_NO_ERROR) {
		_alpm_log(handle, ALPM_LOG_ERROR, _("GPGME error: %s\n"), gpgme_strerror(err));
		RET_ERR(handle, ALPM_ERR_GPGME, -1);
	}
	return ret;
}
Example #10
0
int
main (int argc, char **argv)
{
    int last_argc = -1;
    gpgme_error_t err;
    gpgme_ctx_t ctx;
    gpgme_protocol_t protocol = GPGME_PROTOCOL_OpenPGP;
    FILE *fp_sig = NULL;
    gpgme_data_t sig = NULL;
    FILE *fp_msg = NULL;
    gpgme_data_t msg = NULL;
    gpgme_verify_result_t result;
    int print_status = 0;

    if (argc)
    {
        argc--;
        argv++;
    }

    while (argc && last_argc != argc )
    {
        last_argc = argc;
        if (!strcmp (*argv, "--"))
        {
            argc--;
            argv++;
            break;
        }
        else if (!strcmp (*argv, "--help"))
            show_usage (0);
        else if (!strcmp (*argv, "--verbose"))
        {
            verbose = 1;
            argc--;
            argv++;
        }
        else if (!strcmp (*argv, "--status"))
        {
            print_status = 1;
            argc--;
            argv++;
        }
        else if (!strcmp (*argv, "--openpgp"))
        {
            protocol = GPGME_PROTOCOL_OpenPGP;
            argc--;
            argv++;
        }
        else if (!strcmp (*argv, "--cms"))
        {
            protocol = GPGME_PROTOCOL_CMS;
            argc--;
            argv++;
        }
        else if (!strncmp (*argv, "--", 2))
            show_usage (1);

    }

    if (argc < 1 || argc > 2)
        show_usage (1);

    fp_sig = fopen (argv[0], "rb");
    if (!fp_sig)
    {
        err = gpgme_error_from_syserror ();
        fprintf (stderr, PGM ": can't open `%s': %s\n",
                 argv[0], gpgme_strerror (err));
        exit (1);
    }
    if (argc > 1)
    {
        fp_msg = fopen (argv[1], "rb");
        if (!fp_msg)
        {
            err = gpgme_error_from_syserror ();
            fprintf (stderr, PGM ": can't open `%s': %s\n",
                     argv[1], gpgme_strerror (err));
            exit (1);
        }
    }

    init_gpgme (protocol);

    err = gpgme_new (&ctx);
    fail_if_err (err);
    gpgme_set_protocol (ctx, protocol);
    if (print_status)
    {
        gpgme_set_status_cb (ctx, status_cb, NULL);
        gpgme_set_ctx_flag (ctx, "full-status", "1");
    }
    /* gpgme_set_ctx_flag (ctx, "raw-description", "1"); */

    err = gpgme_data_new_from_stream (&sig, fp_sig);
    if (err)
    {
        fprintf (stderr, PGM ": error allocating data object: %s\n",
                 gpgme_strerror (err));
        exit (1);
    }
    if (fp_msg)
    {
        err = gpgme_data_new_from_stream (&msg, fp_msg);
        if (err)
        {
            fprintf (stderr, PGM ": error allocating data object: %s\n",
                     gpgme_strerror (err));
            exit (1);
        }
    }

    err = gpgme_op_verify (ctx, sig, msg, NULL);
    result = gpgme_op_verify_result (ctx);
    if (result)
        print_result (result);
    if (err)
    {
        fprintf (stderr, PGM ": verify failed: %s\n", gpgme_strerror (err));
        exit (1);
    }

    gpgme_data_release (msg);
    gpgme_data_release (sig);

    gpgme_release (ctx);
    return 0;
}