Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mRemoteNG/PuTTYNG.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
AgeCommit message (Collapse)Author
2022-09-04Rename confusing variables in psftp_main().Simon Tatham
Another of this weekend's warnings pointed out that this function contained a pattern I now regard as a cardinal sin: variables called 'ret' that aren't clear whether they've _been_ returned from a subroutine, or whether they're _planned_ to be returned from the containing function. Worse, psftp_main had both: two of the former kind shadowing a case of the latter in sub-scopes.
2022-08-03Formatting: normalise back to 4-space indentation.Simon Tatham
In several pieces of development recently I've run across the occasional code block in the middle of a function which suddenly switched to 2-space indent from this code base's usual 4. I decided I was tired of it, so I ran the whole code base through a re-indenter, which made a huge mess, and then manually sifted out the changes that actually made sense from that pass. Indeed, this caught quite a few large sections with 2-space indent level, a couple with 8, and a handful of even weirder things like 3 spaces or 12. This commit fixes them all.
2022-07-07Centralise most details of host-key prompting.Simon Tatham
The text of the host key warnings was replicated in three places: the Windows rc file, the GTK dialog setup function, and the console.c shared between both platforms' CLI tools. Now it lives in just one place, namely ssh/common.c where the rest of the centralised host-key checking is done, so it'll be easier to adjust the wording in future. This comes with some extra automation. Paragraph wrapping is no longer done by hand in any version of these prompts. (Previously we let GTK do the wrapping on GTK, but on Windows the resource file contained a bunch of pre-wrapped LTEXT lines, and console.c had pre-wrapped terminal messages.) And the dialog heights in Windows are determined automatically based on the amount of stuff in the window. The main idea of all this is that it'll be easier to set up more elaborate kinds of host key prompt that deal with certificates (if, e.g., a server sends us a certified host key which we don't trust the CA for). But there are side benefits of this refactoring too: each tool now reliably inserts its own appname in the prompts, and also, on Windows the entire prompt text is copy-pastable. Details of implementation: there's a new type SeatDialogText which holds a set of (type, string) pairs describing the contents of a prompt. Type codes distinguish ordinary text paragraphs, paragraphs to be displayed prominently (like key fingerprints), the extra-bold scary title at the top of the 'host key changed' version of the dialog, and the various information that lives in the subsidiary 'more info' box. ssh/common.c constructs this, and passes it to the Seat to present the actual prompt. In order to deal with the different UI for answering the prompt, I've added an extra Seat method 'prompt_descriptions' which returns some snippets of text to interpolate into the messages. ssh/common.c calls that while it's still constructing the text, and incorporates the resulting snippets into the SeatDialogText. For the moment, this refactoring only affects the host key prompts. The warnings about outmoded crypto are still done the old-fashioned way; they probably ought to be similarly refactored to use this new SeatDialogText system, but it's not immediately critical for the purpose I have right now.
2021-11-26Merge be_*.c into one ifdef-controlled module.Simon Tatham
This commit replaces all those fiddly little linking modules (be_all.c, be_none.c, be_ssh.c etc) with a single source file controlled by ifdefs, and introduces a function be_list() in setup.cmake that makes it easy to compile a version of it appropriate to each application. This is a net reduction in code according to 'git diff --stat', even though I've introduced more comments. It also gets rid of another pile of annoying little source files in the top-level directory that didn't deserve to take up so much room in 'ls'. More concretely, doing this has some maintenance advantages. Centralisation means less to maintain (e.g. n_ui_backends is worked out once in a way that makes sense everywhere), and also, 'appname' can now be reliably set per program. Previously, some programs got the wrong appname due to sharing the same linking module (e.g. Plink had appname="PuTTY"), which was a latent bug that would have manifested if I'd wanted to reuse the same string in another context. One thing I've changed in this rework is that Windows pterm no longer has the ConPTY backend in its backends[]: it now has an empty one. The special be_conpty.c module shouldn't really have been there in the first place: it was used in the very earliest uncommitted drafts of the ConPTY work, where I was using another method of selecting that backend, but now that Windows pterm has a dedicated backend_vt_from_conf() that refers to conpty_backend by name, it has no need to live in backends[] at all, just as it doesn't have to in Unix pterm.
2021-11-06New Seat query, has_mixed_input_stream().Simon Tatham
(TL;DR: to suppress redundant 'Press Return to begin session' prompts in between hops of a jump-host configuration, in Plink.) This new query method directly asks the Seat the question: is the same stream of input used to provide responses to interactive login prompts, and the session input provided after login concludes? It's used to suppress the last-ditch anti-spoofing defence in Plink of interactively asking 'Access granted. Press Return to begin session', on the basis that any such spoofing attack works by confusing the user about what's a legit login prompt before the session begins and what's sent by the server after the main session begins - so if those two things take input from different places, the user can't be confused. This doesn't change the existing behaviour of Plink, which was already suppressing the antispoof prompt in cases where its standard input was redirected from something other than a terminal. But previously it was doing it within the can_set_trust_status() seat query, and I've now moved it out into a separate query function. The reason why these need to be separate is for SshProxy, which needs to give an unusual combination of answers when run inside Plink. For can_set_trust_status(), it needs to return whatever the parent Seat returns, so that all the login prompts for a string of proxy connections in session will be antispoofed the same way. But you only want that final 'Access granted' prompt to happen _once_, after all the proxy connection setup phases are done, because up until then you're still in the safe hands of PuTTY itself presenting an unbroken sequence of legit login prompts (even if they come from a succession of different servers). Hence, SshProxy unconditionally returns 'no' to the query of whether it has a single mixed input stream, because indeed, it never does - for purposes of session input it behaves like an always-redirected Plink, no matter what kind of real Seat it ends up sending its pre-session login prompts to.
2021-10-30Split seat_banner from seat_output.Simon Tatham
Previously, SSH authentication banners were displayed by calling the ordinary seat_output function, and passing it a special value in the SeatOutputType enumeration indicating an auth banner. The awkwardness of this was already showing a little in SshProxy's implementation of seat_output, where it had to check for that special value and do totally different things for SEAT_OUTPUT_AUTH_BANNER and everything else. Further work in that area is going to make it more and more awkward if I keep the two output systems unified. So let's split them up. Now, Seat has separate output() and banner() methods, which each implementation can override differently if it wants to. All the 'end user' Seat implementations use the centralised implementation function nullseat_banner_to_stderr(), which turns banner text straight back into SEAT_OUTPUT_STDERR and passes it on to seat_output. So I didn't have to tediously implement a boring version of this function in GTK, Windows GUI, consoles, file transfer etc.
2021-10-25Reorganise host key checking and confirmation.Simon Tatham
Previously, checking the host key against the persistent cache managed by the storage.h API was done as part of the seat_verify_ssh_host_key method, i.e. separately by each Seat. Now that check is done by verify_ssh_host_key(), which is a new function in ssh/common.c that centralises all the parts of host key checking that don't need an interactive prompt. It subsumes the previous verify_ssh_manual_host_key() that checked against the Conf, and it does the check against the storage API that each Seat was previously doing separately. If it can't confirm or definitively reject the host key by itself, _then_ it calls out to the Seat, once an interactive prompt is definitely needed. The main point of doing this is so that when SshProxy forwards a Seat call from the proxy SSH connection to the primary Seat, it won't print an announcement of which connection is involved unless it's actually going to do something interactive. (Not that we're printing those announcements _yet_ anyway, but this is a piece of groundwork that works towards doing so.) But while I'm at it, I've also taken the opportunity to clean things up a bit by renaming functions sensibly. Previously we had three very similarly named functions verify_ssh_manual_host_key(), SeatVtable's 'verify_ssh_host_key' method, and verify_host_key() in storage.h. Now the Seat method is called 'confirm' rather than 'verify' (since its job is now always to print an interactive prompt, so it looks more like the other confirm_foo methods), and the storage.h function is called check_stored_host_key(), which goes better with store_host_key and avoids having too many functions with similar names. And the 'manual' function is subsumed into the new centralised code, so there's now just *one* host key function with 'verify' in the name. Several functions are reindented in this commit. Best viewed with whitespace changes ignored.
2021-09-28Add -pwfile option, a more secure version of -pw.Simon Tatham
Similarly to cmdgen's passphrase options, this replaces the password on the command line with a filename to read the password out of, which means it can't show up in 'ps' or the Windows task manager.
2021-09-16seat_output: add an output type for SSH banners. (NFC)Simon Tatham
The jump host system ought really to be treating SSH authentication banners as a distinct thing from the standard-error session output, so that the former can be presented to the user in the same way as the auth banner for the main session. This change converts the 'bool is_stderr' parameter of seat_output() into an enumerated type with three values. For the moment, stderr and banners are treated the same, but the plan is for that to change.
2021-09-14Backends: notify ldisc when sendok becomes true. (NFC)Simon Tatham
I've introduced a function ldisc_notify_sendok(), which backends should call on their ldisc (if they have one) when anything changes that might cause backend_sendok() to start returning true. At the moment, the function does nothing. But in future, I'm going to make ldisc start buffering typed-ahead input data not yet sent to the backend, and then the effect of this function will be to trigger flushing all that data into the backend. Backends only have to call this function if sendok was previously false: backends requiring no network connection stage (like pty and serial) can safely return true from sendok, and in that case, they don't also have to immediately call this function.
2021-09-12New Seat method, notify_session_started().Simon Tatham
This is called by the backend to notify the Seat that the connection has progressed to the point where the main session channel (i.e. the thing that would typically correspond to the client's stdin/stdout) has been successfully set up. The only Seat that implements this method nontrivially is the one in SshProxy, which uses it as an indication that the proxied connection to the remote host has succeeded, and sends the PLUGLOG_CONNECT_SUCCESS notification to its own Plug. Hence, the only backends that need to implement it at the moment are the two SSH-shaped backends (SSH proper and bare-connection / psusan). For other backends, it's not always obvious what 'main session channel' would even mean, or whether it means anything very useful; so I've also introduced a backend flag indicating whether the backend is expecting to call that method at all, so as not to have to spend pointless effort on defining an arbitrary meaning for it in other contexts. So a lot of this patch is just introducing the new method and putting its trivial do-nothing implementation into all the existing Seat methods. The interesting parts happen in ssh/mainchan.c (which actually calls it), and sshproxy.c (which does something useful in response).
2021-09-12Divide seat_set_trust_status into query and update.Simon Tatham
This complicates the API in one sense (more separate functions), but in another sense, simplifies it (each function does something simpler). When I start putting one Seat in front of another during SSH proxying, the latter will be more important - in particular, it means you can find out _whether_ a seat can support changing trust status without having to actually attempt a destructive modification.
2021-06-27New Seat callback, seat_sent().Simon Tatham
This is used to notify the Seat that some data has been cleared from the backend's outgoing data buffer. In other words, it notifies the Seat that it might be worth calling backend_sendbuffer() again. We've never needed this before, because until now, Seats have always been the 'main program' part of the application, meaning they were also in control of the event loop. So they've been able to call backend_sendbuffer() proactively, every time they go round the event loop, instead of having to wait for a callback. But now, the SSH proxy is the first example of a Seat without privileged access to the event loop, so it has no way to find out that the backend's sendbuffer has got smaller. And without that, it can't pass that notification on to plug_sent, to unblock in turn whatever the proxied connection might have been waiting to send. In fact, before this commit, sshproxy.c never called plug_sent at all. As a result, large data uploads over an SSH jump host would hang forever as soon as the outgoing buffer filled up for the first time: the main backend (to which sshproxy.c was acting as a Socket) would carefully stop filling up the buffer, and then never receive the call to plug_sent that would cause it to start again. The new callback is ignored everywhere except in sshproxy.c. It might be a good idea to remove backend_sendbuffer() entirely and convert all previous uses of it into non-empty implementations of this callback, so that we've only got one system; but for the moment, I haven't done that.
2021-06-19New option to reject 'trivial' success of userauth.Simon Tatham
Suggested by Manfred Kaiser, who also wrote most of this patch (although outlying parts, like documentation and SSH-1 support, are by me). This is a second line of defence against the kind of spoofing attacks in which a malicious or compromised SSH server rushes the client through the userauth phase of SSH without actually requiring any auth inputs (passwords or signatures or whatever), and then at the start of the connection phase it presents something like a spoof prompt, intended to be taken for part of userauth by the user but in fact with some more sinister purpose. Our existing line of defence against this is the trust sigil system, and as far as I know, that's still working. This option allows a bit of extra defence in depth: if you don't expect your SSH server to trivially accept authentication in the first place, then enabling this option will cause PuTTY to disconnect if it unexpectedly does so, without the user having to spot the presence or absence of a fiddly little sigil anywhere. Several types of authentication count as 'trivial'. The obvious one is the SSH-2 "none" method, which clients always try first so that the failure message will tell them what else they can try, and which a server can instead accept in order to authenticate you unconditionally. But there are two other ways to do it that we know of: one is to run keyboard-interactive authentication and send an empty INFO_REQUEST packet containing no actual prompts for the user, and another even weirder one is to send USERAUTH_SUCCESS in response to the user's preliminary *offer* of a public key (instead of sending the usual PK_OK to request an actual signature from the key). This new option detects all of those, by clearing the 'is_trivial_auth' flag only when we send some kind of substantive authentication response (be it a password, a k-i prompt response, a signature, or a GSSAPI token). So even if there's a further path through the userauth maze we haven't spotted, that somehow avoids sending anything substantive, this strategy should still pick it up.
2021-05-22New Seat method, notify_remote_disconnect.Simon Tatham
This notifies the Seat that the entire backend session has finished and closed its network connection - or rather, that it _might_ have done, and that the frontend should check backend_connected() if it wasn't planning to do so already. The existing Seat implementations haven't needed this: the GUI ones don't actually need to do anything specific when the network connection goes away, and the CLI ones deal with it by being in charge of their own event loop so that they can easily check backend_connected() at every possible opportunity in any case. But I'm about to introduce a new Seat implementation that does need to know this, and doesn't have any other way to get notified of it.
2021-04-22Move the SSH implementation into its own subdirectory.Simon Tatham
This clears up another large pile of clutter at the top level, and in the process, allows me to rename source files to things that don't all have that annoying 'ssh' prefix at the top.
2021-04-19Document -ssh-connection (and -ssh) options.Jacob Nevins
2021-03-27Remove MD5 fingerprints from usage messages.Jacob Nevins
2020-11-25Document -logoverwrite and -logappend.Jacob Nevins
2020-03-11Change vtable defs to use C99 designated initialisers.Simon Tatham
This is a sweeping change applied across the whole code base by a spot of Emacs Lisp. Now, everywhere I declare a vtable filled with function pointers (and the occasional const data member), all the members of the vtable structure are initialised by name using the '.fieldname = value' syntax introduced in C99. We were already using this syntax for a handful of things in the new key-generation progress report system, so it's not new to the code base as a whole. The advantage is that now, when a vtable only declares a subset of the available fields, I can initialise the rest to NULL or zero just by leaving them out. This is most dramatic in a couple of the outlying vtables in things like psocks (which has a ConnectionLayerVtable containing only one non-NULL method), but less dramatically, it means that the new 'flags' field in BackendVtable can be completely left out of every backend definition except for the SUPDUP one which defines it to a nonzero value. Similarly, the test_for_upstream method only used by SSH doesn't have to be mentioned in the rest of the backends; network Plugs for listening sockets don't have to explicitly null out 'receive' and 'sent', and vice versa for 'accepting', and so on. While I'm at it, I've normalised the declarations so they don't use the unnecessarily verbose 'struct' keyword. Also a handful of them weren't const; now they are.
2020-03-10Add a new seat method to return the cursor position.Lars Brinkhoff
The motivation is for the SUPDUP protocol. The server may send a signal for the terminal to reset any input buffers. After this, the server will not know the state of the terminal, so it is required to send its cursor position back.
2020-02-26Fix a deadlock in SFTP upload.Simon Tatham
I tried to do an SFTP upload through connection sharing the other day and found that pscp sent some data and then hung. Now I debug it, what seems to have happened was that we were looping in sftp_recv() waiting for an SFTP packet from the remote, but we didn't have any outstanding SFTP requests that the remote was going to reply to. Checking further, xfer_upload_ready() reported true, so we _could_ have sent something - but the logic in the upload loop had a hole through which we managed to get into 'waiting for a packet' state. I think what must have happened is that xfer_upload_ready() reported false so that we entered sftp_recv(), but then the event loop inside sftp_recv() ran a toplevel callback that made xfer_upload_ready() return true. So, the fix: sftp_recv() is our last-ditch fallback, and we always try emptying our callback queue and rechecking upload_ready before we resort to waiting for a remote packet. This not only fixes the hang I observed: it also hugely improves the upload speed. My guess is that the bug must have been preventing us from filling our outgoing request pipeline a _lot_ - but I didn't notice it until the one time the queue accidentally ended up empty, rather than just sparse enough to make transfers slow. Annoyingly, I actually considered this fix back when I was trying to fix the proftpd issue mentioned in commit cd97b7e7e. I decided fixing ssh_sendbuffer() was a better idea. In fact it would have been an even better idea to do both! Oh well, better late than never.
2020-02-22Permit protocol selection in file transfer tools.Simon Tatham
PSCP and PSFTP can only work over a protocol enough like SSH to be able to run subsystems (or at the very least a remote command, for old-style PSCP). Historically we've implemented this restriction by having them not support any protocol-selection command-line options at all, and hardwiring them to instantiating ssh_backend. This commit regularises them to be more like the rest of the tools. You can select a protocol using the appropriate command-line option, provided it's a protocol in those tools' backends[] array. And the setup code will find the BackendVtable to instantiate by the usual method of calling backend_vt_from_proto. Currently, this makes essentially no difference: those tools link in be_ssh.c, which means the only supported backend is SSH. So the effect is that now -ssh is an accepted option with no effect, instead of being rejected. But it opens the way to add other protocols that are SSH-like enough to run file transfer over.
2020-02-05Fix minor memory leak in psftp batch mode.Simon Tatham
Spotted by Leak Sanitiser, while I was investigating the PSFTP / proftpd issue mentioned in the previous commit (with ASan on as usual). The two very similar loops that read PSFTP commands from the interactive prompt and a batch file differed in one respect: only one of them remembered to free the command afterwards. Now I've moved the freeing code out into a subroutine that both loops can use.
2020-02-02Make more file-scope variables static.Simon Tatham
In the previous trawl of this, I didn't bother with the statics in main-program modules, on the grounds that my main aim was to avoid 'library' objects (shared between multiple programs) from polluting the global namespace. But I think it's worth being more strict after all, so this commit adds 'static' to a lot more file-scope variables that aren't needed outside their own module.
2020-02-02Remove the GLOBAL macro itself.Simon Tatham
Now it's no longer used, we can get rid of it, and better still, get rid of every #define PUTTY_DO_GLOBALS in the many source files that previously had them.
2020-02-02Stop having a global Conf.Simon Tatham
It's now a static in the main source file of each application that uses it, and isn't accessible from any other source file unless the main one passes it by reference. In fact, there were almost no instances of the latter: only the config-box functions in windlg.c were using 'conf' by virtue of its globalness, and it's easy to make those take it as a parameter.
2020-01-30Move 'loaded_session' into cmdline.c.Simon Tatham
I haven't managed to make this one _not_ be a mutable variable, but at least it's not global across all tools any more: it lives in cmdline.c along with the code that decides what to set it to, and cmdline.c exports a query method to ask for its value.
2020-01-30Make cmdline_tooltype a const int.Simon Tatham
Another ugly mutable global variable gone: now, instead of this variable being defined in cmdline.c and written to by everyone's main(), it's defined _alongside_ everyone's main() as a constant, and cmdline.c just refers to it. A bonus is that now nocmdline.c doesn't have to define it anyway for tools that don't use cmdline.c. But mostly, it didn't need to be mutable, so better for it not to be. While I'm at it, I've also fiddled with the bit flags that go in it, to define their values automatically using a list macro instead of manually specifying each one to be a different power of 2.
2020-01-30Remove agent_schedule_callback().Simon Tatham
This is another piece of the old 2003 attempt at async agent requests. Nothing ever calls this function (in particular, the new working version of async-agent doesn't need it). Remove it completely, and all its special-window-message implementations too. (If we _were_ still using this function, then it would surely be possible to fold it into the more recently introduced general toplevel-callback system, and get rid of all this single-use special code. But we're not, so removing it completely is even easier.) In particular, this system was the only reason why Windows Plink paid any attention to its message queue. So now I can make it call plain WaitForMultipleObjects instead of MsgWaitForMultipleObjects.
2020-01-30Remove 'GLOBAL int flags' completely!Simon Tatham
It no longer has any flags in it at all, so its day is done.
2020-01-30Remove FLAG_SYNCAGENT.Simon Tatham
This was the easiest flag to remove: nothing ever checks it at all! It was part of an abandoned early attempt to make Pageant requests asynchronous. The flag was added in commit 135abf244 (April 2003); the code that used it was #ifdef-ed out in commit 98d735fde (January 2004), and removed completely in commit f864265e3 (January 2017). We now have an actually working system for async agent requests on Windows, via the new named-pipe IPC. And we also have a perfectly good way to force a particular agent request to work synchronously: just pass NULL as the callback function pointer. All of that works just fine, without ever using this flag. So begone!
2020-01-30Remove FLAG_INTERACTIVE.Simon Tatham
This is simpler than FLAG_VERBOSE: everywhere we need to check it, we have a Seat available, so we can just make it a Seat query method.
2020-01-30Remove FLAG_VERBOSE.Simon Tatham
The global 'int flags' has always been an ugly feature of this code base, and I suddenly thought that perhaps it's time to start throwing it out, one flag at a time, until it's totally unused. My first target is FLAG_VERBOSE. This was usually set by cmdline.c when it saw a -v option on the program's command line, except that GUI PuTTY itself sets it unconditionally on startup. And then various bits of the code would check it in order to decide whether to print a given message. In the current system of front-end abstraction traits, there's no _one_ place that I can move it to. But there are two: every place that checked FLAG_VERBOSE has access to either a Seat or a LogPolicy. So now each of those traits has a query method for 'do I want verbose messages?'. A good effect of this is that subsidiary Seats, like the ones used in Uppity for the main SSH server module itself and the server end of shell channels, now get to have their own verbosity setting instead of inheriting the one global one. In fact I don't expect any code using those Seats to be generating any messages at all, but if that changes later, we'll have a way to control it. (Who knows, perhaps logging in Uppity might become a thing.) As part of this cleanup, I've added a new flag to cmdline_tooltype, called TOOLTYPE_NO_VERBOSE_OPTION. The unconditionally-verbose tools now set that, and it has the effect of making cmdline.c disallow -v completely. So where 'putty -v' would previously have been silently ignored ("I was already verbose"), it's now an error, reminding you that that option doesn't actually do anything. Finally, the 'default_logpolicy' provided by uxcons.c and wincons.c (with identical definitions) has had to move into a new file of its own, because now it has to ask cmdline.c for the verbosity setting as well as asking console.c for the rest of its methods. So there's a new file clicons.c which can only be included by programs that link against both cmdline.c _and_ one of the *cons.c, and I've renamed the logpolicy to reflect that.
2019-12-24Refactor 'struct context *ctx = &actx' pattern.Simon Tatham
When I'm declaring a local instance of some context structure type to pass to a function which will pass it in turn to a callback, I've tended to use a declaration of the form struct context actx, *ctx = &actx; so that the outermost caller can initialise the context, and/or read out fields of it afterwards, by the same syntax 'ctx->foo' that the callback function will be using. So you get visual consistency between the two functions that share this context. It only just occurred to me that there's a much neater way to declare a context struct of this kind, which still makes 'ctx' behave like a pointer in the owning function, and doesn't need all that weird verbiage or a spare variable name: struct context ctx[1]; That's much nicer! I've switched to doing that in all existing cases I could find, and also in a couple of cases where I hadn't previously bothered to do the previous more cumbersome idiom.
2019-10-14Make dupcat() into a variadic macro.Simon Tatham
Up until now, it's been a variadic _function_, whose argument list consists of 'const char *' ASCIZ strings to concatenate, terminated by one containing a null pointer. Now, that function is dupcat_fn(), and it's wrapped by a C99 variadic _macro_ called dupcat(), which automatically suffixes the null-pointer terminating argument. This has three benefits. Firstly, it's just less effort at every call site. Secondly, it protects against the risk of accidentally leaving off the NULL, causing arbitrary words of stack memory to be dereferenced as char pointers. And thirdly, it protects against the more subtle risk of writing a bare 'NULL' as the terminating argument, instead of casting it explicitly to a pointer. That last one is necessary because C permits the macro NULL to expand to an integer constant such as 0, so NULL by itself may not have pointer type, and worse, it may not be marshalled in a variadic argument list in the same way as a pointer. (For example, on a 64-bit machine it might only occupy 32 bits. And yet, on another 64-bit platform, it might work just fine, so that you don't notice the mistake!) I was inspired to do this by happening to notice one of those bare NULL terminators, and thinking I'd better check if there were any more. Turned out there were quite a few. Now there are none.
2019-09-09Convert a few more universal asserts to unreachable().Simon Tatham
When I introduced the unreachable() macro in commit 0112936ef, I searched the source code for assert(0) and assert(false), together with their variant form assert(0 && "explanatory text"). But I didn't search for assert(!"explanatory text"), which is the form I used to use before finding that assert(0 && "text") seemed to be preferred in other code bases. So, here's a belated replacement of all the assert(!"stuff") macros with further instances of unreachable().
2019-09-08Whitespace rationalisation of entire code base.Simon Tatham
The number of people has been steadily increasing who read our source code with an editor that thinks tab stops are 4 spaces apart, as opposed to the traditional tty-derived 8 that the PuTTY code expects. So I've been wondering for ages about just fixing it, and switching to a spaces-only policy throughout the code. And I recently found out about 'git blame -w', which should make this change not too disruptive for the purposes of source-control archaeology; so perhaps now is the time. While I'm at it, I've also taken the opportunity to remove all the trailing spaces from source lines (on the basis that git dislikes them, and is the only thing that seems to have a strong opinion one way or the other). Apologies to anyone downstream of this code who has complicated patch sets to rebase past this change. I don't intend it to be needed again.
2019-07-10Fall back to not sorting large dirs in pscp -ls or psftp 'ls'.Simon Tatham
This mitigates a borderline-DoS in which a malicious SFTP server sends a ludicrously large number of file names in response to a SFTP opendir/readdir request sequence, causing the client to buffer them all and use up all the system's memory simply so that it can produce the output in sorted order. I call it a 'borderline' DoS because it's very likely that this is the same server that you'll also trust to actually send you the _contents_ of some entire file or directory, in which case, if they want to DoS you they can do that anyway at that point and you have no way to tell a legit very large file from a bad one. So it's unclear to me that anyone would get any real advantage out of 'exploiting' this that they couldn't have got anyway by other means. That said, it may have practical benefits in the occasional case. Imagine a _legit_ gigantic directory (something like a maildir, perhaps, and perhaps stored on a server-side filesystem specialising in not choking on really huge single directories), together with a client workflow that involves listing the whole directory but then downloading only one particular file in it. For the moment, the threshold size is fixed at 8Mb of total data (counting the lengths of the file names as well as just the number of files). If that needs to become configurable later, we can always add an option.
2019-07-06Fix assorted memory leaks.Simon Tatham
Affects command-line PuTTYgen, PSFTP, and anything running the SSH-2 userauth client layer. Tweaked version of a patch due to Tim Kosse.
2019-03-16Seat method to set the current trust status.Simon Tatham
In terminal-based GUI applications, this is passed through to term_set_trust_status, to toggle whether lines are prefixed with the new trust sigil. In console applications, the function returns false, indicating to the backend that it should employ some other technique for spoofing protection.
2019-03-09Make stripctrl_string take an existing StripCtrlChars.Simon Tatham
Now instead of making a StripCtrlChars just for that function call, it uses an existing one, pointing it at the output strbuf via stripctrl_retarget. This adds flexibility (now you can use the same convenient string- sanitising function with a StripCtrl configured in any way you like) and also saves pointless setting-up and tearing-down of identical sccs all the time. The existing call sites in PSCP and PSFTP now use a static StripCtrlChars instance that was made at program startup.
2019-03-06Add a Seat vtable method to get a stripctrl.Simon Tatham
If centralised code like the SSH implementation wants to sanitise escape sequences out of a piece of server-provided text, it will need to do it by making a locale-based StripCtrlChars if it's running in a console context, or a Terminal-based one if it's in a GUI terminal- window application. All the other changes of behaviour needed between those two contexts are handled by providing reconfigurable methods in the Seat vtable; this one is no different. So now there's a new method in the Seat vtable that will construct a StripCtrlChars appropriate to that kind of seat. Terminal-window seats (gtkwin.c, window.c) implement it by calling the new stripctrl_new_term(), and console ones use the locale- based stripctrl_new().
2019-02-28New array-growing macros: sgrowarray and sgrowarrayn.Simon Tatham
The idea of these is that they centralise the common idiom along the lines of if (logical_array_len >= physical_array_size) { physical_array_size = logical_array_len * 5 / 4 + 256; array = sresize(array, physical_array_size, ElementType); } which happens at a zillion call sites throughout this code base, with different random choices of the geometric factor and additive constant, sometimes forgetting them completely, and generally doing a lot of repeated work. The new macro sgrowarray(array,size,n) has the semantics: here are the array pointer and its physical size for you to modify, now please ensure that the nth element exists, so I can write into it. And sgrowarrayn(array,size,n,m) is the same except that it ensures that the array has size at least n+m (so sgrowarray is just the special case where m=1). Now that this is a single centralised implementation that will be used everywhere, I've also gone to more effort in the implementation, with careful overflow checks that would have been painful to put at all the previous call sites. This commit also switches over every use of sresize(), apart from a few where I really didn't think it would gain anything. A consequence of that is that a lot of array-size variables have to have their types changed to size_t, because the macros require that (they address-take the size to pass to the underlying function).
2019-02-21Remove duplicate -no-sanitise-stderr from usage().Jacob Nevins
2019-02-20File transfer tools: sanitise remote filenames and stderr.Simon Tatham
This commit adds sanitisation to PSCP and PSFTP in the same style as I've just put it into Plink. This time, standard error is sanitised without reference to whether it's redirected (at least unless you give an override option), on the basis that where Plink is _sometimes_ an SSH transport for some other protocol, PSCP and PSFTP _always_ are. But also, the sanitiser is run over any remote filename sent by the server, substituting ? for any control characters it finds. That removes another avenue for the server to deliberately confuse the display. This commit fixes our bug 'pscp-unsanitised-server-output', aka the two notional 'vulnerabilities' CVE-2019-6109 and CVE-2019-6110. (Although we regard those in isolation as only bugs, not serious vulnerabilities, because their main threat was in hiding the evidence of a server having exploited other more serious vulns that we never had.)
2019-02-07Make lots of 'int' length fields into size_t.Simon Tatham
This is a general cleanup which has been overdue for some time: lots of length fields are now the machine word type rather than the (in practice) fixed 'int'.
2019-02-07Add some missing 'const'.Simon Tatham
plug_receive(), sftp_senddata() and handle_gotdata() in particular now take const pointers. Also fixed 'char *receive_data' in struct ProxySocket.
2019-01-04Replace all 'sizeof(x)/sizeof(*x)' with lenof.Simon Tatham
I noticed a few of these in the course of preparing the previous commit. I must have been writing that idiom out by hand for _ages_ before it became totally habitual to #define it as 'lenof' in every codebase I touch. Now I've gone through and replaced all the old verbosity with nice terse lenofs.
2018-12-27pscp: replace crash with diagnostic on opendir failure.Simon Tatham
A user points out that the call to close_directory() in pscp.c's rsource() function should have been inside rather than outside the if statement that checks whether the directory handle is NULL. As a result, any failed attempt to open a directory during a 'pscp -r' recursive upload leads to a null-pointer dereference. Moved the close_directory call to where it should be, and also arranged to print the OS error code if the directory-open fails, by also changing the API of open_directory to return an error string on failure.