Sending messages to unknown users in XMPP MultiUserChat with OMEMO encryption - ejabberd
I'm trying to build a MUC platform with OMEMO encryption to be used on an Android app. I'm using Ejabberd (v17.11) and Smack library (v4.2.1).
MUC rooms are persistent and they allow_subscription for Muc/Sub support, for offline messages.
When a client starts a new room as 'owner' and adds 'member's from his roster; all the clients join the room and everything seem fine.
The owner can send messages to the group and it is delivered to every member.
But when a group member tries to send a message, if he doesn't 'know' all the members of the group (if they are not in his roster) he cannot send message!
I found out that, when sending OMEMO message to the group, it is necessary to encrypt the message separately for every member and this necessitates getting every members' devicelist!
On this step:
mOmemoManager.encrypt(muc, msgBody);
It tries to encrypt for all recipients but fetching an unknown user's device list causes crash.
SENT:
<iq to='unknownuser#server.com' id='141' type='get'><query xmlns='http://jabber.org/protocol/disco#info' node='eu.siacs.conversations.axolotl.devicelist'></query></iq>
RECV:
<iq xml:lang='en' to='myuser#server.com/mobile' from='unknownuser#server.com' type='error' id='141'><query node='eu.siacs.conversations.axolotl.devicelist' xmlns='http://jabber.org/protocol/disco#info'/><error code='407' type='auth'><subscription-required xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/><text xml:lang='en' xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'>Not subscribed</text></error></iq>
Smack's error:
Could not fetch device list of unknownuser#server.com: .....
XMPPError: subscription-required - auth
So, how I can solve this?
In chat groups every user don't have to meet each other. Should I add everyone to everyone's roster when they come together on a group?
Or is this something about room affiliations or roles?
Or something about Ejabberd configuration?
[{title,<<"groupName">>},
{allow_query_users,true},
{allow_private_messages,true},
{allow_private_messages_from_visitors,anyone},
{allow_visitor_status,true},
{allow_visitor_nickchange,true},
{public,false},
{public_list,false},
{persistent,true},
{moderated,true},
{members_by_default,true},
{members_only,true},
{allow_user_invites,true},
{anonymous,false},
{logging,false},
{allow_voice_requests,true},
{allow_subscription,true},
{mam,true},
{presence_broadcast,[moderator,participant,visitor]},
{voice_request_min_interval,1800},
{vcard,<<>>},
{captcha_whitelist,[]},
{affiliations,[{{<<"user1">>,<<"server.com">>,<<>>},{member,<<>>}}, {{<<"user2">>,<<"server.com">>,<<>>},{owner,<<>>}}, {{<<"user3">>,<<"server.com">>,<<>>},{member,<<>>}}]},
{subject,[]},
{subject_author,<<>>}]
OMEMO requires the sender to be able to read the recipients OMEMO pubsub node. This is necessary to fetch the recipients preKey bundle to build a session.
Modern implementations configure the OMEMO pubsub node to be public - there is also an ejabberd config to force this for legacy clients.
Most client implementations of OMEMO therefore restrict the encryption feature to be available in private group chats only. In this scenario all contacts are in each others rosters and have access to each others OMEMO nodes. Encrypting publicly available group chats doesn't make sense anyways as an attacker could simply join the chat in order to read messages.
If you want to configure your OMEMO pubsub nodes to be public from within your client, take a look at how smack-openpgp does change to access model.
Related
Openshift AMQ6 - message order - queue
I use AMQ 6 (ActiveMQ) on OpenShift, and I use a queue with re-delivery with exponentialBackoff (set in connection query params). When I have one consumer and two messages and the first message gets processed by my single consumer and does NOT get an ACK... Will the broker deliver the 2nd message to the single consumer? Or will the broker wait for the re-delivery to preserve message order. This documentation states: ...Typically a consumer handles redelivery so that it can maintain message order while a message appears as inflight on the broker. ... I don't want to have my consumer wait for re-delivery. It should consume other messages. Can I do this without multiple consumers? If so, how? Note: In my connection query params I don't have the ActiveMQ exclusive consumer set. I have read the Connection Configuration URI docs, but jms.nonBlockingRedelivery isn't mentioned there. Can the resource adapter use it by query param?
If you set jms.nonBlockingRedelivery=true on your client's connection URL then messages will be delivered to your consumer while others are in the process of redelivery. This is false by default.
Is it possible for Multiple Consumers to consume same message on a Pulsar Topic?
Let's say for that one has a Pulsar Producer for a persistent topic topic1 (namespace and tenant are not relevant for the question). And let's say we have multiple consumers for the same topic (topic1) with different subscription names. Is it possible to configure the consumers to receive same message? So for example if message msg1 is sent to the topic both consumer1 and consumer2 receive this message? Both consumers and producer are written in Java but programming language is not important. Clarification The current behavior observed with multiple subscriptions on the same topic with multiple subscriptions is that each of the subscribers do not receive all messages that have been published to the topic. I need to receive all messages from the topic.
Yes, you just need to use multiple subscriptions on the topic. I wrote a blog post on this exact topic: "Subscriptions: Multiple Groups of Consumers on a Pulsar Topic".
Yes. It is possible for multiple consumers to receive the same copy of messages from a topic. Subscription determines how messages are delivered to consumers. What you need is each consumer has own Exclusive subscription. Here is the code example in Java. String topicName = "your-tenant/namespace/topic1" Consumer consumer1 = client.newConsumer() .topic(topicName) .subscriptionName("my-subscription1") .subscriptionInitialPosition(SubscriptionInitialPosition.Earliest) .subscriptionType(SubscriptionType.Exclusive) .subscribe(); // create another consumer Consumer consumer2 = client.newConsumer() .topic(topicName) .subscriptionName("my-subscription2") .subscriptionInitialPosition(SubscriptionInitialPosition.Earliest) .subscriptionType(SubscriptionType.Exclusive) .subscribe(); // two consumers receive messages in alternate from the same topic while (true) { Message msgFromConsumer1 = consumer1.receive(); Message msgFromConsumer2 = consumer2.receive(); }
Ejabberd MucSub issue with room leave/exit
we are working on an Instant Messaging app based on XMPP handling members-only persistent groups using XEP-0045 and MucSub. We have some issues with room occupancy and we didn't find a way to let users abandon a room permanently: we tried several approaches and none of them led to successful behavior. The behavior we are looking for is very similar to WhatsApp and other similar mobile apps. The first thing we had to think about is: which users we consider as participants? The parameters we can use are: Affiliation Role Subscription To consider it as a working solution, we need that: All the standard and obvious features of group conversations Members can join and leave the group If a member leaves a group, he cannot rejoin without invitation Members can see the list of members and their privileges Membership should not be affected by the member’s connection status The member list and privileges must be persistent across server reboots Our test environment: Ejabberd 19.09 with mucsub enabled PostgreSQL DB We explored the following approaches: Approach 1: We can use affiliation to determine if a user is a participant, and consider him as a non-participant when the affiliation is none, outcast or not affiliated. Who we consider as a participant: Affiliation: member (or owner or admin) Role: any Subscription: any How to abandon a room: a. Sending a presence unavailable <presence to='roomX#conference.x.com/test2' from='test2#x.com' type='unavailable'> <status>leave</status> </presence> b. changing your own affiliation <iq from='test2#x.com/app' id='1234' to='roomX#conference.x.com' type='set'> <query xmlns='http://jabber.org/protocol/muc#admin'> <item affiliation='none' jid='test2#x.com'/> </query> </iq> New attributes of ex participants: Affiliation: none (or outcast if the user has been banned) Role: any Subscription: any (more probably the user will be unsubscribed, but this parameter is not checked to determine participants) Issues: Sending a presence unavailable is not affecting the affiliation. (It’s not reflecting anywhere in the DB) Sending a presence unavailable sometimes does not obtain a response from the server (related issue opened here: Ejabberd MucSub: When a member sends a presence unavailable, the service does not respond) Setting an affiliation for yourself does not work (as per specs: only admins can change affiliations) Approach 2: We can use subscriptions status to determine if a user is a participant, and consider him as a non-participant when the he unsubscribes. Who we consider as a participant: Affiliation: member (or owner or admin) Role: any Subscription: subscribed to all kind of events How to abandon a room: The user will abandon a room by unsubscribing. <iq from='test2#x.com' to='roomX#conference.x.com' type='set' id='12345'> <unsubscribe xmlns='urn:xmpp:mucsub:0' /> </iq> New attributes of ex participants: Affiliation: member (or owner or admin) Role: any Subscription: not subscribed Issues: The ex participant can rejoin subscribe again without invitation, and following this approach will lead that he will be considered as a participant again (with no invitation)
Last activity for all users on ejabberd
We have ejabberd installed on our server. I am using asmack 4.0.7 to interact with the ejabberd server. I wish to know last activity (XEP-0012) of all the users. I have 10 user accounts on our server. viz john#myserver.in, mike#myserver.in, jerry#myserver.in etc. The behaviour of ejabberd is that to find last activity of a user, that user has to log in. I mean to check last activity of john#myserver.in, he will have to log in. If i log in as john#myserver.in, then i successfully get last activity for john#myserver.in. With john logged in, if i retrieve last activities for mike#myserver.in, jerry#myserver.in or any other user, i get service-unavailable response for ejabberd server. <iq from='mike#myserver.in/Smack' to='john#myserver.in/Smack' type='error' id='uHn-5'> <query xmlns='jabber:iq:last'/><error code='503' type='cancel'> <service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/> </error></iq> My requirement is that to retrieve last activity without making logins for all users. Is that possible ? Please let me know if any other information is required for this query. thanks
If you want last activity of all users, this is probably for backend tasks. You should not do that using the XMPP client protocol, but with backend module (ejabberd plugin or read from last database).
Spring3, Security3, Hibernate, MYSQL - How to install user tracking into database
First Project: Spring3, Security3, Hibernate, MYSQL - How to install user tracking into database I am working on my first project with Spring3, Security3, Hibernate, MYSQL. I have the system working great I use Spring3 and Security3 goign to MySQL for the login and using Spring3 MVC, Hibernate and MYSQL for system data. I have a number of questions. Once I login does Spring Security save the user object somewhere that I can have Hibrernate access it. I want Hibernate to put the user name or role into each insert to the database so as I do my searches the system knows to only show data for that user and only that user? this somes like it should be easy. Spring should be saving the user somewhere the hibernate can access. please help me out
Once the user is authenticated, you can access the user's authentication session details: Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); SecurityContext will allow you to grab the Authentication object, and from that you can retrieve the principal (an object representing the authenticated user), roles, etc. You could inspect this information and determine what data should be stored/displayed for each user. If you can add a request filter or interceptor (the vocabulary may vary between frameworks), you could probably make these security checks abstract/generic enough to be applied across your entire web app (instead of adding a few lines of code to every resource method you're attempting to secure). Either way, SecurityContext should get you closer to what you want.