This repository has been archived by the owner on Oct 20, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 129
/
putty.h
2284 lines (2097 loc) · 88.4 KB
/
putty.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#ifndef PUTTY_PUTTY_H
#define PUTTY_PUTTY_H
#include <stddef.h> /* for wchar_t */
#include <limits.h> /* for INT_MAX */
#include "defs.h"
#include "puttyps.h"
#include "network.h"
#include "misc.h"
#include "marshal.h"
/*
* We express various time intervals in unsigned long minutes, but may need to
* clip some values so that the resulting number of ticks does not overflow an
* integer value.
*/
#define MAX_TICK_MINS (INT_MAX / (60 * TICKSPERSEC))
/*
* 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_PREV_MASTER_KEY_DETAILS "RSA, 4096-bit"
#define PGP_PREV_MASTER_KEY_FP \
"440D E3B5 B7A1 CA85 B3CC 1718 AB58 5DC6 0467 6F7C"
/* Three attribute types:
* The ATTRs (normal attributes) are stored with the characters in
* the main display arrays
*
* The TATTRs (temporary attributes) are generated on the fly, they
* can overlap with characters but not with normal attributes.
*
* The LATTRs (line attributes) are an entirely disjoint space of
* flags.
*
* The DATTRs (display attributes) are internal to terminal.c (but
* defined here because their values have to match the others
* here); they reuse the TATTR_* space but are always masked off
* before sending to the front end.
*
* ATTR_INVALID is an illegal colour combination.
*/
#define TATTR_ACTCURS 0x40000000UL /* active cursor (block) */
#define TATTR_PASCURS 0x20000000UL /* passive cursor (box) */
#define TATTR_RIGHTCURS 0x10000000UL /* cursor-on-RHS */
#define TATTR_COMBINING 0x80000000UL /* combining characters */
#define DATTR_STARTRUN 0x80000000UL /* start of redraw run */
#define TDATTR_MASK 0xF0000000UL
#define TATTR_MASK (TDATTR_MASK)
#define DATTR_MASK (TDATTR_MASK)
#define LATTR_NORM 0x00000000UL
#define LATTR_WIDE 0x00000001UL
#define LATTR_TOP 0x00000002UL
#define LATTR_BOT 0x00000003UL
#define LATTR_MODE 0x00000003UL
#define LATTR_WRAPPED 0x00000010UL /* this line wraps to next */
#define LATTR_WRAPPED2 0x00000020UL /* with WRAPPED: CJK wide character
wrapped to next line, so last
single-width cell is empty */
#define ATTR_INVALID 0x03FFFFU
/* Like Linux use the F000 page for direct to font. */
#define CSET_OEMCP 0x0000F000UL /* OEM Codepage DTF */
#define CSET_ACP 0x0000F100UL /* Ansi Codepage DTF */
/* These are internal use overlapping with the UTF-16 surrogates */
#define CSET_ASCII 0x0000D800UL /* normal ASCII charset ESC ( B */
#define CSET_LINEDRW 0x0000D900UL /* line drawing charset ESC ( 0 */
#define CSET_SCOACS 0x0000DA00UL /* SCO Alternate charset */
#define CSET_GBCHR 0x0000DB00UL /* UK variant charset ESC ( A */
#define CSET_MASK 0xFFFFFF00UL /* Character set mask */
#define DIRECT_CHAR(c) ((c&0xFFFFFC00)==0xD800)
#define DIRECT_FONT(c) ((c&0xFFFFFE00)==0xF000)
#define UCSERR (CSET_LINEDRW|'a') /* UCS Format error character. */
/*
* UCSWIDE is a special value used in the terminal data to signify
* the character cell containing the right-hand half of a CJK wide
* character. We use 0xDFFF because it's part of the surrogate
* range and hence won't be used for anything else (it's impossible
* to input it via UTF-8 because our UTF-8 decoder correctly
* rejects surrogates).
*/
#define UCSWIDE 0xDFFF
#define ATTR_NARROW 0x0800000U
#define ATTR_WIDE 0x0400000U
#define ATTR_BOLD 0x0040000U
#define ATTR_UNDER 0x0080000U
#define ATTR_REVERSE 0x0100000U
#define ATTR_BLINK 0x0200000U
#define ATTR_FGMASK 0x00001FFU
#define ATTR_BGMASK 0x003FE00U
#define ATTR_COLOURS 0x003FFFFU
#define ATTR_DIM 0x1000000U
#define ATTR_STRIKE 0x2000000U
#define ATTR_FGSHIFT 0
#define ATTR_BGSHIFT 9
/*
* The definitive list of colour numbers stored in terminal
* attribute words is kept here. It is:
*
* - 0-7 are ANSI colours (KRGYBMCW).
* - 8-15 are the bold versions of those colours.
* - 16-255 are the remains of the xterm 256-colour mode (a
* 216-colour cube with R at most significant and B at least,
* followed by a uniform series of grey shades running between
* black and white but not including either on grounds of
* redundancy).
* - 256 is default foreground
* - 257 is default bold foreground
* - 258 is default background
* - 259 is default bold background
* - 260 is cursor foreground
* - 261 is cursor background
*/
#define ATTR_DEFFG (256 << ATTR_FGSHIFT)
#define ATTR_DEFBG (258 << ATTR_BGSHIFT)
#define ATTR_DEFAULT (ATTR_DEFFG | ATTR_DEFBG)
struct sesslist {
int nsessions;
const char **sessions;
char *buffer; /* so memory can be freed later */
};
struct unicode_data {
char **uni_tbl;
bool dbcs_screenfont;
int font_codepage;
int line_codepage;
wchar_t unitab_scoacs[256];
wchar_t unitab_line[256];
wchar_t unitab_font[256];
wchar_t unitab_xterm[256];
wchar_t unitab_oemcp[256];
unsigned char unitab_ctrl[256];
};
#define LGXF_OVR 1 /* existing logfile overwrite */
#define LGXF_APN 0 /* existing logfile append */
#define LGXF_ASK -1 /* existing logfile ask */
#define LGTYP_NONE 0 /* logmode: no logging */
#define LGTYP_ASCII 1 /* logmode: pure ascii */
#define LGTYP_DEBUG 2 /* logmode: all chars of traffic */
#define LGTYP_PACKETS 3 /* logmode: SSH data packets */
#define LGTYP_SSHRAW 4 /* logmode: SSH raw data */
/*
* Enumeration of 'special commands' that can be sent during a
* session, separately from the byte stream of ordinary session data.
*/
typedef enum {
/*
* Commands that are generally useful in multiple backends.
*/
SS_BRK, /* serial-line break */
SS_EOF, /* end-of-file on session input */
SS_NOP, /* transmit data with no effect */
SS_PING, /* try to keep the session alive (probably, but not
* necessarily, implemented as SS_NOP) */
/*
* Commands specific to Telnet.
*/
SS_AYT, /* Are You There */
SS_SYNCH, /* Synch */
SS_EC, /* Erase Character */
SS_EL, /* Erase Line */
SS_GA, /* Go Ahead */
SS_ABORT, /* Abort Process */
SS_AO, /* Abort Output */
SS_IP, /* Interrupt Process */
SS_SUSP, /* Suspend Process */
SS_EOR, /* End Of Record */
SS_EOL, /* Telnet end-of-line sequence (CRLF, as opposed to CR
* NUL that escapes a literal CR) */
/*
* Commands specific to SSH.
*/
SS_REKEY, /* trigger an immediate repeat key exchange */
SS_XCERT, /* cross-certify another host key ('arg' indicates which) */
/*
* Send a POSIX-style signal. (Useful in SSH and also pterm.)
*
* We use the master list in sshsignals.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"
#undef SIGNAL_MAIN
#undef SIGNAL_SUB
/*
* These aren't really special commands, but they appear in the
* enumeration because the list returned from
* backend_get_specials() will use them to specify the structure
* of the GUI specials menu.
*/
SS_SEP, /* Separator */
SS_SUBMENU, /* Start a new submenu with specified name */
SS_EXITMENU, /* Exit current submenu, or end of entire specials list */
} SessionSpecialCode;
/*
* The structure type returned from backend_get_specials.
*/
struct SessionSpecial {
const char *name;
SessionSpecialCode code;
int arg;
};
/* Needed by both sshchan.h and sshppl.h */
typedef void (*add_special_fn_t)(
void *ctx, const char *text, SessionSpecialCode code, int arg);
typedef enum {
MBT_NOTHING,
MBT_LEFT, MBT_MIDDLE, MBT_RIGHT, /* `raw' button designations */
MBT_SELECT, MBT_EXTEND, MBT_PASTE, /* `cooked' button designations */
MBT_WHEEL_UP, MBT_WHEEL_DOWN /* mouse wheel */
} Mouse_Button;
typedef enum {
MA_NOTHING, MA_CLICK, MA_2CLK, MA_3CLK, MA_DRAG, MA_RELEASE
} Mouse_Action;
/* Keyboard modifiers -- keys the user is actually holding down */
#define PKM_SHIFT 0x01
#define PKM_CONTROL 0x02
#define PKM_META 0x04
#define PKM_ALT 0x08
/* Keyboard flags that aren't really modifiers */
#define PKF_CAPSLOCK 0x10
#define PKF_NUMLOCK 0x20
#define PKF_REPEAT 0x40
/* Stand-alone keysyms for function keys */
typedef enum {
PK_NULL, /* No symbol for this key */
/* Main keypad keys */
PK_ESCAPE, PK_TAB, PK_BACKSPACE, PK_RETURN, PK_COMPOSE,
/* Editing keys */
PK_HOME, PK_INSERT, PK_DELETE, PK_END, PK_PAGEUP, PK_PAGEDOWN,
/* Cursor keys */
PK_UP, PK_DOWN, PK_RIGHT, PK_LEFT, PK_REST,
/* Numeric keypad */ /* Real one looks like: */
PK_PF1, PK_PF2, PK_PF3, PK_PF4, /* PF1 PF2 PF3 PF4 */
PK_KPCOMMA, PK_KPMINUS, PK_KPDECIMAL, /* 7 8 9 - */
PK_KP0, PK_KP1, PK_KP2, PK_KP3, PK_KP4, /* 4 5 6 , */
PK_KP5, PK_KP6, PK_KP7, PK_KP8, PK_KP9, /* 1 2 3 en- */
PK_KPBIGPLUS, PK_KPENTER, /* 0 . ter */
/* Top row */
PK_F1, PK_F2, PK_F3, PK_F4, PK_F5,
PK_F6, PK_F7, PK_F8, PK_F9, PK_F10,
PK_F11, PK_F12, PK_F13, PK_F14, PK_F15,
PK_F16, PK_F17, PK_F18, PK_F19, PK_F20,
PK_PAUSE
} Key_Sym;
#define PK_ISEDITING(k) ((k) >= PK_HOME && (k) <= PK_PAGEDOWN)
#define PK_ISCURSOR(k) ((k) >= PK_UP && (k) <= PK_REST)
#define PK_ISKEYPAD(k) ((k) >= PK_PF1 && (k) <= PK_KPENTER)
#define PK_ISFKEY(k) ((k) >= PK_F1 && (k) <= PK_F20)
enum {
VT_XWINDOWS, VT_OEMANSI, VT_OEMONLY, VT_POORMAN, VT_UNICODE
};
enum {
/*
* SSH-2 key exchange algorithms
*/
KEX_WARN,
KEX_DHGROUP1,
KEX_DHGROUP14,
KEX_DHGEX,
KEX_RSA,
KEX_ECDH,
KEX_MAX
};
enum {
/*
* SSH-2 host key algorithms
*/
HK_WARN,
HK_RSA,
HK_DSA,
HK_ECDSA,
HK_ED25519,
HK_ED448,
HK_MAX
};
enum {
/*
* SSH ciphers (both SSH-1 and SSH-2)
*/
CIPHER_WARN, /* pseudo 'cipher' */
CIPHER_3DES,
CIPHER_BLOWFISH,
CIPHER_AES, /* (SSH-2 only) */
CIPHER_DES,
CIPHER_ARCFOUR,
CIPHER_CHACHA20,
CIPHER_MAX /* no. ciphers (inc warn) */
};
enum TriState {
/*
* Several different bits of the PuTTY configuration seem to be
* three-way settings whose values are `always yes', `always
* no', and `decide by some more complex automated means'. This
* is true of line discipline options (local echo and line
* editing), proxy DNS, proxy terminal logging, Close On Exit, and
* SSH server bug workarounds. Accordingly I supply a single enum
* here to deal with them all.
*/
FORCE_ON, FORCE_OFF, AUTO
};
enum {
/*
* Proxy types.
*/
PROXY_NONE, PROXY_SOCKS4, PROXY_SOCKS5,
PROXY_HTTP, PROXY_TELNET, PROXY_CMD, PROXY_FUZZ
};
enum {
/*
* Line discipline options which the backend might try to control.
*/
LD_EDIT, /* local line editing */
LD_ECHO, /* local echo */
LD_N_OPTIONS
};
enum {
/* Actions on remote window title query */
TITLE_NONE, TITLE_EMPTY, TITLE_REAL
};
enum {
/* SUPDUP character set options */
SUPDUP_CHARSET_ASCII, SUPDUP_CHARSET_ITS, SUPDUP_CHARSET_WAITS
};
enum {
/* Protocol back ends. (CONF_protocol) */
PROT_RAW, PROT_TELNET, PROT_RLOGIN, PROT_SSH, PROT_SSHCONN,
/* PROT_SERIAL is supported on a subset of platforms, but it doesn't
* hurt to define it globally. */
PROT_SERIAL,
/* PROT_SUPDUP is the historical RFC 734 protocol. */
PROT_SUPDUP,
PROTOCOL_LIMIT, /* upper bound on number of protocols */
};
enum {
/* Bell settings (CONF_beep) */
BELL_DISABLED, BELL_DEFAULT, BELL_VISUAL, BELL_WAVEFILE, BELL_PCSPEAKER
};
enum {
/* Taskbar flashing indication on bell (CONF_beep_ind) */
B_IND_DISABLED, B_IND_FLASH, B_IND_STEADY
};
enum {
/* Resize actions (CONF_resize_action) */
RESIZE_TERM, RESIZE_DISABLED, RESIZE_FONT, RESIZE_EITHER
};
enum {
/* Function key types (CONF_funky_type) */
FUNKY_TILDE,
FUNKY_LINUX,
FUNKY_XTERM,
FUNKY_VT400,
FUNKY_VT100P,
FUNKY_SCO
};
enum {
FQ_DEFAULT, FQ_ANTIALIASED, FQ_NONANTIALIASED, FQ_CLEARTYPE
};
enum {
SER_PAR_NONE, SER_PAR_ODD, SER_PAR_EVEN, SER_PAR_MARK, SER_PAR_SPACE
};
enum {
SER_FLOW_NONE, SER_FLOW_XONXOFF, SER_FLOW_RTSCTS, SER_FLOW_DSRDTR
};
/*
* Tables of string <-> enum value mappings used in settings.c.
* Defined here so that backends can export their GSS library tables
* to the cross-platform settings code.
*/
struct keyvalwhere {
/*
* Two fields which define a string and enum value to be
* equivalent to each other.
*/
const char *s;
int v;
/*
* The next pair of fields are used by gprefs() in settings.c to
* arrange that when it reads a list of strings representing a
* preference list and translates it into the corresponding list
* of integers, strings not appearing in the list are entered in a
* configurable position rather than uniformly at the end.
*/
/*
* 'vrel' indicates which other value in the list to place this
* element relative to. It should be a value that has occurred in
* a 'v' field of some other element of the array, or -1 to
* indicate that we simply place relative to one or other end of
* the list.
*
* gprefs will try to process the elements in an order which makes
* this field work (i.e. so that the element referenced has been
* added before processing this one).
*/
int vrel;
/*
* 'where' indicates whether to place the new value before or
* after the one referred to by vrel. -1 means before; +1 means
* after.
*
* When vrel is -1, this also implicitly indicates which end of
* the array to use. So vrel=-1, where=-1 means to place _before_
* some end of the list (hence, at the last element); vrel=-1,
* where=+1 means to place _after_ an end (hence, at the first).
*/
int where;
};
#ifndef NO_GSSAPI
extern const int ngsslibs;
extern const char *const gsslibnames[]; /* for displaying in configuration */
extern const struct keyvalwhere gsslibkeywords[]; /* for settings.c */
#endif
extern const char *const ttymodes[];
enum {
/*
* Network address types. Used for specifying choice of IPv4/v6
* in config; also used in proxy.c to indicate whether a given
* host name has already been resolved or will be resolved at
* the proxy end.
*/
ADDRTYPE_UNSPEC,
ADDRTYPE_IPV4,
ADDRTYPE_IPV6,
ADDRTYPE_LOCAL, /* e.g. Unix domain socket, or Windows named pipe */
ADDRTYPE_NAME /* SockAddr storing an unresolved host name */
};
/* Backend flags */
#define BACKEND_RESIZE_FORBIDDEN 0x01 /* Backend does not allow
resizing terminal */
#define BACKEND_NEEDS_TERMINAL 0x02 /* Backend must have terminal */
struct Backend {
const BackendVtable *vt;
};
struct BackendVtable {
char *(*init) (const BackendVtable *vt, Seat *seat,
Backend **backend_out, LogContext *logctx, Conf *conf,
const char *host, int port, char **realhost,
bool nodelay, bool keepalive);
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 */
size_t (*sendbuffer) (Backend *be);
void (*size) (Backend *be, int width, int height);
void (*special) (Backend *be, SessionSpecialCode code, int arg);
const SessionSpecial *(*get_specials) (Backend *be);
bool (*connected) (Backend *be);
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). */
bool (*sendok) (Backend *be);
bool (*ldisc_option_state) (Backend *be, int);
void (*provide_ldisc) (Backend *be, Ldisc *ldisc);
/* Tells the back end that the front end buffer is clearing. */
void (*unthrottle) (Backend *be, size_t bufsize);
int (*cfg_info) (Backend *be);
/* Only implemented in the SSH protocol: check whether a
* connection-sharing upstream exists for a given configuration. */
bool (*test_for_upstream)(const char *host, int port, Conf *conf);
/* '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;
int protocol;
int default_port;
unsigned flags;
/* Only relevant for the serial protocol: bit masks of which
* parity and flow control settings are supported. */
unsigned serial_parity_mask, serial_flow_mask;
};
static inline char *backend_init(
const BackendVtable *vt, Seat *seat, Backend **out, LogContext *logctx,
Conf *conf, const char *host, int port, char **rhost, bool nd, bool ka)
{ return vt->init(vt, seat, out, logctx, conf, host, port, rhost, nd, ka); }
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 size_t backend_sendbuffer(Backend *be)
{ return be->vt->sendbuffer(be); }
static inline void backend_size(Backend *be, int width, int height)
{ be->vt->size(be, width, height); }
static inline void backend_special(
Backend *be, SessionSpecialCode code, int arg)
{ be->vt->special(be, code, arg); }
static inline const SessionSpecial *backend_get_specials(Backend *be)
{ return be->vt->get_specials(be); }
static inline bool backend_connected(Backend *be)
{ return be->vt->connected(be); }
static inline int backend_exitcode(Backend *be)
{ return be->vt->exitcode(be); }
static inline bool backend_sendok(Backend *be)
{ return be->vt->sendok(be); }
static inline bool backend_ldisc_option_state(Backend *be, int state)
{ return be->vt->ldisc_option_state(be, state); }
static inline void backend_provide_ldisc(Backend *be, Ldisc *ldisc)
{ be->vt->provide_ldisc(be, ldisc); }
static inline void backend_unthrottle(Backend *be, size_t bufsize)
{ be->vt->unthrottle(be, bufsize); }
static inline int backend_cfg_info(Backend *be)
{ return be->vt->cfg_info(be); }
extern const struct BackendVtable *const backends[];
/*
* Suggested default protocol provided by the backend link module.
* The application is free to ignore this.
*/
extern const int be_default_protocol;
/*
* Name of this particular application, for use in the config box
* and other pieces of text.
*/
extern const char *const appname;
/*
* 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.
* FIXME We should probably mandate a character set/encoding (probably UTF-8).
*
* Since many of the pieces of text involved may be chosen by the server,
* the caller must take care to ensure that the server can't spoof locally-
* generated prompts such as key passphrase prompts. Some ground rules:
* - If the front-end needs to truncate a string, it should lop off the
* end.
* - The front-end should filter out any dangerous characters and
* generally not trust the strings. (But \n is required to behave
* vaguely sensibly, at least in `instruction', and ideally in
* `prompt[]' too.)
*/
typedef struct {
char *prompt;
bool echo;
strbuf *result;
} prompt_t;
typedef struct {
/*
* Indicates whether the information entered is to be used locally
* (for instance a key passphrase prompt), or is destined for the wire.
* This is a hint only; the front-end is at liberty not to use this
* information (so the caller should ensure that the supplied text is
* sufficient).
*/
bool to_server;
/*
* Indicates whether the prompts originated _at_ the server, so
* that the front end can display some kind of trust sigil that
* distinguishes (say) a legit private-key passphrase prompt from
* a fake one sent by a malicious server.
*/
bool from_server;
char *name; /* Short description, perhaps for dialog box title */
bool name_reqd; /* Display of `name' required or optional? */
char *instruction; /* Long description, maybe with embedded newlines */
bool instr_reqd; /* Display of `instruction' required or optional? */
size_t n_prompts; /* May be zero (in which case display the foregoing,
* if any, and return success) */
size_t prompts_size; /* allocated storage capacity for prompts[] */
prompt_t **prompts;
void *data; /* slot for housekeeping data, managed by
* seat_get_userpass_input(); initially NULL */
} prompts_t;
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);
char *prompt_get_result(prompt_t *pr);
const char *prompt_get_result_ref(prompt_t *pr);
void free_prompts(prompts_t *p);
/*
* Data type definitions for true-colour terminal display.
* 'optionalrgb' describes a single RGB colour, which overrides the
* other colour settings if 'enabled' is nonzero, and is ignored
* otherwise. 'truecolour' contains a pair of those for foreground and
* background.
*/
typedef struct optionalrgb {
bool enabled;
unsigned char r, g, b;
} optionalrgb;
extern const optionalrgb optionalrgb_none;
typedef struct truecolour {
optionalrgb fg, bg;
} truecolour;
#define optionalrgb_equal(r1,r2) ( \
(r1).enabled==(r2).enabled && \
(r1).r==(r2).r && (r1).g==(r2).g && (r1).b==(r2).b)
#define truecolour_equal(c1,c2) ( \
optionalrgb_equal((c1).fg, (c2).fg) && \
optionalrgb_equal((c1).bg, (c2).bg))
/*
* Enumeration of clipboards. We provide some standard ones cross-
* platform, and then permit each platform to extend this enumeration
* further by defining PLATFORM_CLIPBOARDS in its own header file.
*
* CLIP_NULL is a non-clipboard, writes to which are ignored and reads
* from which return no data.
*
* CLIP_LOCAL refers to a buffer within terminal.c, which
* unconditionally saves the last data selected in the terminal. In
* configurations where a system clipboard is not written
* automatically on selection but instead by an explicit UI action,
* this is where the code responding to that action can find the data
* to write to the clipboard in question.
*/
#define CROSS_PLATFORM_CLIPBOARDS(X) \
X(CLIP_NULL, "null clipboard") \
X(CLIP_LOCAL, "last text selected in terminal") \
/* end of list */
#define ALL_CLIPBOARDS(X) \
CROSS_PLATFORM_CLIPBOARDS(X) \
PLATFORM_CLIPBOARDS(X) \
/* end of list */
#define CLIP_ID(id,name) id,
enum { ALL_CLIPBOARDS(CLIP_ID) N_CLIPBOARDS };
#undef CLIP_ID
/* Hint from backend to frontend about time-consuming operations, used
* by seat_set_busy_status. Initial state is assumed to be
* BUSY_NOT. */
typedef enum BusyStatus {
BUSY_NOT, /* Not busy, all user interaction OK */
BUSY_WAITING, /* Waiting for something; local event loops still
running so some local interaction (e.g. menus)
OK, but network stuff is suspended */
BUSY_CPU /* Locally busy (e.g. crypto); user interaction
* suspended */
} BusyStatus;
typedef enum SeatInteractionContext {
SIC_BANNER, SIC_KI_PROMPTS
} SeatInteractionContext;
/*
* Data type 'Seat', which is an API intended to contain essentially
* everything that a back end might need to talk to its client for:
* session output, password prompts, SSH warnings about host keys and
* weak cryptography, notifications of events like the remote process
* exiting or the GUI specials menu needing an update.
*/
struct Seat {
const struct SeatVtable *vt;
};
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.
*
* 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);
/*
* Called when the back end wants to indicate that EOF has arrived
* on the server-to-client stream. Returns false to indicate that
* we intend to keep the session open in the other direction, or
* true to indicate that if they're closing so are we.
*/
bool (*eof)(Seat *seat);
/*
* 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.
*
* (FIXME: it would be nice to distinguish two classes of cancel
* 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.)
*
* (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.)
*/
int (*get_userpass_input)(Seat *seat, prompts_t *p, bufchain *input);
/*
* Notify the seat that the process running at the other end of
* the connection has finished.
*/
void (*notify_remote_exit)(Seat *seat);
/*
* Notify the seat that the connection has suffered a fatal error.
*/
void (*connection_fatal)(Seat *seat, const char *message);
/*
* Notify the seat that the list of special commands available
* from backend_get_specials() has changed, so that it might want
* to call that function to repopulate its menu.
*
* Seats are not expected to call backend_get_specials()
* proactively; they may start by assuming that the backend
* provides no special commands at all, so if the backend does
* provide any, then it should use this notification at startup
* time. Of course it can also invoke it later if the set of
* special commands changes.
*
* It does not need to invoke it at session shutdown.
*/
void (*update_specials_menu)(Seat *seat);
/*
* Get the seat's preferred value for an SSH terminal mode
* setting. Returning NULL indicates no preference (i.e. the SSH
* connection will not attempt to set the mode at all).
*
* The returned value is dynamically allocated, and the caller
* should free it.
*/
char *(*get_ttymode)(Seat *seat, const char *mode);
/*
* Tell the seat whether the backend is currently doing anything
* CPU-intensive (typically a cryptographic key exchange). See
* BusyStatus enumeration above.
*/
void (*set_busy_status)(Seat *seat, BusyStatus status);
/*
* 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.
*
* Return values:
*
* - +1 means `key was OK' (either already known or the user just
* approved it) `so continue with the connection'
*
* - 0 means `key was not OK, 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)(
Seat *seat, const char *host, int port,
const char *keytype, char *keystr, char *key_fingerprint,
void (*callback)(void *ctx, int 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.
*/
int (*confirm_weak_crypto_primitive)(
Seat *seat, const char *algtype, const char *algname,
void (*callback)(void *ctx, int result), void *ctx);
/*
* Variant form of confirm_weak_crypto_primitive, which prints a
* slightly different message but otherwise has the same
* semantics.
*
* This form is used in the case where we're using a host key
* below the warning threshold because that's the best one we have
* cached, but at least one host key algorithm *above* the
* threshold is available that we don't have cached. 'betteralgs'
* lists the better algorithm(s).
*/
int (*confirm_weak_cached_hostkey)(
Seat *seat, const char *algname, const char *betteralgs,
void (*callback)(void *ctx, int result), void *ctx);
/*
* Indicates whether the seat is expecting to interact with the
* user in the UTF-8 character set. (Affects e.g. visual erase
* handling in local line editing.)
*/
bool (*is_utf8)(Seat *seat);
/*
* Notify the seat that the back end, and/or the ldisc between
* them, have changed their idea of whether they currently want
* local echo and/or local line editing enabled.
*/
void (*echoedit_update)(Seat *seat, bool echoing, bool editing);
/*
* Return the local X display string relevant to a seat, or NULL
* if there isn't one or if the concept is meaningless.
*/
const char *(*get_x_display)(Seat *seat);
/*
* Return the X11 id of the X terminal window relevant to a seat,
* by returning true and filling in the output pointer. Return
* false if there isn't one or if the concept is meaningless.
*/
bool (*get_windowid)(Seat *seat, long *id_out);
/*
* Return the size of the terminal window in pixels. If the
* concept is meaningless or the information is unavailable,
* return false; otherwise fill in the output pointers and return
* true.
*/
bool (*get_window_pixel_size)(Seat *seat, int *width, int *height);
/*
* Return a StripCtrlChars appropriate for sanitising untrusted
* terminal data (e.g. SSH banners, prompts) being sent to the
* user of this seat. May return NULL if no sanitisation is
* needed.
*/
StripCtrlChars *(*stripctrl_new)(
Seat *seat, BinarySink *bs_out, SeatInteractionContext sic);
/*
* Set the seat's current idea of where output is coming from.
* True means that output is being generated by our own code base
* (and hence, can be trusted if it's asking you for secrets such
* as your passphrase); false means output is coming from the
* server.
*
* 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);
/*
* Ask the seat whether it would like verbose messages.
*/
bool (*verbose)(Seat *seat);
/*
* Ask the seat whether it's an interactive program.
*/
bool (*interactive)(Seat *seat);
/*
* Return the seat's current idea of where the output cursor is.
*
* Returns true if the seat has a cursor. Returns false if not.
*/
bool (*get_cursor_position)(Seat *seat, int *x, int *y);
};
static inline size_t seat_output(
Seat *seat, bool err, const void *data, size_t len)
{ return seat->vt->output(seat, err, 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_notify_remote_exit(Seat *seat)
{ seat->vt->notify_remote_exit(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,
char *fp, void (*cb)(void *ctx, int result), void *ctx)
{ return seat->vt->verify_ssh_host_key(seat, h, p, ktyp, kstr, fp, 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 bool seat_is_utf8(Seat *seat)
{ return seat->vt->is_utf8(seat); }
static inline void seat_echoedit_update(Seat *seat, bool ec, bool ed)
{ seat->vt->echoedit_update(seat, ec, ed); }
static inline const char *seat_get_x_display(Seat *seat)
{ return seat->vt->get_x_display(seat); }
static inline bool seat_get_windowid(Seat *seat, long *id_out)
{ return seat->vt->get_windowid(seat, id_out); }
static inline bool seat_get_window_pixel_size(Seat *seat, int *w, int *h)
{ return seat->vt->get_window_pixel_size(seat, w, 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 bool seat_verbose(Seat *seat)
{ return seat->vt->verbose(seat); }
static inline bool seat_interactive(Seat *seat)
{ return seat->vt->interactive(seat); }
static inline bool seat_get_cursor_position(Seat *seat, int *x, int *y)
{ return seat->vt->get_cursor_position(seat, x, 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. */