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(); }
/* ############################################################################# * * 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; }
/* ############################################################################# * * 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; }
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; } }
/* ############################################################################# * * 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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
/* 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; }
/* ------------------ * 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; }
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; }
/* ------------------ * 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; }
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; }
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; }
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; }
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 }
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; }
/* ############################################################################# * * 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; }
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); }
/* ############################################################################# * * Description encrypt the given buffer and return the encrypted data with * an updated size information * Author Harry Brueckner * Date 2005-03-31 * Arguments char* buffer - buffer to encrypt * int size - size of the buffer * char** newbuffer - pointer to the new buffer which holds the * encrypted data * int* newsize - size of the returned buffer * PASSPHRASE_FN password_cb - callback function pointer used * to get the current passphrase * SHOWERROR_FN showerror_cb - callback function pointer used * to display errors * Return 0 if ok, otherwise 1 */ int gpgEncrypt(char* buffer, int size, char** newbuffer, int* newsize, PASSPHRASE_FN password_cb, SHOWERROR_FN showerror_cb) { gpgme_ctx_t context; gpgme_data_t input, output; gpgme_encrypt_result_t result; gpgme_error_t error; gpgme_key_t* key = NULL; gpgme_key_t tkey = NULL; gpgme_sign_result_t sign_result; int i, keys = 0, showerror = 1; char* agent; char* fpr; char* tmpbuffer = NULL; TRACE(99, "gpgEncrypt()", NULL); /* we set our passphrase callback function */ passphrase_callback = password_cb; /* we initialize the external size data */ newsize[0] = 0; error = gpgme_new(&context); if (!error) { gpgme_set_textmode(context, 1); gpgme_set_armor(context, 1); /* Flawfinder: ignore */ agent = getenv("GPG_AGENT_INFO"); if (!(agent && strchr(agent, ':'))) { retries = 0; gpgme_set_passphrase_cb(context, gpgRequestPassphrase, NULL); } } if (!error) { error = gpgme_data_new_from_mem(&input, buffer, size, 0); } if (!error) { error = gpgme_data_new(&output); } if (!error) { gpgme_signers_clear(context); } if (!error) { /* allocate the keys */ keys = keyCount(); key = memAlloc(__FILE__, __LINE__, sizeof(gpgme_key_t) * (keys + 1)); key[keys] = NULL; signers = 0; for (i = 0; i < keys && !error; i++) { /* add all keys */ fpr = gpgGetFingerprint(keyGet(i), LIST_SECRET); if (fpr) { error = gpgme_get_key(context, fpr, &tkey, LIST_SECRET); if (tkey -> secret); { error = gpgme_signers_add(context, tkey); signers++; } memFreeString(__FILE__, __LINE__, fpr); } fpr = gpgGetFingerprint(keyGet(i), LIST_ALL); if (fpr) { error = gpgme_get_key(context, fpr, &key[i], LIST_ALL); memFreeString(__FILE__, __LINE__, fpr); } } } if (signers > 1) { /* as soon as we get two signers, we must no longer cache anything */ config -> keeppassphrase = 0; clearPassphrase(1); } /* encrypt and sign the data */ if (!error) { error = gpgme_op_encrypt_sign(context, key, GPGME_ENCRYPT_ALWAYS_TRUST, input, output); } /* we don't need the passphrase any longer */ clearPassphrase(0); if (!error) { result = gpgme_op_encrypt_result(context); } if (!error && result -> invalid_recipients) { tmpbuffer = memAlloc(__FILE__, __LINE__, STDBUFFERLENGTH); snprintf(tmpbuffer, STDBUFFERLENGTH, _("Invalid recipient encountered: %s"), result -> invalid_recipients -> fpr); (showerror_cb)(_("GpgMe error"), tmpbuffer); memFree(__FILE__, __LINE__, tmpbuffer, STDBUFFERLENGTH); showerror = 0; error = 1; } if (!error) { sign_result = gpgme_op_sign_result(context); error = gpgCheckSignResult(showerror_cb, sign_result, GPGME_SIG_MODE_NORMAL); showerror = !error; } if (!error) { tmpbuffer = gpgData2Char(output, newsize); } /* free the keys again */ i = 0; while (key && keys && key[i]) { gpgme_key_unref(key[i++]); } memFree(__FILE__, __LINE__, key, sizeof(gpgme_key_t) * (keys + 1)); gpgme_data_release(input); gpgme_data_release(output); gpgme_release(context); *newbuffer = tmpbuffer; if (error) { if (showerror) { (showerror_cb)(_("GpgMe encrypt error"), gpgme_strerror(error)); } return 1; } else return 0; }
static 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); }
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; }
void init_cryptofox() { init_gpgme (GPGME_PROTOCOL_OpenPGP); _cf_err = gpgme_new (&_cf_ctx); fail_if_err (_cf_err); }