Xpra-org / xpra-html5

HTML5 client for Xpra
Mozilla Public License 2.0
209 stars 55 forks source link

Authentication does not work after #259 #260

Closed goekce closed 1 year ago

goekce commented 1 year ago

After #259 authentication using the HTML5 client does not work anymore.

If I use xpra attach wss://user@server.de authentication is fine but using HTML5 client fails. I could not find a way to print the password string which is sent to PAM.

@oskarbraten did you test the PR? If yes: I don't have experience with Javascript however I can try to print the encoded string before and after the PR.

totaam commented 1 year ago

I could not find a way to print the password string which is sent to PAM

This is generally considered to be a good thing. You can manually enable it by editing the following code: https://github.com/Xpra-org/xpra/blob/9d699dea1293fd4ba00ae722c21f79b996b3c399/xpra/server/auth/sys_auth_base.py#L204-L206

@goekce: what version are you running? It's likely that the clipboard code can switch to this new code, but other packets cannot - at least not yet.

goekce commented 1 year ago

259 replaces String.fromCharCode with TextDecoder().decode(). The former expects a UTF-16 sequence and the latter UTF-8 as default. I set a breakpoint inside Uint8ToString and extracted a sequence which differs for these two functions:

temp1 = new Uint8Array([186, 38, 43, 41, 33, 251, 143, 178]);
console.log(String.fromCharCode.apply(null, temp1));
console.log(new TextDecoder().decode(temp1));

output:

º&+)!û�²
�&+)!���

If we try to decode using UTF-16 to match their output:

temp1 = new Uint8Array([186, 38, 43, 41, 33, 251, 143, 178]);
console.log(String.fromCharCode.apply(null, temp1));
console.log(new TextDecoder('utf-16').decode(temp1));

output:

º&+)!û�²
⚺⤫ﬡ늏

Still different :( . We see four characters in the latter case because UTF-16 requires two bytes for a single char. But why does the first not work similarly? The reason is that we map the fromCharCode to every item in the Uint8Array individually, so fromCharCode regards every byte as a UTF-16 encoded data. So if we want to create the same behavior, we have to pad extra zeroes for TextEncoder:

temp1 = new Uint8Array([186, 38, 43, 41, 33, 251, 143, 178]);
console.log(String.fromCharCode.apply(null, temp1));
console.log(new TextDecoder('utf-16').decode(new Uint16Array(temp1)));

output:

º&+)!û�²
º&+)!û�²

Above would fix the problem I believe but why did the code encode uint8 arrays using UTF-16 (fromCharCode)?


I am running v4.4.5, but I believe this function is also used for encoding the password. I will try to print the password tomorrow.

goekce commented 1 year ago

It's likely that the clipboard code can switch to this new code, but other packets cannot - at least not yet.

Oh, you mean actually I should not use the latest HTML5 with 4.4.5? I probably thought that the latest xpra has also problems due to https://github.com/Xpra-org/xpra/issues/3939 , however this issue is not related. I will test the latest HTML5 against the latest xpra regarding this issue and let you know.

totaam commented 1 year ago

Oh, you mean actually I should not use the latest HTML5 with 4.4.5?

No, I probably just misunderstood this bug. All recent xpra-html5 versions should be compatible with all recent versions of xpra. We never ever want to sent utf-16 over the network. We did switch to rencodeplus as default encoder recently, which should allow clients and server to send strings without first encoding to bytes. The packet encoder should deal with this properly - perhaps it does not? https://github.com/Xpra-org/xpra-html5/blob/6f6295c55937d4508b8c6ae5af67f843f75c3d28/html5/js/lib/rencode.js#L46 https://github.com/Xpra-org/xpra-html5/blob/6f6295c55937d4508b8c6ae5af67f843f75c3d28/html5/js/lib/rencode.js#L72 FYI: the rencode_legacy_mode is going to be removed soon since xpra servers will no longer be using it.

goekce commented 1 year ago

I activated password logging. #259 sends corrupted data to the v4.4.6 server.

I tried to understand when rencode and Utilities.Uint8toString are used. At first rencode.js is involved but for authentication Utilities.Uint8toString seem to be used:

First call stack involving rencode

