浏览代码

Merge branch 'thirdparty' into thirdparty_dev

Source commit: 287e35b4780dc7b89530047c8e41ae44e5d432eb
Martin Prikryl 3 年之前
父节点
当前提交
69d822193b

+ 2 - 0
source/putty/defs.h

@@ -118,6 +118,8 @@ typedef struct Seat Seat;
 typedef struct SeatVtable SeatVtable;
 typedef struct SeatPromptResult SeatPromptResult;
 
+typedef struct cmdline_get_passwd_input_state cmdline_get_passwd_input_state;
+
 typedef struct TermWin TermWin;
 typedef struct TermWinVtable TermWinVtable;
 

+ 22 - 21
source/putty/doc/config.but

@@ -1956,10 +1956,11 @@ in \W{http://www.ietf.org/rfc/rfc2817.txt}{RFC 2817}.
 connections through a \i{SOCKS server}.
 
 \b Many firewalls implement a less formal type of proxy in which a
-user can make a Telnet connection directly to the firewall machine
+user can make a Telnet or TCP connection directly to the firewall machine
 and enter a command such as \c{connect myhost.com 22} to connect
 through to an external host. Selecting \I{Telnet proxy}\q{Telnet}
-allows you to tell PuTTY to use this type of proxy.
+allows you to tell PuTTY to use this type of proxy, with the precise           
+command specified as described in \k{config-proxy-command}.
 
 \b Selecting \q{SSH} causes PuTTY to make a secondary SSH connection
 to the proxy host (sometimes called a \q{\i{jump host}} in this
@@ -2069,13 +2070,18 @@ separate GSSAPI library, so PuTTY can't override or reconfigure it.
 
 \S{config-proxy-auth} \I{proxy username}Username and \I{proxy password}password
 
-If your proxy requires \I{proxy authentication}authentication, you can
-enter a username and a password in the \q{Username} and \q{Password} boxes.
+You can enter a username and a password in the \q{Username} and
+\q{Password} boxes, which will be used if your proxy requires
+\I{proxy authentication}authentication.
 
 \I{security hazard}Note that if you save your session, the proxy
 password will be saved in plain text, so anyone who can access your PuTTY
 configuration data will be able to discover it.
 
+If PuTTY discovers that it needs a proxy username or password and you
+have not specified one here, PuTTY will prompt for it interactively in
+the terminal window.
+
 Authentication is not fully supported for all forms of proxy:
 
 \b Username and password authentication is supported for HTTP
@@ -2099,22 +2105,16 @@ passwords.
 
 \b SSH proxying can use all the same forms of SSH authentication
 supported by PuTTY for its main connection. If the SSH server requests
-password authentication, the configured proxy password will be used,
-but other authentication methods such as public keys will be tried
-first, just as for a primary SSH connection.
+password authentication, any configured proxy password will be used,
+but other authentication methods such as public keys and GSSAPI will
+be tried first, just as for a primary SSH connection, and if they
+require credentials such as a key passphrase, PuTTY will interactively
+prompt for these.
 
 \b You can specify a way to include a username and password in the
-Telnet/Local proxy command (see \k{config-proxy-command}).
-
-If PuTTY discovers that it needs a proxy username or password and you
-have not specified one in the configuration, it will prompt for it
-interactively in the terminal.
-
-(For SSH proxying, this will also happen in the case of other
-interactive SSH login prompts, such as SSH key passphrases or GSSAPI.
-For the Telnet and Local proxy types, PuTTY will prompt for a username
-or password if you included \c{%user} or \c{%pass} in the command
-string and did not provide a corresponding configuration entry.)
+Telnet/Local proxy command (see \k{config-proxy-command}). If you do
+so, and don't also specify the actual username and/or password in the
+configuration, PuTTY will interactively prompt for them.
 
 \S{config-proxy-command} Specifying the Telnet or Local proxy command
 
@@ -2135,7 +2135,8 @@ itself.
 Also, the special strings \c{%host} and \c{%port} will be replaced
 by the host name and port number you want to connect to. The strings
 \c{%user} and \c{%pass} will be replaced by the proxy username and
-password you specify. The strings \c{%proxyhost} and \c{%proxyport}
+password (which, if not specified in the configuration, will be
+prompted for). The strings \c{%proxyhost} and \c{%proxyport}
 will be replaced by the host details specified on the \e{Proxy} panel,
 if any (this is most likely to be useful for the Local proxy type).
 To get a literal \c{%} sign, enter \c{%%}.
@@ -2148,8 +2149,8 @@ before commands can be sent, you can use a command such as:
 This will send your username and password as the first two lines to
 the proxy, followed by a command to connect to the desired host and
 port. Note that if you do not include the \c{%user} or \c{%pass}
-tokens in the Telnet command, then the \q{Username} and \q{Password}
-configuration fields will be ignored.
+tokens in the Telnet command, then anything specified in \q{Username}
+and \q{Password} configuration fields will be ignored.
 
 \S{config-proxy-logging} Controlling \i{proxy logging}
 

+ 5 - 0
source/putty/doc/index.but

@@ -867,6 +867,11 @@ saved sessions from
 \IM{authentication agent} agent, authentication
 
 \IM{-c-pageant} \c{-c} Pageant command-line option
+\IM{--keylist} \c{--keylist} Pageant command-line option
+\IM{--openssh-config} \c{--openssh-config} Pageant command-line option
+
+\IM{Windows OpenSSH} Windows OpenSSH
+\IM{Windows OpenSSH} OpenSSH, on Windows
 
 \IM{FAQ} FAQ
 \IM{FAQ} Frequently Asked Questions

+ 2 - 41
source/putty/doc/pageant.but

@@ -170,7 +170,7 @@ by the command, like this:
 
 \c C:\PuTTY\pageant.exe d:\main.ppk -c C:\PuTTY\putty.exe
 
-\S{pageant-cmdline-openssh} Integrating with Windows OpenSSH
+\S{pageant-cmdline-openssh} Integrating with \i{Windows OpenSSH}
 
 Windows's own port of OpenSSH uses the same mechanism as Pageant to
 talk to its SSH agent (Windows named pipes). This means that Windows
@@ -184,7 +184,7 @@ configuration, then \c{ssh.exe} should automatically use Pageant as
 its agent, so that you can keep your keys in one place and have both
 SSH clients able to use them.
 
-The option is \c{--openssh-config}, and you follow it with a filename.
+The option is \i\c{--openssh-config}, and you follow it with a filename.
 
 To refer to this file from your main OpenSSH configuration, you can
 use the \cq{Include} directive. For example, you might run Pageant
@@ -217,45 +217,6 @@ point at a different program. You could point it at
 \cw{c:\\Windows\\System32\\OpenSSH\\ssh.exe} once you've done this
 setup \dash but it's just as easy to point it at Plink!
 
-\S{pageant-cmdline-unix} Unix-domain sockets: integrating with WSL 1
-
-Pageant can listen on the WinSock implementation of \q{Unix-domain
-sockets}. These interoperate with the Unix-domain sockets found in the
-original Windows Subsystem for Linux (now known as WSL 1). So if you
-ask Pageant to listen on one of these, then your WSL 1 processes can
-talk directly to Pageant.
-
-To configure this, run Pageant with the option \c{--unix}, followed
-with a pathname. Then, in WSL 1, set the environment variable
-\cw{SSH_AUTH_SOCK} to point at the WSL translation of that pathname.
-
-For example, you might run
-
-\c pageant --unix C:\Users\Simon\.ssh\agent.sock
-
-and in WSL 1, set the environment variable
-
-\c SSH_AUTH_SOCK=/mnt/c/Users/Simon/.ssh/agent.sock
-
-Alternatively, you can add a line to your \cw{.ssh/config} file inside
-WSL that says
-
-\c IdentityAgent /mnt/c/Users/Simon/.ssh/agent.sock
-
-although doing it like that may mean that \cw{ssh-add} commands won't
-find the agent, even though \cw{ssh} itself will.
-
-\s{Security note}: Unix-domain sockets are protected against access by
-other users by the file protections on their containing directory. So
-if your Windows machine is multiuser, make sure you create the socket
-inside a directory that other users can't access at all. (In fact,
-that's a good idea on general principles.)
-
-\s{Compatibility note}: WSL 2 processes cannot talk to Pageant by this
-mechanism, because WSL 2's Unix-domain sockets are managed by a
-separate Linux kernel, and not by the same kernel that WinSock talks
-to.
-
 \S{pageant-cmdline-keylist} Starting with the key list visible
 
 Start Pageant with the \i\c{--keylist} option to show the main window

+ 1 - 1
source/putty/doc/plink.but

@@ -41,7 +41,7 @@ use Plink:
 
 \c C:\>plink
 \c Plink: command-line connection utility
-\c Release 0.76
+\c Release 0.77
 \c Usage: plink [options] [user@]host [command]
 \c        ("host" can also be a PuTTY saved session name)
 \c Options:

+ 1 - 1
source/putty/doc/pscp.but

@@ -39,7 +39,7 @@ use PSCP:
 
 \c C:\>pscp
 \c PuTTY Secure Copy client
-\c Release 0.76
+\c Release 0.77
 \c Usage: pscp [options] [user@]host:source target
 \c        pscp [options] source [source...] [user@]host:target
 \c        pscp [options] -ls [user@]host:filespec

+ 5 - 0
source/putty/doc/pubkey.but

@@ -549,6 +549,11 @@ key.
 
 }
 
+\dt \cw{\-E} \e{fptype}
+
+\dd Algorithm to use when displaying key fingerprints. You can
+select \c{sha256} or \c{md5}. See \k{puttygen-fingerprint}.
+
 \H{pubkey-gettingready} Getting ready for public key authentication
 
 Connect to your SSH server using PuTTY with the SSH protocol. When the

+ 41 - 74
source/putty/doc/puttydoc.txt

@@ -3317,11 +3317,13 @@ Chapter 4: Configuring PuTTY
         -  Selecting `SOCKS 4' or `SOCKS 5' allows you to proxy your
            connections through a SOCKS server.
 
-        -  Many firewalls implement a less formal type of proxy in which
-           a user can make a Telnet connection directly to the firewall
-           machine and enter a command such as `connect myhost.com 22' to
-           connect through to an external host. Selecting `Telnet' allows
-           you to tell PuTTY to use this type of proxy.
+        -  Many firewalls implement a less formal type of proxy in
+           which a user can make a Telnet or TCP connection directly
+           to the firewall machine and enter a command such as
+           `connect myhost.com 22' to connect through to an external host.
+           Selecting `Telnet' allows you to tell PuTTY to use this type
+           of proxy, with the precise command specified as described in
+           section 4.16.5.
 
         -  Selecting `SSH' causes PuTTY to make a secondary SSH connection
            to the proxy host (sometimes called a `jump host' in this
@@ -3426,13 +3428,18 @@ Chapter 4: Configuring PuTTY
 
 4.16.4 Username and password
 
-       If your proxy requires authentication, you can enter a username and
-       a password in the `Username' and `Password' boxes.
+       You can enter a username and a password in the `Username' and
+       `Password' boxes, which will be used if your proxy requires
+       authentication.
 
        Note that if you save your session, the proxy password will be saved
        in plain text, so anyone who can access your PuTTY configuration
        data will be able to discover it.
 
+       If PuTTY discovers that it needs a proxy username or password
+       and you have not specified one here, PuTTY will prompt for it
+       interactively in the terminal window.
+
        Authentication is not fully supported for all forms of proxy:
 
         -  Username and password authentication is supported for HTTP
@@ -3452,23 +3459,16 @@ Chapter 4: Configuring PuTTY
 
         -  SSH proxying can use all the same forms of SSH authentication
            supported by PuTTY for its main connection. If the SSH server
-           requests password authentication, the configured proxy password
+           requests password authentication, any configured proxy password
            will be used, but other authentication methods such as public
-           keys will be tried first, just as for a primary SSH connection.
+           keys and GSSAPI will be tried first, just as for a primary
+           SSH connection, and if they require credentials such as a key
+           passphrase, PuTTY will interactively prompt for these.
 
         -  You can specify a way to include a username and password in the
-           Telnet/Local proxy command (see section 4.16.5).
-
-       If PuTTY discovers that it needs a proxy username or password and
-       you have not specified one in the configuration, it will prompt for
-       it interactively in the terminal.
-
-       (For SSH proxying, this will also happen in the case of other
-       interactive SSH login prompts, such as SSH key passphrases or
-       GSSAPI. For the Telnet and Local proxy types, PuTTY will prompt for
-       a username or password if you included `%user' or `%pass' in the
-       command string and did not provide a corresponding configuration
-       entry.)
+           Telnet/Local proxy command (see section 4.16.5). If you do so,
+           and don't also specify the actual username and/or password in
+           the configuration, PuTTY will interactively prompt for them.
 
 4.16.5 Specifying the Telnet or Local proxy command
 
@@ -3488,21 +3488,22 @@ Chapter 4: Configuring PuTTY
        Also, the special strings `%host' and `%port' will be replaced by
        the host name and port number you want to connect to. The strings
        `%user' and `%pass' will be replaced by the proxy username and
-       password you specify. The strings `%proxyhost' and `%proxyport' will
-       be replaced by the host details specified on the _Proxy_ panel, if
-       any (this is most likely to be useful for the Local proxy type). To
-       get a literal `%' sign, enter `%%'.
+       password (which, if not specified in the configuration, will be
+       prompted for). The strings `%proxyhost' and `%proxyport' will be
+       replaced by the host details specified on the _Proxy_ panel, if any
+       (this is most likely to be useful for the Local proxy type). To get
+       a literal `%' sign, enter `%%'.
 
        If a Telnet proxy server prompts for a username and password before
        commands can be sent, you can use a command such as:
 
          %user\n%pass\nconnect %host %port\n
 
-       This will send your username and password as the first two lines
-       to the proxy, followed by a command to connect to the desired host
-       and port. Note that if you do not include the `%user' or `%pass'
-       tokens in the Telnet command, then the `Username' and `Password'
-       configuration fields will be ignored.
+       This will send your username and password as the first two lines to
+       the proxy, followed by a command to connect to the desired host and
+       port. Note that if you do not include the `%user' or `%pass' tokens
+       in the Telnet command, then anything specified in `Username' and
+       `Password' configuration fields will be ignored.
 
 4.16.6 Controlling proxy logging
 
@@ -5208,7 +5209,7 @@ Chapter 5: Using PSCP to transfer files securely
 
          C:\>pscp
          PuTTY Secure Copy client
-         Release 0.76
+         Release 0.77
          Usage: pscp [options] [user@]host:source target
                 pscp [options] source [source...] [user@]host:target
                 pscp [options] -ls [user@]host:filespec
@@ -6130,7 +6131,7 @@ Chapter 7: Using the command-line connection tool Plink
 
          C:\>plink
          Plink: command-line connection utility
-         Release 0.76
+         Release 0.77
          Usage: plink [options] [user@]host [command]
                 ("host" can also be a PuTTY saved session name)
          Options:
@@ -7063,6 +7064,11 @@ Chapter 8: Using public keys for SSH authentication
                Number of parallelisable threads that can be used to decrypt
                the key.
 
+       -E _fptype_
+
+           Algorithm to use when displaying key fingerprints. You can
+           select `sha256' or `md5'. See section 8.2.6.
+
    8.3 Getting ready for public key authentication
 
        Connect to your SSH server using PuTTY with the SSH protocol. When
@@ -7337,51 +7343,12 @@ Chapter 9: Using Pageant for authentication
        c:\Windows\System32\OpenSSH\ssh.exe once you've done this setup -
        but it's just as easy to point it at Plink!
 
- 9.3.4 Unix-domain sockets: integrating with WSL 1
-
-       Pageant can listen on the WinSock implementation of `Unix-domain
-       sockets'. These interoperate with the Unix-domain sockets found in
-       the original Windows Subsystem for Linux (now known as WSL 1). So if
-       you ask Pageant to listen on one of these, then your WSL 1 processes
-       can talk directly to Pageant.
-
-       To configure this, run Pageant with the option `--unix', followed
-       with a pathname. Then, in WSL 1, set the environment variable
-       SSH_AUTH_SOCK to point at the WSL translation of that pathname.
-
-       For example, you might run
-
-         pageant --unix C:\Users\Simon\.ssh\agent.sock
-
-       and in WSL 1, set the environment variable
-
-         SSH_AUTH_SOCK=/mnt/c/Users/Simon/.ssh/agent.sock
-
-       Alternatively, you can add a line to your .ssh/config file inside
-       WSL that says
-
-         IdentityAgent /mnt/c/Users/Simon/.ssh/agent.sock
-
-       although doing it like that may mean that ssh-add commands won't
-       find the agent, even though ssh itself will.
-
-       *Security note*: Unix-domain sockets are protected against access by
-       other users by the file protections on their containing directory.
-       So if your Windows machine is multiuser, make sure you create the
-       socket inside a directory that other users can't access at all. (In
-       fact, that's a good idea on general principles.)
-
-       *Compatibility note*: WSL 2 processes cannot talk to Pageant by this
-       mechanism, because WSL 2's Unix-domain sockets are managed by a
-       separate Linux kernel, and not by the same kernel that WinSock talks
-       to.
-
- 9.3.5 Starting with the key list visible
+ 9.3.4 Starting with the key list visible
 
        Start Pageant with the `--keylist' option to show the main window as
        soon as it starts up.
 
- 9.3.6 Restricting the Windows process ACL
+ 9.3.5 Restricting the Windows process ACL
 
        Pageant supports the same `-restrict-acl' option as the other PuTTY
        utilities to lock down the Pageant process's access control; see
@@ -11448,5 +11415,5 @@ Appendix G: SSH-2 names specified for PuTTY
                user will have to supply a passphrase before the key can be
                used).
 
