Tony Olagbaiye 2 years ago
commit 5c50107bb9
No known key found for this signature in database
GPG Key ID: 9E2FF3BDEBDFC910

@ -5,10 +5,12 @@ export CC=gcc CXX="g++ -fdiagnostics-color=always"
# Miscellaneous packages.
ENVIRONMENTS=(
weechat # Debug runs
profanity # Test
)
# Environment packages.
PACKAGES=(
profanity # Test
autoconf # Deps with autoreconf
autoconf-archive # Deps with m4 tooling
automake # Deps with automake
@ -25,7 +27,7 @@ PACKAGES=(
libxml2 # Dep (libxml2)
libstrophe # Dep (strophe)
libgcrypt # Dep (gcrypt)
libsignal-protocol-c # Dep (libsignal)
libsignal-protocol-c -l libomemo.scm # Dep (libsignal)
lmdb lmdbxx # Dep (lmdb)
rnp # Dep (rnpgp)
)
@ -34,11 +36,17 @@ echo direnv: fetching source - weechat
mkdir -p /tmp/guix-build-weechat-3.2.drv-0
tar -C /tmp/guix-build-weechat-3.2.drv-0 -xJf $(guix build --source weechat)
echo direnv: fetching source - libomemo-c
mkdir -p /tmp/guix-build-libomemo-c-2.3.3.drv-0
ln -sf $(guix build --source -f libomemo.scm) /tmp/guix-build-libomemo-c-2.3.3.drv-0
use guix \
${ENVIRONMENTS[@]} --ad-hoc ${PACKAGES[@]} \
--with-debug-info=profanity\
--with-debug-info=weechat \
--with-debug-info=libstrophe \
--with-debug-info=libsignal-protocol-c \
--with-debug-info=libomemo-c\
--with-debug-info=lmdb \
--with-debug-info=rnp \
clang clang:extra ccls gdb

@ -16,7 +16,7 @@
[[https://github.com/bqv/weechat-xmpp/issues?q=is:issue+is:closed][file:https://img.shields.io/github/issues-closed/bqv/weechat-xmpp.svg]]
[[https://github.com/bqv/weechat-xmpp/blob/master/LICENSE][file:https://img.shields.io/github/license/bqv/weechat-xmpp.svg]]
[[https://github.com/bqv/weechat-extras/][file:https://img.shields.io/badge/weechat--extras-xmpp-blue.svg]]
[[https://github.com/bqv/weechat-extras/][file:https://inverse.chat/badge.svg?room=weechat@muc.xa0.uk]]
[[https://inverse.chat/#converse/room?jid=weechat@muc.xa0.uk][file:https://inverse.chat/badge.svg?room=weechat@muc.xa0.uk]]
| Status: | XMPP for power users and digital masochists |
| Location: | [[http://github.com/bqv/weechat-xmpp]] |
@ -31,14 +31,14 @@
My priority here is to have an android-available XMPP client
that hides as little as possible from the user. To use this with
android, set up a relay (`/relay`) and see weechat-android.
I'm gonna rewrite this in C++ at some point when I have a feel
for the full behaviour of an average client.
I might rewrite this in C++ at some point when I feel like I
can do it without burning out.
* Usage
1. Start with =/xmpp add=, use =/help xmpp= for instructions.
1. Start with =/account add=, use =/help account= for instructions.
2. Use =/xmpp connect <account-name>= with the name set at
2. Use =/account connect <account-name>= with the name set at
add-time.
* Installing
@ -49,7 +49,8 @@
- libstrophe (dynamic, dependency)
- libxml2 (dynamic, dependency)
- libsignal-protocol-c (dynamic, dependency)
- lmdb (dynamic, dependency)
- libomemo-c (libsignal-protocol-c) (dynamic, dependency)
- rnp (dynamic, dependency)
- weechat (>= v3.0)
@ -95,6 +96,7 @@
* [-] OOB messages
* [X] Single media on a line
* [ ] Multiple media inline (protocol?)
* [ ] Encrypted (pgp/omemo)
* [X] Buffer autoswitch on enter/open
* [X] Handle open/enter jids with a resource without breaking
* [X] Allow /close without crashing
@ -119,18 +121,18 @@
* [X] [#B] Leaves
* [X] [#B] Tracking
* [X] [#B] Set/show topic
* [-] OMEMO (libsignal-protocol-c)
* [-] Presence
* [X] OMEMO (libomemo-c)
* [X] Presence
* [X] Disco
* [X] Disco response
* [-] Key Generation / storage (lmdb)
* [X] Key Generation / storage (lmdb)
* [X] Generation
* [?] Storage
* [-] Announce
* [X] Storage
* [X] Announce
* [X] Device ID
* [ ] Bundles
* [ ] Messages
* [ ] [#C] MUC PMs
* [X] Bundles
* [X] Messages
* [X] [#C] MUC PMs
* [X] [#A] Send typing notifications
* [X] [#A] Recv typing notifications
* [X] [#C] Read receipts
@ -156,7 +158,6 @@
* [X] Decryption
* [X] Encryption
* [X] Custom set/clear key (/pgp)
* [ ] OOB data and media
* [ ] Room Explorer (https://search.jabber.network/docs/api)
** TODO [#C] Implement completion engine (milestone v0.3)
** TODO [#D] Close all issues (milestone v1.0)
@ -167,7 +168,7 @@
Please submit a pull request or create an issue
to add a new or missing feature.
* Testemonials
* Testimonials
"Weechat-Strophe - for the discerning dual IRCer XMPPer" -- [[github.com/janicez][Ellenor et al Bjornsdottir]]

@ -11,6 +11,7 @@
#include <libxml/xmlwriter.h>
#include "plugin.h"
#include "xmpp/stanza.h"
#include "config.h"
#include "input.h"
#include "omemo.h"
@ -89,7 +90,7 @@ int account__search_option(const char *option_name)
return -1;
}
struct t_account_device *account__search_device(struct t_account *account, int id)
struct t_account_device *account__search_device(struct t_account *account, uint32_t id)
{
struct t_account_device *ptr_device;
@ -117,6 +118,7 @@ void account__add_device(struct t_account *account,
new_device = malloc(sizeof(*new_device));
new_device->id = device->id;
new_device->name = strdup(device->name);
new_device->label = device->label ? strdup(device->label) : NULL;
new_device->prev_device = account->last_device;
new_device->next_device = NULL;
@ -150,6 +152,8 @@ void account__free_device(struct t_account *account, struct t_account_device *de
(device->next_device)->prev_device = device->prev_device;
/* free device data */
if (device->label)
free(device->label);
if (device->name)
free(device->name);
@ -164,6 +168,59 @@ void account__free_device_all(struct t_account *account)
account__free_device(account, account->devices);
}
xmpp_stanza_t *account__get_devicelist(struct t_account *account)
{
xmpp_stanza_t *parent, **children;
struct t_account_device *device;
const char *ns, *node;
char id[64] = {0};
int i = 0;
device = malloc(sizeof(struct t_account_device));
device->id = account->omemo->device_id;
snprintf(id, sizeof(id), "%u", device->id);
device->name = strdup(id);
device->label = strdup("weechat");
children = malloc(sizeof(xmpp_stanza_t *) * 128);
children[i++] = stanza__iq_pubsub_publish_item_list_device(
account->context, NULL, with_noop(device->name), NULL);
free(device->label);
free(device->name);
free(device);
for (device = account->devices; device;
device = device->next_device)
{
if (device->id != account->omemo->device_id)
children[i++] = stanza__iq_pubsub_publish_item_list_device(
account->context, NULL, with_noop(device->name), NULL);
}
children[i] = NULL;
node = "eu.siacs.conversations.axolotl";
children[0] = stanza__iq_pubsub_publish_item_list(
account->context, NULL, children, with_noop(node));
children[1] = NULL;
children[0] = stanza__iq_pubsub_publish_item(
account->context, NULL, children, with_noop("current"));
node = "eu.siacs.conversations.axolotl.devicelist";
children[0] = stanza__iq_pubsub_publish(account->context,
NULL, children,
with_noop(node));
ns = "http://jabber.org/protocol/pubsub";
children[0] = stanza__iq_pubsub(account->context, NULL,
children, with_noop(ns));
parent = stanza__iq(account->context, NULL,
children, NULL, strdup("announce1"),
NULL, NULL, strdup("set"));
free(children);
return parent;
}
struct t_account_mam_query *account__add_mam_query(struct t_account *account,
struct t_channel *channel,
const char *id,
@ -692,7 +749,7 @@ int account__timer_cb(const void *pointer, void *data, int remaining_calls)
struct t_account *ptr_account;
for (ptr_account = accounts; ptr_account;
ptr_account = ptr_account->next_account)
ptr_account = ptr_account ? ptr_account->next_account : NULL)
{
if (ptr_account->is_connected
&& (xmpp_conn_is_connecting(ptr_account->connection)

@ -66,8 +66,9 @@ enum t_account_option
struct t_account_device
{
int id;
uint32_t id;
char *name;
char *label;
struct t_account_device *prev_device;
struct t_account_device *next_device;
@ -128,10 +129,11 @@ extern char *account_options[][2];
struct t_account *account__search(const char *account_name);
struct t_account *account__casesearch (const char *account_name);
int account__search_option(const char *option_name);
struct t_account_device *account__search_device(struct t_account *account, int id);
struct t_account_device *account__search_device(struct t_account *account, uint32_t id);
void account__add_device(struct t_account *account, struct t_account_device *device);
void account__free_device(struct t_account *account, struct t_account_device *device);
void account__free_device_all(struct t_account *account);
xmpp_stanza_t *account__get_devicelist(struct t_account *account);
struct t_account_mam_query *account__add_mam_query(struct t_account *account,
struct t_channel *channel,
const char *id,

@ -2,6 +2,7 @@
// License, version 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <stdint.h>
#include <string.h>
#include <strophe.h>

@ -10,29 +10,61 @@
#include <strophe.h>
#include "plugin.h"
#include "omemo.h"
#include "account.h"
#include "omemo.h"
#include "user.h"
#include "channel.h"
#include "input.h"
#include "buffer.h"
#include "pgp.h"
#include "util.h"
const char *channel__transport_name(enum t_channel_transport transport)
{
switch (transport)
{
case CHANNEL_TRANSPORT_PLAINTEXT:
case CHANNEL_TRANSPORT_PLAIN:
return "PLAINTEXT";
case CHANNEL_TRANSPORT_OMEMO:
return "OMEMO";
case CHANNEL_TRANSPORT_PGP:
return "PGP";
case CHANNEL_TRANSPORT_OTR:
return "OTR";
default:
return NULL;
}
}
void channel__set_transport(struct t_channel *channel, enum t_channel_transport transport, int force)
{
if (force)
switch (transport)
{
case CHANNEL_TRANSPORT_PLAIN:
channel->omemo.enabled = 0;
channel->pgp.enabled = 0;
break;
case CHANNEL_TRANSPORT_OMEMO:
channel->omemo.enabled = 1;
channel->pgp.enabled = 0;
break;
case CHANNEL_TRANSPORT_PGP:
channel->omemo.enabled = 0;
channel->pgp.enabled = 1;
break;
default:
break;
}
if (channel->transport != transport)
{
channel->transport = transport;
weechat_printf_date_tags(channel->buffer, 0, NULL, "%s%sTransport: %s",
weechat_prefix("network"), weechat_color("gray"),
channel__transport_name(channel->transport));
}
}
struct t_account *channel__account(struct t_channel *channel)
{
struct t_account *ptr_account;
@ -80,7 +112,7 @@ struct t_gui_buffer *channel__search_buffer(struct t_account *account,
{
struct t_hdata *hdata_buffer;
struct t_gui_buffer *ptr_buffer;
const char *ptr_type, *ptr_account_name, *ptr_channel_name;
const char *ptr_type, *ptr_account_name, *ptr_remote_jid;
hdata_buffer = weechat_hdata_get("buffer");
ptr_buffer = weechat_hdata_get_list(hdata_buffer, "gui_buffers");
@ -91,18 +123,18 @@ struct t_gui_buffer *channel__search_buffer(struct t_account *account,
{
ptr_type = weechat_buffer_get_string(ptr_buffer, "localvar_type");
ptr_account_name = weechat_buffer_get_string(ptr_buffer,
"localvar_server");
ptr_channel_name = weechat_buffer_get_string(ptr_buffer,
"localvar_channel");
"localvar_account");
ptr_remote_jid = weechat_buffer_get_string(ptr_buffer,
"localvar_remote_jid");
if (ptr_type && ptr_type[0]
&& ptr_account_name && ptr_account_name[0]
&& ptr_channel_name && ptr_channel_name[0]
&& ptr_remote_jid && ptr_remote_jid[0]
&& ( (( (type == CHANNEL_TYPE_MUC))
&& (strcmp(ptr_type, "channel") == 0))
&& (strcmp(ptr_type, "room") == 0))
|| (( (type == CHANNEL_TYPE_PM))
&& (strcmp(ptr_type, "private") == 0)))
&& (strcmp(ptr_account_name, account->name) == 0)
&& (weechat_strcasecmp(ptr_channel_name, name) == 0))
&& (weechat_strcasecmp(ptr_remote_jid, name) == 0))
{
return ptr_buffer;
}
@ -119,13 +151,13 @@ struct t_gui_buffer *channel__create_buffer(struct t_account *account,
{
struct t_gui_buffer *ptr_buffer;
int buffer_created;
const char *short_name, *localvar_channel;
char buffer_name[256];
const char *short_name, *localvar_remote_jid;
char buffer_name[1024];
buffer_created = 0;
snprintf(buffer_name, sizeof(buffer_name),
"xmpp.%s.%s", account->name, name);
"%s.%s", account->name, name);
ptr_buffer = channel__search_buffer(account, type, name);
if (ptr_buffer)
@ -145,17 +177,19 @@ struct t_gui_buffer *channel__create_buffer(struct t_account *account,
if (buffer_created)
{
char *res = strrchr(name, '/');
if (!weechat_buffer_get_integer(ptr_buffer, "short_name_is_set"))
weechat_buffer_set(ptr_buffer, "short_name", name);
weechat_buffer_set(ptr_buffer, "short_name",
res ? res + 1 : name);
}
else
{
short_name = weechat_buffer_get_string (ptr_buffer, "short_name");
localvar_channel = weechat_buffer_get_string(ptr_buffer,
"localvar_channel");
short_name = weechat_buffer_get_string(ptr_buffer, "short_name");
localvar_remote_jid = weechat_buffer_get_string(ptr_buffer,
"localvar_remote_jid");
if (!short_name ||
(localvar_channel && (strcmp(localvar_channel, short_name) == 0)))
(localvar_remote_jid && (strcmp(localvar_remote_jid, short_name) == 0)))
{
weechat_buffer_set(ptr_buffer, "short_name",
xmpp_jid_node(account->context, name));
@ -165,20 +199,21 @@ struct t_gui_buffer *channel__create_buffer(struct t_account *account,
account_option_set(account, ACCOUNT_OPTION_NICKNAME,
xmpp_jid_node(account->context, account_jid(account)));
weechat_buffer_set(ptr_buffer, "name", name);
weechat_buffer_set(ptr_buffer, "notify",
(type == CHANNEL_TYPE_PM) ? "3" : "1");
weechat_buffer_set(ptr_buffer, "localvar_set_type",
(type == CHANNEL_TYPE_PM) ? "private" : "channel");
weechat_buffer_set(ptr_buffer, "localvar_set_nick",
account_nickname(account));
weechat_buffer_set(ptr_buffer, "localvar_set_server", account->name);
weechat_buffer_set(ptr_buffer, "localvar_set_channel", name);
weechat_buffer_set(ptr_buffer, "localvar_set_account", account->name);
weechat_buffer_set(ptr_buffer, "localvar_set_remote_jid", name);
weechat_buffer_set(ptr_buffer, "input_multiline", "1");
if (buffer_created)
{
(void) weechat_hook_signal_send ("logger_backlog",
WEECHAT_HOOK_SIGNAL_POINTER,
ptr_buffer);
(void) weechat_hook_signal_send("logger_backlog",
WEECHAT_HOOK_SIGNAL_POINTER,
ptr_buffer);
weechat_buffer_set(ptr_buffer, "input_get_unknown_commands", "1");
if (type != CHANNEL_TYPE_PM)
{
@ -271,8 +306,15 @@ struct t_channel *channel__new(struct t_account *account,
new_channel->type = type;
new_channel->id = strdup(id);
new_channel->name = strdup(name);
new_channel->transport = CHANNEL_TRANSPORT_PLAINTEXT;
new_channel->pgp_id = NULL;
new_channel->transport = CHANNEL_TRANSPORT_PLAIN;
new_channel->omemo.enabled = type == CHANNEL_TYPE_PM ? 1 : 0;
new_channel->omemo.devicelist_requests = weechat_hashtable_new(64,
WEECHAT_HASHTABLE_STRING, WEECHAT_HASHTABLE_POINTER, NULL, NULL);
new_channel->omemo.bundle_requests = weechat_hashtable_new(64,
WEECHAT_HASHTABLE_STRING, WEECHAT_HASHTABLE_POINTER, NULL, NULL);
new_channel->pgp.enabled = 1;
new_channel->pgp.id = NULL;
new_channel->otr.enabled = 0;
new_channel->topic.value = NULL;
new_channel->topic.creator = NULL;
@ -788,8 +830,8 @@ void channel__free(struct t_account *account,
free(channel->id);
if (channel->name)
free(channel->name);
if (channel->pgp_id)
free(channel->pgp_id);
if (channel->pgp.id)
free(channel->pgp.id);
if (channel->topic.value)
free(channel->topic.value);
if (channel->topic.creator)
@ -914,10 +956,13 @@ struct t_channel_member *channel__add_member(struct t_account *account,
user->profile.status_text ? " [" : "",
user->profile.status_text ? user->profile.status_text : "",
user->profile.status_text ? "]" : "",
user->profile.pgp_id ? weechat_color("gray") : "",
user->profile.pgp_id ? " with PGP:" : "",
user->profile.pgp_id || user->profile.omemo ? weechat_color("gray") : "",
user->profile.pgp_id || user->profile.omemo ? " with " : "",
user->profile.pgp_id ? "PGP:" : "",
user->profile.pgp_id ? user->profile.pgp_id : "",
user->profile.pgp_id ? weechat_color("reset") : "");
user->profile.omemo && user->profile.pgp_id ? " and " : "",
user->profile.omemo ? "OMEMO" : "",
user->profile.pgp_id || user->profile.omemo ? weechat_color("reset") : "");
return member;
}
@ -983,8 +1028,8 @@ struct t_channel_member *channel__remove_member(struct t_account *account,
return member;
}
void channel__send_message(struct t_account *account, struct t_channel *channel,
const char *to, const char *body)
int channel__send_message(struct t_account *account, struct t_channel *channel,
const char *to, const char *body)
{
channel__send_reads(account, channel);
@ -997,17 +1042,51 @@ void channel__send_message(struct t_account *account, struct t_channel *channel,
xmpp_stanza_set_id(message, id);
xmpp_free(account->context, id);
char *url = strstr(body, "http");
if (channel->pgp_id)
if (account->omemo && channel->omemo.enabled)
{
xmpp_stanza_t *encrypted = omemo__encode(account, to, body);
if (!encrypted)
{
weechat_printf_date_tags(channel->buffer, 0, "notify_none", "%s%s",
weechat_prefix("error"), "OMEMO Error");
channel__set_transport(channel, CHANNEL_TRANSPORT_PLAIN, 1);
xmpp_stanza_release(message);
return WEECHAT_RC_ERROR;
}
xmpp_stanza_add_child(message, encrypted);
xmpp_stanza_release(encrypted);
xmpp_stanza_t *message__encryption = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(message__encryption, "encryption");
xmpp_stanza_set_ns(message__encryption, "urn:xmpp:eme:0");
xmpp_stanza_set_attribute(message__encryption, "namespace",
"eu.siacs.conversations.axolotl");
xmpp_stanza_set_attribute(message__encryption, "name", "OMEMO");
xmpp_stanza_add_child(message, message__encryption);
xmpp_stanza_release(message__encryption);
xmpp_message_set_body(message, OMEMO_ADVICE);
channel__set_transport(channel, CHANNEL_TRANSPORT_OMEMO, 0);
}
else if (channel->pgp.enabled && channel->pgp.id)
{
xmpp_stanza_t *message__x = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(message__x, "x");
xmpp_stanza_set_ns(message__x, "jabber:x:encrypted");
xmpp_stanza_t *message__x__text = xmpp_stanza_new(account->context);
char *ciphertext = pgp__encrypt(channel->buffer, account->pgp, account_pgp_keyid(account), channel->pgp_id, body);
char *ciphertext = pgp__encrypt(channel->buffer, account->pgp, account_pgp_keyid(account), channel->pgp.id, body);
if (ciphertext)
xmpp_stanza_set_text(message__x__text, ciphertext);
else
{
weechat_printf_date_tags(channel->buffer, 0, "notify_none", "%s%s",
weechat_prefix("error"), "PGP Error");
channel__set_transport(channel, CHANNEL_TRANSPORT_PLAIN, 1);
xmpp_stanza_release(message);
return WEECHAT_RC_ERROR;
}
free(ciphertext);
xmpp_stanza_add_child(message__x, message__x__text);
@ -1026,28 +1105,17 @@ void channel__send_message(struct t_account *account, struct t_channel *channel,
xmpp_message_set_body(message, PGP_ADVICE);
if (ciphertext && channel->transport != CHANNEL_TRANSPORT_PGP)
{
channel->transport = CHANNEL_TRANSPORT_PGP;
weechat_printf_date_tags(channel->buffer, 0, NULL, "%s%sTransport: %s",
weechat_prefix("network"), weechat_color("gray"),
channel__transport_name(channel->transport));
}
channel__set_transport(channel, CHANNEL_TRANSPORT_PGP, 0);
}
else
{
xmpp_message_set_body(message, body);
if (channel->transport != CHANNEL_TRANSPORT_PLAINTEXT)
{
channel->transport = CHANNEL_TRANSPORT_PLAINTEXT;
weechat_printf_date_tags(channel->buffer, 0, NULL, "%s%sTransport: %s",
weechat_prefix("network"), weechat_color("gray"),
channel__transport_name(channel->transport));
}
channel__set_transport(channel, CHANNEL_TRANSPORT_PLAIN, 0);
}
if (url)
char *url = strstr(body, "http");
if (url && channel->transport == CHANNEL_TRANSPORT_PLAIN)
{
xmpp_stanza_t *message__x = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(message__x, "x");
@ -1070,11 +1138,28 @@ void channel__send_message(struct t_account *account, struct t_channel *channel,
xmpp_stanza_t *message__active = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(message__active, "active");
xmpp_stanza_set_ns(message__active, "http://jabber./org/protocol/chatstates");
xmpp_stanza_set_ns(message__active, "http://jabber.org/protocol/chatstates");
xmpp_stanza_add_child(message, message__active);
xmpp_stanza_release(message__active);
xmpp_stanza_t *message__request = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(message__request, "request");
xmpp_stanza_set_ns(message__request, "urn:xmpp:receipts");
xmpp_stanza_add_child(message, message__request);
xmpp_stanza_release(message__request);
xmpp_stanza_t *message__markable = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(message__markable, "markable");
xmpp_stanza_set_ns(message__markable, "urn:xmpp:chat-markers:0");
xmpp_stanza_add_child(message, message__markable);
xmpp_stanza_release(message__markable);
xmpp_stanza_t *message__store = xmpp_stanza_new(account->context);
xmpp_stanza_set_name(message__store, "store");
xmpp_stanza_set_ns(message__store, "urn:xmpp:hints");
xmpp_stanza_add_child(message, message__store);
xmpp_stanza_release(message__store);
xmpp_send(account->connection, message);
xmpp_stanza_release(message);
if (channel->type != CHANNEL_TYPE_MUC)
@ -1083,6 +1168,8 @@ void channel__send_message(struct t_account *account, struct t_channel *channel,
"%s\t%s",
user__as_prefix_raw(account, account_jid(account)),
body);
return WEECHAT_RC_OK;
}
void channel__send_reads(struct t_account *account, struct t_channel *channel)

@ -15,9 +15,11 @@ enum t_channel_type
enum t_channel_transport
{
CHANNEL_TRANSPORT_PLAINTEXT,
CHANNEL_TRANSPORT_PLAIN,
CHANNEL_TRANSPORT_OMEMO,
CHANNEL_TRANSPORT_PGP,
CHANNEL_TRANSPORT_OTR,
CHANNEL_TRANSPORT_OX,
};
struct t_channel_typing
@ -63,7 +65,18 @@ struct t_channel
char *id;
char *name;
enum t_channel_transport transport;
char *pgp_id;
struct {
int enabled;
struct t_hashtable *devicelist_requests;
struct t_hashtable *bundle_requests;
} omemo;
struct {
int enabled;
char *id;
} pgp;
struct {
int enabled;
} otr;
struct t_channel_topic topic;
@ -92,6 +105,9 @@ struct t_channel
const char *channel__transport_name(enum t_channel_transport transport);
void channel__set_transport(struct t_channel *channel,
enum t_channel_transport transport, int force);
struct t_account *channel__account(struct t_channel *channel);
struct t_channel *channel__search(struct t_account *account,
@ -179,8 +195,8 @@ struct t_channel_member *channel__remove_member(struct t_account *account,
struct t_channel *channel,
const char *id, const char *reason);
void channel__send_message(struct t_account *account, struct t_channel *channel,
const char *to, const char *body);
int channel__send_message(struct t_account *account, struct t_channel *channel,
const char *to, const char *body);
void channel__send_reads(struct t_account *account, struct t_channel *channel);

@ -4,12 +4,12 @@
#include <strophe.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "plugin.h"
//#include "oauth.h"
#include "account.h"
#include "user.h"
#include "channel.h"
@ -501,7 +501,7 @@ int command__enter(const void *pointer, void *data,
}
else
{
const char *buffer_jid = weechat_buffer_get_string(buffer, "localvar_channel");
const char *buffer_jid = weechat_buffer_get_string(buffer, "localvar_remote_jid");
pres_jid = xmpp_jid_new(
ptr_account->context,
@ -756,6 +756,41 @@ int command__mam(const void *pointer, void *data,
return WEECHAT_RC_OK;
}
int command__omemo(const void *pointer, void *data,
struct t_gui_buffer *buffer, int argc,
char **argv, char **argv_eol)
{
struct t_account *ptr_account = NULL;
struct t_channel *ptr_channel = NULL;
(void) pointer;
(void) data;
(void) argc;
(void) argv;
(void) argv_eol;
buffer__get_account_and_channel(buffer, &ptr_account, &ptr_channel);
if (!ptr_account)
return WEECHAT_RC_ERROR;
if (!ptr_channel)
{
weechat_printf(
ptr_account->buffer,
_("%s%s: \"%s\" command can not be executed on a account buffer"),
weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME, "omemo");
return WEECHAT_RC_OK;
}
ptr_channel->omemo.enabled = 1;
ptr_channel->pgp.enabled = 0;
channel__set_transport(ptr_channel, CHANNEL_TRANSPORT_OMEMO, 0);
return WEECHAT_RC_OK;
}
int command__pgp(const void *pointer, void *data,
struct t_gui_buffer *buffer, int argc,
char **argv, char **argv_eol)
@ -786,13 +821,48 @@ int command__pgp(const void *pointer, void *data,
{
keyid = argv_eol[1];
ptr_channel->pgp_id = strdup(keyid);
ptr_channel->pgp.id = strdup(keyid);
}
else
ptr_channel->omemo.enabled = 0;
ptr_channel->pgp.enabled = 1;
channel__set_transport(ptr_channel, CHANNEL_TRANSPORT_PGP, 0);
return WEECHAT_RC_OK;
}
int command__plain(const void *pointer, void *data,
struct t_gui_buffer *buffer, int argc,
char **argv, char **argv_eol)
{
struct t_account *ptr_account = NULL;
struct t_channel *ptr_channel = NULL;
(void) pointer;
(void) data;
(void) argc;
(void) argv;
(void) argv_eol;
buffer__get_account_and_channel(buffer, &ptr_account, &ptr_channel);
if (!ptr_account)
return WEECHAT_RC_ERROR;
if (!ptr_channel)
{
ptr_channel->pgp_id = NULL;
weechat_printf(
ptr_account->buffer,
_("%s%s: \"%s\" command can not be executed on a account buffer"),
weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME, "plain");
return WEECHAT_RC_OK;
}
ptr_channel->omemo.enabled = 0;
ptr_channel->pgp.enabled = 0;
channel__set_transport(ptr_channel, CHANNEL_TRANSPORT_PLAIN, 0);
return WEECHAT_RC_OK;
}
@ -810,6 +880,9 @@ int command__xml(const void *pointer, void *data,
buffer__get_account_and_channel(buffer, &ptr_account, &ptr_channel);
if (!ptr_account)
return WEECHAT_RC_ERROR;
if (!ptr_account->is_connected)
{
weechat_printf(buffer,
@ -821,7 +894,7 @@ int command__xml(const void *pointer, void *data,
if (argc > 1)
{
stanza = xmpp_stanza_new_from_string(ptr_account->context,
argv_eol[0]);
argv_eol[1]);
if (!stanza)
return WEECHAT_RC_ERROR;
@ -906,15 +979,33 @@ void command__init()
if (!hook)
weechat_printf(NULL, "Failed to setup command /mam");
hook = weechat_hook_command(
"omemo",
N_("set the current buffer to use omemo encryption"),
N_(""),
N_(""),
NULL, &command__omemo, NULL, NULL);
if (!hook)
weechat_printf(NULL, "Failed to setup command /omemo");
hook = weechat_hook_command(
"pgp",
N_("set the target pgp key for the current channel"),
N_("set the current buffer to use pgp encryption (with a given target pgp key)"),
N_("<keyid>"),
N_("keyid: recipient keyid"),
NULL, &command__pgp, NULL, NULL);
if (!hook)
weechat_printf(NULL, "Failed to setup command /pgp");
hook = weechat_hook_command(
"plain",
N_("set the current buffer to use no encryption"),
N_(""),
N_(""),
NULL, &command__plain, NULL, NULL);
if (!hook)
weechat_printf(NULL, "Failed to setup command /plain");
hook = weechat_hook_command(
"xml",
N_("send a raw xml stanza"),

@ -3,6 +3,7 @@
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <strophe.h>

@ -3,6 +3,7 @@
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <strophe.h>

File diff suppressed because it is too large Load Diff

@ -4,6 +4,8 @@
#include <strophe.h>
#include <stdlib.h>
#include <stdint.h>
#include <weechat/weechat-plugin.h>
#include "plugin.h"
#include "account.h"
@ -32,16 +34,20 @@ int input__data(struct t_gui_buffer *buffer, const char *text)
return WEECHAT_RC_OK;
}
channel__send_message(account, channel, channel->id, text);
if (channel__send_message(account, channel, channel->id, text) == WEECHAT_RC_OK)
return WEECHAT_RC_OK;
else
{
return WEECHAT_RC_OK_EAT;
}
}
else
{
weechat_printf(buffer,
_("%s%s: this buffer is not a channel!"),
weechat_prefix("error"), WEECHAT_XMPP_PLUGIN_NAME);
return WEECHAT_RC_OK;
}
return WEECHAT_RC_OK;
}
int input__data_cb(const void *pointer, void *data,

@ -0,0 +1,126 @@
(define-module (libomemo)
#:use-module (gnu packages)
#:use-module (gnu packages admin)
#:use-module (gnu packages aidc)
#:use-module (gnu packages aspell)
#:use-module (gnu packages audio)
#:use-module (gnu packages autotools)
#:use-module (gnu packages avahi)
#:use-module (gnu packages base)
#:use-module (gnu packages bash)
#:use-module (gnu packages bison)
#:use-module (gnu packages boost)
#:use-module (gnu packages check)
#:use-module (gnu packages compression)
#:use-module (gnu packages cpp)
#:use-module (gnu packages crypto)
#:use-module (gnu packages curl)
#:use-module (gnu packages cyrus-sasl)
#:use-module (gnu packages databases)
#:use-module (gnu packages docbook)
#:use-module (gnu packages documentation)
#:use-module (gnu packages enchant)
#:use-module (gnu packages fontutils)
#:use-module (gnu packages freedesktop)
#:use-module (gnu packages gettext)
#:use-module (gnu packages glib)
#:use-module (gnu packages gnome)
#:use-module (gnu packages gnupg)
#:use-module (gnu packages golang)
#:use-module (gnu packages gperf)
#:use-module (gnu packages graphviz)
#:use-module (gnu packages gstreamer)
#:use-module (gnu packages gtk)
#:use-module (gnu packages guile)
#:use-module (gnu packages icu4c)
#:use-module (gnu packages image)
#:use-module (gnu packages kde)
#:use-module (gnu packages kerberos)
#:use-module (gnu packages less)
#:use-module (gnu packages libcanberra)
#:use-module (gnu packages libffi)
#:use-module (gnu packages libidn)
#:use-module (gnu packages libreoffice)
#:use-module (gnu packages linux)
#:use-module (gnu packages logging)
#:use-module (gnu packages lua)
#:use-module (gnu packages man)
#:use-module (gnu packages markup)
#:use-module (gnu packages matrix)
#:use-module (gnu packages mono)
#:use-module (gnu packages mpd)
#:use-module (gnu packages ncurses)
#:use-module (gnu packages networking)
#:use-module (gnu packages nss)
#:use-module (gnu packages pcre)
#:use-module (gnu packages perl)
#:use-module (gnu packages photo)
#:use-module (gnu packages php)
#:use-module (gnu packages pkg-config)
#:use-module (gnu packages protobuf)
#:use-module (gnu packages python)
#:use-module (gnu packages python-check)
#:use-module (gnu packages python-crypto)
#:use-module (gnu packages python-web)
#:use-module (gnu packages python-xyz)
#:use-module (gnu packages qt)
#:use-module (gnu packages readline)
#:use-module (gnu packages ruby)
#:use-module (gnu packages sphinx)
#:use-module (gnu packages sqlite)
#:use-module (gnu packages tcl)
#:use-module (gnu packages texinfo)
#:use-module (gnu packages textutils)
#:use-module (gnu packages tls)
#:use-module (gnu packages video)
#:use-module (gnu packages web)
#:use-module (gnu packages xdisorg)
#:use-module (gnu packages xiph)
#:use-module (gnu packages xml)
#:use-module (gnu packages xorg)
#:use-module (guix build-system cmake)
#:use-module (guix build-system go)
#:use-module (guix build-system glib-or-gtk)
#:use-module (guix build-system gnu)
#:use-module (guix build-system meson)
#:use-module (guix build-system perl)
#:use-module (guix build-system python)
#:use-module (guix build-system qt)
#:use-module (guix build-system trivial)
#:use-module (guix download)
#:use-module (guix git-download)
#:use-module (guix hg-download)
#:use-module ((guix licenses) #:prefix license:)
#:use-module (guix packages)
#:use-module (guix utils))
(define-public libomemo-c
(package
(name "libomemo-c")
(version "2.3.3")
(source (origin
(method git-fetch)
(uri (git-reference
(url "https://github.com/dino/libomemo-c")
(commit "06184660790daa42433e616fa3dee730717d1c1b")))
(file-name (git-file-name name version))
(sha256
(base32
"1wa85r1b54myabsbmbqlq9jz174mmvd02b8zy1j4j0kml0anp6nx"))))
(arguments
`(;; Required for proper linking and for tests to run.
#:configure-flags '("-DBUILD_SHARED_LIBS=on" "-DBUILD_TESTING=1")))
(build-system cmake-build-system)
(inputs `( ;; Required for tests:
("check" ,check)
("openssl" ,openssl)))
(native-inputs `(("pkg-config" ,pkg-config)))
(home-page "https://github.com/WhisperSystems/libsignal-protocol-c")
(synopsis "Implementation of a ratcheting forward secrecy protocol")
(description "libsignal-protocol-c is an implementation of a ratcheting
forward secrecy protocol that works in synchronous and asynchronous
messaging environments. It can be used with messaging software to provide
end-to-end encryption.")
(license license:gpl3+)))
libomemo-c

@ -9,7 +9,7 @@ FIND=find
INCLUDES=-Ilibstrophe \
$(shell xml2-config --cflags) \
$(shell pkg-config --cflags librnp-0) \
$(shell pkg-config --cflags libsignal-protocol-c)
$(shell pkg-config --cflags libomemo-c)
CFLAGS+=$(DBGCFLAGS) \
-fno-omit-frame-pointer -fPIC \
-std=gnu99 -gdwarf-4 \
@ -32,7 +32,7 @@ LDLIBS=-lstrophe \
-lpthread \
$(shell xml2-config --libs) \
$(shell pkg-config --libs librnp-0) \
$(shell pkg-config --libs libsignal-protocol-c) \
$(shell pkg-config --libs libomemo-c) \
-lgcrypt \
-llmdb

@ -4,6 +4,7 @@
#include <strophe.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <regex.h>

2002
omemo.c

File diff suppressed because it is too large Load Diff

@ -13,20 +13,44 @@ struct t_omemo
struct signal_protocol_store_context *store_context;
struct t_omemo_db *db;
char *db_path;
struct ratchet_identity_key_pair *identity;
uint32_t device_id;
};
struct t_omemo_bundle_req
{
char *id;
char *jid;
char *device;
char *message_text;
};
struct t_omemo_devicelist_req
{
char *id;
struct t_omemo_bundle_req bundle_req;
};
xmpp_stanza_t *omemo__get_bundle(xmpp_ctx_t *context, char *from, char *to,
struct t_omemo *omemo);
void omemo__init(struct t_gui_buffer *buffer, struct t_omemo **omemo,
const char *account_name);
void omemo__serialize(struct t_omemo *omemo, char **device,
char **identity, size_t *identity_len);
void omemo__handle_devicelist(struct t_omemo *omemo, const char *jid,
xmpp_stanza_t *items);
void omemo__handle_bundle(struct t_omemo *omemo, const char *jid,
uint32_t device_id, xmpp_stanza_t *items);
char *omemo__decode(struct t_account *account, const char *jid,
xmpp_stanza_t *encrypted);
void omemo__deserialize(struct t_omemo *omemo, const char *device,
const char *identity, size_t identity_len);
xmpp_stanza_t *omemo__encode(struct t_account *account, const char *jid,
const char *unencrypted);
void omemo__free(struct t_omemo *omemo);

@ -5,15 +5,11 @@
#ifndef _WEECHAT_XMPP_PLUGIN_H_
#define _WEECHAT_XMPP_PLUGIN_H_
#ifndef __cplusplus
#include <weechat/weechat-plugin.h>
#define weechat_plugin weechat_xmpp_plugin()
#define WEECHAT_XMPP_PLUGIN_NAME weechat_xmpp_plugin_name()
#define WEECHAT_XMPP_PLUGIN_VERSION weechat_xmpp_plugin_version()
#endif//__cplusplus
#define weechat_plugin weechat_xmpp_plugin
#define WEECHAT_XMPP_PLUGIN_NAME "xmpp"
#define WEECHAT_XMPP_PLUGIN_VERSION "0.1.1"
#define TIMER_INTERVAL_SEC 0.01
struct t_weechat_plugin *weechat_xmpp_plugin();
const char *weechat_xmpp_plugin_name();
const char *weechat_xmpp_plugin_version();
extern struct t_weechat_plugin *weechat_xmpp_plugin;
#endif /*WEECHAT_XMPP_PLUGIN_H*/

@ -3,6 +3,7 @@
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <strophe.h>
@ -140,7 +141,7 @@ void user__nicklist_remove(struct t_account *account,
ptr_buffer = channel ? channel->buffer : account->buffer;
if ((ptr_nick = weechat_nicklist_search_nick(ptr_buffer, NULL, name)))
if (name && (ptr_nick = weechat_nicklist_search_nick(ptr_buffer, NULL, name)))
weechat_nicklist_remove_nick(ptr_buffer, ptr_nick);
}
@ -190,6 +191,7 @@ struct t_user *user__new(struct t_account *account,
new_user->profile.email = NULL;
new_user->profile.role = NULL;
new_user->profile.pgp_id = NULL;
new_user->profile.omemo = 0;
new_user->updated = 0;
new_user->is_away = 0;

@ -16,6 +16,7 @@ struct t_user_profile
char *role;
char *affiliation;
char *pgp_id;
int omemo;
};
struct t_user

@ -98,9 +98,36 @@ xmpp_stanza_t *stanza__iq_pubsub_items(xmpp_ctx_t *context, xmpp_stanza_t *base,
if (node)
{
xmpp_stanza_set_attribute(parent, "node", node);
}
return parent;
}
xmpp_stanza_t *stanza__iq_pubsub_subscribe(xmpp_ctx_t *context, xmpp_stanza_t *base,
struct t_string *node, struct t_string *jid)
{
xmpp_stanza_t *parent = base;
if (!parent)
{
parent = xmpp_stanza_new(context);
xmpp_stanza_set_name(parent, "subscribe");
}
if (node)
{
xmpp_stanza_set_attribute(parent, "node", node->value);
node->finalize(node);
free(node);
}
if (jid)
{
xmpp_stanza_set_attribute(parent, "jid", jid->value);
jid->finalize(jid);
free(jid);
}
return parent;
}
@ -193,7 +220,7 @@ xmpp_stanza_t *stanza__iq_pubsub_publish_item_list(xmpp_ctx_t *context, xmpp_sta
}
xmpp_stanza_t *stanza__iq_pubsub_publish_item_list_device(xmpp_ctx_t *context, xmpp_stanza_t *base,
struct t_string *id)
struct t_string *id, struct t_string *label)
{
xmpp_stanza_t *parent = base;
@ -210,6 +237,13 @@ xmpp_stanza_t *stanza__iq_pubsub_publish_item_list_device(xmpp_ctx_t *context, x
free(id);
}
if (label)
{
xmpp_stanza_set_attribute(parent, "label", label->value);
label->finalize(label);
free(label);
}
return parent;
}
@ -401,3 +435,31 @@ xmpp_stanza_t *stanza__iq_ping(xmpp_ctx_t *context, xmpp_stanza_t *base,
return parent;
}
xmpp_stanza_t *stanza__iq_query(xmpp_ctx_t *context, xmpp_stanza_t *base,
struct t_string *ns, struct t_string *node)
{
xmpp_stanza_t *parent = base;
if (!parent)
{
parent = xmpp_stanza_new(context);
xmpp_stanza_set_name(parent, "query");
}
if (ns)
{
xmpp_stanza_set_ns(parent, ns->value);
ns->finalize(ns);
free(ns);
}
if (node)
{
xmpp_stanza_set_attribute(parent, "node", node->value);
node->finalize(node);
free(node);
}
return parent;
}

@ -49,6 +49,22 @@ static inline struct t_string *with_xmpp_free(char *value, xmpp_ctx_t *pointer)
return string;
}
static inline void stanza__set_text(xmpp_ctx_t *context, xmpp_stanza_t *parent,
struct t_string *value)
{
xmpp_stanza_t *text = xmpp_stanza_new(context);
if (value)
{
xmpp_stanza_set_text(text, value->value);
xmpp_stanza_add_child(parent, text);
value->finalize(value);
free(value);
}
xmpp_stanza_release(text);
}
xmpp_stanza_t *stanza__presence(xmpp_ctx_t *context, xmpp_stanza_t *base,
xmpp_stanza_t **children, const char *ns,
char *from, char *to, const char *type);
@ -62,6 +78,9 @@ xmpp_stanza_t *stanza__iq_pubsub(xmpp_ctx_t *context, xmpp_stanza_t *base,
xmpp_stanza_t *stanza__iq_pubsub_items(xmpp_ctx_t *context, xmpp_stanza_t *base, char *node);
xmpp_stanza_t *stanza__iq_pubsub_subscribe(xmpp_ctx_t *context, xmpp_stanza_t *base,
struct t_string *node, struct t_string *jid);
xmpp_stanza_t *stanza__iq_pubsub_publish(xmpp_ctx_t *context, xmpp_stanza_t *base,
xmpp_stanza_t **children, struct t_string *node);
@ -72,7 +91,7 @@ xmpp_stanza_t *stanza__iq_pubsub_publish_item_list(xmpp_ctx_t *context, xmpp_sta
xmpp_stanza_t **children, struct t_string *ns);
xmpp_stanza_t *stanza__iq_pubsub_publish_item_list_device(xmpp_ctx_t *context, xmpp_stanza_t *base,
struct t_string *id);
struct t_string *id, struct t_string *label);
xmpp_stanza_t *stanza__iq_pubsub_publish_item_bundle(xmpp_ctx_t *context, xmpp_stanza_t *base,
xmpp_stanza_t **children, struct t_string *ns);
@ -98,4 +117,7 @@ xmpp_stanza_t *stanza__iq_enable(xmpp_ctx_t *context, xmpp_stanza_t *base,
xmpp_stanza_t *stanza__iq_ping(xmpp_ctx_t *context, xmpp_stanza_t *base,
struct t_string *ns);
xmpp_stanza_t *stanza__iq_query(xmpp_ctx_t *context, xmpp_stanza_t *base,
struct t_string *ns, struct t_string *node);
#endif /*WEECHAT_XMPP_STANZA_H*/

Loading…
Cancel
Save