Beispiel #1
0
void
p_gpg_on_connect(const char *const barejid)
{
    char *pgpdir = files_get_data_path(DIR_PGP);
    GString *pubsfile = g_string_new(pgpdir);
    free(pgpdir);
    gchar *account_dir = str_replace(barejid, "@", "_at_");
    g_string_append(pubsfile, "/");
    g_string_append(pubsfile, account_dir);
    free(account_dir);

    // mkdir if doesn't exist for account
    errno = 0;
    int res = g_mkdir_with_parents(pubsfile->str, S_IRWXU);
    if (res == -1) {
        char *errmsg = strerror(errno);
        if (errmsg) {
            log_error("Error creating directory: %s, %s", pubsfile->str, errmsg);
        } else {
            log_error("Error creating directory: %s", pubsfile->str);
        }
    }

    // create or read publickeys
    g_string_append(pubsfile, "/pubkeys");
    pubsloc = pubsfile->str;
    g_string_free(pubsfile, FALSE);

    if (g_file_test(pubsloc, G_FILE_TEST_EXISTS)) {
        g_chmod(pubsloc, S_IRUSR | S_IWUSR);
    }

    pubkeyfile = g_key_file_new();
    g_key_file_load_from_file(pubkeyfile, pubsloc, G_KEY_FILE_KEEP_COMMENTS, NULL);

    // load each keyid
    gsize len = 0;
    gchar **jids = g_key_file_get_groups(pubkeyfile, &len);

    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));
        g_strfreev(jids);
        return;
    }

    int i = 0;
    for (i = 0; i < len; i++) {
        GError *gerr = NULL;
        gchar *jid = jids[i];
        gchar *keyid = g_key_file_get_string(pubkeyfile, jid, "keyid", &gerr);
        if (gerr) {
            log_error("Error loading PGP key id for %s", jid);
            g_error_free(gerr);
            g_free(keyid);
        } else {
            gpgme_key_t key = NULL;
            error = gpgme_get_key(ctx, keyid, &key, 0);
            if (error || key == NULL) {
                log_warning("GPG: Failed to get key for %s: %s %s", jid, gpgme_strsource(error), gpgme_strerror(error));
                continue;
            }

            ProfPGPPubKeyId *pubkeyid = malloc(sizeof(ProfPGPPubKeyId));
            pubkeyid->id = strdup(keyid);
            pubkeyid->received = FALSE;
            g_hash_table_replace(pubkeys, strdup(jid), pubkeyid);
            g_free(keyid);
            gpgme_key_unref(key);
        }
    }

    gpgme_release(ctx);
    g_strfreev(jids);

    _save_pubkeys();
}
Beispiel #2
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 gpgDecrypt(char* buffer, int size, char** newbuffer, int* newsize,
    PASSPHRASE_FN password_cb, SHOWERROR_FN showerror_cb)
  {
    gpgme_ctx_t         context;
    gpgme_error_t       error;
    gpgme_data_t        input,
                        output;
    gpgme_decrypt_result_t  decrypt_result = NULL;
    gpgme_verify_result_t   verify_result;
    int                 showerror = 1;
    char*               agent;
    char*               tmpbuffer = NULL;

    TRACE(99, "gpgDecrypt()", NULL);

    /* we set our passphrase callback function */
    passphrase_callback = password_cb;

    *newbuffer = NULL;
    *newsize = 0;

    error = gpgme_new(&context);
    if (error)
      {
        (showerror_cb)(_("GpgMe context error"), gpgme_strerror(error));
        return 1;
      }
    else
      {   /* we got a context, we set the passphrase callback */
        /* 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)
      { error = gpgme_op_decrypt_verify(context, input, output); }

    if (!error)
      { decrypt_result = gpgme_op_decrypt_result(context); }

    if (!error &&
        decrypt_result &&
        decrypt_result -> unsupported_algorithm)
      {
        tmpbuffer = memAlloc(__FILE__, __LINE__, STDBUFFERLENGTH);
        snprintf(tmpbuffer, STDBUFFERLENGTH, _("unsupported algorithm: %s\n"),
            decrypt_result -> unsupported_algorithm);
        (showerror_cb)(_("GpgMe error"), tmpbuffer);
        memFree(__FILE__, __LINE__, tmpbuffer, STDBUFFERLENGTH);

        showerror = 0;
        error = 1;
      }

    if (!error)
      {
        verify_result = gpgme_op_verify_result(context);
        error = gpgCheckVerifyResult(showerror_cb, verify_result,
            GPG_ERR_NO_ERROR);
        showerror = !error;
      }

    /* we don't need the passphrase any longer */
    clearPassphrase(0);

    if (!error)
      { tmpbuffer = gpgData2Char(output, newsize); }

#ifdef GPGME_HAS_RECIPIENT
    /* we get the recipients of the message for the further re-encryption of
     * the file
     */
    if (!error &&
        decrypt_result &&
        decrypt_result -> recipients)
      {
        error = gpgGetRecipients(decrypt_result -> recipients, showerror_cb);
        showerror = 0;
      }
#endif

    gpgme_data_release(input);
    gpgme_data_release(output);
    gpgme_release(context);

    *newbuffer = tmpbuffer;

    if (error)
      {
        if (showerror)
          { (showerror_cb)(_("GpgMe decrypt error"), gpgme_strerror(error)); }
        return 1;
      }
    else
        return 0;
  }
Beispiel #3
0
/* #############################################################################
 *
 * Description    find a fingerprint for the given key
 * Author         Harry Brueckner
 * Date           2005-04-07
 * Arguments      keyname       - description string
 *                secret_only   - if set to 1, only secret keys are listed
 * Return         char* with the found fingerprint; the string must be freed
 *                by the caller
 */
char* gpgGetFingerprint(char* keyname, int secret_only)
  {
    gpgme_ctx_t         context;
    gpgme_key_t         key;
    gpgme_error_t       error;
    char*               identifier = NULL;

    TRACE(99, "gpgGetFingerprint()", NULL);

    if (!config -> encryptdata)
      { return NULL; }

    /* get a new context */
    error = gpgme_new(&context);
    if (error)
      {
        gpgme_release(context);
        gpgError(error);
        return NULL;
      }

    /* start cycling through the list of keys */
    error = gpgme_op_keylist_start(context, keyname, secret_only);
    if (error)
      {
        gpgme_release(context);
        gpgError(error);
        return NULL;
      }

    /* first we look for secret keys */
    while (!identifier &&
        !(error = gpgme_op_keylist_next(context, &key)))
      {   /* take the first key we find */
        if (!identifier &&
            !key -> disabled &&
            !key -> expired &&
            !key -> invalid &&
            !key -> revoked)
          {   /* we just use keys we can encrypt for */
            identifier = memAlloc(__FILE__, __LINE__,
                strlen(key -> subkeys -> fpr) + 1);
            strStrncpy(identifier, key -> subkeys -> fpr,
                strlen(key -> subkeys -> fpr) + 1);
          }

        gpgme_key_unref(key);
      }

    if (error &&
        gpg_err_code(error) != GPG_ERR_EOF)
      {    /* we validate the last value of the 'next' operation */
        gpgme_release(context);
        gpgError(error);
        return NULL;
      }

    /* finish the key listing */
    error = gpgme_op_keylist_end(context);
    if (error)
      {
        gpgme_release(context);
        gpgError(error);
        return NULL;
      }

    gpgme_release(context);

    return identifier;
  }
Beispiel #4
0
int main(int argc, char *argv[])
{
	char * op=(char *)0;
	char * search=(char *)0;
	char * searchdec=(char *)0;
	char * exact=(char *)0;

	gpgme_ctx_t gpgctx;
	gpgme_key_t gpgkey;
	gpgme_error_t gpgerr;
	gpgme_engine_info_t enginfo;

	char * qstring, * pchar;

	pchar=getenv("QUERY_STRING");
	if (! pchar || *pchar == '\0' ) {
		http_header(500,CTYPE_HTML_STR);
		printf("<html><head><title>Error handling request</title></head><body><h1>Error handling request: there is no query string.</h1></body></html>");
		return 1;
	}
	qstring=strndup(pchar,QSTRING_MAX); /* copy the QUERY from env to write in */
	pchar=qstring;

	while (pchar && *pchar) {
		if (!strncmp(pchar,"op=",3)) {
			pchar+=3;
			op=pchar;
		} else if (!strncmp(pchar,"search=",7)) {
			pchar+=7;
			search=pchar;
		} else if (!strncmp(pchar,"options=",8)) {
			/*this parameter is useless now, as today we only support "mr" option and always enable it (machine readable) */
			pchar+=8;
			//options=pchar;
		} else if (!strncmp(pchar,"fingerprint=",12)) {
			/*this parameter is useless now as we only support "mr" options which don't care this */
			pchar+=12;
			//fingerprints=pchar;
		} else if (!strncmp(pchar,"exact=",6)) {
			pchar+=6;
			exact=pchar;
		} /*else: Other parameter not in hkp draft are quietly ignored */
		pchar=strchr(pchar,'&');
		if (pchar) {
			*pchar='\0';
			pchar++;
		}
	}

	if (exact) {
		if (!strcmp(exact,"off")) {
			exact=(char *) 0; /* off is default */
		} else if (!strcmp(exact,"on")) {
			http_header(501,CTYPE_HTML_STR);
			printf("<html><head><title>Not implemented</title></head><body><h1>Error handling request: \"exact\" parameter is not implemented.</h1></body></html>");
			return 1;
		} else {
			http_header(500,CTYPE_HTML_STR);
			printf("<html><head><title>Error handling request</title></head><body><h1>Error handling request: \"exact\" parameter only take \"on\" or \"off\" as argument.</h1></body></html>");
			return 1;
		}
	}

	if ( ! search ) { 
		/* (mandatory parameter) */
		http_header(500,CTYPE_HTML_STR);
		printf("<html><head><title>Error handling request</title></head><body><h1>Error handling request: Missing \"search\" parameter in \"%s\".</h1></body></html>",getenv("QUERY_STRING"));
		return 1;
	} else {
		if (searchdec=malloc(strlen(search)*sizeof(char)+1)) 
			strdecode(searchdec,search);
		else {
			http_header(500,CTYPE_HTML_STR);
			printf("<html><head><title>Internal Error</title></head><body><h1>Internal malloc(%d) for search fail.</h1></body></html>",strlen(search)*sizeof(char)+1);
			return 1;
		}
	}

	if ( ! op )
		op="index"; /* defaut operation */

	/* Check gpgme version ( http://www.gnupg.org/documentation/manuals/gpgme/Library-Version-Check.html )*/
	setlocale (LC_ALL, "");
	gpgme_check_version (NULL);
	gpgme_set_locale (NULL, LC_CTYPE, setlocale (LC_CTYPE, NULL));
	/* check for OpenPGP support */
	gpgerr=gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP);
	if ( gpgerr  != GPG_ERR_NO_ERROR ) {
		http_header(500,CTYPE_HTML_STR);
		printf("<html><head><title>Internal Error</title></head><body><h1>Error handling request due to internal error (gpgme_engine_check_version).</h1></body></html>");
		return 1;
	}

	/* create context */
	gpgerr=gpgme_new(&gpgctx);
	if ( gpgerr  != GPG_ERR_NO_ERROR ) {
		http_header(500,CTYPE_HTML_STR);
		printf("<html><head><title>Internal Error</title></head><body><h1>Error handling request due to internal error (gpgme_new %d).</h1></body></html>",gpgerr);
		return 1;
	}
	/*gpgerr = gpgme_get_engine_info(&enginfo);
	gpgerr |= gpgme_ctx_set_engine_info(gpgctx, GPGME_PROTOCOL_OpenPGP, enginfo->file_name,"../../new");
	if ( gpgerr  != GPG_ERR_NO_ERROR ) {
		http_header(500,CTYPE_HTML_STR);
		printf("<html><head><title>Internal Error</title></head><body><h1>Error handling request due to internal error (gpgme_ctx_set_engine_info %d).</h1></body></html>",gpgerr);
		return 1;
	}*/

	if (!strcmp(op, "get")) {
		gpgme_data_t gpgdata;
		char buff[BUFFSIZE];
		ssize_t read_bytes;

		gpgme_set_armor(gpgctx,1);
		gpgerr = gpgme_data_new(&gpgdata);
		if (gpgerr == GPG_ERR_NO_ERROR) {
			gpgerr = gpgme_data_set_encoding(gpgdata,GPGME_DATA_ENCODING_ARMOR);
			if (gpgerr == GPG_ERR_NO_ERROR)
				gpgerr = gpgme_op_export(gpgctx,searchdec,0,gpgdata);
		}

		if ( gpgerr != GPG_ERR_NO_ERROR) {
			http_header(500,CTYPE_HTML_STR);
			printf("<html><head><title>Internal Error</title></head><body><h1>Error handling request due to internal error (%d).</h1></body></html>",gpgerr);
			return 1;
		}
		gpgme_data_seek (gpgdata, 0, SEEK_SET);
		read_bytes = gpgme_data_read (gpgdata, buff, BUFFSIZE);
		if ( read_bytes == -1 ) {
			http_header(500,CTYPE_HTML_STR);
			printf("<html><head><title>Internal Error</title></head><body><h1>Error handling request due to internal error (%s).</h1></body></html>",gpgme_strerror(errno));
			return 1;
		} else if ( read_bytes <= 0 ) {
			http_header(404,CTYPE_HTML_STR);
			printf("<html><head><title>ludd Public Key Server -- Get: %s</title></head><body><h1>Public Key Server -- Get: %s : No key found ! :-( </h1></body></html>",search,search);
			return 0;
		} else {
			http_header(200,CTYPE_HTML_STR);
			printf("<html><head><title>ludd Public Key Server -- Get: %s</title></head><body><h1>Public Key Server -- Get: %s</h1><pre>",search,search);
			fwrite(buff, sizeof(char),read_bytes,stdout); /* Now it's too late to test fwrite return value ;-) */ 
			while ( (read_bytes = gpgme_data_read (gpgdata, buff, BUFFSIZE)) > 0 )
				fwrite(buff, sizeof(char),read_bytes,stdout);
			printf("\n</pre></body></html>");
			return 0;
		}

	} else if (!strcmp(op, "index")) {
		char uidenc[BUFFSIZE];
		char begin=0;
		gpgme_user_id_t gpguid;

		/* check for the searched key(s) */
		gpgerr = gpgme_op_keylist_start(gpgctx, searchdec, 0);
		//gpgerr = gpgme_op_keylist_start(gpgctx, NULL, 0);
		if ( gpgerr  != GPG_ERR_NO_ERROR ) {
			http_header(500,CTYPE_HTML_STR);
			printf("<html><head><title>Internal Error</title></head><body><h1>Error handling request due to internal error (gpgme_op_keylist_start %d).</h1></body></html>",gpgerr);
			return 1;
		}

		gpgerr = gpgme_op_keylist_next (gpgctx, &gpgkey);
		while (gpgerr == GPG_ERR_NO_ERROR) {
			if (!begin) {
				http_header(200,"text/plain; charset=utf-8");
				begin=1;
				/* Luckily: info "header" is optionnal, see draft-shaw-openpgp-hkp-00.txt */
			}
			/* first subkey is the main key */
			printf("pub:%s:%d:%d:%d:%d\n",gpgkey->subkeys->fpr,gpgkey->subkeys->pubkey_algo,gpgkey->subkeys->length,gpgkey->subkeys->timestamp,(gpgkey->subkeys->expires?gpgkey->subkeys->expires:-1));
			gpguid=gpgkey->uids;
			while (gpguid) {
				printf("uid:%s (%s) <%s>:\n",gpguid->name,gpguid->comment,gpguid->email);
				gpguid=gpguid->next;
			}
			gpgme_key_unref(gpgkey);
			gpgerr = gpgme_op_keylist_next (gpgctx, &gpgkey);
		}
			gpgme_key_unref(gpgkey); /* ... because i don't know how "gpgme_op_keylist_next" behave when not returning GPG_ERR_NO_ERROR */
		if (!begin) {
			http_header(404,CTYPE_HTML_STR);
			printf("<html><head><title>ludd Public Key Server -- index: %s</title></head><body><h1>index Error: No keys found</h1></body></html>",search);
			return 1;
		}
		return 0;

	} else if ( !strcmp(op, "photo") || !strcmp(op, "x-photo") ) {
			http_header(501,CTYPE_HTML_STR);
			printf("<html><head><title>Not implemented</title></head><body><h1>Error handling request: \"%s\" operation is not implemented.</h1></body></html>",op);
			return 1;
	} else {
		http_header(500,CTYPE_HTML_STR);
		printf("<html><head><title>Error handling request</title></head><body><h1>Error handling request: Unrecognized action in \"%s\".</h1></body></html>",getenv("QUERY_STRING"));
		return 1;
	}
}
Beispiel #5
0
/* #############################################################################
 *
 * Description    check if for the given keyname a secret key exists
 * Author         Harry Brueckner
 * Date           2005-04-25
 * Arguments      char* keyname   - the key to check
 * Return         int 1 if there is a secret key, 0 if not and -1 if a gpg
 *                      error occured
 */
