pgp presence

This commit is contained in:
Tony Olagbaiye 2021-07-22 07:48:57 +01:00
parent a384787413
commit 6d6d155574
No known key found for this signature in database
GPG Key ID: 9E2FF3BDEBDFC910
8 changed files with 133 additions and 12 deletions

View File

@ -136,7 +136,12 @@
* [ ] Delete bookmarks
* [ ] Roster
* [ ] OTR (libotr)
* [ ] PGP (libgpgme)
* [X] PGP (rnpgp)
* [X] Use keyrings (e.g. exported from gnupg)
* [X] Presence
* [X] Decryption
* [X] Encryption
* [X] Custom set/clear key (/pgp)
* [ ] Room Explorer (https://search.jabber.network/docs/api)
** TODO [#C] Implement completion engine (milestone v0.3)
** TODO [#D] Close all issues (milestone v1.0)

View File

@ -34,6 +34,7 @@ char *account_options[ACCOUNT_NUM_OPTIONS][2] =
{ "status", "probably about to segfault" },
{ "pgp_pubring_path", "${weechat_data_dir}/pubring.gpg" },
{ "pgp_secring_path", "${weechat_data_dir}/secring.gpg" },
{ "pgp_keyid", "" },
};
struct t_account *account__search(const char *name)

View File

@ -19,6 +19,7 @@ enum t_account_option
ACCOUNT_OPTION_STATUS,
ACCOUNT_OPTION_PGP_PUBRING_PATH,
ACCOUNT_OPTION_PGP_SECRING_PATH,
ACCOUNT_OPTION_PGP_KEYID,
ACCOUNT_NUM_OPTIONS,
};
@ -60,6 +61,8 @@ enum t_account_option
weechat_config_string(account->options[ACCOUNT_OPTION_PGP_PUBRING_PATH])
#define account_pgp_secring_path(account) \
weechat_config_string(account->options[ACCOUNT_OPTION_PGP_SECRING_PATH])
#define account_pgp_keyid(account) \
weechat_config_string(account->options[ACCOUNT_OPTION_PGP_KEYID])
struct t_device
{

View File

@ -662,7 +662,6 @@ int command__pgp(const void *pointer, void *data,
{
struct t_account *ptr_account = NULL;
struct t_channel *ptr_channel = NULL;
xmpp_stanza_t *message;
char *keyid;
(void) pointer;

View File

@ -218,6 +218,22 @@ config__account_new_option (struct t_config_file *config_file,
callback_change_data,
NULL, NULL, NULL);
break;
case ACCOUNT_OPTION_PGP_KEYID:
new_option = weechat_config_new_option (
config_file, section,
option_name, "string",
N_("XMPP Account PGP Key ID"),
NULL, 0, 0,
default_value, value,
null_value_allowed,
callback_check_value,
callback_check_value_pointer,
callback_check_value_data,
callback_change,
callback_change_pointer,
callback_change_data,
NULL, NULL, NULL);
break;
case ACCOUNT_NUM_OPTIONS:
break;
}

View File

@ -908,7 +908,8 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status,
if (status == XMPP_CONN_CONNECT)
{
xmpp_stanza_t *pres, *pres__c, *pres__status, *pres__status__text, **children;
xmpp_stanza_t *pres, *pres__c, *pres__status, *pres__status__text,
*pres__x, *pres__x__text, **children;
char cap_hash[28+1] = {0};
xmpp_handler_add(conn, &connection__version_handler,
@ -922,8 +923,14 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status,
xmpp_handler_add(conn, &connection__iq_handler,
NULL, "iq", NULL, account);
pgp__init(&account->pgp,
weechat_string_eval_expression(account_pgp_pubring_path(account),
NULL, NULL, NULL),
weechat_string_eval_expression(account_pgp_secring_path(account),
NULL, NULL, NULL));
/* Send initial <presence/> so that we appear online to contacts */
children = malloc(sizeof(*children) * (2 + 1));
children = malloc(sizeof(*children) * (3 + 1));
pres__c = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(pres__c, "c");
@ -943,8 +950,25 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status,
xmpp_stanza_release(pres__status__text);
children[1] = pres__status;
children[2] = NULL;
if (account->pgp)
{
pres__x = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(pres__x, "x");
xmpp_stanza_set_ns(pres__x, "jabber:x:signed");
pres__x__text = xmpp_stanza_new(account->context);
char *signature = pgp__sign(account->buffer, account->pgp, account_pgp_keyid(account), account_status(account));
xmpp_stanza_set_text(pres__x__text, signature ? signature : "");
free(signature);
xmpp_stanza_add_child(pres__x, pres__x__text);
xmpp_stanza_release(pres__x__text);
children[2] = pres__x;
children[3] = NULL;
}
pres = stanza__presence(account->context, NULL,
children, NULL, strdup(account_jid(account)),
NULL, NULL);
@ -1042,13 +1066,6 @@ void connection__handler(xmpp_conn_t *conn, xmpp_conn_event_t status,
weechat_command(account->buffer, *command);
weechat_string_dyn_free(command, 1);
}
pgp__init(&account->pgp,
weechat_string_eval_expression(account_pgp_pubring_path(account),
NULL, NULL, NULL),
weechat_string_eval_expression(account_pgp_secring_path(account),
NULL, NULL, NULL));
}
else
{

78
pgp.c
View File

@ -284,3 +284,81 @@ verify_finish:
rnp_input_destroy(signature);
return result;
}
char *pgp__sign(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *source, const char *message)
{
rnp_input_t keyfile = NULL;
rnp_input_t input = NULL;
rnp_output_t output = NULL;
rnp_op_sign_t sign = NULL;
rnp_key_handle_t key = NULL;
uint8_t * buf = NULL;
size_t buf_len = 0;
char * result = NULL;
/* create file input and memory output objects for the encrypted message and decrypted
* message */
if (rnp_input_from_memory(&input, (uint8_t *)message, strlen(message), false) !=
RNP_SUCCESS) {
weechat_printf(buffer, "[PGP]\tfailed to create input object\n");
goto sign_finish;
}
if (rnp_output_to_memory(&output, 0) != RNP_SUCCESS) {
weechat_printf(buffer, "[PGP]\tfailed to create output object\n");
goto sign_finish;
}
/* initialize and configure sign operation */
if (rnp_op_sign_detached_create(&sign, pgp->context, input, output) != RNP_SUCCESS) {
weechat_printf(buffer, "[PGP]\tfailed to create sign operation\n");
goto sign_finish;
}
/* armor, file name, compression */
rnp_op_sign_set_armor(sign, true);
rnp_op_sign_set_file_name(sign, "message.txt");
rnp_op_sign_set_file_mtime(sign, time(NULL));
rnp_op_sign_set_compression(sign, "ZIP", 6);
/* signatures creation time - by default will be set to the current time as well */
rnp_op_sign_set_creation_time(sign, time(NULL));
/* signatures expiration time - by default will be 0, i.e. never expire */
rnp_op_sign_set_expiration_time(sign, 365 * 24 * 60 * 60);
/* set hash algorithm - should be compatible for all signatures */
rnp_op_sign_set_hash(sign, RNP_ALGNAME_SHA256);
/* now add signatures. First locate the signing key, then add and setup signature */
if (rnp_locate_key(pgp->context, "keyid", source, &key) != RNP_SUCCESS) {
weechat_printf(buffer, "[PGP]\tfailed to locate signing key: %s\n", source);
goto sign_finish;
}
if (rnp_op_sign_add_signature(sign, key, NULL) != RNP_SUCCESS) {
weechat_printf(buffer, "[PGP]\tfailed to add signature for key: %s\n", source);
goto sign_finish;
}
rnp_key_handle_destroy(key);
key = NULL;
/* finally do signing */
if (rnp_op_sign_execute(sign) != RNP_SUCCESS) {
weechat_printf(buffer, "[PGP]\tfailed to sign with key: %s\n", source);
goto sign_finish;
}
/* get the signature from the output structure */
if (rnp_output_memory_get_buf(output, &buf, &buf_len, false) != RNP_SUCCESS) {
goto sign_finish;
}
result = strndup((char *)buf + strlen(PGP_SIGNATURE_HEADER),
buf_len - strlen(PGP_SIGNATURE_HEADER) - strlen(PGP_SIGNATURE_FOOTER));
sign_finish:
rnp_input_destroy(keyfile);
rnp_key_handle_destroy(key);
rnp_op_sign_destroy(sign);
rnp_input_destroy(input);
rnp_output_destroy(output);
return result;
}

2
pgp.h
View File

@ -23,4 +23,6 @@ char *pgp__encrypt(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *t
char *pgp__verify(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *certificate);
char *pgp__sign(struct t_gui_buffer *buffer, struct t_pgp *pgp, const char *source, const char *message);
#endif /*WEECHAT_XMPP_PGP_H*/