mirror of
https://github.com/profanity-im/profanity.git
synced 2024-12-04 14:46:46 -05:00
Send encrypted messages
This commit is contained in:
parent
551f7df1f7
commit
eb5cb7b2f8
@ -42,13 +42,14 @@
|
|||||||
#include "pgp/gpg.h"
|
#include "pgp/gpg.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
#define PGP_HEADER "-----BEGIN PGP SIGNATURE-----"
|
#define PGP_SIGNATURE_HEADER "-----BEGIN PGP SIGNATURE-----"
|
||||||
#define PGP_FOOTER "-----END PGP SIGNATURE-----"
|
#define PGP_SIGNATURE_FOOTER "-----END PGP SIGNATURE-----"
|
||||||
|
#define PGP_MESSAGE_FOOTER "-----END PGP MESSAGE-----"
|
||||||
|
|
||||||
static const char *libversion;
|
static const char *libversion;
|
||||||
static GHashTable *fingerprints;
|
static GHashTable *fingerprints;
|
||||||
|
|
||||||
static char* _remove_header_footer(char *str);
|
static char* _remove_header_footer(char *str, const char * const footer);
|
||||||
static char* _add_header_footer(const char * const str);
|
static char* _add_header_footer(const char * const str);
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -171,7 +172,7 @@ p_gpg_verify(const char * const barejid, const char *const sign)
|
|||||||
}
|
}
|
||||||
|
|
||||||
char*
|
char*
|
||||||
p_gpg_sign_str(const char * const str, const char * const fp)
|
p_gpg_sign(const char * const str, const char * const fp)
|
||||||
{
|
{
|
||||||
gpgme_ctx_t ctx;
|
gpgme_ctx_t ctx;
|
||||||
gpgme_error_t error = gpgme_new(&ctx);
|
gpgme_error_t error = gpgme_new(&ctx);
|
||||||
@ -222,7 +223,7 @@ p_gpg_sign_str(const char * const str, const char * const fp)
|
|||||||
char *signed_str = gpgme_data_release_and_get_mem(signed_data, &len);
|
char *signed_str = gpgme_data_release_and_get_mem(signed_data, &len);
|
||||||
if (signed_str != NULL) {
|
if (signed_str != NULL) {
|
||||||
signed_str[len] = 0;
|
signed_str[len] = 0;
|
||||||
result = _remove_header_footer(signed_str);
|
result = _remove_header_footer(signed_str, PGP_SIGNATURE_FOOTER);
|
||||||
}
|
}
|
||||||
gpgme_free(signed_str);
|
gpgme_free(signed_str);
|
||||||
gpgme_release(ctx);
|
gpgme_release(ctx);
|
||||||
@ -231,26 +232,85 @@ p_gpg_sign_str(const char * const str, const char * const fp)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char*
|
char *
|
||||||
_remove_header_footer(char *str)
|
p_gpg_encrypt(const char * const barejid, const char * const message)
|
||||||
{
|
{
|
||||||
char *pointer = str;
|
char *fp = g_hash_table_lookup(fingerprints, barejid);
|
||||||
|
|
||||||
|
if (!fp) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
gpgme_key_t keys[2];
|
||||||
|
|
||||||
|
keys[0] = NULL;
|
||||||
|
keys[1] = 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 key;
|
||||||
|
error = gpgme_get_key(ctx, fp, &key, 0);
|
||||||
|
if (error || key == NULL) {
|
||||||
|
log_error("GPG: Failed to get key. %s %s", gpgme_strsource(error), gpgme_strerror(error));
|
||||||
|
gpgme_release(ctx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
keys[0] = key;
|
||||||
|
|
||||||
|
gpgme_data_t plain;
|
||||||
|
gpgme_data_t cipher;
|
||||||
|
gpgme_data_new_from_mem(&plain, message, strlen(message), 1);
|
||||||
|
gpgme_data_new(&cipher);
|
||||||
|
|
||||||
|
gpgme_set_armor(ctx, 1);
|
||||||
|
error = gpgme_op_encrypt(ctx, keys, GPGME_ENCRYPT_ALWAYS_TRUST, plain, cipher);
|
||||||
|
if (error) {
|
||||||
|
log_error("GPG: Failed to encrypt message. %s %s", gpgme_strsource(error), gpgme_strerror(error));
|
||||||
|
gpgme_release(ctx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
gpgme_data_release(plain);
|
||||||
|
|
||||||
|
char *cipher_str = NULL;
|
||||||
|
char *result = NULL;
|
||||||
|
size_t len;
|
||||||
|
cipher_str = gpgme_data_release_and_get_mem(cipher, &len);
|
||||||
|
if (cipher_str) {
|
||||||
|
result = _remove_header_footer(cipher_str, PGP_MESSAGE_FOOTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
gpgme_free(cipher_str);
|
||||||
|
gpgme_release(ctx);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char*
|
||||||
|
_remove_header_footer(char *str, const char * const footer)
|
||||||
|
{
|
||||||
|
int pos = 0;
|
||||||
int newlines = 0;
|
int newlines = 0;
|
||||||
|
|
||||||
while (newlines < 3) {
|
while (newlines < 3) {
|
||||||
if (pointer[0] == '\n') {
|
if (str[pos] == '\n') {
|
||||||
newlines++;
|
newlines++;
|
||||||
}
|
}
|
||||||
pointer++;
|
pos++;
|
||||||
|
|
||||||
if (strlen(pointer) == 0) {
|
if (str[pos] == '\0') {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char *stripped = malloc(strlen(pointer)+1-strlen(PGP_FOOTER));
|
char *stripped = strdup(&str[pos]);
|
||||||
strncpy(stripped,pointer,strlen(pointer)-strlen(PGP_FOOTER));
|
char *footer_start = g_strrstr(stripped, footer);
|
||||||
stripped[strlen(pointer)-strlen(PGP_FOOTER)] = '\0';
|
footer_start[0] = '\0';
|
||||||
|
|
||||||
return stripped;
|
return stripped;
|
||||||
}
|
}
|
||||||
@ -260,11 +320,11 @@ _add_header_footer(const char * const str)
|
|||||||
{
|
{
|
||||||
GString *result_str = g_string_new("");
|
GString *result_str = g_string_new("");
|
||||||
|
|
||||||
g_string_append(result_str, PGP_HEADER);
|
g_string_append(result_str, PGP_SIGNATURE_HEADER);
|
||||||
g_string_append(result_str, "\n\n");
|
g_string_append(result_str, "\n\n");
|
||||||
g_string_append(result_str, str);
|
g_string_append(result_str, str);
|
||||||
g_string_append(result_str, "\n");
|
g_string_append(result_str, "\n");
|
||||||
g_string_append(result_str, PGP_FOOTER);
|
g_string_append(result_str, PGP_SIGNATURE_FOOTER);
|
||||||
|
|
||||||
char *result = result_str->str;
|
char *result = result_str->str;
|
||||||
g_string_free(result_str, FALSE);
|
g_string_free(result_str, FALSE);
|
||||||
|
@ -47,7 +47,8 @@ GSList* p_gpg_list_keys(void);
|
|||||||
GHashTable* p_gpg_fingerprints(void);
|
GHashTable* p_gpg_fingerprints(void);
|
||||||
const char* p_gpg_libver(void);
|
const char* p_gpg_libver(void);
|
||||||
void p_gpg_free_key(ProfPGPKey *key);
|
void p_gpg_free_key(ProfPGPKey *key);
|
||||||
char* p_gpg_sign_str(const char * const str, const char * const fp);
|
char* p_gpg_sign(const char * const str, const char * const fp);
|
||||||
void p_gpg_verify(const char * const barejid, const char *const sign);
|
void p_gpg_verify(const char * const barejid, const char *const sign);
|
||||||
|
char* p_gpg_encrypt(const char * const barejid, const char * const message);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -49,6 +49,7 @@
|
|||||||
#include "roster_list.h"
|
#include "roster_list.h"
|
||||||
#include "xmpp/stanza.h"
|
#include "xmpp/stanza.h"
|
||||||
#include "xmpp/xmpp.h"
|
#include "xmpp/xmpp.h"
|
||||||
|
#include "pgp/gpg.h"
|
||||||
|
|
||||||
#define HANDLE(ns, type, func) xmpp_handler_add(conn, func, ns, STANZA_NAME_MESSAGE, type, ctx)
|
#define HANDLE(ns, type, func) xmpp_handler_add(conn, func, ns, STANZA_NAME_MESSAGE, type, ctx)
|
||||||
|
|
||||||
@ -104,7 +105,34 @@ message_send_chat(const char * const barejid, const char * const msg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
char *id = create_unique_id("msg");
|
char *id = create_unique_id("msg");
|
||||||
xmpp_stanza_t *message = stanza_create_message(ctx, id, jid, STANZA_TYPE_CHAT, msg);
|
xmpp_stanza_t *message = NULL;
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBGPGME
|
||||||
|
char *account_name = jabber_get_account_name();
|
||||||
|
ProfAccount *account = accounts_get_account(account_name);
|
||||||
|
if (account->pgp_keyid) {
|
||||||
|
Jid *jidp = jid_create(jid);
|
||||||
|
char *encrypted = p_gpg_encrypt(jidp->barejid, msg);
|
||||||
|
if (encrypted) {
|
||||||
|
message = stanza_create_message(ctx, id, jid, STANZA_TYPE_CHAT, "This message is encrypted.");
|
||||||
|
xmpp_stanza_t *x = xmpp_stanza_new(ctx);
|
||||||
|
xmpp_stanza_set_name(x, STANZA_NAME_X);
|
||||||
|
xmpp_stanza_set_ns(x, STANZA_NS_ENCRYPTED);
|
||||||
|
xmpp_stanza_t *enc_st = xmpp_stanza_new(ctx);
|
||||||
|
xmpp_stanza_set_text(enc_st, encrypted);
|
||||||
|
xmpp_stanza_add_child(x, enc_st);
|
||||||
|
xmpp_stanza_release(enc_st);
|
||||||
|
xmpp_stanza_add_child(message, x);
|
||||||
|
xmpp_stanza_release(x);
|
||||||
|
free(encrypted);
|
||||||
|
} else {
|
||||||
|
message = stanza_create_message(ctx, id, jid, STANZA_TYPE_CHAT, msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
message = stanza_create_message(ctx, id, jid, STANZA_TYPE_CHAT, msg);
|
||||||
|
#endif
|
||||||
|
|
||||||
free(jid);
|
free(jid);
|
||||||
|
|
||||||
if (state) {
|
if (state) {
|
||||||
|
@ -232,7 +232,7 @@ presence_update(const resource_presence_t presence_type, const char * const msg,
|
|||||||
char *account_name = jabber_get_account_name();
|
char *account_name = jabber_get_account_name();
|
||||||
ProfAccount *account = accounts_get_account(account_name);
|
ProfAccount *account = accounts_get_account(account_name);
|
||||||
if (account->pgp_keyid) {
|
if (account->pgp_keyid) {
|
||||||
char *signed_status = p_gpg_sign_str(msg, account->pgp_keyid);
|
char *signed_status = p_gpg_sign(msg, account->pgp_keyid);
|
||||||
|
|
||||||
if (signed_status) {
|
if (signed_status) {
|
||||||
xmpp_stanza_t *x = xmpp_stanza_new(ctx);
|
xmpp_stanza_t *x = xmpp_stanza_new(ctx);
|
||||||
|
@ -160,6 +160,7 @@
|
|||||||
#define STANZA_NS_FORWARD "urn:xmpp:forward:0"
|
#define STANZA_NS_FORWARD "urn:xmpp:forward:0"
|
||||||
#define STANZA_NS_RECEIPTS "urn:xmpp:receipts"
|
#define STANZA_NS_RECEIPTS "urn:xmpp:receipts"
|
||||||
#define STANZA_NS_SIGNED "jabber:x:signed"
|
#define STANZA_NS_SIGNED "jabber:x:signed"
|
||||||
|
#define STANZA_NS_ENCRYPTED "jabber:x:encrypted"
|
||||||
|
|
||||||
#define STANZA_DATAFORM_SOFTWARE "urn:xmpp:dataforms:softwareinfo"
|
#define STANZA_DATAFORM_SOFTWARE "urn:xmpp:dataforms:softwareinfo"
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user