int gpgIsSecretKey(char* keyname)
  {
    gpgme_ctx_t         context;
    gpgme_key_t         key;
    gpgme_error_t       error;
    int                 secret = 0;

    TRACE(99, "gpgIsSecretKey()", NULL);

    if (!config -> encryptdata)
      { return 0; }

    /* get a new context */
    error = gpgme_new(&context);
    if (error)
      {
        gpgme_release(context);
        gpgError(error);
        return -1;
      }

    /* start cycling through the list of keys */
    error = gpgme_op_keylist_start(context, keyname, LIST_SECRET);
    if (error)
      {
        gpgme_release(context);
        gpgError(error);
        return -1;
      }

    while (!(error = gpgme_op_keylist_next(context, &key)))
      {   /* take the first usable key we find */
        /* TODO: only choose usable secret keys */
        if (key -> can_encrypt &&
            key -> secret &&
            !key -> disabled &&
            !key -> expired &&
            !key -> invalid &&
            !key -> revoked)
          {   /* we just use keys we can encrypt for */
            secret = 1;
          }

        gpgme_key_unref(key);

        if (secret)
          { break; }
      }

    if (error &&
        gpg_err_code(error) != GPG_ERR_EOF)
      {    /* we validate the last value of the 'next' operation */
        gpgme_release(context);
        gpgError(error);
        return -1;
      }

    /* finish the key listing */
    error = gpgme_op_keylist_end(context);
    if (error)
      {
        gpgme_release(context);
        gpgError(error);
        return -1;
      }

    gpgme_release(context);

    return secret;
  }
