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 *ret = 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 | ret->fp = popen(printer, "w");
21 | if (!ret->fp) {
22 | sfree(ret);
23 | ret = NULL;
24 | }
25 | return ret;
26 | }
27 |
28 | void printer_job_data(printer_job *pj, void *data, int 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 uxcfg.c will disable the
50 | * 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 |
--------------------------------------------------------------------------------
/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{xhtml-contents-filename}{index.html}
18 | \cfg{text-filename}{puttydoc.txt}
19 | \cfg{winhelp-filename}{putty.hlp}
20 | \cfg{info-filename}{putty.info}
21 |
22 | PuTTY is a free (MIT-licensed) Win32 Telnet and SSH client. This
23 | manual documents PuTTY, and its companion utilities PSCP, PSFTP,
24 | Plink, Pageant and PuTTYgen.
25 |
26 | \e{Note to Unix users:} this manual currently primarily documents the
27 | Windows versions of the PuTTY utilities. Some options are therefore
28 | mentioned that are absent from the \i{Unix version}; the Unix version has
29 | features not described here; and the \i\cw{pterm} and command-line
30 | \cw{puttygen} utilities are not described at all. The only
31 | Unix-specific documentation that currently exists is the
32 | \I{man pages for PuTTY tools}man pages.
33 |
34 | \copyright This manual is copyright 2001-2015 Simon Tatham. All
35 | rights reserved. You may distribute this documentation under the MIT
36 | licence. See \k{licence} for the licence text in full.
37 |
--------------------------------------------------------------------------------
/unix/uxpterm.c:
--------------------------------------------------------------------------------
1 | /*
2 | * pterm main program.
3 | */
4 |
5 | #include
6 | #include
7 |
8 | #include "putty.h"
9 |
10 | const char *const appname = "pterm";
11 | const int use_event_log = 0; /* pterm doesn't need it */
12 | const int new_session = 0, saved_sessions = 0; /* or these */
13 | const int use_pty_argv = TRUE;
14 |
15 | Backend *select_backend(Conf *conf)
16 | {
17 | return &pty_backend;
18 | }
19 |
20 | int cfgbox(Conf *conf)
21 | {
22 | /*
23 | * This is a no-op in pterm, except that we'll ensure the
24 | * protocol is set to -1 to inhibit the useless Connection
25 | * panel in the config box.
26 | */
27 | conf_set_int(conf, CONF_protocol, -1);
28 | return 1;
29 | }
30 |
31 | void cleanup_exit(int code)
32 | {
33 | exit(code);
34 | }
35 |
36 | int process_nonoption_arg(char *arg, Conf *conf, int *allow_launch)
37 | {
38 | return 0; /* pterm doesn't have any. */
39 | }
40 |
41 | char *make_default_wintitle(char *hostname)
42 | {
43 | return dupstr("pterm");
44 | }
45 |
46 | int main(int argc, char **argv)
47 | {
48 | extern int pt_main(int argc, char **argv);
49 | extern void pty_pre_init(void); /* declared in pty.c */
50 | int ret;
51 |
52 | cmdline_tooltype = TOOLTYPE_NONNETWORK;
53 | default_protocol = -1;
54 |
55 | pty_pre_init();
56 |
57 | ret = pt_main(argc, argv);
58 | cleanup_exit(ret);
59 | return ret; /* not reached, but placates optimisers */
60 | }
61 |
--------------------------------------------------------------------------------
/windows/README.txt:
--------------------------------------------------------------------------------
1 | PuTTY README
2 | ============
3 |
4 | This is the README file for the PuTTY 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-only file transfer utility PSCP,
16 | you will probably want to put the PuTTY installation directory on
17 | your PATH. On Windows 7 and similar versions, you can do this at
18 | Control Panel > System and Security > System > Advanced system
19 | settings > Environment Variables.
20 |
21 | Some versions of Windows will refuse to run HTML Help files (.CHM)
22 | if they are installed on a network drive. If you have installed
23 | PuTTY on a network drive, you might want to check that the help file
24 | works properly. If not, see http://support.microsoft.com/kb/896054
25 | for information on how to solve this problem.
26 |
27 | What do I do if it doesn't work?
28 | --------------------------------
29 |
30 | The PuTTY home web site is
31 |
32 | http://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 |
--------------------------------------------------------------------------------
/errsock.c:
--------------------------------------------------------------------------------
1 | /*
2 | * A dummy Socket implementation which just holds an error message.
3 | */
4 |
5 | #include
6 | #include
7 |
8 | #define DEFINE_PLUG_METHOD_MACROS
9 | #include "tree234.h"
10 | #include "putty.h"
11 | #include "network.h"
12 |
13 | typedef struct Socket_error_tag *Error_Socket;
14 |
15 | struct Socket_error_tag {
16 | const struct socket_function_table *fn;
17 | /* the above variable absolutely *must* be the first in this structure */
18 |
19 | char *error;
20 | Plug plug;
21 | };
22 |
23 | static Plug sk_error_plug(Socket s, Plug p)
24 | {
25 | Error_Socket ps = (Error_Socket) s;
26 | Plug ret = ps->plug;
27 | if (p)
28 | ps->plug = p;
29 | return ret;
30 | }
31 |
32 | static void sk_error_close(Socket s)
33 | {
34 | Error_Socket ps = (Error_Socket) s;
35 |
36 | sfree(ps->error);
37 | sfree(ps);
38 | }
39 |
40 | static const char *sk_error_socket_error(Socket s)
41 | {
42 | Error_Socket ps = (Error_Socket) s;
43 | return ps->error;
44 | }
45 |
46 | static char *sk_error_peer_info(Socket s)
47 | {
48 | return NULL;
49 | }
50 |
51 | Socket new_error_socket(const char *errmsg, Plug plug)
52 | {
53 | static const struct socket_function_table socket_fn_table = {
54 | sk_error_plug,
55 | sk_error_close,
56 | NULL /* write */,
57 | NULL /* write_oob */,
58 | NULL /* write_eof */,
59 | NULL /* flush */,
60 | NULL /* set_frozen */,
61 | sk_error_socket_error,
62 | sk_error_peer_info,
63 | };
64 |
65 | Error_Socket ret;
66 |
67 | ret = snew(struct Socket_error_tag);
68 | ret->fn = &socket_fn_table;
69 | ret->plug = plug;
70 | ret->error = dupstr(errmsg);
71 |
72 | return (Socket) ret;
73 | }
74 |
--------------------------------------------------------------------------------
/contrib/cygtermd/malloc.h:
--------------------------------------------------------------------------------
1 | /*
2 | * malloc.h: safe wrappers around malloc, realloc, free, strdup
3 | */
4 |
5 | #ifndef UMLWRAP_MALLOC_H
6 | #define UMLWRAP_MALLOC_H
7 |
8 | #include
9 |
10 | /*
11 | * smalloc should guarantee to return a useful pointer - Halibut
12 | * can do nothing except die when it's out of memory anyway.
13 | */
14 | void *smalloc(size_t size);
15 |
16 | /*
17 | * srealloc should guaranteeably be able to realloc NULL
18 | */
19 | void *srealloc(void *p, size_t size);
20 |
21 | /*
22 | * sfree should guaranteeably deal gracefully with freeing NULL
23 | */
24 | void sfree(void *p);
25 |
26 | /*
27 | * dupstr is like strdup, but with the never-return-NULL property
28 | * of smalloc (and also reliably defined in all environments :-)
29 | */
30 | char *dupstr(const char *s);
31 |
32 | /*
33 | * snew allocates one instance of a given type, and casts the
34 | * result so as to type-check that you're assigning it to the
35 | * right kind of pointer. Protects against allocation bugs
36 | * involving allocating the wrong size of thing.
37 | */
38 | #define snew(type) \
39 | ( (type *) smalloc (sizeof (type)) )
40 |
41 | /*
42 | * snewn allocates n instances of a given type, for arrays.
43 | */
44 | #define snewn(number, type) \
45 | ( (type *) smalloc ((number) * sizeof (type)) )
46 |
47 | /*
48 | * sresize wraps realloc so that you specify the new number of
49 | * elements and the type of the element, with the same type-
50 | * checking advantages. Also type-checks the input pointer.
51 | */
52 | #define sresize(array, number, type) \
53 | ( (void)sizeof((array)-(type *)0), \
54 | (type *) srealloc ((array), (number) * sizeof (type)) )
55 |
56 | #endif /* UMLWRAP_MALLOC_H */
57 |
--------------------------------------------------------------------------------
/pinger.c:
--------------------------------------------------------------------------------
1 | /*
2 | * pinger.c: centralised module that deals with sending TS_PING
3 | * keepalives, to avoid replicating this code in multiple backends.
4 | */
5 |
6 | #include "putty.h"
7 |
8 | struct pinger_tag {
9 | int interval;
10 | int pending;
11 | unsigned long next;
12 | Backend *back;
13 | void *backhandle;
14 | };
15 |
16 | static void pinger_schedule(Pinger pinger);
17 |
18 | static void pinger_timer(void *ctx, unsigned long now)
19 | {
20 | Pinger pinger = (Pinger)ctx;
21 |
22 | if (pinger->pending && now == pinger->next) {
23 | pinger->back->special(pinger->backhandle, TS_PING);
24 | pinger->pending = FALSE;
25 | pinger_schedule(pinger);
26 | }
27 | }
28 |
29 | static void pinger_schedule(Pinger pinger)
30 | {
31 | int next;
32 |
33 | if (!pinger->interval) {
34 | pinger->pending = FALSE; /* cancel any pending ping */
35 | return;
36 | }
37 |
38 | next = schedule_timer(pinger->interval * TICKSPERSEC,
39 | pinger_timer, pinger);
40 | if (!pinger->pending || next < pinger->next) {
41 | pinger->next = next;
42 | pinger->pending = TRUE;
43 | }
44 | }
45 |
46 | Pinger pinger_new(Conf *conf, Backend *back, void *backhandle)
47 | {
48 | Pinger pinger = snew(struct pinger_tag);
49 |
50 | pinger->interval = conf_get_int(conf, CONF_ping_interval);
51 | pinger->pending = FALSE;
52 | pinger->back = back;
53 | pinger->backhandle = backhandle;
54 | pinger_schedule(pinger);
55 |
56 | return pinger;
57 | }
58 |
59 | void pinger_reconfig(Pinger pinger, Conf *oldconf, Conf *newconf)
60 | {
61 | int newinterval = conf_get_int(newconf, CONF_ping_interval);
62 | if (conf_get_int(oldconf, CONF_ping_interval) != newinterval) {
63 | pinger->interval = newinterval;
64 | pinger_schedule(pinger);
65 | }
66 | }
67 |
68 | void pinger_free(Pinger pinger)
69 | {
70 | expire_timer_context(pinger);
71 | sfree(pinger);
72 | }
73 |
--------------------------------------------------------------------------------
/windows/version.rc2:
--------------------------------------------------------------------------------
1 | /*
2 | * Standard Windows version information.
3 | * (For inclusion in other .rc files with appropriate macro definitions.)
4 | * FIXME: This file is called '.rc2' rather than '.rc' to avoid MSVC trying
5 | * to compile it on its own when using the project files. Nicer solutions
6 | * welcome.
7 | */
8 |
9 | #include "version.h"
10 |
11 | /*
12 | * The actual VERSIONINFO resource.
13 | */
14 | VS_VERSION_INFO VERSIONINFO
15 | /* (None of this "fixed" info appears to be trivially user-visible on
16 | * Win98SE. The binary version does show up on Win2K.) */
17 | FILEVERSION BINARY_VERSION
18 | PRODUCTVERSION BINARY_VERSION /* version of whole suite */
19 | FILEFLAGSMASK VS_FF_DEBUG | VS_FF_PRERELEASE | VS_FF_PRIVATEBUILD
20 | FILEFLAGS 0x0L
21 | #if defined DEBUG
22 | | VS_FF_DEBUG
23 | #endif
24 | #if defined SNAPSHOT || defined PRERELEASE
25 | | VS_FF_PRERELEASE
26 | #elif !defined RELEASE
27 | | VS_FF_PRIVATEBUILD
28 | #endif
29 | FILEOS VOS__WINDOWS32
30 | FILETYPE VFT_APP
31 | FILESUBTYPE 0x0L /* n/a for VFT_APP */
32 | BEGIN
33 | /* (On Win98SE and Win2K, we can see most of this on the Version tab
34 | * in the file properties in Explorer.) */
35 | BLOCK "StringFileInfo"
36 | BEGIN
37 | /* "lang-charset" LLLLCCCC = (UK English, Unicode) */
38 | BLOCK "080904B0"
39 | BEGIN
40 | VALUE "CompanyName", "Simon Tatham" /* required :/ */
41 | VALUE "ProductName", "PuTTY suite"
42 | VALUE "FileDescription", APPDESC
43 | VALUE "InternalName", APPNAME
44 | VALUE "OriginalFilename", APPNAME
45 | VALUE "FileVersion", TEXTVER
46 | VALUE "ProductVersion", TEXTVER
47 | VALUE "LegalCopyright", "Copyright \251 1997-2015 Simon Tatham."
48 | #if (!defined SNAPSHOT) && (!defined RELEASE) && (!defined PRERELEASE)
49 | /* Only if VS_FF_PRIVATEBUILD. */
50 | VALUE "PrivateBuild", TEXTVER /* NBI */
51 | #endif
52 | END
53 | END
54 | BLOCK "VarFileInfo"
55 | BEGIN
56 | /* Once again -- same meanings -- apparently necessary */
57 | VALUE "Translation", 0x809, 1200
58 | END
59 | END
60 |
--------------------------------------------------------------------------------
/callback.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Facility for queueing callback functions to be run from the
3 | * top-level event loop after the current top-level activity finishes.
4 | */
5 |
6 | #include
7 |
8 | #include "putty.h"
9 |
10 | struct callback {
11 | struct callback *next;
12 |
13 | toplevel_callback_fn_t fn;
14 | void *ctx;
15 | };
16 |
17 | struct callback *cbhead = NULL, *cbtail = NULL;
18 |
19 | toplevel_callback_notify_fn_t notify_frontend = NULL;
20 | void *frontend = NULL;
21 |
22 | void request_callback_notifications(toplevel_callback_notify_fn_t fn,
23 | void *fr)
24 | {
25 | notify_frontend = fn;
26 | frontend = fr;
27 | }
28 |
29 | void queue_toplevel_callback(toplevel_callback_fn_t fn, void *ctx)
30 | {
31 | struct callback *cb;
32 |
33 | cb = snew(struct callback);
34 | cb->fn = fn;
35 | cb->ctx = ctx;
36 |
37 | /* If the front end has requested notification of pending
38 | * callbacks, and we didn't already have one queued, let it know
39 | * we do have one now. */
40 | if (notify_frontend && !cbhead)
41 | notify_frontend(frontend);
42 |
43 | if (cbtail)
44 | cbtail->next = cb;
45 | else
46 | cbhead = cb;
47 | cbtail = cb;
48 | cb->next = NULL;
49 | }
50 |
51 | void run_toplevel_callbacks(void)
52 | {
53 | if (cbhead) {
54 | struct callback *cb = cbhead;
55 | /*
56 | * Careful ordering here. We call the function _before_
57 | * advancing cbhead (though, of course, we must free cb
58 | * _after_ advancing it). This means that if the very last
59 | * callback schedules another callback, cbhead does not become
60 | * NULL at any point, and so the frontend notification
61 | * function won't be needlessly pestered.
62 | */
63 | cb->fn(cb->ctx);
64 | cbhead = cb->next;
65 | sfree(cb);
66 | if (!cbhead)
67 | cbtail = NULL;
68 | }
69 | }
70 |
71 | int toplevel_callback_pending(void)
72 | {
73 | return cbhead != NULL;
74 | }
75 |
--------------------------------------------------------------------------------
/unix/gtkcols.h:
--------------------------------------------------------------------------------
1 | /*
2 | * gtkcols.h - header file for a columns-based widget container
3 | * capable of supporting the PuTTY portable dialog box layout
4 | * mechanism.
5 | */
6 |
7 | #ifndef COLUMNS_H
8 | #define COLUMNS_H
9 |
10 | #include
11 | #include
12 |
13 | #ifdef __cplusplus
14 | extern "C" {
15 | #endif /* __cplusplus */
16 |
17 | #define TYPE_COLUMNS (columns_get_type())
18 | #define COLUMNS(obj) (GTK_CHECK_CAST((obj), TYPE_COLUMNS, Columns))
19 | #define COLUMNS_CLASS(klass) \
20 | (GTK_CHECK_CLASS_CAST((klass), TYPE_COLUMNS, ColumnsClass))
21 | #define IS_COLUMNS(obj) (GTK_CHECK_TYPE((obj), TYPE_COLUMNS))
22 | #define IS_COLUMNS_CLASS(klass) (GTK_CHECK_CLASS_TYPE((klass), TYPE_COLUMNS))
23 |
24 | typedef struct Columns_tag Columns;
25 | typedef struct ColumnsClass_tag ColumnsClass;
26 | typedef struct ColumnsChild_tag ColumnsChild;
27 |
28 | struct Columns_tag {
29 | GtkContainer container;
30 | /* private after here */
31 | GList *children; /* this holds ColumnsChild structures */
32 | GList *taborder; /* this just holds GtkWidgets */
33 | gint spacing;
34 | };
35 |
36 | struct ColumnsClass_tag {
37 | GtkContainerClass parent_class;
38 | };
39 |
40 | struct ColumnsChild_tag {
41 | /* If `widget' is non-NULL, this entry represents an actual widget. */
42 | GtkWidget *widget;
43 | gint colstart, colspan;
44 | gboolean force_left; /* for recalcitrant GtkLabels */
45 | /* Otherwise, this entry represents a change in the column setup. */
46 | gint ncols;
47 | gint *percentages;
48 | };
49 |
50 | GtkType columns_get_type(void);
51 | GtkWidget *columns_new(gint spacing);
52 | void columns_set_cols(Columns *cols, gint ncols, const gint *percentages);
53 | void columns_add(Columns *cols, GtkWidget *child,
54 | gint colstart, gint colspan);
55 | void columns_taborder_last(Columns *cols, GtkWidget *child);
56 | void columns_force_left_align(Columns *cols, GtkWidget *child);
57 |
58 | #ifdef __cplusplus
59 | }
60 | #endif /* __cplusplus */
61 |
62 | #endif /* COLUMNS_H */
63 |
--------------------------------------------------------------------------------
/puttymem.h:
--------------------------------------------------------------------------------
1 | /*
2 | * PuTTY memory-handling header.
3 | */
4 |
5 | #ifndef PUTTY_PUTTYMEM_H
6 | #define PUTTY_PUTTYMEM_H
7 |
8 | #include /* for size_t */
9 | #include /* for memcpy() */
10 |
11 |
12 | /* #define MALLOC_LOG do this if you suspect putty of leaking memory */
13 | #ifdef MALLOC_LOG
14 | #define smalloc(z) (mlog(__FILE__,__LINE__), safemalloc(z,1))
15 | #define snmalloc(z,s) (mlog(__FILE__,__LINE__), safemalloc(z,s))
16 | #define srealloc(y,z) (mlog(__FILE__,__LINE__), saferealloc(y,z,1))
17 | #define snrealloc(y,z,s) (mlog(__FILE__,__LINE__), saferealloc(y,z,s))
18 | #define sfree(z) (mlog(__FILE__,__LINE__), safefree(z))
19 | void mlog(char *, int);
20 | #else
21 | #define smalloc(z) safemalloc(z,1)
22 | #define snmalloc safemalloc
23 | #define srealloc(y,z) saferealloc(y,z,1)
24 | #define snrealloc saferealloc
25 | #define sfree safefree
26 | #endif
27 |
28 | void *safemalloc(size_t, size_t);
29 | void *saferealloc(void *, size_t, size_t);
30 | void safefree(void *);
31 |
32 | /*
33 | * Direct use of smalloc within the code should be avoided where
34 | * possible, in favour of these type-casting macros which ensure
35 | * you don't mistakenly allocate enough space for one sort of
36 | * structure and assign it to a different sort of pointer.
37 | *
38 | * The nasty trick in sresize with sizeof arranges for the compiler,
39 | * in passing, to type-check the expression ((type *)0 == (ptr)), i.e.
40 | * to type-check that the input pointer is a pointer to the correct
41 | * type. The construction sizeof(stuff) ? (b) : (b) looks like a
42 | * violation of the first principle of safe macros, but in fact it's
43 | * OK - although it _expands_ the macro parameter more than once, it
44 | * only _evaluates_ it once, so it's still side-effect safe.
45 | */
46 | #define snew(type) ((type *)snmalloc(1, sizeof(type)))
47 | #define snewn(n, type) ((type *)snmalloc((n), sizeof(type)))
48 | #define sresize(ptr, n, type) \
49 | ((type *)snrealloc(sizeof((type *)0 == (ptr)) ? (ptr) : (ptr), \
50 | (n), sizeof(type)))
51 |
52 | #endif
53 |
--------------------------------------------------------------------------------
/charset/toucs.c:
--------------------------------------------------------------------------------
1 | /*
2 | * toucs.c - convert charsets to Unicode.
3 | */
4 |
5 | #include "charset.h"
6 | #include "internal.h"
7 |
8 | struct unicode_emit_param {
9 | wchar_t *output;
10 | int outlen;
11 | const wchar_t *errstr;
12 | int errlen;
13 | int stopped;
14 | };
15 |
16 | static void unicode_emit(void *ctx, long int output)
17 | {
18 | struct unicode_emit_param *param = (struct unicode_emit_param *)ctx;
19 | wchar_t outval;
20 | wchar_t const *p;
21 | int outlen;
22 |
23 | if (output == ERROR) {
24 | if (param->errstr) {
25 | p = param->errstr;
26 | outlen = param->errlen;
27 | } else {
28 | outval = 0xFFFD; /* U+FFFD REPLACEMENT CHARACTER */
29 | p = &outval;
30 | outlen = 1;
31 | }
32 | } else {
33 | outval = output;
34 | p = &outval;
35 | outlen = 1;
36 | }
37 |
38 | if (param->outlen >= outlen) {
39 | while (outlen > 0) {
40 | *param->output++ = *p++;
41 | param->outlen--;
42 | outlen--;
43 | }
44 | } else {
45 | param->stopped = 1;
46 | }
47 | }
48 |
49 | int charset_to_unicode(const char **input, int *inlen,
50 | wchar_t *output, int outlen,
51 | int charset, charset_state *state,
52 | const wchar_t *errstr, int errlen)
53 | {
54 | charset_spec const *spec = charset_find_spec(charset);
55 | charset_state localstate;
56 | struct unicode_emit_param param;
57 |
58 | param.output = output;
59 | param.outlen = outlen;
60 | param.errstr = errstr;
61 | param.errlen = errlen;
62 | param.stopped = 0;
63 |
64 | if (!state) {
65 | localstate.s0 = 0;
66 | } else {
67 | localstate = *state; /* structure copy */
68 | }
69 |
70 | while (*inlen > 0) {
71 | int lenbefore = param.output - output;
72 | spec->read(spec, (unsigned char)**input, &localstate,
73 | unicode_emit, ¶m);
74 | if (param.stopped) {
75 | /*
76 | * The emit function has _tried_ to output some
77 | * characters, but ran up against the end of the
78 | * buffer. Leave immediately, and return what happened
79 | * _before_ attempting to process this character.
80 | */
81 | return lenbefore;
82 | }
83 | if (state)
84 | *state = localstate; /* structure copy */
85 | (*input)++;
86 | (*inlen)--;
87 | }
88 |
89 | return param.output - output;
90 | }
91 |
--------------------------------------------------------------------------------
/charset/fromucs.c:
--------------------------------------------------------------------------------
1 | /*
2 | * fromucs.c - convert Unicode to other character sets.
3 | */
4 |
5 | #include "charset.h"
6 | #include "internal.h"
7 |
8 | struct charset_emit_param {
9 | char *output;
10 | int outlen;
11 | const char *errstr;
12 | int errlen;
13 | int stopped;
14 | };
15 |
16 | static void charset_emit(void *ctx, long int output)
17 | {
18 | struct charset_emit_param *param = (struct charset_emit_param *)ctx;
19 | char outval;
20 | char const *p;
21 | int outlen;
22 |
23 | if (output == ERROR) {
24 | p = param->errstr;
25 | outlen = param->errlen;
26 | } else {
27 | outval = output;
28 | p = &outval;
29 | outlen = 1;
30 | }
31 |
32 | if (param->outlen >= outlen) {
33 | while (outlen > 0) {
34 | *param->output++ = *p++;
35 | param->outlen--;
36 | outlen--;
37 | }
38 | } else {
39 | param->stopped = 1;
40 | }
41 | }
42 |
43 | int charset_from_unicode(const wchar_t **input, int *inlen,
44 | char *output, int outlen,
45 | int charset, charset_state *state,
46 | const char *errstr, int errlen)
47 | {
48 | charset_spec const *spec = charset_find_spec(charset);
49 | charset_state localstate;
50 | struct charset_emit_param param;
51 |
52 | param.output = output;
53 | param.outlen = outlen;
54 | param.stopped = 0;
55 |
56 | /*
57 | * charset_emit will expect a valid errstr.
58 | */
59 | if (!errstr) {
60 | /* *shrug* this is good enough, and consistent across all SBCS... */
61 | param.errstr = ".";
62 | param.errlen = 1;
63 | }
64 | param.errstr = errstr;
65 | param.errlen = errlen;
66 |
67 | if (!state) {
68 | localstate.s0 = 0;
69 | } else {
70 | localstate = *state; /* structure copy */
71 | }
72 | state = &localstate;
73 |
74 | while (*inlen > 0) {
75 | int lenbefore = param.output - output;
76 | spec->write(spec, **input, &localstate, charset_emit, ¶m);
77 | if (param.stopped) {
78 | /*
79 | * The emit function has _tried_ to output some
80 | * characters, but ran up against the end of the
81 | * buffer. Leave immediately, and return what happened
82 | * _before_ attempting to process this character.
83 | */
84 | return lenbefore;
85 | }
86 | if (state)
87 | *state = localstate; /* structure copy */
88 | (*input)++;
89 | (*inlen)--;
90 | }
91 | return param.output - output;
92 | }
93 |
--------------------------------------------------------------------------------
/windows/winsecur.h:
--------------------------------------------------------------------------------
1 | /*
2 | * winsecur.h: some miscellaneous security-related helper functions,
3 | * defined in winsecur.c, that use the advapi32 library. Also
4 | * centralises the machinery for dynamically loading that library.
5 | */
6 |
7 | #if !defined NO_SECURITY
8 |
9 | #include
10 |
11 | #ifndef WINSECUR_GLOBAL
12 | #define WINSECUR_GLOBAL extern
13 | #endif
14 |
15 | /*
16 | * Functions loaded from advapi32.dll.
17 | */
18 | DECL_WINDOWS_FUNCTION(WINSECUR_GLOBAL, BOOL, OpenProcessToken,
19 | (HANDLE, DWORD, PHANDLE));
20 | DECL_WINDOWS_FUNCTION(WINSECUR_GLOBAL, BOOL, GetTokenInformation,
21 | (HANDLE, TOKEN_INFORMATION_CLASS,
22 | LPVOID, DWORD, PDWORD));
23 | DECL_WINDOWS_FUNCTION(WINSECUR_GLOBAL, BOOL, InitializeSecurityDescriptor,
24 | (PSECURITY_DESCRIPTOR, DWORD));
25 | DECL_WINDOWS_FUNCTION(WINSECUR_GLOBAL, BOOL, SetSecurityDescriptorOwner,
26 | (PSECURITY_DESCRIPTOR, PSID, BOOL));
27 | DECL_WINDOWS_FUNCTION(WINSECUR_GLOBAL, DWORD, GetSecurityInfo,
28 | (HANDLE, SE_OBJECT_TYPE, SECURITY_INFORMATION,
29 | PSID *, PSID *, PACL *, PACL *,
30 | PSECURITY_DESCRIPTOR *));
31 | DECL_WINDOWS_FUNCTION(WINSECUR_GLOBAL, DWORD, SetEntriesInAclA,
32 | (ULONG, PEXPLICIT_ACCESS, PACL, PACL *));
33 | int got_advapi(void);
34 |
35 | /*
36 | * Functions loaded from crypt32.dll.
37 | */
38 | DECL_WINDOWS_FUNCTION(WINSECUR_GLOBAL, BOOL, CryptProtectMemory,
39 | (LPVOID, DWORD, DWORD));
40 | int got_crypt(void);
41 |
42 | /*
43 | * Find the SID describing the current user. The return value (if not
44 | * NULL for some error-related reason) is smalloced.
45 | */
46 | PSID get_user_sid(void);
47 |
48 | /*
49 | * Construct a PSECURITY_DESCRIPTOR of the type used for named pipe
50 | * servers, i.e. allowing access only to the current user id and also
51 | * only local (i.e. not over SMB) connections.
52 | *
53 | * If this function returns TRUE, then 'psd' and 'acl' will have been
54 | * filled in with memory allocated using LocalAlloc (and hence must be
55 | * freed later using LocalFree). If it returns FALSE, then instead
56 | * 'error' has been filled with a dynamically allocated error message.
57 | */
58 | int make_private_security_descriptor(DWORD permissions,
59 | PSECURITY_DESCRIPTOR *psd,
60 | PACL *acl,
61 | char **error);
62 |
63 | #endif
64 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.o
2 | *.pyc
3 | .dirstamp
4 | .deps
5 | /*.pdb
6 | /*.ilk
7 | /*.res
8 | /*.RES
9 | /*.pch
10 | /*.rsp
11 | /*.obj
12 | /*.exe
13 | /*.ncb
14 | /*.plg
15 | /*.dsw
16 | /*.opt
17 | /*.dsp
18 | /*.tds
19 | /*.td2
20 | /*.map
21 | /Makefile.bor
22 | /Makefile.cyg
23 | /Makefile.vc
24 | /Makefile.lcc
25 | /MSVC
26 | /*.log
27 | /*.GID
28 | /local
29 | /Output
30 | /pageant
31 | /plink
32 | /pscp
33 | /psftp
34 | /putty
35 | /puttytel
36 | /puttygen
37 | /pterm
38 | /*.DSA
39 | /*.RSA
40 | /*.cnt
41 | /*.hlp
42 | /.bmake
43 | /build.log
44 | /build.out
45 | /uxconfig.h
46 | /empty.h
47 | /config.status
48 | /Makefile.am
49 | /Makefile.in
50 | /Makefile
51 | /compile
52 | /config.status
53 | /configure
54 | /stamp-h1
55 | /aclocal.m4
56 | /ar-lib
57 | /autom4te.cache
58 | /depcomp
59 | /install-sh
60 | /local
61 | /missing
62 | /uxconfig.in
63 | /uxconfig.h
64 | /*.a
65 | /charset/sbcsdat.c
66 | /contrib/cygtermd/cygtermd.exe
67 | /doc/*.html
68 | /doc/*.txt
69 | /doc/*.cnt
70 | /doc/*.hlp
71 | /doc/*.gid
72 | /doc/*.GID
73 | /doc/*.chm
74 | /doc/*.log
75 | /doc/*.1
76 | /doc/*.info
77 | /doc/vstr.but
78 | /doc/*.hhp
79 | /doc/*.hhc
80 | /doc/*.hhk
81 | /icons/*.png
82 | /icons/*.ico
83 | /icons/*.xpm
84 | /icons/*.c
85 | /macosx/Makefile
86 | /macosx/*.app
87 | /macosx/puttygen
88 | /macosx/plink
89 | /macosx/psftp
90 | /macosx/pscp
91 | /testdata/bignum.txt
92 | /unix/Makefile.gtk
93 | /unix/Makefile.ux
94 | /unix/Makefile.local
95 | /unix/empty.h
96 | /unix/plink
97 | /unix/pterm
98 | /unix/putty
99 | /unix/puttytel
100 | /unix/psftp
101 | /unix/pscp
102 | /unix/puttygen
103 | /unix/stamp-h1
104 | /unix/*.log
105 | /unix/.deps
106 | /windows/*.pdb
107 | /windows/*.ilk
108 | /windows/*.res
109 | /windows/*.RES
110 | /windows/*.pch
111 | /windows/*.rsp
112 | /windows/*.obj
113 | /windows/*.exe
114 | /windows/*.ncb
115 | /windows/*.plg
116 | /windows/*.dsw
117 | /windows/*.opt
118 | /windows/*.dsp
119 | /windows/*.tds
120 | /windows/*.td2
121 | /windows/*.map
122 | /windows/Makefile.bor
123 | /windows/Makefile.cyg
124 | /windows/Makefile.vc
125 | /windows/Makefile.lcc
126 | /windows/MSVC
127 | /windows/DEVCPP
128 | /windows/VS2010
129 | /windows/VS2012
130 | /windows/*.log
131 | /windows/*.GID
132 | /windows/local
133 | /windows/Output
134 | /windows/*.DSA
135 | /windows/*.RSA
136 | /windows/*.cnt
137 | /windows/*.hlp
138 | /windows/.bmake
139 | /windows/*.sln
140 | /windows/*.suo
141 |
--------------------------------------------------------------------------------
/doc/Makefile:
--------------------------------------------------------------------------------
1 | all: man index.html
2 |
3 | # Decide on the versionid policy.
4 | #
5 | # If the user has passed in $(VERSION) on the command line (`make
6 | # VERSION="Release 0.56"'), we use that as an explicit version string.
7 | # Otherwise, we use `svnversion' to examine the checked-out
8 | # documentation source, and if that returns a single revision number
9 | # then we invent a version string reflecting just that number. Failing
10 | # _that_, we resort to versionids.but which gives 'version
11 | # unavailable'.
12 | #
13 | # So here, we define VERSION using svnversion if it isn't already
14 | # defined ...
15 | ifndef VERSION
16 | SVNVERSION=$(shell test -d .svn && svnversion .)
17 | BADCHARS=$(findstring :,$(SVNVERSION))$(findstring S,$(SVNVERSION))
18 | ifeq ($(BADCHARS),)
19 | ifneq ($(SVNVERSION),)
20 | ifneq ($(SVNVERSION),exported)
21 | VERSION=Built from revision $(patsubst M,,$(SVNVERSION))
22 | endif
23 | endif
24 | endif
25 | endif
26 | # ... and now, we condition our build behaviour on whether or not
27 | # VERSION _is_ defined.
28 | ifdef VERSION
29 | VERSIONIDS=vstr
30 | vstr.but: FORCE
31 | printf '\\versionid $(VERSION)\n' > vstr.but
32 | FORCE:;
33 | else
34 | VERSIONIDS=vids
35 | endif
36 |
37 | CHAPTERS := $(SITE) blurb intro gs using config pscp psftp plink pubkey
38 | CHAPTERS += pageant errors faq feedback licence udp pgpkeys sshnames
39 | CHAPTERS += index $(VERSIONIDS)
40 |
41 | INPUTS = $(patsubst %,%.but,$(CHAPTERS))
42 |
43 | # This is temporary. Hack it locally or something.
44 | HALIBUT = halibut
45 |
46 | index.html: $(INPUTS)
47 | $(HALIBUT) --text --html --winhelp $(INPUTS)
48 |
49 | # During formal builds it's useful to be able to build this one alone.
50 | putty.hlp: $(INPUTS)
51 | $(HALIBUT) --winhelp $(INPUTS)
52 |
53 | putty.info: $(INPUTS)
54 | $(HALIBUT) --info $(INPUTS)
55 |
56 | chm: putty.hhp
57 | putty.hhp: $(INPUTS) chm.but
58 | $(HALIBUT) --html $(INPUTS) chm.but
59 |
60 | MKMAN = $(HALIBUT) --man=$@ mancfg.but $<
61 | MANPAGES = putty.1 puttygen.1 plink.1 pscp.1 psftp.1 puttytel.1 pterm.1
62 | man: $(MANPAGES)
63 |
64 | putty.1: man-putt.but mancfg.but; $(MKMAN)
65 | puttygen.1: man-pg.but mancfg.but; $(MKMAN)
66 | plink.1: man-pl.but mancfg.but; $(MKMAN)
67 | pscp.1: man-pscp.but mancfg.but; $(MKMAN)
68 | psftp.1: man-psft.but mancfg.but; $(MKMAN)
69 | puttytel.1: man-ptel.but mancfg.but; $(MKMAN)
70 | pterm.1: man-pter.but mancfg.but; $(MKMAN)
71 |
72 | mostlyclean:
73 | rm -f *.html *.txt *.hlp *.cnt *.1 *.info vstr.but *.hh[pck]
74 | clean: mostlyclean
75 | rm -f *.chm
76 |
--------------------------------------------------------------------------------
/unix/uxcfg.c:
--------------------------------------------------------------------------------
1 | /*
2 | * uxcfg.c - the Unix-specific parts of the PuTTY configuration
3 | * box.
4 | */
5 |
6 | #include
7 | #include
8 |
9 | #include "putty.h"
10 | #include "dialog.h"
11 | #include "storage.h"
12 |
13 | void unix_setup_config_box(struct controlbox *b, int midsession, int protocol)
14 | {
15 | struct controlset *s;
16 | union control *c;
17 |
18 | /*
19 | * The Conf structure contains two Unix-specific elements which
20 | * are not configured in here: stamp_utmp and login_shell. This
21 | * is because pterm does not put up a configuration box right at
22 | * the start, which is the only time when these elements would
23 | * be useful to configure.
24 | */
25 |
26 | /*
27 | * On Unix, we don't have a drop-down list for the printer
28 | * control.
29 | */
30 | s = ctrl_getset(b, "Terminal", "printing", "Remote-controlled printing");
31 | assert(s->ncontrols == 1 && s->ctrls[0]->generic.type == CTRL_EDITBOX);
32 | s->ctrls[0]->editbox.has_list = 0;
33 |
34 | /*
35 | * Unix supports a local-command proxy. This also means we must
36 | * adjust the text on the `Telnet command' control.
37 | */
38 | if (!midsession) {
39 | int i;
40 | s = ctrl_getset(b, "Connection/Proxy", "basics", NULL);
41 | for (i = 0; i < s->ncontrols; i++) {
42 | c = s->ctrls[i];
43 | if (c->generic.type == CTRL_RADIO &&
44 | c->generic.context.i == CONF_proxy_type) {
45 | assert(c->generic.handler == conf_radiobutton_handler);
46 | c->radio.nbuttons++;
47 | c->radio.buttons =
48 | sresize(c->radio.buttons, c->radio.nbuttons, char *);
49 | c->radio.buttons[c->radio.nbuttons-1] =
50 | dupstr("Local");
51 | c->radio.buttondata =
52 | sresize(c->radio.buttondata, c->radio.nbuttons, intorptr);
53 | c->radio.buttondata[c->radio.nbuttons-1] = I(PROXY_CMD);
54 | break;
55 | }
56 | }
57 |
58 | for (i = 0; i < s->ncontrols; i++) {
59 | c = s->ctrls[i];
60 | if (c->generic.type == CTRL_EDITBOX &&
61 | c->generic.context.i == CONF_proxy_telnet_command) {
62 | assert(c->generic.handler == conf_editbox_handler);
63 | sfree(c->generic.label);
64 | c->generic.label = dupstr("Telnet command, or local"
65 | " proxy command");
66 | break;
67 | }
68 | }
69 | }
70 |
71 | /*
72 | * Serial back end is available on Unix. However, we have to
73 | * mask out a couple of the configuration options: mark and
74 | * space parity are not conveniently supported, and neither is
75 | * DSR/DTR flow control.
76 | */
77 | if (!midsession || (protocol == PROT_SERIAL))
78 | ser_setup_config_box(b, midsession, 0x07, 0x07);
79 | }
80 |
--------------------------------------------------------------------------------
/doc/sshnames.but:
--------------------------------------------------------------------------------
1 | \A{sshnames} SSH-2 names specified for PuTTY
2 |
3 | There are various parts of the SSH-2 protocol where things are specified
4 | using a textual name. Names ending in \cw{@putty.projects.tartarus.org}
5 | are reserved for allocation by the PuTTY team. Allocated names are
6 | documented here.
7 |
8 | \H{sshnames-channel} Connection protocol channel request names
9 |
10 | These names can be sent in a \cw{SSH_MSG_CHANNEL_REQUEST} message.
11 |
12 | \dt \cw{simple@putty.projects.tartarus.org}
13 |
14 | \dd This is sent by a client to announce that it will not have more than
15 | one channel open at a time in the current connection (that one being
16 | the one the request is sent on). The intention is that the server,
17 | knowing this, can set the window on that one channel to something very
18 | large, and leave flow control to TCP. There is no message-specific data.
19 |
20 | \dt \cw{winadj@putty.projects.tartarus.org}
21 |
22 | \dd PuTTY sends this request along with some
23 | \cw{SSH_MSG_CHANNEL_WINDOW_ADJUST} messages as part of its window-size
24 | tuning. It can be sent on any type of channel. There is no
25 | message-specific data. Servers MUST treat it as an unrecognised request
26 | and respond with \cw{SSH_MSG_CHANNEL_FAILURE}.
27 |
28 | \lcont{
29 | (Some SSH servers get confused by this message, so there is a
30 | bug-compatibility mode for disabling it. See \k{config-ssh-bug-winadj}.)
31 | }
32 |
33 | \H{sshnames-kex} Key exchange method names
34 |
35 | \dt \cw{rsa-sha1-draft-00@putty.projects.tartarus.org}
36 |
37 | \dt \cw{rsa-sha256-draft-00@putty.projects.tartarus.org}
38 |
39 | \dt \cw{rsa1024-sha1-draft-01@putty.projects.tartarus.org}
40 |
41 | \dt \cw{rsa1024-sha256-draft-01@putty.projects.tartarus.org}
42 |
43 | \dt \cw{rsa2048-sha256-draft-01@putty.projects.tartarus.org}
44 |
45 | \dt \cw{rsa1024-sha1-draft-02@putty.projects.tartarus.org}
46 |
47 | \dt \cw{rsa2048-sha512-draft-02@putty.projects.tartarus.org}
48 |
49 | \dt \cw{rsa1024-sha1-draft-03@putty.projects.tartarus.org}
50 |
51 | \dt \cw{rsa2048-sha256-draft-03@putty.projects.tartarus.org}
52 |
53 | \dt \cw{rsa1024-sha1-draft-04@putty.projects.tartarus.org}
54 |
55 | \dt \cw{rsa2048-sha256-draft-04@putty.projects.tartarus.org}
56 |
57 | \dd These appeared in various drafts of what eventually became RFC\_4432.
58 | They have been superseded by \cw{rsa1024-sha1} and \cw{rsa2048-sha256}.
59 |
60 | \H{sshnames-encrypt} Encryption algorithm names
61 |
62 | \dt \cw{arcfour128-draft-00@putty.projects.tartarus.org}
63 |
64 | \dt \cw{arcfour256-draft-00@putty.projects.tartarus.org}
65 |
66 | \dd These were used in drafts of what eventually became RFC\_4345.
67 | They have been superseded by \cw{arcfour128} and \cw{arcfour256}.
68 |
--------------------------------------------------------------------------------
/charset/xenc.c:
--------------------------------------------------------------------------------
1 | /*
2 | * xenc.c - translate our internal character set codes to and from
3 | * X11 character encoding names.
4 | *
5 | */
6 |
7 | #include
8 | #include "charset.h"
9 | #include "internal.h"
10 |
11 | static const struct {
12 | const char *name;
13 | int charset;
14 | } xencs[] = {
15 | /*
16 | * Officially registered encoding names. This list is derived
17 | * from the font encodings section of
18 | *
19 | * http://ftp.x.org/pub/DOCS/registry
20 | *
21 | * Where multiple encoding names map to the same encoding id
22 | * (such as iso8859-15 and fcd8859-15), the first is considered
23 | * canonical and will be returned when translating the id to a
24 | * string.
25 | */
26 | { "iso8859-1", CS_ISO8859_1 },
27 | { "iso8859-2", CS_ISO8859_2 },
28 | { "iso8859-3", CS_ISO8859_3 },
29 | { "iso8859-4", CS_ISO8859_4 },
30 | { "iso8859-5", CS_ISO8859_5 },
31 | { "iso8859-6", CS_ISO8859_6 },
32 | { "iso8859-7", CS_ISO8859_7 },
33 | { "iso8859-8", CS_ISO8859_8 },
34 | { "iso8859-9", CS_ISO8859_9 },
35 | { "iso8859-10", CS_ISO8859_10 },
36 | { "iso8859-13", CS_ISO8859_13 },
37 | { "iso8859-14", CS_ISO8859_14 },
38 | { "iso8859-15", CS_ISO8859_15 },
39 | { "fcd8859-15", CS_ISO8859_15 },
40 | { "hp-roman8", CS_HP_ROMAN8 },
41 | { "koi8-r", CS_KOI8_R },
42 | /*
43 | * Unofficial encoding names found in the wild.
44 | */
45 | { "iso8859-16", CS_ISO8859_16 },
46 | { "koi8-u", CS_KOI8_U },
47 | { "ibm-cp437", CS_CP437 },
48 | { "ibm-cp850", CS_CP850 },
49 | { "ibm-cp852", CS_CP852 },
50 | { "ibm-cp866", CS_CP866 },
51 | { "microsoft-cp1250", CS_CP1250 },
52 | { "microsoft-cp1251", CS_CP1251 },
53 | { "microsoft-cp1252", CS_CP1252 },
54 | { "microsoft-cp1253", CS_CP1253 },
55 | { "microsoft-cp1254", CS_CP1254 },
56 | { "microsoft-cp1255", CS_CP1255 },
57 | { "microsoft-cp1256", CS_CP1256 },
58 | { "microsoft-cp1257", CS_CP1257 },
59 | { "microsoft-cp1258", CS_CP1258 },
60 | { "mac-roman", CS_MAC_ROMAN },
61 | { "viscii1.1-1", CS_VISCII },
62 | { "viscii1-1", CS_VISCII },
63 | };
64 |
65 | const char *charset_to_xenc(int charset)
66 | {
67 | int i;
68 |
69 | for (i = 0; i < (int)lenof(xencs); i++)
70 | if (charset == xencs[i].charset)
71 | return xencs[i].name;
72 |
73 | return NULL; /* not found */
74 | }
75 |
76 | int charset_from_xenc(const char *name)
77 | {
78 | int i;
79 |
80 | for (i = 0; i < (int)lenof(xencs); i++) {
81 | const char *p, *q;
82 | p = name;
83 | q = xencs[i].name;
84 | while (*p || *q) {
85 | if (tolower((unsigned char)*p) != tolower((unsigned char)*q))
86 | break;
87 | p++; q++;
88 | }
89 | if (!*p && !*q)
90 | return xencs[i].charset;
91 | }
92 |
93 | return CS_NONE; /* not found */
94 | }
95 |
--------------------------------------------------------------------------------
/ldiscucs.c:
--------------------------------------------------------------------------------
1 | /*
2 | * ldisc.c: PuTTY line discipline. Sits between the input coming
3 | * from keypresses in the window, and the output channel leading to
4 | * the back end. Implements echo and/or local line editing,
5 | * depending on what's currently configured.
6 | */
7 |
8 | #include
9 | #include
10 |
11 | #include "putty.h"
12 | #include "terminal.h"
13 | #include "ldisc.h"
14 |
15 | void lpage_send(void *handle,
16 | int codepage, char *buf, int len, int interactive)
17 | {
18 | Ldisc ldisc = (Ldisc)handle;
19 | wchar_t *widebuffer = 0;
20 | int widesize = 0;
21 | int wclen;
22 |
23 | if (codepage < 0) {
24 | ldisc_send(ldisc, buf, len, interactive);
25 | return;
26 | }
27 |
28 | widesize = len * 2;
29 | widebuffer = snewn(widesize, wchar_t);
30 |
31 | wclen = mb_to_wc(codepage, 0, buf, len, widebuffer, widesize);
32 | luni_send(ldisc, widebuffer, wclen, interactive);
33 |
34 | sfree(widebuffer);
35 | }
36 |
37 | void luni_send(void *handle, wchar_t * widebuf, int len, int interactive)
38 | {
39 | Ldisc ldisc = (Ldisc)handle;
40 | int ratio = (in_utf(ldisc->term))?3:1;
41 | char *linebuffer;
42 | int linesize;
43 | int i;
44 | char *p;
45 |
46 | linesize = len * ratio * 2;
47 | linebuffer = snewn(linesize, char);
48 |
49 | if (in_utf(ldisc->term)) {
50 | /* UTF is a simple algorithm */
51 | for (p = linebuffer, i = 0; i < len; i++) {
52 | unsigned long ch = widebuf[i];
53 |
54 | if (IS_SURROGATE(ch)) {
55 | #ifdef PLATFORM_IS_UTF16
56 | if (i+1 < len) {
57 | unsigned long ch2 = widebuf[i+1];
58 | if (IS_SURROGATE_PAIR(ch, ch2)) {
59 | ch = FROM_SURROGATES(ch, ch2);
60 | i++;
61 | }
62 | } else
63 | #endif
64 | {
65 | /* Unrecognised UTF-16 sequence */
66 | ch = '.';
67 | }
68 | }
69 |
70 | if (ch < 0x80) {
71 | *p++ = (char) (ch);
72 | } else if (ch < 0x800) {
73 | *p++ = (char) (0xC0 | (ch >> 6));
74 | *p++ = (char) (0x80 | (ch & 0x3F));
75 | } else if (ch < 0x10000) {
76 | *p++ = (char) (0xE0 | (ch >> 12));
77 | *p++ = (char) (0x80 | ((ch >> 6) & 0x3F));
78 | *p++ = (char) (0x80 | (ch & 0x3F));
79 | } else {
80 | *p++ = (char) (0xF0 | (ch >> 18));
81 | *p++ = (char) (0x80 | ((ch >> 12) & 0x3F));
82 | *p++ = (char) (0x80 | ((ch >> 6) & 0x3F));
83 | *p++ = (char) (0x80 | (ch & 0x3F));
84 | }
85 | }
86 | } else {
87 | int rv;
88 | rv = wc_to_mb(ldisc->term->ucsdata->line_codepage, 0, widebuf, len,
89 | linebuffer, linesize, NULL, NULL, ldisc->term->ucsdata);
90 | if (rv >= 0)
91 | p = linebuffer + rv;
92 | else
93 | p = linebuffer;
94 | }
95 | if (p > linebuffer)
96 | ldisc_send(ldisc, linebuffer, p - linebuffer, interactive);
97 |
98 | sfree(linebuffer);
99 | }
100 |
--------------------------------------------------------------------------------
/unix/gtkfont.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Header file for gtkfont.c. Has to be separate from unix.h
3 | * because it depends on GTK data types, hence can't be included
4 | * from cross-platform code (which doesn't go near GTK).
5 | */
6 |
7 | #ifndef PUTTY_GTKFONT_H
8 | #define PUTTY_GTKFONT_H
9 |
10 | /*
11 | * Exports from gtkfont.c.
12 | */
13 | struct unifont_vtable; /* contents internal to gtkfont.c */
14 | typedef struct unifont {
15 | const struct unifont_vtable *vt;
16 | /*
17 | * `Non-static data members' of the `class', accessible to
18 | * external code.
19 | */
20 |
21 | /*
22 | * public_charset is the charset used when the user asks for
23 | * `Use font encoding'.
24 | */
25 | int public_charset;
26 |
27 | /*
28 | * Font dimensions needed by clients.
29 | */
30 | int width, height, ascent, descent;
31 |
32 | /*
33 | * Indicates whether this font is capable of handling all glyphs
34 | * (Pango fonts can do this because Pango automatically supplies
35 | * missing glyphs from other fonts), or whether it would like a
36 | * fallback font to cope with missing glyphs.
37 | */
38 | int want_fallback;
39 | } unifont;
40 |
41 | unifont *unifont_create(GtkWidget *widget, const char *name,
42 | int wide, int bold,
43 | int shadowoffset, int shadowalways);
44 | void unifont_destroy(unifont *font);
45 | void unifont_draw_text(GdkDrawable *target, GdkGC *gc, unifont *font,
46 | int x, int y, const wchar_t *string, int len,
47 | int wide, int bold, int cellwidth);
48 |
49 | /*
50 | * This function behaves exactly like the low-level unifont_create,
51 | * except that as well as the requested font it also allocates (if
52 | * necessary) a fallback font for filling in replacement glyphs.
53 | *
54 | * Return value is usable with unifont_destroy and unifont_draw_text
55 | * as if it were an ordinary unifont.
56 | */
57 | unifont *multifont_create(GtkWidget *widget, const char *name,
58 | int wide, int bold,
59 | int shadowoffset, int shadowalways);
60 |
61 | /*
62 | * Unified font selector dialog. I can't be bothered to do a
63 | * proper GTK subclassing today, so this will just be an ordinary
64 | * data structure with some useful members.
65 | *
66 | * (Of course, these aren't the only members; this structure is
67 | * contained within a bigger one which holds data visible only to
68 | * the implementation.)
69 | */
70 | typedef struct unifontsel {
71 | void *user_data; /* settable by the user */
72 | GtkWindow *window;
73 | GtkWidget *ok_button, *cancel_button;
74 | } unifontsel;
75 |
76 | unifontsel *unifontsel_new(const char *wintitle);
77 | void unifontsel_destroy(unifontsel *fontsel);
78 | void unifontsel_set_name(unifontsel *fontsel, const char *fontname);
79 | char *unifontsel_get_name(unifontsel *fontsel);
80 |
81 | #endif /* PUTTY_GTKFONT_H */
82 |
--------------------------------------------------------------------------------
/windows/winproxy.c:
--------------------------------------------------------------------------------
1 | /*
2 | * winproxy.c: Windows implementation of platform_new_connection(),
3 | * supporting an OpenSSH-like proxy command via the winhandl.c
4 | * mechanism.
5 | */
6 |
7 | #include
8 | #include
9 |
10 | #define DEFINE_PLUG_METHOD_MACROS
11 | #include "tree234.h"
12 | #include "putty.h"
13 | #include "network.h"
14 | #include "proxy.h"
15 |
16 | Socket make_handle_socket(HANDLE send_H, HANDLE recv_H, Plug plug,
17 | int overlapped);
18 |
19 | Socket platform_new_connection(SockAddr addr, char *hostname,
20 | int port, int privport,
21 | int oobinline, int nodelay, int keepalive,
22 | Plug plug, Conf *conf)
23 | {
24 | char *cmd;
25 | HANDLE us_to_cmd, us_from_cmd, cmd_to_us, cmd_from_us;
26 | SECURITY_ATTRIBUTES sa;
27 | STARTUPINFO si;
28 | PROCESS_INFORMATION pi;
29 |
30 | if (conf_get_int(conf, CONF_proxy_type) != PROXY_CMD)
31 | return NULL;
32 |
33 | cmd = format_telnet_command(addr, port, conf);
34 |
35 | /* We are responsible for this and don't need it any more */
36 | sk_addr_free(addr);
37 |
38 | {
39 | char *msg = dupprintf("Starting local proxy command: %s", cmd);
40 | /* We're allowed to pass NULL here, because we're part of the Windows
41 | * front end so we know logevent doesn't expect any data. */
42 | logevent(NULL, msg);
43 | sfree(msg);
44 | }
45 |
46 | /*
47 | * Create the pipes to the proxy command, and spawn the proxy
48 | * command process.
49 | */
50 | sa.nLength = sizeof(sa);
51 | sa.lpSecurityDescriptor = NULL; /* default */
52 | sa.bInheritHandle = TRUE;
53 | if (!CreatePipe(&us_from_cmd, &cmd_to_us, &sa, 0)) {
54 | Socket ret =
55 | new_error_socket("Unable to create pipes for proxy command", plug);
56 | sfree(cmd);
57 | return ret;
58 | }
59 |
60 | if (!CreatePipe(&cmd_from_us, &us_to_cmd, &sa, 0)) {
61 | Socket ret =
62 | new_error_socket("Unable to create pipes for proxy command", plug);
63 | sfree(cmd);
64 | CloseHandle(us_from_cmd);
65 | CloseHandle(cmd_to_us);
66 | return ret;
67 | }
68 |
69 | SetHandleInformation(us_to_cmd, HANDLE_FLAG_INHERIT, 0);
70 | SetHandleInformation(us_from_cmd, HANDLE_FLAG_INHERIT, 0);
71 |
72 | si.cb = sizeof(si);
73 | si.lpReserved = NULL;
74 | si.lpDesktop = NULL;
75 | si.lpTitle = NULL;
76 | si.dwFlags = STARTF_USESTDHANDLES;
77 | si.cbReserved2 = 0;
78 | si.lpReserved2 = NULL;
79 | si.hStdInput = cmd_from_us;
80 | si.hStdOutput = cmd_to_us;
81 | si.hStdError = NULL;
82 | CreateProcess(NULL, cmd, NULL, NULL, TRUE,
83 | CREATE_NO_WINDOW | NORMAL_PRIORITY_CLASS,
84 | NULL, NULL, &si, &pi);
85 | CloseHandle(pi.hProcess);
86 | CloseHandle(pi.hThread);
87 |
88 | sfree(cmd);
89 |
90 | CloseHandle(cmd_from_us);
91 | CloseHandle(cmd_to_us);
92 |
93 | return make_handle_socket(us_to_cmd, us_from_cmd, plug, FALSE);
94 | }
95 |
--------------------------------------------------------------------------------
/doc/man-psft.but:
--------------------------------------------------------------------------------
1 | \cfg{man-identity}{psftp}{1}{2004-03-24}{PuTTY tool suite}{PuTTY tool suite}
2 |
3 | \H{psftp-manpage} Man page for PSFTP
4 |
5 | \S{psftp-manpage-name} NAME
6 |
7 | \cw{psftp} \- interactive SFTP (secure file transfer protocol) client
8 |
9 | \S{psftp-manpage-synopsis} SYNOPSIS
10 |
11 | \c psftp [options] [user@]host
12 | \e bbbbb iiiiiii iiiib iiii
13 |
14 | \S{psftp-manpage-description} DESCRIPTION
15 |
16 | \cw{psftp} is an interactive text-based client for the SSH-based SFTP
17 | (secure file transfer) protocol.
18 |
19 | \S{psftp-manpage-options} OPTIONS
20 |
21 | The command-line options supported by \cw{psftp} are:
22 |
23 | \dt \cw{-V}
24 |
25 | \dd Show version information and exit.
26 |
27 | \dt \cw{-pgpfp}
28 |
29 | \dd Display the fingerprints of the PuTTY PGP Master Keys and exit,
30 | to aid in verifying new files released by the PuTTY team.
31 |
32 | \dt \cw{-b} \e{batchfile}
33 |
34 | \dd Use specified batchfile.
35 |
36 | \dt \cw{-bc}
37 |
38 | \dd Output batchfile commands.
39 |
40 | \dt \cw{-be}
41 |
42 | \dd Don't stop batchfile processing on errors.
43 |
44 | \dt \cw{-v}
45 |
46 | \dd Show verbose messages.
47 |
48 | \dt \cw{-load} \e{session}
49 |
50 | \dd Load settings from saved session.
51 |
52 | \dt \cw{-P} \e{port}
53 |
54 | \dd Connect to port \e{port}.
55 |
56 | \dt \cw{-l} \e{user}
57 |
58 | \dd Set remote username to \e{user}.
59 |
60 | \dt \cw{-batch}
61 |
62 | \dd Disable interactive prompts.
63 |
64 | \dt \cw{-pw} \e{password}
65 |
66 | \dd Set remote password to \e{password}. \e{CAUTION:} this will likely
67 | make the password visible to other users of the local machine (via
68 | commands such as \q{\c{w}}).
69 |
70 | \dt \cw{-1}
71 |
72 | \dd Force use of SSH protocol version 1.
73 |
74 | \dt \cw{-2}
75 |
76 | \dd Force use of SSH protocol version 2.
77 |
78 | \dt \cw{-C}
79 |
80 | \dd Enable SSH compression.
81 |
82 | \dt \cw{-i} \e{path}
83 |
84 | \dd Private key file for user authentication.
85 |
86 | \dt \cw{\-hostkey} \e{key}
87 |
88 | \dd Specify an acceptable host public key. This option may be specified
89 | multiple times; each key can be either a fingerprint (\cw{99:aa:bb:...}) or
90 | a base64-encoded blob in OpenSSH's one-line format.
91 |
92 | \lcont{ Specifying this option overrides automated host key
93 | management; \e{only} the key(s) specified on the command-line will be
94 | accepted (unless a saved session also overrides host keys, in which
95 | case those will be added to), and the host key cache will not be
96 | written. }
97 |
98 | \S{psftp-manpage-commands} COMMANDS
99 |
100 | For a list of commands available inside \cw{psftp}, type \cw{help}
101 | at the \cw{psftp>} prompt.
102 |
103 | \S{psftp-manpage-more-information} MORE INFORMATION
104 |
105 | For more information on \cw{psftp} it's probably best to go and look at
106 | the manual on the PuTTY web page:
107 |
108 | \cw{http://www.chiark.greenend.org.uk/~sgtatham/putty/}
109 |
110 | \S{psftp-manpage-bugs} BUGS
111 |
112 | This man page isn't terribly complete. See the above web link for
113 | better documentation.
114 |
--------------------------------------------------------------------------------
/charset/sbcsgen.pl:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env perl -w
2 |
3 | # This script generates sbcsdat.c (the data for all the SBCSes) from its
4 | # source form sbcs.dat.
5 |
6 | $infile = "sbcs.dat";
7 | $outfile = "sbcsdat.c";
8 |
9 | open FOO, $infile;
10 | open BAR, ">$outfile";
11 | select BAR;
12 |
13 | print "/*\n";
14 | print " * sbcsdat.c - data definitions for single-byte character sets.\n";
15 | print " *\n";
16 | print " * Generated by sbcsgen.pl from sbcs.dat.\n";
17 | print " * You should edit those files rather than editing this one.\n";
18 | print " */\n";
19 | print "\n";
20 | print "#ifndef ENUM_CHARSETS\n";
21 | print "\n";
22 | print "#include \"charset.h\"\n";
23 | print "#include \"internal.h\"\n";
24 | print "\n";
25 |
26 | my $charsetname = undef;
27 | my @vals = ();
28 |
29 | my @charsetnames = ();
30 | my @sortpriority = ();
31 |
32 | while () {
33 | chomp;
34 | if (/^charset (.*)$/) {
35 | $charsetname = $1;
36 | @vals = ();
37 | @sortpriority = map { 0 } 0..255;
38 | } elsif (/^sortpriority ([^-]*)-([^-]*) (.*)$/) {
39 | for ($i = hex $1; $i <= hex $2; $i++) {
40 | $sortpriority[$i] += $3;
41 | }
42 | } elsif (/^[0-9a-fA-FX]/) {
43 | push @vals, map { $_ eq "XXXX" ? -1 : hex $_ } split / +/, $_;
44 | if (scalar @vals > 256) {
45 | die "$infile:$.: charset $charsetname has more than 256 values\n";
46 | } elsif (scalar @vals == 256) {
47 | &outcharset($charsetname, \@vals, \@sortpriority);
48 | push @charsetnames, $charsetname;
49 | $charsetname = undef;
50 | @vals = ();
51 | @sortpriority = map { 0 } 0..255;
52 | }
53 | }
54 | }
55 |
56 | print "#else /* ENUM_CHARSETS */\n";
57 | print "\n";
58 |
59 | foreach $i (@charsetnames) {
60 | print "ENUM_CHARSET($i)\n";
61 | }
62 |
63 | print "\n";
64 | print "#endif /* ENUM_CHARSETS */\n";
65 |
66 | sub outcharset($$$) {
67 | my ($name, $vals, $sortpriority) = @_;
68 | my ($prefix, $i, @sorted);
69 |
70 | print "static const sbcs_data data_$name = {\n";
71 | print " {\n";
72 | $prefix = " ";
73 | @sorted = ();
74 | for ($i = 0; $i < 256; $i++) {
75 | if ($vals->[$i] < 0) {
76 | printf "%sERROR ", $prefix;
77 | } else {
78 | printf "%s0x%04x", $prefix, $vals->[$i];
79 | die "ooh? $i\n" unless defined $sortpriority->[$i];
80 | push @sorted, [$i, $vals->[$i], 0+$sortpriority->[$i]];
81 | }
82 | if ($i % 8 == 7) {
83 | $prefix = ",\n ";
84 | } else {
85 | $prefix = ", ";
86 | }
87 | }
88 | print "\n },\n {\n";
89 | @sorted = sort { ($a->[1] == $b->[1] ?
90 | $b->[2] <=> $a->[2] :
91 | $a->[1] <=> $b->[1]) ||
92 | $a->[0] <=> $b->[0] } @sorted;
93 | $prefix = " ";
94 | $uval = -1;
95 | for ($i = $j = 0; $i < scalar @sorted; $i++) {
96 | next if ($uval == $sorted[$i]->[1]); # low-priority alternative
97 | $uval = $sorted[$i]->[1];
98 | printf "%s0x%02x", $prefix, $sorted[$i]->[0];
99 | if ($j % 8 == 7) {
100 | $prefix = ",\n ";
101 | } else {
102 | $prefix = ", ";
103 | }
104 | $j++;
105 | }
106 | printf "\n },\n %d\n", $j;
107 | print "};\n";
108 | print "const charset_spec charset_$name = {\n" .
109 | " $name, read_sbcs, write_sbcs, &data_$name\n};\n\n";
110 | }
111 |
--------------------------------------------------------------------------------
/unix/uxsel.c:
--------------------------------------------------------------------------------
1 | /*
2 | * uxsel.c
3 | *
4 | * This module is a sort of all-purpose interchange for file
5 | * descriptors. At one end it talks to uxnet.c and pty.c and
6 | * anything else which might have one or more fds that need
7 | * select()-type things doing to them during an extended program
8 | * run; at the other end it talks to pterm.c or uxplink.c or
9 | * anything else which might have its own means of actually doing
10 | * those select()-type things.
11 | */
12 |
13 | #include
14 |
15 | #include "putty.h"
16 | #include "tree234.h"
17 |
18 | struct fd {
19 | int fd;
20 | int rwx; /* 4=except 2=write 1=read */
21 | uxsel_callback_fn callback;
22 | int id; /* for uxsel_input_remove */
23 | };
24 |
25 | static tree234 *fds;
26 |
27 | static int uxsel_fd_cmp(void *av, void *bv)
28 | {
29 | struct fd *a = (struct fd *)av;
30 | struct fd *b = (struct fd *)bv;
31 | if (a->fd < b->fd)
32 | return -1;
33 | if (a->fd > b->fd)
34 | return +1;
35 | return 0;
36 | }
37 | static int uxsel_fd_findcmp(void *av, void *bv)
38 | {
39 | int *a = (int *)av;
40 | struct fd *b = (struct fd *)bv;
41 | if (*a < b->fd)
42 | return -1;
43 | if (*a > b->fd)
44 | return +1;
45 | return 0;
46 | }
47 |
48 | void uxsel_init(void)
49 | {
50 | fds = newtree234(uxsel_fd_cmp);
51 | }
52 |
53 | /*
54 | * Here is the interface to fd-supplying modules. They supply an
55 | * fd, a set of read/write/execute states, and a callback function
56 | * for when the fd satisfies one of those states. Repeated calls to
57 | * uxsel_set on the same fd are perfectly legal and serve to change
58 | * the rwx state (typically you only want to select an fd for
59 | * writing when you actually have pending data you want to write to
60 | * it!).
61 | */
62 |
63 | void uxsel_set(int fd, int rwx, uxsel_callback_fn callback)
64 | {
65 | struct fd *newfd;
66 |
67 | uxsel_del(fd);
68 |
69 | if (rwx) {
70 | newfd = snew(struct fd);
71 | newfd->fd = fd;
72 | newfd->rwx = rwx;
73 | newfd->callback = callback;
74 | newfd->id = uxsel_input_add(fd, rwx);
75 | add234(fds, newfd);
76 | }
77 | }
78 |
79 | void uxsel_del(int fd)
80 | {
81 | struct fd *oldfd = find234(fds, &fd, uxsel_fd_findcmp);
82 | if (oldfd) {
83 | uxsel_input_remove(oldfd->id);
84 | del234(fds, oldfd);
85 | sfree(oldfd);
86 | }
87 | }
88 |
89 | /*
90 | * And here is the interface to select-functionality-supplying
91 | * modules.
92 | */
93 |
94 | int next_fd(int *state, int *rwx)
95 | {
96 | struct fd *fd;
97 | fd = index234(fds, (*state)++);
98 | if (fd) {
99 | *rwx = fd->rwx;
100 | return fd->fd;
101 | } else
102 | return -1;
103 | }
104 |
105 | int first_fd(int *state, int *rwx)
106 | {
107 | *state = 0;
108 | return next_fd(state, rwx);
109 | }
110 |
111 | int select_result(int fd, int event)
112 | {
113 | struct fd *fdstruct = find234(fds, &fd, uxsel_fd_findcmp);
114 | /*
115 | * Apparently this can sometimes be NULL. Can't see how, but I
116 | * assume it means I need to ignore the event since it's on an
117 | * fd I've stopped being interested in. Sigh.
118 | */
119 | if (fdstruct)
120 | return fdstruct->callback(fd, event);
121 | else
122 | return 1;
123 | }
124 |
--------------------------------------------------------------------------------
/macosx/osxclass.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Header file for the Objective-C parts of Mac OS X PuTTY. This
3 | * file contains the class definitions, which would cause compile
4 | * failures in the pure C modules if they appeared in osx.h.
5 | */
6 |
7 | #ifndef PUTTY_OSXCLASS_H
8 | #define PUTTY_OSXCLASS_H
9 |
10 | #include "putty.h"
11 |
12 | /*
13 | * The application controller class, defined in osxmain.m.
14 | */
15 | @interface AppController : NSObject
16 | {
17 | NSTimer *timer;
18 | }
19 | - (void)newSessionConfig:(id)sender;
20 | - (void)newTerminal:(id)sender;
21 | - (void)newSessionWithConfig:(id)cfg;
22 | - (void)setTimer:(long)next;
23 | @end
24 | extern AppController *controller;
25 |
26 | /*
27 | * The SessionWindow class, defined in osxwin.m.
28 | */
29 |
30 | struct alert_queue {
31 | struct alert_queue *next;
32 | NSAlert *alert;
33 | void (*callback)(void *, int);
34 | void *ctx;
35 | };
36 |
37 | @class SessionWindow;
38 | @class TerminalView;
39 |
40 | @interface SessionWindow : NSWindow
41 | {
42 | Terminal *term;
43 | TerminalView *termview;
44 | struct unicode_data ucsdata;
45 | void *logctx;
46 | Config cfg;
47 | void *ldisc;
48 | Backend *back;
49 | void *backhandle;
50 | int exited;
51 | /*
52 | * The following two members relate to the currently active
53 | * alert sheet, if any. They are NULL if there isn't one.
54 | */
55 | void (*alert_callback)(void *, int);
56 | void *alert_ctx;
57 | /* This queues future alerts that need to be shown. */
58 | struct alert_queue *alert_qhead, *alert_qtail;
59 | }
60 | - (id)initWithConfig:(Config)cfg;
61 | - (void)drawStartFinish:(BOOL)start;
62 | - (void)setColour:(int)n r:(float)r g:(float)g b:(float)b;
63 | - (Config *)cfg;
64 | - (void)doText:(wchar_t *)text len:(int)len x:(int)x y:(int)y
65 | attr:(unsigned long)attr lattr:(int)lattr;
66 | - (int)fromBackend:(const char *)data len:(int)len isStderr:(int)is_stderr;
67 | - (int)fromBackendUntrusted:(const char *)data len:(int)len;
68 | - (void)startAlert:(NSAlert *)alert
69 | withCallback:(void (*)(void *, int))callback andCtx:(void *)ctx;
70 | - (void)endSession:(int)clean;
71 | - (void)notifyRemoteExit;
72 | - (Terminal *)term;
73 | @end
74 |
75 | /*
76 | * The ConfigWindow class, defined in osxdlg.m.
77 | */
78 |
79 | @class ConfigWindow;
80 |
81 | @interface ConfigWindow : NSWindow
82 | {
83 | NSOutlineView *treeview;
84 | struct controlbox *ctrlbox;
85 | void *dv;
86 | Config cfg;
87 | }
88 | - (id)initWithConfig:(Config)cfg;
89 | @end
90 |
91 | /*
92 | * Functions exported by osxctrls.m. (They have to go in this
93 | * header file and not osx.h, because some of them have Cocoa class
94 | * types in their prototypes.)
95 | */
96 | #define HSPACING 12 /* needed in osxdlg.m and osxctrls.m */
97 | #define VSPACING 8
98 |
99 | void *fe_dlg_init(void *data, NSWindow *window, NSObject *target, SEL action);
100 | void fe_dlg_free(void *dv);
101 | void create_ctrls(void *dv, NSView *parent, struct controlset *s,
102 | int *minw, int *minh);
103 | int place_ctrls(void *dv, struct controlset *s, int leftx, int topy,
104 | int width); /* returns height used */
105 | void select_panel(void *dv, struct controlbox *b, const char *name);
106 |
107 | #endif /* PUTTY_OSXCLASS_H */
108 |
--------------------------------------------------------------------------------
/charset/internal.h:
--------------------------------------------------------------------------------
1 | /*
2 | * internal.h - internal header stuff for the charset library.
3 | */
4 |
5 | #ifndef charset_internal_h
6 | #define charset_internal_h
7 |
8 | /* This invariably comes in handy */
9 | #define lenof(x) ( sizeof((x)) / sizeof(*(x)) )
10 |
11 | /* This is an invalid Unicode value used to indicate an error. */
12 | #define ERROR 0xFFFFL /* Unicode value representing error */
13 |
14 | typedef struct charset_spec charset_spec;
15 | typedef struct sbcs_data sbcs_data;
16 |
17 | struct charset_spec {
18 | int charset; /* numeric identifier */
19 |
20 | /*
21 | * A function to read the character set and output Unicode
22 | * characters. The `emit' function expects to get Unicode chars
23 | * passed to it; it should be sent ERROR for any encoding error
24 | * on the input.
25 | */
26 | void (*read)(charset_spec const *charset, long int input_chr,
27 | charset_state *state,
28 | void (*emit)(void *ctx, long int output), void *emitctx);
29 | /*
30 | * A function to read Unicode characters and output in this
31 | * character set. The `emit' function expects to get byte
32 | * values passed to it; it should be sent ERROR for any
33 | * non-representable characters on the input.
34 | */
35 | void (*write)(charset_spec const *charset, long int input_chr,
36 | charset_state *state,
37 | void (*emit)(void *ctx, long int output), void *emitctx);
38 | void const *data;
39 | };
40 |
41 | /*
42 | * This is the format of `data' used by the SBCS read and write
43 | * functions; so it's the format used in all SBCS definitions.
44 | */
45 | struct sbcs_data {
46 | /*
47 | * This is a simple mapping table converting each SBCS position
48 | * to a Unicode code point. Some positions may contain ERROR,
49 | * indicating that that byte value is not defined in the SBCS
50 | * in question and its occurrence in input is an error.
51 | */
52 | unsigned long sbcs2ucs[256];
53 |
54 | /*
55 | * This lookup table is used to convert Unicode back to the
56 | * SBCS. It consists of the valid byte values in the SBCS,
57 | * sorted in order of their Unicode translation. So given a
58 | * Unicode value U, you can do a binary search on this table
59 | * using the above table as a lookup: when testing the Xth
60 | * position in this table, you branch according to whether
61 | * sbcs2ucs[ucs2sbcs[X]] is less than, greater than, or equal
62 | * to U.
63 | *
64 | * Note that since there may be fewer than 256 valid byte
65 | * values in a particular SBCS, we must supply the length of
66 | * this table as well as the contents.
67 | */
68 | unsigned char ucs2sbcs[256];
69 | int nvalid;
70 | };
71 |
72 | /*
73 | * Prototypes for internal library functions.
74 | */
75 | charset_spec const *charset_find_spec(int charset);
76 | void read_sbcs(charset_spec const *charset, long int input_chr,
77 | charset_state *state,
78 | void (*emit)(void *ctx, long int output), void *emitctx);
79 | void write_sbcs(charset_spec const *charset, long int input_chr,
80 | charset_state *state,
81 | void (*emit)(void *ctx, long int output), void *emitctx);
82 |
83 | /*
84 | * Placate compiler warning about unused parameters, of which we
85 | * expect to have some in this library.
86 | */
87 | #define UNUSEDARG(x) ( (x) = (x) )
88 |
89 | #endif /* charset_internal_h */
90 |
--------------------------------------------------------------------------------
/ssharcf.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Arcfour (RC4) implementation for PuTTY.
3 | *
4 | * Coded from Schneier.
5 | */
6 |
7 | #include
8 | #include "ssh.h"
9 |
10 | typedef struct {
11 | unsigned char i, j, s[256];
12 | } ArcfourContext;
13 |
14 | static void arcfour_block(void *handle, unsigned char *blk, int len)
15 | {
16 | ArcfourContext *ctx = (ArcfourContext *)handle;
17 | unsigned k;
18 | unsigned char tmp, i, j, *s;
19 |
20 | s = ctx->s;
21 | i = ctx->i; j = ctx->j;
22 | for (k = 0; (int)k < len; k++) {
23 | i = (i + 1) & 0xff;
24 | j = (j + s[i]) & 0xff;
25 | tmp = s[i]; s[i] = s[j]; s[j] = tmp;
26 | blk[k] ^= s[(s[i]+s[j]) & 0xff];
27 | }
28 | ctx->i = i; ctx->j = j;
29 | }
30 |
31 | static void arcfour_setkey(ArcfourContext *ctx, unsigned char const *key,
32 | unsigned keybytes)
33 | {
34 | unsigned char tmp, k[256], *s;
35 | unsigned i, j;
36 |
37 | s = ctx->s;
38 | assert(keybytes <= 256);
39 | ctx->i = ctx->j = 0;
40 | for (i = 0; i < 256; i++) {
41 | s[i] = i;
42 | k[i] = key[i % keybytes];
43 | }
44 | j = 0;
45 | for (i = 0; i < 256; i++) {
46 | j = (j + s[i] + k[i]) & 0xff;
47 | tmp = s[i]; s[i] = s[j]; s[j] = tmp;
48 | }
49 | }
50 |
51 | /* -- Interface with PuTTY -- */
52 |
53 | /*
54 | * We don't implement Arcfour in SSH-1 because it's utterly insecure in
55 | * several ways. See CERT Vulnerability Notes VU#25309, VU#665372,
56 | * and VU#565052.
57 | *
58 | * We don't implement the "arcfour" algorithm in SSH-2 because it doesn't
59 | * stir the cipher state before emitting keystream, and hence is likely
60 | * to leak data about the key.
61 | */
62 |
63 | static void *arcfour_make_context(void)
64 | {
65 | return snew(ArcfourContext);
66 | }
67 |
68 | static void arcfour_free_context(void *handle)
69 | {
70 | sfree(handle);
71 | }
72 |
73 | static void arcfour_stir(ArcfourContext *ctx)
74 | {
75 | unsigned char *junk = snewn(1536, unsigned char);
76 | memset(junk, 0, 1536);
77 | arcfour_block(ctx, junk, 1536);
78 | smemclr(junk, 1536);
79 | sfree(junk);
80 | }
81 |
82 | static void arcfour128_key(void *handle, unsigned char *key)
83 | {
84 | ArcfourContext *ctx = (ArcfourContext *)handle;
85 | arcfour_setkey(ctx, key, 16);
86 | arcfour_stir(ctx);
87 | }
88 |
89 | static void arcfour256_key(void *handle, unsigned char *key)
90 | {
91 | ArcfourContext *ctx = (ArcfourContext *)handle;
92 | arcfour_setkey(ctx, key, 32);
93 | arcfour_stir(ctx);
94 | }
95 |
96 | static void arcfour_iv(void *handle, unsigned char *key)
97 | {
98 |
99 | }
100 |
101 | const struct ssh2_cipher ssh_arcfour128_ssh2 = {
102 | arcfour_make_context, arcfour_free_context, arcfour_iv, arcfour128_key,
103 | arcfour_block, arcfour_block,
104 | "arcfour128",
105 | 1, 128, 0, "Arcfour-128"
106 | };
107 |
108 | const struct ssh2_cipher ssh_arcfour256_ssh2 = {
109 | arcfour_make_context, arcfour_free_context, arcfour_iv, arcfour256_key,
110 | arcfour_block, arcfour_block,
111 | "arcfour256",
112 | 1, 256, 0, "Arcfour-256"
113 | };
114 |
115 | static const struct ssh2_cipher *const arcfour_list[] = {
116 | &ssh_arcfour256_ssh2,
117 | &ssh_arcfour128_ssh2,
118 | };
119 |
120 | const struct ssh2_ciphers ssh2_arcfour = {
121 | sizeof(arcfour_list) / sizeof(*arcfour_list),
122 | arcfour_list
123 | };
124 |
--------------------------------------------------------------------------------
/windows/winnpc.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Windows support module which deals with being a named-pipe client.
3 | */
4 |
5 | #include
6 | #include
7 |
8 | #define DEFINE_PLUG_METHOD_MACROS
9 | #include "tree234.h"
10 | #include "putty.h"
11 | #include "network.h"
12 | #include "proxy.h"
13 | #include "ssh.h"
14 |
15 | #if !defined NO_SECURITY
16 |
17 | #include "winsecur.h"
18 |
19 | Socket make_handle_socket(HANDLE send_H, HANDLE recv_H, Plug plug,
20 | int overlapped);
21 |
22 | Socket new_named_pipe_client(const char *pipename, Plug plug)
23 | {
24 | HANDLE pipehandle;
25 | PSID usersid, pipeowner;
26 | PSECURITY_DESCRIPTOR psd;
27 | char *err;
28 | Socket ret;
29 |
30 | assert(strncmp(pipename, "\\\\.\\pipe\\", 9) == 0);
31 | assert(strchr(pipename + 9, '\\') == NULL);
32 |
33 | while (1) {
34 | pipehandle = CreateFile(pipename, GENERIC_READ | GENERIC_WRITE,
35 | 0, NULL, OPEN_EXISTING,
36 | FILE_FLAG_OVERLAPPED, NULL);
37 |
38 | if (pipehandle != INVALID_HANDLE_VALUE)
39 | break;
40 |
41 | if (GetLastError() != ERROR_PIPE_BUSY) {
42 | err = dupprintf("Unable to open named pipe '%s': %s",
43 | pipename, win_strerror(GetLastError()));
44 | ret = new_error_socket(err, plug);
45 | sfree(err);
46 | return ret;
47 | }
48 |
49 | /*
50 | * If we got ERROR_PIPE_BUSY, wait for the server to
51 | * create a new pipe instance. (Since the server is
52 | * expected to be winnps.c, which will do that immediately
53 | * after a previous connection is accepted, that shouldn't
54 | * take excessively long.)
55 | */
56 | if (!WaitNamedPipe(pipename, NMPWAIT_USE_DEFAULT_WAIT)) {
57 | err = dupprintf("Error waiting for named pipe '%s': %s",
58 | pipename, win_strerror(GetLastError()));
59 | ret = new_error_socket(err, plug);
60 | sfree(err);
61 | return ret;
62 | }
63 | }
64 |
65 | if ((usersid = get_user_sid()) == NULL) {
66 | CloseHandle(pipehandle);
67 | err = dupprintf("Unable to get user SID");
68 | ret = new_error_socket(err, plug);
69 | sfree(err);
70 | return ret;
71 | }
72 |
73 | if (p_GetSecurityInfo(pipehandle, SE_KERNEL_OBJECT,
74 | OWNER_SECURITY_INFORMATION,
75 | &pipeowner, NULL, NULL, NULL,
76 | &psd) != ERROR_SUCCESS) {
77 | err = dupprintf("Unable to get named pipe security information: %s",
78 | win_strerror(GetLastError()));
79 | ret = new_error_socket(err, plug);
80 | sfree(err);
81 | CloseHandle(pipehandle);
82 | sfree(usersid);
83 | return ret;
84 | }
85 |
86 | if (!EqualSid(pipeowner, usersid)) {
87 | err = dupprintf("Owner of named pipe '%s' is not us", pipename);
88 | ret = new_error_socket(err, plug);
89 | sfree(err);
90 | CloseHandle(pipehandle);
91 | LocalFree(psd);
92 | sfree(usersid);
93 | return ret;
94 | }
95 |
96 | LocalFree(psd);
97 | sfree(usersid);
98 |
99 | return make_handle_socket(pipehandle, pipehandle, plug, TRUE);
100 | }
101 |
102 | #endif /* !defined NO_SECURITY */
103 |
--------------------------------------------------------------------------------
/doc/man-pscp.but:
--------------------------------------------------------------------------------
1 | \cfg{man-identity}{pscp}{1}{2004-03-24}{PuTTY tool suite}{PuTTY tool suite}
2 |
3 | \H{pscp-manpage} Man page for PSCP
4 |
5 | \S{pscp-manpage-name} NAME
6 |
7 | \cw{pscp} \- command-line SCP (secure copy) / SFTP client
8 |
9 | \S{pscp-manpage-synopsis} SYNOPSIS
10 |
11 | \c pscp [options] [user@]host:source target
12 | \e bbbb iiiiiii iiiib iiiibiiiiii iiiiii
13 | \c pscp [options] source [source...] [user@]host:target
14 | \e bbbb iiiiiii iiiiii iiiiii iiiib iiiibiiiiii
15 | \c pscp [options] -ls [user@]host:filespec
16 | \e bbbb iiiiiii bbb iiiib iiiibiiiiiiii
17 |
18 | \S{pscp-manpage-description} DESCRIPTION
19 |
20 | \cw{pscp} is a command-line client for the SSH-based SCP (secure
21 | copy) and SFTP (secure file transfer protocol) protocols.
22 |
23 | \S{pscp-manpage-options} OPTIONS
24 |
25 | The command-line options supported by \e{pscp} are:
26 |
27 | \dt \cw{-V}
28 |
29 | \dd Show version information and exit.
30 |
31 | \dt \cw{-pgpfp}
32 |
33 | \dd Display the fingerprints of the PuTTY PGP Master Keys and exit,
34 | to aid in verifying new files released by the PuTTY team.
35 |
36 | \dt \cw{-ls}
37 |
38 | \dd Remote directory listing.
39 |
40 | \dt \cw{-p}
41 |
42 | \dd Preserve file attributes.
43 |
44 | \dt \cw{-q}
45 |
46 | \dd Quiet, don't show statistics.
47 |
48 | \dt \cw{-r}
49 |
50 | \dd Copy directories recursively.
51 |
52 | \dt \cw{-unsafe}
53 |
54 | \dd Allow server-side wildcards (DANGEROUS).
55 |
56 | \dt \cw{-v}
57 |
58 | \dd Show verbose messages.
59 |
60 | \dt \cw{-load} \e{session}
61 |
62 | \dd Load settings from saved session.
63 |
64 | \dt \cw{-P} \e{port}
65 |
66 | \dd Connect to port \e{port}.
67 |
68 | \dt \cw{-l} \e{user}
69 |
70 | \dd Set remote username to \e{user}.
71 |
72 | \dt \cw{-batch}
73 |
74 | \dd Disable interactive prompts.
75 |
76 | \dt \cw{-pw} \e{password}
77 |
78 | \dd Set remote password to \e{password}. \e{CAUTION:} this will likely
79 | make the password visible to other users of the local machine (via
80 | commands such as \q{\c{w}}).
81 |
82 | \dt \cw{-1}
83 |
84 | \dd Force use of SSH protocol version 1.
85 |
86 | \dt \cw{-2}
87 |
88 | \dd Force use of SSH protocol version 2.
89 |
90 | \dt \cw{-C}
91 |
92 | \dd Enable SSH compression.
93 |
94 | \dt \cw{-i} \e{path}
95 |
96 | \dd Private key file for user authentication.
97 |
98 | \dt \cw{\-hostkey} \e{key}
99 |
100 | \dd Specify an acceptable host public key. This option may be specified
101 | multiple times; each key can be either a fingerprint (\cw{99:aa:bb:...}) or
102 | a base64-encoded blob in OpenSSH's one-line format.
103 |
104 | \lcont{ Specifying this option overrides automated host key
105 | management; \e{only} the key(s) specified on the command-line will be
106 | accepted (unless a saved session also overrides host keys, in which
107 | case those will be added to), and the host key cache will not be
108 | written. }
109 |
110 | \dt \cw{-scp}
111 |
112 | \dd Force use of SCP protocol.
113 |
114 | \dt \cw{-sftp}
115 |
116 | \dd Force use of SFTP protocol.
117 |
118 | \S{pscp-manpage-more-information} MORE INFORMATION
119 |
120 | For more information on \cw{pscp} it's probably best to go and look at
121 | the manual on the PuTTY web page:
122 |
123 | \W{http://www.chiark.greenend.org.uk/~sgtatham/putty/}\cw{http://www.chiark.greenend.org.uk/~sgtatham/putty/}
124 |
125 | \S{pscp-manpage-bugs} BUGS
126 |
127 | This man page isn't terribly complete. See the above web link for
128 | better documentation.
129 |
--------------------------------------------------------------------------------
/contrib/encodelib.py:
--------------------------------------------------------------------------------
1 | # Python module to make it easy to manually encode SSH packets, by
2 | # supporting the various uint32, string, mpint primitives.
3 | #
4 | # The idea of this is that you can use it to manually construct key
5 | # exchange sequences of interesting kinds, for testing purposes.
6 |
7 | import struct, random
8 |
9 | def boolean(b):
10 | return "\1" if b else "\0"
11 |
12 | def byte(b):
13 | assert 0 <= b < 0x100
14 | return chr(b)
15 |
16 | def uint32(u):
17 | assert 0 <= u < 0x100000000
18 | return struct.pack(">I", u)
19 |
20 | def uint64(u):
21 | assert 0 <= u < 0x10000000000000000
22 | return struct.pack(">L", u)
23 |
24 | def string(s):
25 | return uint32(len(s)) + s
26 |
27 | def mpint(m):
28 | s = ""
29 | lastbyte = 0
30 | while m > 0:
31 | lastbyte = m & 0xFF
32 | s = chr(lastbyte) + s
33 | m >>= 8
34 | if lastbyte & 0x80:
35 | s = "\0" + s
36 | return string(s)
37 |
38 | def name_list(ns):
39 | s = ""
40 | for n in ns:
41 | assert "," not in n
42 | if s != "":
43 | s += ","
44 | s += n
45 | return string(s)
46 |
47 | def ssh_rsa_key_blob(modulus, exponent):
48 | return string(string("ssh-rsa") + mpint(modulus) + mpint(exponent))
49 |
50 | def ssh_rsa_signature_blob(signature):
51 | return string(string("ssh-rsa") + mpint(signature))
52 |
53 | def greeting(string):
54 | # Greeting at the start of an SSH connection.
55 | return string + "\r\n"
56 |
57 | # Packet types.
58 | SSH2_MSG_DISCONNECT = 1
59 | SSH2_MSG_IGNORE = 2
60 | SSH2_MSG_UNIMPLEMENTED = 3
61 | SSH2_MSG_DEBUG = 4
62 | SSH2_MSG_SERVICE_REQUEST = 5
63 | SSH2_MSG_SERVICE_ACCEPT = 6
64 | SSH2_MSG_KEXINIT = 20
65 | SSH2_MSG_NEWKEYS = 21
66 | SSH2_MSG_KEXDH_INIT = 30
67 | SSH2_MSG_KEXDH_REPLY = 31
68 | SSH2_MSG_KEX_DH_GEX_REQUEST = 30
69 | SSH2_MSG_KEX_DH_GEX_GROUP = 31
70 | SSH2_MSG_KEX_DH_GEX_INIT = 32
71 | SSH2_MSG_KEX_DH_GEX_REPLY = 33
72 | SSH2_MSG_KEXRSA_PUBKEY = 30
73 | SSH2_MSG_KEXRSA_SECRET = 31
74 | SSH2_MSG_KEXRSA_DONE = 32
75 | SSH2_MSG_USERAUTH_REQUEST = 50
76 | SSH2_MSG_USERAUTH_FAILURE = 51
77 | SSH2_MSG_USERAUTH_SUCCESS = 52
78 | SSH2_MSG_USERAUTH_BANNER = 53
79 | SSH2_MSG_USERAUTH_PK_OK = 60
80 | SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ = 60
81 | SSH2_MSG_USERAUTH_INFO_REQUEST = 60
82 | SSH2_MSG_USERAUTH_INFO_RESPONSE = 61
83 | SSH2_MSG_GLOBAL_REQUEST = 80
84 | SSH2_MSG_REQUEST_SUCCESS = 81
85 | SSH2_MSG_REQUEST_FAILURE = 82
86 | SSH2_MSG_CHANNEL_OPEN = 90
87 | SSH2_MSG_CHANNEL_OPEN_CONFIRMATION = 91
88 | SSH2_MSG_CHANNEL_OPEN_FAILURE = 92
89 | SSH2_MSG_CHANNEL_WINDOW_ADJUST = 93
90 | SSH2_MSG_CHANNEL_DATA = 94
91 | SSH2_MSG_CHANNEL_EXTENDED_DATA = 95
92 | SSH2_MSG_CHANNEL_EOF = 96
93 | SSH2_MSG_CHANNEL_CLOSE = 97
94 | SSH2_MSG_CHANNEL_REQUEST = 98
95 | SSH2_MSG_CHANNEL_SUCCESS = 99
96 | SSH2_MSG_CHANNEL_FAILURE = 100
97 | SSH2_MSG_USERAUTH_GSSAPI_RESPONSE = 60
98 | SSH2_MSG_USERAUTH_GSSAPI_TOKEN = 61
99 | SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE = 63
100 | SSH2_MSG_USERAUTH_GSSAPI_ERROR = 64
101 | SSH2_MSG_USERAUTH_GSSAPI_ERRTOK = 65
102 | SSH2_MSG_USERAUTH_GSSAPI_MIC = 66
103 |
104 | def clearpkt(msgtype, *stuff):
105 | # SSH-2 binary packet, in the cleartext format used for initial
106 | # setup and kex.
107 | s = byte(msgtype)
108 | for thing in stuff:
109 | s += thing
110 | padlen = 0
111 | while padlen < 4 or len(s) % 8 != 3:
112 | padlen += 1
113 | s += byte(random.randint(0,255))
114 | s = byte(padlen) + s
115 | return string(s)
116 |
--------------------------------------------------------------------------------
/macosx/README.OSX:
--------------------------------------------------------------------------------
1 | This directory contains a Mac OS X port of PuTTY/pterm, running as a
2 | native Aqua GUI application.
3 |
4 | THIS PORT IS CURRENTLY UNFINISHED AND EXPERIMENTAL. It is _not_
5 | considered to be of release quality, even if you've found it (and
6 | are reading this) in a PuTTY release source archive. You are welcome
7 | to try using it, but don't be surprised at unexpected behaviour. I'm
8 | not kidding.
9 |
10 | In particular, I have not yet decided where OS X PuTTY should store
11 | its configuration data. Options include storing it in ~/.putty to be
12 | compatible with Unix PuTTY, storing it wherever is compatible with
13 | Mac Classic PuTTY, storing it in a natively OS X location, or
14 | sorting out the `config-locations' wishlist item and doing all
15 | three. Therefore, if you start using this port and create a whole
16 | load of saved sessions, you should not be surprised if a future
17 | version of the port decides to look somewhere completely different
18 | for the data and therefore loses them all. If that happens, don't
19 | say you weren't warned!
20 |
21 | Other ways in which the port is currently unfinished include:
22 |
23 | Bit rot
24 | -------
25 |
26 | - the conversion of the old fixed-size 'Config' structure to the
27 | new dynamic 'Conf' was never applied to this directory
28 |
29 | - probably other things are out of date too; it would need some
30 | work to make it compile again
31 |
32 | Missing terminal window features
33 | --------------------------------
34 |
35 | - terminal display is horribly slow
36 |
37 | - fonts aren't configurable
38 |
39 | - several features are unimplemented in the terminal display:
40 | underlining, non-solid-block cursors, double-width and
41 | double-height line attributes, bold as font rather than as
42 | colour, wide (CJK) characters, combining characters.
43 |
44 | - there's no scrollbar
45 |
46 | - terminal window resizing isn't implemented yet
47 |
48 | - proper window placement (cascading down and right from the
49 | starting position, plus remembering previous window positions per
50 | the Apple HIG) is not implemented
51 |
52 | Missing alert box features
53 | --------------------------
54 |
55 | - warn-on-close isn't implemented
56 |
57 | Missing input features
58 | ----------------------
59 |
60 | - use of Alt+numberpad to enter arbitrary numeric character codes
61 | is not yet supported
62 |
63 | - there's no Meta key yet. (I'd like to at least have the
64 | possibility of using Command rather than Option as the Meta key,
65 | since the latter is necessary to send some characters, including
66 | the rather important # on Apple UK keyboards; but trapping
67 | Command- and sending it to the window rather than the
68 | application menu requires me to make a positive effort of some
69 | sort and I haven't got round to it yet. For those Mac users who
70 | consider their Command key sacrosanct, don't worry, this option
71 | _will_ be configurable and _will_ be off by default.)
72 |
73 | - there's no specials menu
74 |
75 | - mouse activity isn't supported (neither cut-and-paste nor xterm
76 | mouse tracking)
77 |
78 | Missing terminal emulation features
79 | -----------------------------------
80 |
81 | - currently no support for server-side window management requests
82 | (i.e. escape sequences to minimise or maximise the window,
83 | request or change its position and size, change its title etc)
84 |
85 | - window title is currently fixed
86 |
87 | Other missing features
88 | ----------------------
89 |
90 | - no Event Log
91 |
92 | - no mid-session Change Settings
93 |
--------------------------------------------------------------------------------
/icons/Makefile:
--------------------------------------------------------------------------------
1 | # Makefile for the PuTTY icon suite.
2 |
3 | ICONS = putty puttycfg puttygen pscp pageant pterm ptermcfg puttyins
4 | SIZES = 16 32 48
5 |
6 | MODE = # override to -it on command line for opaque testing
7 |
8 | PNGS = $(foreach I,$(ICONS),$(foreach S,$(SIZES),$(I)-$(S).png))
9 | MONOPNGS = $(foreach I,$(ICONS),$(foreach S,$(SIZES),$(I)-$(S)-mono.png))
10 | TRUEPNGS = $(foreach I,$(ICONS),$(foreach S,$(SIZES),$(I)-$(S)-true.png))
11 |
12 | ICOS = putty.ico puttygen.ico pscp.ico pageant.ico pageants.ico puttycfg.ico \
13 | puttyins.ico
14 | CICONS = xpmputty.c xpmpucfg.c xpmpterm.c xpmptcfg.c
15 |
16 | base: icos cicons
17 |
18 | all: pngs monopngs base # truepngs currently disabled by default
19 |
20 | pngs: $(PNGS)
21 | monopngs: $(MONOPNGS)
22 | truepngs: $(TRUEPNGS)
23 |
24 | icos: $(ICOS)
25 | cicons: $(CICONS)
26 |
27 | install: icos cicons
28 | cp $(ICOS) ../windows
29 | cp $(CICONS) ../unix
30 |
31 | $(PNGS): %.png: mkicon.py
32 | ./mkicon.py $(MODE) $(join $(subst -, ,$(basename $@)),_icon) $@
33 |
34 | $(MONOPNGS): %.png: mkicon.py
35 | ./mkicon.py -2 $(MODE) $(join $(subst -, ,$(subst -mono,,$(basename $@))),_icon) $@
36 |
37 | $(TRUEPNGS): %.png: mkicon.py
38 | ./mkicon.py -T $(MODE) $(join $(subst -, ,$(subst -true,,$(basename $@))),_icon) $@
39 |
40 | putty.ico: putty-16.png putty-32.png putty-48.png \
41 | putty-16-mono.png putty-32-mono.png putty-48-mono.png
42 | ./icon.pl -4 $(filter-out %-mono.png, $^) -1 $(filter %-mono.png, $^) > $@
43 |
44 | puttycfg.ico: puttycfg-16.png puttycfg-32.png puttycfg-48.png \
45 | puttycfg-16-mono.png puttycfg-32-mono.png puttycfg-48-mono.png
46 | ./icon.pl -4 $(filter-out %-mono.png, $^) -1 $(filter %-mono.png, $^) > $@
47 |
48 | puttygen.ico: puttygen-16.png puttygen-32.png puttygen-48.png \
49 | puttygen-16-mono.png puttygen-32-mono.png puttygen-48-mono.png
50 | ./icon.pl -4 $(filter-out %-mono.png, $^) -1 $(filter %-mono.png, $^) > $@
51 |
52 | pageant.ico: pageant-16.png pageant-32.png pageant-48.png \
53 | pageant-16-mono.png pageant-32-mono.png pageant-48-mono.png
54 | ./icon.pl -4 $(filter-out %-mono.png, $^) -1 $(filter %-mono.png, $^) > $@
55 |
56 | pageants.ico: pageant-16.png pageant-16-mono.png
57 | ./icon.pl -4 $(filter-out %-mono.png, $^) -1 $(filter %-mono.png, $^) > $@
58 |
59 | pscp.ico: pscp-16.png pscp-32.png pscp-48.png \
60 | pscp-16-mono.png pscp-32-mono.png pscp-48-mono.png
61 | ./icon.pl -4 $(filter-out %-mono.png, $^) -1 $(filter %-mono.png, $^) > $@
62 |
63 | # Because the installer icon makes heavy use of brown when drawing
64 | # the cardboard box, it's worth having 8-bit versions of it in
65 | # addition to the 4- and 1-bit ones.
66 | puttyins.ico: puttyins-16.png puttyins-32.png puttyins-48.png \
67 | puttyins-16-mono.png puttyins-32-mono.png \
68 | puttyins-48-mono.png \
69 | puttyins-16-true.png puttyins-32-true.png \
70 | puttyins-48-true.png
71 | ./icon.pl -8 $(filter %-true.png, $^) \
72 | -4 $(filter-out %-true.png, $(filter-out %-mono.png, $^)) \
73 | -1 $(filter %-mono.png, $^) > $@
74 |
75 | # Icon for the website. (This isn't linked into "make all".)
76 | website.ico: putty-16.png
77 | ./icon.pl -4 $^ >$@
78 |
79 | xpmputty.c: putty-16.png putty-32.png putty-48.png
80 | ./cicon.pl main_icon $^ > $@
81 |
82 | xpmpucfg.c: puttycfg-16.png puttycfg-32.png puttycfg-48.png
83 | ./cicon.pl cfg_icon $^ > $@
84 |
85 | xpmpterm.c: pterm-16.png pterm-32.png pterm-48.png
86 | ./cicon.pl main_icon $^ > $@
87 |
88 | xpmptcfg.c: ptermcfg-16.png ptermcfg-32.png ptermcfg-48.png
89 | ./cicon.pl cfg_icon $^ > $@
90 |
91 | clean:
92 | rm -f *.png *.ico *.c
93 |
--------------------------------------------------------------------------------
/windows/winhelp.c:
--------------------------------------------------------------------------------
1 | /*
2 | * winhelp.c: centralised functions to launch Windows help files,
3 | * and to decide whether to use .HLP or .CHM help in any given
4 | * situation.
5 | */
6 |
7 | #include
8 | #include
9 | #include
10 | #include
11 |
12 | #include "putty.h"
13 |
14 | #ifndef NO_HTMLHELP
15 | #include
16 | #endif /* NO_HTMLHELP */
17 |
18 | static int requested_help;
19 | static char *help_path;
20 | static int help_has_contents;
21 | #ifndef NO_HTMLHELP
22 | DECL_WINDOWS_FUNCTION(static, HWND, HtmlHelpA, (HWND, LPCSTR, UINT, DWORD));
23 | static char *chm_path;
24 | #endif /* NO_HTMLHELP */
25 |
26 | void init_help(void)
27 | {
28 | char b[2048], *p, *q, *r;
29 | FILE *fp;
30 |
31 | GetModuleFileName(NULL, b, sizeof(b) - 1);
32 | r = b;
33 | p = strrchr(b, '\\');
34 | if (p && p >= r) r = p+1;
35 | q = strrchr(b, ':');
36 | if (q && q >= r) r = q+1;
37 | strcpy(r, PUTTY_HELP_FILE);
38 | if ( (fp = fopen(b, "r")) != NULL) {
39 | help_path = dupstr(b);
40 | fclose(fp);
41 | } else
42 | help_path = NULL;
43 | strcpy(r, PUTTY_HELP_CONTENTS);
44 | if ( (fp = fopen(b, "r")) != NULL) {
45 | help_has_contents = TRUE;
46 | fclose(fp);
47 | } else
48 | help_has_contents = FALSE;
49 |
50 | #ifndef NO_HTMLHELP
51 | strcpy(r, PUTTY_CHM_FILE);
52 | if ( (fp = fopen(b, "r")) != NULL) {
53 | chm_path = dupstr(b);
54 | fclose(fp);
55 | } else
56 | chm_path = NULL;
57 | if (chm_path) {
58 | HINSTANCE dllHH = load_system32_dll("hhctrl.ocx");
59 | GET_WINDOWS_FUNCTION(dllHH, HtmlHelpA);
60 | if (!p_HtmlHelpA) {
61 | chm_path = NULL;
62 | if (dllHH)
63 | FreeLibrary(dllHH);
64 | }
65 | }
66 | #endif /* NO_HTMLHELP */
67 | }
68 |
69 | void shutdown_help(void)
70 | {
71 | /* Nothing to do currently.
72 | * (If we were running HTML Help single-threaded, this is where we'd
73 | * call HH_UNINITIALIZE.) */
74 | }
75 |
76 | int has_help(void)
77 | {
78 | /*
79 | * FIXME: it would be nice here to disregard help_path on
80 | * platforms that didn't have WINHLP32. But that's probably
81 | * unrealistic, since even Vista will have it if the user
82 | * specifically downloads it.
83 | */
84 | return (help_path != NULL
85 | #ifndef NO_HTMLHELP
86 | || chm_path
87 | #endif /* NO_HTMLHELP */
88 | );
89 | }
90 |
91 | void launch_help(HWND hwnd, const char *topic)
92 | {
93 | if (topic) {
94 | int colonpos = strcspn(topic, ":");
95 |
96 | #ifndef NO_HTMLHELP
97 | if (chm_path) {
98 | char *fname;
99 | assert(topic[colonpos] != '\0');
100 | fname = dupprintf("%s::/%s.html>main", chm_path,
101 | topic + colonpos + 1);
102 | p_HtmlHelpA(hwnd, fname, HH_DISPLAY_TOPIC, 0);
103 | sfree(fname);
104 | } else
105 | #endif /* NO_HTMLHELP */
106 | if (help_path) {
107 | char *cmd = dupprintf("JI(`',`%.*s')", colonpos, topic);
108 | WinHelp(hwnd, help_path, HELP_COMMAND, (DWORD)cmd);
109 | sfree(cmd);
110 | }
111 | } else {
112 | #ifndef NO_HTMLHELP
113 | if (chm_path) {
114 | p_HtmlHelpA(hwnd, chm_path, HH_DISPLAY_TOPIC, 0);
115 | } else
116 | #endif /* NO_HTMLHELP */
117 | if (help_path) {
118 | WinHelp(hwnd, help_path,
119 | help_has_contents ? HELP_FINDER : HELP_CONTENTS, 0);
120 | }
121 | }
122 | requested_help = TRUE;
123 | }
124 |
125 | void quit_help(HWND hwnd)
126 | {
127 | if (requested_help) {
128 | #ifndef NO_HTMLHELP
129 | if (chm_path) {
130 | p_HtmlHelpA(NULL, NULL, HH_CLOSE_ALL, 0);
131 | } else
132 | #endif /* NO_HTMLHELP */
133 | if (help_path) {
134 | WinHelp(hwnd, help_path, HELP_QUIT, 0);
135 | }
136 | requested_help = FALSE;
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/unix/uxnoise.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Noise generation for PuTTY's cryptographic random number
3 | * generator.
4 | */
5 |
6 | #include
7 | #include
8 | #include
9 |
10 | #include
11 | #include
12 | #include
13 | #include
14 |
15 | #include "putty.h"
16 | #include "ssh.h"
17 | #include "storage.h"
18 |
19 | static int read_dev_urandom(char *buf, int len)
20 | {
21 | int fd;
22 | int ngot, ret;
23 |
24 | fd = open("/dev/urandom", O_RDONLY);
25 | if (fd < 0)
26 | return 0;
27 |
28 | ngot = 0;
29 | while (ngot < len) {
30 | ret = read(fd, buf+ngot, len-ngot);
31 | if (ret < 0) {
32 | close(fd);
33 | return 0;
34 | }
35 | ngot += ret;
36 | }
37 |
38 | close(fd);
39 |
40 | return 1;
41 | }
42 |
43 | /*
44 | * This function is called once, at PuTTY startup. It will do some
45 | * slightly silly things such as fetching an entire process listing
46 | * and scanning /tmp, load the saved random seed from disk, and
47 | * also read 32 bytes out of /dev/urandom.
48 | */
49 |
50 | void noise_get_heavy(void (*func) (void *, int))
51 | {
52 | char buf[512];
53 | FILE *fp;
54 | int ret;
55 | int got_dev_urandom = 0;
56 |
57 | if (read_dev_urandom(buf, 32)) {
58 | got_dev_urandom = 1;
59 | func(buf, 32);
60 | }
61 |
62 | fp = popen("ps -axu 2>/dev/null", "r");
63 | if (fp) {
64 | while ( (ret = fread(buf, 1, sizeof(buf), fp)) > 0)
65 | func(buf, ret);
66 | pclose(fp);
67 | } else if (!got_dev_urandom) {
68 | fprintf(stderr, "popen: %s\n"
69 | "Unable to access fallback entropy source\n", strerror(errno));
70 | exit(1);
71 | }
72 |
73 | fp = popen("ls -al /tmp 2>/dev/null", "r");
74 | if (fp) {
75 | while ( (ret = fread(buf, 1, sizeof(buf), fp)) > 0)
76 | func(buf, ret);
77 | pclose(fp);
78 | } else if (!got_dev_urandom) {
79 | fprintf(stderr, "popen: %s\n"
80 | "Unable to access fallback entropy source\n", strerror(errno));
81 | exit(1);
82 | }
83 |
84 | read_random_seed(func);
85 | random_save_seed();
86 | }
87 |
88 | void random_save_seed(void)
89 | {
90 | int len;
91 | void *data;
92 |
93 | if (random_active) {
94 | random_get_savedata(&data, &len);
95 | write_random_seed(data, len);
96 | sfree(data);
97 | }
98 | }
99 |
100 | /*
101 | * This function is called every time the random pool needs
102 | * stirring, and will acquire the system time.
103 | */
104 | void noise_get_light(void (*func) (void *, int))
105 | {
106 | struct timeval tv;
107 | gettimeofday(&tv, NULL);
108 | func(&tv, sizeof(tv));
109 | }
110 |
111 | /*
112 | * This function is called on a timer, and grabs as much changeable
113 | * system data as it can quickly get its hands on.
114 | */
115 | void noise_regular(void)
116 | {
117 | int fd;
118 | int ret;
119 | char buf[512];
120 | struct rusage rusage;
121 |
122 | if ((fd = open("/proc/meminfo", O_RDONLY)) >= 0) {
123 | while ( (ret = read(fd, buf, sizeof(buf))) > 0)
124 | random_add_noise(buf, ret);
125 | close(fd);
126 | }
127 | if ((fd = open("/proc/stat", O_RDONLY)) >= 0) {
128 | while ( (ret = read(fd, buf, sizeof(buf))) > 0)
129 | random_add_noise(buf, ret);
130 | close(fd);
131 | }
132 | getrusage(RUSAGE_SELF, &rusage);
133 | random_add_noise(&rusage, sizeof(rusage));
134 | }
135 |
136 | /*
137 | * This function is called on every keypress or mouse move, and
138 | * will add the current time to the noise pool. It gets the scan
139 | * code or mouse position passed in, and adds that too.
140 | */
141 | void noise_ultralight(unsigned long data)
142 | {
143 | struct timeval tv;
144 | gettimeofday(&tv, NULL);
145 | random_add_noise(&tv, sizeof(tv));
146 | random_add_noise(&data, sizeof(data));
147 | }
148 |
--------------------------------------------------------------------------------
/windows/puttygen.rc:
--------------------------------------------------------------------------------
1 | /*
2 | * Windows resources for PuTTYgen.
3 | */
4 |
5 | #include "rcstuff.h"
6 |
7 | #define APPNAME "PuTTYgen"
8 | #define APPDESC "PuTTY SSH key generation utility"
9 |
10 | 200 ICON "puttygen.ico"
11 |
12 | 201 DIALOG DISCARDABLE 0, 0, 318, 270
13 | STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
14 | CAPTION "PuTTY Key Generator"
15 | FONT 8, "MS Shell Dlg"
16 | BEGIN
17 | END
18 |
19 | 210 DIALOG DISCARDABLE 0, 0, 140, 60
20 | STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
21 | CAPTION "PuTTYgen: Enter Passphrase"
22 | FONT 8, "MS Shell Dlg"
23 | BEGIN
24 | CTEXT "Enter passphrase for key", 100, 10, 6, 120, 8
25 | CTEXT "", 101, 10, 16, 120, 8
26 | EDITTEXT 102, 10, 26, 120, 12, ES_PASSWORD | ES_AUTOHSCROLL
27 | DEFPUSHBUTTON "O&K", IDOK, 20, 42, 40, 14
28 | PUSHBUTTON "&Cancel", IDCANCEL, 80, 42, 40, 14
29 | END
30 |
31 | /* Accelerators used: cl */
32 | 213 DIALOG DISCARDABLE 140, 40, 136, 70
33 | STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
34 | CAPTION "About PuTTYgen"
35 | FONT 8, "MS Shell Dlg"
36 | BEGIN
37 | DEFPUSHBUTTON "&Close", IDOK, 82, 52, 48, 14
38 | PUSHBUTTON "View &Licence", 101, 6, 52, 70, 14
39 | CTEXT "PuTTYgen", 102, 10, 6, 120, 8
40 | CTEXT "", 100, 10, 16, 120, 16
41 | CTEXT "\251 1997-2015 Simon Tatham. All rights reserved.",
42 | 103, 10, 34, 120, 16
43 | END
44 |
45 | /* No accelerators used */
46 | 214 DIALOG DISCARDABLE 50, 50, 226, 263
47 | STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
48 | CAPTION "PuTTY Licence"
49 | FONT 8, "MS Shell Dlg"
50 | BEGIN
51 | DEFPUSHBUTTON "OK", IDOK, 98, 243, 44, 14
52 |
53 | LTEXT "Copyright \251 1997-2015 Simon Tatham", 1000, 10, 10, 206, 8
54 |
55 | LTEXT "Portions copyright Robert de Bath, Joris van Rantwijk, Delian", 1001, 10, 26, 206, 8
56 | LTEXT "Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas", 1002, 10, 34, 206, 8
57 | LTEXT "Barry, Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa,", 1003, 10, 42, 206, 8
58 | LTEXT "Markus Kuhn, Colin Watson, and CORE SDI S.A.", 1004, 10, 50, 206, 8
59 |
60 | LTEXT "Permission is hereby granted, free of charge, to any person", 1005, 10, 66, 206, 8
61 | LTEXT "obtaining a copy of this software and associated documentation", 1006, 10, 74, 206, 8
62 | LTEXT "files (the ""Software""), to deal in the Software without restriction,", 1007, 10, 82, 206, 8
63 | LTEXT "including without limitation the rights to use, copy, modify, merge,", 1008, 10, 90, 206, 8
64 | LTEXT "publish, distribute, sublicense, and/or sell copies of the Software,", 1009, 10, 98, 206, 8
65 | LTEXT "and to permit persons to whom the Software is furnished to do so,", 1010, 10, 106, 206, 8
66 | LTEXT "subject to the following conditions:", 1011, 10, 114, 206, 8
67 |
68 | LTEXT "The above copyright notice and this permission notice shall be", 1012, 10, 130, 206, 8
69 | LTEXT "included in all copies or substantial portions of the Software.", 1013, 10, 138, 206, 8
70 |
71 | LTEXT "THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT", 1014, 10, 154, 206, 8
72 | LTEXT "WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,", 1015, 10, 162, 206, 8
73 | LTEXT "INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF", 1016, 10, 170, 206, 8
74 | LTEXT "MERCHANTABILITY, FITNESS FOR A PARTICULAR", 1017, 10, 178, 206, 8
75 | LTEXT "PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE", 1018, 10, 186, 206, 8
76 | LTEXT "COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES", 1019, 10, 194, 206, 8
77 | LTEXT "OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,", 1020, 10, 202, 206, 8
78 | LTEXT "TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN", 1021, 10, 210, 206, 8
79 | LTEXT "CONNECTION WITH THE SOFTWARE OR THE USE OR", 1022, 10, 218, 206, 8
80 | LTEXT "OTHER DEALINGS IN THE SOFTWARE.", 1023, 10, 226, 206, 8
81 |
82 | END
83 |
84 | #include "version.rc2"
85 |
86 | #ifndef NO_MANIFESTS
87 | 1 RT_MANIFEST "puttygen.mft"
88 | #endif /* NO_MANIFESTS */
89 |
--------------------------------------------------------------------------------
/proxy.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Network proxy abstraction in PuTTY
3 | *
4 | * A proxy layer, if necessary, wedges itself between the
5 | * network code and the higher level backend.
6 | *
7 | * Supported proxies: HTTP CONNECT, generic telnet, SOCKS 4 & 5
8 | */
9 |
10 | #ifndef PUTTY_PROXY_H
11 | #define PUTTY_PROXY_H
12 |
13 | #define PROXY_ERROR_GENERAL 8000
14 | #define PROXY_ERROR_UNEXPECTED 8001
15 |
16 | typedef struct Socket_proxy_tag * Proxy_Socket;
17 |
18 | struct Socket_proxy_tag {
19 | const struct socket_function_table *fn;
20 | /* the above variable absolutely *must* be the first in this structure */
21 |
22 | char * error;
23 |
24 | Socket sub_socket;
25 | Plug plug;
26 | SockAddr remote_addr;
27 | int remote_port;
28 |
29 | bufchain pending_output_data;
30 | bufchain pending_oob_output_data;
31 | int pending_flush;
32 | bufchain pending_input_data;
33 | int pending_eof;
34 |
35 | #define PROXY_STATE_NEW -1
36 | #define PROXY_STATE_ACTIVE 0
37 |
38 | int state; /* proxy states greater than 0 are implementation
39 | * dependent, but represent various stages/states
40 | * of the initialization/setup/negotiation with the
41 | * proxy server.
42 | */
43 | int freeze; /* should we freeze the underlying socket when
44 | * we are done with the proxy negotiation? this
45 | * simply caches the value of sk_set_frozen calls.
46 | */
47 |
48 | #define PROXY_CHANGE_NEW -1
49 | #define PROXY_CHANGE_CLOSING 0
50 | #define PROXY_CHANGE_SENT 1
51 | #define PROXY_CHANGE_RECEIVE 2
52 | #define PROXY_CHANGE_ACCEPTING 3
53 |
54 | /* something has changed (a call from the sub socket
55 | * layer into our Proxy Plug layer, or we were just
56 | * created, etc), so the proxy layer needs to handle
57 | * this change (the type of which is the second argument)
58 | * and further the proxy negotiation process.
59 | */
60 |
61 | int (*negotiate) (Proxy_Socket /* this */, int /* change type */);
62 |
63 | /* current arguments of plug handlers
64 | * (for use by proxy's negotiate function)
65 | */
66 |
67 | /* closing */
68 | const char *closing_error_msg;
69 | int closing_error_code;
70 | int closing_calling_back;
71 |
72 | /* receive */
73 | int receive_urgent;
74 | char *receive_data;
75 | int receive_len;
76 |
77 | /* sent */
78 | int sent_bufsize;
79 |
80 | /* accepting */
81 | accept_fn_t accepting_constructor;
82 | accept_ctx_t accepting_ctx;
83 |
84 | /* configuration, used to look up proxy settings */
85 | Conf *conf;
86 |
87 | /* CHAP transient data */
88 | int chap_num_attributes;
89 | int chap_num_attributes_processed;
90 | int chap_current_attribute;
91 | int chap_current_datalen;
92 | };
93 |
94 | typedef struct Plug_proxy_tag * Proxy_Plug;
95 |
96 | struct Plug_proxy_tag {
97 | const struct plug_function_table *fn;
98 | /* the above variable absolutely *must* be the first in this structure */
99 |
100 | Proxy_Socket proxy_socket;
101 |
102 | };
103 |
104 | extern void proxy_activate (Proxy_Socket);
105 |
106 | extern int proxy_http_negotiate (Proxy_Socket, int);
107 | extern int proxy_telnet_negotiate (Proxy_Socket, int);
108 | extern int proxy_socks4_negotiate (Proxy_Socket, int);
109 | extern int proxy_socks5_negotiate (Proxy_Socket, int);
110 |
111 | /*
112 | * This may be reused by local-command proxies on individual
113 | * platforms.
114 | */
115 | char *format_telnet_command(SockAddr addr, int port, Conf *conf);
116 |
117 | /*
118 | * These are implemented in cproxy.c or nocproxy.c, depending on
119 | * whether encrypted proxy authentication is available.
120 | */
121 | extern void proxy_socks5_offerencryptedauth(char *command, int *len);
122 | extern int proxy_socks5_handlechap (Proxy_Socket p);
123 | extern int proxy_socks5_selectchap(Proxy_Socket p);
124 |
125 | #endif
126 |
--------------------------------------------------------------------------------
/doc/intro.but:
--------------------------------------------------------------------------------
1 | \C{intro} Introduction to PuTTY
2 |
3 | PuTTY is a free SSH, Telnet and Rlogin client for 32-bit Windows
4 | systems.
5 |
6 | \H{you-what} What are SSH, Telnet and Rlogin?
7 |
8 | If you already know what SSH, Telnet and Rlogin are, you can safely
9 | skip on to the next section.
10 |
11 | SSH, Telnet and Rlogin are three ways of doing the same thing:
12 | logging in to a multi-user computer from another computer, over a
13 | network.
14 |
15 | Multi-user operating systems, such as Unix and VMS, usually present
16 | a \i{command-line interface} to the user, much like the \q{\i{Command
17 | Prompt}} or \q{\i{MS-DOS Prompt}} in Windows. The system prints a
18 | prompt, and you type commands which the system will obey.
19 |
20 | Using this type of interface, there is no need for you to be sitting
21 | at the same machine you are typing commands to. The commands, and
22 | responses, can be sent over a network, so you can sit at one
23 | computer and give commands to another one, or even to more than one.
24 |
25 | SSH, Telnet and Rlogin are \i\e{network protocols} that allow you to
26 | do this. On the computer you sit at, you run a \i\e{client}, which
27 | makes a network connection to the other computer (the \i\e{server}).
28 | The network connection carries your keystrokes and commands from the
29 | client to the server, and carries the server's responses back to
30 | you.
31 |
32 | These protocols can also be used for other types of keyboard-based
33 | interactive session. In particular, there are a lot of bulletin
34 | boards, \i{talker systems} and \i{MUDs} (Multi-User Dungeons) which support
35 | access using Telnet. There are even a few that support SSH.
36 |
37 | You might want to use SSH, Telnet or Rlogin if:
38 |
39 | \b you have an account on a Unix or VMS system which you want to be
40 | able to access from somewhere else
41 |
42 | \b your Internet Service Provider provides you with a login account
43 | on a \i{web server}. (This might also be known as a \i\e{shell account}.
44 | A \e{shell} is the program that runs on the server and interprets
45 | your commands for you.)
46 |
47 | \b you want to use a \i{bulletin board system}, talker or MUD which can
48 | be accessed using Telnet.
49 |
50 | You probably do \e{not} want to use SSH, Telnet or Rlogin if:
51 |
52 | \b you only use Windows. Windows computers have their own
53 | ways of networking between themselves, and unless you are doing
54 | something fairly unusual, you will not need to use any of these
55 | remote login protocols.
56 |
57 | \H{which-one} How do SSH, Telnet and Rlogin differ?
58 |
59 | This list summarises some of the \i{differences between SSH, Telnet
60 | and Rlogin}.
61 |
62 | \b SSH (which stands for \q{\i{secure shell}}) is a recently designed,
63 | high-security protocol. It uses strong cryptography to protect your
64 | connection against eavesdropping, hijacking and other attacks. Telnet
65 | and Rlogin are both older protocols offering minimal security.
66 |
67 | \b SSH and Rlogin both allow you to \I{passwordless login}log in to the
68 | server without having to type a password. (Rlogin's method of doing this is
69 | insecure, and can allow an attacker to access your account on the
70 | server. SSH's method is much more secure, and typically breaking the
71 | security requires the attacker to have gained access to your actual
72 | client machine.)
73 |
74 | \b SSH allows you to connect to the server and automatically send a
75 | command, so that the server will run that command and then
76 | disconnect. So you can use it in automated processing.
77 |
78 | The Internet is a hostile environment and security is everybody's
79 | responsibility. If you are connecting across the open Internet, then
80 | we recommend you use SSH. If the server you want to connect to
81 | doesn't support SSH, it might be worth trying to persuade the
82 | administrator to install it.
83 |
84 | If your client and server are both behind the same (good) firewall,
85 | it is more likely to be safe to use Telnet or Rlogin, but we still
86 | recommend you use SSH.
87 |
--------------------------------------------------------------------------------
/contrib/samplekex.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | # Example Python script to synthesise the server end of an SSH key exchange.
4 |
5 | # This is an output-only script; you run it by means of saying
6 | # something like
7 | #
8 | # samplekex.py | nc -l 2222 | hex dump utility of your choice
9 | #
10 | # and then connecting PuTTY to port 2222. Being output-only, of
11 | # course, it cannot possibly get the key exchange _right_, so PuTTY
12 | # will terminate with an error when the signature in the final message
13 | # doesn't validate. But everything until then should be processed as
14 | # if it was a normal SSH-2 connection, which means you can use this
15 | # script as a starting point for constructing interestingly malformed
16 | # key exchanges to test bug fixes.
17 |
18 | import sys, random
19 | from encodelib import *
20 |
21 | # A random Diffie-Hellman group, taken from an SSH server I made a
22 | # test connection to.
23 | groupgen = 5
24 | group = 0xf5d3849d2092fd427b4ebd838ea4830397a55f80b644626320dbbe51e8f63ed88148d787c94e7e67e4f393f26c565e1992b0cff8a47a953439462a4d0ffa5763ef60ff908f8ee6c4f6ef9f32b9ba50f01ad56fe7ebe90876a5cf61813a4ad4ba7ec0704303c9bf887d36abbd6c2aa9545fc2263232927e731060f5c701c96dc34016636df438ce30973715f121d767cfb98b5d09ae7b86fa36a051ad3c2941a295a68e2f583a56bc69913ec9d25abef4fdf1e31ede827a02620db058b9f041da051c8c0f13b132c17ceb893fa7c4cd8d8feebd82c5f9120cb221b8e88c5fe4dc17ca020a535484c92c7d4bee69c7703e1fa9a652d444c80065342c6ec0fac23c24de246e3dee72ca8bc8beccdade2b36771efcc350558268f5352ae53f2f71db62249ad9ac4fabdd6dfb099c6cff8c05bdea894390f9860f011cca046dfeb2f6ef81094e7980be526742706d1f3db920db107409291bb4c11f9a7dcbfaf26d808e6f9fe636b26b939de419129e86b1e632c60ec23b65c815723c5d861af068fd0ac8b37f4c06ecbd5cb2ef069ca8daac5cbd67c6182a65fed656d0dfbbb8a430b1dbac7bd6303bec8de078fe69f443a7bc8131a284d25dc2844f096240bfc61b62e91a87802987659b884c094c68741d29aa5ca19b9457e1f9df61c7dbbb13a61a79e4670b086027f20da2af4f5b020725f8828726379f429178926a1f0ea03f
25 |
26 | # An RSA key, generated specially for this script.
27 | rsaexp = 0x10001
28 | rsamod = 0xB98FE0C0BEE1E05B35FDDF5517B3E29D8A9A6A7834378B6783A19536968968F755E341B5822CAE15B465DECB80EE4116CF8D22DB5A6C85444A68D0D45D9D42008329619BE3CAC3B192EF83DD2B75C4BB6B567E11B841073BACE92108DA7E97E543ED7F032F454F7AC3C6D3F27DB34BC9974A85C7963C546662AE300A61CBABEE274481FD041C41D0145704F5FA9C77A5A442CD7A64827BB0F21FB56FDE388B596A20D7A7D1C5F22DA96C6C2171D90A673DABC66596CD99499D75AD82FEFDBE04DEC2CC7E1414A95388F668591B3F4D58249F80489646ED2C318E77D4F4E37EE8A588E79F2960620E6D28BF53653F1C974C91845F0BABFE5D167E1CA7044EE20D
29 |
30 | # 16 bytes of random data for the start of KEXINIT.
31 | cookie = "".join([chr(random.randint(0,255)) for i in range(16)])
32 |
33 | sys.stdout.write(greeting("SSH-2.0-Example KEX synthesis"))
34 |
35 | # Expect client to send KEXINIT
36 |
37 | sys.stdout.write(
38 | clearpkt(SSH2_MSG_KEXINIT,
39 | cookie,
40 | name_list(("diffie-hellman-group-exchange-sha256",)), # kex
41 | name_list(("ssh-rsa",)), # host keys
42 | name_list(("aes128-ctr",)), # client->server ciphers
43 | name_list(("aes128-ctr",)), # server->client ciphers
44 | name_list(("hmac-sha2-256",)), # client->server MACs
45 | name_list(("hmac-sha2-256",)), # server->client MACs
46 | name_list(("none",)), # client->server compression
47 | name_list(("none",)), # server->client compression
48 | name_list(()), # client->server languages
49 | name_list(()), # server->client languages
50 | boolean(False), # first kex packet does not follow
51 | uint32(0)))
52 |
53 | # Expect client to send SSH2_MSG_KEX_DH_GEX_REQUEST(0x1000)
54 |
55 | sys.stdout.write(
56 | clearpkt(SSH2_MSG_KEX_DH_GEX_GROUP,
57 | mpint(group),
58 | mpint(groupgen)))
59 |
60 | # Expect client to send SSH2_MSG_KEX_DH_GEX_INIT
61 |
62 | sys.stdout.write(
63 | clearpkt(SSH2_MSG_KEX_DH_GEX_REPLY,
64 | ssh_rsa_key_blob(rsaexp, rsamod),
65 | mpint(random.randint(2, group-2)),
66 | ssh_rsa_signature_blob(random.randint(2, rsamod-2))))
67 |
--------------------------------------------------------------------------------
/unix/uxputty.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Unix PuTTY main program.
3 | */
4 |
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 |
12 | #include "putty.h"
13 | #include "storage.h"
14 |
15 | /*
16 | * Stubs to avoid uxpty.c needing to be linked in.
17 | */
18 | const int use_pty_argv = FALSE;
19 | char **pty_argv; /* never used */
20 |
21 | /*
22 | * Clean up and exit.
23 | */
24 | void cleanup_exit(int code)
25 | {
26 | /*
27 | * Clean up.
28 | */
29 | sk_cleanup();
30 | random_save_seed();
31 | exit(code);
32 | }
33 |
34 | Backend *select_backend(Conf *conf)
35 | {
36 | Backend *back = backend_from_proto(conf_get_int(conf, CONF_protocol));
37 | assert(back != NULL);
38 | return back;
39 | }
40 |
41 | int cfgbox(Conf *conf)
42 | {
43 | char *title = dupcat(appname, " Configuration", NULL);
44 | int ret = do_config_box(title, conf, 0, 0);
45 | sfree(title);
46 | return ret;
47 | }
48 |
49 | static int got_host = 0;
50 |
51 | const int use_event_log = 1, new_session = 1, saved_sessions = 1;
52 |
53 | int process_nonoption_arg(char *arg, Conf *conf, int *allow_launch)
54 | {
55 | char *p, *q = arg;
56 |
57 | if (got_host) {
58 | /*
59 | * If we already have a host name, treat this argument as a
60 | * port number. NB we have to treat this as a saved -P
61 | * argument, so that it will be deferred until it's a good
62 | * moment to run it.
63 | */
64 | int ret = cmdline_process_param("-P", arg, 1, conf);
65 | assert(ret == 2);
66 | } else if (!strncmp(q, "telnet:", 7)) {
67 | /*
68 | * If the hostname starts with "telnet:",
69 | * set the protocol to Telnet and process
70 | * the string as a Telnet URL.
71 | */
72 | char c;
73 |
74 | q += 7;
75 | if (q[0] == '/' && q[1] == '/')
76 | q += 2;
77 | conf_set_int(conf, CONF_protocol, PROT_TELNET);
78 | p = q;
79 | p += host_strcspn(p, ":/");
80 | c = *p;
81 | if (*p)
82 | *p++ = '\0';
83 | if (c == ':')
84 | conf_set_int(conf, CONF_port, atoi(p));
85 | else
86 | conf_set_int(conf, CONF_port, -1);
87 | conf_set_str(conf, CONF_host, q);
88 | got_host = 1;
89 | } else {
90 | /*
91 | * Otherwise, treat this argument as a host name.
92 | */
93 | p = arg;
94 | while (*p && !isspace((unsigned char)*p))
95 | p++;
96 | if (*p)
97 | *p++ = '\0';
98 | conf_set_str(conf, CONF_host, q);
99 | got_host = 1;
100 | }
101 | if (got_host)
102 | *allow_launch = TRUE;
103 | return 1;
104 | }
105 |
106 | char *make_default_wintitle(char *hostname)
107 | {
108 | return dupcat(hostname, " - ", appname, NULL);
109 | }
110 |
111 | /*
112 | * X11-forwarding-related things suitable for Gtk app.
113 | */
114 |
115 | char *platform_get_x_display(void) {
116 | const char *display;
117 | /* Try to take account of --display and what have you. */
118 | if (!(display = gdk_get_display()))
119 | /* fall back to traditional method */
120 | display = getenv("DISPLAY");
121 | return dupstr(display);
122 | }
123 |
124 | const int share_can_be_downstream = TRUE;
125 | const int share_can_be_upstream = TRUE;
126 |
127 | int main(int argc, char **argv)
128 | {
129 | extern int pt_main(int argc, char **argv);
130 | int ret;
131 |
132 | sk_init();
133 | flags = FLAG_VERBOSE | FLAG_INTERACTIVE;
134 | default_protocol = be_default_protocol;
135 | /* Find the appropriate default port. */
136 | {
137 | Backend *b = backend_from_proto(default_protocol);
138 | default_port = 0; /* illegal */
139 | if (b)
140 | default_port = b->default_port;
141 | }
142 | ret = pt_main(argc, argv);
143 | cleanup_exit(ret);
144 | return ret; /* not reached, but placates optimisers */
145 | }
146 |
--------------------------------------------------------------------------------
/sshrsag.c:
--------------------------------------------------------------------------------
1 | /*
2 | * RSA key generation.
3 | */
4 |
5 | #include
6 |
7 | #include "ssh.h"
8 |
9 | #define RSA_EXPONENT 37 /* we like this prime */
10 |
11 | int rsa_generate(struct RSAKey *key, int bits, progfn_t pfn,
12 | void *pfnparam)
13 | {
14 | Bignum pm1, qm1, phi_n;
15 | unsigned pfirst, qfirst;
16 |
17 | /*
18 | * Set up the phase limits for the progress report. We do this
19 | * by passing minus the phase number.
20 | *
21 | * For prime generation: our initial filter finds things
22 | * coprime to everything below 2^16. Computing the product of
23 | * (p-1)/p for all prime p below 2^16 gives about 20.33; so
24 | * among B-bit integers, one in every 20.33 will get through
25 | * the initial filter to be a candidate prime.
26 | *
27 | * Meanwhile, we are searching for primes in the region of 2^B;
28 | * since pi(x) ~ x/log(x), when x is in the region of 2^B, the
29 | * prime density will be d/dx pi(x) ~ 1/log(B), i.e. about
30 | * 1/0.6931B. So the chance of any given candidate being prime
31 | * is 20.33/0.6931B, which is roughly 29.34 divided by B.
32 | *
33 | * So now we have this probability P, we're looking at an
34 | * exponential distribution with parameter P: we will manage in
35 | * one attempt with probability P, in two with probability
36 | * P(1-P), in three with probability P(1-P)^2, etc. The
37 | * probability that we have still not managed to find a prime
38 | * after N attempts is (1-P)^N.
39 | *
40 | * We therefore inform the progress indicator of the number B
41 | * (29.34/B), so that it knows how much to increment by each
42 | * time. We do this in 16-bit fixed point, so 29.34 becomes
43 | * 0x1D.57C4.
44 | */
45 | pfn(pfnparam, PROGFN_PHASE_EXTENT, 1, 0x10000);
46 | pfn(pfnparam, PROGFN_EXP_PHASE, 1, -0x1D57C4 / (bits / 2));
47 | pfn(pfnparam, PROGFN_PHASE_EXTENT, 2, 0x10000);
48 | pfn(pfnparam, PROGFN_EXP_PHASE, 2, -0x1D57C4 / (bits - bits / 2));
49 | pfn(pfnparam, PROGFN_PHASE_EXTENT, 3, 0x4000);
50 | pfn(pfnparam, PROGFN_LIN_PHASE, 3, 5);
51 | pfn(pfnparam, PROGFN_READY, 0, 0);
52 |
53 | /*
54 | * We don't generate e; we just use a standard one always.
55 | */
56 | key->exponent = bignum_from_long(RSA_EXPONENT);
57 |
58 | /*
59 | * Generate p and q: primes with combined length `bits', not
60 | * congruent to 1 modulo e. (Strictly speaking, we wanted (p-1)
61 | * and e to be coprime, and (q-1) and e to be coprime, but in
62 | * general that's slightly more fiddly to arrange. By choosing
63 | * a prime e, we can simplify the criterion.)
64 | */
65 | invent_firstbits(&pfirst, &qfirst);
66 | key->p = primegen(bits / 2, RSA_EXPONENT, 1, NULL,
67 | 1, pfn, pfnparam, pfirst);
68 | key->q = primegen(bits - bits / 2, RSA_EXPONENT, 1, NULL,
69 | 2, pfn, pfnparam, qfirst);
70 |
71 | /*
72 | * Ensure p > q, by swapping them if not.
73 | */
74 | if (bignum_cmp(key->p, key->q) < 0) {
75 | Bignum t = key->p;
76 | key->p = key->q;
77 | key->q = t;
78 | }
79 |
80 | /*
81 | * Now we have p, q and e. All we need to do now is work out
82 | * the other helpful quantities: n=pq, d=e^-1 mod (p-1)(q-1),
83 | * and (q^-1 mod p).
84 | */
85 | pfn(pfnparam, PROGFN_PROGRESS, 3, 1);
86 | key->modulus = bigmul(key->p, key->q);
87 | pfn(pfnparam, PROGFN_PROGRESS, 3, 2);
88 | pm1 = copybn(key->p);
89 | decbn(pm1);
90 | qm1 = copybn(key->q);
91 | decbn(qm1);
92 | phi_n = bigmul(pm1, qm1);
93 | pfn(pfnparam, PROGFN_PROGRESS, 3, 3);
94 | freebn(pm1);
95 | freebn(qm1);
96 | key->private_exponent = modinv(key->exponent, phi_n);
97 | assert(key->private_exponent);
98 | pfn(pfnparam, PROGFN_PROGRESS, 3, 4);
99 | key->iqmp = modinv(key->q, key->p);
100 | assert(key->iqmp);
101 | pfn(pfnparam, PROGFN_PROGRESS, 3, 5);
102 |
103 | /*
104 | * Clean up temporary numbers.
105 | */
106 | freebn(phi_n);
107 |
108 | return 1;
109 | }
110 |
--------------------------------------------------------------------------------
/windows/pageant.rc:
--------------------------------------------------------------------------------
1 | /*
2 | * Windows resources for Pageant.
3 | */
4 |
5 | #include "rcstuff.h"
6 |
7 | #define APPNAME "Pageant"
8 | #define APPDESC "PuTTY SSH authentication agent"
9 |
10 | 200 ICON "pageant.ico"
11 | 201 ICON "pageants.ico"
12 |
13 | 210 DIALOG DISCARDABLE 0, 0, 140, 60
14 | STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
15 | CAPTION "Pageant: Enter Passphrase"
16 | FONT 8, "MS Shell Dlg"
17 | BEGIN
18 | CTEXT "Enter passphrase for key", 100, 10, 6, 120, 8
19 | CTEXT "", 101, 10, 16, 120, 8
20 | EDITTEXT 102, 10, 26, 120, 12, ES_PASSWORD | ES_AUTOHSCROLL
21 | DEFPUSHBUTTON "O&K", IDOK, 20, 42, 40, 14
22 | PUSHBUTTON "&Cancel", IDCANCEL, 80, 42, 40, 14
23 | END
24 |
25 | 211 DIALOG DISCARDABLE 0, 0, 330, 200
26 | STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
27 | CAPTION "Pageant Key List"
28 | FONT 8, "MS Shell Dlg"
29 | BEGIN
30 | LISTBOX 100, 10, 10, 310, 155,
31 | LBS_EXTENDEDSEL | LBS_HASSTRINGS | LBS_USETABSTOPS | WS_VSCROLL | WS_TABSTOP
32 | PUSHBUTTON "&Add Key", 101, 75, 162, 60, 14
33 | PUSHBUTTON "&Remove Key", 102, 195, 162, 60, 14
34 | PUSHBUTTON "&Help", 103, 10, 182, 50, 14
35 | DEFPUSHBUTTON "&Close", IDOK, 270, 182, 50, 14
36 | END
37 |
38 | /* Accelerators used: cl */
39 | 213 DIALOG DISCARDABLE 140, 40, 136, 70
40 | STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
41 | CAPTION "About Pageant"
42 | FONT 8, "MS Shell Dlg"
43 | BEGIN
44 | DEFPUSHBUTTON "&Close", IDOK, 82, 52, 48, 14
45 | PUSHBUTTON "View &Licence", 101, 6, 52, 70, 14
46 | CTEXT "Pageant", 102, 10, 6, 120, 8
47 | CTEXT "", 100, 10, 16, 120, 16
48 | CTEXT "\251 1997-2015 Simon Tatham. All rights reserved.",
49 | 103, 10, 34, 120, 16
50 | END
51 |
52 | /* No accelerators used */
53 | 214 DIALOG DISCARDABLE 50, 50, 226, 263
54 | STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
55 | CAPTION "PuTTY Licence"
56 | FONT 8, "MS Shell Dlg"
57 | BEGIN
58 | DEFPUSHBUTTON "OK", IDOK, 98, 243, 44, 14
59 |
60 | LTEXT "Copyright \251 1997-2015 Simon Tatham", 1000, 10, 10, 206, 8
61 |
62 | LTEXT "Portions copyright Robert de Bath, Joris van Rantwijk, Delian", 1001, 10, 26, 206, 8
63 | LTEXT "Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas", 1002, 10, 34, 206, 8
64 | LTEXT "Barry, Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa,", 1003, 10, 42, 206, 8
65 | LTEXT "Markus Kuhn, Colin Watson, and CORE SDI S.A.", 1004, 10, 50, 206, 8
66 |
67 | LTEXT "Permission is hereby granted, free of charge, to any person", 1005, 10, 66, 206, 8
68 | LTEXT "obtaining a copy of this software and associated documentation", 1006, 10, 74, 206, 8
69 | LTEXT "files (the ""Software""), to deal in the Software without restriction,", 1007, 10, 82, 206, 8
70 | LTEXT "including without limitation the rights to use, copy, modify, merge,", 1008, 10, 90, 206, 8
71 | LTEXT "publish, distribute, sublicense, and/or sell copies of the Software,", 1009, 10, 98, 206, 8
72 | LTEXT "and to permit persons to whom the Software is furnished to do so,", 1010, 10, 106, 206, 8
73 | LTEXT "subject to the following conditions:", 1011, 10, 114, 206, 8
74 |
75 | LTEXT "The above copyright notice and this permission notice shall be", 1012, 10, 130, 206, 8
76 | LTEXT "included in all copies or substantial portions of the Software.", 1013, 10, 138, 206, 8
77 |
78 | LTEXT "THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT", 1014, 10, 154, 206, 8
79 | LTEXT "WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,", 1015, 10, 162, 206, 8
80 | LTEXT "INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF", 1016, 10, 170, 206, 8
81 | LTEXT "MERCHANTABILITY, FITNESS FOR A PARTICULAR", 1017, 10, 178, 206, 8
82 | LTEXT "PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE", 1018, 10, 186, 206, 8
83 | LTEXT "COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES", 1019, 10, 194, 206, 8
84 | LTEXT "OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,", 1020, 10, 202, 206, 8
85 | LTEXT "TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN", 1021, 10, 210, 206, 8
86 | LTEXT "CONNECTION WITH THE SOFTWARE OR THE USE OR", 1022, 10, 218, 206, 8
87 | LTEXT "OTHER DEALINGS IN THE SOFTWARE.", 1023, 10, 226, 206, 8
88 |
89 | END
90 |
91 | #include "version.rc2"
92 |
93 | #ifndef NO_MANIFESTS
94 | 1 RT_MANIFEST "pageant.mft"
95 | #endif /* NO_MANIFESTS */
96 |
--------------------------------------------------------------------------------
/int64.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Handling of the int64 and uint64 types. Done in 32-bit integers,
3 | * for (pre-C99) portability. Hopefully once C99 becomes widespread
4 | * we can kiss this lot goodbye...
5 | */
6 |
7 | #include
8 | #include
9 |
10 | #include "int64.h"
11 |
12 | uint64 uint64_div10(uint64 x, int *remainder)
13 | {
14 | uint64 y;
15 | unsigned int rem, r2;
16 | y.hi = x.hi / 10;
17 | y.lo = x.lo / 10;
18 | rem = x.lo % 10;
19 | /*
20 | * Now we have to add in the remainder left over from x.hi.
21 | */
22 | r2 = x.hi % 10;
23 | y.lo += r2 * 429496729;
24 | rem += r2 * 6;
25 | y.lo += rem / 10;
26 | rem %= 10;
27 |
28 | if (remainder)
29 | *remainder = rem;
30 | return y;
31 | }
32 |
33 | void uint64_decimal(uint64 x, char *buffer)
34 | {
35 | char buf[20];
36 | int start = 20;
37 | int d;
38 |
39 | do {
40 | x = uint64_div10(x, &d);
41 | assert(start > 0);
42 | buf[--start] = d + '0';
43 | } while (x.hi || x.lo);
44 |
45 | memcpy(buffer, buf + start, sizeof(buf) - start);
46 | buffer[sizeof(buf) - start] = '\0';
47 | }
48 |
49 | uint64 uint64_make(unsigned long hi, unsigned long lo)
50 | {
51 | uint64 y;
52 | y.hi = hi & 0xFFFFFFFFU;
53 | y.lo = lo & 0xFFFFFFFFU;
54 | return y;
55 | }
56 |
57 | uint64 uint64_add(uint64 x, uint64 y)
58 | {
59 | x.lo = (x.lo + y.lo) & 0xFFFFFFFFU;
60 | x.hi += y.hi + (x.lo < y.lo ? 1 : 0);
61 | return x;
62 | }
63 |
64 | uint64 uint64_add32(uint64 x, unsigned long y)
65 | {
66 | uint64 yy;
67 | yy.hi = 0;
68 | yy.lo = y;
69 | return uint64_add(x, yy);
70 | }
71 |
72 | int uint64_compare(uint64 x, uint64 y)
73 | {
74 | if (x.hi != y.hi)
75 | return x.hi < y.hi ? -1 : +1;
76 | if (x.lo != y.lo)
77 | return x.lo < y.lo ? -1 : +1;
78 | return 0;
79 | }
80 |
81 | uint64 uint64_subtract(uint64 x, uint64 y)
82 | {
83 | x.lo = (x.lo - y.lo) & 0xFFFFFFFFU;
84 | x.hi = (x.hi - y.hi - (x.lo > (y.lo ^ 0xFFFFFFFFU) ? 1 : 0)) & 0xFFFFFFFFU;
85 | return x;
86 | }
87 |
88 | double uint64_to_double(uint64 x)
89 | {
90 | return (4294967296.0 * x.hi) + (double)x.lo;
91 | }
92 |
93 | uint64 uint64_shift_right(uint64 x, int shift)
94 | {
95 | if (shift < 32) {
96 | x.lo >>= shift;
97 | x.lo |= (x.hi << (32-shift)) & 0xFFFFFFFFU;
98 | x.hi >>= shift;
99 | } else {
100 | x.lo = x.hi >> (shift-32);
101 | x.hi = 0;
102 | }
103 | return x;
104 | }
105 |
106 | uint64 uint64_shift_left(uint64 x, int shift)
107 | {
108 | if (shift < 32) {
109 | x.hi = (x.hi << shift) & 0xFFFFFFFFU;
110 | x.hi |= (x.lo >> (32-shift));
111 | x.lo = (x.lo << shift) & 0xFFFFFFFFU;
112 | } else {
113 | x.hi = (x.lo << (shift-32)) & 0xFFFFFFFFU;
114 | x.lo = 0;
115 | }
116 | return x;
117 | }
118 |
119 | uint64 uint64_from_decimal(char *str)
120 | {
121 | uint64 ret;
122 | ret.hi = ret.lo = 0;
123 | while (*str >= '0' && *str <= '9') {
124 | ret = uint64_add(uint64_shift_left(ret, 3),
125 | uint64_shift_left(ret, 1));
126 | ret = uint64_add32(ret, *str - '0');
127 | str++;
128 | }
129 | return ret;
130 | }
131 |
132 | #ifdef TESTMODE
133 |
134 | #include
135 |
136 | int main(void)
137 | {
138 | uint64 x, y, z;
139 | char buf[80];
140 |
141 | x = uint64_make(0x3456789AUL, 0xDEF01234UL);
142 | printf("%08lx.%08lx\n", x.hi, x.lo);
143 | uint64_decimal(x, buf);
144 | printf("%s\n", buf);
145 |
146 | y = uint64_add32(x, 0xFFFFFFFFU);
147 | printf("%08lx.%08lx\n", y.hi, y.lo);
148 | uint64_decimal(y, buf);
149 | printf("%s\n", buf);
150 |
151 | z = uint64_subtract(y, x);
152 | printf("%08lx.%08lx\n", z.hi, z.lo);
153 | uint64_decimal(z, buf);
154 | printf("%s\n", buf);
155 |
156 | z = uint64_subtract(x, y);
157 | printf("%08lx.%08lx\n", z.hi, z.lo);
158 | uint64_decimal(z, buf);
159 | printf("%s\n", buf);
160 |
161 | y = uint64_shift_right(x, 4);
162 | printf("%08lx.%08lx\n", y.hi, y.lo);
163 |
164 | y = uint64_shift_right(x, 36);
165 | printf("%08lx.%08lx\n", y.hi, y.lo);
166 |
167 | y = uint64_shift_left(x, 4);
168 | printf("%08lx.%08lx\n", x.hi, x.lo);
169 |
170 | y = uint64_shift_left(x, 36);
171 | printf("%08lx.%08lx\n", x.hi, x.lo);
172 |
173 | return 0;
174 | }
175 | #endif
176 |
--------------------------------------------------------------------------------
/windows/win_res.rc2:
--------------------------------------------------------------------------------
1 | /*
2 | * Windows resources shared between PuTTY and PuTTYtel, to be #include'd
3 | * after defining appropriate macros.
4 | * Note that many of these strings mention PuTTY. Due to restrictions in
5 | * VC's handling of string concatenation, this can't easily be fixed.
6 | * It's fixed up at runtime.
7 | * FIXME: This file is called '.rc2' rather than '.rc' to avoid MSVC trying
8 | * to compile it on its own when using the project files. Nicer solutions
9 | * welcome.
10 | */
11 |
12 | #include "win_res.h"
13 |
14 | IDI_MAINICON ICON "putty.ico"
15 |
16 | IDI_CFGICON ICON "puttycfg.ico"
17 |
18 | /* Accelerators used: clw */
19 | IDD_ABOUTBOX DIALOG DISCARDABLE 140, 40, 214, 70
20 | STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
21 | CAPTION "About PuTTY"
22 | FONT 8, "MS Shell Dlg"
23 | BEGIN
24 | DEFPUSHBUTTON "&Close", IDOK, 160, 52, 48, 14
25 | PUSHBUTTON "View &Licence", IDA_LICENCE, 6, 52, 70, 14
26 | PUSHBUTTON "Visit &Web Site", IDA_WEB, 84, 52, 70, 14
27 | CTEXT "PuTTY", IDA_TEXT1, 10, 6, 194, 8
28 | CTEXT "", IDA_VERSION, 10, 16, 194, 16
29 | CTEXT "\251 1997-2015 Simon Tatham. All rights reserved.",
30 | IDA_TEXT2, 10, 34, 194, 16
31 | END
32 |
33 | /* Accelerators used: aco */
34 | IDD_MAINBOX DIALOG DISCARDABLE 0, 0, 300, 252
35 | STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
36 | CAPTION "PuTTY Configuration"
37 | FONT 8, "MS Shell Dlg"
38 | CLASS "PuTTYConfigBox"
39 | BEGIN
40 | END
41 |
42 | /* Accelerators used: co */
43 | IDD_LOGBOX DIALOG DISCARDABLE 100, 20, 300, 119
44 | STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
45 | CAPTION "PuTTY Event Log"
46 | FONT 8, "MS Shell Dlg"
47 | BEGIN
48 | DEFPUSHBUTTON "&Close", IDOK, 135, 102, 44, 14
49 | PUSHBUTTON "C&opy", IDN_COPY, 81, 102, 44, 14
50 | LISTBOX IDN_LIST, 3, 3, 294, 95, LBS_HASSTRINGS | LBS_USETABSTOPS | WS_VSCROLL | LBS_EXTENDEDSEL
51 | END
52 |
53 | /* No accelerators used */
54 | IDD_LICENCEBOX DIALOG DISCARDABLE 50, 50, 226, 263
55 | STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
56 | CAPTION "PuTTY Licence"
57 | FONT 8, "MS Shell Dlg"
58 | BEGIN
59 | DEFPUSHBUTTON "OK", IDOK, 98, 243, 44, 14
60 |
61 | LTEXT "Copyright \251 1997-2015 Simon Tatham", 1000, 10, 10, 206, 8
62 |
63 | LTEXT "Portions copyright Robert de Bath, Joris van Rantwijk, Delian", 1001, 10, 26, 206, 8
64 | LTEXT "Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas", 1002, 10, 34, 206, 8
65 | LTEXT "Barry, Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa,", 1003, 10, 42, 206, 8
66 | LTEXT "Markus Kuhn, Colin Watson, and CORE SDI S.A.", 1004, 10, 50, 206, 8
67 |
68 | LTEXT "Permission is hereby granted, free of charge, to any person", 1005, 10, 66, 206, 8
69 | LTEXT "obtaining a copy of this software and associated documentation", 1006, 10, 74, 206, 8
70 | LTEXT "files (the ""Software""), to deal in the Software without restriction,", 1007, 10, 82, 206, 8
71 | LTEXT "including without limitation the rights to use, copy, modify, merge,", 1008, 10, 90, 206, 8
72 | LTEXT "publish, distribute, sublicense, and/or sell copies of the Software,", 1009, 10, 98, 206, 8
73 | LTEXT "and to permit persons to whom the Software is furnished to do so,", 1010, 10, 106, 206, 8
74 | LTEXT "subject to the following conditions:", 1011, 10, 114, 206, 8
75 |
76 | LTEXT "The above copyright notice and this permission notice shall be", 1012, 10, 130, 206, 8
77 | LTEXT "included in all copies or substantial portions of the Software.", 1013, 10, 138, 206, 8
78 |
79 | LTEXT "THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT", 1014, 10, 154, 206, 8
80 | LTEXT "WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,", 1015, 10, 162, 206, 8
81 | LTEXT "INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF", 1016, 10, 170, 206, 8
82 | LTEXT "MERCHANTABILITY, FITNESS FOR A PARTICULAR", 1017, 10, 178, 206, 8
83 | LTEXT "PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE", 1018, 10, 186, 206, 8
84 | LTEXT "COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES", 1019, 10, 194, 206, 8
85 | LTEXT "OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,", 1020, 10, 202, 206, 8
86 | LTEXT "TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN", 1021, 10, 210, 206, 8
87 | LTEXT "CONNECTION WITH THE SOFTWARE OR THE USE OR", 1022, 10, 218, 206, 8
88 | LTEXT "OTHER DEALINGS IN THE SOFTWARE.", 1023, 10, 226, 206, 8
89 |
90 | END
91 |
92 | #include "version.rc2"
93 |
--------------------------------------------------------------------------------
/unix/uxagentc.c:
--------------------------------------------------------------------------------
1 | /*
2 | * SSH agent client code.
3 | */
4 |
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 |
13 | #include "putty.h"
14 | #include "misc.h"
15 | #include "tree234.h"
16 | #include "puttymem.h"
17 |
18 | int agent_exists(void)
19 | {
20 | const char *p = getenv("SSH_AUTH_SOCK");
21 | if (p && *p)
22 | return TRUE;
23 | return FALSE;
24 | }
25 |
26 | static tree234 *agent_connections;
27 | struct agent_connection {
28 | int fd;
29 | char *retbuf;
30 | char sizebuf[4];
31 | int retsize, retlen;
32 | void (*callback)(void *, void *, int);
33 | void *callback_ctx;
34 | };
35 | static int agent_conncmp(void *av, void *bv)
36 | {
37 | struct agent_connection *a = (struct agent_connection *) av;
38 | struct agent_connection *b = (struct agent_connection *) bv;
39 | if (a->fd < b->fd)
40 | return -1;
41 | if (a->fd > b->fd)
42 | return +1;
43 | return 0;
44 | }
45 | static int agent_connfind(void *av, void *bv)
46 | {
47 | int afd = *(int *) av;
48 | struct agent_connection *b = (struct agent_connection *) bv;
49 | if (afd < b->fd)
50 | return -1;
51 | if (afd > b->fd)
52 | return +1;
53 | return 0;
54 | }
55 |
56 | static int agent_select_result(int fd, int event)
57 | {
58 | int ret;
59 | struct agent_connection *conn;
60 |
61 | assert(event == 1); /* not selecting for anything but R */
62 |
63 | conn = find234(agent_connections, &fd, agent_connfind);
64 | if (!conn) {
65 | uxsel_del(fd);
66 | return 1;
67 | }
68 |
69 | ret = read(fd, conn->retbuf+conn->retlen, conn->retsize-conn->retlen);
70 | if (ret <= 0) {
71 | if (conn->retbuf != conn->sizebuf) sfree(conn->retbuf);
72 | conn->retbuf = NULL;
73 | conn->retlen = 0;
74 | goto done;
75 | }
76 | conn->retlen += ret;
77 | if (conn->retsize == 4 && conn->retlen == 4) {
78 | conn->retsize = toint(GET_32BIT(conn->retbuf) + 4);
79 | if (conn->retsize <= 0) {
80 | conn->retbuf = NULL;
81 | conn->retlen = 0;
82 | goto done;
83 | }
84 | assert(conn->retbuf == conn->sizebuf);
85 | conn->retbuf = snewn(conn->retsize, char);
86 | memcpy(conn->retbuf, conn->sizebuf, 4);
87 | }
88 |
89 | if (conn->retlen < conn->retsize)
90 | return 0; /* more data to come */
91 |
92 | done:
93 | /*
94 | * We have now completed the agent query. Do the callback, and
95 | * clean up. (Of course we don't free retbuf, since ownership
96 | * of that passes to the callback.)
97 | */
98 | conn->callback(conn->callback_ctx, conn->retbuf, conn->retlen);
99 | uxsel_del(fd);
100 | close(fd);
101 | del234(agent_connections, conn);
102 | sfree(conn);
103 | return 0;
104 | }
105 |
106 | int agent_query(void *in, int inlen, void **out, int *outlen,
107 | void (*callback)(void *, void *, int), void *callback_ctx)
108 | {
109 | char *name;
110 | int sock;
111 | struct sockaddr_un addr;
112 | int done;
113 | struct agent_connection *conn;
114 |
115 | name = getenv("SSH_AUTH_SOCK");
116 | if (!name)
117 | goto failure;
118 |
119 | sock = socket(PF_UNIX, SOCK_STREAM, 0);
120 | if (sock < 0) {
121 | perror("socket(PF_UNIX)");
122 | exit(1);
123 | }
124 |
125 | cloexec(sock);
126 |
127 | addr.sun_family = AF_UNIX;
128 | strncpy(addr.sun_path, name, sizeof(addr.sun_path));
129 | if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
130 | close(sock);
131 | goto failure;
132 | }
133 |
134 | for (done = 0; done < inlen ;) {
135 | int ret = write(sock, (char *)in + done, inlen - done);
136 | if (ret <= 0) {
137 | close(sock);
138 | goto failure;
139 | }
140 | done += ret;
141 | }
142 |
143 | if (!agent_connections)
144 | agent_connections = newtree234(agent_conncmp);
145 |
146 | conn = snew(struct agent_connection);
147 | conn->fd = sock;
148 | conn->retbuf = conn->sizebuf;
149 | conn->retsize = 4;
150 | conn->retlen = 0;
151 | conn->callback = callback;
152 | conn->callback_ctx = callback_ctx;
153 | add234(agent_connections, conn);
154 |
155 | uxsel_set(sock, 1, agent_select_result);
156 | return 0;
157 |
158 | failure:
159 | *out = NULL;
160 | *outlen = 0;
161 | return 1;
162 | }
163 |
--------------------------------------------------------------------------------
/charset/localenc.c:
--------------------------------------------------------------------------------
1 | /*
2 | * local.c - translate our internal character set codes to and from
3 | * our own set of plausibly legible character-set names. Also
4 | * provides a canonical name for each encoding (useful for software
5 | * announcing what character set it will be using), and a set of
6 | * enumeration functions which return a list of supported
7 | * encodings one by one.
8 | *
9 | * charset_from_localenc will attempt all other text translations
10 | * as well as this table, to maximise the number of different ways
11 | * you can select a supported charset.
12 | */
13 |
14 | #include
15 | #include "charset.h"
16 | #include "internal.h"
17 |
18 | static const struct {
19 | const char *name;
20 | int charset;
21 | int return_in_enum; /* enumeration misses some charsets */
22 | } localencs[] = {
23 | { "", CS_NONE, 0 },
24 | { "UTF-8", CS_UTF8, 1 },
25 | { "ISO-8859-1", CS_ISO8859_1, 1 },
26 | { "ISO-8859-1 with X11 line drawing", CS_ISO8859_1_X11, 0 },
27 | { "ISO-8859-2", CS_ISO8859_2, 1 },
28 | { "ISO-8859-3", CS_ISO8859_3, 1 },
29 | { "ISO-8859-4", CS_ISO8859_4, 1 },
30 | { "ISO-8859-5", CS_ISO8859_5, 1 },
31 | { "ISO-8859-6", CS_ISO8859_6, 1 },
32 | { "ISO-8859-7", CS_ISO8859_7, 1 },
33 | { "ISO-8859-8", CS_ISO8859_8, 1 },
34 | { "ISO-8859-9", CS_ISO8859_9, 1 },
35 | { "ISO-8859-10", CS_ISO8859_10, 1 },
36 | { "ISO-8859-11", CS_ISO8859_11, 1 },
37 | { "ISO-8859-13", CS_ISO8859_13, 1 },
38 | { "ISO-8859-14", CS_ISO8859_14, 1 },
39 | { "ISO-8859-15", CS_ISO8859_15, 1 },
40 | { "ISO-8859-16", CS_ISO8859_16, 1 },
41 | { "CP437", CS_CP437, 1 },
42 | { "CP850", CS_CP850, 1 },
43 | { "CP852", CS_CP852, 1 },
44 | { "CP866", CS_CP866, 1 },
45 | { "CP1250", CS_CP1250, 1 },
46 | { "CP1251", CS_CP1251, 1 },
47 | { "CP1252", CS_CP1252, 1 },
48 | { "CP1253", CS_CP1253, 1 },
49 | { "CP1254", CS_CP1254, 1 },
50 | { "CP1255", CS_CP1255, 1 },
51 | { "CP1256", CS_CP1256, 1 },
52 | { "CP1257", CS_CP1257, 1 },
53 | { "CP1258", CS_CP1258, 1 },
54 | { "KOI8-R", CS_KOI8_R, 1 },
55 | { "KOI8-U", CS_KOI8_U, 1 },
56 | { "Mac Roman", CS_MAC_ROMAN, 1 },
57 | { "Mac Turkish", CS_MAC_TURKISH, 1 },
58 | { "Mac Croatian", CS_MAC_CROATIAN, 1 },
59 | { "Mac Iceland", CS_MAC_ICELAND, 1 },
60 | { "Mac Romanian", CS_MAC_ROMANIAN, 1 },
61 | { "Mac Greek", CS_MAC_GREEK, 1 },
62 | { "Mac Cyrillic", CS_MAC_CYRILLIC, 1 },
63 | { "Mac Thai", CS_MAC_THAI, 1 },
64 | { "Mac Centeuro", CS_MAC_CENTEURO, 1 },
65 | { "Mac Symbol", CS_MAC_SYMBOL, 1 },
66 | { "Mac Dingbats", CS_MAC_DINGBATS, 1 },
67 | { "Mac Roman (old)", CS_MAC_ROMAN_OLD, 0 },
68 | { "Mac Croatian (old)", CS_MAC_CROATIAN_OLD, 0 },
69 | { "Mac Iceland (old)", CS_MAC_ICELAND_OLD, 0 },
70 | { "Mac Romanian (old)", CS_MAC_ROMANIAN_OLD, 0 },
71 | { "Mac Greek (old)", CS_MAC_GREEK_OLD, 0 },
72 | { "Mac Cyrillic (old)", CS_MAC_CYRILLIC_OLD, 0 },
73 | { "Mac Ukraine", CS_MAC_UKRAINE, 1 },
74 | { "Mac VT100", CS_MAC_VT100, 1 },
75 | { "Mac VT100 (old)", CS_MAC_VT100_OLD, 0 },
76 | { "VISCII", CS_VISCII, 1 },
77 | { "HP ROMAN8", CS_HP_ROMAN8, 1 },
78 | { "DEC MCS", CS_DEC_MCS, 1 },
79 | };
80 |
81 | const char *charset_to_localenc(int charset)
82 | {
83 | int i;
84 |
85 | for (i = 0; i < (int)lenof(localencs); i++)
86 | if (charset == localencs[i].charset)
87 | return localencs[i].name;
88 |
89 | return NULL; /* not found */
90 | }
91 |
92 | int charset_from_localenc(const char *name)
93 | {
94 | int i;
95 |
96 | if ( (i = charset_from_mimeenc(name)) != CS_NONE)
97 | return i;
98 | if ( (i = charset_from_xenc(name)) != CS_NONE)
99 | return i;
100 |
101 | for (i = 0; i < (int)lenof(localencs); i++) {
102 | const char *p, *q;
103 | p = name;
104 | q = localencs[i].name;
105 | while (*p || *q) {
106 | if (tolower((unsigned char)*p) != tolower((unsigned char)*q))
107 | break;
108 | p++; q++;
109 | }
110 | if (!*p && !*q)
111 | return localencs[i].charset;
112 | }
113 |
114 | return CS_NONE; /* not found */
115 | }
116 |
117 | int charset_localenc_nth(int n)
118 | {
119 | int i;
120 |
121 | for (i = 0; i < (int)lenof(localencs); i++)
122 | if (localencs[i].return_in_enum && !n--)
123 | return localencs[i].charset;
124 |
125 | return CS_NONE; /* end of list */
126 | }
127 |
--------------------------------------------------------------------------------
/contrib/cygtermd/main.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Main program.
3 | */
4 |
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 |
13 | #include
14 | #include
15 | #include
16 |
17 | #include "sel.h"
18 | #include "pty.h"
19 | #include "telnet.h"
20 |
21 | int signalpipe[2];
22 |
23 | sel *asel;
24 | sel_rfd *netr, *ptyr, *sigr;
25 | int ptyfd;
26 | sel_wfd *netw, *ptyw;
27 | Telnet telnet;
28 |
29 | #define BUF 65536
30 |
31 | void sigchld(int signum)
32 | {
33 | write(signalpipe[1], "C", 1);
34 | }
35 |
36 | void fatal(const char *fmt, ...)
37 | {
38 | va_list ap;
39 | fprintf(stderr, "FIXME: ");
40 | va_start(ap, fmt);
41 | vfprintf(stderr, fmt, ap);
42 | va_end(ap);
43 | fprintf(stderr, "\n");
44 | exit(1);
45 | }
46 |
47 | void net_readdata(sel_rfd *rfd, void *data, size_t len)
48 | {
49 | if (len == 0)
50 | exit(0); /* EOF on network - client went away */
51 | telnet_from_net(telnet, data, len);
52 | if (sel_write(netw, NULL, 0) > BUF)
53 | sel_rfd_freeze(ptyr);
54 | if (sel_write(ptyw, NULL, 0) > BUF)
55 | sel_rfd_freeze(netr);
56 | }
57 |
58 | void net_readerr(sel_rfd *rfd, int error)
59 | {
60 | fprintf(stderr, "standard input: read: %s\n", strerror(errno));
61 | exit(1);
62 | }
63 |
64 | void net_written(sel_wfd *wfd, size_t bufsize)
65 | {
66 | if (bufsize < BUF)
67 | sel_rfd_unfreeze(ptyr);
68 | }
69 |
70 | void net_writeerr(sel_wfd *wfd, int error)
71 | {
72 | fprintf(stderr, "standard input: write: %s\n", strerror(errno));
73 | exit(1);
74 | }
75 |
76 | void pty_readdata(sel_rfd *rfd, void *data, size_t len)
77 | {
78 | if (len == 0)
79 | exit(0); /* EOF on pty */
80 | telnet_from_pty(telnet, data, len);
81 | if (sel_write(netw, NULL, 0) > BUF)
82 | sel_rfd_freeze(ptyr);
83 | if (sel_write(ptyw, NULL, 0) > BUF)
84 | sel_rfd_freeze(netr);
85 | }
86 |
87 | void pty_readerr(sel_rfd *rfd, int error)
88 | {
89 | if (error == EIO) /* means EOF, on a pty */
90 | exit(0);
91 | fprintf(stderr, "pty: read: %s\n", strerror(errno));
92 | exit(1);
93 | }
94 |
95 | void pty_written(sel_wfd *wfd, size_t bufsize)
96 | {
97 | if (bufsize < BUF)
98 | sel_rfd_unfreeze(netr);
99 | }
100 |
101 | void pty_writeerr(sel_wfd *wfd, int error)
102 | {
103 | fprintf(stderr, "pty: write: %s\n", strerror(errno));
104 | exit(1);
105 | }
106 |
107 | void sig_readdata(sel_rfd *rfd, void *data, size_t len)
108 | {
109 | char *p = data;
110 |
111 | while (len > 0) {
112 | if (*p == 'C') {
113 | int status;
114 | pid_t pid = waitpid(-1, &status, WNOHANG);
115 | if (WIFEXITED(status) || WIFSIGNALED(status))
116 | exit(0); /* child process vanished */
117 | }
118 | }
119 | }
120 |
121 | void sig_readerr(sel_rfd *rfd, int error)
122 | {
123 | fprintf(stderr, "signal pipe: read: %s\n", strerror(errno));
124 | exit(1);
125 | }
126 |
127 | int main(int argc, char **argv)
128 | {
129 | int ret;
130 | int shell_started = 0;
131 | char *directory = NULL;
132 | char **program_args = NULL;
133 |
134 | if (argc > 1 && argv[1][0]) {
135 | directory = argv[1];
136 | argc--, argv++;
137 | }
138 | if (argc > 1) {
139 | program_args = argv + 1;
140 | }
141 |
142 | pty_preinit();
143 |
144 | asel = sel_new(NULL);
145 | netr = sel_rfd_add(asel, 0, net_readdata, net_readerr, NULL);
146 | netw = sel_wfd_add(asel, 1, net_written, net_writeerr, NULL);
147 | ptyr = sel_rfd_add(asel, -1, pty_readdata, pty_readerr, NULL);
148 | ptyw = sel_wfd_add(asel, -1, pty_written, pty_writeerr, NULL);
149 |
150 | telnet = telnet_new(netw, ptyw);
151 |
152 | if (pipe(signalpipe) < 0) {
153 | perror("pipe");
154 | return 1;
155 | }
156 | sigr = sel_rfd_add(asel, signalpipe[0], sig_readdata,
157 | sig_readerr, NULL);
158 |
159 | signal(SIGCHLD, sigchld);
160 |
161 | do {
162 | struct shell_data shdata;
163 |
164 | ret = sel_iterate(asel, -1);
165 | if (!shell_started && telnet_shell_ok(telnet, &shdata)) {
166 | ptyfd = run_program_in_pty(&shdata, directory, program_args);
167 | sel_rfd_setfd(ptyr, ptyfd);
168 | sel_wfd_setfd(ptyw, ptyfd);
169 | shell_started = 1;
170 | }
171 | } while (ret == 0);
172 |
173 | return 0;
174 | }
175 |
--------------------------------------------------------------------------------
/storage.h:
--------------------------------------------------------------------------------
1 | /*
2 | * storage.h: interface defining functions for storage and recovery
3 | * of PuTTY's persistent data.
4 | */
5 |
6 | #ifndef PUTTY_STORAGE_H
7 | #define PUTTY_STORAGE_H
8 |
9 | /* ----------------------------------------------------------------------
10 | * Functions to save and restore PuTTY sessions. Note that this is
11 | * only the low-level code to do the reading and writing. The
12 | * higher-level code that translates an internal Conf structure into
13 | * a set of (key,value) pairs in their external storage format is
14 | * elsewhere, since it doesn't (mostly) change between platforms.
15 | */
16 |
17 | /*
18 | * Write a saved session. The caller is expected to call
19 | * open_setting_w() to get a `void *' handle, then pass that to a
20 | * number of calls to write_setting_s() and write_setting_i(), and
21 | * then close it using close_settings_w(). At the end of this call
22 | * sequence the settings should have been written to the PuTTY
23 | * persistent storage area.
24 | *
25 | * A given key will be written at most once while saving a session.
26 | * Keys may be up to 255 characters long. String values have no length
27 | * limit.
28 | *
29 | * Any returned error message must be freed after use.
30 | */
31 | void *open_settings_w(const char *sessionname, char **errmsg);
32 | void write_setting_s(void *handle, const char *key, const char *value);
33 | void write_setting_i(void *handle, const char *key, int value);
34 | void write_setting_filename(void *handle, const char *key, Filename *value);
35 | void write_setting_fontspec(void *handle, const char *key, FontSpec *font);
36 | void close_settings_w(void *handle);
37 |
38 | /*
39 | * Read a saved session. The caller is expected to call
40 | * open_setting_r() to get a `void *' handle, then pass that to a
41 | * number of calls to read_setting_s() and read_setting_i(), and
42 | * then close it using close_settings_r().
43 | *
44 | * read_setting_s() returns a dynamically allocated string which the
45 | * caller must free. read_setting_filename() and
46 | * read_setting_fontspec() likewise return dynamically allocated
47 | * structures.
48 | *
49 | * If a particular string setting is not present in the session,
50 | * read_setting_s() can return NULL, in which case the caller
51 | * should invent a sensible default. If an integer setting is not
52 | * present, read_setting_i() returns its provided default.
53 | */
54 | void *open_settings_r(const char *sessionname);
55 | char *read_setting_s(void *handle, const char *key);
56 | int read_setting_i(void *handle, const char *key, int defvalue);
57 | Filename *read_setting_filename(void *handle, const char *key);
58 | FontSpec *read_setting_fontspec(void *handle, const char *key);
59 | void close_settings_r(void *handle);
60 |
61 | /*
62 | * Delete a whole saved session.
63 | */
64 | void del_settings(const char *sessionname);
65 |
66 | /*
67 | * Enumerate all saved sessions.
68 | */
69 | void *enum_settings_start(void);
70 | char *enum_settings_next(void *handle, char *buffer, int buflen);
71 | void enum_settings_finish(void *handle);
72 |
73 | /* ----------------------------------------------------------------------
74 | * Functions to access PuTTY's host key database.
75 | */
76 |
77 | /*
78 | * See if a host key matches the database entry. Return values can
79 | * be 0 (entry matches database), 1 (entry is absent in database),
80 | * or 2 (entry exists in database and is different).
81 | */
82 | int verify_host_key(const char *hostname, int port,
83 | const char *keytype, const char *key);
84 |
85 | /*
86 | * Write a host key into the database, overwriting any previous
87 | * entry that might have been there.
88 | */
89 | void store_host_key(const char *hostname, int port,
90 | const char *keytype, const char *key);
91 |
92 | /* ----------------------------------------------------------------------
93 | * Functions to access PuTTY's random number seed file.
94 | */
95 |
96 | typedef void (*noise_consumer_t) (void *data, int len);
97 |
98 | /*
99 | * Read PuTTY's random seed file and pass its contents to a noise
100 | * consumer function.
101 | */
102 | void read_random_seed(noise_consumer_t consumer);
103 |
104 | /*
105 | * Write PuTTY's random seed file from a given chunk of noise.
106 | */
107 | void write_random_seed(void *data, int len);
108 |
109 | /* ----------------------------------------------------------------------
110 | * Cleanup function: remove all of PuTTY's persistent state.
111 | */
112 | void cleanup_all(void);
113 |
114 | #endif
115 |
--------------------------------------------------------------------------------
/testdata/bignum.py:
--------------------------------------------------------------------------------
1 | # Generate test cases for a bignum implementation.
2 |
3 | import sys
4 |
5 | # integer square roots
6 | def sqrt(n):
7 | d = long(n)
8 | a = 0L
9 | # b must start off as a power of 4 at least as large as n
10 | ndigits = len(hex(long(n)))
11 | b = 1L << (ndigits*4)
12 | while 1:
13 | a = a >> 1
14 | di = 2*a + b
15 | if di <= d:
16 | d = d - di
17 | a = a + b
18 | b = b >> 2
19 | if b == 0: break
20 | return a
21 |
22 | # continued fraction convergents of a rational
23 | def confrac(n, d):
24 | coeffs = [(1,0),(0,1)]
25 | while d != 0:
26 | i = n / d
27 | n, d = d, n % d
28 | coeffs.append((coeffs[-2][0]-i*coeffs[-1][0],
29 | coeffs[-2][1]-i*coeffs[-1][1]))
30 | return coeffs
31 |
32 | def findprod(target, dir = +1, ratio=(1,1)):
33 | # Return two numbers whose product is as close as we can get to
34 | # 'target', with any deviation having the sign of 'dir', and in
35 | # the same approximate ratio as 'ratio'.
36 |
37 | r = sqrt(target * ratio[0] * ratio[1])
38 | a = r / ratio[1]
39 | b = r / ratio[0]
40 | if a*b * dir < target * dir:
41 | a = a + 1
42 | b = b + 1
43 | assert a*b * dir >= target * dir
44 |
45 | best = (a,b,a*b)
46 |
47 | while 1:
48 | improved = 0
49 | a, b = best[:2]
50 |
51 | coeffs = confrac(a, b)
52 | for c in coeffs:
53 | # a*c[0]+b*c[1] is as close as we can get it to zero. So
54 | # if we replace a and b with a+c[1] and b+c[0], then that
55 | # will be added to our product, along with c[0]*c[1].
56 | da, db = c[1], c[0]
57 |
58 | # Flip signs as appropriate.
59 | if (a+da) * (b+db) * dir < target * dir:
60 | da, db = -da, -db
61 |
62 | # Multiply up. We want to get as close as we can to a
63 | # solution of the quadratic equation in n
64 | #
65 | # (a + n da) (b + n db) = target
66 | # => n^2 da db + n (b da + a db) + (a b - target) = 0
67 | A,B,C = da*db, b*da+a*db, a*b-target
68 | discrim = B^2-4*A*C
69 | if discrim > 0 and A != 0:
70 | root = sqrt(discrim)
71 | vals = []
72 | vals.append((-B + root) / (2*A))
73 | vals.append((-B - root) / (2*A))
74 | if root * root != discrim:
75 | root = root + 1
76 | vals.append((-B + root) / (2*A))
77 | vals.append((-B - root) / (2*A))
78 |
79 | for n in vals:
80 | ap = a + da*n
81 | bp = b + db*n
82 | pp = ap*bp
83 | if pp * dir >= target * dir and pp * dir < best[2]*dir:
84 | best = (ap, bp, pp)
85 | improved = 1
86 |
87 | if not improved:
88 | break
89 |
90 | return best
91 |
92 | def hexstr(n):
93 | s = hex(n)
94 | if s[:2] == "0x": s = s[2:]
95 | if s[-1:] == "L": s = s[:-1]
96 | return s
97 |
98 | # Tests of multiplication which exercise the propagation of the last
99 | # carry to the very top of the number.
100 | for i in range(1,4200):
101 | a, b, p = findprod((1< */
61 | #define DIVMOD_WORD(q, r, hi, lo, w) do { \
62 | __asm mov edx, hi \
63 | __asm mov eax, lo \
64 | __asm div w \
65 | __asm mov r, edx \
66 | __asm mov q, eax \
67 | } while(0)
68 | #elif defined _LP64
69 | /* 64-bit architectures can do 32x32->64 chunks at a time */
70 | typedef unsigned int BignumInt;
71 | typedef unsigned long BignumDblInt;
72 | #define BIGNUM_INT_MASK 0xFFFFFFFFU
73 | #define BIGNUM_TOP_BIT 0x80000000U
74 | #define BIGNUM_INT_BITS 32
75 | #define MUL_WORD(w1, w2) ((BignumDblInt)w1 * w2)
76 | #define DIVMOD_WORD(q, r, hi, lo, w) do { \
77 | BignumDblInt n = (((BignumDblInt)hi) << BIGNUM_INT_BITS) | lo; \
78 | q = n / w; \
79 | r = n % w; \
80 | } while (0)
81 | #elif defined _LLP64
82 | /* 64-bit architectures in which unsigned long is 32 bits, not 64 */
83 | typedef unsigned long BignumInt;
84 | typedef unsigned long long BignumDblInt;
85 | #define BIGNUM_INT_MASK 0xFFFFFFFFUL
86 | #define BIGNUM_TOP_BIT 0x80000000UL
87 | #define BIGNUM_INT_BITS 32
88 | #define MUL_WORD(w1, w2) ((BignumDblInt)w1 * w2)
89 | #define DIVMOD_WORD(q, r, hi, lo, w) do { \
90 | BignumDblInt n = (((BignumDblInt)hi) << BIGNUM_INT_BITS) | lo; \
91 | q = n / w; \
92 | r = n % w; \
93 | } while (0)
94 | #else
95 | /* Fallback for all other cases */
96 | typedef unsigned short BignumInt;
97 | typedef unsigned long BignumDblInt;
98 | #define BIGNUM_INT_MASK 0xFFFFU
99 | #define BIGNUM_TOP_BIT 0x8000U
100 | #define BIGNUM_INT_BITS 16
101 | #define MUL_WORD(w1, w2) ((BignumDblInt)w1 * w2)
102 | #define DIVMOD_WORD(q, r, hi, lo, w) do { \
103 | BignumDblInt n = (((BignumDblInt)hi) << BIGNUM_INT_BITS) | lo; \
104 | q = n / w; \
105 | r = n % w; \
106 | } while (0)
107 | #endif
108 |
109 | #define BIGNUM_INT_BYTES (BIGNUM_INT_BITS / 8)
110 |
--------------------------------------------------------------------------------
/windows/sizetip.c:
--------------------------------------------------------------------------------
1 | /*
2 | * sizetip.c - resize tips for PuTTY(tel) terminal window.
3 | */
4 |
5 | #include
6 | #include
7 | #include
8 |
9 | #include "putty.h"
10 |
11 | static ATOM tip_class = 0;
12 |
13 | static HFONT tip_font;
14 | static COLORREF tip_bg;
15 | static COLORREF tip_text;
16 |
17 | static LRESULT CALLBACK SizeTipWndProc(HWND hWnd, UINT nMsg,
18 | WPARAM wParam, LPARAM lParam)
19 | {
20 |
21 | switch (nMsg) {
22 | case WM_ERASEBKGND:
23 | return TRUE;
24 |
25 | case WM_PAINT:
26 | {
27 | HBRUSH hbr;
28 | HGDIOBJ holdbr;
29 | RECT cr;
30 | int wtlen;
31 | LPTSTR wt;
32 | HDC hdc;
33 |
34 | PAINTSTRUCT ps;
35 | hdc = BeginPaint(hWnd, &ps);
36 |
37 | SelectObject(hdc, tip_font);
38 | SelectObject(hdc, GetStockObject(BLACK_PEN));
39 |
40 | hbr = CreateSolidBrush(tip_bg);
41 | holdbr = SelectObject(hdc, hbr);
42 |
43 | GetClientRect(hWnd, &cr);
44 | Rectangle(hdc, cr.left, cr.top, cr.right, cr.bottom);
45 |
46 | wtlen = GetWindowTextLength(hWnd);
47 | wt = (LPTSTR) snewn(wtlen + 1, TCHAR);
48 | GetWindowText(hWnd, wt, wtlen + 1);
49 |
50 | SetTextColor(hdc, tip_text);
51 | SetBkColor(hdc, tip_bg);
52 |
53 | TextOut(hdc, cr.left + 3, cr.top + 3, wt, wtlen);
54 |
55 | sfree(wt);
56 |
57 | SelectObject(hdc, holdbr);
58 | DeleteObject(hbr);
59 |
60 | EndPaint(hWnd, &ps);
61 | }
62 | return 0;
63 |
64 | case WM_NCHITTEST:
65 | return HTTRANSPARENT;
66 |
67 | case WM_DESTROY:
68 | DeleteObject(tip_font);
69 | tip_font = NULL;
70 | break;
71 |
72 | case WM_SETTEXT:
73 | {
74 | LPCTSTR str = (LPCTSTR) lParam;
75 | SIZE sz;
76 | HDC hdc = CreateCompatibleDC(NULL);
77 |
78 | SelectObject(hdc, tip_font);
79 | GetTextExtentPoint32(hdc, str, _tcslen(str), &sz);
80 |
81 | SetWindowPos(hWnd, NULL, 0, 0, sz.cx + 6, sz.cy + 6,
82 | SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
83 | InvalidateRect(hWnd, NULL, FALSE);
84 |
85 | DeleteDC(hdc);
86 | }
87 | break;
88 | }
89 |
90 | return DefWindowProc(hWnd, nMsg, wParam, lParam);
91 | }
92 |
93 | static HWND tip_wnd = NULL;
94 | static int tip_enabled = 0;
95 |
96 | void UpdateSizeTip(HWND src, int cx, int cy)
97 | {
98 | TCHAR str[32];
99 |
100 | if (!tip_enabled)
101 | return;
102 |
103 | if (!tip_wnd) {
104 | NONCLIENTMETRICS nci;
105 |
106 | /* First make sure the window class is registered */
107 |
108 | if (!tip_class) {
109 | WNDCLASS wc;
110 | wc.style = CS_HREDRAW | CS_VREDRAW;
111 | wc.lpfnWndProc = SizeTipWndProc;
112 | wc.cbClsExtra = 0;
113 | wc.cbWndExtra = 0;
114 | wc.hInstance = hinst;
115 | wc.hIcon = NULL;
116 | wc.hCursor = NULL;
117 | wc.hbrBackground = NULL;
118 | wc.lpszMenuName = NULL;
119 | wc.lpszClassName = "SizeTipClass";
120 |
121 | tip_class = RegisterClass(&wc);
122 | }
123 | #if 0
124 | /* Default values based on Windows Standard color scheme */
125 |
126 | tip_font = GetStockObject(SYSTEM_FONT);
127 | tip_bg = RGB(255, 255, 225);
128 | tip_text = RGB(0, 0, 0);
129 | #endif
130 |
131 | /* Prepare other GDI objects and drawing info */
132 |
133 | tip_bg = GetSysColor(COLOR_INFOBK);
134 | tip_text = GetSysColor(COLOR_INFOTEXT);
135 |
136 | memset(&nci, 0, sizeof(NONCLIENTMETRICS));
137 | nci.cbSize = sizeof(NONCLIENTMETRICS);
138 | SystemParametersInfo(SPI_GETNONCLIENTMETRICS,
139 | sizeof(NONCLIENTMETRICS), &nci, 0);
140 | tip_font = CreateFontIndirect(&nci.lfStatusFont);
141 | }
142 |
143 | /* Generate the tip text */
144 |
145 | sprintf(str, "%dx%d", cx, cy);
146 |
147 | if (!tip_wnd) {
148 | HDC hdc;
149 | SIZE sz;
150 | RECT wr;
151 | int ix, iy;
152 |
153 | /* calculate the tip's size */
154 |
155 | hdc = CreateCompatibleDC(NULL);
156 | GetTextExtentPoint32(hdc, str, _tcslen(str), &sz);
157 | DeleteDC(hdc);
158 |
159 | GetWindowRect(src, &wr);
160 |
161 | ix = wr.left;
162 | if (ix < 16)
163 | ix = 16;
164 |
165 | iy = wr.top - sz.cy;
166 | if (iy < 16)
167 | iy = 16;
168 |
169 | /* Create the tip window */
170 |
171 | tip_wnd =
172 | CreateWindowEx(WS_EX_TOOLWINDOW | WS_EX_TOPMOST,
173 | MAKEINTRESOURCE(tip_class), str, WS_POPUP, ix,
174 | iy, sz.cx, sz.cy, NULL, NULL, hinst, NULL);
175 |
176 | ShowWindow(tip_wnd, SW_SHOWNOACTIVATE);
177 |
178 | } else {
179 |
180 | /* Tip already exists, just set the text */
181 |
182 | SetWindowText(tip_wnd, str);
183 | }
184 | }
185 |
186 | void EnableSizeTip(int bEnable)
187 | {
188 | if (tip_wnd && !bEnable) {
189 | DestroyWindow(tip_wnd);
190 | tip_wnd = NULL;
191 | }
192 |
193 | tip_enabled = bEnable;
194 | }
195 |
--------------------------------------------------------------------------------