-
Notifications
You must be signed in to change notification settings - Fork 11
/
putty.h
2798 lines (2532 loc) · 108 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 "platform.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 "2023"
#define PGP_MASTER_KEY_DETAILS "RSA, 4096-bit"
#define PGP_MASTER_KEY_FP \
"28D4 7C46 55E7 65A6 D827 AC66 B15D 9EFC 216B 06A1"
#define PGP_PREV_MASTER_KEY_YEAR "2021"
#define PGP_PREV_MASTER_KEY_DETAILS "RSA, 3072-bit"
#define PGP_PREV_MASTER_KEY_FP \
"A872 D42F 1660 890F 0E05 223E DD43 55EA AC11 19DE"
/*
* Definitions of three separate indexing schemes for colour palette
* entries.
*
* Why three? Because history, sorry.
*
* Two of the colour indexings are used in escape sequences. The
* Linux-console style OSC P sequences for setting the palette use an
* indexing in which the eight standard ANSI SGR colours come first,
* then their bold versions, and then six extra colours for default
* fg/bg and the terminal cursor. And the xterm OSC 4 sequences for
* querying the palette use a related indexing in which the six extra
* colours are pushed up to indices 256 and onwards, with the previous
* 16 being the first part of the xterm 256-colour space, and 240
* additional terminal-accessible colours inserted in the middle.
*
* The third indexing is the order that the colours appear in the
* PuTTY configuration panel, and also the order in which they're
* described in the saved session files. This order specifies the same
* set of colours as the OSC P encoding, but in a different order,
* with the default fg/bg colours (which users are most likely to want
* to reconfigure) at the start, and the ANSI SGR colours coming
* later.
*
* So all three indices really are needed, because all three appear in
* protocols or file formats outside the PuTTY binary. (Changing the
* saved-session encoding would have a backwards-compatibility impact;
* also, if we ever do, it would be better to replace the numeric
* indices with descriptive keywords.)
*
* Since the OSC 4 encoding contains the full set of colours used in
* the terminal display, that's the encoding used by front ends to
* store any actual data associated with their palette entries. So the
* TermWin palette_set and palette_get_overrides methods use that
* encoding, and so does the bitwise encoding of attribute words used
* in terminal redraw operations.
*
* The Conf encoding, of course, is used by config.c and settings.c.
*
* The aim is that those two sections of the code should never need to
* come directly into contact, and the only module that should have to
* deal directly with the mapping between these colour encodings - or
* to deal _at all_ with the intermediate OSC P encoding - is
* terminal.c itself.
*/
#define CONF_NCOLOURS 22 /* 16 + 6 special ones */
#define OSCP_NCOLOURS 22 /* same as CONF, but different order */
#define OSC4_NCOLOURS 262 /* 256 + the same 6 special ones */
/* The list macro for the conf colours also gives the textual names
* used in the GUI configurer */
#define CONF_COLOUR_LIST(X) \
X(fg, "Default Foreground") \
X(fg_bold, "Default Bold Foreground") \
X(bg, "Default Background") \
X(bg_bold, "Default Bold Background") \
X(cursor_fg, "Cursor Text") \
X(cursor_bg, "Cursor Colour") \
X(black, "ANSI Black") \
X(black_bold, "ANSI Black Bold") \
X(red, "ANSI Red") \
X(red_bold, "ANSI Red Bold") \
X(green, "ANSI Green") \
X(green_bold, "ANSI Green Bold") \
X(yellow, "ANSI Yellow") \
X(yellow_bold, "ANSI Yellow Bold") \
X(blue, "ANSI Blue") \
X(blue_bold, "ANSI Blue Bold") \
X(magenta, "ANSI Magenta") \
X(magenta_bold, "ANSI Magenta Bold") \
X(cyan, "ANSI Cyan") \
X(cyan_bold, "ANSI Cyan Bold") \
X(white, "ANSI White") \
X(white_bold, "ANSI White Bold") \
/* end of list */
#define OSCP_COLOUR_LIST(X) \
X(black) \
X(red) \
X(green) \
X(yellow) \
X(blue) \
X(magenta) \
X(cyan) \
X(white) \
X(black_bold) \
X(red_bold) \
X(green_bold) \
X(yellow_bold) \
X(blue_bold) \
X(magenta_bold) \
X(cyan_bold) \
X(white_bold) \
/*
* In the OSC 4 indexing, this is where the extra 240 colours go.
* They consist of:
*
* - 216 colours forming a 6x6x6 cube, with R the most
* significant colour and G the least. In other words, these
* occupy the space of indices 16 <= i < 232, with each
* individual colour found as i = 16 + 36*r + 6*g + b, for all
* 0 <= r,g,b <= 5.
*
* - The remaining indices, 232 <= i < 256, consist of a uniform
* series of grey shades running between black and white (but
* not including either, since actual black and white are
* already provided in the previous colour cube).
*
* After that, we have the remaining 6 special colours:
*/ \
X(fg) \
X(fg_bold) \
X(bg) \
X(bg_bold) \
X(cursor_fg) \
X(cursor_bg) \
/* end of list */
/* Enumerations of the colour lists. These are available everywhere in
* the code. The OSC P encoding shouldn't be used outside terminal.c,
* but the easiest way to define the OSC 4 enum is to have the OSC P
* one available to compute with. */
enum {
#define ENUM_DECL(id,name) CONF_COLOUR_##id,
CONF_COLOUR_LIST(ENUM_DECL)
#undef ENUM_DECL
};
enum {
#define ENUM_DECL(id) OSCP_COLOUR_##id,
OSCP_COLOUR_LIST(ENUM_DECL)
#undef ENUM_DECL
};
enum {
#define ENUM_DECL(id) OSC4_COLOUR_##id = \
OSCP_COLOUR_##id + (OSCP_COLOUR_##id >= 16 ? 240 : 0),
OSCP_COLOUR_LIST(ENUM_DECL)
#undef ENUM_DECL
};
/* Mapping tables defined in terminal.c */
extern const int colour_indices_conf_to_oscp[CONF_NCOLOURS];
extern const int colour_indices_conf_to_osc4[CONF_NCOLOURS];
extern const int colour_indices_oscp_to_osc4[OSCP_NCOLOURS];
/* 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
/* Use the DC00 page for direct to font. */
#define CSET_OEMCP 0x0000DC00UL /* OEM Codepage DTF */
#define CSET_ACP 0x0000DD00UL /* 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)==0xDC00)
#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 /* stores a colour in OSC 4 indexing */
#define ATTR_BGMASK 0x003FE00U /* stores a colour in OSC 4 indexing */
#define ATTR_COLOURS 0x003FFFFU
#define ATTR_DIM 0x1000000U
#define ATTR_STRIKE 0x2000000U
#define ATTR_FGSHIFT 0
#define ATTR_BGSHIFT 9
#define ATTR_DEFFG (OSC4_COLOUR_fg << ATTR_FGSHIFT)
#define ATTR_DEFBG (OSC4_COLOUR_bg << 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 {
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 */
/* Platform-generic function to set up a struct unicode_data. This is
* only likely to be useful to test programs; real clients will want
* to use the more flexible per-platform setup functions. */
void init_ucs_generic(Conf *conf, struct unicode_data *ucsdata);
/*
* Enumeration of 'special commands' that can be sent during a
* session, separately from the byte stream of ordinary session data.
*/
typedef enum {
/* The list of enum constants is defined in a separate header so
* they can be reused in other contexts */
#define SPECIAL(x) SS_ ## x,
#include "specials.h"
#undef SPECIAL
} SessionSpecialCode;
/*
* The structure type returned from backend_get_specials.
*/
struct SessionSpecial {
const char *name;
SessionSpecialCode code;
int arg;
};
/* 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);
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, /* vertical mouse wheel */
MBT_WHEEL_LEFT, MBT_WHEEL_RIGHT /* horizontal mouse wheel */
} Mouse_Button;
typedef enum {
MA_NOTHING, MA_CLICK, MA_2CLK, MA_3CLK, MA_DRAG, MA_RELEASE, MA_MOVE
} 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_DHGROUP15,
KEX_DHGROUP16,
KEX_DHGROUP17,
KEX_DHGROUP18,
KEX_DHGEX,
KEX_RSA,
KEX_ECDH,
KEX_NTRU_HYBRID,
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_AESGCM,
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_SSH_TCPIP,
PROXY_SSH_EXEC, PROXY_SSH_SUBSYSTEM,
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 {
/* Mouse-button assignments */
MOUSE_COMPROMISE, /* xterm-ish but with paste on RB in case no MB exists */
MOUSE_XTERM, /* xterm-style: MB pastes, RB extends selection */
MOUSE_WINDOWS /* Windows-style: RB brings up menu. MB still extends. */
};
enum {
/* Function key types (CONF_funky_type) */
FUNKY_TILDE,
FUNKY_LINUX,
FUNKY_XTERM,
FUNKY_VT400,
FUNKY_VT100P,
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 {
FQ_DEFAULT, FQ_ANTIALIASED, FQ_NONANTIALIASED, FQ_CLEARTYPE
};
enum {
CURSOR_BLOCK, CURSOR_UNDERLINE, CURSOR_VERTICAL_LINE
};
enum {
/* these are really bit flags */
BOLD_STYLE_FONT = 1,
BOLD_STYLE_COLOUR = 2,
};
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 */
#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,
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);
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);
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).
*
* 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);
/* 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);
/* Special-purpose function to return additional information to put
* in a "are you sure you want to close this session" dialog;
* return NULL if no such info, otherwise caller must free.
* Only implemented in the SSH protocol, to warn about downstream
* connections that would be lost if this one were terminated. */
char *(*close_warn_text)(Backend *be);
/* 'id' is a machine-readable name for the backend, used in
* 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;
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 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)
{ 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[];
/*
* In programs with a config UI, only the first few members of
* backends[] will be displayed at the top-level; the others will be
* relegated to a drop-down.
*/
extern const size_t n_ui_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;
/*
* 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.
* 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 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.
* 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 */
SeatPromptResult spr; /* some implementations need to cache one of these */
/*
* Set this flag to indicate that the caller has encoded the
* prompts in UTF-8, and expects the responses to be UTF-8 too.
*
* Ideally this flag would be unnecessary because it would always
* be true, but for legacy reasons, we have to switch over a bit
* at a time from the old behaviour, and may never manage to get
* rid of it completely.
*/
bool utf8;
/*
* 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;
};