Beispiel #6
0
static gint pgpinline_check_signature(MimeInfo *mimeinfo)
{
    PrivacyDataPGP *data = NULL;
    gchar *textdata = NULL, *tmp = NULL;
    gpgme_data_t plain = NULL, cipher = NULL;
    gpgme_error_t err;

    cm_return_val_if_fail(mimeinfo != NULL, 0);

    if (procmime_mimeinfo_parent(mimeinfo) == NULL) {
        privacy_set_error(_("Incorrect part"));
        return 0; /* not parent */
    }
    if (mimeinfo->type != MIMETYPE_TEXT) {
        privacy_set_error(_("Not a text part"));
        debug_print("type %d\n", mimeinfo->type);
        return 0;
    }
    cm_return_val_if_fail(mimeinfo->privacy != NULL, 0);
    data = (PrivacyDataPGP *) mimeinfo->privacy;

    textdata = get_part_as_string(mimeinfo);

    if (!textdata) {
        g_free(textdata);
        privacy_set_error(_("Couldn't get text data."));
        return 0;
    }

    /* gtk2: convert back from utf8 */
    tmp = conv_codeset_strdup(textdata, CS_UTF_8,
                              procmime_mimeinfo_get_parameter(mimeinfo, "charset"));
    if (!tmp) {
        tmp = conv_codeset_strdup(textdata, CS_UTF_8,
                                  conv_get_locale_charset_str_no_utf8());
    }
    if (!tmp) {
        g_warning("Can't convert charset to anything sane");
        tmp = conv_codeset_strdup(textdata, CS_UTF_8, CS_US_ASCII);
    }
    g_free(textdata);

    if (!tmp) {
        privacy_set_error(_("Couldn't convert text data to any sane charset."));
        return 0;
    }
    textdata = g_strdup(tmp);
    g_free(tmp);

    if ((err = gpgme_new(&data->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));
        g_free(textdata);
        return 0;
    }
    gpgme_set_textmode(data->ctx, 1);
    gpgme_set_armor(data->ctx, 1);

    gpgme_data_new_from_mem(&plain, textdata, (size_t)strlen(textdata), 1);
    gpgme_data_new(&cipher);

    data->sigstatus = sgpgme_verify_signature(data->ctx, plain, NULL, cipher);

    gpgme_data_release(plain);
    gpgme_data_release(cipher);

    g_free(textdata);

    return 0;
}
Beispiel #7
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;
}
Beispiel #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;
}
Beispiel #9
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;
}
Beispiel #10
0
char*
p_gpg_decrypt(const char *const cipher)
{
    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);

    char *cipher_with_headers = _add_header_footer(cipher, PGP_MESSAGE_HEADER, PGP_MESSAGE_FOOTER);
    gpgme_data_t cipher_data;
    gpgme_data_new_from_mem(&cipher_data, cipher_with_headers, strlen(cipher_with_headers), 1);
    free(cipher_with_headers);

    gpgme_data_t plain_data;
    gpgme_data_new(&plain_data);

    error = gpgme_op_decrypt(ctx, cipher_data, plain_data);
    gpgme_data_release(cipher_data);

    if (error) {
        log_error("GPG: Failed to encrypt message. %s %s", gpgme_strsource(error), gpgme_strerror(error));
        gpgme_data_release(plain_data);
        gpgme_release(ctx);
        return NULL;
    }

    gpgme_decrypt_result_t res = gpgme_op_decrypt_result(ctx);
    if (res) {
        GString *recipients_str = g_string_new("");
        gpgme_recipient_t recipient = res->recipients;
        while (recipient) {
            gpgme_key_t key;
            error = gpgme_get_key(ctx, recipient->keyid, &key, 1);

            if (!error && key) {
                const char *addr = gpgme_key_get_string_attr(key, GPGME_ATTR_EMAIL, NULL, 0);
                if (addr) {
                    g_string_append(recipients_str, addr);
                }
                gpgme_key_unref(key);
            }

            if (recipient->next) {
                g_string_append(recipients_str, ", ");
            }

            recipient = recipient->next;
        }

        log_debug("GPG: Decrypted message for recipients: %s", recipients_str->str);
        g_string_free(recipients_str, TRUE);
    }
    gpgme_release(ctx);

    size_t len = 0;
    char *plain_str = gpgme_data_release_and_get_mem(plain_data, &len);
    char *result = NULL;
    if (plain_str) {
        plain_str[len] = 0;
        result = g_strdup(plain_str);
    }
    gpgme_free(plain_str);

    if (passphrase_attempt) {
        passphrase = strdup(passphrase_attempt);
    }

    return result;
}
Beispiel #11
0
int
main (int argc, char **argv)
{
  int last_argc = -1;
  gpgme_error_t err;
  gpgme_ctx_t ctx;
  const char *key_string = NULL;
  gpgme_protocol_t protocol = GPGME_PROTOCOL_OpenPGP;
  gpgme_sig_mode_t sigmode = GPGME_SIG_MODE_CLEAR;
  gpgme_data_t in, out;

  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, "--key"))
        {
          argc--; argv++;
          if (!argc)
            show_usage (1);
          key_string = *argv;
          argc--; argv++;
        }
      else if (!strncmp (*argv, "--", 2))
        show_usage (1);

    }

  if (argc != 1)
    show_usage (1);

  init_gpgme (protocol);

  err = gpgme_new (&ctx);
  fail_if_err (err);
  gpgme_set_protocol (ctx, protocol);
  gpgme_set_armor (ctx, 1);

  if (key_string)
    {
      gpgme_key_t akey;

      err = gpgme_get_key (ctx, key_string, &akey, 1);
      if (err)
        {
          exit (1);
        }
      err = gpgme_signers_add (ctx, akey);
      fail_if_err (err);
      gpgme_key_unref (akey);
    }

  err = gpgme_data_new_from_file (&in, *argv, 1);
  if (err)
    {
      fprintf (stderr, PGM ": error reading `%s': %s\n",
               *argv, gpg_strerror (err));
      exit (1);
    }

  err = gpgme_data_new (&out);
  fail_if_err (err);

  err = gpgme_op_sign (ctx, in, out, sigmode);
  if (err)
    {
      fprintf (stderr, PGM ": signing failed: %s\n", gpg_strerror (err));
      exit (1);
    }

  print_data (out);
  gpgme_data_release (out);

  gpgme_data_release (in);

  gpgme_release (ctx);
  return 0;
}
Beispiel #12
0
char*
p_gpg_encrypt(const char *const barejid, const char *const message, const char *const fp)
{
    ProfPGPPubKeyId *pubkeyid = g_hash_table_lookup(pubkeys, barejid);
    if (!pubkeyid) {
        return NULL;
    }
    if (!pubkeyid->id) {
        return NULL;
    }

    gpgme_key_t keys[3];

    keys[0] = NULL;
    keys[1] = NULL;
    keys[2] = NULL;

    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_key_t receiver_key;
    error = gpgme_get_key(ctx, pubkeyid->id, &receiver_key, 0);
    if (error || receiver_key == NULL) {
        log_error("GPG: Failed to get receiver_key. %s %s", gpgme_strsource(error), gpgme_strerror(error));
        gpgme_release(ctx);
        return NULL;
    }
    keys[0] = receiver_key;

    gpgme_key_t sender_key = NULL;
    error = gpgme_get_key(ctx, fp, &sender_key, 0);
    if (error || sender_key == NULL) {
        log_error("GPG: Failed to get sender_key. %s %s", gpgme_strsource(error), gpgme_strerror(error));
        gpgme_release(ctx);
        return NULL;
    }
    keys[1] = sender_key;

    gpgme_data_t plain;
    gpgme_data_new_from_mem(&plain, message, strlen(message), 1);

    gpgme_data_t cipher;
    gpgme_data_new(&cipher);

    gpgme_set_armor(ctx, 1);
    error = gpgme_op_encrypt(ctx, keys, GPGME_ENCRYPT_ALWAYS_TRUST, plain, cipher);
    gpgme_data_release(plain);
    gpgme_release(ctx);
    gpgme_key_unref(receiver_key);
    gpgme_key_unref(sender_key);

    if (error) {
        log_error("GPG: Failed to encrypt message. %s %s", gpgme_strsource(error), gpgme_strerror(error));
        return NULL;
    }

    size_t len;
    char *cipher_str = gpgme_data_release_and_get_mem(cipher, &len);

    char *result = NULL;
    if (cipher_str) {
        GString *cipher_gstr = g_string_new("");
        g_string_append_len(cipher_gstr, cipher_str, len);
        result = _remove_header_footer(cipher_gstr->str, PGP_MESSAGE_FOOTER);
        g_string_free(cipher_gstr, TRUE);
        gpgme_free(cipher_str);
    }

    return result;
}
Beispiel #13
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 #14
0
GHashTable*
p_gpg_list_keys(void)
{
    gpgme_error_t error;
    GHashTable *result = g_hash_table_new_full(g_str_hash, g_str_equal, free, (GDestroyNotify)_p_gpg_free_key);

    gpgme_ctx_t ctx;
    error = gpgme_new(&ctx);

    if (error) {
        log_error("GPG: Could not list keys. %s %s", gpgme_strsource(error), gpgme_strerror(error));
        return NULL;
    }

    error = gpgme_op_keylist_start(ctx, NULL, 0);
    if (error == GPG_ERR_NO_ERROR) {
        gpgme_key_t key;
        error = gpgme_op_keylist_next(ctx, &key);
        while (!error) {
            gpgme_subkey_t sub = key->subkeys;

            ProfPGPKey *p_pgpkey = _p_gpg_key_new();
            p_pgpkey->id = strdup(sub->keyid);
            p_pgpkey->name = strdup(key->uids->uid);
            p_pgpkey->fp = strdup(sub->fpr);
            if (sub->can_encrypt) p_pgpkey->encrypt = TRUE;
            if (sub->can_authenticate) p_pgpkey->authenticate = TRUE;
            if (sub->can_certify) p_pgpkey->certify = TRUE;
            if (sub->can_sign) p_pgpkey->sign = TRUE;

            sub = sub->next;
            while (sub) {
                if (sub->can_encrypt) p_pgpkey->encrypt = TRUE;
                if (sub->can_authenticate) p_pgpkey->authenticate = TRUE;
                if (sub->can_certify) p_pgpkey->certify = TRUE;
                if (sub->can_sign) p_pgpkey->sign = TRUE;

                sub = sub->next;
            }

            g_hash_table_insert(result, strdup(p_pgpkey->name), p_pgpkey);

            gpgme_key_unref(key);
            error = gpgme_op_keylist_next(ctx, &key);
        }
    }

    error = gpgme_op_keylist_start(ctx, NULL, 1);
    if (error == GPG_ERR_NO_ERROR) {
        gpgme_key_t key;
        error = gpgme_op_keylist_next(ctx, &key);
        while (!error) {
            gpgme_subkey_t sub = key->subkeys;
            while (sub) {
                if (sub->secret) {
                    ProfPGPKey *p_pgpkey = g_hash_table_lookup(result, key->uids->uid);
                    if (p_pgpkey) {
                        p_pgpkey->secret = TRUE;
                    }
                }
                sub = sub->next;
            }

            gpgme_key_unref(key);
            error = gpgme_op_keylist_next(ctx, &key);
        }
    }

    gpgme_release(ctx);

    autocomplete_clear(key_ac);
    GList *ids = g_hash_table_get_keys(result);
    GList *curr = ids;
    while (curr) {
        ProfPGPKey *key = g_hash_table_lookup(result, curr->data);
        autocomplete_add(key_ac, key->id);
        curr = curr->next;
    }
    g_list_free(ids);

    return result;
}
Beispiel #15
0
/* Loop through all files in metalink structure and retrieve them.
   Returns RETROK if all files were downloaded.
   Returns last retrieval error (from retrieve_url) if some files
   could not be downloaded.  */
