1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-09 09:27:59 +00:00

Initial checkin: beta 0.43

[originally from svn r11]
This commit is contained in:
Simon Tatham 1999-01-08 13:02:13 +00:00
commit c74130d423
20 changed files with 8474 additions and 0 deletions

56
Makefile Normal file
View File

@ -0,0 +1,56 @@
# Makefile for PuTTY. Use `FWHACK=/DFWHACK' to cause the firewall hack
# to be built in. (requires rebuild of ssh.obj only)
CFLAGS = /nologo /W3 /YX /O2 /Yd /D_X86_ /D_WINDOWS /DDEBUG /ML /Fd
.c.obj:
cl $(FWHACK) $(CFLAGS) /c $*.c
OBJS1 = window.obj windlg.obj terminal.obj telnet.obj misc.obj noise.obj
OBJS2 = ssh.obj sshcrc.obj sshdes.obj sshmd5.obj sshrsa.obj sshrand.obj
OBJS3 = sshsha.obj
RESRC = win_res.res
LIBS1 = advapi32.lib user32.lib gdi32.lib
LIBS2 = wsock32.lib comctl32.lib comdlg32.lib
putty.exe: $(OBJS1) $(OBJS2) $(OBJS3) $(RESRC) link.rsp
link /debug -out:putty.exe @link.rsp
puttyd.exe: $(OBJS1) $(OBJS2) $(OBJS3) $(RESRC) link.rsp
link /debug -out:puttyd.exe @link.rsp
link.rsp: makefile
echo /nologo /subsystem:windows > link.rsp
echo $(OBJS1) >> link.rsp
echo $(OBJS2) >> link.rsp
echo $(OBJS3) >> link.rsp
echo $(RESRC) >> link.rsp
echo $(LIBS1) >> link.rsp
echo $(LIBS2) >> link.rsp
window.obj: window.c putty.h win_res.h
windlg.obj: windlg.c putty.h ssh.h win_res.h
terminal.obj: terminal.c putty.h
telnet.obj: telnet.c putty.h
misc.obj: misc.c putty.h
noise.obj: noise.c putty.h ssh.h
ssh.obj: ssh.c ssh.h putty.h
sshcrc.obj: sshcrc.c ssh.h
sshdes.obj: sshdes.c ssh.h
sshmd5.obj: sshmd5.c ssh.h
sshrsa.obj: sshrsa.c ssh.h
sshsha.obj: sshsha.c ssh.h
sshrand.obj: sshrand.c ssh.h
win_res.res: win_res.rc win_res.h putty.ico
rc $(FWHACK) -r win_res.rc
clean:
del *.obj
del *.exe
del *.res
del *.pch
del *.aps
del *.ilk
del *.pdb
del link.rsp

67
misc.c Normal file
View File

@ -0,0 +1,67 @@
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include "putty.h"
/* My own versions of malloc, realloc and free. Because I want malloc and
* realloc to bomb out and exit the program if they run out of memory,
* realloc to reliably call malloc if passed a NULL pointer, and free
* to reliably do nothing if passed a NULL pointer. Of course we can also
* put trace printouts in, if we need to. */
#ifdef MALLOC_LOG
static FILE *fp = NULL;
void mlog(char *file, int line) {
if (!fp)
fp = fopen("putty_mem.log", "w");
if (fp)
fprintf (fp, "%s:%d: ", file, line);
}
#endif
void *safemalloc(size_t size) {
void *p = malloc (size);
if (!p) {
MessageBox(NULL, "Out of memory!", "PuTTY Fatal Error",
MB_SYSTEMMODAL | MB_ICONERROR | MB_OK);
exit(1);
}
#ifdef MALLOC_LOG
if (fp)
fprintf(fp, "malloc(%d) returns %p\n", size, p);
#endif
return p;
}
void *saferealloc(void *ptr, size_t size) {
void *p;
if (!ptr)
p = malloc (size);
else
p = realloc (ptr, size);
if (!p) {
MessageBox(NULL, "Out of memory!", "PuTTY Fatal Error",
MB_SYSTEMMODAL | MB_ICONERROR | MB_OK);
exit(1);
}
#ifdef MALLOC_LOG
if (fp)
fprintf(fp, "realloc(%p,%d) returns %p\n", ptr, size, p);
#endif
return p;
}
void safefree(void *ptr) {
if (ptr) {
#ifdef MALLOC_LOG
if (fp)
fprintf(fp, "free(%p)\n", ptr);
#endif
free (ptr);
}
#ifdef MALLOC_LOG
else if (fp)
fprintf(fp, "freeing null pointer - no action taken\n");
#endif
}

148
noise.c Normal file
View File

