tabby-rdp 0.4.1 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/CHANGELOG.md +580 -0
  2. package/README.md +252 -34
  3. package/dist/accountForm.js +0 -1
  4. package/dist/accounts.js +0 -1
  5. package/dist/audio.js +0 -1
  6. package/dist/authorities.js +331 -0
  7. package/dist/byteQueue.js +102 -0
  8. package/dist/clipboard.js +106 -0
  9. package/dist/connectionStatus.js +0 -1
  10. package/dist/desk.js +16 -47
  11. package/dist/deskScript.js +196 -6
  12. package/dist/desktop.service.js +1763 -204
  13. package/dist/desktopForm.js +72 -13
  14. package/dist/desktops.js +243 -19
  15. package/dist/drives.js +525 -0
  16. package/dist/fileTransfer.js +1064 -72
  17. package/dist/gateway.js +651 -0
  18. package/dist/header.js +76 -5
  19. package/dist/help.js +34 -13
  20. package/dist/hyperv.js +129 -0
  21. package/dist/index.js +2 -2
  22. package/dist/keyboard.js +0 -1
  23. package/dist/microphone.js +57 -13
  24. package/dist/ntlm.js +225 -0
  25. package/dist/osd.js +56 -15
  26. package/dist/probe.js +15 -3
  27. package/dist/rdcleanpath.js +468 -52
  28. package/dist/rdpFile.js +53 -4
  29. package/dist/rdpProfile.js +75 -22
  30. package/dist/remoteSetup.js +103 -23
  31. package/dist/sessionLog.js +53 -0
  32. package/dist/settingsPage.js +117 -27
  33. package/dist/signin.js +429 -54
  34. package/dist/ssh.js +99 -18
  35. package/dist/sshChannelStream.js +50 -6
  36. package/dist/targets.js +185 -39
  37. package/dist/ui.js +98 -20
  38. package/dist/unshowable.js +41 -0
  39. package/dist/updates.js +37 -2
  40. package/dist/vms.js +36 -5
  41. package/dist/wake.js +31 -12
  42. package/package.json +4 -3
  43. package/remote/trd-pty.py +74 -13
  44. package/vendor/SHA256SUMS +26 -0
  45. package/vendor/iron-remote-desktop-rdp.js +418 -390
  46. package/vendor/ironrdp_web_bg.wasm +0 -0
  47. package/dist/accountForm.js.map +0 -1
  48. package/dist/accounts.js.map +0 -1
  49. package/dist/audio.js.map +0 -1
  50. package/dist/connectionStatus.js.map +0 -1
  51. package/dist/desk.js.map +0 -1
  52. package/dist/deskScript.js.map +0 -1
  53. package/dist/desktop.service.js.map +0 -1
  54. package/dist/desktopForm.js.map +0 -1
  55. package/dist/desktops.js.map +0 -1
  56. package/dist/fileTransfer.js.map +0 -1
  57. package/dist/header.js.map +0 -1
  58. package/dist/help.js.map +0 -1
  59. package/dist/index.js.map +0 -1
  60. package/dist/keyboard.js.map +0 -1
  61. package/dist/microphone.js.map +0 -1
  62. package/dist/osd.js.map +0 -1
  63. package/dist/probe.js.map +0 -1
  64. package/dist/rdcleanpath.js.map +0 -1
  65. package/dist/rdpFile.js.map +0 -1
  66. package/dist/rdpProfile.js.map +0 -1
  67. package/dist/remoteSetup.js.map +0 -1
  68. package/dist/settingsPage.js.map +0 -1
  69. package/dist/signin.js.map +0 -1
  70. package/dist/ssh.js.map +0 -1
  71. package/dist/sshChannelStream.js.map +0 -1
  72. package/dist/targets.js.map +0 -1
  73. package/dist/ui.js.map +0 -1
  74. package/dist/updates.js.map +0 -1
  75. package/dist/vms.js.map +0 -1
  76. package/dist/wake.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,585 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.5.1