uerr_t
retrieve_from_metalink (const metalink_t* metalink)
{
  metalink_file_t **mfile_ptr;
  uerr_t last_retr_err = RETROK; /* Store last encountered retrieve error.  */

  FILE *_output_stream = output_stream;
  bool _output_stream_regular = output_stream_regular;
  char *_output_document = opt.output_document;

  DEBUGP (("Retrieving from Metalink\n"));

  /* No files to download.  */
  if (!metalink->files)
    return RETROK;

  if (opt.output_document)
    {
      /* We cannot support output_document as we need to compute checksum
         of downloaded file, and to remove it if the checksum is bad.  */
      logputs (LOG_NOTQUIET,
               _("-O not supported for metalink download. Ignoring.\n"));
    }

  for (mfile_ptr = metalink->files; *mfile_ptr; mfile_ptr++)
    {
      metalink_file_t *mfile = *mfile_ptr;
      metalink_resource_t **mres_ptr;
      char *filename = NULL;
      bool hash_ok = false;

      uerr_t retr_err = METALINK_MISSING_RESOURCE;

      /* -1 -> file should be rejected
         0 -> could not verify
         1 -> verified successfully  */
      char sig_status = 0;

      output_stream = NULL;

      DEBUGP (("Processing metalink file %s...\n", quote (mfile->name)));

      /* Resources are sorted by priority.  */
      for (mres_ptr = mfile->resources; *mres_ptr; mres_ptr++)
        {
          metalink_resource_t *mres = *mres_ptr;
          metalink_checksum_t **mchksum_ptr, *mchksum;
          struct iri *iri;
          struct url *url;
          int url_err;

          if (!RES_TYPE_SUPPORTED (mres->type))
            {
              logprintf (LOG_VERBOSE,
                         _("Resource type %s not supported, ignoring...\n"),
                         quote (mres->type));
              continue;
            }

          retr_err = METALINK_RETR_ERROR;

          /* If output_stream is not NULL, then we have failed on
             previous resource and are retrying. Thus, remove the file.  */
          if (output_stream)
            {
              fclose (output_stream);
              output_stream = NULL;
              if (unlink (filename))
                logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
              xfree (filename);
            }

          /* Parse our resource URL.  */
          iri = iri_new ();
          set_uri_encoding (iri, opt.locale, true);
          url = url_parse (mres->url, &url_err, iri, false);

          if (!url)
            {
              char *error = url_error (mres->url, url_err);
              logprintf (LOG_NOTQUIET, "%s: %s.\n", mres->url, error);
              xfree (error);
              inform_exit_status (URLERROR);
              iri_free (iri);
              continue;
            }
          else
            {
              /* Avoid recursive Metalink from HTTP headers.  */
              bool _metalink_http = opt.metalink_over_http;

              /* Assure proper local file name regardless of the URL
                 of particular Metalink resource.
                 To do that we create the local file here and put
                 it as output_stream. We restore the original configuration
                 after we are finished with the file.  */
              output_stream = unique_create (mfile->name, true, &filename);
              output_stream_regular = true;

              /* Store the real file name for displaying in messages.  */
              opt.output_document = filename;

              opt.metalink_over_http = false;
              DEBUGP (("Storing to %s\n", filename));
              retr_err = retrieve_url (url, mres->url, NULL, NULL,
                                       NULL, NULL, opt.recursive, iri, false);
              opt.metalink_over_http = _metalink_http;
            }
          url_free (url);
          iri_free (iri);

          if (retr_err == RETROK)
            {
              FILE *local_file;

              /* Check the digest.  */
              local_file = fopen (filename, "rb");
              if (!local_file)
                {
                  logprintf (LOG_NOTQUIET, _("Could not open downloaded file.\n"));
                  continue;
                }

              for (mchksum_ptr = mfile->checksums; *mchksum_ptr; mchksum_ptr++)
                {
                  char sha256[SHA256_DIGEST_SIZE];
                  char sha256_txt[2 * SHA256_DIGEST_SIZE + 1];

                  mchksum = *mchksum_ptr;

                  /* I have seen both variants...  */
                  if (strcasecmp (mchksum->type, "sha256")
                      && strcasecmp (mchksum->type, "sha-256"))
                    {
                      DEBUGP (("Ignoring unsupported checksum type %s.\n",
                               quote (mchksum->type)));
                      continue;
                    }

                  logprintf (LOG_VERBOSE, _("Computing checksum for %s\n"),
                             quote (mfile->name));

                  sha256_stream (local_file, sha256);
                  wg_hex_to_string (sha256_txt, sha256, SHA256_DIGEST_SIZE);
                  DEBUGP (("Declared hash: %s\n", mchksum->hash));
                  DEBUGP (("Computed hash: %s\n", sha256_txt));
                  if (!strcmp (sha256_txt, mchksum->hash))
                    {
                      logputs (LOG_VERBOSE,
                               _("Checksum matches.\n"));
                      hash_ok = true;
                    }
                  else
                    {
                      logprintf (LOG_NOTQUIET,
                                 _("Checksum mismatch for file %s.\n"),
                                 quote (mfile->name));
                      hash_ok = false;
                    }

                  /* Stop as soon as we checked the supported checksum.  */
                  break;
                } /* Iterate over available checksums.  */
              fclose (local_file);
              local_file = NULL;

              if (!hash_ok)
                continue;

              sig_status = 0; /* Not verified.  */

#ifdef HAVE_GPGME
              /* Check the crypto signature.

                 Note that the signtures from Metalink in XML will not be
                 parsed when using libmetalink version older than 0.1.3.
                 Metalink-over-HTTP is not affected by this problem.  */
              if (mfile->signature)
                {
                  metalink_signature_t *msig = mfile->signature;
                  gpgme_error_t gpgerr;
                  gpgme_ctx_t gpgctx;
                  gpgme_data_t gpgsigdata, gpgdata;
                  gpgme_verify_result_t gpgres;
                  gpgme_signature_t gpgsig;
                  gpgme_protocol_t gpgprot = GPGME_PROTOCOL_UNKNOWN;
                  int fd = -1;

                  /* Initialize the library - as name suggests.  */
                  gpgme_check_version (NULL);

                  /* Open data file.  */
                  fd = open (filename, O_RDONLY);
                  if (fd == -1)
                    {
                      logputs (LOG_NOTQUIET,
                               _("Could not open downloaded file for signature "
                                 "verification.\n"));
                      goto gpg_skip_verification;
                    }

                  /* Assign file descriptor to GPG data structure.  */
                  gpgerr = gpgme_data_new_from_fd (&gpgdata, fd);
                  if (gpgerr != GPG_ERR_NO_ERROR)
                    {
                      logprintf (LOG_NOTQUIET,
                                 "GPGME data_new_from_fd: %s\n",
                                 gpgme_strerror (gpgerr));
                      goto gpg_skip_verification;
                    }

                  /* Prepare new GPGME context.  */
                  gpgerr = gpgme_new (&gpgctx);
                  if (gpgerr != GPG_ERR_NO_ERROR)
                    {
                      logprintf (LOG_NOTQUIET,
                                 "GPGME new: %s\n",
                                 gpgme_strerror (gpgerr));
                      gpgme_data_release (gpgdata);
                      goto gpg_skip_verification;
                    }

                  DEBUGP (("Verifying signature %s:\n%s\n",
                           quote (msig->mediatype),
                           msig->signature));

                  /* Check signature type.  */
                  if (!strcmp (msig->mediatype, "application/pgp-signature"))
                    gpgprot = GPGME_PROTOCOL_OpenPGP;
                  else /* Unsupported signature type.  */
                    {
                      gpgme_release (gpgctx);
                      gpgme_data_release (gpgdata);
                      goto gpg_skip_verification;
                    }

                  gpgerr = gpgme_set_protocol (gpgctx, gpgprot);
                  if (gpgerr != GPG_ERR_NO_ERROR)
                    {
                      logprintf (LOG_NOTQUIET,
                                 "GPGME set_protocol: %s\n",
                                 gpgme_strerror (gpgerr));
                      gpgme_release (gpgctx);
                      gpgme_data_release (gpgdata);
                      goto gpg_skip_verification;
                    }

                  /* Load the signature.  */
                  gpgerr = gpgme_data_new_from_mem (&gpgsigdata,
                                                    msig->signature,
                                                    strlen (msig->signature),
                                                    0);
                  if (gpgerr != GPG_ERR_NO_ERROR)
                    {
                      logprintf (LOG_NOTQUIET,
                                 _("GPGME data_new_from_mem: %s\n"),
                                 gpgme_strerror (gpgerr));
                      gpgme_release (gpgctx);
                      gpgme_data_release (gpgdata);
                      goto gpg_skip_verification;
                    }

                  /* Verify the signature.  */
                  gpgerr = gpgme_op_verify (gpgctx, gpgsigdata, gpgdata, NULL);
                  if (gpgerr != GPG_ERR_NO_ERROR)
                    {
                      logprintf (LOG_NOTQUIET,
                                 _("GPGME op_verify: %s\n"),
                                 gpgme_strerror (gpgerr));
                      gpgme_data_release (gpgsigdata);
                      gpgme_release (gpgctx);
                      gpgme_data_release (gpgdata);
                      goto gpg_skip_verification;
                    }

                  /* Check the results.  */
                  gpgres = gpgme_op_verify_result (gpgctx);
                  if (!gpgres)
                    {
                      logputs (LOG_NOTQUIET,
                               _("GPGME op_verify_result: NULL\n"));
                      gpgme_data_release (gpgsigdata);
                      gpgme_release (gpgctx);
                      gpgme_data_release (gpgdata);
                      goto gpg_skip_verification;
                    }

                  /* The list is null-terminated.  */
                  for (gpgsig = gpgres->signatures; gpgsig; gpgsig = gpgsig->next)
                    {
                      DEBUGP (("Checking signature %s\n", gpgsig->fpr));

                      if (gpgsig->summary
                          & (GPGME_SIGSUM_VALID | GPGME_SIGSUM_GREEN))
                        {
                          logputs (LOG_VERBOSE,
                                   _("Signature validation suceeded.\n"));
                          sig_status = 1;
                          break;
                        }

                      if (gpgsig->summary & GPGME_SIGSUM_RED)
                        {
                          logputs (LOG_NOTQUIET,
                                   _("Invalid signature. Rejecting resource.\n"));
                          sig_status = -1;
                          break;
                        }

                      if (gpgsig->summary == 0
                          && (gpgsig->status & 0xFFFF) == GPG_ERR_NO_ERROR)
                        {
                          logputs (LOG_VERBOSE,
                                   _("Data matches signature, but signature "
                                     "is not trusted.\n"));
                        }

                      if ((gpgsig->status & 0xFFFF) != GPG_ERR_NO_ERROR)
                        {
                          logprintf (LOG_NOTQUIET,
                                     "GPGME: %s\n",
                                     gpgme_strerror (gpgsig->status & 0xFFFF));
                        }
                    }
                  gpgme_data_release (gpgsigdata);
                  gpgme_release (gpgctx);
                  gpgme_data_release (gpgdata);
gpg_skip_verification:
                  if (fd != -1)
                    close (fd);
                } /* endif (mfile->signature) */
#endif
              /* Stop if file was downloaded with success.  */
              if (sig_status >= 0)
                break;
            } /* endif RETR_OK.  */
        } /* Iterate over resources.  */

      if (retr_err != RETROK)
        {
          logprintf (LOG_VERBOSE, _("Failed to download %s. Skipping resource.\n"),
                     quote (mfile->name));
        }
      else if (!hash_ok)
        {
          retr_err = METALINK_CHKSUM_ERROR;
          logprintf (LOG_NOTQUIET,
                     _("File %s retrieved but checksum does not match. "
                       "\n"), quote (mfile->name));
        }
#ifdef HAVE_GPGME
        /* Signature will be only validated if hash check was successful.  */
      else if (sig_status < 0)
        {
          retr_err = METALINK_SIG_ERROR;
          logprintf (LOG_NOTQUIET,
                     _("File %s retrieved but signature does not match. "
                       "\n"), quote (mfile->name));
        }
#endif
      last_retr_err = retr_err == RETROK ? last_retr_err : retr_err;

      /* Remove the file if error encountered or if option specified.
         Note: the file has been downloaded using *_loop. Therefore, it
         is not necessary to keep the file for continuated download.  */
      if ((retr_err != RETROK || opt.delete_after)
           && filename != NULL && file_exists_p (filename))
        {
          logprintf (LOG_VERBOSE, _("Removing %s.\n"), quote (filename));
          if (unlink (filename))
            logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
        }
      if (output_stream)
        {
          fclose (output_stream);
          output_stream = NULL;
        }
      xfree (filename);
    } /* Iterate over files.  */

  /* Restore original values.  */
  opt.output_document = _output_document;
  output_stream_regular = _output_stream_regular;
  output_stream = _output_stream;

  return last_retr_err;
}
Beispiel #16
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 #17
0
int 
main (int argc, char **argv)
{
  gpgme_error_t err;
  gpgme_ctx_t ctx;
  gpgme_key_t key;
  gpgme_keylist_result_t result;
  int i = 0;

  init_gpgme (GPGME_PROTOCOL_CMS);

  err = gpgme_new (&ctx);
  fail_if_err (err);
  gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS);

  err = gpgme_op_keylist_start (ctx, NULL, 0);
  fail_if_err (err);
    
  while (!(err = gpgme_op_keylist_next (ctx, &key)))
    {
      if (!keys[i].fpr)
	{
	  fprintf (stderr, "More keys returned than expected\n");
	  exit (1);
	}

      if (strcmp (key->subkeys->fpr, keys[i].fpr))
	{
	  fprintf (stderr, "Warning: Skipping unknown key %s\n",
		   key->subkeys->fpr);
	  continue;
	}
      else
	printf ("Checking key %s\n", key->subkeys->fpr);

      /* Global key flags.  */
      if (key->revoked)
	{
	  fprintf (stderr, "Key unexpectedly revoked\n");
	  exit (1);
	}
      if (key->expired)
	{
	  fprintf (stderr, "Key unexpectedly expired\n");
	  exit (1);
	}
      if (key->disabled)
	{
	  fprintf (stderr, "Key unexpectedly disabled\n");
	  exit (1);
	}
      if (key->invalid)
	{
	  fprintf (stderr, "Key unexpectedly invalid\n");
	  exit (1);
	}
      if (key->can_encrypt != keys[i].secret)
	{
	  fprintf (stderr, "Key unexpectedly%s usable for encryption\n",
		   key->can_encrypt ? "" : " not");
	  exit (1);
	}
      if (key->can_sign != keys[i].secret)
	{
	  fprintf (stderr, "Key unexpectedly%s usable for signing\n",
		   key->can_sign ? "" : " not");
	  exit (1);
	}
      if (!key->can_certify)
	{
	  fprintf (stderr, "Key unexpectedly unusable for certifications\n");
	  exit (1);
	}
      if (key->secret != keys[i].secret)
	{
	  fprintf (stderr, "Key unexpectedly%s secret\n",
		   key->secret ? "" : " not");
	  exit (1);
	}
      if (key->protocol != GPGME_PROTOCOL_CMS)
	{
	  fprintf (stderr, "Key has unexpected protocol: %s\n",
		   gpgme_get_protocol_name (key->protocol));
	  exit (1);
	}
      if (!key->issuer_serial)
	{
	  fprintf (stderr, "Key unexpectedly misses issuer serial\n");
	  exit (1);
	}
      if (strcmp (key->issuer_serial, keys[i].issuer_serial))
	{
	  fprintf (stderr, "Key has unexpected issuer serial: %s\n",
		   key->issuer_serial);
	  exit (1);
	}
      if (!key->issuer_name)
	{
	  fprintf (stderr, "Key unexpectedly misses issuer name\n");
	  exit (1);
	}
      if (strcmp (key->issuer_name, keys[i].issuer_name))
	{
	  fprintf (stderr, "Key has unexpected issuer name: %s\n",
		   key->issuer_name);
	  exit (1);
	}
      if (key->chain_id && !keys[i].chain_id)
	{
	  fprintf (stderr, "Key unexpectedly carries chain ID: %s\n",
		   key->chain_id);
	  exit (1);
	}
      if (!key->chain_id && keys[i].chain_id)
	{
	  fprintf (stderr, "Key unexpectedly carries no chain ID\n");
	  exit (1);
	}
      if (key->chain_id && strcmp (key->chain_id, keys[i].chain_id))
	{
	  fprintf (stderr, "Key carries unexpected chain ID: %s\n",
		   key->chain_id);
	  exit (1);
	}
      if (key->owner_trust != GPGME_VALIDITY_UNKNOWN)
	{
	  fprintf (stderr, "Key has unexpected owner trust: %i\n",
		   key->owner_trust);
	  exit (1);
	}
      if (!key->subkeys || key->subkeys->next)
	{
	  fprintf (stderr, "Key has unexpected number of subkeys\n");
	  exit (1);
	}

      /* Primary key.  */
      if (key->subkeys->revoked)
	{
	  fprintf (stderr, "Primary key unexpectedly revoked\n");
	  exit (1);
	}
      if (key->subkeys->expired)
	{
	  fprintf (stderr, "Primary key unexpectedly expired\n");
	  exit (1);
	}
      if (key->subkeys->disabled)
	{
	  fprintf (stderr, "Primary key unexpectedly disabled\n");
	  exit (1);
	}
      if (key->subkeys->invalid)
	{
	  fprintf (stderr, "Primary key unexpectedly invalid\n");
	  exit (1);
	}
      if (key->subkeys->can_encrypt != keys[i].secret)
	{
	  fprintf (stderr, "Key unexpectedly%s usable for encryption\n",
		   key->subkeys->can_encrypt ? "" : " not");
	  exit (1);
	}
      if (key->subkeys->can_sign != keys[i].secret)
	{
	  fprintf (stderr, "Key unexpectedly%s usable for signing\n",
		   key->subkeys->can_sign ? "" : " not");
	  exit (1);
	}
      if (!key->subkeys->can_certify)
	{
	  fprintf (stderr, "Primary key unexpectedly unusable for certifications\n");
	  exit (1);
	}
      if (key->subkeys->secret != keys[i].secret)
	{
	  fprintf (stderr, "Primary Key unexpectedly%s secret\n",
		   key->secret ? "" : " not");
	  exit (1);
	}
      if (key->subkeys->pubkey_algo != GPGME_PK_RSA)
	{
	  fprintf (stderr, "Primary key has unexpected public key algo: %s\n",
		   gpgme_pubkey_algo_name (key->subkeys->pubkey_algo));
	  exit (1);
	}
      if (key->subkeys->length != keys[i].key_length)
	{
	  fprintf (stderr, "Primary key has unexpected length: %i\n",
		   key->subkeys->length);
	  exit (1);
	}
      if (strcmp (key->subkeys->keyid, &keys[i].fpr[40 - 16]))
	{
	  fprintf (stderr, "Primary key has unexpected key ID: %s\n",
		   key->subkeys->keyid);
	  exit (1);
	}
      if (strcmp (key->subkeys->fpr, keys[i].fpr))
	{
	  fprintf (stderr, "Primary key has unexpected fingerprint: %s\n",
		   key->subkeys->fpr);
	  exit (1);
	}
      if (key->subkeys->timestamp != keys[i].timestamp)
	{
	  fprintf (stderr, "Primary key unexpected timestamp: %lu\n",
		   key->subkeys->timestamp);
	  exit (1);
	}
      if (key->subkeys->expires != keys[i].expires)
	{
	  fprintf (stderr, "Primary key unexpectedly expires: %lu\n",
		   key->subkeys->expires);
	  exit (1);
	}

      /* Be tolerant against a missing email (ie, older gpgsm versions).  */
      if (!key->uids || (key->uids->next && !keys[i].email))
	{
	  fprintf (stderr, "Key has unexpected number of user IDs\n");
	  exit (1);
	}
      if (key->uids->revoked)
	{
	  fprintf (stderr, "User ID unexpectedly revoked\n");
	  exit (1);
	}
      if (key->uids->invalid)
	{
	  fprintf (stderr, "User ID unexpectedly invalid\n");
	  exit (1);
	}
      if (key->uids->validity != keys[i].validity)
	{
	  fprintf (stderr, "User ID unexpectedly validity: %i\n",
		   key->uids->validity);
	  exit (1);
	}
      if (key->uids->signatures)
	{
	  fprintf (stderr, "User ID unexpectedly signed\n");
	  exit (1);
	}
      if (!key->uids->name || key->uids->name[0])
	{
	  fprintf (stderr, "Unexpected name in user ID: %s\n",
		   key->uids->name);
	  exit (1);
	}
      if (!key->uids->comment || key->uids->comment[0])
	{
	  fprintf (stderr, "Unexpected comment in user ID: %s\n",
		   key->uids->comment);
	  exit (1);
	}
      if (!key->uids->email || key->uids->email[0])
	{
	  fprintf (stderr, "Unexpected email in user ID: %s\n",
		   key->uids->email);
	  exit (1);
	}
      if (!key->uids->uid || strcmp (key->uids->uid, keys[i].uid))
	{
	  fprintf (stderr, "Unexpected uid in user ID: %s\n",
		   key->uids->uid);
	  exit (1);
	}
      if (key->uids->next && strcmp (key->uids->next->uid, keys[i].email))
	{
	  fprintf (stderr, "Unexpected email in user ID: %s\n",
		   key->uids->next->uid);
	  exit (1);
	}
      if (key->uids->next && strcmp (key->uids->next->uid, keys[i].email))
	{
	  fprintf (stderr, "Unexpected email in user ID: %s\n",
		   key->uids->next->uid);
	  exit (1);
	}



      gpgme_key_unref (key);
      i++;
    }
  if (gpg_err_code (err) != GPG_ERR_EOF)
    fail_if_err (err);
  err = gpgme_op_keylist_end (ctx);
  fail_if_err (err);

  result = gpgme_op_keylist_result (ctx);
  if (result->truncated)
    {
      fprintf (stderr, "Key listing unexpectedly truncated\n");
      exit (1);
    }

  if (keys[i].fpr)
    {
      fprintf (stderr, "Less keys returned than expected\n");
      exit (1);
    }

  gpgme_release (ctx);
  return 0;
}
Beispiel #18
0
/* ------------------
 * encrypt a plain string with the key found with fingerprint fpr
 * ------------------ */