@ -0,0 +1,148 @@
/*
* Noise generation for PuTTY's cryptographic random number
* generator.
*/
#include <windows.h>
#include <stdio.h>
#include "putty.h"
#include "ssh.h"
static char seedpath[2*MAX_PATH+10] = "\0";
/*
* Find the random seed file path and store it in `seedpath'.
*/
static void get_seedpath(void) {
HKEY rkey;
DWORD type, size;
size = sizeof(seedpath);
if (RegOpenKey(HKEY_CURRENT_USER, PUTTY_REG_POS, &rkey)==ERROR_SUCCESS) {
int ret = RegQueryValueEx(rkey, "RandSeedFile",
0, &type, seedpath, &size);
if (ret != ERROR_SUCCESS || type != REG_SZ)
seedpath[0] = '\0';
RegCloseKey(rkey);
} else
seedpath[0] = '\0';
if (!seedpath[0]) {
int len, ret;
len = GetEnvironmentVariable("HOMEDRIVE", seedpath, sizeof(seedpath));
ret = GetEnvironmentVariable("HOMEPATH", seedpath+len,
sizeof(seedpath)-len);
if (ret == 0) { /* probably win95; store in \WINDOWS */
GetWindowsDirectory(seedpath, sizeof(seedpath));
len = strlen(seedpath);
} else
len += ret;
strcpy(seedpath+len, "\\PUTTY.RND");
}
}
/*
* This function is called once, at PuTTY startup, and will do some
* seriously silly things like listing directories and getting disk
* free space and a process snapshot.
*/
void noise_get_heavy(void (*func) (void *, int)) {
HANDLE srch;
HANDLE seedf;
WIN32_FIND_DATA finddata;
char winpath[MAX_PATH+3];
GetWindowsDirectory(winpath, sizeof(winpath));
strcat(winpath, "\\*");
srch = FindFirstFile(winpath, &finddata);
if (srch != INVALID_HANDLE_VALUE) {
do {
func(&finddata, sizeof(finddata));
} while (FindNextFile(srch, &finddata));
FindClose(srch);
}
if (!seedpath[0])
get_seedpath();
seedf = CreateFile(seedpath, GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL);
if (seedf) {
while (1) {
char buf[1024];
DWORD len;
if (ReadFile(seedf, buf, sizeof(buf), &len, NULL) && len)
func(buf, len);
else
break;
}
CloseHandle(seedf);
}
}
void random_save_seed(void) {
HANDLE seedf;
if (!seedpath[0])
get_seedpath();
seedf = CreateFile(seedpath, GENERIC_WRITE, 0,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (seedf) {
int len;
DWORD lenwritten;
void *data;
random_get_savedata(&data, &len);
WriteFile(seedf, data, len, &lenwritten, NULL);
CloseHandle(seedf);
}
}
/*
* This function is called every time the random pool needs
* stirring, and will acquire the system time in all available
* forms and the battery status.
*/
void noise_get_light(void (*func) (void *, int)) {
SYSTEMTIME systime;
DWORD adjust[2];
BOOL rubbish;
SYSTEM_POWER_STATUS pwrstat;
GetSystemTime(&systime);
func(&systime, sizeof(systime));
GetSystemTimeAdjustment(&adjust[0], &adjust[1], &rubbish);
func(&adjust, sizeof(adjust));
if (GetSystemPowerStatus(&pwrstat))
func(&pwrstat, sizeof(pwrstat));
}
/*
* This function is called on every keypress or mouse move, and
* will add the current Windows time and performance monitor
* counter to the noise pool. It gets the scan code or mouse
* position passed in.
*/
void noise_ultralight(DWORD data) {
DWORD wintime;
LARGE_INTEGER perftime;
random_add_noise(&data, sizeof(DWORD));
wintime = GetTickCount();
random_add_noise(&wintime, sizeof(DWORD));
if (QueryPerformanceCounter(&perftime))
random_add_noise(&perftime, sizeof(perftime));
}

252
putty.h Normal file
View File

@ -0,0 +1,252 @@
#ifndef PUTTY_PUTTY_H
#define PUTTY_PUTTY_H
#define PUTTY_REG_POS "Software\\SimonTatham\\PuTTY"
/*
* Global variables. Most modules declare these `extern', but
* window.c will do `#define PUTTY_DO_GLOBALS' before including this
* module, and so will get them properly defined.
*/
#ifdef PUTTY_DO_GLOBALS
#define GLOBAL
#else
#define GLOBAL extern
#endif
#define ATTR_ACTCURS 0x80000000UL /* active cursor (block) */
#define ATTR_PASCURS 0x40000000UL /* passive cursor (box) */
#define ATTR_INVALID 0x20000000UL
#define ATTR_WRAPPED 0x10000000UL
#define ATTR_ASCII 0x00000000UL /* normal ASCII charset ESC ( B */
#define ATTR_GBCHR 0x00100000UL /* UK variant charset ESC ( A */
#define ATTR_LINEDRW 0x00200000UL /* line drawing charset ESC ( 0 */
#define ATTR_BOLD 0x00000100UL
#define ATTR_UNDER 0x00000200UL
#define ATTR_REVERSE 0x00000400UL
#define ATTR_FGMASK 0x0000F000UL
#define ATTR_BGMASK 0x000F0000UL
#define ATTR_FGSHIFT 12
#define ATTR_BGSHIFT 16
#define ATTR_DEFAULT 0x00098000UL
#define ATTR_DEFFG 0x00008000UL
#define ATTR_DEFBG 0x00090000UL
#define ATTR_CUR_XOR 0x000BA000UL
#define ERASE_CHAR (ATTR_DEFAULT | ' ')
#define ATTR_MASK 0xFFFFFF00UL
#define CHAR_MASK 0x000000FFUL
typedef HDC Context;
#define SEL_NL { 13, 10 }
GLOBAL int rows, cols, savelines;
GLOBAL int font_width, font_height;
#define INBUF_SIZE 2048
#define INBUF_MASK (INBUF_SIZE-1)
GLOBAL unsigned char inbuf[INBUF_SIZE];
GLOBAL int inbuf_head, inbuf_reap;
#define OUTBUF_SIZE 2048
#define OUTBUF_MASK (OUTBUF_SIZE-1)
GLOBAL unsigned char outbuf[OUTBUF_SIZE];
GLOBAL int outbuf_head, outbuf_reap;
GLOBAL int has_focus;
GLOBAL int app_cursor_keys, app_keypad_keys;
#define WM_NETEVENT (WM_USER + 1)
typedef enum {
TS_AYT, TS_BRK, TS_SYNCH, TS_EC, TS_EL, TS_GA, TS_NOP, TS_ABORT,
TS_AO, TS_IP, TS_SUSP, TS_EOR, TS_EOF
} Telnet_Special;
typedef enum {
MB_NOTHING, MB_SELECT, MB_EXTEND, MB_PASTE
} Mouse_Button;
typedef enum {
MA_NOTHING, MA_CLICK, MA_2CLK, MA_3CLK, MA_DRAG, MA_RELEASE
} Mouse_Action;
typedef enum {
VT_XWINDOWS, VT_OEMANSI, VT_OEMONLY, VT_POORMAN
} VT_Mode;
typedef struct {
char *(*init) (HWND hwnd, char *host, int port, char **realhost);
int (*msg) (WPARAM wParam, LPARAM lParam);
void (*send) (char *buf, int len);
void (*size) (void);
void (*special) (Telnet_Special code);
} Backend;
GLOBAL Backend *back;
typedef struct {
/* Basic options */
char host[512];
int port;
enum { PROT_TELNET, PROT_SSH } protocol;
int close_on_exit;
/* Telnet options */
char termtype[32];
char termspeed[32];
char environ[1024]; /* VAR\tvalue\0VAR\tvalue\0\0 */
char username[32];
int rfc_environ;
/* Keyboard options */
int bksp_is_delete;
int rxvt_homeend;
int linux_funkeys;
int app_cursor;
int app_keypad;
/* Terminal options */
int savelines;
int dec_om;
int wrap_mode;
int win_name_always;
int width, height;
char font[64];
int fontisbold;
int fontheight;
VT_Mode vtmode;
/* Colour options */
int try_palette;
int bold_colour;
unsigned char colours[22][3];
/* Selection options */
int mouse_is_xterm;
short wordness[256];
} Config;
GLOBAL Config cfg;
/*
* Exports from window.c.
*/
void request_resize (int, int);
void do_text (Context, int, int, char *, int, unsigned long);
void set_title (char *);
void set_icon (char *);
void set_sbar (int, int, int);
Context get_ctx();
void free_ctx (Context);
void palette_set (int, int, int, int);
void palette_reset (void);
void write_clip (void *, int);
void get_clip (void **, int *);
void optimised_move (int, int, int);
void fatalbox (char *, ...);
void beep (void);
#define OPTIMISE_IS_SCROLL 1
/*
* Exports from noise.c.
*/
void noise_get_heavy(void (*func) (void *, int));
void noise_get_light(void (*func) (void *, int));
void noise_ultralight(DWORD data);
void random_save_seed(void);
/*
* Exports from windlg.c.
*/
int do_config (void);
int do_reconfig (HWND);
void do_defaults (char *);
void lognegot (char *);
void shownegot (HWND);
void showabout (HWND);
void verify_ssh_host_key(char *host, struct RSAKey *key);
/*
* Exports from terminal.c.
*/
void term_init (void);
void term_size (int, int, int);
void term_out (void);
void term_paint (Context, int, int, int, int);
void term_scroll (int, int);
void term_pwron (void);
void term_clrsb (void);
void term_mouse (Mouse_Button, Mouse_Action, int, int);
void term_deselect (void);
void term_update (void);
void term_invalidate(void);
/*
* Exports from telnet.c.
*/
Backend telnet_backend;
/*
* Exports from ssh.c.
*/
Backend ssh_backend;
/*
* Exports from sshrand.c.
*/
void random_add_noise(void *noise, int length);
void random_init(void);
int random_byte(void);
void random_get_savedata(void **data, int *len);
/*
* Exports from misc.c.
*/
/* #define MALLOC_LOG do this if you suspect putty of leaking memory */
#ifdef MALLOC_LOG
#define smalloc(z) (mlog(__FILE__,__LINE__), safemalloc(z))
#define srealloc(y,z) (mlog(__FILE__,__LINE__), saferealloc(y,z))
#define sfree(z) (mlog(__FILE__,__LINE__), safefree(z))
void mlog(char *, int);
#else
#define smalloc safemalloc
#define srealloc saferealloc
#define sfree safefree
#endif
void *safemalloc(size_t);
void *saferealloc(void *, size_t);
void safefree(void *);
/*
* A debug system.
*/
#ifdef DEBUG
#include <stdarg.h>
#define debug(x) (dprintf x)
static void dprintf(char *fmt, ...) {
char buf[2048];
DWORD dw;
va_list ap;
static int gotconsole = 0;
if (!gotconsole) {
AllocConsole();
gotconsole = 1;
}
va_start(ap, fmt);
vsprintf(buf, fmt, ap);
WriteFile (GetStdHandle(STD_OUTPUT_HANDLE), buf, strlen(buf), &dw, NULL);
va_end(ap);
}
#else
#define debug(x)
#endif
#endif

BIN
putty.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

15
resource.h Normal file
View File

@ -0,0 +1,15 @@
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by win_res.rc
//
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

694
ssh.c Normal file
View File

@ -0,0 +1,694 @@
#include <stdio.h>
#include <stdlib.h>
#include <winsock.h>
#include "putty.h"
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
#include "ssh.h"
/* Coroutine mechanics for the sillier bits of the code */
#define crBegin1 static int crLine = 0;
#define crBegin2 switch(crLine) { case 0:;
#define crBegin crBegin1; crBegin2;
#define crFinish(z) } crLine = 0; return (z)
#define crFinishV } crLine = 0; return
#define crReturn(z) \
do {\
crLine=__LINE__; return (z); case __LINE__:;\
} while (0)
#define crReturnV \
do {\
crLine=__LINE__; return; case __LINE__:;\
} while (0)
#define crStop(z) do{ crLine = 0; return (z); }while(0)
#define crStopV do{ crLine = 0; return; }while(0)
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
static SOCKET s = INVALID_SOCKET;
static unsigned char session_key[32];
static struct ssh_cipher *cipher = NULL;
static char *savedhost;
static enum {
SSH_STATE_BEFORE_SIZE,
SSH_STATE_INTERMED,
SSH_STATE_SESSION
} ssh_state = SSH_STATE_BEFORE_SIZE;
static int size_needed = FALSE;
static void s_write (char *buf, int len) {
while (len > 0) {
int i = send (s, buf, len, 0);
if (i > 0)
len -= i, buf += i;
}
}
static int s_read (char *buf, int len) {
int ret = 0;
while (len > 0) {
int i = recv (s, buf, len, 0);
if (i > 0)
len -= i, buf += i, ret += i;
else
return i;
}
return ret;
}
static void c_write (char *buf, int len) {
while (len--) {
int new_head = (inbuf_head + 1) & INBUF_MASK;
int c = (unsigned char) *buf;
if (new_head != inbuf_reap) {
inbuf[inbuf_head] = *buf++;
inbuf_head = new_head;
}
}
}
struct Packet {
long length;
int type;
unsigned long crc;
unsigned char *data;
unsigned char *body;
long maxlen;
};
static struct Packet pktin = { 0, 0, 0, NULL, 0 };
static struct Packet pktout = { 0, 0, 0, NULL, 0 };
static void ssh_protocol(unsigned char *in, int inlen, int ispkt);
static void ssh_size(void);
static void ssh_gotdata(unsigned char *data, int datalen) {
static long len, biglen, to_read;
static unsigned char c, *p;
static int i, pad;
static char padding[8];
static unsigned char word[4];
crBegin;
while (1) {
for (i = len = 0; i < 4; i++) {
while (datalen == 0)
crReturnV;
len = (len << 8) + *data;
data++, datalen--;
}
pad = 8 - (len%8);
biglen = len + pad;
len -= 5; /* type and CRC */
pktin.length = len;
if (pktin.maxlen < biglen) {
pktin.maxlen = biglen;
pktin.data = (pktin.data == NULL ? malloc(biglen) :
realloc(pktin.data, biglen));
if (!pktin.data)
fatalbox("Out of memory");
}
p = pktin.data, to_read = biglen;
while (to_read > 0) {
static int chunk;
chunk = to_read;
while (datalen == 0)
crReturnV;
if (chunk > datalen)
chunk = datalen;
memcpy(p, data, chunk);
data += chunk;
datalen -= chunk;
p += chunk;
to_read -= chunk;
}
if (cipher)
cipher->decrypt(pktin.data, biglen);
pktin.type = pktin.data[pad];
pktin.body = pktin.data+pad+1;
if (pktin.type == 36) { /* SSH_MSG_DEBUG */
/* FIXME: log it */
} else
ssh_protocol(NULL, 0, 1);
}
crFinishV;
}
static void s_wrpkt_start(int type, int len) {
int pad, biglen;
len += 5; /* type and CRC */
pad = 8 - (len%8);
biglen = len + pad;
pktout.length = len-5;
if (pktout.maxlen < biglen) {
pktout.maxlen = biglen;
pktout.data = (pktout.data == NULL ? malloc(biglen) :
realloc(pktout.data, biglen));
if (!pktout.data)
fatalbox("Out of memory");
}
pktout.type = type;
pktout.body = pktout.data+4+pad+1;
}
static void s_wrpkt(void) {
int pad, len, biglen, i;
unsigned long crc;
len = pktout.length + 5; /* type and CRC */
pad = 8 - (len%8);
biglen = len + pad;
pktout.body[-1] = pktout.type;
for (i=0; i<pad; i++)
pktout.data[i+4] = random_byte();
crc = crc32(pktout.data+4, biglen-4);
pktout.data[biglen+0] = (unsigned char) ((crc >> 24) & 0xFF);
pktout.data[biglen+1] = (unsigned char) ((crc >> 16) & 0xFF);
pktout.data[biglen+2] = (unsigned char) ((crc >> 8) & 0xFF);
pktout.data[biglen+3] = (unsigned char) (crc & 0xFF);
pktout.data[0] = (len >> 24) & 0xFF;
pktout.data[1] = (len >> 16) & 0xFF;
pktout.data[2] = (len >> 8) & 0xFF;
pktout.data[3] = len & 0xFF;
if (cipher)
cipher->encrypt(pktout.data+4, biglen);
s_write(pktout.data, biglen+4);
}
static int do_ssh_init(void) {
char c;
char version[10];
char vstring[40];
int i;
#ifdef FWHACK
i = 0;
while (s_read(&c, 1) == 1) {
if (c == 'S' && i < 2) i++;
else if (c == 'S' && i == 2) i = 2;
else if (c == 'H' && i == 2) break;
else i = 0;
}
#else
if (s_read(&c,1) != 1 || c != 'S') return 0;
if (s_read(&c,1) != 1 || c != 'S') return 0;
if (s_read(&c,1) != 1 || c != 'H') return 0;
#endif
if (s_read(&c,1) != 1 || c != '-') return 0;
i = 0;
while (1) {
if (s_read(&c,1) != 1)
return 0;
if (i >= 0) {
if (c == '-') {
version[i] = '\0';
i = -1;
} else if (i < sizeof(version)-1)
version[i++] = c;
}
else if (c == '\n')
break;
}
sprintf(vstring, "SSH-%s-7.7.7\n",
(strcmp(version, "1.5") <= 0 ? version : "1.5"));
s_write(vstring, strlen(vstring));
}
static void ssh_protocol(unsigned char *in, int inlen, int ispkt) {
int i, j, len;
unsigned char session_id[16];
unsigned char *rsabuf, *keystr1, *keystr2;
unsigned char cookie[8];
struct RSAKey servkey, hostkey;
struct MD5Context md5c;
extern struct ssh_cipher ssh_3des;
crBegin;
random_init();
while (!ispkt)
crReturnV;
if (pktin.type != 2)
fatalbox("Public key packet not received");
memcpy(cookie, pktin.body, 8);
MD5Init(&md5c);
i = makekey(pktin.body+8, &servkey, &keystr1);
j = makekey(pktin.body+8+i, &hostkey, &keystr2);
MD5Update(&md5c, keystr2, hostkey.bytes);
MD5Update(&md5c, keystr1, servkey.bytes);
MD5Update(&md5c, pktin.body, 8);
MD5Final(session_id, &md5c);
for (i=0; i<32; i++)
session_key[i] = random_byte();
len = (hostkey.bytes > servkey.bytes ? hostkey.bytes : servkey.bytes);
rsabuf = malloc(len);
if (!rsabuf)
fatalbox("Out of memory");
verify_ssh_host_key(savedhost, &hostkey);
for (i=0; i<32; i++) {
rsabuf[i] = session_key[i];
if (i < 16)
rsabuf[i] ^= session_id[i];
}
if (hostkey.bytes > servkey.bytes) {
rsaencrypt(rsabuf, 32, &servkey);
rsaencrypt(rsabuf, servkey.bytes, &hostkey);
} else {
rsaencrypt(rsabuf, 32, &hostkey);
rsaencrypt(rsabuf, hostkey.bytes, &servkey);
}
s_wrpkt_start(3, len+15);
pktout.body[0] = 3; /* SSH_CIPHER_3DES */
memcpy(pktout.body+1, cookie, 8);
pktout.body[9] = (len*8) >> 8;
pktout.body[10] = (len*8) & 0xFF;
memcpy(pktout.body+11, rsabuf, len);
pktout.body[len+11] = pktout.body[len+12] = 0; /* protocol flags */
pktout.body[len+13] = pktout.body[len+14] = 0;
s_wrpkt();
free(rsabuf);
cipher = &ssh_3des;
cipher->sesskey(session_key);
do { crReturnV; } while (!ispkt);
if (pktin.type != 14)
fatalbox("Encryption not successfully enabled");
fflush(stdout);
{
static char username[100];
static int pos = 0;
static char c;
if (!*cfg.username) {
c_write("login as: ", 10);
while (pos >= 0) {
do { crReturnV; } while (ispkt);
while (inlen--) switch (c = *in++) {
case 10: case 13:
username[pos] = 0;
pos = -1;
break;
case 8: case 127:
if (pos > 0) {
c_write("\b \b", 3);
pos--;
}
break;
case 21: case 27:
while (pos > 0) {
c_write("\b \b", 3);
pos--;
}
break;
case 3: case 4:
random_save_seed();
exit(0);
break;
default:
if (c >= ' ' && c <= '~' && pos < 40) {
username[pos++] = c;
c_write(&c, 1);
}
break;
}
}
c_write("\r\n", 2);
username[strcspn(username, "\n\r")] = '\0';
} else {
char stuff[200];
strncpy(username, cfg.username, 99);
username[99] = '\0';
sprintf(stuff, "Sent username \"%s\".\r\n", username);
c_write(stuff, strlen(stuff));
}
s_wrpkt_start(4, 4+strlen(username));
pktout.body[0] = pktout.body[1] = pktout.body[2] = 0;
pktout.body[3] = strlen(username);
memcpy(pktout.body+4, username, strlen(username));
s_wrpkt();
}
do { crReturnV; } while (!ispkt);
while (pktin.type == 15) {
static char password[100];
static int pos;
static char c;
c_write("password: ", 10);
pos = 0;
while (pos >= 0) {
do { crReturnV; } while (ispkt);
while (inlen--) switch (c = *in++) {
case 10: case 13:
password[pos] = 0;
pos = -1;
break;
case 8: case 127:
if (pos > 0)
pos--;
break;
case 21: case 27:
pos = 0;
break;
case 3: case 4:
random_save_seed();
exit(0);
break;
default:
if (c >= ' ' && c <= '~' && pos < 40)
password[pos++] = c;
break;
}
}
c_write("\r\n", 2);
s_wrpkt_start(9, 4+strlen(password));
pktout.body[0] = pktout.body[1] = pktout.body[2] = 0;
pktout.body[3] = strlen(password);
memcpy(pktout.body+4, password, strlen(password));
s_wrpkt();
memset(password, 0, strlen(password));
do { crReturnV; } while (!ispkt);
if (pktin.type == 15) {
c_write("Access denied\r\n", 15);
} else if (pktin.type != 14) {
fatalbox("Strange packet received, type %d", pktin.type);
}
}
i = strlen(cfg.termtype);
s_wrpkt_start(10, i+5*4+1);
pktout.body[0] = (i >> 24) & 0xFF;
pktout.body[1] = (i >> 16) & 0xFF;
pktout.body[2] = (i >> 8) & 0xFF;
pktout.body[3] = i & 0xFF;
memcpy(pktout.body+4, cfg.termtype, i);
i += 4;
pktout.body[i++] = (rows >> 24) & 0xFF;
pktout.body[i++] = (rows >> 16) & 0xFF;
pktout.body[i++] = (rows >> 8) & 0xFF;
pktout.body[i++] = rows & 0xFF;
pktout.body[i++] = (cols >> 24) & 0xFF;
pktout.body[i++] = (cols >> 16) & 0xFF;
pktout.body[i++] = (cols >> 8) & 0xFF;
pktout.body[i++] = cols & 0xFF;
memset(pktout.body+i, 0, 9); /* 0 pixwidth, 0 pixheight, 0.b endofopt */
s_wrpkt();
ssh_state = SSH_STATE_INTERMED;
do { crReturnV; } while (!ispkt);
if (pktin.type != 14 && pktin.type != 15) {
fatalbox("Protocol confusion");
} else if (pktin.type == 15) {
c_write("Server refused to allocate pty\r\n", 32);
}
s_wrpkt_start(12, 0);
s_wrpkt();
ssh_state = SSH_STATE_SESSION;
if (size_needed)
ssh_size();
while (1) {
crReturnV;
if (ispkt) {
if (pktin.type == 17 || pktin.type == 18) {
long len = 0;
for (i = 0; i < 4; i++)
len = (len << 8) + pktin.body[i];
c_write(pktin.body+4, len);
} else if (pktin.type == 1) {
/* SSH_MSG_DISCONNECT: do nothing */
} else if (pktin.type == 14) {
/* SSH_MSG_SUCCESS: may be from EXEC_SHELL on some servers */
} else if (pktin.type == 15) {
/* SSH_MSG_FAILURE: may be from EXEC_SHELL on some servers
* if no pty is available or in other odd cases. Ignore */
} else if (pktin.type == 20) {
/* EXITSTATUS */
s_wrpkt_start(33, 0);
s_wrpkt();
} else {
fatalbox("Strange packet received: type %d", pktin.type);
}
} else {
s_wrpkt_start(16, 4+inlen);
pktout.body[0] = (inlen >> 24) & 0xFF;
pktout.body[1] = (inlen >> 16) & 0xFF;
pktout.body[2] = (inlen >> 8) & 0xFF;
pktout.body[3] = inlen & 0xFF;
memcpy(pktout.body+4, in, inlen);
s_wrpkt();
}
}
crFinishV;
}
/*
* Called to set up the connection. Will arrange for WM_NETEVENT
* messages to be passed to the specified window, whose window
* procedure should then call telnet_msg().
*
* Returns an error message, or NULL on success.
*
* Also places the canonical host name into `realhost'.
*/
static char *ssh_init (HWND hwnd, char *host, int port, char **realhost) {
SOCKADDR_IN addr;
struct hostent *h;
unsigned long a;
#ifdef FWHACK
char *FWhost;
int FWport;
#endif
savedhost = malloc(1+strlen(host));
if (!savedhost)
fatalbox("Out of memory");
strcpy(savedhost, host);
#ifdef FWHACK
FWhost = host;
FWport = port;
host = FWSTR;
port = 23;
#endif
/*
* Try to find host.
*/
if ( (a = inet_addr(host)) == (unsigned long) INADDR_NONE) {
if ( (h = gethostbyname(host)) == NULL)
switch (WSAGetLastError()) {
case WSAENETDOWN: return "Network is down";
case WSAHOST_NOT_FOUND: case WSANO_DATA:
return "Host does not exist";
case WSATRY_AGAIN: return "Host not found";
default: return "gethostbyname: unknown error";
}
memcpy (&a, h->h_addr, sizeof(a));
*realhost = h->h_name;
} else
*realhost = host;
#ifdef FWHACK
*realhost = FWhost;
#endif
a = ntohl(a);
if (port < 0)
port = 22; /* default ssh port */
/*
* Open socket.
*/
s = socket(AF_INET, SOCK_STREAM, 0);
if (s == INVALID_SOCKET)
switch (WSAGetLastError()) {
case WSAENETDOWN: return "Network is down";
case WSAEAFNOSUPPORT: return "TCP/IP support not present";
default: return "socket(): unknown error";
}
/*
* Bind to local address.
*/
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(0);
if (bind (s, (struct sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR)
switch (WSAGetLastError()) {
case WSAENETDOWN: return "Network is down";
default: return "bind(): unknown error";
}
/*
* Connect to remote address.
*/
addr.sin_addr.s_addr = htonl(a);
addr.sin_port = htons((short)port);
if (connect (s, (struct sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR)
switch (WSAGetLastError()) {
case WSAENETDOWN: return "Network is down";
case WSAECONNREFUSED: return "Connection refused";
case WSAENETUNREACH: return "Network is unreachable";
case WSAEHOSTUNREACH: return "No route to host";
default: return "connect(): unknown error";
}
#ifdef FWHACK
send(s, "connect ", 8, 0);
send(s, FWhost, strlen(FWhost), 0);
{
char buf[20];
sprintf(buf, " %d\n", FWport);
send (s, buf, strlen(buf), 0);
}
#endif
if (!do_ssh_init())
return "Protocol initialisation error";
if (WSAAsyncSelect (s, hwnd, WM_NETEVENT, FD_READ | FD_CLOSE) == SOCKET_ERROR)
switch (WSAGetLastError()) {
case WSAENETDOWN: return "Network is down";
default: return "WSAAsyncSelect(): unknown error";
}
return NULL;
}
/*
* Process a WM_NETEVENT message. Will return 0 if the connection
* has closed, or <0 for a socket error.
*/
static int ssh_msg (WPARAM wParam, LPARAM lParam) {
int ret;
char buf[256];
if (s == INVALID_SOCKET) /* how the hell did we get here?! */
return -5000;
if (WSAGETSELECTERROR(lParam) != 0)
return -WSAGETSELECTERROR(lParam);
switch (WSAGETSELECTEVENT(lParam)) {
case FD_READ:
ret = recv(s, buf, sizeof(buf), 0);
if (ret < 0 && WSAGetLastError() == WSAEWOULDBLOCK)
return 1;
if (ret < 0) /* any _other_ error */
return -10000-WSAGetLastError();
if (ret == 0) {
s = INVALID_SOCKET;
return 0; /* can't happen, in theory */
}
ssh_gotdata (buf, ret);
return 1;
case FD_CLOSE:
s = INVALID_SOCKET;
return 0;
}
return 1; /* shouldn't happen, but WTF */
}
/*
* Called to send data down the Telnet connection.
*/
static void ssh_send (char *buf, int len) {
if (s == INVALID_SOCKET)
return;
ssh_protocol(buf, len, 0);
}
/*
* Called to set the size of the window from Telnet's POV.
*/
static void ssh_size(void) {
switch (ssh_state) {
case SSH_STATE_BEFORE_SIZE:
break; /* do nothing */
case SSH_STATE_INTERMED:
size_needed = TRUE; /* buffer for later */
break;
case SSH_STATE_SESSION:
s_wrpkt_start(11, 16);
pktout.body[0] = (rows >> 24) & 0xFF;
pktout.body[1] = (rows >> 16) & 0xFF;
pktout.body[2] = (rows >> 8) & 0xFF;
pktout.body[3] = rows & 0xFF;
pktout.body[4] = (cols >> 24) & 0xFF;
pktout.body[5] = (cols >> 16) & 0xFF;
pktout.body[6] = (cols >> 8) & 0xFF;
pktout.body[7] = cols & 0xFF;
memset(pktout.body+8, 0, 8);
s_wrpkt();
}
}
/*
* (Send Telnet special codes)
*/
static void ssh_special (Telnet_Special code) {
/* do nothing */
}
Backend ssh_backend = {
ssh_init,
ssh_msg,
ssh_send,
ssh_size,
ssh_special
};

39
ssh.h Normal file
View File

@ -0,0 +1,39 @@
struct RSAKey {
int bits;
int bytes;
void *modulus;
void *exponent;
};
int makekey(unsigned char *data, struct RSAKey *result,
unsigned char **keystr);
void rsaencrypt(unsigned char *data, int length, struct RSAKey *key);
int rsastr_len(struct RSAKey *key);
void rsastr_fmt(char *str, struct RSAKey *key);
typedef unsigned int word32;
typedef unsigned int uint32;
unsigned long crc32(const unsigned char *s, unsigned int len);
struct MD5Context {
uint32 buf[4];
uint32 bits[2];
unsigned char in[64];
};
void MD5Init(struct MD5Context *context);
void MD5Update(struct MD5Context *context, unsigned char const *buf,
unsigned len);
void MD5Final(unsigned char digest[16], struct MD5Context *context);
struct ssh_cipher {
void (*sesskey)(unsigned char *key);
void (*encrypt)(unsigned char *blk, int len);
void (*decrypt)(unsigned char *blk, int len);
};
void SHATransform(word32 *digest, word32 *data);
int random_byte(void);
void random_add_noise(void *noise, int length);

111
sshcrc.c Normal file
View File

@ -0,0 +1,111 @@
/* ============================================================= */
/* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or */
/* code or tables extracted from it, as desired without restriction. */
/* */
/* First, the polynomial itself and its table of feedback terms. The */
/* polynomial is */
/* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */
/* */
/* Note that we take it "backwards" and put the highest-order term in */
/* the lowest-order bit. The X^32 term is "implied"; the LSB is the */
/* X^31 term, etc. The X^0 term (usually shown as "+1") results in */
/* the MSB being 1. */
/* */
/* Note that the usual hardware shift register implementation, which */
/* is what we're using (we're merely optimizing it by doing eight-bit */
/* chunks at a time) shifts bits into the lowest-order term. In our */
/* implementation, that means shifting towards the right. Why do we */
/* do it this way? Because the calculated CRC must be transmitted in */
/* order from highest-order term to lowest-order term. UARTs transmit */
/* characters in order from LSB to MSB. By storing the CRC this way, */
/* we hand it to the UART in the order low-byte to high-byte; the UART */
/* sends each low-bit to hight-bit; and the result is transmission bit */
/* by bit from highest- to lowest-order term without requiring any bit */
/* shuffling on our part. Reception works similarly. */
/* */
/* The feedback terms table consists of 256, 32-bit entries. Notes: */
/* */
/* The table can be generated at runtime if desired; code to do so */
/* is shown later. It might not be obvious, but the feedback */
/* terms simply represent the results of eight shift/xor opera- */
/* tions for all combinations of data and CRC register values. */
/* */
/* The values must be right-shifted by eight bits by the "updcrc" */
/* logic; the shift must be unsigned (bring in zeroes). On some */
/* hardware you could probably optimize the shift in assembler by */
/* using byte-swap instructions. */
/* polynomial $edb88320 */
/* */
/* -------------------------------------------------------------------- */
static unsigned long crc32_tab[] = {
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
0x2d02ef8dL
};
/* Return a 32-bit CRC of the contents of the buffer. */
unsigned long crc32(const unsigned char *s, unsigned int len)
{
unsigned int i;
unsigned long crc32val;
crc32val = 0;
for (i = 0; i < len; i ++)
{
crc32val =
crc32_tab[(crc32val ^ s[i]) & 0xff] ^
(crc32val >> 8);
}
return crc32val;
}

768
sshdes.c Normal file
View File

@ -0,0 +1,768 @@
#include <assert.h>
#include "ssh.h"
/*
DES implementation; 1995 Tatu Ylonen <ylo@cs.hut.fi>
This implementation is derived from libdes-3.06, which is copyright
(c) 1993 Eric Young, and distributed under the GNU GPL or the ARTISTIC licence
(at the user's option). The original distribution can be found e.g. from
ftp://ftp.dsi.unimi.it/pub/security/crypt/libdes/libdes-3.06.tar.gz.
This implementation is distributed under the same terms. See
libdes-README, libdes-ARTISTIC, and libdes-COPYING for more
information.
*/
/*
* $Id: sshdes.c,v 1.1 1999/01/08 13:02:12 simon Exp $
* $Log: sshdes.c,v $
* Revision 1.1 1999/01/08 13:02:12 simon
* Initial checkin: beta 0.43
*
* Revision 1.1.1.1 1996/02/18 21:38:11 ylo
* Imported ssh-1.2.13.
*
* Revision 1.2 1995/07/13 01:22:57 ylo
* Added cvs log.
*
* $Endlog$
*/
typedef struct
{
word32 key_schedule[32];
} DESContext;
/* Sets the des key for the context. Initializes the context. The least
significant bit of each byte of the key is ignored as parity. */
static void des_set_key(unsigned char *key, DESContext *ks);
/* Encrypts 32 bits in l,r, and stores the result in output[0] and output[1].
Performs encryption if encrypt is non-zero, and decryption if it is zero.
The key context must have been initialized previously with des_set_key. */
static void des_encrypt(word32 l, word32 r, word32 *output, DESContext *ks,
int encrypt);
/* Encrypts len bytes from src to dest in CBC modes. Len must be a multiple
of 8. iv will be modified at end to a value suitable for continuing
encryption. */
static void des_cbc_encrypt(DESContext *ks, unsigned char *iv, unsigned char *dest,
const unsigned char *src, unsigned int len);
/* Decrypts len bytes from src to dest in CBC modes. Len must be a multiple
of 8. iv will be modified at end to a value suitable for continuing
decryption. */
static void des_cbc_decrypt(DESContext *ks, unsigned char *iv, unsigned char *dest,
const unsigned char *src, unsigned int len);
/* Encrypts in CBC mode using triple-DES. */
static void des_3cbc_encrypt(DESContext *ks1, unsigned char *iv1,
DESContext *ks2, unsigned char *iv2,
DESContext *ks3, unsigned char *iv3,
unsigned char *dest, const unsigned char *src,
unsigned int len);
/* Decrypts in CBC mode using triple-DES. */
static void des_3cbc_decrypt(DESContext *ks1, unsigned char *iv1,
DESContext *ks2, unsigned char *iv2,
DESContext *ks3, unsigned char *iv3,
unsigned char *dest, const unsigned char *src,
unsigned int len);
#define GET_32BIT_LSB_FIRST(cp) \
(((unsigned long)(unsigned char)(cp)[0]) | \
((unsigned long)(unsigned char)(cp)[1] << 8) | \
((unsigned long)(unsigned char)(cp)[2] << 16) | \
((unsigned long)(unsigned char)(cp)[3] << 24))
#define PUT_32BIT_LSB_FIRST(cp, value) do { \
(cp)[0] = (value); \
(cp)[1] = (value) >> 8; \
(cp)[2] = (value) >> 16; \
(cp)[3] = (value) >> 24; } while (0)
/*
DES implementation; 1995 Tatu Ylonen <ylo@cs.hut.fi>
This implementation is derived from libdes-3.06, which is copyright
(c) 1993 Eric Young, and distributed under the GNU GPL or the ARTISTIC licence
(at the user's option). The original distribution can be found e.g. from
ftp://ftp.dsi.unimi.it/pub/security/crypt/libdes/libdes-3.06.tar.gz.
This implementation is distributed under the same terms. See
libdes-README, libdes-ARTISTIC, and libdes-COPYING for more
information.
A description of the DES algorithm can be found in every modern book on
cryptography and data security, including the following:
Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1994.
Jennifer Seberry and Josed Pieprzyk: Cryptography: An Introduction to
Computer Security. Prentice-Hall, 1989.
Man Young Rhee: Cryptography and Secure Data Communications. McGraw-Hill,
1994.
*/
/*
* $Id: sshdes.c,v 1.1 1999/01/08 13:02:12 simon Exp $
* $Log: sshdes.c,v $
* Revision 1.1 1999/01/08 13:02:12 simon
* Initial checkin: beta 0.43
*
* Revision 1.1.1.1 1996/02/18 21:38:11 ylo
* Imported ssh-1.2.13.
*
* Revision 1.2 1995/07/13 01:22:25 ylo
* Added cvs log.
*
* $Endlog$
*/
/* Table for key generation. This used to be in sk.h. */
/* Copyright (C) 1993 Eric Young - see README for more details */
static const word32 des_skb[8][64]={
/* for C bits (numbered as per FIPS 46) 1 2 3 4 5 6 */
{ 0x00000000,0x00000010,0x20000000,0x20000010,
0x00010000,0x00010010,0x20010000,0x20010010,
0x00000800,0x00000810,0x20000800,0x20000810,
0x00010800,0x00010810,0x20010800,0x20010810,
0x00000020,0x00000030,0x20000020,0x20000030,
0x00010020,0x00010030,0x20010020,0x20010030,
0x00000820,0x00000830,0x20000820,0x20000830,
0x00010820,0x00010830,0x20010820,0x20010830,
0x00080000,0x00080010,0x20080000,0x20080010,
0x00090000,0x00090010,0x20090000,0x20090010,
0x00080800,0x00080810,0x20080800,0x20080810,
0x00090800,0x00090810,0x20090800,0x20090810,
0x00080020,0x00080030,0x20080020,0x20080030,
0x00090020,0x00090030,0x20090020,0x20090030,
0x00080820,0x00080830,0x20080820,0x20080830,
0x00090820,0x00090830,0x20090820,0x20090830 },
/* for C bits (numbered as per FIPS 46) 7 8 10 11 12 13 */
{ 0x00000000,0x02000000,0x00002000,0x02002000,
0x00200000,0x02200000,0x00202000,0x02202000,
0x00000004,0x02000004,0x00002004,0x02002004,
0x00200004,0x02200004,0x00202004,0x02202004,
0x00000400,0x02000400,0x00002400,0x02002400,
0x00200400,0x02200400,0x00202400,0x02202400,
0x00000404,0x02000404,0x00002404,0x02002404,
0x00200404,0x02200404,0x00202404,0x02202404,
0x10000000,0x12000000,0x10002000,0x12002000,
0x10200000,0x12200000,0x10202000,0x12202000,
0x10000004,0x12000004,0x10002004,0x12002004,
0x10200004,0x12200004,0x10202004,0x12202004,
0x10000400,0x12000400,0x10002400,0x12002400,
0x10200400,0x12200400,0x10202400,0x12202400,
0x10000404,0x12000404,0x10002404,0x12002404,
0x10200404,0x12200404,0x10202404,0x12202404 },
/* for C bits (numbered as per FIPS 46) 14 15 16 17 19 20 */
{ 0x00000000,0x00000001,0x00040000,0x00040001,
0x01000000,0x01000001,0x01040000,0x01040001,
0x00000002,0x00000003,0x00040002,0x00040003,
0x01000002,0x01000003,0x01040002,0x01040003,
0x00000200,0x00000201,0x00040200,0x00040201,
0x01000200,0x01000201,0x01040200,0x01040201,
0x00000202,0x00000203,0x00040202,0x00040203,
0x01000202,0x01000203,0x01040202,0x01040203,
0x08000000,0x08000001,0x08040000,0x08040001,
0x09000000,0x09000001,0x09040000,0x09040001,
0x08000002,0x08000003,0x08040002,0x08040003,
0x09000002,0x09000003,0x09040002,0x09040003,
0x08000200,0x08000201,0x08040200,0x08040201,
0x09000200,0x09000201,0x09040200,0x09040201,
0x08000202,0x08000203,0x08040202,0x08040203,
0x09000202,0x09000203,0x09040202,0x09040203 },
/* for C bits (numbered as per FIPS 46) 21 23 24 26 27 28 */
{ 0x00000000,0x00100000,0x00000100,0x00100100,
0x00000008,0x00100008,0x00000108,0x00100108,
0x00001000,0x00101000,0x00001100,0x00101100,
0x00001008,0x00101008,0x00001108,0x00101108,
0x04000000,0x04100000,0x04000100,0x04100100,
0x04000008,0x04100008,0x04000108,0x04100108,
0x04001000,0x04101000,0x04001100,0x04101100,
0x04001008,0x04101008,0x04001108,0x04101108,
0x00020000,0x00120000,0x00020100,0x00120100,
0x00020008,0x00120008,0x00020108,0x00120108,
0x00021000,0x00121000,0x00021100,0x00121100,
0x00021008,0x00121008,0x00021108,0x00121108,
0x04020000,0x04120000,0x04020100,0x04120100,
0x04020008,0x04120008,0x04020108,0x04120108,
0x04021000,0x04121000,0x04021100,0x04121100,
0x04021008,0x04121008,0x04021108,0x04121108 },
/* for D bits (numbered as per FIPS 46) 1 2 3 4 5 6 */
{ 0x00000000,0x10000000,0x00010000,0x10010000,
0x00000004,0x10000004,0x00010004,0x10010004,
0x20000000,0x30000000,0x20010000,0x30010000,
0x20000004,0x30000004,0x20010004,0x30010004,
0x00100000,0x10100000,0x00110000,0x10110000,
0x00100004,0x10100004,0x00110004,0x10110004,
0x20100000,0x30100000,0x20110000,0x30110000,
0x20100004,0x30100004,0x20110004,0x30110004,
0x00001000,0x10001000,0x00011000,0x10011000,
0x00001004,0x10001004,0x00011004,0x10011004,
0x20001000,0x30001000,0x20011000,0x30011000,
0x20001004,0x30001004,0x20011004,0x30011004,
0x00101000,0x10101000,0x00111000,0x10111000,
0x00101004,0x10101004,0x00111004,0x10111004,
0x20101000,0x30101000,0x20111000,0x30111000,
0x20101004,0x30101004,0x20111004,0x30111004 },
/* for D bits (numbered as per FIPS 46) 8 9 11 12 13 14 */
{ 0x00000000,0x08000000,0x00000008,0x08000008,
0x00000400,0x08000400,0x00000408,0x08000408,
0x00020000,0x08020000,0x00020008,0x08020008,
0x00020400,0x08020400,0x00020408,0x08020408,
0x00000001,0x08000001,0x00000009,0x08000009,
0x00000401,0x08000401,0x00000409,0x08000409,
0x00020001,0x08020001,0x00020009,0x08020009,
0x00020401,0x08020401,0x00020409,0x08020409,
0x02000000,0x0A000000,0x02000008,0x0A000008,
0x02000400,0x0A000400,0x02000408,0x0A000408,
0x02020000,0x0A020000,0x02020008,0x0A020008,
0x02020400,0x0A020400,0x02020408,0x0A020408,
0x02000001,0x0A000001,0x02000009,0x0A000009,
0x02000401,0x0A000401,0x02000409,0x0A000409,
0x02020001,0x0A020001,0x02020009,0x0A020009,
0x02020401,0x0A020401,0x02020409,0x0A020409 },
/* for D bits (numbered as per FIPS 46) 16 17 18 19 20 21 */
{ 0x00000000,0x00000100,0x00080000,0x00080100,
0x01000000,0x01000100,0x01080000,0x01080100,
0x00000010,0x00000110,0x00080010,0x00080110,
0x01000010,0x01000110,0x01080010,0x01080110,
0x00200000,0x00200100,0x00280000,0x00280100,
0x01200000,0x01200100,0x01280000,0x01280100,
0x00200010,0x00200110,0x00280010,0x00280110,
0x01200010,0x01200110,0x01280010,0x01280110,
0x00000200,0x00000300,0x00080200,0x00080300,
0x01000200,0x01000300,0x01080200,0x01080300,
0x00000210,0x00000310,0x00080210,0x00080310,
0x01000210,0x01000310,0x01080210,0x01080310,
0x00200200,0x00200300,0x00280200,0x00280300,
0x01200200,0x01200300,0x01280200,0x01280300,
0x00200210,0x00200310,0x00280210,0x00280310,
0x01200210,0x01200310,0x01280210,0x01280310 },
/* for D bits (numbered as per FIPS 46) 22 23 24 25 27 28 */
{ 0x00000000,0x04000000,0x00040000,0x04040000,
0x00000002,0x04000002,0x00040002,0x04040002,
0x00002000,0x04002000,0x00042000,0x04042000,
0x00002002,0x04002002,0x00042002,0x04042002,
0x00000020,0x04000020,0x00040020,0x04040020,
0x00000022,0x04000022,0x00040022,0x04040022,
0x00002020,0x04002020,0x00042020,0x04042020,
0x00002022,0x04002022,0x00042022,0x04042022,
0x00000800,0x04000800,0x00040800,0x04040800,
0x00000802,0x04000802,0x00040802,0x04040802,
0x00002800,0x04002800,0x00042800,0x04042800,
0x00002802,0x04002802,0x00042802,0x04042802,
0x00000820,0x04000820,0x00040820,0x04040820,
0x00000822,0x04000822,0x00040822,0x04040822,
0x00002820,0x04002820,0x00042820,0x04042820,
0x00002822,0x04002822,0x00042822,0x04042822 }
};
/* Tables used for executing des. This used to be in spr.h. */
/* Copyright (C) 1993 Eric Young - see README for more details */
static const word32 des_SPtrans[8][64]={
/* nibble 0 */
{ 0x00820200, 0x00020000, 0x80800000, 0x80820200,
0x00800000, 0x80020200, 0x80020000, 0x80800000,
0x80020200, 0x00820200, 0x00820000, 0x80000200,
0x80800200, 0x00800000, 0x00000000, 0x80020000,
0x00020000, 0x80000000, 0x00800200, 0x00020200,
0x80820200, 0x00820000, 0x80000200, 0x00800200,
0x80000000, 0x00000200, 0x00020200, 0x80820000,
0x00000200, 0x80800200, 0x80820000, 0x00000000,
0x00000000, 0x80820200, 0x00800200, 0x80020000,
0x00820200, 0x00020000, 0x80000200, 0x00800200,
0x80820000, 0x00000200, 0x00020200, 0x80800000,
0x80020200, 0x80000000, 0x80800000, 0x00820000,
0x80820200, 0x00020200, 0x00820000, 0x80800200,
0x00800000, 0x80000200, 0x80020000, 0x00000000,
0x00020000, 0x00800000, 0x80800200, 0x00820200,
0x80000000, 0x80820000, 0x00000200, 0x80020200 },
/* nibble 1 */
{ 0x10042004, 0x00000000, 0x00042000, 0x10040000,
0x10000004, 0x00002004, 0x10002000, 0x00042000,
0x00002000, 0x10040004, 0x00000004, 0x10002000,
0x00040004, 0x10042000, 0x10040000, 0x00000004,
0x00040000, 0x10002004, 0x10040004, 0x00002000,
0x00042004, 0x10000000, 0x00000000, 0x00040004,
0x10002004, 0x00042004, 0x10042000, 0x10000004,
0x10000000, 0x00040000, 0x00002004, 0x10042004,
0x00040004, 0x10042000, 0x10002000, 0x00042004,
0x10042004, 0x00040004, 0x10000004, 0x00000000,
0x10000000, 0x00002004, 0x00040000, 0x10040004,
0x00002000, 0x10000000, 0x00042004, 0x10002004,
0x10042000, 0x00002000, 0x00000000, 0x10000004,
0x00000004, 0x10042004, 0x00042000, 0x10040000,
0x10040004, 0x00040000, 0x00002004, 0x10002000,
0x10002004, 0x00000004, 0x10040000, 0x00042000 },
/* nibble 2 */
{ 0x41000000, 0x01010040, 0x00000040, 0x41000040,
0x40010000, 0x01000000, 0x41000040, 0x00010040,
0x01000040, 0x00010000, 0x01010000, 0x40000000,
0x41010040, 0x40000040, 0x40000000, 0x41010000,
0x00000000, 0x40010000, 0x01010040, 0x00000040,
0x40000040, 0x41010040, 0x00010000, 0x41000000,
0x41010000, 0x01000040, 0x40010040, 0x01010000,
0x00010040, 0x00000000, 0x01000000, 0x40010040,
0x01010040, 0x00000040, 0x40000000, 0x00010000,
0x40000040, 0x40010000, 0x01010000, 0x41000040,
0x00000000, 0x01010040, 0x00010040, 0x41010000,
0x40010000, 0x01000000, 0x41010040, 0x40000000,
0x40010040, 0x41000000, 0x01000000, 0x41010040,
0x00010000, 0x01000040, 0x41000040, 0x00010040,
0x01000040, 0x00000000, 0x41010000, 0x40000040,
0x41000000, 0x40010040, 0x00000040, 0x01010000 },
/* nibble 3 */
{ 0x00100402, 0x04000400, 0x00000002, 0x04100402,
0x00000000, 0x04100000, 0x04000402, 0x00100002,
0x04100400, 0x04000002, 0x04000000, 0x00000402,
0x04000002, 0x00100402, 0x00100000, 0x04000000,
0x04100002, 0x00100400, 0x00000400, 0x00000002,
0x00100400, 0x04000402, 0x04100000, 0x00000400,
0x00000402, 0x00000000, 0x00100002, 0x04100400,
0x04000400, 0x04100002, 0x04100402, 0x00100000,
0x04100002, 0x00000402, 0x00100000, 0x04000002,
0x00100400, 0x04000400, 0x00000002, 0x04100000,
0x04000402, 0x00000000, 0x00000400, 0x00100002,
0x00000000, 0x04100002, 0x04100400, 0x00000400,
0x04000000, 0x04100402, 0x00100402, 0x00100000,
0x04100402, 0x00000002, 0x04000400, 0x00100402,
0x00100002, 0x00100400, 0x04100000, 0x04000402,
0x00000402, 0x04000000, 0x04000002, 0x04100400 },
/* nibble 4 */
{ 0x02000000, 0x00004000, 0x00000100, 0x02004108,
0x02004008, 0x02000100, 0x00004108, 0x02004000,
0x00004000, 0x00000008, 0x02000008, 0x00004100,
0x02000108, 0x02004008, 0x02004100, 0x00000000,
0x00004100, 0x02000000, 0x00004008, 0x00000108,
0x02000100, 0x00004108, 0x00000000, 0x02000008,
0x00000008, 0x02000108, 0x02004108, 0x00004008,
0x02004000, 0x00000100, 0x00000108, 0x02004100,
0x02004100, 0x02000108, 0x00004008, 0x02004000,
0x00004000, 0x00000008, 0x02000008, 0x02000100,
0x02000000, 0x00004100, 0x02004108, 0x00000000,
0x00004108, 0x02000000, 0x00000100, 0x00004008,
0x02000108, 0x00000100, 0x00000000, 0x02004108,
0x02004008, 0x02004100, 0x00000108, 0x00004000,
0x00004100, 0x02004008, 0x02000100, 0x00000108,
0x00000008, 0x00004108, 0x02004000, 0x02000008 },
/* nibble 5 */
{ 0x20000010, 0x00080010, 0x00000000, 0x20080800,
0x00080010, 0x00000800, 0x20000810, 0x00080000,
0x00000810, 0x20080810, 0x00080800, 0x20000000,
0x20000800, 0x20000010, 0x20080000, 0x00080810,
0x00080000, 0x20000810, 0x20080010, 0x00000000,
0x00000800, 0x00000010, 0x20080800, 0x20080010,
0x20080810, 0x20080000, 0x20000000, 0x00000810,
0x00000010, 0x00080800, 0x00080810, 0x20000800,
0x00000810, 0x20000000, 0x20000800, 0x00080810,
0x20080800, 0x00080010, 0x00000000, 0x20000800,
0x20000000, 0x00000800, 0x20080010, 0x00080000,
0x00080010, 0x20080810, 0x00080800, 0x00000010,
0x20080810, 0x00080800, 0x00080000, 0x20000810,
0x20000010, 0x20080000, 0x00080810, 0x00000000,
0x00000800, 0x20000010, 0x20000810, 0x20080800,
0x20080000, 0x00000810, 0x00000010, 0x20080010 },
/* nibble 6 */
{ 0x00001000, 0x00000080, 0x00400080, 0x00400001,
0x00401081, 0x00001001, 0x00001080, 0x00000000,
0x00400000, 0x00400081, 0x00000081, 0x00401000,
0x00000001, 0x00401080, 0x00401000, 0x00000081,
0x00400081, 0x00001000, 0x00001001, 0x00401081,
0x00000000, 0x00400080, 0x00400001, 0x00001080,
0x00401001, 0x00001081, 0x00401080, 0x00000001,
0x00001081, 0x00401001, 0x00000080, 0x00400000,
0x00001081, 0x00401000, 0x00401001, 0x00000081,
0x00001000, 0x00000080, 0x00400000, 0x00401001,
0x00400081, 0x00001081, 0x00001080, 0x00000000,
0x00000080, 0x00400001, 0x00000001, 0x00400080,
0x00000000, 0x00400081, 0x00400080, 0x00001080,
0x00000081, 0x00001000, 0x00401081, 0x00400000,
0x00401080, 0x00000001, 0x00001001, 0x00401081,
0x00400001, 0x00401080, 0x00401000, 0x00001001 },
/* nibble 7 */
{ 0x08200020, 0x08208000, 0x00008020, 0x00000000,
0x08008000, 0x00200020, 0x08200000, 0x08208020,
0x00000020, 0x08000000, 0x00208000, 0x00008020,
0x00208020, 0x08008020, 0x08000020, 0x08200000,
0x00008000, 0x00208020, 0x00200020, 0x08008000,
0x08208020, 0x08000020, 0x00000000, 0x00208000,
0x08000000, 0x00200000, 0x08008020, 0x08200020,
0x00200000, 0x00008000, 0x08208000, 0x00000020,
0x00200000, 0x00008000, 0x08000020, 0x08208020,
0x00008020, 0x08000000, 0x00000000, 0x00208000,
0x08200020, 0x08008020, 0x08008000, 0x00200020,
0x08208000, 0x00000020, 0x00200020, 0x08008000,
0x08208020, 0x00200000, 0x08200000, 0x08000020,
0x00208000, 0x00008020, 0x08008020, 0x08200000,
0x00000020, 0x08208000, 0x00208020, 0x00000000,
0x08000000, 0x08200020, 0x00008000, 0x00208020 }};
/* Some stuff that used to be in des_locl.h. Heavily modified. */
/* IP and FP
* The problem is more of a geometric problem that random bit fiddling.
0 1 2 3 4 5 6 7 62 54 46 38 30 22 14 6
8 9 10 11 12 13 14 15 60 52 44 36 28 20 12 4
16 17 18 19 20 21 22 23 58 50 42 34 26 18 10 2
24 25 26 27 28 29 30 31 to 56 48 40 32 24 16 8 0
32 33 34 35 36 37 38 39 63 55 47 39 31 23 15 7
40 41 42 43 44 45 46 47 61 53 45 37 29 21 13 5
48 49 50 51 52 53 54 55 59 51 43 35 27 19 11 3
56 57 58 59 60 61 62 63 57 49 41 33 25 17 9 1
The output has been subject to swaps of the form
0 1 -> 3 1 but the odd and even bits have been put into
2 3 2 0
different words. The main trick is to remember that
t=((l>>size)^r)&(mask);
r^=t;
l^=(t<<size);
can be used to swap and move bits between words.
So l = 0 1 2 3 r = 16 17 18 19
4 5 6 7 20 21 22 23
8 9 10 11 24 25 26 27
12 13 14 15 28 29 30 31
becomes (for size == 2 and mask == 0x3333)
t = 2^16 3^17 -- -- l = 0 1 16 17 r = 2 3 18 19
6^20 7^21 -- -- 4 5 20 21 6 7 22 23
10^24 11^25 -- -- 8 9 24 25 10 11 24 25
14^28 15^29 -- -- 12 13 28 29 14 15 28 29
Thanks for hints from Richard Outerbridge - he told me IP&FP
could be done in 15 xor, 10 shifts and 5 ands.
When I finally started to think of the problem in 2D
I first got ~42 operations without xors. When I remembered
how to use xors :-) I got it to its final state.
*/
#define PERM_OP(a,b,t,n,m) ((t)=((((a)>>(n))^(b))&(m)),\
(b)^=(t),\
(a)^=((t)<<(n)))
#define IP(l,r,t) \
PERM_OP(r,l,t, 4,0x0f0f0f0f); \
PERM_OP(l,r,t,16,0x0000ffff); \
PERM_OP(r,l,t, 2,0x33333333); \
PERM_OP(l,r,t, 8,0x00ff00ff); \
PERM_OP(r,l,t, 1,0x55555555);
#define FP(l,r,t) \
PERM_OP(l,r,t, 1,0x55555555); \
PERM_OP(r,l,t, 8,0x00ff00ff); \
PERM_OP(l,r,t, 2,0x33333333); \
PERM_OP(r,l,t,16,0x0000ffff); \
PERM_OP(l,r,t, 4,0x0f0f0f0f);
#define D_ENCRYPT(L,R,S) \
u=(R^s[S ]); \
t=R^s[S+1]; \
t=((t>>4)+(t<<28)); \
L^= des_SPtrans[1][(t )&0x3f]| \
des_SPtrans[3][(t>> 8)&0x3f]| \
des_SPtrans[5][(t>>16)&0x3f]| \
des_SPtrans[7][(t>>24)&0x3f]| \
des_SPtrans[0][(u )&0x3f]| \
des_SPtrans[2][(u>> 8)&0x3f]| \
des_SPtrans[4][(u>>16)&0x3f]| \
des_SPtrans[6][(u>>24)&0x3f];
/* This part is based on code that used to be in ecb_enc.c. */
/* Copyright (C) 1993 Eric Young - see README for more details */
static void des_encrypt(word32 l, word32 r, word32 *output, DESContext *ks,
int encrypt)
{
register word32 t,u;
register int i;
register word32 *s;
s = ks->key_schedule;
IP(l,r,t);
/* Things have been modified so that the initial rotate is
* done outside the loop. This required the
* des_SPtrans values in sp.h to be rotated 1 bit to the right.
* One perl script later and things have a 5% speed up on a sparc2.
* Thanks to Richard Outerbridge <71755.204@CompuServe.COM>
* for pointing this out. */
t=(r<<1)|(r>>31);
r=(l<<1)|(l>>31);
l=t;
/* I don't know if it is worth the effort of loop unrolling the
* inner loop */
if (encrypt)
{
for (i=0; i<32; i+=4)
{
D_ENCRYPT(l,r,i+0); /* 1 */
D_ENCRYPT(r,l,i+2); /* 2 */
}
}
else
{
for (i=30; i>0; i-=4)
{
D_ENCRYPT(l,r,i-0); /* 16 */
D_ENCRYPT(r,l,i-2); /* 15 */
}
}
l=(l>>1)|(l<<31);
r=(r>>1)|(r<<31);
FP(r,l,t);
output[0]=l;
output[1]=r;
}
/* Code based on set_key.c. */
/* Copyright (C) 1993 Eric Young - see README for more details */
#define HPERM_OP(a,t,n,m) ((t)=((((a)<<(16-(n)))^(a))&(m)),\
(a)=(a)^(t)^(t>>(16-(n))))
static void des_set_key(unsigned char *key, DESContext *ks)
{
register word32 c, d, t, s, shifts;
register int i;
register word32 *schedule;
schedule = ks->key_schedule;
c = GET_32BIT_LSB_FIRST(key);
d = GET_32BIT_LSB_FIRST(key + 4);
/* I now do it in 47 simple operations :-)
* Thanks to John Fletcher (john_fletcher@lccmail.ocf.llnl.gov)
* for the inspiration. :-) */
PERM_OP(d,c,t,4,0x0f0f0f0f);
HPERM_OP(c,t,-2,0xcccc0000);
HPERM_OP(d,t,-2,0xcccc0000);
PERM_OP(d,c,t,1,0x55555555);
PERM_OP(c,d,t,8,0x00ff00ff);
PERM_OP(d,c,t,1,0x55555555);
d = ((d & 0xff) << 16) | (d & 0xff00) |
((d >> 16) & 0xff) | ((c >> 4) & 0xf000000);
c&=0x0fffffff;
shifts = 0x7efc;
for (i=0; i < 16; i++)
{
if (shifts & 1)
{ c=((c>>2)|(c<<26)); d=((d>>2)|(d<<26)); }
else
{ c=((c>>1)|(c<<27)); d=((d>>1)|(d<<27)); }
shifts >>= 1;
c&=0x0fffffff;
d&=0x0fffffff;
/* could be a few less shifts but I am to lazy at this
* point in time to investigate */
s = des_skb[0][ (c )&0x3f ] |
des_skb[1][((c>> 6)&0x03)|((c>> 7)&0x3c)] |
des_skb[2][((c>>13)&0x0f)|((c>>14)&0x30)] |
des_skb[3][((c>>20)&0x01)|((c>>21)&0x06)|((c>>22)&0x38)];
t = des_skb[4][ (d )&0x3f ] |
des_skb[5][((d>> 7)&0x03)|((d>> 8)&0x3c)] |
des_skb[6][ (d>>15)&0x3f ] |
des_skb[7][((d>>21)&0x0f)|((d>>22)&0x30)];
/* table contained 0213 4657 */
*schedule++ = ((t << 16) | (s & 0xffff));
s = ((s >> 16) | (t & 0xffff0000));
*schedule++ = (s << 4) | (s >> 28);
}
}
static void des_cbc_encrypt(DESContext *ks, unsigned char *iv,
unsigned char *dest, const unsigned char *src,
unsigned int len)
{
word32 iv0, iv1, out[2];
unsigned int i;
assert((len & 7) == 0);
iv0 = GET_32BIT_LSB_FIRST(iv);
iv1 = GET_32BIT_LSB_FIRST(iv + 4);
for (i = 0; i < len; i += 8)
{
iv0 ^= GET_32BIT_LSB_FIRST(src + i);
iv1 ^= GET_32BIT_LSB_FIRST(src + i + 4);
des_encrypt(iv0, iv1, out, ks, 1);
iv0 = out[0];
iv1 = out[1];
PUT_32BIT_LSB_FIRST(dest + i, iv0);
PUT_32BIT_LSB_FIRST(dest + i + 4, iv1);
}
PUT_32BIT_LSB_FIRST(iv, iv0);
PUT_32BIT_LSB_FIRST(iv + 4, iv1);
}
static void des_cbc_decrypt(DESContext *ks, unsigned char *iv,
unsigned char *dest, const unsigned char *src,
unsigned int len)
{
word32 iv0, iv1, d0, d1, out[2];
unsigned int i;
assert((len & 7) == 0);
iv0 = GET_32BIT_LSB_FIRST(iv);
iv1 = GET_32BIT_LSB_FIRST(iv + 4);
for (i = 0; i < len; i += 8)
{
d0 = GET_32BIT_LSB_FIRST(src + i);
d1 = GET_32BIT_LSB_FIRST(src + i + 4);
des_encrypt(d0, d1, out, ks, 0);
iv0 ^= out[0];
iv1 ^= out[1];
PUT_32BIT_LSB_FIRST(dest + i, iv0);
PUT_32BIT_LSB_FIRST(dest + i + 4, iv1);
iv0 = d0;
iv1 = d1;
}
PUT_32BIT_LSB_FIRST(iv, iv0);
PUT_32BIT_LSB_FIRST(iv + 4, iv1);
}
static void des_3cbc_encrypt(DESContext *ks1, unsigned char *iv1,
DESContext *ks2, unsigned char *iv2,
DESContext *ks3, unsigned char *iv3,
unsigned char *dest, const unsigned char *src,
unsigned int len)
{
des_cbc_encrypt(ks1, iv1, dest, src, len);
des_cbc_decrypt(ks2, iv2, dest, dest, len);
des_cbc_encrypt(ks3, iv3, dest, dest, len);
}
static void des_3cbc_decrypt(DESContext *ks1, unsigned char *iv1,
DESContext *ks2, unsigned char *iv2,
DESContext *ks3, unsigned char *iv3,
unsigned char *dest, const unsigned char *src,
unsigned int len)
{
des_cbc_decrypt(ks3, iv3, dest, src, len);
des_cbc_encrypt(ks2, iv2, dest, dest, len);
des_cbc_decrypt(ks1, iv1, dest, dest, len);
}
DESContext ekey1, ekey2, ekey3;
unsigned char eiv1[8], eiv2[8], eiv3[8];
DESContext dkey1, dkey2, dkey3;
unsigned char div1[8], div2[8], div3[8];
static void des3_sesskey(unsigned char *key) {
des_set_key(key, &ekey1);
des_set_key(key+8, &ekey2);
des_set_key(key+16, &ekey3);
memset(eiv1, 0, sizeof(eiv1));
memset(eiv2, 0, sizeof(eiv2));
memset(eiv3, 0, sizeof(eiv3));
des_set_key(key, &dkey1);
des_set_key(key+8, &dkey2);
des_set_key(key+16, &dkey3);
memset(div1, 0, sizeof(div1));
memset(div2, 0, sizeof(div2));
memset(div3, 0, sizeof(div3));
}
static void des3_encrypt_blk(unsigned char *blk, int len) {
des_3cbc_encrypt(&ekey1, eiv1, &ekey2, eiv2, &ekey3, eiv3, blk, blk, len);
}
static void des3_decrypt_blk(unsigned char *blk, int len) {
des_3cbc_decrypt(&dkey1, div1, &dkey2, div2, &dkey3, div3, blk, blk, len);
}
struct ssh_cipher ssh_3des = {
des3_sesskey,
des3_encrypt_blk,
des3_decrypt_blk
};
#ifdef DES_TEST
void des_encrypt_buf(DESContext *ks, unsigned char *out,
const unsigned char *in, int encrypt)
{
word32 in0, in1, output[0];
in0 = GET_32BIT_LSB_FIRST(in);
in1 = GET_32BIT_LSB_FIRST(in + 4);
des_encrypt(in0, in1, output, ks, encrypt);
PUT_32BIT_LSB_FIRST(out, output[0]);
PUT_32BIT_LSB_FIRST(out + 4, output[1]);
}
int main(int ac, char **av)
{
FILE *f;
char line[1024], *cp;
int i, value;
unsigned char key[8], data[8], result[8], output[8];
DESContext ks;
while (fgets(line, sizeof(line), stdin))
{
for (i = 0; i < 8; i++)
{
if (sscanf(line + 2 * i, "%02x", &value) != 1)
{
fprintf(stderr, "1st col, i = %d, line: %s", i, line);
exit(1);
}
key[i] = value;
}
for (i = 0; i < 8; i++)
{
if (sscanf(line + 2 * i + 17, "%02x", &value) != 1)
{
fprintf(stderr, "2nd col, i = %d, line: %s", i, line);
exit(1);
}
data[i] = value;
}
for (i = 0; i < 8; i++)
{
if (sscanf(line + 2 * i + 2*17, "%02x", &value) != 1)
{
fprintf(stderr, "3rd col, i = %d, line: %s", i, line);
exit(1);
}
result[i] = value;
}
des_set_key(key, &ks);
des_encrypt_buf(&ks, output, data, 1);
if (memcmp(output, result, 8) != 0)
fprintf(stderr, "Encrypt failed: %s", line);
des_encrypt_buf(&ks, output, result, 0);
if (memcmp(output, data, 8) != 0)
fprintf(stderr, "Decrypt failed: %s", line);
}
exit(0);
}
#endif /* DES_TEST */

249
sshmd5.c Normal file
View File

@ -0,0 +1,249 @@
/* This code has been heavily hacked by Tatu Ylonen <ylo@cs.hut.fi> to
make it compile on machines like Cray that don't have a 32 bit integer
type. */
/*
* This code implements the MD5 message-digest algorithm.
* The algorithm is due to Ron Rivest. This code was
* written by Colin Plumb in 1993, no copyright is claimed.
* This code is in the public domain; do with it what you wish.
*
* Equivalent code is available from RSA Data Security, Inc.
* This code has been tested against that, and is equivalent,
* except that you don't need to include two pages of legalese
* with every copy.
*
* To compute the message digest of a chunk of bytes, declare an
* MD5Context structure, pass it to MD5Init, call MD5Update as
* needed on buffers full of bytes, and then call MD5Final, which
* will fill a supplied 16-byte array with the digest.
*/
#include "ssh.h"
#define GET_32BIT_LSB_FIRST(cp) \
(((unsigned long)(unsigned char)(cp)[0]) | \
((unsigned long)(unsigned char)(cp)[1] << 8) | \
((unsigned long)(unsigned char)(cp)[2] << 16) | \
((unsigned long)(unsigned char)(cp)[3] << 24))
#define PUT_32BIT_LSB_FIRST(cp, value) do { \
(cp)[0] = (value); \
(cp)[1] = (value) >> 8; \
(cp)[2] = (value) >> 16; \
(cp)[3] = (value) >> 24; } while (0)
void MD5Transform(uint32 buf[4], const unsigned char in[64]);
/*
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
* initialization constants.
*/
void MD5Init(struct MD5Context *ctx)
{
ctx->buf[0] = 0x67452301;
ctx->buf[1] = 0xefcdab89;
ctx->buf[2] = 0x98badcfe;
ctx->buf[3] = 0x10325476;
ctx->bits[0] = 0;
ctx->bits[1] = 0;
}
/*
* Update context to reflect the concatenation of another buffer full
* of bytes.
*/
void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
{
uint32 t;
/* Update bitcount */
t = ctx->bits[0];
if ((ctx->bits[0] = (t + ((uint32)len << 3)) & 0xffffffff) < t)
ctx->bits[1]++; /* Carry from low to high */
ctx->bits[1] += len >> 29;
t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
/* Handle any leading odd-sized chunks */
if (t) {
unsigned char *p = ctx->in + t;
t = 64 - t;
if (len < t) {
memcpy(p, buf, len);
return;
}
memcpy(p, buf, t);
MD5Transform(ctx->buf, ctx->in);
buf += t;
len -= t;
}
/* Process data in 64-byte chunks */
while (len >= 64) {
memcpy(ctx->in, buf, 64);
MD5Transform(ctx->buf, ctx->in);
buf += 64;
len -= 64;
}
/* Handle any remaining bytes of data. */
memcpy(ctx->in, buf, len);
}
/*
* Final wrapup - pad to 64-byte boundary with the bit pattern
* 1 0* (64-bit count of bits processed, MSB-first)
*/
void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
{
unsigned count;
unsigned char *p;
/* Compute number of bytes mod 64 */
count = (ctx->bits[0] >> 3) & 0x3F;
/* Set the first char of padding to 0x80. This is safe since there is
always at least one byte free */
p = ctx->in + count;
*p++ = 0x80;
/* Bytes of padding needed to make 64 bytes */
count = 64 - 1 - count;
/* Pad out to 56 mod 64 */
if (count < 8) {
/* Two lots of padding: Pad the first block to 64 bytes */
memset(p, 0, count);
MD5Transform(ctx->buf, ctx->in);
/* Now fill the next block with 56 bytes */
memset(ctx->in, 0, 56);
} else {
/* Pad block to 56 bytes */
memset(p, 0, count - 8);
}
/* Append length in bits and transform */
PUT_32BIT_LSB_FIRST(ctx->in + 56, ctx->bits[0]);
PUT_32BIT_LSB_FIRST(ctx->in + 60, ctx->bits[1]);
MD5Transform(ctx->buf, ctx->in);
PUT_32BIT_LSB_FIRST(digest, ctx->buf[0]);
PUT_32BIT_LSB_FIRST(digest + 4, ctx->buf[1]);
PUT_32BIT_LSB_FIRST(digest + 8, ctx->buf[2]);
PUT_32BIT_LSB_FIRST(digest + 12, ctx->buf[3]);
memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */
}
#ifndef ASM_MD5
/* The four core functions - F1 is optimized somewhat */
/* #define F1(x, y, z) (x & y | ~x & z) */
#define F1(x, y, z) (z ^ (x & (y ^ z)))
#define F2(x, y, z) F1(z, x, y)
#define F3(x, y, z) (x ^ y ^ z)
#define F4(x, y, z) (y ^ (x | ~z))
/* This is the central step in the MD5 algorithm. */
#define MD5STEP(f, w, x, y, z, data, s) \
( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
/*
* The core of the MD5 algorithm, this alters an existing MD5 hash to
* reflect the addition of 16 longwords of new data. MD5Update blocks
* the data and converts bytes into longwords for this routine.
*/
void MD5Transform(uint32 buf[4], const unsigned char inext[64])
{
register word32 a, b, c, d, i;
word32 in[16];
for (i = 0; i < 16; i++)
in[i] = GET_32BIT_LSB_FIRST(inext + 4 * i);
a = buf[0];
b = buf[1];
c = buf[2];
d = buf[3];
MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
buf[0] += a;
buf[1] += b;
buf[2] += c;
buf[3] += d;
}
#endif

169
sshrand.c Normal file
View File

@ -0,0 +1,169 @@
/*
* cryptographic random number generator for PuTTY's ssh client
*/
#include "ssh.h"
void noise_get_heavy(void (*func) (void *, int));
void noise_get_light(void (*func) (void *, int));
/*
* `pool' itself is a pool of random data which we actually use: we
* return bytes from `pool', at position `poolpos', until `poolpos'
* reaches the end of the pool. At this point we generate more
* random data, by adding noise, stirring well, and resetting
* `poolpos' to point to just past the beginning of the pool (not
* _the_ beginning, since otherwise we'd give away the whole
* contents of our pool, and attackers would just have to guess the
* next lot of noise).
*
* `incomingb' buffers acquired noise data, until it gets full, at
* which point the acquired noise is SHA'ed into `incoming' and
* `incomingb' is cleared. The noise in `incoming' is used as part
* of the noise for each stirring of the pool, in addition to local
* time, process listings, and other such stuff.
*/
#define HASHINPUT 64 /* 64 bytes SHA input */
#define HASHSIZE 20 /* 160 bits SHA output */
#define POOLSIZE 1200 /* size of random pool */
struct RandPool {
unsigned char pool[POOLSIZE];
int poolpos;
unsigned char incoming[HASHSIZE];
unsigned char incomingb[HASHINPUT];
int incomingpos;
};
static struct RandPool pool;
void random_add_noise(void *noise, int length) {
unsigned char *p = noise;
while (length >= (HASHINPUT - pool.incomingpos)) {
memcpy(pool.incomingb + pool.incomingpos, p,
HASHINPUT - pool.incomingpos);
p += HASHINPUT - pool.incomingpos;
length -= HASHINPUT - pool.incomingpos;
SHATransform((word32 *)pool.incoming, (word32 *)pool.incomingb);
pool.incomingpos = 0;
}
memcpy(pool.incomingb, p, length);
pool.incomingpos = length;
}
void random_stir(void) {
word32 block[HASHINPUT/sizeof(word32)];
word32 digest[HASHSIZE/sizeof(word32)];
int i, j, k;
noise_get_light(random_add_noise);
SHATransform((word32 *)pool.incoming, (word32 *)pool.incomingb);
pool.incomingpos = 0;
/*
* Chunks of this code are blatantly endianness-dependent, but
* as it's all random bits anyway, WHO CARES?
*/
memcpy(digest, pool.incoming, sizeof(digest));
/*
* Make two passes over the pool.
*/
for (i = 0; i < 2; i++) {
/*
* We operate SHA in CFB mode, repeatedly adding the same
* block of data to the digest. But we're also fiddling
* with the digest-so-far, so this shouldn't be Bad or
* anything.
*/
memcpy(block, pool.pool, sizeof(block));
/*
* Each pass processes the pool backwards in blocks of
* HASHSIZE, just so that in general we get the output of
* SHA before the corresponding input, in the hope that
* things will be that much less predictable that way
* round, when we subsequently return bytes ...
*/
for (j = POOLSIZE; (j -= HASHSIZE) >= 0 ;) {
/*
* XOR the bit of the pool we're processing into the
* digest.
*/
for (k = 0; k < sizeof(digest)/sizeof(*digest); k++)
digest[k] ^= ((word32 *)(pool.pool+j))[k];
/*
* Munge our unrevealed first block of the pool into
* it.
*/
SHATransform(digest, block);
/*
* Stick the result back into the pool.
*/
for (k = 0; k < sizeof(digest)/sizeof(*digest); k++)
((word32 *)(pool.pool+j))[k] = digest[k];
}
}
/*
* Might as well save this value back into `incoming', just so
* there'll be some extra bizarreness there.
*/
SHATransform(digest, block);
memcpy(digest, pool.incoming, sizeof(digest));
pool.poolpos = sizeof(pool.incoming);
}
static void random_add_heavynoise(void *noise, int length) {
unsigned char *p = noise;
while (length >= (POOLSIZE - pool.poolpos)) {
memcpy(pool.pool + pool.poolpos, p, POOLSIZE - pool.poolpos);
p += POOLSIZE - pool.poolpos;
length -= POOLSIZE - pool.poolpos;
random_stir();
pool.poolpos = 0;
}
memcpy(pool.pool, p, length);
pool.poolpos = length;
}
void random_init(void) {
memset(&pool, 0, sizeof(pool)); /* just to start with */
/*
* For noise_get_heavy, we temporarily use `poolpos' as the
* pointer for addition of noise, rather than extraction of
* random numbers.
*/
pool.poolpos = 0;
noise_get_heavy(random_add_heavynoise);
random_stir();
}
int random_byte(void) {
if (pool.poolpos >= POOLSIZE)
random_stir();
return pool.pool[pool.poolpos++];
}
void random_get_savedata(void **data, int *len) {
random_stir();
*data = pool.pool+pool.poolpos;
*len = POOLSIZE/2;
}

412
sshrsa.c Normal file
View File

@ -0,0 +1,412 @@
/*
* RSA implementation just sufficient for ssh client-side
* initialisation step
*/
/*#include <windows.h>
#define RSADEBUG
#define DLVL 2
#include "stel.h"*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ssh.h"
typedef unsigned short *Bignum;
static unsigned short Zero[1] = { 0 };
#if defined TESTMODE || defined RSADEBUG
#ifndef DLVL
#define DLVL 10000
#endif
#define debug(x) bndebug(#x,x)
static int level = 0;
static void bndebug(char *name, Bignum b) {
int i;
int w = 50-level-strlen(name)-5*b[0];
if (level >= DLVL)
return;
if (w < 0) w = 0;
dprintf("%*s%s%*s", level, "", name, w, "");
for (i=b[0]; i>0; i--)
dprintf(" %04x", b[i]);
dprintf("\n");
}
#define dmsg(x) do {if(level<DLVL){dprintf("%*s",level,"");printf x;}} while(0)
#define enter(x) do { dmsg(x); level += 4; } while(0)
#define leave(x) do { level -= 4; dmsg(x); } while(0)
#else
#define debug(x)
#define dmsg(x)
#define enter(x)
#define leave(x)
#endif
static Bignum newbn(int length) {
Bignum b = malloc((length+1)*sizeof(unsigned short));
if (!b)
abort(); /* FIXME */
b[0] = length;
return b;
}
static void freebn(Bignum b) {
free(b);
}
static int msb(Bignum r) {
int i;
int j;
unsigned short n;
for (i=r[0]; i>0; i--)
if (r[i])
break;
j = (i-1)*16;
n = r[i];
if (n & 0xFF00) j += 8, n >>= 8;
if (n & 0x00F0) j += 4, n >>= 4;
if (n & 0x000C) j += 2, n >>= 2;
if (n & 0x0002) j += 1, n >>= 1;
return j;
}
static void add(Bignum r1, Bignum r2, Bignum result) {
int i;
long stuff = 0;
enter((">add\n"));
debug(r1);
debug(r2);
for (i = 1 ;; i++) {
if (i <= r1[0])
stuff += r1[i];
if (i <= r2[0])
stuff += r2[i];
if (i <= result[0])
result[i] = stuff & 0xFFFFU;
if (i > r1[0] && i > r2[0] && i >= result[0])
break;
stuff >>= 16;
}
debug(result);
leave(("<add\n"));
}
static void sub(Bignum r1, Bignum r2, Bignum result) {
int i;
long stuff = 0;
enter((">sub\n"));
debug(r1);
debug(r2);
for (i = 1 ;; i++) {
if (i <= r1[0])
stuff += r1[i];
if (i <= r2[0])
stuff -= r2[i];
if (i <= result[0])
result[i] = stuff & 0xFFFFU;
if (i > r1[0] && i > r2[0] && i >= result[0])
break;
stuff = stuff<0 ? -1 : 0;
}
debug(result);
leave(("<sub\n"));
}
static int ge(Bignum r1, Bignum r2) {
int i;
enter((">ge\n"));
debug(r1);
debug(r2);
if (r1[0] < r2[0])
i = r2[0];
else
i = r1[0];
while (i > 0) {
unsigned short n1 = (i > r1[0] ? 0 : r1[i]);
unsigned short n2 = (i > r2[0] ? 0 : r2[i]);
if (n1 > n2) {
dmsg(("greater\n"));
leave(("<ge\n"));
return 1; /* r1 > r2 */
} else if (n1 < n2) {
dmsg(("less\n"));
leave(("<ge\n"));
return 0; /* r1 < r2 */
}
i--;
}
dmsg(("equal\n"));
leave(("<ge\n"));
return 1; /* r1 = r2 */
}
static void modmult(Bignum r1, Bignum r2, Bignum modulus, Bignum result) {
Bignum temp = newbn(modulus[0]+1);
Bignum tmp2 = newbn(modulus[0]+1);
int i;
int bit, bits, digit, smallbit;
enter((">modmult\n"));
debug(r1);
debug(r2);
debug(modulus);
for (i=1; i<=result[0]; i++)
result[i] = 0; /* result := 0 */
for (i=1; i<=temp[0]; i++)
temp[i] = (i > r2[0] ? 0 : r2[i]); /* temp := r2 */
bits = 1+msb(r1);
for (bit = 0; bit < bits; bit++) {
digit = 1 + bit / 16;
smallbit = bit % 16;
debug(temp);
if (digit <= r1[0] && (r1[digit] & (1<<smallbit))) {
dmsg(("bit %d\n", bit));
add(temp, result, tmp2);
if (ge(tmp2, modulus))
sub(tmp2, modulus, result);
else
add(tmp2, Zero, result);
debug(result);
}
add(temp, temp, tmp2);
if (ge(tmp2, modulus))
sub(tmp2, modulus, temp);
else
add(tmp2, Zero, temp);
}
freebn(temp);
freebn(tmp2);
debug(result);
leave(("<modmult\n"));
}
static void modpow(Bignum r1, Bignum r2, Bignum modulus, Bignum result) {
Bignum temp = newbn(modulus[0]+1);
Bignum tmp2 = newbn(modulus[0]+1);
int i;
int bit, bits, digit, smallbit;
enter((">modpow\n"));
debug(r1);
debug(r2);
debug(modulus);
for (i=1; i<=result[0]; i++)
result[i] = (i==1); /* result := 1 */
for (i=1; i<=temp[0]; i++)
temp[i] = (i > r1[0] ? 0 : r1[i]); /* temp := r1 */
bits = 1+msb(r2);
for (bit = 0; bit < bits; bit++) {
digit = 1 + bit / 16;
smallbit = bit % 16;
debug(temp);
if (digit <= r2[0] && (r2[digit] & (1<<smallbit))) {
dmsg(("bit %d\n", bit));
modmult(temp, result, modulus, tmp2);
add(tmp2, Zero, result);
debug(result);
}
modmult(temp, temp, modulus, tmp2);
add(tmp2, Zero, temp);
}
freebn(temp);
freebn(tmp2);
debug(result);
leave(("<modpow\n"));
}
int makekey(unsigned char *data, struct RSAKey *result,
unsigned char **keystr) {
unsigned char *p = data;
Bignum bn[2];
int i, j;
int w, b;
result->bits = 0;
for (i=0; i<4; i++)
result->bits = (result->bits << 8) + *p++;
for (j=0; j<2; j++) {
w = 0;
for (i=0; i<2; i++)
w = (w << 8) + *p++;
result->bytes = b = (w+7)/8; /* bits -> bytes */
w = (w+15)/16; /* bits -> words */
bn[j] = newbn(w);
if (keystr) *keystr = p; /* point at key string, second time */
for (i=1; i<=w; i++)
bn[j][i] = 0;
for (i=0; i<b; i++) {
unsigned char byte = *p++;
if ((b-i) & 1)
bn[j][w-i/2] |= byte;
else
bn[j][w-i/2] |= byte<<8;
}
debug(bn[j]);
}
result->exponent = bn[0];
result->modulus = bn[1];
return p - data;
}
void rsaencrypt(unsigned char *data, int length, struct RSAKey *key) {
Bignum b1, b2;
int w, i;
unsigned char *p;
debug(key->exponent);
memmove(data+key->bytes-length, data, length);
data[0] = 0;
data[1] = 2;
for (i = 2; i < key->bytes-length-1; i++) {
do {
data[i] = random_byte();
} while (data[i] == 0);
}
data[key->bytes-length-1] = 0;
w = (key->bytes+1)/2;
b1 = newbn(w);
b2 = newbn(w);
p = data;
for (i=1; i<=w; i++)
b1[i] = 0;
for (i=0; i<key->bytes; i++) {
unsigned char byte = *p++;
if ((key->bytes-i) & 1)
b1[w-i/2] |= byte;
else
b1[w-i/2] |= byte<<8;
}
debug(b1);
modpow(b1, key->exponent, key->modulus, b2);
debug(b2);
p = data;
for (i=0; i<key->bytes; i++) {
unsigned char b;
if (i & 1)
b = b2[w-i/2] & 0xFF;
else
b = b2[w-i/2] >> 8;
*p++ = b;
}
freebn(b1);
freebn(b2);
}
int rsastr_len(struct RSAKey *key) {
Bignum md, ex;
md = key->modulus;
ex = key->exponent;
return 4 * (ex[0]+md[0]) + 10;
}
void rsastr_fmt(char *str, struct RSAKey *key) {
Bignum md, ex;
int len = 0, i;
md = key->modulus;
ex = key->exponent;
for (i=1; i<=ex[0]; i++) {
sprintf(str+len, "%04x", ex[i]);
len += strlen(str+len);
}
str[len++] = '/';
for (i=1; i<=md[0]; i++) {
sprintf(str+len, "%04x", md[i]);
len += strlen(str+len);
}
str[len] = '\0';
}
#ifdef TESTMODE
#ifndef NODDY
#define p1 10007
#define p2 10069
#define p3 10177
#else
#define p1 3
#define p2 7
#define p3 13
#endif
unsigned short P1[2] = { 1, p1 };
unsigned short P2[2] = { 1, p2 };
unsigned short P3[2] = { 1, p3 };
unsigned short bigmod[5] = { 4, 0, 0, 0, 32768U };
unsigned short mod[5] = { 4, 0, 0, 0, 0 };
unsigned short a[5] = { 4, 0, 0, 0, 0 };
unsigned short b[5] = { 4, 0, 0, 0, 0 };
unsigned short c[5] = { 4, 0, 0, 0, 0 };
unsigned short One[2] = { 1, 1 };
unsigned short Two[2] = { 1, 2 };
int main(void) {
modmult(P1, P2, bigmod, a); debug(a);
modmult(a, P3, bigmod, mod); debug(mod);
sub(P1, One, a); debug(a);
sub(P2, One, b); debug(b);
modmult(a, b, bigmod, c); debug(c);
sub(P3, One, a); debug(a);
modmult(a, c, bigmod, b); debug(b);
modpow(Two, b, mod, a); debug(a);
return 0;
}
#endif

141
sshsha.c Normal file
View File

@ -0,0 +1,141 @@
/*
* The following code was taken directly from drivers/char/random.c
* in the Linux kernel.
*/
#include "ssh.h"
/*
* SHA transform algorithm, taken from code written by Peter Gutman,
* and apparently in the public domain.
*/
/* The SHA f()-functions. */
#define f1(x,y,z) ( z ^ ( x & ( y ^ z ) ) ) /* Rounds 0-19 */
#define f2(x,y,z) ( x ^ y ^ z ) /* Rounds 20-39 */
#define f3(x,y,z) ( ( x & y ) | ( z & ( x | y ) ) ) /* Rounds 40-59 */
#define f4(x,y,z) ( x ^ y ^ z ) /* Rounds 60-79 */
/* The SHA Mysterious Constants */
#define K1 0x5A827999L /* Rounds 0-19 */
#define K2 0x6ED9EBA1L /* Rounds 20-39 */
#define K3 0x8F1BBCDCL /* Rounds 40-59 */
#define K4 0xCA62C1D6L /* Rounds 60-79 */
#define ROTL(n,X) ( ( ( X ) << n ) | ( ( X ) >> ( 32 - n ) ) )
#define expand(W,i) ( W[ i & 15 ] = \
ROTL( 1, ( W[ i & 15 ] ^ W[ (i - 14) & 15 ] ^ \
W[ (i - 8) & 15 ] ^ W[ (i - 3) & 15 ] ) ) )
#define subRound(a, b, c, d, e, f, k, data) \
( e += ROTL( 5, a ) + f( b, c, d ) + k + data, b = ROTL( 30, b ) )
void SHATransform(word32 *digest, word32 *data)
{
word32 A, B, C, D, E; /* Local vars */
word32 eData[ 16 ]; /* Expanded data */
/* Set up first buffer and local data buffer */
A = digest[ 0 ];
B = digest[ 1 ];
C = digest[ 2 ];
D = digest[ 3 ];
E = digest[ 4 ];
memcpy( eData, data, 16*sizeof(word32));
/* Heavy mangling, in 4 sub-rounds of 20 iterations each. */
subRound( A, B, C, D, E, f1, K1, eData[ 0 ] );
subRound( E, A, B, C, D, f1, K1, eData[ 1 ] );
subRound( D, E, A, B, C, f1, K1, eData[ 2 ] );
subRound( C, D, E, A, B, f1, K1, eData[ 3 ] );
subRound( B, C, D, E, A, f1, K1, eData[ 4 ] );
subRound( A, B, C, D, E, f1, K1, eData[ 5 ] );
subRound( E, A, B, C, D, f1, K1, eData[ 6 ] );
subRound( D, E, A, B, C, f1, K1, eData[ 7 ] );
subRound( C, D, E, A, B, f1, K1, eData[ 8 ] );
subRound( B, C, D, E, A, f1, K1, eData[ 9 ] );
subRound( A, B, C, D, E, f1, K1, eData[ 10 ] );
subRound( E, A, B, C, D, f1, K1, eData[ 11 ] );
subRound( D, E, A, B, C, f1, K1, eData[ 12 ] );
subRound( C, D, E, A, B, f1, K1, eData[ 13 ] );
subRound( B, C, D, E, A, f1, K1, eData[ 14 ] );
subRound( A, B, C, D, E, f1, K1, eData[ 15 ] );
subRound( E, A, B, C, D, f1, K1, expand( eData, 16 ) );
subRound( D, E, A, B, C, f1, K1, expand( eData, 17 ) );
subRound( C, D, E, A, B, f1, K1, expand( eData, 18 ) );
subRound( B, C, D, E, A, f1, K1, expand( eData, 19 ) );
subRound( A, B, C, D, E, f2, K2, expand( eData, 20 ) );
subRound( E, A, B, C, D, f2, K2, expand( eData, 21 ) );
subRound( D, E, A, B, C, f2, K2, expand( eData, 22 ) );
subRound( C, D, E, A, B, f2, K2, expand( eData, 23 ) );
subRound( B, C, D, E, A, f2, K2, expand( eData, 24 ) );
subRound( A, B, C, D, E, f2, K2, expand( eData, 25 ) );
subRound( E, A, B, C, D, f2, K2, expand( eData, 26 ) );
subRound( D, E, A, B, C, f2, K2, expand( eData, 27 ) );
subRound( C, D, E, A, B, f2, K2, expand( eData, 28 ) );
subRound( B, C, D, E, A, f2, K2, expand( eData, 29 ) );
subRound( A, B, C, D, E, f2, K2, expand( eData, 30 ) );
subRound( E, A, B, C, D, f2, K2, expand( eData, 31 ) );
subRound( D, E, A, B, C, f2, K2, expand( eData, 32 ) );
subRound( C, D, E, A, B, f2, K2, expand( eData, 33 ) );
subRound( B, C, D, E, A, f2, K2, expand( eData, 34 ) );
subRound( A, B, C, D, E, f2, K2, expand( eData, 35 ) );
subRound( E, A, B, C, D, f2, K2, expand( eData, 36 ) );
subRound( D, E, A, B, C, f2, K2, expand( eData, 37 ) );
subRound( C, D, E, A, B, f2, K2, expand( eData, 38 ) );
subRound( B, C, D, E, A, f2, K2, expand( eData, 39 ) );
subRound( A, B, C, D, E, f3, K3, expand( eData, 40 ) );
subRound( E, A, B, C, D, f3, K3, expand( eData, 41 ) );
subRound( D, E, A, B, C, f3, K3, expand( eData, 42 ) );
subRound( C, D, E, A, B, f3, K3, expand( eData, 43 ) );
subRound( B, C, D, E, A, f3, K3, expand( eData, 44 ) );
subRound( A, B, C, D, E, f3, K3, expand( eData, 45 ) );
subRound( E, A, B, C, D, f3, K3, expand( eData, 46 ) );
subRound( D, E, A, B, C, f3, K3, expand( eData, 47 ) );
subRound( C, D, E, A, B, f3, K3, expand( eData, 48 ) );
subRound( B, C, D, E, A, f3, K3, expand( eData, 49 ) );
subRound( A, B, C, D, E, f3, K3, expand( eData, 50 ) );
subRound( E, A, B, C, D, f3, K3, expand( eData, 51 ) );
subRound( D, E, A, B, C, f3, K3, expand( eData, 52 ) );
subRound( C, D, E, A, B, f3, K3, expand( eData, 53 ) );
subRound( B, C, D, E, A, f3, K3, expand( eData, 54 ) );
subRound( A, B, C, D, E, f3, K3, expand( eData, 55 ) );
subRound( E, A, B, C, D, f3, K3, expand( eData, 56 ) );
subRound( D, E, A, B, C, f3, K3, expand( eData, 57 ) );
subRound( C, D, E, A, B, f3, K3, expand( eData, 58 ) );
subRound( B, C, D, E, A, f3, K3, expand( eData, 59 ) );
subRound( A, B, C, D, E, f4, K4, expand( eData, 60 ) );
subRound( E, A, B, C, D, f4, K4, expand( eData, 61 ) );
subRound( D, E, A, B, C, f4, K4, expand( eData, 62 ) );
subRound( C, D, E, A, B, f4, K4, expand( eData, 63 ) );
subRound( B, C, D, E, A, f4, K4, expand( eData, 64 ) );
subRound( A, B, C, D, E, f4, K4, expand( eData, 65 ) );
subRound( E, A, B, C, D, f4, K4, expand( eData, 66 ) );
subRound( D, E, A, B, C, f4, K4, expand( eData, 67 ) );
subRound( C, D, E, A, B, f4, K4, expand( eData, 68 ) );
subRound( B, C, D, E, A, f4, K4, expand( eData, 69 ) );
subRound( A, B, C, D, E, f4, K4, expand( eData, 70 ) );
subRound( E, A, B, C, D, f4, K4, expand( eData, 71 ) );
subRound( D, E, A, B, C, f4, K4, expand( eData, 72 ) );
subRound( C, D, E, A, B, f4, K4, expand( eData, 73 ) );
subRound( B, C, D, E, A, f4, K4, expand( eData, 74 ) );
subRound( A, B, C, D, E, f4, K4, expand( eData, 75 ) );
subRound( E, A, B, C, D, f4, K4, expand( eData, 76 ) );
subRound( D, E, A, B, C, f4, K4, expand( eData, 77 ) );
subRound( C, D, E, A, B, f4, K4, expand( eData, 78 ) );
subRound( B, C, D, E, A, f4, K4, expand( eData, 79 ) );
/* Build message digest */
digest[ 0 ] += A;
digest[ 1 ] += B;
digest[ 2 ] += C;
digest[ 3 ] += D;
digest[ 4 ] += E;
}

