9 |
10 | /*
11 | * smalloc should guarantee to return a useful pointer - Halibut
12 | * can do nothing except die when it's out of memory anyway.
13 | */
14 | void *smalloc(size_t size);
15 |
16 | /*
17 | * srealloc should guaranteeably be able to realloc NULL
18 | */
19 | void *srealloc(void *p, size_t size);
20 |
21 | /*
22 | * sfree should guaranteeably deal gracefully with freeing NULL
23 | */
24 | void sfree(void *p);
25 |
26 | /*
27 | * dupstr is like strdup, but with the never-return-NULL property
28 | * of smalloc (and also reliably defined in all environments :-)
29 | */
30 | char *dupstr(const char *s);
31 |
32 | /*
33 | * snew allocates one instance of a given type, and casts the
34 | * result so as to type-check that you're assigning it to the
35 | * right kind of pointer. Protects against allocation bugs
36 | * involving allocating the wrong size of thing.
37 | */
38 | #define snew(type) \
39 | ( (type *) smalloc (sizeof (type)) )
40 |
41 | /*
42 | * snewn allocates n instances of a given type, for arrays.
43 | */
44 | #define snewn(number, type) \
45 | ( (type *) smalloc ((number) * sizeof (type)) )
46 |
47 | /*
48 | * sresize wraps realloc so that you specify the new number of
49 | * elements and the type of the element, with the same type-
50 | * checking advantages. Also type-checks the input pointer.
51 | */
52 | #define sresize(array, number, type) \
53 | ( (void)sizeof((array)-(type *)0), \
54 | (type *) srealloc ((array), (number) * sizeof (type)) )
55 |
56 | #endif /* UMLWRAP_MALLOC_H */
57 |
--------------------------------------------------------------------------------
/doc/blurb.but:
--------------------------------------------------------------------------------
1 | \define{dash} \u2013{-}
2 |
3 | \title PuTTY User Manual
4 |
5 | \cfg{xhtml-leaf-level}{1}
6 | \cfg{xhtml-leaf-smallest-contents}{2}
7 | \cfg{xhtml-leaf-contains-contents}{true}
8 | \cfg{xhtml-body-end}{If you want to provide feedback on this manual
9 | or on the PuTTY tools themselves, see the
10 | Feedback
11 | page.
}
12 |
13 | \cfg{html-template-fragment}{%k}{%b}
14 |
15 | \cfg{info-max-file-size}{0}
16 |
17 | \cfg{chm-contents-filename}{index.html}
18 | \cfg{chm-template-filename}{%k.html}
19 | \cfg{chm-head-end}{}
20 | \cfg{chm-extra-file}{chm.css}
21 |
22 | \cfg{xhtml-contents-filename}{index.html}
23 | \cfg{text-filename}{puttydoc.txt}
24 | \cfg{winhelp-filename}{putty.hlp}
25 | \cfg{info-filename}{putty.info}
26 | \cfg{chm-filename}{putty.chm}
27 |
28 | PuTTY is a free (MIT-licensed) Windows Telnet and SSH client. This
29 | manual documents PuTTY, and its companion utilities PSCP, PSFTP,
30 | Plink, Pageant and PuTTYgen.
31 |
32 | \e{Note to Unix users:} this manual currently primarily documents the
33 | Windows versions of the PuTTY utilities. Some options are therefore
34 | mentioned that are absent from the \i{Unix version}; the Unix version has
35 | features not described here; and the \i\cw{pterm} and command-line
36 | \cw{puttygen} utilities are not described at all. The only
37 | Unix-specific documentation that currently exists is the
38 | \I{man pages for PuTTY tools}man pages.
39 |
40 | \copyright This manual is copyright \shortcopyrightdetails. All
41 | rights reserved. You may distribute this documentation under the MIT
42 | licence. See \k{licence} for the licence text in full.
43 |
--------------------------------------------------------------------------------
/contrib/logrewrap.pl:
--------------------------------------------------------------------------------
1 | #!/usr/bin/perl
2 |
3 | # Process a PuTTY SSH packet log that has gone through inappropriate
4 | # line wrapping, and try to make it legible again.
5 | #
6 | # Motivation: people often include PuTTY packet logs in email
7 | # messages, and if they're not careful, the sending MUA 'helpfully'
8 | # wraps the lines at 72 characters, corrupting all the hex dumps into
9 | # total unreadability.
10 | #
11 | # But as long as it's only the ASCII part of the dump at the end of
12 | # the line that gets wrapped, and the hex part is untouched, this is a
13 | # mechanically recoverable kind of corruption, because the ASCII is
14 | # redundant and can be reconstructed from the hex. Better still, you
15 | # can spot lines in which this has happened (because the ASCII at the
16 | # end of the line is a truncated version of what we think it should
17 | # say), and use that as a cue to remove the following line.
18 |
19 | use strict;
20 | use warnings;
21 |
22 | while (<>) {
23 | if (/^ ([0-9a-f]{8}) ((?:[0-9a-f]{2} ){0,15}(?:[0-9a-f]{2}))/) {
24 | my $addr = $1;
25 | my $hex = $2;
26 | my $ascii = "";
27 | for (my $i = 0; $i < length($2); $i += 3) {
28 | my $byte = hex(substr($hex, $i, 2));
29 | my $char = ($byte >= 32 && $byte < 127 ? chr($byte) : ".");
30 | $ascii .= $char;
31 | }
32 | $hex = substr($hex . (" " x 48), 0, 47);
33 | my $old_line = $_;
34 | chomp($old_line);
35 | my $new_line = " $addr $hex $ascii";
36 | if ($old_line ne $new_line and
37 | $old_line eq substr($new_line, 0, length($old_line))) {
38 | print "$new_line\n";
39 | <>; # eat the subsequent wrapped line
40 | next;
41 | }
42 | }
43 | print $_;
44 | }
45 |
--------------------------------------------------------------------------------
/windows/puttygen.rc:
--------------------------------------------------------------------------------
1 | /*
2 | * Windows resources for PuTTYgen.
3 | */
4 |
5 | #include "rcstuff.h"
6 |
7 | #define APPNAME "PuTTYgen"
8 | #define APPDESC "PuTTY SSH key generation utility"
9 |
10 | 200 ICON "puttygen.ico"
11 |
12 | 201 DIALOG DISCARDABLE 0, 0, 318, 270
13 | STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
14 | CAPTION "PuTTY Key Generator"
15 | FONT 8, "MS Shell Dlg"
16 | BEGIN
17 | END
18 |
19 | 210 DIALOG DISCARDABLE 0, 0, 140, 60
20 | STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
21 | CAPTION "PuTTYgen: Enter Passphrase"
22 | FONT 8, "MS Shell Dlg"
23 | BEGIN
24 | CTEXT "Enter passphrase for key", 100, 10, 6, 120, 8
25 | CTEXT "", 101, 10, 16, 120, 8
26 | EDITTEXT 102, 10, 26, 120, 12, ES_PASSWORD | ES_AUTOHSCROLL
27 | DEFPUSHBUTTON "O&K", IDOK, 20, 42, 40, 14
28 | PUSHBUTTON "&Cancel", IDCANCEL, 80, 42, 40, 14
29 | END
30 |
31 | /* Accelerators used: cl */
32 | 213 DIALOG DISCARDABLE 140, 40, 270, 106
33 | STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
34 | CAPTION "About PuTTYgen"
35 | FONT 8, "MS Shell Dlg"
36 | BEGIN
37 | DEFPUSHBUTTON "&Close", IDOK, 216, 88, 48, 14
38 | PUSHBUTTON "View &Licence", 101, 6, 88, 70, 14
39 | PUSHBUTTON "Visit &Web Site", 102, 140, 88, 70, 14
40 | EDITTEXT 1000, 10, 6, 250, 80, ES_READONLY | ES_MULTILINE | ES_CENTER, WS_EX_STATICEDGE
41 | END
42 |
43 | /* No accelerators used */
44 | 214 DIALOG DISCARDABLE 50, 50, 326, 231
45 | STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
46 | CAPTION "PuTTY Licence"
47 | FONT 8, "MS Shell Dlg"
48 | BEGIN
49 | DEFPUSHBUTTON "OK", IDOK, 148, 211, 44, 14
50 |
51 | EDITTEXT 1000, 10, 10, 306, 192, ES_READONLY | ES_MULTILINE | ES_LEFT, WS_EX_STATICEDGE
52 | END
53 |
54 | #include "version.rc2"
55 |
56 | #ifndef NO_MANIFESTS
57 | 1 RT_MANIFEST "puttygen.mft"
58 | #endif /* NO_MANIFESTS */
59 |
--------------------------------------------------------------------------------
/rdb/git-commit-putty-bin:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -e
3 |
4 | # This is required to clear the windows compile timestamp, and, obviously,
5 | # it makes things smaller.
6 |
7 | for i in $(ls windows/*.exe)
8 | do
9 | j=$(basename $i .exe)
10 | i686-w64-mingw32-strip -p $i
11 | [ -f unix/$j ] && strip -p unix/$j
12 | done
13 |
14 | NCOMMIT=$(
15 | {
16 | {
17 | sed 's/^[ ]*//' < $(date +%s) +0000
46 | committer Makefile <> $(date +%s) +0000
47 |
48 | PuTTY binaries.
49 | " ; } | git hash-object -t commit -w --stdin )
50 |
51 | # If 'binary' branch is missing create it quietly.
52 | [ "$(git show-ref --hash refs/heads/binary)" = "" ] &&
53 | git update-ref refs/heads/binary $NCOMMIT
54 |
55 | # Only update if the tree changed.
56 | [ "$(git log -1 --format=%T $NCOMMIT)" != "$(git log -1 --format=%T refs/heads/binary)" ] && {
57 | git update-ref refs/heads/binary $NCOMMIT
58 | echo Updated refs/heads/binary
59 | }
60 |
61 | exit 0
62 |
--------------------------------------------------------------------------------
/sshbpp.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Abstraction of the binary packet protocols used in SSH.
3 | */
4 |
5 | #ifndef PUTTY_SSHBPP_H
6 | #define PUTTY_SSHBPP_H
7 |
8 | typedef struct BinaryPacketProtocol BinaryPacketProtocol;
9 |
10 | struct BinaryPacketProtocolVtable {
11 | void (*free)(BinaryPacketProtocol *);
12 | void (*handle_input)(BinaryPacketProtocol *);
13 | PktOut *(*new_pktout)(int type);
14 | void (*format_packet)(BinaryPacketProtocol *, PktOut *);
15 | };
16 |
17 | struct BinaryPacketProtocol {
18 | const struct BinaryPacketProtocolVtable *vt;
19 | bufchain *in_raw, *out_raw;
20 | PacketQueue *in_pq;
21 | PacketLogSettings *pls;
22 | void *logctx;
23 |
24 | int seen_disconnect;
25 | char *error;
26 | };
27 |
28 | #define ssh_bpp_free(bpp) ((bpp)->vt->free(bpp))
29 | #define ssh_bpp_handle_input(bpp) ((bpp)->vt->handle_input(bpp))
30 | #define ssh_bpp_new_pktout(bpp, type) ((bpp)->vt->new_pktout(type))
31 | #define ssh_bpp_format_packet(bpp, pkt) ((bpp)->vt->format_packet(bpp, pkt))
32 |
33 | BinaryPacketProtocol *ssh1_bpp_new(void);
34 | void ssh1_bpp_new_cipher(BinaryPacketProtocol *bpp,
35 | const struct ssh_cipher *cipher,
36 | const void *session_key);
37 | void ssh1_bpp_start_compression(BinaryPacketProtocol *bpp);
38 |
39 | BinaryPacketProtocol *ssh2_bpp_new(void);
40 | void ssh2_bpp_new_outgoing_crypto(
41 | BinaryPacketProtocol *bpp,
42 | const struct ssh2_cipher *cipher, const void *ckey, const void *iv,
43 | const struct ssh_mac *mac, int etm_mode, const void *mac_key,
44 | const struct ssh_compress *compression);
45 | void ssh2_bpp_new_incoming_crypto(
46 | BinaryPacketProtocol *bpp,
47 | const struct ssh2_cipher *cipher, const void *ckey, const void *iv,
48 | const struct ssh_mac *mac, int etm_mode, const void *mac_key,
49 | const struct ssh_compress *compression);
50 |
51 | BinaryPacketProtocol *ssh2_bare_bpp_new(void);
52 |
53 | #endif /* PUTTY_SSHBPP_H */
54 |
--------------------------------------------------------------------------------
/pinger.c:
--------------------------------------------------------------------------------
1 | /*
2 | * pinger.c: centralised module that deals with sending TS_PING
3 | * keepalives, to avoid replicating this code in multiple backends.
4 | */
5 |
6 | #include "putty.h"
7 |
8 | struct pinger_tag {
9 | int interval;
10 | int pending;
11 | unsigned long when_set, next;
12 | Backend *back;
13 | void *backhandle;
14 | };
15 |
16 | static void pinger_schedule(Pinger pinger);
17 |
18 | static void pinger_timer(void *ctx, unsigned long now)
19 | {
20 | Pinger pinger = (Pinger)ctx;
21 |
22 | if (pinger->pending && now == pinger->next) {
23 | pinger->back->special(pinger->backhandle, TS_PING);
24 | pinger->pending = FALSE;
25 | pinger_schedule(pinger);
26 | }
27 | }
28 |
29 | static void pinger_schedule(Pinger pinger)
30 | {
31 | unsigned long next;
32 |
33 | if (!pinger->interval) {
34 | pinger->pending = FALSE; /* cancel any pending ping */
35 | return;
36 | }
37 |
38 | next = schedule_timer(pinger->interval * TICKSPERSEC,
39 | pinger_timer, pinger);
40 | if (!pinger->pending ||
41 | (next - pinger->when_set) < (pinger->next - pinger->when_set)) {
42 | pinger->next = next;
43 | pinger->when_set = timing_last_clock();
44 | pinger->pending = TRUE;
45 | }
46 | }
47 |
48 | Pinger pinger_new(Conf *conf, Backend *back, void *backhandle)
49 | {
50 | Pinger pinger = snew(struct pinger_tag);
51 |
52 | pinger->interval = conf_get_int(conf, CONF_ping_interval);
53 | pinger->pending = FALSE;
54 | pinger->back = back;
55 | pinger->backhandle = backhandle;
56 | pinger_schedule(pinger);
57 |
58 | return pinger;
59 | }
60 |
61 | void pinger_reconfig(Pinger pinger, Conf *oldconf, Conf *newconf)
62 | {
63 | int newinterval = conf_get_int(newconf, CONF_ping_interval);
64 | if (conf_get_int(oldconf, CONF_ping_interval) != newinterval) {
65 | pinger->interval = newinterval;
66 | pinger_schedule(pinger);
67 | }
68 | }
69 |
70 | void pinger_free(Pinger pinger)
71 | {
72 | expire_timer_context(pinger);
73 | sfree(pinger);
74 | }
75 |
--------------------------------------------------------------------------------
/windows/README-msi.txt:
--------------------------------------------------------------------------------
1 | PuTTY README
2 | ============
3 |
4 | This is the README file for the PuTTY MSI installer distribution. If
5 | you're reading this, you've probably just run our installer and
6 | installed PuTTY on your system.
7 |
8 | What should I do next?
9 | ----------------------
10 |
11 | If you want to use PuTTY to connect to other computers, or use PSFTP
12 | to transfer files, you should just be able to run them from the
13 | Start menu.
14 |
15 | If you want to use the command-line file transfer utility PSCP, you
16 | will need to run this from a Command Prompt or equivalent, because it
17 | will not do anything useful without command-line options telling it
18 | what files to copy to and from where. You can do this by just running
19 | the command 'pscp' from a Command Prompt, if you used the installer's
20 | option to put the PuTTY installation directory on your PATH.
21 | Alternatively, you can always run pscp.exe by its full pathname, e.g.
22 | "C:\Program Files\PuTTY\pscp.exe".
23 |
24 | (Note that a Command Prompt that was already open before you ran the
25 | installer will not have inherited the update of PATH.)
26 |
27 | Some versions of Windows will refuse to run HTML Help files (.CHM)
28 | if they are installed on a network drive. If you have installed
29 | PuTTY on a network drive, you might want to check that the help file
30 | works properly. If not, see http://support.microsoft.com/kb/896054
31 | for information on how to solve this problem.
32 |
33 | What do I do if it doesn't work?
34 | --------------------------------
35 |
36 | The PuTTY home web site is
37 |
38 | https://www.chiark.greenend.org.uk/~sgtatham/putty/
39 |
40 | Here you will find our list of known bugs and pending feature
41 | requests. If your problem is not listed in there, or in the FAQ, or
42 | in the manuals, read the Feedback page to find out how to report
43 | bugs to us. PLEASE read the Feedback page carefully: it is there to
44 | save you time as well as us. Do not send us one-line bug reports
45 | telling us `it doesn't work'.
46 |
--------------------------------------------------------------------------------
/windows/version.rc2:
--------------------------------------------------------------------------------
1 | /*
2 | * Standard Windows version information.
3 | * (For inclusion in other .rc files with appropriate macro definitions.)
4 | * FIXME: This file is called '.rc2' rather than '.rc' to avoid MSVC trying
5 | * to compile it on its own when using the project files. Nicer solutions
6 | * welcome.
7 | */
8 |
9 | #include "version.h"
10 | #include "licence.h"
11 |
12 | /*
13 | * The actual VERSIONINFO resource.
14 | */
15 | VS_VERSION_INFO VERSIONINFO
16 | /* (None of this "fixed" info appears to be trivially user-visible on
17 | * Win98SE. The binary version does show up on Win2K.) */
18 | FILEVERSION BINARY_VERSION
19 | PRODUCTVERSION BINARY_VERSION /* version of whole suite */
20 | FILEFLAGSMASK VS_FF_DEBUG | VS_FF_PRERELEASE | VS_FF_PRIVATEBUILD
21 | FILEFLAGS 0x0L
22 | #if defined DEBUG
23 | | VS_FF_DEBUG
24 | #endif
25 | #if defined SNAPSHOT || defined PRERELEASE
26 | | VS_FF_PRERELEASE
27 | #elif !defined RELEASE
28 | | VS_FF_PRIVATEBUILD
29 | #endif
30 | FILEOS VOS__WINDOWS32
31 | FILETYPE VFT_APP
32 | FILESUBTYPE 0x0L /* n/a for VFT_APP */
33 | BEGIN
34 | /* (On Win98SE and Win2K, we can see most of this on the Version tab
35 | * in the file properties in Explorer.) */
36 | BLOCK "StringFileInfo"
37 | BEGIN
38 | /* "lang-charset" LLLLCCCC = (UK English, Unicode) */
39 | BLOCK "080904B0"
40 | BEGIN
41 | VALUE "CompanyName", "Simon Tatham" /* required :/ */
42 | VALUE "ProductName", "PuTTY suite"
43 | VALUE "FileDescription", APPDESC
44 | VALUE "InternalName", APPNAME
45 | VALUE "OriginalFilename", APPNAME
46 | VALUE "FileVersion", TEXTVER
47 | VALUE "ProductVersion", TEXTVER
48 | VALUE "LegalCopyright", "Copyright \251 " SHORT_COPYRIGHT_DETAILS "."
49 | #if (!defined SNAPSHOT) && (!defined RELEASE) && (!defined PRERELEASE)
50 | /* Only if VS_FF_PRIVATEBUILD. */
51 | VALUE "PrivateBuild", TEXTVER /* NBI */
52 | #endif
53 | END
54 | END
55 | BLOCK "VarFileInfo"
56 | BEGIN
57 | /* Once again -- same meanings -- apparently necessary */
58 | VALUE "Translation", 0x809, 1200
59 | END
60 | END
61 |
--------------------------------------------------------------------------------
/sshcr.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Coroutine mechanics used in PuTTY's SSH code.
3 | */
4 |
5 | #ifndef PUTTY_SSHCR_H
6 | #define PUTTY_SSHCR_H
7 |
8 | /*
9 | * If these macros look impenetrable to you, you might find it helpful
10 | * to read
11 | *
12 | * https://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
13 | *
14 | * which explains the theory behind these macros.
15 | *
16 | * In particular, if you are getting `case expression not constant'
17 | * errors when building with MS Visual Studio, this is because MS's
18 | * Edit and Continue debugging feature causes their compiler to
19 | * violate ANSI C. To disable Edit and Continue debugging:
20 | *
21 | * - right-click ssh.c in the FileView
22 | * - click Settings
23 | * - select the C/C++ tab and the General category
24 | * - under `Debug info:', select anything _other_ than `Program
25 | * Database for Edit and Continue'.
26 | */
27 |
28 | #define crBegin(v) { int *crLine = &v; switch(v) { case 0:;
29 | #define crBeginState crBegin(s->crLine)
30 | #define crStateP(t, v) \
31 | struct t *s; \
32 | if (!(v)) { s = (v) = snew(struct t); s->crLine = 0; } \
33 | s = (v);
34 | #define crState(t) crStateP(t, ssh->t)
35 | #define crFinish(z) } *crLine = 0; return (z); }
36 | #define crFinishV } *crLine = 0; return; }
37 | #define crFinishFree(z) } sfree(s); return (z); }
38 | #define crFinishFreeV } sfree(s); return; }
39 | #define crReturn(z) \
40 | do {\
41 | *crLine =__LINE__; return (z); case __LINE__:;\
42 | } while (0)
43 | #define crReturnV \
44 | do {\
45 | *crLine=__LINE__; return; case __LINE__:;\
46 | } while (0)
47 | #define crStop(z) do{ *crLine = 0; return (z); }while(0)
48 | #define crStopV do{ *crLine = 0; return; }while(0)
49 | #define crWaitUntil(c) do { crReturn(0); } while (!(c))
50 | #define crWaitUntilV(c) do { crReturnV; } while (!(c))
51 | #define crMaybeWaitUntil(c) do { while (!(c)) crReturn(0); } while (0)
52 | #define crMaybeWaitUntilV(c) do { while (!(c)) crReturnV; } while (0)
53 |
54 | #endif /* PUTTY_SSHCR_H */
55 |
--------------------------------------------------------------------------------
/sshecdsag.c:
--------------------------------------------------------------------------------
1 | /*
2 | * EC key generation.
3 | */
4 |
5 | #include "ssh.h"
6 |
7 | /* Forward reference from sshecc.c */
8 | struct ec_point *ecp_mul(const struct ec_point *a, const Bignum b);
9 |
10 | int ec_generate(struct ec_key *key, int bits, progfn_t pfn,
11 | void *pfnparam)
12 | {
13 | struct ec_point *publicKey;
14 |
15 | if (!ec_nist_alg_and_curve_by_bits(bits, &key->publicKey.curve,
16 | &key->sshk))
17 | return 0;
18 |
19 | key->privateKey = bignum_random_in_range(One, key->publicKey.curve->w.n);
20 | if (!key->privateKey) return 0;
21 |
22 | publicKey = ec_public(key->privateKey, key->publicKey.curve);
23 | if (!publicKey) {
24 | freebn(key->privateKey);
25 | key->privateKey = NULL;
26 | return 0;
27 | }
28 |
29 | key->publicKey.x = publicKey->x;
30 | key->publicKey.y = publicKey->y;
31 | key->publicKey.z = NULL;
32 | sfree(publicKey);
33 |
34 | return 1;
35 | }
36 |
37 | int ec_edgenerate(struct ec_key *key, int bits, progfn_t pfn,
38 | void *pfnparam)
39 | {
40 | struct ec_point *publicKey;
41 |
42 | if (!ec_ed_alg_and_curve_by_bits(bits, &key->publicKey.curve,
43 | &key->sshk))
44 | return 0;
45 |
46 | {
47 | /* EdDSA secret keys are just 32 bytes of hash preimage; the
48 | * 64-byte SHA-512 hash of that key will be used when signing,
49 | * but the form of the key stored on disk is the preimage
50 | * only. */
51 | Bignum privMax = bn_power_2(bits);
52 | if (!privMax) return 0;
53 | key->privateKey = bignum_random_in_range(Zero, privMax);
54 | freebn(privMax);
55 | if (!key->privateKey) return 0;
56 | }
57 |
58 | publicKey = ec_public(key->privateKey, key->publicKey.curve);
59 | if (!publicKey) {
60 | freebn(key->privateKey);
61 | key->privateKey = NULL;
62 | return 0;
63 | }
64 |
65 | key->publicKey.x = publicKey->x;
66 | key->publicKey.y = publicKey->y;
67 | key->publicKey.z = NULL;
68 | sfree(publicKey);
69 |
70 | return 1;
71 | }
72 |
--------------------------------------------------------------------------------
/windows/pageant.rc:
--------------------------------------------------------------------------------
1 | /*
2 | * Windows resources for Pageant.
3 | */
4 |
5 | #include "rcstuff.h"
6 |
7 | #define APPNAME "Pageant"
8 | #define APPDESC "PuTTY SSH authentication agent"
9 |
10 | 200 ICON "pageant.ico"
11 | 201 ICON "pageants.ico"
12 |
13 | 210 DIALOG DISCARDABLE 0, 0, 140, 60
14 | STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
15 | CAPTION "Pageant: Enter Passphrase"
16 | FONT 8, "MS Shell Dlg"
17 | BEGIN
18 | CTEXT "Enter passphrase for key", 100, 10, 6, 120, 8
19 | CTEXT "", 101, 10, 16, 120, 8
20 | EDITTEXT 102, 10, 26, 120, 12, ES_PASSWORD | ES_AUTOHSCROLL
21 | DEFPUSHBUTTON "O&K", IDOK, 20, 42, 40, 14
22 | PUSHBUTTON "&Cancel", IDCANCEL, 80, 42, 40, 14
23 | END
24 |
25 | 211 DIALOG DISCARDABLE 0, 0, 330, 200
26 | STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
27 | CAPTION "Pageant Key List"
28 | FONT 8, "MS Shell Dlg"
29 | BEGIN
30 | LISTBOX 100, 10, 10, 310, 155,
31 | LBS_EXTENDEDSEL | LBS_HASSTRINGS | LBS_USETABSTOPS | WS_VSCROLL | WS_TABSTOP
32 | PUSHBUTTON "&Add Key", 101, 75, 162, 60, 14
33 | PUSHBUTTON "&Remove Key", 102, 195, 162, 60, 14
34 | PUSHBUTTON "&Help", 103, 10, 182, 50, 14
35 | DEFPUSHBUTTON "&Close", IDOK, 270, 182, 50, 14
36 | END
37 |
38 | /* Accelerators used: cl */
39 | 213 DIALOG DISCARDABLE 140, 40, 270, 106
40 | STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
41 | CAPTION "About Pageant"
42 | FONT 8, "MS Shell Dlg"
43 | BEGIN
44 | DEFPUSHBUTTON "&Close", IDOK, 216, 88, 48, 14
45 | PUSHBUTTON "View &Licence", 101, 6, 88, 70, 14
46 | PUSHBUTTON "Visit &Web Site", 102, 140, 88, 70, 14
47 | EDITTEXT 1000, 10, 6, 250, 80, ES_READONLY | ES_MULTILINE | ES_CENTER, WS_EX_STATICEDGE
48 | END
49 |
50 | /* No accelerators used */
51 | 214 DIALOG DISCARDABLE 50, 50, 326, 231
52 | STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
53 | CAPTION "PuTTY Licence"
54 | FONT 8, "MS Shell Dlg"
55 | BEGIN
56 | DEFPUSHBUTTON "OK", IDOK, 148, 211, 44, 14
57 |
58 | EDITTEXT 1000, 10, 10, 306, 192, ES_READONLY | ES_MULTILINE | ES_LEFT, WS_EX_STATICEDGE
59 | END
60 |
61 | #include "version.rc2"
62 |
63 | #ifndef NO_MANIFESTS
64 | 1 RT_MANIFEST "pageant.mft"
65 | #endif /* NO_MANIFESTS */
66 |
--------------------------------------------------------------------------------
/windows/win_res.rc2:
--------------------------------------------------------------------------------
1 | /*
2 | * Windows resources shared between PuTTY and PuTTYtel, to be #include'd
3 | * after defining appropriate macros.
4 | * Note that many of these strings mention PuTTY. Due to restrictions in
5 | * VC's handling of string concatenation, this can't easily be fixed.
6 | * It's fixed up at runtime.
7 | * FIXME: This file is called '.rc2' rather than '.rc' to avoid MSVC trying
8 | * to compile it on its own when using the project files. Nicer solutions
9 | * welcome.
10 | */
11 |
12 | #include "win_res.h"
13 |
14 | IDI_MAINICON ICON "putty.ico"
15 |
16 | IDI_CFGICON ICON "puttycfg.ico"
17 |
18 | /* Accelerators used: clw */
19 | IDD_ABOUTBOX DIALOG DISCARDABLE 140, 40, 270, 136
20 | STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
21 | CAPTION "About PuTTY"
22 | FONT 8, "MS Shell Dlg"
23 | BEGIN
24 | DEFPUSHBUTTON "&Close", IDOK, 216, 118, 48, 14
25 | PUSHBUTTON "View &Licence", IDA_LICENCE, 6, 118, 70, 14
26 | PUSHBUTTON "Visit &Web Site", IDA_WEB, 140, 118, 70, 14
27 | EDITTEXT IDA_TEXT, 10, 6, 250, 110, ES_READONLY | ES_MULTILINE | ES_CENTER, WS_EX_STATICEDGE
28 | END
29 |
30 | /* Accelerators used: aco */
31 | IDD_MAINBOX DIALOG DISCARDABLE 0, 0, 300, 252
32 | STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
33 | CAPTION "PuTTY Configuration"
34 | FONT 8, "MS Shell Dlg"
35 | CLASS "PuTTYConfigBox"
36 | BEGIN
37 | END
38 |
39 | /* Accelerators used: co */
40 | IDD_LOGBOX DIALOG DISCARDABLE 100, 20, 300, 119
41 | STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
42 | CAPTION "PuTTY Event Log"
43 | FONT 8, "MS Shell Dlg"
44 | BEGIN
45 | DEFPUSHBUTTON "&Close", IDOK, 135, 102, 44, 14
46 | PUSHBUTTON "C&opy", IDN_COPY, 81, 102, 44, 14
47 | LISTBOX IDN_LIST, 3, 3, 294, 95, LBS_HASSTRINGS | LBS_USETABSTOPS | WS_VSCROLL | LBS_EXTENDEDSEL
48 | END
49 |
50 | /* No accelerators used */
51 | IDD_LICENCEBOX DIALOG DISCARDABLE 50, 50, 326, 231
52 | STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
53 | CAPTION "PuTTY Licence"
54 | FONT 8, "MS Shell Dlg"
55 | BEGIN
56 | DEFPUSHBUTTON "OK", IDOK, 148, 211, 44, 14
57 |
58 | EDITTEXT IDA_TEXT, 10, 10, 306, 192, ES_READONLY | ES_MULTILINE | ES_LEFT, WS_EX_STATICEDGE
59 | END
60 |
61 | #include "version.rc2"
62 |
--------------------------------------------------------------------------------
/rdb/mk_pcodes.sh:
--------------------------------------------------------------------------------
1 | #!/bin/ksh
2 |
3 | TMP=/tmp/mk_x
4 | [ "$1" = "" ] && LOCAL=0.71-rdb
5 |
6 | [ -e ${TMP}1 -o -e ${TMP}2 -o -e ${TMP}3 -o -e ${TMP}4 -o -e ${TMP}5 -o -e x.ed ] &&
7 | { echo Temp file exists ; exit 1; }
8 |
9 | : > x.ed
10 | j=0.45
11 | echo 0i > x.ed
12 | expand PuTTY-Codes-$j.txt >> x.ed
13 | echo . >> x.ed
14 |
15 | for i in 0.49 0.50 0.52 0.53 0.54 0.58 0.63 0.71 ${LOCAL}
16 | do
17 | GL="`git log -1 $i --format=$i\ --\ %ai 2>/dev/null`"
18 | if [ "$GL" != "" ]
19 | then echo "VERSION $GL"
20 | else echo "VERSION $i"
21 | fi
22 |
23 | x="$i"
24 | [ "$x" = "0.71-rdb" ] && x=RDB
25 |
26 | expand PuTTY-Codes-$j.txt |
27 | awk > ${TMP}1 -v i=$x \
28 | '{
29 | str=$0
30 | if (str != "") str=substr($0 " ",1,76) i
31 | print str;
32 | }'
33 |
34 | expand PuTTY-Codes-$i.txt |
35 | awk > ${TMP}2 -v i=$x \
36 | '{
37 | str=$0
38 | if (str != "") str=substr($0 " ",1,76) i
39 | print str;
40 | }'
41 |
42 | diff -e ${TMP}1 ${TMP}2 >> x.ed
43 |
44 | diff -e PuTTY-Codes-$i.txt PuTTY-Codes-$j.txt | grep '^..........' > ${TMP}5
45 | if [ -s ${TMP}5 ]
46 | then
47 | {
48 | echo
49 | echo BEFORE VERSION $i
50 | cat ${TMP}5
51 | [ -f ${TMP}3 ] && cat ${TMP}3
52 | } > ${TMP}4
53 | mv ${TMP}4 ${TMP}3
54 | fi
55 |
56 | j=$i
57 | done
58 |
59 | echo 1i >> x.ed
60 | cat >> x.ed <<\!
61 | ANSI and VTxxx codes understood by PuTTY
62 |
63 | The basic emulation for PuTTY is that of an eight bit VT102 with
64 | cherry picked features from other ANSI terminals. As such it only
65 | understands seven bit ECMA-35 but adds onto that numerous 8 bit
66 | "codepages" and UTF-8.
67 |
68 | PuTTY Releases
69 |
70 | !
71 | for i in 0.45 0.49 0.50 0.52 0.53 0.54 0.58 0.63 0.71 ; do echo ' '$i `git log -1 $i --format=%ai | sed 's/..:.*//'` ; done >> x.ed
72 | echo >> x.ed
73 | echo . >> x.ed
74 |
75 | echo wq PuTTY-Codes.txt >> x.ed
76 | ed < x.ed
77 |
78 | {
79 | echo
80 | echo Items changed from previous versions
81 | echo ------------------------------------
82 | cat ${TMP}3
83 | } >> PuTTY-Codes.txt
84 |
85 | rm ${TMP}1 ${TMP}2 ${TMP}3 ${TMP}5 x.ed
86 |
--------------------------------------------------------------------------------
/unix/gtkcols.h:
--------------------------------------------------------------------------------
1 | /*
2 | * gtkcols.h - header file for a columns-based widget container
3 | * capable of supporting the PuTTY portable dialog box layout
4 | * mechanism.
5 | */
6 |
7 | #ifndef COLUMNS_H
8 | #define COLUMNS_H
9 |
10 | #include
11 | #include
12 |
13 | #ifdef __cplusplus
14 | extern "C" {
15 | #endif /* __cplusplus */
16 |
17 | #define TYPE_COLUMNS (columns_get_type())
18 | #define COLUMNS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), TYPE_COLUMNS, Columns))
19 | #define COLUMNS_CLASS(klass) \
20 | (G_TYPE_CHECK_CLASS_CAST((klass), TYPE_COLUMNS, ColumnsClass))
21 | #define IS_COLUMNS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), TYPE_COLUMNS))
22 | #define IS_COLUMNS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), TYPE_COLUMNS))
23 |
24 | typedef struct Columns_tag Columns;
25 | typedef struct ColumnsClass_tag ColumnsClass;
26 | typedef struct ColumnsChild_tag ColumnsChild;
27 |
28 | struct Columns_tag {
29 | GtkContainer container;
30 | /* private after here */
31 | GList *children; /* this holds ColumnsChild structures */
32 | GList *taborder; /* this just holds GtkWidgets */
33 | gint spacing;
34 | };
35 |
36 | struct ColumnsClass_tag {
37 | GtkContainerClass parent_class;
38 | };
39 |
40 | struct ColumnsChild_tag {
41 | /* If `widget' is non-NULL, this entry represents an actual widget. */
42 | GtkWidget *widget;
43 | gint colstart, colspan;
44 | gboolean force_left; /* for recalcitrant GtkLabels */
45 | ColumnsChild *same_height_as;
46 | /* Otherwise, this entry represents a change in the column setup. */
47 | gint ncols;
48 | gint *percentages;
49 | gint x, y, w, h; /* used during an individual size computation */
50 | };
51 |
52 | GType columns_get_type(void);
53 | GtkWidget *columns_new(gint spacing);
54 | void columns_set_cols(Columns *cols, gint ncols, const gint *percentages);
55 | void columns_add(Columns *cols, GtkWidget *child,
56 | gint colstart, gint colspan);
57 | void columns_taborder_last(Columns *cols, GtkWidget *child);
58 | void columns_force_left_align(Columns *cols, GtkWidget *child);
59 | void columns_force_same_height(Columns *cols, GtkWidget *ch1, GtkWidget *ch2);
60 |
61 | #ifdef __cplusplus
62 | }
63 | #endif /* __cplusplus */
64 |
65 | #endif /* COLUMNS_H */
66 |
--------------------------------------------------------------------------------
/unix/uxputty.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Unix PuTTY main program.
3 | */
4 |
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 |
13 | #define MAY_REFER_TO_GTK_IN_HEADERS
14 |
15 | #include "putty.h"
16 | #include "storage.h"
17 |
18 | #include "gtkcompat.h"
19 |
20 | /*
21 | * Stubs to avoid uxpty.c needing to be linked in.
22 | */
23 | const int use_pty_argv = FALSE;
24 | char **pty_argv; /* never used */
25 | char *pty_osx_envrestore_prefix;
26 |
27 | /*
28 | * Clean up and exit.
29 | */
30 | void cleanup_exit(int code)
31 | {
32 | /*
33 | * Clean up.
34 | */
35 | sk_cleanup();
36 | random_save_seed();
37 | exit(code);
38 | }
39 |
40 | Backend *select_backend(Conf *conf)
41 | {
42 | Backend *back = backend_from_proto(conf_get_int(conf, CONF_protocol));
43 | assert(back != NULL);
44 | return back;
45 | }
46 |
47 | void initial_config_box(Conf *conf, post_dialog_fn_t after, void *afterctx)
48 | {
49 | char *title = dupcat(appname, " Configuration", NULL);
50 | create_config_box(title, conf, FALSE, 0, after, afterctx);
51 | sfree(title);
52 | }
53 |
54 | const int use_event_log = 1, new_session = 1, saved_sessions = 1;
55 | const int dup_check_launchable = 1;
56 |
57 | char *make_default_wintitle(char *hostname)
58 | {
59 | return dupcat(hostname, " - ", appname, NULL);
60 | }
61 |
62 | /*
63 | * X11-forwarding-related things suitable for Gtk app.
64 | */
65 |
66 | char *platform_get_x_display(void) {
67 | const char *display;
68 | /* Try to take account of --display and what have you. */
69 | if (!(display = gdk_get_display()))
70 | /* fall back to traditional method */
71 | display = getenv("DISPLAY");
72 | return dupstr(display);
73 | }
74 |
75 | const int share_can_be_downstream = TRUE;
76 | const int share_can_be_upstream = TRUE;
77 |
78 | void setup(int single)
79 | {
80 | sk_init();
81 | flags = FLAG_VERBOSE | FLAG_INTERACTIVE;
82 | cmdline_tooltype |= TOOLTYPE_HOST_ARG | TOOLTYPE_PORT_ARG;
83 | default_protocol = be_default_protocol;
84 | /* Find the appropriate default port. */
85 | {
86 | Backend *b = backend_from_proto(default_protocol);
87 | default_port = 0; /* illegal */
88 | if (b)
89 | default_port = b->default_port;
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/charset/toucs.c:
--------------------------------------------------------------------------------
1 | /*
2 | * toucs.c - convert charsets to Unicode.
3 | */
4 |
5 | #include "charset.h"
6 | #include "internal.h"
7 |
8 | struct unicode_emit_param {
9 | wchar_t *output;
10 | int outlen;
11 | const wchar_t *errstr;
12 | int errlen;
13 | int stopped;
14 | };
15 |
16 | static void unicode_emit(void *ctx, long int output)
17 | {
18 | struct unicode_emit_param *param = (struct unicode_emit_param *)ctx;
19 | wchar_t outval;
20 | wchar_t const *p;
21 | int outlen;
22 |
23 | if (output == ERROR) {
24 | if (param->errstr) {
25 | p = param->errstr;
26 | outlen = param->errlen;
27 | } else {
28 | outval = 0xFFFD; /* U+FFFD REPLACEMENT CHARACTER */
29 | p = &outval;
30 | outlen = 1;
31 | }
32 | } else {
33 | outval = output;
34 | p = &outval;
35 | outlen = 1;
36 | }
37 |
38 | if (param->outlen >= outlen) {
39 | while (outlen > 0) {
40 | *param->output++ = *p++;
41 | param->outlen--;
42 | outlen--;
43 | }
44 | } else {
45 | param->stopped = 1;
46 | }
47 | }
48 |
49 | int charset_to_unicode(const char **input, int *inlen,
50 | wchar_t *output, int outlen,
51 | int charset, charset_state *state,
52 | const wchar_t *errstr, int errlen)
53 | {
54 | charset_spec const *spec = charset_find_spec(charset);
55 | charset_state localstate;
56 | struct unicode_emit_param param;
57 |
58 | param.output = output;
59 | param.outlen = outlen;
60 | param.errstr = errstr;
61 | param.errlen = errlen;
62 | param.stopped = 0;
63 |
64 | if (!state) {
65 | localstate.s0 = 0;
66 | } else {
67 | localstate = *state; /* structure copy */
68 | }
69 |
70 | while (*inlen > 0) {
71 | int lenbefore = param.output - output;
72 | spec->read(spec, (unsigned char)**input, &localstate,
73 | unicode_emit, ¶m);
74 | if (param.stopped) {
75 | /*
76 | * The emit function has _tried_ to output some
77 | * characters, but ran up against the end of the
78 | * buffer. Leave immediately, and return what happened
79 | * _before_ attempting to process this character.
80 | */
81 | return lenbefore;
82 | }
83 | if (state)
84 | *state = localstate; /* structure copy */
85 | (*input)++;
86 | (*inlen)--;
87 | }
88 |
89 | return param.output - output;
90 | }
91 |
--------------------------------------------------------------------------------
/windows/winsecur.h:
--------------------------------------------------------------------------------
1 | /*
2 | * winsecur.h: some miscellaneous security-related helper functions,
3 | * defined in winsecur.c, that use the advapi32 library. Also
4 | * centralises the machinery for dynamically loading that library.
5 | */
6 |
7 | #if !defined NO_SECURITY
8 |
9 | #include
10 |
11 | #ifndef WINSECUR_GLOBAL
12 | #define WINSECUR_GLOBAL extern
13 | #endif
14 |
15 | /*
16 | * Functions loaded from advapi32.dll.
17 | */
18 | DECL_WINDOWS_FUNCTION(WINSECUR_GLOBAL, BOOL, OpenProcessToken,
19 | (HANDLE, DWORD, PHANDLE));
20 | DECL_WINDOWS_FUNCTION(WINSECUR_GLOBAL, BOOL, GetTokenInformation,
21 | (HANDLE, TOKEN_INFORMATION_CLASS,
22 | LPVOID, DWORD, PDWORD));
23 | DECL_WINDOWS_FUNCTION(WINSECUR_GLOBAL, BOOL, InitializeSecurityDescriptor,
24 | (PSECURITY_DESCRIPTOR, DWORD));
25 | DECL_WINDOWS_FUNCTION(WINSECUR_GLOBAL, BOOL, SetSecurityDescriptorOwner,
26 | (PSECURITY_DESCRIPTOR, PSID, BOOL));
27 | DECL_WINDOWS_FUNCTION(WINSECUR_GLOBAL, DWORD, GetSecurityInfo,
28 | (HANDLE, SE_OBJECT_TYPE, SECURITY_INFORMATION,
29 | PSID *, PSID *, PACL *, PACL *,
30 | PSECURITY_DESCRIPTOR *));
31 | DECL_WINDOWS_FUNCTION(WINSECUR_GLOBAL, DWORD, SetSecurityInfo,
32 | (HANDLE, SE_OBJECT_TYPE, SECURITY_INFORMATION,
33 | PSID, PSID, PACL, PACL));
34 | DECL_WINDOWS_FUNCTION(WINSECUR_GLOBAL, DWORD, SetEntriesInAclA,
35 | (ULONG, PEXPLICIT_ACCESS, PACL, PACL *));
36 | int got_advapi(void);
37 |
38 | /*
39 | * Find the SID describing the current user. The return value (if not
40 | * NULL for some error-related reason) is smalloced.
41 | */
42 | PSID get_user_sid(void);
43 |
44 | /*
45 | * Construct a PSECURITY_DESCRIPTOR of the type used for named pipe
46 | * servers, i.e. allowing access only to the current user id and also
47 | * only local (i.e. not over SMB) connections.
48 | *
49 | * If this function returns TRUE, then 'psd' and 'acl' will have been
50 | * filled in with memory allocated using LocalAlloc (and hence must be
51 | * freed later using LocalFree). If it returns FALSE, then instead
52 | * 'error' has been filled with a dynamically allocated error message.
53 | */
54 | int make_private_security_descriptor(DWORD permissions,
55 | PSECURITY_DESCRIPTOR *psd,
56 | PACL *acl,
57 | char **error);
58 |
59 | #endif
60 |
--------------------------------------------------------------------------------
/charset/fromucs.c:
--------------------------------------------------------------------------------
1 | /*
2 | * fromucs.c - convert Unicode to other character sets.
3 | */
4 |
5 | #include "charset.h"
6 | #include "internal.h"
7 |
8 | struct charset_emit_param {
9 | char *output;
10 | int outlen;
11 | const char *errstr;
12 | int errlen;
13 | int stopped;
14 | };
15 |
16 | static void charset_emit(void *ctx, long int output)
17 | {
18 | struct charset_emit_param *param = (struct charset_emit_param *)ctx;
19 | char outval;
20 | char const *p;
21 | int outlen;
22 |
23 | if (output == ERROR) {
24 | p = param->errstr;
25 | outlen = param->errlen;
26 | } else {
27 | outval = output;
28 | p = &outval;
29 | outlen = 1;
30 | }
31 |
32 | if (param->outlen >= outlen) {
33 | while (outlen > 0) {
34 | *param->output++ = *p++;
35 | param->outlen--;
36 | outlen--;
37 | }
38 | } else {
39 | param->stopped = 1;
40 | }
41 | }
42 |
43 | int charset_from_unicode(const wchar_t **input, int *inlen,
44 | char *output, int outlen,
45 | int charset, charset_state *state,
46 | const char *errstr, int errlen)
47 | {
48 | charset_spec const *spec = charset_find_spec(charset);
49 | charset_state localstate;
50 | struct charset_emit_param param;
51 |
52 | param.output = output;
53 | param.outlen = outlen;
54 | param.stopped = 0;
55 |
56 | /*
57 | * charset_emit will expect a valid errstr.
58 | */
59 | if (!errstr) {
60 | /* *shrug* this is good enough, and consistent across all SBCS... */
61 | param.errstr = ".";
62 | param.errlen = 1;
63 | }
64 | param.errstr = errstr;
65 | param.errlen = errlen;
66 |
67 | if (!state) {
68 | localstate.s0 = 0;
69 | } else {
70 | localstate = *state; /* structure copy */
71 | }
72 | state = &localstate;
73 |
74 | while (*inlen > 0) {
75 | int lenbefore = param.output - output;
76 | spec->write(spec, **input, &localstate, charset_emit, ¶m);
77 | if (param.stopped) {
78 | /*
79 | * The emit function has _tried_ to output some
80 | * characters, but ran up against the end of the
81 | * buffer. Leave immediately, and return what happened
82 | * _before_ attempting to process this character.
83 | */
84 | return lenbefore;
85 | }
86 | if (state)
87 | *state = localstate; /* structure copy */
88 | (*input)++;
89 | (*inlen)--;
90 | }
91 | return param.output - output;
92 | }
93 |
--------------------------------------------------------------------------------
/rdb/dbcs_chars.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh -
2 |
3 | # CP10001:Lead Bytes: 0x81 0x9f 0xe0 0xfc 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
4 | # CP10002:Lead Bytes: 0x81 0xfc 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
5 | # CP10003:Lead Bytes: 0xa1 0xac 0xb0 0xc8 0xca 0xfd 0x00 0x00 0x00 0x00 0x00 0x00
6 | # CP10008:Lead Bytes: 0xa1 0xa9 0xb0 0xf7 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
7 | # CP1361 :Lead Bytes: 0x84 0xd3 0xd8 0xde 0xe0 0xf9 0x00 0x00 0x00 0x00 0x00 0x00
8 | # CP20000:Lead Bytes: 0xa1 0xfe 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
9 | # CP20001:Lead Bytes: 0x81 0x84 0x91 0xd8 0xdf 0xfc 0x00 0x00 0x00 0x00 0x00 0x00
10 | # CP20002:Lead Bytes: 0x81 0xaf 0xdd 0xfe 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
11 | # CP20003:Lead Bytes: 0x81 0x84 0x87 0x87 0x89 0xe8 0xf9 0xfb 0x00 0x00 0x00 0x00
12 | # CP20004:Lead Bytes: 0xa1 0xfe 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
13 | # CP20005:Lead Bytes: 0x8d 0xf5 0xf9 0xfc 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
14 | # CP20261:Lead Bytes: 0xc1 0xcf 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
15 | # CP20932:Lead Bytes: 0x8e 0x8e 0xa1 0xfe 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
16 | # CP20936:Lead Bytes: 0xa1 0xa9 0xb0 0xf7 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
17 | # CP51949:Lead Bytes: 0xa1 0xac 0xb0 0xc8 0xca 0xfd 0x00 0x00 0x00 0x00 0x00 0x00
18 | # CP932 :Lead Bytes: 0x81 0x9f 0xe0 0xfc 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
19 | # CP936 :Lead Bytes: 0x81 0xfe 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
20 | # CP949 :Lead Bytes: 0x81 0xfe 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
21 | # CP950 :Lead Bytes: 0x81 0xfe 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
22 |
23 |
24 | mawk '
25 | BEGIN{
26 | widespace = 1;
27 |
28 | {
29 | page = 0;
30 | if (widespace) printf("\033%%@")
31 | printf("Characters starting at 0x%04x", 32);
32 | for(i=32; i<256; i++) {
33 | if (i%16 == 0) printf("\n%04x: ", page*256 + i);
34 | if (i == 127)
35 | ;
36 | else
37 | printf(" %c ", i);
38 | }
39 | printf("\n");
40 | }
41 |
42 |
43 | for (page=129; page < 255; page++) {
44 | printf("Characters starting at 0x%04x", page*256 + 64);
45 | for(i=64; i<256; i++) {
46 | if (i%16 == 0) printf("\n%04x: ", page*256 + i);
47 | if (i == 127)
48 | ;
49 | else
50 | printf("%c%c", page, i);
51 | if (widespace) printf("\033%%G\xe3\x80\x80\033%%@")
52 | else printf(" ");
53 | }
54 | printf("\n");
55 | }
56 | }
57 | '
58 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | PuTTY Patched
2 | =============
3 |
4 | This is a mirror of Simon's git repository with my PuTTY
5 | patches in the putty-rdb branch.
6 |
7 | The [master branch](https://github.com/rdebath/PuTTY/tree/master) of this
8 | repository is a clone of the master from Simon's PuTTY repo at
9 | [git://git.tartarus.org/simon/putty.git](http://tartarus.org/~simon-git/gitweb/?p=putty.git)
10 | and I am pushing Binaries to [here](https://github.com/rdebath/PuTTY/tree/binary).
11 |
12 | *NOTE* ...
13 | I'm pushing to this repository using rebase to keep each patch as a single commit.
14 |
15 | Bugfixes
16 | ========
17 | * Fix WM_NETEVENT delayed processing.
18 | * Repair handling of WM_NETEVENT (part 2)
19 | * Repair GTK timer handling
20 | * Minimise, maximise, etc are as annoying as other terminal resize operations.
21 | * Adjust DEC-MCS character set.
22 | * This is a fix for the direct to font DBCS cursor.
23 | * Windows codepages do not have C1 controls
24 | * Fix the scoasc translation on unix
25 | * Function x11font_draw_text uses the UCS2 character set
26 | * SCO Ansi Keyboard correction
27 | * Make sure all ISO-2022 codes are checked.
28 | * Timer starvation fix
29 | * Fix support of Windows 256 colour palettes.
30 |
31 | Performance Improvements
32 | ========================
33 | * Pango font performance update
34 | * Optimisation to delete windows code on unix
35 | * Windows font drawing change.
36 | * Don't let dopaint eat too much CPU
37 | * Remove unneeded special case code for proportional fonts.
38 |
39 | Small Features
40 | ==============
41 | * Add XTerm extensions for VTTEST and reverse BS
42 | * Add new interpretation for XTerm SGR 38/48
43 | * Add XTerm/Konsole truecolour mode.
44 | * Line character set for Window title on windows.
45 | * Add wcwidth override sequence
46 | * Add Ansi REP sequence and SCO CSI = g
47 | * Add DIM, CONCEAL, BGBOLD and Blink control.
48 | * Add Linux default attribute set.
49 | * Adding better support for Windows MBCS (codepages)
50 | * Add Linux default attribute set. Comments
51 | * Reconfigure PuTTY colour scheme from Unix host.
52 |
53 | Large Features
54 | ==============
55 | * UTF-8 processing update
56 |
57 | Code Cleanups
58 | =============
59 | * Changes to the internal usage of unicode areas for character set conversion.
60 | * Clean up VT52 leftovers from the 256 colours patch
61 | * Waaay overkill on uuid generation
62 | * Changes for compiling under MinGW
63 |
64 | Obviously, some of these will depend on earlier changes *plus* I am only
65 | testing the full set so partial sets may have significant bugs.
66 |
--------------------------------------------------------------------------------
/unix/x11misc.c:
--------------------------------------------------------------------------------
1 | /*
2 | * x11misc.c: miscellaneous stuff for dealing directly with X servers.
3 | */
4 |
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | #include "putty.h"
12 |
13 | #ifndef NOT_X_WINDOWS
14 |
15 | #include
16 | #include
17 | #include
18 |
19 | #include "x11misc.h"
20 |
21 | /* ----------------------------------------------------------------------
22 | * Error handling mechanism which permits us to ignore specific X11
23 | * errors from particular requests. We maintain a list of upcoming
24 | * potential error events that we want to not treat as fatal errors.
25 | */
26 |
27 | static int (*orig_x11_error_handler)(Display *thisdisp, XErrorEvent *err);
28 |
29 | struct x11_err_to_ignore {
30 | Display *display;
31 | unsigned char error_code;
32 | unsigned long serial;
33 | };
34 |
35 | struct x11_err_to_ignore *errs;
36 |
37 | int nerrs, errsize;
38 |
39 | static int x11_error_handler(Display *thisdisp, XErrorEvent *err)
40 | {
41 | int i;
42 | for (i = 0; i < nerrs; i++) {
43 | if (thisdisp == errs[i].display &&
44 | err->serial == errs[i].serial &&
45 | err->error_code == errs[i].error_code) {
46 | /* Ok, this is an error we're happy to ignore */
47 | return 0;
48 | }
49 | }
50 |
51 | return (*orig_x11_error_handler)(thisdisp, err);
52 | }
53 |
54 | void x11_ignore_error(Display *disp, unsigned char errcode)
55 | {
56 | /*
57 | * Install our error handler, if we haven't already.
58 | */
59 | if (!orig_x11_error_handler)
60 | orig_x11_error_handler = XSetErrorHandler(x11_error_handler);
61 |
62 | /*
63 | * This is as good a moment as any to winnow the ignore list based
64 | * on requests we know to have been processed.
65 | */
66 | {
67 | unsigned long last = LastKnownRequestProcessed(disp);
68 | int i, j;
69 | for (i = j = 0; i < nerrs; i++) {
70 | if (errs[i].display == disp && errs[i].serial <= last)
71 | continue;
72 | errs[j++] = errs[i];
73 | }
74 | nerrs = j;
75 | }
76 |
77 | if (nerrs >= errsize) {
78 | errsize = nerrs * 5 / 4 + 16;
79 | errs = sresize(errs, errsize, struct x11_err_to_ignore);
80 | }
81 | errs[nerrs].display = disp;
82 | errs[nerrs].error_code = errcode;
83 | errs[nerrs].serial = NextRequest(disp);
84 | nerrs++;
85 | }
86 |
87 | #endif
88 |
89 |
--------------------------------------------------------------------------------
/doc/Makefile:
--------------------------------------------------------------------------------
1 | all: man index.html
2 |
3 | # Decide on the versionid policy.
4 | #
5 | # If the user has passed in $(VERSION) on the command line (`make
6 | # VERSION="Release 0.56"'), we use that as an explicit version string.
7 | # Otherwise, we use `svnversion' to examine the checked-out
8 | # documentation source, and if that returns a single revision number
9 | # then we invent a version string reflecting just that number. Failing
10 | # _that_, we resort to versionids.but which gives 'version
11 | # unavailable'.
12 | #
13 | # So here, we define VERSION using svnversion if it isn't already
14 | # defined ...
15 | ifndef VERSION
16 | SVNVERSION=$(shell test -d .svn && svnversion .)
17 | BADCHARS=$(findstring :,$(SVNVERSION))$(findstring S,$(SVNVERSION))
18 | ifeq ($(BADCHARS),)
19 | ifneq ($(SVNVERSION),)
20 | ifneq ($(SVNVERSION),exported)
21 | VERSION=Built from revision $(patsubst M,,$(SVNVERSION))
22 | endif
23 | endif
24 | endif
25 | endif
26 | # ... and now, we condition our build behaviour on whether or not
27 | # VERSION _is_ defined.
28 | ifdef VERSION
29 | VERSIONIDS=vstr
30 | vstr.but: FORCE
31 | printf '\\versionid $(VERSION)\n' > vstr.but
32 | FORCE:;
33 | else
34 | VERSIONIDS=vids
35 | endif
36 |
37 | CHAPTERS := $(SITE) copy blurb intro gs using config pscp psftp plink
38 | CHAPTERS += pubkey pageant errors faq feedback licence udp pgpkeys sshnames
39 | CHAPTERS += index $(VERSIONIDS)
40 |
41 | INPUTS = $(patsubst %,%.but,$(CHAPTERS))
42 |
43 | # This is temporary. Hack it locally or something.
44 | HALIBUT = halibut
45 |
46 | index.html: $(INPUTS)
47 | $(HALIBUT) --text --html --winhelp --chm $(INPUTS)
48 |
49 | # During formal builds it's useful to be able to build these ones alone.
50 | putty.hlp: $(INPUTS)
51 | $(HALIBUT) --winhelp $(INPUTS)
52 | putty.chm: $(INPUTS)
53 | $(HALIBUT) --chm $(INPUTS)
54 |
55 | putty.info: $(INPUTS)
56 | $(HALIBUT) --info $(INPUTS)
57 |
58 | MKMAN = $(HALIBUT) --man=$@ mancfg.but $<
59 | MANPAGES = putty.1 puttygen.1 plink.1 pscp.1 psftp.1 puttytel.1 pterm.1 \
60 | pageant.1
61 | man: $(MANPAGES)
62 |
63 | putty.1: man-putt.but mancfg.but; $(MKMAN)
64 | puttygen.1: man-pg.but mancfg.but; $(MKMAN)
65 | plink.1: man-pl.but mancfg.but; $(MKMAN)
66 | pscp.1: man-pscp.but mancfg.but; $(MKMAN)
67 | psftp.1: man-psft.but mancfg.but; $(MKMAN)
68 | puttytel.1: man-ptel.but mancfg.but; $(MKMAN)
69 | pterm.1: man-pter.but mancfg.but; $(MKMAN)
70 | pageant.1: man-pag.but mancfg.but; $(MKMAN)
71 |
72 | mostlyclean:
73 | rm -f *.html *.txt *.hlp *.cnt *.1 *.info vstr.but *.hh[pck]
74 | clean: mostlyclean
75 | rm -f *.chm
76 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.o
2 | *.pyc
3 | .dirstamp
4 | .deps
5 | .DS_Store
6 | /*.pdb
7 | /*.ilk
8 | /*.res
9 | /*.RES
10 | /*.pch
11 | /*.rsp
12 | /*.obj
13 | /*.exe
14 | /*.ncb
15 | /*.plg
16 | /*.dsw
17 | /*.opt
18 | /*.dsp
19 | /*.tds
20 | /*.td2
21 | /*.map
22 | /Makefile.mgw
23 | /Makefile.vc
24 | /Makefile.lcc
25 | /MSVC
26 | /*.log
27 | /*.GID
28 | /local
29 | /Output
30 | /pageant
31 | /plink
32 | /pscp
33 | /psftp
34 | /putty
35 | /puttytel
36 | /puttygen
37 | /pterm
38 | /puttyapp
39 | /ptermapp
40 | /osxlaunch
41 | /unix/PuTTY.app
42 | /unix/Pterm.app
43 | /fuzzterm
44 | /testbn
45 | /cgtest
46 | /*.DSA
47 | /*.RSA
48 | /*.cnt
49 | /*.hlp
50 | /.bmake
51 | /build.log
52 | /build.out
53 | /uxconfig.h
54 | /empty.h
55 | /config.status
56 | /Makefile.am
57 | /Makefile.in
58 | /Makefile
59 | /compile
60 | /config.status
61 | /configure
62 | /stamp-h1
63 | /aclocal.m4
64 | /ar-lib
65 | /autom4te.cache
66 | /depcomp
67 | /install-sh
68 | /local
69 | /missing
70 | /uxconfig.in
71 | /uxconfig.h
72 | /licence.h
73 | /*.a
74 | /charset/sbcsdat.c
75 | /contrib/cygtermd/cygtermd.exe
76 | /doc/*.html
77 | /doc/*.txt
78 | /doc/*.cnt
79 | /doc/*.hlp
80 | /doc/*.gid
81 | /doc/*.GID
82 | /doc/*.chm
83 | /doc/*.log
84 | /doc/*.1
85 | /doc/*.info
86 | /doc/vstr.but
87 | /doc/*.hhp
88 | /doc/*.hhc
89 | /doc/*.hhk
90 | /doc/licence.but
91 | /doc/copy.but
92 | /icons/*.pam
93 | /icons/*.png
94 | /icons/*.ico
95 | /icons/*.icns
96 | /icons/*.xpm
97 | /icons/*.c
98 | /testdata/bignum.txt
99 | /unix/Makefile.gtk
100 | /unix/Makefile.ux
101 | /unix/Makefile.local
102 | /unix/empty.h
103 | /unix/plink
104 | /unix/pterm
105 | /unix/putty
106 | /unix/puttytel
107 | /unix/psftp
108 | /unix/pscp
109 | /unix/puttygen
110 | /unix/stamp-h1
111 | /unix/*.log
112 | /unix/.deps
113 | /windows/*.pdb
114 | /windows/*.ilk
115 | /windows/*.res
116 | /windows/*.RES
117 | /windows/*.pch
118 | /windows/*.rsp
119 | /windows/*.obj
120 | /windows/*.exe
121 | /windows/*.ncb
122 | /windows/*.plg
123 | /windows/*.dsw
124 | /windows/*.opt
125 | /windows/*.dsp
126 | /windows/*.tds
127 | /windows/*.td2
128 | /windows/*.map
129 | /windows/Makefile.clangcl
130 | /windows/Makefile.mgw
131 | /windows/Makefile.vc
132 | /windows/Makefile.lcc
133 | /windows/MSVC
134 | /windows/DEVCPP
135 | /windows/VS2010
136 | /windows/VS2012
137 | /windows/*.log
138 | /windows/*.GID
139 | /windows/local
140 | /windows/Output
141 | /windows/*.DSA
142 | /windows/*.RSA
143 | /windows/*.cnt
144 | /windows/*.hlp
145 | /windows/.bmake
146 | /windows/*.sln
147 | /windows/*.suo
148 | /windows/*.msi
149 | /windows/*.wixobj
150 | /windows/*.wixpdb
151 |
--------------------------------------------------------------------------------
/unix/uxcfg.c:
--------------------------------------------------------------------------------
1 | /*
2 | * uxcfg.c - the Unix-specific parts of the PuTTY configuration
3 | * box.
4 | */
5 |
6 | #include
7 | #include
8 |
9 | #include "putty.h"
10 | #include "dialog.h"
11 | #include "storage.h"
12 |
13 | void unix_setup_config_box(struct controlbox *b, int midsession, int protocol)
14 | {
15 | struct controlset *s;
16 | union control *c;
17 |
18 | /*
19 | * The Conf structure contains two Unix-specific elements which
20 | * are not configured in here: stamp_utmp and login_shell. This
21 | * is because pterm does not put up a configuration box right at
22 | * the start, which is the only time when these elements would
23 | * be useful to configure.
24 | */
25 |
26 | /*
27 | * On Unix, we don't have a drop-down list for the printer
28 | * control.
29 | */
30 | s = ctrl_getset(b, "Terminal", "printing", "Remote-controlled printing");
31 | assert(s->ncontrols == 1 && s->ctrls[0]->generic.type == CTRL_EDITBOX);
32 | s->ctrls[0]->editbox.has_list = 0;
33 |
34 | /*
35 | * Unix supports a local-command proxy. This also means we must
36 | * adjust the text on the `Telnet command' control.
37 | */
38 | if (!midsession) {
39 | int i;
40 | s = ctrl_getset(b, "Connection/Proxy", "basics", NULL);
41 | for (i = 0; i < s->ncontrols; i++) {
42 | c = s->ctrls[i];
43 | if (c->generic.type == CTRL_RADIO &&
44 | c->generic.context.i == CONF_proxy_type) {
45 | assert(c->generic.handler == conf_radiobutton_handler);
46 | c->radio.nbuttons++;
47 | c->radio.buttons =
48 | sresize(c->radio.buttons, c->radio.nbuttons, char *);
49 | c->radio.buttons[c->radio.nbuttons-1] =
50 | dupstr("Local");
51 | c->radio.buttondata =
52 | sresize(c->radio.buttondata, c->radio.nbuttons, intorptr);
53 | c->radio.buttondata[c->radio.nbuttons-1] = I(PROXY_CMD);
54 | break;
55 | }
56 | }
57 |
58 | for (i = 0; i < s->ncontrols; i++) {
59 | c = s->ctrls[i];
60 | if (c->generic.type == CTRL_EDITBOX &&
61 | c->generic.context.i == CONF_proxy_telnet_command) {
62 | assert(c->generic.handler == conf_editbox_handler);
63 | sfree(c->generic.label);
64 | c->generic.label = dupstr("Telnet command, or local"
65 | " proxy command");
66 | break;
67 | }
68 | }
69 | }
70 |
71 | /*
72 | * Serial back end is available on Unix. However, we have to
73 | * mask out a couple of the configuration options: mark and
74 | * space parity are not conveniently supported, and neither is
75 | * DSR/DTR flow control.
76 | */
77 | if (!midsession || (protocol == PROT_SERIAL))
78 | ser_setup_config_box(b, midsession, 0x07, 0x07);
79 | }
80 |
--------------------------------------------------------------------------------
/doc/sshnames.but:
--------------------------------------------------------------------------------
1 | \A{sshnames} SSH-2 names specified for PuTTY
2 |
3 | There are various parts of the SSH-2 protocol where things are specified
4 | using a textual name. Names ending in \cw{@putty.projects.tartarus.org}
5 | are reserved for allocation by the PuTTY team. Allocated names are
6 | documented here.
7 |
8 | \H{sshnames-channel} Connection protocol channel request names
9 |
10 | These names can be sent in a \cw{SSH_MSG_CHANNEL_REQUEST} message.
11 |
12 | \dt \cw{simple@putty.projects.tartarus.org}
13 |
14 | \dd This is sent by a client to announce that it will not have more than
15 | one channel open at a time in the current connection (that one being
16 | the one the request is sent on). The intention is that the server,
17 | knowing this, can set the window on that one channel to something very
18 | large, and leave flow control to TCP. There is no message-specific data.
19 |
20 | \dt \cw{winadj@putty.projects.tartarus.org}
21 |
22 | \dd PuTTY sends this request along with some
23 | \cw{SSH_MSG_CHANNEL_WINDOW_ADJUST} messages as part of its window-size
24 | tuning. It can be sent on any type of channel. There is no
25 | message-specific data. Servers MUST treat it as an unrecognised request
26 | and respond with \cw{SSH_MSG_CHANNEL_FAILURE}.
27 |
28 | \lcont{
29 | (Some SSH servers get confused by this message, so there is a
30 | bug-compatibility mode for disabling it. See \k{config-ssh-bug-winadj}.)
31 | }
32 |
33 | \H{sshnames-kex} Key exchange method names
34 |
35 | \dt \cw{rsa-sha1-draft-00@putty.projects.tartarus.org}
36 |
37 | \dt \cw{rsa-sha256-draft-00@putty.projects.tartarus.org}
38 |
39 | \dt \cw{rsa1024-sha1-draft-01@putty.projects.tartarus.org}
40 |
41 | \dt \cw{rsa1024-sha256-draft-01@putty.projects.tartarus.org}
42 |
43 | \dt \cw{rsa2048-sha256-draft-01@putty.projects.tartarus.org}
44 |
45 | \dt \cw{rsa1024-sha1-draft-02@putty.projects.tartarus.org}
46 |
47 | \dt \cw{rsa2048-sha512-draft-02@putty.projects.tartarus.org}
48 |
49 | \dt \cw{rsa1024-sha1-draft-03@putty.projects.tartarus.org}
50 |
51 | \dt \cw{rsa2048-sha256-draft-03@putty.projects.tartarus.org}
52 |
53 | \dt \cw{rsa1024-sha1-draft-04@putty.projects.tartarus.org}
54 |
55 | \dt \cw{rsa2048-sha256-draft-04@putty.projects.tartarus.org}
56 |
57 | \dd These appeared in various drafts of what eventually became RFC\_4432.
58 | They have been superseded by \cw{rsa1024-sha1} and \cw{rsa2048-sha256}.
59 |
60 | \H{sshnames-encrypt} Encryption algorithm names
61 |
62 | \dt \cw{arcfour128-draft-00@putty.projects.tartarus.org}
63 |
64 | \dt \cw{arcfour256-draft-00@putty.projects.tartarus.org}
65 |
66 | \dd These were used in drafts of what eventually became RFC\_4345.
67 | They have been superseded by \cw{arcfour128} and \cw{arcfour256}.
68 |
--------------------------------------------------------------------------------
/defs.h:
--------------------------------------------------------------------------------
1 | /*
2 | * defs.h: initial definitions for PuTTY.
3 | *
4 | * The rule about this header file is that it can't depend on any
5 | * other header file in this code base. This is where we define
6 | * things, as much as we can, that other headers will want to refer
7 | * to, such as opaque structure types and their associated typedefs,
8 | * or macros that are used by other headers.
9 | */
10 |
11 | #ifndef PUTTY_DEFS_H
12 | #define PUTTY_DEFS_H
13 |
14 | #include
15 |
16 | #ifndef FALSE
17 | #define FALSE 0
18 | #endif
19 | #ifndef TRUE
20 | #define TRUE 1
21 | #endif
22 |
23 | typedef struct conf_tag Conf;
24 | typedef struct backend_tag Backend;
25 | typedef struct terminal_tag Terminal;
26 |
27 | typedef struct Filename Filename;
28 | typedef struct FontSpec FontSpec;
29 |
30 | typedef struct bufchain_tag bufchain;
31 |
32 | typedef struct strbuf strbuf;
33 |
34 | struct RSAKey;
35 |
36 | #include
37 | typedef uint32_t uint32;
38 |
39 | typedef struct BinarySink BinarySink;
40 | typedef struct BinarySource BinarySource;
41 |
42 | typedef struct SockAddr_tag *SockAddr;
43 |
44 | typedef struct Socket_vtable Socket_vtable;
45 | typedef struct Plug_vtable Plug_vtable;
46 |
47 | /* Note indirection: for historical reasons (it used to be closer to
48 | * the OS socket type), the type that most code uses for a socket is
49 | * 'Socket', not 'Socket *'. So an implementation of Socket or Plug
50 | * has a 'const Socket *' field for the vtable pointer, and the
51 | * 'Socket' type returned to client code is a pointer to _that_ in
52 | * turn. */
53 | typedef const Socket_vtable **Socket;
54 | typedef const Plug_vtable **Plug;
55 |
56 | /*
57 | * A small structure wrapping up a (pointer, length) pair so that it
58 | * can be conveniently passed to or from a function.
59 | */
60 | typedef struct ptrlen {
61 | const void *ptr;
62 | size_t len;
63 | } ptrlen;
64 |
65 | typedef struct logblank_t logblank_t;
66 |
67 | /* Do a compile-time type-check of 'to_check' (without evaluating it),
68 | * as a side effect of returning the value 'to_return'. Note that
69 | * although this macro double-*expands* to_return, it always
70 | * *evaluates* exactly one copy of it, so it's side-effect safe. */
71 | #define TYPECHECK(to_check, to_return) \
72 | (sizeof(to_check) ? (to_return) : (to_return))
73 |
74 | /* Return a pointer to the object of structure type 'type' whose field
75 | * with name 'field' is pointed at by 'object'. */
76 | #define FROMFIELD(object, type, field) \
77 | TYPECHECK(object == &((type *)0)->field, \
78 | ((type *)(((char *)(object)) - offsetof(type, field))))
79 |
80 | #endif /* PUTTY_DEFS_H */
81 |
--------------------------------------------------------------------------------
/puttymem.h:
--------------------------------------------------------------------------------
1 | /*
2 | * PuTTY memory-handling header.
3 | */
4 |
5 | #ifndef PUTTY_PUTTYMEM_H
6 | #define PUTTY_PUTTYMEM_H
7 |
8 | #include /* for size_t */
9 | #include /* for memcpy() */
10 |
11 |
12 | /* #define MALLOC_LOG do this if you suspect putty of leaking memory */
13 | #ifdef MALLOC_LOG
14 | #define smalloc(z) (mlog(__FILE__,__LINE__), safemalloc(z,1))
15 | #define snmalloc(z,s) (mlog(__FILE__,__LINE__), safemalloc(z,s))
16 | #define srealloc(y,z) (mlog(__FILE__,__LINE__), saferealloc(y,z,1))
17 | #define snrealloc(y,z,s) (mlog(__FILE__,__LINE__), saferealloc(y,z,s))
18 | #define sfree(z) (mlog(__FILE__,__LINE__), safefree(z))
19 | void mlog(char *, int);
20 | #else
21 | #define smalloc(z) safemalloc(z,1)
22 | #define snmalloc safemalloc
23 | #define srealloc(y,z) saferealloc(y,z,1)
24 | #define snrealloc saferealloc
25 | #define sfree safefree
26 | #endif
27 |
28 | void *safemalloc(size_t, size_t);
29 | void *saferealloc(void *, size_t, size_t);
30 | void safefree(void *);
31 |
32 | /*
33 | * Direct use of smalloc within the code should be avoided where
34 | * possible, in favour of these type-casting macros which ensure
35 | * you don't mistakenly allocate enough space for one sort of
36 | * structure and assign it to a different sort of pointer.
37 | *
38 | * The nasty trick in sresize with sizeof arranges for the compiler,
39 | * in passing, to type-check the expression ((type *)0 == (ptr)), i.e.
40 | * to type-check that the input pointer is a pointer to the correct
41 | * type. The construction sizeof(stuff) ? (b) : (b) looks like a
42 | * violation of the first principle of safe macros, but in fact it's
43 | * OK - although it _expands_ the macro parameter more than once, it
44 | * only _evaluates_ it once, so it's still side-effect safe.
45 | */
46 | #define snew(type) ((type *)snmalloc(1, sizeof(type)))
47 | #define snewn(n, type) ((type *)snmalloc((n), sizeof(type)))
48 | #define sresize(ptr, n, type) \
49 | ((type *)snrealloc(sizeof((type *)0 == (ptr)) ? (ptr) : (ptr), \
50 | (n), sizeof(type)))
51 |
52 | /*
53 | * For cases where you want to allocate a struct plus a subsidiary
54 | * data buffer in one step, this macro lets you add a constant to the
55 | * amount malloced.
56 | *
57 | * Since the return value is already cast to the struct type, a
58 | * pointer to that many bytes of extra data can be conveniently
59 | * obtained by simply adding 1 to the returned pointer!
60 | * snew_plus_get_aux is a handy macro that does that and casts the
61 | * result to void *, so you can assign it straight to wherever you
62 | * wanted it.
63 | */
64 | #define snew_plus(type, extra) ((type *)snmalloc(1, sizeof(type) + (extra)))
65 | #define snew_plus_get_aux(ptr) ((void *)((ptr) + 1))
66 |
67 | #endif
68 |
--------------------------------------------------------------------------------
/charset/xenc.c:
--------------------------------------------------------------------------------
1 | /*
2 | * xenc.c - translate our internal character set codes to and from
3 | * X11 character encoding names.
4 | *
5 | */
6 |
7 | #include
8 | #include "charset.h"
9 | #include "internal.h"
10 |
11 | static const struct {
12 | const char *name;
13 | int charset;
14 | } xencs[] = {
15 | /*
16 | * Officially registered encoding names. This list is derived
17 | * from the font encodings section of
18 | *
19 | * http://ftp.x.org/pub/DOCS/registry
20 | *
21 | * Where multiple encoding names map to the same encoding id
22 | * (such as iso8859-15 and fcd8859-15), the first is considered
23 | * canonical and will be returned when translating the id to a
24 | * string.
25 | */
26 | { "iso8859-1", CS_ISO8859_1 },
27 | { "iso8859-2", CS_ISO8859_2 },
28 | { "iso8859-3", CS_ISO8859_3 },
29 | { "iso8859-4", CS_ISO8859_4 },
30 | { "iso8859-5", CS_ISO8859_5 },
31 | { "iso8859-6", CS_ISO8859_6 },
32 | { "iso8859-7", CS_ISO8859_7 },
33 | { "iso8859-8", CS_ISO8859_8 },
34 | { "iso8859-9", CS_ISO8859_9 },
35 | { "iso8859-10", CS_ISO8859_10 },
36 | { "iso8859-13", CS_ISO8859_13 },
37 | { "iso8859-14", CS_ISO8859_14 },
38 | { "iso8859-15", CS_ISO8859_15 },
39 | { "fcd8859-15", CS_ISO8859_15 },
40 | { "hp-roman8", CS_HP_ROMAN8 },
41 | { "koi8-r", CS_KOI8_R },
42 | /*
43 | * Unofficial encoding names found in the wild.
44 | */
45 | { "iso8859-16", CS_ISO8859_16 },
46 | { "koi8-u", CS_KOI8_U },
47 | { "ibm-cp437", CS_CP437 },
48 | { "ibm-cp850", CS_CP850 },
49 | { "ibm-cp852", CS_CP852 },
50 | { "ibm-cp866", CS_CP866 },
51 | { "microsoft-cp1250", CS_CP1250 },
52 | { "microsoft-cp1251", CS_CP1251 },
53 | { "microsoft-cp1252", CS_CP1252 },
54 | { "microsoft-cp1253", CS_CP1253 },
55 | { "microsoft-cp1254", CS_CP1254 },
56 | { "microsoft-cp1255", CS_CP1255 },
57 | { "microsoft-cp1256", CS_CP1256 },
58 | { "microsoft-cp1257", CS_CP1257 },
59 | { "microsoft-cp1258", CS_CP1258 },
60 | { "mac-roman", CS_MAC_ROMAN },
61 | { "viscii1.1-1", CS_VISCII },
62 | { "viscii1-1", CS_VISCII },
63 | };
64 |
65 | const char *charset_to_xenc(int charset)
66 | {
67 | int i;
68 |
69 | for (i = 0; i < (int)lenof(xencs); i++)
70 | if (charset == xencs[i].charset)
71 | return xencs[i].name;
72 |
73 | return NULL; /* not found */
74 | }
75 |
76 | int charset_from_xenc(const char *name)
77 | {
78 | int i;
79 |
80 | for (i = 0; i < (int)lenof(xencs); i++) {
81 | const char *p, *q;
82 | p = name;
83 | q = xencs[i].name;
84 | while (*p || *q) {
85 | if (tolower((unsigned char)*p) != tolower((unsigned char)*q))
86 | break;
87 | p++; q++;
88 | }
89 | if (!*p && !*q)
90 | return xencs[i].charset;
91 | }
92 |
93 | return CS_NONE; /* not found */
94 | }
95 |
--------------------------------------------------------------------------------
/ssh1censor.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Packet-censoring code for SSH-1, used to identify sensitive fields
3 | * like passwords so that the logging system can avoid writing them
4 | * into log files.
5 | */
6 |
7 | #include
8 |
9 | #include "putty.h"
10 | #include "ssh.h"
11 |
12 | int ssh1_censor_packet(
13 | const PacketLogSettings *pls, int type, int sender_is_client,
14 | ptrlen pkt, logblank_t *blanks)
15 | {
16 | int nblanks = 0;
17 | ptrlen str;
18 | BinarySource src[1];
19 |
20 | BinarySource_BARE_INIT(src, pkt.ptr, pkt.len);
21 |
22 | if (pls->omit_data &&
23 | (type == SSH1_SMSG_STDOUT_DATA ||
24 | type == SSH1_SMSG_STDERR_DATA ||
25 | type == SSH1_CMSG_STDIN_DATA ||
26 | type == SSH1_MSG_CHANNEL_DATA)) {
27 | /* "Session data" packets - omit the data string. */
28 | if (type == SSH1_MSG_CHANNEL_DATA)
29 | get_uint32(src); /* skip channel id */
30 | str = get_string(src);
31 | if (!get_err(src)) {
32 | assert(nblanks < MAX_BLANKS);
33 | blanks[nblanks].offset = src->pos - str.len;
34 | blanks[nblanks].type = PKTLOG_OMIT;
35 | blanks[nblanks].len = str.len;
36 | nblanks++;
37 | }
38 | }
39 |
40 | if (sender_is_client && pls->omit_passwords) {
41 | if (type == SSH1_CMSG_AUTH_PASSWORD ||
42 | type == SSH1_CMSG_AUTH_TIS_RESPONSE ||
43 | type == SSH1_CMSG_AUTH_CCARD_RESPONSE) {
44 | /* If this is a password or similar packet, blank the
45 | * password(s). */
46 | assert(nblanks < MAX_BLANKS);
47 | blanks[nblanks].offset = 0;
48 | blanks[nblanks].len = pkt.len;
49 | blanks[nblanks].type = PKTLOG_BLANK;
50 | nblanks++;
51 | } else if (type == SSH1_CMSG_X11_REQUEST_FORWARDING) {
52 | /*
53 | * If this is an X forwarding request packet, blank the
54 | * fake auth data.
55 | *
56 | * Note that while we blank the X authentication data
57 | * here, we don't take any special action to blank the
58 | * start of an X11 channel, so using MIT-MAGIC-COOKIE-1
59 | * and actually opening an X connection without having
60 | * session blanking enabled is likely to leak your cookie
61 | * into the log.
62 | */
63 | get_string(src); /* skip protocol name */
64 | str = get_string(src);
65 | if (!get_err(src)) {
66 | assert(nblanks < MAX_BLANKS);
67 | blanks[nblanks].offset = src->pos - str.len;
68 | blanks[nblanks].type = PKTLOG_BLANK;
69 | blanks[nblanks].len = str.len;
70 | nblanks++;
71 | }
72 | }
73 | }
74 |
75 | return nblanks;
76 | }
77 |
--------------------------------------------------------------------------------
/unix/putty.bundle:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
38 | ${env:PUTTY_GTK_PREFIX_FROM_MAKEFILE}
39 |
40 |
41 | gtk+-3.0
42 |
48 | ${project}/../osxlaunch
49 |
50 |
51 | ${project}/putty.plist
52 |
53 |
54 | ${project}/../puttyapp
55 |
56 |
57 |
58 | ${prefix}/lib/${gtkdir}/${pkg:${gtk}:gtk_binary_version}/immodules/*.so
59 |
60 |
61 |
62 | ${prefix}/lib/${gtkdir}/${pkg:${gtk}:gtk_binary_version}/printbackends/*.so
63 |
64 |
65 |
66 | ${prefix}/share/themes/Adwaita
67 |
68 |
69 |
70 | ${project}/../icons/PuTTY.icns
71 |
72 |
73 |
74 | Adwaita
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/sessprep.c:
--------------------------------------------------------------------------------
1 | /*
2 | * sessprep.c: centralise some preprocessing done on Conf objects
3 | * before launching them.
4 | */
5 |
6 | #include "putty.h"
7 |
8 | void prepare_session(Conf *conf)
9 | {
10 | char *hostbuf = dupstr(conf_get_str(conf, CONF_host));
11 | char *host = hostbuf;
12 | char *p, *q;
13 |
14 | /*
15 | * Trim leading whitespace from the hostname.
16 | */
17 | host += strspn(host, " \t");
18 |
19 | /*
20 | * See if host is of the form user@host, and separate out the
21 | * username if so.
22 | */
23 | if (host[0] != '\0') {
24 | /*
25 | * Use strrchr, in case the _username_ in turn is of the form
26 | * user@host, which has been known.
27 | */
28 | char *atsign = strrchr(host, '@');
29 | if (atsign) {
30 | *atsign = '\0';
31 | conf_set_str(conf, CONF_username, host);
32 | host = atsign + 1;
33 | }
34 | }
35 |
36 | /*
37 | * Trim a colon suffix off the hostname if it's there, and discard
38 | * the text after it.
39 | *
40 | * The exact reason why we _ignore_ this text, rather than
41 | * treating it as a port number, is unfortunately lost in the
42 | * mists of history: the commit which originally introduced this
43 | * change on 2001-05-06 was clear on _what_ it was doing but
44 | * didn't bother to explain _why_. But I [SGT, 2017-12-03] suspect
45 | * it has to do with priority order: what should a saved session
46 | * do if its CONF_host contains 'server.example.com:123' and its
47 | * CONF_port contains 456? If CONF_port contained the _default_
48 | * port number then it might be a good guess that the colon suffix
49 | * on the host name was intended to override that, but you don't
50 | * really want to get into making heuristic judgments on that
51 | * basis.
52 | *
53 | * (Then again, you could just as easily make the same argument
54 | * about whether a 'user@' prefix on the host name should override
55 | * CONF_username, which this code _does_ do. I don't have a good
56 | * answer, sadly. Both these pieces of behaviour have been around
57 | * for years and it would probably cause subtle breakage in all
58 | * sorts of long-forgotten scripting to go changing things around
59 | * now.)
60 | *
61 | * In order to protect unbracketed IPv6 address literals against
62 | * this treatment, we do not make this change at all if there's
63 | * _more_ than one (un-IPv6-bracketed) colon.
64 | */
65 | p = host_strchr(host, ':');
66 | if (p && p != host_strrchr(host, ':')) {
67 | *p = '\0';
68 | }
69 |
70 | /*
71 | * Remove any remaining whitespace.
72 | */
73 | p = hostbuf;
74 | q = host;
75 | while (*q) {
76 | if (*q != ' ' && *q != '\t')
77 | *p++ = *q;
78 | q++;
79 | }
80 | *p = '\0';
81 |
82 | conf_set_str(conf, CONF_host, hostbuf);
83 | sfree(hostbuf);
84 | }
85 |
--------------------------------------------------------------------------------
/rdb/ITU-T-T.416-P41.txt:
--------------------------------------------------------------------------------
1 |
2 | A parameter substring for values 38 or 48 may be divided by one or more
3 | separators (03/10) into parameter elements, denoted as Pe. The format
4 | of such a parameter sub-string is indicated as:
5 |
6 | Pe : P ...
7 |
8 | Each parameter element consists of zero, one or more bit combinations from
9 | 03/00 to 03/09, representing the digits 0 to 9. An empty parameter element
10 | represents a default value for this parameter element. Empty parameter
11 | elements at the end of the parameter substring need not be included.
12 | The first parameter element indicates a choice between:
13 |
14 | 0 implementation defined (only applicable for the
15 | character foreground colour)
16 | 1 transparent;
17 | 2 direct colour in RGB space;
18 | 3 direct colour in CMY space;
19 | 4 direct colour in CMYK space;
20 | 5 indexed colour.
21 |
22 | If the first parameter has the value 0 or 1, there are no additional
23 | parameter elements.
24 |
25 | If the first parameter element has the value 5, then there is a second
26 | parameter element specifying the index into the colour table given by
27 | the attribute “content colour table” applying to the object with
28 | which the content is associated.
29 |
30 | If the first parameter element has the value 2, 3, or 4, the second
31 | parameter element specifies a colour space identifier referring to a
32 | colour space definition in the document profile.
33 |
34 | If the first parameter element has the value 2, the parameter elements
35 | 3, 4, and 5, are three integers for red, green, and blue colour
36 | components. Parameter 6 has no meaning.
37 |
38 | If the first parameter has the value 3, the parameter elements 3,
39 | 4, and 5 and three integers for cyan, magenta, and yellow colour
40 | components. Parameter 6 has no meaning.
41 |
42 | If the first parameter has the value 4, the parameter elements 3, 4,
43 | 5, and 6, are four integers for cyan, magenta, yellow, and black colour
44 | components.
45 |
46 | If the first parameter element has the value 2, 3, or 4, the parameter
47 | element 7 may be used to specify a tolerance value (an integer) and the
48 | parameter element 8 may be used to specify a colour space associated
49 | with the tolerance (0 for CIELUV, 1 for CIELAB).
50 |
51 | NOTE 3 – The “colour space id” component will refer
52 | to the applicable colour space description in the document
53 | profile which may contain colour scaling data that describe
54 | the scale and offset to be applied to the specified colour
55 | components in the character content. Appropriate use of
56 | scaling and offsets may be required to map all colour values
57 | required into the integer encoding space provided. This may
58 | be particularly important if concatenated content requires the
59 | insertion of such SGR sequences by the content layout process.
60 |
61 |
62 | ITU-T Rec. T.416 (1993 E) Page:41
63 |
--------------------------------------------------------------------------------
/ldiscucs.c:
--------------------------------------------------------------------------------
1 | /*
2 | * ldisc.c: PuTTY line discipline. Sits between the input coming
3 | * from keypresses in the window, and the output channel leading to
4 | * the back end. Implements echo and/or local line editing,
5 | * depending on what's currently configured.
6 | */
7 |
8 | #include
9 | #include
10 |
11 | #include "putty.h"
12 | #include "terminal.h"
13 | #include "ldisc.h"
14 |
15 | void lpage_send(void *handle,
16 | int codepage, const char *buf, int len, int interactive)
17 | {
18 | Ldisc ldisc = (Ldisc)handle;
19 | wchar_t *widebuffer = 0;
20 | int widesize = 0;
21 | int wclen;
22 |
23 | if (codepage < 0) {
24 | ldisc_send(ldisc, buf, len, interactive);
25 | return;
26 | }
27 |
28 | widesize = len * 2;
29 | widebuffer = snewn(widesize, wchar_t);
30 |
31 | wclen = mb_to_wc(codepage, 0, buf, len, widebuffer, widesize);
32 | luni_send(ldisc, widebuffer, wclen, interactive);
33 |
34 | sfree(widebuffer);
35 | }
36 |
37 | void luni_send(void *handle, const wchar_t *widebuf, int len, int interactive)
38 | {
39 | Ldisc ldisc = (Ldisc)handle;
40 | char *linebuffer;
41 | int linesize;
42 | int i;
43 | char *p;
44 |
45 | /* UTF-8 is now upto 4 bytes/char as is GB18030. Largest windows MBCS
46 | * is 5 bytes/character */
47 | linesize = len * 5;
48 | linebuffer = snewn(linesize, char);
49 |
50 | if (in_utf(ldisc->term)) {
51 | /* UTF is a simple algorithm */
52 | for (p = linebuffer, i = 0; i < len; i++) {
53 | unsigned long ch = widebuf[i];
54 |
55 | if (IS_SURROGATE(ch)) {
56 | #ifdef PLATFORM_IS_UTF16
57 | if (i+1 < len) {
58 | unsigned long ch2 = widebuf[i+1];
59 | if (IS_SURROGATE_PAIR(ch, ch2)) {
60 | ch = FROM_SURROGATES(ch, ch2);
61 | i++;
62 | }
63 | } else
64 | #endif
65 | {
66 | /* Unrecognised UTF-16 sequence */
67 | ch = '.';
68 | }
69 | }
70 |
71 | if (ch < 0x80) {
72 | *p++ = (char) (ch);
73 | } else if (ch < 0x800) {
74 | *p++ = (char) (0xC0 | (ch >> 6));
75 | *p++ = (char) (0x80 | (ch & 0x3F));
76 | } else if (ch < 0x10000) {
77 | *p++ = (char) (0xE0 | (ch >> 12));
78 | *p++ = (char) (0x80 | ((ch >> 6) & 0x3F));
79 | *p++ = (char) (0x80 | (ch & 0x3F));
80 | } else {
81 | *p++ = (char) (0xF0 | (ch >> 18));
82 | *p++ = (char) (0x80 | ((ch >> 12) & 0x3F));
83 | *p++ = (char) (0x80 | ((ch >> 6) & 0x3F));
84 | *p++ = (char) (0x80 | (ch & 0x3F));
85 | }
86 | }
87 | } else {
88 | int rv;
89 | if (ldisc->term->ucsdata->line_codepage == CP_UTF8) {
90 | rv = wc_to_mb(CP_ISO8859_1, 0, widebuf, len,
91 | linebuffer, linesize, NULL, NULL, ldisc->term->ucsdata);
92 | } else
93 | rv = wc_to_mb(ldisc->term->ucsdata->line_codepage, 0, widebuf, len,
94 | linebuffer, linesize, NULL, NULL, ldisc->term->ucsdata);
95 | if (rv >= 0)
96 | p = linebuffer + rv;
97 | else
98 | p = linebuffer;
99 | }
100 | if (p > linebuffer)
101 | ldisc_send(ldisc, linebuffer, p - linebuffer, interactive);
102 |
103 | sfree(linebuffer);
104 | }
105 |
--------------------------------------------------------------------------------
/rdb/Missing-patches/rdb24bit/0008-Add-flag-to-reduce-scrollback-memory-consumption.patch:
--------------------------------------------------------------------------------
1 | From 512ed1518808fceede2afcc596c25cde7d6f4faf Mon Sep 17 00:00:00 2001
2 | From: Robert de Bath
3 | Date: Sun, 20 Dec 2015 20:29:06 +0000
4 | Subject: [PATCH 08/71] Add flag to reduce scrollback memory consumption
5 |
6 | when there are no combining characters.
7 | ---
8 | putty.h | 1 +
9 | terminal.c | 22 ++++++++++++++++++----
10 | 2 files changed, 19 insertions(+), 4 deletions(-)
11 |
12 | diff --git a/putty.h b/putty.h
13 | index e622e80..de831c5 100644
14 | --- a/putty.h
15 | +++ b/putty.h
16 | @@ -72,6 +72,7 @@ typedef struct terminal_tag Terminal;
17 | #define LATTR_TOP 0x00000002UL
18 | #define LATTR_BOT 0x00000003UL
19 | #define LATTR_MODE 0x00000003UL
20 | +#define LATTR_HASCC 0x00000004UL
21 | #define LATTR_HASTC 0x00000008UL
22 | #define LATTR_WRAPPED 0x00000010UL /* this line wraps to next */
23 | #define LATTR_WRAPPED2 0x00000020UL /* with WRAPPED: CJK wide character
24 | diff --git a/terminal.c b/terminal.c
25 | index d938be0..66552ce 100644
26 | --- a/terminal.c
27 | +++ b/terminal.c
28 | @@ -673,7 +673,7 @@ static unsigned char *compressline(termline *ldata)
29 | {
30 | struct buf buffer = { NULL, 0, 0 }, *b = &buffer;
31 | #if !defined(COMBI_COLOUR) && !defined(THIN_TC24)
32 | - int has_tc = 0;
33 | + int has_tc = 0, has_cc = 0;
34 | {
35 | int i, c = ldata->cols;
36 | for(i=0; ichars[i].cc_next) {
43 | + has_cc = 1;
44 | + break;
45 | + }
46 | + }
47 | }
48 | #endif
49 |
50 | @@ -704,7 +710,7 @@ static unsigned char *compressline(termline *ldata)
51 | */
52 | {
53 | #if !defined(COMBI_COLOUR) && !defined(THIN_TC24)
54 | - int n = ldata->lattr | (has_tc?LATTR_HASTC:0);
55 | + int n = ldata->lattr | (has_tc?LATTR_HASTC:0) | (has_cc?LATTR_HASCC:0);
56 | #else
57 | int n = ldata->lattr;
58 | #endif
59 | @@ -730,10 +736,13 @@ static unsigned char *compressline(termline *ldata)
60 | */
61 | makerle(b, ldata, makeliteral_chr);
62 | makerle(b, ldata, makeliteral_attr);
63 | - makerle(b, ldata, makeliteral_cc);
64 | #if !defined(COMBI_COLOUR) && !defined(THIN_TC24)
65 | + if (has_cc)
66 | + makerle(b, ldata, makeliteral_cc);
67 | if (has_tc)
68 | makerle(b, ldata, makeliteral_t416);
69 | +#else
70 | + makerle(b, ldata, makeliteral_cc);
71 | #endif
72 |
73 | /*
74 | @@ -985,12 +994,17 @@ static termline *decompressline(unsigned char *data, int *bytes_used)
75 | */
76 | readrle(b, ldata, readliteral_chr);
77 | readrle(b, ldata, readliteral_attr);
78 | - readrle(b, ldata, readliteral_cc);
79 | #if !defined(COMBI_COLOUR) && !defined(THIN_TC24)
80 | + if (ldata->lattr & LATTR_HASCC) {
81 | + ldata->lattr &= ~LATTR_HASCC;
82 | + readrle(b, ldata, readliteral_cc);
83 | + }
84 | if (ldata->lattr & LATTR_HASTC) {
85 | ldata->lattr &= ~LATTR_HASTC;
86 | readrle(b, ldata, readliteral_t416);
87 | }
88 | +#else
89 | + readrle(b, ldata, readliteral_cc);
90 | #endif
91 |
92 | /* Return the number of bytes read, for diagnostic purposes. */
93 | --
94 | 2.1.4
95 |
96 |
--------------------------------------------------------------------------------
/charset/sbcsgen.pl:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env perl -w
2 |
3 | # This script generates sbcsdat.c (the data for all the SBCSes) from its
4 | # source form sbcs.dat.
5 |
6 | $infile = "sbcs.dat";
7 | $outfile = "sbcsdat.c";
8 |
9 | open FOO, $infile;
10 | open BAR, ">$outfile";
11 | select BAR;
12 |
13 | print "/*\n";
14 | print " * sbcsdat.c - data definitions for single-byte character sets.\n";
15 | print " *\n";
16 | print " * Generated by sbcsgen.pl from sbcs.dat.\n";
17 | print " * You should edit those files rather than editing this one.\n";
18 | print " */\n";
19 | print "\n";
20 | print "#ifndef ENUM_CHARSETS\n";
21 | print "\n";
22 | print "#include \"charset.h\"\n";
23 | print "#include \"internal.h\"\n";
24 | print "\n";
25 |
26 | my $charsetname = undef;
27 | my @vals = ();
28 |
29 | my @charsetnames = ();
30 | my @sortpriority = ();
31 |
32 | while () {
33 | chomp;
34 | if (/^charset (.*)$/) {
35 | $charsetname = $1;
36 | @vals = ();
37 | @sortpriority = map { 0 } 0..255;
38 | } elsif (/^sortpriority ([^-]*)-([^-]*) (.*)$/) {
39 | for ($i = hex $1; $i <= hex $2; $i++) {
40 | $sortpriority[$i] += $3;
41 | }
42 | } elsif (/^[0-9a-fA-FX]/) {
43 | push @vals, map { $_ eq "XXXX" ? -1 : hex $_ } split / +/, $_;
44 | if (scalar @vals > 256) {
45 | die "$infile:$.: charset $charsetname has more than 256 values\n";
46 | } elsif (scalar @vals == 256) {
47 | &outcharset($charsetname, \@vals, \@sortpriority);
48 | push @charsetnames, $charsetname;
49 | $charsetname = undef;
50 | @vals = ();
51 | @sortpriority = map { 0 } 0..255;
52 | }
53 | }
54 | }
55 |
56 | print "#else /* ENUM_CHARSETS */\n";
57 | print "\n";
58 |
59 | foreach $i (@charsetnames) {
60 | print "ENUM_CHARSET($i)\n";
61 | }
62 |
63 | print "\n";
64 | print "#endif /* ENUM_CHARSETS */\n";
65 |
66 | sub outcharset($$$) {
67 | my ($name, $vals, $sortpriority) = @_;
68 | my ($prefix, $i, @sorted);
69 |
70 | print "static const sbcs_data data_$name = {\n";
71 | print " {\n";
72 | $prefix = " ";
73 | @sorted = ();
74 | for ($i = 0; $i < 256; $i++) {
75 | if ($vals->[$i] < 0) {
76 | printf "%sERROR ", $prefix;
77 | } else {
78 | printf "%s0x%04x", $prefix, $vals->[$i];
79 | die "ooh? $i\n" unless defined $sortpriority->[$i];
80 | push @sorted, [$i, $vals->[$i], 0+$sortpriority->[$i]];
81 | }
82 | if ($i % 8 == 7) {
83 | $prefix = ",\n ";
84 | } else {
85 | $prefix = ", ";
86 | }
87 | }
88 | print "\n },\n {\n";
89 | @sorted = sort { ($a->[1] == $b->[1] ?
90 | $b->[2] <=> $a->[2] :
91 | $a->[1] <=> $b->[1]) ||
92 | $a->[0] <=> $b->[0] } @sorted;
93 | $prefix = " ";
94 | $uval = -1;
95 | for ($i = $j = 0; $i < scalar @sorted; $i++) {
96 | next if ($uval == $sorted[$i]->[1]); # low-priority alternative
97 | $uval = $sorted[$i]->[1];
98 | printf "%s0x%02x", $prefix, $sorted[$i]->[0];
99 | if ($j % 8 == 7) {
100 | $prefix = ",\n ";
101 | } else {
102 | $prefix = ", ";
103 | }
104 | $j++;
105 | }
106 | printf "\n },\n %d\n", $j;
107 | print "};\n";
108 | print "const charset_spec charset_$name = {\n" .
109 | " $name, read_sbcs, write_sbcs, &data_$name\n};\n\n";
110 | }
111 |
--------------------------------------------------------------------------------
/licence.pl:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env perl -w
2 |
3 | # This script generates licence.h (containing the PuTTY licence in the
4 | # form of macros expanding to C string literals) from the LICENCE
5 | # master file. It also regenerates the licence-related Halibut input
6 | # files.
7 |
8 | use File::Basename;
9 |
10 | # Read the input file.
11 | $infile = "LICENCE";
12 | open my $in, $infile or die "$infile: open: $!\n";
13 | my @lines = ();
14 | while (<$in>) {
15 | chomp;
16 | push @lines, $_;
17 | }
18 | close $in;
19 |
20 | # Format into paragraphs.
21 | my @paras = ();
22 | my $para = undef;
23 | for my $line (@lines) {
24 | if ($line eq "") {
25 | $para = undef;
26 | } elsif (!defined $para) {
27 | push @paras, $line;
28 | $para = \$paras[$#paras];
29 | } else {
30 | $$para .= " " . $line;
31 | }
32 | }
33 |
34 | # Get the copyright years and short form of copyright holder.
35 | die "bad format of first paragraph\n"
36 | unless $paras[0] =~ m!copyright ([^\.]*)\.!i;
37 | $shortdetails = $1;
38 |
39 | # Write out licence.h.
40 |
41 | $outfile = "licence.h";
42 | open my $out, ">", $outfile or die "$outfile: open: $!\n";
43 | select $out;
44 |
45 | print "/*\n";
46 | print " * $outfile - macro definitions for the PuTTY licence.\n";
47 | print " *\n";
48 | print " * Generated by @{[basename __FILE__]} from $infile.\n";
49 | print " * You should edit those files rather than editing this one.\n";
50 | print " */\n";
51 | print "\n";
52 |
53 | print "#define LICENCE_TEXT(parsep) \\\n";
54 | for my $i (0..$#paras) {
55 | my $lit = &stringlit($paras[$i]);
56 | print " parsep \\\n" if $i > 0;
57 | print " \"$lit\"";
58 | print " \\" if $i < $#paras;
59 | print "\n";
60 | }
61 | print "\n";
62 |
63 | printf "#define SHORT_COPYRIGHT_DETAILS \"%s\"\n", &stringlit($shortdetails);
64 |
65 | sub stringlit {
66 | my ($lit) = @_;
67 | $lit =~ s!\\!\\\\!g;
68 | $lit =~ s!"!\\"!g;
69 | return $lit;
70 | }
71 |
72 | close $out;
73 |
74 | # Write out doc/licence.but.
75 |
76 | $outfile = "doc/licence.but";
77 | open $out, ">", $outfile or die "$outfile: open: $!\n";
78 | select $out;
79 |
80 | print "\\# Generated by @{[basename __FILE__]} from $infile.\n";
81 | print "\\# You should edit those files rather than editing this one.\n\n";
82 |
83 | print "\\A{licence} PuTTY \\ii{Licence}\n\n";
84 |
85 | for my $i (0..$#paras) {
86 | my $para = &halibutescape($paras[$i]);
87 | if ($i == 0) {
88 | $para =~ s!copyright!\\i{copyright}!; # index term in paragraph 1
89 | }
90 | print "$para\n\n";
91 | }
92 |
93 | close $out;
94 |
95 | # And write out doc/copy.but, which defines a macro used in the manual
96 | # preamble blurb.
97 |
98 | $outfile = "doc/copy.but";
99 | open $out, ">", $outfile or die "$outfile: open: $!\n";
100 | select $out;
101 |
102 | print "\\# Generated by @{[basename __FILE__]} from $infile.\n";
103 | print "\\# You should edit those files rather than editing this one.\n\n";
104 |
105 | printf "\\define{shortcopyrightdetails} %s\n\n",
106 | &halibutescape($shortdetails);
107 |
108 | close $out;
109 |
110 | sub halibutescape {
111 | my ($text) = @_;
112 | $text =~ s![\\{}]!\\$&!g; # Halibut escaping
113 | $text =~ s!"([^"]*)"!\\q{$1}!g; # convert quoted strings to \q{}
114 | return $text;
115 | }
116 |
--------------------------------------------------------------------------------
/unix/uxsel.c:
--------------------------------------------------------------------------------
1 | /*
2 | * uxsel.c
3 | *
4 | * This module is a sort of all-purpose interchange for file
5 | * descriptors. At one end it talks to uxnet.c and pty.c and
6 | * anything else which might have one or more fds that need
7 | * select()-type things doing to them during an extended program
8 | * run; at the other end it talks to pterm.c or uxplink.c or
9 | * anything else which might have its own means of actually doing
10 | * those select()-type things.
11 | */
12 |
13 | #include
14 |
15 | #include "putty.h"
16 | #include "tree234.h"
17 |
18 | struct fd {
19 | int fd;
20 | int rwx; /* 4=except 2=write 1=read */
21 | uxsel_callback_fn callback;
22 | uxsel_id *id; /* for uxsel_input_remove */
23 | };
24 |
25 | static tree234 *fds;
26 |
27 | static int uxsel_fd_cmp(void *av, void *bv)
28 | {
29 | struct fd *a = (struct fd *)av;
30 | struct fd *b = (struct fd *)bv;
31 | if (a->fd < b->fd)
32 | return -1;
33 | if (a->fd > b->fd)
34 | return +1;
35 | return 0;
36 | }
37 | static int uxsel_fd_findcmp(void *av, void *bv)
38 | {
39 | int *a = (int *)av;
40 | struct fd *b = (struct fd *)bv;
41 | if (*a < b->fd)
42 | return -1;
43 | if (*a > b->fd)
44 | return +1;
45 | return 0;
46 | }
47 |
48 | void uxsel_init(void)
49 | {
50 | fds = newtree234(uxsel_fd_cmp);
51 | }
52 |
53 | /*
54 | * Here is the interface to fd-supplying modules. They supply an
55 | * fd, a set of read/write/execute states, and a callback function
56 | * for when the fd satisfies one of those states. Repeated calls to
57 | * uxsel_set on the same fd are perfectly legal and serve to change
58 | * the rwx state (typically you only want to select an fd for
59 | * writing when you actually have pending data you want to write to
60 | * it!).
61 | */
62 |
63 | void uxsel_set(int fd, int rwx, uxsel_callback_fn callback)
64 | {
65 | struct fd *newfd;
66 |
67 | assert(fd >= 0);
68 |
69 | uxsel_del(fd);
70 |
71 | if (rwx) {
72 | newfd = snew(struct fd);
73 | newfd->fd = fd;
74 | newfd->rwx = rwx;
75 | newfd->callback = callback;
76 | newfd->id = uxsel_input_add(fd, rwx);
77 | add234(fds, newfd);
78 | }
79 | }
80 |
81 | void uxsel_del(int fd)
82 | {
83 | struct fd *oldfd = find234(fds, &fd, uxsel_fd_findcmp);
84 | if (oldfd) {
85 | if (oldfd->id)
86 | uxsel_input_remove(oldfd->id);
87 | del234(fds, oldfd);
88 | sfree(oldfd);
89 | }
90 | }
91 |
92 | /*
93 | * And here is the interface to select-functionality-supplying
94 | * modules.
95 | */
96 |
97 | int next_fd(int *state, int *rwx)
98 | {
99 | struct fd *fd;
100 | fd = index234(fds, (*state)++);
101 | if (fd) {
102 | *rwx = fd->rwx;
103 | return fd->fd;
104 | } else
105 | return -1;
106 | }
107 |
108 | int first_fd(int *state, int *rwx)
109 | {
110 | *state = 0;
111 | return next_fd(state, rwx);
112 | }
113 |
114 | void select_result(int fd, int event)
115 | {
116 | struct fd *fdstruct = find234(fds, &fd, uxsel_fd_findcmp);
117 | /*
118 | * Apparently this can sometimes be NULL. Can't see how, but I
119 | * assume it means I need to ignore the event since it's on an
120 | * fd I've stopped being interested in. Sigh.
121 | */
122 | if (fdstruct)
123 | fdstruct->callback(fd, event);
124 | }
125 |
--------------------------------------------------------------------------------
/charset/internal.h:
--------------------------------------------------------------------------------
1 | /*
2 | * internal.h - internal header stuff for the charset library.
3 | */
4 |
5 | #ifndef charset_internal_h
6 | #define charset_internal_h
7 |
8 | /* This invariably comes in handy */
9 | #define lenof(x) ( sizeof((x)) / sizeof(*(x)) )
10 |
11 | /* This is an invalid Unicode value used to indicate an error. */
12 | #define ERROR 0xFFFFL /* Unicode value representing error */
13 |
14 | typedef struct charset_spec charset_spec;
15 | typedef struct sbcs_data sbcs_data;
16 |
17 | struct charset_spec {
18 | int charset; /* numeric identifier */
19 |
20 | /*
21 | * A function to read the character set and output Unicode
22 | * characters. The `emit' function expects to get Unicode chars
23 | * passed to it; it should be sent ERROR for any encoding error
24 | * on the input.
25 | */
26 | void (*read)(charset_spec const *charset, long int input_chr,
27 | charset_state *state,
28 | void (*emit)(void *ctx, long int output), void *emitctx);
29 | /*
30 | * A function to read Unicode characters and output in this
31 | * character set. The `emit' function expects to get byte
32 | * values passed to it; it should be sent ERROR for any
33 | * non-representable characters on the input.
34 | */
35 | void (*write)(charset_spec const *charset, long int input_chr,
36 | charset_state *state,
37 | void (*emit)(void *ctx, long int output), void *emitctx);
38 | void const *data;
39 | };
40 |
41 | /*
42 | * This is the format of `data' used by the SBCS read and write
43 | * functions; so it's the format used in all SBCS definitions.
44 | */
45 | struct sbcs_data {
46 | /*
47 | * This is a simple mapping table converting each SBCS position
48 | * to a Unicode code point. Some positions may contain ERROR,
49 | * indicating that that byte value is not defined in the SBCS
50 | * in question and its occurrence in input is an error.
51 | */
52 | unsigned long sbcs2ucs[256];
53 |
54 | /*
55 | * This lookup table is used to convert Unicode back to the
56 | * SBCS. It consists of the valid byte values in the SBCS,
57 | * sorted in order of their Unicode translation. So given a
58 | * Unicode value U, you can do a binary search on this table
59 | * using the above table as a lookup: when testing the Xth
60 | * position in this table, you branch according to whether
61 | * sbcs2ucs[ucs2sbcs[X]] is less than, greater than, or equal
62 | * to U.
63 | *
64 | * Note that since there may be fewer than 256 valid byte
65 | * values in a particular SBCS, we must supply the length of
66 | * this table as well as the contents.
67 | */
68 | unsigned char ucs2sbcs[256];
69 | int nvalid;
70 | };
71 |
72 | /*
73 | * Prototypes for internal library functions.
74 | */
75 | charset_spec const *charset_find_spec(int charset);
76 | void read_sbcs(charset_spec const *charset, long int input_chr,
77 | charset_state *state,
78 | void (*emit)(void *ctx, long int output), void *emitctx);
79 | void write_sbcs(charset_spec const *charset, long int input_chr,
80 | charset_state *state,
81 | void (*emit)(void *ctx, long int output), void *emitctx);
82 |
83 | /*
84 | * Placate compiler warning about unused parameters, of which we
85 | * expect to have some in this library.
86 | */
87 | #define UNUSEDARG(x) ( (x) = (x) )
88 |
89 | #endif /* charset_internal_h */
90 |
--------------------------------------------------------------------------------
/windows/winnpc.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Windows support module which deals with being a named-pipe client.
3 | */
4 |
5 | #include
6 | #include
7 |
8 | #define DEFINE_PLUG_METHOD_MACROS
9 | #include "tree234.h"
10 | #include "putty.h"
11 | #include "network.h"
12 | #include "proxy.h"
13 | #include "ssh.h"
14 |
15 | #if !defined NO_SECURITY
16 |
17 | #include "winsecur.h"
18 |
19 | Socket make_handle_socket(HANDLE send_H, HANDLE recv_H, HANDLE stderr_H,
20 | Plug plug, int overlapped);
21 |
22 | Socket new_named_pipe_client(const char *pipename, Plug plug)
23 | {
24 | HANDLE pipehandle;
25 | PSID usersid, pipeowner;
26 | PSECURITY_DESCRIPTOR psd;
27 | char *err;
28 | Socket ret;
29 |
30 | assert(strncmp(pipename, "\\\\.\\pipe\\", 9) == 0);
31 | assert(strchr(pipename + 9, '\\') == NULL);
32 |
33 | while (1) {
34 | pipehandle = CreateFile(pipename, GENERIC_READ | GENERIC_WRITE,
35 | 0, NULL, OPEN_EXISTING,
36 | FILE_FLAG_OVERLAPPED, NULL);
37 |
38 | if (pipehandle != INVALID_HANDLE_VALUE)
39 | break;
40 |
41 | if (GetLastError() != ERROR_PIPE_BUSY) {
42 | err = dupprintf("Unable to open named pipe '%s': %s",
43 | pipename, win_strerror(GetLastError()));
44 | ret = new_error_socket(err, plug);
45 | sfree(err);
46 | return ret;
47 | }
48 |
49 | /*
50 | * If we got ERROR_PIPE_BUSY, wait for the server to
51 | * create a new pipe instance. (Since the server is
52 | * expected to be winnps.c, which will do that immediately
53 | * after a previous connection is accepted, that shouldn't
54 | * take excessively long.)
55 | */
56 | if (!WaitNamedPipe(pipename, NMPWAIT_USE_DEFAULT_WAIT)) {
57 | err = dupprintf("Error waiting for named pipe '%s': %s",
58 | pipename, win_strerror(GetLastError()));
59 | ret = new_error_socket(err, plug);
60 | sfree(err);
61 | return ret;
62 | }
63 | }
64 |
65 | if ((usersid = get_user_sid()) == NULL) {
66 | CloseHandle(pipehandle);
67 | err = dupprintf("Unable to get user SID");
68 | ret = new_error_socket(err, plug);
69 | sfree(err);
70 | return ret;
71 | }
72 |
73 | if (p_GetSecurityInfo(pipehandle, SE_KERNEL_OBJECT,
74 | OWNER_SECURITY_INFORMATION,
75 | &pipeowner, NULL, NULL, NULL,
76 | &psd) != ERROR_SUCCESS) {
77 | err = dupprintf("Unable to get named pipe security information: %s",
78 | win_strerror(GetLastError()));
79 | ret = new_error_socket(err, plug);
80 | sfree(err);
81 | CloseHandle(pipehandle);
82 | return ret;
83 | }
84 |
85 | if (!EqualSid(pipeowner, usersid)) {
86 | err = dupprintf("Owner of named pipe '%s' is not us", pipename);
87 | ret = new_error_socket(err, plug);
88 | sfree(err);
89 | CloseHandle(pipehandle);
90 | LocalFree(psd);
91 | return ret;
92 | }
93 |
94 | LocalFree(psd);
95 |
96 | return make_handle_socket(pipehandle, pipehandle, NULL, plug, TRUE);
97 | }
98 |
99 | #endif /* !defined NO_SECURITY */
100 |
--------------------------------------------------------------------------------
/ssharcf.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Arcfour (RC4) implementation for PuTTY.
3 | *
4 | * Coded from Schneier.
5 | */
6 |
7 | #include
8 | #include "ssh.h"
9 |
10 | typedef struct {
11 | unsigned char i, j, s[256];
12 | } ArcfourContext;
13 |
14 | static void arcfour_block(void *handle, void *vblk, int len)
15 | {
16 | unsigned char *blk = (unsigned char *)vblk;
17 | ArcfourContext *ctx = (ArcfourContext *)handle;
18 | unsigned k;
19 | unsigned char tmp, i, j, *s;
20 |
21 | s = ctx->s;
22 | i = ctx->i; j = ctx->j;
23 | for (k = 0; (int)k < len; k++) {
24 | i = (i + 1) & 0xff;
25 | j = (j + s[i]) & 0xff;
26 | tmp = s[i]; s[i] = s[j]; s[j] = tmp;
27 | blk[k] ^= s[(s[i]+s[j]) & 0xff];
28 | }
29 | ctx->i = i; ctx->j = j;
30 | }
31 |
32 | static void arcfour_setkey(ArcfourContext *ctx, unsigned char const *key,
33 | unsigned keybytes)
34 | {
35 | unsigned char tmp, k[256], *s;
36 | unsigned i, j;
37 |
38 | s = ctx->s;
39 | assert(keybytes <= 256);
40 | ctx->i = ctx->j = 0;
41 | for (i = 0; i < 256; i++) {
42 | s[i] = i;
43 | k[i] = key[i % keybytes];
44 | }
45 | j = 0;
46 | for (i = 0; i < 256; i++) {
47 | j = (j + s[i] + k[i]) & 0xff;
48 | tmp = s[i]; s[i] = s[j]; s[j] = tmp;
49 | }
50 | }
51 |
52 | /* -- Interface with PuTTY -- */
53 |
54 | /*
55 | * We don't implement Arcfour in SSH-1 because it's utterly insecure in
56 | * several ways. See CERT Vulnerability Notes VU#25309, VU#665372,
57 | * and VU#565052.
58 | *
59 | * We don't implement the "arcfour" algorithm in SSH-2 because it doesn't
60 | * stir the cipher state before emitting keystream, and hence is likely
61 | * to leak data about the key.
62 | */
63 |
64 | static void *arcfour_make_context(void)
65 | {
66 | return snew(ArcfourContext);
67 | }
68 |
69 | static void arcfour_free_context(void *handle)
70 | {
71 | sfree(handle);
72 | }
73 |
74 | static void arcfour_stir(ArcfourContext *ctx)
75 | {
76 | unsigned char *junk = snewn(1536, unsigned char);
77 | memset(junk, 0, 1536);
78 | arcfour_block(ctx, junk, 1536);
79 | smemclr(junk, 1536);
80 | sfree(junk);
81 | }
82 |
83 | static void arcfour128_key(void *handle, const void *key)
84 | {
85 | ArcfourContext *ctx = (ArcfourContext *)handle;
86 | arcfour_setkey(ctx, key, 16);
87 | arcfour_stir(ctx);
88 | }
89 |
90 | static void arcfour256_key(void *handle, const void *key)
91 | {
92 | ArcfourContext *ctx = (ArcfourContext *)handle;
93 | arcfour_setkey(ctx, key, 32);
94 | arcfour_stir(ctx);
95 | }
96 |
97 | static void arcfour_iv(void *handle, const void *iv)
98 | {
99 |
100 | }
101 |
102 | const struct ssh2_cipher ssh_arcfour128_ssh2 = {
103 | arcfour_make_context, arcfour_free_context, arcfour_iv, arcfour128_key,
104 | arcfour_block, arcfour_block, NULL, NULL,
105 | "arcfour128",
106 | 1, 128, 16, 0, "Arcfour-128",
107 | NULL
108 | };
109 |
110 | const struct ssh2_cipher ssh_arcfour256_ssh2 = {
111 | arcfour_make_context, arcfour_free_context, arcfour_iv, arcfour256_key,
112 | arcfour_block, arcfour_block, NULL, NULL,
113 | "arcfour256",
114 | 1, 256, 32, 0, "Arcfour-256",
115 | NULL
116 | };
117 |
118 | static const struct ssh2_cipher *const arcfour_list[] = {
119 | &ssh_arcfour256_ssh2,
120 | &ssh_arcfour128_ssh2,
121 | };
122 |
123 | const struct ssh2_ciphers ssh2_arcfour = {
124 | sizeof(arcfour_list) / sizeof(*arcfour_list),
125 | arcfour_list
126 | };
127 |
--------------------------------------------------------------------------------
/proxy.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Network proxy abstraction in PuTTY
3 | *
4 | * A proxy layer, if necessary, wedges itself between the
5 | * network code and the higher level backend.
6 | *
7 | * Supported proxies: HTTP CONNECT, generic telnet, SOCKS 4 & 5
8 | */
9 |
10 | #ifndef PUTTY_PROXY_H
11 | #define PUTTY_PROXY_H
12 |
13 | #define PROXY_ERROR_GENERAL 8000
14 | #define PROXY_ERROR_UNEXPECTED 8001
15 |
16 | typedef struct ProxySocket ProxySocket;
17 |
18 | struct ProxySocket {
19 | const char *error;
20 |
21 | Socket sub_socket;
22 | Plug plug;
23 | SockAddr remote_addr;
24 | int remote_port;
25 |
26 | bufchain pending_output_data;
27 | bufchain pending_oob_output_data;
28 | int pending_flush;
29 | bufchain pending_input_data;
30 | int pending_eof;
31 |
32 | #define PROXY_STATE_NEW -1
33 | #define PROXY_STATE_ACTIVE 0
34 |
35 | int state; /* proxy states greater than 0 are implementation
36 | * dependent, but represent various stages/states
37 | * of the initialization/setup/negotiation with the
38 | * proxy server.
39 | */
40 | int freeze; /* should we freeze the underlying socket when
41 | * we are done with the proxy negotiation? this
42 | * simply caches the value of sk_set_frozen calls.
43 | */
44 |
45 | #define PROXY_CHANGE_NEW -1
46 | #define PROXY_CHANGE_CLOSING 0
47 | #define PROXY_CHANGE_SENT 1
48 | #define PROXY_CHANGE_RECEIVE 2
49 | #define PROXY_CHANGE_ACCEPTING 3
50 |
51 | /* something has changed (a call from the sub socket
52 | * layer into our Proxy Plug layer, or we were just
53 | * created, etc), so the proxy layer needs to handle
54 | * this change (the type of which is the second argument)
55 | * and further the proxy negotiation process.
56 | */
57 |
58 | int (*negotiate) (ProxySocket * /* this */, int /* change type */);
59 |
60 | /* current arguments of plug handlers
61 | * (for use by proxy's negotiate function)
62 | */
63 |
64 | /* closing */
65 | const char *closing_error_msg;
66 | int closing_error_code;
67 | int closing_calling_back;
68 |
69 | /* receive */
70 | int receive_urgent;
71 | char *receive_data;
72 | int receive_len;
73 |
74 | /* sent */
75 | int sent_bufsize;
76 |
77 | /* accepting */
78 | accept_fn_t accepting_constructor;
79 | accept_ctx_t accepting_ctx;
80 |
81 | /* configuration, used to look up proxy settings */
82 | Conf *conf;
83 |
84 | /* CHAP transient data */
85 | int chap_num_attributes;
86 | int chap_num_attributes_processed;
87 | int chap_current_attribute;
88 | int chap_current_datalen;
89 |
90 | const Socket_vtable *sockvt;
91 | const Plug_vtable *plugvt;
92 | };
93 |
94 | extern void proxy_activate (ProxySocket *);
95 |
96 | extern int proxy_http_negotiate (ProxySocket *, int);
97 | extern int proxy_telnet_negotiate (ProxySocket *, int);
98 | extern int proxy_socks4_negotiate (ProxySocket *, int);
99 | extern int proxy_socks5_negotiate (ProxySocket *, int);
100 |
101 | /*
102 | * This may be reused by local-command proxies on individual
103 | * platforms.
104 | */
105 | char *format_telnet_command(SockAddr addr, int port, Conf *conf);
106 |
107 | /*
108 | * These are implemented in cproxy.c or nocproxy.c, depending on
109 | * whether encrypted proxy authentication is available.
110 | */
111 | extern void proxy_socks5_offerencryptedauth(BinarySink *);
112 | extern int proxy_socks5_handlechap (ProxySocket *);
113 | extern int proxy_socks5_selectchap(ProxySocket *);
114 |
115 | #endif
116 |
--------------------------------------------------------------------------------
/contrib/gdb.py:
--------------------------------------------------------------------------------
1 | import gdb
2 | import re
3 | import gdb.printing
4 |
5 | class PuTTYBignumPrettyPrinter(gdb.printing.PrettyPrinter):
6 | "Pretty-print PuTTY's Bignum type."
7 | name = "Bignum"
8 |
9 | def __init__(self, val):
10 | super(PuTTYBignumPrettyPrinter, self).__init__(self.name)
11 | self.val = val
12 |
13 | def to_string(self):
14 | type_BignumInt = gdb.lookup_type("BignumInt")
15 | type_BignumIntPtr = type_BignumInt.pointer()
16 | BIGNUM_INT_BITS = 8 * type_BignumInt.sizeof
17 | array = self.val.cast(type_BignumIntPtr)
18 | aget = lambda i: int(array[i]) & ((1 << BIGNUM_INT_BITS)-1)
19 |
20 | try:
21 | length = aget(0)
22 | value = 0
23 | for i in range(length):
24 | value |= aget(i+1) << (BIGNUM_INT_BITS * i)
25 | return "Bignum({:#x})".format(value)
26 |
27 | except gdb.MemoryError:
28 | address = int(array)
29 | if address == 0:
30 | return "Bignum(NULL)".format(address)
31 | return "Bignum(invalid @ {:#x})".format(address)
32 |
33 | rcpp = gdb.printing.RegexpCollectionPrettyPrinter("PuTTY")
34 | rcpp.add_printer(PuTTYBignumPrettyPrinter.name, "^Bignum$",
35 | PuTTYBignumPrettyPrinter)
36 |
37 | gdb.printing.register_pretty_printer(None, rcpp)
38 |
39 | class MemDumpCommand(gdb.Command):
40 | """Print a hex+ASCII dump of object EXP.
41 |
42 | EXP must be an expression whose value resides in memory. The
43 | contents of the memory it occupies are printed in a standard hex
44 | dump format, with each line showing an offset relative to the
45 | address of EXP, then the hex byte values of the memory at that
46 | offset, and then a translation into ASCII of the same bytes (with
47 | values outside the printable ASCII range translated as '.').
48 |
49 | To dump a number of bytes from a particular address, it's useful
50 | to use the gdb expression extensions {TYPE} and @LENGTH. For
51 | example, if 'ptr' and 'len' are variables giving an address and a
52 | length in bytes, then the command
53 |
54 | memdump {char} ptr @ len
55 |
56 | will dump the range of memory described by those two variables."""
57 |
58 | def __init__(self):
59 | super(MemDumpCommand, self).__init__(
60 | "memdump", gdb.COMMAND_DATA, gdb.COMPLETE_EXPRESSION)
61 |
62 | def invoke(self, cmdline, from_tty):
63 | expr = gdb.parse_and_eval(cmdline)
64 | try:
65 | start, size = int(expr.address), expr.type.sizeof
66 | except gdb.error as e:
67 | sys.stderr.write(str(e))
68 | return
69 | except (TypeError, AttributeError):
70 | sys.stderr.write("expression must identify an object in memory")
71 | return
72 |
73 | width = 16
74 | line_ptr_type = gdb.lookup_type(
75 | "unsigned char").const().array(width).pointer()
76 |
77 | dumpaddr = 0
78 | while size > 0:
79 | line = gdb.Value(start).cast(line_ptr_type).dereference()
80 | thislinelen = min(size, width)
81 | start += thislinelen
82 | size -= thislinelen
83 |
84 | dumpline = [None, " "] + [" "] * width + [" "] + [""] * width
85 |
86 | dumpline[0] = "{:08x}".format(dumpaddr)
87 | dumpaddr += thislinelen
88 |
89 | for i in range(thislinelen):
90 | ch = int(line[i]) & 0xFF
91 | dumpline[2+i] = " {:02x}".format(ch)
92 | dumpline[3+width+i] = chr(ch) if 0x20 <= ch < 0x7F else "."
93 |
94 | sys.stdout.write("".join(dumpline) + "\n")
95 |
96 | MemDumpCommand()
97 |
--------------------------------------------------------------------------------
/rdb/pickscript:
--------------------------------------------------------------------------------
1 | set -e
2 | P=`pwd`
3 |
4 | TMP=/tmp/picker
5 | G="$TMP.git"
6 | S="$TMP.safe"
7 | rm -rf "$G" ||:
8 | rm -rf "$S" ||:
9 |
10 | mkdir "$G" "$S"
11 |
12 | cd "$G"
13 | git init
14 | git fetch "$P" origin/master:temp
15 |
16 | next_commit() {
17 | git checkout $1
18 | cp -a * "$S"/.
19 |
20 | git checkout picker
21 |
22 | rm -rf *
23 | mv "$S"/* .
24 | git add -A
25 | git commit -a --allow-empty -m "Hashes $PREV..$1"
26 |
27 | PREV="$1"
28 | }
29 |
30 | PREV=49ff9f4
31 | git checkout -f -B picker $PREV
32 |
33 | next_commit 976e778
34 | next_commit 7658b29
35 | next_commit ad994ba
36 | next_commit 1840103
37 | next_commit 097d5ff
38 | next_commit dc253b3
39 | next_commit 0afc496
40 | next_commit 1e0e962
41 | next_commit bb68baf
42 | next_commit 11eb75a
43 | next_commit e88b8d2
44 | next_commit 7524da6
45 | next_commit 0de1ac9
46 | next_commit a50da0e
47 | next_commit b62af0f
48 | next_commit 6744387
49 | next_commit 30e63c1
50 | next_commit fd7687a
51 | next_commit 82824e1
52 | next_commit b08895f
53 | next_commit 43be90e
54 | next_commit 5f6e443
55 | next_commit bea758a
56 | next_commit 342f287
57 | next_commit 13edf90
58 | next_commit 5c5ca11
59 | next_commit e162810
60 | next_commit 64ec5e0
61 | next_commit 06cf210
62 | next_commit 2496760
63 | next_commit 5a9711a
64 | next_commit e0252a4
65 | next_commit 1489299
66 | next_commit 7c2ea22
67 | next_commit 5133d2a
68 | next_commit 5bb3334
69 | next_commit 0f759e4
70 | next_commit 4df5d56
71 | next_commit 431f8db
72 | next_commit 854fae8
73 | next_commit 3c7557d
74 | next_commit 777f38e
75 | next_commit 9458377
76 | next_commit 81152e5
77 | next_commit 9a3b743
78 | next_commit 46b7cb6
79 | next_commit 291cbfc
80 | next_commit 612534a
81 | next_commit 10d3b73
82 | next_commit 1bdeff7
83 | next_commit acff0a6
84 | next_commit 675a5ba
85 | next_commit df006f3
86 | next_commit c01dff3
87 | next_commit 9f9d72e
88 | next_commit 9dd9860
89 | next_commit 48eafd6
90 | next_commit 758ac4c
91 | next_commit 323c3c7
92 | next_commit 557a99e
93 | next_commit 1f7f422
94 | next_commit 3dfb9ac
95 | next_commit d4e5b0d
96 | next_commit d61c6ca
97 | next_commit f594450
98 | next_commit 417421c
99 | next_commit 0eb3bf0
100 | next_commit 1446476
101 | next_commit eb319f9
102 | next_commit a063e52
103 | next_commit 43865aa
104 | next_commit aaeaae0
105 | next_commit 6c04165
106 | next_commit 4252cdb
107 | next_commit 8c803e7
108 | next_commit a815c3a
109 | next_commit 31c5784
110 | next_commit fbea11f
111 | next_commit 5c76a93
112 | next_commit 9c8a3cb
113 | next_commit 3a43bec
114 | next_commit e170041
115 | next_commit c445c74
116 | next_commit f7365a2
117 | next_commit 6056396
118 | next_commit 5936c55
119 | next_commit 72b659c
120 | next_commit 98c9469
121 | next_commit 7552ddb
122 | next_commit 986b8f8
123 | next_commit 07af4ed
124 | next_commit 503061e
125 | next_commit 1a009ab
126 | next_commit e3fe709
127 | next_commit f69b371
128 | next_commit 63b47ed
129 | next_commit 7707aa2
130 | next_commit c0e19ca
131 | next_commit 4f34059
132 | next_commit 19d1ad3
133 | next_commit b94a076
134 | next_commit 0629f1d
135 | next_commit 5171dcb
136 | next_commit 7924aa9
137 | next_commit 389eb4b
138 | next_commit b9cb75e
139 | next_commit f6b81af
140 | next_commit 1d20c1b
141 | next_commit 5471539
142 | next_commit af1460d
143 | next_commit 12702cb
144 | next_commit 7a5cb28
145 | next_commit 9022dcd
146 | next_commit 6627c1c
147 | next_commit fe16b57
148 | next_commit f14382c
149 | next_commit 3552f37
150 | next_commit f3230c8
151 | next_commit b003e5c
152 | next_commit 222c134
153 | next_commit a454399
154 | next_commit fa7b23c
155 | next_commit 5815d6a
156 | next_commit 5b7833c
157 | next_commit f08e2de
158 | next_commit 3e811b3
159 | next_commit 470337d
160 |
--------------------------------------------------------------------------------
/callback.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Facility for queueing callback functions to be run from the
3 | * top-level event loop after the current top-level activity finishes.
4 | */
5 |
6 | #include
7 |
8 | #include "putty.h"
9 |
10 | struct callback {
11 | struct callback *next;
12 |
13 | toplevel_callback_fn_t fn;
14 | void *ctx;
15 | };
16 |
17 | struct callback *cbcurr = NULL, *cbhead = NULL, *cbtail = NULL;
18 |
19 | toplevel_callback_notify_fn_t notify_frontend = NULL;
20 | void *frontend = NULL;
21 |
22 | void request_callback_notifications(toplevel_callback_notify_fn_t fn,
23 | void *fr)
24 | {
25 | notify_frontend = fn;
26 | frontend = fr;
27 | }
28 |
29 | static void run_idempotent_callback(void *ctx)
30 | {
31 | struct IdempotentCallback *ic = (struct IdempotentCallback *)ctx;
32 | ic->queued = FALSE;
33 | ic->fn(ic->ctx);
34 | }
35 |
36 | void queue_idempotent_callback(struct IdempotentCallback *ic)
37 | {
38 | if (ic->queued)
39 | return;
40 | ic->queued = TRUE;
41 | queue_toplevel_callback(run_idempotent_callback, ic);
42 | }
43 |
44 | void delete_callbacks_for_context(void *ctx)
45 | {
46 | struct callback *newhead, *newtail;
47 |
48 | newhead = newtail = NULL;
49 | while (cbhead) {
50 | struct callback *cb = cbhead;
51 | cbhead = cbhead->next;
52 | if (cb->ctx == ctx ||
53 | (cb->fn == run_idempotent_callback &&
54 | ((struct IdempotentCallback *)cb->ctx)->ctx == ctx)) {
55 | sfree(cb);
56 | } else {
57 | if (!newhead)
58 | newhead = cb;
59 | else
60 | newtail->next = cb;
61 |
62 | newtail = cb;
63 | }
64 | }
65 |
66 | cbhead = newhead;
67 | cbtail = newtail;
68 | }
69 |
70 | void queue_toplevel_callback(toplevel_callback_fn_t fn, void *ctx)
71 | {
72 | struct callback *cb;
73 |
74 | cb = snew(struct callback);
75 | cb->fn = fn;
76 | cb->ctx = ctx;
77 |
78 | /*
79 | * If the front end has requested notification of pending
80 | * callbacks, and we didn't already have one queued, let it know
81 | * we do have one now.
82 | *
83 | * If cbcurr is non-NULL, i.e. we are actually in the middle of
84 | * executing a callback right now, then we count that as the queue
85 | * already having been non-empty. That saves the front end getting
86 | * a constant stream of needless re-notifications if the last
87 | * callback keeps re-scheduling itself.
88 | */
89 | if (notify_frontend && !cbhead && !cbcurr)
90 | notify_frontend(frontend);
91 |
92 | if (cbtail)
93 | cbtail->next = cb;
94 | else
95 | cbhead = cb;
96 | cbtail = cb;
97 | cb->next = NULL;
98 | }
99 |
100 | int run_toplevel_callbacks(void)
101 | {
102 | int done_something = FALSE;
103 |
104 | if (cbhead) {
105 | /*
106 | * Transfer the head callback into cbcurr to indicate that
107 | * it's being executed. Then operations which transform the
108 | * queue, like delete_callbacks_for_context, can proceed as if
109 | * it's not there.
110 | */
111 | cbcurr = cbhead;
112 | cbhead = cbhead->next;
113 | if (!cbhead)
114 | cbtail = NULL;
115 |
116 | /*
117 | * Now run the callback, and then clear it out of cbcurr.
118 | */
119 | cbcurr->fn(cbcurr->ctx);
120 | sfree(cbcurr);
121 | cbcurr = NULL;
122 |
123 | done_something = TRUE;
124 | }
125 | return done_something;
126 | }
127 |
128 | int toplevel_callback_pending(void)
129 | {
130 | return cbcurr != NULL || cbhead != NULL;
131 | }
132 |
--------------------------------------------------------------------------------
/windows/winhelp.c:
--------------------------------------------------------------------------------
1 | /*
2 | * winhelp.c: centralised functions to launch Windows help files,
3 | * and to decide whether to use .HLP or .CHM help in any given
4 | * situation.
5 | */
6 |
7 | #include
8 | #include
9 | #include
10 | #include
11 |
12 | #include "putty.h"
13 |
14 | #ifndef NO_HTMLHELP
15 | #include
16 | #endif /* NO_HTMLHELP */
17 |
18 | static int requested_help;
19 | static char *help_path;
20 | static int help_has_contents;
21 | #ifndef NO_HTMLHELP
22 | DECL_WINDOWS_FUNCTION(static, HWND, HtmlHelpA, (HWND, LPCSTR, UINT, DWORD_PTR));
23 | static char *chm_path;
24 | #endif /* NO_HTMLHELP */
25 |
26 | void init_help(void)
27 | {
28 | char b[2048], *p, *q, *r;
29 | FILE *fp;
30 |
31 | GetModuleFileName(NULL, b, sizeof(b) - 1);
32 | r = b;
33 | p = strrchr(b, '\\');
34 | if (p && p >= r) r = p+1;
35 | q = strrchr(b, ':');
36 | if (q && q >= r) r = q+1;
37 | strcpy(r, PUTTY_HELP_FILE);
38 | if ( (fp = fopen(b, "r")) != NULL) {
39 | help_path = dupstr(b);
40 | fclose(fp);
41 | } else
42 | help_path = NULL;
43 | strcpy(r, PUTTY_HELP_CONTENTS);
44 | if ( (fp = fopen(b, "r")) != NULL) {
45 | help_has_contents = TRUE;
46 | fclose(fp);
47 | } else
48 | help_has_contents = FALSE;
49 |
50 | #ifndef NO_HTMLHELP
51 | strcpy(r, PUTTY_CHM_FILE);
52 | if ( (fp = fopen(b, "r")) != NULL) {
53 | chm_path = dupstr(b);
54 | fclose(fp);
55 | } else
56 | chm_path = NULL;
57 | if (chm_path) {
58 | HINSTANCE dllHH = load_system32_dll("hhctrl.ocx");
59 | GET_WINDOWS_FUNCTION(dllHH, HtmlHelpA);
60 | if (!p_HtmlHelpA) {
61 | sfree(chm_path);
62 | chm_path = NULL;
63 | if (dllHH)
64 | FreeLibrary(dllHH);
65 | }
66 | }
67 | #endif /* NO_HTMLHELP */
68 | }
69 |
70 | void shutdown_help(void)
71 | {
72 | /* Nothing to do currently.
73 | * (If we were running HTML Help single-threaded, this is where we'd
74 | * call HH_UNINITIALIZE.) */
75 | }
76 |
77 | int has_help(void)
78 | {
79 | /*
80 | * FIXME: it would be nice here to disregard help_path on
81 | * platforms that didn't have WINHLP32. But that's probably
82 | * unrealistic, since even Vista will have it if the user
83 | * specifically downloads it.
84 | */
85 | return (help_path != NULL
86 | #ifndef NO_HTMLHELP
87 | || chm_path
88 | #endif /* NO_HTMLHELP */
89 | );
90 | }
91 |
92 | void launch_help(HWND hwnd, const char *topic)
93 | {
94 | if (topic) {
95 | int colonpos = strcspn(topic, ":");
96 |
97 | #ifndef NO_HTMLHELP
98 | if (chm_path) {
99 | char *fname;
100 | assert(topic[colonpos] != '\0');
101 | fname = dupprintf("%s::/%s.html>main", chm_path,
102 | topic + colonpos + 1);
103 | p_HtmlHelpA(hwnd, fname, HH_DISPLAY_TOPIC, 0);
104 | sfree(fname);
105 | } else
106 | #endif /* NO_HTMLHELP */
107 | if (help_path) {
108 | char *cmd = dupprintf("JI(`',`%.*s')", colonpos, topic);
109 | WinHelp(hwnd, help_path, HELP_COMMAND, (ULONG_PTR)cmd);
110 | sfree(cmd);
111 | }
112 | } else {
113 | #ifndef NO_HTMLHELP
114 | if (chm_path) {
115 | p_HtmlHelpA(hwnd, chm_path, HH_DISPLAY_TOPIC, 0);
116 | } else
117 | #endif /* NO_HTMLHELP */
118 | if (help_path) {
119 | WinHelp(hwnd, help_path,
120 | help_has_contents ? HELP_FINDER : HELP_CONTENTS, 0);
121 | }
122 | }
123 | requested_help = TRUE;
124 | }
125 |
126 | void quit_help(HWND hwnd)
127 | {
128 | if (requested_help) {
129 | #ifndef NO_HTMLHELP
130 | if (chm_path) {
131 | p_HtmlHelpA(NULL, NULL, HH_CLOSE_ALL, 0);
132 | } else
133 | #endif /* NO_HTMLHELP */
134 | if (help_path) {
135 | WinHelp(hwnd, help_path, HELP_QUIT, 0);
136 | }
137 | requested_help = FALSE;
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/be_misc.c:
--------------------------------------------------------------------------------
1 | /*
2 | * be_misc.c: helper functions shared between main network backends.
3 | */
4 |
5 | #include
6 | #include
7 |
8 | #define DEFINE_PLUG_METHOD_MACROS
9 | #include "putty.h"
10 | #include "network.h"
11 |
12 | void backend_socket_log(void *frontend, int type, SockAddr addr, int port,
13 | const char *error_msg, int error_code, Conf *conf,
14 | int session_started)
15 | {
16 | char addrbuf[256], *msg;
17 |
18 | switch (type) {
19 | case 0:
20 | sk_getaddr(addr, addrbuf, lenof(addrbuf));
21 | if (sk_addr_needs_port(addr)) {
22 | msg = dupprintf("Connecting to %s port %d", addrbuf, port);
23 | } else {
24 | msg = dupprintf("Connecting to %s", addrbuf);
25 | }
26 | break;
27 | case 1:
28 | sk_getaddr(addr, addrbuf, lenof(addrbuf));
29 | msg = dupprintf("Failed to connect to %s: %s", addrbuf, error_msg);
30 | break;
31 | case 2:
32 | /* Proxy-related log messages have their own identifying
33 | * prefix already, put on by our caller. */
34 | {
35 | int len, log_to_term;
36 |
37 | /* Suffix \r\n temporarily, so we can log to the terminal. */
38 | msg = dupprintf("%s\r\n", error_msg);
39 | len = strlen(msg);
40 | assert(len >= 2);
41 |
42 | log_to_term = conf_get_int(conf, CONF_proxy_log_to_term);
43 | if (log_to_term == AUTO)
44 | log_to_term = session_started ? FORCE_OFF : FORCE_ON;
45 | if (log_to_term == FORCE_ON)
46 | from_backend(frontend, TRUE, msg, len);
47 |
48 | msg[len-2] = '\0'; /* remove the \r\n again */
49 | }
50 | break;
51 | default:
52 | msg = NULL; /* shouldn't happen, but placate optimiser */
53 | break;
54 | }
55 |
56 | if (msg) {
57 | logevent(frontend, msg);
58 | sfree(msg);
59 | }
60 | }
61 |
62 | void log_proxy_stderr(Plug plug, bufchain *buf, const void *vdata, int len)
63 | {
64 | const char *data = (const char *)vdata;
65 | int pos = 0;
66 | int msglen;
67 | const char *nlpos;
68 | char *msg, *fullmsg;
69 |
70 | /*
71 | * This helper function allows us to collect the data written to a
72 | * local proxy command's standard error in whatever size chunks we
73 | * happen to get from its pipe, and whenever we have a complete
74 | * line, we pass it to plug_log.
75 | *
76 | * Prerequisites: a plug to log to, and a bufchain stored
77 | * somewhere to collect the data in.
78 | */
79 |
80 | while (pos < len && (nlpos = memchr(data+pos, '\n', len-pos)) != NULL) {
81 | /*
82 | * Found a newline in the current input buffer. Append it to
83 | * the bufchain (which may contain a partial line from last
84 | * time).
85 | */
86 | bufchain_add(buf, data + pos, nlpos - (data + pos));
87 |
88 | /*
89 | * Collect the resulting line of data and pass it to plug_log.
90 | */
91 | msglen = bufchain_size(buf);
92 | msg = snewn(msglen+1, char);
93 | bufchain_fetch(buf, msg, msglen);
94 | bufchain_consume(buf, msglen);
95 | msg[msglen] = '\0';
96 | fullmsg = dupprintf("proxy: %s", msg);
97 | plug_log(plug, 2, NULL, 0, fullmsg, 0);
98 | sfree(fullmsg);
99 | sfree(msg);
100 |
101 | /*
102 | * Advance past the newline.
103 | */
104 | pos += nlpos+1 - (data + pos);
105 | }
106 |
107 | /*
108 | * Now any remaining data is a partial line, which we save for
109 | * next time.
110 | */
111 | bufchain_add(buf, data + pos, len - pos);
112 | }
113 |
--------------------------------------------------------------------------------
/unix/uxnoise.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Noise generation for PuTTY's cryptographic random number
3 | * generator.
4 | */
5 |
6 | #include
7 | #include
8 | #include
9 |
10 | #include
11 | #include
12 | #include
13 | #include
14 |
15 | #include "putty.h"
16 | #include "ssh.h"
17 | #include "storage.h"
18 |
19 | static int read_dev_urandom(char *buf, int len)
20 | {
21 | int fd;
22 | int ngot, ret;
23 |
24 | fd = open("/dev/urandom", O_RDONLY);
25 | if (fd < 0)
26 | return 0;
27 |
28 | ngot = 0;
29 | while (ngot < len) {
30 | ret = read(fd, buf+ngot, len-ngot);
31 | if (ret < 0) {
32 | close(fd);
33 | return 0;
34 | }
35 | ngot += ret;
36 | }
37 |
38 | close(fd);
39 |
40 | return 1;
41 | }
42 |
43 | /*
44 | * This function is called once, at PuTTY startup. It will do some
45 | * slightly silly things such as fetching an entire process listing
46 | * and scanning /tmp, load the saved random seed from disk, and
47 | * also read 32 bytes out of /dev/urandom.
48 | */
49 |
50 | void noise_get_heavy(void (*func) (void *, int))
51 | {
52 | char buf[512];
53 | FILE *fp;
54 | int ret;
55 | int got_dev_urandom = 0;
56 |
57 | if (read_dev_urandom(buf, 32)) {
58 | got_dev_urandom = 1;
59 | func(buf, 32);
60 | }
61 |
62 | fp = popen("ps -axu 2>/dev/null", "r");
63 | if (fp) {
64 | while ( (ret = fread(buf, 1, sizeof(buf), fp)) > 0)
65 | func(buf, ret);
66 | pclose(fp);
67 | } else if (!got_dev_urandom) {
68 | fprintf(stderr, "popen: %s\n"
69 | "Unable to access fallback entropy source\n", strerror(errno));
70 | exit(1);
71 | }
72 |
73 | fp = popen("ls -al /tmp 2>/dev/null", "r");
74 | if (fp) {
75 | while ( (ret = fread(buf, 1, sizeof(buf), fp)) > 0)
76 | func(buf, ret);
77 | pclose(fp);
78 | } else if (!got_dev_urandom) {
79 | fprintf(stderr, "popen: %s\n"
80 | "Unable to access fallback entropy source\n", strerror(errno));
81 | exit(1);
82 | }
83 |
84 | read_random_seed(func);
85 | random_save_seed();
86 | }
87 |
88 | void random_save_seed(void)
89 | {
90 | int len;
91 | void *data;
92 |
93 | if (random_active) {
94 | random_get_savedata(&data, &len);
95 | write_random_seed(data, len);
96 | sfree(data);
97 | }
98 | }
99 |
100 | /*
101 | * This function is called every time the random pool needs
102 | * stirring, and will acquire the system time.
103 | */
104 | void noise_get_light(void (*func) (void *, int))
105 | {
106 | struct timeval tv;
107 | gettimeofday(&tv, NULL);
108 | func(&tv, sizeof(tv));
109 | }
110 |
111 | /*
112 | * This function is called on a timer, and grabs as much changeable
113 | * system data as it can quickly get its hands on.
114 | */
115 | void noise_regular(void)
116 | {
117 | int fd;
118 | int ret;
119 | char buf[512];
120 | struct rusage rusage;
121 |
122 | if ((fd = open("/proc/meminfo", O_RDONLY)) >= 0) {
123 | while ( (ret = read(fd, buf, sizeof(buf))) > 0)
124 | random_add_noise(buf, ret);
125 | close(fd);
126 | }
127 | if ((fd = open("/proc/stat", O_RDONLY)) >= 0) {
128 | while ( (ret = read(fd, buf, sizeof(buf))) > 0)
129 | random_add_noise(buf, ret);
130 | close(fd);
131 | }
132 | getrusage(RUSAGE_SELF, &rusage);
133 | random_add_noise(&rusage, sizeof(rusage));
134 | }
135 |
136 | /*
137 | * This function is called on every keypress or mouse move, and
138 | * will add the current time to the noise pool. It gets the scan
139 | * code or mouse position passed in, and adds that too.
140 | */
141 | void noise_ultralight(unsigned long data)
142 | {
143 | struct timeval tv;
144 | gettimeofday(&tv, NULL);
145 | random_add_noise(&tv, sizeof(tv));
146 | random_add_noise(&data, sizeof(data));
147 | }
148 |
--------------------------------------------------------------------------------