static char* encrypt(const char* plain_str, const char* fpr)
{
	gpgme_error_t error;
	gpgme_ctx_t ctx;
	gpgme_key_t key;
	gpgme_data_t plain,cipher;
	char* cipher_str = NULL;
	char* cipher_str_dup = NULL;
	size_t len;
	gpgme_key_t key_arr[2];

	key_arr[0] = NULL;
	key_arr[1] = NULL;

	// 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,0);
	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;
	}
	key_arr[0] = key;

	// create data containers
	gpgme_data_new_from_mem (&plain, plain_str,strlen(plain_str),1);
	gpgme_data_new(&cipher);

	// encrypt, ascii armored
	gpgme_set_armor(ctx,1);
	error = gpgme_op_encrypt (ctx, key_arr,GPGME_ENCRYPT_ALWAYS_TRUST,plain,cipher);
	if (error)
	{
		purple_debug_error(PLUGIN_ID,"gpgme_op_encrypt failed: %s %s\n",gpgme_strsource (error), gpgme_strerror (error));
		gpgme_release (ctx);
		return NULL;
	}

	// release memory for data containers
	gpgme_data_release(plain);
	cipher_str = gpgme_data_release_and_get_mem(cipher,&len);
	if (cipher_str != NULL)
	{
		cipher_str_dup = str_unarmor(cipher_str);
	}
	gpgme_free(cipher_str);

	// close gpgme connection
	gpgme_release (ctx);

	return cipher_str_dup;
}
Beispiel #19
0
static MimeInfo *pgpinline_decrypt(MimeInfo *mimeinfo)
{
    MimeInfo *decinfo, *parseinfo;
    gpgme_data_t cipher, plain;
    FILE *dstfp;
    gchar *fname;
    gchar *textdata = NULL;
    static gint id = 0;
    const gchar *src_codeset = NULL;
    gpgme_verify_result_t sigstat = 0;
    PrivacyDataPGP *data = NULL;
    gpgme_ctx_t ctx;
    gchar *chars;
    size_t len;
    const gchar *begin_indicator = "-----BEGIN PGP MESSAGE-----";
    const gchar *end_indicator = "-----END PGP MESSAGE-----";
    gchar *pos;

    if (gpgme_new(&ctx) != GPG_ERR_NO_ERROR)
        return NULL;

    gpgme_set_textmode(ctx, 1);
    gpgme_set_armor(ctx, 1);

    cm_return_val_if_fail(mimeinfo != NULL, NULL);
    cm_return_val_if_fail(pgpinline_is_encrypted(mimeinfo), NULL);

    if (procmime_mimeinfo_parent(mimeinfo) == NULL ||
            mimeinfo->type != MIMETYPE_TEXT) {
        gpgme_release(ctx);
        privacy_set_error(_("Couldn't parse mime part."));
        return NULL;
    }

    textdata = get_part_as_string(mimeinfo);
    if (!textdata) {
        gpgme_release(ctx);
        privacy_set_error(_("Couldn't get text data."));
        return NULL;
    }

    debug_print("decrypting '%s'\n", textdata);
    gpgme_data_new_from_mem(&cipher, textdata, (size_t)strlen(textdata), 1);

    plain = sgpgme_decrypt_verify(cipher, &sigstat, ctx);
    if (sigstat && !sigstat->signatures)
        sigstat = NULL;

    gpgme_data_release(cipher);

    if (plain == NULL) {
        gpgme_release(ctx);
        return NULL;
    }

    fname = g_strdup_printf("%s%cplaintext.%08x",
                            get_mime_tmp_dir(), G_DIR_SEPARATOR, ++id);

    if ((dstfp = g_fopen(fname, "wb")) == NULL) {
        FILE_OP_ERROR(fname, "fopen");
        privacy_set_error(_("Couldn't open decrypted file %s"), fname);
        g_free(fname);
        gpgme_data_release(plain);
        gpgme_release(ctx);
        return NULL;
    }

    src_codeset = procmime_mimeinfo_get_parameter(mimeinfo, "charset");
    if (src_codeset == NULL)
        src_codeset = CS_ISO_8859_1;

    if (fprintf(dstfp, "MIME-Version: 1.0\r\n"
                "Content-Type: text/plain; charset=%s\r\n"
                "Content-Transfer-Encoding: 8bit\r\n"
                "\r\n",
                src_codeset) < 0) {
        FILE_OP_ERROR(fname, "fprintf");
        privacy_set_error(_("Couldn't write to decrypted file %s"), fname);
        goto FILE_ERROR;
    }

    /* Store any part before encrypted text */
    pos = pgp_locate_armor_header(textdata, begin_indicator);
    if (pos != NULL && (pos - textdata) > 0) {
        if (fwrite(textdata, 1, pos - textdata, dstfp) < pos - textdata) {
            FILE_OP_ERROR(fname, "fwrite");
            privacy_set_error(_("Couldn't write to decrypted file %s"), fname);
            goto FILE_ERROR;
        }
    }

    if (fwrite(_("\n--- Start of PGP/Inline encrypted data ---\n"), 1,
               strlen(_("\n--- Start of PGP/Inline encrypted data ---\n")),
               dstfp) < strlen(_("\n--- Start of PGP/Inline encrypted data ---\n"))) {
        FILE_OP_ERROR(fname, "fwrite");
        privacy_set_error(_("Couldn't write to decrypted file %s"), fname);
        goto FILE_ERROR;
    }
    chars = sgpgme_data_release_and_get_mem(plain, &len);
    if (len > 0) {
        if (fwrite(chars, 1, len, dstfp) < len) {
            FILE_OP_ERROR(fname, "fwrite");
            g_free(chars);
            privacy_set_error(_("Couldn't write to decrypted file %s"), fname);
            goto FILE_ERROR;
        }
    }
    g_free(chars);
    /* Store any part after encrypted text */
    if (fwrite(_("--- End of PGP/Inline encrypted data ---\n"), 1,
               strlen(_("--- End of PGP/Inline encrypted data ---\n")),
               dstfp) < strlen(_("--- End of PGP/Inline encrypted data ---\n"))) {
        FILE_OP_ERROR(fname, "fwrite");
        privacy_set_error(_("Couldn't write to decrypted file %s"), fname);
        goto FILE_ERROR;
    }
    if (pos != NULL) {
        pos = pgp_locate_armor_header(pos, end_indicator);
        if (pos != NULL && *pos != '\0') {
            pos += strlen(end_indicator);
            if (fwrite(pos, 1, strlen(pos), dstfp) < strlen(pos)) {
                FILE_OP_ERROR(fname, "fwrite");
                privacy_set_error(_("Couldn't write to decrypted file %s"), fname);
                goto FILE_ERROR;
            }
        }
    }

    if (fclose(dstfp) == EOF) {
        FILE_OP_ERROR(fname, "fclose");
        privacy_set_error(_("Couldn't close decrypted file %s"), fname);
        g_free(fname);
        gpgme_data_release(plain);
        gpgme_release(ctx);
        return NULL;
    }

    parseinfo = procmime_scan_file(fname);
    g_free(fname);

    if (parseinfo == NULL) {
        gpgme_release(ctx);
        privacy_set_error(_("Couldn't scan decrypted file."));
        return NULL;
    }
    decinfo = g_node_first_child(parseinfo->node) != NULL ?
              g_node_first_child(parseinfo->node)->data : NULL;

    if (decinfo == NULL) {
        gpgme_release(ctx);
        privacy_set_error(_("Couldn't scan decrypted file parts."));
        return NULL;
    }

    g_node_unlink(decinfo->node);
    procmime_mimeinfo_free_all(parseinfo);

    decinfo->tmp = TRUE;

    if (sigstat != GPGME_SIG_STAT_NONE) {
        if (decinfo->privacy != NULL) {
            data = (PrivacyDataPGP *) decinfo->privacy;
        } else {
            data = pgpinline_new_privacydata();
            decinfo->privacy = (PrivacyData *) data;
        }
        if (data != NULL) {
            data->done_sigtest = TRUE;
            data->is_signed = TRUE;
            data->sigstatus = sigstat;
            if (data->ctx)
                gpgme_release(data->ctx);
            data->ctx = ctx;
        }
    } else
        gpgme_release(ctx);

    return decinfo;

FILE_ERROR:
    fclose(dstfp);
    g_free(fname);
    gpgme_data_release(plain);
    gpgme_release(ctx);
    return NULL;
}
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;
}
Beispiel #21
0
static gboolean pgpinline_encrypt(MimeInfo *mimeinfo, const gchar *encrypt_data)
{
    MimeInfo *msgcontent;
    FILE *fp;
    gchar *enccontent;
    size_t len;
    gchar *textstr, *tmp;
    gpgme_data_t gpgtext, gpgenc;
    gpgme_ctx_t ctx;
    gpgme_key_t *kset = NULL;
    gchar **fprs = g_strsplit(encrypt_data, " ", -1);
    gpgme_error_t err;
    gint i = 0;

    while (fprs[i] && strlen(fprs[i])) {
        i++;
    }

    kset = g_malloc(sizeof(gpgme_key_t)*(i+1));
    memset(kset, 0, sizeof(gpgme_key_t)*(i+1));
    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));
        g_free(kset);
        return FALSE;
    }
    i = 0;
    while (fprs[i] && strlen(fprs[i])) {
        gpgme_key_t key;
        err = gpgme_get_key(ctx, fprs[i], &key, 0);
        if (err) {
            debug_print("can't add key '%s'[%d] (%s)\n", fprs[i],i, gpgme_strerror(err));
            privacy_set_error(_("Couldn't add GPG key %s, %s"), fprs[i], gpgme_strerror(err));
            g_free(kset);
            return FALSE;
        }
        debug_print("found %s at %d\n", fprs[i], i);
        kset[i] = key;
        i++;
    }


    debug_print("Encrypting message content\n");

    /* 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"));
            g_free(kset);
            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) {
        privacy_set_error(_("Couldn't create temporary file, %s"), g_strerror(errno));
        perror("my_tmpfile");
        g_free(kset);
        return FALSE;
    }
    procmime_write_mimeinfo(msgcontent, fp);
    rewind(fp);

    /* read temporary file into memory */
    textstr = fp_read_noconv(fp);

    fclose(fp);

    /* encrypt data */
    gpgme_data_new_from_mem(&gpgtext, textstr, (size_t)strlen(textstr), 0);
    gpgme_data_new(&gpgenc);
    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));
        g_free(kset);
        return FALSE;
    }
    gpgme_set_armor(ctx, 1);

    err = gpgme_op_encrypt(ctx, kset, GPGME_ENCRYPT_ALWAYS_TRUST, gpgtext, gpgenc);

    enccontent = sgpgme_data_release_and_get_mem(gpgenc, &len);
    g_free(kset);

    if (enccontent == NULL || len <= 0) {
        g_warning("sgpgme_data_release_and_get_mem failed");
        privacy_set_error(_("Encryption failed, %s"), gpgme_strerror(err));
        gpgme_data_release(gpgtext);
        g_free(textstr);
        gpgme_release(ctx);
        g_free(enccontent);
        return FALSE;
    }

    tmp = g_malloc(len+1);
    g_memmove(tmp, enccontent, len+1);
    tmp[len] = '\0';
    g_free(enccontent);

    gpgme_data_release(gpgtext);
    g_free(textstr);

    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);
    gpgme_release(ctx);

    return TRUE;
}
Beispiel #22
0
int
main (int argc, char **argv)
{
  int last_argc = -1;
  gpgme_error_t err;
  gpgme_ctx_t ctx;
  gpgme_key_t key;
  gpgme_keylist_result_t result;
  gpgme_key_t keyarray[100];
  int keyidx = 0;
  gpgme_data_t out;
  gpgme_protocol_t protocol = GPGME_PROTOCOL_OpenPGP;
  gpgme_export_mode_t mode = 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, "--openpgp"))
        {
          protocol = GPGME_PROTOCOL_OpenPGP;
          argc--; argv++;
        }
      else if (!strcmp (*argv, "--cms"))
        {
          protocol = GPGME_PROTOCOL_CMS;
          argc--; argv++;
        }
      else if (!strcmp (*argv, "--extern"))
        {
          mode |= GPGME_EXPORT_MODE_EXTERN;
          argc--; argv++;
        }
      else if (!strcmp (*argv, "--secret"))
        {
          mode |= GPGME_EXPORT_MODE_SECRET;
          argc--; argv++;
        }
      else if (!strcmp (*argv, "--raw"))
        {
          mode |= GPGME_EXPORT_MODE_RAW;
          argc--; argv++;
        }
      else if (!strcmp (*argv, "--pkcs12"))
        {
          mode |= GPGME_EXPORT_MODE_PKCS12;
          argc--; argv++;
        }
      else if (!strncmp (*argv, "--", 2))
        show_usage (1);

    }

  if (!argc)
    show_usage (1);

  init_gpgme (protocol);

  err = gpgme_new (&ctx);
  fail_if_err (err);
  gpgme_set_protocol (ctx, protocol);

  /* Lookup the keys.  */
  err = gpgme_op_keylist_ext_start (ctx, (const char**)argv, 0, 0);
  fail_if_err (err);

  while (!(err = gpgme_op_keylist_next (ctx, &key)))
    {
      printf ("keyid: %s  (fpr: %s)\n",
              key->subkeys?nonnull (key->subkeys->keyid):"?",
              key->subkeys?nonnull (key->subkeys->fpr):"?");

      if (keyidx < DIM (keyarray)-1)
        keyarray[keyidx++] = key;
      else
        {
          fprintf (stderr, PGM": too many keys"
                   "- skipping this key\n");
          gpgme_key_unref (key);
        }
    }
  if (gpgme_err_code (err) != GPG_ERR_EOF)
    fail_if_err (err);
  err = gpgme_op_keylist_end (ctx);
  fail_if_err (err);
  keyarray[keyidx] = NULL;

  result = gpgme_op_keylist_result (ctx);
  if (result->truncated)
    {
      fprintf (stderr, PGM ": key listing unexpectedly truncated\n");
      exit (1);
    }

  /* Now for the actual export.  */
  if ((mode & GPGME_EXPORT_MODE_EXTERN))
    printf ("sending keys to keyserver\n");
  if ((mode & GPGME_EXPORT_MODE_SECRET))
    printf ("exporting secret keys!\n");

  err = gpgme_data_new (&out);
  fail_if_err (err);

  gpgme_set_armor (ctx, 1);
  err = gpgme_op_export_keys (ctx, keyarray, mode,
                              (mode & GPGME_KEYLIST_MODE_EXTERN)? NULL:out);
  fail_if_err (err);

  fflush (NULL);
  if (!(mode & GPGME_KEYLIST_MODE_EXTERN))
    {
      fputs ("Begin Result:\n", stdout);
      print_data (out);
      fputs ("End Result.\n", stdout);
    }

  /* Cleanup.  */
  gpgme_data_release (out);

  for (keyidx=0; keyarray[keyidx]; keyidx++)
    gpgme_key_unref (keyarray[keyidx]);

  gpgme_release (ctx);
  return 0;
}
Beispiel #23
0
int
opkg_verify_file (char *text_file, char *sig_file)
{
#if defined HAVE_GPGME
    if (conf->check_signature == 0 )
        return 0;
    int status = -1;
    gpgme_ctx_t ctx;
    gpgme_data_t sig, text, key;
    gpgme_error_t err;
    gpgme_verify_result_t result;
    gpgme_signature_t s;
    char *trusted_path = NULL;

    gpgme_check_version (NULL);

    err = gpgme_new (&ctx);

    if (err)
	return -1;

    sprintf_alloc(&trusted_path, "%s/%s", conf->offline_root, "/etc/opkg/trusted.gpg");
    err = gpgme_data_new_from_file (&key, trusted_path, 1);
    free (trusted_path);
    if (err)
    {
      return -1;
    }
    err = gpgme_op_import (ctx, key);
    if (err)
    {
      gpgme_data_release (key);
      return -1;
    }
    gpgme_data_release (key);

    err = gpgme_data_new_from_file (&sig, sig_file, 1);
    if (err)
    {
	gpgme_release (ctx);
	return -1;
    }

    err = gpgme_data_new_from_file (&text, text_file, 1);
    if (err)
    {
        gpgme_data_release (sig);
	gpgme_release (ctx);
	return -1;
    }

    err = gpgme_op_verify (ctx, sig, text, NULL);

    result = gpgme_op_verify_result (ctx);
    if (!result)
	return -1;

    /* see if any of the signitures matched */
    s = result->signatures;
    while (s)
    {
	status = gpg_err_code (s->status);
	if (status == GPG_ERR_NO_ERROR)
	    break;
	s = s->next;
    }


    gpgme_data_release (sig);
    gpgme_data_release (text);
    gpgme_release (ctx);

    return status;
#elif defined HAVE_OPENSSL
    X509_STORE *store = NULL;
    PKCS7 *p7 = NULL;
    BIO *in = NULL, *indata = NULL;

    // Sig check failed by default !
    int status = -1;

    openssl_init();

    // Set-up the key store
    if(!(store = setup_verify(conf->signature_ca_file, conf->signature_ca_path))){
        opkg_msg(ERROR, "Can't open CA certificates.\n");
        goto verify_file_end;
    }

    // Open a BIO to read the sig file
    if (!(in = BIO_new_file(sig_file, "rb"))){
        opkg_msg(ERROR, "Can't open signature file %s.\n", sig_file);
        goto verify_file_end;
    }

    // Read the PKCS7 block contained in the sig file
    p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL);
    if(!p7){
        opkg_msg(ERROR, "Can't read signature file %s (Corrupted ?).\n",
		sig_file);
        goto verify_file_end;
    }
