CCPM - Client to Client Private Message

While digging through old logs and code, I found an extension that had been dubbed CCPM.

CCPM - Client to Client Private Message

Signalling support for CCPM means you support C-type MSG. Signal CCPM in SUP and in the INF’s SU field.

I don’t know if it’s something that really needs to be signalled or whatnot…

This should just work out of the box. C type mesages and MSG are both part of the base specification. Even if an old client doesnt know what a CMSG is, it should respect the rules of ADC regarding valid but unknown messages.

Implementing it however is more difficult. What happens if a client wants to send a CMSG while a CSND is in progress? It cant just insert the CMSG into the stream as that would cause corruption on the recieving side. However, this then leaves a potentially huge lag for the text while the transfer is finishing (which can be rather a long time for large segments on a slow connection)

One solution to this would be to have an extra TCP stream between the two clients but this screams messy to me.

Also, how do you expose this to the user? Give them a choice of Hub Private Message or Client Private Message and most of them will have no clue, or care what the difference is.

Overall, what are the benifits of this? Slightly reduced bandwidth on the hub (but dwarfed in comparison to things like BMSG). Added privacy for the two clients in question? I dont think that these are good enough reasons to justify the associated problems with this (despite the fact I do like the idea in principle)

~Andrew

Greater privacy in private messages would be a nice thing. Most users are a little unnerved when they learn the hub owner can read their private conversations if they wish to.

I’d assume they way most peer-to-peer messaging protocols handle file-transfers is to open an additional port for the transfer, but it would be nice to avoid this.

Due to the presence of C-C file transfers, I don’t think CMSG is a viable option, and thus p2p messaging won’t work in ADC.

An alternative approach would be the use of public-key cryptography for the text parameter of the MSG command. Clients could publish their public key in their INF broadcast (base32 encoded?), and support for the extension in INF SU. If sending a private message to a client supporting the feature, then it MUST encrypt the the text parameter (note: potential complications here with PM being used to support chat channels). A receiving client would then decrypt the message.

When ADCS is in use, this will effectively double-encrypt a private message in the eyes of everyone except the hub, but the entire point is to hide the message contents from the hub, since ADCS does not do this. Given the relatively small size of PM messages, the added encryption time and message link shouldn’t provide too much bloat. Such a feature will have to specify a key algorithm, such as RSA.

This won’t work.

The hub can still replace the public keys beforehand and break like this the encryption.

My Recommendation would be using SUDP for sending encrypted PMs over UDP.
Though every message would have to be confirmed to mitigate possibility for Addressspoofing.

i.e. just short example how this could look like

  1. A->B Send encrypted PM
  2. B->A Created and send challenge for PM
  3. A->B answer challenge
  4. B->A ACK

    \

Alternative using the hub:

  1. A->B Send encrypted PM over UDP
  2. A->B Send hash of message over the hub as ACK
  3. B->A confirm message over hub / Alternative send NACK (STA) if message is missing

implemented this in DC++ (as of rev 3342).

i went with the additional TCP stream, which was the most straight-forward way. why is it considered “messy”? the confusion here may be stemming from the fact that multiple TCP connections to a same inbound port are perfectly possible, as long as the outbound port differs (TCP connections are identified by their IP+port pairs so changing the port on one end only is enough to create a new, separate stream).

that then sweeps away most of the discussion about custom crypto, SUDP etc.

protocol details:

  • the “PM” param is not sent in C-type MSG messages (the peer is already known from the connection, and group-SIDs don’t make sense here).
  • the connection token sent in CTM & co is the string “PM”, in order for implementations to be able to distinguish PM connections from other types of transfer early on. this could be loosened to “should start with ‘PM’” if people want it to be more flexible.
  • signalling support for the CCPM extension in the INF SU is necessary; otherwise, DC++ and derivatives assume PM connections are uploads and just sit there waiting for a GET. it is also useful in SUP should hubs try to play smart and remove it from INF SU.
  • (maybe just a recommendation?) the CCPM extension doesn’t make sense with unencrypted connections (avoid the hub spying but keep open to the rest of the world…).

waiting for opinions - the above impl has not been released yet so i’m open to modifications.

here is how i did it - carefully avoided the terms “client” and “peer-to-peer”:

http://i.imgur.com/4CN2NiZ.png
http://i.imgur.com/2IefsGC.png
http://i.imgur.com/hi29iy2.png

and here are the corresponding help contents:

Communication channel

Private messages are usually sent through a hub, the name of which is indicated here. This part can also show “Direct encrypted channel” when private messages flow directly between you and the user (no hub involved in that case).
Click this part to select the desired communication channel.

Information on direct encrypted private message channels