stringToUtf8ByteArray (https://server.de/js/lib/rencode.js:formatted#72)
rencode_string (https://server.de/js/lib/rencode.js:formatted#75)
rencode (https://server.de/js/lib/rencode.js:formatted#207)
rencode_list (https://server.de/js/lib/rencode.js:formatted#152)
rencode (https://server.de/js/lib/rencode.js:formatted#198)
rencodeplus (https://server.de/js/lib/rencode.js:formatted#222)
process_send_queue (https://server.de/js/Protocol.js#1)
send (https://server.de/js/Protocol.js#1)
send (https://server.de/js/Protocol.js#1)
 (https://server.de/js/Protocol.js#1)
 (https://server.de/js/Protocol.js#1)
Second call stack involving Utilities

Uint8ToString (https://server.de/js/Utilities.js:formatted#243)
s (https://server.de/js/Utilities.js:formatted#247)
_process_challenge (https://server.de/js/Client.js#2)
_route_packet (https://server.de/js/Client.js#1)
open_protocol (https://server.de/js/Client.js#1)
open (https://server.de/js/Protocol.js#1)
open (https://server.de/js/Protocol.js#1)
open_protocol (https://server.de/js/Client.js#1)
_do_connect (https://server.de/js/Client.js#1)
initialize_workers (https://server.de/js/Client.js#1)
initialize_workers (https://server.de/js/Client.js#1)
connect (https://server.de/js/Client.js#1)
init_page (https://server.de/index.html#1520)
onload (https://server.de/index.html#1654)
load_default_settings (https://server.de/index.html#1644)
 (https://server.de/index.html#1678)
mightThrow (https://server.de/js/lib/jquery.js#1)
process (https://server.de/js/lib/jquery.js#1)
resolve (https://server.de/js/lib/jquery.js#1)
fire (https://server.de/js/lib/jquery.js#1)
fireWith (https://server.de/js/lib/jquery.js#1)
fire (https://server.de/js/lib/jquery.js#1)
fire (https://server.de/js/lib/jquery.js#1)
fireWith (https://server.de/js/lib/jquery.js#1)
ready (https://server.de/js/lib/jquery.js#1)
completed (https://server.de/js/lib/jquery.js#1)
 (https://server.de/js/lib/jquery.js#1)
 (https://server.de/js/lib/jquery.js#1)
 (https://server.de/js/lib/jquery.js#1)

You mean that Utilities.Uint8toString will not be additionally required and rencodeplus should be used solely?

What I don't understand:

I can send a PR which fixes the Textencoder using UTF-8 which would be a quick fix.

totaam commented 1 year ago

Your backtrace was from a minimized version of the source, so it's difficult to know which exact line triggered which call. (you may want to just copy the xpra-html5/html5/* into /usr/share/xpra/www/)

IIRC, _process_challenge: https://github.com/Xpra-org/xpra-html5/blob/6f6295c55937d4508b8c6ae5af67f843f75c3d28/html5/js/Client.js#L2956 Calls Utilities.s to ensure that the value is a string, even when receiving data using a legacy packet encoder that only sends bytes. It may be redundant / unhelpful nowadays with rencodeplus. Perhaps the correct fix is to remove these hacks.

goekce commented 1 year ago

Then v4.4.6 must be using the legacy packet encoder. So the idea is to ensure that Utilities.s never receives a Uint8Array but only strings. Then we don't have to decode it using Utilities.

This issue is related to websockets. Due to https://github.com/Xpra-org/xpra/issues/3939 I cannot establish a websocket connection to the latest server so I cannot fix this without fixing https://github.com/Xpra-org/xpra/issues/3939. I'll try https://github.com/Xpra-org/xpra/issues/3939 first.

oskarbraten commented 1 year ago

@goekce I did not perform any tests with authentication enabled. I’ll do some debugging. It seems quite odd that the clipboard works as intended, while the challenge fails. Perhaps there are other unintended side-effects as well. @totaam Yes, removing the hacks is the way to go long term. I’ll see what I can do.

totaam commented 1 year ago

@goekce https://github.com/Xpra-org/xpra/issues/3939 is closed as fixed so I don't see how it could be blocking anything.

goekce commented 1 year ago

@goekce Xpra-org/xpra#3939 is closed as fixed so I don't see how it could be blocking anything.

this is related to ArchLinux which is unsupported, so I closed the issue before fixing.


I’ll see what I can do.

Great @oskarbraten !

totaam commented 1 year ago

so I closed the issue before fixing.

No. AFAIK, the issue was already fixed, you're just running an older version.