#if defined(HAVE_PATHFINDER)
    if(conf->check_x509_path){
	if(!pkcs7_pathfinder_verify_signers(p7)){
	    opkg_msg(ERROR, "pkcs7_pathfinder_verify_signers: "
		    "Path verification failed.\n");
	    goto verify_file_end;
	}
    }
#endif

    // Open the Package file to authenticate
    if (!(indata = BIO_new_file(text_file, "rb"))){
        opkg_msg(ERROR, "Can't open file %s.\n", text_file);
        goto verify_file_end;
    }

    // Let's verify the autenticity !
    if (PKCS7_verify(p7, NULL, store, indata, NULL, PKCS7_BINARY) != 1){
        // Get Off My Lawn!
        opkg_msg(ERROR, "Verification failure.\n");
    }else{
        // Victory !
        status = 0;
    }

verify_file_end:
    BIO_free(in);
    BIO_free(indata);
    PKCS7_free(p7);
    X509_STORE_free(store);

    return status;
#else
    /* mute `unused variable' warnings. */
    (void) sig_file;
    (void) text_file;
    (void) conf;
    return 0;
#endif
}
Beispiel #24
0
gboolean
lr_gpg_check_signature_fd(int signature_fd,
                          int data_fd,
                          const char *home_dir,
                          GError **err)
{
    gpgme_error_t gpgerr;
    gpgme_ctx_t context;
    gpgme_data_t signature_data;
    gpgme_data_t data_data;
    gpgme_verify_result_t result;
    gpgme_signature_t sig;

    assert(!err || *err == NULL);

    // Initialization
    gpgme_check_version(NULL);
    gpgerr = gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP);
    if (gpgerr != GPG_ERR_NO_ERROR) {
        g_debug("%s: gpgme_engine_check_version: %s",
                 __func__, gpgme_strerror(gpgerr));
        g_set_error(err, LR_GPG_ERROR, LRE_GPGNOTSUPPORTED,
                    "gpgme_engine_check_version() error: %s",
                    gpgme_strerror(gpgerr));
        return FALSE;
    }

    gpgerr = gpgme_new(&context);
    if (gpgerr != GPG_ERR_NO_ERROR) {
        g_debug("%s: gpgme_new: %s", __func__, gpgme_strerror(gpgerr));
        g_set_error(err, LR_GPG_ERROR, LRE_GPGERROR,
                    "gpgme_new() error: %s", gpgme_strerror(gpgerr));
        return FALSE;
    }

    gpgerr = gpgme_set_protocol(context, GPGME_PROTOCOL_OpenPGP);
    if (gpgerr != GPG_ERR_NO_ERROR) {
        g_debug("%s: gpgme_set_protocol: %s", __func__, gpgme_strerror(gpgerr));
        g_set_error(err, LR_GPG_ERROR, LRE_GPGERROR,
                    "gpgme_set_protocol() error: %s", gpgme_strerror(gpgerr));
        gpgme_release(context);
        return FALSE;
    }

    if (home_dir) {
        gpgerr = gpgme_ctx_set_engine_info(context, GPGME_PROTOCOL_OpenPGP,
                                        NULL, home_dir);
        if (gpgerr != GPG_ERR_NO_ERROR) {
            g_debug("%s: gpgme_ctx_set_engine_info: %s", __func__,
                    gpgme_strerror(gpgerr));
            g_set_error(err, LR_GPG_ERROR, LRE_GPGERROR,
                        "gpgme_ctx_set_engine_info() error: %s",
                        gpgme_strerror(gpgerr));
            gpgme_release(context);
            return FALSE;
        }
    }

    gpgme_set_armor(context, 1);

    gpgerr = gpgme_data_new_from_fd(&signature_data, signature_fd);
    if (gpgerr != GPG_ERR_NO_ERROR) {
        g_debug("%s: gpgme_data_new_from_fd: %s",
                 __func__, gpgme_strerror(gpgerr));
        g_set_error(err, LR_GPG_ERROR, LRE_GPGERROR,
                    "gpgme_data_new_from_fd(_, %d) error: %s",
                    signature_fd, gpgme_strerror(gpgerr));
        gpgme_release(context);
        return FALSE;
    }

    gpgerr = gpgme_data_new_from_fd(&data_data, data_fd);
    if (gpgerr != GPG_ERR_NO_ERROR) {
        g_debug("%s: gpgme_data_new_from_fd: %s",
                 __func__, gpgme_strerror(gpgerr));
        g_set_error(err, LR_GPG_ERROR, LRE_GPGERROR,
                    "gpgme_data_new_from_fd(_, %d) error: %s",
                    data_fd, gpgme_strerror(gpgerr));
        gpgme_data_release(signature_data);
        gpgme_release(context);
        return FALSE;
    }

    // Verify
    gpgerr = gpgme_op_verify(context, signature_data, data_data, NULL);
    gpgme_data_release(signature_data);
    gpgme_data_release(data_data);
    if (gpgerr != GPG_ERR_NO_ERROR) {
        g_debug("%s: gpgme_op_verify: %s", __func__, gpgme_strerror(gpgerr));
        g_set_error(err, LR_GPG_ERROR, LRE_GPGERROR,
                    "gpgme_op_verify() error: %s", gpgme_strerror(gpgerr));
        gpgme_release(context);
        return FALSE;
    }

    result = gpgme_op_verify_result(context);
    if (!result) {
        g_debug("%s: gpgme_op_verify_result: error", __func__);
        g_set_error(err, LR_GPG_ERROR, LRE_GPGERROR,
                    "gpgme_op_verify_result() error: %s",
                    gpgme_strerror(gpgerr));
        gpgme_release(context);
        return FALSE;
    }

    // Check result of verification
    sig = result->signatures;
    if(!sig) {
        g_debug("%s: signature verify error (no signatures)", __func__);
        g_set_error(err, LR_GPG_ERROR, LRE_BADGPG,
                    "Signature verify error - no signatures");
        gpgme_release(context);
        return FALSE;
    }

    // Example of signature usage could be found in gpgme git repository
    // in the gpgme/tests/run-verify.c
    for (; sig; sig = sig->next) {
        if ((sig->summary & GPGME_SIGSUM_VALID) ||  // Valid
            (sig->summary & GPGME_SIGSUM_GREEN) ||  // Valid
            (sig->summary == 0 && sig->status == GPG_ERR_NO_ERROR)) // Valid but key is not certified with a trusted signature
        {
            gpgme_release(context);
            return TRUE;
        }
    }

    gpgme_release(context);
    g_debug("%s: Bad GPG signature", __func__);
    g_set_error(err, LR_GPG_ERROR, LRE_BADGPG, "Bad GPG signature");
    return FALSE;
}
Beispiel #25
0
/* #############################################################################
 *
 * Description    validate the given encryption key
 * Author         Harry Brueckner
 * Date           2005-03-31
 * Arguments      char* key   - the key to validate
 * Return         char* NULL on error, otherwise the name and mail address
 */