Hubs can spy upon any private message they may be involved in routing from one user to another. In order to avoid such spying, one can initiate a peer-to-peer connection with the desired user and use it to send private messages.
The hub used to establish the initial peer-to-peer connection must be an ADC hub and the connection between the user and the hub must be encrypted (“adcs” scheme instead of “adc”). Additionally, both users must support the “CCPM” ADC extension.
Ways to attempt a direct encrypted channel:
•Click the “Communication channel” part of the status bar and select the “Start a direct encrypted channel” menu command.
•Send the “/direct” chat command.
•Send the “/encrypted” chat command.
Ways to disconnect the direct encrypted channel: •Click the “Communication channel” part of the status bar and select the “Disconnect the direct encrypted channel” menu command.
•Close the private message window.
•Disconnect the transfer from the Transfers list.

AirDC++ uses tokens as transfer identifiers instead of using the user/type combination so it’s necessary that all tokens are unique. While I see the benefits in your implementation, having an extension that adds additional special meanings for the token format seems a bit ugly. Couldn’t an additional (C-C INF) flag be used for this? The current implementation seems a bit problematic as it doesn’t handle timeouts or other failures during the connecting in any way so it might make sense to make the initiation phase traceable.

Hmm… sounds like a perfect extension for spam bots to send malicious links to all users without letting the hub know anything about it. This is far bigger (security) issue in my opinion than the fact that hub owners might be reading your private message. The best solution to fight against spam in large public hubs is to prevent unregistered users from sending web links/private messages. If hubs have no control over to who the clients are able to send private messages, the only way to avoid spamming is to prevent unregistered from initiating transfer connections and I’m not sure why would anyone want this to happen.

Even though there aren’t currently large public hubs using ADC, I still wouldn’t create unnecessary restrictions for doing that. The best way for those hubs would be to remove CCPM from INFs that are sent to unregistered users. It would also be required for all clients to disallow initiating a CCPM channel with users that are missing the INF support. Actually… having a specific token format would allow the hubs to filter out all PM connection requests already.

identifying PM connections early on (by the time CINF has been received, at least) is very useful for various reasons:

  • a proper message can be shown to the user in the connection list.
  • the implementation can take decisions as to which bits of code are going to manage the connection.

the “PM” token trick was the most simple; we can go with any solution as long as the ability to detect PM connections remains. how about “PM1” in CINF? alternatively, the convention “the token should start with ‘PM’” allows variation and hubs can even spot the connections. my preference is for the latter solution.

regarding spam concerns:

  • it depends on the implementation. for example, the client could throw all these PMs in an innocuous place so as not to bother the user until he actually opens them (ie they would have “lower priority”).
  • i am hoping this may pave the way for client-side filtering rules rather than having to rely on hubs for that. with DC++, this is trivial with the plugin system.
  • as you mentioned, “PM” tokens may alleviate that, so that’s a bonus point for my preferred solution. :slight_smile:
  • i have no opinion on the presence of CCPM in CSUP. you make a good point regarding hub-side filtering.

That’s what I was thinking too.


Possibly the SUP parameter could be added for possible future use in case problems arise… or maybe it could be added only then. It could also be used for confirmation purposes to see if the hub is filtering the supports instead of actually utilizing it in other ways. Having a secondary parameter only because of fighting against hub owners feels a bit rude. Most users in public hubs won’t probably probably prefer encryption over filtering spam if they aren’t sending any sensitive information. How many normal users would drop the spam filtering from their email service just to prevent the email provider from scanning their texts? :stuck_out_tongue:

see http://bazaar.launchpad.net/~dcplusplus-team/dcplusplus/trunk/revision/3345 & http://bazaar.launchpad.net/~dcplusplus-team/dcplusplus/trunk/revision/3346 - now sending PM1 in CINF, and moved back to dynamic tokens (also, they are now actually taken into account :slight_smile:).

DC++ 0.830 has been released with this extension. example handshake:

