mirror of
https://github.com/profanity-im/profanity.git
synced 2025-01-03 14:57:42 -05:00
Add /pgp sendpub
command
Command allows to share your PGP pub key with ease, it's not described in XEP-0027, but used in some clients, such as PSI, Pidgin. Fix typos Minor improvements
This commit is contained in:
parent
f3265565e8
commit
a59623a007
@ -910,6 +910,7 @@ cmd_ac_init(void)
|
||||
autocomplete_add(pgp_ac, "log");
|
||||
autocomplete_add(pgp_ac, "char");
|
||||
autocomplete_add(pgp_ac, "sendfile");
|
||||
autocomplete_add(pgp_ac, "sendpub");
|
||||
|
||||
pgp_log_ac = autocomplete_new();
|
||||
autocomplete_add(pgp_log_ac, "on");
|
||||
|
@ -1705,7 +1705,8 @@ static const struct cmd_t command_defs[] = {
|
||||
"/pgp end",
|
||||
"/pgp log on|off|redact",
|
||||
"/pgp char <char>",
|
||||
"/pgp sendfile on|off")
|
||||
"/pgp sendfile on|off",
|
||||
"/pgp sendpub")
|
||||
CMD_DESC(
|
||||
"Open PGP commands to manage keys, and perform PGP encryption during chat sessions. "
|
||||
"See the /account command to set your own PGP key.")
|
||||
@ -1719,7 +1720,8 @@ static const struct cmd_t command_defs[] = {
|
||||
{ "log on|off", "Enable or disable plaintext logging of PGP encrypted messages." },
|
||||
{ "log redact", "Log PGP encrypted messages, but replace the contents with [redacted]. This is the default." },
|
||||
{ "char <char>", "Set the character to be displayed next to PGP encrypted messages." },
|
||||
{ "sendfile on|off", "Allow /sendfile to send unencrypted files while otherwise using PGP." })
|
||||
{ "sendfile on|off", "Allow /sendfile to send unencrypted files while otherwise using PGP." },
|
||||
{ "sendpub", "Used in chat. Sends a message to the current recipient with your PGP public key." })
|
||||
CMD_EXAMPLES(
|
||||
"/pgp log off",
|
||||
"/pgp setkey odin@valhalla.edda BA19CACE5A9592C5",
|
||||
|
@ -7489,12 +7489,12 @@ cmd_pgp(ProfWin* window, const char* const command, gchar** args)
|
||||
if (g_strcmp0(args[0], "start") == 0) {
|
||||
jabber_conn_status_t conn_status = connection_get_status();
|
||||
if (conn_status != JABBER_CONNECTED) {
|
||||
cons_show("You must be connected to start PGP encrpytion.");
|
||||
cons_show("You must be connected to start PGP encryption.");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (window->type != WIN_CHAT && args[1] == NULL) {
|
||||
cons_show("You must be in a regular chat window to start PGP encrpytion.");
|
||||
cons_show("You must be in a regular chat window to start PGP encryption.");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -7533,14 +7533,17 @@ cmd_pgp(ProfWin* window, const char* const command, gchar** args)
|
||||
}
|
||||
|
||||
ProfAccount* account = accounts_get_account(session_get_account_name());
|
||||
char* err_str = NULL;
|
||||
if (!p_gpg_valid_key(account->pgp_keyid, &err_str)) {
|
||||
win_println(window, THEME_DEFAULT, "!", "Invalid PGP key ID %s: %s, cannot start PGP encryption.", account->pgp_keyid, err_str);
|
||||
free(err_str);
|
||||
if (account->pgp_keyid == NULL) {
|
||||
win_println(window, THEME_DEFAULT, "!", "Couldn't start PGP session. Please, set your PGP key using /account set %s pgpkeyid <pgpkeyid>. To list pgp keys, use /pgp keys.", account->name);
|
||||
account_free(account);
|
||||
return TRUE;
|
||||
}
|
||||
auto_char char* err_str = NULL;
|
||||
if (!p_gpg_valid_key(account->pgp_keyid, &err_str)) {
|
||||
win_println(window, THEME_DEFAULT, "!", "Invalid PGP key ID %s: %s, cannot start PGP encryption.", account->pgp_keyid, err_str);
|
||||
account_free(account);
|
||||
return TRUE;
|
||||
}
|
||||
free(err_str);
|
||||
account_free(account);
|
||||
|
||||
if (!p_gpg_available(chatwin->barejid)) {
|
||||
@ -7562,7 +7565,7 @@ cmd_pgp(ProfWin* window, const char* const command, gchar** args)
|
||||
}
|
||||
|
||||
if (window->type != WIN_CHAT) {
|
||||
cons_show("You must be in a regular chat window to end PGP encrpytion.");
|
||||
cons_show("You must be in a regular chat window to end PGP encryption.");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -7583,6 +7586,31 @@ cmd_pgp(ProfWin* window, const char* const command, gchar** args)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (g_strcmp0(args[0], "sendpub") == 0) {
|
||||
if (window->type != WIN_CHAT) {
|
||||
cons_show_error("Please, use this command only in chat windows.");
|
||||
return TRUE;
|
||||
}
|
||||
ProfChatWin* chatwin = (ProfChatWin*)window;
|
||||
ProfAccount* account = accounts_get_account(session_get_account_name());
|
||||
|
||||
if (account->pgp_keyid == NULL) {
|
||||
cons_show_error("Please, set the PGP key first using /account set %s pgpkeyid <pgpkeyid>. To list pgp keys, use /pgp keys.", account->name);
|
||||
account_free(account);
|
||||
return TRUE;
|
||||
}
|
||||
auto_char char* pubkey = p_gpg_get_pubkey(account->pgp_keyid);
|
||||
if (pubkey == NULL) {
|
||||
cons_show_error("Couldn't get your PGP public key. Please, check error logs.");
|
||||
account_free(account);
|
||||
return TRUE;
|
||||
}
|
||||
cl_ev_send_msg(chatwin, pubkey, NULL);
|
||||
cons_show("PGP key has been shared with %s.", chatwin->barejid);
|
||||
account_free(account);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
cons_bad_cmd_usage(command);
|
||||
return TRUE;
|
||||
#else
|
||||
@ -7691,12 +7719,12 @@ cmd_ox(ProfWin* window, const char* const command, gchar** args)
|
||||
} else if (g_strcmp0(args[0], "start") == 0) {
|
||||
jabber_conn_status_t conn_status = connection_get_status();
|
||||
if (conn_status != JABBER_CONNECTED) {
|
||||
cons_show("You must be connected to start OX encrpytion.");
|
||||
cons_show("You must be connected to start OX encryption.");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (window->type != WIN_CHAT && args[1] == NULL) {
|
||||
cons_show("You must be in a regular chat window to start OX encrpytion.");
|
||||
cons_show("You must be in a regular chat window to start OX encryption.");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -71,6 +71,7 @@ static Autocomplete key_ac;
|
||||
|
||||
static char* _remove_header_footer(char* str, const char* const footer);
|
||||
static char* _add_header_footer(const char* const str, const char* const header, const char* const footer);
|
||||
static char* _gpgme_data_to_char(gpgme_data_t data);
|
||||
static void _save_pubkeys(void);
|
||||
|
||||
void
|
||||
@ -422,7 +423,9 @@ p_gpg_valid_key(const char* const keyid, char** err_str)
|
||||
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));
|
||||
*err_str = strdup(gpgme_strerror(error));
|
||||
if (err_str) {
|
||||
*err_str = strdup(gpgme_strerror(error));
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -431,13 +434,9 @@ p_gpg_valid_key(const char* const keyid, char** err_str)
|
||||
|
||||
if (error || key == NULL) {
|
||||
log_error("GPG: Failed to get key. %s %s", gpgme_strsource(error), gpgme_strerror(error));
|
||||
*err_str = strdup(gpgme_strerror(error));
|
||||
gpgme_release(ctx);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (key == NULL) {
|
||||
*err_str = strdup("Unknown error");
|
||||
if (err_str) {
|
||||
*err_str = strdup(error ? gpgme_strerror(error) : "gpgme didn't return any error, but it didn't return a key");
|
||||
}
|
||||
gpgme_release(ctx);
|
||||
return FALSE;
|
||||
}
|
||||
@ -717,19 +716,11 @@ p_gpg_decrypt(const char* const cipher)
|
||||
}
|
||||
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) {
|
||||
result = strndup(plain_str, len);
|
||||
gpgme_free(plain_str);
|
||||
}
|
||||
|
||||
if (passphrase_attempt) {
|
||||
passphrase = strdup(passphrase_attempt);
|
||||
}
|
||||
|
||||
return result;
|
||||
return _gpgme_data_to_char(plain_data);
|
||||
}
|
||||
|
||||
void
|
||||
@ -769,6 +760,72 @@ p_gpg_format_fp_str(char* fp)
|
||||
return g_string_free(format, FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Function to extract specific public key from PGP
|
||||
* \param keyid Key ID that will be used to search key in the current PGP context, if NULL returns null
|
||||
* \returns null-terminated char* string with the the public key in armored format, that must be free'd to avoid memory leaks
|
||||
* or NULL on error
|
||||
*/
|
||||
char*
|
||||
p_gpg_get_pubkey(const char* keyid)
|
||||
{
|
||||
if (!keyid || *keyid == '\0') {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gpgme_ctx_t context = NULL;
|
||||
gpgme_error_t error = GPG_ERR_NO_ERROR;
|
||||
gpgme_data_t data = NULL;
|
||||
|
||||
error = gpgme_new(&context);
|
||||
if (error != GPG_ERR_NO_ERROR) {
|
||||
log_error("GPG: Failed to create gpgme context. %s", gpgme_strerror(error));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
error = gpgme_data_new(&data);
|
||||
if (error != GPG_ERR_NO_ERROR || data == NULL) {
|
||||
log_error("GPG: Failed to create new gpgme data. %s", gpgme_strerror(error));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
gpgme_set_armor(context, 1);
|
||||
|
||||
error = gpgme_op_export(context, keyid, GPGME_EXPORT_MODE_MINIMAL, data);
|
||||
if (error != GPG_ERR_NO_ERROR) {
|
||||
log_error("GPG: Failed to export public key. %s", gpgme_strerror(error));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
gpgme_release(context);
|
||||
return _gpgme_data_to_char(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a gpgme_data_t object to a null-terminated char* string.
|
||||
* The returned string is allocated using malloc and should be freed by the caller.
|
||||
* If an error occurs or the data is empty, NULL is returned and errors written to the error log.
|
||||
*/
|
||||
static char*
|
||||
_gpgme_data_to_char(gpgme_data_t data)
|
||||
{
|
||||
size_t buffer_size = 0;
|
||||
char* gpgme_buffer = gpgme_data_release_and_get_mem(data, &buffer_size);
|
||||
|
||||
if (!gpgme_buffer) {
|
||||
log_error("GPG: Unable to extract gpgmedata.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* buffer = malloc(buffer_size + 1);
|
||||
memcpy(buffer, gpgme_buffer, buffer_size);
|
||||
buffer[buffer_size] = '\0';
|
||||
gpgme_free(gpgme_buffer);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static char*
|
||||
_remove_header_footer(char* str, const char* const footer)
|
||||
{
|
||||
|
@ -73,6 +73,7 @@ void p_gpg_free_decrypted(char* decrypted);
|
||||
char* p_gpg_autocomplete_key(const char* const search_str, gboolean previous, void* context);
|
||||
void p_gpg_autocomplete_key_reset(void);
|
||||
char* p_gpg_format_fp_str(char* fp);
|
||||
char* p_gpg_get_pubkey(const char* const keyid);
|
||||
|
||||
ProfPGPKey* p_gpg_key_new(void);
|
||||
void p_gpg_free_key(ProfPGPKey* key);
|
||||
|
@ -98,3 +98,9 @@ p_gpg_format_fp_str(char* fp)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char*
|
||||
p_gpg_get_pubkey(const char* const keyid)
|
||||
{
|
||||
return NULL;
|
||||
}
|
@ -36,7 +36,7 @@ cmd_pgp_start_shows_message_when_connection(jabber_conn_status_t conn_status)
|
||||
|
||||
will_return(connection_get_status, conn_status);
|
||||
|
||||
expect_cons_show("You must be connected to start PGP encrpytion.");
|
||||
expect_cons_show("You must be connected to start PGP encryption.");
|
||||
|
||||
gboolean result = cmd_pgp(&window, CMD_PGP, args);
|
||||
assert_true(result);
|
||||
@ -69,7 +69,7 @@ cmd_pgp_start_shows_message_when_no_arg_in_wintype(win_type_t wintype)
|
||||
|
||||
will_return(connection_get_status, JABBER_CONNECTED);
|
||||
|
||||
expect_cons_show("You must be in a regular chat window to start PGP encrpytion.");
|
||||
expect_cons_show("You must be in a regular chat window to start PGP encryption.");
|
||||
|
||||
gboolean result = cmd_pgp(&window, CMD_PGP, args);
|
||||
assert_true(result);
|
||||
|
Loading…
Reference in New Issue
Block a user