-       ersionid PuTTY development snapshot 2022-03-28.a101444
+       ersionid PuTTY release 0.77
 

+ 1 - 1
source/putty/doc/version.but

@@ -1 +1 @@
-ersionid PuTTY development snapshot 2022-03-28.a101444
+ersionid PuTTY release 0.77

+ 7 - 0
source/putty/proxy/proxy.c

@@ -232,6 +232,13 @@ static void proxy_negotiate(ProxySocket *ps)
                                 ps->proxy_nodelay, ps->proxy_keepalive,
                                 &ps->plugimpl);
         ps->pn->reconnect = false;
+        /* If the negotiator has asked us to reconnect, they are
+         * expecting that on the next call their input queue will
+         * consist entirely of data from the _new_ connection, without
+         * any remaining data buffered from the old one. (If they'd
+         * wanted the latter, they could have read it out of the input
+         * queue before asking us to close the connection.) */
+        bufchain_clear(&ps->pending_input_data);
     }
 
     while (bufchain_size(&ps->output_from_negotiator)) {

+ 7 - 1
source/putty/putty.h

@@ -2137,6 +2137,7 @@ void term_pwron(Terminal *, bool);
 void term_clrsb(Terminal *);
 void term_mouse(Terminal *, Mouse_Button, Mouse_Button, Mouse_Action,
                 int, int, bool, bool, bool);
+void term_cancel_selection_drag(Terminal *);
 void term_key(Terminal *, Key_Sym, wchar_t *, size_t, unsigned int,
               unsigned int);
 void term_lost_clipboard_ownership(Terminal *, int clipboard);
@@ -2524,10 +2525,15 @@ void printer_finish_job(printer_job *);
  * zero out password arguments in the hope of not having them show up
  * avoidably in Unix 'ps'.
  */
+struct cmdline_get_passwd_input_state { bool tried; };
+#define CMDLINE_GET_PASSWD_INPUT_STATE_INIT { .tried = false }
+extern const cmdline_get_passwd_input_state cmdline_get_passwd_input_state_new;
+
 int cmdline_process_param(const char *, char *, int, Conf *);
 void cmdline_run_saved(Conf *);
 void cmdline_cleanup(void);
-SeatPromptResult cmdline_get_passwd_input(prompts_t *p);
+SeatPromptResult cmdline_get_passwd_input(
+    prompts_t *p, cmdline_get_passwd_input_state *state, bool restartable);
 bool cmdline_host_ok(Conf *);
 bool cmdline_verbose(void);
 bool cmdline_loaded_session(void);

+ 13 - 5
source/putty/settings.c

@@ -1307,6 +1307,8 @@ static int sessioncmp(const void *av, const void *bv)
     return strcmp(a, b);               /* otherwise, compare normally */
 }
 