119 [In] 11.22.33.44:2000 (Hub <adcs://example.com:2000>): DNAT GYAA DD32 ADCS/0.10 1480 2168510784
120 [Out] 11.22.33.44:2000 (Hub <adcs://example.com:2000>): DRNT DD32 GYAA ADCS/0.10 51971 2168510784
121 [Out] 11.22.33.44:2000 (User [unknown]): CSUP ADBAS0 ADBASE ADTIGR ADBZIP ADZLIG
122 [Out] 11.22.33.44:2000 (User [unknown]): CSTA 000  RFadcs://example.com:2000
123 [In] 11.22.33.44:2000 (User [unknown]): CSUP ADBAS0 ADBASE ADTIGR ADBZIP ADZLIG
124 [Out] 11.22.33.44:2000 (User [unknown]): CINF IDABCDA4ST5DRMUX6AVWPWNWD2SBRT5PXQJAFABCD TO2168510784 PM1
125 [In] 11.22.33.44:2000 (User [unknown]): CSTA 000  RFadcs://example.com:2000
126 [In] 11.22.33.44:2000 (User [unknown]): CINF ID12343CGICZL4ZYOGHWXX7S557PQIJTMUTLE1234 TO2168510784

Below is a write-up (or at least what I think I’ve gathered) of the discussions here and on the hub.

=== CCPM - Client to client private messages
This extension adds support for private messages in a client to client context. The extension adds support for the C-type for MSG, and uses a field in the (C-type) INF to signal that the connection should be used for private messages.

Implementations shall signal “CCPM” in the SU field of their (H-type) INF.

Implementations should differentiate between a C-C transfer connection and a C-C private message connection, so as to allow transfers and chat at the same time. The initiating client should issue a secondary CTM/RCM sequence to deal with the other connection. Implementations shall disallow GET (and other file transfer commands) in the private message connection.

Implementations may choose if private messages shall be allowed in unencrypted connections. Implementations may choose for which users that are allowed to send them private messages, so as to avoid spam (e.g., only trusted users, hub operators etc may initiate a C-C private message).

Removing the INF field ‘PM’ shall cause a disconnect of the connection (with an appropriate STA).

Implementations may decide what to do when the hub connection is lost during a private message connection.

Implementations should adhere to any requirements the DI field in the QUI command in BASE poses regarding non-file transfer connections. Beyond that is up to implementations.

[options=“autowidth”]
|=====
|PM |Field in the CINF to denote that the connection should be used for private messages. The field’s value should be ‘1’.
|=====

Regarding the DI field, it’s possible that there is a requirement to change it from

Any client that has this flag in the QUI message should have its transfers terminated by other clients connected to it, as it is unwanted in the system

to

Any client that has this flag in the QUI message should have its file transfer connections terminated by other clients connected to it, as it is unwanted in the system. Extensions may further limit non-file transfer connections.

Looking good; here are a few points I can spot:

  • “Implementations shall signal “CCPM” in the SU field of their (H-type) INF.” > It’s usually a BINF so I would change “H-type” to “hub-targeted”.
  • Add a note about the possibility of reusing a port on one end and only changing it on the other, as that isn’t obvious as evidenced by the first posts in this thread.
  • Add a note about the impossibility in the above port-being-reused case when going through NAT-T to then have a C-C PM and transfers at the same time.
  • “Implementations may choose if private messages shall be allowed in unencrypted connections.” sounds too sweet; I would give it some weight by strongly advising to encrypyt C-C PMs.
  • The “PM” parameter of the “MSG” command is not required in C-C PMs.

There are a few novelties here regarding error handling that are probably not all implemented in DC++ - to be checked…

Changes, per above points and discussion.

=== CCPM - Client to client private messages
This extension adds support for private messages in a client to client context. The extension adds support for the C-type for MSG, and uses a field in the (C-type) INF to signal that the connection should be used for private messages.

Implementations shall signal “CCPM” in the SU field of their > hub-targeted INF.

Implementations should differentiate between a C-C transfer connection and a C-C private message connection, so as to allow transfers and chat at the same time. The initiating client should issue a secondary CTM/RCM sequence to deal with the other connection. Implementations shall disallow GET (and other file transfer commands) in the private message connection.

Implementations are strongly discouraged but may choose to allow private messages in unencrypted connections.

Implementations may choose for which users that are allowed to send them private messages, so as to avoid spam (e.g., only trusted users, hub operators etc may initiate a C-C private message).

Removing the INF field ‘PM’ shall cause a disconnect of the connection (with an appropriate STA).

Implementations may decide what to do when the hub connection is lost during a private message connection.

Implementations should adhere to any requirements the DI field in the QUI command in BASE poses regarding non-file transfer connections. Beyond that is up to implementations.

The same port may, but needn’t be, reused for a file transfer connection and a private message connection. Concurrent connections may be rendered unfeasible with extensions such as NAT-T.

The “PM” field of the MSG command should not be used in C-C private messages.

[options=“autowidth”]
|=====
|PM |Field in the CINF to denote that the connection should be used for private messages. The field’s value should be ‘1’.
|=====

Sorry for the delay…

The above write-up is just fine. Nitpicks:

  • "Implementations shall signal “CCPM” " > Implementations supporting this extension shall signal “CCPM”
  • "Removing the INF field ‘PM’ " sounds strange to me gramatically (to be confirmed by an English expert :mrgreen:).

It should be noted that the released implementation in DC++ mostly adheres to this, except for error handling (does not send / care about STA, ignores INF updates regarding the “PM” field).