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
diff options
context:
space:
mode:
Diffstat (limited to 'PUTTY.H')
-rw-r--r--PUTTY.H836
1 files changed, 674 insertions, 162 deletions
diff --git a/PUTTY.H b/PUTTY.H
index 693a6a0e..bfb705c2 100644
--- a/PUTTY.H
+++ b/PUTTY.H
@@ -5,7 +5,7 @@
#include <limits.h> /* for INT_MAX */
#include "defs.h"
-#include "puttyps.h"
+#include "platform.h"
#include "network.h"
#include "misc.h"
#include "marshal.h"
@@ -21,14 +21,14 @@
* Fingerprints of the current and previous PGP master keys, to
* establish a trust path between an executable and other files.
*/
-#define PGP_MASTER_KEY_YEAR "2018"
-#define PGP_MASTER_KEY_DETAILS "RSA, 4096-bit"
-#define PGP_MASTER_KEY_FP \
- "24E1 B1C5 75EA 3C9F F752 A922 76BC 7FE4 EBFD 2D9E"
-#define PGP_PREV_MASTER_KEY_YEAR "2015"
+#define PGP_MASTER_KEY_YEAR "2021"
+#define PGP_MASTER_KEY_DETAILS "RSA, 3072-bit"
+#define PGP_MASTER_KEY_FP \
+ "A872 D42F 1660 890F 0E05 223E DD43 55EA AC11 19DE"
+#define PGP_PREV_MASTER_KEY_YEAR "2018"
#define PGP_PREV_MASTER_KEY_DETAILS "RSA, 4096-bit"
#define PGP_PREV_MASTER_KEY_FP \
- "440D E3B5 B7A1 CA85 B3CC 1718 AB58 5DC6 0467 6F7C"
+ "24E1 B1C5 75EA 3C9F F752 A922 76BC 7FE4 EBFD 2D9E"
/*
* Definitions of three separate indexing schemes for colour palette
@@ -266,7 +266,6 @@ struct sesslist {
};
struct unicode_data {
- char **uni_tbl;
bool dbcs_screenfont;
int font_codepage;
int line_codepage;
@@ -326,13 +325,13 @@ typedef enum {
/*
* Send a POSIX-style signal. (Useful in SSH and also pterm.)
*
- * We use the master list in sshsignals.h to define these enum
+ * We use the master list in ssh/signal-list.h to define these enum
* values, which will come out looking like names of the form
* SS_SIGABRT, SS_SIGINT etc.
*/
#define SIGNAL_MAIN(name, text) SS_SIG ## name,
#define SIGNAL_SUB(name) SS_SIG ## name,
- #include "sshsignals.h"
+ #include "ssh/signal-list.h"
#undef SIGNAL_MAIN
#undef SIGNAL_SUB
@@ -356,7 +355,7 @@ struct SessionSpecial {
int arg;
};
-/* Needed by both sshchan.h and sshppl.h */
+/* Needed by both ssh/channel.h and ssh/ppl.h */
typedef void (*add_special_fn_t)(
void *ctx, const char *text, SessionSpecialCode code, int arg);
@@ -423,9 +422,14 @@ enum {
KEX_WARN,
KEX_DHGROUP1,
KEX_DHGROUP14,
+ KEX_DHGROUP15,
+ KEX_DHGROUP16,
+ KEX_DHGROUP17,
+ KEX_DHGROUP18,
KEX_DHGEX,
KEX_RSA,
KEX_ECDH,
+ KEX_NTRU_HYBRID,
KEX_MAX
};
@@ -453,6 +457,7 @@ enum {
CIPHER_DES,
CIPHER_ARCFOUR,
CIPHER_CHACHA20,
+ CIPHER_AESGCM,
CIPHER_MAX /* no. ciphers (inc warn) */
};
@@ -474,7 +479,9 @@ enum {
* Proxy types.
*/
PROXY_NONE, PROXY_SOCKS4, PROXY_SOCKS5,
- PROXY_HTTP, PROXY_TELNET, PROXY_CMD, PROXY_FUZZ
+ PROXY_HTTP, PROXY_TELNET, PROXY_CMD, PROXY_SSH_TCPIP,
+ PROXY_SSH_EXEC, PROXY_SSH_SUBSYSTEM,
+ PROXY_FUZZ
};
enum {
@@ -529,7 +536,14 @@ enum {
FUNKY_XTERM,
FUNKY_VT400,
FUNKY_VT100P,
- FUNKY_SCO
+ FUNKY_SCO,
+ FUNKY_XTERM_216
+};
+
+enum {
+ /* Shifted arrow key types (CONF_sharrow_type) */
+ SHARROW_APPLICATION, /* Ctrl flips between ESC O A and ESC [ A */
+ SHARROW_BITMAP /* ESC [ 1 ; n A, where n = 1 + bitmap of CAS */
};
enum {
@@ -617,9 +631,123 @@ enum {
#define BACKEND_RESIZE_FORBIDDEN 0x01 /* Backend does not allow
resizing terminal */
#define BACKEND_NEEDS_TERMINAL 0x02 /* Backend must have terminal */
+#define BACKEND_SUPPORTS_NC_HOST 0x04 /* Backend can honour
+ CONF_ssh_nc_host */
+#define BACKEND_NOTIFIES_SESSION_START 0x08 /* Backend will call
+ seat_notify_session_started */
+
+/* In (no)sshproxy.c */
+extern const bool ssh_proxy_supported;
+
+/*
+ * This structure type wraps a Seat pointer, in a way that has no
+ * purpose except to be a different type.
+ *
+ * The Seat wrapper functions that present interactive prompts all
+ * expect one of these in place of their ordinary Seat pointer. You
+ * get one by calling interactor_announce (defined below), which will
+ * print a message (if not already done) identifying the Interactor
+ * that originated the prompt.
+ *
+ * This arranges that the C type system itself will check that no call
+ * to any of those Seat methods has omitted the mandatory call to
+ * interactor_announce beforehand.
+ */
+struct InteractionReadySeat {
+ Seat *seat;
+};
+
+/*
+ * The Interactor trait is implemented by anything that is capable of
+ * presenting interactive prompts or questions to the user during
+ * network connection setup. Every Backend that ever needs to do this
+ * is an Interactor, but also, while a Backend is making its initial
+ * network connection, it may go via network proxy code which is also
+ * an Interactor and can ask questions of its own.
+ */
+struct Interactor {
+ const InteractorVtable *vt;
+
+ /* The parent Interactor that we are a proxy for, if any. */
+ Interactor *parent;
+
+ /*
+ * If we're the top-level Interactor (parent==NULL), then this
+ * field records the last Interactor that actually did anything
+ * interactive, so that we know when to announce a changeover
+ * between levels of proxying.
+ *
+ * If parent != NULL, this field is not used.
+ */
+ Interactor *last_to_talk;
+};
+
+struct InteractorVtable {
+ /*
+ * Returns a user-facing description of the nature of the network
+ * connection being made. Used in interactive proxy authentication
+ * to announce which connection attempt is now in control of the
+ * Seat.
+ *
+ * The idea is not just to be written in natural language, but to
+ * connect with the user's idea of _why_ they think some
+ * connection is being made. For example, instead of saying 'TCP
+ * connection to 123.45.67.89 port 22', you might say 'SSH
+ * connection to [logical host name for SSH host key purposes]'.
+ *
+ * The returned string must be freed by the caller.
+ */
+ char *(*description)(Interactor *itr);
+
+ /*
+ * Returns the LogPolicy associated with this Interactor. (A
+ * Backend can derive this from its logging context; a proxy
+ * Interactor inherits it from the Interactor for the parent
+ * network connection.)
+ */
+ LogPolicy *(*logpolicy)(Interactor *itr);
+
+ /*
+ * Gets and sets the Seat that this Interactor talks to. When a
+ * Seat is borrowed and replaced with a TempSeat, this will be the
+ * mechanism by which that replacement happens.
+ */
+ Seat *(*get_seat)(Interactor *itr);
+ void (*set_seat)(Interactor *itr, Seat *seat);
+};
+
+static inline char *interactor_description(Interactor *itr)
+{ return itr->vt->description(itr); }
+static inline LogPolicy *interactor_logpolicy(Interactor *itr)
+{ return itr->vt->logpolicy(itr); }
+static inline Seat *interactor_get_seat(Interactor *itr)
+{ return itr->vt->get_seat(itr); }
+static inline void interactor_set_seat(Interactor *itr, Seat *seat)
+{ itr->vt->set_seat(itr, seat); }
+
+static inline void interactor_set_child(Interactor *parent, Interactor *child)
+{ child->parent = parent; }
+Seat *interactor_borrow_seat(Interactor *itr);
+void interactor_return_seat(Interactor *itr);
+InteractionReadySeat interactor_announce(Interactor *itr);
+
+/* Interactors that are Backends will find this helper function useful
+ * in constructing their description strings */
+char *default_description(const BackendVtable *backvt,
+ const char *host, int port);
+
+/*
+ * The Backend trait is the top-level one that governs each of the
+ * user-facing main modes that PuTTY can use to talk to some
+ * destination: SSH, Telnet, serial port, pty, etc.
+ */
struct Backend {
const BackendVtable *vt;
+
+ /* Many Backends are also Interactors. If this one is, a pointer
+ * to its Interactor trait lives here. */
+ Interactor *interactor;
};
struct BackendVtable {
char *(*init) (const BackendVtable *vt, Seat *seat,
@@ -630,9 +758,8 @@ struct BackendVtable {
void (*free) (Backend *be);
/* Pass in a replacement configuration. */
void (*reconfig) (Backend *be, Conf *conf);
- /* send() returns the current amount of buffered data. */
- size_t (*send) (Backend *be, const char *buf, size_t len);
- /* sendbuffer() does the same thing but without attempting a send */
+ void (*send) (Backend *be, const char *buf, size_t len);
+ /* sendbuffer() returns the current amount of buffered data */
size_t (*sendbuffer) (Backend *be);
void (*size) (Backend *be, int width, int height);
void (*special) (Backend *be, SessionSpecialCode code, int arg);
@@ -641,7 +768,14 @@ struct BackendVtable {
int (*exitcode) (Backend *be);
/* If back->sendok() returns false, the backend doesn't currently
* want input data, so the frontend should avoid acquiring any if
- * possible (passing back-pressure on to its sender). */
+ * possible (passing back-pressure on to its sender).
+ *
+ * Policy rule: no backend shall return true from sendok() while
+ * its network connection attempt is still ongoing. This ensures
+ * that if making the network connection involves a proxy type
+ * which wants to interact with the user via the terminal, the
+ * proxy implementation and the backend itself won't fight over
+ * who gets the terminal input. */
bool (*sendok) (Backend *be);
bool (*ldisc_option_state) (Backend *be, int);
void (*provide_ldisc) (Backend *be, Ldisc *ldisc);
@@ -660,9 +794,10 @@ struct BackendVtable {
char *(*close_warn_text)(Backend *be);
/* 'id' is a machine-readable name for the backend, used in
- * saved-session storage. 'displayname' is a human-readable name
- * for error messages. */
- const char *id, *displayname;
+ * saved-session storage. 'displayname_tc' and 'displayname_lc'
+ * are human-readable names, one in title-case for config boxes,
+ * and one in lower-case for use in mid-sentence. */
+ const char *id, *displayname_tc, *displayname_lc;
int protocol;
int default_port;
@@ -681,8 +816,8 @@ static inline void backend_free(Backend *be)
{ be->vt->free(be); }
static inline void backend_reconfig(Backend *be, Conf *conf)
{ be->vt->reconfig(be, conf); }
-static inline size_t backend_send(Backend *be, const char *buf, size_t len)
-{ return be->vt->send(be, buf, len); }
+static inline void backend_send(Backend *be, const char *buf, size_t len)
+{ be->vt->send(be, buf, len); }
static inline size_t backend_sendbuffer(Backend *be)
{ return be->vt->sendbuffer(be); }
static inline void backend_size(Backend *be, int width, int height)
@@ -733,6 +868,87 @@ int hwnd_parent;
#endif // PUTTYNG
/*
+ * Used by callback.c; declared up here so that prompts_t can use it
+ */
+typedef void (*toplevel_callback_fn_t)(void *ctx);
+
+/* Enum of result types in SeatPromptResult below */
+typedef enum SeatPromptResultKind {
+ /* Answer not yet available at all; either try again later or wait
+ * for a callback (depending on the request's API) */
+ SPRK_INCOMPLETE,
+
+ /* We're abandoning the connection because the user interactively
+ * told us to. (Hence, no need to present an error message
+ * telling the user we're doing that: they already know.) */
+ SPRK_USER_ABORT,
+
+ /* We're abandoning the connection for some other reason (e.g. we
+ * were unable to present the prompt at all, or a batch-mode
+ * configuration told us to give the answer no). This may
+ * ultimately have stemmed from some user configuration, but they
+ * didn't _tell us right now_ to abandon this connection, so we
+ * still need to inform them that we've done so. */
+ SPRK_SW_ABORT,
+
+ /* We're proceeding with the connection and have all requested
+ * information (if any) */
+ SPRK_OK
+} SeatPromptResultKind;
+
+/* Small struct to present the results of interactive requests from
+ * backend to Seat (see below) */
+struct SeatPromptResult {
+ SeatPromptResultKind kind;
+
+ /*
+ * In the case of SPRK_SW_ABORT, the frontend provides an error
+ * message to present to the user. But dynamically allocating it
+ * up front would mean having to make sure it got freed at any
+ * call site where one of these structs is received (and freed
+ * _once_ no matter how many times the struct is copied). So
+ * instead we provide a function that will generate the error
+ * message into a BinarySink.
+ */
+ void (*errfn)(SeatPromptResult, BinarySink *);
+
+ /*
+ * And some fields the error function can use to construct the
+ * message (holding, e.g. an OS error code).
+ */
+ const char *errdata_lit; /* statically allocated, e.g. a string literal */
+ unsigned errdata_u;
+};
+
+/* Helper function to construct the simple versions of these
+ * structures inline */
+static inline SeatPromptResult make_spr_simple(SeatPromptResultKind kind)
+{
+ SeatPromptResult spr;
+ spr.kind = kind;
+ spr.errdata_lit = NULL;
+ return spr;
+}
+
+/* Most common constructor function for SPRK_SW_ABORT errors */
+SeatPromptResult make_spr_sw_abort_static(const char *);
+
+/* Convenience macros wrapping those constructors in turn */
+#define SPR_INCOMPLETE make_spr_simple(SPRK_INCOMPLETE)
+#define SPR_USER_ABORT make_spr_simple(SPRK_USER_ABORT)
+#define SPR_SW_ABORT(lit) make_spr_sw_abort_static(lit)
+#define SPR_OK make_spr_simple(SPRK_OK)
+
+/* Query function that folds both kinds of abort together */
+static inline bool spr_is_abort(SeatPromptResult spr)
+{
+ return spr.kind == SPRK_USER_ABORT || spr.kind == SPRK_SW_ABORT;
+}
+
+/* Function to return a dynamically allocated copy of the error message */
+char *spr_get_error_message(SeatPromptResult spr);
+
+/*
* Mechanism for getting text strings such as usernames and passwords
* from the front-end.
* The fields are mostly modelled after SSH's keyboard-interactive auth.
@@ -753,7 +969,8 @@ typedef struct {
bool echo;
strbuf *result;
} prompt_t;
-typedef struct {
+typedef struct prompts_t prompts_t;
+struct prompts_t {
/*
* Indicates whether the information entered is to be used locally
* (for instance a key passphrase prompt), or is destined for the wire.
@@ -781,7 +998,25 @@ typedef struct {
prompt_t **prompts;
void *data; /* slot for housekeeping data, managed by
* seat_get_userpass_input(); initially NULL */
-} prompts_t;
+ SeatPromptResult spr; /* some implementations need to cache one of these */
+
+ /*
+ * Callback you can fill in to be notified when all the prompts'
+ * responses are available. After you receive this notification, a
+ * further call to the get_userpass_input function will return the
+ * final state of the prompts system, which is guaranteed not to
+ * be negative for 'still ongoing'.
+ */
+ toplevel_callback_fn_t callback;
+ void *callback_ctx;
+
+ /*
+ * When this prompts_t is known to an Ldisc, we might need to
+ * break the connection if things get freed in an emergency. So
+ * this is a pointer to the Ldisc's pointer to us.
+ */
+ prompts_t **ldisc_ptr_to_us;
+};
prompts_t *new_prompts(void);
void add_prompt(prompts_t *p, char *promptstr, bool echo);
void prompt_set_result(prompt_t *pr, const char *newstr);
@@ -856,6 +1091,28 @@ typedef enum SeatInteractionContext {
SIC_BANNER, SIC_KI_PROMPTS
} SeatInteractionContext;
+typedef enum SeatOutputType {
+ SEAT_OUTPUT_STDOUT, SEAT_OUTPUT_STDERR
+} SeatOutputType;
+
+typedef enum SeatDialogTextType {
+ SDT_PARA, SDT_DISPLAY, SDT_SCARY_HEADING,
+ SDT_TITLE, SDT_PROMPT, SDT_BATCH_ABORT,
+ SDT_MORE_INFO_KEY, SDT_MORE_INFO_VALUE_SHORT, SDT_MORE_INFO_VALUE_BLOB
+} SeatDialogTextType;
+struct SeatDialogTextItem {
+ SeatDialogTextType type;
+ char *text;
+};
+struct SeatDialogText {
+ size_t nitems, itemsize;
+ SeatDialogTextItem *items;
+};
+SeatDialogText *seat_dialog_text_new(void);
+void seat_dialog_text_free(SeatDialogText *sdt);
+PRINTF_LIKE(3, 4) void seat_dialog_text_append(
+ SeatDialogText *sdt, SeatDialogTextType type, const char *fmt, ...);
+
/*
* Data type 'Seat', which is an API intended to contain essentially
* everything that a back end might need to talk to its client for:
@@ -868,14 +1125,16 @@ struct Seat {
};
struct SeatVtable {
/*
- * Provide output from the remote session. 'is_stderr' indicates
- * that the output should be sent to a separate error message
- * channel, if the seat has one. But combining both channels into
- * one is OK too; that's what terminal-window based seats do.
+ * Provide output from the remote session. 'type' indicates the
+ * type of the output (stdout or stderr), which can be used to
+ * split the output into separate message channels, if the seat
+ * wants to handle them differently. But combining the channels
+ * into one is OK too; that's what terminal-window based seats do.
*
* The return value is the current size of the output backlog.
*/
- size_t (*output)(Seat *seat, bool is_stderr, const void *data, size_t len);
+ size_t (*output)(Seat *seat, SeatOutputType type,
+ const void *data, size_t len);
/*
* Called when the back end wants to indicate that EOF has arrived
@@ -886,40 +1145,49 @@ struct SeatVtable {
bool (*eof)(Seat *seat);
/*
+ * Called by the back end to notify that the output backlog has
+ * changed size. A front end in control of the event loop won't
+ * necessarily need this (they can just keep checking it via
+ * backend_sendbuffer at every opportunity), but one buried in the
+ * depths of something else (like an SSH proxy) will need to be
+ * proactively notified that the amount of buffered data has
+ * become smaller.
+ */
+ void (*sent)(Seat *seat, size_t new_sendbuffer);
+
+ /*
+ * Provide authentication-banner output from the session setup.
+ * End-user Seats can treat this as very similar to 'output', but
+ * intermediate Seats in complex proxying situations will want to
+ * implement this and 'output' differently.
+ */
+ size_t (*banner)(Seat *seat, const void *data, size_t len);
+
+ /*
* Try to get answers from a set of interactive login prompts. The
- * prompts are provided in 'p'; the bufchain 'input' holds the
- * data currently outstanding in the session's normal standard-
- * input channel. Seats may implement this function by consuming
- * data from 'input' (e.g. password prompts in GUI PuTTY,
- * displayed in the same terminal as the subsequent session), or
- * by doing something entirely different (e.g. directly
- * interacting with standard I/O, or putting up a dialog box).
- *
- * A positive return value means that all prompts have had answers
- * filled in. A zero return means that the user performed a
- * deliberate 'cancel' UI action. A negative return means that no
- * answer can be given yet but please try again later.
+ * prompts are provided in 'p'.
*
- * (FIXME: it would be nice to distinguish two classes of cancel
- * action, so the user could specify 'I want to abandon this
+ * (FIXME: it would be nice to distinguish two classes of user-
+ * abort action, so the user could specify 'I want to abandon this
* entire attempt to start a session' or the milder 'I want to
* abandon this particular form of authentication and fall back to
* a different one' - e.g. if you turn out not to be able to
* remember your private key passphrase then perhaps you'd rather
* fall back to password auth rather than aborting the whole
* session.)
+ */
+ SeatPromptResult (*get_userpass_input)(Seat *seat, prompts_t *p);
+
+ /*
+ * Notify the seat that the main session channel has been
+ * successfully set up.
*
- * (Also FIXME: currently, backends' only response to the 'try
- * again later' is to try again when more input data becomes
- * available, because they assume that a seat is returning that
- * value because it's consuming keyboard input. But a seat that
- * handled this function by putting up a dialog box might want to
- * put it up non-modally, and therefore would want to proactively
- * notify the backend to retry once the dialog went away. So if I
- * ever do want to move password prompts into a dialog box, I'll
- * want a backend method for sending that notification.)
+ * This is only used as part of the SSH proxying system, so it's
+ * not necessary to implement it in all backends. A backend must
+ * call this if it advertises the BACKEND_NOTIFIES_SESSION_START
+ * flag, and otherwise, doesn't have to.
*/
- int (*get_userpass_input)(Seat *seat, prompts_t *p, bufchain *input);
+ void (*notify_session_started)(Seat *seat);
/*
* Notify the seat that the process running at the other end of
@@ -928,6 +1196,29 @@ struct SeatVtable {
void (*notify_remote_exit)(Seat *seat);
/*
+ * Notify the seat that the whole connection has finished.
+ * (Distinct from notify_remote_exit, e.g. in the case where you
+ * have port forwardings still active when the main foreground
+ * session goes away: then you'd get notify_remote_exit when the
+ * foreground session dies, but notify_remote_disconnect when the
+ * last forwarding vanishes and the network connection actually
+ * closes.)
+ *
+ * This function might be called multiple times by accident; seats
+ * should be prepared to cope.
+ *
+ * More precisely: this function notifies the seat that
+ * backend_connected() might now return false where previously it
+ * returned true. (Note the 'might': an accidental duplicate call
+ * might happen when backend_connected() was already returning
+ * false. Or even, in weird situations, when it hadn't stopped
+ * returning true yet. The point is, when you get this
+ * notification, all it's really telling you is that it's worth
+ * _checking_ backend_connected, if you weren't already.)
+ */
+ void (*notify_remote_disconnect)(Seat *seat);
+
+ /*
* Notify the seat that the connection has suffered a fatal error.
*/
void (*connection_fatal)(Seat *seat, const char *message);
@@ -967,35 +1258,47 @@ struct SeatVtable {
/*
* Ask the seat whether a given SSH host key should be accepted.
- * This may return immediately after checking saved configuration
- * or command-line options, or it may have to present a prompt to
- * the user and return asynchronously later.
+ * This is called after we've already checked it by any means we
+ * can do ourselves, such as checking against host key
+ * fingerprints in the Conf or the host key cache on disk: once we
+ * call this function, we've already decided there's nothing for
+ * it but to prompt the user.
+ *
+ * 'mismatch' reports the result of checking the host key cache:
+ * it is true if the server has presented a host key different
+ * from the one we expected, and false if we had no expectation in
+ * the first place.
+ *
+ * This call may prompt the user synchronously and not return
+ * until the answer is available, or it may present the prompt and
+ * return immediately, giving the answer later via the provided
+ * callback.
*
* Return values:
*
- * - +1 means `key was OK' (either already known or the user just
- * approved it) `so continue with the connection'
+ * - +1 means `user approved the key, so continue with the
+ * connection'
*
- * - 0 means `key was not OK, abandon the connection'
+ * - 0 means `user rejected the key, abandon the connection'
*
* - -1 means `I've initiated enquiries, please wait to be called
* back via the provided function with a result that's either 0
* or +1'.
*/
- int (*verify_ssh_host_key)(
+ SeatPromptResult (*confirm_ssh_host_key)(
Seat *seat, const char *host, int port, const char *keytype,
- char *keystr, const char *keydisp, char **key_fingerprints,
- void (*callback)(void *ctx, int result), void *ctx);
+ char *keystr, SeatDialogText *text, HelpCtx helpctx,
+ void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
/*
* Check with the seat whether it's OK to use a cryptographic
* primitive from below the 'warn below this line' threshold in
* the input Conf. Return values are the same as
- * verify_ssh_host_key above.
+ * confirm_ssh_host_key above.
*/
- int (*confirm_weak_crypto_primitive)(
+ SeatPromptResult (*confirm_weak_crypto_primitive)(
Seat *seat, const char *algtype, const char *algname,
- void (*callback)(void *ctx, int result), void *ctx);
+ void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
/*
* Variant form of confirm_weak_crypto_primitive, which prints a
@@ -1008,9 +1311,16 @@ struct SeatVtable {
* threshold is available that we don't have cached. 'betteralgs'
* lists the better algorithm(s).
*/
- int (*confirm_weak_cached_hostkey)(
+ SeatPromptResult (*confirm_weak_cached_hostkey)(
Seat *seat, const char *algname, const char *betteralgs,
- void (*callback)(void *ctx, int result), void *ctx);
+ void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
+
+ /*
+ * Some snippets of text describing the UI actions in host key
+ * prompts / dialog boxes, to be used in ssh/common.c when it
+ * assembles the full text of those prompts.
+ */
+ const SeatDialogPromptDescriptions *(*prompt_descriptions)(Seat *seat);
/*
* Indicates whether the seat is expecting to interact with the
@@ -1062,13 +1372,31 @@ struct SeatVtable {
* (and hence, can be trusted if it's asking you for secrets such
* as your passphrase); false means output is coming from the
* server.
+ */
+ void (*set_trust_status)(Seat *seat, bool trusted);
+
+ /*
+ * Query whether this Seat can do anything user-visible in
+ * response to set_trust_status.
*
* Returns true if the seat has a way to indicate this
* distinction. Returns false if not, in which case the backend
* should use a fallback defence against spoofing of PuTTY's local
* prompts by malicious servers.
*/
- bool (*set_trust_status)(Seat *seat, bool trusted);
+ bool (*can_set_trust_status)(Seat *seat);
+
+ /*
+ * Query whether this Seat's interactive prompt responses and its
+ * session input come from the same place.
+ *
+ * If false, this is used to suppress the final 'Press Return to
+ * begin session' anti-spoofing prompt in Plink. For example,
+ * Plink itself sets this flag if its standard input is redirected
+ * (and therefore not coming from the same place as the console
+ * it's sending its prompts to).
+ */
+ bool (*has_mixed_input_stream)(Seat *seat);
/*
* Ask the seat whether it would like verbose messages.
@@ -1089,34 +1417,49 @@ struct SeatVtable {
};
static inline size_t seat_output(
- Seat *seat, bool err, const void *data, size_t len)
-{ return seat->vt->output(seat, err, data, len); }
+ Seat *seat, SeatOutputType type, const void *data, size_t len)
+{ return seat->vt->output(seat, type, data, len); }
static inline bool seat_eof(Seat *seat)
{ return seat->vt->eof(seat); }
-static inline int seat_get_userpass_input(
- Seat *seat, prompts_t *p, bufchain *input)
-{ return seat->vt->get_userpass_input(seat, p, input); }
+static inline void seat_sent(Seat *seat, size_t bufsize)
+{ seat->vt->sent(seat, bufsize); }
+static inline size_t seat_banner(
+ InteractionReadySeat iseat, const void *data, size_t len)
+{ return iseat.seat->vt->banner(iseat.seat, data, len); }
+static inline SeatPromptResult seat_get_userpass_input(
+ InteractionReadySeat iseat, prompts_t *p)
+{ return iseat.seat->vt->get_userpass_input(iseat.seat, p); }
+static inline void seat_notify_session_started(Seat *seat)
+{ seat->vt->notify_session_started(seat); }
static inline void seat_notify_remote_exit(Seat *seat)
{ seat->vt->notify_remote_exit(seat); }
+static inline void seat_notify_remote_disconnect(Seat *seat)
+{ seat->vt->notify_remote_disconnect(seat); }
static inline void seat_update_specials_menu(Seat *seat)
{ seat->vt->update_specials_menu(seat); }
static inline char *seat_get_ttymode(Seat *seat, const char *mode)
{ return seat->vt->get_ttymode(seat, mode); }
static inline void seat_set_busy_status(Seat *seat, BusyStatus status)
{ seat->vt->set_busy_status(seat, status); }
-static inline int seat_verify_ssh_host_key(
- Seat *seat, const char *h, int p, const char *ktyp, char *kstr,
- const char *kdsp, char **fps, void (*cb)(void *ctx, int result), void *ctx)
-{ return seat->vt->verify_ssh_host_key(seat, h, p, ktyp, kstr, kdsp, fps,
- cb, ctx); }
-static inline int seat_confirm_weak_crypto_primitive(
- Seat *seat, const char *atyp, const char *aname,
- void (*cb)(void *ctx, int result), void *ctx)
-{ return seat->vt->confirm_weak_crypto_primitive(seat, atyp, aname, cb, ctx); }
-static inline int seat_confirm_weak_cached_hostkey(
- Seat *seat, const char *aname, const char *better,
- void (*cb)(void *ctx, int result), void *ctx)
-{ return seat->vt->confirm_weak_cached_hostkey(seat, aname, better, cb, ctx); }
+static inline SeatPromptResult seat_confirm_ssh_host_key(
+ InteractionReadySeat iseat, const char *h, int p, const char *ktyp,
+ char *kstr, SeatDialogText *text, HelpCtx helpctx,
+ void (*cb)(void *ctx, SeatPromptResult result), void *ctx)
+{ return iseat.seat->vt->confirm_ssh_host_key(
+ iseat.seat, h, p, ktyp, kstr, text, helpctx, cb, ctx); }
+static inline SeatPromptResult seat_confirm_weak_crypto_primitive(
+ InteractionReadySeat iseat, const char *atyp, const char *aname,
+ void (*cb)(void *ctx, SeatPromptResult result), void *ctx)
+{ return iseat.seat->vt->confirm_weak_crypto_primitive(
+ iseat.seat, atyp, aname, cb, ctx); }
+static inline SeatPromptResult seat_confirm_weak_cached_hostkey(
+ InteractionReadySeat iseat, const char *aname, const char *better,
+ void (*cb)(void *ctx, SeatPromptResult result), void *ctx)
+{ return iseat.seat->vt->confirm_weak_cached_hostkey(
+ iseat.seat, aname, better, cb, ctx); }
+static inline const SeatDialogPromptDescriptions *seat_prompt_descriptions(
+ Seat *seat)
+{ return seat->vt->prompt_descriptions(seat); }
static inline bool seat_is_utf8(Seat *seat)
{ return seat->vt->is_utf8(seat); }
static inline void seat_echoedit_update(Seat *seat, bool ec, bool ed)
@@ -1130,8 +1473,12 @@ static inline bool seat_get_window_pixel_size(Seat *seat, int *w, int *h)
static inline StripCtrlChars *seat_stripctrl_new(
Seat *seat, BinarySink *bs, SeatInteractionContext sic)
{ return seat->vt->stripctrl_new(seat, bs, sic); }
-static inline bool seat_set_trust_status(Seat *seat, bool trusted)
-{ return seat->vt->set_trust_status(seat, trusted); }
+static inline void seat_set_trust_status(Seat *seat, bool trusted)
+{ seat->vt->set_trust_status(seat, trusted); }
+static inline bool seat_can_set_trust_status(Seat *seat)
+{ return seat->vt->can_set_trust_status(seat); }
+static inline bool seat_has_mixed_input_stream(Seat *seat)
+{ return seat->vt->has_mixed_input_stream(seat); }
static inline bool seat_verbose(Seat *seat)
{ return seat->vt->verbose(seat); }
static inline bool seat_interactive(Seat *seat)
@@ -1141,18 +1488,32 @@ static inline bool seat_get_cursor_position(Seat *seat, int *x, int *y)
/* Unlike the seat's actual method, the public entry point
* seat_connection_fatal is a wrapper function with a printf-like API,
- * defined in misc.c. */
+ * defined in utils. */
void seat_connection_fatal(Seat *seat, const char *fmt, ...) PRINTF_LIKE(2, 3);
/* Handy aliases for seat_output which set is_stderr to a fixed value. */
static inline size_t seat_stdout(Seat *seat, const void *data, size_t len)
-{ return seat_output(seat, false, data, len); }
+{ return seat_output(seat, SEAT_OUTPUT_STDOUT, data, len); }
static inline size_t seat_stdout_pl(Seat *seat, ptrlen data)
-{ return seat_output(seat, false, data.ptr, data.len); }
+{ return seat_output(seat, SEAT_OUTPUT_STDOUT, data.ptr, data.len); }
static inline size_t seat_stderr(Seat *seat, const void *data, size_t len)
-{ return seat_output(seat, true, data, len); }
+{ return seat_output(seat, SEAT_OUTPUT_STDERR, data, len); }
static inline size_t seat_stderr_pl(Seat *seat, ptrlen data)
-{ return seat_output(seat, true, data.ptr, data.len); }
+{ return seat_output(seat, SEAT_OUTPUT_STDERR, data.ptr, data.len); }
+
+/* Alternative API for seat_banner taking a ptrlen */
+static inline size_t seat_banner_pl(InteractionReadySeat iseat, ptrlen data)
+{ return iseat.seat->vt->banner(iseat.seat, data.ptr, data.len); }
+
+struct SeatDialogPromptDescriptions {
+ const char *hk_accept_action;
+ const char *hk_connect_once_action;
+ const char *hk_cancel_action, *hk_cancel_action_Participle;
+};
+
+/* In the utils subdir: print a message to the Seat which can't be
+ * spoofed by server-supplied auth-time output such as SSH banners */
+void seat_antispoof_msg(InteractionReadySeat iseat, const char *msg);
/*
* Stub methods for seat implementations that want to use the obvious
@@ -1162,24 +1523,30 @@ static inline size_t seat_stderr_pl(Seat *seat, ptrlen data)
* plausibly want to return either fixed answer 'no' or 'yes'.
*/
size_t nullseat_output(
- Seat *seat, bool is_stderr, const void *data, size_t len);
+ Seat *seat, SeatOutputType type, const void *data, size_t len);
bool nullseat_eof(Seat *seat);
-int nullseat_get_userpass_input(Seat *seat, prompts_t *p, bufchain *input);
+void nullseat_sent(Seat *seat, size_t bufsize);
+size_t nullseat_banner(Seat *seat, const void *data, size_t len);
+size_t nullseat_banner_to_stderr(Seat *seat, const void *data, size_t len);
+SeatPromptResult nullseat_get_userpass_input(Seat *seat, prompts_t *p);
+void nullseat_notify_session_started(Seat *seat);
void nullseat_notify_remote_exit(Seat *seat);
+void nullseat_notify_remote_disconnect(Seat *seat);
void nullseat_connection_fatal(Seat *seat, const char *message);
void nullseat_update_specials_menu(Seat *seat);
char *nullseat_get_ttymode(Seat *seat, const char *mode);
void nullseat_set_busy_status(Seat *seat, BusyStatus status);
-int nullseat_verify_ssh_host_key(
+SeatPromptResult nullseat_confirm_ssh_host_key(
Seat *seat, const char *host, int port, const char *keytype,
- char *keystr, const char *keydisp, char **key_fingerprints,
- void (*callback)(void *ctx, int result), void *ctx);
-int nullseat_confirm_weak_crypto_primitive(
+ char *keystr, SeatDialogText *text, HelpCtx helpctx,
+ void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
+SeatPromptResult nullseat_confirm_weak_crypto_primitive(
Seat *seat, const char *algtype, const char *algname,
- void (*callback)(void *ctx, int result), void *ctx);
-int nullseat_confirm_weak_cached_hostkey(
+ void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
+SeatPromptResult nullseat_confirm_weak_cached_hostkey(
Seat *seat, const char *algname, const char *betteralgs,
- void (*callback)(void *ctx, int result), void *ctx);
+ void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
+const SeatDialogPromptDescriptions *nullseat_prompt_descriptions(Seat *seat);
bool nullseat_is_never_utf8(Seat *seat);
bool nullseat_is_always_utf8(Seat *seat);
void nullseat_echoedit_update(Seat *seat, bool echoing, bool editing);
@@ -1187,9 +1554,12 @@ const char *nullseat_get_x_display(Seat *seat);
bool nullseat_get_windowid(Seat *seat, long *id_out);
bool nullseat_get_window_pixel_size(Seat *seat, int *width, int *height);
StripCtrlChars *nullseat_stripctrl_new(
- Seat *seat, BinarySink *bs_out, SeatInteractionContext sic);
-bool nullseat_set_trust_status(Seat *seat, bool trusted);
-bool nullseat_set_trust_status_vacuously(Seat *seat, bool trusted);
+ Seat *seat, BinarySink *bs_out, SeatInteractionContext sic);
+void nullseat_set_trust_status(Seat *seat, bool trusted);
+bool nullseat_can_set_trust_status_yes(Seat *seat);
+bool nullseat_can_set_trust_status_no(Seat *seat);
+bool nullseat_has_mixed_input_stream_yes(Seat *seat);
+bool nullseat_has_mixed_input_stream_no(Seat *seat);
bool nullseat_verbose_no(Seat *seat);
bool nullseat_verbose_yes(Seat *seat);
bool nullseat_interactive_no(Seat *seat);
@@ -1198,30 +1568,58 @@ bool nullseat_get_cursor_position(Seat *seat, int *x, int *y);
/*
* Seat functions provided by the platform's console-application
- * support module (wincons.c, uxcons.c).
+ * support module (console.c in each platform subdirectory).
*/
void console_connection_fatal(Seat *seat, const char *message);
-int console_verify_ssh_host_key(
+SeatPromptResult console_confirm_ssh_host_key(
Seat *seat, const char *host, int port, const char *keytype,
- char *keystr, const char *keydisp, char **key_fingerprints,
- void (*callback)(void *ctx, int result), void *ctx);
-int console_confirm_weak_crypto_primitive(
+ char *keystr, SeatDialogText *text, HelpCtx helpctx,
+ void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
+SeatPromptResult console_confirm_weak_crypto_primitive(
Seat *seat, const char *algtype, const char *algname,
- void (*callback)(void *ctx, int result), void *ctx);
-int console_confirm_weak_cached_hostkey(
+ void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
+SeatPromptResult console_confirm_weak_cached_hostkey(
Seat *seat, const char *algname, const char *betteralgs,
- void (*callback)(void *ctx, int result), void *ctx);
+ void (*callback)(void *ctx, SeatPromptResult result), void *ctx);
StripCtrlChars *console_stripctrl_new(
- Seat *seat, BinarySink *bs_out, SeatInteractionContext sic);
-bool console_set_trust_status(Seat *seat, bool trusted);
+ Seat *seat, BinarySink *bs_out, SeatInteractionContext sic);
+void console_set_trust_status(Seat *seat, bool trusted);
+bool console_can_set_trust_status(Seat *seat);
+bool console_has_mixed_input_stream(Seat *seat);
+const SeatDialogPromptDescriptions *console_prompt_descriptions(Seat *seat);
/*
* Other centralised seat functions.
*/
-int filexfer_get_userpass_input(Seat *seat, prompts_t *p, bufchain *input);
+SeatPromptResult filexfer_get_userpass_input(Seat *seat, prompts_t *p);
bool cmdline_seat_verbose(Seat *seat);
+/*
+ * TempSeat: a seat implementation that can be given to a backend
+ * temporarily while network proxy setup is using the real seat.
+ * Buffers output and trust-status changes until the real seat is
+ * available again.
+ */
+
+/* Called by the proxy code to make a TempSeat. */
+Seat *tempseat_new(Seat *real);
+
+/* Query functions to tell if a Seat _is_ temporary, and if so, to
+ * return the underlying real Seat. */
+bool is_tempseat(Seat *seat);
+Seat *tempseat_get_real(Seat *seat);
+
+/* Called by interactor_return_seat once the proxy connection has
+ * finished setting up (or failed), to pass on any buffered stuff to
+ * the real seat. */
+void tempseat_flush(Seat *ts);
+
+/* Frees a TempSeat, without flushing anything it has buffered. (Call
+ * this after tempseat_flush, or alternatively, when you were going to
+ * abandon the whole connection anyway.) */
+void tempseat_free(Seat *ts);
+
typedef struct rgb {
uint8_t r, g, b;
} rgb;
@@ -1282,10 +1680,22 @@ struct TermWinVtable {
void (*refresh)(TermWin *);
+ /* request_resize asks the front end if the terminal can please be
+ * resized to (w,h) in characters. The front end MAY call
+ * term_size() in response to tell the terminal its new size
+ * (which MAY be the requested size, or some other size if the
+ * requested one can't be achieved). The front end MAY also not
+ * call term_size() at all. But the front end MUST reply to this
+ * request by calling term_resize_request_completed(), after the
+ * responding resize event has taken place (if any).
+ *
+ * The calls to term_size and term_resize_request_completed may be
+ * synchronous callbacks from within the call to request_resize(). */
void (*request_resize)(TermWin *, int w, int h);
- void (*set_title)(TermWin *, const char *title);
- void (*set_icon_title)(TermWin *, const char *icontitle);
+ void (*set_title)(TermWin *, const char *title, int codepage);
+ void (*set_icon_title)(TermWin *, const char *icontitle, int codepage);
+
/* set_minimised and set_maximised are assumed to set two
* independent settings, rather than a single three-way
* {min,normal,max} switch. The idea is that when you un-minimise
@@ -1312,6 +1722,11 @@ struct TermWinVtable {
* object, because that doesn't happen until term_init
* returns. */
void (*palette_get_overrides)(TermWin *, Terminal *);
+
+ /* Notify the front end that the terminal's buffer of unprocessed
+ * output has reduced. (Front ends will likely pass this straight
+ * on to backend_unthrottle.) */
+ void (*unthrottle)(TermWin *, size_t bufsize);
};
static inline bool win_setup_draw_ctx(TermWin *win)
@@ -1350,10 +1765,11 @@ static inline void win_refresh(TermWin *win)
{ win->vt->refresh(win); }
static inline void win_request_resize(TermWin *win, int w, int h)
{ win->vt->request_resize(win, w, h); }
-static inline void win_set_title(TermWin *win, const char *title)
-{ win->vt->set_title(win, title); }
-static inline void win_set_icon_title(TermWin *win, const char *icontitle)
-{ win->vt->set_icon_title(win, icontitle); }
+static inline void win_set_title(TermWin *win, const char *title, int codepage)
+{ win->vt->set_title(win, title, codepage); }
+static inline void win_set_icon_title(TermWin *win, const char *icontitle,
+ int codepage)
+{ win->vt->set_icon_title(win, icontitle, codepage); }
static inline void win_set_minimised(TermWin *win, bool minimised)
{ win->vt->set_minimised(win, minimised); }
static inline void win_set_maximised(TermWin *win, bool maximised)
@@ -1367,6 +1783,8 @@ static inline void win_palette_set(
{ win->vt->palette_set(win, start, ncolours, colours); }
static inline void win_palette_get_overrides(TermWin *win, Terminal *term)
{ win->vt->palette_get_overrides(win, term); }
+static inline void win_unthrottle(TermWin *win, size_t size)
+{ win->vt->unthrottle(win, size); }
/*
* Global functions not specific to a connection instance.
@@ -1417,6 +1835,8 @@ NORETURN void cleanup_exit(int);
X(BOOL, NONE, change_username) /* allow username switching in SSH-2 */ \
X(INT, INT, ssh_cipherlist) \
X(FILENAME, NONE, keyfile) \
+ X(FILENAME, NONE, detached_cert) \
+ X(STR, NONE, auth_plugin) \
/* \
* Which SSH protocol to use. \
* For historical reasons, the current legal values for CONF_sshprot \
@@ -1474,6 +1894,7 @@ NORETURN void cleanup_exit(int);
X(BOOL, NONE, bksp_is_delete) \
X(BOOL, NONE, rxvt_homeend) \
X(INT, NONE, funky_type) /* FUNKY_XTERM, FUNKY_LINUX, ... */ \
+ X(INT, NONE, sharrow_type) /* SHARROW_APPLICATION, SHARROW_BITMAP, ... */ \
X(BOOL, NONE, no_applic_c) /* totally disable app cursor keys */ \
X(BOOL, NONE, no_applic_k) /* totally disable app keypad */ \
X(BOOL, NONE, no_mouse_rep) /* totally disable mouse reporting */ \
@@ -1606,6 +2027,8 @@ NORETURN void cleanup_exit(int);
X(INT, NONE, sshbug_oldgex2) \
X(INT, NONE, sshbug_winadj) \
X(INT, NONE, sshbug_chanreq) \
+ X(INT, NONE, sshbug_dropstart) \
+ X(INT, NONE, sshbug_filter_kexinit) \
/* \
* ssh_simple means that we promise never to open any channel \
* other than the main one, which means it can safely use a very \
@@ -1686,7 +2109,7 @@ void fontspec_serialise(BinarySink *bs, FontSpec *f);
FontSpec *fontspec_deserialise(BinarySource *src);
/*
- * Exports from noise.c.
+ * Exports from each platform's noise.c.
*/
typedef enum NoiseSourceId {
NOISE_SOURCE_TIME,
@@ -1712,6 +2135,10 @@ void noise_get_heavy(void (*func) (void *, int));
void noise_get_light(void (*func) (void *, int));
void noise_regular(void);
void noise_ultralight(NoiseSourceId id, unsigned long data);
+
+/*
+ * Exports from sshrand.c.
+ */
void random_save_seed(void);
void random_destroy_seed(void);
@@ -1763,6 +2190,7 @@ FontSpec *platform_default_fontspec(const char *name);
Terminal *term_init(Conf *, struct unicode_data *, TermWin *);
void term_free(Terminal *);
void term_size(Terminal *, int, int, int);
+void term_resize_request_completed(Terminal *);
void term_paint(Terminal *, int, int, int, int, bool);
void term_scroll(Terminal *, int, int);
void term_scroll_to_selection(Terminal *, int);
@@ -1770,6 +2198,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);
@@ -1784,15 +2213,15 @@ void term_reconfig(Terminal *, Conf *);
void term_request_copy(Terminal *, const int *clipboards, int n_clipboards);
void term_request_paste(Terminal *, int clipboard);
void term_seen_key_event(Terminal *);
-size_t term_data(Terminal *, bool is_stderr, const void *data, size_t len);
+size_t term_data(Terminal *, const void *data, size_t len);
void term_provide_backend(Terminal *term, Backend *backend);
void term_provide_logctx(Terminal *term, LogContext *logctx);
void term_set_focus(Terminal *term, bool has_focus);
char *term_get_ttymode(Terminal *term, const char *mode);
-int term_get_userpass_input(Terminal *term, prompts_t *p, bufchain *input);
+SeatPromptResult term_get_userpass_input(Terminal *term, prompts_t *p);
void term_set_trust_status(Terminal *term, bool trusted);
void term_keyinput(Terminal *, int codepage, const void *buf, int len);
-void term_keyinputw(Terminal *, const wchar_t * widebuf, int len);
+void term_keyinputw(Terminal *, const wchar_t *widebuf, int len);
void term_get_cursor_position(Terminal *term, int *x, int *y);
void term_setup_window_titles(Terminal *term, const char *title_hostname);
void term_notify_minimised(Terminal *term, bool minimised);
@@ -1804,10 +2233,13 @@ void term_palette_override(Terminal *term, unsigned osc4_index, rgb rgb);
typedef enum SmallKeypadKey {
SKK_HOME, SKK_END, SKK_INSERT, SKK_DELETE, SKK_PGUP, SKK_PGDN,
} SmallKeypadKey;
-int format_arrow_key(char *buf, Terminal *term, int xkey, bool ctrl);
+int format_arrow_key(char *buf, Terminal *term, int xkey,
+ bool shift, bool ctrl, bool alt, bool *consumed_alt);
int format_function_key(char *buf, Terminal *term, int key_number,
- bool shift, bool ctrl);
-int format_small_keypad_key(char *buf, Terminal *term, SmallKeypadKey key);
+ bool shift, bool ctrl, bool alt, bool *consumed_alt);
+int format_small_keypad_key(char *buf, Terminal *term, SmallKeypadKey key,
+ bool shift, bool ctrl, bool alt,
+ bool *consumed_alt);
int format_numeric_keypad_key(char *buf, Terminal *term, char key,
bool shift, bool ctrl);
@@ -1870,7 +2302,7 @@ static inline void lp_logging_error(LogPolicy *lp, const char *event)
static inline bool lp_verbose(LogPolicy *lp)
{ return lp->vt->verbose(lp); }
-/* Defined in conscli.c, used in several console command-line tools */
+/* Defined in clicons.c, used in several console command-line tools */
extern LogPolicy console_cli_logpolicy[];
int console_askappend(LogPolicy *lp, Filename *filename,
@@ -1888,6 +2320,7 @@ void logfopen(LogContext *logctx);
void logfclose(LogContext *logctx);
void logtraffic(LogContext *logctx, unsigned char c, int logmode);
void logflush(LogContext *logctx);
+LogPolicy *log_get_policy(LogContext *logctx);
void logevent(LogContext *logctx, const char *event);
void logeventf(LogContext *logctx, const char *fmt, ...) PRINTF_LIKE(2, 3);
void logeventvf(LogContext *logctx, const char *fmt, va_list ap);
@@ -1937,7 +2370,7 @@ extern const struct BackendVtable rlogin_backend;
extern const struct BackendVtable telnet_backend;
/*
- * Exports from ssh.c.
+ * Exports from ssh/ssh.c.
*/
extern const struct BackendVtable ssh_backend;
extern const struct BackendVtable sshconn_backend;
@@ -1955,6 +2388,29 @@ void ldisc_configure(Ldisc *, Conf *);
void ldisc_free(Ldisc *);
void ldisc_send(Ldisc *, const void *buf, int len, bool interactive);
void ldisc_echoedit_update(Ldisc *);
+typedef struct LdiscInputToken {
+ /*
+ * Structure that encodes any single item of data that Ldisc can
+ * buffer: either a single character of raw data, or a session
+ * special.
+ */
+ bool is_special;
+ union {
+ struct {
+ /* if is_special == false */
+ char chr;
+ };
+ struct {
+ /* if is_special == true */
+ SessionSpecialCode code;
+ int arg;
+ };
+ };
+} LdiscInputToken;
+bool ldisc_has_input_buffered(Ldisc *);
+LdiscInputToken ldisc_get_input_token(Ldisc *); /* asserts there is input */
+void ldisc_enable_prompt_callback(Ldisc *, prompts_t *);
+void ldisc_check_sendok(Ldisc *);
/*
* Exports from sshrand.c.
@@ -1999,7 +2455,7 @@ void pinger_reconfig(Pinger *, Conf *oldconf, Conf *newconf);
void pinger_free(Pinger *);
/*
- * Exports from misc.c.
+ * Exports from modules in utils.
*/
#include "misc.h"
@@ -2012,19 +2468,13 @@ char const *conf_dest(Conf *conf);
void prepare_session(Conf *conf);
/*
- * Exports from sercfg.c.
- */
-void ser_setup_config_box(struct controlbox *b, bool midsession,
- int parity_mask, int flow_mask);
-
-/*
- * Exports from version.c.
+ * Exports from version.c and cmake_commit.c.
*/
extern const char ver[];
extern const char commitid[];
/*
- * Exports from unicode.c.
+ * Exports from unicode.c in platform subdirs.
*/
#ifndef CP_UTF8
#define CP_UTF8 65001
@@ -2034,14 +2484,13 @@ bool is_dbcs_leadbyte(int codepage, char byte);
int mb_to_wc(int codepage, int flags, const char *mbstr, int mblen,
wchar_t *wcstr, int wclen);
int wc_to_mb(int codepage, int flags, const wchar_t *wcstr, int wclen,
- char *mbstr, int mblen, const char *defchr,
- struct unicode_data *ucsdata);
+ char *mbstr, int mblen, const char *defchr);
wchar_t xlat_uskbd2cyrllic(int ch);
int check_compose(int first, int second);
-int decode_codepage(char *cp_name);
+int decode_codepage(const char *cp_name);
const char *cp_enumerate (int index);
const char *cp_name(int codepage);
-void get_unitab(int codepage, wchar_t * unitab, int ftype);
+void get_unitab(int codepage, wchar_t *unitab, int ftype);
/*
* Exports from wcwidth.c
@@ -2052,7 +2501,7 @@ int mk_wcwidth_cjk(unsigned int ucs);
int mk_wcswidth_cjk(const unsigned int *pwcs, size_t n);
/*
- * Exports from pageantc.c.
+ * Exports from agent-client.c in platform subdirs.
*
* agent_query returns NULL for here's-a-response, and non-NULL for
* query-in- progress. In the latter case there will be a call to
@@ -2071,8 +2520,8 @@ int mk_wcswidth_cjk(const unsigned int *pwcs, size_t n);
*
* Passing a null pointer as callback forces agent_query to behave
* synchronously, i.e. it will block if necessary, and guarantee to
- * return NULL. The wrapper function agent_query_synchronous() makes
- * this easier.
+ * return NULL. The wrapper function agent_query_synchronous()
+ * (defined in its own module aqsync.c) makes this easier.
*/
typedef struct agent_pending_query agent_pending_query;
agent_pending_query *agent_query(
@@ -2094,7 +2543,7 @@ int wc_match(const char *wildcard, const char *target);
bool wc_unescape(char *output, const char *wildcard);
/*
- * Exports from frontend (windlg.c etc)
+ * Exports from frontend (dialog.c etc)
*/
void pgp_fingerprints(void);
/*
@@ -2104,11 +2553,11 @@ void pgp_fingerprints(void);
bool have_ssh_host_key(const char *host, int port, const char *keytype);
/*
- * Exports from console frontends (wincons.c, uxcons.c)
+ * Exports from console frontends (console.c in platform subdirs)
* that aren't equivalents to things in windlg.c et al.
*/
extern bool console_batch_mode, console_antispoof_prompt;
-int console_get_userpass_input(prompts_t *p);
+SeatPromptResult console_get_userpass_input(prompts_t *p);
bool is_interactive(void);
void console_print_error_msg(const char *prefix, const char *msg);
void console_print_error_msg_fmt_v(
@@ -2117,7 +2566,7 @@ void console_print_error_msg_fmt(const char *prefix, const char *fmt, ...)
PRINTF_LIKE(2, 3);
/*
- * Exports from printing.c.
+ * Exports from printing.c in platform subdirs.
*/
typedef struct printer_enum_tag printer_enum;
typedef struct printer_job_tag printer_job;
@@ -2138,10 +2587,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);
-int 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);
@@ -2180,31 +2634,80 @@ void cmdline_error(const char *, ...) PRINTF_LIKE(1, 2);
* Exports from config.c.
*/
struct controlbox;
-union control;
-void conf_radiobutton_handler(union control *ctrl, dlgparam *dlg,
+void conf_radiobutton_handler(dlgcontrol *ctrl, dlgparam *dlg,
void *data, int event);
#define CHECKBOX_INVERT (1<<30)
-void conf_checkbox_handler(union control *ctrl, dlgparam *dlg,
+void conf_checkbox_handler(dlgcontrol *ctrl, dlgparam *dlg,
void *data, int event);
-void conf_editbox_handler(union control *ctrl, dlgparam *dlg,
+void conf_editbox_handler(dlgcontrol *ctrl, dlgparam *dlg,
void *data, int event);
-void conf_filesel_handler(union control *ctrl, dlgparam *dlg,
+void conf_filesel_handler(dlgcontrol *ctrl, dlgparam *dlg,
void *data, int event);
-void conf_fontsel_handler(union control *ctrl, dlgparam *dlg,
+void conf_fontsel_handler(dlgcontrol *ctrl, dlgparam *dlg,
void *data, int event);
+struct conf_editbox_handler_type {
+ /* Structure passed as context2 to conf_editbox_handler */
+ enum { EDIT_STR, EDIT_INT, EDIT_FIXEDPOINT } type;
+ union {
+ /*
+ * EDIT_STR means the edit box is connected to a string
+ * field in Conf. No further parameters needed.
+ */
+
+ /*
+ * EDIT_INT means the edit box is connected to an int field in
+ * Conf, and the input string is interpreted as decimal. No
+ * further parameters needed. (But we could add one here later
+ * if for some reason we wanted int fields in hex.)
+ */
+
+ /*
+ * EDIT_FIXEDPOINT means the edit box is connected to an int
+ * field in Conf, but the input string is interpreted as
+ * _floating point_, and converted to/from the output int by
+ * means of a fixed denominator. That is,
+ *
+ * (floating value in edit box) * denominator = value in Conf
+ */
+ struct {
+ double denominator;
+ };
+ };
+};
+
+extern const struct conf_editbox_handler_type conf_editbox_str;
+extern const struct conf_editbox_handler_type conf_editbox_int;
+#define ED_STR CP(&conf_editbox_str)
+#define ED_INT CP(&conf_editbox_int)
+
void setup_config_box(struct controlbox *b, bool midsession,
int protocol, int protcfginfo);
+void setup_ca_config_box(struct controlbox *b);
+
+/* Platforms provide this to be called from config.c */
+void show_ca_config_box(dlgparam *dlg);
+extern const bool has_ca_config_box; /* false if, e.g., we're PuTTYtel */
+
+/* Visible outside config.c so that platforms can use it to recognise
+ * the proxy type control */
+void proxy_type_handler(dlgcontrol *ctrl, dlgparam *dlg,
+ void *data, int event);
+/* And then they'll set this flag in its generic.context.i */
+#define PROXY_UI_FLAG_LOCAL 1 /* has a local proxy */
+
/*
- * Exports from minibidi.c.
+ * Exports from bidi.c.
*/
#define BIDI_CHAR_INDEX_NONE ((unsigned short)-1)
typedef struct bidi_char {
unsigned int origwc, wc;
unsigned short index, nchars;
} bidi_char;
-int do_bidi(bidi_char *line, int count);
+BidiContext *bidi_new_context(void);
+void bidi_free_context(BidiContext *ctx);
+void do_bidi(BidiContext *ctx, bidi_char *line, size_t count);
int do_shape(bidi_char *line, bidi_char *to, int count);
bool is_rtl(int c);
@@ -2217,7 +2720,7 @@ enum {
X11_XDM, /* XDM-AUTHORIZATION-1 */
X11_NAUTHS
};
-extern const char *const x11_authnames[]; /* declared in x11fwd.c */
+extern const char *const x11_authnames[X11_NAUTHS];
/*
* An enum for the copy-paste UI action configuration.
@@ -2371,7 +2874,6 @@ unsigned long timing_last_clock(void);
* loop, as in PSFTP, for example - if a callback has run then perhaps
* it might have done whatever the loop's caller was waiting for.
*/
-typedef void (*toplevel_callback_fn_t)(void *ctx);
void queue_toplevel_callback(toplevel_callback_fn_t fn, void *ctx);
bool run_toplevel_callbacks(void);
bool toplevel_callback_pending(void);
@@ -2398,6 +2900,16 @@ void request_callback_notifications(toplevel_callback_notify_fn_t notify,
void *ctx);
/*
+ * Facility provided by the platform to spawn a parallel subprocess
+ * and present its stdio via a Socket.
+ *
+ * 'prefix' indicates the prefix that should appear on messages passed
+ * to plug_log to provide stderr output from the process.
+ */
+Socket *platform_start_subprocess(const char *cmd, Plug *plug,
+ const char *prefix);
+
+/*
* Define no-op macros for the jump list functions, on platforms that
* don't support them. (This is a bit of a hack, and it'd be nicer to
* localise even the calls to those functions into the Windows front