char* gpgValidateEncryptionKey(char* keyname)
  {
    gpgme_ctx_t         context;
    gpgme_key_t         key;
    gpgme_error_t       error;
    int                 secret,
                        size;
    char*               identifier = NULL;
    char*               tcomment;
    char*               tname;

    TRACE(99, "gpgValidateEncryptionKey()", NULL);

    if (!config -> encryptdata)
      { return NULL; }

    /* get a new context */
    error = gpgme_new(&context);
    if (error)
      {
        gpgme_release(context);
        gpgError(error);
        return NULL;
      }

    for (secret = 1; secret >= 0 && !identifier; secret--)
      {
        /* start cycling through the list of keys */
        error = gpgme_op_keylist_start(context, keyname,
            (secret == 1) ? LIST_SECRET : LIST_ALL);
        if (error)
          {
            gpgme_release(context);
            gpgError(error);
            return NULL;
          }

        while (!(error = gpgme_op_keylist_next(context, &key)))
          {   /* take the first key we find */
#ifdef TEST_OPTION
  #ifdef KEY_DEBUG
            gpgDebugKey(key);
  #endif
#endif
            if (key -> can_encrypt &&
                !key -> disabled &&
                !key -> expired &&
                !key -> invalid &&
                !key -> revoked)
              {   /* we just use keys we can encrypt for and sign with */
                tname = convert2terminal((unsigned char*)key -> uids -> name);
                if (key -> uids -> comment)
                  { tcomment = key -> uids -> comment; }
                else
                  { tcomment = NULL; }

                if (tcomment && strlen(tcomment))
                  {   /* a comment exists for this key */
                    size = strlen(key -> subkeys -> keyid) + 1 +
                        strlen(tname) + 1 +
                        strlen(tcomment) + 2 + 1 +
                        strlen(key -> uids -> email) + 2 + 1;
                    identifier = memAlloc(__FILE__, __LINE__, size);
                    snprintf(identifier, size, "%s %s (%s) <%s>",
                        key -> subkeys -> keyid,
                        tname,
                        tcomment,
                        key -> uids -> email);
                  }
                else
                  {   /* no comment exists */
                    size = strlen(key -> subkeys -> keyid) + 1 +
                        strlen(tname) + 1 +
                        strlen(key -> uids -> email) + 2 + 1;
                    identifier = memAlloc(__FILE__, __LINE__, size);
                    snprintf(identifier, size, "%s %s <%s>",
                        key -> subkeys -> keyid,
                        tname,
                        key -> uids -> email);
                  }
              }

            gpgme_key_unref(key);

            if (identifier)
              { break; }
          }

        if (error &&
            gpg_err_code(error) != GPG_ERR_EOF)
          {    /* we validate the last value of the 'next' operation */
            gpgme_release(context);
            gpgError(error);
            return NULL;
          }
      }

    /* finish the key listing */
    error = gpgme_op_keylist_end(context);
    if (error)
      {
        gpgme_release(context);
        gpgError(error);
        return NULL;
      }

    gpgme_release(context);

    return identifier;
  }