+bool sesslist_demo_mode = false;
+
 void get_sesslist(struct sesslist *list, bool allocate)
 {
     int i;
@@ -1316,12 +1318,18 @@ void get_sesslist(struct sesslist *list, bool allocate)
     if (allocate) {
         strbuf *sb = strbuf_new();
 
-        if ((handle = enum_settings_start()) != NULL) {
-            while (enum_settings_next(handle, sb))
-                put_byte(sb, '\0');
-            enum_settings_finish(handle);
+        if (sesslist_demo_mode) {
+            put_asciz(sb, "demo-server");
+            put_asciz(sb, "demo-server-2");
+        } else {
+            if ((handle = enum_settings_start()) != NULL) {
+                while (enum_settings_next(handle, sb))
+                    put_byte(sb, '\0');
+                enum_settings_finish(handle);
+            }
+            put_byte(sb, '\0');
         }
-        put_byte(sb, '\0');
+
         list->buffer = strbuf_to_str(sb);
 
         /*

+ 3 - 0
source/putty/ssh/connection2.c

@@ -178,6 +178,7 @@ void ssh2_queue_global_request_handler(
         snew(struct outstanding_global_request);
     ogr->handler = handler;
     ogr->ctx = ctx;
+    ogr->next = NULL;
     if (s->globreq_tail)
         s->globreq_tail->next = ogr;
     else
@@ -372,6 +373,8 @@ static bool ssh2_connection_filter_queue(struct ssh2_connection_state *s)
                 s->globreq_head = s->globreq_head->next;
                 sfree(tmp);
             }
+            if (!s->globreq_head)
+                s->globreq_tail = NULL;
 
             pq_pop(s->ppl.in_pq);
             break;

+ 4 - 4
source/putty/ssh/mainchan.c

@@ -296,8 +296,8 @@ static void mainchan_request_response(Channel *chan, bool success)
              * If there's no remote_cmd2 configured, then we have no
              * fallback command, so we've run out of options.
              */
-            ssh_sw_abort(mc->ppl->ssh,
-                         "Server refused to start a shell/command");
+            ssh_sw_abort_deferred(mc->ppl->ssh,
+                                  "Server refused to start a shell/command");
         }
         return;
     }
@@ -310,8 +310,8 @@ static void mainchan_request_response(Channel *chan, bool success)
             ssh_got_fallback_cmd(mc->ppl->ssh);
             mainchan_ready(mc);
         } else {
-            ssh_sw_abort(mc->ppl->ssh,
-                         "Server refused to start a shell/command");
+            ssh_sw_abort_deferred(mc->ppl->ssh,
+                                  "Server refused to start a shell/command");
         }
         return;
     }

