From e52087719c4e185e433f7b5b1fb8383b4d910c2e Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sun, 7 Aug 2022 12:06:36 +0100 Subject: [PATCH] Documentation for OpenSSH certificates. Also I've filled in the help contexts in all the new GUI controls. --- config.c | 5 +- doc/config.but | 164 +++++++++++++++++++++++++++++++++++++++++++ doc/errors.but | 33 +++++++++ doc/index.but | 5 ++ doc/man-pageant.but | 6 ++ doc/man-puttygen.but | 36 +++++++++- doc/pageant.but | 9 +++ doc/pubkey.but | 42 +++++++++++ doc/using.but | 22 ++++++ ssh/ca-config.c | 31 ++++---- ssh/common.c | 9 +-- windows/help.h | 5 ++ 12 files changed, 346 insertions(+), 21 deletions(-) diff --git a/config.c b/config.c index f77384d5..59b6976a 100644 --- a/config.c +++ b/config.c @@ -2835,7 +2835,8 @@ void setup_config_box(struct controlbox *b, bool midsession, s = ctrl_getset(b, "Connection/SSH/Host keys", "ca", "Configure trusted certification authorities"); c = ctrl_pushbutton(s, "Configure host CAs", NO_SHORTCUT, - HELPCTX(no_help), host_ca_button_handler, I(0)); + HELPCTX(ssh_kex_cert), + host_ca_button_handler, I(0)); if (!midsession || !(protcfginfo == 1 || protcfginfo == -1)) { /* @@ -2909,7 +2910,7 @@ void setup_config_box(struct controlbox *b, bool midsession, conf_filesel_handler, I(CONF_keyfile)); ctrl_filesel(s, "Certificate to use with the private key:", 'e', NULL, false, "Select certificate file", - HELPCTX(ssh_auth_privkey), + HELPCTX(ssh_auth_cert), conf_filesel_handler, I(CONF_detached_cert)); #ifndef NO_GSSAPI diff --git a/doc/config.but b/doc/config.but index 66d57711..28da9638 100644 --- a/doc/config.but +++ b/doc/config.but @@ -2610,6 +2610,142 @@ neither read \e{nor written}, unless you explicitly do so. If the box is empty (as it usually is), then PuTTY's automated host key management will work as normal. +\S{config-ssh-kex-cert} Configuring PuTTY to accept host \i{certificates} + +In some environments, the SSH host keys for a lot of servers will all +be signed in turn by a central \q{certification authority} (\q{CA} for +short). This simplifies host key configuration for users, because if +they configure their SSH client to accept host keys certified by that +CA, then they don't need to individually confirm each host key the +first time they connect to that server. + +In order to do this, press the \q{Configure host CAs} button in the +\q{Host keys} configuration panel. This will launch a secondary +configuration dialog box where you can configure what CAs PuTTY will +accept signatures from. + +\s{Note that this configuration is common to all saved sessions}. +Everything in the main PuTTY configuration is specific to one saved +session, and you can prepare a separate session with all the +configuration different. But there's only one copy of the host CA +configuration, and it applies to all sessions PuTTY runs, whether +saved or not. + +(Otherwise, it would be useless \dash configuring a CA by hand for +each new host wouldn't be any more convenient than pressing the +\q{confirm} button for each new host's host key.) + +To set up a new CA using this config box: + +First, load the CA's public key from a file, or paste it directly into +the \q{Public key of certification authority} edit box. If your +organisation signs its host keys in this way, they will publish the +public key of their CA so that SSH users can include it in their +configuration. + +Next, in the \q{Valid hosts this key is trusted to certify} box, +configure at least one hostname wildcard to say what servers PuTTY +should trust this CA to speak for. For example, suppose you work for +Example Corporation (\cw{example.com}), and the Example Corporation IT +department has advertised a CA that signs all the Example internal +machines' host keys. Then probably you want to trust that CA to sign +host keys for machines in the domain \cw{example.com}, but not for +anything else. So you might enter \cq{*.example.com} into the \q{Valid +hosts} box. + +\s{It's important to limit what the CA key is allowed to sign}. Don't +just enter \cq{*} in that box! If you do that, you're saying that +Example Corporation IT department is authorised to sign a host key for +\e{anything at all} you might decide to connect to \dash even if +you're connecting out of the company network to a machine somewhere +else, such as your own personal server. So that configuration would +enable the Example IT department to act as a \q{man-in-the-middle} +between your PuTTY process and your server, and listen in to your +communications \dash exactly the thing SSH is supposed to avoid. + +So, if the CA was provided to you by the sysadmins responsible for +\cw{example.com} (or whatever), make sure PuTTY will \e{only} trust it +for machines in the \cw{example.com} domain. + +For the full syntax of the \q{Valid hosts} expression, see +\k{config-ssh-cert-valid-expr}. + +Finally, choose an identifying name for this CA; enter that name in +the \q{Name for this CA} edit box at the top of the window, and press +\q{Save} to record the CA in your configuration. The name you chose +will appear in the list of saved CAs to the left of the \q{Save} +button. + +The identifying name can be anything you like. It's there so that if +you store multiple certificates you can tell which is which later when +you want to edit or delete them. It also appears in the PuTTY Event +Log when a server presents a certificate signed by that CA. + +To reload an existing CA configuration, select it in the list box and +press \q{Load}. Then you can make changes, and save it again. + +To remove a CA from your configuration completely, select it in the +list and press \q{Delete}. + +\S2{config-ssh-cert-valid-expr} Expressions you can enter in \q{Valid +hosts} + +The simplest thing you can enter in the \q{Valid hosts this key is +trusted to certify} edit box is just a hostname wildcard such as +\cq{*.example.com}. But you can also enter multiple host name +wildcards, and port number ranges, and make complicated Boolean +expressions out of them using the operators \cq{&&} for \q{and}, +\cq{||} for \q{or}, \cq{!} for \q{not}, and parentheses. + +For example, here are some other things you could enter. + +\b \cq{*.foo.example.com || *.bar.example.com}. This means the CA is +trusted to sign the host key for a connection if the host name matches +\q{*.foo.example.com} \e{or} it matches \q{*.bar.example.com}. In +other words, the CA has authority over those two particular subdomains +of \cw{example.com}, but not for anything else, like +\cw{www.example.com}. + +\b \cq{*.example.com && ! *.extrasecure.example.com}. This means the +CA is trusted to sign the host key for a connection if the host name +matches \q{*.example.com} \e{but does not} match +\q{*.extrasecure.example.com}. (Imagine if there was one top-secret +set of servers in your company that the main IT department didn't have +security clearance to administer.) + +\b \cq{*.example.com && port:22}. This means the CA is trusted to sign +the host key for a connection if the host name matches +\q{*.example.com} \e{and} the port number is 22. SSH servers running +on other ports would not be covered. + +\b \cq{(*.foo.example.com || *.bar.example.com) && port:0-1023}. This +matches two subdomains of \cw{example.com}, as before, but \e{also} +restricts the port number to the range 0-1023. + +A certificate configuration expression consists of one or more +individual requirements which can each be a hostname wildcard, a +single port number, or a port number range, combined together with +these Boolean operators. + +Unlike other languages such as C, there is no implied priority between +\cq{&&} and \cq{||}. If you write \cq{A && B || C} (where \cw{A}, +\cw{B} and \cw{C} are some particular requirements), then PuTTY will +report a syntax error, because you haven't said which of the \cq{&&} +and \cq{||} takes priority tightly. You will have to write either +\cq{(A && B) || C}, meaning \q{both of \cw{A} and \cw{B}, or +alternatively just \cw{C}}, or \cq{A && (B || C)} (\q{\cw{A}, and also +at least one of \cw{B} and \cw{C}}), to make it clear. + +\S2{config-ssh-cert-rsa-hash} RSA signature types in certificates + +RSA keys can be used to generate signatures with a choice of secure +hash function. Typically, any version of OpenSSH new enough to support +certificates at all will also be new enough to avoid using SHA-1, so +the default settings of accepting the more modern SHA-256 and SHA-512 +should be suitable for nearly all cases. For completeness, however, +you can configure which types of RSA signature PuTTY will accept in a +certificate from a CA using an RSA key. + \H{config-ssh-encryption} The Cipher panel PuTTY supports a variety of different \i{encryption algorithm}s, and @@ -2849,6 +2985,34 @@ in this case (in RFC 4716 or OpenSSH format), as that's sufficient to identify the key to Pageant, but of course if Pageant isn't present PuTTY can't fall back to using this file itself. +\S{config-ssh-cert} \q{\ii{Certificate} to use with the private key} + +In some environments, user authentication keys can be signed in turn +by a \q{certifying authority} (\q{CA} for short), and user accounts on +an SSH server can be configured to automatically trust any key that's +certified by the right signature. + +This can be a convenient setup if you have a very large number of +servers. When you change your key pair, you might otherwise have to +edit the \cw{authorized_keys} file on every server individually, to +make them all accept the new key. But if instead you configure all +those servers \e{once} to accept keys signed as yours by a CA, then +when you change your public key, all you have to do is to get the new +key certified by the same CA as before, and then all your servers will +automatically accept it without needing individual reconfiguration. + +One way to use a certificate is to incorporate it into your private +key file. \K{puttygen-cert} explains how to do that using PuTTYgen. +But another approach is to tell PuTTY itself where to find the public +certificate file, and then it will automatically present that +certificate when authenticating with the corresponding private key. + +To do this, enter the pathname of the certificate file into the +\q{Certificate to use with the private key} file selector. + +When this setting is configured, PuTTY will honour it no matter +whether the private key is found in a file, or loaded into Pageant. + \H{config-ssh-auth-gssapi} The \i{GSSAPI} panel The \q{GSSAPI} subpanel of the \q{Auth} panel controls the use of diff --git a/doc/errors.but b/doc/errors.but index 27e2ae32..cea3201c 100644 --- a/doc/errors.but +++ b/doc/errors.but @@ -52,6 +52,39 @@ in the same way as you would if it was new. See \k{gs-hostkey} for more information on host keys. +\H{errors-cert-mismatch} \q{This server presented a certified host key +which was signed by a different certification authority ...} + +If you've configured PuTTY to trust at least one +\I{certificate}certification authority for signing host keys (see +\k{config-ssh-kex-cert}), then it will ask the SSH server to send it +any available certified host keys. If the server sends back a +certified key signed by a \e{different} certification authority, PuTTY +will present this variant of the host key prompt. + +One reason why this can happen is a deliberate attack. Just like an +ordinary man-in-the-middle attack which substitutes a wrong host key, +a particularly ambitious attacker might substitute an entire wrong +certification authority, and hope that you connect anyway. + +But it's also possible in some situations that this error might arise +legitimately. For example, if your organisation's IT department has +just rolled out a new CA key which you haven't yet entered in PuTTY's +configuration, or if your CA configuration involves two overlapping +domains, or something similar. + +So, unfortunately, you'll have to work out what to do about it +yourself: install a new CA key (if you're really sure you trust it), +or edit your configuration in some other way, or abandon the +connection. + +If you're convinced that this particular server is legitimate even +though the CA is not one you trust, PuTTY will let you cache the +certified host key in the same way as an uncertified one. Then that +particular certificate will be accepted on the next connection, even +though other certificates signed by the same CA will still be +rejected. + \H{errors-ssh-protocol} \q{SSH protocol version 2 required by our configuration but remote only provides (old, insecure) SSH-1} diff --git a/doc/index.but b/doc/index.but index 4c76bb05..cc043d5a 100644 --- a/doc/index.but +++ b/doc/index.but @@ -942,3 +942,8 @@ saved sessions from \IM{shifted arrow keys} arrow keys, shifted \IM{shifted arrow keys} shifted arrow keys + +\IM{certificate}{certificates} certificates, SSH +\IM{certificate}{certificates} SSH certificates +\IM{certificate}{certificates} OpenSSH certificates +\IM{certificate}{certificates} CA (certification authority) diff --git a/doc/man-pageant.but b/doc/man-pageant.but index 3f407a47..d202f166 100644 --- a/doc/man-pageant.but +++ b/doc/man-pageant.but @@ -256,6 +256,12 @@ be matched \dd to indicate that it is a fingerprint of a specific format +\dt \cq{sha256-cert:} or \cq{md5-cert:} + +\dd to indicate that it is a fingerprint of a specific format, and +specifically matches the fingerprint of the public key \e{including} a +certificate if any + } \dt \cw{--public-openssh} \e{key-identifiers}, \cw{-L} \e{key-identifiers} diff --git a/doc/man-puttygen.but b/doc/man-puttygen.but index 021af205..092f05c0 100644 --- a/doc/man-puttygen.but +++ b/doc/man-puttygen.but @@ -143,6 +143,18 @@ to type). automatic when you are generating a new key, but not when you are modifying an existing key. +\dt \cw{\-\-certificate} \e{certificate-file} + +\dd Adds an OpenSSH-style certificate to the public half of the key, +so that the output file contains a certified public key with the same +private key. If the input file already contained a certificate, it +will be replaced with the new one. + +\dt \cw{\-\-remove\-certificate} + +\dd Removes any certificate that was part of the key, to recover the +uncertified version of the underlying key. + \dt \cw{\-\-reencrypt} \dd For an existing private key saved with a passphrase, refresh the @@ -260,6 +272,13 @@ newer format even for RSA, DSA, and ECDSA keys. \dd Save an SSH-2 private key in ssh.com's format. This option is not permitted for SSH-1 keys. +\dt \cw{cert-info} + +\dd Save a textual dump of information about the certificate on the +key, if any: whether it's a host or a user certificate, what host(s) +or user(s) it's certified to be, its validity period, ID and serial +number, and the fingerprint of the signing CA. + \dt \cw{text} \dd Save a textual dump of the numeric components comprising the key @@ -298,6 +317,10 @@ fingerprint. Otherwise, the \c{\-o} option is required. \dd Synonym for \q{\cw{-O public}}. +\dt \cw{\-\-cert\-info} + +\dd Synonym for \q{\cw{-O cert-info}}. + \dt \cw{\-\-dump} \dd Synonym for \q{\cw{-O text}}. @@ -305,7 +328,18 @@ fingerprint. Otherwise, the \c{\-o} option is required. \dt \cw{-E} \e{fptype} \dd Specify the algorithm to use if generating a fingerprint. The -options are \cw{sha256} (the default) and \cw{md5}. +available algorithms are are \cw{sha256} (the default) and \cw{md5}. + +\lcont{ + +By default, when showing the fingerprint of a public key that includes +a certificate, \c{puttygen} will not include the certificate, so that +the fingerprint shown will be the same as the underlying public key. +If you want the fingerprint including the certificate (for example, so +as to tell two certified keys apart), you can specify \cw{sha256-cert} +or \cw{md5-cert} as the fingerprint type. + +} \dt \cw{\-\-new\-passphrase} \e{file} diff --git a/doc/pageant.but b/doc/pageant.but index c94b88d6..206811f5 100644 --- a/doc/pageant.but +++ b/doc/pageant.but @@ -90,6 +90,15 @@ By default this is shown in the \q{SHA256} format. You can change to the older \q{MD5} format (which looks like \c{aa:bb:cc:...}) with the \q{Fingerprint type} drop-down, but bear in mind that this format is less secure and should be avoided for comparison purposes where possible. + +If some of the keys loaded into Pageant have certificates attached, +then Pageant will default to showing the fingerprint of the underlying +key. This way, a certified and uncertified version of the same key +will have the same fingerprint, so you can see that they match. You +can instead use the \q{Fingerprint type} drop-down to ask for a +different fingerprint to be shown for certified keys, which includes +the certificate as part of the fingerprinted data. That way you can +tell two certificates apart. } \b The comment attached to the key. diff --git a/doc/pubkey.but b/doc/pubkey.but index 80382076..539b55b4 100644 --- a/doc/pubkey.but +++ b/doc/pubkey.but @@ -307,6 +307,48 @@ a result. \e{Do not forget your passphrase}. There is no way to recover it. +\S{puttygen-cert} Adding a \i{certificate} to your key + +In some environments, user authentication keys can be signed in turn +by a \q{certifying authority} (\q{CA} for short), and user accounts on +an SSH server can be configured to automatically trust any key that's +certified by the right signature. + +This can be a convenient setup if you have a very large number of +servers. When you change your key pair, you might otherwise have to +edit the \cw{authorized_keys} file on every server individually, to +make them all accept the new key. But if instead you configure all +those servers \e{once} to accept keys signed as yours by a CA, then +when you change your public key, all you have to do is to get the new +key certified by the same CA as before, and then all your servers will +automatically accept it without needing individual reconfiguration. + +To get your key signed by a CA, you'll probably send the CA the new +\e{public} key (not the private half), and get back a modified version +of the public key with the certificate included. + +If you want to incorporate the certificate into your PPK file for +convenience, you can use the \q{Add certificate to key} menu option in +PuTTYgen's \q{Key} menu. This will give you a single file containing +your private key and the certificate, which is everything you need to +authenticate to a server prepared to accept that certificate. + +To remove the certificate again and restore the uncertified PPK file, +there's also a \q{Remove certificate from key} option. + +(However, you don't \e{have} to incorporate the certificate into your +PPK file. You can equally well use it separately, via the +\q{Certificate to use with the private key} option in PuTTY itself. +See \k{config-ssh-cert}. It's up to you which you find more +convenient.) + +When the currently loaded key in PuTTYgen contains a certificate, the +large \q{Public key for pasting} edit box (see \k{puttygen-pastekey}) +is replaced by a button that brings up an information box telling you +about the certificate, such as who it certifies your key as belonging +to, when it expires (if ever), and the fingerprint of the CA key that +signed it in turn. + \S{puttygen-savepriv} Saving your private key to a disk file Once you have generated a key, set a comment field and set a diff --git a/doc/using.but b/doc/using.but index d5cf41c4..5865ac95 100644 --- a/doc/using.but +++ b/doc/using.but @@ -1024,6 +1024,19 @@ This option is equivalent to the \q{Private key file for authentication} box in the Auth panel of the PuTTY configuration box (see \k{config-ssh-privkey}). +\S2{using-cmdline-cert} \i\c{-cert}: specify an SSH \i{certificate} + +The \c{-cert} option allows you to specify the name of a certificate +file containing a signed version of your public key. If you specify +this option, PuTTY will present that certificate in place of the plain +public key, whenever it tries to authenticate with a key that matches. +(This applies whether the key is stored in Pageant or loaded directly +from a file by PuTTY.) + +This option is equivalent to the \q{Certificate to use with the +private key} box in the Auth panel of the PuTTY configuration box (see +\k{config-ssh-cert}). + \S2{using-cmdline-no-trivial-auth} \i\c{-no-trivial-auth}: disconnect if SSH authentication succeeds trivially @@ -1162,3 +1175,12 @@ the extra protection), so it's reasonable to want to run Pageant but not PuTTY with the ACL restrictions. You can force Pageant to start subsidiary PuTTY processes with a restricted ACL if you also pass the \i\c{-restrict-putty-acl} option. + +\S2{using-cmdline-host-ca} \i{\c{-host-ca}}: launch the +\I{certificate}host CA configuration + +If you start PuTTY with the \c{-host-ca} option, it will not launch a +session at all. Instead, it will just display the configuration dialog +box for host certification authorities, as described in +\k{config-ssh-kex-cert}. When you dismiss that dialog box, PuTTY will +terminate. diff --git a/ssh/ca-config.c b/ssh/ca-config.c index 350613df..8c180b36 100644 --- a/ssh/ca-config.c +++ b/ssh/ca-config.c @@ -412,7 +412,7 @@ void setup_ca_config_box(struct controlbox *b) /* Action area, with the Done button in it */ s = ctrl_getset(b, "", "", ""); ctrl_columns(s, 5, 20, 20, 20, 20, 20); - c = ctrl_pushbutton(s, "Done", 'o', HELPCTX(no_help), + c = ctrl_pushbutton(s, "Done", 'o', HELPCTX(ssh_kex_cert), ca_ok_handler, P(st)); c->button.iscancel = true; c->column = 4; @@ -422,7 +422,7 @@ void setup_ca_config_box(struct controlbox *b) "Load, save or delete a host CA record"); ctrl_columns(s, 2, 75, 25); c = ctrl_editbox(s, "Name for this CA (shown in log messages)", - 'n', 100, HELPCTX(no_help), + 'n', 100, HELPCTX(ssh_kex_cert), ca_name_handler, P(st), P(NULL)); c->column = 0; st->ca_name_edit = c; @@ -430,18 +430,18 @@ void setup_ca_config_box(struct controlbox *b) * than alongside that edit box. */ ctrl_columns(s, 1, 100); ctrl_columns(s, 2, 75, 25); - c = ctrl_listbox(s, NULL, NO_SHORTCUT, HELPCTX(no_help), + c = ctrl_listbox(s, NULL, NO_SHORTCUT, HELPCTX(ssh_kex_cert), ca_reclist_handler, P(st)); c->column = 0; c->listbox.height = 6; st->ca_reclist = c; - c = ctrl_pushbutton(s, "Load", 'l', HELPCTX(no_help), + c = ctrl_pushbutton(s, "Load", 'l', HELPCTX(ssh_kex_cert), ca_load_handler, P(st)); c->column = 1; - c = ctrl_pushbutton(s, "Save", 'v', HELPCTX(no_help), + c = ctrl_pushbutton(s, "Save", 'v', HELPCTX(ssh_kex_cert), ca_save_handler, P(st)); c->column = 1; - c = ctrl_pushbutton(s, "Delete", 'd', HELPCTX(no_help), + c = ctrl_pushbutton(s, "Delete", 'd', HELPCTX(ssh_kex_cert), ca_delete_handler, P(st)); c->column = 1; @@ -449,42 +449,45 @@ void setup_ca_config_box(struct controlbox *b) ctrl_columns(s, 2, 75, 25); c = ctrl_editbox(s, "Public key of certification authority", 'k', 100, - HELPCTX(no_help), ca_pubkey_edit_handler, P(st), P(NULL)); + HELPCTX(ssh_kex_cert), ca_pubkey_edit_handler, + P(st), P(NULL)); c->column = 0; st->ca_pubkey_edit = c; c = ctrl_filesel(s, "Read from file", NO_SHORTCUT, NULL, false, "Select public key file of certification authority", - HELPCTX(no_help), ca_pubkey_file_handler, P(st)); + HELPCTX(ssh_kex_cert), ca_pubkey_file_handler, P(st)); c->fileselect.just_button = true; c->align_next_to = st->ca_pubkey_edit; c->column = 1; ctrl_columns(s, 1, 100); - st->ca_pubkey_info = c = ctrl_text(s, " ", HELPCTX(no_help)); + st->ca_pubkey_info = c = ctrl_text(s, " ", HELPCTX(ssh_kex_cert)); c->text.wrap = false; s = ctrl_getset(b, "Main", "options", "What this CA is trusted to do"); c = ctrl_editbox(s, "Valid hosts this key is trusted to certify", 'h', 100, - HELPCTX(no_help), ca_validity_handler, P(st), P(NULL)); + HELPCTX(ssh_cert_valid_expr), ca_validity_handler, + P(st), P(NULL)); st->ca_validity_edit = c; ctrl_columns(s, 4, 44, 18, 18, 18); - c = ctrl_text(s, "Signature types (RSA keys only):", HELPCTX(no_help)); + c = ctrl_text(s, "Signature types (RSA keys only):", + HELPCTX(ssh_cert_rsa_hash)); c->column = 0; dlgcontrol *sigtypelabel = c; - c = ctrl_checkbox(s, "SHA-1", NO_SHORTCUT, HELPCTX(no_help), + c = ctrl_checkbox(s, "SHA-1", NO_SHORTCUT, HELPCTX(ssh_cert_rsa_hash), ca_rsa_type_handler, P(st)); c->column = 1; c->align_next_to = sigtypelabel; c->context2 = I(offsetof(ca_options, permit_rsa_sha1)); st->rsa_type_checkboxes[0] = c; - c = ctrl_checkbox(s, "SHA-256", NO_SHORTCUT, HELPCTX(no_help), + c = ctrl_checkbox(s, "SHA-256", NO_SHORTCUT, HELPCTX(ssh_cert_rsa_hash), ca_rsa_type_handler, P(st)); c->column = 2; c->align_next_to = sigtypelabel; c->context2 = I(offsetof(ca_options, permit_rsa_sha256)); st->rsa_type_checkboxes[1] = c; - c = ctrl_checkbox(s, "SHA-512", NO_SHORTCUT, HELPCTX(no_help), + c = ctrl_checkbox(s, "SHA-512", NO_SHORTCUT, HELPCTX(ssh_cert_rsa_hash), ca_rsa_type_handler, P(st)); c->column = 3; c->align_next_to = sigtypelabel; diff --git a/ssh/common.c b/ssh/common.c index fa5d48d0..161bebbd 100644 --- a/ssh/common.c +++ b/ssh/common.c @@ -934,6 +934,8 @@ SeatPromptResult verify_ssh_host_key( seat_dialog_text_append( text, SDT_TITLE, "%s Security Alert", appname); + HelpCtx helpctx; + if (key && ssh_key_alg(key)->is_certificate) { seat_dialog_text_append( text, SDT_SCARY_HEADING, "WARNING - POTENTIAL SECURITY BREACH!"); @@ -978,6 +980,7 @@ SeatPromptResult verify_ssh_host_key( text, SDT_PARA, "The new %s key fingerprint is:", keytype); seat_dialog_text_append( text, SDT_DISPLAY, "%s", fingerprints[fptype_default]); + helpctx = HELPCTX(errors_cert_mismatch); } else if (storage_status == 1) { seat_dialog_text_append( text, SDT_PARA, "The host key is not cached for this server:"); @@ -990,6 +993,7 @@ SeatPromptResult verify_ssh_host_key( text, SDT_PARA, "The server's %s key fingerprint is:", keytype); seat_dialog_text_append( text, SDT_DISPLAY, "%s", fingerprints[fptype_default]); + helpctx = HELPCTX(errors_hostkey_absent); } else { seat_dialog_text_append( text, SDT_SCARY_HEADING, "WARNING - POTENTIAL SECURITY BREACH!"); @@ -1006,6 +1010,7 @@ SeatPromptResult verify_ssh_host_key( text, SDT_PARA, "The new %s key fingerprint is:", keytype); seat_dialog_text_append( text, SDT_DISPLAY, "%s", fingerprints[fptype_default]); + helpctx = HELPCTX(errors_hostkey_changed); } /* The above text is printed even in batch mode. Here's where we stop if @@ -1013,8 +1018,6 @@ SeatPromptResult verify_ssh_host_key( seat_dialog_text_append( text, SDT_BATCH_ABORT, "Connection abandoned."); - HelpCtx helpctx; - if (storage_status == 1) { seat_dialog_text_append( text, SDT_PARA, "If you trust this host, %s to add the key to " @@ -1029,7 +1032,6 @@ SeatPromptResult verify_ssh_host_key( "connection.", pds->hk_cancel_action); seat_dialog_text_append( text, SDT_PROMPT, "Store key in cache?"); - helpctx = HELPCTX(errors_hostkey_absent); } else { seat_dialog_text_append( text, SDT_PARA, "If you were expecting this change and trust the " @@ -1044,7 +1046,6 @@ SeatPromptResult verify_ssh_host_key( pds->hk_cancel_action, pds->hk_cancel_action_Participle); seat_dialog_text_append( text, SDT_PROMPT, "Update cached key?"); - helpctx = HELPCTX(errors_hostkey_changed); } seat_dialog_text_append(text, SDT_MORE_INFO_KEY, diff --git a/windows/help.h b/windows/help.h index d0f76496..cdd55a11 100644 --- a/windows/help.h +++ b/windows/help.h @@ -113,10 +113,14 @@ typedef const char *HelpCtx; #define WINHELP_CTX_ssh_gssapi_kex_delegation "config-ssh-kex-gssapi-delegation" #define WINHELP_CTX_ssh_kex_repeat "config-ssh-kex-rekey" #define WINHELP_CTX_ssh_kex_manual_hostkeys "config-ssh-kex-manual-hostkeys" +#define WINHELP_CTX_ssh_kex_cert "config-ssh-kex-cert" +#define WINHELP_CTX_ssh_cert_valid_expr "config-ssh-cert-valid-expr" +#define WINHELP_CTX_ssh_cert_rsa_hash "config-ssh-cert-rsa-hash" #define WINHELP_CTX_ssh_auth_bypass "config-ssh-noauth" #define WINHELP_CTX_ssh_no_trivial_userauth "config-ssh-notrivialauth" #define WINHELP_CTX_ssh_auth_banner "config-ssh-banner" #define WINHELP_CTX_ssh_auth_privkey "config-ssh-privkey" +#define WINHELP_CTX_ssh_auth_cert "config-ssh-cert" #define WINHELP_CTX_ssh_auth_agentfwd "config-ssh-agentfwd" #define WINHELP_CTX_ssh_auth_changeuser "config-ssh-changeuser" #define WINHELP_CTX_ssh_auth_pageant "config-ssh-tryagent" @@ -193,6 +197,7 @@ typedef const char *HelpCtx; #define WINHELP_CTX_puttygen_conversions "puttygen-conversions" #define WINHELP_CTX_puttygen_ppkver "puttygen-save-ppk-version" #define WINHELP_CTX_puttygen_kdfparam "puttygen-save-passphrase-hashing" +#define WINHELP_CTX_errors_cert_mismatch "errors-cert-mismatch" /* These are used in Windows-specific bits of the frontend. * We (ab)use "help context identifiers" (dwContextId) to identify them. */