4
+
5
+ Security fixes from an audit of 0.5.0: saved passwords and certificates, what a host says about its desktops, `desk`,
6
+ shared folders and file transfers, what a server, gateway or SSH host can make Tabby do, and what a connected desktop
7
+ can do. Clipboard sharing can be narrowed or turned off, and a release ships IronRDP only as its sources build it.
8
+
9
+ **Security**
10
+ - **An imported .rdp profile no longer signs in with a saved account on its own.** If you had set a default account
11
+ for a profile group or for remote desktops in general, a profile made from an .rdp file used to adopt it and send
12
+ its password to the address and gateway the file named, with no sign-in prompt. Once such a profile had been saved
13
+ in Tabby's profile editor (which drops the values that equal the defaults then), it could also take a default
14
+ gateway account set since, which went to the gateway the file named the same way, and a default kind of xrdp, which
15
+ would have had the password go without Network Level Authentication, unasked. An imported profile now has no
16
+ account, no gateway account and the Windows kind whatever the defaults say (`null` for each, which Tabby's profile
17
+ editor keeps when it saves), so it asks for its sign-in, unless a password was saved already for that same address
18
+ reached the same way (through the same gateway, or none; not one 0.5.0 saved there for a desktop reached through a
19
+ gateway, which is forgotten: below); pick a saved account or a kind in its profile settings if you want one.
20
+ Profiles imported before this update and not saved in the profile editor since are changed the same way, when Tabby
21
+ starts and whenever its config changes (config sync included): they ask for their account once instead of taking a
22
+ default one. And removing a saved account now leaves the profiles that used it asking for an account, as its
23
+ confirmation says, rather than taking their group's default.
24
+ - **A certificate this computer can't verify is confirmed before anything of your sign-in goes to the server.** A
25
+ remote desktop you connect to directly (an RDP profile, quick connect, an imported .rdp file, a restored tab)
26
+ remembered the first certificate it met without asking, and so did an RD Gateway, so someone in the middle of that
27
+ first connection, or a file naming a gateway of its own, could take the sign-in: a proof of your password that can be
28
+ attacked offline. Now a certificate valid for the server's name by the certificate authorities this computer trusts
29
+ (the public ones, and with a recent Tabby those of the system's own store too, such as an organisation's) connects
30
+ without a question, and any other is shown the first time, before anything of your sign-in goes to the server (the
31
+ connection request and the TLS handshake have): the address, why it can't be verified, its SHA-256 fingerprint and
32
+ what it says of itself (whom it was issued to and by, and when it is valid, which the desktop's log has too), with
33
+ Cancel as what Enter picks. Why it can't be verified is the plugin's own reading, since the TLS library reports only
34
+ the last of its checks that failed, which whoever makes the certificate can choose. First, unless its chain leads to
35
+ an authority this computer trusts, where that chain stands: self-signed (Windows' own RDP certificate included,
36
+ whatever its key usage), from an authority this computer doesn't trust, or no way to one from what the server sent
37
+ (only an authority counts as an issuer, so one signed with the key of a certificate issued to a server leads to
38
+ none; and an authority is known by its name and key, as the TLS library knows it, so its root sent along
39
+ cross-signed by another counts). Then, whatever the chain: issued for another name (checked by the plugin, since
40
+ Node checks the name only once a chain checks out), expired or not valid yet (by its own dates), and marked for
41
+ other uses than a server's. Only one for that name whose chain leads to an authority this computer trusts is said to
42
+ be like some organisations' Remote Desktop certificates. What it says of itself is marked as its own word, which
43
+ nothing has checked, unless an authority vouched for it or its chain leads to one this computer trusts (another
44
+ machine's certificate then shows that machine's name), and the TLS library didn't refuse it for a reason of its own (a
45
+ limit set on the authority, say): an issuer you would expect there proves nothing, since anyone can make a certificate
46
+ that names it; only the fingerprint, checked some other way, does. For a server without Network Level Authentication
47
+ it says that signing in sends the password itself, not a proof of it. A certificate
48
+ whose only use is Remote Desktop Authentication (as Active Directory's Remote Desktop templates issue them) isn't
49
+ valid for a server by these rules, whatever issued it, and is asked about too, at each renewal as well.
50
+ Automatic reconnects stop at the question. A certificate you trust is remembered as yours, and a different one there
51
+ later stops the connection whatever vouches for it; one an authority vouched for may be replaced by another it
52
+ vouches for (a renewal), which connects and is noted in the desktop's log. The same one connects only while that word
53
+ holds: once it has expired, or its authority is gone from this computer's store, it is asked about as at first, since
54
+ you never confirmed it, and trusting it then makes it yours. Trusting a certificate never allows signing in without
55
+ Network Level Authentication. Desktops behind an SSH host still remember their first certificate without asking: SSH
56
+ vouches for the host they are reached through, though not for what answers behind it.
57
+ Certificates remembered before this update stay remembered: a desktop's is held to that certificate as before
58
+ (unless an authority vouches for it, when it counts as met for the first time now), and a gateway's may still be
59
+ replaced by one an authority vouches for. The .rdp import dialog says plainly that a gateway is signed in to first.
60
+ - **A machine reached with `ssh` typed in an SSH tab is filed under that tab's host.** What the plugin keeps per
61
+ desktop (a saved password, the remembered certificate, permission to sign in without Network Level Authentication)
62
+ was found for such a machine by a name the host there reported, so a hostile host could pass a desktop of its own
63
+ off as another one you had used, behind another host too, and have that desktop's saved password sent to it. Such a
64
+ machine's desktop is now kept under the host it is reached through: a host can only ever name desktops of its own.
65
+ Desktops reached this way ask for their sign-in once more and remember their certificate anew (a sharpness set for
66
+ one is set again): what was saved for them can't be told apart from what a host could claim, so none of it is used.
67
+ The same machine opened in a tab of its own now counts as another desktop: a tab with that one open isn't switched
68
+ to. Desktops configured behind a host belong to tabs connected to that host, not to a machine reached through
69
+ another one, whose name there is that host's word: only that machine's own desktop opens through it. And the names
70
+ hosts are kept under are now written so that no two can be the same: a host whose user or host name has a `%`, `#`
71
+ or `>` in it (an IPv6 address with its zone, `fe80::1%en0`) is kept under a new name, and what was kept for it moves
72
+ along, its remembered certificates and sharpness at once and a saved password at its next sign-in; desk's key and
73
+ the choices made "from now on" for it are asked about again. A host whose user name has a `#` gets its desktops'
74
+ passwords asked for again instead, and those kept under its old name are forgotten once a tab to that host is open
75
+ again: from the keychain the next time a saved password is looked up, saved or forgotten and it answers, and from
76
+ Tabby's Vault (if it is on) the next such time the Vault is open. There they read as no desktop's, so removing or
77
+ editing one of its desktops left them in place, kept for good. Where the old name could be another account's new
78
+ one, nothing moves, and that host's desktops ask again: `alice%23ops@host` is how `alice#ops@host` is written now,
79
+ and an old name with a numeric IPv6 zone whose first two digits are 10 to 19, 23, 25 or 40 (`%12`, say) reads as such
80
+ a name too. What a hostile host may have planted under another desktop's name before this update can't be told
81
+ apart, and stays: a certificate that isn't the server's still stops the connection.
82
+ - **Desktop asks when a console's `ssh` would lead it elsewhere.** Which `ssh` runs in an SSH tab's console is what
83
+ the host there says, so a host could have **Desktop** open a machine of its choosing in place of its own, without a
84
+ word. Desktop now asks which desktop to open: the tab's own (the first choice), or that machine's, this time or
85
+ **from now on**. Only "from now on" opens that machine's desktop at once the next times `ssh` leads there from that
86
+ host. An `ssh` to a name with characters that could hide part of it or show it in another order (control and format
87
+ characters, and the others that don't show, as the .rdp import has them) isn't offered. A "from now on" is taken back
88
+ in Tabby's config file (`remoteDesktop.nestedSSH`). A desktop picked in the tab's menus is always the tab's host's,
89
+ also where a machine's own desktop is open in the pane, which the menus then offer to replace with the host's own
90
+ (and `desk` opens the desktop of the machine it ran on), and a sign-in form for a machine reached through a host
91
+ names that host.
92
+ - **A saved desktop password is no longer reused for a different gateway.** A remembered password was kept by the
93
+ desktop's address alone, so a profile that named the same address through another gateway could send it there without
94
+ asking. Saved passwords are now tied to the way they were entered for: through that gateway (in any spelling of it),
95
+ whether it takes the desktop's sign-in or an account of its own, or through none. A desktop reached through a gateway
96
+ asks for its password once after this update; the password 0.5.0 saved for it, under the address alone, which a
97
+ desktop at that address without a gateway (a quick connect, another profile, an .rdp file naming it) would now find
98
+ and use unasked, is forgotten after the update, for each desktop configured to go through a gateway by then, so that
99
+ desktop asks once too: once in each computer's keychain and once in Tabby's Vault, the first time a password is looked
100
+ up, saved or forgotten (marked done in the keychain itself, and for the Vault in the config, which config sync takes
101
+ to other computers with the Vault). Until that has been done (a keychain that doesn't answer, a Vault whose passphrase
102
+ prompt was cancelled), such a password isn't used. Changing its gateway, user name, domain or account forgets the
103
+ password and asks again, as does removing the desktop; a sign-in that was under way when that happened (the server
104
+ took its time) isn't saved when it ends, which would undo it. A new address takes it along, through the same gateway,
105
+ unless a desktop is known at that address already, and behind an SSH host only along with its desktop's remembered
106
+ certificate (below). Each store of passwords, Tabby's Vault and the keychain, forgets such a password on its own: at
107
+ once where it can be read, and where it can't be just then (the Vault locked and its prompt cancelled, the keychain
108
+ not answering) the password isn't used, and goes the next time that store can be read while the Tabby window is open;
109
+ an edit or a removal says so, naming that store. Should the window be closed first, it is found again by a desktop at
110
+ that address (**Sign in again…** in the desktop's menu replaces it). The desktop's remembered certificate stays
111
+ meanwhile, so that a password still kept there goes only to the machine it was saved for: a removal keeps it while a
112
+ store waits (Settings › Remote Desktop › Certificates can forget it), and a new address leaves it at the old one too,
113
+ as well as taking it along, which also keeps another desktop's password at that address, reached another way, from
114
+ going to a machine that isn't the one it was saved for.
115
+ - **Desktops that are xrdp only by a host's word ask before the password goes without Network Level Authentication.**
116
+ 0.5.0 stopped before sending the password to a server without NLA, except for desktops of the xrdp kind, which sign
117
+ in that way by design. But a VM a host lists, a machine reached through a host, and the host's own desktop are xrdp
118
+ only because that host says so: a host could call any server it offers xrdp and get the password typed for it as it
119
+ is, and a host you sign in to with an SSH key need not have that password. Now only desktops you made xrdp ones (a
120
+ desktop or profile of that kind) go on unasked; the others, the xrdp of the host you SSH into included, ask once, in
121
+ xrdp's terms, and the answer is remembered for that desktop (with its certificate, below). A VM saved from a host's
122
+ list is asked about the same way, one saved before this update too, until you pick its kind in its edit form, where
123
+ the host's word is a choice of its own; the question says so. (A desktop of yours of the xrdp kind that starts a VM
124
+ by name looks like such a VM, and asks once too.)
125
+ - **"Send the password anyway" is kept with the certificate it was given for.** Permission to sign in without Network
126
+ Level Authentication was kept for the desktop alone, from before any certificate had been seen: an attempt that didn't
127
+ get as far as one left it for whatever answered there next, which then got the password unasked, its certificate
128
+ trusted as a first use. And it outlived **Trust the new certificate** and a new address in the edit form. It is now
129
+ kept with the certificate accepted for that sign-in, and holds for that certificate only; trusting a changed one, a
130
+ new address or forgetting the certificate takes it back, so another server there asks again, and the
131
+ changed-certificate question says so. 0.5.0 kept the answer only until Tabby restarted (under Fixed, below), so none
132
+ of its answers carries over; development builds since kept them without a certificate, and those ask once more.
133
+ - **A VM a host lists can no longer be given another desktop's saved password.** A found VM's address is part of the
134
+ name its saved password is looked up by, and a host could list one at an address made up to read as a desktop
135
+ configured behind it whose sign-in goes to an RD Gateway: opening that VM sent the desktop's saved password to
136
+ wherever the host had it lead. A found VM's address is now an IPv4 address, the only kind the scan reports; others
137
+ aren't listed.
138
+ - **`desk` requests need the machine's key, and act only in the pane you're in.** With `desk` on, anything shown in a
139
+ console could ask Tabby to open that machine's desktop and run its setup there, as typing `desk` does: a file shown
140
+ with `cat`, a log being followed, another machine's output. Tabby now acts only on a request that carries the key of
141
+ the machine it is for, which only your account there can read and which the machine's setup gives Tabby when its
142
+ desktop is opened with `desk` on. A setup run with `desk` off makes Tabby forget that machine's key as it starts,
143
+ whatever the machine then says, so also when the setup fails or never finishes; one during which `desk` is turned off
144
+ does when it ends or fails with `desk` still off (with `desk` on again by then, it changes nothing: a setup since
145
+ keeps what it found), as does one that finds xrdp or Windows there instead of GNOME. Requests without a known key are
146
+ dropped as they are read, with nothing shown, even while `desk` is off; of the others, a terminal passes on one every
147
+ 2 seconds, and a pane handles one at a time (timed by a clock that only goes forward: the time of day set back doesn't
148
+ keep `desk` quiet meanwhile). A request from a pane that isn't the one in front, or that stops being it by the time
149
+ the desktop would show (Tabby first asks the machine which one it is), gets a note there instead: shown there, the
150
+ desktop would take the keyboard (and this computer's clipboard) from the pane you are typing in, even from another
151
+ tab. The key tells `desk` apart from look-alike output, not from the machine itself, which can always send it, nor
152
+ from a recording of `desk`'s output shown again there: open the desktop of a machine you don't trust with `desk` off.
153
+ After updating, open each machine's desktop once before using `desk` there: that installs the new `desk` and lets
154
+ Tabby recognize it. Tabby keeps a fingerprint of each key, not the key.
155
+ - **`desk` attaches the desktop's terminal only to your own sessions.** A request could name a tmux session that
156
+ another user of the machine had opened to others, and the terminal on the desktop attached to it, where that user
157
+ would see what you type. Now it attaches only to your own trd-pty sessions and to tmux servers in tmux's own folder
158
+ for you, where no other user can replace a folder on the way; anything else gets a terminal in the folder instead.
159
+ trd-pty, `desk`'s session helper, also checks that a session runs as you before sending it anything, doesn't use
160
+ `/tmp` where another user could swap its folder, and starts no session (logins fall back to tmux) on a system that
161
+ can't say which user is at the other end of a connection.
162
+ - **A desktop that finishes connecting while you're in another pane no longer takes the keyboard**, nor does a sign-in
163
+ form (its own, or its gateway's) or a question (a certificate to trust) that shows up for it meanwhile, nor the tip
164
+ shown on the first connection when it closes. They took it from whatever pane you had moved to, in another tab too
165
+ (Tabby keeps those in the page, out of sight), so what you typed there went to that desktop, and this computer's
166
+ clipboard went with the keyboard. The remote decides how long connecting takes, and when a dropped connection comes
167
+ back. They now get the keyboard when their pane does, and a question waiting where it isn't in view brings a note
168
+ that stays a few seconds.
169
+ - **Pasting a copied folder (⌘V) no longer sends what its links lead to outside it.** A folder can hold links to
170
+ anywhere (one unpacked from an archive, or a repository), and the paste sent the files behind them too, a folder
171
+ of keys as easily as a document. A link in a copied folder is now followed only when it leads somewhere in that
172
+ folder; the others are left out, and the message on the desktop says how many. When that leaves no file to send,
173
+ nothing is pasted (⌘V would have pasted whatever the remote had), and the message says why; the same where what was
174
+ copied is gone, or is links that lead nowhere or folders with nothing in them. Folders dropped on a
175
+ desktop weren't affected: Tabby's browser engine doesn't follow their links. Reading a copied folder holds Tabby up
176
+ while it goes on, so besides its limits on what it sends (10,000 files and folders, 20 deep) it now stops at limits
177
+ on what it looks at (20,000 names and folders, 2,000 links), and looks at nothing past them: a folder of a million
178
+ names or links no longer holds Tabby up for long, and the message says when something was left out. A folder found
179
+ swapped for another while it was read stops the paste, as one that can't be read does (⌘V pasted whatever the remote
180
+ had).
181
+ - **A release ships IronRDP only as its sources build it.** The remote desktop itself (IronRDP's WebAssembly and
182
+ JavaScript, in `vendor/`) is committed prebuilt and runs with Tabby's access to this computer, and nothing checked
183
+ that it was what IronRDP and the plugin's patches build to: a changed or out-of-date build would have been published
184
+ as it was. The build now records what it was made from and each file's hash (`vendor/SHA256SUMS`), every change is
185
+ checked against that, and a release is staged only after CI has rebuilt IronRDP from source and found every file
186
+ identical, byte for byte. The base commit has to be one of IronRDP's own (GitHub serves a fork's commits through
187
+ IronRDP's address too), and the build's tools are pinned: wasm-bindgen is built from its own lock file rather than
188
+ from the newest releases of what it uses (one of the right version built without it is built again; this release's
189
+ WebAssembly is built so, and differs from 0.5.0's only in the version of a library of wasm-bindgen's it names), and on
190
+ the Apple Silicon Mac `vendor/` is built on, binaryen's optimizer is checked against its hash before it runs, and is
191
+ all that is kept of its release: the folder it is in goes ahead on PATH, so nothing else may be there. The package's
192
+ IronRDP files, and every other committed file in it, are checked against the tagged commit in the repository, not
193
+ against the copy of the list it carries, before it is staged, and a staged release can be checked the same way before
194
+ it is approved, its built `dist/` against a build of your own. The patches' own tests now run in CI as well.
195
+ - **An SSH host can no longer freeze or crash Tabby with what it prints.** The plugin runs small commands on your SSH
196
+ hosts (looking for VMs does so by itself while an SSH tab is active), and it kept all that a host printed in answer,
197
+ then read it in a way that took far longer the more there was: a host that answered with a few megabytes of made-up
198
+ VMs could freeze Tabby for a minute or more, a single long line could do it for hours, and a larger answer could
199
+ crash it, closing every tab. An answer is now cut off at 4 MB (the plugin's commands print a few lines), kept as its
200
+ bytes however small the pieces it comes in, and read in time that grows only with its size: the VM scans, Hyper-V's
201
+ answers and the line that says how an `ssh` typed on a host ended are read line by line or by hand, not with
202
+ patterns that a long line could make retry each way of splitting it. At most 256 VMs are listed for a host, and its
203
+ menu says so when that cuts the list short. A command's minute now runs from the moment its channel is asked for, so
204
+ a host that stops answering partway through starting one no longer keeps a VM scan or a desktop's setup waiting for
205
+ good. A host whose scan fails waits a minute before it is asked again, as one that answered does. A command run
206
+ through the `ssh` typed in a terminal that takes longer than a minute is now an error, rather than taken as finished
207
+ with what it printed so far, and a tunnel through it keeps only the end of what ssh prints (a host's sign-in banner
208
+ can be as long as it likes). The list of this computer's processes, read to find the `ssh` in a local terminal, is
209
+ read the same way: a program with a long run of spaces in its arguments could freeze Tabby while it was looked at.
210
+ A host's reason for an error is shown and logged as far as 1,000 characters (a Hyper-V host's answer, 1,024), and a
211
+ line logged from a host's answer is kept as a copy of its own, not as part of the answer, which could keep megabytes
212
+ in memory for each line. To find an `ssh` typed in a pane (to open the desktop of the machine it went to), the
213
+ plugin has the host print a mark in the terminal of each `ssh` running there, which tells which one is the pane's;
214
+ it kept every such mark the host printed while it answered, up to a minute, which could fill Tabby's memory as
215
+ well. It now keeps only marks of the form its script prints, 64 at most.
216
+ - **A remote desktop's server can no longer freeze Tabby by sending its data in tiny pieces.** Each piece was joined
217
+ to everything still waiting, so a message sent a byte at a time cost the square of its size, all of it on the thread
218
+ that runs Tabby's window: a few megabytes could hold Tabby still for tens of seconds at a time, and more for far
219
+ longer. Pieces are now joined once, when the message is complete, and the server's sign-in messages (a few
220
+ kilobytes) may be 256 KB at most, instead of 16 MB. The same goes for what an RD Gateway sends. What waits for the
221
+ rest of a message is copied into storage of its own rather than kept as it came, since a piece can be a few bytes of
222
+ a much larger read: a gateway could otherwise have every read kept whole for a byte of a packet it never finishes,
223
+ a gigabyte for one packet. What comes through an SSH host while the desktop's side isn't reading is kept the same
224
+ way, as its bytes rather than the pieces they came in: 64 MB of it a byte at a time could take gigabytes. A server
225
+ that answers the connection request with something other than RDP (a web server on that port, say) is refused at
226
+ once, rather than waited on for the length its answer seemed to give.
227
+ - **A remote desktop has a limit on the files it keeps open through a shared folder.** The server decides how many files
228
+ it opens there and when it closes them, and a hostile one could keep opening until Tabby's window could open no file
229
+ or connection in any tab, or crashed. A desktop now has at most 1,024 files open at once (programs there keep far
230
+ fewer), and all the desktops in a Tabby window 2,048 together, since they share the window's files; more are refused
231
+ until some are closed. That leaves most of what a Tabby window may have open to its other tabs where it may have far
232
+ more: on macOS (some 138,000, measured) and on Windows (8,192). On Linux that wasn't measured: where a Tabby window
233
+ may have 4,096 files open or fewer, these 2,048 are half of that or more. A file counts until it has been closed, not
234
+ from when the server asks for that (closing waits for what is under way on the file), and a file still being opened
235
+ when the connection ended was left open until Tabby quit; it is closed now.
236
+ - **The desktop name overlay's settings can't become part of Tabby's window.** A color for the overlay could get past
237
+ the plugin's check and be read as page content, which in Tabby's window runs as code; it took someone able to change
238
+ your Tabby config (through config sync, say). The overlay is now built without reading anything as page content,
239
+ and only plain colors are used (a name, `#hex`, `rgb()` and the like). Other odd values are handled too: an overlay
240
+ font or size such as `constructor` is ignored, where it used to break the overlay and with it the connection of the
241
+ desktop it was naming; an overlay duration or an idle shutdown time that is neither a number nor text no longer
242
+ stops every desktop from connecting, nor does a desktop's port, address, name or other field of that kind (in its
243
+ entry or its profile) stop that desktop and those listed with it. Such a field, or an item in the desktops list that
244
+ is no entry at all (an empty one), no longer takes away the right-click menu of every SSH tab (Tabby's own items
245
+ with it) or the lists of the settings page, nor does a profile's address, port, user name or gateway of that kind
246
+ keep Tabby's profile selector from opening; a desktop behind a host with such a field can still be edited and
247
+ removed, shown by what of it is text, or by its address. Whatever goes wrong with the overlay, reading its settings
248
+ included, is logged rather than failing the connection; and a shortcut in the config that isn't text no longer
249
+ breaks the settings page.
250
+ - **The GNOME desktop's generated password no longer shows in the host's process list on every connect.** Checking it
251
+ went through a command whose arguments other users of the host can see, and with the password one of them could sign
252
+ in to that desktop. It is now compared in the shell, and set through `grdctl`'s input where `grdctl` reads it from
253
+ there; a `grdctl` that doesn't still gets it as an argument each time it is set that way (when the setup can't tell
254
+ whether it is set already, too), so on a host shared with others the password can still be caught then.
255
+ - **A shared folder's hard links can't be used to change files elsewhere.** A file with more than one name (a hard link,
256
+ as pnpm's `node_modules` and some backup tools make) is the same file under each name, possibly outside the shared
257
+ folder, so through a read-write share the remote could change it there too. Such files (as their count of names is
258
+ when the file is opened) are now read-only from the remote; reading them is as before.
259
+ - **The microphone shows in Tabby's header whenever a desktop gets it**, whatever tab is in front, and in full screen,
260
+ which hides Tabby's header, at the top of the window in the middle (over the desktop in view, clear of a maximized
261
+ window's close button and GNOME's system menu); its menu shows that desktop, or stops sending the microphone there. A
262
+ desktop that starts receiving the microphone while it isn't showing also brings a note. The remote decides when it
263
+ takes the microphone, and the red dot on the desktop was the only sign in Tabby: out of sight while the console was in
264
+ front or the tab in the background, and partly covered by a note from the remote. Capturing still carries on while the
265
+ desktop is hidden, so hiding it doesn't cut a call short. **Stop** holds for that desktop until you turn **Send the
266
+ microphone** back on in its menu (or that Tabby window is closed), reconnects included, so a server can't get the
267
+ microphone back by dropping the connection; the same switch keeps a desktop from getting it beforehand. Turning the
268
+ Microphone setting off now stops it at once on every desktop, one still connecting included, also when it is changed
269
+ in another window or the config file; turning it on still applies on the next connection. Importing an .rdp file says
270
+ when the desktop will get the microphone, and no longer calls a file's request for it not applied while the setting is
271
+ on.
272
+ - **Clipboard sharing can be narrowed or turned off.** The clipboard always went both ways: a desktop that had the
273
+ keyboard got what was on this computer's clipboard, whatever was copied meanwhile and what was copied elsewhere
274
+ before clicking back into it, passwords from a password manager included, and could put anything on this computer's
275
+ clipboard, such as a command waiting to be pasted into a terminal. Settings › Remote Desktop › Settings ›
276
+ **Clipboard sharing** now offers both ways (the default, as before), only from the remote desktop to this computer,
277
+ or off, for text, pictures and files alike; a desktop can have its own, in its profile's settings (or its group's or
278
+ type's defaults) or in the form of a desktop behind an SSH host, and the Clipboard menu on such a desktop says so.
279
+ Only from the remote desktop stops the reading of this computer's clipboard altogether, so a desktop connected that
280
+ way only gets an empty one from this side; off leaves the clipboard channel out of the connection. **Paste to all
281
+ desktops** leaves out the desktops that don't take this computer's clipboard and says which, and files go only where
282
+ the clipboard does. Applies on the next connection; narrowing it also stops the sending right away to open desktops
283
+ that follow the setting, however it was changed (here, in another window, in the config file or by config sync),
284
+ takes back the files offered to them (a paste still pulling them fails), and stops a paste to all desktops or a save
285
+ of several files that is under way before its next step. Narrowing applies in full once those desktops reconnect. An
286
+ .rdp file's `redirectclipboard:i:0` (`0`, `00`, `+0` or `-0`, on any of its lines) now turns the clipboard off for the
287
+ profile it makes, where the import used to note it as not applied; a file can't turn it on, and without it the
288
+ profile follows its group's and type's defaults, which the import's question names. Importing such a file for a
289
+ desktop that already has a profile sharing the clipboard asks whether to turn it off there, rather than opening that
290
+ profile as it is. A desktop configured twice behind a host gets the narrower clipboard of the two, and a desktop
291
+ opened with a narrower clipboard while it is open already (from another profile for it, say) narrows the open one
292
+ until it is closed, its reconnects included and when it is shown again after its server ended it; its Clipboard menu
293
+ says so.
294
+ - **Paste to all desktops and Type into all desktops leave out the desktops that aren't showing.** In a split tab, a
295
+ desktop whose console was in front of it (or behind a pane maximized over it, nearly transparent) still got the
296
+ paste and every key typed into the others, passwords included, with nothing on screen saying so: its label was on
297
+ the hidden desktop. Now only the desktops showing get them, and the menus count only those; a key held down when a
298
+ desktop is hidden is still let go there.
299
+ - **An open remote desktop tab connects with its profile as saved.** Reconnect, Try again, automatic reconnects and a
300
+ reconnect at a new size used the profile as it was when the tab opened, so a new address or account only applied once
301
+ the tab was closed and the profile opened again. A tab whose profile now goes through an SSH profile no longer
302
+ connects directly.
303
+ - **Files saved from a remote desktop are marked as downloaded**, as a browser marks its downloads, so the system's
304
+ checks of downloads apply to them: on macOS, Gatekeeper's, for apps, scripts and installers opened from Finder; on
305
+ Windows, SmartScreen's and Office's Protected View. They were saved without the mark, so none applied. Not every kind
306
+ of file, or every way of opening one, gets those checks. A file that can't be marked (on a disk that keeps no such
307
+ marks) is saved anyway, and the message says the system may not warn before opening it, also when a later file
308
+ fails to save. A file that fails to be saved whole (on a full disk, say) isn't left there part saved. And what the
309
+ remote sends now goes into new folders of its own (one whose name is taken in Downloads gets a number, as a file
310
+ does, and each is made as it is chosen), never into a folder that was there before or made since, such as an app of
311
+ yours, which the system wouldn't check again.
312
+ - **Names of files saved from a remote desktop can't be disguised with invisible characters.** The remote chooses the
313
+ names, and invisible characters in one can change how it reads (one that reverses the text after it can make an
314
+ app's name end in ".pdf"). Those and control characters are now taken out (but for the invisible tags of a flag such
315
+ as England's, Scotland's or Wales', in such a flag: a region's code after a black flag, not text of any length), and
316
+ names are saved composed (NFC). On Windows, characters it doesn't allow in names become `_`, dots or spaces at the
317
+ end go, and a device's name (`CON`, `NUL.txt`), which would write to the device rather than a file, gets a `_` in
318
+ front. Letters that look like others can still mislead.
319
+ - **The .rdp import dialog can't be dressed up to read as a different address.** A file's address, gateway, user name
320
+ and domain are shown faithfully: control characters, right-to-left overrides, and zero-width and other characters
321
+ that don't show (variation selectors, tags, fillers, blanks other than the space) are refused (but for the joiners
322
+ between letters that Persian and Indic scripts write names with, in a user name or a domain), and a name written
323
+ with international letters is shown and saved as the punycode it actually resolves to, a gateway's port kept, so a
324
+ look-alike can't pose as a name you trust. The account is named with its domain (`CORP\alice`), and such
325
+ characters in the file's own name show as �.
326
+ - **The user name no longer goes out before the server is checked.** The first thing sent to a server, before
327
+ encryption, the certificate check and the stop at a server without NLA, carried the account's user name (a routing
328
+ cookie IronRDP adds), readable on the way and kept by servers the plugin then refused. The plugin's proxy now leaves
329
+ it out, and sends no request that still names the user. Servers don't need it: it is for load balancers that route by
330
+ user name, which the plugin doesn't support.
331
+ - **The fallback to TLS without forward secrecy can no longer be set off by words.** Windows' own certificate rules
332
+ out modern TLS in Tabby, so for it the proxy falls back to TLS 1.2 with RSA key exchange, which has no forward
333
+ secrecy. It did so whenever an error's message named the reason, and a gateway or an SSH host can word its own
334
+ errors; something on the network could also make the first handshake fail. It now falls back only on the TLS
335
+ library's own refusal, not on an error with its code that the SSH channel or the gateway underneath passed on, and
336
+ keeps to it only for a certificate that shows it rules out modern TLS, as Windows' does (one whose key usage can't
337
+ be read doesn't). Otherwise the connection stops, saying something may be interfering, and the next one starts
338
+ without the fallback. Later attempts of the same connection start with the fallback only once it worked with a
339
+ certificate that was accepted, and go back to modern TLS first after an attempt with it that doesn't get that far
340
+ (it fails, the server doesn't answer in time, or the attempt is closed first). A server whose TLS fails through the
341
+ system `ssh` no longer leaves an error behind that nothing handles.
342
+ - **An RD Gateway's answer is no longer kept, however long it says it is.** A gateway, or whatever answered in its
343
+ place on a first connection, could announce an answer of any length and send data until the step's time ran out,
344
+ all of it kept and copied over and over, with Tabby crawling meanwhile. The page that comes with a gateway's refusal
345
+ is now counted off and dropped as it arrives, its length must be a number and at most 256 KB, and the gateway's
346
+ control messages are held to the 125 bytes the standard allows. A gateway that takes the connection and never
347
+ starts TLS is given up on after 20 seconds, like the other steps, instead of being waited for, and a desktop closed
348
+ while its gateway's sign-in is under way ends it, sending nothing more and closing its connection, rather than letting
349
+ it run to those timeouts. A gateway could also freeze Tabby, or fill its memory, in ways that didn't depend on a
350
+ length: a header line with a stray line break after a long run of spaces held Tabby still for seconds while it was
351
+ matched; an administrator's message, which the log shows 300 characters of, was searched to its end, seconds for a
352
+ long one, at any time during a session; and each of its pings was answered with a pong that waited to be sent, so a
353
+ gateway that sent pings and read nothing had them pile up without end. Header lines are now split at their colon, and
354
+ refused with a line break of their own; only as much of a message as the log shows is read; and only the latest ping's
355
+ pong waits to go out, as the standard allows. And a gateway's messages (or a server's doings) can no longer grow a
356
+ desktop's log without end: only its first ten messages are logged, and the log keeps its first 200 lines and at least
357
+ its latest 2,000, saying how many it left out between them.
358
+ - **A remote desktop can't fill a shared folder's disk in an instant.** One request could make a file any size
359
+ without sending what is in it: on disks without sparse files (HFS+, NTFS, exFAT) that took the space at once, from
360
+ the whole disk, and elsewhere it made files that look petabytes long. Now the part of a file the remote sent no data
361
+ for may be no larger than the free space of the disk the file is on (a disk mounted inside a shared folder counts
362
+ for itself), less 1 GB (on a disk under 20 GB, a twentieth of its size). That part is counted from what the file
363
+ has on disk, so growing a file again and again doesn't get past it, and desktops in a Tabby window take turns growing
364
+ files on a disk, each checking the free space as the growth before it left it. Where files can have holes (APFS,
365
+ ext4), the limit is for each file on its own, and what it allows takes no space until written. The remote is told that
366
+ much less is free, so Explorer says before a copy that it won't fit. What the remote writes isn't limited: it takes
367
+ space as any copy does.
368
+ - **A remote desktop gets files sent from here 16 MB at a time at most, and pasted ones are read in the
369
+ background.** It could ask for all of a large file at once, as often as it liked: a pasted one was read in Tabby's
370
+ window, holding it up meanwhile (a third of a second and a gigabyte of memory for a 1 GB file), a dropped or picked
371
+ one into memory. A request for more than 16 MB of a file now gets an error, not part of it, which a remote could
372
+ take for all of it (FUSE, through which xrdp and GNOME Remote Desktop read pasted files, asks for 1 MB at most, 16
373
+ MB on systems with 64 KB pages). At most 64 MB is read for a desktop at a time; more requests wait their turn, and
374
+ past 256 waiting they get an error, as does a request on a stream that has one under way (the remote numbers its
375
+ streams, and couldn't tell which of two requests on one an answer is for). An answer counts only for the request it
376
+ was made for, matched by a number of the plugin's own, not the remote's: one for a request that is no more (expired,
377
+ or gone with the files offered) goes to no one. What is read for a
378
+ desktop's remote, parts of files and a shared folder's reads, waits in Tabby's window until its server reads it, and a
379
+ server that kept asking, and read what came back slowly or not at all, could fill the window's memory in seconds. Now
380
+ what is read for it, beyond what has gone out through the desktop's connection (everything the connection sends
381
+ counts, its other messages too), is at most 64 MB and one part more (16 MB at most), and about 8 MB more may wait on
382
+ the way to the server. A server that reads nothing at all gets no more than that; while one that reads keeps asking,
383
+ what waits can grow beyond it by as much as the proxy reads of the connection's other messages meanwhile. A file's
384
+ size and errors, and a shared folder's answers other than its reads (the names in a folder, a file's details), are
385
+ answered at once, outside that: a size or an error is about as large as the request it answers. A pasted file is read
386
+ a part at a time on Node's background threads, so a slow disk or network folder no longer holds Tabby up. A request
387
+ that can't be answered (for a pasted file replaced, removed or cut short since) gets an error, where it used to get no
388
+ answer at all, or a short one. And only the file that was pasted is read: one put in its place since, a link or a
389
+ pipe, isn't.
390
+ - **Other programs can no longer keep a desktop from connecting.** A desktop's local proxy takes four connections at
391
+ a time, and anything on this computer, or a web page in a browser, could take all four without knowing the proxy's
392
+ secret token: the desktop's own client was then turned away for as long as that went on. The token is now part of
393
+ the proxy's address and checked before a connection is let in, connections from pages in a browser are refused
394
+ whatever they have (sandboxed pages, which say they come from `null`, and extensions' included; the plugin's own
395
+ client is in Tabby's window, a file's page), and the token is compared in a way whose time doesn't tell how much of
396
+ a guess was right. Since the token is in the address, the plugin takes it out of IronRDP's errors, which name the
397
+ address when it can't connect there, before they reach the desktop's status and its log (**Copy log**). A desktop
398
+ closed while its proxy was starting no longer leaves the proxy running until Tabby quits, and one closed while it
399
+ connects no longer gets a clipboard, a video decoder, sound, the microphone or shared folders that nothing would
400
+ close.
401
+ - **The release workflow no longer takes whatever is newest.** It ran GitHub's checkout and Node.js actions by version
402
+ tag, which can be moved to other code, and installed the newest npm 11, all in the job that can publish the package.
403
+ The actions are now pinned to fixed commits, which Dependabot proposes updates to, and npm is the one that comes with
404
+ Node.js 26.8.2 (npm 11.19.1) rather than a download of its own. Only the publishing job can get npm's publishing
405
+ token, and it runs none of the dependencies' code: the package is built in a job of its own, and the publishing job
406
+ stages that very file, taken by the SHA-256 that job reported (any job of the run could replace the file it passes
407
+ on), without running any of its scripts.
408
+ - **The plugin needs ws 8.21.1 or later.** Before 8.21.1, ws let a connection send a message in any number of tiny
409
+ pieces and kept them all; a program on this computer that found the plugin's local proxy could fill Tabby's memory
410
+ that way and crash it, without knowing the desktop's token. A fresh install already got a fixed ws, but the plugin
411
+ accepted 8.18 and later, so an older copy kept in Tabby's plugin folder (by another plugin, say) stayed in use.
412
+ 8.21.1 is now the minimum.
413
+ - **The update check has limits.** It asked npm for the latest version with no limit on time or size, so whatever
414
+ answered in npm's name (a network that inspects TLS, say) could keep the request open for good or send without end
415
+ into Tabby's memory. It now gives up after 15 seconds or 256 KB; the answer is a few KB.
416
+ - **A desktop that drops right after connecting no longer reconnects every second without end.** Connecting reset the
417
+ waits between automatic reconnects, so a server that ended each connection at once, or a video decoder the browser
418
+ kept taking back, had the plugin connect and sign in again every second. The waits now start over only once a
419
+ connection has stayed up for 30 seconds: until then the usual 1, 2, 4, 8, 15 and 30 seconds apply, and automatic
420
+ reconnecting stops after them. A video decoder taken back twice within ten minutes turns H.264 off for that desktop,
421
+ as a decoding failure does, until Tabby restarts or the setting is turned on again.
422
+ - **An alternate spelling of a gateway is treated as the same gateway.** Its remembered certificate and the passwords
423
+ saved for it are keyed by one canonical form (lower case, no trailing dot, international letters as punycode, IPv6
424
+ compressed), so `RDGW.Example.com` and `rdgw.example.com` don't each get trusted on first use. A gateway setting that
425
+ names no host (`gw..example`, a name with `#`, `?`, `@` or `%` in it) is refused rather than read as part of one. A
426
+ gateway written with capitals, a trailing dot or international letters whose certificate was remembered asks once to
427
+ trust it again, unless an authority this computer trusts vouches for it; its old entry leaves Settings › Remote
428
+ Desktop › Certificates.
429
+ - **Removing or editing one desktop no longer drops a gateway's certificate, or one of a desktop at another address.**
430
+ The keys that hold a desktop's remembered certificate and its "Send the password anyway" choice were matched by how
431
+ they end, so a gateway's certificate, or a desktop whose address ended the same way, could go with it; they are
432
+ matched exactly now. A new address no longer takes the place of what a desktop already there has (its certificate,
433
+ sharpness or saved password), and where a desktop is known at the new address (its certificate remembered), the
434
+ saved password doesn't move there either: that desktop's certificate would check out, and it would sign in with the
435
+ password unasked. The edited desktop asks. Desktops at the same address behind different SSH hosts are still edited
436
+ and removed together, since a desktop's keys don't say which host it was added behind; so a saved password behind a
437
+ host moves only along with the certificate remembered for its desktop, which goes along and stays at the old address
438
+ too. Without one (forgotten in Settings › Certificates, which keeps the password), it is forgotten instead: it would
439
+ otherwise go, unasked, to whatever answered first at the new address behind its host, another host's desktop's
440
+ password included.
441
+ - **A malformed .rdp file is reported instead of failing in silence.** A file whose contents named a built-in property
442
+ (a line keyed `__proto__`, say) made the import stop with nothing shown; such a file is parsed without trouble now,
443
+ and an import that does fail says why.
444
+ - **A server that chooses NLA with early user authorization is no longer cut off right after signing in** when it
445
+ also sets the plain NLA flag: the plugin's proxy now reads that choice the way IronRDP does. And the proxy's stop
446
+ before a password goes to a server without NLA can't be left out by mistake: it refuses such servers unless it is
447
+ told otherwise, rather than letting them through.
448
+ - **The idle-shutdown watcher's folder and pid file on the SSH host are private**, as the plugin's folder is when the
449
+ desktop's setup makes it. Made by the watcher first, they were readable by other users; ones made so before are
450
+ made private the next time a watcher starts, the folder in `/tmp` it uses where the home folder can't keep them
451
+ included (one that can't be made private isn't used).
452
+
453
+ **Changed**
454
+ - **The package no longer includes source maps** (`dist/*.js.map`). They pointed at TypeScript sources that were never
455
+ in the package, so they were of no use to anyone installing it, and their long encoded lines are what package
456
+ scanners flag as "long strings" (possibly packed code). The package is about 450 KB smaller unpacked. `npm run
457
+ watch` still writes them, for debugging from the repository.
458
+
459
+ **Fixed**
460
+ - **"Send the password anyway" wasn't remembered.** The choice is meant to stay with that desktop and its certificate
461
+ (listed with it under Settings › Remote Desktop › Certificates), but the setting it's kept in was missing from the
462
+ plugin's defaults, and Tabby only saves settings a plugin's defaults name. The choice held until Tabby restarted and
463
+ was never written to the config, so a desktop without Network Level Authentication asked again after every restart.
464
+ A unit test now checks that every setting the plugin writes is in its defaults.
465
+ - **Turning `desk` off no longer turns a linked `~/.bashrc` or `~/.zshrc` into a copy** of the file it linked to (nor
466
+ one with other names, hard links, into a file of its own), and removes only the line it added: a line of yours that
467
+ merely ended like it went too, and one that mentioned it kept `desk` from adding its line at all. The line from
468
+ before 0.2 is removed only as those versions wrote it. The rest of the file is written back byte for byte (a last
469
+ line without its newline gets one), into the file itself, so its mode and owner stay; a read-only file is left as it
470
+ is, and the desktop's log (Settings › Remote Desktop › Troubleshooting › Open desktops › Copy log) says so, as it
471
+ does when the line can't be added. Should the writing fail part way (a full disk), what the file should hold stays
472
+ in the plugin's folder there, and the log says where.
473
+ - **A machine reached with `ssh` typed in an SSH tab says why when that host's ssh can't reach it.** ssh ends its
474
+ messages with CR LF, and the CR kept the plugin from recognizing the line that says how that ssh ended: a refused
475
+ sign-in or a connection that failed came back as if it were the command's output, and the desktop's setup failed
476
+ saying only that it gave no result. The failure is now reported in ssh's own words.
477
+ - **View only stays on for a desktop shown again after its server ended it**, as it does when it reconnects: shown
478
+ with the Desktop toggle or picked in the menu, it came back taking the keys typed in its pane.
479
+ - **A reconnect at a new size reconnects the same desktop.** In an SSH tab with two of a host's desktops open, one in
480
+ each pane, resizing the older pane with **Reconnect at the new size** opened the host's last used desktop there,
481
+ which went to the other pane, rather than reconnecting its own.
482
+ - **trd-pty works for a user whose uid is 2^31 or more.** It read such a uid as negative on Linux, so a session and
483
+ its client refused each other: the login went on as a plain shell, without tmux either, and the session it had
484
+ started stayed behind.
485
+ - **Removing a Hyper-V VM's desktop no longer forgets what is kept for another desktop.** Its entry was read as one for
486
+ 127.0.0.1:3389, and removing it forgot the saved password and the remembered certificate of every desktop at that
487
+ address behind an SSH host. What a VM signs in with, and its certificate, are its host's, for all of that host's
488
+ VMs, and stay, as the question before removing it now says. A desktop's address is now read the same way wherever it
489
+ is used, as it connects: removing one whose address was left empty, or whose port was written as `0` or as text such
490
+ as `"03390"`, forgets what is kept for it, where it forgot nothing; and a remote desktop profile through an SSH
491
+ profile whose port is written as text, such as `"03390"`, opens, where it said the desktop was no longer configured.
492
+
493
+ ## 0.5.0
494
+
495
+ Shared folders, desktops behind an RD Gateway, Hyper-V VMs' consoles, more of what an .rdp file says, text sent as
496
+ typed; more care with addresses that come from someone else; and fixes from a review of the code.
497
+
498
+ **New**
499
+ - **Shared folders** ([#26](https://github.com/meanaverage/tabby-rdp/issues/26)): folders from this computer appear as
500
+ drives on the remote desktop, under `\\tsclient` in Explorer, like mstsc's drive redirection. Settings › Remote
501
+ Desktop › Settings › Shared folders: **Share a folder…**, each one read-write or read-only. Every desktop you connect
502
+ to sees them; applies on the next connection. Windows mounts them (xrdp can, with FUSE); GNOME Remote Desktop
503
+ doesn't serve drives. Files move at the drive's pace through the RDP connection, so this is for working with files
504
+ in place rather than copying gigabytes; the clipboard still carries files either way. The remote gets the folder
505
+ and nothing else: `..` and symbolic links that lead out of it don't resolve, and only files and folders are served.
506
+ File operations run in the background (Node's thread pool), one request at a time, so a slow disk or network
507
+ folder slows the drive, not Tabby's window.
508
+ - **Hyper-V VMs** ([#28](https://github.com/meanaverage/tabby-rdp/issues/28)): on a Windows SSH host that runs
509
+ Hyper-V, its VMs are listed among the host's desktops (`Get-VM`, with PowerShell over the SSH connection), and one
510
+ that is off is started when opened. What opens is the VM's console, through the host (port 2179), as Hyper-V
511
+ Manager's Connect does: no network or Remote Desktop needed in the VM. A Windows guest that is up gets an enhanced
512
+ session; otherwise it is the basic console. The sign-in is the host's, asked once per host; an account the host
513
+ signs in but doesn't let open the console (it ends the connection at once) brings the form back, saying so.
514
+ - **RD Gateway** ([#29](https://github.com/meanaverage/tabby-rdp/issues/29)): a remote desktop profile, or a desktop
515
+ behind an SSH host, can name a Remote Desktop Gateway (**RD Gateway**: `rdgw.example.com`, or `host:port`). The
516
+ connection then goes to the gateway over HTTPS (its WebSocket transport, Windows Server 2012 R2 and later), signs in
517
+ there with a user name and password, and is connected on to the desktop, whose address is as the gateway sees it.
518
+ The desktop's sign-in is the gateway's too unless the profile picks a saved account for the gateway. A sign-in the
519
+ gateway refuses brings the form back saying it was the gateway, before anything goes to the desktop; a desktop its
520
+ policy doesn't allow, or that it can't reach, is an error saying which. The gateway's certificate is accepted when
521
+ valid for its name and otherwise remembered on first use; a changed one stops the connection until it is trusted.
522
+ The sign-in (NTLMv2) is bound to the gateway's TLS certificate, which gateways require by default. Smart cards,
523
+ sign-in pages and one-time codes at the gateway aren't supported.
524
+ - **.rdp files** ([#27](https://github.com/meanaverage/tabby-rdp/issues/27)): an import applies the file's display
525
+ scale (`desktopscalefactor` 150 or more becomes the desktop's Retina sharpness) and its RD Gateway
526
+ (`gatewayhostname`, unless the file turns it off), and says which of its other settings the plugin doesn't apply
527
+ (sound left on the remote or off, a fixed window size, its own drives (shared folders are a setting here), printer,
528
+ smart card or USB redirection, several monitors, RemoteApp, an account of its own or a smart card at the gateway),
529
+ instead of ignoring them silently.
530
+ - **Send text as typed** ([#31](https://github.com/meanaverage/tabby-rdp/issues/31)), a setting: the characters the
531
+ keyboard produces go to the desktop rather than key positions, so dead keys and a layout the remote doesn't have
532
+ come out right; keys with Ctrl, Alt or ⌘ still go by position, so shortcuts keep working. Off by default. Windows
533
+ types any character; a GNOME desktop only those its own layout has. Input methods (Chinese, Japanese, Korean) need
534
+ more than this and stay open in #31.
535
+ - IronRDP's web client gains drive redirection (MS-RDPEFS) through a JavaScript file system (patch 15), and its
536
+ static channels send multi-chunk messages Windows accepts (patch 16): a response over 1600 bytes was flagged for the
537
+ receiver to keep the channel header, which Windows' drive redirector didn't expect and dropped the channel on.
538
+
539
+ **Safer with addresses that come from someone else**
540
+ - **Importing an .rdp file asks first**, naming the address, the gateway and the account the file leads to, with
541
+ **Add and connect**, **Add only** and **Cancel**. It used to add the profile and connect at once. Nothing in a file
542
+ runs on this computer (and a program it names for the remote isn't asked for), but a file decides where your
543
+ sign-in goes.
544
+ - **A Windows desktop whose server doesn't use Network Level Authentication stops before the password is sent.**
545
+ Without it the password goes to the server as it is (encrypted on the way, readable to whatever answered), which a
546
+ server posing as a Windows machine can ask for; the first certificate being trusted on sight, nothing stood in the
547
+ way. The connection now stops when the server's answer says so, before TLS, and asks: **Send the password anyway**
548
+ (remembered for that desktop, shown and forgotten with its certificate under Settings › Remote Desktop ›
549
+ Certificates) or **Cancel**. xrdp signs in this way by design: desktops of the xrdp kind aren't asked about.
550
+
551
+ **Fixed**
552
+ - **Save to Downloads** couldn't be led elsewhere by the remote's file names alone, but could by a link already in
553
+ Downloads with a name the remote chose (a folder name, say). Folders are now made one at a time and must stay inside
554
+ the folder once links are followed, and each file is created new: an existing name, link or not, gets a number.
555
+ - **Large files copied from the remote** were held in memory, twice over while being saved. They now arrive in a
556
+ private temporary file and are moved into place.
557
+ - **The plugin's local proxy** (loopback, one per desktop) kept whatever a local program sent before showing the
558
+ session's token, with no limit or deadline, and an error on such a connection wasn't handled. The first message is
559
+ now capped at a request's size and has ten seconds to arrive, at most four clients connect at once, and messages
560
+ are capped at 32 MB. Reaching the server has a deadline too.
561
+ - **A connection given up while the server was being reached** (the tab closed, Cancel) left that connection open
562
+ until it finished; closing a desktop could leave an idle proxy connection behind. Both end at once now.
563
+ - **Data waiting for a slow side** was buffered without limit. The proxy now pauses the side it reads from while the
564
+ other has more than 8 MB waiting, and a desktop reached through SSH whose data isn't being read at all is closed at
565
+ 64 MB rather than growing.
566
+ - **Dropping files on a desktop after a reconnect** (a wrong password first, a certificate question) offered them
567
+ once per connection attempt, through handlers the earlier attempts left behind.
568
+ - **Shortcut modifiers could stay held on the remote:** turning on view only, or turning off typing into all
569
+ desktops, by a shortcut sent the modifiers' key-down to the remote but not their release. Keys held at that moment
570
+ are released first.
571
+ - **H.264: small changes far apart** (a clock in one corner, a cursor in another) read back everything between them:
572
+ 33 MB for a 4K picture to get a few pixels. Regions far apart are read one by one (IronRDP patch 17).
573
+ - **A desktop whose server went away could stay on screen, frozen.** Through an SSH host, a server that closes the
574
+ connection (a machine shut down, a VM stopped) is reported as the end of what it sends, and not always as closed;
575
+ the plugin waited for "closed", so the desktop sometimes stayed up, still marked connected, with no reconnect. The
576
+ end of the server's side now ends the desktop, and reconnecting takes over as for any drop.
577
+ - **Linux without an unlocked keyring: Tabby could stop opening connections.** A keychain call there never returns
578
+ and keeps one of Node's four worker threads waiting. The plugin gave the keychain up after the first such call, but
579
+ calls started together (the settings page asking whether each saved account has a password, a desktop signing in
580
+ meanwhile) each kept a thread first, and with all four taken, Tabby's file access and name lookups waited forever:
581
+ a new SSH tab stayed at "Connecting". Keychain calls now go one at a time, so at most one thread is ever kept.
582
+
3
583
  ## 0.4.1
4
584
 
5
585
  Fixes from a review of 0.4.0.