+ 2 - 1
source/putty/utils/stripctrl.c

@@ -305,7 +305,7 @@ static void stripctrl_locale_BinarySink_write(
         container_of(sccpub, StripCtrlCharsImpl, public);
     const char *p = (const char *)vp;
 
-    const char *previous_locale = setlocale(LC_CTYPE, NULL);
+    char *previous_locale = dupstr(setlocale(LC_CTYPE, NULL));
     setlocale(LC_CTYPE, "");
 
     /*
@@ -391,6 +391,7 @@ static void stripctrl_locale_BinarySink_write(
 
   out:
     setlocale(LC_CTYPE, previous_locale);
+    sfree(previous_locale);
 }
 
 static void stripctrl_term_BinarySink_write(

+ 4 - 4
source/putty/version.h

@@ -1,5 +1,5 @@
 /* Generated by automated build script */
-#define SNAPSHOT
-#define TEXTVER "Development snapshot 2022-03-28.a101444"
-#define SSHVER "-Snapshot-2022-03-28.a101444"
-#define BINARY_VERSION 0,76,1261,0
+#define RELEASE 0.77
+#define TEXTVER "Release 0.77"
+#define SSHVER "-Release-0.77"
+#define BINARY_VERSION 0,77,0,0

+ 1 - 1
source/putty/windows/gss.c

@@ -465,7 +465,7 @@ static Ssh_gss_stat ssh_sspi_init_sec_context(struct ssh_gss_library *lib,
     SecBufferDesc input_desc ={SECBUFFER_VERSION,1,&wrecv_tok};
     unsigned long flags=ISC_REQ_MUTUAL_AUTH|ISC_REQ_REPLAY_DETECT|
         ISC_REQ_CONFIDENTIALITY|ISC_REQ_ALLOCATE_MEMORY;
-    unsigned long ret_flags=0;
+    ULONG ret_flags=0;
     TimeStamp localexp;
 
     /* check if we have to delegate ... */

+ 127 - 195
source/putty/windows/network.c

@@ -20,10 +20,6 @@
 
 #include <ws2tcpip.h>
 
-#if HAVE_AFUNIX_H
-#include <afunix.h>
-#endif
-
 #ifndef NO_IPV6
 #ifdef __clang__
 #pragma clang diagnostic push
@@ -83,28 +79,12 @@ struct NetSocket {
     Socket sock;
 };
 
-/*
- * Top-level discriminator for SockAddr.
- *
- * UNRESOLVED means a host name not yet put through DNS; IP means a
- * resolved IP address (or list of them); UNIX indicates the AF_UNIX
- * network family (which Windows also has); NAMEDPIPE indicates that
- * this SockAddr is phony, holding a Windows named pipe pathname
- * instead of any address WinSock can understand.
- */
-typedef enum SuperFamily {
-    UNRESOLVED,
-    IP,
-#if HAVE_AFUNIX_H
-    UNIX,
-#endif
-    NAMEDPIPE
-} SuperFamily;
-
 struct SockAddr {
     int refcount;
     char *error;
-    SuperFamily superfamily;
+    bool resolved;
+    bool namedpipe; /* indicates that this SockAddr is phony, holding a Windows
+                     * named pipe pathname instead of a network address */
 #ifndef NO_IPV6
     struct addrinfo *ais;              /* Addresses IPv6 style. */
 #endif
@@ -115,27 +95,18 @@ struct SockAddr {
 
 /*
  * Which address family this address belongs to. AF_INET for IPv4;
- * AF_INET6 for IPv6; AF_UNIX for Unix-domain sockets; AF_UNSPEC
- * indicates that name resolution has not been done and a simple host
- * name is held in this SockAddr structure.
+ * AF_INET6 for IPv6; AF_UNSPEC indicates that name resolution has
+ * not been done and a simple host name is held in this SockAddr
+ * structure.
  */
-static inline int sockaddr_family(SockAddr *addr, SockAddrStep step)
-{
-    switch (addr->superfamily) {
-      case IP:
 #ifndef NO_IPV6
-        if (step.ai)
-            return step.ai->ai_family;
-#endif
-        return AF_INET;
-#if HAVE_AFUNIX_H
-      case UNIX:
-        return AF_UNIX;
+#define SOCKADDR_FAMILY(addr, step) \
+    (!(addr)->resolved ? AF_UNSPEC : \
+     (step).ai ? (step).ai->ai_family : AF_INET)
+#else
+#define SOCKADDR_FAMILY(addr, step) \
+    (!(addr)->resolved ? AF_UNSPEC : AF_INET)
 #endif
-      default:
-        return AF_UNSPEC;
-    }
-}
 
 /*
  * Start a SockAddrStep structure to step through multiple
@@ -475,8 +446,9 @@ SockAddr *sk_namelookup(const char *host, char **canonicalname,
 #ifndef NO_IPV6
     ret->ais = NULL;
 #endif
+    ret->namedpipe = false;
     ret->addresses = NULL;
-    ret->superfamily = UNRESOLVED;
+    ret->resolved = false;
     ret->refcount = 1;
     *realhost = '\0';
 
@@ -499,7 +471,7 @@ SockAddr *sk_namelookup(const char *host, char **canonicalname,
                 sfree(trimmed_host);
             }
             if (err == 0)
-                ret->superfamily = IP;
+                ret->resolved = true;
         } else
 #endif
         {
@@ -508,12 +480,12 @@ SockAddr *sk_namelookup(const char *host, char **canonicalname,
              * (NOTE: we don't use gethostbyname as a fallback!)
              */
             if ( (h = p_gethostbyname(host)) )
-                ret->superfamily = IP;
+                ret->resolved = true;
             else
                 err = p_WSAGetLastError();
         }
 
-        if (ret->superfamily != IP) {
+        if (!ret->resolved) {
             ret->error = (err == WSAENETDOWN ? "Network is down" :
                           err == WSAHOST_NOT_FOUND ? "Host does not exist" :
                           err == WSATRY_AGAIN ? "Host not found" :
@@ -564,7 +536,7 @@ SockAddr *sk_namelookup(const char *host, char **canonicalname,
         ret->addresses = snewn(1, unsigned long);
         ret->naddresses = 1;
         ret->addresses[0] = p_ntohl(a);
-        ret->superfamily = IP;
+        ret->resolved = true;
         strncpy(realhost, host, sizeof(realhost));
     }
     realhost[lenof(realhost)-1] = '\0';
@@ -572,38 +544,39 @@ SockAddr *sk_namelookup(const char *host, char **canonicalname,
     return ret;
 }
 
-static SockAddr *sk_special_addr(SuperFamily superfamily, const char *name)
+SockAddr *sk_nonamelookup(const char *host)
 {
     SockAddr *ret = snew(SockAddr);
     ret->error = NULL;
-    ret->superfamily = superfamily;
+    ret->resolved = false;
 #ifndef NO_IPV6
     ret->ais = NULL;
 #endif
+    ret->namedpipe = false;
     ret->addresses = NULL;
     ret->naddresses = 0;
     ret->refcount = 1;
-    strncpy(ret->hostname, name, lenof(ret->hostname));
+    strncpy(ret->hostname, host, lenof(ret->hostname));
     ret->hostname[lenof(ret->hostname)-1] = '\0';
     return ret;
 }
 
-SockAddr *sk_nonamelookup(const char *host)
-{
-    return sk_special_addr(UNRESOLVED, host);
-}
-
 SockAddr *sk_namedpipe_addr(const char *pipename)
 {
-    return sk_special_addr(NAMEDPIPE, pipename);
-}
-
-#if HAVE_AFUNIX_H
-SockAddr *sk_unix_addr(const char *sockpath)
-{
-    return sk_special_addr(UNIX, sockpath);
-}
+    SockAddr *ret = snew(SockAddr);
+    ret->error = NULL;
+    ret->resolved = false;
+#ifndef NO_IPV6
+    ret->ais = NULL;
 #endif
+    ret->namedpipe = true;
+    ret->addresses = NULL;
+    ret->naddresses = 0;
+    ret->refcount = 1;
+    strncpy(ret->hostname, pipename, lenof(ret->hostname));
+    ret->hostname[lenof(ret->hostname)-1] = '\0';
+    return ret;
+}
 
 static bool sk_nextaddr(SockAddr *addr, SockAddrStep *step)
 {
@@ -646,7 +619,7 @@ void sk_getaddr(SockAddr *addr, char *buf, int buflen)
         }
     } else
 #endif
-    if (sockaddr_family(addr, step) == AF_INET) {
+    if (SOCKADDR_FAMILY(addr, step) == AF_INET) {
         struct in_addr a;
         assert(addr->addresses && step.curraddr < addr->naddresses);
         a.s_addr = p_htonl(addr->addresses[step.curraddr]);
@@ -677,7 +650,7 @@ static SockAddr sk_extractaddr_tmp(
 #ifndef NO_IPV6
     toret.ais = step->ai;
 #endif
-    if (sockaddr_family(addr, *step) == AF_INET
+    if (SOCKADDR_FAMILY(addr, *step) == AF_INET
 #ifndef NO_IPV6
         && !toret.ais
 #endif
@@ -689,11 +662,7 @@ static SockAddr sk_extractaddr_tmp(
 
 bool sk_addr_needs_port(SockAddr *addr)
 {
-    return addr->superfamily != NAMEDPIPE
-#if HAVE_AFUNIX_H
-        && addr->superfamily != UNIX
-#endif
-        ;
+    return !addr->namedpipe;
 }
 
 bool sk_hostname_is_local(const char *name)
@@ -741,7 +710,7 @@ bool sk_address_is_local(SockAddr *addr)
     SockAddrStep step;
     int family;
     START_STEP(addr, step);
-    family = sockaddr_family(addr, step);
+    family = SOCKADDR_FAMILY(addr, step);
 
 #ifndef NO_IPV6
     if (family == AF_INET6) {
@@ -777,7 +746,7 @@ int sk_addrtype(SockAddr *addr)
     SockAddrStep step;
     int family;
     START_STEP(addr, step);
-    family = sockaddr_family(addr, step);
+    family = SOCKADDR_FAMILY(addr, step);
 
     return (family == AF_INET ? ADDRTYPE_IPV4 :
 #ifndef NO_IPV6
@@ -791,7 +760,7 @@ void sk_addrcopy(SockAddr *addr, char *buf)
     SockAddrStep step;
     int family;
     START_STEP(addr, step);
-    family = sockaddr_family(addr, step);
+    family = SOCKADDR_FAMILY(addr, step);
 
     assert(family != AF_UNSPEC);
 #ifndef NO_IPV6
@@ -935,7 +904,7 @@ static DWORD try_connect(NetSocket *sock)
     /*
      * Open socket.
      */
-    family = sockaddr_family(sock->addr, sock->step);
+    family = SOCKADDR_FAMILY(sock->addr, sock->step);
 
     /*
      * Remove the socket from the tree before we overwrite its
@@ -1151,26 +1120,21 @@ Socket *sk_new(SockAddr *addr, int port, bool privport, bool oobinline,
     return &ret->sock;
 }
 
-Socket *sk_newlistener_internal(const char *srcaddr, int port, Plug *plug,
-                                bool local_host_only, int orig_address_family)
+Socket *sk_newlistener(const char *srcaddr, int port, Plug *plug,
+                       bool local_host_only, int orig_address_family)
 {
     SOCKET s;
-    SOCKADDR_IN a;
 #ifndef NO_IPV6
     SOCKADDR_IN6 a6;
 #endif
-#if HAVE_AFUNIX_H
-    SOCKADDR_UN au;
-#endif
-    struct sockaddr *bindaddr;
-    unsigned bindsize;
+    SOCKADDR_IN a;
 
     DWORD err;
     const char *errstr;
     NetSocket *ret;
     int retcode;
 
-    int address_family = orig_address_family;
+    int address_family;
 
     /*
      * Create NetSocket structure.
@@ -1190,6 +1154,16 @@ Socket *sk_newlistener_internal(const char *srcaddr, int port, Plug *plug,
     ret->parent = ret->child = NULL;
     ret->addr = NULL;
 
+    /*
+     * Translate address_family from platform-independent constants
+     * into local reality.
+     */
+    address_family = (orig_address_family == ADDRTYPE_IPV4 ? AF_INET :
+#ifndef NO_IPV6
+                      orig_address_family == ADDRTYPE_IPV6 ? AF_INET6 :
+#endif
+                      AF_UNSPEC);
+
     /*
      * Our default, if passed the `don't care' value
      * ADDRTYPE_UNSPEC, is to listen on IPv4. If IPv6 is supported,
@@ -1215,100 +1189,85 @@ Socket *sk_newlistener_internal(const char *srcaddr, int port, Plug *plug,
 
     ret->oobinline = false;
 
-#if HAVE_AFUNIX_H
-    if (address_family != AF_UNIX)
-#endif
     {
         BOOL on = true;
         p_setsockopt(s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE,
                      (const char *)&on, sizeof(on));
     }
 
-    switch (address_family) {
 #ifndef NO_IPV6
-      case AF_INET6: {
-        memset(&a6, 0, sizeof(a6));
-        a6.sin6_family = AF_INET6;
-        if (local_host_only)
-            a6.sin6_addr = in6addr_loopback;
-        else
-            a6.sin6_addr = in6addr_any;
-        if (srcaddr != NULL && p_getaddrinfo) {
-            struct addrinfo hints;
-            struct addrinfo *ai;
-            int err;
-
-            memset(&hints, 0, sizeof(hints));
-            hints.ai_family = AF_INET6;
-            hints.ai_flags = 0;
-            {
-                /* strip [] on IPv6 address literals */
-                char *trimmed_addr = host_strduptrim(srcaddr);
-                err = p_getaddrinfo(trimmed_addr, NULL, &hints, &ai);
-                sfree(trimmed_addr);
-            }
-            if (err == 0 && ai->ai_family == AF_INET6) {
-                a6.sin6_addr =
-                    ((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr;
+        if (address_family == AF_INET6) {
+            memset(&a6, 0, sizeof(a6));
+            a6.sin6_family = AF_INET6;
+            if (local_host_only)
+                a6.sin6_addr = in6addr_loopback;
+            else
+                a6.sin6_addr = in6addr_any;
+            if (srcaddr != NULL && p_getaddrinfo) {
+                struct addrinfo hints;
+                struct addrinfo *ai;
+                int err;
+
+                memset(&hints, 0, sizeof(hints));
+                hints.ai_family = AF_INET6;
+                hints.ai_flags = 0;
+                {
+                    /* strip [] on IPv6 address literals */
+                    char *trimmed_addr = host_strduptrim(srcaddr);
+                    err = p_getaddrinfo(trimmed_addr, NULL, &hints, &ai);
+                    sfree(trimmed_addr);
+                }
+                if (err == 0 && ai->ai_family == AF_INET6) {
+                    a6.sin6_addr =
+                        ((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr;
+                }
             }
-        }
-        a6.sin6_port = p_htons(port);
-        bindaddr = (struct sockaddr *)&a6;
-        bindsize = sizeof(a6);
-        break;
-      }
+            a6.sin6_port = p_htons(port);
+        } else
 #endif
-      case AF_INET: {
-        bool got_addr = false;
-        a.sin_family = AF_INET;
+        {
+            bool got_addr = false;
+            a.sin_family = AF_INET;
 
-        /*
-         * Bind to source address. First try an explicitly
-         * specified one...
-         */
-        if (srcaddr) {
-            a.sin_addr.s_addr = p_inet_addr(srcaddr);
-            if (a.sin_addr.s_addr != INADDR_NONE) {
-                /* Override localhost_only with specified listen addr. */
-                ret->localhost_only = ipv4_is_loopback(a.sin_addr);
-                got_addr = true;
+            /*
+             * Bind to source address. First try an explicitly
+             * specified one...
+             */
+            if (srcaddr) {
+                a.sin_addr.s_addr = p_inet_addr(srcaddr);
+                if (a.sin_addr.s_addr != INADDR_NONE) {
+                    /* Override localhost_only with specified listen addr. */
+                    ret->localhost_only = ipv4_is_loopback(a.sin_addr);
+                    got_addr = true;
+                }
             }
-        }
 
-        /*
-         * ... and failing that, go with one of the standard ones.
-         */
-        if (!got_addr) {
-            if (local_host_only)
-                a.sin_addr.s_addr = p_htonl(INADDR_LOOPBACK);
-            else
-                a.sin_addr.s_addr = p_htonl(INADDR_ANY);
-        }
+            /*
+             * ... and failing that, go with one of the standard ones.
+             */
+            if (!got_addr) {
+                if (local_host_only)
+                    a.sin_addr.s_addr = p_htonl(INADDR_LOOPBACK);
+                else
+                    a.sin_addr.s_addr = p_htonl(INADDR_ANY);
+            }
 
-        a.sin_port = p_htons((short)port);
-        bindaddr = (struct sockaddr *)&a;
-        bindsize = sizeof(a);
-        break;
-      }
-#if HAVE_AFUNIX_H
-      case AF_UNIX: {
-        au.sun_family = AF_UNIX;
-        strncpy(au.sun_path, srcaddr, sizeof(au.sun_path));
-        bindaddr = (struct sockaddr *)&au;
-        bindsize = sizeof(au);
-        break;
-      }
+            a.sin_port = p_htons((short)port);
+        }
+#ifndef NO_IPV6
+        retcode = p_bind(s, (address_family == AF_INET6 ?
+                           (struct sockaddr *) &a6 :
+                           (struct sockaddr *) &a),
+                       (address_family ==
+                        AF_INET6 ? sizeof(a6) : sizeof(a)));
+#else
+        retcode = p_bind(s, (struct sockaddr *) &a, sizeof(a));
 #endif
-      default:
-        unreachable("bad address family in sk_newlistener_internal");
-    }
-
-    retcode = p_bind(s, bindaddr, bindsize);
-    if (retcode != SOCKET_ERROR) {
-        err = 0;
-    } else {
-        err = p_WSAGetLastError();
-    }
+        if (retcode != SOCKET_ERROR) {
+            err = 0;
+        } else {
+            err = p_WSAGetLastError();
+        }
 
     if (err) {
         p_closesocket(s);
@@ -1339,9 +1298,9 @@ Socket *sk_newlistener_internal(const char *srcaddr, int port, Plug *plug,
      * If we were given ADDRTYPE_UNSPEC, we must also create an
      * IPv6 listening socket and link it to this one.
      */
-    if (address_family == AF_INET && orig_address_family == AF_UNSPEC) {
-        Socket *other = sk_newlistener_internal(srcaddr, port, plug,
-                                                local_host_only, AF_INET6);
+    if (address_family == AF_INET && orig_address_family == ADDRTYPE_UNSPEC) {
+        Socket *other = sk_newlistener(srcaddr, port, plug,
+                                       local_host_only, ADDRTYPE_IPV6);
 
         if (other) {
             NetSocket *ns = container_of(other, NetSocket, sock);
@@ -1358,33 +1317,6 @@ Socket *sk_newlistener_internal(const char *srcaddr, int port, Plug *plug,
     return &ret->sock;
 }
 
-Socket *sk_newlistener(const char *srcaddr, int port, Plug *plug,
-                       bool local_host_only, int orig_address_family)
-{
-    /*
-     * Translate address_family from platform-independent constants
-     * into local reality.
-     */
-    int address_family = (orig_address_family == ADDRTYPE_IPV4 ? AF_INET :
-#ifndef NO_IPV6
-                          orig_address_family == ADDRTYPE_IPV6 ? AF_INET6 :
-#endif
-                          AF_UNSPEC);
-
-    return sk_newlistener_internal(srcaddr, port, plug, local_host_only,
-                                   address_family);
-}
-
-Socket *sk_newlistener_unix(const char *path, Plug *plug)
-{
-#if HAVE_AFUNIX_H
-    return sk_newlistener_internal(path, 0, plug, false, AF_UNIX);
-#else
-    return new_error_socket_fmt(
-        plug, "AF_UNIX support not compiled into this program");
-#endif
-}
-
 static void sk_net_close(Socket *sock)
 {
     NetSocket *s = container_of(sock, NetSocket, sock);
@@ -1724,7 +1656,7 @@ void select_result(WPARAM wParam, LPARAM lParam)
 #ifdef NO_IPV6
         struct sockaddr_in isa;
 #else
-        struct sockaddr_storage isa; // FIXME: also if Unix and no IPv6
+        struct sockaddr_storage isa;
 #endif
         int addrlen = sizeof(isa);
         SOCKET t;  /* socket of connection */
@@ -1780,7 +1712,7 @@ static SocketPeerInfo *sk_net_peer_info(Socket *sock)
 #ifdef NO_IPV6
     struct sockaddr_in addr;
 #else
-    struct sockaddr_storage addr; // FIXME: also if Unix and no IPv6
+    struct sockaddr_storage addr;
     char buf[INET6_ADDRSTRLEN];
 #endif
     int addrlen = sizeof(addr);
@@ -1899,7 +1831,7 @@ SockAddr *platform_get_x11_unix_address(const char *display, int displaynum)
 {
     SockAddr *ret = snew(SockAddr);
     memset(ret, 0, sizeof(SockAddr));
-    ret->error = "unix sockets for X11 not supported on this platform";
+    ret->error = "unix sockets not supported on this platform";
     ret->refcount = 1;
     return ret;
 }

+ 3 - 2
source/putty/windows/platform.h

@@ -293,7 +293,6 @@ void socket_reselect_all(void);
 SockAddr *sk_namedpipe_addr(const char *pipename);
 /* Turn a WinSock error code into a string. */
 const char *winsock_error_string(int error);
-Socket *sk_newlistener_unix(const char *socketpath, Plug *plug);
 
 /*
  * network.c dynamically loads WinSock 2 or WinSock 1 depending on
@@ -333,7 +332,6 @@ const char *do_select(SOCKET skt, bool enable);
  */
 void winselgui_set_hwnd(HWND hwnd);
 void winselgui_clear_hwnd(void);
-void winselgui_response(WPARAM wParam, LPARAM lParam);
 
 void winselcli_setup(void);
 SOCKET winselcli_unique_socket(void);
@@ -759,4 +757,7 @@ bool aux_match_arg(AuxMatchOpt *amo, char **val);
 bool aux_match_opt(AuxMatchOpt *amo, char **val, const char *optname, ...);
 bool aux_match_done(AuxMatchOpt *amo);
 
+char *save_screenshot(HWND hwnd, const char *outfile);
+void gui_terminal_ready(HWND hwnd, Seat *seat, Backend *backend);
+
 #endif /* PUTTY_WINDOWS_PLATFORM_H */