7 |
8 | #include "putty.h"
9 | #include "ssh.h"
10 | #include "sha512.h"
11 |
12 | static const ssh_hashalg *const real_sha512_algs[] = {
13 | #if HAVE_NEON_SHA512
14 | &ssh_sha512_neon,
15 | #endif
16 | &ssh_sha512_sw,
17 | NULL,
18 | };
19 |
20 | static const ssh_hashalg *const real_sha384_algs[] = {
21 | #if HAVE_NEON_SHA512
22 | &ssh_sha384_neon,
23 | #endif
24 | &ssh_sha384_sw,
25 | NULL,
26 | };
27 |
28 | static ssh_hash *sha512_select(const ssh_hashalg *alg)
29 | {
30 | const ssh_hashalg *const *real_algs =
31 | (const ssh_hashalg *const *)alg->extra;
32 |
33 | for (size_t i = 0; real_algs[i]; i++) {
34 | const ssh_hashalg *alg = real_algs[i];
35 | const struct sha512_extra *alg_extra =
36 | (const struct sha512_extra *)alg->extra;
37 | if (check_availability(alg_extra))
38 | return ssh_hash_new(alg);
39 | }
40 |
41 | /* We should never reach the NULL at the end of the list, because
42 | * the last non-NULL entry should be software-only SHA-512, which
43 | * is always available. */
44 | unreachable("sha512_select ran off the end of its list");
45 | }
46 |
47 | const ssh_hashalg ssh_sha512 = {
48 | .new = sha512_select,
49 | .hlen = 64,
50 | .blocklen = 128,
51 | HASHALG_NAMES_ANNOTATED("SHA-512", "dummy selector vtable"),
52 | .extra = real_sha512_algs,
53 | };
54 |
55 | const ssh_hashalg ssh_sha384 = {
56 | .new = sha512_select,
57 | .hlen = 48,
58 | .blocklen = 128,
59 | HASHALG_NAMES_ANNOTATED("SHA-384", "dummy selector vtable"),
60 | .extra = real_sha384_algs,
61 | };
62 |
--------------------------------------------------------------------------------
/crypto/xdmauth.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Convenience functions to encrypt and decrypt the cookies used in
3 | * XDM-AUTHORIZATION-1.
4 | */
5 |
6 | #include "ssh.h"
7 |
8 | static ssh_cipher *des_xdmauth_cipher(const void *vkeydata)
9 | {
10 | /*
11 | * XDM-AUTHORIZATION-1 uses single-DES, but packs the key into 7
12 | * bytes, so here we have to repack it manually into the canonical
13 | * form where it occupies 8 bytes each with the low bit unused.
14 | */
15 | const unsigned char *keydata = (const unsigned char *)vkeydata;
16 | unsigned char key[8];
17 | int i, nbits, j;
18 | unsigned int bits;
19 |
20 | bits = 0;
21 | nbits = 0;
22 | j = 0;
23 | for (i = 0; i < 8; i++) {
24 | if (nbits < 7) {
25 | bits = (bits << 8) | keydata[j];
26 | nbits += 8;
27 | j++;
28 | }
29 | key[i] = (bits >> (nbits - 7)) << 1;
30 | bits &= ~(0x7F << (nbits - 7));
31 | nbits -= 7;
32 | }
33 |
34 | ssh_cipher *c = ssh_cipher_new(&ssh_des);
35 | ssh_cipher_setkey(c, key);
36 | smemclr(key, sizeof(key));
37 | ssh_cipher_setiv(c, key);
38 | return c;
39 | }
40 |
41 | void des_encrypt_xdmauth(const void *keydata, void *blk, int len)
42 | {
43 | ssh_cipher *c = des_xdmauth_cipher(keydata);
44 | ssh_cipher_encrypt(c, blk, len);
45 | ssh_cipher_free(c);
46 | }
47 |
48 | void des_decrypt_xdmauth(const void *keydata, void *blk, int len)
49 | {
50 | ssh_cipher *c = des_xdmauth_cipher(keydata);
51 | ssh_cipher_decrypt(c, blk, len);
52 | ssh_cipher_free(c);
53 | }
54 |
--------------------------------------------------------------------------------
/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 |
21 | \cfg{xhtml-contents-filename}{index.html}
22 | \cfg{text-filename}{puttydoc.txt}
23 | \cfg{winhelp-filename}{putty.hlp}
24 | \cfg{info-filename}{putty.info}
25 | \cfg{chm-filename}{putty.chm}
26 | \cfg{pdf-filename}{putty.pdf}
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} and \cw{pageant} utilities are not described at all. The
37 | only 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 |
--------------------------------------------------------------------------------
/doc/chm.css:
--------------------------------------------------------------------------------
1 | /* Stylesheet for a Windows .CHM help file */
2 |
3 | body { font-size: 75%; font-family: Verdana, Arial, Helvetica, Sans-Serif; }
4 |
5 | h1 { font-weight: bold; font-size: 150%; }
6 | h2 { font-weight: bold; font-size: 130%; }
7 | h3 { font-weight: bold; font-size: 120%; }
8 |
--------------------------------------------------------------------------------
/doc/chmextra.but:
--------------------------------------------------------------------------------
1 | \# If you want to do a Halibut build of the CHM file by hand, without
2 | \# the help of the CMake edifice, then include this file which will
3 | \# refer to chm.css. The CMake edifice builds its own with a different
4 | \# pathname in it, for the sake of out-of-tree builds.
5 |
6 | \cfg{chm-extra-file}{chm.css}
7 |
--------------------------------------------------------------------------------
/doc/mancfg.but:
--------------------------------------------------------------------------------
1 | \cfg{man-mindepth}{2}
2 |
3 | \C{not-shown} Chapter title which is not shown
4 |
--------------------------------------------------------------------------------
/doc/manpages.but:
--------------------------------------------------------------------------------
1 | \A{man-pages} Man pages for Unix PuTTY
2 |
3 | This appendix contains all the man pages for Unix PuTTY.
4 |
--------------------------------------------------------------------------------
/doc/site.but:
--------------------------------------------------------------------------------
1 | \# Additional configuration for the version of the PuTTY docs
2 | \# actually published as HTML on the website.
3 |
4 | \cfg{xhtml-head-end}{}
5 |
--------------------------------------------------------------------------------
/doc/vids.but:
--------------------------------------------------------------------------------
1 | \# Fallback versionid for use when the build system hasn't provided a
2 | better one.
3 |
4 | \versionid no version information available
5 |
--------------------------------------------------------------------------------
/icons/cicon.pl:
--------------------------------------------------------------------------------
1 | #!/usr/bin/perl
2 |
3 | # Given a list of input PNGs, create a C source file containing a
4 | # const array of XPMs, named by a given C identifier.
5 |
6 | $id = shift @ARGV;
7 | $k = 0;
8 | @xpms = ();
9 | foreach $f (@ARGV) {
10 | # XPM format is generated directly by ImageMagick, so that's easy
11 | # enough. We just have to adjust the declaration line so that it
12 | # has the right name, linkage and storage class.
13 | @lines = ();
14 | open XPM, "convert $f xpm:- |";
15 | push @lines, $_ while ;
16 | close XPM;
17 | die "XPM from $f in unexpected format\n" unless $lines[1] =~ /^static.*\{$/;
18 | $lines[1] = "static const char *const ${id}_$k"."[] = {\n";
19 | $k++;
20 | push @xpms, @lines, "\n";
21 | }
22 |
23 | # Now output.
24 | foreach $line (@xpms) { print $line; }
25 | print "const char *const *const ${id}[] = {\n";
26 | for ($i = 0; $i < $k; $i++) { print " ${id}_$i,\n"; }
27 | print "};\n";
28 | print "const int n_${id} = $k;\n";
29 |
--------------------------------------------------------------------------------
/keygen/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_sources_from_current_dir(keygen
2 | dsa.c
3 | ecdsa.c
4 | millerrabin.c
5 | mpunsafe.c
6 | pockle.c
7 | prime.c
8 | primecandidate.c
9 | rsa.c
10 | smallprimes.c)
11 |
--------------------------------------------------------------------------------
/keygen/ecdsa.c:
--------------------------------------------------------------------------------
1 | /*
2 | * EC key generation.
3 | */
4 |
5 | #include "ssh.h"
6 | #include "sshkeygen.h"
7 | #include "mpint.h"
8 |
9 | int ecdsa_generate(struct ecdsa_key *ek, int bits)
10 | {
11 | if (!ec_nist_alg_and_curve_by_bits(bits, &ek->curve, &ek->sshk.vt))
12 | return 0;
13 |
14 | mp_int *one = mp_from_integer(1);
15 | ek->privateKey = mp_random_in_range(one, ek->curve->w.G_order);
16 | mp_free(one);
17 |
18 | ek->publicKey = ecdsa_public(ek->privateKey, ek->sshk.vt);
19 |
20 | return 1;
21 | }
22 |
23 | int eddsa_generate(struct eddsa_key *ek, int bits)
24 | {
25 | if (!ec_ed_alg_and_curve_by_bits(bits, &ek->curve, &ek->sshk.vt))
26 | return 0;
27 |
28 | /* EdDSA secret keys are just 32 bytes of hash preimage; the
29 | * 64-byte SHA-512 hash of that key will be used when signing,
30 | * but the form of the key stored on disk is the preimage
31 | * only. */
32 | ek->privateKey = mp_random_bits(bits);
33 |
34 | ek->publicKey = eddsa_public(ek->privateKey, ek->sshk.vt);
35 |
36 | return 1;
37 | }
38 |
--------------------------------------------------------------------------------
/keygen/mpunsafe.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #include "defs.h"
6 | #include "misc.h"
7 | #include "puttymem.h"
8 |
9 | #include "mpint.h"
10 | #include "mpunsafe.h"
11 | #include "crypto/mpint_i.h"
12 |
13 | /*
14 | * This global symbol is also defined in ssh/kex2-client.c, to ensure
15 | * that these unsafe non-constant-time mp_int functions can't end up
16 | * accidentally linked in to any PuTTY tool that actually makes an SSH
17 | * client connection.
18 | *
19 | * (Only _client_ connections, however. Uppity, being a test server
20 | * only, is exempt.)
21 | */
22 | const int deliberate_symbol_clash = 12345;
23 |
24 | static size_t mp_unsafe_words_needed(mp_int *x)
25 | {
26 | size_t words = x->nw;
27 | while (words > 1 && !x->w[words-1])
28 | words--;
29 | return words;
30 | }
31 |
32 | mp_int *mp_unsafe_shrink(mp_int *x)
33 | {
34 | x->nw = mp_unsafe_words_needed(x);
35 | /* This potentially leaves some allocated words between the new
36 | * and old values of x->nw, which won't be wiped by mp_free now
37 | * that x->nw doesn't mention that they exist. But we've just
38 | * checked they're all zero, so we don't need to wipe them now
39 | * either. */
40 | return x;
41 | }
42 |
43 | mp_int *mp_unsafe_copy(mp_int *x)
44 | {
45 | mp_int *copy = mp_make_sized(mp_unsafe_words_needed(x));
46 | mp_copy_into(copy, x);
47 | return copy;
48 | }
49 |
--------------------------------------------------------------------------------
/keygen/mpunsafe.h:
--------------------------------------------------------------------------------
1 | /*
2 | * mpunsafe.h: functions that deal with mp_ints in ways that are *not*
3 | * expected to be constant-time. Used during key generation, in which
4 | * constant run time is a lost cause anyway.
5 | *
6 | * These functions are in a separate header, so that you can easily
7 | * check that you're not calling them in the wrong context. They're
8 | * also defined in a separate source file, which is only linked in to
9 | * the key generation tools. Furthermore, that source file also
10 | * defines a global symbol that intentionally conflicts with one
11 | * defined in the SSH client code, so that any attempt to put these
12 | * functions into the same binary as the live SSH client
13 | * implementation will cause a link-time failure. They should only be
14 | * linked into PuTTYgen and auxiliary test programs.
15 | *
16 | * Also, just in case those precautions aren't enough, all the unsafe
17 | * functions have 'unsafe' in the name.
18 | */
19 |
20 | #ifndef PUTTY_MPINT_UNSAFE_H
21 | #define PUTTY_MPINT_UNSAFE_H
22 |
23 | /*
24 | * The most obvious unsafe thing you want to do with an mp_int is to
25 | * get rid of leading zero words in its representation, so that its
26 | * nominal size is as close as possible to its true size, and you
27 | * don't waste any time processing it.
28 | *
29 | * mp_unsafe_shrink performs this operation in place, mutating the
30 | * size field of the mp_int it's given. It returns the same pointer it
31 | * was given.
32 | *
33 | * mp_unsafe_copy leaves the original mp_int alone and makes a new one
34 | * with the minimal size.
35 | */
36 | mp_int *mp_unsafe_shrink(mp_int *m);
37 | mp_int *mp_unsafe_copy(mp_int *m);
38 |
39 | #endif /* PUTTY_MPINT_UNSAFE_H */
40 |
--------------------------------------------------------------------------------
/keygen/smallprimes.c:
--------------------------------------------------------------------------------
1 | /*
2 | * smallprimes.c: implementation of the array of small primes defined
3 | * in sshkeygen.h.
4 | */
5 |
6 | #include
7 | #include "ssh.h"
8 | #include "sshkeygen.h"
9 |
10 | /* The real array that stores the primes. It has to be writable in
11 | * this module, but outside this module, we only expose the
12 | * const-qualified pointer 'smallprimes' so that nobody else can
13 | * accidentally overwrite it. */
14 | static unsigned short smallprimes_array[NSMALLPRIMES];
15 |
16 | const unsigned short *const smallprimes = smallprimes_array;
17 |
18 | void init_smallprimes(void)
19 | {
20 | if (smallprimes_array[0])
21 | return; /* already done */
22 |
23 | bool A[65536];
24 |
25 | for (size_t i = 2; i < lenof(A); i++)
26 | A[i] = true;
27 |
28 | for (size_t i = 2; i < lenof(A); i++) {
29 | if (!A[i])
30 | continue;
31 | for (size_t j = 2*i; j < lenof(A); j += i)
32 | A[j] = false;
33 | }
34 |
35 | size_t pos = 0;
36 | for (size_t i = 2; i < lenof(A); i++) {
37 | if (A[i]) {
38 | assert(pos < NSMALLPRIMES);
39 | smallprimes_array[pos++] = i;
40 | }
41 | }
42 |
43 | assert(pos == NSMALLPRIMES);
44 | }
45 |
--------------------------------------------------------------------------------
/make_with_mingw.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | # install compiler first:
4 | # sudo apt install mingw-w64
5 | #
6 | # i686 (32 bit) version is built by default.
7 | #
8 | # For x86_64 (64 bit) build, replace
9 | # i686-w64-mingw32
10 | # with
11 | # x86_64-w64-mingw32
12 | #
13 | cmake -DCMAKE_SYSTEM_NAME=Windows \
14 | -DCMAKE_SYSTEM_PROCESSOR=x86 \
15 | -DCMAKE_C_COMPILER=i686-w64-mingw32-gcc \
16 | -DCMAKE_CXX_COMPILER=i686-w64-mingw32-g++ \
17 | -DCMAKE_RC_COMPILER=i686-w64-mingw32-windres \
18 | -B build -S .
19 | cd build
20 | make -j$(nproc --all)
21 |
--------------------------------------------------------------------------------
/mksrcarc.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | set -e
4 |
5 | # These are text files.
6 | text=`{ find . -name CVS -prune -o \
7 | -name .cvsignore -prune -o \
8 | -name .svn -prune -o \
9 | -name .git -prune -o \
10 | -name LATEST.VER -prune -o \
11 | -name CHECKLST.txt -prune -o \
12 | -name mksrcarc.sh -prune -o \
13 | -name '*.chm' -prune -o \
14 | -name '*.cur' -prune -o \
15 | -type f -print | sed 's/^\.\///'; } | \
16 | grep -ivE 'test/.*\.txt|MODULE|website.url' | grep -vF .ico | grep -vF .icns`
17 | # These are files which I'm _sure_ should be treated as text, but
18 | # which zip might complain about, so we direct its moans to
19 | # /dev/null! Apparently its heuristics are doubtful of UTF-8 text
20 | # files.
21 | bintext=test/*.txt
22 | # These are actual binary files which we don't want transforming.
23 | bin=`{ ls -1 windows/*.ico windows/website.url; \
24 | find . -name '*.chm' -print -o -name '*.cur' -print; }`
25 |
26 | verbosely() {
27 | echo "$@"
28 | "$@"
29 | }
30 |
31 | verbosely zip -l putty-src.zip $text
32 | verbosely zip -l putty-src.zip $bintext
33 | verbosely zip putty-src.zip $bin
34 |
--------------------------------------------------------------------------------
/mkunxarc.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # Build a Unix source distribution from the PuTTY CVS area.
4 | #
5 | # Expects the following arguments:
6 | # - the suffix to put on the Unix source tarball
7 | # - the options to put on the 'make' command line for the docs
8 |
9 | arcsuffix="$1"
10 |
11 | relver=`cat LATEST.VER`
12 | arcname="putty$arcsuffix"
13 | mkdir uxarc
14 | mkdir uxarc/$arcname
15 | find . -name uxarc -prune -o \
16 | -name CVS -prune -o \
17 | -name .svn -prune -o \
18 | -name . -o \
19 | -type d -exec mkdir uxarc/$arcname/{} \;
20 | find . -name uxarc -prune -o \
21 | -name CVS -prune -o \
22 | -name .cvsignore -prune -o \
23 | -name .svn -prune -o \
24 | -name '*.zip' -prune -o \
25 | -name '*.tar.gz' -prune -o \
26 | -type f -exec ln -s $PWD/{} uxarc/$arcname/{} \;
27 |
28 | tar -C uxarc -chzof $arcname.tar.gz $arcname
29 | rm -rf uxarc
30 |
--------------------------------------------------------------------------------
/otherbackends/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_sources_from_current_dir(otherbackends
2 | raw.c
3 | rlogin.c
4 | supdup.c
5 | telnet.c
6 | testback.c)
7 |
--------------------------------------------------------------------------------
/proxy/nocproxy.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Routines to refuse to do cryptographic interaction with proxies
3 | * in PuTTY. This is a stub implementation of the same interfaces
4 | * provided by cproxy.c, for use in PuTTYtel.
5 | */
6 |
7 | #include
8 | #include
9 | #include
10 |
11 | #include "putty.h"
12 | #include "network.h"
13 | #include "proxy.h"
14 |
15 | const bool socks5_chap_available = false;
16 | const bool http_digest_available = false;
17 |
18 | strbuf *chap_response(ptrlen challenge, ptrlen password)
19 | {
20 | unreachable("CHAP is not built into this binary");
21 | }
22 |
23 | /* dummy arrays to prevent link error */
24 | const char *const httphashnames[] = { NULL };
25 | const bool httphashaccepted[] = { false };
26 |
27 | void http_digest_response(BinarySink *bs, ptrlen username, ptrlen password,
28 | ptrlen realm, ptrlen method, ptrlen uri, ptrlen qop,
29 | ptrlen nonce, ptrlen opaque, uint32_t nonce_count,
30 | HttpDigestHash hash, bool hash_username)
31 | {
32 | unreachable("HTTP DIGEST is not built into this binary");
33 | }
34 |
--------------------------------------------------------------------------------
/proxy/noproxy.c:
--------------------------------------------------------------------------------
1 | /*
2 | * noproxy.c: an alternative to proxy.c, for use by auxiliary programs
3 | * that need to make network connections but don't want to include all
4 | * the full-on support for endless network proxies (and its
5 | * configuration requirements). Implements the primary APIs of
6 | * proxy.c, but maps them straight to the underlying network layer.
7 | */
8 |
9 | #include "putty.h"
10 | #include "network.h"
11 | #include "proxy.h"
12 |
13 | SockAddr *name_lookup(const char *host, int port, char **canonicalname,
14 | Conf *conf, int addressfamily, LogContext *logctx,
15 | const char *reason)
16 | {
17 | return sk_namelookup(host, canonicalname, addressfamily);
18 | }
19 |
20 | Socket *new_connection(SockAddr *addr, const char *hostname,
21 | int port, bool privport,
22 | bool oobinline, bool nodelay, bool keepalive,
23 | Plug *plug, Conf *conf, Interactor *itr)
24 | {
25 | return sk_new(addr, port, privport, oobinline, nodelay, keepalive, plug);
26 | }
27 |
28 | Socket *new_listener(const char *srcaddr, int port, Plug *plug,
29 | bool local_host_only, Conf *conf, int addressfamily)
30 | {
31 | return sk_newlistener(srcaddr, port, plug, local_host_only, addressfamily);
32 | }
33 |
--------------------------------------------------------------------------------
/proxy/nosshproxy.c:
--------------------------------------------------------------------------------
1 | /*
2 | * nosshproxy.c: stub implementation of sshproxy_new_connection().
3 | */
4 |
5 | #include "putty.h"
6 | #include "network.h"
7 |
8 | const bool ssh_proxy_supported = false;
9 |
10 | Socket *sshproxy_new_connection(SockAddr *addr, const char *hostname,
11 | int port, bool privport,
12 | bool oobinline, bool nodelay, bool keepalive,
13 | Plug *plug, Conf *conf, Interactor *itr)
14 | {
15 | return NULL;
16 | }
17 |
--------------------------------------------------------------------------------
/proxy/pproxy.c:
--------------------------------------------------------------------------------
1 | /*
2 | * pproxy.c: dummy implementation of platform_new_connection(), to
3 | * be supplanted on any platform which has its own local proxy
4 | * method.
5 | */
6 |
7 | #include "putty.h"
8 | #include "network.h"
9 | #include "proxy.h"
10 |
11 | Socket *platform_new_connection(SockAddr *addr, const char *hostname,
12 | int port, int privport,
13 | int oobinline, int nodelay, int keepalive,
14 | Plug *plug, Conf *conf, Interactor *itr)
15 | {
16 | return NULL;
17 | }
18 |
--------------------------------------------------------------------------------
/psocks.h:
--------------------------------------------------------------------------------
1 | typedef struct psocks_state psocks_state;
2 |
3 | typedef struct PsocksPlatform PsocksPlatform;
4 | typedef struct PsocksDataSink PsocksDataSink;
5 |
6 | /* indices into PsocksDataSink arrays */
7 | typedef enum PsocksDirection { UP, DN } PsocksDirection;
8 |
9 | typedef struct PsocksDataSink {
10 | void (*free)(PsocksDataSink *);
11 | BinarySink *s[2];
12 | } PsocksDataSink;
13 | static inline void pds_free(PsocksDataSink *pds)
14 | { pds->free(pds); }
15 |
16 | PsocksDataSink *pds_stdio(FILE *fp[2]);
17 |
18 | struct PsocksPlatform {
19 | PsocksDataSink *(*open_pipes)(
20 | const char *cmd, const char *const *direction_args,
21 | const char *index_arg, char **err);
22 | void (*start_subcommand)(strbuf *args);
23 | };
24 |
25 | psocks_state *psocks_new(const PsocksPlatform *);
26 | void psocks_free(psocks_state *ps);
27 | void psocks_cmdline(psocks_state *ps, int argc, char **argv);
28 | void psocks_start(psocks_state *ps);
29 |
--------------------------------------------------------------------------------
/ssh/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | add_library(sshcommon OBJECT
2 | bpp1.c
3 | bpp2.c
4 | bpp-bare.c
5 | ca-config.c
6 | censor1.c
7 | censor2.c
8 | common.c
9 | connection1.c
10 | connection2.c
11 | crc-attack-detector.c
12 | gssc.c
13 | login1.c
14 | pgssapi.c
15 | portfwd.c
16 | ../sshpubk.c
17 | ../sshrand.c
18 | transient-hostkey-cache.c
19 | transport2.c
20 | verstring.c
21 | x11fwd.c
22 | zlib.c)
23 |
24 | add_library(sftpcommon OBJECT sftpcommon.c)
25 |
26 | add_library(sshclient STATIC
27 | agentf.c
28 | connection1-client.c
29 | connection2-client.c
30 | kex2-client.c
31 | mainchan.c
32 | sharing.c
33 | ssh.c
34 | userauth2-client.c
35 | $
36 | $
37 | $)
38 |
39 | add_library(sshserver STATIC
40 | connection1-server.c
41 | connection2-server.c
42 | kex2-server.c
43 | login1-server.c
44 | server.c
45 | sesschan.c
46 | sftpserver.c
47 | userauth2-server.c
48 | $
49 | $)
50 |
51 | add_sources_from_current_dir(sftpclient sftp.c)
52 | target_sources(sftpclient PRIVATE $)
53 |
--------------------------------------------------------------------------------
/ssh/gssc.h:
--------------------------------------------------------------------------------
1 | #ifndef PUTTY_SSHGSSC_H
2 | #define PUTTY_SSHGSSC_H
3 | #include "putty.h"
4 | #ifndef NO_GSSAPI
5 |
6 | #include "pgssapi.h"
7 | #include "gss.h"
8 |
9 | typedef struct gssapi_ssh_gss_ctx {
10 | OM_uint32 maj_stat;
11 | OM_uint32 min_stat;
12 | gss_ctx_id_t ctx;
13 | time_t expiry;
14 | } gssapi_ssh_gss_ctx;
15 |
16 | void ssh_gssapi_bind_fns(struct ssh_gss_library *lib);
17 |
18 | #else
19 |
20 | int ssh_gssapi_init(void);
21 |
22 | #endif /*NO_GSSAPI*/
23 |
24 | #endif /*PUTTY_SSHGSSC_H*/
25 |
--------------------------------------------------------------------------------
/ssh/nogss.c:
--------------------------------------------------------------------------------
1 | #include "putty.h"
2 | #ifndef NO_GSSAPI
3 |
4 | /* For platforms not supporting GSSAPI */
5 |
6 | struct ssh_gss_liblist *ssh_gss_setup(Conf *conf)
7 | {
8 | struct ssh_gss_liblist *list = snew(struct ssh_gss_liblist *);
9 | list->libraries = NULL;
10 | list->nlibraries = 0;
11 | return list;
12 | }
13 |
14 | void ssh_gss_cleanup(struct ssh_gss_liblist *list)
15 | {
16 | sfree(list);
17 | }
18 |
19 | #endif /* NO_GSSAPI */
20 |
--------------------------------------------------------------------------------
/ssh/nosharing.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Stub implementation of SSH connection-sharing IPC, for any
3 | * platform which can't support it at all.
4 | */
5 |
6 | #include
7 | #include
8 | #include
9 |
10 | #include "tree234.h"
11 | #include "putty.h"
12 | #include "ssh.h"
13 | #include "network.h"
14 |
15 | int platform_ssh_share(const char *name, Conf *conf,
16 | Plug *downplug, Plug *upplug, Socket **sock,
17 | char **logtext, char **ds_err, char **us_err,
18 | bool can_upstream, bool can_downstream)
19 | {
20 | return SHARE_NONE;
21 | }
22 |
23 | void platform_ssh_share_cleanup(const char *name)
24 | {
25 | }
26 |
--------------------------------------------------------------------------------
/stubs/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # This subdirectory is generally full of 'stubs' in the sense of
2 | # functions and types that don't do anything interesting, and are
3 | # substituted in some contexts for ones that do.
4 | #
5 | # Some of the files here, with names beginning 'no-', are substituted
6 | # at link time, conditional on the application. For example, a program
7 | # that doesn't use the timing subsystem but still includes a module
8 | # that makes a passing reference to it (say, in a context that never
9 | # turns out to be called) can link against no-timing.c in place of the
10 | # real timing.c.
11 | #
12 | # Other files, with names beginning 'null-', provide non-functional
13 | # implementations of a particular internal API, or a selection of
14 | # non-functional methods for that API that real implementations can
15 | # selectively use. Those are linked in to a program _alongside_ real
16 | # implementations of the same API.
17 | #
18 | # So the cmake setup for this directory puts all the 'null-' files
19 | # into the utils library (at the end of the link, where they'll be
20 | # available everywhere), but doesn't mention the 'no-' files, because
21 | # those will be selected manually by add_executable() commands
22 | # elsewhere.
23 |
24 | add_sources_from_current_dir(utils
25 | null-lp.c
26 | null-cipher.c
27 | null-key.c
28 | null-mac.c
29 | null-opener.c
30 | null-plug.c
31 | null-seat.c)
32 |
--------------------------------------------------------------------------------
/stubs/no-agent.c:
--------------------------------------------------------------------------------
1 | #include "putty.h"
2 |
3 | bool agent_exists(void) { return false; }
4 | Socket *agent_connect(Plug *plug) {
5 | return new_error_socket_fmt(
6 | plug, "no actual networking in this application");
7 | }
8 | void agent_cancel_query(agent_pending_query *pq) {}
9 | agent_pending_query *agent_query(
10 | strbuf *query, void **out, int *outlen,
11 | void (*callback)(void *, void *, int), void *callback_ctx) {return NULL;}
12 |
--------------------------------------------------------------------------------
/stubs/no-ca-config.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Stub version of setup_ca_config_box, for tools that don't have SSH
3 | * code linked in.
4 | */
5 |
6 | #include "putty.h"
7 | #include "dialog.h"
8 |
9 | const bool has_ca_config_box = false;
10 |
11 | void setup_ca_config_box(struct controlbox *b)
12 | {
13 | unreachable("should never call setup_ca_config_box in this application");
14 | }
15 |
--------------------------------------------------------------------------------
/stubs/no-callback.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Stub version of the callback.c functions. Doesn't let anyone
3 | * _schedule_ a callback (because that would lead them into the false
4 | * assumption that it would actually happen later on), but permits the
5 | * other functions without error, on the grounds that it's well
6 | * defined what they would do if nobody had scheduled any callbacks.
7 | */
8 |
9 | #include "putty.h"
10 |
11 | void queue_idempotent_callback(struct IdempotentCallback *ic)
12 | {
13 | unreachable("callbacks are not supported in this application");
14 | }
15 |
16 | void delete_callbacks_for_context(void *ctx)
17 | {
18 | }
19 |
20 | void queue_toplevel_callback(toplevel_callback_fn_t fn, void *ctx)
21 | {
22 | unreachable("callbacks are not supported in this application");
23 | }
24 |
25 | bool run_toplevel_callbacks(void)
26 | {
27 | return false;
28 | }
29 |
30 | bool toplevel_callback_pending(void)
31 | {
32 | return false;
33 | }
34 |
--------------------------------------------------------------------------------
/stubs/no-cmdline.c:
--------------------------------------------------------------------------------
1 | /*
2 | * no-cmdline.c - stubs in applications which don't do the
3 | * standard(ish) PuTTY tools' command-line parsing
4 | */
5 |
6 | #include
7 | #include
8 | #include
9 | #include "putty.h"
10 |
11 | /*
12 | * Stub version of the function in cmdline.c which provides the
13 | * password to SSH authentication by remembering it having been passed
14 | * as a command-line option. If we're not doing normal command-line
15 | * handling, then there is no such option, so that function always
16 | * returns failure.
17 | */
18 | SeatPromptResult cmdline_get_passwd_input(
19 | prompts_t *p, cmdline_get_passwd_input_state *state, bool restartable)
20 | {
21 | return SPR_INCOMPLETE;
22 | }
23 |
--------------------------------------------------------------------------------
/stubs/no-console.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Stub functions for when console.c is not linked into a program.
3 | */
4 |
5 | #include "putty.h"
6 |
7 | bool console_set_batch_mode(bool newvalue)
8 | {
9 | return false;
10 | }
11 |
12 | bool console_set_stdio_prompts(bool newvalue)
13 | {
14 | return false;
15 | }
16 |
--------------------------------------------------------------------------------
/stubs/no-gss.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Stub definitions of the GSSAPI library list, for Unix pterm and
3 | * any other application that needs the symbols defined but has no
4 | * use for them.
5 | */
6 |
7 | #include "putty.h"
8 |
9 | #include "ssh/pgssapi.h"
10 | #include "ssh/gss.h"
11 | #include "ssh/gssc.h"
12 |
13 | const int ngsslibs = 0;
14 | const char *const gsslibnames[1] = { "dummy" };
15 | const struct keyvalwhere gsslibkeywords[1] = { { "dummy", 0, -1, -1 } };
16 |
17 | struct ssh_gss_liblist *ssh_gss_setup(Conf *conf)
18 | {
19 | struct ssh_gss_liblist *list = snew(struct ssh_gss_liblist);
20 |
21 | list->libraries = NULL;
22 | list->nlibraries = 0;
23 | return list;
24 | }
25 |
26 | void ssh_gss_cleanup(struct ssh_gss_liblist *list)
27 | {
28 | sfree(list->libraries); /* I know it's always NULL, but stay consistent */
29 | sfree(list);
30 | }
31 |
--------------------------------------------------------------------------------
/stubs/no-ldisc.c:
--------------------------------------------------------------------------------
1 | #include "putty.h"
2 |
3 | struct Ldisc_tag {
4 | int dummy;
5 | };
6 |
7 | Ldisc *ldisc_create(Conf *conf, Terminal *term, Backend *backend, Seat *seat)
8 | {
9 | Ldisc *ldisc = snew(Ldisc);
10 | memset(ldisc, 0, sizeof(Ldisc));
11 | return ldisc;
12 | }
13 |
14 | void ldisc_configure(Ldisc *ldisc, Conf *conf)
15 | {
16 | }
17 |
18 | void ldisc_free(Ldisc *ldisc)
19 | {
20 | sfree(ldisc);
21 | }
22 |
23 | void ldisc_echoedit_update(Ldisc *ldisc)
24 | {
25 | }
26 |
27 | void ldisc_provide_userpass_le(Ldisc *ldisc, TermLineEditor *le)
28 | {
29 | }
30 |
31 | void ldisc_check_sendok(Ldisc *ldisc)
32 | {
33 | }
34 |
35 | void ldisc_send(Ldisc *ldisc, const void *vbuf, int len, bool interactive)
36 | {
37 | }
38 |
--------------------------------------------------------------------------------
/stubs/no-lineedit.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Stubs of functions in lineedit.c, for use in programs that don't
3 | * have any use for line editing (e.g. because they don't have a
4 | * terminal either).
5 | */
6 |
7 | #include "putty.h"
8 | #include "terminal.h"
9 |
10 | TermLineEditor *lineedit_new(Terminal *term, unsigned flags,
11 | TermLineEditorCallbackReceiver *receiver)
12 | {
13 | return NULL;
14 | }
15 | void lineedit_free(TermLineEditor *le) {}
16 | void lineedit_input(TermLineEditor *le, char ch, bool dedicated) {}
17 | void lineedit_modify_flags(TermLineEditor *le, unsigned clr, unsigned flip) {}
18 | void lineedit_send_line(TermLineEditor *le) {}
19 |
--------------------------------------------------------------------------------
/stubs/no-logging.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Stub module implementing the logging API for tools that don't do
3 | * session logging.
4 | */
5 |
6 | #include "putty.h"
7 |
8 | void logtraffic(LogContext *ctx, unsigned char c, int logmode) {}
9 | void logflush(LogContext *ctx) {}
10 | void logevent(LogContext *ctx, const char *event) {}
11 | void log_free(LogContext *ctx) {}
12 | void log_reconfig(LogContext *ctx, Conf *conf) {}
13 | void log_packet(LogContext *ctx, int direction, int type,
14 | const char *texttype, const void *data, size_t len,
15 | int n_blanks, const struct logblank_t *blanks,
16 | const unsigned long *seq,
17 | unsigned downstream_id, const char *additional_log_text) {}
18 |
19 | LogContext *log_init(LogPolicy *lp, Conf *conf)
20 | { return NULL; }
21 |
--------------------------------------------------------------------------------
/stubs/no-print.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Stub implementation of the printing interface for PuTTY, for the
3 | * benefit of non-printing terminal applications.
4 | */
5 |
6 | #include
7 | #include
8 | #include "putty.h"
9 |
10 | struct printer_job_tag {
11 | int dummy;
12 | };
13 |
14 | printer_job *printer_start_job(char *printer)
15 | {
16 | return NULL;
17 | }
18 |
19 | void printer_job_data(printer_job *pj, const void *data, size_t len)
20 | {
21 | }
22 |
23 | void printer_finish_job(printer_job *pj)
24 | {
25 | }
26 |
27 | printer_enum *printer_start_enum(int *nprinters_ptr)
28 | {
29 | *nprinters_ptr = 0;
30 | return NULL;
31 | }
32 | char *printer_get_name(printer_enum *pe, int i)
33 | {
34 | return NULL;
35 | }
36 | void printer_finish_enum(printer_enum *pe)
37 | {
38 | }
39 |
--------------------------------------------------------------------------------
/stubs/no-printing.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Stub module implementing the printing API for tools that don't
3 | * print.
4 | */
5 |
6 | #include "putty.h"
7 |
8 | printer_job *printer_start_job(char *printer) { return NULL; }
9 | void printer_job_data(printer_job *pj, const void *data, size_t len) {}
10 | void printer_finish_job(printer_job *pj) {}
11 |
12 | printer_enum *printer_start_enum(int *nprinters_ptr)
13 | {
14 | *nprinters_ptr = 0;
15 | return NULL;
16 | }
17 | char *printer_get_name(printer_enum *pe, int i) { return NULL; }
18 | void printer_finish_enum(printer_enum *pe) {}
19 |
--------------------------------------------------------------------------------
/stubs/no-rand.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Stub implementations of RNG functions for applications without an RNG.
3 | */
4 |
5 | #include "putty.h"
6 |
7 | void random_read(void *out, size_t size)
8 | {
9 | unreachable("Random numbers are not available in this application");
10 | }
11 |
12 | void random_save_seed(void)
13 | {
14 | }
15 |
16 | void random_destroy_seed(void)
17 | {
18 | }
19 |
20 | void noise_ultralight(NoiseSourceId id, unsigned long data)
21 | {
22 | }
23 |
--------------------------------------------------------------------------------
/stubs/no-term.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Stubs of functions in terminal.c, for use in programs that don't
3 | * have a terminal.
4 | */
5 |
6 | #include "putty.h"
7 | #include "terminal.h"
8 |
9 | void term_nopaste(Terminal *term)
10 | {
11 | }
12 |
13 | SeatPromptResult term_get_userpass_input(Terminal *term, prompts_t *p)
14 | {
15 | return SPR_SW_ABORT("No terminal to send interactive prompts to");
16 | }
17 |
--------------------------------------------------------------------------------
/stubs/no-timing.c:
--------------------------------------------------------------------------------
1 | /*
2 | * no-timing.c: stub version of timing API.
3 | *
4 | * Used in any tool which needs a subsystem linked against the
5 | * timing API but doesn't want to actually provide timing. For
6 | * example, key generation tools need the random number generator,
7 | * but they don't want the hassle of calling noise_regular() at
8 | * regular intervals - and they don't _need_ it either, since they
9 | * have their own rigorous and different means of noise collection.
10 | */
11 |
12 | #include "putty.h"
13 |
14 | unsigned long schedule_timer(int ticks, timer_fn_t fn, void *ctx)
15 | {
16 | return 0;
17 | }
18 |
19 | void expire_timer_context(void *ctx)
20 | {
21 | }
22 |
23 | unsigned long timing_last_clock(void)
24 | {
25 | return 0;
26 | }
27 |
--------------------------------------------------------------------------------
/stubs/null-cipher.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Implementation of shared trivial routines that ssh_cipher
3 | * implementations might use.
4 | */
5 |
6 | #include "ssh.h"
7 |
8 | void nullcipher_next_message(ssh_cipher *cipher)
9 | {
10 | /* Most ciphers don't do anything at all with this */
11 | }
12 |
--------------------------------------------------------------------------------
/stubs/null-key.c:
--------------------------------------------------------------------------------
1 | #include "misc.h"
2 | #include "ssh.h"
3 |
4 | unsigned nullkey_supported_flags(const ssh_keyalg *self)
5 | {
6 | return 0;
7 | }
8 |
9 | const char *nullkey_alternate_ssh_id(const ssh_keyalg *self, unsigned flags)
10 | {
11 | /* There are no alternate ids */
12 | return self->ssh_id;
13 | }
14 |
15 | ssh_key *nullkey_base_key(ssh_key *key)
16 | {
17 | /* When a key is not certified, it is its own base */
18 | return key;
19 | }
20 |
21 | bool nullkey_variable_size_no(const ssh_keyalg *self) { return false; }
22 | bool nullkey_variable_size_yes(const ssh_keyalg *self) { return true; }
23 |
--------------------------------------------------------------------------------
/stubs/null-lp.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Stub methods usable by LogPolicy implementations.
3 | */
4 |
5 | #include "putty.h"
6 |
7 | bool null_lp_verbose_no(LogPolicy *lp) { return false; }
8 | bool null_lp_verbose_yes(LogPolicy *lp) { return true; }
9 |
--------------------------------------------------------------------------------
/stubs/null-mac.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Implementation of shared trivial routines that ssh2_mac
3 | * implementations might use.
4 | */
5 |
6 | #include "ssh.h"
7 |
8 | void nullmac_next_message(ssh2_mac *m)
9 | {
10 | /* Most MACs don't do anything at all with this */
11 | }
12 |
--------------------------------------------------------------------------------
/stubs/null-opener.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Null implementation of DeferredSocketOpener. Doesn't even bother to
3 | * allocate and free itself: there's just one static implementation
4 | * which we hand out to any caller.
5 | */
6 |
7 | #include "putty.h"
8 |
9 | static void null_opener_free(DeferredSocketOpener *opener) {}
10 |
11 | static const DeferredSocketOpenerVtable NullOpener_vt = {
12 | .free = null_opener_free,
13 | };
14 |
15 | static DeferredSocketOpener null_opener = { .vt = &NullOpener_vt };
16 |
17 | DeferredSocketOpener *null_deferred_socket_opener(void)
18 | {
19 | return &null_opener;
20 | }
21 |
--------------------------------------------------------------------------------
/stubs/null-plug.c:
--------------------------------------------------------------------------------
1 | /*
2 | * nullplug.c: provide a null implementation of the Plug vtable which
3 | * ignores all calls. Occasionally useful in cases where we want to
4 | * make a network connection just to see if it works, but not do
5 | * anything with it afterwards except close it again.
6 | */
7 |
8 | #include "putty.h"
9 |
10 | void nullplug_log(Plug *plug, PlugLogType type, SockAddr *addr,
11 | int port, const char *err_msg, int err_code)
12 | {
13 | }
14 |
15 | void nullplug_closing(Plug *plug, PlugCloseType type, const char *error_msg)
16 | {
17 | }
18 |
19 | void nullplug_receive(Plug *plug, int urgent, const char *data, size_t len)
20 | {
21 | }
22 |
23 | void nullplug_sent(Plug *plug, size_t bufsize)
24 | {
25 | }
26 |
27 | static const PlugVtable nullplug_plugvt = {
28 | .log = nullplug_log,
29 | .closing = nullplug_closing,
30 | .receive = nullplug_receive,
31 | .sent = nullplug_sent,
32 | };
33 |
34 | static Plug nullplug_plug = { &nullplug_plugvt };
35 |
36 | /*
37 | * There's a singleton instance of nullplug, because it's not
38 | * interesting enough to worry about making more than one of them.
39 | */
40 | Plug *const nullplug = &nullplug_plug;
41 |
--------------------------------------------------------------------------------
/terminal/bidi_gettype.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Standalone test program that exposes the minibidi getType function.
3 | */
4 |
5 | #include
6 | #include
7 |
8 | #include "putty.h"
9 | #include "misc.h"
10 | #include "bidi.h"
11 |
12 | void out_of_memory(void)
13 | {
14 | fprintf(stderr, "out of memory!\n");
15 | exit(2);
16 | }
17 |
18 | #define TYPETONAME(X) #X,
19 | static const char *const typenames[] = { BIDI_CHAR_TYPE_LIST(TYPETONAME) };
20 | #undef TYPETONAME
21 |
22 | int main(int argc, char **argv)
23 | {
24 | int i;
25 |
26 | for (i = 1; i < argc; i++) {
27 | unsigned long chr = strtoul(argv[i], NULL, 0);
28 | int type = bidi_getType(chr);
29 | printf("U+%04x: %s\n", (unsigned)chr, typenames[type]);
30 | }
31 |
32 | return 0;
33 | }
34 |
--------------------------------------------------------------------------------
/test/display.txt:
--------------------------------------------------------------------------------
1 | Test of all features involved in do_text()
2 | ==========================================
3 |
4 | Reverse video + red on yellow: [31;43;7m bing! [m
5 | Yellow on red should look the same: [33;41m bong! [m
6 |
7 | Basic attrs, combining chars, both widths: [1mBold[22m [5mblink[25m [4munder[24m [9mstrike[29m [Λ̊][チ][text]
8 | Wide char should be off by 1 narrow char: [1mBold[22m [5mblink[25m [4munder[24m [9mstrike[29m [Λ̊][チ][text]
9 |
10 | Double width, double height. Should be red top, magenta bottom, blue DW only:
11 | #3[41m[1mBold[22m [5mblink[25m [4munder[24m [9mstrike[29m [Λ̊][チ][text][m
12 | #4[45m[1mBold[22m [5mblink[25m [4munder[24m [9mstrike[29m [Λ̊][チ][text][m
13 | #6[44m[1mBold[22m [5mblink[25m [4munder[24m [9mstrike[29m [Λ̊][チ][text][m
14 |
15 |
--------------------------------------------------------------------------------
/test/lattrs.txt:
--------------------------------------------------------------------------------
1 | Test of line attributes:
2 |
3 | #3Double-height top
4 | #4Double-height bottom
5 | #5Normal text (#5)
6 | #6Double-width only
7 |
--------------------------------------------------------------------------------
/test/list-accel.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | # Simple client of the testcrypt system that reports the available
4 | # variants of each of the crypto primitives that have hardware-
5 | # accelerated implementations.
6 | #
7 | # It will report the set of primitives compiled in to testcrypt, and
8 | # also report whether each one can be instantiated at run time.
9 |
10 | from testcrypt import *
11 |
12 | def get_implementations(alg):
13 | return get_implementations_commasep(alg).decode("ASCII").split(",")
14 |
15 | def list_implementations(alg, checkfn):
16 | print(f"Implementations of {alg}:")
17 | for impl in get_implementations(alg):
18 | if impl == alg:
19 | continue
20 | if checkfn(impl):
21 | print(f" {impl:<32s} available")
22 | else:
23 | print(f" {impl:<32s} compiled in, but unavailable at run time")
24 |
25 | def list_cipher_implementations(alg):
26 | list_implementations(alg, lambda impl: ssh_cipher_new(impl) is not None)
27 |
28 | def list_mac_implementations(alg):
29 | list_implementations(alg, lambda impl: ssh2_mac_new(impl, None) is not None)
30 |
31 | def list_hash_implementations(alg):
32 | list_implementations(alg, lambda impl: ssh_hash_new(impl) is not None)
33 |
34 | list_cipher_implementations("aes256_cbc")
35 | list_mac_implementations("aesgcm")
36 | list_hash_implementations("sha1")
37 | list_hash_implementations("sha256")
38 | list_hash_implementations("sha512")
39 |
--------------------------------------------------------------------------------
/test/mpu-check.pl:
--------------------------------------------------------------------------------
1 | #!/usr/bin/perl
2 |
3 | # Trivial command-line client for the function
4 | # Math::Prime::Util::verify_prime, which checks a certificate of
5 | # primality in MPU format.
6 |
7 | use strict;
8 | use warnings;
9 | use Math::Prime::Util;
10 |
11 | Math::Prime::Util::prime_set_config(verbose => 1);
12 |
13 | my $cert = "";
14 | $cert .= $_ while <<>>;
15 |
16 | my $success = Math::Prime::Util::verify_prime($cert);
17 |
18 | die "verification failed\n" unless $success;
19 | warn "verification succeeded\n";
20 |
--------------------------------------------------------------------------------
/test/sclog/.gitignore:
--------------------------------------------------------------------------------
1 | /.ninja_*
2 | /CMakeFiles
3 | /CMakeCache.txt
4 | /cmake_install.cmake
5 | /*.ninja
6 | /*.ldscript
7 | /libsclog.so
8 |
--------------------------------------------------------------------------------
/test/sclog/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # CMake script for the 'sclog' DynamoRIO instrumentation system that
2 | # goes with the PuTTY test binary 'testsc'. For build instructions see
3 | # the comment at the top of testsc.c.
4 |
5 | cmake_minimum_required(VERSION 3.5)
6 |
7 | project(sclog LANGUAGES C)
8 |
9 | find_package(DynamoRIO)
10 | if (NOT DynamoRIO_FOUND)
11 | message(FATAL_ERROR "DynamoRIO not found")
12 | endif()
13 |
14 | add_library(sclog SHARED sclog.c)
15 | configure_DynamoRIO_client(sclog)
16 | foreach(extension drmgr drsyms drreg drutil drwrap)
17 | use_DynamoRIO_extension(sclog ${extension})
18 | endforeach()
19 |
--------------------------------------------------------------------------------
/test/scocols.txt:
--------------------------------------------------------------------------------
1 | Test of (destructive) SCO colour rendering.
2 | SCO fg: [=0F0[=7F [=1F1[=7F [=2F2[=7F [=3F3[=7F [=4F4[=7F [=5F5[=7F [=6F6[=7F [=7F7[=7F [=8F8[=7F [=9F9[=7F [=10F10[=7F [=11F11[=7F [=12F12[=7F [=13F13[=7F [=14F14[=7F [=15F15[=7F
3 | SCO bg: [=0G0[=0G [=1G1[=0G [=2G2[=0G [=3G3[=0G [=4G4[=0G [=5G5[=0G [=6G6[=0G [=7G7[=0G [=8G8[=0G [=9G9[=0G [=10G10[=0G [=11G11[=0G [=12G12[=0G [=13G13[=0G [=14G14[=0G [=15G15[=0G
4 |
--------------------------------------------------------------------------------
/test/utf8.txt:
--------------------------------------------------------------------------------
1 | Test of UTF-8 output in a terminal emulator
2 | ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
3 |
4 | Some basic Unicode:
5 | ∮ E⋅da = Q, n → ∞, ∑ f(i) = ∏ g(i), ∀x∈ℝ: ⌈x⌉ = −⌊−x⌋, α ∧ ¬β = ¬(¬α ∨ β),
6 | ℕ ⊆ ℕ₀ ⊂ ℤ ⊂ ℚ ⊂ ℝ ⊂ ℂ, ⊥ < a ≠ b ≡ c ≤ d ≪ ⊤ ⇒ (A ⇔ B),
7 |
8 | Combining characters:
9 | STARGΛ̊TE SG-1, a = v̇ = r̈, a⃑ ⊥ b⃑
10 | [----------------------------|------------------------]
11 | ๏ แผ่นดินฮั่นเสื่อมโทรมแสนสังเวช พระปกเกศกองบู๊กู้ขึ้นใหม่
12 | สิบสองกษัตริย์ก่อนหน้าแลถัดไป สององค์ไซร้โง่เขลาเบาปัญญา
13 |
14 | Wide characters with difficult wrapping:
15 | Here we go then: コンニチハ コンニチハ コンニチハ コンニチハ コンニチハ コンニチハ コンニチハ コンニチハ コンニチハ コンニチハ コンニチハ コンニチハ コンニチハ コンニチハ コンニチハ
16 |
17 | Arabic and bidirectional text:
18 | (من مجمع الزوائد ومنبع الفوائد للهيثمي ، ج 1 ، ص 74-84)
19 | عن [44mجرير[m [41mرضي[m الله عنه قال قال رسول الله صلى الله عليه
20 | وسلم: بني الاسلام على خمس شهادة ان لا اله الا الله واقام
21 | Mixed LTR and RTL text: [44mجرير[m [41mرضي[m back to LTR.
22 |
23 | East Asian Ambiguous characters: ¼½¾¼½¾¼½¾¼½¾¼½¾¼½¾¼½¾¼½¾¼½¾¼½¾
24 |
--------------------------------------------------------------------------------
/test/vt100.txt:
--------------------------------------------------------------------------------
1 | VT100 line drawing characters, actually using the VT100 escapes
2 | (B)0ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
3 |
4 | lqqqqqqqqqqpoopqrssrqqqqqqqqqqwqqqqqqqqqqpoopqrssrqqqqqqqqqqk
5 | x x x
6 | x ooh, swirly! x top right corner x
7 | x x x
8 | tqqqqqqqqqqpoopqrssrqqqqqqqqqqnqqqqqqqqqqpoopqrssrqqqqqqqqqqu
9 | x x x
10 | x stuff down here x is quite inane x
11 | x x x
12 | mqqqqqqqqqqpoopqrssrqqqqqqqqqqvqqqqqqqqqqpoopqrssrqqqqqqqqqqj
13 |
14 | (This won't do the right thing in PuTTY's default UTF-8 translation;
15 | you'll just see lqqqk letters. It should work with a character set
16 | like ISO8859-1.)
17 |
--------------------------------------------------------------------------------
/unicode/version.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Autogenerated by read_ucd.py from The Unicode Standard 15.0.0
3 | *
4 | * String literals giving the currently supported version of Unicode.
5 | * Useful for error messages and 'about' boxes.
6 | */
7 |
8 | #define UNICODE_VERSION_FULL "The Unicode Standard 15.0.0"
9 | #define UNICODE_VERSION_SHORT "15.0.0"
10 |
--------------------------------------------------------------------------------
/unix/config-unix.c:
--------------------------------------------------------------------------------
1 | /*
2 | * config-unix.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, bool midsession, int protocol)
14 | {
15 | struct controlset *s;
16 | dlgcontrol *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]->type == CTRL_EDITBOX);
32 | s->ctrls[0]->editbox.has_list = false;
33 |
34 | /*
35 | * Unix supports a local-command proxy.
36 | */
37 | if (!midsession) {
38 | int i;
39 | s = ctrl_getset(b, "Connection/Proxy", "basics", NULL);
40 | for (i = 0; i < s->ncontrols; i++) {
41 | c = s->ctrls[i];
42 | if (c->type == CTRL_LISTBOX &&
43 | c->handler == proxy_type_handler) {
44 | c->context.i |= PROXY_UI_FLAG_LOCAL;
45 | break;
46 | }
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/unix/gtkmisc.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Miscellaneous helper functions for GTK.
3 | */
4 |
5 | #ifndef PUTTY_GTKMISC_H
6 | #define PUTTY_GTKMISC_H
7 |
8 | int string_width(const char *text);
9 | void get_label_text_dimensions(const char *text, int *width, int *height);
10 |
11 | void align_label_left(GtkLabel *label);
12 |
13 | GtkWidget *our_dialog_new(void);
14 | void our_dialog_add_to_content_area(GtkWindow *dlg, GtkWidget *w,
15 | bool expand, bool fill, guint padding);
16 | void our_dialog_set_action_area(GtkWindow *dlg, GtkWidget *w);
17 | GtkBox *our_dialog_make_action_hbox(GtkWindow *dlg);
18 |
19 | #endif /* PUTTY_GTKMISC_H */
20 |
--------------------------------------------------------------------------------
/unix/keygen-noise.c:
--------------------------------------------------------------------------------
1 | /*
2 | * keygen-noise.c: Unix implementation of get_heavy_noise() from cmdgen.c.
3 | */
4 |
5 | #include
6 | #include
7 |
8 | #include
9 | #include
10 |
11 | #include "putty.h"
12 |
13 | char *get_random_data(int len, const char *device)
14 | {
15 | char *buf = snewn(len, char);
16 | int fd;
17 | int ngot, ret;
18 |
19 | if (!device) {
20 | static const char *const default_devices[] = {
21 | "/dev/urandom", "/dev/random"
22 | };
23 | size_t i;
24 |
25 | for (i = 0; i < lenof(default_devices); i++) {
26 | if (access(default_devices[i], R_OK) == 0) {
27 | device = default_devices[i];
28 | break;
29 | }
30 | }
31 |
32 | if (!device) {
33 | sfree(buf);
34 | fprintf(stderr, "puttygen: cannot find a readable "
35 | "random number source; use --random-device\n");
36 | return NULL;
37 | }
38 | }
39 |
40 | fd = open(device, O_RDONLY);
41 | if (fd < 0) {
42 | sfree(buf);
43 | fprintf(stderr, "puttygen: %s: open: %s\n",
44 | device, strerror(errno));
45 | return NULL;
46 | }
47 |
48 | ngot = 0;
49 | while (ngot < len) {
50 | ret = read(fd, buf+ngot, len-ngot);
51 | if (ret < 0) {
52 | close(fd);
53 | sfree(buf);
54 | fprintf(stderr, "puttygen: %s: read: %s\n",
55 | device, strerror(errno));
56 | return NULL;
57 | }
58 | ngot += ret;
59 | }
60 |
61 | close(fd);
62 |
63 | return buf;
64 | }
65 |
--------------------------------------------------------------------------------
/unix/no-gtk.c:
--------------------------------------------------------------------------------
1 | /*
2 | * no-gtk.c: link into non-GUI Unix programs so that they can tell
3 | * buildinfo about a lack of GTK.
4 | */
5 |
6 | #include "putty.h"
7 |
8 | char *buildinfo_gtk_version(void)
9 | {
10 | return NULL;
11 | }
12 |
--------------------------------------------------------------------------------
/unix/noaskpass.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Dummy (lack-of-)implementation of a GUI password/passphrase prompt.
3 | */
4 |
5 | #include "putty.h"
6 |
7 | void random_add_noise(NoiseSourceId source, const void *noise, int length)
8 | {
9 | /* We have no keypress_prng here, so no need to implement this */
10 | }
11 |
12 | const bool buildinfo_gtk_relevant = false;
13 |
14 | char *gtk_askpass_main(const char *display, const char *wintitle,
15 | const char *prompt, bool *success)
16 | {
17 | *success = false;
18 | return dupstr("this Pageant was built without GTK");
19 | }
20 |
--------------------------------------------------------------------------------
/unix/peerinfo.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Unix: wrapper for getsockopt(SO_PEERCRED), conditionalised on
3 | * appropriate autoconfery.
4 | */
5 |
6 | #if HAVE_CMAKE_H
7 | #include "cmake.h"
8 | #endif
9 |
10 | #if HAVE_SO_PEERCRED
11 | #define _GNU_SOURCE
12 | #include
13 | #endif
14 |
15 | #include
16 |
17 | #include "putty.h"
18 |
19 | bool so_peercred(int fd, int *pid, int *uid, int *gid)
20 | {
21 | #if HAVE_SO_PEERCRED
22 | struct ucred cr;
23 | socklen_t crlen = sizeof(cr);
24 | if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cr, &crlen) == 0) {
25 | *pid = cr.pid;
26 | *uid = cr.uid;
27 | *gid = cr.gid;
28 | return true;
29 | }
30 | #endif
31 | return false;
32 | }
33 |
--------------------------------------------------------------------------------
/unix/printing.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Printing interface for PuTTY.
3 | */
4 |
5 | #include
6 | #include
7 | #include "putty.h"
8 |
9 | struct printer_job_tag {
10 | FILE *fp;
11 | };
12 |
13 | printer_job *printer_start_job(char *printer)
14 | {
15 | printer_job *pj = snew(printer_job);
16 | /*
17 | * On Unix, we treat the printer string as the name of a
18 | * command to pipe to - typically lpr, of course.
19 | */
20 | pj->fp = popen(printer, "w");
21 | if (!pj->fp) {
22 | sfree(pj);
23 | pj = NULL;
24 | }
25 | return pj;
26 | }
27 |
28 | void printer_job_data(printer_job *pj, const void *data, size_t len)
29 | {
30 | if (!pj)
31 | return;
32 |
33 | if (fwrite(data, 1, len, pj->fp) < len)
34 | /* ignore */;
35 | }
36 |
37 | void printer_finish_job(printer_job *pj)
38 | {
39 | if (!pj)
40 | return;
41 |
42 | pclose(pj->fp);
43 | sfree(pj);
44 | }
45 |
46 | /*
47 | * There's no sensible way to enumerate printers under Unix, since
48 | * practically any valid Unix command is a valid printer :-) So
49 | * these are useless stub functions, and config-unix.c will disable
50 | * the drop-down list in the printer configurer.
51 | */
52 | printer_enum *printer_start_enum(int *nprinters_ptr) {
53 | *nprinters_ptr = 0;
54 | return NULL;
55 | }
56 | char *printer_get_name(printer_enum *pe, int i) { return NULL;
57 | }
58 | void printer_finish_enum(printer_enum *pe) { }
59 |
--------------------------------------------------------------------------------
/unix/pterm.bundle:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 | ${env:PUTTY_GTK_PREFIX_FROM_MAKEFILE}
9 |
10 |
11 | gtk+-3.0
12 |
18 | ${project}/../osxlaunch
19 |
20 |
21 | ${project}/pterm.plist
22 |
23 |
24 | ${project}/../ptermapp
25 |
26 |
27 |
28 | ${prefix}/lib/${gtkdir}/${pkg:${gtk}:gtk_binary_version}/immodules/*.so
29 |
30 |
31 |
32 | ${prefix}/lib/${gtkdir}/${pkg:${gtk}:gtk_binary_version}/printbackends/*.so
33 |
34 |
35 |
36 | ${prefix}/share/themes/Adwaita
37 |
38 |
39 |
40 | ${project}/../icons/Pterm.icns
41 |
42 |
43 |
44 | Adwaita
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/unix/pterm.c:
--------------------------------------------------------------------------------
1 | /*
2 | * pterm main program.
3 | */
4 |
5 | #include
6 | #include
7 |
8 | #include "putty.h"
9 |
10 | const bool use_event_log = false; /* pterm doesn't need it */
11 | const bool new_session = false, saved_sessions = false; /* or these */
12 | const bool dup_check_launchable = false; /* no need to check host name
13 | * in conf */
14 | const bool use_pty_argv = true;
15 |
16 | const unsigned cmdline_tooltype = TOOLTYPE_NONNETWORK;
17 |
18 | /* window.c will call this, and in pterm it's not needed */
19 | void noise_ultralight(NoiseSourceId id, unsigned long data) { }
20 |
21 | const struct BackendVtable *select_backend(Conf *conf)
22 | {
23 | return &pty_backend;
24 | }
25 |
26 | void initial_config_box(Conf *conf, post_dialog_fn_t after, void *afterctx)
27 | {
28 | /*
29 | * This is a no-op in pterm, except that we'll ensure the protocol
30 | * is set to -1 to inhibit the useless Connection panel in the
31 | * config box. So we do that and then just immediately call the
32 | * post-dialog function with a positive result.
33 | */
34 | conf_set_int(conf, CONF_protocol, -1);
35 | after(afterctx, 1);
36 | }
37 |
38 | void cleanup_exit(int code)
39 | {
40 | exit(code);
41 | }
42 |
43 | void setup(bool single)
44 | {
45 | settings_set_default_protocol(-1);
46 |
47 | if (single)
48 | pty_pre_init();
49 | }
50 |
--------------------------------------------------------------------------------
/unix/pterm.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleIconFile
6 | Pterm.icns
7 | CFBundleName
8 | Pterm
9 | CFBundleDisplayName
10 | Pterm
11 | CFBundleExecutable
12 | Pterm
13 | CFBundleVersion
14 | Unidentified build
15 | CFBundleShortVersionString
16 | Unidentified build
17 | CFBundleDevelopmentRegion
18 | en
19 | CFBundleIdentifier
20 | org.tartarus.projects.putty.macpterm
21 | CFBundleInfoDictionaryVersion
22 | 6.0
23 | CFBundlePackageType
24 | APPL
25 | CFBundleSignature
26 | ????
27 | NSHumanReadableCopyright
28 | © 1997-2015 Simon Tatham. All rights reserved.
29 |
30 |
31 |
--------------------------------------------------------------------------------
/unix/putty.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleIconFile
6 | PuTTY.icns
7 | CFBundleName
8 | PuTTY
9 | CFBundleDisplayName
10 | PuTTY
11 | CFBundleExecutable
12 | PuTTY
13 | CFBundleVersion
14 | Unidentified build
15 | CFBundleShortVersionString
16 | Unidentified build
17 | CFBundleDevelopmentRegion
18 | en
19 | CFBundleIdentifier
20 | org.tartarus.projects.putty.macputty
21 | CFBundleInfoDictionaryVersion
22 | 6.0
23 | CFBundlePackageType
24 | APPL
25 | CFBundleSignature
26 | ????
27 | NSHumanReadableCopyright
28 | © 1997-2015 Simon Tatham. All rights reserved.
29 |
30 |
31 |
--------------------------------------------------------------------------------
/unix/stubs/no-uxsel.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Stub version of uxsel.c, for test programs.
3 | */
4 |
5 | #include "putty.h"
6 |
7 | void uxsel_init(void)
8 | {
9 | }
10 |
11 | void uxsel_set(int fd, int rwx, uxsel_callback_fn callback)
12 | {
13 | }
14 |
15 | void uxsel_del(int fd)
16 | {
17 | }
18 |
19 | int next_fd(int *state, int *rwx)
20 | {
21 | return -1;
22 | }
23 |
24 | int first_fd(int *state, int *rwx)
25 | {
26 | return -1;
27 | }
28 |
29 | void select_result(int fd, int event)
30 | {
31 | }
32 |
--------------------------------------------------------------------------------
/unix/utils/align_label_left.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Helper function to align the text in a GtkLabel to the left, which
3 | * has to be done in several different ways depending on GTK version.
4 | */
5 |
6 | #include
7 | #include "putty.h"
8 | #include "gtkcompat.h"
9 | #include "gtkmisc.h"
10 |
11 | void align_label_left(GtkLabel *label)
12 | {
13 | #if GTK_CHECK_VERSION(3,16,0)
14 | gtk_label_set_xalign(label, 0.0);
15 | #elif GTK_CHECK_VERSION(3,14,0)
16 | gtk_widget_set_halign(GTK_WIDGET(label), GTK_ALIGN_START);
17 | #else
18 | gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
19 | #endif
20 | }
21 |
--------------------------------------------------------------------------------
/unix/utils/block_signal.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Handy function to block or unblock a signal, which does all the
3 | * messing about with sigset_t for you.
4 | */
5 |
6 | #include
7 | #include
8 |
9 | #include "defs.h"
10 |
11 | void block_signal(int sig, bool block_it)
12 | {
13 | sigset_t ss;
14 |
15 | sigemptyset(&ss);
16 | sigaddset(&ss, sig);
17 | if (sigprocmask(block_it ? SIG_BLOCK : SIG_UNBLOCK, &ss, 0) < 0) {
18 | perror("sigprocmask");
19 | exit(1);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/unix/utils/buildinfo_gtk_version.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Return the version of GTK we were compiled against, for buildinfo.
3 | */
4 |
5 | #include
6 | #include "putty.h"
7 | #include "gtkcompat.h"
8 | #include "gtkmisc.h"
9 |
10 | char *buildinfo_gtk_version(void)
11 | {
12 | return dupprintf("%d.%d.%d",
13 | GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION);
14 | }
15 |
--------------------------------------------------------------------------------
/unix/utils/cloexec.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Set and clear the FD_CLOEXEC fcntl option on a file descriptor.
3 | *
4 | * We don't realistically expect these operations to fail (the most
5 | * plausible error condition is EBADF, but we always believe ourselves
6 | * to be passing a valid fd so even that's an assertion-fail sort of
7 | * response), so we don't make any effort to return sensible error
8 | * codes to the caller - we just log to standard error and die
9 | * unceremoniously.
10 | */
11 |
12 | #include
13 | #include
14 | #include
15 | #include
16 |
17 | #include
18 |
19 | #include "putty.h"
20 |
21 | void cloexec(int fd)
22 | {
23 | int fdflags;
24 |
25 | fdflags = fcntl(fd, F_GETFD);
26 | if (fdflags < 0) {
27 | fprintf(stderr, "%d: fcntl(F_GETFD): %s\n", fd, strerror(errno));
28 | exit(1);
29 | }
30 | if (fcntl(fd, F_SETFD, fdflags | FD_CLOEXEC) < 0) {
31 | fprintf(stderr, "%d: fcntl(F_SETFD): %s\n", fd, strerror(errno));
32 | exit(1);
33 | }
34 | }
35 |
36 | void noncloexec(int fd)
37 | {
38 | int fdflags;
39 |
40 | fdflags = fcntl(fd, F_GETFD);
41 | if (fdflags < 0) {
42 | fprintf(stderr, "%d: fcntl(F_GETFD): %s\n", fd, strerror(errno));
43 | exit(1);
44 | }
45 | if (fcntl(fd, F_SETFD, fdflags & ~FD_CLOEXEC) < 0) {
46 | fprintf(stderr, "%d: fcntl(F_SETFD): %s\n", fd, strerror(errno));
47 | exit(1);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/unix/utils/dputs.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Implementation of dputs() for Unix.
3 | *
4 | * The debug messages are written to standard output, and also into a
5 | * file called debug.log.
6 | */
7 |
8 | #include
9 |
10 | #include "putty.h"
11 |
12 | static FILE *debug_fp = NULL;
13 |
14 | void dputs(const char *buf)
15 | {
16 | if (!debug_fp) {
17 | debug_fp = fopen("debug.log", "w");
18 | }
19 |
20 | if (write(1, buf, strlen(buf)) < 0) {} /* 'error check' to placate gcc */
21 |
22 | fputs(buf, debug_fp);
23 | fflush(debug_fp);
24 | }
25 |
--------------------------------------------------------------------------------
/unix/utils/filename.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Implementation of Filename for Unix, including f_open().
3 | */
4 |
5 | #include
6 | #include
7 |
8 | #include "putty.h"
9 |
10 | Filename *filename_from_str(const char *str)
11 | {
12 | Filename *fn = snew(Filename);
13 | fn->path = dupstr(str);
14 | return fn;
15 | }
16 |
17 | Filename *filename_copy(const Filename *fn)
18 | {
19 | return filename_from_str(fn->path);
20 | }
21 |
22 | const char *filename_to_str(const Filename *fn)
23 | {
24 | return fn->path;
25 | }
26 |
27 | bool filename_equal(const Filename *f1, const Filename *f2)
28 | {
29 | return !strcmp(f1->path, f2->path);
30 | }
31 |
32 | bool filename_is_null(const Filename *fn)
33 | {
34 | return !fn->path[0];
35 | }
36 |
37 | void filename_free(Filename *fn)
38 | {
39 | sfree(fn->path);
40 | sfree(fn);
41 | }
42 |
43 | void filename_serialise(BinarySink *bs, const Filename *f)
44 | {
45 | put_asciz(bs, f->path);
46 | }
47 | Filename *filename_deserialise(BinarySource *src)
48 | {
49 | return filename_from_str(get_asciz(src));
50 | }
51 |
52 | char filename_char_sanitise(char c)
53 | {
54 | if (c == '/')
55 | return '.';
56 | return c;
57 | }
58 |
59 | FILE *f_open(const Filename *filename, char const *mode, bool is_private)
60 | {
61 | if (!is_private) {
62 | return fopen(filename->path, mode);
63 | } else {
64 | int fd;
65 | assert(mode[0] == 'w'); /* is_private is meaningless for read,
66 | and tricky for append */
67 | fd = open(filename->path, O_WRONLY | O_CREAT | O_TRUNC, 0600);
68 | if (fd < 0)
69 | return NULL;
70 | return fdopen(fd, mode);
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/unix/utils/fontspec.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Implementation of FontSpec for Unix. This is more or less
3 | * degenerate - on this platform a font specification is just a
4 | * string.
5 | */
6 |
7 | #include "putty.h"
8 |
9 | FontSpec *fontspec_new(const char *name)
10 | {
11 | FontSpec *f = snew(FontSpec);
12 | f->name = dupstr(name);
13 | return f;
14 | }
15 |
16 | FontSpec *fontspec_new_default(void)
17 | {
18 | return fontspec_new("");
19 | }
20 |
21 | FontSpec *fontspec_copy(const FontSpec *f)
22 | {
23 | return fontspec_new(f->name);
24 | }
25 |
26 | void fontspec_free(FontSpec *f)
27 | {
28 | sfree(f->name);
29 | sfree(f);
30 | }
31 |
32 | void fontspec_serialise(BinarySink *bs, FontSpec *f)
33 | {
34 | put_asciz(bs, f->name);
35 | }
36 |
37 | FontSpec *fontspec_deserialise(BinarySource *src)
38 | {
39 | return fontspec_new(get_asciz(src));
40 | }
41 |
--------------------------------------------------------------------------------
/unix/utils/get_label_text_dimensions.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Determine the dimensions of a piece of text in the standard
3 | * font used in GTK interface elements like labels. We do this by
4 | * instantiating an actual GtkLabel, and then querying its size.
5 | */
6 |
7 | #include
8 | #include "putty.h"
9 | #include "gtkcompat.h"
10 | #include "gtkmisc.h"
11 |
12 | void get_label_text_dimensions(const char *text, int *width, int *height)
13 | {
14 | GtkWidget *label = gtk_label_new(text);
15 |
16 | /*
17 | * GTK2 and GTK3 require us to query the size completely
18 | * differently. I'm sure there ought to be an easier approach than
19 | * the way I'm doing this in GTK3, too!
20 | */
21 | #if GTK_CHECK_VERSION(3,0,0)
22 | PangoLayout *layout = gtk_label_get_layout(GTK_LABEL(label));
23 | PangoRectangle logrect;
24 | pango_layout_get_extents(layout, NULL, &logrect);
25 | if (width)
26 | *width = logrect.width / PANGO_SCALE;
27 | if (height)
28 | *height = logrect.height / PANGO_SCALE;
29 | #else
30 | GtkRequisition req;
31 | gtk_widget_size_request(label, &req);
32 | if (width)
33 | *width = req.width;
34 | if (height)
35 | *height = req.height;
36 | #endif
37 |
38 | g_object_ref_sink(G_OBJECT(label));
39 | #if GTK_CHECK_VERSION(2,10,0)
40 | g_object_unref(label);
41 | #endif
42 | }
43 |
--------------------------------------------------------------------------------
/unix/utils/get_username.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Implementation of get_username() for Unix.
3 | */
4 |
5 | #include
6 | #include
7 |
8 | #include "putty.h"
9 |
10 | char *get_username(void)
11 | {
12 | struct passwd *p;
13 | uid_t uid = getuid();
14 | char *user, *ret = NULL;
15 |
16 | /*
17 | * First, find who we think we are using getlogin. If this
18 | * agrees with our uid, we'll go along with it. This should
19 | * allow sharing of uids between several login names whilst
20 | * coping correctly with people who have su'ed.
21 | */
22 | user = getlogin();
23 | #if HAVE_SETPWENT
24 | setpwent();
25 | #endif
26 | if (user)
27 | p = getpwnam(user);
28 | else
29 | p = NULL;
30 | if (p && p->pw_uid == uid) {
31 | /*
32 | * The result of getlogin() really does correspond to
33 | * our uid. Fine.
34 | */
35 | ret = user;
36 | } else {
37 | /*
38 | * If that didn't work, for whatever reason, we'll do
39 | * the simpler version: look up our uid in the password
40 | * file and map it straight to a name.
41 | */
42 | p = getpwuid(uid);
43 | if (!p)
44 | return NULL;
45 | ret = p->pw_name;
46 | }
47 | #if HAVE_ENDPWENT
48 | endpwent();
49 | #endif
50 |
51 | return dupstr(ret);
52 | }
53 |
--------------------------------------------------------------------------------
/unix/utils/get_x11_display.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Return the Xlib 'Display *' underlying our GTK environment, if any.
3 | */
4 |
5 | #include
6 | #include "putty.h"
7 | #include "gtkcompat.h"
8 | #include "gtkmisc.h"
9 |
10 | #ifndef NOT_X_WINDOWS
11 |
12 | #include
13 | #include
14 |
15 | Display *get_x11_display(void)
16 | {
17 | #if GTK_CHECK_VERSION(3,0,0)
18 | if (!GDK_IS_X11_DISPLAY(gdk_display_get_default()))
19 | return NULL;
20 | #endif
21 | return GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
22 | }
23 |
24 | #else
25 |
26 | /*
27 | * Include _something_ in this file to prevent an annoying compiler
28 | * warning, and to avoid having to condition out this file in
29 | * CMakeLists. It's in a library, so this variable shouldn't end up in
30 | * any actual program, because nothing will refer to it.
31 | */
32 | const int get_x11_display_dummy_variable = 0;
33 |
34 | #endif
35 |
--------------------------------------------------------------------------------
/unix/utils/getticks.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Implement getticks() for Unix.
3 | */
4 |
5 | #include
6 | #include
7 |
8 | #include "putty.h"
9 |
10 | unsigned long getticks(void)
11 | {
12 | /*
13 | * We want to use milliseconds rather than the microseconds or
14 | * nanoseconds given by the underlying clock functions, because we
15 | * need a decent number of them to fit into a 32-bit word so it
16 | * can be used for keepalives.
17 | */
18 | #if HAVE_CLOCK_GETTIME && HAVE_CLOCK_MONOTONIC
19 | {
20 | /* Use CLOCK_MONOTONIC if available, so as to be unconfused if
21 | * the system clock changes. */
22 | struct timespec ts;
23 | if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
24 | return ts.tv_sec * TICKSPERSEC +
25 | ts.tv_nsec / (1000000000 / TICKSPERSEC);
26 | }
27 | #endif
28 | {
29 | struct timeval tv;
30 | gettimeofday(&tv, NULL);
31 | return tv.tv_sec * TICKSPERSEC + tv.tv_usec / (1000000 / TICKSPERSEC);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/unix/utils/make_dir_path.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Make a path of subdirectories, tolerating EEXIST at every step.
3 | */
4 |
5 | #include
6 | #include
7 |
8 | #include
9 | #include
10 | #include
11 |
12 | #include "putty.h"
13 |
14 | char *make_dir_path(const char *path, mode_t mode)
15 | {
16 | int pos = 0;
17 | char *prefix;
18 |
19 | while (1) {
20 | pos += strcspn(path + pos, "/");
21 |
22 | if (pos > 0) {
23 | prefix = dupprintf("%.*s", pos, path);
24 |
25 | if (mkdir(prefix, mode) < 0 && errno != EEXIST) {
26 | char *ret = dupprintf("%s: mkdir: %s",
27 | prefix, strerror(errno));
28 | sfree(prefix);
29 | return ret;
30 | }
31 |
32 | sfree(prefix);
33 | }
34 |
35 | if (!path[pos])
36 | return NULL;
37 | pos += strspn(path + pos, "/");
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/unix/utils/make_spr_sw_abort_errno.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Constructor function for a SeatPromptResult of the 'software abort'
3 | * category, whose error message includes the translation of an OS
4 | * error code.
5 | */
6 |
7 | #include "putty.h"
8 |
9 | static void spr_errno_errfn(SeatPromptResult spr, BinarySink *bs)
10 | {
11 | put_fmt(bs, "%s: %s", spr.errdata_lit, strerror(spr.errdata_u));
12 | }
13 |
14 | SeatPromptResult make_spr_sw_abort_errno(const char *prefix, int errno_value)
15 | {
16 | SeatPromptResult spr;
17 | spr.kind = SPRK_SW_ABORT;
18 | spr.errfn = spr_errno_errfn;
19 | spr.errdata_lit = prefix;
20 | spr.errdata_u = errno_value;
21 | return spr;
22 | }
23 |
--------------------------------------------------------------------------------
/unix/utils/nonblock.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Set and clear the O_NONBLOCK fcntl option on an open file.
3 | *
4 | * We don't realistically expect these operations to fail (the most
5 | * plausible error condition is EBADF, but we always believe ourselves
6 | * to be passing a valid fd so even that's an assertion-fail sort of
7 | * response), so we don't make any effort to return sensible error
8 | * codes to the caller - we just log to standard error and die
9 | * unceremoniously.
10 | *
11 | * Returns the previous state of O_NONBLOCK.
12 | */
13 |
14 | #include
15 | #include
16 | #include
17 | #include
18 |
19 | #include
20 |
21 | #include "putty.h"
22 |
23 | bool nonblock(int fd)
24 | {
25 | int fdflags;
26 |
27 | fdflags = fcntl(fd, F_GETFL);
28 | if (fdflags < 0) {
29 | fprintf(stderr, "%d: fcntl(F_GETFL): %s\n", fd, strerror(errno));
30 | exit(1);
31 | }
32 | if (fcntl(fd, F_SETFL, fdflags | O_NONBLOCK) < 0) {
33 | fprintf(stderr, "%d: fcntl(F_SETFL): %s\n", fd, strerror(errno));
34 | exit(1);
35 | }
36 |
37 | return fdflags & O_NONBLOCK;
38 | }
39 |
40 | bool no_nonblock(int fd)
41 | {
42 | int fdflags;
43 |
44 | fdflags = fcntl(fd, F_GETFL);
45 | if (fdflags < 0) {
46 | fprintf(stderr, "%d: fcntl(F_GETFL): %s\n", fd, strerror(errno));
47 | exit(1);
48 | }
49 | if (fcntl(fd, F_SETFL, fdflags & ~O_NONBLOCK) < 0) {
50 | fprintf(stderr, "%d: fcntl(F_SETFL): %s\n", fd, strerror(errno));
51 | exit(1);
52 | }
53 |
54 | return fdflags & O_NONBLOCK;
55 | }
56 |
--------------------------------------------------------------------------------
/unix/utils/open_for_write_would_lose_data.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Unix implementation of open_for_write_would_lose_data().
3 | */
4 |
5 | #include
6 | #include
7 |
8 | #include "putty.h"
9 |
10 | bool open_for_write_would_lose_data(const Filename *fn)
11 | {
12 | struct stat st;
13 |
14 | if (stat(fn->path, &st) < 0) {
15 | /*
16 | * If the file doesn't even exist, we obviously want to return
17 | * false. If we failed to stat it for any other reason,
18 | * ignoring the precise error code and returning false still
19 | * doesn't seem too unreasonable, because then we'll try to
20 | * open the file for writing and report _that_ error, which is
21 | * likely to be more to the point.
22 | */
23 | return false;
24 | }
25 |
26 | /*
27 | * OK, something exists at this pathname and we've found out
28 | * something about it. But an open-for-write will only
29 | * destructively truncate it if it's a regular file with nonzero
30 | * size. If it's empty, or some other kind of special thing like a
31 | * character device (e.g. /dev/tty) or a named pipe, then opening
32 | * it for write is already non-destructive and it's pointless and
33 | * annoying to warn about it just because the same file can be
34 | * opened for reading. (Indeed, if it's a named pipe, opening it
35 | * for reading actually _causes inconvenience_ in its own right,
36 | * even before the question of whether it gives misleading
37 | * information.)
38 | */
39 | if (S_ISREG(st.st_mode) && st.st_size > 0) {
40 | return true;
41 | }
42 |
43 | return false;
44 | }
45 |
--------------------------------------------------------------------------------
/unix/utils/pgp_fingerprints.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Display the fingerprints of the PGP Master Keys to the user.
3 | *
4 | * (This is in its own file rather than in console.c, because it's
5 | * appropriate even for Unix GUI apps.)
6 | */
7 |
8 | #include "putty.h"
9 |
10 | void pgp_fingerprints(void)
11 | {
12 | fputs("These are the fingerprints of the PuTTY PGP Master Keys. They can\n"
13 | "be used to establish a trust path from this executable to another\n"
14 | "one. See the manual for more information.\n"
15 | "(Note: these fingerprints have nothing to do with SSH!)\n"
16 | "\n"
17 | "PuTTY Master Key as of " PGP_MASTER_KEY_YEAR
18 | " (" PGP_MASTER_KEY_DETAILS "):\n"
19 | " " PGP_MASTER_KEY_FP "\n\n"
20 | "Previous Master Key (" PGP_PREV_MASTER_KEY_YEAR
21 | ", " PGP_PREV_MASTER_KEY_DETAILS "):\n"
22 | " " PGP_PREV_MASTER_KEY_FP "\n", stdout);
23 | }
24 |
--------------------------------------------------------------------------------
/unix/utils/signal.c:
--------------------------------------------------------------------------------
1 | /*
2 | * PuTTY's wrapper on signal(2).
3 | *
4 | * Calling signal() is non-portable, as it varies in meaning between
5 | * platforms and depending on feature macros, and has stupid semantics
6 | * at least some of the time.
7 | *
8 | * This function provides the same interface as the libc function, but
9 | * provides consistent semantics. It assumes POSIX semantics for
10 | * sigaction() (so you might need to do some more work if you port to
11 | * something ancient like SunOS 4).
12 | */
13 |
14 | #include
15 |
16 | #include "defs.h"
17 |
18 | void (*putty_signal(int sig, void (*func)(int)))(int)
19 | {
20 | struct sigaction sa;
21 | struct sigaction old;
22 |
23 | sa.sa_handler = func;
24 | if (sigemptyset(&sa.sa_mask) < 0)
25 | return SIG_ERR;
26 | sa.sa_flags = SA_RESTART;
27 | if (sigaction(sig, &sa, &old) < 0)
28 | return SIG_ERR;
29 | return old.sa_handler;
30 | }
31 |
--------------------------------------------------------------------------------
/unix/utils/string_width.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Return the width of a string in the font used in GTK controls. Used
3 | * as a means of picking a sensible size for dialog boxes and pieces
4 | * of them, in a way that should adapt sensibly to changes in font and
5 | * resolution.
6 | */
7 |
8 | #include
9 | #include "putty.h"
10 | #include "gtkcompat.h"
11 | #include "gtkmisc.h"
12 |
13 | int string_width(const char *text)
14 | {
15 | int ret;
16 | get_label_text_dimensions(text, &ret, NULL);
17 | return ret;
18 | }
19 |
--------------------------------------------------------------------------------
/unix/x11misc.h:
--------------------------------------------------------------------------------
1 | /*
2 | * x11misc.h: header file for functions that need to refer to Xlib
3 | * data types. Has to be separate from unix.h so that we can include
4 | * it only after including the X headers, which in turn has to be done
5 | * after putty.h has told us whether NOT_X_WINDOWS is defined.
6 | */
7 |
8 | #ifndef NOT_X_WINDOWS
9 |
10 | /* Defined in unix/utils */
11 | void x11_ignore_error(Display *disp, unsigned char errcode);
12 | Display *get_x11_display(void);
13 |
14 | #endif
15 |
--------------------------------------------------------------------------------
/utils/antispoof.c:
--------------------------------------------------------------------------------
1 | #include "putty.h"
2 | #include "misc.h"
3 |
4 | void seat_antispoof_msg(InteractionReadySeat iseat, const char *msg)
5 | {
6 | strbuf *sb = strbuf_new();
7 | seat_set_trust_status(iseat.seat, true);
8 | if (seat_can_set_trust_status(iseat.seat)) {
9 | /*
10 | * If the seat can directly indicate that this message is
11 | * generated by the client, then we can just use the message
12 | * unmodified as an unspoofable header.
13 | */
14 | put_dataz(sb, msg);
15 | } else if (*msg) {
16 | /*
17 | * Otherwise, add enough padding around it that the server
18 | * wouldn't be able to mimic it within our line-length
19 | * constraint.
20 | */
21 | put_fmt(sb, "-- %s ", msg);
22 | while (sb->len < 78)
23 | put_byte(sb, '-');
24 | }
25 | put_datapl(sb, PTRLEN_LITERAL("\r\n"));
26 | seat_banner_pl(iseat, ptrlen_from_strbuf(sb));
27 | strbuf_free(sb);
28 | }
29 |
--------------------------------------------------------------------------------
/utils/base64_decode.c:
--------------------------------------------------------------------------------
1 | #include "misc.h"
2 |
3 | void base64_decode_bs(BinarySink *bs, ptrlen input)
4 | {
5 | BinarySource src[1];
6 | BinarySource_BARE_INIT_PL(src, input);
7 |
8 | while (get_avail(src)) {
9 | char b64atom[4];
10 | unsigned char binatom[3];
11 |
12 | for (size_t i = 0; i < 4 ;) {
13 | char c = get_byte(src);
14 | if (get_err(src))
15 | c = '=';
16 | if (c == '\n' || c == '\r')
17 | continue;
18 | b64atom[i++] = c;
19 | }
20 |
21 | put_data(bs, binatom, base64_decode_atom(b64atom, binatom));
22 | }
23 | }
24 |
25 | void base64_decode_fp(FILE *fp, ptrlen input)
26 | {
27 | stdio_sink ss;
28 | stdio_sink_init(&ss, fp);
29 | base64_decode_bs(BinarySink_UPCAST(&ss), input);
30 | }
31 |
32 | strbuf *base64_decode_sb(ptrlen input)
33 | {
34 | strbuf *sb = strbuf_new_nm();
35 | base64_decode_bs(BinarySink_UPCAST(sb), input);
36 | return sb;
37 | }
38 |
--------------------------------------------------------------------------------
/utils/base64_decode_atom.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Core routine to decode a single atomic base64 chunk.
3 | */
4 |
5 | #include "defs.h"
6 | #include "misc.h"
7 |
8 | int base64_decode_atom(const char *atom, unsigned char *out)
9 | {
10 | int vals[4];
11 | int i, v, len;
12 | unsigned word;
13 | char c;
14 |
15 | for (i = 0; i < 4; i++) {
16 | c = atom[i];
17 | if (c >= 'A' && c <= 'Z')
18 | v = c - 'A';
19 | else if (c >= 'a' && c <= 'z')
20 | v = c - 'a' + 26;
21 | else if (c >= '0' && c <= '9')
22 | v = c - '0' + 52;
23 | else if (c == '+')
24 | v = 62;
25 | else if (c == '/')
26 | v = 63;
27 | else if (c == '=')
28 | v = -1;
29 | else
30 | return 0; /* invalid atom */
31 | vals[i] = v;
32 | }
33 |
34 | if (vals[0] == -1 || vals[1] == -1)
35 | return 0;
36 | if (vals[2] == -1 && vals[3] != -1)
37 | return 0;
38 |
39 | if (vals[3] != -1)
40 | len = 3;
41 | else if (vals[2] != -1)
42 | len = 2;
43 | else
44 | len = 1;
45 |
46 | word = ((vals[0] << 18) |
47 | (vals[1] << 12) | ((vals[2] & 0x3F) << 6) | (vals[3] & 0x3F));
48 | out[0] = (word >> 16) & 0xFF;
49 | if (len > 1)
50 | out[1] = (word >> 8) & 0xFF;
51 | if (len > 2)
52 | out[2] = word & 0xFF;
53 | return len;
54 | }
55 |
--------------------------------------------------------------------------------
/utils/base64_encode.c:
--------------------------------------------------------------------------------
1 | #include "misc.h"
2 |
3 | void base64_encode_bs(BinarySink *bs, ptrlen input, int cpl)
4 | {
5 | BinarySource src[1];
6 | BinarySource_BARE_INIT_PL(src, input);
7 | int linelen = 0;
8 |
9 | while (get_avail(src)) {
10 | size_t n = get_avail(src) < 3 ? get_avail(src) : 3;
11 | ptrlen binatom = get_data(src, n);
12 |
13 | char b64atom[4];
14 | base64_encode_atom(binatom.ptr, binatom.len, b64atom);
15 | for (size_t i = 0; i < 4; i++) {
16 | if (cpl > 0 && linelen >= cpl) {
17 | linelen = 0;
18 | put_byte(bs, '\n');
19 | }
20 | put_byte(bs, b64atom[i]);
21 | linelen++;
22 | }
23 | }
24 | if (cpl > 0)
25 | put_byte(bs, '\n');
26 | }
27 |
28 | void base64_encode_fp(FILE *fp, ptrlen input, int cpl)
29 | {
30 | stdio_sink ss;
31 | stdio_sink_init(&ss, fp);
32 | base64_encode_bs(BinarySink_UPCAST(&ss), input, cpl);
33 | }
34 |
35 | strbuf *base64_encode_sb(ptrlen input, int cpl)
36 | {
37 | strbuf *sb = strbuf_new_nm();
38 | base64_encode_bs(BinarySink_UPCAST(sb), input, cpl);
39 | return sb;
40 | }
41 |
--------------------------------------------------------------------------------
/utils/base64_encode_atom.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Core routine to encode a single atomic base64 chunk.
3 | */
4 |
5 | #include "defs.h"
6 | #include "misc.h"
7 |
8 | void base64_encode_atom(const unsigned char *data, int n, char *out)
9 | {
10 | static const char base64_chars[] =
11 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
12 |
13 | unsigned word;
14 |
15 | word = data[0] << 16;
16 | if (n > 1)
17 | word |= data[1] << 8;
18 | if (n > 2)
19 | word |= data[2];
20 | out[0] = base64_chars[(word >> 18) & 0x3F];
21 | out[1] = base64_chars[(word >> 12) & 0x3F];
22 | if (n > 1)
23 | out[2] = base64_chars[(word >> 6) & 0x3F];
24 | else
25 | out[2] = '=';
26 | if (n > 2)
27 | out[3] = base64_chars[word & 0x3F];
28 | else
29 | out[3] = '=';
30 | }
31 |
--------------------------------------------------------------------------------
/utils/base64_valid.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Determine whether a string looks like valid base64-encoded data.
3 | */
4 |
5 | #include "misc.h"
6 |
7 | static inline bool valid_char_main(char c)
8 | {
9 | return ((c >= 'A' && c <= 'Z') ||
10 | (c >= 'a' && c <= 'z') ||
11 | (c >= '0' && c <= '9') ||
12 | c == '+' || c == '/');
13 | }
14 |
15 | bool base64_valid(ptrlen data)
16 | {
17 | size_t blocklen = 0, nequals = 0;
18 |
19 | for (size_t i = 0; i < data.len; i++) {
20 | char c = ((const char *)data.ptr)[i];
21 |
22 | if (c == '\n' || c == '\r')
23 | continue;
24 |
25 | if (valid_char_main(c)) {
26 | if (nequals) /* can't go back to data after = */
27 | return false;
28 | blocklen++;
29 | if (blocklen == 4)
30 | blocklen = 0;
31 | continue;
32 | }
33 |
34 | if (c == '=') {
35 | if (blocklen == 0 && nequals) /* started a fresh block */
36 | return false;
37 |
38 | nequals++;
39 | blocklen++;
40 | if (blocklen == 4) {
41 | if (nequals > 2)
42 | return false; /* nonsensical final block */
43 | blocklen = 0;
44 | }
45 | continue;
46 | }
47 |
48 | return false; /* bad character */
49 | }
50 |
51 | if (blocklen == 0 || blocklen == 2 || blocklen == 3)
52 | return true; /* permit eliding the trailing = */
53 | return false;
54 | }
55 |
--------------------------------------------------------------------------------
/utils/burnstr.c:
--------------------------------------------------------------------------------
1 | /*
2 | * 'Burn' a dynamically allocated string, in the sense of destroying
3 | * it beyond recovery: overwrite it with zeroes and then free it.
4 | */
5 |
6 | #include "defs.h"
7 | #include "misc.h"
8 |
9 | void burnstr(char *string)
10 | {
11 | if (string) {
12 | smemclr(string, strlen(string));
13 | sfree(string);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/utils/burnwcs.c:
--------------------------------------------------------------------------------
1 | /*
2 | * 'Burn' a dynamically allocated wide string, in the sense of
3 | * destroying it beyond recovery: overwrite it with zeroes and then
4 | * free it.
5 | */
6 |
7 | #include
8 |
9 | #include "defs.h"
10 | #include "misc.h"
11 |
12 | void burnwcs(wchar_t *string)
13 | {
14 | if (string) {
15 | smemclr(string, sizeof(*string) * wcslen(string));
16 | sfree(string);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/utils/chomp.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Perl-style 'chomp', for a line we just read with fgetline.
3 | *
4 | * Unlike Perl chomp, however, we're deliberately forgiving of strange
5 | * line-ending conventions.
6 | *
7 | * Also we forgive NULL on input, so you can just write 'line =
8 | * chomp(fgetline(fp));' and not bother checking for NULL until
9 | * afterwards.
10 | */
11 |
12 | #include
13 |
14 | #include "defs.h"
15 | #include "misc.h"
16 |
17 | char *chomp(char *str)
18 | {
19 | if (str) {
20 | int len = strlen(str);
21 | while (len > 0 && (str[len-1] == '\r' || str[len-1] == '\n'))
22 | len--;
23 | str[len] = '\0';
24 | }
25 | return str;
26 | }
27 |
--------------------------------------------------------------------------------
/utils/cmdline_get_passwd_input_state_new.c:
--------------------------------------------------------------------------------
1 | /*
2 | * A preinitialised cmdline_get_passwd_input_state which makes it easy
3 | * to assign by structure copy.
4 | */
5 |
6 | #include "putty.h"
7 |
8 | const cmdline_get_passwd_input_state cmdline_get_passwd_input_state_new =
9 | CMDLINE_GET_PASSWD_INPUT_STATE_INIT;
10 |
--------------------------------------------------------------------------------
/utils/conf_dest.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Decide whether the 'host name' or 'serial line' field of a Conf is
3 | * important, based on which protocol it has selected.
4 | */
5 |
6 | #include "putty.h"
7 |
8 | char const *conf_dest(Conf *conf)
9 | {
10 | if (conf_get_int(conf, CONF_protocol) == PROT_SERIAL)
11 | return conf_get_str(conf, CONF_serline);
12 | else
13 | return conf_get_str(conf, CONF_host);
14 | }
15 |
16 |
--------------------------------------------------------------------------------
/utils/conf_launchable.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Determine whether or not a Conf represents a session which can
3 | * sensibly be launched right now.
4 | */
5 |
6 | #include "putty.h"
7 |
8 | bool conf_launchable(Conf *conf)
9 | {
10 | if (conf_get_int(conf, CONF_protocol) == PROT_SERIAL)
11 | return conf_get_str(conf, CONF_serline)[0] != 0;
12 | else
13 | return conf_get_str(conf, CONF_host)[0] != 0;
14 | }
15 |
--------------------------------------------------------------------------------
/utils/ctrlparse.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Parse a ^C style character specification.
3 | * Returns NULL in `next' if we didn't recognise it as a control character,
4 | * in which case `c' should be ignored.
5 | * The precise current parsing is an oddity inherited from the terminal
6 | * answerback-string parsing code. All sequences start with ^; all except
7 | * ^<123> are two characters. The ones that are worth keeping are probably:
8 | * ^? 127
9 | * ^@A-Z[\]^_ 0-31
10 | * a-z 1-26
11 | * specified by number (decimal, 0octal, 0xHEX)
12 | * ~ ^ escape
13 | */
14 |
15 | #include
16 |
17 | #include "defs.h"
18 | #include "misc.h"
19 |
20 | char ctrlparse(char *s, char **next)
21 | {
22 | char c = 0;
23 | if (*s != '^') {
24 | *next = NULL;
25 | } else {
26 | s++;
27 | if (*s == '\0') {
28 | *next = NULL;
29 | } else if (*s == '<') {
30 | s++;
31 | c = (char)strtol(s, next, 0);
32 | if ((*next == s) || (**next != '>')) {
33 | c = 0;
34 | *next = NULL;
35 | } else
36 | (*next)++;
37 | } else if (*s >= 'a' && *s <= 'z') {
38 | c = (*s - ('a' - 1));
39 | *next = s+1;
40 | } else if ((*s >= '@' && *s <= '_') || *s == '?' || (*s & 0x80)) {
41 | c = ('@' ^ *s);
42 | *next = s+1;
43 | } else if (*s == '~') {
44 | c = '^';
45 | *next = s+1;
46 | }
47 | }
48 | return c;
49 | }
50 |
--------------------------------------------------------------------------------
/utils/debug.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Debugging routines used by the debug() macros, at least if you
3 | * compiled with -DDEBUG (aka the PUTTY_DEBUG cmake option) so that
4 | * those macros don't optimise down to nothing.
5 | */
6 |
7 | #include "defs.h"
8 | #include "misc.h"
9 | #include "utils/utils.h"
10 |
11 | void debug_printf(const char *fmt, ...)
12 | {
13 | char *buf;
14 | va_list ap;
15 |
16 | va_start(ap, fmt);
17 | buf = dupvprintf(fmt, ap);
18 | dputs(buf);
19 | sfree(buf);
20 | va_end(ap);
21 | }
22 |
23 | void debug_memdump(const void *buf, int len, bool L)
24 | {
25 | int i;
26 | const unsigned char *p = buf;
27 | char foo[17];
28 | if (L) {
29 | int delta;
30 | debug_printf("\t%d (0x%x) bytes:\n", len, len);
31 | delta = 15 & (uintptr_t)p;
32 | p -= delta;
33 | len += delta;
34 | }
35 | for (; 0 < len; p += 16, len -= 16) {
36 | dputs(" ");
37 | if (L)
38 | debug_printf("%p: ", p);
39 | strcpy(foo, "................"); /* sixteen dots */
40 | for (i = 0; i < 16 && i < len; ++i) {
41 | if (&p[i] < (unsigned char *) buf) {
42 | dputs(" "); /* 3 spaces */
43 | foo[i] = ' ';
44 | } else {
45 | debug_printf("%c%2.2x",
46 | &p[i] != (unsigned char *) buf
47 | && i % 4 ? '.' : ' ', p[i]
48 | );
49 | if (p[i] >= ' ' && p[i] <= '~')
50 | foo[i] = (char) p[i];
51 | }
52 | }
53 | foo[i] = '\0';
54 | debug_printf("%*s%s\n", (16 - i) * 3 + 2, "", foo);
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/utils/decode_utf8_to_wchar.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Decode a single UTF-8 character to the platform's local wchar_t.
3 | */
4 |
5 | #include "putty.h"
6 | #include "misc.h"
7 |
8 | size_t decode_utf8_to_wchar(BinarySource *src, wchar_t *out,
9 | DecodeUTF8Failure *err)
10 | {
11 | size_t outlen = 0;
12 | unsigned wc = decode_utf8(src, err);
13 | if (sizeof(wchar_t) > 2 || wc < 0x10000) {
14 | out[outlen++] = wc;
15 | } else {
16 | unsigned wcoff = wc - 0x10000;
17 | out[outlen++] = 0xD800 | (0x3FF & (wcoff >> 10));
18 | out[outlen++] = 0xDC00 | (0x3FF & wcoff);
19 | }
20 | return outlen;
21 | }
22 |
--------------------------------------------------------------------------------
/utils/decode_utf8_to_wide_string.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Decode a string of UTF-8 to a wchar_t string.
3 | */
4 |
5 | #include "misc.h"
6 |
7 | wchar_t *decode_utf8_to_wide_string(const char *s)
8 | {
9 | wchar_t *ws = NULL;
10 | size_t wlen = 0, wsize = 0;
11 |
12 | BinarySource src[1];
13 | BinarySource_BARE_INIT_PL(src, ptrlen_from_asciz(s));
14 |
15 | while (get_avail(src) > 0) {
16 | /*
17 | * decode_utf8_to_wchar might emit up to 2 wchar_t if wchar_t
18 | * is 16 bits (because of UTF-16 surrogates), but will emit at
19 | * most one if wchar_t is 32-bit
20 | */
21 | sgrowarrayn(ws, wsize, wlen, 1 + (sizeof(wchar_t) < 4));
22 |
23 | /* We ignore 'err': if it is set, then the character decode
24 | * function will have emitted U+FFFD REPLACEMENT CHARACTER,
25 | * which is what we'd have done in response anyway. */
26 | DecodeUTF8Failure err;
27 | wlen += decode_utf8_to_wchar(src, ws + wlen, &err);
28 | }
29 |
30 | /* Reallocate to the final size and append the trailing NUL */
31 | ws = sresize(ws, wlen + 1, wchar_t);
32 | ws[wlen] = L'\0';
33 |
34 | return ws;
35 | }
36 |
--------------------------------------------------------------------------------
/utils/default_description.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Construct a description string for a backend to use as
3 | * backend_description(), or a plug as plug_description().
4 | *
5 | * For some backends this will be overridden: e.g. SSH prefers to
6 | * think in terms of _logical_ host names (i.e. the one associated
7 | * with the host key) rather than the physical details of where you're
8 | * connecting to. But this default is good for simpler backends.
9 | */
10 |
11 | #include "putty.h"
12 |
13 | char *default_description(const BackendVtable *backvt,
14 | const char *host, int port)
15 | {
16 | const char *be_name = backvt->displayname_lc;
17 |
18 | if (backvt->default_port && port == backvt->default_port)
19 | return dupprintf("%s connection to %s", be_name, host);
20 | else
21 | return dupprintf("%s connection to %s port %d", be_name, host, port);
22 | }
23 |
--------------------------------------------------------------------------------
/utils/dup_mb_to_wc.c:
--------------------------------------------------------------------------------
1 | /*
2 | * dup_mb_to_wc: memory-allocating wrapper on mb_to_wc.
3 | *
4 | * Also dup_mb_to_wc_c: same but you already know the length of the
5 | * string, and you get told the length of the returned wide string.
6 | * (But it's still NUL-terminated, for convenience.)
7 | */
8 |
9 | #include "putty.h"
10 | #include "misc.h"
11 |
12 | wchar_t *dup_mb_to_wc_c(int codepage, int flags, const char *string,
13 | size_t inlen, size_t *outlen_p)
14 | {
15 | assert(inlen <= INT_MAX);
16 | size_t mult;
17 | for (mult = 1 ;; mult++) {
18 | wchar_t *ret = snewn(mult*inlen + 2, wchar_t);
19 | size_t outlen = mb_to_wc(codepage, flags, string, inlen, ret,
20 | mult*inlen + 1);
21 | if (outlen < mult*inlen+1) {
22 | if (outlen_p)
23 | *outlen_p = outlen;
24 | ret[outlen] = L'\0';
25 | return ret;
26 | }
27 | sfree(ret);
28 | }
29 | }
30 |
31 | wchar_t *dup_mb_to_wc(int codepage, int flags, const char *string)
32 | {
33 | return dup_mb_to_wc_c(codepage, flags, string, strlen(string), NULL);
34 | }
35 |
--------------------------------------------------------------------------------
/utils/dup_wc_to_mb.c:
--------------------------------------------------------------------------------
1 | /*
2 | * dup_wc_to_mb: memory-allocating wrapper on wc_to_mb.
3 | *
4 | * Also dup_wc_to_mb_c: same but you already know the length of the
5 | * wide string, and you get told the length of the returned string.
6 | * (But it's still NUL-terminated, for convenience.).
7 | */
8 |
9 | #include
10 |
11 | #include "putty.h"
12 | #include "misc.h"
13 |
14 | char *dup_wc_to_mb_c(int codepage, int flags, const wchar_t *string,
15 | size_t inlen, const char *defchr, size_t *outlen_p)
16 | {
17 | assert(inlen <= INT_MAX);
18 |
19 | size_t outsize = inlen+1;
20 | char *out = snewn(outsize, char);
21 |
22 | while (true) {
23 | size_t outlen = wc_to_mb(codepage, flags, string, inlen, out, outsize,
24 | defchr);
25 | /* We can only be sure we've consumed the whole input if the
26 | * output is not within a multibyte-character-length of the
27 | * end of the buffer! */
28 | if (outlen < outsize && outsize - outlen > MB_LEN_MAX) {
29 | if (outlen_p)
30 | *outlen_p = outlen;
31 | out[outlen] = '\0';
32 | return out;
33 | }
34 |
35 | sgrowarray(out, outsize, outsize);
36 | }
37 | }
38 |
39 | char *dup_wc_to_mb(int codepage, int flags, const wchar_t *string,
40 | const char *defchr)
41 | {
42 | return dup_wc_to_mb_c(codepage, flags, string, wcslen(string),
43 | defchr, NULL);
44 | }
45 |
--------------------------------------------------------------------------------
/utils/dupcat.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Implementation function behind dupcat() in misc.h.
3 | *
4 | * This function is called with an arbitrary number of 'const char *'
5 | * parameters, of which the last one is a null pointer. The wrapper
6 | * macro puts on the null pointer itself, so normally callers don't
7 | * have to.
8 | */
9 |
10 | #include
11 | #include
12 |
13 | #include "defs.h"
14 | #include "misc.h"
15 |
16 | char *dupcat_fn(const char *s1, ...)
17 | {
18 | int len;
19 | char *p, *q, *sn;
20 | va_list ap;
21 |
22 | len = strlen(s1);
23 | va_start(ap, s1);
24 | while (1) {
25 | sn = va_arg(ap, char *);
26 | if (!sn)
27 | break;
28 | len += strlen(sn);
29 | }
30 | va_end(ap);
31 |
32 | p = snewn(len + 1, char);
33 | strcpy(p, s1);
34 | q = p + strlen(p);
35 |
36 | va_start(ap, s1);
37 | while (1) {
38 | sn = va_arg(ap, char *);
39 | if (!sn)
40 | break;
41 | strcpy(q, sn);
42 | q += strlen(q);
43 | }
44 | va_end(ap);
45 |
46 | return p;
47 | }
48 |
49 |
--------------------------------------------------------------------------------
/utils/dupstr.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Allocate a duplicate of an ordinary C NUL-terminated string.
3 | */
4 |
5 | #include
6 |
7 | #include "defs.h"
8 | #include "misc.h"
9 |
10 | char *dupstr(const char *s)
11 | {
12 | char *p = NULL;
13 | if (s) {
14 | int len = strlen(s);
15 | p = snewn(len + 1, char);
16 | strcpy(p, s);
17 | }
18 | return p;
19 | }
20 |
--------------------------------------------------------------------------------
/utils/dupwcs.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Allocate a duplicate of a NUL-terminated wchar_t string.
3 | */
4 |
5 | #include
6 |
7 | #include "defs.h"
8 | #include "misc.h"
9 |
10 | wchar_t *dupwcs(const wchar_t *s)
11 | {
12 | wchar_t *p = NULL;
13 | if (s) {
14 | int len = wcslen(s);
15 | p = snewn(len + 1, wchar_t);
16 | wcscpy(p, s);
17 | }
18 | return p;
19 | }
20 |
--------------------------------------------------------------------------------
/utils/encode_utf8.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Encode a single code point as UTF-8.
3 | */
4 |
5 | #include "defs.h"
6 | #include "misc.h"
7 |
8 | void BinarySink_put_utf8_char(BinarySink *output, unsigned ch)
9 | {
10 | if (ch < 0x80) {
11 | put_byte(output, ch);
12 | } else if (ch < 0x800) {
13 | put_byte(output, 0xC0 | (ch >> 6));
14 | put_byte(output, 0x80 | (ch & 0x3F));
15 | } else if (ch < 0x10000) {
16 | put_byte(output, 0xE0 | (ch >> 12));
17 | put_byte(output, 0x80 | ((ch >> 6) & 0x3F));
18 | put_byte(output, 0x80 | (ch & 0x3F));
19 | } else {
20 | assert(ch <= 0x10FFFF);
21 | put_byte(output, 0xF0 | (ch >> 18));
22 | put_byte(output, 0x80 | ((ch >> 12) & 0x3F));
23 | put_byte(output, 0x80 | ((ch >> 6) & 0x3F));
24 | put_byte(output, 0x80 | (ch & 0x3F));
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/utils/encode_wide_string_as_utf8.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Encode a string of wchar_t as UTF-8.
3 | */
4 |
5 | #include "putty.h"
6 | #include "misc.h"
7 |
8 | char *encode_wide_string_as_utf8(const wchar_t *ws)
9 | {
10 | strbuf *sb = strbuf_new();
11 | while (*ws) {
12 | unsigned long ch = *ws++;
13 | if (sizeof(wchar_t) == 2 && IS_HIGH_SURROGATE(ch) &&
14 | IS_LOW_SURROGATE(*ws)) {
15 | ch = FROM_SURROGATES(ch, *ws);
16 | ws++;
17 | } else if (IS_SURROGATE(ch)) {
18 | ch = 0xfffd; /* illegal UTF-16 -> REPLACEMENT CHARACTER */
19 | }
20 | put_utf8_char(sb, ch);
21 | }
22 | return strbuf_to_str(sb);
23 | }
24 |
--------------------------------------------------------------------------------
/utils/fgetline.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Read an entire line of text from a file. Return a buffer
3 | * malloced to be as big as necessary (caller must free).
4 | */
5 |
6 | #include "defs.h"
7 | #include "misc.h"
8 |
9 | char *fgetline(FILE *fp)
10 | {
11 | char *ret = snewn(512, char);
12 | size_t size = 512, len = 0;
13 | while (fgets(ret + len, size - len, fp)) {
14 | len += strlen(ret + len);
15 | if (len > 0 && ret[len-1] == '\n')
16 | break; /* got a newline, we're done */
17 | sgrowarrayn_nm(ret, size, len, 512);
18 | }
19 | if (len == 0) { /* first fgets returned NULL */
20 | sfree(ret);
21 | return NULL;
22 | }
23 | ret[len] = '\0';
24 | return ret;
25 | }
26 |
--------------------------------------------------------------------------------
/utils/host_ca_new_free.c:
--------------------------------------------------------------------------------
1 | #include "defs.h"
2 | #include "misc.h"
3 | #include "storage.h"
4 |
5 | host_ca *host_ca_new(void)
6 | {
7 | host_ca *hca = snew(host_ca);
8 | memset(hca, 0, sizeof(*hca));
9 | hca->opts.permit_rsa_sha1 = false;
10 | hca->opts.permit_rsa_sha256 = true;
11 | hca->opts.permit_rsa_sha512 = true;
12 | return hca;
13 | }
14 |
15 | void host_ca_free(host_ca *hca)
16 | {
17 | sfree(hca->name);
18 | sfree(hca->validity_expression);
19 | if (hca->ca_public_key)
20 | strbuf_free(hca->ca_public_key);
21 | sfree(hca);
22 | }
23 |
--------------------------------------------------------------------------------
/utils/host_strchr.c:
--------------------------------------------------------------------------------
1 | /*
2 | * strchr-like wrapper around host_strchr_internal.
3 | */
4 |
5 | #include
6 | #include
7 |
8 | #include "defs.h"
9 | #include "misc.h"
10 | #include "utils/utils.h"
11 |
12 | char *host_strchr(const char *s, int c)
13 | {
14 | char set[2];
15 | set[0] = c;
16 | set[1] = '\0';
17 | return (char *) host_strchr_internal(s, set, true);
18 | }
19 |
--------------------------------------------------------------------------------
/utils/host_strcspn.c:
--------------------------------------------------------------------------------
1 | /*
2 | * strcspn-like wrapper around host_strchr_internal.
3 | */
4 |
5 | #include
6 | #include
7 |
8 | #include "defs.h"
9 | #include "misc.h"
10 | #include "utils/utils.h"
11 |
12 | size_t host_strcspn(const char *s, const char *set)
13 | {
14 | const char *answer = host_strchr_internal(s, set, true);
15 | if (answer)
16 | return answer - s;
17 | else
18 | return strlen(s);
19 | }
20 |
--------------------------------------------------------------------------------
/utils/host_strduptrim.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Trim square brackets off the outside of an IPv6 address literal.
3 | * Leave all other strings unchanged. Returns a fresh dynamically
4 | * allocated string.
5 | */
6 |
7 | #include
8 | #include
9 |
10 | #include "defs.h"
11 | #include "misc.h"
12 |
13 | char *host_strduptrim(const char *s)
14 | {
15 | if (s[0] == '[') {
16 | const char *p = s+1;
17 | int colons = 0;
18 | while (*p && *p != ']') {
19 | if (isxdigit((unsigned char)*p))
20 | /* OK */;
21 | else if (*p == ':')
22 | colons++;
23 | else
24 | break;
25 | p++;
26 | }
27 | if (*p == '%') {
28 | /*
29 | * This delimiter character introduces an RFC 4007 scope
30 | * id suffix (e.g. suffixing the address literal with
31 | * %eth1 or %2 or some such). There's no syntax
32 | * specification for the scope id, so just accept anything
33 | * except the closing ].
34 | */
35 | p += strcspn(p, "]");
36 | }
37 | if (*p == ']' && !p[1] && colons > 1) {
38 | /*
39 | * This looks like an IPv6 address literal (hex digits and
40 | * at least two colons, plus optional scope id, contained
41 | * in square brackets). Trim off the brackets.
42 | */
43 | return dupprintf("%.*s", (int)(p - (s+1)), s+1);
44 | }
45 | }
46 |
47 | /*
48 | * Any other shape of string is simply duplicated.
49 | */
50 | return dupstr(s);
51 | }
52 |
--------------------------------------------------------------------------------
/utils/host_strrchr.c:
--------------------------------------------------------------------------------
1 | /*
2 | * strchr-like wrapper around host_strchr_internal.
3 | */
4 |
5 | #include
6 | #include
7 |
8 | #include "defs.h"
9 | #include "misc.h"
10 | #include "utils/utils.h"
11 |
12 | char *host_strrchr(const char *s, int c)
13 | {
14 | char set[2];
15 | set[0] = c;
16 | set[1] = '\0';
17 | return (char *) host_strchr_internal(s, set, false);
18 | }
19 |
--------------------------------------------------------------------------------
/utils/logeventf.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Helpful wrapper functions around the raw logevent().
3 | *
4 | * This source file lives in 'utils' because it's conceptually a
5 | * convenience utility rather than core functionality. But it can't
6 | * live in the utils _library_, because then it might refer to
7 | * logevent() in an earlier library after Unix ld had already finished
8 | * searching that library, and cause a link failure. So it must live
9 | * alongside logging.c.
10 | */
11 |
12 | #include "putty.h"
13 |
14 | void logevent_and_free(LogContext *ctx, char *event)
15 | {
16 | logevent(ctx, event);
17 | sfree(event);
18 | }
19 |
20 | void logeventvf(LogContext *ctx, const char *fmt, va_list ap)
21 | {
22 | logevent_and_free(ctx, dupvprintf(fmt, ap));
23 | }
24 |
25 | void logeventf(LogContext *ctx, const char *fmt, ...)
26 | {
27 | va_list ap;
28 |
29 | va_start(ap, fmt);
30 | logeventvf(ctx, fmt, ap);
31 | va_end(ap);
32 | }
33 |
--------------------------------------------------------------------------------
/utils/ltime.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Portable implementation of ltime() for any ISO-C platform where
3 | * time_t behaves. (In practice, we've found that platforms such as
4 | * Windows and Mac have needed their own specialised implementations.)
5 | */
6 |
7 | #include
8 | #include
9 |
10 | struct tm ltime(void)
11 | {
12 | time_t t;
13 | time(&t);
14 | assert (t != ((time_t)-1));
15 | return *localtime(&t);
16 | }
17 |
--------------------------------------------------------------------------------
/utils/make_spr_sw_abort_static.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Constructor function for a SeatPromptResult of the 'software abort'
3 | * category, whose error message is in the simplest possible form of a
4 | * static string constant.
5 | */
6 |
7 | #include "putty.h"
8 |
9 | static void spr_static_errfn(SeatPromptResult spr, BinarySink *bs)
10 | {
11 | put_dataz(bs, spr.errdata_lit);
12 | }
13 |
14 | SeatPromptResult make_spr_sw_abort_static(const char *str)
15 | {
16 | SeatPromptResult spr;
17 | spr.kind = SPRK_SW_ABORT;
18 | spr.errfn = spr_static_errfn;
19 | spr.errdata_lit = str;
20 | return spr;
21 | }
22 |
--------------------------------------------------------------------------------
/utils/memxor.c:
--------------------------------------------------------------------------------
1 | /*
2 | * XOR two pieces of memory, copying the result into a third, which
3 | * may precisely alias one of the input pair (but no guarantees if it
4 | * partially overlaps).
5 | */
6 |
7 | #include "defs.h"
8 | #include "misc.h"
9 |
10 | void memxor(uint8_t *out, const uint8_t *in1, const uint8_t *in2, size_t size)
11 | {
12 | switch (size & 15) {
13 | case 0:
14 | while (size >= 16) {
15 | size -= 16;
16 | *out++ = *in1++ ^ *in2++;
17 | case 15: *out++ = *in1++ ^ *in2++;
18 | case 14: *out++ = *in1++ ^ *in2++;
19 | case 13: *out++ = *in1++ ^ *in2++;
20 | case 12: *out++ = *in1++ ^ *in2++;
21 | case 11: *out++ = *in1++ ^ *in2++;
22 | case 10: *out++ = *in1++ ^ *in2++;
23 | case 9: *out++ = *in1++ ^ *in2++;
24 | case 8: *out++ = *in1++ ^ *in2++;
25 | case 7: *out++ = *in1++ ^ *in2++;
26 | case 6: *out++ = *in1++ ^ *in2++;
27 | case 5: *out++ = *in1++ ^ *in2++;
28 | case 4: *out++ = *in1++ ^ *in2++;
29 | case 3: *out++ = *in1++ ^ *in2++;
30 | case 2: *out++ = *in1++ ^ *in2++;
31 | case 1: *out++ = *in1++ ^ *in2++;
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/utils/nullstrcmp.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Compare two strings, just like strcmp, except that we tolerate null
3 | * pointers as a legal input, and define them to compare before any
4 | * non-null string (even the empty string).
5 | */
6 |
7 | #include
8 |
9 | #include "defs.h"
10 | #include "misc.h"
11 |
12 | int nullstrcmp(const char *a, const char *b)
13 | {
14 | if (a == NULL && b == NULL)
15 | return 0;
16 | if (a == NULL)
17 | return -1;
18 | if (b == NULL)
19 | return +1;
20 | return strcmp(a, b);
21 | }
22 |
--------------------------------------------------------------------------------
/utils/out_of_memory.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Standard implementation of the out_of_memory function called by our
3 | * malloc wrappers.
4 | */
5 |
6 | #include "putty.h"
7 |
8 | void out_of_memory(void)
9 | {
10 | modalfatalbox("Out of memory");
11 | }
12 |
--------------------------------------------------------------------------------
/utils/parse_blocksize.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Parse a string block size specification. This is approximately a
3 | * subset of the block size specs supported by GNU fileutils:
4 | * "nk" = n kilobytes
5 | * "nM" = n megabytes
6 | * "nG" = n gigabytes
7 | * All numbers are decimal, and suffixes refer to powers of two.
8 | * Case-insensitive.
9 | */
10 |
11 | #include
12 | #include
13 | #include
14 |
15 | #include "defs.h"
16 | #include "misc.h"
17 |
18 | unsigned long parse_blocksize(const char *bs)
19 | {
20 | char *suf;
21 | unsigned long r = strtoul(bs, &suf, 10);
22 | if (*suf != '\0') {
23 | while (*suf && isspace((unsigned char)*suf)) suf++;
24 | switch (*suf) {
25 | case 'k': case 'K':
26 | r *= 1024ul;
27 | break;
28 | case 'm': case 'M':
29 | r *= 1024ul * 1024ul;
30 | break;
31 | case 'g': case 'G':
32 | r *= 1024ul * 1024ul * 1024ul;
33 | break;
34 | case '\0':
35 | default:
36 | break;
37 | }
38 | }
39 | return r;
40 | }
41 |
--------------------------------------------------------------------------------
/utils/percent_decode.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Decode %-encoding in URL style.
3 | */
4 |
5 | #include
6 |
7 | #include "misc.h"
8 |
9 | void percent_decode_bs(BinarySink *bs, ptrlen data)
10 | {
11 | for (const char *p = data.ptr, *e = ptrlen_end(data); p < e; p++) {
12 | char c = *p;
13 | if (c == '%' && e-p >= 3 &&
14 | isxdigit((unsigned char)p[1]) &&
15 | isxdigit((unsigned char)p[2])) {
16 | char hex[3];
17 | hex[0] = p[1];
18 | hex[1] = p[2];
19 | hex[2] = '\0';
20 | put_byte(bs, strtoul(hex, NULL, 16));
21 | p += 2;
22 | } else {
23 | put_byte(bs, c);
24 | }
25 | }
26 |
27 | }
28 |
29 | void percent_decode_fp(FILE *fp, ptrlen data)
30 | {
31 | stdio_sink ss;
32 | stdio_sink_init(&ss, fp);
33 | percent_decode_bs(BinarySink_UPCAST(&ss), data);
34 | }
35 |
36 | strbuf *percent_decode_sb(ptrlen data)
37 | {
38 | strbuf *sb = strbuf_new();
39 | percent_decode_bs(BinarySink_UPCAST(sb), data);
40 | return sb;
41 | }
42 |
--------------------------------------------------------------------------------
/utils/percent_encode.c:
--------------------------------------------------------------------------------
1 | /*
2 | * %-encoding in URL style.
3 | *
4 | * Defaults to escaping % itself (necessary for decoding to even
5 | * work), and any C0 escape character. Further bad characters can be
6 | * provided in 'badchars'.
7 | */
8 |
9 | #include "misc.h"
10 |
11 | void percent_encode_bs(BinarySink *bs, ptrlen data, const char *badchars)
12 | {
13 | for (const char *p = data.ptr, *e = ptrlen_end(data); p < e; p++) {
14 | char c = *p;
15 | if (c == '%' || c < ' ' || (badchars && strchr(badchars, c)))
16 | put_fmt(bs, "%%%02X", (unsigned char)c);
17 | else
18 | put_byte(bs, c);
19 | }
20 | }
21 |
22 | void percent_encode_fp(FILE *fp, ptrlen data, const char *badchars)
23 | {
24 | stdio_sink ss;
25 | stdio_sink_init(&ss, fp);
26 | percent_encode_bs(BinarySink_UPCAST(&ss), data, badchars);
27 | }
28 |
29 | strbuf *percent_encode_sb(ptrlen data, const char *badchars)
30 | {
31 | strbuf *sb = strbuf_new();
32 | percent_encode_bs(BinarySink_UPCAST(sb), data, badchars);
33 | return sb;
34 | }
35 |
--------------------------------------------------------------------------------
/utils/read_file_into.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Read an entire file into a BinarySink.
3 | */
4 |
5 | #include
6 |
7 | #include "defs.h"
8 | #include "misc.h"
9 |
10 | bool read_file_into(BinarySink *bs, FILE *fp)
11 | {
12 | char buf[4096];
13 | while (1) {
14 | size_t retd = fread(buf, 1, sizeof(buf), fp);
15 | if (retd == 0)
16 | return !ferror(fp);
17 | put_data(bs, buf, retd);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/utils/seat_connection_fatal.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Wrapper function for the connection_fatal() method of a Seat,
3 | * providing printf-style formatting.
4 | */
5 |
6 | #include "putty.h"
7 |
8 | void seat_connection_fatal(Seat *seat, const char *fmt, ...)
9 | {
10 | va_list ap;
11 | char *msg;
12 |
13 | va_start(ap, fmt);
14 | msg = dupvprintf(fmt, ap);
15 | va_end(ap);
16 |
17 | seat->vt->connection_fatal(seat, msg);
18 | sfree(msg); /* if we return */
19 | }
20 |
21 |
--------------------------------------------------------------------------------
/utils/seat_dialog_text.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Helper routines for dealing with SeatDialogText structures.
3 | */
4 |
5 | #include
6 |
7 | #include "putty.h"
8 |
9 | SeatDialogText *seat_dialog_text_new(void)
10 | {
11 | SeatDialogText *sdt = snew(SeatDialogText);
12 | sdt->nitems = sdt->itemsize = 0;
13 | sdt->items = NULL;
14 | return sdt;
15 | }
16 |
17 | void seat_dialog_text_free(SeatDialogText *sdt)
18 | {
19 | for (size_t i = 0; i < sdt->nitems; i++)
20 | sfree(sdt->items[i].text);
21 | sfree(sdt->items);
22 | sfree(sdt);
23 | }
24 |
25 | static void seat_dialog_text_append_v(
26 | SeatDialogText *sdt, SeatDialogTextType type, const char *fmt, va_list ap)
27 | {
28 | sgrowarray(sdt->items, sdt->itemsize, sdt->nitems);
29 | SeatDialogTextItem *item = &sdt->items[sdt->nitems++];
30 | item->type = type;
31 | item->text = dupvprintf(fmt, ap);
32 | }
33 |
34 | void seat_dialog_text_append(SeatDialogText *sdt, SeatDialogTextType type,
35 | const char *fmt, ...)
36 | {
37 | va_list ap;
38 | va_start(ap, fmt);
39 | seat_dialog_text_append_v(sdt, type, fmt, ap);
40 | va_end(ap);
41 | }
42 |
--------------------------------------------------------------------------------
/utils/seat_nonfatal.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Wrapper function for the nonfatal() method of a Seat,
3 | * providing printf-style formatting.
4 | */
5 |
6 | #include "putty.h"
7 |
8 | void seat_nonfatal(Seat *seat, const char *fmt, ...)
9 | {
10 | va_list ap;
11 | char *msg;
12 |
13 | va_start(ap, fmt);
14 | msg = dupvprintf(fmt, ap);
15 | va_end(ap);
16 |
17 | seat->vt->nonfatal(seat, msg);
18 | sfree(msg);
19 | }
20 |
--------------------------------------------------------------------------------
/utils/sk_free_peer_info.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Free a SocketPeerInfo, and everything that dangles off it.
3 | */
4 |
5 | #include "putty.h"
6 |
7 | void sk_free_peer_info(SocketPeerInfo *pi)
8 | {
9 | if (pi) {
10 | sfree((char *)pi->addr_text);
11 | sfree((char *)pi->log_text);
12 | sfree(pi);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/utils/smemeq.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Compare two fixed-size regions of memory, in a crypto-safe way,
3 | * i.e. without timing or cache side channels indicating anything
4 | * about what the answer was or where the first difference (if any)
5 | * might have been.
6 | */
7 |
8 | #include "defs.h"
9 | #include "misc.h"
10 |
11 | unsigned smemeq(const void *av, const void *bv, size_t len)
12 | {
13 | const unsigned char *a = (const unsigned char *)av;
14 | const unsigned char *b = (const unsigned char *)bv;
15 | unsigned val = 0;
16 |
17 | while (len-- > 0) {
18 | val |= *a++ ^ *b++;
19 | }
20 | /* Now val is 0 iff we want to return 1, and in the range
21 | * 0x01..0xFF iff we want to return 0. So subtracting from 0x100
22 | * will clear bit 8 iff we want to return 0, and leave it set iff
23 | * we want to return 1, so then we can just shift down. */
24 | return (0x100 - val) >> 8;
25 | }
26 |
--------------------------------------------------------------------------------
/utils/spr_get_error_message.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Construct the error message from a SeatPromptResult, and return it
3 | * in a dynamically allocated string.
4 | */
5 |
6 | #include "putty.h"
7 |
8 | char *spr_get_error_message(SeatPromptResult spr)
9 | {
10 | strbuf *sb = strbuf_new();
11 | spr.errfn(spr, BinarySink_UPCAST(sb));
12 | return strbuf_to_str(sb);
13 | }
14 |
--------------------------------------------------------------------------------
/utils/ssh2_pick_fingerprint.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Choose an SSH-2 fingerprint type, out of an array of possible ones.
3 | */
4 |
5 | #include "defs.h"
6 | #include "misc.h"
7 | #include "ssh.h"
8 |
9 | FingerprintType ssh2_pick_fingerprint(
10 | char **fingerprints, FingerprintType preferred_type)
11 | {
12 | /*
13 | * Keys are either SSH-2, in which case we have all fingerprint
14 | * types, or SSH-1, in which case we have only MD5. So we return
15 | * the default type if we can, or MD5 if that's all we have; no
16 | * need for a fully general preference-list system.
17 | */
18 | FingerprintType fptype = fingerprints[preferred_type] ?
19 | preferred_type : SSH_FPTYPE_MD5;
20 | assert(fingerprints[fptype]);
21 | return fptype;
22 | }
23 |
24 | FingerprintType ssh2_pick_default_fingerprint(char **fingerprints)
25 | {
26 | return ssh2_pick_fingerprint(fingerprints, SSH_FPTYPE_DEFAULT);
27 | }
28 |
--------------------------------------------------------------------------------
/utils/ssh_key_clone.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Make a copy of an existing ssh_key object, e.g. to survive after
3 | * the original is freed.
4 | */
5 |
6 | #include "misc.h"
7 | #include "ssh.h"
8 |
9 | ssh_key *ssh_key_clone(ssh_key *key)
10 | {
11 | /*
12 | * To avoid having to add a special method in the vtable API, we
13 | * clone by round-tripping through public and private blobs.
14 | */
15 | strbuf *pub = strbuf_new_nm();
16 | ssh_key_public_blob(key, BinarySink_UPCAST(pub));
17 |
18 | ssh_key *copy;
19 |
20 | if (ssh_key_has_private(key)) {
21 | strbuf *priv = strbuf_new_nm();
22 | ssh_key_private_blob(key, BinarySink_UPCAST(priv));
23 | copy = ssh_key_new_priv(ssh_key_alg(key), ptrlen_from_strbuf(pub),
24 | ptrlen_from_strbuf(priv));
25 | strbuf_free(priv);
26 | } else {
27 | copy = ssh_key_new_pub(ssh_key_alg(key), ptrlen_from_strbuf(pub));
28 | }
29 |
30 | strbuf_free(pub);
31 | return copy;
32 | }
33 |
--------------------------------------------------------------------------------
/utils/string_length_for_printf.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Convert a size_t value to int, by saturating it at INT_MAX. Useful
3 | * if you want to use the printf idiom "%.*s", where the '*' precision
4 | * specifier expects an int in the variadic argument list, but what
5 | * you have is not an int but a size_t. This method of converting to
6 | * int will at least do something _safe_ with overlong values, even if
7 | * (due to the limitation of printf itself) the whole string still
8 | * won't be printed.
9 | */
10 |
11 | #include
12 |
13 | #include "defs.h"
14 | #include "misc.h"
15 |
16 | int string_length_for_printf(size_t s)
17 | {
18 | if (s > INT_MAX)
19 | return INT_MAX;
20 | return s;
21 | }
22 |
--------------------------------------------------------------------------------
/utils/utils.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Internal header to the utils subdirectory, for definitions shared
3 | * between the library implementations but not intended to be exposed
4 | * further than that.
5 | */
6 |
7 | void dputs(const char *);
8 |
9 | char *dupvprintf_inner(char *buf, size_t oldlen, size_t *sizeptr,
10 | const char *fmt, va_list ap);
11 |
12 | const char *host_strchr_internal(const char *s, const char *set, bool first);
13 |
--------------------------------------------------------------------------------
/utils/version.c:
--------------------------------------------------------------------------------
1 | /*
2 | * PuTTY version numbering
3 | */
4 |
5 | /*
6 | * The difficult part of deciding what goes in these version strings
7 | * is done in Buildscr, and then written into version.h. All we have
8 | * to do here is to drop it into variables of the right names.
9 | */
10 |
11 | #include "putty.h"
12 | #include "ssh.h"
13 |
14 | #include "version.h"
15 |
16 | const char ver[] = TEXTVER;
17 | const char sshver[] = SSHVER;
18 |
19 | /*
20 | * SSH local version string MUST be under 40 characters. Here's a
21 | * compile time assertion to verify this.
22 | */
23 | enum { vorpal_sword = 1 / (sizeof(sshver) <= 40) };
24 |
--------------------------------------------------------------------------------
/utils/wordwrap.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Function to wrap text to a fixed number of columns.
3 | *
4 | * Currently, assumes the text is in a single-byte character set,
5 | * because it's only used to display host key prompt messages.
6 | * Extending to Unicode and using wcwidth() could be an extension.
7 | */
8 |
9 | #include "misc.h"
10 |
11 | void wordwrap(BinarySink *bs, ptrlen input, size_t maxwid)
12 | {
13 | size_t col = 0;
14 | while (true) {
15 | ptrlen word = ptrlen_get_word(&input, " ");
16 | if (!word.len)
17 | break;
18 |
19 | /* At the start of a line, any word is legal, even if it's
20 | * overlong, because we have to display it _somehow_ and
21 | * wrapping to the next line won't make it any better. */
22 | if (col > 0) {
23 | size_t newcol = col + 1 + word.len;
24 | if (newcol <= maxwid) {
25 | put_byte(bs, ' ');
26 | col++;
27 | } else {
28 | put_byte(bs, '\n');
29 | col = 0;
30 | }
31 | }
32 |
33 | put_datapl(bs, word);
34 | col += word.len;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/utils/write_c_string_literal.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Write data to a file or BinarySink in the form of a C string
3 | * literal, with any non-printable-ASCII character escaped
4 | * appropriately.
5 | */
6 |
7 | #include "defs.h"
8 | #include "misc.h"
9 |
10 | void BinarySink_put_c_string_literal(BinarySink *bs, ptrlen str)
11 | {
12 | for (const char *p = str.ptr; p < (const char *)str.ptr + str.len; p++) {
13 | char c = *p;
14 |
15 | if (c == '\n')
16 | put_datalit(bs, "\\n");
17 | else if (c == '\r')
18 | put_datalit(bs, "\\r");
19 | else if (c == '\t')
20 | put_datalit(bs, "\\t");
21 | else if (c == '\b')
22 | put_datalit(bs, "\\b");
23 | else if (c == '\\')
24 | put_datalit(bs, "\\\\");
25 | else if (c == '"')
26 | put_datalit(bs, "\\\"");
27 | else if (c >= 32 && c <= 126)
28 | put_byte(bs, c);
29 | else
30 | put_fmt(bs, "\\%03o", (unsigned)c & 0xFFU);
31 | }
32 | }
33 |
34 | void write_c_string_literal(FILE *fp, ptrlen str)
35 | {
36 | stdio_sink s;
37 | stdio_sink_init(&s, fp);
38 | put_c_string_literal(&s, str);
39 | }
40 |
--------------------------------------------------------------------------------
/utils/x11_dehexify.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Utility function to convert a textual representation of an X11
3 | * auth hex cookie into binary auth data.
4 | */
5 |
6 | #include "putty.h"
7 | #include "ssh.h"
8 |
9 | void *x11_dehexify(ptrlen hexpl, int *outlen)
10 | {
11 | int len, i;
12 | unsigned char *ret;
13 |
14 | len = hexpl.len / 2;
15 | ret = snewn(len, unsigned char);
16 |
17 | for (i = 0; i < len; i++) {
18 | char bytestr[3];
19 | unsigned val = 0;
20 | bytestr[0] = ((const char *)hexpl.ptr)[2*i];
21 | bytestr[1] = ((const char *)hexpl.ptr)[2*i+1];
22 | bytestr[2] = '\0';
23 | sscanf(bytestr, "%x", &val);
24 | ret[i] = val;
25 | }
26 |
27 | *outlen = len;
28 | return ret;
29 | }
30 |
--------------------------------------------------------------------------------
/utils/x11_identify_auth_proto.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Utility function to convert a textual representation of an X11
3 | * auth protocol name into our integer protocol ids.
4 | */
5 |
6 | #include "putty.h"
7 | #include "ssh.h"
8 |
9 | int x11_identify_auth_proto(ptrlen protoname)
10 | {
11 | int protocol;
12 |
13 | for (protocol = 1; protocol < lenof(x11_authnames); protocol++)
14 | if (ptrlen_eq_string(protoname, x11_authnames[protocol]))
15 | return protocol;
16 | return -1;
17 | }
18 |
--------------------------------------------------------------------------------
/utils/x11_parse_ip.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Try to make sense of a string as an IPv4 address, for
3 | * XDM-AUTHORIZATION-1 purposes.
4 | */
5 |
6 | #include
7 |
8 | #include "putty.h"
9 | #include "ssh.h"
10 |
11 | bool x11_parse_ip(const char *addr_string, unsigned long *ip)
12 | {
13 | int i[4];
14 | if (addr_string &&
15 | 4 == sscanf(addr_string, "%d.%d.%d.%d", i+0, i+1, i+2, i+3)) {
16 | *ip = (i[0] << 24) | (i[1] << 16) | (i[2] << 8) | i[3];
17 | return true;
18 | } else {
19 | return false;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/utils/x11authnames.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Definition of the array of X11 authorisation method names.
3 | */
4 |
5 | #include "putty.h"
6 |
7 | const char *const x11_authnames[X11_NAUTHS] = {
8 | "", "MIT-MAGIC-COOKIE-1", "XDM-AUTHORIZATION-1"
9 | };
10 |
--------------------------------------------------------------------------------
/version.h:
--------------------------------------------------------------------------------
1 | /*
2 | * This header file provides the various versioning-related #defines
3 | * for a particular PuTTY build.
4 | *
5 | * When my automated build system does a full build, Buildscr
6 | * completely overwrites this file with information derived from the
7 | * circumstances and type of that build. The information _here_ is
8 | * default stuff used for local development runs of 'make'.
9 | */
10 |
11 | #define TEXTVER "Unidentified build with far2l extensions support"
12 | #define SSHVER "-Unidentified-Local-Build"
13 | #define BINARY_VERSION 0,0,0,0
14 |
--------------------------------------------------------------------------------
/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 | What do I do if it doesn't work?
28 | --------------------------------
29 |
30 | The PuTTY home web site is
31 |
32 | https://www.chiark.greenend.org.uk/~sgtatham/putty/
33 |
34 | Here you will find our list of known bugs and pending feature
35 | requests. If your problem is not listed in there, or in the FAQ, or
36 | in the manuals, read the Feedback page to find out how to report
37 | bugs to us. PLEASE read the Feedback page carefully: it is there to
38 | save you time as well as us. Do not send us one-line bug reports
39 | telling us `it doesn't work'.
40 |
--------------------------------------------------------------------------------
/windows/cryptoapi.h:
--------------------------------------------------------------------------------
1 | /*
2 | * cryptoapi.h: Windows Crypto API functions defined in PuTTY that
3 | * use the crypt32 library. Also centralises the machinery for
4 | * dynamically loading that library, and our own functions using that
5 | * in turn.
6 | */
7 |
8 | DECL_WINDOWS_FUNCTION(extern, BOOL, CryptProtectMemory, (LPVOID,DWORD,DWORD));
9 |
10 | bool got_crypt(void);
11 |
12 | /*
13 | * Function to obfuscate an input string into something usable as a
14 | * pathname for a Windows named pipe. Uses CryptProtectMemory to make
15 | * the obfuscation depend on a key Windows stores for the owning user,
16 | * and then hashes the string as well to make it have a manageable
17 | * length and be composed of filename-legal characters.
18 | *
19 | * Rationale: Windows's named pipes all live in the same namespace, so
20 | * one user can see what pipes another user has open. This is an
21 | * undesirable privacy leak: in particular, if we used unobfuscated
22 | * names for the connection-sharing pipe names, it would permit one
23 | * user to know what username@host another user is SSHing to.
24 | *
25 | * The returned string is dynamically allocated.
26 | */
27 | char *capi_obfuscate_string(const char *realname);
28 |
--------------------------------------------------------------------------------
/windows/help.rc2:
--------------------------------------------------------------------------------
1 | #include "putty-rc.h"
2 |
3 | #ifdef EMBEDDED_CHM_FILE
4 | ID_CUSTOM_CHMFILE TYPE_CUSTOM_CHMFILE EMBEDDED_CHM_FILE
5 | #define HELPVER " (with embedded help)"
6 | #else
7 | #define HELPVER " (without embedded help)"
8 | #endif
9 |
--------------------------------------------------------------------------------
/windows/make_install_images.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # Script to make the bitmap files that go into the PuTTY MSI installer.
4 |
5 | set -e
6 |
7 | # For convenience, allow this script to be run from the Windows
8 | # subdirectory as well as the top level of the source tree.
9 | if test -f installer.wxs -a ! -f putty.h -a -f ../putty.h; then
10 | cd ..
11 | fi
12 |
13 | convert -size 164x312 'gradient:blue-white' -distort SRT -90 -swirl 180 \
14 | \( icons/putty-48.png -geometry +28+24 \) -composite \
15 | \( icons/pscp-48.png -geometry +88+96 \) -composite \
16 | \( icons/puttygen-48.png -geometry +28+168 \) -composite \
17 | \( icons/pageant-48.png -geometry +88+240 \) -composite \
18 | windows/msidialog.bmp
19 |
20 | convert -size 493x58 canvas:white \
21 | \( icons/putty-48.png -geometry +440+5 \) -composite \
22 | windows/msibanner.bmp
23 |
--------------------------------------------------------------------------------
/windows/no-jump-list.c:
--------------------------------------------------------------------------------
1 | /*
2 | * no-jump-list.c: stub jump list functions for Windows executables
3 | * that don't update the jump list.
4 | */
5 |
6 | #include "putty.h"
7 |
8 | void add_session_to_jumplist(const char * const sessionname) {}
9 | void remove_session_from_jumplist(const char * const sessionname) {}
10 | void clear_jumplist(void) {}
11 |
--------------------------------------------------------------------------------
/windows/nohelp.c:
--------------------------------------------------------------------------------
1 | /*
2 | * nohelp.c: implement the has_embedded_chm() function for
3 | * applications that have no help file at all, so that buildinfo.c's
4 | * buildinfo string knows not to talk meaninglessly about whether the
5 | * nonexistent help file is present.
6 | */
7 |
8 | #include
9 | #include
10 | #include
11 | #include
12 |
13 | #include "putty.h"
14 |
15 | int has_embedded_chm(void) { return -1; }
16 |
--------------------------------------------------------------------------------
/windows/pageant-rc.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Constant definitions for the Pageant resource file.
3 | */
4 |
5 | #define IDI_MAINICON 200
6 | #define IDI_TRAYICON 201
7 |
8 | #define IDD_KEYLIST 211
9 | #define IDD_LOAD_PASSPHRASE 210
10 | #define IDD_ONDEMAND_PASSPHRASE 212
11 | #define IDD_ABOUT 213
12 | #define IDD_LICENCE 214
13 |
14 | #define IDC_PASSPHRASE_STATIC1 100
15 | #define IDC_PASSPHRASE_FINGERPRINT 101
16 | #define IDC_PASSPHRASE_STATIC2 102
17 | #define IDC_PASSPHRASE_STATIC3 103
18 | #define IDC_PASSPHRASE_EDITBOX 104
19 |
20 | #define IDC_KEYLIST_LISTBOX 100
21 | #define IDC_KEYLIST_ADDKEY 101
22 | #define IDC_KEYLIST_ADDKEY_ENC 110
23 | #define IDC_KEYLIST_REENCRYPT 106
24 | #define IDC_KEYLIST_REMOVE 102
25 | #define IDC_KEYLIST_HELP 103
26 | #define IDC_KEYLIST_FPTYPE_STATIC 104
27 | #define IDC_KEYLIST_FPTYPE 105
28 |
29 | #define IDC_ABOUT_LICENCE 101
30 | #define IDC_ABOUT_WEBSITE 102
31 | #define IDC_ABOUT_TEXTBOX 1000
32 |
33 | #define IDC_LICENCE_TEXTBOX 1000
34 |
--------------------------------------------------------------------------------
/windows/pageant.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unxed/putty4far2l/1816bdba0554f9f4465b92bc0df95fb845ff4170/windows/pageant.ico
--------------------------------------------------------------------------------
/windows/pageant.mft:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
11 | PuTTY SSH authentication agent
12 |
13 |
14 |
16 |
22 |
23 |
24 |
25 |
26 |
28 | true
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/windows/pageants.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unxed/putty4far2l/1816bdba0554f9f4465b92bc0df95fb845ff4170/windows/pageants.ico
--------------------------------------------------------------------------------
/windows/plink.rc:
--------------------------------------------------------------------------------
1 | #include "rcstuff.h"
2 |
3 | #define APPNAME "Plink"
4 | #define APPDESC "Command-line SSH, Telnet, and Rlogin client"
5 |
6 | 200 ICON "putty.ico"
7 |
8 | #include "version.rc2"
9 |
--------------------------------------------------------------------------------
/windows/pscp.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unxed/putty4far2l/1816bdba0554f9f4465b92bc0df95fb845ff4170/windows/pscp.ico
--------------------------------------------------------------------------------
/windows/pscp.rc:
--------------------------------------------------------------------------------
1 | #include "rcstuff.h"
2 |
3 | #define APPNAME "PSCP"
4 | #define APPDESC "Command-line SCP/SFTP client"
5 |
6 | 200 ICON "pscp.ico"
7 |
8 | #include "version.rc2"
9 |
--------------------------------------------------------------------------------
/windows/psftp.rc:
--------------------------------------------------------------------------------
1 | #include "rcstuff.h"
2 |
3 | #define APPNAME "PSFTP"
4 | #define APPDESC "Command-line interactive SFTP client"
5 |
6 | 200 ICON "pscp.ico"
7 |
8 | #include "version.rc2"
9 |
--------------------------------------------------------------------------------
/windows/psocks.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Main program for Windows psocks.
3 | */
4 |
5 | #include "putty.h"
6 | #include "ssh.h"
7 | #include "psocks.h"
8 |
9 | static const PsocksPlatform platform = {
10 | NULL /* open_pipes */,
11 | NULL /* start_subcommand */,
12 | };
13 |
14 | int main(int argc, char **argv)
15 | {
16 | psocks_state *ps = psocks_new(&platform);
17 | psocks_cmdline(ps, argc, argv);
18 |
19 | sk_init();
20 | winselcli_setup();
21 | psocks_start(ps);
22 |
23 | cli_main_loop(cliloop_null_pre, cliloop_null_post, NULL);
24 | }
25 |
--------------------------------------------------------------------------------
/windows/pterm.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unxed/putty4far2l/1816bdba0554f9f4465b92bc0df95fb845ff4170/windows/pterm.ico
--------------------------------------------------------------------------------
/windows/pterm.rc:
--------------------------------------------------------------------------------
1 | #include "rcstuff.h"
2 | #include "putty-rc.h"
3 |
4 | #define APPNAME "pterm"
5 | #define APPDESC "PuTTY-style wrapper for Windows command prompts"
6 |
7 | IDI_MAINICON ICON "pterm.ico"
8 | IDI_CFGICON ICON "ptermcfg.ico"
9 |
10 | #include "help.rc2"
11 | #include "putty-common.rc2"
12 |
13 | #ifndef NO_MANIFESTS
14 | 1 RT_MANIFEST "putty.mft"
15 | #endif /* NO_MANIFESTS */
16 |
--------------------------------------------------------------------------------
/windows/ptermcfg.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unxed/putty4far2l/1816bdba0554f9f4465b92bc0df95fb845ff4170/windows/ptermcfg.ico
--------------------------------------------------------------------------------
/windows/putty-rc.h:
--------------------------------------------------------------------------------
1 | /*
2 | * putty-rc.h - constants shared between putty-common.rc2 and the C code.
3 | */
4 |
5 | #ifndef PUTTY_WIN_RES_H
6 | #define PUTTY_WIN_RES_H
7 |
8 | #define IDI_MAINICON 200
9 | #define IDI_CFGICON 201
10 |
11 | #define IDD_MAINBOX 102
12 | #define IDD_LOGBOX 110
13 | #define IDD_ABOUTBOX 111
14 | #define IDD_RECONF 112
15 | #define IDD_LICENCEBOX 113
16 | #define IDD_HOSTKEY 114
17 | #define IDD_HK_MOREINFO 116
18 | #define IDD_CA_CONFIG 117
19 |
20 | #define IDN_LIST 1001
21 | #define IDN_COPY 1002
22 |
23 | #define IDA_ICON 1001
24 | #define IDA_TEXT 1002
25 | #define IDA_LICENCE 1003
26 | #define IDA_WEB 1004
27 |
28 | #define IDC_TAB 1001
29 | #define IDC_TABSTATIC1 1002
30 | #define IDC_TABSTATIC2 1003
31 | #define IDC_TABLIST 1004
32 | #define IDC_HELPBTN 1005
33 | #define IDC_ABOUT 1006
34 |
35 | #define IDC_HK_ICON 98
36 | #define IDC_HK_TITLE 99
37 | #define IDC_HK_TEXT 100
38 | #define IDC_HK_ACCEPT 1001
39 | #define IDC_HK_ONCE 1000
40 | #define IDC_HK_HOST 1002
41 | #define IDC_HK_FINGERPRINT 1003
42 | #define IDC_HK_MOREINFO 1004
43 |
44 | #define IDC_HKI_SHA256 1000
45 | #define IDC_HKI_MD5 1001
46 | #define IDC_HKI_PUBKEY 1002
47 |
48 | #define ID_CUSTOM_CHMFILE 2000
49 | #define TYPE_CUSTOM_CHMFILE 2000
50 |
51 | #endif
52 |
--------------------------------------------------------------------------------
/windows/putty.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unxed/putty4far2l/1816bdba0554f9f4465b92bc0df95fb845ff4170/windows/putty.ico
--------------------------------------------------------------------------------
/windows/putty.mft:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
11 | A network client and terminal emulator
12 |
13 |
14 |
16 |
22 |
23 |
24 |
25 |
26 |
28 | true
29 |
31 | PerMonitorV2
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/windows/putty.rc:
--------------------------------------------------------------------------------
1 | #include "rcstuff.h"
2 | #include "putty-rc.h"
3 |
4 | #define APPNAME "PuTTY"
5 | #define APPDESC "SSH, Telnet, Rlogin, and SUPDUP client"
6 |
7 | IDI_MAINICON ICON "putty.ico"
8 | IDI_CFGICON ICON "puttycfg.ico"
9 |
10 | #include "help.rc2"
11 | #include "putty-common.rc2"
12 |
13 | #ifndef NO_MANIFESTS
14 | 1 RT_MANIFEST "putty.mft"
15 | #endif /* NO_MANIFESTS */
16 |
--------------------------------------------------------------------------------
/windows/puttycfg.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unxed/putty4far2l/1816bdba0554f9f4465b92bc0df95fb845ff4170/windows/puttycfg.ico
--------------------------------------------------------------------------------
/windows/puttygen-rc.h:
--------------------------------------------------------------------------------
1 | #define IDC_PPKVER_STATIC 100
2 | #define IDC_PPKVER_2 101
3 | #define IDC_PPKVER_3 102
4 | #define IDC_KDF_STATIC 103
5 | #define IDC_KDF_ARGON2ID 104
6 | #define IDC_KDF_ARGON2I 105
7 | #define IDC_KDF_ARGON2D 106
8 | #define IDC_ARGON2_MEM_STATIC 107
9 | #define IDC_ARGON2_MEM 108
10 | #define IDC_ARGON2_MEM_STATIC2 109
11 | #define IDC_PPK_AUTO_STATIC 110
12 | #define IDC_PPK_AUTO_YES 111
13 | #define IDC_PPK_AUTO_NO 112
14 | #define IDC_ARGON2_TIME_STATIC 113
15 | #define IDC_ARGON2_TIME 114
16 | #define IDC_ARGON2_PARALLEL_STATIC 115
17 | #define IDC_ARGON2_PARALLEL 116
18 |
--------------------------------------------------------------------------------
/windows/puttygen.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unxed/putty4far2l/1816bdba0554f9f4465b92bc0df95fb845ff4170/windows/puttygen.ico
--------------------------------------------------------------------------------
/windows/puttygen.mft:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
11 | SSH key generator for PuTTY
12 |
13 |
14 |
16 |
22 |
23 |
24 |
25 |
26 |
28 | true
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/windows/puttyins.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unxed/putty4far2l/1816bdba0554f9f4465b92bc0df95fb845ff4170/windows/puttyins.ico
--------------------------------------------------------------------------------
/windows/puttytel.mft:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
11 | A network client and terminal emulator
12 |
13 |
14 |
16 |
22 |
23 |
24 |
25 |
26 |
28 | true
29 |
31 | PerMonitorV2
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/windows/puttytel.rc:
--------------------------------------------------------------------------------
1 | #include "rcstuff.h"
2 | #include "putty-rc.h"
3 |
4 | #define APPNAME "PuTTYtel"
5 | #define APPDESC "Telnet and Rlogin client"
6 |
7 | IDI_MAINICON ICON "putty.ico"
8 | IDI_CFGICON ICON "puttycfg.ico"
9 |
10 | #include "help.rc2"
11 | #include "putty-common.rc2"
12 |
13 | #ifndef NO_MANIFESTS
14 | 1 RT_MANIFEST "puttytel.mft"
15 | #endif /* NO_MANIFESTS */
16 |
--------------------------------------------------------------------------------
/windows/rcstuff.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Miscellaneous stuff to include in all .rc files.
3 | */
4 |
5 | #ifndef PUTTY_RCSTUFF_H
6 | #define PUTTY_RCSTUFF_H
7 |
8 | #ifdef HAVE_CMAKE_H
9 | #include "cmake.h"
10 | #endif
11 |
12 | #if HAVE_WINRESRC_H
13 | #include
14 | #elif HAVE_WINRES_H
15 | #include
16 | #endif
17 |
18 | /* Some systems don't define this, so I do it myself if necessary */
19 | #ifndef TCS_MULTILINE
20 | #define TCS_MULTILINE 0x0200
21 | #endif
22 |
23 | /* Likewise */
24 | #ifndef RT_MANIFEST
25 | #define RT_MANIFEST 24
26 | #endif
27 |
28 | /* LCC is the offender here. */
29 | #ifndef VS_FF_DEBUG
30 | #define VS_FF_DEBUG 1
31 | #endif
32 | #ifndef VS_FF_PRERELEASE
33 | #define VS_FF_PRERELEASE 2
34 | #endif
35 | #ifndef VS_FF_PRIVATEBUILD
36 | #define VS_FF_PRIVATEBUILD 8
37 | #endif
38 | #ifndef VOS__WINDOWS32
39 | #define VOS__WINDOWS32 4
40 | #endif
41 | #ifndef VFT_APP
42 | #define VFT_APP 1
43 | #endif
44 |
45 | #endif /* PUTTY_RCSTUFF_H */
46 |
--------------------------------------------------------------------------------
/windows/test/test_screenshot.c:
--------------------------------------------------------------------------------
1 | #include "putty.h"
2 |
3 | static NORETURN PRINTF_LIKE(1, 2) void fatal_error(const char *p, ...)
4 | {
5 | va_list ap;
6 | fprintf(stderr, "screenshot: ");
7 | va_start(ap, p);
8 | vfprintf(stderr, p, ap);
9 | va_end(ap);
10 | fputc('\n', stderr);
11 | exit(1);
12 | }
13 |
14 | void out_of_memory(void) { fatal_error("out of memory"); }
15 |
16 | int main(int argc, char **argv)
17 | {
18 | const char *outfile = NULL;
19 |
20 | AuxMatchOpt amo = aux_match_opt_init(argc-1, argv+1, 0, fatal_error);
21 | while (!aux_match_done(&amo)) {
22 | char *val;
23 | #define match_opt(...) aux_match_opt( \
24 | &amo, NULL, __VA_ARGS__, (const char *)NULL)
25 | #define match_optval(...) aux_match_opt( \
26 | &amo, &val, __VA_ARGS__, (const char *)NULL)
27 |
28 | if (aux_match_arg(&amo, &val)) {
29 | fatal_error("unexpected argument '%s'", val);
30 | } else if (match_optval("-o", "--output")) {
31 | outfile = val;
32 | } else {
33 | fatal_error("unrecognised option '%s'\n", amo.argv[amo.index]);
34 | }
35 | }
36 |
37 | if (!outfile)
38 | fatal_error("expected an output file name");
39 |
40 | char *err = save_screenshot(NULL, outfile);
41 | if (err)
42 | fatal_error("%s", err);
43 |
44 | return 0;
45 | }
46 |
--------------------------------------------------------------------------------
/windows/utils/agent_mutex_name.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Return the full pathname of the global mutex that Pageant uses at
3 | * startup to atomically decide whether to be a server or a client.
4 | */
5 |
6 | #include "putty.h"
7 |
8 | char *agent_mutex_name(void)
9 | {
10 | char *username = get_username();
11 | char *mutexname = dupprintf("Local\\pageant-mutex.%s", username);
12 | sfree(username);
13 | return mutexname;
14 | }
15 |
--------------------------------------------------------------------------------
/windows/utils/agent_named_pipe_name.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Return the full pathname of the named pipe Pageant will listen on.
3 | * Used by both the Pageant server code and client code.
4 | */
5 |
6 | #include "putty.h"
7 | #include "cryptoapi.h"
8 |
9 | char *agent_named_pipe_name(void)
10 | {
11 | char *username = get_username();
12 | char *suffix = capi_obfuscate_string("Pageant");
13 | char *pipename = dupprintf("\\\\.\\pipe\\pageant.%s.%s", username, suffix);
14 | sfree(username);
15 | sfree(suffix);
16 | return pipename;
17 | }
18 |
--------------------------------------------------------------------------------
/windows/utils/arm_arch_queries.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Windows implementation of the OS query functions that detect Arm
3 | * architecture extensions.
4 | */
5 |
6 | #include "putty.h"
7 | #include "ssh.h"
8 |
9 | #if !(defined _M_ARM || defined _M_ARM64)
10 | /*
11 | * For non-Arm, stub out these functions. This module shouldn't be
12 | * _called_ in that situation anyway, but it will still be compiled
13 | * (because that's easier than getting CMake to identify the
14 | * architecture in all cases).
15 | */
16 | #define IsProcessorFeaturePresent(...) false
17 | #endif
18 |
19 | bool platform_aes_neon_available(void)
20 | {
21 | return IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE);
22 | }
23 |
24 | bool platform_pmull_neon_available(void)
25 | {
26 | return IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE);
27 | }
28 |
29 | bool platform_sha256_neon_available(void)
30 | {
31 | return IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE);
32 | }
33 |
34 | bool platform_sha1_neon_available(void)
35 | {
36 | return IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE);
37 | }
38 |
39 | bool platform_sha512_neon_available(void)
40 | {
41 | /* As of 2020-12-24, as far as I can tell from docs.microsoft.com,
42 | * Windows on Arm does not yet provide a PF_ARM_V8_* flag for the
43 | * SHA-512 architecture extension. */
44 | return false;
45 | }
46 |
--------------------------------------------------------------------------------
/windows/utils/centre_window.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Centre a window on the screen. Used to position the main config box.
3 | */
4 |
5 | #include "putty.h"
6 |
7 | void centre_window(HWND win)
8 | {
9 | RECT rd, rw;
10 |
11 | if (!GetWindowRect(GetDesktopWindow(), &rd))
12 | return;
13 | if (!GetWindowRect(win, &rw))
14 | return;
15 |
16 | MoveWindow(win,
17 | (rd.right + rd.left + rw.left - rw.right) / 2,
18 | (rd.bottom + rd.top + rw.top - rw.bottom) / 2,
19 | rw.right - rw.left, rw.bottom - rw.top, true);
20 | }
21 |
--------------------------------------------------------------------------------
/windows/utils/defaults.c:
--------------------------------------------------------------------------------
1 | /*
2 | * windows/utils/defaults.c: default settings that are specific to Windows.
3 | */
4 |
5 | #include "putty.h"
6 |
7 | #include
8 |
9 | FontSpec *platform_default_fontspec(const char *name)
10 | {
11 | if (!strcmp(name, "Font"))
12 | return fontspec_new("Courier New", false, 10, ANSI_CHARSET);
13 | else
14 | return fontspec_new_default();
15 | }
16 |
17 | Filename *platform_default_filename(const char *name)
18 | {
19 | if (!strcmp(name, "LogFileName"))
20 | return filename_from_str("putty.log");
21 | else
22 | return filename_from_str("");
23 | }
24 |
25 | char *platform_default_s(const char *name)
26 | {
27 | if (!strcmp(name, "SerialLine"))
28 | return dupstr("COM1");
29 | return NULL;
30 | }
31 |
32 | bool platform_default_b(const char *name, bool def)
33 | {
34 | return def;
35 | }
36 |
37 | int platform_default_i(const char *name, int def)
38 | {
39 | return def;
40 | }
41 |
--------------------------------------------------------------------------------
/windows/utils/dputs.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Implementation of dputs() for Windows.
3 | *
4 | * The debug messages are written to STD_OUTPUT_HANDLE, except that
5 | * first it has to make sure that handle _exists_, by calling
6 | * AllocConsole first if necessary.
7 | *
8 | * They also go into a file called debug.log.
9 | */
10 |
11 | #include "putty.h"
12 | #include "utils/utils.h"
13 |
14 | static HANDLE debug_fp = INVALID_HANDLE_VALUE;
15 | static HANDLE debug_hdl = INVALID_HANDLE_VALUE;
16 | static int debug_got_console = 0;
17 |
18 | void dputs(const char *buf)
19 | {
20 | DWORD dw;
21 |
22 | if (!debug_got_console) {
23 | if (AllocConsole()) {
24 | debug_got_console = 1;
25 | debug_hdl = GetStdHandle(STD_OUTPUT_HANDLE);
26 | }
27 | }
28 | if (debug_fp == INVALID_HANDLE_VALUE) {
29 | debug_fp = CreateFile("debug.log", GENERIC_WRITE, FILE_SHARE_READ,
30 | NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
31 | }
32 |
33 | if (debug_fp != INVALID_HANDLE_VALUE) {
34 | WriteFile(debug_fp, buf, strlen(buf), &dw, NULL);
35 | }
36 | if (debug_hdl != INVALID_HANDLE_VALUE) {
37 | WriteFile(debug_hdl, buf, strlen(buf), &dw, NULL);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/windows/utils/escape_registry_key.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Escaping/unescaping functions to translate between a saved session
3 | * name, and the key name used to represent it in the Registry area
4 | * where we store saved sessions.
5 | *
6 | * The basic technique is to %-escape characters we can't use in
7 | * Registry keys.
8 | */
9 |
10 | #include "putty.h"
11 |
12 | void escape_registry_key(const char *in, strbuf *out)
13 | {
14 | bool candot = false;
15 | static const char hex[16] = "0123456789ABCDEF";
16 |
17 | while (*in) {
18 | if (*in == ' ' || *in == '\\' || *in == '*' || *in == '?' ||
19 | *in == '%' || *in < ' ' || *in > '~' || (*in == '.'
20 | && !candot)) {
21 | put_byte(out, '%');
22 | put_byte(out, hex[((unsigned char) *in) >> 4]);
23 | put_byte(out, hex[((unsigned char) *in) & 15]);
24 | } else
25 | put_byte(out, *in);
26 | in++;
27 | candot = true;
28 | }
29 | }
30 |
31 | void unescape_registry_key(const char *in, strbuf *out)
32 | {
33 | while (*in) {
34 | if (*in == '%' && in[1] && in[2]) {
35 | int i, j;
36 |
37 | i = in[1] - '0';
38 | i -= (i > 9 ? 7 : 0);
39 | j = in[2] - '0';
40 | j -= (j > 9 ? 7 : 0);
41 |
42 | put_byte(out, (i << 4) + j);
43 | in += 3;
44 | } else {
45 | put_byte(out, *in++);
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/windows/utils/fontspec.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Implementation of FontSpec for Windows.
3 | */
4 |
5 | #include "putty.h"
6 |
7 | FontSpec *fontspec_new(const char *name, bool bold, int height, int charset)
8 | {
9 | FontSpec *f = snew(FontSpec);
10 | f->name = dupstr(name);
11 | f->isbold = bold;
12 | f->height = height;
13 | f->charset = charset;
14 | return f;
15 | }
16 |
17 | FontSpec *fontspec_new_default(void)
18 | {
19 | return fontspec_new("", false, 0, 0);
20 | }
21 |
22 | FontSpec *fontspec_copy(const FontSpec *f)
23 | {
24 | return fontspec_new(f->name, f->isbold, f->height, f->charset);
25 | }
26 |
27 | void fontspec_free(FontSpec *f)
28 | {
29 | sfree(f->name);
30 | sfree(f);
31 | }
32 |
33 | void fontspec_serialise(BinarySink *bs, FontSpec *f)
34 | {
35 | put_asciz(bs, f->name);
36 | put_uint32(bs, f->isbold);
37 | put_uint32(bs, f->height);
38 | put_uint32(bs, f->charset);
39 | }
40 |
41 | FontSpec *fontspec_deserialise(BinarySource *src)
42 | {
43 | const char *name = get_asciz(src);
44 | unsigned isbold = get_uint32(src);
45 | unsigned height = get_uint32(src);
46 | unsigned charset = get_uint32(src);
47 | return fontspec_new(name, isbold, height, charset);
48 | }
49 |
--------------------------------------------------------------------------------
/windows/utils/get_system_dir.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Wrapper function around GetSystemDirectory that deals with
3 | * allocating the output buffer, and also caches the result for future
4 | * calls.
5 | */
6 |
7 | #include "putty.h"
8 |
9 | const char *get_system_dir(void)
10 | {
11 | static char *sysdir = NULL;
12 | static size_t sysdirsize = 0;
13 |
14 | if (!sysdir) {
15 | size_t len;
16 | while ((len = GetSystemDirectory(sysdir, sysdirsize)) >= sysdirsize)
17 | sgrowarray(sysdir, sysdirsize, len);
18 | }
19 |
20 | return sysdir;
21 | }
22 |
--------------------------------------------------------------------------------
/windows/utils/getdlgitemtext_alloc.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Handy wrappers around GetDlgItemText (A and W) which don't make you
3 | * invent an arbitrary length limit on the output string. Returned
4 | * string is dynamically allocated; caller must free.
5 | */
6 |
7 | #include "putty.h"
8 |
9 | char *GetDlgItemText_alloc(HWND hwnd, int id)
10 | {
11 | char *ret = NULL;
12 | size_t size = 0;
13 |
14 | do {
15 | sgrowarray_nm(ret, size, size);
16 | GetDlgItemText(hwnd, id, ret, size);
17 | } while (!memchr(ret, '\0', size-1));
18 |
19 | return ret;
20 | }
21 |
22 | wchar_t *GetDlgItemTextW_alloc(HWND hwnd, int id)
23 | {
24 | wchar_t *ret = NULL;
25 | size_t size = 0;
26 |
27 | do {
28 | sgrowarray_nm(ret, size, size);
29 | GetDlgItemTextW(hwnd, id, ret, size);
30 | } while (!memchr(ret, '\0', size-1));
31 |
32 | return ret;
33 | }
34 |
--------------------------------------------------------------------------------
/windows/utils/gui-timing.c:
--------------------------------------------------------------------------------
1 | #include "putty.h"
2 |
3 | #define TIMING_CLASS_NAME "PuTTYTimerWindow"
4 | #define TIMING_TIMER_ID 1234
5 | static long timing_next_time;
6 | static HWND timing_hwnd;
7 |
8 | static LRESULT CALLBACK TimingWndProc(HWND hwnd, UINT message,
9 | WPARAM wParam, LPARAM lParam)
10 | {
11 | switch (message) {
12 | case WM_TIMER:
13 | if ((UINT_PTR)wParam == TIMING_TIMER_ID) {
14 | unsigned long next;
15 |
16 | KillTimer(hwnd, TIMING_TIMER_ID);
17 | if (run_timers(timing_next_time, &next)) {
18 | timer_change_notify(next);
19 | } else {
20 | }
21 | }
22 | return 0;
23 | }
24 | return DefWindowProc(hwnd, message, wParam, lParam);
25 | }
26 |
27 | void setup_gui_timing(void)
28 | {
29 | WNDCLASS wndclass;
30 |
31 | memset(&wndclass, 0, sizeof(wndclass));
32 | wndclass.lpfnWndProc = TimingWndProc;
33 | wndclass.hInstance = hinst;
34 | wndclass.lpszClassName = TIMING_CLASS_NAME;
35 |
36 | RegisterClass(&wndclass);
37 |
38 | timing_hwnd = CreateWindow(
39 | TIMING_CLASS_NAME, "PuTTY: hidden timing window",
40 | WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
41 | 100, 100, NULL, NULL, hinst, NULL);
42 | ShowWindow(timing_hwnd, SW_HIDE);
43 | }
44 |
45 | void timer_change_notify(unsigned long next)
46 | {
47 | unsigned long now = GETTICKCOUNT();
48 | long ticks;
49 | if (now - next < INT_MAX)
50 | ticks = 0;
51 | else
52 | ticks = next - now;
53 | KillTimer(timing_hwnd, TIMING_TIMER_ID);
54 | SetTimer(timing_hwnd, TIMING_TIMER_ID, ticks, NULL);
55 | timing_next_time = next;
56 | }
57 |
--------------------------------------------------------------------------------
/windows/utils/interprocess_mutex.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Lock and unlock a mutex with a globally visible name. Used to
3 | * synchronise between unrelated processes, such as two
4 | * connection-sharing PuTTYs deciding which will be the upstream.
5 | */
6 |
7 | #include "putty.h"
8 | #include "security-api.h"
9 |
10 | HANDLE lock_interprocess_mutex(const char *mutexname, char **error)
11 | {
12 | PSECURITY_DESCRIPTOR psd = NULL;
13 | PACL acl = NULL;
14 | HANDLE mutex = NULL;
15 |
16 | if (should_have_security() && !make_private_security_descriptor(
17 | MUTEX_ALL_ACCESS, &psd, &acl, error))
18 | goto out;
19 |
20 | SECURITY_ATTRIBUTES sa;
21 | memset(&sa, 0, sizeof(sa));
22 | sa.nLength = sizeof(sa);
23 | sa.lpSecurityDescriptor = psd;
24 | sa.bInheritHandle = false;
25 |
26 | mutex = CreateMutex(&sa, false, mutexname);
27 | if (!mutex) {
28 | *error = dupprintf("CreateMutex(\"%s\") failed: %s",
29 | mutexname, win_strerror(GetLastError()));
30 | goto out;
31 | }
32 |
33 | WaitForSingleObject(mutex, INFINITE);
34 |
35 | out:
36 | if (psd)
37 | LocalFree(psd);
38 | if (acl)
39 | LocalFree(acl);
40 |
41 | return mutex;
42 | }
43 |
44 | void unlock_interprocess_mutex(HANDLE mutex)
45 | {
46 | ReleaseMutex(mutex);
47 | CloseHandle(mutex);
48 | }
49 |
--------------------------------------------------------------------------------
/windows/utils/is_console_handle.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Determine whether a Windows HANDLE points at a console device.
3 | */
4 |
5 | #include "putty.h"
6 |
7 | bool is_console_handle(HANDLE handle)
8 | {
9 | DWORD ignored_output;
10 | if (GetConsoleMode(handle, &ignored_output))
11 | return true;
12 | return false;
13 | }
14 |
--------------------------------------------------------------------------------
/windows/utils/load_system32_dll.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Wrapper function to load a DLL out of c:\windows\system32 without
3 | * going through the full DLL search path. (Hence no attack is
4 | * possible by placing a substitute DLL earlier on that path.)
5 | */
6 |
7 | #include "putty.h"
8 |
9 | HMODULE load_system32_dll(const char *libname)
10 | {
11 | char *fullpath;
12 | HMODULE ret;
13 |
14 | fullpath = dupcat(get_system_dir(), "\\", libname);
15 | ret = LoadLibrary(fullpath);
16 | sfree(fullpath);
17 | return ret;
18 | }
19 |
--------------------------------------------------------------------------------
/windows/utils/ltime.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Implementation of ltime() that avoids trouble with time() returning
3 | * (time_t)-1 on Windows.
4 | */
5 |
6 | #include "putty.h"
7 | #include
8 |
9 | struct tm ltime(void)
10 | {
11 | SYSTEMTIME st;
12 | struct tm tm;
13 |
14 | memset(&tm, 0, sizeof(tm)); /* in case there are any other fields */
15 |
16 | GetLocalTime(&st);
17 | tm.tm_sec=st.wSecond;
18 | tm.tm_min=st.wMinute;
19 | tm.tm_hour=st.wHour;
20 | tm.tm_mday=st.wDay;
21 | tm.tm_mon=st.wMonth-1;
22 | tm.tm_year=(st.wYear>=1900?st.wYear-1900:0);
23 | tm.tm_wday=st.wDayOfWeek;
24 | tm.tm_yday=-1; /* GetLocalTime doesn't tell us */
25 | tm.tm_isdst=0; /* GetLocalTime doesn't tell us */
26 | return tm;
27 | }
28 |
--------------------------------------------------------------------------------
/windows/utils/make_spr_sw_abort_winerror.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Constructor function for a SeatPromptResult of the 'software abort'
3 | * category, whose error message includes the translation of an OS
4 | * error code.
5 | */
6 |
7 | #include "putty.h"
8 |
9 | static void spr_winerror_errfn(SeatPromptResult spr, BinarySink *bs)
10 | {
11 | put_fmt(bs, "%s: %s", spr.errdata_lit, win_strerror(spr.errdata_u));
12 | }
13 |
14 | SeatPromptResult make_spr_sw_abort_winerror(const char *prefix, DWORD error)
15 | {
16 | SeatPromptResult spr;
17 | spr.kind = SPRK_SW_ABORT;
18 | spr.errfn = spr_winerror_errfn;
19 | spr.errdata_lit = prefix;
20 | spr.errdata_u = error;
21 | return spr;
22 | }
23 |
--------------------------------------------------------------------------------
/windows/utils/makedlgitemborderless.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Helper function to remove the border around a dialog item such as
3 | * a read-only edit control.
4 | */
5 |
6 | #include "putty.h"
7 |
8 | void MakeDlgItemBorderless(HWND parent, int id)
9 | {
10 | HWND child = GetDlgItem(parent, id);
11 | LONG_PTR style = GetWindowLongPtr(child, GWL_STYLE);
12 | LONG_PTR exstyle = GetWindowLongPtr(child, GWL_EXSTYLE);
13 | style &= ~WS_BORDER;
14 | exstyle &= ~(WS_EX_CLIENTEDGE | WS_EX_STATICEDGE | WS_EX_WINDOWEDGE);
15 | SetWindowLongPtr(child, GWL_STYLE, style);
16 | SetWindowLongPtr(child, GWL_EXSTYLE, exstyle);
17 | SetWindowPos(child, NULL, 0, 0, 0, 0,
18 | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
19 | }
20 |
--------------------------------------------------------------------------------
/windows/utils/pgp_fingerprints_msgbox.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Display the fingerprints of the PGP Master Keys to the user as a
3 | * GUI message box.
4 | */
5 |
6 | #include "putty.h"
7 |
8 | void pgp_fingerprints_msgbox(HWND owner)
9 | {
10 | message_box(
11 | owner,
12 | "These are the fingerprints of the PuTTY PGP Master Keys. They can\n"
13 | "be used to establish a trust path from this executable to another\n"
14 | "one. See the manual for more information.\n"
15 | "(Note: these fingerprints have nothing to do with SSH!)\n"
16 | "\n"
17 | "PuTTY Master Key as of " PGP_MASTER_KEY_YEAR
18 | " (" PGP_MASTER_KEY_DETAILS "):\n"
19 | " " PGP_MASTER_KEY_FP "\n\n"
20 | "Previous Master Key (" PGP_PREV_MASTER_KEY_YEAR
21 | ", " PGP_PREV_MASTER_KEY_DETAILS "):\n"
22 | " " PGP_PREV_MASTER_KEY_FP,
23 | "PGP fingerprints", MB_ICONINFORMATION | MB_OK,
24 | false, HELPCTXID(pgp_fingerprints));
25 | }
26 |
--------------------------------------------------------------------------------
/windows/utils/platform_get_x_display.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Implementation of platform_get_x_display for Windows, common to all
3 | * tools.
4 | */
5 |
6 | #include "putty.h"
7 | #include "ssh.h"
8 |
9 | char *platform_get_x_display(void)
10 | {
11 | /* We may as well check for DISPLAY in case it's useful. */
12 | return dupstr(getenv("DISPLAY"));
13 | }
14 |
--------------------------------------------------------------------------------
/windows/utils/split_into_argv_w.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Unicode version of split_into_argv.
3 | */
4 |
5 | #define SPLIT_INTO_ARGV_W
6 | #include "split_into_argv.c"
7 |
--------------------------------------------------------------------------------
/windows/utils/strtoumax.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Work around lack of strtoumax in older MSVC libraries.
3 | */
4 |
5 | #include
6 |
7 | #include "defs.h"
8 |
9 | uintmax_t strtoumax(const char *nptr, char **endptr, int base)
10 | {
11 | return _strtoui64(nptr, endptr, base);
12 | }
13 |
--------------------------------------------------------------------------------
/windows/website.url:
--------------------------------------------------------------------------------
1 | [InternetShortcut]
2 | URL=https://www.chiark.greenend.org.uk/~sgtatham/putty/
3 |
--------------------------------------------------------------------------------
/windows/x11.c:
--------------------------------------------------------------------------------
1 | /*
2 | * x11.c: fetch local auth data for X forwarding.
3 | */
4 |
5 | #include
6 | #include
7 | #include
8 |
9 | #include "putty.h"
10 | #include "ssh.h"
11 |
12 | void platform_get_x11_auth(struct X11Display *disp, Conf *conf)
13 | {
14 | Filename *xauthfn = conf_get_filename(conf, CONF_xauthfile);
15 | if (!filename_is_null(xauthfn))
16 | x11_get_auth_from_authfile(disp, xauthfn);
17 | }
18 |
19 | const bool platform_uses_x11_unix_by_default = false;
20 |
--------------------------------------------------------------------------------