Beispiel #26
0
void sgpgme_create_secret_key(PrefsAccount *account, gboolean ask_create)
{
	AlertValue val = G_ALERTDEFAULT;
	gchar *key_parms = NULL;
	gchar *name = NULL;
	gchar *email = NULL;
	gchar *passphrase = NULL, *passphrase_second = NULL;
	gint prev_bad = 0;
	gchar *tmp = NULL;
	gpgme_error_t err = 0;
	gpgme_ctx_t ctx;
	GtkWidget *window = NULL;
	gpgme_genkey_result_t key;

	if (account == NULL)
		account = account_get_default();

	if (account->address == NULL) {
		alertpanel_error(_("You have to save the account's information with \"OK\" "
				   "before being able to generate a key pair.\n"));
		return;
	}
	if (ask_create) {
		val = alertpanel(_("No PGP key found"),
				_("Claws Mail did not find a secret PGP key, "
				  "which means that you won't be able to sign "
				  "emails or receive encrypted emails.\n"
				  "Do you want to create a new key pair now?"),
				  GTK_STOCK_NO, "+" GTK_STOCK_YES, NULL);
		if (val == G_ALERTDEFAULT) {
			prefs_gpg_get_config()->gpg_ask_create_key = FALSE;
			prefs_gpg_save_config();
			return;
		}
	}

	if (account->name) {
		name = g_strdup(account->name);
	} else {
		name = g_strdup(account->address);
	}
	email = g_strdup(account->address);
	tmp = g_strdup_printf("%s <%s>", account->name?account->name:account->address, account->address);
again:
	passphrase = passphrase_mbox(tmp, NULL, prev_bad, 1);
	if (passphrase == NULL) {
		g_free(tmp);
		g_free(email);
		g_free(name);		
		return;
	}
	passphrase_second = passphrase_mbox(tmp, NULL, 0, 2);
	if (passphrase_second == NULL) {
		g_free(tmp);
		g_free(email);
		g_free(passphrase);		
		g_free(name);		
		return;
	}
	if (strcmp(passphrase, passphrase_second)) {
		g_free(passphrase);
		g_free(passphrase_second);
		prev_bad = 1;
		goto again;
	}
	
	key_parms = g_strdup_printf("<GnupgKeyParms format=\"internal\">\n"
					"Key-Type: RSA\n"
					"Key-Length: 2048\n"
					"Subkey-Type: RSA\n"
					"Subkey-Length: 2048\n"
					"Name-Real: %s\n"
					"Name-Email: %s\n"
					"Expire-Date: 0\n"
					"%s%s%s"
					"</GnupgKeyParms>\n",
					name, email, 
					strlen(passphrase)?"Passphrase: ":"",
					passphrase,
					strlen(passphrase)?"\n":"");
#ifndef G_PLATFORM_WIN32
	if (mlock(passphrase, strlen(passphrase)) == -1)
		debug_print("couldn't lock passphrase\n");
	if (mlock(passphrase_second, strlen(passphrase_second)) == -1)
		debug_print("couldn't lock passphrase2\n");
#endif
	g_free(tmp);
	g_free(email);
	g_free(name);
	g_free(passphrase_second);
	g_free(passphrase);
	
	err = gpgme_new (&ctx);
	if (err) {
		alertpanel_error(_("Couldn't generate a new key pair: %s"),
				 gpgme_strerror(err));
		g_free(key_parms);
		return;
	}
	

	window = label_window_create(_("Generating your new key pair... Please move the mouse "
			      "around to help generate entropy..."));

	err = gpgme_op_genkey(ctx, key_parms, NULL, NULL);
	g_free(key_parms);

	label_window_destroy(window);

	if (err) {
		alertpanel_error(_("Couldn't generate a new key pair: %s"), gpgme_strerror(err));
		gpgme_release(ctx);
		return;
	}
	key = gpgme_op_genkey_result(ctx);
	if (key == NULL) {
		alertpanel_error(_("Couldn't generate a new key pair: unknown error"));
		gpgme_release(ctx);
		return;
	} else {
		gchar *buf = g_strdup_printf(_("Your new key pair has been generated. "
				    "Its fingerprint is:\n%s\n\nDo you want to export it "
				    "to a keyserver?"),
				    key->fpr ? key->fpr:"null");
		AlertValue val = alertpanel(_("Key generated"), buf,
				  GTK_STOCK_NO, "+" GTK_STOCK_YES, NULL);
		g_free(buf);
		if (val == G_ALERTALTERNATE) {
#ifndef G_OS_WIN32
			gchar *cmd = g_strdup_printf("gpg --no-tty --send-keys %s", key->fpr);
			int res = 0;
			pid_t pid = 0;
			pid = fork();
			if (pid == -1) {
				res = -1;
			} else if (pid == 0) {
				/* son */
				res = system(cmd);
				res = WEXITSTATUS(res);
				_exit(res);
			} else {
				int status = 0;
				time_t start_wait = time(NULL);
				res = -1;
				do {
					if (waitpid(pid, &status, WNOHANG) == 0 || !WIFEXITED(status)) {
						usleep(200000);
					} else {
						res = WEXITSTATUS(status);
						break;
					}
					if (time(NULL) - start_wait > 5) {
						debug_print("SIGTERM'ing gpg\n");
						kill(pid, SIGTERM);
					}
					if (time(NULL) - start_wait > 6) {
						debug_print("SIGKILL'ing gpg\n");
						kill(pid, SIGKILL);
						break;
					}
				} while(1);
			}
			if (res == 0) {
				alertpanel_notice(_("Key exported."));
			} else {
				alertpanel_error(_("Couldn't export key."));
			}
			g_free(cmd);
#else
			alertpanel_error(_("Key export isn't implemented in Windows."));
#endif
		}
	}
	prefs_gpg_get_config()->gpg_ask_create_key = FALSE;
	prefs_gpg_save_config();
	gpgme_release(ctx);
}
Beispiel #27
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 #28
0
static gpgme_key_t 
fill_clist (struct select_keys_s *sk, const char *pattern, gpgme_protocol_t proto)
{
    GtkCMCList *clist;
    gpgme_ctx_t ctx;
    gpgme_error_t err;
    gpgme_key_t key;
    int running=0;
    int num_results = 0;
    gboolean exact_match = FALSE;
    gpgme_key_t last_key = NULL;
    gpgme_user_id_t last_uid = NULL;
    cm_return_val_if_fail (sk, NULL);
    clist = sk->clist;
    cm_return_val_if_fail (clist, NULL);

    debug_print ("select_keys:fill_clist:  pattern '%s' proto %d\n", pattern != NULL ? pattern : "NULL", proto);

    /*gtk_cmclist_freeze (select_keys.clist);*/
    err = gpgme_new (&ctx);
    g_assert (!err);

    gpgme_set_protocol(ctx, proto);
    sk->select_ctx = ctx;

    update_progress (sk, ++running, pattern);
    while (gtk_events_pending ())
        gtk_main_iteration ();

    err = gpgme_op_keylist_start (ctx, pattern, 0);
    if (err) {
        debug_print ("** gpgme_op_keylist_start(%s) failed: %s",
                     pattern != NULL ? pattern : "NULL", gpgme_strerror (err));
        sk->select_ctx = NULL;
        gpgme_release(ctx);
        return NULL;
    }
    update_progress (sk, ++running, pattern);
    while ( !(err = gpgme_op_keylist_next ( ctx, &key )) ) {
	gpgme_user_id_t uid = key->uids;
	if (!key->can_encrypt || key->revoked || key->expired || key->disabled)
		continue;
        debug_print ("%% %s:%d:  insert\n", __FILE__ ,__LINE__ );
        set_row (clist, key, proto ); 
	for (; uid; uid = uid->next) {
		gchar *raw_mail = NULL;

		if (!uid->email)
			continue;
		if (uid->revoked || uid->invalid)
			continue;
		raw_mail = g_strdup(uid->email);
		extract_address(raw_mail);
		if (pattern != NULL && !strcasecmp(pattern, raw_mail)) {
			exact_match = TRUE;
			last_uid = uid;
			g_free(raw_mail);
			break;
		}
		g_free(raw_mail);
	}
	num_results++;
	last_key = key;
	key = NULL;
        update_progress (sk, ++running, pattern);
        while (gtk_events_pending ())
            gtk_main_iteration ();
    }
 
    if (exact_match == TRUE && num_results == 1) {
	    if (last_key->uids->validity < GPGME_VALIDITY_FULL && 
		!use_untrusted(last_key, last_uid, proto))
		    exact_match = FALSE;
    }

    debug_print ("%% %s:%d:  ready\n", __FILE__ ,__LINE__ );
    if (gpgme_err_code(err) != GPG_ERR_EOF) {
        debug_print ("** gpgme_op_keylist_next failed: %s",
                     gpgme_strerror (err));
        gpgme_op_keylist_end(ctx);
    }
    if (!exact_match || num_results != 1) {
	    sk->select_ctx = NULL;
	    gpgme_release (ctx);
    }
    /*gtk_cmclist_thaw (select_keys.clist);*/
    return (exact_match == TRUE && num_results == 1 ? last_key:NULL);
}
Beispiel #29
0
Datei: gpg.c Projekt: zde/librepo
gboolean
lr_gpg_import_key(const char *key_fn, const char *home_dir, GError **err)
{
    gpgme_error_t gpgerr;
    int key_fd;
    gpgme_ctx_t context;
    gpgme_data_t key_data;

    assert(!err || *err == NULL);

    // Initialization
    gpgme_check_version(NULL);
    gpgerr = gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP);
    if (gpgerr != GPG_ERR_NO_ERROR) {
        g_debug("%s: gpgme_engine_check_version: %s",
                 __func__, gpgme_strerror(gpgerr));
        g_set_error(err, LR_GPG_ERROR, LRE_GPGNOTSUPPORTED,
                    "gpgme_engine_check_version() error: %s",
                    gpgme_strerror(gpgerr));
        return FALSE;
    }

    gpgerr = gpgme_new(&context);
    if (gpgerr != GPG_ERR_NO_ERROR) {
        g_debug("%s: gpgme_new: %s", __func__, gpgme_strerror(gpgerr));
        g_set_error(err, LR_GPG_ERROR, LRE_GPGERROR,
                    "gpgme_new() error: %s", gpgme_strerror(gpgerr));
        return FALSE;
    }

    gpgerr = gpgme_set_protocol(context, GPGME_PROTOCOL_OpenPGP);
    if (gpgerr != GPG_ERR_NO_ERROR) {
        g_debug("%s: gpgme_set_protocol: %s", __func__, gpgme_strerror(gpgerr));
        g_set_error(err, LR_GPG_ERROR, LRE_GPGERROR,
                    "gpgme_set_protocol() error: %s", gpgme_strerror(gpgerr));
        gpgme_release(context);
        return FALSE;
    }

    if (home_dir) {
        gpgerr = gpgme_ctx_set_engine_info(context, GPGME_PROTOCOL_OpenPGP,
                                        NULL, home_dir);
        if (gpgerr != GPG_ERR_NO_ERROR) {
            g_debug("%s: gpgme_ctx_set_engine_info: %s", __func__, gpgme_strerror(gpgerr));
            g_set_error(err, LR_GPG_ERROR, LRE_GPGERROR,
                        "gpgme_ctx_set_engine_info() error: %s",
                        gpgme_strerror(gpgerr));
            gpgme_release(context);
            return FALSE;
        }
    }

    gpgme_set_armor(context, 1);

    // Key import

    key_fd = open(key_fn, O_RDONLY);
    if (key_fd == -1) {
        g_debug("%s: Opening key: %s", __func__, strerror(errno));
        g_set_error(err, LR_GPG_ERROR, LRE_IO,
                    "Error while opening key %s: %s",
                    key_fn, strerror(errno));
        gpgme_release(context);
        return FALSE;
    }

    gpgerr = gpgme_data_new_from_fd(&key_data, key_fd);
    if (gpgerr != GPG_ERR_NO_ERROR) {
        g_debug("%s: gpgme_data_new_from_fd: %s",
                 __func__, gpgme_strerror(gpgerr));
        g_set_error(err, LR_GPG_ERROR, LRE_GPGERROR,
                    "gpgme_data_new_from_fd(_, %d) error: %s",
                    key_fd, gpgme_strerror(gpgerr));
        gpgme_release(context);
        close(key_fd);
        return FALSE;
    }

    gpgerr = gpgme_op_import(context, key_data);
    gpgme_data_release(key_data);
    if (gpgerr != GPG_ERR_NO_ERROR) {
        g_debug("%s: gpgme_op_import: %s", __func__, gpgme_strerror(gpgerr));
        g_set_error(err, LR_GPG_ERROR, LRE_GPGERROR,
                    "gpgme_op_import() error: %s", gpgme_strerror(gpgerr));
        gpgme_release(context);
        close(key_fd);
        return FALSE;
    }

    close(key_fd);
    gpgme_release(context);

    return TRUE;
}
Beispiel #30
0
void init_cryptofox() {
	init_gpgme (GPGME_PROTOCOL_OpenPGP);
	_cf_err = gpgme_new (&_cf_ctx);
	fail_if_err (_cf_err);
}