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
path: root/ssh
AgeCommit message (Collapse)Author
2022-10-23Restrict -pwfile / -pw to apply to server prompts only.Simon Tatham
Jacob spotted that an unused -pwfile input can be accidentally used as the answer to Plink's antispoof 'press Return to begin session' prompt, which is unintended and confusing. To fix that, I've made the use of a command-line password conditional on p->to_server, the flag in a prompts_t that indicates whether the results of the prompts are going to be sent directly to the server or consumed locally by PuTTY. (And I've also corrected the setting of to_server in the antispoof prompt, which was true when it should have been false.) A side effect of this is that -pwfile will no longer work to provide a private-key passphrase, if you're using public-key authentication without Pageant. This is deliberate, because if you're doing that on purpose then Pageant is a better way to achieve the same thing (or else just store the key unencrypted, which is no worse); but in the case of a server that sequentially demands public-key _and_ password authentication, the new behaviour makes -pwfile apply to the right one of the two prompts, i.e. the actual password.
2022-10-21Tweak certified-host-key prompt.Jacob Nevins
Add a specific reassurance that taking the add-to-cache action will not cause the CA that signed the key to be trusted in any wider context.
2022-09-17GSSAPI fix: don't pass GSS_C_NO_NAME to inquire_cred_by_mech.Simon Tatham
This was pointed out by another compiler warning. The 'name' parameter of inquire_cred_by_mech is not a gss_name_t (which is the type of GSS_C_NO_NAME); it's a gss_name_t *, because it's an _output_ parameter. We're not telling the library that we aren't _passing_ a name: we're telling it that we don't need it to _return_ us a name. So the appropriate null pointer representation is just NULL. (This was harmless apart from a compiler warning, because gss_name_t is a pointer type in turn and GSS_C_NO_NAME expands to a null pointer anyway. It was just a wrongly-typed null pointer.)
2022-09-17Unix GSSAPI: support static linking against Heimdal.Simon Tatham
Heimdal provides its own definitions of OIDs like GSS_C_NT_USER_NAME in the form of macros, which conflict with our attempt to redefine them as variables - the macro gets expanded into the middle of the variable declaration, leaving the poor C compiler trying to parse a non-declaration along the lines of const_gss_OID (&__gss_c_nt_anonymous_oid_desc) = oids+5; Easily fixed by just not redefining these at all if they're already defined as macros. To make that easier, I've broken up the oids[] array into individual gss_OID_desc declarations, so I can put each one inside the appropriate ifdef. In the process, I've removed the 'const' from the gss_OID_desc declarations. That's on purpose! The problem is that not all implementations of the GSSAPI headers make const_gss_OID a pointer to a *const* gss_OID_desc; sometimes it's just a plain one and the 'const' prefix is just a comment to the user. So removing that const prevents compiler warnings (or worse) about address-taking a const thing and assigning it into a non-const pointer.
2022-09-13GSSAPI kex: don't call dh_is_gex() on ECDH algorithms.Simon Tatham
dh_is_gex() expects to find a 'struct dh_extra' in the 'extra' field of the kex_alg you pass in, and won't look kindly on finding an instance of some totally different structure type. We were being careful about that everywhere in the GSSAPI kex code except for the final free step.
2022-09-12Standardise RFC URLs in docs and comments.Jacob Nevins
(Plus one internet-draft URL.)
2022-09-10Uppity: clear the right KEXINIT packet at kex startup!Simon Tatham
Just spotted this in eyeball review: we're about to construct our new outgoing KEXINIT and write it into the strbuf s->outgoing_kexinit. So we should clear that strbuf first. But in fact we were clearing s->client_kexinit, which aliases s->outgoing_kexinit in an SSH client, but in a server, aliases s->incoming_kexinit. This was harmless in PuTTY (since the strbuf we cleared was the right one anyway). And it was harmless in Uppity's initial kex (since the strbuf we _meant_ to clear was empty anyway). But if Uppity had ever initiated a rekey, this would have exploded messily.
2022-09-10Make rekeys work when KEXINIT filtering is enabled.Simon Tatham
I only realised this bug while writing up the feature for the wishlist: It's one thing _at connection startup_ to delay sending your KEXINIT until the server has sent its: the server is very likely to send it anyway (unless it's attempting the same workaround against us), so probably nothing goes wrong. But if we want to initiate a rekey, we do that _by_ sending a KEXINIT. In that situation we can't just wait until the server sends one, because it has no idea it's supposed to be doing so! Happily, in that situation, we already have a KEXINIT from the server, left over from the previous key exchange. So we can filter against that, and still have the intended effect of not spending KEXINIT space on algorithms the server doesn't know about.
2022-09-07Fix a batch of resource leaks spotted by Coverity.Simon Tatham
2022-09-03Add a batch of missing 'static's.Simon Tatham
2022-09-02Auth plugin: fix early socket closure.Simon Tatham
My correspondent on the new authentication-plugin feature reports that their plugin is not reliably receiving the final PLUGIN_AUTH_SUCCESS message on Windows. I _think_ this is because the whole userauth layer is being dismissed, leading to sk_close() of the Socket talking to the plugin, before the data has actually been written to the outgoing pipe. This should fix it: track the Socket's backlog, and immediately after sending that message, wait until we receive a notification that the backlog has decreased to size 0. That stops us from terminating the userauth layer until the message has left our process.
2022-09-01New feature: k-i authentication helper plugins.Simon Tatham
In recent months I've had two requests from different people to build support into PuTTY for automatically handling complicated third-party auth protocols layered on top of keyboard-interactive - the kind of thing where you're asked to enter some auth response, and you have to refer to some external source like a web server to find out what the right response _is_, which is a pain to do by hand, so you'd prefer it to be automated in the SSH client. That seems like a reasonable thing for an end user to want, but I didn't think it was a good idea to build support for specific protocols of that kind directly into PuTTY, where there would no doubt be an ever-lengthening list, and maintenance needed on all of them. So instead, in collaboration with one of my correspondents, I've designed and implemented a protocol to be spoken between PuTTY and a plugin running as a subprocess. The plugin can opt to handle the keyboard-interactive authentication loop on behalf of the user, in which case PuTTY passes on all the INFO_REQUEST packets to it, and lets it make up responses. It can also ask questions of the user if necessary. The protocol spec is provided in a documentation appendix. The entire configuration for the end user consists of providing a full command line to use as the subprocess. In the contrib directory I've provided an example plugin written in Python. It gives a set of fixed responses suitable for getting through Uppity's made-up k-i system, because that was a reasonable thing I already had lying around to test against. But it also provides example code that someone else could pick up and insert their own live response-provider into the middle of, assuming they were happy with it being in Python.
2022-09-01userauth: factor out the keyboard-interactive code.Simon Tatham
No functional change, but I've pulled the bulk of the k-i setup and prompting code out of ssh2_userauth_process_queue and into subroutines, in preparation for wanting to do the same work in more than one place in the main coroutine's control flow.
2022-09-01Pass port through to userauth.Simon Tatham
I'm going to want to use it in an upcoming commit, because together with 'savedhost', it forms the identification of an SSH server (at least as far as the host key cache is concerned, and therefore it's appropriate for other uses too). We were already passing the hostname through for use in user-facing prompts (not to mention the FQDN version for use in GSSAPI).
2022-08-30New bug workaround: KEXINIT filtering.Simon Tatham
We've occasionally had reports of SSH servers disconnecting as soon as they receive PuTTY's KEXINIT. I think all such reports have involved the kind of simple ROM-based SSH server software you find in small embedded devices. I've never been able to prove it, but I've always suspected that one possible cause of this is simply that PuTTY's KEXINIT is _too long_, either in number of algorithms listed or in total length (especially given all the ones that end in @very.long.domain.name suffixes). If I'm right about either of those being the cause, then it's just become even more likely to happen, because of all the extra Diffie-Hellman groups and GSSAPI algorithms we just threw into our already-long list in the previous few commits. A workaround I've had in mind for ages is to wait for the server's KEXINIT, and then filter our own down to just the algorithms the server also mentioned. Then our KEXINIT is no longer than that of the server, and hence, presumably fits in whatever buffer it has. So I've implemented that workaround, in anticipation of it being needed in the near future. (Well ... it's not _quite_ true that our KEXINIT is at most the same length as the server. In fact I had to leave in one KEXINIT item that won't match anything in the server's list, namely "ext-info-c" which gates access to SHA-2 based RSA. So if we turn out to support absolutely everything on all the server's lists, then our KEXINIT would be a few bytes longer than the server's, even with this workaround. But that would only cause trouble if the server's outgoing KEXINIT was skating very close to whatever buffer size it has for the incoming one, and I'm guessing that's not very likely.) ((Another possible cause of this kind of disconnection would be a server that simply objects to seeing any KEXINIT string it doesn't know how to speak. But _surely_ no such server would have survived initial testing against any full-featured client at all!))
2022-08-30Support elliptic-curve Diffie-Hellman GSS KEX.Simon Tatham
This is surprisingly simple, because it wasn't necessary to touch the GSS parts at all. Nothing changes about the message formats between integer DH and ECDH in GSS KEX, except that the mpints sent back and forth as part of integer DH are replaced by the opaque strings used in ECDH. So I've invented a new KEXTYPE and made it control a bunch of small conditionals in the middle of the GSS KEX code, leaving the rest unchanged.
2022-08-30Add RFC8268 / RFC3126 Diffie-Hellman group{15,16,17,18}.Simon Tatham
These are a new set of larger integer Diffie-Hellman fixed groups, using SHA-512 as the hash.
2022-08-30ECDH kex: remove pointless NULL check.Simon Tatham
None of the constructors can fail and return NULL. I think this must have come in with a lot of other unnecessary null-pointer checks when ECC support was first added. I've got rid of most of them since then, but that one apparently escaped my notice.
2022-08-30Fix crash in GSSAPI key exchange.Simon Tatham
Introduced recently by commit 42740a54550476e, in which I decided to call ssh_key_cache_str() even on certified host keys. But that call was conditional on s->hkey being non-NULL (which happens in GSS KEX) as well as on it not being certified, and I managed to absentmindedly remove _both_ conditions. As a result we got a null-pointer dereference on any GSS kex.
2022-08-21Fix session channel unthrottling in psusan and Uppity.Simon Tatham
I ran 'ls /usr/share/doc' in a psusan session the other day and the output hung part way through the long directory listing. This turned out to be because the ssh-connection channel window had run out temporarily, and PuTTY had sent a WINDOW_ADJUST extending it again, which the connection layer acted on by calling chan_set_input_wanted ... which sesschan was ignoring with a comment saying /* I don't think we need to do anything here */. Well, turns out we do need to. Implemented the simplest possible unblocking action.
2022-08-16Implement AES-GCM using the @openssh.com protocol IDs.Simon Tatham
I only recently found out that OpenSSH defined their own protocol IDs for AES-GCM, defined to work the same as the standard ones except that they fixed the semantics for how you select the linked cipher+MAC pair during key exchange. (RFC 5647 defines protocol ids for AES-GCM in both the cipher and MAC namespaces, and requires that you MUST select both or neither - but this contradicts the selection policy set out in the base SSH RFCs, and there's no discussion of how you resolve a conflict between them! OpenSSH's answer is to do it the same way ChaCha20-Poly1305 works, because that will ensure the two suites don't fight.) People do occasionally ask us for this linked cipher/MAC pair, and now I know it's actually feasible, I've implemented it, including a pair of vector implementations for x86 and Arm using their respective architecture extensions for multiplying polynomials over GF(2). Unlike ChaCha20-Poly1305, I've kept the cipher and MAC implementations in separate objects, with an arm's-length link between them that the MAC uses when it needs to encrypt single cipher blocks to use as the inputs to the MAC algorithm. That enables the cipher and the MAC to be independently selected from their hardware-accelerated versions, just in case someone runs on a system that has polynomial multiplication instructions but not AES acceleration, or vice versa. There's a fourth implementation of the GCM MAC, which is a pure software implementation of the same algorithm used in the vectorised versions. It's too slow to use live, but I've kept it in the code for future testing needs, and because it's a convenient place to dump my design comments. The vectorised implementations are fairly crude as far as optimisation goes. I'm sure serious x86 _or_ Arm optimisation engineers would look at them and laugh. But GCM is a fast MAC compared to HMAC-SHA-256 (indeed compared to HMAC-anything-at-all), so it should at least be good enough to use. And we've got a working version with some tests now, so if someone else wants to improve them, they can.
2022-08-16Add 'next_message' methods to cipher and MAC vtables.Simon Tatham
This provides a convenient hook to be called between SSH messages, for the crypto components to do any per-message processing like incrementing a sequence number.
2022-08-16Change the rules for how we free a linked cipher and MAC.Simon Tatham
In the situation where a MAC and cipher implementation are tied together by being facets of the same underlying object (used by the inseparable ChaCha20 + Poly1305 pair), previously we freed them by having the cipher_free function actually do the freeing, having the mac_free function do nothing, and taking great care to call those in the right order. (Otherwise, the mac_free function dereferences a no-longer-valid vtable pointer and doesn't get as far as _finding out_ that it doesn't have to do anything.) That's a time bomb in general, and especially awkward in situations like testcrypt where we don't get precise control over freeing order in any case. So I've replaced that system with one in which there are two flags in the ChaCha20-Poly1305 structure, saying whether each of the cipher and MAC facets is currently considered to be allocated. When the last of those flags is cleared, the object is actually freed. So now they can be freed in either order.
2022-08-07Documentation for OpenSSH certificates.Simon Tatham
Also I've filled in the help contexts in all the new GUI controls.
2022-08-05Certificate-aware handling of key fingerprints.Simon Tatham
OpenSSH, when called on to give the fingerprint of a certified public key, will in many circumstances generate the hash of the public blob of the _underlying_ key, rather than the hash of the full certificate. I think the hash of the certificate is also potentially useful (if nothing else, it provides a way to tell apart multiple certificates on the same key). But I can also see that it's useful to be able to recognise a key as the same one 'really' (since all certificates on the same key share a private key, so they're unavoidably related). So I've dealt with this by introducing an extra pair of fingerprint types, giving the cross product of {MD5, SHA-256} x {base key only, full certificate}. You can manually select which one you want to see in some circumstances (notably PuTTYgen), and in others (such as diagnostics) both fingerprints will be emitted side by side via the new functions ssh2_double_fingerprint[_blob]. The default, following OpenSSH, is to just fingerprint the base key.
2022-08-03Formatting: miscellaneous.Simon Tatham
This patch fixes a few other whitespace and formatting issues which were pointed out by the bulk-reindent or which I spotted in passing, some involving manual editing to break lines more nicely. I think the weirdest hunk in here is the one in windows/window.c TranslateKey() where _half_ of an assignment statement inside an 'if' was on the same line as the trailing paren of the if condition. No idea at all how that one managed to happen!
2022-08-03Formatting: remove spurious spaces in 'type * var'.Simon Tatham
I think a lot of these were inserted by a prior run through GNU indent many years ago. I noticed in a more recent experiment that that tool doesn't always correctly distinguish which instances of 'id * id' are pointer variable declarations and which are multiplications, so it spaces some of the former as if they were the latter.
2022-08-03Formatting: standardise on "func(\n", not "func\n(".Simon Tatham
If the function name (or expression) in a function call or declaration is itself so long that even the first argument doesn't fit after it on the same line, or if that would leave so little space that it would be silly to try to wrap all the run-on lines into a tall thin column, then I used to do this ludicrously_long_function_name (arg1, arg2, arg3); and now prefer this ludicrously_long_function_name( arg1, arg2, arg3); I picked up the habit from Python, where the latter idiom is required by Python's syntactic significance of newlines (you can write the former if you use a backslash-continuation, but pretty much everyone seems to agree that that's much uglier). But I've found it works well in C as well: it makes it more obvious that the previous line is incomplete, it gives you a tiny bit more space to wrap the following lines into (the old idiom indents the _third_ line one space beyond the second), and I generally turn out to agree with the knock-on indentation decisions made by at least Emacs if you do it in the middle of a complex expression. Plus, of course, using the _same_ idiom between C and Python means less state-switching. So, while I'm making annoying indentation changes in general, this seems like a good time to dig out all the cases of the old idiom in this code, and switch them over to the new.
2022-08-03Formatting: realign run-on parenthesised stuff.Simon Tatham
My bulk indentation check also turned up a lot of cases where a run-on function call or if statement didn't have its later lines aligned correctly relative to the open paren. I think this is quite easy to do by getting things out of sync (editing the first line of the function call and forgetting to update the rest, perhaps even because you never _saw_ the rest during a search-replace). But a few didn't quite fit into that pattern, in particular an outright misleading case in unix/askpass.c where the second line of a call was aligned neatly below the _wrong_ one of the open parens on the opening line. Restored as many alignments as I could easily find.
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-17Allow manually confirming and caching certified keys.Simon Tatham
In the case where a server presents a host key signed by a different certificate from the one you've configured, it need not _always_ be evidence of wrongdoing. I can imagine situations in which two CAs cover overlapping sets of things, and you don't want to blanket-trust one of them, but you do want to connect to a specific host signed by that one. Accordingly, PuTTY's previous policy of unconditionally aborting the connection if certificate validation fails (which was always intended as a stopgap until I thought through what I wanted to replace it with) is now replaced by fallback handling: we present the host key fingerprint to the user and give them the option to accept and/or cache it based on the public key itself. This means that the certified key types have to have a representation in the host key cache. So I've assigned each one a type id, and generate the cache string itself by simply falling back to the base key. (Rationale for the latter: re-signing a public key with a different certificate doesn't change the _private_ key, or the set of valid signatures generated with it. So if you've been convinced for reasons other than the certificate that a particular private key is in the possession of $host, then proof of ownership of that private key should be enough to convince you you're talking to $host no matter what CA has signed the public half this week.) We now offer to receive a given certified host key type if _either_ we have at least one CA configured to trust that host, _or_ we have a certified key of that type cached. (So once you've decided manually that you trust a particular key, we can still receive that key and authenticate the host with it, even if you later delete the CA record that it didn't match anyway.) One change from normal (uncertified) host key handling is that for certified key types _all_ the host key prompts use the stronger language, with "WARNING - POTENTIAL SECURITY BREACH!" rather than the mild 'hmm, we haven't seen this host before'. Rationale: if you expected this CA key and got that one, it _could_ be a bold-as-brass MITM attempt in which someone hoped you'd accept their entire CA key. The mild wording is only for the case where we had no previous expectations _at all_ for the host to violate: not a CA _or_ a cached key.
2022-07-16Fix typo in #undef.Simon Tatham
In the macro automation for ssh2_bpp_check_unimplemented, I #defined SSH2_BITMAP_WORD, and 20 lines later, tried to #undef it by the wrong spelling. Of course this gave no error, so I didn't notice! But I spotted it just now, so let's fix it.
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.
2022-06-25Certificate trust scope: change to a boolean-expression system.Simon Tatham
This replaces the previous placeholder scheme of having a list of hostname wildcards with implicit logical-OR semantics (if any wildcard matched then the certificate would be trusted to sign for that host). That scheme didn't allow for exceptions within a domain ('everything in example.com except extra-high-security-machine.example.com'), and also had no way to specify port numbers. In the new system, you can still write a hostname wildcard by itself in the simple case, but now those are just atomic subexpressions in a boolean-logic domain-specific language I've made up. So if you want multiple wildcards, you can separate them with || in a single longer expression, and also you can use && and ! to impose exceptions on top of that. Full details of the expression language are in the comment at the top of utils/cert-expr.c. It'll need documenting properly before release, of course. For the sake of backwards compatibility for early adopters who've already set up configuration in the old system, I've put in some code that will read the old MatchHosts configuration and automatically translate it into the equivalent boolean expression (by simply stringing together the list of wildcards with || between them).
2022-05-07CA config box: fully validate the CA public key.Simon Tatham
Now we check that we can actually make an ssh_key out of it, and moreover, that the key is of a sensible kind (i.e. not a certificate in turn). If that's not true, we report something about the problem in a new CTRL_TEXT below the public key input box. If the key _is_ valid, that same text control is used to show its type, length and fingerprint. On Windows, I've widened the dialog box a little to make fingerprints fit sensibly in it.
2022-05-05CA config box: add some align_next_to.Simon Tatham
Now the RSA signature-type checkboxes should be aligned with their label; the 'Add' and 'Remove' buttons for wildcards should align with the edit box for entering a wildcard; and the 'Load from file' button for a public key aligns with the edit box for that.
2022-05-04Merge global request queue fix from 'pre-0.77'.Simon Tatham
2022-05-04Fix linked-list mismanagement in global request queue.Simon Tatham
When we linked a new entry on to the global request queue, we forgot to set its next pointer to NULL, so that when it was removed again, s->globreq_head could end up pointing to nonsense. In addition, even if the next pointer happened to be NULL by luck, we also did not notice that s->globreq_head had become NULL and respond by nulling out s->globreq_tail, which would leave s->globreq_tail as a stale pointer to the just-freed list element, causing a memory access error on the next attempt to link something on to the list. This could come up in the situation where you open Change Settings and configure a remote port forwarding, close it (so that the global request is sent, queued, replied to, and unqueued again), and then reopen Change Settings and configure a second one (so that the linked list in the confused state actually gets used).
2022-05-02Fix null-pointer dereferences in CA config.Simon Tatham
Introduced in dc7ba12253c68d1 earlier today. On GTK these caused no problems worse than a GTK warning, but I'd better fix them before they (potentially) do worse on Windows!
2022-05-02Add some blank lines in setup_ca_config_box.Simon Tatham
It's becoming hard to see what's going on in all that control setup.
2022-05-02Permit configuring RSA signature types in certificates.Simon Tatham
As distinct from the type of signature generated by the SSH server itself from the host key, this lets you exclude (and by default does exclude) the old "ssh-rsa" SHA-1 signature type from the signature of the CA on the certificate.
2022-05-01CA config: protect against saving a key with no wildcards.Simon Tatham
2022-05-01CA config: permit pasting a whole OpenSSH public key.Simon Tatham
Now, we try putting the contents of the public-key edit box through ppk_load_s if it isn't a plain base64-encoded string.
2022-05-01CA config: make the 'Done' button cancel and not default.Simon Tatham
This means that, on the one hand, an absentminded press of Return doesn't dismiss the entire CA config box, which would be pretty annoying if you were half way through entering a load of fiddly stuff. And on the other hand, you _can_ press Escape to dismiss the box, which is less likely to happen by accident.
2022-05-01CA config box: add a 'Read from file' button.Simon Tatham
This allows you to load a CA public key from a disk file (in any format acceptable to ppk_load_pub, which means OpenSSH one-line public keys and also RFC4716 ones).
2022-05-01Move host CA config box out into its own source file.Simon Tatham
In the course of polishing up this dialog box, I'm going to want it to actually do cryptographic things (such as checking validity of a public key blob and printing its fingerprint), which means it will need to link against SSH utility functions. So I've moved the dialog-box setup and handling code out of config.c into a new file in the ssh subdirectory and in the ssh library, where those facilities will be conveniently available. This also means that dialog-box setup code _won't_ be linked into PuTTYtel or pterm (on either platform), so I've added a stub source file to provide its entry-point function in those tools. Also, provided a const bool to indicate whether that dialog is available, which we use to decide whether to recognise that command-line option.
2022-04-30Fix rekeying when using a certified host key.Simon Tatham
In a rekey, we expect to see the same host key again, which we enforce by comparing its cache string, which we happened to have handy. But certified host keys don't have cache strings, so this no longer works reliably - the 'assert(s->keystr)' fails. (This is what I get for making a zillion short-lived test connections and not leaving any of them running for more than 2 minutes!) Instead, we now keep the official public blob of the host key from the first key exchange, and compare that to the public blob of the one in the rekey.
2022-04-29ssh/verstring.c: fix use of '\r' and '\n'.Simon Tatham
It's a thoroughly pedantic point, but I just spotted that the comparison of wire data against theoretically platform-dependent char escapes is a violation of \k{udp-portability}.
2022-04-28ssh2_scan_kexinits: dynamically allocate server_hostkeys[].Simon Tatham
In commit 7d44e35bb3780c0 I introduced a bug: we were providing an array of MAXKEXLIST ints to ssh2_scan_kexinits() to write a list of server-supplied host keys into, and when MAXKEXLIST stopped being a thing, I mindlessly replaced it with an array dynamically allocated to the number of host key types we'd offered the server. But we return a list of host key types the _server_ offered _us_ (and that we can speak at all), which isn't necessarily the same thing. In particular, if you deliberately ask to cache a new host key type from the specials menu, we send a KEXINIT offering just _one_ host key type, namely the one you've asked for. But that loop still writes down all the key types it gets back from the server, which is (almost certainly) more than one. So the array overflows. In that situation we don't really need the returned array of key types at all, but it's easier to just make it work than to add conditionals. Replaced it with a dynamically grown array in the usual sort of way.
2022-04-25Initial support for host certificates.Simon Tatham
Now we offer the OpenSSH certificate key types in our KEXINIT host key algorithm list, so that if the server has a certificate, they can send it to us. There's a new storage.h abstraction for representing a list of trusted host CAs, and which ones are trusted to certify hosts for what domains. This is stored outside the normal saved session data, because the whole point of host certificates is to avoid per-host faffing. Configuring this set of trusted CAs is done via a new GUI dialog box, separate from the main PuTTY config box (because it modifies a single set of settings across all saved sessions), which you can launch by clicking a button in the 'Host keys' pane. The GUI is pretty crude for the moment, and very much at a 'just about usable' stage right now. It will want some polishing. If we have no CA configured that matches the hostname, we don't offer to receive certified host keys in the first place. So for existing users who haven't set any of this up yet, nothing will immediately change. Currently, if we do offer to receive certified host keys and the server presents one signed by a CA we don't trust, PuTTY will bomb out unconditionally with an error, instead of offering a confirmation box. That's an unfinished part which I plan to fix before this goes into a release.