├── LATEST.VER ├── unix ├── configure ├── uxpeer.c ├── uxgen.c ├── ux_x11.c ├── uxsignal.c ├── uxprint.c ├── uxpterm.c ├── gtkcols.h ├── uxcfg.c ├── gtkfont.h ├── uxsel.c ├── uxnoise.c ├── uxputty.c └── uxagentc.c ├── windows ├── pscp.ico ├── pageant.ico ├── putty.ico ├── pageants.ico ├── puttycfg.ico ├── puttygen.ico ├── puttyins.ico ├── website.url ├── pscp.rc ├── psftp.rc ├── plink.rc ├── putty.rc ├── puttytel.rc ├── winnojmp.c ├── winx11.c ├── wintime.c ├── windefs.c ├── win_res.h ├── rcstuff.h ├── pageant.mft ├── puttygen.mft ├── putty.mft ├── README.txt ├── version.rc2 ├── winsecur.h ├── winproxy.c ├── winnpc.c ├── winhelp.c ├── puttygen.rc ├── pageant.rc ├── win_res.rc2 └── sizetip.c ├── doc ├── mancfg.but ├── manpages.but ├── vids.but ├── site.but ├── chm.css ├── chm.but ├── licence.but ├── blurb.but ├── Makefile ├── sshnames.but ├── man-psft.but ├── man-pscp.but └── intro.but ├── macosx ├── putty.icns ├── info.plist ├── osx.h ├── osxclass.h └── README.OSX ├── contrib ├── nice-ibeam.cur ├── cygtermd │ ├── Makefile │ ├── README │ ├── pty.h │ ├── malloc.c │ ├── telnet.h │ ├── malloc.h │ └── main.c ├── encodelib.py └── samplekex.py ├── testdata ├── lattrs.txt ├── scocols.txt ├── vt100.txt ├── utf8.txt └── bignum.py ├── be_none.c ├── noterm.c ├── puttyps.h ├── nogss.c ├── mkauto.sh ├── time.c ├── sshnogss.c ├── resource.h ├── be_ssh.c ├── pproxy.c ├── sshgssc.h ├── version.h ├── version.c ├── be_nossh.c ├── charset ├── slookup.c ├── enum.c ├── README ├── sbcs.c ├── toucs.c ├── fromucs.c ├── xenc.c ├── sbcsgen.pl ├── internal.h └── localenc.c ├── be_nos_s.c ├── notiming.c ├── noshare.c ├── ldisc.h ├── int64.h ├── noprint.c ├── README.md ├── be_all.c ├── sign.sh ├── be_all_s.c ├── icons ├── cicon.pl └── Makefile ├── nocproxy.c ├── mksrcarc.sh ├── mkunxarc.sh ├── LICENCE ├── Buildscr.cv ├── errsock.c ├── pinger.c ├── callback.c ├── puttymem.h ├── .gitignore ├── ldiscucs.c ├── ssharcf.c ├── proxy.h ├── sshrsag.c ├── int64.c ├── storage.h └── sshbn.h /LATEST.VER: -------------------------------------------------------------------------------- 1 | 0.65 2 | -------------------------------------------------------------------------------- /unix/configure: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | $(echo "$0" | sed '$s!configure$!../configure!') "$@" 4 | -------------------------------------------------------------------------------- /windows/pscp.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ns130291/putty/config-in-file/windows/pscp.ico -------------------------------------------------------------------------------- /doc/mancfg.but: -------------------------------------------------------------------------------- 1 | \cfg{man-mindepth}{2} 2 | 3 | \C{not-shown} Chapter title which is not shown 4 | -------------------------------------------------------------------------------- /macosx/putty.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ns130291/putty/config-in-file/macosx/putty.icns -------------------------------------------------------------------------------- /windows/pageant.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ns130291/putty/config-in-file/windows/pageant.ico -------------------------------------------------------------------------------- /windows/putty.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ns130291/putty/config-in-file/windows/putty.ico -------------------------------------------------------------------------------- /windows/pageants.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ns130291/putty/config-in-file/windows/pageants.ico -------------------------------------------------------------------------------- /windows/puttycfg.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ns130291/putty/config-in-file/windows/puttycfg.ico -------------------------------------------------------------------------------- /windows/puttygen.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ns130291/putty/config-in-file/windows/puttygen.ico -------------------------------------------------------------------------------- /windows/puttyins.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ns130291/putty/config-in-file/windows/puttyins.ico -------------------------------------------------------------------------------- /contrib/nice-ibeam.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ns130291/putty/config-in-file/contrib/nice-ibeam.cur -------------------------------------------------------------------------------- /doc/manpages.but: -------------------------------------------------------------------------------- 1 | \A{man-pages} Man pages for Unix PuTTY 2 | 3 | This appendix contains all the man pages for Unix PuTTY. 4 | -------------------------------------------------------------------------------- /windows/website.url: -------------------------------------------------------------------------------- 1 | [InternetShortcut] 2 | URL=http://www.chiark.greenend.org.uk/~sgtatham/putty/ 3 | -------------------------------------------------------------------------------- /contrib/cygtermd/Makefile: -------------------------------------------------------------------------------- 1 | cygtermd.exe: main.c sel.c telnet.c pty.c malloc.c 2 | gcc -o cygtermd.exe main.c sel.c telnet.c pty.c malloc.c 3 | -------------------------------------------------------------------------------- /doc/vids.but: -------------------------------------------------------------------------------- 1 | \# Fallback versionid for use when the build system hasn't provided a 2 | better one. 3 | 4 | \versionid no version information available 5 | -------------------------------------------------------------------------------- /testdata/lattrs.txt: -------------------------------------------------------------------------------- 1 | Test of line attributes: 2 | 3 | #3Double-height top 4 | #4Double-height bottom 5 | #5Normal text (#5) 6 | #6Double-width only 7 | -------------------------------------------------------------------------------- /windows/pscp.rc: -------------------------------------------------------------------------------- 1 | #include "rcstuff.h" 2 | 3 | #define APPNAME "PSCP" 4 | #define APPDESC "Command-line SCP/SFTP client" 5 | 6 | 200 ICON "pscp.ico" 7 | 8 | #include "version.rc2" 9 | -------------------------------------------------------------------------------- /windows/psftp.rc: -------------------------------------------------------------------------------- 1 | #include "rcstuff.h" 2 | 3 | #define APPNAME "PSFTP" 4 | #define APPDESC "Command-line interactive SFTP client" 5 | 6 | 200 ICON "pscp.ico" 7 | 8 | #include "version.rc2" 9 | -------------------------------------------------------------------------------- /windows/plink.rc: -------------------------------------------------------------------------------- 1 | #include "rcstuff.h" 2 | 3 | #define APPNAME "Plink" 4 | #define APPDESC "Command-line SSH, Telnet, and Rlogin client" 5 | 6 | 200 ICON "putty.ico" 7 | 8 | #include "version.rc2" 9 | -------------------------------------------------------------------------------- /doc/site.but: -------------------------------------------------------------------------------- 1 | \# Additional configuration for the version of the PuTTY docs 2 | \# actually published as HTML on the website. 3 | 4 | \cfg{xhtml-head-end}{} 5 | -------------------------------------------------------------------------------- /be_none.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Linking module for programs that do not support selection of backend 3 | * (such as pterm). 4 | */ 5 | 6 | #include 7 | #include "putty.h" 8 | 9 | Backend *backends[] = { 10 | NULL 11 | }; 12 | -------------------------------------------------------------------------------- /noterm.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Stubs of functions in terminal.c, for use in programs that don't 3 | * have a terminal. 4 | */ 5 | 6 | #include "putty.h" 7 | #include "terminal.h" 8 | 9 | void term_nopaste(Terminal *term) 10 | { 11 | } 12 | -------------------------------------------------------------------------------- /windows/putty.rc: -------------------------------------------------------------------------------- 1 | #include "rcstuff.h" 2 | 3 | #define APPNAME "PuTTY" 4 | #define APPDESC "SSH, Telnet and Rlogin client" 5 | 6 | #include "win_res.rc2" 7 | 8 | #ifndef NO_MANIFESTS 9 | 1 RT_MANIFEST "putty.mft" 10 | #endif /* NO_MANIFESTS */ 11 | -------------------------------------------------------------------------------- /windows/puttytel.rc: -------------------------------------------------------------------------------- 1 | #include "rcstuff.h" 2 | 3 | #define APPNAME "PuTTYtel" 4 | #define APPDESC "Telnet and Rlogin client" 5 | 6 | #include "win_res.rc2" 7 | 8 | #ifndef NO_MANIFESTS 9 | /* FIXME */ 10 | 1 RT_MANIFEST "putty.mft" 11 | #endif /* NO_MANIFESTS */ 12 | -------------------------------------------------------------------------------- /doc/chm.css: -------------------------------------------------------------------------------- 1 | /* Stylesheet for a Windows .CHM help file */ 2 | 3 | body { font-size: 75%; font-family: Verdana, Arial, Helvetica, Sans-Serif; } 4 | 5 | h1 { font-weight: bold; font-size: 150%; } 6 | h2 { font-weight: bold; font-size: 130%; } 7 | h3 { font-weight: bold; font-size: 120%; } 8 | -------------------------------------------------------------------------------- /macosx/info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleIconFile 6 | PuTTY.icns 7 | 8 | 9 | -------------------------------------------------------------------------------- /windows/winnojmp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * winnojmp.c: stub jump list functions for Windows executables that 3 | * don't update the jump list. 4 | */ 5 | 6 | void add_session_to_jumplist(const char * const sessionname) {} 7 | void remove_session_from_jumplist(const char * const sessionname) {} 8 | void clear_jumplist(void) {} 9 | -------------------------------------------------------------------------------- /puttyps.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Find the platform-specific header for this platform. 3 | */ 4 | 5 | #ifndef PUTTY_PUTTYPS_H 6 | #define PUTTY_PUTTYPS_H 7 | 8 | #ifdef _WINDOWS 9 | 10 | #include "winstuff.h" 11 | 12 | #elif defined(MACOSX) 13 | 14 | #include "osx.h" 15 | 16 | #else 17 | 18 | #include "unix.h" 19 | 20 | #endif 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /nogss.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Stub definitions of the GSSAPI library list, for Unix pterm and 3 | * any other application that needs the symbols defined but has no 4 | * use for them. 5 | */ 6 | 7 | #include "putty.h" 8 | 9 | const int ngsslibs = 0; 10 | const char *const gsslibnames[1] = { "dummy" }; 11 | const struct keyvalwhere gsslibkeywords[1] = { { "dummy", 0, -1, -1 } }; 12 | -------------------------------------------------------------------------------- /mkauto.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # This script makes the autoconf mechanism for the Unix port work. 3 | # It's separate from mkfiles.pl because it won't work (and isn't needed) 4 | # on a non-Unix system. 5 | 6 | # It's nice to be able to run this from inside the unix subdir as 7 | # well as from outside. 8 | test -f unix.h && cd .. 9 | 10 | # Run autoconf on our real configure.in. 11 | autoreconf -i && rm -rf autom4te.cache 12 | -------------------------------------------------------------------------------- /time.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Portable implementation of ltime() for any ISO-C platform where 3 | * time_t behaves. (In practice, we've found that platforms such as 4 | * Windows and Mac have needed their own specialised implementations.) 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | struct tm ltime(void) 11 | { 12 | time_t t; 13 | time(&t); 14 | assert (t != ((time_t)-1)); 15 | return *localtime(&t); 16 | } 17 | -------------------------------------------------------------------------------- /sshnogss.c: -------------------------------------------------------------------------------- 1 | #include "putty.h" 2 | #ifndef NO_GSSAPI 3 | 4 | /* For platforms not supporting GSSAPI */ 5 | 6 | struct ssh_gss_liblist *ssh_gss_setup(Conf *conf) 7 | { 8 | struct ssh_gss_liblist *list = snew(struct ssh_gss_liblist *); 9 | list->libraries = NULL; 10 | list->nlibraries = 0; 11 | return list; 12 | } 13 | 14 | void ssh_gss_cleanup(struct ssh_gss_liblist *list) 15 | { 16 | sfree(list); 17 | } 18 | 19 | #endif /* NO_GSSAPI */ 20 | -------------------------------------------------------------------------------- /resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Developer Studio generated include file. 3 | // Used by win_res.rc 4 | // 5 | 6 | // Next default values for new objects 7 | // 8 | #ifdef APSTUDIO_INVOKED 9 | #ifndef APSTUDIO_READONLY_SYMBOLS 10 | #define _APS_NEXT_RESOURCE_VALUE 101 11 | #define _APS_NEXT_COMMAND_VALUE 40001 12 | #define _APS_NEXT_CONTROL_VALUE 1000 13 | #define _APS_NEXT_SYMED_VALUE 101 14 | #endif 15 | #endif 16 | -------------------------------------------------------------------------------- /be_ssh.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Linking module for programs that are restricted to only using SSH 3 | * (pscp and psftp). These do not support selection of backend, but 4 | * must still have a backends[] array mentioning SSH because 5 | * settings.c will want to consult it during session load. 6 | */ 7 | 8 | #include 9 | #include "putty.h" 10 | 11 | const int be_default_protocol = PROT_SSH; 12 | 13 | Backend *backends[] = { 14 | &ssh_backend, 15 | NULL 16 | }; 17 | -------------------------------------------------------------------------------- /testdata/scocols.txt: -------------------------------------------------------------------------------- 1 | Test of (destructive) SCO colour rendering. 2 | SCO fg: [=0F0[=7F [=1F1[=7F [=2F2[=7F [=3F3[=7F [=4F4[=7F [=5F5[=7F [=6F6[=7F [=7F7[=7F [=8F8[=7F [=9F9[=7F [=10F10[=7F [=11F11[=7F [=12F12[=7F [=13F13[=7F [=14F14[=7F [=15F15[=7F 3 | SCO bg: [=0G0[=0G [=1G1[=0G [=2G2[=0G [=3G3[=0G [=4G4[=0G [=5G5[=0G [=6G6[=0G [=7G7[=0G [=8G8[=0G [=9G9[=0G [=10G10[=0G [=11G11[=0G [=12G12[=0G [=13G13[=0G [=14G14[=0G [=15G15[=0G 4 | -------------------------------------------------------------------------------- /pproxy.c: -------------------------------------------------------------------------------- 1 | /* 2 | * pproxy.c: dummy implementation of platform_new_connection(), to 3 | * be supplanted on any platform which has its own local proxy 4 | * method. 5 | */ 6 | 7 | #include "putty.h" 8 | #include "network.h" 9 | #include "proxy.h" 10 | 11 | Socket platform_new_connection(SockAddr addr, char *hostname, 12 | int port, int privport, 13 | int oobinline, int nodelay, int keepalive, 14 | Plug plug, Conf *conf) 15 | { 16 | return NULL; 17 | } 18 | -------------------------------------------------------------------------------- /sshgssc.h: -------------------------------------------------------------------------------- 1 | #ifndef PUTTY_SSHGSSC_H 2 | #define PUTTY_SSHGSSC_H 3 | #include "putty.h" 4 | #ifndef NO_GSSAPI 5 | 6 | #include "pgssapi.h" 7 | #include "sshgss.h" 8 | 9 | typedef struct gssapi_ssh_gss_ctx { 10 | OM_uint32 maj_stat; 11 | OM_uint32 min_stat; 12 | gss_ctx_id_t ctx; 13 | } gssapi_ssh_gss_ctx; 14 | 15 | void ssh_gssapi_bind_fns(struct ssh_gss_library *lib); 16 | 17 | #else 18 | 19 | int ssh_gssapi_init(void); 20 | 21 | #endif /*NO_GSSAPI*/ 22 | 23 | #endif /*PUTTY_SSHGSSC_H*/ 24 | -------------------------------------------------------------------------------- /windows/winx11.c: -------------------------------------------------------------------------------- 1 | /* 2 | * winx11.c: fetch local auth data for X forwarding. 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "putty.h" 10 | #include "ssh.h" 11 | 12 | void platform_get_x11_auth(struct X11Display *disp, Conf *conf) 13 | { 14 | char *xauthpath = conf_get_filename(conf, CONF_xauthfile)->path; 15 | if (xauthpath[0]) 16 | x11_get_auth_from_authfile(disp, xauthpath); 17 | } 18 | 19 | const int platform_uses_x11_unix_by_default = FALSE; 20 | -------------------------------------------------------------------------------- /version.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This header file provides the various versioning-related #defines 3 | * for a particular PuTTY build. 4 | * 5 | * When my automated build system does a full build, Buildscr 6 | * completely overwrites this file with information derived from the 7 | * circumstances and type of that build. The information _here_ is 8 | * default stuff used for local development runs of 'make'. 9 | */ 10 | 11 | #define TEXTVER "Unidentified build" 12 | #define SSHVER "PuTTY-Unidentified-Local-Build" 13 | #define BINARY_VERSION 0,0,0,0 14 | -------------------------------------------------------------------------------- /version.c: -------------------------------------------------------------------------------- 1 | /* 2 | * PuTTY version numbering 3 | */ 4 | 5 | /* 6 | * The difficult part of deciding what goes in these version strings 7 | * is done in Buildscr, and then written into version.h. All we have 8 | * to do here is to drop it into variables of the right names. 9 | */ 10 | 11 | #include "version.h" 12 | 13 | char ver[] = TEXTVER; 14 | char sshver[] = SSHVER; 15 | 16 | /* 17 | * SSH local version string MUST be under 40 characters. Here's a 18 | * compile time assertion to verify this. 19 | */ 20 | enum { vorpal_sword = 1 / (sizeof(sshver) <= 40) }; 21 | -------------------------------------------------------------------------------- /contrib/cygtermd/README: -------------------------------------------------------------------------------- 1 | This directory contains 'cygtermd', a small and specialist Telnet 2 | server designed to act as middleware between PuTTY and a Cygwin shell 3 | session running on the same machine, so that PuTTY can act as an 4 | xterm-alike for Cygwin. 5 | 6 | To install it, you must compile it from source using Cygwin gcc, 7 | install it in Cygwin's /bin, and configure PuTTY to use it as a local 8 | proxy process. For detailed instructions, see the PuTTY Wishlist page 9 | at 10 | 11 | http://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/cygwin-terminal-window.html 12 | -------------------------------------------------------------------------------- /be_nossh.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Linking module for PuTTYtel: list the available backends not 3 | * including ssh. 4 | */ 5 | 6 | #include 7 | #include "putty.h" 8 | 9 | const int be_default_protocol = PROT_TELNET; 10 | 11 | const char *const appname = "PuTTYtel"; 12 | 13 | Backend *backends[] = { 14 | &telnet_backend, 15 | &rlogin_backend, 16 | &raw_backend, 17 | NULL 18 | }; 19 | 20 | /* 21 | * Stub implementations of functions not used in non-ssh versions. 22 | */ 23 | void random_save_seed(void) 24 | { 25 | } 26 | 27 | void random_destroy_seed(void) 28 | { 29 | } 30 | 31 | void noise_ultralight(unsigned long data) 32 | { 33 | } 34 | -------------------------------------------------------------------------------- /windows/wintime.c: -------------------------------------------------------------------------------- 1 | /* 2 | * wintime.c - Avoid trouble with time() returning (time_t)-1 on Windows. 3 | */ 4 | 5 | #include "putty.h" 6 | #include 7 | 8 | struct tm ltime(void) 9 | { 10 | SYSTEMTIME st; 11 | struct tm tm; 12 | 13 | GetLocalTime(&st); 14 | tm.tm_sec=st.wSecond; 15 | tm.tm_min=st.wMinute; 16 | tm.tm_hour=st.wHour; 17 | tm.tm_mday=st.wDay; 18 | tm.tm_mon=st.wMonth-1; 19 | tm.tm_year=(st.wYear>=1900?st.wYear-1900:0); 20 | tm.tm_wday=st.wDayOfWeek; 21 | tm.tm_yday=-1; /* GetLocalTime doesn't tell us */ 22 | tm.tm_isdst=0; /* GetLocalTime doesn't tell us */ 23 | return tm; 24 | } 25 | -------------------------------------------------------------------------------- /charset/slookup.c: -------------------------------------------------------------------------------- 1 | /* 2 | * slookup.c - static lookup of character sets. 3 | */ 4 | 5 | #include "charset.h" 6 | #include "internal.h" 7 | 8 | #define ENUM_CHARSET(x) extern charset_spec const charset_##x; 9 | #include "enum.c" 10 | #undef ENUM_CHARSET 11 | 12 | static charset_spec const *const cs_table[] = { 13 | 14 | #define ENUM_CHARSET(x) &charset_##x, 15 | #include "enum.c" 16 | #undef ENUM_CHARSET 17 | 18 | }; 19 | 20 | charset_spec const *charset_find_spec(int charset) 21 | { 22 | int i; 23 | 24 | for (i = 0; i < (int)lenof(cs_table); i++) 25 | if (cs_table[i]->charset == charset) 26 | return cs_table[i]; 27 | 28 | return NULL; 29 | } 30 | -------------------------------------------------------------------------------- /be_nos_s.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Linking module for PuTTYtel: list the available backends not 3 | * including ssh. 4 | */ 5 | 6 | #include 7 | #include "putty.h" 8 | 9 | const int be_default_protocol = PROT_TELNET; 10 | 11 | const char *const appname = "PuTTYtel"; 12 | 13 | Backend *backends[] = { 14 | &telnet_backend, 15 | &rlogin_backend, 16 | &raw_backend, 17 | &serial_backend, 18 | NULL 19 | }; 20 | 21 | /* 22 | * Stub implementations of functions not used in non-ssh versions. 23 | */ 24 | void random_save_seed(void) 25 | { 26 | } 27 | 28 | void random_destroy_seed(void) 29 | { 30 | } 31 | 32 | void noise_ultralight(unsigned long data) 33 | { 34 | } 35 | -------------------------------------------------------------------------------- /notiming.c: -------------------------------------------------------------------------------- 1 | /* 2 | * notiming.c: stub version of timing API. 3 | * 4 | * Used in any tool which needs a subsystem linked against the 5 | * timing API but doesn't want to actually provide timing. For 6 | * example, key generation tools need the random number generator, 7 | * but they don't want the hassle of calling noise_regular() at 8 | * regular intervals - and they don't _need_ it either, since they 9 | * have their own rigorous and different means of noise collection. 10 | */ 11 | 12 | #include "putty.h" 13 | 14 | unsigned long schedule_timer(int ticks, timer_fn_t fn, void *ctx) 15 | { 16 | return 0; 17 | } 18 | 19 | void expire_timer_context(void *ctx) 20 | { 21 | } 22 | -------------------------------------------------------------------------------- /noshare.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Stub implementation of SSH connection-sharing IPC, for any 3 | * platform which can't support it at all. 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include "tree234.h" 11 | #include "putty.h" 12 | #include "ssh.h" 13 | #include "network.h" 14 | 15 | int platform_ssh_share(const char *name, Conf *conf, 16 | Plug downplug, Plug upplug, Socket *sock, 17 | char **logtext, char **ds_err, char **us_err, 18 | int can_upstream, int can_downstream) 19 | { 20 | return SHARE_NONE; 21 | } 22 | 23 | void platform_ssh_share_cleanup(const char *name) 24 | { 25 | } 26 | -------------------------------------------------------------------------------- /ldisc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ldisc.h: defines the Ldisc data structure used by ldisc.c and 3 | * ldiscucs.c. (Unfortunately it was necessary to split the ldisc 4 | * module in two, to avoid unnecessarily linking in the Unicode 5 | * stuff in tools that don't require it.) 6 | */ 7 | 8 | #ifndef PUTTY_LDISC_H 9 | #define PUTTY_LDISC_H 10 | 11 | typedef struct ldisc_tag { 12 | Terminal *term; 13 | Backend *back; 14 | void *backhandle; 15 | void *frontend; 16 | 17 | /* 18 | * Values cached out of conf. 19 | */ 20 | int telnet_keyboard, telnet_newline, protocol, localecho, localedit; 21 | 22 | char *buf; 23 | int buflen, bufsiz, quotenext; 24 | } *Ldisc; 25 | 26 | #endif /* PUTTY_LDISC_H */ 27 | -------------------------------------------------------------------------------- /int64.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Header for int64.c. 3 | */ 4 | 5 | #ifndef PUTTY_INT64_H 6 | #define PUTTY_INT64_H 7 | 8 | typedef struct { 9 | unsigned long hi, lo; 10 | } uint64; 11 | 12 | uint64 uint64_div10(uint64 x, int *remainder); 13 | void uint64_decimal(uint64 x, char *buffer); 14 | uint64 uint64_make(unsigned long hi, unsigned long lo); 15 | uint64 uint64_add(uint64 x, uint64 y); 16 | uint64 uint64_add32(uint64 x, unsigned long y); 17 | int uint64_compare(uint64 x, uint64 y); 18 | uint64 uint64_subtract(uint64 x, uint64 y); 19 | double uint64_to_double(uint64 x); 20 | uint64 uint64_shift_right(uint64 x, int shift); 21 | uint64 uint64_shift_left(uint64 x, int shift); 22 | uint64 uint64_from_decimal(char *str); 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /contrib/cygtermd/pty.h: -------------------------------------------------------------------------------- 1 | /* 2 | * pty.h - FIXME 3 | */ 4 | 5 | #ifndef FIXME_PTY_H 6 | #define FIXME_PTY_H 7 | 8 | #include "telnet.h" /* for struct shdata */ 9 | 10 | /* 11 | * Called at program startup to actually allocate a pty, so that 12 | * we can start passing in resize events as soon as they arrive. 13 | */ 14 | void pty_preinit(void); 15 | 16 | /* 17 | * Set the terminal size for the pty. 18 | */ 19 | void pty_resize(int w, int h); 20 | 21 | /* 22 | * Start a program in a subprocess running in the pty we allocated. 23 | * Returns the fd of the pty master. 24 | */ 25 | int run_program_in_pty(const struct shell_data *shdata, 26 | char *directory, char **program_args); 27 | 28 | #endif /* FIXME_PTY_H */ 29 | -------------------------------------------------------------------------------- /charset/enum.c: -------------------------------------------------------------------------------- 1 | /* 2 | * enum.c - enumerate all charsets defined by the library. 3 | * 4 | * This file maintains a list of every other source file which 5 | * contains ENUM_CHARSET definitions. It #includes each one with 6 | * ENUM_CHARSETS defined, which causes those source files to do 7 | * nothing at all except call the ENUM_CHARSET macro on each 8 | * charset they define. 9 | * 10 | * This file in turn is included from various other places, with 11 | * the ENUM_CHARSET macro defined to various different things. This 12 | * allows us to have multiple implementations of the master charset 13 | * lookup table (a static one and a dynamic one). 14 | */ 15 | 16 | #define ENUM_CHARSETS 17 | #include "sbcsdat.c" 18 | #include "utf8.c" 19 | #undef ENUM_CHARSETS 20 | -------------------------------------------------------------------------------- /testdata/vt100.txt: -------------------------------------------------------------------------------- 1 | VT100 line drawing characters, actually using the VT100 escapes 2 | (B)0ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo 3 | 4 | lqqqqqqqqqqpoopqrssrqqqqqqqqqqwqqqqqqqqqqpoopqrssrqqqqqqqqqqk 5 | x x x 6 | x ooh, swirly! x top right corner x 7 | x x x 8 | tqqqqqqqqqqpoopqrssrqqqqqqqqqqnqqqqqqqqqqpoopqrssrqqqqqqqqqqu 9 | x x x 10 | x stuff down here x is quite inane x 11 | x x x 12 | mqqqqqqqqqqpoopqrssrqqqqqqqqqqvqqqqqqqqqqpoopqrssrqqqqqqqqqqj 13 | -------------------------------------------------------------------------------- /noprint.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Stub implementation of the printing interface for PuTTY, for the 3 | * benefit of non-printing terminal applications. 4 | */ 5 | 6 | #include 7 | #include 8 | #include "putty.h" 9 | 10 | struct printer_job_tag { 11 | int dummy; 12 | }; 13 | 14 | printer_job *printer_start_job(char *printer) 15 | { 16 | return NULL; 17 | } 18 | 19 | void printer_job_data(printer_job *pj, void *data, int len) 20 | { 21 | } 22 | 23 | void printer_finish_job(printer_job *pj) 24 | { 25 | } 26 | 27 | printer_enum *printer_start_enum(int *nprinters_ptr) 28 | { 29 | *nprinters_ptr = 0; 30 | return NULL; 31 | } 32 | char *printer_get_name(printer_enum *pe, int i) 33 | { 34 | return NULL; 35 | } 36 | void printer_finish_enum(printer_enum *pe) 37 | { 38 | } 39 | -------------------------------------------------------------------------------- /doc/chm.but: -------------------------------------------------------------------------------- 1 | \# File containing the magic HTML configuration directives to create 2 | \# an MS HTML Help project. We put this on the end of the PuTTY 3 | \# docs build command line to build the HHP and friends. 4 | 5 | \cfg{html-leaf-level}{infinite} 6 | \cfg{html-leaf-contains-contents}{false} 7 | \cfg{html-suppress-navlinks}{true} 8 | \cfg{html-suppress-address}{true} 9 | 10 | \cfg{html-contents-filename}{index.html} 11 | \cfg{html-template-filename}{%k.html} 12 | \cfg{html-template-fragment}{%k} 13 | 14 | \cfg{html-mshtmlhelp-chm}{putty.chm} 15 | \cfg{html-mshtmlhelp-project}{putty.hhp} 16 | \cfg{html-mshtmlhelp-contents}{putty.hhc} 17 | \cfg{html-mshtmlhelp-index}{putty.hhk} 18 | 19 | \cfg{html-body-end}{} 20 | 21 | \cfg{html-head-end}{} 22 | 23 | -------------------------------------------------------------------------------- /unix/uxpeer.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Unix: wrapper for getsockopt(SO_PEERCRED), conditionalised on 3 | * appropriate autoconfery. 4 | */ 5 | 6 | #ifdef HAVE_CONFIG_H 7 | # include "uxconfig.h" /* leading space prevents mkfiles.pl trying to follow */ 8 | #endif 9 | 10 | #ifdef HAVE_SO_PEERCRED 11 | #define _GNU_SOURCE 12 | #include 13 | #endif 14 | 15 | #include 16 | 17 | #include "putty.h" 18 | 19 | int so_peercred(int fd, int *pid, int *uid, int *gid) 20 | { 21 | #ifdef HAVE_SO_PEERCRED 22 | struct ucred cr; 23 | socklen_t crlen = sizeof(cr); 24 | if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cr, &crlen) == 0) { 25 | *pid = cr.pid; 26 | *uid = cr.uid; 27 | *gid = cr.gid; 28 | return TRUE; 29 | } 30 | #endif 31 | return FALSE; 32 | } 33 | -------------------------------------------------------------------------------- /charset/README: -------------------------------------------------------------------------------- 1 | This subdirectory contains a general character-set conversion 2 | library, used in the Unix port of PuTTY, and available for use in 3 | other ports if it should happen to be useful. 4 | 5 | This is a variant of a library that's currently used in some other 6 | programs such as Timber and Halibut. At some future date, we would 7 | like to merge the two libraries, so that all programs use the same 8 | libcharset. 9 | 10 | It is therefore a _strong_ design goal that this library should remain 11 | perfectly general, and not tied to particulars of PuTTY. It must not 12 | reference any code outside its own subdirectory; it should not have 13 | PuTTY-specific helper routines added to it unless they can be 14 | documented in a general manner which might make them useful in other 15 | circumstances as well. 16 | -------------------------------------------------------------------------------- /contrib/cygtermd/malloc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * malloc.c: implementation of malloc.h 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | #include "malloc.h" 9 | 10 | extern void fatal(const char *, ...); 11 | 12 | void *smalloc(size_t size) { 13 | void *p; 14 | p = malloc(size); 15 | if (!p) { 16 | fatal("out of memory"); 17 | } 18 | return p; 19 | } 20 | 21 | void sfree(void *p) { 22 | if (p) { 23 | free(p); 24 | } 25 | } 26 | 27 | void *srealloc(void *p, size_t size) { 28 | void *q; 29 | if (p) { 30 | q = realloc(p, size); 31 | } else { 32 | q = malloc(size); 33 | } 34 | if (!q) 35 | fatal("out of memory"); 36 | return q; 37 | } 38 | 39 | char *dupstr(const char *s) { 40 | char *r = smalloc(1+strlen(s)); 41 | strcpy(r,s); 42 | return r; 43 | } 44 | -------------------------------------------------------------------------------- /unix/uxgen.c: -------------------------------------------------------------------------------- 1 | /* 2 | * uxgen.c: Unix implementation of get_heavy_noise() from cmdgen.c. 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "putty.h" 10 | 11 | char *get_random_data(int len) 12 | { 13 | char *buf = snewn(len, char); 14 | int fd; 15 | int ngot, ret; 16 | 17 | fd = open("/dev/random", O_RDONLY); 18 | if (fd < 0) { 19 | sfree(buf); 20 | perror("puttygen: unable to open /dev/random"); 21 | return NULL; 22 | } 23 | 24 | ngot = 0; 25 | while (ngot < len) { 26 | ret = read(fd, buf+ngot, len-ngot); 27 | if (ret < 0) { 28 | close(fd); 29 | sfree(buf); 30 | perror("puttygen: unable to read /dev/random"); 31 | return NULL; 32 | } 33 | ngot += ret; 34 | } 35 | 36 | close(fd); 37 | 38 | return buf; 39 | } 40 | -------------------------------------------------------------------------------- /windows/windefs.c: -------------------------------------------------------------------------------- 1 | /* 2 | * windefs.c: default settings that are specific to Windows. 3 | */ 4 | 5 | #include "putty.h" 6 | 7 | #include 8 | 9 | FontSpec *platform_default_fontspec(const char *name) 10 | { 11 | if (!strcmp(name, "Font")) 12 | return fontspec_new("Courier New", 0, 10, ANSI_CHARSET); 13 | else 14 | return fontspec_new("", 0, 0, 0); 15 | } 16 | 17 | Filename *platform_default_filename(const char *name) 18 | { 19 | if (!strcmp(name, "LogFileName")) 20 | return filename_from_str("putty.log"); 21 | else 22 | return filename_from_str(""); 23 | } 24 | 25 | char *platform_default_s(const char *name) 26 | { 27 | if (!strcmp(name, "SerialLine")) 28 | return dupstr("COM1"); 29 | return NULL; 30 | } 31 | 32 | int platform_default_i(const char *name, int def) 33 | { 34 | return def; 35 | } 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PuTTY for win32 storing configuration into file 2 | Original patch and documentation can be found at http://jakub.kotrla.net/putty/ 3 | 4 | ## Build with Windows 5 | For building with Windows you need to have following tools installed: 6 | - `Perl` 7 | - `mingw32` 8 | - maybe `msys` 9 | 10 | Build 11 | ``` 12 | perl mkfiles.pl 13 | cd windows 14 | ``` 15 | 16 | mingw32 17 | 18 | mingw32-make XFLAGS=-DCOVERITY -f Makefile.cyg putty.exe 19 | 20 | msys 21 | 22 | make XFLAGS=-DCOVERITY -f Makefile.cyg putty.exe 23 | 24 | ## Build with Linux 25 | For building with Linux you need to have following tools installed: 26 | - `Perl` 27 | - `mingw32` 28 | 29 | e.g. for Debian based distributions 30 | 31 | apt-get install perl mingw32 32 | 33 | Build 34 | 35 | perl mkfiles.pl 36 | cd windows 37 | make TOOLPATH=i586-mingw32msvc- -f Makefile.cyg putty.exe 38 | 39 | -------------------------------------------------------------------------------- /windows/win_res.h: -------------------------------------------------------------------------------- 1 | /* 2 | * win_res.h - constants shared between win_res.rc2 and the C code. 3 | */ 4 | 5 | #ifndef PUTTY_WIN_RES_H 6 | #define PUTTY_WIN_RES_H 7 | 8 | #define IDI_MAINICON 200 9 | #define IDI_CFGICON 201 10 | 11 | #define IDD_MAINBOX 102 12 | #define IDD_LOGBOX 110 13 | #define IDD_ABOUTBOX 111 14 | #define IDD_RECONF 112 15 | #define IDD_LICENCEBOX 113 16 | 17 | #define IDN_LIST 1001 18 | #define IDN_COPY 1002 19 | 20 | #define IDA_ICON 1001 21 | #define IDA_TEXT1 1002 22 | #define IDA_VERSION 1003 23 | #define IDA_TEXT2 1004 24 | #define IDA_LICENCE 1005 25 | #define IDA_WEB 1006 26 | 27 | #define IDC_TAB 1001 28 | #define IDC_TABSTATIC1 1002 29 | #define IDC_TABSTATIC2 1003 30 | #define IDC_TABLIST 1004 31 | #define IDC_HELPBTN 1005 32 | #define IDC_ABOUT 1006 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /be_all.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Linking module for PuTTY proper: list the available backends 3 | * including ssh. 4 | */ 5 | 6 | #include 7 | #include "putty.h" 8 | 9 | /* 10 | * This appname is not strictly in the right place, since Plink 11 | * also uses this module. However, Plink doesn't currently use any 12 | * of the dialog-box sorts of things that make use of appname, so 13 | * it shouldn't do any harm here. I'm trying to avoid having to 14 | * have tiny little source modules containing nothing but 15 | * declarations of appname, for as long as I can... 16 | */ 17 | const char *const appname = "PuTTY"; 18 | 19 | #ifdef TELNET_DEFAULT 20 | const int be_default_protocol = PROT_TELNET; 21 | #else 22 | const int be_default_protocol = PROT_SSH; 23 | #endif 24 | 25 | Backend *backends[] = { 26 | &ssh_backend, 27 | &telnet_backend, 28 | &rlogin_backend, 29 | &raw_backend, 30 | NULL 31 | }; 32 | -------------------------------------------------------------------------------- /unix/ux_x11.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ux_x11.c: fetch local auth data for X forwarding. 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "putty.h" 12 | #include "ssh.h" 13 | #include "network.h" 14 | 15 | void platform_get_x11_auth(struct X11Display *disp, Conf *conf) 16 | { 17 | char *xauthfile; 18 | int needs_free; 19 | 20 | /* 21 | * Find the .Xauthority file. 22 | */ 23 | needs_free = FALSE; 24 | xauthfile = getenv("XAUTHORITY"); 25 | if (!xauthfile) { 26 | xauthfile = getenv("HOME"); 27 | if (xauthfile) { 28 | xauthfile = dupcat(xauthfile, "/.Xauthority", NULL); 29 | needs_free = TRUE; 30 | } 31 | } 32 | 33 | if (xauthfile) { 34 | x11_get_auth_from_authfile(disp, xauthfile); 35 | if (needs_free) 36 | sfree(xauthfile); 37 | } 38 | } 39 | 40 | const int platform_uses_x11_unix_by_default = TRUE; 41 | -------------------------------------------------------------------------------- /sign.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Generate GPG signatures on a PuTTY release/snapshot directory as 4 | # delivered by Buildscr. 5 | 6 | # Usage: sh sign.sh 7 | # e.g. sh sign.sh putty Snapshots (probably in the build.out directory) 8 | # or sh sign.sh 0.60 Releases 9 | 10 | set -e 11 | 12 | sign() { 13 | # Check for the prior existence of the signature, so we can 14 | # re-run this script if it encounters an error part way 15 | # through. 16 | echo "----- Signing $2 with '$keyname'" 17 | test -f "$3" || \ 18 | gpg --load-extension=idea "$1" -u "$keyname" -o "$3" "$2" 19 | } 20 | 21 | cd "$1" 22 | for t in DSA RSA; do 23 | keyname="$2 ($t)" 24 | echo "===== Signing with '$keyname'" 25 | for i in putty*src.zip putty*.tar.gz x86/*.exe x86/*.zip; do 26 | sign --detach-sign "$i" "$i.$t" 27 | done 28 | for i in md5sums sha1sums sha256sums sha512sums; do 29 | sign --clearsign $i ${i}.$t 30 | done 31 | done 32 | -------------------------------------------------------------------------------- /be_all_s.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Linking module for PuTTY proper: list the available backends 3 | * including ssh, plus the serial backend. 4 | */ 5 | 6 | #include 7 | #include "putty.h" 8 | 9 | /* 10 | * This appname is not strictly in the right place, since Plink 11 | * also uses this module. However, Plink doesn't currently use any 12 | * of the dialog-box sorts of things that make use of appname, so 13 | * it shouldn't do any harm here. I'm trying to avoid having to 14 | * have tiny little source modules containing nothing but 15 | * declarations of appname, for as long as I can... 16 | */ 17 | const char *const appname = "PuTTY"; 18 | 19 | #ifdef TELNET_DEFAULT 20 | const int be_default_protocol = PROT_TELNET; 21 | #else 22 | const int be_default_protocol = PROT_SSH; 23 | #endif 24 | 25 | Backend *backends[] = { 26 | &ssh_backend, 27 | &telnet_backend, 28 | &rlogin_backend, 29 | &raw_backend, 30 | &serial_backend, 31 | NULL 32 | }; 33 | -------------------------------------------------------------------------------- /icons/cicon.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # Given a list of input PNGs, create a C source file containing a 4 | # const array of XPMs, named by a given C identifier. 5 | 6 | $id = shift @ARGV; 7 | $k = 0; 8 | @xpms = (); 9 | foreach $f (@ARGV) { 10 | # XPM format is generated directly by ImageMagick, so that's easy 11 | # enough. We just have to adjust the declaration line so that it 12 | # has the right name, linkage and storage class. 13 | @lines = (); 14 | open XPM, "convert $f xpm:- |"; 15 | push @lines, $_ while ; 16 | close XPM; 17 | die "XPM from $f in unexpected format\n" unless $lines[1] =~ /^static.*\{$/; 18 | $lines[1] = "static const char *const ${id}_$k"."[] = {\n"; 19 | $k++; 20 | push @xpms, @lines, "\n"; 21 | } 22 | 23 | # Now output. 24 | foreach $line (@xpms) { print $line; } 25 | print "const char *const *const ${id}[] = {\n"; 26 | for ($i = 0; $i < $k; $i++) { print " ${id}_$i,\n"; } 27 | print "};\n"; 28 | print "const int n_${id} = $k;\n"; 29 | -------------------------------------------------------------------------------- /macosx/osx.h: -------------------------------------------------------------------------------- 1 | #ifndef PUTTY_OSX_H 2 | #define PUTTY_OSX_H 3 | 4 | /* 5 | * Cocoa defines `FontSpec' itself, so we must change its name. 6 | * (Arrgh.) 7 | */ 8 | #define FontSpec FontSpec_OSX_Proof 9 | 10 | /* 11 | * Define the various compatibility symbols to make uxpty.c compile 12 | * correctly on OS X. 13 | */ 14 | #define BSD_PTYS 15 | #define OMIT_UTMP 16 | #define HAVE_NO_SETRESUID 17 | #define NOT_X_WINDOWS 18 | 19 | /* 20 | * OS X is largely just Unix, so we can include most of this 21 | * unchanged. 22 | */ 23 | #include "unix.h" 24 | 25 | /* 26 | * Functions exported by osxsel.m. (Both of these functions are 27 | * expected to be called in the _main_ thread: the select subthread 28 | * is an implementation detail of osxsel.m and ideally should not 29 | * be visible at all outside it.) 30 | */ 31 | void osxsel_init(void); /* call this to kick things off */ 32 | void osxsel_process_results(void); /* call this on receipt of a netevent */ 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /nocproxy.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Routines to refuse to do cryptographic interaction with proxies 3 | * in PuTTY. This is a stub implementation of the same interfaces 4 | * provided by cproxy.c, for use in PuTTYtel. 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #define DEFINE_PLUG_METHOD_MACROS 12 | #include "putty.h" 13 | #include "network.h" 14 | #include "proxy.h" 15 | 16 | void proxy_socks5_offerencryptedauth(char * command, int * len) 17 | { 18 | /* For telnet, don't add any new encrypted authentication routines */ 19 | } 20 | 21 | int proxy_socks5_handlechap (Proxy_Socket p) 22 | { 23 | 24 | plug_closing(p->plug, "Proxy error: Trying to handle a SOCKS5 CHAP request" 25 | " in telnet-only build", 26 | PROXY_ERROR_GENERAL, 0); 27 | return 1; 28 | } 29 | 30 | int proxy_socks5_selectchap(Proxy_Socket p) 31 | { 32 | plug_closing(p->plug, "Proxy error: Trying to handle a SOCKS5 CHAP request" 33 | " in telnet-only build", 34 | PROXY_ERROR_GENERAL, 0); 35 | return 1; 36 | } 37 | -------------------------------------------------------------------------------- /contrib/cygtermd/telnet.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Header declaring Telnet-handling functions. 3 | */ 4 | 5 | #ifndef FIXME_TELNET_H 6 | #define FIXME_TELNET_H 7 | 8 | #include "sel.h" 9 | 10 | typedef struct telnet_tag *Telnet; 11 | 12 | struct shell_data { 13 | char **envvars; /* array of "VAR=value" terms */ 14 | int nenvvars; 15 | char *termtype; 16 | }; 17 | 18 | /* 19 | * Create and destroy a Telnet structure. 20 | */ 21 | Telnet telnet_new(sel_wfd *net, sel_wfd *pty); 22 | void telnet_free(Telnet telnet); 23 | 24 | /* 25 | * Process data read from the pty. 26 | */ 27 | void telnet_from_pty(Telnet telnet, char *buf, int len); 28 | 29 | /* 30 | * Process Telnet protocol data received from the network. 31 | */ 32 | void telnet_from_net(Telnet telnet, char *buf, int len); 33 | 34 | /* 35 | * Return true if pre-shell-startup negotiations are complete and 36 | * it's safe to start the shell subprocess now. On a true return, 37 | * also fills in the shell_data structure. 38 | */ 39 | int telnet_shell_ok(Telnet telnet, struct shell_data *shdata); 40 | 41 | #endif /* FIXME_TELNET_H */ 42 | -------------------------------------------------------------------------------- /windows/rcstuff.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Miscellaneous stuff to include in all .rc files. 3 | */ 4 | 5 | #ifndef PUTTY_RCSTUFF_H 6 | #define PUTTY_RCSTUFF_H 7 | 8 | #ifdef __LCC__ 9 | #include 10 | #else 11 | 12 | /* Some compilers, like Borland, don't have winresrc.h */ 13 | #ifndef NO_WINRESRC_H 14 | #ifndef MSVC4 15 | #include 16 | #else 17 | #include 18 | #endif 19 | #endif 20 | 21 | #endif /* end #ifdef __LCC__ */ 22 | 23 | /* Some systems don't define this, so I do it myself if necessary */ 24 | #ifndef TCS_MULTILINE 25 | #define TCS_MULTILINE 0x0200 26 | #endif 27 | 28 | /* Likewise */ 29 | #ifndef RT_MANIFEST 30 | #define RT_MANIFEST 24 31 | #endif 32 | 33 | /* LCC is the offender here. */ 34 | #ifndef VS_FF_DEBUG 35 | #define VS_FF_DEBUG 1 36 | #endif 37 | #ifndef VS_FF_PRERELEASE 38 | #define VS_FF_PRERELEASE 2 39 | #endif 40 | #ifndef VS_FF_PRIVATEBUILD 41 | #define VS_FF_PRIVATEBUILD 8 42 | #endif 43 | #ifndef VOS__WINDOWS32 44 | #define VOS__WINDOWS32 4 45 | #endif 46 | #ifndef VFT_APP 47 | #define VFT_APP 1 48 | #endif 49 | 50 | #endif /* PUTTY_RCSTUFF_H */ 51 | -------------------------------------------------------------------------------- /testdata/utf8.txt: -------------------------------------------------------------------------------- 1 | Test of UTF-8 output in a terminal emulator 2 | ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ 3 | 4 | Some basic Unicode: 5 | ∮ E⋅da = Q, n → ∞, ∑ f(i) = ∏ g(i), ∀x∈ℝ: ⌈x⌉ = −⌊−x⌋, α ∧ ¬β = ¬(¬α ∨ β), 6 | ℕ ⊆ ℕ₀ ⊂ ℤ ⊂ ℚ ⊂ ℝ ⊂ ℂ, ⊥ < a ≠ b ≡ c ≤ d ≪ ⊤ ⇒ (A ⇔ B), 7 | 8 | Combining characters: 9 | STARGΛ̊TE SG-1, a = v̇ = r̈, a⃑ ⊥ b⃑ 10 | [----------------------------|------------------------] 11 | ๏ แผ่นดินฮั่นเสื่อมโทรมแสนสังเวช พระปกเกศกองบู๊กู้ขึ้นใหม่ 12 | สิบสองกษัตริย์ก่อนหน้าแลถัดไป สององค์ไซร้โง่เขลาเบาปัญญา 13 | 14 | Wide characters with difficult wrapping: 15 | Here we go then: コンニチハ コンニチハ コンニチハ コンニチハ コンニチハ コンニチハ コンニチハ コンニチハ コンニチハ コンニチハ コンニチハ コンニチハ コンニチハ コンニチハ コンニチハ 16 | 17 | Arabic and bidirectional text: 18 | (من مجمع الزوائد ومنبع الفوائد للهيثمي ، ج 1 ، ص 74-84) 19 | عن جرير رضي الله عنه قال قال رسول الله صلى الله عليه 20 | وسلم: بني الاسلام على خمس شهادة ان لا اله الا الله واقام 21 | Mixed LTR and RTL text: جرير رضي back to LTR. 22 | 23 | East Asian Ambiguous characters: ¼½¾¼½¾¼½¾¼½¾¼½¾¼½¾¼½¾¼½¾¼½¾¼½¾ 24 | -------------------------------------------------------------------------------- /mksrcarc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | perl mkfiles.pl 6 | # These are text files. 7 | text=`{ find . -name CVS -prune -o \ 8 | -name .cvsignore -prune -o \ 9 | -name .svn -prune -o \ 10 | -name LATEST.VER -prune -o \ 11 | -name CHECKLST.txt -prune -o \ 12 | -name mksrcarc.sh -prune -o \ 13 | -name '*.dsp' -prune -o \ 14 | -name '*.dsw' -prune -o \ 15 | -type f -print | sed 's/^\.\///'; } | \ 16 | grep -ivE 'testdata/.*\.txt|MODULE|putty.iss|website.url' | grep -vF .ico | grep -vF .icns` 17 | # These are files which I'm _sure_ should be treated as text, but 18 | # which zip might complain about, so we direct its moans to 19 | # /dev/null! Apparently its heuristics are doubtful of UTF-8 text 20 | # files. 21 | bintext=testdata/*.txt 22 | # These are actual binary files which we don't want transforming. 23 | bin=`{ ls -1 windows/*.ico windows/putty.iss windows/website.url macosx/*.icns; \ 24 | find . -name '*.dsp' -print -o -name '*.dsw' -print; }` 25 | 26 | verbosely() { 27 | echo "$@" 28 | "$@" 29 | } 30 | 31 | verbosely zip -l putty-src.zip $text 32 | verbosely zip -l putty-src.zip $bintext 33 | verbosely zip putty-src.zip $bin 34 | -------------------------------------------------------------------------------- /unix/uxsignal.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /* 6 | * Calling signal() is non-portable, as it varies in meaning 7 | * between platforms and depending on feature macros, and has 8 | * stupid semantics at least some of the time. 9 | * 10 | * This function provides the same interface as the libc function, 11 | * but provides consistent semantics. It assumes POSIX semantics 12 | * for sigaction() (so you might need to do some more work if you 13 | * port to something ancient like SunOS 4) 14 | */ 15 | void (*putty_signal(int sig, void (*func)(int)))(int) { 16 | struct sigaction sa; 17 | struct sigaction old; 18 | 19 | sa.sa_handler = func; 20 | if(sigemptyset(&sa.sa_mask) < 0) 21 | return SIG_ERR; 22 | sa.sa_flags = SA_RESTART; 23 | if(sigaction(sig, &sa, &old) < 0) 24 | return SIG_ERR; 25 | return old.sa_handler; 26 | } 27 | 28 | void block_signal(int sig, int block_it) 29 | { 30 | sigset_t ss; 31 | 32 | sigemptyset(&ss); 33 | sigaddset(&ss, sig); 34 | if(sigprocmask(block_it ? SIG_BLOCK : SIG_UNBLOCK, &ss, 0) < 0) { 35 | perror("sigprocmask"); 36 | exit(1); 37 | } 38 | } 39 | 40 | /* 41 | Local Variables: 42 | c-basic-offset:4 43 | comment-column:40 44 | End: 45 | */ 46 | -------------------------------------------------------------------------------- /mkunxarc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Build a Unix source distribution from the PuTTY CVS area. 4 | # 5 | # Expects the following arguments: 6 | # - the version number to write into configure.ac 7 | # - the suffix to put on the Unix source tarball 8 | # - the options to put on the 'make' command line for the docs 9 | 10 | autoconfver="$1" 11 | arcsuffix="$2" 12 | docver="$3" 13 | 14 | perl mkfiles.pl 15 | (cd doc && make -s ${docver:+"$docver"}) 16 | 17 | relver=`cat LATEST.VER` 18 | arcname="putty$arcsuffix" 19 | mkdir uxarc 20 | mkdir uxarc/$arcname 21 | find . -name uxarc -prune -o \ 22 | -name CVS -prune -o \ 23 | -name .svn -prune -o \ 24 | -name . -o \ 25 | -type d -exec mkdir uxarc/$arcname/{} \; 26 | find . -name uxarc -prune -o \ 27 | -name CVS -prune -o \ 28 | -name .cvsignore -prune -o \ 29 | -name .svn -prune -o \ 30 | -name configure.ac -prune -o \ 31 | -name '*.zip' -prune -o \ 32 | -name '*.tar.gz' -prune -o \ 33 | -type f -exec ln -s $PWD/{} uxarc/$arcname/{} \; 34 | sed "s/^AC_INIT(putty,.*/AC_INIT(putty, $autoconfver)/" configure.ac > uxarc/$arcname/configure.ac 35 | (cd uxarc/$arcname && sh mkauto.sh) 2>errors || { cat errors >&2; exit 1; } 36 | 37 | tar -C uxarc -chzof $arcname.tar.gz $arcname 38 | rm -rf uxarc 39 | -------------------------------------------------------------------------------- /windows/pageant.mft: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 11 | PuTTY SSH authentication agent 12 | 13 | 14 | 16 | 22 | 23 | 24 | 25 | 26 | 28 | true 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /windows/puttygen.mft: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 11 | SSH key generator for PuTTY 12 | 13 | 14 | 16 | 22 | 23 | 24 | 25 | 26 | 28 | true 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /windows/putty.mft: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 11 | A network client and terminal emulator 12 | 13 | 14 | 16 | 22 | 23 | 24 | 25 | 26 | 28 | true 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | PuTTY is copyright 1997-2015 Simon Tatham. 2 | 3 | Portions copyright Robert de Bath, Joris van Rantwijk, Delian 4 | Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry, 5 | Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa, Markus 6 | Kuhn, Colin Watson, and CORE SDI S.A. 7 | 8 | Permission is hereby granted, free of charge, to any person 9 | obtaining a copy of this software and associated documentation files 10 | (the "Software"), to deal in the Software without restriction, 11 | including without limitation the rights to use, copy, modify, merge, 12 | publish, distribute, sublicense, and/or sell copies of the Software, 13 | and to permit persons to whom the Software is furnished to do so, 14 | subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be 17 | included in all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 | NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE 23 | FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 24 | CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 25 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /charset/sbcs.c: -------------------------------------------------------------------------------- 1 | /* 2 | * sbcs.c - routines to handle single-byte character sets. 3 | */ 4 | 5 | #include "charset.h" 6 | #include "internal.h" 7 | 8 | /* 9 | * The charset_spec for any single-byte character set should 10 | * provide read_sbcs() as its read function, and its `data' field 11 | * should be a wchar_t string constant containing the 256 entries 12 | * of the translation table. 13 | */ 14 | 15 | void read_sbcs(charset_spec const *charset, long int input_chr, 16 | charset_state *state, 17 | void (*emit)(void *ctx, long int output), void *emitctx) 18 | { 19 | const struct sbcs_data *sd = charset->data; 20 | 21 | UNUSEDARG(state); 22 | 23 | emit(emitctx, sd->sbcs2ucs[input_chr]); 24 | } 25 | 26 | void write_sbcs(charset_spec const *charset, long int input_chr, 27 | charset_state *state, 28 | void (*emit)(void *ctx, long int output), void *emitctx) 29 | { 30 | const struct sbcs_data *sd = charset->data; 31 | int i, j, k, c; 32 | 33 | UNUSEDARG(state); 34 | 35 | /* 36 | * Binary-search in the ucs2sbcs table. 37 | */ 38 | i = -1; 39 | j = sd->nvalid; 40 | while (i+1 < j) { 41 | k = (i+j)/2; 42 | c = sd->ucs2sbcs[k]; 43 | if (input_chr < sd->sbcs2ucs[c]) 44 | j = k; 45 | else if (input_chr > sd->sbcs2ucs[c]) 46 | i = k; 47 | else { 48 | emit(emitctx, c); 49 | return; 50 | } 51 | } 52 | emit(emitctx, ERROR); 53 | } 54 | -------------------------------------------------------------------------------- /Buildscr.cv: -------------------------------------------------------------------------------- 1 | # -*- sh -*- 2 | 3 | # Build script to scan PuTTY with the downloadable Coverity scanner 4 | # and generate a tar file to upload to their open-source scanning 5 | # service. 6 | 7 | module putty 8 | 9 | # Preparations. 10 | in putty do ./mkfiles.pl 11 | in putty do ./mkauto.sh 12 | in putty/doc do make 13 | 14 | # Scan the Unix build, on a 64-bit system to differentiate as much as 15 | # possible from the other scan of the cross-platform files. 16 | delegate covscan64 17 | in putty do ./configure 18 | in putty do cov-build --dir cov-int make 19 | in putty do tar czvf cov-int.tar.gz cov-int 20 | return putty/cov-int.tar.gz 21 | enddelegate 22 | 23 | # Scan the Windows build, by means of building with Winelib (since as 24 | # of 2013-07-22, the Coverity Scan website doesn't offer a 32-bit 25 | # Windows scanner for download). 26 | delegate covscan32wine 27 | in putty do tar xzvf cov-int.tar.gz 28 | in putty/windows do cov-build --dir ../cov-int make -f Makefile.cyg CC=winegcc RC=wrc XFLAGS=-DCOVERITY 29 | in putty do tar czvf cov-int.tar.gz cov-int 30 | return putty/cov-int.tar.gz 31 | enddelegate 32 | 33 | # Provide the revision number as one of the build outputs, to make it 34 | # easy to construct a curl upload command which will annotate it 35 | # appropriately when uploaded. 36 | in putty do echo $(vcsfullid) > revision.txt 37 | 38 | deliver putty/revision.txt $@ 39 | deliver putty/cov-int.tar.gz $@ 40 | -------------------------------------------------------------------------------- /doc/licence.but: -------------------------------------------------------------------------------- 1 | \A{licence} PuTTY \ii{Licence} 2 | 3 | PuTTY is \i{copyright} 1997-2015 Simon Tatham. 4 | 5 | Portions copyright Robert de Bath, Joris van Rantwijk, Delian 6 | Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry, 7 | Justin Bradford, Ben Harris, Malcolm Smith, Ahmad Khalifa, Markus 8 | Kuhn, Colin Watson, and CORE SDI S.A. 9 | 10 | Permission is hereby granted, free of charge, to any person 11 | obtaining a copy of this software and associated documentation files 12 | (the \q{Software}), to deal in the Software without restriction, 13 | including without limitation the rights to use, copy, modify, merge, 14 | publish, distribute, sublicense, and/or sell copies of the Software, 15 | and to permit persons to whom the Software is furnished to do so, 16 | subject to the following conditions: 17 | 18 | The above copyright notice and this permission notice shall be 19 | included in all copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED \q{AS IS}, WITHOUT WARRANTY OF ANY KIND, 22 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE 25 | FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 26 | CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 27 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28 | -------------------------------------------------------------------------------- /unix/uxprint.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Printing interface for PuTTY. 3 | */ 4 | 5 | #include 6 | #include 7 | #include "putty.h" 8 | 9 | struct printer_job_tag { 10 | FILE *fp; 11 | }; 12 | 13 | printer_job *printer_start_job(char *printer) 14 | { 15 | printer_job *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 | --------------------------------------------------------------------------------