720
telnet.c Normal file
View File

@ -0,0 +1,720 @@
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <winsock.h>
#include "putty.h"
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
static SOCKET s = INVALID_SOCKET;
#define IAC 255 /* interpret as command: */
#define DONT 254 /* you are not to use option */
#define DO 253 /* please, you use option */
#define WONT 252 /* I won't use option */
#define WILL 251 /* I will use option */
#define SB 250 /* interpret as subnegotiation */
#define SE 240 /* end sub negotiation */
#define GA 249 /* you may reverse the line */
#define EL 248 /* erase the current line */
#define EC 247 /* erase the current character */
#define AYT 246 /* are you there */
#define AO 245 /* abort output--but let prog finish */
#define IP 244 /* interrupt process--permanently */
#define BREAK 243 /* break */
#define DM 242 /* data mark--for connect. cleaning */
#define NOP 241 /* nop */
#define EOR 239 /* end of record (transparent mode) */
#define ABORT 238 /* Abort process */
#define SUSP 237 /* Suspend process */
#define xEOF 236 /* End of file: EOF is already used... */
#define TELOPT_BINARY 0 /* 8-bit data path */
#define TELOPT_ECHO 1 /* echo */
#define TELOPT_RCP 2 /* prepare to reconnect */
#define TELOPT_SGA 3 /* suppress go ahead */
#define TELOPT_NAMS 4 /* approximate message size */
#define TELOPT_STATUS 5 /* give status */
#define TELOPT_TM 6 /* timing mark */
#define TELOPT_RCTE 7 /* remote controlled transmission and echo */
#define TELOPT_NAOL 8 /* negotiate about output line width */
#define TELOPT_NAOP 9 /* negotiate about output page size */
#define TELOPT_NAOCRD 10 /* negotiate about CR disposition */
#define TELOPT_NAOHTS 11 /* negotiate about horizontal tabstops */
#define TELOPT_NAOHTD 12 /* negotiate about horizontal tab disposition */
#define TELOPT_NAOFFD 13 /* negotiate about formfeed disposition */
#define TELOPT_NAOVTS 14 /* negotiate about vertical tab stops */
#define TELOPT_NAOVTD 15 /* negotiate about vertical tab disposition */
#define TELOPT_NAOLFD 16 /* negotiate about output LF disposition */
#define TELOPT_XASCII 17 /* extended ascic character set */
#define TELOPT_LOGOUT 18 /* force logout */
#define TELOPT_BM 19 /* byte macro */
#define TELOPT_DET 20 /* data entry terminal */
#define TELOPT_SUPDUP 21 /* supdup protocol */
#define TELOPT_SUPDUPOUTPUT 22 /* supdup output */
#define TELOPT_SNDLOC 23 /* send location */
#define TELOPT_TTYPE 24 /* terminal type */
#define TELOPT_EOR 25 /* end or record */
#define TELOPT_TUID 26 /* TACACS user identification */
#define TELOPT_OUTMRK 27 /* output marking */
#define TELOPT_TTYLOC 28 /* terminal location number */
#define TELOPT_3270REGIME 29 /* 3270 regime */
#define TELOPT_X3PAD 30 /* X.3 PAD */
#define TELOPT_NAWS 31 /* window size */
#define TELOPT_TSPEED 32 /* terminal speed */
#define TELOPT_LFLOW 33 /* remote flow control */
#define TELOPT_LINEMODE 34 /* Linemode option */
#define TELOPT_XDISPLOC 35 /* X Display Location */
#define TELOPT_OLD_ENVIRON 36 /* Old - Environment variables */
#define TELOPT_AUTHENTICATION 37/* Authenticate */
#define TELOPT_ENCRYPT 38 /* Encryption option */
#define TELOPT_NEW_ENVIRON 39 /* New - Environment variables */
#define TELOPT_EXOPL 255 /* extended-options-list */
#define TELQUAL_IS 0 /* option is... */
#define TELQUAL_SEND 1 /* send option */
#define TELQUAL_INFO 2 /* ENVIRON: informational version of IS */
#define BSD_VAR 1
#define BSD_VALUE 0
#define RFC_VAR 0
#define RFC_VALUE 1
#define CR 13
#define LF 10
#define NUL 0
#define iswritable(x) ( (x) != IAC && (x) != CR )
static char *telopt(int opt) {
#define i(x) if (opt == TELOPT_ ## x) return #x;
i(BINARY); i(ECHO); i(RCP); i(SGA); i(NAMS); i(STATUS); i(TM); i(RCTE);
i(NAOL); i(NAOP); i(NAOCRD); i(NAOHTS); i(NAOHTD); i(NAOFFD); i(NAOVTS);
i(NAOVTD); i(NAOLFD); i(XASCII); i(LOGOUT); i(BM); i(DET); i(SUPDUP);
i(SUPDUPOUTPUT); i(SNDLOC); i(TTYPE); i(EOR); i(TUID); i(OUTMRK);
i(TTYLOC); i(X3PAD); i(NAWS); i(TSPEED); i(LFLOW); i(LINEMODE);
i(XDISPLOC); i(OLD_ENVIRON); i(AUTHENTICATION); i(ENCRYPT);
i(NEW_ENVIRON); i(EXOPL);
#undef i
return "<unknown>";
}
static void telnet_size(void);
struct Opt {
int send; /* what we initially send */
int nsend; /* -ve send if requested to stop it */
int ack, nak; /* +ve and -ve acknowledgements */
int option; /* the option code */
enum {
REQUESTED, ACTIVE, INACTIVE, REALLY_INACTIVE
} state;
};
static struct Opt o_naws = {WILL, WONT, DO, DONT, TELOPT_NAWS, REQUESTED};
static struct Opt o_tspeed = {WILL, WONT, DO, DONT, TELOPT_TSPEED, REQUESTED};
static struct Opt o_ttype = {WILL, WONT, DO, DONT, TELOPT_TTYPE, REQUESTED};
static struct Opt o_oenv = {WILL, WONT, DO, DONT, TELOPT_OLD_ENVIRON,
INACTIVE};
static struct Opt o_nenv = {WILL, WONT, DO, DONT, TELOPT_NEW_ENVIRON,
REQUESTED};
static struct Opt o_echo = {DO, DONT, WILL, WONT, TELOPT_ECHO, REQUESTED};
static struct Opt o_we_sga = {WILL, WONT, DO, DONT, TELOPT_SGA, REQUESTED};
static struct Opt o_they_sga = {DO, DONT, WILL, WONT, TELOPT_SGA, REQUESTED};
static struct Opt *opts[] = {
&o_naws, &o_tspeed, &o_ttype, &o_oenv, &o_nenv, &o_echo,
&o_we_sga, &o_they_sga, NULL
};
#if 0
static int in_synch;
#endif
static int sb_opt, sb_len;
static char *sb_buf = NULL;
static int sb_size = 0;
#define SB_DELTA 1024
static void try_write (void) {
while (outbuf_head != outbuf_reap) {
int end = (outbuf_reap < outbuf_head ? outbuf_head : OUTBUF_SIZE);
int len = end - outbuf_reap;
int ret;
ret = send (s, outbuf+outbuf_reap, len, 0);
if (ret > 0)
outbuf_reap = (outbuf_reap + ret) & OUTBUF_MASK;
if (ret < len)
return;
}
}
static void s_write (void *buf, int len) {
unsigned char *p = buf;
while (len--) {
int new_head = (outbuf_head + 1) & OUTBUF_MASK;
if (new_head != outbuf_reap) {
outbuf[outbuf_head] = *p++;
outbuf_head = new_head;
}
}
try_write();
}
static void c_write (char *buf, int len) {
while (len--) {
int new_head = (inbuf_head + 1) & INBUF_MASK;
int c = (unsigned char) *buf;
if (new_head != inbuf_reap) {
inbuf[inbuf_head] = *buf++;
inbuf_head = new_head;
}
}
}
static void log_option (char *sender, int cmd, int option) {
char buf[50];
sprintf(buf, "%s:\t%s %s", sender,
(cmd == WILL ? "WILL" : cmd == WONT ? "WONT" :
cmd == DO ? "DO" : cmd == DONT ? "DONT" : "<??>"),
telopt(option));
lognegot(buf);
}
static void send_opt (int cmd, int option) {
unsigned char b[3];
b[0] = IAC; b[1] = cmd; b[2] = option;
s_write (b, 3);
log_option("client", cmd, option);
}
static void deactivate_option (struct Opt *o) {
if (o->state == REQUESTED || o->state == ACTIVE)
send_opt (o->nsend, o->option);
o->state = REALLY_INACTIVE;
}
static void activate_option (struct Opt *o) {
if (o->send == WILL && o->option == TELOPT_NAWS)
telnet_size();
if (o->send == WILL &&
(o->option == TELOPT_NEW_ENVIRON ||
o->option == TELOPT_OLD_ENVIRON)) {
/*
* We may only have one kind of ENVIRON going at a time.
* This is a hack, but who cares.
*/
deactivate_option (o->option==TELOPT_NEW_ENVIRON ? &o_oenv : &o_nenv);
}
}
static void refused_option (struct Opt *o) {
if (o->send == WILL && o->option == TELOPT_NEW_ENVIRON &&
o_oenv.state == INACTIVE) {
send_opt (WILL, TELOPT_OLD_ENVIRON);
o_oenv.state = REQUESTED;
}
}
static void proc_rec_opt (int cmd, int option) {
struct Opt **o;
log_option ("server", cmd, option);
for (o = opts; *o; o++) {
if ((*o)->option == option && (*o)->ack == cmd) {
switch ((*o)->state) {
case REQUESTED:
(*o)->state = ACTIVE;
activate_option (*o);
break;
case ACTIVE:
break;
case INACTIVE:
(*o)->state = ACTIVE;
send_opt ((*o)->send, option);
activate_option (*o);
break;
case REALLY_INACTIVE:
send_opt ((*o)->nsend, option);
break;
}
return;
} else if ((*o)->option == option && (*o)->nak == cmd) {
switch ((*o)->state) {
case REQUESTED:
(*o)->state = INACTIVE;
refused_option (*o);
break;
case ACTIVE:
(*o)->state = INACTIVE;
send_opt ((*o)->nsend, option);
break;
case INACTIVE:
case REALLY_INACTIVE:
break;
}
return;
}
}
/*
* If we reach here, the option was one we weren't prepared to
* cope with. So send a negative ack.
*/
send_opt ((cmd == WILL ? DONT : WONT), option);
}
static void process_subneg (void) {
unsigned char b[2048], *p, *q;
int var, value, n;
char *e;
switch (sb_opt) {
case TELOPT_TSPEED:
if (sb_len == 1 && sb_buf[0] == TELQUAL_SEND) {
char logbuf[sizeof(cfg.termspeed)+80];
b[0] = IAC; b[1] = SB; b[2] = TELOPT_TSPEED;
b[3] = TELQUAL_IS;
strcpy(b+4, cfg.termspeed);
n = 4 + strlen(cfg.termspeed);
b[n] = IAC; b[n+1] = SE;
s_write (b, n+2);
lognegot("server:\tSB TSPEED SEND");
sprintf(logbuf, "client:\tSB TSPEED IS %s", cfg.termspeed);
lognegot (logbuf);
} else
lognegot ("server:\tSB TSPEED <something weird>");
break;
case TELOPT_TTYPE:
if (sb_len == 1 && sb_buf[0] == TELQUAL_SEND) {
char logbuf[sizeof(cfg.termtype)+80];
b[0] = IAC; b[1] = SB; b[2] = TELOPT_TTYPE;
b[3] = TELQUAL_IS;
for (n = 0; cfg.termtype[n]; n++)
b[n+4] = (cfg.termtype[n] >= 'a' && cfg.termtype[n] <= 'z' ?
cfg.termtype[n] + 'A'-'a' : cfg.termtype[n]);
b[n+4] = IAC; b[n+5] = SE;
s_write (b, n+6);
b[n+4] = 0;
lognegot("server:\tSB TTYPE SEND");
sprintf(logbuf, "client:\tSB TTYPE IS %s", b+4);
lognegot(logbuf);
} else
lognegot("server:\tSB TTYPE <something weird>\r\n");
break;
case TELOPT_OLD_ENVIRON:
case TELOPT_NEW_ENVIRON:
p = sb_buf;
q = p + sb_len;
if (p < q && *p == TELQUAL_SEND) {
char logbuf[50];
p++;
sprintf (logbuf, "server:\tSB %s SEND", telopt(sb_opt));
lognegot (logbuf);
if (sb_opt == TELOPT_OLD_ENVIRON) {
if (cfg.rfc_environ) {
value = RFC_VALUE;
var = RFC_VAR;
} else {
value = BSD_VALUE;
var = BSD_VAR;
}
/*
* Try to guess the sense of VAR and VALUE.
*/
while (p < q) {
if (*p == RFC_VAR) {
value = RFC_VALUE;
var = RFC_VAR;
} else if (*p == BSD_VAR) {
value = BSD_VALUE;
var = BSD_VAR;
}
p++;
}
} else {
/*
* With NEW_ENVIRON, the sense of VAR and VALUE
* isn't in doubt.
*/
value = RFC_VALUE;
var = RFC_VAR;
}
b[0] = IAC; b[1] = SB; b[2] = sb_opt;
b[3] = TELQUAL_IS;
n = 4;
e = cfg.environ;
while (*e) {
b[n++] = var;
while (*e && *e != '\t') b[n++] = *e++;
if (*e == '\t') e++;
b[n++] = value;
while (*e) b[n++] = *e++;
e++;
}
if (*cfg.username) {
b[n++] = var; b[n++] = 'U'; b[n++] = 'S';
b[n++] = 'E'; b[n++] = 'R'; b[n++] = value;
e = cfg.username;
while (*e) b[n++] = *e++;
}
b[n++] = IAC; b[n++] = SE;
s_write (b, n);
sprintf(logbuf, "client:\tSB %s IS %s", telopt(sb_opt),
n==6 ? "<nothing>" : "<stuff>");
lognegot (logbuf);
}
break;
}
}
static enum {
TOPLEVEL, SEENIAC, SEENWILL, SEENWONT, SEENDO, SEENDONT,
SEENSB, SUBNEGOT, SUBNEG_IAC, SEENCR
} telnet_state = TOPLEVEL;
static void do_telnet_read (char *buf, int len) {
unsigned char b[10];
while (len--) {
int c = (unsigned char) *buf++;
switch (telnet_state) {
case TOPLEVEL:
case SEENCR:
if (c == NUL && telnet_state == SEENCR)
telnet_state = TOPLEVEL;
else if (c == IAC)
telnet_state = SEENIAC;
else {
b[0] = c;
#if 0
if (!in_synch)
#endif
c_write (b, 1);
if (c == CR)
telnet_state = SEENCR;
else
telnet_state = TOPLEVEL;
}
break;
case SEENIAC:
if (c == DO) telnet_state = SEENDO;
else if (c == DONT) telnet_state = SEENDONT;
else if (c == WILL) telnet_state = SEENWILL;
else if (c == WONT) telnet_state = SEENWONT;
else if (c == SB) telnet_state = SEENSB;
else telnet_state = TOPLEVEL;/* ignore _everything_ else! */
break;
case SEENWILL:
proc_rec_opt (WILL, c);
telnet_state = TOPLEVEL;
break;
case SEENWONT:
proc_rec_opt (WONT, c);
telnet_state = TOPLEVEL;
break;
case SEENDO:
proc_rec_opt (DO, c);
telnet_state = TOPLEVEL;
break;
case SEENDONT:
proc_rec_opt (DONT, c);
telnet_state = TOPLEVEL;
break;
case SEENSB:
sb_opt = c;
sb_len = 0;
telnet_state = SUBNEGOT;
break;
case SUBNEGOT:
if (c == IAC)
telnet_state = SUBNEG_IAC;
else {
subneg_addchar:
if (sb_len >= sb_size) {
char *newbuf;
sb_size += SB_DELTA;
newbuf = (sb_buf ?
realloc(sb_buf, sb_size) :
malloc(sb_size));
if (newbuf)
sb_buf = newbuf;
else
sb_size -= SB_DELTA;
}
if (sb_len < sb_size)
sb_buf[sb_len++] = c;
telnet_state = SUBNEGOT;/* in case we came here by goto */
}
break;
case SUBNEG_IAC:
if (c != SE)
goto subneg_addchar; /* yes, it's a hack, I know, but... */
else {
process_subneg();
telnet_state = TOPLEVEL;
}
break;
}
}
}
/*
* Called to set up the Telnet connection. Will arrange for
* WM_NETEVENT messages to be passed to the specified window, whose
* window procedure should then call telnet_msg().
*
* Returns an error message, or NULL on success.
*
* Also places the canonical host name into `realhost'.
*/
static char *telnet_init (HWND hwnd, char *host, int port, char **realhost) {
SOCKADDR_IN addr;
struct hostent *h;
unsigned long a;
/*
* Try to find host.
*/
if ( (a = inet_addr(host)) == (unsigned long) INADDR_NONE) {
if ( (h = gethostbyname(host)) == NULL)
switch (WSAGetLastError()) {
case WSAENETDOWN: return "Network is down";
case WSAHOST_NOT_FOUND: case WSANO_DATA:
return "Host does not exist";
case WSATRY_AGAIN: return "Host not found";
default: return "gethostbyname: unknown error";
}
memcpy (&a, h->h_addr, sizeof(a));
*realhost = h->h_name;
} else
*realhost = host;
a = ntohl(a);
if (port < 0)
port = 23; /* default telnet port */
/*
* Open socket.
*/
s = socket(AF_INET, SOCK_STREAM, 0);
if (s == INVALID_SOCKET)
switch (WSAGetLastError()) {
case WSAENETDOWN: return "Network is down";
case WSAEAFNOSUPPORT: return "TCP/IP support not present";
default: return "socket(): unknown error";
}
#if 0
{
BOOL b = TRUE;
setsockopt (s, SOL_SOCKET, SO_OOBINLINE, (void *)&b, sizeof(b));
}
#endif
/*
* Bind to local address.
*/
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(0);
if (bind (s, (struct sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR)
switch (WSAGetLastError()) {
case WSAENETDOWN: return "Network is down";
default: return "bind(): unknown error";
}
/*
* Connect to remote address.
*/
addr.sin_addr.s_addr = htonl(a);
addr.sin_port = htons((short)port);
if (connect (s, (struct sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR)
switch (WSAGetLastError()) {
case WSAENETDOWN: return "Network is down";
case WSAECONNREFUSED: return "Connection refused";
case WSAENETUNREACH: return "Network is unreachable";
case WSAEHOSTUNREACH: return "No route to host";
default: return "connect(): unknown error";
}
if (WSAAsyncSelect (s, hwnd, WM_NETEVENT, FD_READ |
FD_WRITE | FD_OOB | FD_CLOSE) == SOCKET_ERROR)
switch (WSAGetLastError()) {
case WSAENETDOWN: return "Network is down";
default: return "WSAAsyncSelect(): unknown error";
}
/*
* Initialise option states.
*/
{
struct Opt **o;
for (o = opts; *o; o++)
if ((*o)->state == REQUESTED)
send_opt ((*o)->send, (*o)->option);
}
#if 0
/*
* Set up SYNCH state.
*/
in_synch = FALSE;
#endif
return NULL;
}
/*
* Process a WM_NETEVENT message. Will return 0 if the connection
* has closed, or <0 for a socket error.
*/
static int telnet_msg (WPARAM wParam, LPARAM lParam) {
int ret;
char buf[256];
if (s == INVALID_SOCKET) /* how the hell did we get here?! */
return -5000;
if (WSAGETSELECTERROR(lParam) != 0)
return -WSAGETSELECTERROR(lParam);
switch (WSAGETSELECTEVENT(lParam)) {
case FD_READ:
ret = recv(s, buf, sizeof(buf), 0);
if (ret < 0 && WSAGetLastError() == WSAEWOULDBLOCK)
return 1;
if (ret < 0) /* any _other_ error */
return -10000-WSAGetLastError();
if (ret == 0) {
s = INVALID_SOCKET;
return 0; /* can't happen, in theory */
}
#if 0
if (in_synch) {
BOOL i;
if (ioctlsocket (s, SIOCATMARK, &i) < 0) {
return -20000-WSAGetLastError();
}
if (i)
in_synch = FALSE;
}
#endif
do_telnet_read (buf, ret);
return 1;
case FD_OOB:
do {
ret = recv(s, buf, sizeof(buf), 0);
} while (ret > 0);
telnet_state = TOPLEVEL;
do {
ret = recv(s, buf, 1, MSG_OOB);
if (ret > 0)
do_telnet_read (buf, ret);
} while (ret > 0);
if (ret < 0 && WSAGetLastError() != WSAEWOULDBLOCK)
return -30000-WSAGetLastError();
return 1;
case FD_WRITE:
if (outbuf_head != outbuf_reap)
try_write();
return 1;
case FD_CLOSE:
s = INVALID_SOCKET;
return 0;
}
return 1; /* shouldn't happen, but WTF */
}
/*
* Called to send data down the Telnet connection.
*/
static void telnet_send (char *buf, int len) {
char *p;
static unsigned char iac[2] = { IAC, IAC };
static unsigned char cr[2] = { CR, NUL };
if (s == INVALID_SOCKET)
return;
p = buf;
while (p < buf+len) {
char *q = p;
while (iswritable((unsigned char)*p) && p < buf+len) p++;
s_write (q, p-q);
while (p < buf+len && !iswritable((unsigned char)*p)) {
s_write ((unsigned char)*p == IAC ? iac : cr, 2);
p++;
}
}
}
/*
* Called to set the size of the window from Telnet's POV.
*/
static void telnet_size(void) {
unsigned char b[16];
char logbuf[50];
if (s == INVALID_SOCKET || o_naws.state != ACTIVE)
return;
b[0] = IAC; b[1] = SB; b[2] = TELOPT_NAWS;
b[3] = cols >> 8; b[4] = cols & 0xFF;
b[5] = rows >> 8; b[6] = rows & 0xFF;
b[7] = IAC; b[8] = SE;
s_write (b, 9);
sprintf(logbuf, "client:\tSB NAWS %d,%d",
((unsigned char)b[3] << 8) + (unsigned char)b[4],
((unsigned char)b[5] << 8) + (unsigned char)b[6]);
lognegot (logbuf);
}
/*
* Send Telnet special codes.
*/
static void telnet_special (Telnet_Special code) {
unsigned char b[2];
if (s == INVALID_SOCKET)
return;
b[0] = IAC;
switch (code) {
case TS_AYT: b[1] = AYT; s_write (b, 2); break;
case TS_BRK: b[1] = BREAK; s_write (b, 2); break;
case TS_EC: b[1] = EC; s_write (b, 2); break;
case TS_EL: b[1] = EL; s_write (b, 2); break;
case TS_GA: b[1] = GA; s_write (b, 2); break;
case TS_NOP: b[1] = NOP; s_write (b, 2); break;
case TS_ABORT: b[1] = ABORT; s_write (b, 2); break;
case TS_AO: b[1] = AO; s_write (b, 2); break;
case TS_IP: b[1] = IP; s_write (b, 2); break;
case TS_SUSP: b[1] = SUSP; s_write (b, 2); break;
case TS_EOR: b[1] = EOR; s_write (b, 2); break;
case TS_EOF: b[1] = xEOF; s_write (b, 2); break;
case TS_SYNCH:
outbuf_head = outbuf_reap = 0;
b[0] = DM;
send (s, b, 1, MSG_OOB);
break;
}
}
Backend telnet_backend = {
telnet_init,
telnet_msg,
telnet_send,
telnet_size,
telnet_special
};

1447
terminal.c Normal file

File diff suppressed because it is too large Load Diff

116
win_res.h Normal file
View File

@ -0,0 +1,116 @@
#ifndef PUTTY_WIN_RES_H
#define PUTTY_WIN_RES_H
#define IDI_MAINICON 200
#define IDD_MAINBOX 102
#define IDD_PANEL0 103
#define IDD_PANEL1 104
#define IDD_PANEL2 105
#define IDD_PANEL3 106
#define IDD_PANEL35 107
#define IDD_PANEL4 108
#define IDD_PANEL5 109
#define IDD_LOGBOX 110
#define IDD_ABOUTBOX 111
#define IDD_RECONF 112
#define IDD_LICENCEBOX 113
#define IDN_LIST 1001
#define IDA_ICON 1001
#define IDA_TEXT 1002
#define IDA_LICENCE 1003
#define IDC_TAB 1001
#define IDC_ABOUT 1002
#define IDC0_HOSTSTATIC 1001
#define IDC0_HOST 1002
#define IDC0_PORTSTATIC 1003
#define IDC0_PORT 1004
#define IDC0_PROTSTATIC 1005
#define IDC0_PROTTELNET 1006
#define IDC0_PROTSSH 1007
#define IDC0_SESSSTATIC 1008
#define IDC0_SESSEDIT 1009
#define IDC0_SESSLIST 1010
#define IDC0_SESSLOAD 1011
#define IDC0_SESSSAVE 1012
#define IDC0_SESSDEL 1013
#define IDC0_CLOSEEXIT 1014
#define IDC1_DELSTATIC 1001
#define IDC1_DEL008 1002
#define IDC1_DEL127 1003
#define IDC1_HOMESTATIC 1004
#define IDC1_HOMETILDE 1005
#define IDC1_HOMERXVT 1006
#define IDC1_FUNCSTATIC 1007
#define IDC1_FUNCTILDE 1008
#define IDC1_FUNCLINUX 1009
#define IDC1_KPSTATIC 1010
#define IDC1_KPNORMAL 1011
#define IDC1_KPAPPLIC 1012
#define IDC1_CURSTATIC 1013
#define IDC1_CURNORMAL 1014
#define IDC1_CURAPPLIC 1015
#define IDC2_WRAPMODE 1001
#define IDC2_DECOM 1002
#define IDC2_WINNAME 1003
#define IDC2_DIMSTATIC 1004
#define IDC2_ROWSSTATIC 1005
#define IDC2_ROWSEDIT 1006
#define IDC2_COLSSTATIC 1007
#define IDC2_COLSEDIT 1008
#define IDC2_SAVESTATIC 1009
#define IDC2_SAVEEDIT 1010
#define IDC2_FONTSTATIC 1011
#define IDC2_CHOOSEFONT 1012
#define IDC2_VTSTATIC 1013
#define IDC2_VTXWINDOWS 1014
#define IDC2_VTOEMANSI 1015
#define IDC2_VTOEMONLY 1016
#define IDC2_VTPOORMAN 1017
#define IDC3_TTSTATIC 1001
#define IDC3_TTEDIT 1002
#define IDC3_TSSTATIC 1003
#define IDC3_TSEDIT 1004
#define IDC3_LOGSTATIC 1005
#define IDC3_LOGEDIT 1006
#define IDC3_ENVSTATIC 1007
#define IDC3_VARSTATIC 1008
#define IDC3_VAREDIT 1009
#define IDC3_VALSTATIC 1010
#define IDC3_VALEDIT 1011
#define IDC3_ENVLIST 1012
#define IDC3_ENVADD 1013
#define IDC3_ENVREMOVE 1014
#define IDC3_EMSTATIC 1015
#define IDC3_EMBSD 1016
#define IDC3_EMRFC 1017
#define IDC4_MBSTATIC 1001
#define IDC4_MBWINDOWS 1002
#define IDC4_MBXTERM 1003
#define IDC4_CCSTATIC 1004
#define IDC4_CCLIST 1005
#define IDC4_CCSET 1006
#define IDC4_CCSTATIC2 1007
#define IDC4_CCEDIT 1008
#define IDC5_BOLDCOLOUR 1001
#define IDC5_PALETTE 1002
#define IDC5_STATIC 1003
#define IDC5_LIST 1004
#define IDC5_RSTATIC 1005
#define IDC5_GSTATIC 1006
#define IDC5_BSTATIC 1007
#define IDC5_RVALUE 1008
#define IDC5_GVALUE 1009
#define IDC5_BVALUE 1010
#define IDC5_CHANGE 1011
#endif

235
win_res.rc Normal file
View File

@ -0,0 +1,235 @@
#include <winresrc.h>
#define TCS_MULTILINE 0x0200
#include "win_res.h"
IDI_MAINICON ICON "putty.ico"
IDD_ABOUTBOX DIALOG DISCARDABLE 140, 40, 136, 58
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "About PuTTY"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "&Close", IDOK, 82, 40, 48, 14
PUSHBUTTON "View &Licence", IDA_LICENCE, 6, 40, 70, 14
ICON IDI_MAINICON, IDA_ICON, 10, 10, 0, 0
LTEXT "PuTTY Beta 0.43\n\251 1997-8 Simon Tatham\nAll rights reserved.",
IDA_TEXT, 40, 6, 96, 24
END
IDD_MAINBOX DIALOG DISCARDABLE 0, 0, 180, 216
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "PuTTY Configuration"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "&Open", IDOK, 86, 199, 44, 14
PUSHBUTTON "&Cancel", IDCANCEL, 133, 199, 44, 14
PUSHBUTTON "&About", IDC_ABOUT, 3, 199, 44, 14, NOT WS_TABSTOP
CONTROL "", IDC_TAB, L"SysTabControl32", TCS_MULTILINE | WS_TABSTOP,
3, 3, 174, 193
END
IDD_RECONF DIALOG DISCARDABLE 0, 0, 180, 216
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "PuTTY Reconfiguration"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "&Apply", IDOK, 86, 199, 44, 14
PUSHBUTTON "&Cancel", IDCANCEL, 133, 199, 44, 14
CONTROL "", IDC_TAB, L"SysTabControl32", TCS_MULTILINE | WS_TABSTOP,
3, 3, 174, 193
END
IDD_PANEL0 DIALOG DISCARDABLE 6, 30, 168, 163
STYLE WS_CHILD | WS_VISIBLE | NOT WS_BORDER
FONT 8, "MS Sans Serif"
BEGIN
LTEXT "Host Name", IDC0_HOSTSTATIC, 3, 3, 122, 8
EDITTEXT IDC0_HOST, 3, 11, 122, 12, ES_AUTOHSCROLL
LTEXT "Port", IDC0_PORTSTATIC, 131, 3, 34, 8
EDITTEXT IDC0_PORT, 131, 11, 34, 12
#ifdef FWHACK
RTEXT "Protocol:", IDC0_PROTSTATIC, 3, 29, 77, 8
AUTORADIOBUTTON "Telnet", IDC0_PROTTELNET, 86, 29, 33, 10, WS_GROUP
AUTORADIOBUTTON "SSH/hack", IDC0_PROTSSH, 122, 29, 43, 10
#else
RTEXT "Protocol:", IDC0_PROTSTATIC, 3, 29, 87, 8
AUTORADIOBUTTON "Telnet", IDC0_PROTTELNET, 96, 29, 33, 10, WS_GROUP
AUTORADIOBUTTON "SSH", IDC0_PROTSSH, 132, 29, 33, 10
#endif
LTEXT "Stored Sessions", IDC0_SESSSTATIC, 3, 40, 122, 8
EDITTEXT IDC0_SESSEDIT, 3, 48, 122, 12, ES_AUTOHSCROLL
LISTBOX IDC0_SESSLIST, 3, 63, 122, 81, LBS_HASSTRINGS | WS_VSCROLL
PUSHBUTTON "Load", IDC0_SESSLOAD, 131, 63, 34, 14
PUSHBUTTON "Save", IDC0_SESSSAVE, 131, 80, 34, 14
PUSHBUTTON "Delete", IDC0_SESSDEL, 131, 97, 34, 14
AUTOCHECKBOX "Close Window on Exit", IDC0_CLOSEEXIT, 3, 147, 162, 10
END
IDD_PANEL1 DIALOG DISCARDABLE 6, 30, 168, 163
STYLE WS_CHILD | WS_VISIBLE | NOT WS_BORDER
FONT 8, "MS Sans Serif"
BEGIN
LTEXT "Action of Backspace:", IDC1_DELSTATIC, 3, 3, 162, 8
AUTORADIOBUTTON "Control-H (ASCII 8)", IDC1_DEL008, 3, 12, 162, 10, WS_GROUP
AUTORADIOBUTTON "Control-? (ASCII 127)", IDC1_DEL127, 3, 22, 162, 10
LTEXT "Action of Home and End:", IDC1_HOMESTATIC, 3, 35, 162, 8
AUTORADIOBUTTON "Standard (ESC [ 1 ~ and ESC [ 4 ~)",
IDC1_HOMETILDE, 3, 44, 162, 10, WS_GROUP
AUTORADIOBUTTON "rxvt (ESC [ H and ESC O w)",
IDC1_HOMERXVT, 3, 54, 162, 10
LTEXT "Action of F1 through F5:", IDC1_FUNCSTATIC, 3, 67, 162, 8
AUTORADIOBUTTON "Standard (ESC [ 11 ~ through ESC [ 15 ~)",
IDC1_FUNCTILDE, 3, 76, 162, 10, WS_GROUP
AUTORADIOBUTTON "Linux (ESC [ [ A through ESC [ [ E)",
IDC1_FUNCLINUX, 3, 86, 162, 10
LTEXT "Initial state of numeric keypad:", IDC1_KPSTATIC, 3, 99, 162, 8
AUTORADIOBUTTON "Normal (depends on NumLock)",
IDC1_KPNORMAL, 3, 108, 162, 10, WS_GROUP
AUTORADIOBUTTON "Application (ESC O P etc)",
IDC1_KPAPPLIC, 3, 118, 162, 10
LTEXT "Initial state of cursor keys:", IDC1_CURSTATIC, 3, 131, 162, 8
AUTORADIOBUTTON "Normal (ESC [ A through ESC [ D)",
IDC1_CURNORMAL, 3, 140, 162, 10, WS_GROUP
AUTORADIOBUTTON "Application (ESC O A through ESC O D)",
IDC1_CURAPPLIC, 3, 150, 162, 10
END
IDD_PANEL2 DIALOG DISCARDABLE 6, 30, 168, 163
STYLE WS_CHILD | WS_VISIBLE | NOT WS_BORDER
FONT 8, "MS Sans Serif"
BEGIN
AUTOCHECKBOX "Auto wrap mode initially on", IDC2_WRAPMODE, 3, 3, 162, 10
AUTOCHECKBOX "DEC Origin Mode initially on", IDC2_DECOM, 3, 13, 162, 10
AUTOCHECKBOX "Avoid ever using icon title", IDC2_WINNAME, 3, 23, 162, 10
LTEXT "Terminal screen dimensions:", IDC2_DIMSTATIC, 3, 33, 162, 8
RTEXT "Rows", IDC2_ROWSSTATIC, 20, 44, 90, 8
EDITTEXT IDC2_ROWSEDIT, 118, 42, 30, 12
RTEXT "Columns", IDC2_COLSSTATIC, 20, 59, 90, 8
EDITTEXT IDC2_COLSEDIT, 118, 57, 30, 12
RTEXT "Saved lines of scrollback", IDC2_SAVESTATIC, 20, 74, 90, 8
EDITTEXT IDC2_SAVEEDIT, 118, 72, 30, 12
LTEXT "Font:", IDC2_FONTSTATIC, 3, 93, 99, 8
PUSHBUTTON "Change...", IDC2_CHOOSEFONT, 105, 90, 60, 14
LTEXT "Handling of VT100 line drawing characters:",IDC2_VTSTATIC, 3, 111, 162, 8
AUTORADIOBUTTON "Font has XWindows encoding",
IDC2_VTXWINDOWS, 3, 120, 162, 10, WS_GROUP
AUTORADIOBUTTON "Use font in both ANSI and OEM modes",
IDC2_VTOEMANSI, 3, 130, 162, 10
AUTORADIOBUTTON "Use font in OEM mode only",
IDC2_VTOEMONLY, 3, 140, 162, 10
AUTORADIOBUTTON "Poor man's line drawing (""+"", ""-"" and ""|"")",
IDC2_VTPOORMAN, 3, 150, 162, 10
END
IDD_PANEL3 DIALOG DISCARDABLE 6, 30, 168, 163
STYLE WS_CHILD | WS_VISIBLE | NOT WS_BORDER
FONT 8, "MS Sans Serif"
BEGIN
LTEXT "Terminal-type string", IDC3_TTSTATIC, 3, 5, 90, 8
EDITTEXT IDC3_TTEDIT, 96, 3, 69, 12, ES_AUTOHSCROLL
LTEXT "Terminal-speed string", IDC3_TSSTATIC, 3, 20, 90, 8
EDITTEXT IDC3_TSEDIT, 96, 18, 69, 12, ES_AUTOHSCROLL
LTEXT "Auto-login username", IDC3_LOGSTATIC, 3, 35, 90, 8
EDITTEXT IDC3_LOGEDIT, 96, 33, 69, 12, ES_AUTOHSCROLL
LTEXT "Environment variables:", IDC3_ENVSTATIC, 3, 53, 162, 8
LTEXT "Variable", IDC3_VARSTATIC, 3, 70, 29, 8
EDITTEXT IDC3_VAREDIT, 35, 68, 35, 12, ES_AUTOHSCROLL
LTEXT "Value", IDC3_VALSTATIC, 76, 70, 19, 8
EDITTEXT IDC3_VALEDIT, 98, 68, 67, 12, ES_AUTOHSCROLL
LISTBOX IDC3_ENVLIST, 3, 85, 122, 55,
LBS_HASSTRINGS | LBS_USETABSTOPS | WS_VSCROLL
PUSHBUTTON "Add", IDC3_ENVADD, 131, 85, 34, 14
PUSHBUTTON "Remove", IDC3_ENVREMOVE, 131, 102, 34, 14
LTEXT "ENVIRON interpretation:", IDC3_EMSTATIC, 3, 147, 90, 8
AUTORADIOBUTTON "BSD", IDC3_EMBSD, 96, 147, 33, 10, WS_GROUP
AUTORADIOBUTTON "RFC", IDC3_EMRFC, 132, 147, 33, 10
END
IDD_PANEL35 DIALOG DISCARDABLE 6, 30, 168, 163
STYLE WS_CHILD | WS_VISIBLE | NOT WS_BORDER
FONT 8, "MS Sans Serif"
BEGIN
LTEXT "Terminal-type string", IDC3_TTSTATIC, 3, 5, 90, 8
EDITTEXT IDC3_TTEDIT, 96, 3, 69, 12, ES_AUTOHSCROLL
LTEXT "Auto-login username", IDC3_LOGSTATIC, 3, 35, 90, 8
EDITTEXT IDC3_LOGEDIT, 96, 33, 69, 12, ES_AUTOHSCROLL
END
IDD_PANEL4 DIALOG DISCARDABLE 6, 30, 168, 163
STYLE WS_CHILD | WS_VISIBLE | NOT WS_BORDER
FONT 8, "MS Sans Serif"
BEGIN
LTEXT "Action of mouse buttons:", IDC4_MBSTATIC, 3, 3, 162, 8
AUTORADIOBUTTON "Windows (Right pastes, Middle extends)",
IDC4_MBWINDOWS, 3, 12, 162, 10, WS_GROUP
AUTORADIOBUTTON "xterm (Right extends, Middle pastes)",
IDC4_MBXTERM, 3, 22, 162, 10
LTEXT "Character classes:", IDC4_CCSTATIC, 3, 35, 162, 8
LISTBOX IDC4_CCLIST, 3, 45, 162, 96,
LBS_HASSTRINGS | WS_VSCROLL | LBS_USETABSTOPS | LBS_MULTIPLESEL
PUSHBUTTON "Set", IDC4_CCSET, 33, 145, 34, 14
LTEXT "to class", IDC4_CCSTATIC2, 73, 148, 26, 8
EDITTEXT IDC4_CCEDIT, 105, 146, 36, 12
END
IDD_PANEL5 DIALOG DISCARDABLE 6, 30, 168, 163
STYLE WS_CHILD | WS_VISIBLE | NOT WS_BORDER
FONT 8, "MS Sans Serif"
BEGIN
AUTOCHECKBOX "Bolded text is a different colour", IDC5_BOLDCOLOUR,3, 10, 162, 10
AUTOCHECKBOX "Attempt to use logical palettes", IDC5_PALETTE, 3, 25, 162, 10
LTEXT "Colours:", IDC5_STATIC, 3, 40, 162, 8
LISTBOX IDC5_LIST, 3, 50, 100, 110, LBS_HASSTRINGS | WS_VSCROLL
LTEXT "Red:", IDC5_RSTATIC, 109, 50, 27, 8
RTEXT "", IDC5_RVALUE, 138, 50, 27, 8
LTEXT "Green:", IDC5_GSTATIC, 109, 58, 27, 8
RTEXT "", IDC5_GVALUE, 138, 58, 27, 8
LTEXT "Blue:", IDC5_BSTATIC, 109, 66, 27, 8
RTEXT "", IDC5_BVALUE, 138, 66, 27, 8
PUSHBUTTON "Change...", IDC5_CHANGE, 109, 140, 56, 14
END
IDD_LOGBOX DIALOG DISCARDABLE 100, 20, 160, 119
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "PuTTY Negotiation Log"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "&Close", IDOK, 58, 102, 44, 14
LISTBOX IDN_LIST, 3, 3, 154, 95, LBS_HASSTRINGS | LBS_USETABSTOPS | WS_VSCROLL
END
IDD_LICENCEBOX DIALOG DISCARDABLE 50, 50, 226, 231
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "PuTTY Licence"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "OK", IDOK, 98, 211, 44, 14
LTEXT "Copyright \251 1998 Simon Tatham", 1000, 10, 10, 206, 8
LTEXT "Portions copyright Gary S. Brown and Eric Young", 1100, 10, 18, 206, 8
LTEXT "Permission is hereby granted, free of charge, to any person", 1002, 10, 34, 206, 8
LTEXT "obtaining a copy of this software and associated documentation", 1003, 10, 42, 206, 8
LTEXT "files (the ""Software""), to deal in the Software without restriction,", 1004, 10, 50, 206, 8
LTEXT "including without limitation the rights to use, copy, modify, merge,", 1005, 10, 58, 206, 8
LTEXT "publish, distribute, sublicense, and/or sell copies of the Software,", 1006, 10, 66, 206, 8
LTEXT "and to permit persons to whom the Software is furnished to do so,", 1007, 10, 74, 206, 8
LTEXT "subject to the following conditions:", 1008, 10, 82, 206, 8
LTEXT "The above copyright notice and this permission notice shall be", 1010, 10, 98, 206, 8
LTEXT "included in all copies or substantial portions of the Software.", 1011, 10, 106, 206, 8
LTEXT "THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT", 1013, 10, 122, 206, 8
LTEXT "WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,", 1014, 10, 130, 206, 8
LTEXT "INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF", 1015, 10, 138, 206, 8
LTEXT "MERCHANTABILITY, FITNESS FOR A PARTICULAR", 1016, 10, 146, 206, 8
LTEXT "PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL", 1017, 10, 154, 206, 8
LTEXT "SIMON TATHAM BE LIABLE FOR ANY CLAIM, DAMAGES OR", 1018, 10, 162, 206, 8
LTEXT "OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,", 1019, 10, 170, 206, 8
LTEXT "TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN", 1020, 10, 178, 206, 8
LTEXT "CONNECTION WITH THE SOFTWARE OR THE USE OR", 1021, 10, 186, 206, 8
LTEXT "OTHER DEALINGS IN THE SOFTWARE.", 1022, 10, 194, 206, 8
END

1336
windlg.c Normal file

File diff suppressed because it is too large Load Diff

1499
window.c Normal file

File diff suppressed because it is too large Load Diff