зеркало из https://github.com/github/putty.git
5 Коммитов
Автор | SHA1 | Сообщение | Дата |
---|---|---|---|
Simon Tatham | 3214563d8e |
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'! |
|
Simon Tatham | 1378bb049a |
Switch some Conf settings over to being bool.
I think this is the full set of things that ought logically to be boolean. One annoyance is that quite a few radio-button controls in config.c address Conf fields that are now bool rather than int, which means that the shared handler function can't just access them all with conf_{get,set}_int. Rather than back out the rigorous separation of int and bool in conf.c itself, I've just added a similar alternative handler function for the bool-typed ones. |
|
Simon Tatham | a6f1709c2f |
Adopt C99 <stdbool.h>'s true/false.
This commit includes <stdbool.h> from defs.h and deletes my traditional definitions of TRUE and FALSE, but other than that, it's a 100% mechanical search-and-replace transforming all uses of TRUE and FALSE into the C99-standardised lowercase spellings. No actual types are changed in this commit; that will come next. This is just getting the noise out of the way, so that subsequent commits can have a higher proportion of signal. |
|
Simon Tatham | a081dd0a4c |
Add an SFTP server to the SSH server code.
Unlike the traditional Unix SSH server organisation, the SFTP server is built into the same process as all the rest of the code. sesschan.c spots a subsystem request for "sftp", and responds to it by instantiating an SftpServer object and swapping out its own vtable for one that talks to it. (I rather like the idea of an object swapping its own vtable for a different one in the middle of its lifetime! This is one of those tricks that would be absurdly hard to implement in a 'proper' OO language, but when you're doing vtables by hand in C, it's no more difficult than any other piece of ordinary pointer manipulation. As long as the methods in both vtables expect the same physical structure layout, it doesn't cause a problem.) The SftpServer object doesn't deal directly with SFTP packet formats; it implements the SFTP server logic in a more abstract way, by having a vtable method for each SFTP request type with an appropriate parameter list. It sends its replies by calling methods in another vtable called SftpReplyBuilder, which in the normal case will write an SFTP reply packet to send back to the client. So SftpServer can focus more or less completely on the details of a particular filesystem API - and hence, the implementation I've got lives in the unix source directory, and works directly with file descriptors and struct stat and the like. (One purpose of this abstraction layer is that I may well want to write a second dummy implementation, for test-suite purposes, with completely controllable behaviour, and now I have a handy place to plug it in in place of the live filesystem.) In between sesschan's parsing of the byte stream into SFTP packets and the SftpServer object, there's a layer in the new file sftpserver.c which does the actual packet decoding and encoding: each request packet is passed to that, which pulls the fields out of the request packet and calls the appropriate method of SftpServer. It also provides the default SftpReplyBuilder which makes the output packet. I've moved some code out of the previous SFTP client implementation - basic packet construction code, and in particular the BinarySink/ BinarySource marshalling fuinction for fxp_attrs - into sftpcommon.c, so that the two directions can share as much as possible. |
|
Simon Tatham | 1d323d5c80 |
Add an actual SSH server program.
This server is NOT SECURE! If anyone is reading this commit message, DO NOT DEPLOY IT IN A HOSTILE-FACING ENVIRONMENT! Its purpose is to speak the server end of everything PuTTY speaks on the client side, so that I can test that I haven't broken PuTTY when I reorganise its code, even things like RSA key exchange or chained auth methods which it's hard to find a server that speaks at all. (For this reason, it's declared with [UT] in the Recipe file, so that it falls into the same category as programs like testbn, which won't be installed by 'make install'.) Working title is 'Uppity', partly for 'Universal PuTTY Protocol Interaction Test Yoke', but mostly because it looks quite like the word 'PuTTY' with part of it reversed. (Apparently 'test yoke' is a very rarely used term meaning something not altogether unlike 'test harness', which is a bit of a stretch, but it'll do.) It doesn't actually _support_ everything I want yet. At the moment, it's a proof of concept only. But it has most of the machinery present, and the parts it's missing - such as chained auth methods - should be easy enough to add because I've built in the required flexibility, in the form of an AuthPolicy object which can request them if it wants to. However, the current AuthPolicy object is entirely trivial, and will let in any user with the password "weasel". (Another way in which this is not a production-ready server is that it also has no interaction with the OS's authentication system. In particular, it will not only let in any user with the same password, but it won't even change uid - it will open shells and forwardings under whatever user id you started it up as.) Currently, the program can only speak the SSH protocol on its standard I/O channels (using the new FdSocket facility), so if you want it to listen on a network port, you'll have to run it from some kind of separate listening program similar to inetd. For my own tests, I'm not even doing that: I'm just having PuTTY spawn it as a local proxy process, which also conveniently eliminates the risk of anyone hostile connecting to it. The bulk of the actual code reorganisation is already done by previous commits, so this change is _mostly_ just dropping in a new set of server-specific source files alongside the client-specific ones I created recently. The remaining changes in the shared SSH code are numerous, but all minor: - a few extra parameters to BPP and PPL constructors (e.g. 'are you in server mode?'), and pass both sets of SSH-1 protocol flags from the login to the connection layer - in server mode, unconditionally send our version string _before_ waiting for the remote one - a new hook in the SSH-1 BPP to handle enabling compression in server mode, where the message exchange works the other way round - new code in the SSH-2 BPP to do _deferred_ compression the other way round (the non-deferred version is still nicely symmetric) - in the SSH-2 transport layer, some adjustments to do key derivation either way round (swapping round the identifying letters in the various hash preimages, and making sure to list the KEXINITs in the right order) - also in the SSH-2 transport layer, an if statement that controls whether we send SERVICE_REQUEST and wait for SERVICE_ACCEPT, or vice versa - new ConnectionLayer methods for opening outgoing channels for X and agent forwardings - new functions in portfwd.c to establish listening sockets suitable for remote-to-local port forwarding (i.e. not under the direction of a Conf the way it's done on the client side). |