1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-24 16:52:24 +00:00

Run entire source base through GNU indent to tidy up the varying

coding styles of the various contributors! Woohoo!

[originally from svn r1098]
This commit is contained in:
Simon Tatham 2001-05-06 14:35:20 +00:00
parent 93101b5a71
commit 3730ada5ce
52 changed files with 15112 additions and 12426 deletions

View File

@ -17,14 +17,18 @@ struct backend_list backends[] = {
/* /*
* Stub implementations of functions not used in non-ssh versions. * Stub implementations of functions not used in non-ssh versions.
*/ */
void random_save_seed(void) { void random_save_seed(void)
{
} }
void random_destroy_seed(void) { void random_destroy_seed(void)
{
} }
void noise_ultralight(DWORD data) { void noise_ultralight(DWORD data)
{
} }
void noise_regular(void) { void noise_regular(void)
{
} }

19
int64.c
View File

@ -10,7 +10,8 @@ typedef struct {
unsigned long hi, lo; unsigned long hi, lo;
} uint64, int64; } uint64, int64;
uint64 uint64_div10(uint64 x, int *remainder) { uint64 uint64_div10(uint64 x, int *remainder)
{
uint64 y; uint64 y;
int rem, r2; int rem, r2;
y.hi = x.hi / 10; y.hi = x.hi / 10;
@ -30,7 +31,8 @@ uint64 uint64_div10(uint64 x, int *remainder) {
return y; return y;
} }
void uint64_decimal(uint64 x, char *buffer) { void uint64_decimal(uint64 x, char *buffer)
{
char buf[20]; char buf[20];
int start = 20; int start = 20;
int d; int d;
@ -41,24 +43,27 @@ void uint64_decimal(uint64 x, char *buffer) {
buf[--start] = d + '0'; buf[--start] = d + '0';
} }
memcpy(buffer, buf+start, sizeof(buf)-start); memcpy(buffer, buf + start, sizeof(buf) - start);
buffer[sizeof(buf)-start] = '\0'; buffer[sizeof(buf) - start] = '\0';
} }
uint64 uint64_make(unsigned long hi, unsigned long lo) { uint64 uint64_make(unsigned long hi, unsigned long lo)
{
uint64 y; uint64 y;
y.hi = hi; y.hi = hi;
y.lo = lo; y.lo = lo;
return y; return y;
} }
uint64 uint64_add(uint64 x, uint64 y) { uint64 uint64_add(uint64 x, uint64 y)
{
x.lo += y.lo; x.lo += y.lo;
x.hi += y.hi + (x.lo < y.lo ? 1 : 0); x.hi += y.hi + (x.lo < y.lo ? 1 : 0);
return x; return x;
} }
uint64 uint64_add32(uint64 x, unsigned long y) { uint64 uint64_add32(uint64 x, unsigned long y)
{
uint64 yy; uint64 yy;
yy.hi = 0; yy.hi = 0;
yy.lo = y; yy.lo = y;

260
ldisc.c
View File

@ -18,164 +18,170 @@
(cfg.localedit == LD_BACKEND && \ (cfg.localedit == LD_BACKEND && \
(back->ldisc(LD_EDIT) || term_ldisc(LD_EDIT)))) (back->ldisc(LD_EDIT) || term_ldisc(LD_EDIT))))
static void c_write (char *buf, int len) { static void c_write(char *buf, int len)
{
from_backend(0, buf, len); from_backend(0, buf, len);
} }
static char *term_buf = NULL; static char *term_buf = NULL;
static int term_buflen = 0, term_bufsiz = 0, term_quotenext = 0; static int term_buflen = 0, term_bufsiz = 0, term_quotenext = 0;
static int plen(unsigned char c) { static int plen(unsigned char c)
if ((c >= 32 && c <= 126) || {
(c >= 160)) if ((c >= 32 && c <= 126) || (c >= 160))
return 1; return 1;
else if (c < 128) else if (c < 128)
return 2; /* ^x for some x */ return 2; /* ^x for some x */
else else
return 4; /* <XY> for hex XY */ return 4; /* <XY> for hex XY */
} }
static void pwrite(unsigned char c) { static void pwrite(unsigned char c)
if ((c >= 32 && c <= 126) || {
(c >= 160)) { if ((c >= 32 && c <= 126) || (c >= 160)) {
c_write(&c, 1); c_write(&c, 1);
} else if (c < 128) { } else if (c < 128) {
char cc[2]; char cc[2];
cc[1] = (c == 127 ? '?' : c + 0x40); cc[1] = (c == 127 ? '?' : c + 0x40);
cc[0] = '^'; cc[0] = '^';
c_write(cc, 2); c_write(cc, 2);
} else { } else {
char cc[5]; char cc[5];
sprintf(cc, "<%02X>", c); sprintf(cc, "<%02X>", c);
c_write(cc, 4); c_write(cc, 4);
} }
} }
static void bsb(int n) { static void bsb(int n)
{
while (n--) while (n--)
c_write("\010 \010", 3); c_write("\010 \010", 3);
} }
#define CTRL(x) (x^'@') #define CTRL(x) (x^'@')
void ldisc_send(char *buf, int len) { void ldisc_send(char *buf, int len)
{
/* /*
* Called with len=0 when the options change. We must inform * Called with len=0 when the options change. We must inform
* the front end in case it needs to know. * the front end in case it needs to know.
*/ */
if (len == 0) { if (len == 0) {
void ldisc_update(int echo, int edit); void ldisc_update(int echo, int edit);
ldisc_update(ECHOING, EDITING); ldisc_update(ECHOING, EDITING);
} }
/* /*
* Either perform local editing, or just send characters. * Either perform local editing, or just send characters.
*/ */
if (EDITING) { if (EDITING) {
while (len--) { while (len--) {
char c; char c;
c = *buf++; c = *buf++;
switch (term_quotenext ? ' ' : c) { switch (term_quotenext ? ' ' : c) {
/* /*
* ^h/^?: delete one char and output one BSB * ^h/^?: delete one char and output one BSB
* ^w: delete, and output BSBs, to return to last * ^w: delete, and output BSBs, to return to last
* space/nonspace boundary * space/nonspace boundary
* ^u: delete, and output BSBs, to return to BOL * ^u: delete, and output BSBs, to return to BOL
* ^c: Do a ^u then send a telnet IP * ^c: Do a ^u then send a telnet IP
* ^z: Do a ^u then send a telnet SUSP * ^z: Do a ^u then send a telnet SUSP
* ^\: Do a ^u then send a telnet ABORT * ^\: Do a ^u then send a telnet ABORT
* ^r: echo "^R\n" and redraw line * ^r: echo "^R\n" and redraw line
* ^v: quote next char * ^v: quote next char
* ^d: if at BOL, end of file and close connection, * ^d: if at BOL, end of file and close connection,
* else send line and reset to BOL * else send line and reset to BOL
* ^m: send line-plus-\r\n and reset to BOL * ^m: send line-plus-\r\n and reset to BOL
*/ */
case CTRL('H'): case CTRL('?'): /* backspace/delete */ case CTRL('H'):
if (term_buflen > 0) { case CTRL('?'): /* backspace/delete */
if (ECHOING) if (term_buflen > 0) {
bsb(plen(term_buf[term_buflen-1])); if (ECHOING)
term_buflen--; bsb(plen(term_buf[term_buflen - 1]));
} term_buflen--;
break; }
case CTRL('W'): /* delete word */ break;
while (term_buflen > 0) { case CTRL('W'): /* delete word */
if (ECHOING) while (term_buflen > 0) {
bsb(plen(term_buf[term_buflen-1])); if (ECHOING)
term_buflen--; bsb(plen(term_buf[term_buflen - 1]));
if (term_buflen > 0 && term_buflen--;
isspace(term_buf[term_buflen-1]) && if (term_buflen > 0 &&
!isspace(term_buf[term_buflen])) isspace(term_buf[term_buflen - 1]) &&
break; !isspace(term_buf[term_buflen]))
} break;
break; }
case CTRL('U'): /* delete line */ break;
case CTRL('C'): /* Send IP */ case CTRL('U'): /* delete line */
case CTRL('\\'): /* Quit */ case CTRL('C'): /* Send IP */
case CTRL('Z'): /* Suspend */ case CTRL('\\'): /* Quit */
while (term_buflen > 0) { case CTRL('Z'): /* Suspend */
if (ECHOING) while (term_buflen > 0) {
bsb(plen(term_buf[term_buflen-1])); if (ECHOING)
term_buflen--; bsb(plen(term_buf[term_buflen - 1]));
} term_buflen--;
back->special (TS_EL); }
if( c == CTRL('C') ) back->special (TS_IP); back->special(TS_EL);
if( c == CTRL('Z') ) back->special (TS_SUSP); if (c == CTRL('C'))
if( c == CTRL('\\') ) back->special (TS_ABORT); back->special(TS_IP);
break; if (c == CTRL('Z'))
case CTRL('R'): /* redraw line */ back->special(TS_SUSP);
if (ECHOING) { if (c == CTRL('\\'))
int i; back->special(TS_ABORT);
c_write("^R\r\n", 4); break;
for (i = 0; i < term_buflen; i++) case CTRL('R'): /* redraw line */
pwrite(term_buf[i]); if (ECHOING) {
} int i;
break; c_write("^R\r\n", 4);
case CTRL('V'): /* quote next char */ for (i = 0; i < term_buflen; i++)
term_quotenext = TRUE; pwrite(term_buf[i]);
break; }
case CTRL('D'): /* logout or send */ break;
if (term_buflen == 0) { case CTRL('V'): /* quote next char */
back->special (TS_EOF); term_quotenext = TRUE;
} else { break;
back->send(term_buf, term_buflen); case CTRL('D'): /* logout or send */
term_buflen = 0; if (term_buflen == 0) {
} back->special(TS_EOF);
break; } else {
case CTRL('M'): /* send with newline */ back->send(term_buf, term_buflen);
if (term_buflen > 0) term_buflen = 0;
back->send(term_buf, term_buflen); }
if (cfg.protocol == PROT_RAW) break;
back->send("\r\n", 2); case CTRL('M'): /* send with newline */
else if (term_buflen > 0)
back->send("\r", 1); back->send(term_buf, term_buflen);
if (ECHOING) if (cfg.protocol == PROT_RAW)
c_write("\r\n", 2); back->send("\r\n", 2);
term_buflen = 0; else
break; back->send("\r", 1);
default: /* get to this label from ^V handler */ if (ECHOING)
if (term_buflen >= term_bufsiz) { c_write("\r\n", 2);
term_bufsiz = term_buflen + 256; term_buflen = 0;
term_buf = saferealloc(term_buf, term_bufsiz); break;
} default: /* get to this label from ^V handler */
term_buf[term_buflen++] = c; if (term_buflen >= term_bufsiz) {
if (ECHOING) term_bufsiz = term_buflen + 256;
pwrite(c); term_buf = saferealloc(term_buf, term_bufsiz);
term_quotenext = FALSE; }
break; term_buf[term_buflen++] = c;
} if (ECHOING)
} pwrite(c);
term_quotenext = FALSE;
break;
}
}
} else { } else {
if( term_buflen != 0 ) if (term_buflen != 0) {
{ back->send(term_buf, term_buflen);
back->send(term_buf, term_buflen); while (term_buflen > 0) {
while (term_buflen > 0) { bsb(plen(term_buf[term_buflen - 1]));
bsb(plen(term_buf[term_buflen-1])); term_buflen--;
term_buflen--; }
} }
} if (len > 0) {
if (len > 0) { if (ECHOING)
if (ECHOING) c_write(buf, len);
c_write(buf, len); back->send(buf, len);
back->send(buf, len); }
}
} }
} }

209
misc.c
View File

@ -43,21 +43,23 @@ static long minefield_curpos = 0;
static unsigned short *minefield_admin = NULL; static unsigned short *minefield_admin = NULL;
static void *minefield_pages = NULL; static void *minefield_pages = NULL;
static void minefield_admin_hide(int hide) { static void minefield_admin_hide(int hide)
{
int access = hide ? PAGE_NOACCESS : PAGE_READWRITE; int access = hide ? PAGE_NOACCESS : PAGE_READWRITE;
VirtualProtect(minefield_admin, minefield_npages*2, access, NULL); VirtualProtect(minefield_admin, minefield_npages * 2, access, NULL);
} }
static void minefield_init(void) { static void minefield_init(void)
{
int size; int size;
int admin_size; int admin_size;
int i; int i;
for (size = 0x40000000; size > 0; size = ((size >> 3) * 7) &~ 0xFFF) { for (size = 0x40000000; size > 0; size = ((size >> 3) * 7) & ~0xFFF) {
minefield_region = VirtualAlloc(NULL, size, minefield_region = VirtualAlloc(NULL, size,
MEM_RESERVE, PAGE_NOACCESS); MEM_RESERVE, PAGE_NOACCESS);
if (minefield_region) if (minefield_region)
break; break;
} }
minefield_size = size; minefield_size = size;
@ -67,21 +69,21 @@ static void minefield_init(void) {
*/ */
minefield_admin = minefield_region; minefield_admin = minefield_region;
minefield_npages = minefield_size / PAGESIZE; minefield_npages = minefield_size / PAGESIZE;
admin_size = (minefield_npages * 2 + PAGESIZE-1) &~ (PAGESIZE-1); admin_size = (minefield_npages * 2 + PAGESIZE - 1) & ~(PAGESIZE - 1);
minefield_npages = (minefield_size - admin_size) / PAGESIZE; minefield_npages = (minefield_size - admin_size) / PAGESIZE;
minefield_pages = (char *)minefield_region + admin_size; minefield_pages = (char *) minefield_region + admin_size;
/* /*
* Commit the admin region. * Commit the admin region.
*/ */
VirtualAlloc(minefield_admin, minefield_npages * 2, VirtualAlloc(minefield_admin, minefield_npages * 2,
MEM_COMMIT, PAGE_READWRITE); MEM_COMMIT, PAGE_READWRITE);
/* /*
* Mark all pages as unused (0xFFFF). * Mark all pages as unused (0xFFFF).
*/ */
for (i = 0; i < minefield_npages; i++) for (i = 0; i < minefield_npages; i++)
minefield_admin[i] = 0xFFFF; minefield_admin[i] = 0xFFFF;
/* /*
* Hide the admin region. * Hide the admin region.
@ -91,17 +93,19 @@ static void minefield_init(void) {
minefield_initialised = 1; minefield_initialised = 1;
} }
static void minefield_bomb(void) { static void minefield_bomb(void)
div(1, *(int*)minefield_pages); {
div(1, *(int *) minefield_pages);
} }
static void *minefield_alloc(int size) { static void *minefield_alloc(int size)
{
int npages; int npages;
int pos, lim, region_end, region_start; int pos, lim, region_end, region_start;
int start; int start;
int i; int i;
npages = (size + PAGESIZE-1) / PAGESIZE; npages = (size + PAGESIZE - 1) / PAGESIZE;
minefield_admin_hide(0); minefield_admin_hide(0);
@ -112,96 +116,102 @@ static void *minefield_alloc(int size) {
pos = minefield_curpos; pos = minefield_curpos;
lim = minefield_npages; lim = minefield_npages;
while (1) { while (1) {
/* Skip over used pages. */ /* Skip over used pages. */
while (pos < lim && minefield_admin[pos] != 0xFFFF) while (pos < lim && minefield_admin[pos] != 0xFFFF)
pos++; pos++;
/* Count unused pages. */ /* Count unused pages. */
start = pos; start = pos;
while (pos < lim && pos - start < npages+2 && while (pos < lim && pos - start < npages + 2 &&
minefield_admin[pos] == 0xFFFF) minefield_admin[pos] == 0xFFFF)
pos++; pos++;
if (pos - start == npages+2) if (pos - start == npages + 2)
break; break;
/* If we've reached the limit, reset the limit or stop. */ /* If we've reached the limit, reset the limit or stop. */
if (pos >= lim) { if (pos >= lim) {
if (lim == minefield_npages) { if (lim == minefield_npages) {
/* go round and start again at zero */ /* go round and start again at zero */
lim = minefield_curpos; lim = minefield_curpos;
pos = 0; pos = 0;
} else { } else {
minefield_admin_hide(1); minefield_admin_hide(1);
return NULL; return NULL;
} }
} }
} }
minefield_curpos = pos-1; minefield_curpos = pos - 1;
/* /*
* We have npages+2 unused pages starting at start. We leave * We have npages+2 unused pages starting at start. We leave
* the first and last of these alone and use the rest. * the first and last of these alone and use the rest.
*/ */
region_end = (start + npages+1) * PAGESIZE; region_end = (start + npages + 1) * PAGESIZE;
region_start = region_end - size; region_start = region_end - size;
/* FIXME: could align here if we wanted */ /* FIXME: could align here if we wanted */
/* /*
* Update the admin region. * Update the admin region.
*/ */
for (i = start + 2; i < start + npages-1; i++) for (i = start + 2; i < start + npages - 1; i++)
minefield_admin[i] = 0xFFFE; /* used but no region starts here */ minefield_admin[i] = 0xFFFE; /* used but no region starts here */
minefield_admin[start+1] = region_start % PAGESIZE; minefield_admin[start + 1] = region_start % PAGESIZE;
minefield_admin_hide(1); minefield_admin_hide(1);
VirtualAlloc((char *)minefield_pages + region_start, size, VirtualAlloc((char *) minefield_pages + region_start, size,
MEM_COMMIT, PAGE_READWRITE); MEM_COMMIT, PAGE_READWRITE);
return (char *)minefield_pages + region_start; return (char *) minefield_pages + region_start;
} }
static void minefield_free(void *ptr) { static void minefield_free(void *ptr)
{
int region_start, i, j; int region_start, i, j;
minefield_admin_hide(0); minefield_admin_hide(0);
region_start = (char *)ptr - (char *)minefield_pages; region_start = (char *) ptr - (char *) minefield_pages;
i = region_start / PAGESIZE; i = region_start / PAGESIZE;
if (i < 0 || i >= minefield_npages || if (i < 0 || i >= minefield_npages ||
minefield_admin[i] != region_start % PAGESIZE) minefield_admin[i] != region_start % PAGESIZE)
minefield_bomb(); minefield_bomb();
for (j = i; j < minefield_npages && minefield_admin[j] != 0xFFFF; j++) { for (j = i; j < minefield_npages && minefield_admin[j] != 0xFFFF; j++) {
minefield_admin[j] = 0xFFFF; minefield_admin[j] = 0xFFFF;
} }
VirtualFree(ptr, j*PAGESIZE - region_start, MEM_DECOMMIT); VirtualFree(ptr, j * PAGESIZE - region_start, MEM_DECOMMIT);
minefield_admin_hide(1); minefield_admin_hide(1);
} }
static int minefield_get_size(void *ptr) { static int minefield_get_size(void *ptr)
{
int region_start, i, j; int region_start, i, j;
minefield_admin_hide(0); minefield_admin_hide(0);
region_start = (char *)ptr - (char *)minefield_pages; region_start = (char *) ptr - (char *) minefield_pages;
i = region_start / PAGESIZE; i = region_start / PAGESIZE;
if (i < 0 || i >= minefield_npages || if (i < 0 || i >= minefield_npages ||
minefield_admin[i] != region_start % PAGESIZE) minefield_admin[i] != region_start % PAGESIZE)
minefield_bomb(); minefield_bomb();
for (j = i; j < minefield_npages && minefield_admin[j] != 0xFFFF; j++); for (j = i; j < minefield_npages && minefield_admin[j] != 0xFFFF; j++);
minefield_admin_hide(1); minefield_admin_hide(1);
return j*PAGESIZE - region_start; return j * PAGESIZE - region_start;
} }
static void *minefield_c_malloc(size_t size) { static void *minefield_c_malloc(size_t size)
if (!minefield_initialised) minefield_init(); {
if (!minefield_initialised)
minefield_init();
return minefield_alloc(size); return minefield_alloc(size);
} }
static void minefield_c_free(void *p) { static void minefield_c_free(void *p)
if (!minefield_initialised) minefield_init(); {
if (!minefield_initialised)
minefield_init();
minefield_free(p); minefield_free(p);
} }
@ -209,10 +219,12 @@ static void minefield_c_free(void *p) {
* realloc _always_ moves the chunk, for rapid detection of code * realloc _always_ moves the chunk, for rapid detection of code
* that assumes it won't. * that assumes it won't.
*/ */
static void *minefield_c_realloc(void *p, size_t size) { static void *minefield_c_realloc(void *p, size_t size)
{
size_t oldsize; size_t oldsize;
void *q; void *q;
if (!minefield_initialised) minefield_init(); if (!minefield_initialised)
minefield_init();
q = minefield_alloc(size); q = minefield_alloc(size);
oldsize = minefield_get_size(p); oldsize = minefield_get_size(p);
memcpy(q, p, (oldsize < size ? oldsize : size)); memcpy(q, p, (oldsize < size ? oldsize : size));
@ -220,27 +232,29 @@ static void *minefield_c_realloc(void *p, size_t size) {
return q; return q;
} }
#endif /* MINEFIELD */ #endif /* MINEFIELD */
#ifdef MALLOC_LOG #ifdef MALLOC_LOG
static FILE *fp = NULL; static FILE *fp = NULL;
void mlog(char *file, int line) { void mlog(char *file, int line)
{
if (!fp) { if (!fp) {
fp = fopen("putty_mem.log", "w"); fp = fopen("putty_mem.log", "w");
setvbuf(fp, NULL, _IONBF, BUFSIZ); setvbuf(fp, NULL, _IONBF, BUFSIZ);
} }
if (fp) if (fp)
fprintf (fp, "%s:%d: ", file, line); fprintf(fp, "%s:%d: ", file, line);
} }
#endif #endif
void *safemalloc(size_t size) { void *safemalloc(size_t size)
{
void *p; void *p;
#ifdef MINEFIELD #ifdef MINEFIELD
p = minefield_c_malloc (size); p = minefield_c_malloc(size);
#else #else
p = malloc (size); p = malloc(size);
#endif #endif
if (!p) { if (!p) {
MessageBox(NULL, "Out of memory!", "PuTTY Fatal Error", MessageBox(NULL, "Out of memory!", "PuTTY Fatal Error",
@ -254,19 +268,20 @@ void *safemalloc(size_t size) {
return p; return p;
} }
void *saferealloc(void *ptr, size_t size) { void *saferealloc(void *ptr, size_t size)
{
void *p; void *p;
if (!ptr) { if (!ptr) {
#ifdef MINEFIELD #ifdef MINEFIELD
p = minefield_c_malloc (size); p = minefield_c_malloc(size);
#else #else
p = malloc (size); p = malloc(size);
#endif #endif
} else { } else {
#ifdef MINEFIELD #ifdef MINEFIELD
p = minefield_c_realloc (ptr, size); p = minefield_c_realloc(ptr, size);
#else #else
p = realloc (ptr, size); p = realloc(ptr, size);
#endif #endif
} }
if (!p) { if (!p) {
@ -281,16 +296,17 @@ void *saferealloc(void *ptr, size_t size) {
return p; return p;
} }
void safefree(void *ptr) { void safefree(void *ptr)
{
if (ptr) { if (ptr) {
#ifdef MALLOC_LOG #ifdef MALLOC_LOG
if (fp) if (fp)
fprintf(fp, "free(%p)\n", ptr); fprintf(fp, "free(%p)\n", ptr);
#endif #endif
#ifdef MINEFIELD #ifdef MINEFIELD
minefield_c_free (ptr); minefield_c_free(ptr);
#else #else
free (ptr); free(ptr);
#endif #endif
} }
#ifdef MALLOC_LOG #ifdef MALLOC_LOG
@ -303,7 +319,8 @@ void safefree(void *ptr) {
static FILE *debug_fp = NULL; static FILE *debug_fp = NULL;
static int debug_got_console = 0; static int debug_got_console = 0;
static void dputs (char *buf) { static void dputs(char *buf)
{
DWORD dw; DWORD dw;
if (!debug_got_console) { if (!debug_got_console) {
@ -314,56 +331,58 @@ static void dputs (char *buf) {
debug_fp = fopen("debug.log", "w"); debug_fp = fopen("debug.log", "w");
} }
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, strlen(buf), &dw, NULL); WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, strlen(buf), &dw,
NULL);
fputs(buf, debug_fp); fputs(buf, debug_fp);
fflush(debug_fp); fflush(debug_fp);
} }
void dprintf(char *fmt, ...) { void dprintf(char *fmt, ...)
{
char buf[2048]; char buf[2048];
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
vsprintf(buf, fmt, ap); vsprintf(buf, fmt, ap);
dputs (buf); dputs(buf);
va_end(ap); va_end(ap);
} }
void debug_memdump (void *buf, int len, int L) { void debug_memdump(void *buf, int len, int L)
{
int i; int i;
unsigned char *p = buf; unsigned char *p = buf;
char foo[17]; char foo[17];
if (L) { if (L) {
int delta; int delta;
dprintf ("\t%d (0x%x) bytes:\n", len, len); dprintf("\t%d (0x%x) bytes:\n", len, len);
delta = 15 & (int) p; delta = 15 & (int) p;
p -= delta; p -= delta;
len += delta; len += delta;
} }
for (; 0 < len; p += 16, len -= 16) { for (; 0 < len; p += 16, len -= 16) {
dputs (" "); dputs(" ");
if (L) dprintf ("%p: ", p); if (L)
strcpy(foo, "................"); /* sixteen dots */ dprintf("%p: ", p);
strcpy(foo, "................"); /* sixteen dots */
for (i = 0; i < 16 && i < len; ++i) { for (i = 0; i < 16 && i < len; ++i) {
if (&p[i] < (unsigned char *) buf) { if (&p[i] < (unsigned char *) buf) {
dputs (" "); /* 3 spaces */ dputs(" "); /* 3 spaces */
foo[i] = ' '; foo[i] = ' ';
} else { } else {
dprintf ( dprintf("%c%02.2x",
"%c%02.2x", &p[i] != (unsigned char *) buf
&p[i] != (unsigned char *) buf && i % 4 ? '.' : ' ', && i % 4 ? '.' : ' ', p[i]
p[i] );
);
if (p[i] >= ' ' && p[i] <= '~') if (p[i] >= ' ' && p[i] <= '~')
foo[i] = (char)p[i]; foo[i] = (char) p[i];
} }
} }
foo[i] = '\0'; foo[i] = '\0';
dprintf("%*s%s\n", (16-i)*3+2, "", foo); dprintf("%*s%s\n", (16 - i) * 3 + 2, "", foo);
} }
} }
#endif /* def DEBUG */ #endif /* def DEBUG */

2
misc.h
View File

@ -19,7 +19,7 @@
#ifdef DEBUG #ifdef DEBUG
void dprintf(char *fmt, ...); void dprintf(char *fmt, ...);
void debug_memdump (void *buf, int len, int L); void debug_memdump(void *buf, int len, int L);
#define debug(x) (dprintf x) #define debug(x) (dprintf x)
#define dmemdump(buf,len) debug_memdump (buf, len, 0); #define dmemdump(buf,len) debug_memdump (buf, len, 0);
#define dmemdumpl(buf,len) debug_memdump (buf, len, 1); #define dmemdumpl(buf,len) debug_memdump (buf, len, 1);

View File

@ -11,15 +11,14 @@ static HCRYPTKEY create_des_key(unsigned char *key);
HCRYPTPROV hCryptProv; HCRYPTPROV hCryptProv;
HCRYPTKEY hDESKey[2][3] = {{0,0,0},{0,0,0}}; /* global for now */ HCRYPTKEY hDESKey[2][3] = { {0, 0, 0}, {0, 0, 0} }; /* global for now */
/* use Microsoft Enhanced Cryptographic Service Provider */ /* use Microsoft Enhanced Cryptographic Service Provider */
#define CSP MS_ENHANCED_PROV #define CSP MS_ENHANCED_PROV
static BYTE PrivateKeyWithExponentOfOne[] = static BYTE PrivateKeyWithExponentOfOne[] = {
{
0x07, 0x02, 0x00, 0x00, 0x00, 0xA4, 0x00, 0x00, 0x07, 0x02, 0x00, 0x00, 0x00, 0xA4, 0x00, 0x00,
0x52, 0x53, 0x41, 0x32, 0x00, 0x02, 0x00, 0x00, 0x52, 0x53, 0x41, 0x32, 0x00, 0x02, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0xAB, 0xEF, 0xFA, 0xC6, 0x01, 0x00, 0x00, 0x00, 0xAB, 0xEF, 0xFA, 0xC6,
@ -73,33 +72,35 @@ static BYTE PrivateKeyWithExponentOfOne[] =
* ---------------------------------------------------------*/ * ---------------------------------------------------------*/
int crypto_startup() { int crypto_startup()
if(CryptAcquireContext(&hCryptProv, "Putty", CSP, PROV_RSA_FULL, {
CRYPT_NEWKEYSET) == 0) { if (CryptAcquireContext(&hCryptProv, "Putty", CSP, PROV_RSA_FULL,
if(GetLastError() == NTE_EXISTS) { CRYPT_NEWKEYSET) == 0) {
if(CryptAcquireContext(&hCryptProv, "Putty", CSP, if (GetLastError() == NTE_EXISTS) {
PROV_RSA_FULL, 0) == 0) { if (CryptAcquireContext(&hCryptProv, "Putty", CSP,
return FALSE; /* failed to acquire context - probably PROV_RSA_FULL, 0) == 0) {
* don't have high encryption installed! */ return FALSE; /* failed to acquire context - probably
* don't have high encryption installed! */
} }
} else } else
return FALSE; /* failed to acquire context - probably return FALSE; /* failed to acquire context - probably
* don't have high encryption installed! */ * don't have high encryption installed! */
} }
return TRUE; return TRUE;
} }
void crypto_wrapup() { void crypto_wrapup()
{
int i, j; int i, j;
for(i=0; i<2; i++) { for (i = 0; i < 2; i++) {
for(j=0; j<3; j++) { for (j = 0; j < 3; j++) {
if(hDESKey[i][j]) if (hDESKey[i][j])
CryptDestroyKey(hDESKey[i][j]); CryptDestroyKey(hDESKey[i][j]);
hDESKey[i][j] = 0; hDESKey[i][j] = 0;
} }
} }
if(hCryptProv) if (hCryptProv)
CryptReleaseContext(hCryptProv, 0); CryptReleaseContext(hCryptProv, 0);
hCryptProv = 0; hCryptProv = 0;
} }
@ -109,32 +110,40 @@ void crypto_wrapup() {
* Random number functions * * Random number functions *
* ---------------------------------------------------------*/ * ---------------------------------------------------------*/
int random_byte(void) { int random_byte(void)
{
unsigned char b; unsigned char b;
if(!CryptGenRandom(hCryptProv, 1, &b)) if (!CryptGenRandom(hCryptProv, 1, &b))
fatalbox("random number generator failure!"); fatalbox("random number generator failure!");
return b; return b;
} }
void random_add_noise(void *noise, int length) { void random_add_noise(void *noise, int length)
{
/* do nothing */ /* do nothing */
} }
void random_init(void) { void random_init(void)
{
/* do nothing */ /* do nothing */
} }
void random_get_savedata(void **data, int *len) { void random_get_savedata(void **data, int *len)
{
/* do nothing */ /* do nothing */
} }
void noise_get_heavy(void (*func) (void *, int)) { void noise_get_heavy(void (*func) (void *, int))
{
/* do nothing */ /* do nothing */
} }
void noise_get_light(void (*func) (void *, int)) { void noise_get_light(void (*func) (void *, int))
{
/* do nothing */ /* do nothing */
} }
void noise_ultralight(DWORD data) { void noise_ultralight(DWORD data)
{
/* do nothing */ /* do nothing */
} }
void random_save_seed(void) { void random_save_seed(void)
{
/* do nothing */ /* do nothing */
} }
@ -144,24 +153,27 @@ void random_save_seed(void) {
* ---------------------------------------------------------*/ * ---------------------------------------------------------*/
void MD5Init(struct MD5Context *ctx) { void MD5Init(struct MD5Context *ctx)
if(!CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &ctx->hHash)) {
if (!CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &ctx->hHash))
fatalbox("Error during CryptBeginHash!\n"); fatalbox("Error during CryptBeginHash!\n");
} }
void MD5Update(struct MD5Context *ctx, void MD5Update(struct MD5Context *ctx,
unsigned char const *buf, unsigned len) { unsigned char const *buf, unsigned len)
if(CryptHashData(ctx->hHash, buf, len, 0) == 0) {
if (CryptHashData(ctx->hHash, buf, len, 0) == 0)
fatalbox("Error during CryptHashSessionKey!\n"); fatalbox("Error during CryptHashSessionKey!\n");
} }
void MD5Final(unsigned char digest[16], struct MD5Context *ctx) { void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
{
DWORD cb = 16; DWORD cb = 16;
if(CryptGetHashParam(ctx->hHash, HP_HASHVAL, digest, &cb, 0) == 0) if (CryptGetHashParam(ctx->hHash, HP_HASHVAL, digest, &cb, 0) == 0)
fatalbox("Error during CryptGetHashParam!\n"); fatalbox("Error during CryptGetHashParam!\n");
if(ctx->hHash) if (ctx->hHash)
CryptDestroyHash(ctx->hHash); CryptDestroyHash(ctx->hHash);
ctx->hHash = 0; ctx->hHash = 0;
} }
@ -172,7 +184,8 @@ void MD5Final(unsigned char digest[16], struct MD5Context *ctx) {
* ---------------------------------------------------------*/ * ---------------------------------------------------------*/
int makekey(unsigned char *data, struct RSAKey *result, int makekey(unsigned char *data, struct RSAKey *result,
unsigned char **keystr) { unsigned char **keystr)
{
unsigned char *p = data; unsigned char *p = data;
int i; int i;
@ -180,38 +193,40 @@ int makekey(unsigned char *data, struct RSAKey *result,
/* get size (bits) of modulus */ /* get size (bits) of modulus */
result->bits = 0; result->bits = 0;
for(i=0; i<4; i++) for (i = 0; i < 4; i++)
result->bits = (result->bits << 8) + *p++; result->bits = (result->bits << 8) + *p++;
/* get size (bits) of public exponent */ /* get size (bits) of public exponent */
w = 0; w = 0;
for (i=0; i<2; i++) for (i = 0; i < 2; i++)
w = (w << 8) + *p++; w = (w << 8) + *p++;
b = (w+7)/8; /* bits -> bytes */ b = (w + 7) / 8; /* bits -> bytes */
/* convert exponent to DWORD */ /* convert exponent to DWORD */
result->exponent = 0; result->exponent = 0;
for (i=0; i<b; i++) for (i = 0; i < b; i++)
result->exponent = (result->exponent << 8) + *p++; result->exponent = (result->exponent << 8) + *p++;
/* get size (bits) of modulus */ /* get size (bits) of modulus */
w = 0; w = 0;
for (i=0; i<2; i++) for (i = 0; i < 2; i++)
w = (w << 8) + *p++; w = (w << 8) + *p++;
result->bytes = b = (w+7)/8; /* bits -> bytes */ result->bytes = b = (w + 7) / 8; /* bits -> bytes */
/* allocate buffer for modulus & copy it */ /* allocate buffer for modulus & copy it */
result->modulus = malloc(b); result->modulus = malloc(b);
memcpy(result->modulus, p, b); memcpy(result->modulus, p, b);
/* update callers pointer */ /* update callers pointer */
if (keystr) *keystr = p; /* point at key string, second time */ if (keystr)
*keystr = p; /* point at key string, second time */
return (p - data) + b; return (p - data) + b;
} }
void rsaencrypt(unsigned char *data, int length, struct RSAKey *rsakey) { void rsaencrypt(unsigned char *data, int length, struct RSAKey *rsakey)
{
int i; int i;
unsigned char *pKeybuf, *pKeyin; unsigned char *pKeybuf, *pKeyin;
@ -223,35 +238,36 @@ void rsaencrypt(unsigned char *data, int length, struct RSAKey *rsakey) {
DWORD bufsize; DWORD bufsize;
/* allocate buffer for public key blob */ /* allocate buffer for public key blob */
if((pBlob = malloc(sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY) + if ((pBlob = malloc(sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY) +
rsakey->bytes)) == NULL) rsakey->bytes)) == NULL)
fatalbox("Out of memory"); fatalbox("Out of memory");
/* allocate buffer for message encryption block */ /* allocate buffer for message encryption block */
bufsize = (length + rsakey->bytes) << 1; bufsize = (length + rsakey->bytes) << 1;
if((buf = malloc(bufsize)) == NULL) if ((buf = malloc(bufsize)) == NULL)
fatalbox("Out of memory"); fatalbox("Out of memory");
/* construct public key blob from host public key */ /* construct public key blob from host public key */
pKeybuf = ((unsigned char*)pBlob) + sizeof(PUBLICKEYSTRUC) + pKeybuf = ((unsigned char *) pBlob) + sizeof(PUBLICKEYSTRUC) +
sizeof(RSAPUBKEY); sizeof(RSAPUBKEY);
pKeyin = ((unsigned char*)rsakey->modulus); pKeyin = ((unsigned char *) rsakey->modulus);
/* change big endian to little endian */ /* change big endian to little endian */
for(i=0; i<rsakey->bytes; i++) for (i = 0; i < rsakey->bytes; i++)
pKeybuf[i] = pKeyin[rsakey->bytes-i-1]; pKeybuf[i] = pKeyin[rsakey->bytes - i - 1];
pBlob->bType = PUBLICKEYBLOB; pBlob->bType = PUBLICKEYBLOB;
pBlob->bVersion = 0x02; pBlob->bVersion = 0x02;
pBlob->reserved = 0; pBlob->reserved = 0;
pBlob->aiKeyAlg = CALG_RSA_KEYX; pBlob->aiKeyAlg = CALG_RSA_KEYX;
pRPK = (RSAPUBKEY*)(((unsigned char*)pBlob) + sizeof(PUBLICKEYSTRUC)); pRPK =
pRPK->magic = 0x31415352; /* "RSA1" */ (RSAPUBKEY *) (((unsigned char *) pBlob) + sizeof(PUBLICKEYSTRUC));
pRPK->magic = 0x31415352; /* "RSA1" */
pRPK->bitlen = rsakey->bits; pRPK->bitlen = rsakey->bits;
pRPK->pubexp = rsakey->exponent; pRPK->pubexp = rsakey->exponent;
/* import public key blob into key container */ /* import public key blob into key container */
if(CryptImportKey(hCryptProv, (void*)pBlob, if (CryptImportKey(hCryptProv, (void *) pBlob,
sizeof(PUBLICKEYSTRUC)+sizeof(RSAPUBKEY)+rsakey->bytes, sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY) +
0, 0, &hRsaKey) == 0) rsakey->bytes, 0, 0, &hRsaKey) == 0)
fatalbox("Error importing RSA key!"); fatalbox("Error importing RSA key!");
/* copy message into buffer */ /* copy message into buffer */
@ -259,7 +275,7 @@ void rsaencrypt(unsigned char *data, int length, struct RSAKey *rsakey) {
dlen = length; dlen = length;
/* using host public key, encrypt the message */ /* using host public key, encrypt the message */
if(CryptEncrypt(hRsaKey, 0, TRUE, 0, buf, &dlen, bufsize) == 0) if (CryptEncrypt(hRsaKey, 0, TRUE, 0, buf, &dlen, bufsize) == 0)
fatalbox("Error encrypting using RSA key!"); fatalbox("Error encrypting using RSA key!");
/* /*
@ -267,8 +283,8 @@ void rsaencrypt(unsigned char *data, int length, struct RSAKey *rsakey) {
* key, returns the cyphertext in backwards (little endian) * key, returns the cyphertext in backwards (little endian)
* order, so reverse it! * order, so reverse it!
*/ */
for(i = 0; i < (int)dlen; i++) for (i = 0; i < (int) dlen; i++)
data[i] = buf[dlen - i - 1]; /* make it big endian */ data[i] = buf[dlen - i - 1]; /* make it big endian */
CryptDestroyKey(hRsaKey); CryptDestroyKey(hRsaKey);
free(buf); free(buf);
@ -277,22 +293,24 @@ void rsaencrypt(unsigned char *data, int length, struct RSAKey *rsakey) {
} }
int rsastr_len(struct RSAKey *key) { int rsastr_len(struct RSAKey *key)
{
return 2 * (sizeof(DWORD) + key->bytes) + 10; return 2 * (sizeof(DWORD) + key->bytes) + 10;
} }
void rsastr_fmt(char *str, struct RSAKey *key) { void rsastr_fmt(char *str, struct RSAKey *key)
{
int len = 0, i; int len = 0, i;
sprintf(str+len, "%04x", key->exponent); sprintf(str + len, "%04x", key->exponent);
len += strlen(str+len); len += strlen(str + len);
str[len++] = '/'; str[len++] = '/';
for (i=1; i<key->bytes; i++) { for (i = 1; i < key->bytes; i++) {
sprintf(str+len, "%02x", key->modulus[i]); sprintf(str + len, "%02x", key->modulus[i]);
len += strlen(str+len); len += strlen(str + len);
} }
str[len] = '\0'; str[len] = '\0';
} }
@ -304,39 +322,42 @@ void rsastr_fmt(char *str, struct RSAKey *key) {
* ---------------------------------------------------------*/ * ---------------------------------------------------------*/
void des3_sesskey(unsigned char *key) { void des3_sesskey(unsigned char *key)
{
int i, j; int i, j;
for(i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
for(j = 0; j < 3; j++) { for (j = 0; j < 3; j++) {
hDESKey[i][j] = create_des_key(key + (j * 8)); hDESKey[i][j] = create_des_key(key + (j * 8));
} }
} }
} }
void des3_encrypt_blk(unsigned char *blk, int len) { void des3_encrypt_blk(unsigned char *blk, int len)
{
DWORD dlen; DWORD dlen;
dlen = len; dlen = len;
if(CryptEncrypt(hDESKey[0][0], 0, FALSE, 0, blk, &dlen, len + 8) == 0) if (CryptEncrypt(hDESKey[0][0], 0, FALSE, 0, blk, &dlen, len + 8) == 0)
fatalbox("Error encrypting block!\n"); fatalbox("Error encrypting block!\n");
if(CryptDecrypt(hDESKey[0][1], 0, FALSE, 0, blk, &dlen) == 0) if (CryptDecrypt(hDESKey[0][1], 0, FALSE, 0, blk, &dlen) == 0)
fatalbox("Error encrypting block!\n"); fatalbox("Error encrypting block!\n");
if(CryptEncrypt(hDESKey[0][2], 0, FALSE, 0, blk, &dlen, len + 8) == 0) if (CryptEncrypt(hDESKey[0][2], 0, FALSE, 0, blk, &dlen, len + 8) == 0)
fatalbox("Error encrypting block!\n"); fatalbox("Error encrypting block!\n");
} }
void des3_decrypt_blk(unsigned char *blk, int len) { void des3_decrypt_blk(unsigned char *blk, int len)
{
DWORD dlen; DWORD dlen;
dlen = len; dlen = len;
if(CryptDecrypt(hDESKey[1][2], 0, FALSE, 0, blk, &dlen) == 0) if (CryptDecrypt(hDESKey[1][2], 0, FALSE, 0, blk, &dlen) == 0)
fatalbox("Error decrypting block!\n"); fatalbox("Error decrypting block!\n");
if(CryptEncrypt(hDESKey[1][1], 0, FALSE, 0, blk, &dlen, len + 8) == 0) if (CryptEncrypt(hDESKey[1][1], 0, FALSE, 0, blk, &dlen, len + 8) == 0)
fatalbox("Error decrypting block!\n"); fatalbox("Error decrypting block!\n");
if(CryptDecrypt(hDESKey[1][0], 0, FALSE, 0, blk, &dlen) == 0) if (CryptDecrypt(hDESKey[1][0], 0, FALSE, 0, blk, &dlen) == 0)
fatalbox("Error decrypting block!\n"); fatalbox("Error decrypting block!\n");
} }
@ -348,26 +369,29 @@ struct ssh_cipher ssh_3des = {
}; };
void des_sesskey(unsigned char *key) { void des_sesskey(unsigned char *key)
{
int i; int i;
for(i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
hDESKey[i][0] = create_des_key(key); hDESKey[i][0] = create_des_key(key);
} }
} }
void des_encrypt_blk(unsigned char *blk, int len) { void des_encrypt_blk(unsigned char *blk, int len)
{
DWORD dlen; DWORD dlen;
dlen = len; dlen = len;
if(CryptEncrypt(hDESKey[0][0], 0, FALSE, 0, blk, &dlen, len + 8) == 0) if (CryptEncrypt(hDESKey[0][0], 0, FALSE, 0, blk, &dlen, len + 8) == 0)
fatalbox("Error encrypting block!\n"); fatalbox("Error encrypting block!\n");
} }
void des_decrypt_blk(unsigned char *blk, int len) { void des_decrypt_blk(unsigned char *blk, int len)
{
DWORD dlen; DWORD dlen;
dlen = len; dlen = len;
if(CryptDecrypt(hDESKey[1][0], 0, FALSE, 0, blk, &dlen) == 0) if (CryptDecrypt(hDESKey[1][0], 0, FALSE, 0, blk, &dlen) == 0)
fatalbox("Error decrypting block!\n"); fatalbox("Error decrypting block!\n");
} }
@ -378,7 +402,8 @@ struct ssh_cipher ssh_des = {
}; };
static HCRYPTKEY create_des_key(unsigned char *key) { static HCRYPTKEY create_des_key(unsigned char *key)
{
HCRYPTKEY hSessionKey, hPrivateKey; HCRYPTKEY hSessionKey, hPrivateKey;
DWORD dlen = 8; DWORD dlen = 8;
@ -390,33 +415,33 @@ static HCRYPTKEY create_des_key(unsigned char *key) {
* import session key, since only encrypted session keys can be * import session key, since only encrypted session keys can be
* imported * imported
*/ */
if(CryptImportKey(hCryptProv, PrivateKeyWithExponentOfOne, if (CryptImportKey(hCryptProv, PrivateKeyWithExponentOfOne,
sizeof(PrivateKeyWithExponentOfOne), sizeof(PrivateKeyWithExponentOfOne),
0, 0, &hPrivateKey) == 0) 0, 0, &hPrivateKey) == 0)
return 0; return 0;
/* now encrypt session key using special private key */ /* now encrypt session key using special private key */
memcpy(buf + sizeof(BLOBHEADER) + sizeof(ALG_ID), key, 8); memcpy(buf + sizeof(BLOBHEADER) + sizeof(ALG_ID), key, 8);
if(CryptEncrypt(hPrivateKey, 0, TRUE, 0, if (CryptEncrypt(hPrivateKey, 0, TRUE, 0,
buf + sizeof(BLOBHEADER) + sizeof(ALG_ID), buf + sizeof(BLOBHEADER) + sizeof(ALG_ID),
&dlen, 256) == 0) &dlen, 256) == 0)
return 0; return 0;
/* build session key blob */ /* build session key blob */
pbh = (BLOBHEADER*)buf; pbh = (BLOBHEADER *) buf;
pbh->bType = SIMPLEBLOB; pbh->bType = SIMPLEBLOB;
pbh->bVersion = 0x02; pbh->bVersion = 0x02;
pbh->reserved = 0; pbh->reserved = 0;
pbh->aiKeyAlg = CALG_DES; pbh->aiKeyAlg = CALG_DES;
*((ALG_ID*)(buf+sizeof(BLOBHEADER))) = CALG_RSA_KEYX; *((ALG_ID *) (buf + sizeof(BLOBHEADER))) = CALG_RSA_KEYX;
/* import session key into key container */ /* import session key into key container */
if(CryptImportKey(hCryptProv, buf, if (CryptImportKey(hCryptProv, buf,
dlen + sizeof(BLOBHEADER) + sizeof(ALG_ID), dlen + sizeof(BLOBHEADER) + sizeof(ALG_ID),
hPrivateKey, 0, &hSessionKey) == 0) hPrivateKey, 0, &hSessionKey) == 0)
return 0; return 0;
if(hPrivateKey) if (hPrivateKey)
CryptDestroyKey(hPrivateKey); CryptDestroyKey(hPrivateKey);
return hSessionKey; return hSessionKey;

View File

@ -19,35 +19,35 @@ typedef struct socket_function_table **Socket;
typedef struct plug_function_table **Plug; typedef struct plug_function_table **Plug;
struct socket_function_table { struct socket_function_table {
Plug (*plug) (Socket s, Plug p); Plug(*plug) (Socket s, Plug p);
/* use a different plug (return the old one) */ /* use a different plug (return the old one) */
/* if p is NULL, it doesn't change the plug */ /* if p is NULL, it doesn't change the plug */
/* but it does return the one it's using */ /* but it does return the one it's using */
void (*close) (Socket s); void (*close) (Socket s);
void (*write) (Socket s, char *data, int len); void (*write) (Socket s, char *data, int len);
void (*write_oob) (Socket s, char *data, int len); void (*write_oob) (Socket s, char *data, int len);
void (*flush) (Socket s); void (*flush) (Socket s);
/* ignored by tcp, but vital for ssl */ /* ignored by tcp, but vital for ssl */
char *(*socket_error) (Socket s); char *(*socket_error) (Socket s);
}; };
struct plug_function_table { struct plug_function_table {
int (*closing) int (*closing)
(Plug p, char *error_msg, int error_code, int calling_back); (Plug p, char *error_msg, int error_code, int calling_back);
/* error_msg is NULL iff it is not an error (ie it closed normally) */ /* error_msg is NULL iff it is not an error (ie it closed normally) */
/* calling_back != 0 iff there is a Plug function */ /* calling_back != 0 iff there is a Plug function */
/* currently running (would cure the fixme in try_send()) */ /* currently running (would cure the fixme in try_send()) */
int (*receive) (Plug p, int urgent, char *data, int len); int (*receive) (Plug p, int urgent, char *data, int len);
/* /*
* - urgent==0. `data' points to `len' bytes of perfectly * - urgent==0. `data' points to `len' bytes of perfectly
* ordinary data. * ordinary data.
* *
* - urgent==1. `data' points to `len' bytes of data, * - urgent==1. `data' points to `len' bytes of data,
* which were read from before an Urgent pointer. * which were read from before an Urgent pointer.
* *
* - urgent==2. `data' points to `len' bytes of data, * - urgent==2. `data' points to `len' bytes of data,
* the first of which was the one at the Urgent mark. * the first of which was the one at the Urgent mark.
*/ */
}; };
@ -56,7 +56,8 @@ void sk_init(void); /* called once at program startup */
SockAddr sk_namelookup(char *host, char **canonicalname); SockAddr sk_namelookup(char *host, char **canonicalname);
void sk_addr_free(SockAddr addr); void sk_addr_free(SockAddr addr);
Socket sk_new(SockAddr addr, int port, int privport, int oobinline, Plug p); Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
Plug p);
#define sk_plug(s,p) (((*s)->plug) (s, p)) #define sk_plug(s,p) (((*s)->plug) (s, p))
#define sk_close(s) (((*s)->close) (s)) #define sk_close(s) (((*s)->close) (s))
@ -106,24 +107,22 @@ typedef struct ssl_client_plug_function_table **SSL_Client_Plug;
struct ssl_client_socket_function_table { struct ssl_client_socket_function_table {
struct socket_function_table base; struct socket_function_table base;
void (*renegotiate) (SSL_Client_Socket s); void (*renegotiate) (SSL_Client_Socket s);
/* renegotiate the cipher spec */ /* renegotiate the cipher spec */
}; };
struct ssl_client_plug_function_table { struct ssl_client_plug_function_table {
struct plug_function_table base; struct plug_function_table base;
int (*refuse_cert) (SSL_Client_Plug p, Certificate cert[]); int (*refuse_cert) (SSL_Client_Plug p, Certificate cert[]);
/* do we accept this certificate chain? If not, why not? */ /* do we accept this certificate chain? If not, why not? */
/* cert[0] is the server's certificate, cert[] is NULL-terminated */ /* cert[0] is the server's certificate, cert[] is NULL-terminated */
/* the last certificate may or may not be the root certificate */ /* the last certificate may or may not be the root certificate */
Our_Certificate (*client_cert) (SSL_Client_Plug p); Our_Certificate(*client_cert) (SSL_Client_Plug p);
/* the server wants us to identify ourselves */ /* the server wants us to identify ourselves */
/* may return NULL if we want anonymity */ /* may return NULL if we want anonymity */
}; };
SSL_Client_Socket sk_ssl_client_over ( SSL_Client_Socket sk_ssl_client_over(Socket s, /* pre-existing (tcp) connection */
Socket s, /* pre-existing (tcp) connection */ SSL_Client_Plug p);
SSL_Client_Plug p
);
#define sk_renegotiate(s) (((*s)->renegotiate) (s)) #define sk_renegotiate(s) (((*s)->renegotiate) (s))

49
noise.c
View File

@ -13,7 +13,7 @@
/* /*
* GetSystemPowerStatus function. * GetSystemPowerStatus function.
*/ */
typedef BOOL (WINAPI *gsps_t)(LPSYSTEM_POWER_STATUS); typedef BOOL(WINAPI * gsps_t) (LPSYSTEM_POWER_STATUS);
static gsps_t gsps; static gsps_t gsps;
/* /*
@ -22,10 +22,11 @@ static gsps_t gsps;
* free space and a process snapshot. * free space and a process snapshot.
*/ */
void noise_get_heavy(void (*func) (void *, int)) { void noise_get_heavy(void (*func) (void *, int))
{
HANDLE srch; HANDLE srch;
WIN32_FIND_DATA finddata; WIN32_FIND_DATA finddata;
char winpath[MAX_PATH+3]; char winpath[MAX_PATH + 3];
HMODULE mod; HMODULE mod;
GetWindowsDirectory(winpath, sizeof(winpath)); GetWindowsDirectory(winpath, sizeof(winpath));
@ -43,11 +44,12 @@ void noise_get_heavy(void (*func) (void *, int)) {
gsps = NULL; gsps = NULL;
mod = GetModuleHandle("KERNEL32"); mod = GetModuleHandle("KERNEL32");
if (mod) { if (mod) {
gsps = (gsps_t)GetProcAddress(mod, "GetSystemPowerStatus"); gsps = (gsps_t) GetProcAddress(mod, "GetSystemPowerStatus");
} }
} }
void random_save_seed(void) { void random_save_seed(void)
{
int len; int len;
void *data; void *data;
@ -60,7 +62,8 @@ void random_save_seed(void) {
* stirring, and will acquire the system time in all available * stirring, and will acquire the system time in all available
* forms and the battery status. * forms and the battery status.
*/ */
void noise_get_light(void (*func) (void *, int)) { void noise_get_light(void (*func) (void *, int))
{
SYSTEMTIME systime; SYSTEMTIME systime;
DWORD adjust[2]; DWORD adjust[2];
BOOL rubbish; BOOL rubbish;
@ -76,8 +79,8 @@ void noise_get_light(void (*func) (void *, int)) {
* Call GetSystemPowerStatus if present. * Call GetSystemPowerStatus if present.
*/ */
if (gsps) { if (gsps) {
if (gsps(&pwrstat)) if (gsps(&pwrstat))
func(&pwrstat, sizeof(pwrstat)); func(&pwrstat, sizeof(pwrstat));
} }
} }
@ -87,25 +90,34 @@ void noise_get_light(void (*func) (void *, int)) {
* virtual memory, the state of the process's message queue, which * virtual memory, the state of the process's message queue, which
* window is in the foreground, which owns the clipboard, etc. * window is in the foreground, which owns the clipboard, etc.
*/ */
void noise_regular(void) { void noise_regular(void)
{
HWND w; HWND w;
DWORD z; DWORD z;
POINT pt; POINT pt;
MEMORYSTATUS memstat; MEMORYSTATUS memstat;
FILETIME times[4]; FILETIME times[4];
w = GetForegroundWindow(); random_add_noise(&w, sizeof(w)); w = GetForegroundWindow();
w = GetCapture(); random_add_noise(&w, sizeof(w)); random_add_noise(&w, sizeof(w));
w = GetClipboardOwner(); random_add_noise(&w, sizeof(w)); w = GetCapture();
z = GetQueueStatus(QS_ALLEVENTS); random_add_noise(&z, sizeof(z)); random_add_noise(&w, sizeof(w));
w = GetClipboardOwner();
random_add_noise(&w, sizeof(w));
z = GetQueueStatus(QS_ALLEVENTS);
random_add_noise(&z, sizeof(z));
GetCursorPos(&pt); random_add_noise(&pt, sizeof(pt)); GetCursorPos(&pt);
random_add_noise(&pt, sizeof(pt));
GlobalMemoryStatus(&memstat); random_add_noise(&memstat, sizeof(memstat)); GlobalMemoryStatus(&memstat);
random_add_noise(&memstat, sizeof(memstat));
GetThreadTimes(GetCurrentThread(), times, times+1, times+2, times+3); GetThreadTimes(GetCurrentThread(), times, times + 1, times + 2,
times + 3);
random_add_noise(&times, sizeof(times)); random_add_noise(&times, sizeof(times));
GetProcessTimes(GetCurrentProcess(), times, times+1, times+2, times+3); GetProcessTimes(GetCurrentProcess(), times, times + 1, times + 2,
times + 3);
random_add_noise(&times, sizeof(times)); random_add_noise(&times, sizeof(times));
} }
@ -115,7 +127,8 @@ void noise_regular(void) {
* counter to the noise pool. It gets the scan code or mouse * counter to the noise pool. It gets the scan code or mouse
* position passed in. * position passed in.
*/ */
void noise_ultralight(DWORD data) { void noise_ultralight(DWORD data)
{
DWORD wintime; DWORD wintime;
LARGE_INTEGER perftime; LARGE_INTEGER perftime;

1304
pageant.c

File diff suppressed because it is too large Load Diff

View File

@ -23,16 +23,18 @@
((unsigned long)(unsigned char)(cp)[2] << 8) | \ ((unsigned long)(unsigned char)(cp)[2] << 8) | \
((unsigned long)(unsigned char)(cp)[3])) ((unsigned long)(unsigned char)(cp)[3]))
int agent_exists(void) { int agent_exists(void)
{
HWND hwnd; HWND hwnd;
hwnd = FindWindow("Pageant", "Pageant"); hwnd = FindWindow("Pageant", "Pageant");
if (!hwnd) if (!hwnd)
return FALSE; return FALSE;
else else
return TRUE; return TRUE;
} }
void agent_query(void *in, int inlen, void **out, int *outlen) { void agent_query(void *in, int inlen, void **out, int *outlen)
{
HWND hwnd; HWND hwnd;
char mapname[64]; char mapname[64];
HANDLE filemap; HANDLE filemap;
@ -46,28 +48,28 @@ void agent_query(void *in, int inlen, void **out, int *outlen) {
hwnd = FindWindow("Pageant", "Pageant"); hwnd = FindWindow("Pageant", "Pageant");
debug(("hwnd is %p\n", hwnd)); debug(("hwnd is %p\n", hwnd));
if (!hwnd) if (!hwnd)
return; return;
sprintf(mapname, "PageantRequest%08x", GetCurrentThreadId()); sprintf(mapname, "PageantRequest%08x", GetCurrentThreadId());
filemap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, filemap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
0, AGENT_MAX_MSGLEN, mapname); 0, AGENT_MAX_MSGLEN, mapname);
if (!filemap) if (!filemap)
return; return;
p = MapViewOfFile(filemap, FILE_MAP_WRITE, 0, 0, 0); p = MapViewOfFile(filemap, FILE_MAP_WRITE, 0, 0, 0);
memcpy(p, in, inlen); memcpy(p, in, inlen);
cds.dwData = AGENT_COPYDATA_ID; cds.dwData = AGENT_COPYDATA_ID;
cds.cbData = 1+strlen(mapname); cds.cbData = 1 + strlen(mapname);
cds.lpData = mapname; cds.lpData = mapname;
id = SendMessage(hwnd, WM_COPYDATA, (WPARAM)NULL, (LPARAM)&cds); id = SendMessage(hwnd, WM_COPYDATA, (WPARAM) NULL, (LPARAM) & cds);
debug(("return is %d\n", id)); debug(("return is %d\n", id));
if (id > 0) { if (id > 0) {
retlen = 4 + GET_32BIT(p); retlen = 4 + GET_32BIT(p);
debug(("len is %d\n", retlen)); debug(("len is %d\n", retlen));
ret = smalloc(retlen); ret = smalloc(retlen);
if (ret) { if (ret) {
memcpy(ret, p, retlen); memcpy(ret, p, retlen);
*out = ret; *out = ret;
*outlen = retlen; *outlen = retlen;
} }
} }
UnmapViewOfFile(p); UnmapViewOfFile(p);
CloseHandle(filemap); CloseHandle(filemap);
@ -75,7 +77,8 @@ void agent_query(void *in, int inlen, void **out, int *outlen) {
#ifdef TESTMODE #ifdef TESTMODE
int main(void) { int main(void)
{
void *msg; void *msg;
int len; int len;
int i; int i;
@ -83,7 +86,7 @@ int main(void) {
agent_query("\0\0\0\1\1", 5, &msg, &len); agent_query("\0\0\0\1\1", 5, &msg, &len);
debug(("%d:", len)); debug(("%d:", len));
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
debug((" %02x", ((unsigned char *)msg)[i])); debug((" %02x", ((unsigned char *) msg)[i]));
debug(("\n")); debug(("\n"));
return 0; return 0;
} }

699
plink.c
View File

@ -10,12 +10,13 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdarg.h> #include <stdarg.h>
#define PUTTY_DO_GLOBALS /* actually _define_ globals */ #define PUTTY_DO_GLOBALS /* actually _define_ globals */
#include "putty.h" #include "putty.h"
#include "storage.h" #include "storage.h"
#include "tree234.h" #include "tree234.h"
void fatalbox (char *p, ...) { void fatalbox(char *p, ...)
{
va_list ap; va_list ap;
fprintf(stderr, "FATAL ERROR: "); fprintf(stderr, "FATAL ERROR: ");
va_start(ap, p); va_start(ap, p);
@ -25,7 +26,8 @@ void fatalbox (char *p, ...) {
WSACleanup(); WSACleanup();
exit(1); exit(1);
} }
void connection_fatal (char *p, ...) { void connection_fatal(char *p, ...)
{
va_list ap; va_list ap;
fprintf(stderr, "FATAL ERROR: "); fprintf(stderr, "FATAL ERROR: ");
va_start(ap, p); va_start(ap, p);
@ -38,43 +40,45 @@ void connection_fatal (char *p, ...) {
static char *password = NULL; static char *password = NULL;
void logevent(char *string) { } void logevent(char *string)
{
}
void verify_ssh_host_key(char *host, int port, char *keytype, void verify_ssh_host_key(char *host, int port, char *keytype,
char *keystr, char *fingerprint) { char *keystr, char *fingerprint)
{
int ret; int ret;
HANDLE hin; HANDLE hin;
DWORD savemode, i; DWORD savemode, i;
static const char absentmsg[] = static const char absentmsg[] =
"The server's host key is not cached in the registry. You\n" "The server's host key is not cached in the registry. You\n"
"have no guarantee that the server is the computer you\n" "have no guarantee that the server is the computer you\n"
"think it is.\n" "think it is.\n"
"The server's key fingerprint is:\n" "The server's key fingerprint is:\n"
"%s\n" "%s\n"
"If you trust this host, enter \"y\" to add the key to\n" "If you trust this host, enter \"y\" to add the key to\n"
"PuTTY's cache and carry on connecting.\n" "PuTTY's cache and carry on connecting.\n"
"If you do not trust this host, enter \"n\" to abandon the\n" "If you do not trust this host, enter \"n\" to abandon the\n"
"connection.\n" "connection.\n" "Continue connecting? (y/n) ";
"Continue connecting? (y/n) ";
static const char wrongmsg[] = static const char wrongmsg[] =
"WARNING - POTENTIAL SECURITY BREACH!\n" "WARNING - POTENTIAL SECURITY BREACH!\n"
"The server's host key does not match the one PuTTY has\n" "The server's host key does not match the one PuTTY has\n"
"cached in the registry. This means that either the\n" "cached in the registry. This means that either the\n"
"server administrator has changed the host key, or you\n" "server administrator has changed the host key, or you\n"
"have actually connected to another computer pretending\n" "have actually connected to another computer pretending\n"
"to be the server.\n" "to be the server.\n"
"The new key fingerprint is:\n" "The new key fingerprint is:\n"
"%s\n" "%s\n"
"If you were expecting this change and trust the new key,\n" "If you were expecting this change and trust the new key,\n"
"enter \"y\" to update PuTTY's cache and continue connecting.\n" "enter \"y\" to update PuTTY's cache and continue connecting.\n"
"If you want to carry on connecting but without updating\n" "If you want to carry on connecting but without updating\n"
"the cache, enter \"n\".\n" "the cache, enter \"n\".\n"
"If you want to abandon the connection completely, press\n" "If you want to abandon the connection completely, press\n"
"Return to cancel. Pressing Return is the ONLY guaranteed\n" "Return to cancel. Pressing Return is the ONLY guaranteed\n"
"safe choice.\n" "safe choice.\n"
"Update cached key? (y/n, Return cancels connection) "; "Update cached key? (y/n, Return cancels connection) ";
static const char abandoned[] = "Connection abandoned.\n"; static const char abandoned[] = "Connection abandoned.\n";
@ -85,41 +89,41 @@ void verify_ssh_host_key(char *host, int port, char *keytype,
*/ */
ret = verify_host_key(host, port, keytype, keystr); ret = verify_host_key(host, port, keytype, keystr);
if (ret == 0) /* success - key matched OK */ if (ret == 0) /* success - key matched OK */
return; return;
if (ret == 2) { /* key was different */ if (ret == 2) { /* key was different */
fprintf(stderr, wrongmsg, fingerprint); fprintf(stderr, wrongmsg, fingerprint);
fflush(stderr); fflush(stderr);
} }
if (ret == 1) { /* key was absent */ if (ret == 1) { /* key was absent */
fprintf(stderr, absentmsg, fingerprint); fprintf(stderr, absentmsg, fingerprint);
fflush(stderr); fflush(stderr);
} }
hin = GetStdHandle(STD_INPUT_HANDLE); hin = GetStdHandle(STD_INPUT_HANDLE);
GetConsoleMode(hin, &savemode); GetConsoleMode(hin, &savemode);
SetConsoleMode(hin, (savemode | ENABLE_ECHO_INPUT | SetConsoleMode(hin, (savemode | ENABLE_ECHO_INPUT |
ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT)); ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT));
ReadFile(hin, line, sizeof(line)-1, &i, NULL); ReadFile(hin, line, sizeof(line) - 1, &i, NULL);
SetConsoleMode(hin, savemode); SetConsoleMode(hin, savemode);
if (ret == 2) { /* key was different */ if (ret == 2) { /* key was different */
if (line[0] != '\0' && line[0] != '\r' && line[0] != '\n') { if (line[0] != '\0' && line[0] != '\r' && line[0] != '\n') {
if (line[0] == 'y' || line[0] == 'Y') if (line[0] == 'y' || line[0] == 'Y')
store_host_key(host, port, keytype, keystr); store_host_key(host, port, keytype, keystr);
} else { } else {
fprintf(stderr, abandoned); fprintf(stderr, abandoned);
exit(0); exit(0);
} }
} }
if (ret == 1) { /* key was absent */ if (ret == 1) { /* key was absent */
if (line[0] == 'y' || line[0] == 'Y') if (line[0] == 'y' || line[0] == 'Y')
store_host_key(host, port, keytype, keystr); store_host_key(host, port, keytype, keystr);
else { else {
fprintf(stderr, abandoned); fprintf(stderr, abandoned);
exit(0); exit(0);
} }
} }
} }
@ -128,33 +132,38 @@ DWORD orig_console_mode;
WSAEVENT netevent; WSAEVENT netevent;
void from_backend(int is_stderr, char *data, int len) { void from_backend(int is_stderr, char *data, int len)
{
int pos; int pos;
DWORD ret; DWORD ret;
HANDLE h = (is_stderr ? errhandle : outhandle); HANDLE h = (is_stderr ? errhandle : outhandle);
pos = 0; pos = 0;
while (pos < len) { while (pos < len) {
if (!WriteFile(h, data+pos, len-pos, &ret, NULL)) if (!WriteFile(h, data + pos, len - pos, &ret, NULL))
return; /* give up in panic */ return; /* give up in panic */
pos += ret; pos += ret;
} }
} }
int term_ldisc(int mode) { return FALSE; } int term_ldisc(int mode)
void ldisc_update(int echo, int edit) { {
return FALSE;
}
void ldisc_update(int echo, int edit)
{
/* Update stdin read mode to reflect changes in line discipline. */ /* Update stdin read mode to reflect changes in line discipline. */
DWORD mode; DWORD mode;
mode = ENABLE_PROCESSED_INPUT; mode = ENABLE_PROCESSED_INPUT;
if (echo) if (echo)
mode = mode | ENABLE_ECHO_INPUT; mode = mode | ENABLE_ECHO_INPUT;
else else
mode = mode &~ ENABLE_ECHO_INPUT; mode = mode & ~ENABLE_ECHO_INPUT;
if (edit) if (edit)
mode = mode | ENABLE_LINE_INPUT; mode = mode | ENABLE_LINE_INPUT;
else else
mode = mode &~ ENABLE_LINE_INPUT; mode = mode & ~ENABLE_LINE_INPUT;
SetConsoleMode(inhandle, mode); SetConsoleMode(inhandle, mode);
} }
@ -170,57 +179,61 @@ static int get_line(const char *prompt, char *str, int maxlen, int is_pw)
DWORD savemode, newmode, i; DWORD savemode, newmode, i;
if (is_pw && password) { if (is_pw && password) {
static int tried_once = 0; static int tried_once = 0;
if (tried_once) { if (tried_once) {
return 0; return 0;
} else { } else {
strncpy(str, password, maxlen); strncpy(str, password, maxlen);
str[maxlen-1] = '\0'; str[maxlen - 1] = '\0';
tried_once = 1; tried_once = 1;
return 1; return 1;
} }
} }
hin = GetStdHandle(STD_INPUT_HANDLE); hin = GetStdHandle(STD_INPUT_HANDLE);
hout = GetStdHandle(STD_OUTPUT_HANDLE); hout = GetStdHandle(STD_OUTPUT_HANDLE);
if (hin == INVALID_HANDLE_VALUE || hout == INVALID_HANDLE_VALUE) { if (hin == INVALID_HANDLE_VALUE || hout == INVALID_HANDLE_VALUE) {
fprintf(stderr, "Cannot get standard input/output handles"); fprintf(stderr, "Cannot get standard input/output handles");
return 0; return 0;
} }
GetConsoleMode(hin, &savemode); GetConsoleMode(hin, &savemode);
newmode = savemode | ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT; newmode = savemode | ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT;
if (is_pw) if (is_pw)
newmode &= ~ENABLE_ECHO_INPUT; newmode &= ~ENABLE_ECHO_INPUT;
else else
newmode |= ENABLE_ECHO_INPUT; newmode |= ENABLE_ECHO_INPUT;
SetConsoleMode(hin, newmode); SetConsoleMode(hin, newmode);
WriteFile(hout, prompt, strlen(prompt), &i, NULL); WriteFile(hout, prompt, strlen(prompt), &i, NULL);
ReadFile(hin, str, maxlen-1, &i, NULL); ReadFile(hin, str, maxlen - 1, &i, NULL);
SetConsoleMode(hin, savemode); SetConsoleMode(hin, savemode);
if ((int)i > maxlen) i = maxlen-1; else i = i - 2; if ((int) i > maxlen)
i = maxlen - 1;
else
i = i - 2;
str[i] = '\0'; str[i] = '\0';
if (is_pw) if (is_pw)
WriteFile(hout, "\r\n", 2, &i, NULL); WriteFile(hout, "\r\n", 2, &i, NULL);
return 1; return 1;
} }
static DWORD WINAPI stdin_read_thread(void *param) { static DWORD WINAPI stdin_read_thread(void *param)
struct input_data *idata = (struct input_data *)param; {
struct input_data *idata = (struct input_data *) param;
HANDLE inhandle; HANDLE inhandle;
inhandle = GetStdHandle(STD_INPUT_HANDLE); inhandle = GetStdHandle(STD_INPUT_HANDLE);
while (ReadFile(inhandle, idata->buffer, sizeof(idata->buffer), while (ReadFile(inhandle, idata->buffer, sizeof(idata->buffer),
&idata->len, NULL) && idata->len > 0) { &idata->len, NULL) && idata->len > 0) {
SetEvent(idata->event); SetEvent(idata->event);
WaitForSingleObject(idata->eventback, INFINITE); WaitForSingleObject(idata->eventback, INFINITE);
} }
idata->len = 0; idata->len = 0;
@ -246,23 +259,27 @@ static void usage(void)
exit(1); exit(1);
} }
char *do_select(SOCKET skt, int startup) { char *do_select(SOCKET skt, int startup)
{
int events; int events;
if (startup) { if (startup) {
events = FD_READ | FD_WRITE | FD_OOB | FD_CLOSE; events = FD_READ | FD_WRITE | FD_OOB | FD_CLOSE;
} else { } else {
events = 0; events = 0;
} }
if (WSAEventSelect (skt, netevent, events) == SOCKET_ERROR) { if (WSAEventSelect(skt, netevent, events) == SOCKET_ERROR) {
switch (WSAGetLastError()) { switch (WSAGetLastError()) {
case WSAENETDOWN: return "Network is down"; case WSAENETDOWN:
default: return "WSAAsyncSelect(): unknown error"; return "Network is down";
} default:
return "WSAAsyncSelect(): unknown error";
}
} }
return NULL; return NULL;
} }
int main(int argc, char **argv) { int main(int argc, char **argv)
{
WSADATA wsadata; WSADATA wsadata;
WORD winsock_ver; WORD winsock_ver;
WSAEVENT stdinevent; WSAEVENT stdinevent;
@ -277,7 +294,8 @@ int main(int argc, char **argv) {
ssh_get_line = get_line; ssh_get_line = get_line;
sklist = NULL; skcount = sksize = 0; sklist = NULL;
skcount = sksize = 0;
flags = FLAG_STDERR; flags = FLAG_STDERR;
/* /*
@ -287,208 +305,220 @@ int main(int argc, char **argv) {
default_protocol = cfg.protocol; default_protocol = cfg.protocol;
default_port = cfg.port; default_port = cfg.port;
{ {
/* /*
* Override the default protocol if PLINK_PROTOCOL is set. * Override the default protocol if PLINK_PROTOCOL is set.
*/ */
char *p = getenv("PLINK_PROTOCOL"); char *p = getenv("PLINK_PROTOCOL");
int i; int i;
if (p) { if (p) {
for (i = 0; backends[i].backend != NULL; i++) { for (i = 0; backends[i].backend != NULL; i++) {
if (!strcmp(backends[i].name, p)) { if (!strcmp(backends[i].name, p)) {
default_protocol = cfg.protocol = backends[i].protocol; default_protocol = cfg.protocol = backends[i].protocol;
default_port = cfg.port = backends[i].backend->default_port; default_port = cfg.port =
break; backends[i].backend->default_port;
} break;
} }
} }
}
} }
while (--argc) { while (--argc) {
char *p = *++argv; char *p = *++argv;
if (*p == '-') { if (*p == '-') {
if (!strcmp(p, "-ssh")) { if (!strcmp(p, "-ssh")) {
default_protocol = cfg.protocol = PROT_SSH; default_protocol = cfg.protocol = PROT_SSH;
default_port = cfg.port = 22; default_port = cfg.port = 22;
} else if (!strcmp(p, "-telnet")) { } else if (!strcmp(p, "-telnet")) {
default_protocol = cfg.protocol = PROT_TELNET; default_protocol = cfg.protocol = PROT_TELNET;
default_port = cfg.port = 23; default_port = cfg.port = 23;
} else if (!strcmp(p, "-raw")) { } else if (!strcmp(p, "-raw")) {
default_protocol = cfg.protocol = PROT_RAW; default_protocol = cfg.protocol = PROT_RAW;
} else if (!strcmp(p, "-v")) { } else if (!strcmp(p, "-v")) {
flags |= FLAG_VERBOSE; flags |= FLAG_VERBOSE;
} else if (!strcmp(p, "-log")) { } else if (!strcmp(p, "-log")) {
logfile = "putty.log"; logfile = "putty.log";
} else if (!strcmp(p, "-pw") && argc > 1) { } else if (!strcmp(p, "-pw") && argc > 1) {
--argc, password = *++argv; --argc, password = *++argv;
} else if (!strcmp(p, "-l") && argc > 1) { } else if (!strcmp(p, "-l") && argc > 1) {
char *username; char *username;
--argc, username = *++argv; --argc, username = *++argv;
strncpy(cfg.username, username, sizeof(cfg.username)); strncpy(cfg.username, username, sizeof(cfg.username));
cfg.username[sizeof(cfg.username)-1] = '\0'; cfg.username[sizeof(cfg.username) - 1] = '\0';
} else if (!strcmp(p, "-m") && argc > 1) { } else if (!strcmp(p, "-m") && argc > 1) {
char *filename, *command; char *filename, *command;
int cmdlen, cmdsize; int cmdlen, cmdsize;
FILE *fp; FILE *fp;
int c, d; int c, d;
--argc, filename = *++argv; --argc, filename = *++argv;
cmdlen = cmdsize = 0; cmdlen = cmdsize = 0;
command = NULL; command = NULL;
fp = fopen(filename, "r"); fp = fopen(filename, "r");
if (!fp) { if (!fp) {
fprintf(stderr, "plink: unable to open command " fprintf(stderr, "plink: unable to open command "
"file \"%s\"\n", filename); "file \"%s\"\n", filename);
return 1; return 1;
} }
do { do {
c = fgetc(fp); c = fgetc(fp);
d = c; d = c;
if (c == EOF) if (c == EOF)
d = 0; d = 0;
if (cmdlen >= cmdsize) { if (cmdlen >= cmdsize) {
cmdsize = cmdlen + 512; cmdsize = cmdlen + 512;
command = srealloc(command, cmdsize); command = srealloc(command, cmdsize);
} }
command[cmdlen++] = d; command[cmdlen++] = d;
} while (c != EOF); } while (c != EOF);
cfg.remote_cmd_ptr = command; cfg.remote_cmd_ptr = command;
cfg.nopty = TRUE; /* command => no terminal */ cfg.nopty = TRUE; /* command => no terminal */
} else if (!strcmp(p, "-P") && argc > 1) { } else if (!strcmp(p, "-P") && argc > 1) {
--argc, portnumber = atoi(*++argv); --argc, portnumber = atoi(*++argv);
} }
} else if (*p) { } else if (*p) {
if (!*cfg.host) { if (!*cfg.host) {
char *q = p; char *q = p;
/* /*
* If the hostname starts with "telnet:", set the * If the hostname starts with "telnet:", set the
* protocol to Telnet and process the string as a * protocol to Telnet and process the string as a
* Telnet URL. * Telnet URL.
*/ */
if (!strncmp(q, "telnet:", 7)) { if (!strncmp(q, "telnet:", 7)) {
char c; char c;
q += 7; q += 7;
if (q[0] == '/' && q[1] == '/') if (q[0] == '/' && q[1] == '/')
q += 2; q += 2;
cfg.protocol = PROT_TELNET; cfg.protocol = PROT_TELNET;
p = q; p = q;
while (*p && *p != ':' && *p != '/') p++; while (*p && *p != ':' && *p != '/')
c = *p; p++;
if (*p) c = *p;
*p++ = '\0'; if (*p)
if (c == ':') *p++ = '\0';
cfg.port = atoi(p); if (c == ':')
else cfg.port = atoi(p);
cfg.port = -1; else
strncpy (cfg.host, q, sizeof(cfg.host)-1); cfg.port = -1;
cfg.host[sizeof(cfg.host)-1] = '\0'; strncpy(cfg.host, q, sizeof(cfg.host) - 1);
} else { cfg.host[sizeof(cfg.host) - 1] = '\0';
char *r; } else {
/* char *r;
* Before we process the [user@]host string, we /*
* first check for the presence of a protocol * Before we process the [user@]host string, we
* prefix (a protocol name followed by ","). * first check for the presence of a protocol
*/ * prefix (a protocol name followed by ",").
r = strchr(p, ','); */
if (r) { r = strchr(p, ',');
int i, j; if (r) {
for (i = 0; backends[i].backend != NULL; i++) { int i, j;
j = strlen(backends[i].name); for (i = 0; backends[i].backend != NULL; i++) {
if (j == r-p && j = strlen(backends[i].name);
!memcmp(backends[i].name, p, j)) { if (j == r - p &&
default_protocol = cfg.protocol = backends[i].protocol; !memcmp(backends[i].name, p, j)) {
portnumber = backends[i].backend->default_port; default_protocol = cfg.protocol =
p = r+1; backends[i].protocol;
break; portnumber =
} backends[i].backend->default_port;
} p = r + 1;
} break;
}
}
}
/* /*
* Three cases. Either (a) there's a nonzero * Three cases. Either (a) there's a nonzero
* length string followed by an @, in which * length string followed by an @, in which
* case that's user and the remainder is host. * case that's user and the remainder is host.
* Or (b) there's only one string, not counting * Or (b) there's only one string, not counting
* a potential initial @, and it exists in the * a potential initial @, and it exists in the
* saved-sessions database. Or (c) only one * saved-sessions database. Or (c) only one
* string and it _doesn't_ exist in the * string and it _doesn't_ exist in the
* database. * database.
*/ */
r = strrchr(p, '@'); r = strrchr(p, '@');
if (r == p) p++, r = NULL; /* discount initial @ */ if (r == p)
if (r == NULL) { p++, r = NULL; /* discount initial @ */
/* if (r == NULL) {
* One string. /*
*/ * One string.
Config cfg2; */
do_defaults (p, &cfg2); Config cfg2;
if (cfg2.host[0] == '\0') { do_defaults(p, &cfg2);
/* No settings for this host; use defaults */ if (cfg2.host[0] == '\0') {
strncpy(cfg.host, p, sizeof(cfg.host)-1); /* No settings for this host; use defaults */
cfg.host[sizeof(cfg.host)-1] = '\0'; strncpy(cfg.host, p, sizeof(cfg.host) - 1);
cfg.port = default_port; cfg.host[sizeof(cfg.host) - 1] = '\0';
} else { cfg.port = default_port;
cfg = cfg2; } else {
cfg.remote_cmd_ptr = cfg.remote_cmd; cfg = cfg2;
} cfg.remote_cmd_ptr = cfg.remote_cmd;
} else { }
*r++ = '\0'; } else {
strncpy(cfg.username, p, sizeof(cfg.username)-1); *r++ = '\0';
cfg.username[sizeof(cfg.username)-1] = '\0'; strncpy(cfg.username, p, sizeof(cfg.username) - 1);
strncpy(cfg.host, r, sizeof(cfg.host)-1); cfg.username[sizeof(cfg.username) - 1] = '\0';
cfg.host[sizeof(cfg.host)-1] = '\0'; strncpy(cfg.host, r, sizeof(cfg.host) - 1);
cfg.port = default_port; cfg.host[sizeof(cfg.host) - 1] = '\0';
} cfg.port = default_port;
} }
} else { }
int len = sizeof(cfg.remote_cmd) - 1; } else {
char *cp = cfg.remote_cmd; int len = sizeof(cfg.remote_cmd) - 1;
int len2; char *cp = cfg.remote_cmd;
int len2;
strncpy(cp, p, len); cp[len] = '\0'; strncpy(cp, p, len);
len2 = strlen(cp); len -= len2; cp += len2; cp[len] = '\0';
while (--argc) { len2 = strlen(cp);
if (len > 0) len -= len2;
len--, *cp++ = ' '; cp += len2;
strncpy(cp, *++argv, len); cp[len] = '\0'; while (--argc) {
len2 = strlen(cp); len -= len2; cp += len2; if (len > 0)
} len--, *cp++ = ' ';
cfg.nopty = TRUE; /* command => no terminal */ strncpy(cp, *++argv, len);
break; /* done with cmdline */ cp[len] = '\0';
} len2 = strlen(cp);
len -= len2;
cp += len2;
}
cfg.nopty = TRUE; /* command => no terminal */
break; /* done with cmdline */
}
} }
} }
if (!*cfg.host) { if (!*cfg.host) {
usage(); usage();
} }
if (!*cfg.remote_cmd_ptr) if (!*cfg.remote_cmd_ptr)
flags |= FLAG_INTERACTIVE; flags |= FLAG_INTERACTIVE;
/* /*
* Select protocol. This is farmed out into a table in a * Select protocol. This is farmed out into a table in a
* separate file to enable an ssh-free variant. * separate file to enable an ssh-free variant.
*/ */
{ {
int i; int i;
back = NULL; back = NULL;
for (i = 0; backends[i].backend != NULL; i++) for (i = 0; backends[i].backend != NULL; i++)
if (backends[i].protocol == cfg.protocol) { if (backends[i].protocol == cfg.protocol) {
back = backends[i].backend; back = backends[i].backend;
break; break;
} }
if (back == NULL) { if (back == NULL) {
fprintf(stderr, "Internal fault: Unsupported protocol found\n"); fprintf(stderr,
return 1; "Internal fault: Unsupported protocol found\n");
} return 1;
}
} }
/* /*
* Select port. * Select port.
*/ */
if (portnumber != -1) if (portnumber != -1)
cfg.port = portnumber; cfg.port = portnumber;
/* /*
* Initialise WinSock. * Initialise WinSock.
@ -515,7 +545,7 @@ int main(int argc, char **argv) {
char *error; char *error;
char *realhost; char *realhost;
error = back->init (cfg.host, cfg.port, &realhost); error = back->init(cfg.host, cfg.port, &realhost);
if (error) { if (error) {
fprintf(stderr, "Unable to open connection:\n%s", error); fprintf(stderr, "Unable to open connection:\n%s", error);
return 1; return 1;
@ -540,97 +570,98 @@ int main(int argc, char **argv) {
handles[1] = stdinevent; handles[1] = stdinevent;
sending = FALSE; sending = FALSE;
while (1) { while (1) {
int n; int n;
if (!sending && back->sendok()) { if (!sending && back->sendok()) {
/* /*
* Create a separate thread to read from stdin. This is * Create a separate thread to read from stdin. This is
* a total pain, but I can't find another way to do it: * a total pain, but I can't find another way to do it:
* *
* - an overlapped ReadFile or ReadFileEx just doesn't * - an overlapped ReadFile or ReadFileEx just doesn't
* happen; we get failure from ReadFileEx, and * happen; we get failure from ReadFileEx, and
* ReadFile blocks despite being given an OVERLAPPED * ReadFile blocks despite being given an OVERLAPPED
* structure. Perhaps we can't do overlapped reads * structure. Perhaps we can't do overlapped reads
* on consoles. WHY THE HELL NOT? * on consoles. WHY THE HELL NOT?
* *
* - WaitForMultipleObjects(netevent, console) doesn't * - WaitForMultipleObjects(netevent, console) doesn't
* work, because it signals the console when * work, because it signals the console when
* _anything_ happens, including mouse motions and * _anything_ happens, including mouse motions and
* other things that don't cause data to be readable * other things that don't cause data to be readable
* - so we're back to ReadFile blocking. * - so we're back to ReadFile blocking.
*/ */
idata.event = stdinevent; idata.event = stdinevent;
idata.eventback = CreateEvent(NULL, FALSE, FALSE, NULL); idata.eventback = CreateEvent(NULL, FALSE, FALSE, NULL);
if (!CreateThread(NULL, 0, stdin_read_thread, if (!CreateThread(NULL, 0, stdin_read_thread,
&idata, 0, &threadid)) { &idata, 0, &threadid)) {
fprintf(stderr, "Unable to create second thread\n"); fprintf(stderr, "Unable to create second thread\n");
exit(1); exit(1);
} }
sending = TRUE; sending = TRUE;
} }
n = WaitForMultipleObjects(2, handles, FALSE, INFINITE); n = WaitForMultipleObjects(2, handles, FALSE, INFINITE);
if (n == 0) { if (n == 0) {
WSANETWORKEVENTS things; WSANETWORKEVENTS things;
SOCKET socket; SOCKET socket;
extern SOCKET first_socket(int *), next_socket(int *); extern SOCKET first_socket(int *), next_socket(int *);
extern int select_result(WPARAM, LPARAM); extern int select_result(WPARAM, LPARAM);
int i, socketstate; int i, socketstate;
/* /*
* We must not call select_result() for any socket * We must not call select_result() for any socket
* until we have finished enumerating within the tree. * until we have finished enumerating within the tree.
* This is because select_result() may close the socket * This is because select_result() may close the socket
* and modify the tree. * and modify the tree.
*/ */
/* Count the active sockets. */ /* Count the active sockets. */
i = 0; i = 0;
for (socket = first_socket(&socketstate); socket != INVALID_SOCKET; for (socket = first_socket(&socketstate);
socket = next_socket(&socketstate)) socket != INVALID_SOCKET;
i++; socket = next_socket(&socketstate)) i++;
/* Expand the buffer if necessary. */ /* Expand the buffer if necessary. */
if (i > sksize) { if (i > sksize) {
sksize = i+16; sksize = i + 16;
sklist = srealloc(sklist, sksize * sizeof(*sklist)); sklist = srealloc(sklist, sksize * sizeof(*sklist));
} }
/* Retrieve the sockets into sklist. */ /* Retrieve the sockets into sklist. */
skcount = 0; skcount = 0;
for (socket = first_socket(&socketstate); socket != INVALID_SOCKET; for (socket = first_socket(&socketstate);
socket != INVALID_SOCKET;
socket = next_socket(&socketstate)) { socket = next_socket(&socketstate)) {
sklist[skcount++] = socket; sklist[skcount++] = socket;
} }
/* Now we're done enumerating; go through the list. */ /* Now we're done enumerating; go through the list. */
for (i = 0; i < skcount; i++) { for (i = 0; i < skcount; i++) {
WPARAM wp; WPARAM wp;
socket = sklist[i]; socket = sklist[i];
wp = (WPARAM)socket; wp = (WPARAM) socket;
if (!WSAEnumNetworkEvents(socket, NULL, &things)) { if (!WSAEnumNetworkEvents(socket, NULL, &things)) {
noise_ultralight(socket); noise_ultralight(socket);
noise_ultralight(things.lNetworkEvents); noise_ultralight(things.lNetworkEvents);
if (things.lNetworkEvents & FD_READ) if (things.lNetworkEvents & FD_READ)
connopen &= select_result(wp, (LPARAM)FD_READ); connopen &= select_result(wp, (LPARAM) FD_READ);
if (things.lNetworkEvents & FD_CLOSE) if (things.lNetworkEvents & FD_CLOSE)
connopen &= select_result(wp, (LPARAM)FD_CLOSE); connopen &= select_result(wp, (LPARAM) FD_CLOSE);
if (things.lNetworkEvents & FD_OOB) if (things.lNetworkEvents & FD_OOB)
connopen &= select_result(wp, (LPARAM)FD_OOB); connopen &= select_result(wp, (LPARAM) FD_OOB);
if (things.lNetworkEvents & FD_WRITE) if (things.lNetworkEvents & FD_WRITE)
connopen &= select_result(wp, (LPARAM)FD_WRITE); connopen &= select_result(wp, (LPARAM) FD_WRITE);
} }
} }
} else if (n == 1) { } else if (n == 1) {
noise_ultralight(idata.len); noise_ultralight(idata.len);
if (idata.len > 0) { if (idata.len > 0) {
back->send(idata.buffer, idata.len); back->send(idata.buffer, idata.len);
} else { } else {
back->special(TS_EOF); back->special(TS_EOF);
} }
SetEvent(idata.eventback); SetEvent(idata.eventback);
} }
if (!connopen || back->socket() == NULL) if (!connopen || back->socket() == NULL)
break; /* we closed the connection */ break; /* we closed the connection */
} }
WSACleanup(); WSACleanup();
return 0; return 0;

509
psftp.c
View File

@ -20,15 +20,17 @@
* String handling routines. * String handling routines.
*/ */
char *dupstr(char *s) { char *dupstr(char *s)
{
int len = strlen(s); int len = strlen(s);
char *p = smalloc(len+1); char *p = smalloc(len + 1);
strcpy(p, s); strcpy(p, s);
return p; return p;
} }
/* Allocate the concatenation of N strings. Terminate arg list with NULL. */ /* Allocate the concatenation of N strings. Terminate arg list with NULL. */
char *dupcat(char *s1, ...) { char *dupcat(char *s1, ...)
{
int len; int len;
char *p, *q, *sn; char *p, *q, *sn;
va_list ap; va_list ap;
@ -43,7 +45,7 @@ char *dupcat(char *s1, ...) {
} }
va_end(ap); va_end(ap);
p = smalloc(len+1); p = smalloc(len + 1);
strcpy(p, s1); strcpy(p, s1);
q = p + strlen(p); q = p + strlen(p);
@ -75,14 +77,15 @@ char *pwd, *homedir;
* canonification fails, at least fall back to returning a _valid_ * canonification fails, at least fall back to returning a _valid_
* pathname (though it may be ugly, eg /home/simon/../foobar). * pathname (though it may be ugly, eg /home/simon/../foobar).
*/ */
char *canonify(char *name) { char *canonify(char *name)
{
char *fullname, *canonname; char *fullname, *canonname;
if (name[0] == '/') { if (name[0] == '/') {
fullname = dupstr(name); fullname = dupstr(name);
} else { } else {
char *slash; char *slash;
if (pwd[strlen(pwd)-1] == '/') if (pwd[strlen(pwd) - 1] == '/')
slash = ""; slash = "";
else else
slash = "/"; slash = "/";
@ -95,73 +98,73 @@ char *canonify(char *name) {
sfree(fullname); sfree(fullname);
return canonname; return canonname;
} else { } else {
/* /*
* Attempt number 2. Some FXP_REALPATH implementations * Attempt number 2. Some FXP_REALPATH implementations
* (glibc-based ones, in particular) require the _whole_ * (glibc-based ones, in particular) require the _whole_
* path to point to something that exists, whereas others * path to point to something that exists, whereas others
* (BSD-based) only require all but the last component to * (BSD-based) only require all but the last component to
* exist. So if the first call failed, we should strip off * exist. So if the first call failed, we should strip off
* everything from the last slash onwards and try again, * everything from the last slash onwards and try again,
* then put the final component back on. * then put the final component back on.
* *
* Special cases: * Special cases:
* *
* - if the last component is "/." or "/..", then we don't * - if the last component is "/." or "/..", then we don't
* bother trying this because there's no way it can work. * bother trying this because there's no way it can work.
* *
* - if the thing actually ends with a "/", we remove it * - if the thing actually ends with a "/", we remove it
* before we start. Except if the string is "/" itself * before we start. Except if the string is "/" itself
* (although I can't see why we'd have got here if so, * (although I can't see why we'd have got here if so,
* because surely "/" would have worked the first * because surely "/" would have worked the first
* time?), in which case we don't bother. * time?), in which case we don't bother.
* *
* - if there's no slash in the string at all, give up in * - if there's no slash in the string at all, give up in
* confusion (we expect at least one because of the way * confusion (we expect at least one because of the way
* we constructed the string). * we constructed the string).
*/ */
int i;
char *returnname;
i = strlen(fullname); int i;
if (i > 2 && fullname[i-1] == '/') char *returnname;
fullname[--i] = '\0'; /* strip trailing / unless at pos 0 */
while (i > 0 && fullname[--i] != '/');
/* i = strlen(fullname);
* Give up on special cases. if (i > 2 && fullname[i - 1] == '/')
*/ fullname[--i] = '\0'; /* strip trailing / unless at pos 0 */
if (fullname[i] != '/' || /* no slash at all */ while (i > 0 && fullname[--i] != '/');
!strcmp(fullname+i, "/.") || /* ends in /. */
!strcmp(fullname+i, "/..") || /* ends in /.. */
!strcmp(fullname, "/")) {
return fullname;
}
/* /*
* Now i points at the slash. Deal with the final special * Give up on special cases.
* case i==0 (ie the whole path was "/nonexistentfile"). */
*/ if (fullname[i] != '/' || /* no slash at all */
fullname[i] = '\0'; /* separate the string */ !strcmp(fullname + i, "/.") || /* ends in /. */
if (i == 0) { !strcmp(fullname + i, "/..") || /* ends in /.. */
canonname = fxp_realpath("/"); !strcmp(fullname, "/")) {
} else { return fullname;
canonname = fxp_realpath(fullname); }
}
if (!canonname) /*
return fullname; /* even that failed; give up */ * Now i points at the slash. Deal with the final special
* case i==0 (ie the whole path was "/nonexistentfile").
*/
fullname[i] = '\0'; /* separate the string */
if (i == 0) {
canonname = fxp_realpath("/");
} else {
canonname = fxp_realpath(fullname);
}
/* if (!canonname)
* We have a canonical name for all but the last path return fullname; /* even that failed; give up */
* component. Concatenate the last component and return.
*/ /*
returnname = dupcat(canonname, * We have a canonical name for all but the last path
canonname[strlen(canonname)-1] == '/' ? "" : "/", * component. Concatenate the last component and return.
fullname+i+1, NULL); */
sfree(fullname); returnname = dupcat(canonname,
sfree(canonname); canonname[strlen(canonname) - 1] ==
return returnname; '/' ? "" : "/", fullname + i + 1, NULL);
sfree(fullname);
sfree(canonname);
return returnname;
} }
} }
@ -171,19 +174,22 @@ char *canonify(char *name) {
struct sftp_command { struct sftp_command {
char **words; char **words;
int nwords, wordssize; int nwords, wordssize;
int (*obey)(struct sftp_command *);/* returns <0 to quit */ int (*obey) (struct sftp_command *); /* returns <0 to quit */
}; };
int sftp_cmd_null(struct sftp_command *cmd) { int sftp_cmd_null(struct sftp_command *cmd)
{
return 0; return 0;
} }
int sftp_cmd_unknown(struct sftp_command *cmd) { int sftp_cmd_unknown(struct sftp_command *cmd)
{
printf("psftp: unknown command \"%s\"\n", cmd->words[0]); printf("psftp: unknown command \"%s\"\n", cmd->words[0]);
return 0; return 0;
} }
int sftp_cmd_quit(struct sftp_command *cmd) { int sftp_cmd_quit(struct sftp_command *cmd)
{
return -1; return -1;
} }
@ -191,12 +197,14 @@ int sftp_cmd_quit(struct sftp_command *cmd) {
* List a directory. If no arguments are given, list pwd; otherwise * List a directory. If no arguments are given, list pwd; otherwise
* list the directory given in words[1]. * list the directory given in words[1].
*/ */
static int sftp_ls_compare(const void *av, const void *bv) { static int sftp_ls_compare(const void *av, const void *bv)
const struct fxp_name *a = (const struct fxp_name *)av; {
const struct fxp_name *b = (const struct fxp_name *)bv; const struct fxp_name *a = (const struct fxp_name *) av;
const struct fxp_name *b = (const struct fxp_name *) bv;
return strcmp(a->filename, b->filename); return strcmp(a->filename, b->filename);
} }
int sftp_cmd_ls(struct sftp_command *cmd) { int sftp_cmd_ls(struct sftp_command *cmd)
{
struct fxp_handle *dirh; struct fxp_handle *dirh;
struct fxp_names *names; struct fxp_names *names;
struct fxp_name *ournames; struct fxp_name *ournames;
@ -240,7 +248,8 @@ int sftp_cmd_ls(struct sftp_command *cmd) {
if (nnames + names->nnames >= namesize) { if (nnames + names->nnames >= namesize) {
namesize += names->nnames + 128; namesize += names->nnames + 128;
ournames = srealloc(ournames, namesize * sizeof(*ournames)); ournames =
srealloc(ournames, namesize * sizeof(*ournames));
} }
for (i = 0; i < names->nnames; i++) for (i = 0; i < names->nnames; i++)
@ -273,7 +282,8 @@ int sftp_cmd_ls(struct sftp_command *cmd) {
* Change directories. We do this by canonifying the new name, then * Change directories. We do this by canonifying the new name, then
* trying to OPENDIR it. Only if that succeeds do we set the new pwd. * trying to OPENDIR it. Only if that succeeds do we set the new pwd.
*/ */
int sftp_cmd_cd(struct sftp_command *cmd) { int sftp_cmd_cd(struct sftp_command *cmd)
{
struct fxp_handle *dirh; struct fxp_handle *dirh;
char *dir; char *dir;
@ -306,7 +316,8 @@ int sftp_cmd_cd(struct sftp_command *cmd) {
/* /*
* Get a file and save it at the local end. * Get a file and save it at the local end.
*/ */
int sftp_cmd_get(struct sftp_command *cmd) { int sftp_cmd_get(struct sftp_command *cmd)
{
struct fxp_handle *fh; struct fxp_handle *fh;
char *fname, *outfname; char *fname, *outfname;
uint64 offset; uint64 offset;
@ -333,14 +344,14 @@ int sftp_cmd_get(struct sftp_command *cmd) {
fp = fopen(outfname, "wb"); fp = fopen(outfname, "wb");
if (!fp) { if (!fp) {
printf("local: unable to open %s\n", outfname); printf("local: unable to open %s\n", outfname);
fxp_close(fh); fxp_close(fh);
sfree(fname); sfree(fname);
return 0; return 0;
} }
printf("remote:%s => local:%s\n", fname, outfname); printf("remote:%s => local:%s\n", fname, outfname);
offset = uint64_make(0,0); offset = uint64_make(0, 0);
/* /*
* FIXME: we can use FXP_FSTAT here to get the file size, and * FIXME: we can use FXP_FSTAT here to get the file size, and
@ -352,17 +363,16 @@ int sftp_cmd_get(struct sftp_command *cmd) {
int wpos, wlen; int wpos, wlen;
len = fxp_read(fh, buffer, offset, sizeof(buffer)); len = fxp_read(fh, buffer, offset, sizeof(buffer));
if ((len == -1 && fxp_error_type() == SSH_FX_EOF) || if ((len == -1 && fxp_error_type() == SSH_FX_EOF) || len == 0)
len == 0)
break; break;
if (len == -1) { if (len == -1) {
printf("error while reading: %s\n", fxp_error()); printf("error while reading: %s\n", fxp_error());
break; break;
} }
wpos = 0; wpos = 0;
while (wpos < len) { while (wpos < len) {
wlen = fwrite(buffer, 1, len-wpos, fp); wlen = fwrite(buffer, 1, len - wpos, fp);
if (wlen <= 0) { if (wlen <= 0) {
printf("error while writing local file\n"); printf("error while writing local file\n");
break; break;
@ -384,7 +394,8 @@ int sftp_cmd_get(struct sftp_command *cmd) {
/* /*
* Send a file and store it at the remote end. * Send a file and store it at the remote end.
*/ */
int sftp_cmd_put(struct sftp_command *cmd) { int sftp_cmd_put(struct sftp_command *cmd)
{
struct fxp_handle *fh; struct fxp_handle *fh;
char *fname, *origoutfname, *outfname; char *fname, *origoutfname, *outfname;
uint64 offset; uint64 offset;
@ -418,7 +429,7 @@ int sftp_cmd_put(struct sftp_command *cmd) {
printf("local:%s => remote:%s\n", fname, outfname); printf("local:%s => remote:%s\n", fname, outfname);
offset = uint64_make(0,0); offset = uint64_make(0, 0);
/* /*
* FIXME: we can use FXP_FSTAT here to get the file size, and * FIXME: we can use FXP_FSTAT here to get the file size, and
@ -451,26 +462,27 @@ int sftp_cmd_put(struct sftp_command *cmd) {
static struct sftp_cmd_lookup { static struct sftp_cmd_lookup {
char *name; char *name;
int (*obey)(struct sftp_command *); int (*obey) (struct sftp_command *);
} sftp_lookup[] = { } sftp_lookup[] = {
/* /*
* List of sftp commands. This is binary-searched so it MUST be * List of sftp commands. This is binary-searched so it MUST be
* in ASCII order. * in ASCII order.
*/ */
{"bye", sftp_cmd_quit}, {
{"cd", sftp_cmd_cd}, "bye", sftp_cmd_quit}, {
{"dir", sftp_cmd_ls}, "cd", sftp_cmd_cd}, {
{"exit", sftp_cmd_quit}, "dir", sftp_cmd_ls}, {
{"get", sftp_cmd_get}, "exit", sftp_cmd_quit}, {
{"ls", sftp_cmd_ls}, "get", sftp_cmd_get}, {
{"put", sftp_cmd_put}, "ls", sftp_cmd_ls}, {
{"quit", sftp_cmd_quit}, "put", sftp_cmd_put}, {
}; "quit", sftp_cmd_quit},};
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
* Command line reading and parsing. * Command line reading and parsing.
*/ */
struct sftp_command *sftp_getcmd(void) { struct sftp_command *sftp_getcmd(void)
{
char *line; char *line;
int linelen, linesize; int linelen, linesize;
struct sftp_command *cmd; struct sftp_command *cmd;
@ -493,16 +505,16 @@ struct sftp_command *sftp_getcmd(void) {
linesize += 512; linesize += 512;
line = srealloc(line, linesize); line = srealloc(line, linesize);
ret = fgets(line+linelen, linesize-linelen, stdin); ret = fgets(line + linelen, linesize - linelen, stdin);
if (!ret || (linelen == 0 && line[0] == '\0')) { if (!ret || (linelen == 0 && line[0] == '\0')) {
cmd->obey = sftp_cmd_quit; cmd->obey = sftp_cmd_quit;
printf("quit\n"); printf("quit\n");
return cmd; /* eof */ return cmd; /* eof */
} }
len = linelen + strlen(line+linelen); len = linelen + strlen(line + linelen);
linelen += len; linelen += len;
if (line[linelen-1] == '\n') { if (line[linelen - 1] == '\n') {
linelen--; linelen--;
line[linelen] = '\0'; line[linelen] = '\0';
break; break;
@ -528,7 +540,8 @@ struct sftp_command *sftp_getcmd(void) {
p = line; p = line;
while (*p) { while (*p) {
/* skip whitespace */ /* skip whitespace */
while (*p && (*p == ' ' || *p == '\t')) p++; while (*p && (*p == ' ' || *p == '\t'))
p++;
/* mark start of word */ /* mark start of word */
q = r = p; /* q sits at start, r writes word */ q = r = p; /* q sits at start, r writes word */
quoting = 0; quoting = 0;
@ -536,17 +549,19 @@ struct sftp_command *sftp_getcmd(void) {
if (!quoting && (*p == ' ' || *p == '\t')) if (!quoting && (*p == ' ' || *p == '\t'))
break; /* reached end of word */ break; /* reached end of word */
else if (*p == '"' && p[1] == '"') else if (*p == '"' && p[1] == '"')
p+=2, *r++ = '"'; /* a literal quote */ p += 2, *r++ = '"'; /* a literal quote */
else if (*p == '"') else if (*p == '"')
p++, quoting = !quoting; p++, quoting = !quoting;
else else
*r++ = *p++; *r++ = *p++;
} }
if (*p) p++; /* skip over the whitespace */ if (*p)
p++; /* skip over the whitespace */
*r = '\0'; *r = '\0';
if (cmd->nwords >= cmd->wordssize) { if (cmd->nwords >= cmd->wordssize) {
cmd->wordssize = cmd->nwords + 16; cmd->wordssize = cmd->nwords + 16;
cmd->words = srealloc(cmd->words, cmd->wordssize*sizeof(char *)); cmd->words =
srealloc(cmd->words, cmd->wordssize * sizeof(char *));
} }
cmd->words[cmd->nwords++] = q; cmd->words[cmd->nwords++] = q;
} }
@ -581,14 +596,14 @@ struct sftp_command *sftp_getcmd(void) {
return cmd; return cmd;
} }
void do_sftp(void) { void do_sftp(void)
{
/* /*
* Do protocol initialisation. * Do protocol initialisation.
*/ */
if (!fxp_init()) { if (!fxp_init()) {
fprintf(stderr, fprintf(stderr,
"Fatal: unable to initialise SFTP: %s\n", "Fatal: unable to initialise SFTP: %s\n", fxp_error());
fxp_error());
return; return;
} }
@ -626,38 +641,38 @@ void do_sftp(void) {
static int verbose = 0; static int verbose = 0;
void verify_ssh_host_key(char *host, int port, char *keytype, void verify_ssh_host_key(char *host, int port, char *keytype,
char *keystr, char *fingerprint) { char *keystr, char *fingerprint)
{
int ret; int ret;
static const char absentmsg[] = static const char absentmsg[] =
"The server's host key is not cached in the registry. You\n" "The server's host key is not cached in the registry. You\n"
"have no guarantee that the server is the computer you\n" "have no guarantee that the server is the computer you\n"
"think it is.\n" "think it is.\n"
"The server's key fingerprint is:\n" "The server's key fingerprint is:\n"
"%s\n" "%s\n"
"If you trust this host, enter \"y\" to add the key to\n" "If you trust this host, enter \"y\" to add the key to\n"
"PuTTY's cache and carry on connecting.\n" "PuTTY's cache and carry on connecting.\n"
"If you do not trust this host, enter \"n\" to abandon the\n" "If you do not trust this host, enter \"n\" to abandon the\n"
"connection.\n" "connection.\n" "Continue connecting? (y/n) ";
"Continue connecting? (y/n) ";
static const char wrongmsg[] = static const char wrongmsg[] =
"WARNING - POTENTIAL SECURITY BREACH!\n" "WARNING - POTENTIAL SECURITY BREACH!\n"
"The server's host key does not match the one PuTTY has\n" "The server's host key does not match the one PuTTY has\n"
"cached in the registry. This means that either the\n" "cached in the registry. This means that either the\n"
"server administrator has changed the host key, or you\n" "server administrator has changed the host key, or you\n"
"have actually connected to another computer pretending\n" "have actually connected to another computer pretending\n"
"to be the server.\n" "to be the server.\n"
"The new key fingerprint is:\n" "The new key fingerprint is:\n"
"%s\n" "%s\n"
"If you were expecting this change and trust the new key,\n" "If you were expecting this change and trust the new key,\n"
"enter Yes to update PuTTY's cache and continue connecting.\n" "enter Yes to update PuTTY's cache and continue connecting.\n"
"If you want to carry on connecting but without updating\n" "If you want to carry on connecting but without updating\n"
"the cache, enter No.\n" "the cache, enter No.\n"
"If you want to abandon the connection completely, press\n" "If you want to abandon the connection completely, press\n"
"Return to cancel. Pressing Return is the ONLY guaranteed\n" "Return to cancel. Pressing Return is the ONLY guaranteed\n"
"safe choice.\n" "safe choice.\n"
"Update cached key? (y/n, Return cancels connection) "; "Update cached key? (y/n, Return cancels connection) ";
static const char abandoned[] = "Connection abandoned.\n"; static const char abandoned[] = "Connection abandoned.\n";
@ -668,28 +683,28 @@ void verify_ssh_host_key(char *host, int port, char *keytype,
*/ */
ret = verify_host_key(host, port, keytype, keystr); ret = verify_host_key(host, port, keytype, keystr);
if (ret == 0) /* success - key matched OK */ if (ret == 0) /* success - key matched OK */
return; return;
if (ret == 2) { /* key was different */ if (ret == 2) { /* key was different */
fprintf(stderr, wrongmsg, fingerprint); fprintf(stderr, wrongmsg, fingerprint);
if (fgets(line, sizeof(line), stdin) && if (fgets(line, sizeof(line), stdin) &&
line[0] != '\0' && line[0] != '\n') { line[0] != '\0' && line[0] != '\n') {
if (line[0] == 'y' || line[0] == 'Y') if (line[0] == 'y' || line[0] == 'Y')
store_host_key(host, port, keytype, keystr); store_host_key(host, port, keytype, keystr);
} else { } else {
fprintf(stderr, abandoned); fprintf(stderr, abandoned);
exit(0); exit(0);
} }
} }
if (ret == 1) { /* key was absent */ if (ret == 1) { /* key was absent */
fprintf(stderr, absentmsg, fingerprint); fprintf(stderr, absentmsg, fingerprint);
if (fgets(line, sizeof(line), stdin) && if (fgets(line, sizeof(line), stdin) &&
(line[0] == 'y' || line[0] == 'Y')) (line[0] == 'y' || line[0] == 'Y'))
store_host_key(host, port, keytype, keystr); store_host_key(host, port, keytype, keystr);
else { else {
fprintf(stderr, abandoned); fprintf(stderr, abandoned);
exit(0); exit(0);
} }
} }
} }
@ -698,11 +713,11 @@ void verify_ssh_host_key(char *host, int port, char *keytype,
*/ */
void fatalbox(char *fmt, ...) void fatalbox(char *fmt, ...)
{ {
char str[0x100]; /* Make the size big enough */ char str[0x100]; /* Make the size big enough */
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
strcpy(str, "Fatal:"); strcpy(str, "Fatal:");
vsprintf(str+strlen(str), fmt, ap); vsprintf(str + strlen(str), fmt, ap);
va_end(ap); va_end(ap);
strcat(str, "\n"); strcat(str, "\n");
fprintf(stderr, str); fprintf(stderr, str);
@ -711,11 +726,11 @@ void fatalbox(char *fmt, ...)
} }
void connection_fatal(char *fmt, ...) void connection_fatal(char *fmt, ...)
{ {
char str[0x100]; /* Make the size big enough */ char str[0x100]; /* Make the size big enough */
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
strcpy(str, "Fatal:"); strcpy(str, "Fatal:");
vsprintf(str+strlen(str), fmt, ap); vsprintf(str + strlen(str), fmt, ap);
va_end(ap); va_end(ap);
strcat(str, "\n"); strcat(str, "\n");
fprintf(stderr, str); fprintf(stderr, str);
@ -723,9 +738,12 @@ void connection_fatal(char *fmt, ...)
exit(1); exit(1);
} }
void logevent(char *string) { } void logevent(char *string)
{
}
void ldisc_send(char *buf, int len) { void ldisc_send(char *buf, int len)
{
/* /*
* This is only here because of the calls to ldisc_send(NULL, * This is only here because of the calls to ldisc_send(NULL,
* 0) in ssh.c. Nothing in PSFTP actually needs to use the * 0) in ssh.c. Nothing in PSFTP actually needs to use the
@ -739,7 +757,8 @@ void ldisc_send(char *buf, int len) {
* Be told what socket we're supposed to be using. * Be told what socket we're supposed to be using.
*/ */
static SOCKET sftp_ssh_socket; static SOCKET sftp_ssh_socket;
char *do_select(SOCKET skt, int startup) { char *do_select(SOCKET skt, int startup)
{
if (startup) if (startup)
sftp_ssh_socket = skt; sftp_ssh_socket = skt;
else else
@ -757,13 +776,14 @@ extern int select_result(WPARAM, LPARAM);
* do this until we have enough data. * do this until we have enough data.
*/ */
static unsigned char *outptr; /* where to put the data */ static unsigned char *outptr; /* where to put the data */
static unsigned outlen; /* how much data required */ static unsigned outlen; /* how much data required */
static unsigned char *pending = NULL; /* any spare data */ static unsigned char *pending = NULL; /* any spare data */
static unsigned pendlen=0, pendsize=0; /* length and phys. size of buffer */ static unsigned pendlen = 0, pendsize = 0; /* length and phys. size of buffer */
void from_backend(int is_stderr, char *data, int datalen) { void from_backend(int is_stderr, char *data, int datalen)
unsigned char *p = (unsigned char *)data; {
unsigned len = (unsigned)datalen; unsigned char *p = (unsigned char *) data;
unsigned len = (unsigned) datalen;
/* /*
* stderr data is just spouted to local stderr and otherwise * stderr data is just spouted to local stderr and otherwise
@ -778,30 +798,34 @@ void from_backend(int is_stderr, char *data, int datalen) {
* If this is before the real session begins, just return. * If this is before the real session begins, just return.
*/ */
if (!outptr) if (!outptr)
return; return;
if (outlen > 0) { if (outlen > 0) {
unsigned used = outlen; unsigned used = outlen;
if (used > len) used = len; if (used > len)
memcpy(outptr, p, used); used = len;
outptr += used; outlen -= used; memcpy(outptr, p, used);
p += used; len -= used; outptr += used;
outlen -= used;
p += used;
len -= used;
} }
if (len > 0) { if (len > 0) {
if (pendsize < pendlen + len) { if (pendsize < pendlen + len) {
pendsize = pendlen + len + 4096; pendsize = pendlen + len + 4096;
pending = (pending ? srealloc(pending, pendsize) : pending = (pending ? srealloc(pending, pendsize) :
smalloc(pendsize)); smalloc(pendsize));
if (!pending) if (!pending)
fatalbox("Out of memory"); fatalbox("Out of memory");
} }
memcpy(pending+pendlen, p, len); memcpy(pending + pendlen, p, len);
pendlen += len; pendlen += len;
} }
} }
int sftp_recvdata(char *buf, int len) { int sftp_recvdata(char *buf, int len)
outptr = (unsigned char *)buf; {
outptr = (unsigned char *) buf;
outlen = len; outlen = len;
/* /*
@ -809,53 +833,55 @@ int sftp_recvdata(char *buf, int len) {
* need. * need.
*/ */
if (pendlen > 0) { if (pendlen > 0) {
unsigned pendused = pendlen; unsigned pendused = pendlen;
if (pendused > outlen) if (pendused > outlen)
pendused = outlen; pendused = outlen;
memcpy(outptr, pending, pendused); memcpy(outptr, pending, pendused);
memmove(pending, pending+pendused, pendlen-pendused); memmove(pending, pending + pendused, pendlen - pendused);
outptr += pendused; outptr += pendused;
outlen -= pendused; outlen -= pendused;
pendlen -= pendused; pendlen -= pendused;
if (pendlen == 0) { if (pendlen == 0) {
pendsize = 0; pendsize = 0;
sfree(pending); sfree(pending);
pending = NULL; pending = NULL;
} }
if (outlen == 0) if (outlen == 0)
return 1; return 1;
} }
while (outlen > 0) { while (outlen > 0) {
fd_set readfds; fd_set readfds;
FD_ZERO(&readfds); FD_ZERO(&readfds);
FD_SET(sftp_ssh_socket, &readfds); FD_SET(sftp_ssh_socket, &readfds);
if (select(1, &readfds, NULL, NULL, NULL) < 0) if (select(1, &readfds, NULL, NULL, NULL) < 0)
return 0; /* doom */ return 0; /* doom */
select_result((WPARAM)sftp_ssh_socket, (LPARAM)FD_READ); select_result((WPARAM) sftp_ssh_socket, (LPARAM) FD_READ);
} }
return 1; return 1;
} }
int sftp_senddata(char *buf, int len) { int sftp_senddata(char *buf, int len)
back->send((unsigned char *)buf, len); {
back->send((unsigned char *) buf, len);
return 1; return 1;
} }
/* /*
* Loop through the ssh connection and authentication process. * Loop through the ssh connection and authentication process.
*/ */
static void ssh_sftp_init(void) { static void ssh_sftp_init(void)
{
if (sftp_ssh_socket == INVALID_SOCKET) if (sftp_ssh_socket == INVALID_SOCKET)
return; return;
while (!back->sendok()) { while (!back->sendok()) {
fd_set readfds; fd_set readfds;
FD_ZERO(&readfds); FD_ZERO(&readfds);
FD_SET(sftp_ssh_socket, &readfds); FD_SET(sftp_ssh_socket, &readfds);
if (select(1, &readfds, NULL, NULL, NULL) < 0) if (select(1, &readfds, NULL, NULL, NULL) < 0)
return; /* doom */ return; /* doom */
select_result((WPARAM)sftp_ssh_socket, (LPARAM)FD_READ); select_result((WPARAM) sftp_ssh_socket, (LPARAM) FD_READ);
} }
} }
@ -866,16 +892,16 @@ static int get_line(const char *prompt, char *str, int maxlen, int is_pw)
DWORD savemode, newmode, i; DWORD savemode, newmode, i;
if (password) { if (password) {
static int tried_once = 0; static int tried_once = 0;
if (tried_once) { if (tried_once) {
return 0; return 0;
} else { } else {
strncpy(str, password, maxlen); strncpy(str, password, maxlen);
str[maxlen-1] = '\0'; str[maxlen - 1] = '\0';
tried_once = 1; tried_once = 1;
return 1; return 1;
} }
} }
hin = GetStdHandle(STD_INPUT_HANDLE); hin = GetStdHandle(STD_INPUT_HANDLE);
@ -888,21 +914,24 @@ static int get_line(const char *prompt, char *str, int maxlen, int is_pw)
GetConsoleMode(hin, &savemode); GetConsoleMode(hin, &savemode);
newmode = savemode | ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT; newmode = savemode | ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT;
if (is_pw) if (is_pw)
newmode &= ~ENABLE_ECHO_INPUT; newmode &= ~ENABLE_ECHO_INPUT;
else else
newmode |= ENABLE_ECHO_INPUT; newmode |= ENABLE_ECHO_INPUT;
SetConsoleMode(hin, newmode); SetConsoleMode(hin, newmode);
WriteFile(hout, prompt, strlen(prompt), &i, NULL); WriteFile(hout, prompt, strlen(prompt), &i, NULL);
ReadFile(hin, str, maxlen-1, &i, NULL); ReadFile(hin, str, maxlen - 1, &i, NULL);
SetConsoleMode(hin, savemode); SetConsoleMode(hin, savemode);
if ((int)i > maxlen) i = maxlen-1; else i = i - 2; if ((int) i > maxlen)
i = maxlen - 1;
else
i = i - 2;
str[i] = '\0'; str[i] = '\0';
if (is_pw) if (is_pw)
WriteFile(hout, "\r\n", 2, &i, NULL); WriteFile(hout, "\r\n", 2, &i, NULL);
return 1; return 1;
} }
@ -920,8 +949,7 @@ static void init_winsock(void)
fprintf(stderr, "Unable to initialise WinSock"); fprintf(stderr, "Unable to initialise WinSock");
exit(1); exit(1);
} }
if (LOBYTE(wsadata.wVersion) != 1 || if (LOBYTE(wsadata.wVersion) != 1 || HIBYTE(wsadata.wVersion) != 1) {
HIBYTE(wsadata.wVersion) != 1) {
fprintf(stderr, "WinSock version is incompatible with 1.1"); fprintf(stderr, "WinSock version is incompatible with 1.1");
exit(1); exit(1);
} }
@ -970,11 +998,11 @@ int main(int argc, char *argv[])
} else if (strcmp(argv[i], "-h") == 0 || } else if (strcmp(argv[i], "-h") == 0 ||
strcmp(argv[i], "-?") == 0) { strcmp(argv[i], "-?") == 0) {
usage(); usage();
} else if (strcmp(argv[i], "-l") == 0 && i+1 < argc) { } else if (strcmp(argv[i], "-l") == 0 && i + 1 < argc) {
user = argv[++i]; user = argv[++i];
} else if (strcmp(argv[i], "-P") == 0 && i+1 < argc) { } else if (strcmp(argv[i], "-P") == 0 && i + 1 < argc) {
portnumber = atoi(argv[++i]); portnumber = atoi(argv[++i]);
} else if (strcmp(argv[i], "-pw") == 0 && i+1 < argc) { } else if (strcmp(argv[i], "-pw") == 0 && i + 1 < argc) {
password = argv[++i]; password = argv[++i];
} else if (strcmp(argv[i], "--") == 0) { } else if (strcmp(argv[i], "--") == 0) {
i++; i++;
@ -998,7 +1026,8 @@ int main(int argc, char *argv[])
} else { } else {
*host++ = '\0'; *host++ = '\0';
if (user) { if (user) {
printf("psftp: multiple usernames specified; using \"%s\"\n", user); printf("psftp: multiple usernames specified; using \"%s\"\n",
user);
} else } else
user = userhost; user = userhost;
} }
@ -1007,16 +1036,16 @@ int main(int argc, char *argv[])
do_defaults(host, &cfg); do_defaults(host, &cfg);
if (cfg.host[0] == '\0') { if (cfg.host[0] == '\0') {
/* No settings for this host; use defaults */ /* No settings for this host; use defaults */
do_defaults(NULL, &cfg); do_defaults(NULL, &cfg);
strncpy(cfg.host, host, sizeof(cfg.host)-1); strncpy(cfg.host, host, sizeof(cfg.host) - 1);
cfg.host[sizeof(cfg.host)-1] = '\0'; cfg.host[sizeof(cfg.host) - 1] = '\0';
cfg.port = 22; cfg.port = 22;
} }
/* Set username */ /* Set username */
if (user != NULL && user[0] != '\0') { if (user != NULL && user[0] != '\0') {
strncpy(cfg.username, user, sizeof(cfg.username)-1); strncpy(cfg.username, user, sizeof(cfg.username) - 1);
cfg.username[sizeof(cfg.username)-1] = '\0'; cfg.username[sizeof(cfg.username) - 1] = '\0';
} }
if (!cfg.username[0]) { if (!cfg.username[0]) {
printf("login as: "); printf("login as: ");
@ -1025,8 +1054,8 @@ int main(int argc, char *argv[])
exit(1); exit(1);
} else { } else {
int len = strlen(cfg.username); int len = strlen(cfg.username);
if (cfg.username[len-1] == '\n') if (cfg.username[len - 1] == '\n')
cfg.username[len-1] = '\0'; cfg.username[len - 1] = '\0';
} }
} }

118
putty.h
View File

@ -83,12 +83,12 @@ GLOBAL int seen_disp_event;
GLOBAL int session_closed; GLOBAL int session_closed;
#define LGXF_OVR 1 /* existing logfile overwrite */ #define LGXF_OVR 1 /* existing logfile overwrite */
#define LGXF_APN 0 /* existing logfile append */ #define LGXF_APN 0 /* existing logfile append */
#define LGXF_ASK -1 /* existing logfile ask */ #define LGXF_ASK -1 /* existing logfile ask */
#define LGTYP_NONE 0 /* logmode: no logging */ #define LGTYP_NONE 0 /* logmode: no logging */
#define LGTYP_ASCII 1 /* logmode: pure ascii */ #define LGTYP_ASCII 1 /* logmode: pure ascii */
#define LGTYP_DEBUG 2 /* logmode: all chars of taffic */ #define LGTYP_DEBUG 2 /* logmode: all chars of taffic */
GLOBAL char *logfile; GLOBAL char *logfile;
/* /*
@ -136,17 +136,17 @@ enum {
/* /*
* Line discipline options which the backend might try to control. * Line discipline options which the backend might try to control.
*/ */
LD_EDIT, /* local line editing */ LD_EDIT, /* local line editing */
LD_ECHO /* local echo */ LD_ECHO /* local echo */
}; };
enum { enum {
/* /*
* Close On Exit behaviours. (cfg.close_on_exit) * Close On Exit behaviours. (cfg.close_on_exit)
*/ */
COE_NEVER, /* Never close the window */ COE_NEVER, /* Never close the window */
COE_NORMAL, /* Close window on "normal" (non-error) exits only */ COE_NORMAL, /* Close window on "normal" (non-error) exits only */
COE_ALWAYS /* Always close the window */ COE_ALWAYS /* Always close the window */
}; };
typedef struct { typedef struct {
@ -154,7 +154,7 @@ typedef struct {
void (*send) (char *buf, int len); void (*send) (char *buf, int len);
void (*size) (void); void (*size) (void);
void (*special) (Telnet_Special code); void (*special) (Telnet_Special code);
Socket (*socket) (void); Socket(*socket) (void);
int (*sendok) (void); int (*sendok) (void);
int (*ldisc) (int); int (*ldisc) (int);
int default_port; int default_port;
@ -175,24 +175,24 @@ typedef struct {
enum { PROT_RAW, PROT_TELNET, PROT_RLOGIN, PROT_SSH } protocol; enum { PROT_RAW, PROT_TELNET, PROT_RLOGIN, PROT_SSH } protocol;
int close_on_exit; int close_on_exit;
int warn_on_close; int warn_on_close;
int ping_interval; /* in seconds */ int ping_interval; /* in seconds */
/* SSH options */ /* SSH options */
char remote_cmd[512]; char remote_cmd[512];
char *remote_cmd_ptr; /* might point to a larger command char *remote_cmd_ptr; /* might point to a larger command
* but never for loading/saving */ * but never for loading/saving */
int nopty; int nopty;
int compression; int compression;
int agentfwd; int agentfwd;
enum { CIPHER_3DES, CIPHER_BLOWFISH, CIPHER_DES, CIPHER_AES } cipher; enum { CIPHER_3DES, CIPHER_BLOWFISH, CIPHER_DES, CIPHER_AES } cipher;
char keyfile[FILENAME_MAX]; char keyfile[FILENAME_MAX];
int sshprot; /* use v1 or v2 when both available */ int sshprot; /* use v1 or v2 when both available */
int buggymac; /* MAC bug commmercial <=v2.3.x SSH2 */ int buggymac; /* MAC bug commmercial <=v2.3.x SSH2 */
int try_tis_auth; int try_tis_auth;
int ssh_subsys; /* run a subsystem rather than a command */ int ssh_subsys; /* run a subsystem rather than a command */
/* Telnet options */ /* Telnet options */
char termtype[32]; char termtype[32];
char termspeed[32]; char termspeed[32];
char environmt[1024]; /* VAR\tvalue\0VAR\tvalue\0\0 */ char environmt[1024]; /* VAR\tvalue\0VAR\tvalue\0\0 */
char username[32]; char username[32];
char localusername[32]; char localusername[32];
int rfc_environ; int rfc_environ;
@ -200,8 +200,8 @@ typedef struct {
int bksp_is_delete; int bksp_is_delete;
int rxvt_homeend; int rxvt_homeend;
int funky_type; int funky_type;
int no_applic_c; /* totally disable app cursor keys */ int no_applic_c; /* totally disable app cursor keys */
int no_applic_k; /* totally disable app keypad */ int no_applic_k; /* totally disable app keypad */
int app_cursor; int app_cursor;
int app_keypad; int app_keypad;
int nethack_keypad; int nethack_keypad;
@ -215,7 +215,7 @@ typedef struct {
int scroll_on_disp; int scroll_on_disp;
int compose_key; int compose_key;
int ctrlaltkeys; int ctrlaltkeys;
char wintitle[256]; /* initial window title */ char wintitle[256]; /* initial window title */
/* Terminal options */ /* Terminal options */
int savelines; int savelines;
int dec_om; int dec_om;
@ -305,23 +305,23 @@ struct RSAKey; /* be a little careful of scope */
/* /*
* Exports from window.c. * Exports from window.c.
*/ */
void request_resize (int, int, int); void request_resize(int, int, int);
void do_text (Context, int, int, char *, int, unsigned long, int); void do_text(Context, int, int, char *, int, unsigned long, int);
void set_title (char *); void set_title(char *);
void set_icon (char *); void set_icon(char *);
void set_sbar (int, int, int); void set_sbar(int, int, int);
Context get_ctx(void); Context get_ctx(void);
void free_ctx (Context); void free_ctx(Context);
void palette_set (int, int, int, int); void palette_set(int, int, int, int);
void palette_reset (void); void palette_reset(void);
void write_clip (void *, int, int); void write_clip(void *, int, int);
void get_clip (void **, int *); void get_clip(void **, int *);
void optimised_move (int, int, int); void optimised_move(int, int, int);
void set_raw_mouse_mode(int); void set_raw_mouse_mode(int);
Mouse_Button translate_button(Mouse_Button b); Mouse_Button translate_button(Mouse_Button b);
void connection_fatal(char *, ...); void connection_fatal(char *, ...);
void fatalbox (char *, ...); void fatalbox(char *, ...);
void beep (int); void beep(int);
void begin_session(void); void begin_session(void);
void sys_cursor(int x, int y); void sys_cursor(int x, int y);
#define OPTIMISE_IS_SCROLL 1 #define OPTIMISE_IS_SCROLL 1
@ -329,8 +329,8 @@ void sys_cursor(int x, int y);
/* /*
* Exports from noise.c. * Exports from noise.c.
*/ */
void noise_get_heavy(void (*func)(void *, int)); void noise_get_heavy(void (*func) (void *, int));
void noise_get_light(void (*func)(void *, int)); void noise_get_light(void (*func) (void *, int));
void noise_regular(void); void noise_regular(void);
void noise_ultralight(DWORD data); void noise_ultralight(DWORD data);
void random_save_seed(void); void random_save_seed(void);
@ -340,14 +340,14 @@ void random_destroy_seed(void);
* Exports from windlg.c. * Exports from windlg.c.
*/ */
void defuse_showwindow(void); void defuse_showwindow(void);
int do_config (void); int do_config(void);
int do_reconfig (HWND); int do_reconfig(HWND);
void do_defaults (char *, Config *); void do_defaults(char *, Config *);
void logevent (char *); void logevent(char *);
void showeventlog (HWND); void showeventlog(HWND);
void showabout (HWND); void showabout(HWND);
void verify_ssh_host_key(char *host, int port, char *keytype, void verify_ssh_host_key(char *host, int port, char *keytype,
char *keystr, char *fingerprint); char *keystr, char *fingerprint);
int askappend(char *filename); int askappend(char *filename);
void registry_cleanup(void); void registry_cleanup(void);
void force_normal(HWND hwnd); void force_normal(HWND hwnd);
@ -358,32 +358,32 @@ GLOBAL char **sessions;
/* /*
* Exports from settings.c. * Exports from settings.c.
*/ */
void save_settings (char *section, int do_host, Config *cfg); void save_settings(char *section, int do_host, Config * cfg);
void load_settings (char *section, int do_host, Config *cfg); void load_settings(char *section, int do_host, Config * cfg);
void get_sesslist(int allocate); void get_sesslist(int allocate);
/* /*
* Exports from terminal.c. * Exports from terminal.c.
*/ */
void term_init (void); void term_init(void);
void term_size (int, int, int); void term_size(int, int, int);
void term_out (void); void term_out(void);
void term_paint (Context, int, int, int, int); void term_paint(Context, int, int, int, int);
void term_scroll (int, int); void term_scroll(int, int);
void term_pwron (void); void term_pwron(void);
void term_clrsb (void); void term_clrsb(void);
void term_mouse (Mouse_Button, Mouse_Action, int, int, int, int); void term_mouse(Mouse_Button, Mouse_Action, int, int, int, int);
void term_deselect (void); void term_deselect(void);
void term_update (void); void term_update(void);
void term_invalidate(void); void term_invalidate(void);
void term_blink(int set_cursor); void term_blink(int set_cursor);
void term_paste(void); void term_paste(void);
void term_nopaste(void); void term_nopaste(void);
int term_ldisc(int option); int term_ldisc(int option);
void from_backend(int is_stderr, char *data, int len); void from_backend(int is_stderr, char *data, int len);
void logfopen (void); void logfopen(void);
void logfclose (void); void logfclose(void);
void term_copyall(void); void term_copyall(void);
/* /*
@ -408,8 +408,8 @@ extern Backend telnet_backend;
* Exports from ssh.c. * Exports from ssh.c.
*/ */
extern int (*ssh_get_line)(const char *prompt, char *str, int maxlen, extern int (*ssh_get_line) (const char *prompt, char *str, int maxlen,
int is_pw); int is_pw);
extern Backend ssh_backend; extern Backend ssh_backend;
/* /*

File diff suppressed because it is too large Load Diff

View File

@ -5,8 +5,8 @@
#ifndef PUTTY_PUTTYMEM_H #ifndef PUTTY_PUTTYMEM_H
#define PUTTY_PUTTYMEM_H #define PUTTY_PUTTYMEM_H
#include <stddef.h> /* for size_t */ #include <stddef.h> /* for size_t */
#include <string.h> /* for memcpy() */ #include <string.h> /* for memcpy() */
/* #define MALLOC_LOG do this if you suspect putty of leaking memory */ /* #define MALLOC_LOG do this if you suspect putty of leaking memory */

47
raw.c
View File

@ -20,21 +20,25 @@ static char *sb_buf = NULL;
static int sb_size = 0; static int sb_size = 0;
#define SB_DELTA 1024 #define SB_DELTA 1024
static void c_write (char *buf, int len) { static void c_write(char *buf, int len)
{
from_backend(0, buf, len); from_backend(0, buf, len);
} }
static int raw_closing (Plug plug, char *error_msg, int error_code, int calling_back) { static int raw_closing(Plug plug, char *error_msg, int error_code,
int calling_back)
{
sk_close(s); sk_close(s);
s = NULL; s = NULL;
if (error_msg) { if (error_msg) {
/* A socket error has occurred. */ /* A socket error has occurred. */
connection_fatal (error_msg); connection_fatal(error_msg);
} /* Otherwise, the remote side closed the connection normally. */ } /* Otherwise, the remote side closed the connection normally. */
return 0; return 0;
} }
static int raw_receive (Plug plug, int urgent, char *data, int len) { static int raw_receive(Plug plug, int urgent, char *data, int len)
{
c_write(data, len); c_write(data, len);
return 1; return 1;
} }
@ -46,7 +50,8 @@ static int raw_receive (Plug plug, int urgent, char *data, int len) {
* *
* Also places the canonical host name into `realhost'. * Also places the canonical host name into `realhost'.
*/ */
static char *raw_init (char *host, int port, char **realhost) { static char *raw_init(char *host, int port, char **realhost)
{
static struct plug_function_table fn_table = { static struct plug_function_table fn_table = {
raw_closing, raw_closing,
raw_receive raw_receive
@ -59,7 +64,7 @@ static char *raw_init (char *host, int port, char **realhost) {
* Try to find host. * Try to find host.
*/ */
addr = sk_namelookup(host, realhost); addr = sk_namelookup(host, realhost);
if ( (err = sk_addr_error(addr)) ) if ((err = sk_addr_error(addr)))
return err; return err;
if (port < 0) if (port < 0)
@ -69,7 +74,7 @@ static char *raw_init (char *host, int port, char **realhost) {
* Open socket. * Open socket.
*/ */
s = sk_new(addr, port, 0, 1, &fn_table_ptr); s = sk_new(addr, port, 0, 1, &fn_table_ptr);
if ( (err = sk_socket_error(s)) ) if ((err = sk_socket_error(s)))
return err; return err;
sk_addr_free(addr); sk_addr_free(addr);
@ -80,7 +85,8 @@ static char *raw_init (char *host, int port, char **realhost) {
/* /*
* Called to send data down the raw connection. * Called to send data down the raw connection.
*/ */
static void raw_send (char *buf, int len) { static void raw_send(char *buf, int len)
{
if (s == NULL) if (s == NULL)
return; return;
@ -91,7 +97,8 @@ static void raw_send (char *buf, int len) {
/* /*
* Called to set the size of the window * Called to set the size of the window
*/ */
static void raw_size(void) { static void raw_size(void)
{
/* Do nothing! */ /* Do nothing! */
return; return;
} }
@ -99,18 +106,26 @@ static void raw_size(void) {
/* /*
* Send raw special codes. * Send raw special codes.
*/ */
static void raw_special (Telnet_Special code) { static void raw_special(Telnet_Special code)
{
/* Do nothing! */ /* Do nothing! */
return; return;
} }
static Socket raw_socket(void) { return s; } static Socket raw_socket(void)
{
return s;
}
static int raw_sendok(void) { return 1; } static int raw_sendok(void)
{
return 1;
}
static int raw_ldisc(int option) { static int raw_ldisc(int option)
{
if (option == LD_EDIT || option == LD_ECHO) if (option == LD_EDIT || option == LD_ECHO)
return 1; return 1;
return 0; return 0;
} }

126
rlogin.c
View File

@ -21,48 +21,53 @@ static char *sb_buf = NULL;
static int sb_size = 0; static int sb_size = 0;
#define SB_DELTA 1024 #define SB_DELTA 1024
static void c_write (char *buf, int len) { static void c_write(char *buf, int len)
{
from_backend(0, buf, len); from_backend(0, buf, len);
} }
static int rlogin_closing (Plug plug, char *error_msg, int error_code, int calling_back) { static int rlogin_closing(Plug plug, char *error_msg, int error_code,
int calling_back)
{
sk_close(s); sk_close(s);
s = NULL; s = NULL;
if (error_msg) { if (error_msg) {
/* A socket error has occurred. */ /* A socket error has occurred. */
connection_fatal (error_msg); connection_fatal(error_msg);
} /* Otherwise, the remote side closed the connection normally. */ } /* Otherwise, the remote side closed the connection normally. */
return 0; return 0;
} }
static int rlogin_receive (Plug plug, int urgent, char *data, int len) { static int rlogin_receive(Plug plug, int urgent, char *data, int len)
{
if (urgent == 2) { if (urgent == 2) {
char c; char c;
c = *data++; len--; c = *data++;
if (c == '\x80') len--;
rlogin_size(); if (c == '\x80')
/* rlogin_size();
* We should flush everything (aka Telnet SYNCH) if we see /*
* 0x02, and we should turn off and on _local_ flow control * We should flush everything (aka Telnet SYNCH) if we see
* on 0x10 and 0x20 respectively. I'm not convinced it's * 0x02, and we should turn off and on _local_ flow control
* worth it... * on 0x10 and 0x20 respectively. I'm not convinced it's
*/ * worth it...
*/
} else { } else {
/* /*
* Main rlogin protocol. This is really simple: the first * Main rlogin protocol. This is really simple: the first
* byte is expected to be NULL and is ignored, and the rest * byte is expected to be NULL and is ignored, and the rest
* is printed. * is printed.
*/ */
static int firstbyte = 1; static int firstbyte = 1;
if (firstbyte) { if (firstbyte) {
if (data[0] == '\0') { if (data[0] == '\0') {
data++; data++;
len--; len--;
} }
firstbyte = 0; firstbyte = 0;
} }
c_write(data, len); c_write(data, len);
} }
return 1; return 1;
} }
@ -74,7 +79,8 @@ static int rlogin_receive (Plug plug, int urgent, char *data, int len) {
* *
* Also places the canonical host name into `realhost'. * Also places the canonical host name into `realhost'.
*/ */
static char *rlogin_init (char *host, int port, char **realhost) { static char *rlogin_init(char *host, int port, char **realhost)
{
static struct plug_function_table fn_table = { static struct plug_function_table fn_table = {
rlogin_closing, rlogin_closing,
rlogin_receive rlogin_receive
@ -87,7 +93,7 @@ static char *rlogin_init (char *host, int port, char **realhost) {
* Try to find host. * Try to find host.
*/ */
addr = sk_namelookup(host, realhost); addr = sk_namelookup(host, realhost);
if ( (err = sk_addr_error(addr)) ) if ((err = sk_addr_error(addr)))
return err; return err;
if (port < 0) if (port < 0)
@ -97,7 +103,7 @@ static char *rlogin_init (char *host, int port, char **realhost) {
* Open socket. * Open socket.
*/ */
s = sk_new(addr, port, 1, 0, &fn_table_ptr); s = sk_new(addr, port, 1, 0, &fn_table_ptr);
if ( (err = sk_socket_error(s)) ) if ((err = sk_socket_error(s)))
return err; return err;
sk_addr_free(addr); sk_addr_free(addr);
@ -107,18 +113,18 @@ static char *rlogin_init (char *host, int port, char **realhost) {
*/ */
{ {
char z = 0; char z = 0;
char *p; char *p;
sk_write(s, &z, 1); sk_write(s, &z, 1);
sk_write(s, cfg.localusername, strlen(cfg.localusername)); sk_write(s, cfg.localusername, strlen(cfg.localusername));
sk_write(s, &z, 1); sk_write(s, &z, 1);
sk_write(s, cfg.username, strlen(cfg.username)); sk_write(s, cfg.username, strlen(cfg.username));
sk_write(s, &z, 1); sk_write(s, &z, 1);
sk_write(s, cfg.termtype, strlen(cfg.termtype)); sk_write(s, cfg.termtype, strlen(cfg.termtype));
sk_write(s, "/", 1); sk_write(s, "/", 1);
for(p = cfg.termspeed; isdigit(*p); p++); for (p = cfg.termspeed; isdigit(*p); p++);
sk_write(s, cfg.termspeed, p - cfg.termspeed); sk_write(s, cfg.termspeed, p - cfg.termspeed);
sk_write(s, &z, 1); sk_write(s, &z, 1);
} }
return NULL; return NULL;
@ -127,7 +133,8 @@ static char *rlogin_init (char *host, int port, char **realhost) {
/* /*
* Called to send data down the rlogin connection. * Called to send data down the rlogin connection.
*/ */
static void rlogin_send (char *buf, int len) { static void rlogin_send(char *buf, int len)
{
if (s == NULL) if (s == NULL)
return; return;
@ -138,11 +145,14 @@ static void rlogin_send (char *buf, int len) {
/* /*
* Called to set the size of the window * Called to set the size of the window
*/ */
static void rlogin_size(void) { static void rlogin_size(void)
{
char b[12] = { '\xFF', '\xFF', 0x73, 0x73, 0, 0, 0, 0, 0, 0, 0, 0 }; char b[12] = { '\xFF', '\xFF', 0x73, 0x73, 0, 0, 0, 0, 0, 0, 0, 0 };
b[6] = cols >> 8; b[7] = cols & 0xFF; b[6] = cols >> 8;
b[4] = rows >> 8; b[5] = rows & 0xFF; b[7] = cols & 0xFF;
b[4] = rows >> 8;
b[5] = rows & 0xFF;
sk_write(s, b, 12); sk_write(s, b, 12);
return; return;
} }
@ -150,16 +160,24 @@ static void rlogin_size(void) {
/* /*
* Send rlogin special codes. * Send rlogin special codes.
*/ */
static void rlogin_special (Telnet_Special code) { static void rlogin_special(Telnet_Special code)
{
/* Do nothing! */ /* Do nothing! */
return; return;
} }
static Socket rlogin_socket(void) { return s; } static Socket rlogin_socket(void)
{
return s;
}
static int rlogin_sendok(void) { return 1; } static int rlogin_sendok(void)
{
return 1;
}
static int rlogin_ldisc(int option) { static int rlogin_ldisc(int option)
{
return 0; return 0;
} }

531
scp.c
View File

@ -56,7 +56,7 @@ static char *password = NULL;
static int errs = 0; static int errs = 0;
/* GUI Adaptation - Sept 2000 */ /* GUI Adaptation - Sept 2000 */
#define NAME_STR_MAX 2048 #define NAME_STR_MAX 2048
static char statname[NAME_STR_MAX+1]; static char statname[NAME_STR_MAX + 1];
static unsigned long statsize = 0; static unsigned long statsize = 0;
static int statperct = 0; static int statperct = 0;
static unsigned long statelapsed = 0; static unsigned long statelapsed = 0;
@ -67,17 +67,20 @@ static void source(char *src);
static void rsource(char *src); static void rsource(char *src);
static void sink(char *targ, char *src); static void sink(char *targ, char *src);
/* GUI Adaptation - Sept 2000 */ /* GUI Adaptation - Sept 2000 */
static void tell_char(FILE *stream, char c); static void tell_char(FILE * stream, char c);
static void tell_str(FILE *stream, char *str); static void tell_str(FILE * stream, char *str);
static void tell_user(FILE *stream, char *fmt, ...); static void tell_user(FILE * stream, char *fmt, ...);
static void send_char_msg(unsigned int msg_id, char c); static void send_char_msg(unsigned int msg_id, char c);
static void send_str_msg(unsigned int msg_id, char *str); static void send_str_msg(unsigned int msg_id, char *str);
static void gui_update_stats(char *name, unsigned long size, static void gui_update_stats(char *name, unsigned long size,
int percentage, unsigned long elapsed); int percentage, unsigned long elapsed);
void logevent(char *string) { } void logevent(char *string)
{
}
void ldisc_send(char *buf, int len) { void ldisc_send(char *buf, int len)
{
/* /*
* This is only here because of the calls to ldisc_send(NULL, * This is only here because of the calls to ldisc_send(NULL,
* 0) in ssh.c. Nothing in PSCP actually needs to use the ldisc * 0) in ssh.c. Nothing in PSCP actually needs to use the ldisc
@ -88,38 +91,38 @@ void ldisc_send(char *buf, int len) {
} }
void verify_ssh_host_key(char *host, int port, char *keytype, void verify_ssh_host_key(char *host, int port, char *keytype,
char *keystr, char *fingerprint) { char *keystr, char *fingerprint)
{
int ret; int ret;
static const char absentmsg[] = static const char absentmsg[] =
"The server's host key is not cached in the registry. You\n" "The server's host key is not cached in the registry. You\n"
"have no guarantee that the server is the computer you\n" "have no guarantee that the server is the computer you\n"
"think it is.\n" "think it is.\n"
"The server's key fingerprint is:\n" "The server's key fingerprint is:\n"
"%s\n" "%s\n"
"If you trust this host, enter \"y\" to add the key to\n" "If you trust this host, enter \"y\" to add the key to\n"
"PuTTY's cache and carry on connecting.\n" "PuTTY's cache and carry on connecting.\n"
"If you do not trust this host, enter \"n\" to abandon the\n" "If you do not trust this host, enter \"n\" to abandon the\n"
"connection.\n" "connection.\n" "Continue connecting? (y/n) ";
"Continue connecting? (y/n) ";
static const char wrongmsg[] = static const char wrongmsg[] =
"WARNING - POTENTIAL SECURITY BREACH!\n" "WARNING - POTENTIAL SECURITY BREACH!\n"
"The server's host key does not match the one PuTTY has\n" "The server's host key does not match the one PuTTY has\n"
"cached in the registry. This means that either the\n" "cached in the registry. This means that either the\n"
"server administrator has changed the host key, or you\n" "server administrator has changed the host key, or you\n"
"have actually connected to another computer pretending\n" "have actually connected to another computer pretending\n"
"to be the server.\n" "to be the server.\n"
"The new key fingerprint is:\n" "The new key fingerprint is:\n"
"%s\n" "%s\n"
"If you were expecting this change and trust the new key,\n" "If you were expecting this change and trust the new key,\n"
"enter Yes to update PuTTY's cache and continue connecting.\n" "enter Yes to update PuTTY's cache and continue connecting.\n"
"If you want to carry on connecting but without updating\n" "If you want to carry on connecting but without updating\n"
"the cache, enter No.\n" "the cache, enter No.\n"
"If you want to abandon the connection completely, press\n" "If you want to abandon the connection completely, press\n"
"Return to cancel. Pressing Return is the ONLY guaranteed\n" "Return to cancel. Pressing Return is the ONLY guaranteed\n"
"safe choice.\n" "safe choice.\n"
"Update cached key? (y/n, Return cancels connection) "; "Update cached key? (y/n, Return cancels connection) ";
static const char abandoned[] = "Connection abandoned.\n"; static const char abandoned[] = "Connection abandoned.\n";
@ -130,63 +133,63 @@ void verify_ssh_host_key(char *host, int port, char *keytype,
*/ */
ret = verify_host_key(host, port, keytype, keystr); ret = verify_host_key(host, port, keytype, keystr);
if (ret == 0) /* success - key matched OK */ if (ret == 0) /* success - key matched OK */
return; return;
if (ret == 2) { /* key was different */ if (ret == 2) { /* key was different */
fprintf(stderr, wrongmsg, fingerprint); fprintf(stderr, wrongmsg, fingerprint);
fflush(stderr); fflush(stderr);
if (fgets(line, sizeof(line), stdin) && if (fgets(line, sizeof(line), stdin) &&
line[0] != '\0' && line[0] != '\n') { line[0] != '\0' && line[0] != '\n') {
if (line[0] == 'y' || line[0] == 'Y') if (line[0] == 'y' || line[0] == 'Y')
store_host_key(host, port, keytype, keystr); store_host_key(host, port, keytype, keystr);
} else { } else {
fprintf(stderr, abandoned); fprintf(stderr, abandoned);
fflush(stderr); fflush(stderr);
exit(0); exit(0);
} }
} }
if (ret == 1) { /* key was absent */ if (ret == 1) { /* key was absent */
fprintf(stderr, absentmsg, fingerprint); fprintf(stderr, absentmsg, fingerprint);
if (fgets(line, sizeof(line), stdin) && if (fgets(line, sizeof(line), stdin) &&
(line[0] == 'y' || line[0] == 'Y')) (line[0] == 'y' || line[0] == 'Y'))
store_host_key(host, port, keytype, keystr); store_host_key(host, port, keytype, keystr);
else { else {
fprintf(stderr, abandoned); fprintf(stderr, abandoned);
exit(0); exit(0);
} }
} }
} }
/* GUI Adaptation - Sept 2000 */ /* GUI Adaptation - Sept 2000 */
static void send_msg(HWND h, UINT message, WPARAM wParam) static void send_msg(HWND h, UINT message, WPARAM wParam)
{ {
while (!PostMessage( h, message, wParam, 0)) while (!PostMessage(h, message, wParam, 0))
SleepEx(1000,TRUE); SleepEx(1000, TRUE);
} }
static void tell_char(FILE *stream, char c) static void tell_char(FILE * stream, char c)
{ {
if (!gui_mode) if (!gui_mode)
fputc(c, stream); fputc(c, stream);
else else {
{
unsigned int msg_id = WM_STD_OUT_CHAR; unsigned int msg_id = WM_STD_OUT_CHAR;
if (stream == stderr) msg_id = WM_STD_ERR_CHAR; if (stream == stderr)
send_msg( (HWND)atoi(gui_hwnd), msg_id, (WPARAM)c ); msg_id = WM_STD_ERR_CHAR;
send_msg((HWND) atoi(gui_hwnd), msg_id, (WPARAM) c);
} }
} }
static void tell_str(FILE *stream, char *str) static void tell_str(FILE * stream, char *str)
{ {
unsigned int i; unsigned int i;
for( i = 0; i < strlen(str); ++i ) for (i = 0; i < strlen(str); ++i)
tell_char(stream, str[i]); tell_char(stream, str[i]);
} }
static void tell_user(FILE *stream, char *fmt, ...) static void tell_user(FILE * stream, char *fmt, ...)
{ {
char str[0x100]; /* Make the size big enough */ char str[0x100]; /* Make the size big enough */
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
vsprintf(str, fmt, ap); vsprintf(str, fmt, ap);
@ -195,30 +198,30 @@ static void tell_user(FILE *stream, char *fmt, ...)
tell_str(stream, str); tell_str(stream, str);
} }
static void gui_update_stats(char *name, unsigned long size, int percentage, unsigned long elapsed) static void gui_update_stats(char *name, unsigned long size,
int percentage, unsigned long elapsed)
{ {
unsigned int i; unsigned int i;
if (strcmp(name,statname) != 0) if (strcmp(name, statname) != 0) {
{ for (i = 0; i < strlen(name); ++i)
for( i = 0; i < strlen(name); ++i ) send_msg((HWND) atoi(gui_hwnd), WM_STATS_CHAR,
send_msg( (HWND)atoi(gui_hwnd), WM_STATS_CHAR, (WPARAM)name[i]); (WPARAM) name[i]);
send_msg( (HWND)atoi(gui_hwnd), WM_STATS_CHAR, (WPARAM)'\n' ); send_msg((HWND) atoi(gui_hwnd), WM_STATS_CHAR, (WPARAM) '\n');
strcpy(statname,name); strcpy(statname, name);
} }
if (statsize != size) if (statsize != size) {
{ send_msg((HWND) atoi(gui_hwnd), WM_STATS_SIZE, (WPARAM) size);
send_msg( (HWND)atoi(gui_hwnd), WM_STATS_SIZE, (WPARAM)size );
statsize = size; statsize = size;
} }
if (statelapsed != elapsed) if (statelapsed != elapsed) {
{ send_msg((HWND) atoi(gui_hwnd), WM_STATS_ELAPSED,
send_msg( (HWND)atoi(gui_hwnd), WM_STATS_ELAPSED, (WPARAM)elapsed ); (WPARAM) elapsed);
statelapsed = elapsed; statelapsed = elapsed;
} }
if (statperct != percentage) if (statperct != percentage) {
{ send_msg((HWND) atoi(gui_hwnd), WM_STATS_PERCENT,
send_msg( (HWND)atoi(gui_hwnd), WM_STATS_PERCENT, (WPARAM)percentage ); (WPARAM) percentage);
statperct = percentage; statperct = percentage;
} }
} }
@ -228,11 +231,11 @@ static void gui_update_stats(char *name, unsigned long size, int percentage, uns
*/ */
void fatalbox(char *fmt, ...) void fatalbox(char *fmt, ...)
{ {
char str[0x100]; /* Make the size big enough */ char str[0x100]; /* Make the size big enough */
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
strcpy(str, "Fatal:"); strcpy(str, "Fatal:");
vsprintf(str+strlen(str), fmt, ap); vsprintf(str + strlen(str), fmt, ap);
va_end(ap); va_end(ap);
strcat(str, "\n"); strcat(str, "\n");
tell_str(stderr, str); tell_str(stderr, str);
@ -241,11 +244,11 @@ void fatalbox(char *fmt, ...)
} }
void connection_fatal(char *fmt, ...) void connection_fatal(char *fmt, ...)
{ {
char str[0x100]; /* Make the size big enough */ char str[0x100]; /* Make the size big enough */
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
strcpy(str, "Fatal:"); strcpy(str, "Fatal:");
vsprintf(str+strlen(str), fmt, ap); vsprintf(str + strlen(str), fmt, ap);
va_end(ap); va_end(ap);
strcat(str, "\n"); strcat(str, "\n");
tell_str(stderr, str); tell_str(stderr, str);
@ -257,7 +260,8 @@ void connection_fatal(char *fmt, ...)
* Be told what socket we're supposed to be using. * Be told what socket we're supposed to be using.
*/ */
static SOCKET scp_ssh_socket; static SOCKET scp_ssh_socket;
char *do_select(SOCKET skt, int startup) { char *do_select(SOCKET skt, int startup)
{
if (startup) if (startup)
scp_ssh_socket = skt; scp_ssh_socket = skt;
else else
@ -275,13 +279,14 @@ extern int select_result(WPARAM, LPARAM);
* do this until we have enough data. * do this until we have enough data.
*/ */
static unsigned char *outptr; /* where to put the data */ static unsigned char *outptr; /* where to put the data */
static unsigned outlen; /* how much data required */ static unsigned outlen; /* how much data required */
static unsigned char *pending = NULL; /* any spare data */ static unsigned char *pending = NULL; /* any spare data */
static unsigned pendlen=0, pendsize=0; /* length and phys. size of buffer */ static unsigned pendlen = 0, pendsize = 0; /* length and phys. size of buffer */
void from_backend(int is_stderr, char *data, int datalen) { void from_backend(int is_stderr, char *data, int datalen)
unsigned char *p = (unsigned char *)data; {
unsigned len = (unsigned)datalen; unsigned char *p = (unsigned char *) data;
unsigned len = (unsigned) datalen;
/* /*
* stderr data is just spouted to local stderr and otherwise * stderr data is just spouted to local stderr and otherwise
@ -298,29 +303,33 @@ void from_backend(int is_stderr, char *data, int datalen) {
* If this is before the real session begins, just return. * If this is before the real session begins, just return.
*/ */
if (!outptr) if (!outptr)
return; return;
if (outlen > 0) { if (outlen > 0) {
unsigned used = outlen; unsigned used = outlen;
if (used > len) used = len; if (used > len)
memcpy(outptr, p, used); used = len;
outptr += used; outlen -= used; memcpy(outptr, p, used);
p += used; len -= used; outptr += used;
outlen -= used;
p += used;
len -= used;
} }
if (len > 0) { if (len > 0) {
if (pendsize < pendlen + len) { if (pendsize < pendlen + len) {
pendsize = pendlen + len + 4096; pendsize = pendlen + len + 4096;
pending = (pending ? srealloc(pending, pendsize) : pending = (pending ? srealloc(pending, pendsize) :
smalloc(pendsize)); smalloc(pendsize));
if (!pending) if (!pending)
fatalbox("Out of memory"); fatalbox("Out of memory");
} }
memcpy(pending+pendlen, p, len); memcpy(pending + pendlen, p, len);
pendlen += len; pendlen += len;
} }
} }
static int ssh_scp_recv(unsigned char *buf, int len) { static int ssh_scp_recv(unsigned char *buf, int len)
{
outptr = buf; outptr = buf;
outlen = len; outlen = len;
@ -329,31 +338,31 @@ static int ssh_scp_recv(unsigned char *buf, int len) {
* need. * need.
*/ */
if (pendlen > 0) { if (pendlen > 0) {
unsigned pendused = pendlen; unsigned pendused = pendlen;
if (pendused > outlen) if (pendused > outlen)
pendused = outlen; pendused = outlen;
memcpy(outptr, pending, pendused); memcpy(outptr, pending, pendused);
memmove(pending, pending+pendused, pendlen-pendused); memmove(pending, pending + pendused, pendlen - pendused);
outptr += pendused; outptr += pendused;
outlen -= pendused; outlen -= pendused;
pendlen -= pendused; pendlen -= pendused;
if (pendlen == 0) { if (pendlen == 0) {
pendsize = 0; pendsize = 0;
sfree(pending); sfree(pending);
pending = NULL; pending = NULL;
} }
if (outlen == 0) if (outlen == 0)
return len; return len;
} }
while (outlen > 0) { while (outlen > 0) {
fd_set readfds; fd_set readfds;
FD_ZERO(&readfds); FD_ZERO(&readfds);
FD_SET(scp_ssh_socket, &readfds); FD_SET(scp_ssh_socket, &readfds);
if (select(1, &readfds, NULL, NULL, NULL) < 0) if (select(1, &readfds, NULL, NULL, NULL) < 0)
return 0; /* doom */ return 0; /* doom */
select_result((WPARAM)scp_ssh_socket, (LPARAM)FD_READ); select_result((WPARAM) scp_ssh_socket, (LPARAM) FD_READ);
} }
return len; return len;
@ -362,16 +371,17 @@ static int ssh_scp_recv(unsigned char *buf, int len) {
/* /*
* Loop through the ssh connection and authentication process. * Loop through the ssh connection and authentication process.
*/ */
static void ssh_scp_init(void) { static void ssh_scp_init(void)
{
if (scp_ssh_socket == INVALID_SOCKET) if (scp_ssh_socket == INVALID_SOCKET)
return; return;
while (!back->sendok()) { while (!back->sendok()) {
fd_set readfds; fd_set readfds;
FD_ZERO(&readfds); FD_ZERO(&readfds);
FD_SET(scp_ssh_socket, &readfds); FD_SET(scp_ssh_socket, &readfds);
if (select(1, &readfds, NULL, NULL, NULL) < 0) if (select(1, &readfds, NULL, NULL, NULL) < 0)
return; /* doom */ return; /* doom */
select_result((WPARAM)scp_ssh_socket, (LPARAM)FD_READ); select_result((WPARAM) scp_ssh_socket, (LPARAM) FD_READ);
} }
} }
@ -380,11 +390,11 @@ static void ssh_scp_init(void) {
*/ */
static void bump(char *fmt, ...) static void bump(char *fmt, ...)
{ {
char str[0x100]; /* Make the size big enough */ char str[0x100]; /* Make the size big enough */
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
strcpy(str, "Fatal:"); strcpy(str, "Fatal:");
vsprintf(str+strlen(str), fmt, ap); vsprintf(str + strlen(str), fmt, ap);
va_end(ap); va_end(ap);
strcat(str, "\n"); strcat(str, "\n");
tell_str(stderr, str); tell_str(stderr, str);
@ -403,21 +413,22 @@ static int get_line(const char *prompt, char *str, int maxlen, int is_pw)
DWORD savemode, newmode, i; DWORD savemode, newmode, i;
if (is_pw && password) { if (is_pw && password) {
static int tried_once = 0; static int tried_once = 0;
if (tried_once) { if (tried_once) {
return 0; return 0;
} else { } else {
strncpy(str, password, maxlen); strncpy(str, password, maxlen);
str[maxlen-1] = '\0'; str[maxlen - 1] = '\0';
tried_once = 1; tried_once = 1;
return 1; return 1;
} }
} }
/* GUI Adaptation - Sept 2000 */ /* GUI Adaptation - Sept 2000 */
if (gui_mode) { if (gui_mode) {
if (maxlen>0) str[0] = '\0'; if (maxlen > 0)
str[0] = '\0';
} else { } else {
hin = GetStdHandle(STD_INPUT_HANDLE); hin = GetStdHandle(STD_INPUT_HANDLE);
hout = GetStdHandle(STD_OUTPUT_HANDLE); hout = GetStdHandle(STD_OUTPUT_HANDLE);
@ -425,23 +436,26 @@ static int get_line(const char *prompt, char *str, int maxlen, int is_pw)
bump("Cannot get standard input/output handles"); bump("Cannot get standard input/output handles");
GetConsoleMode(hin, &savemode); GetConsoleMode(hin, &savemode);
newmode = savemode | ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT; newmode = savemode | ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT;
if (is_pw) if (is_pw)
newmode &= ~ENABLE_ECHO_INPUT; newmode &= ~ENABLE_ECHO_INPUT;
else else
newmode |= ENABLE_ECHO_INPUT; newmode |= ENABLE_ECHO_INPUT;
SetConsoleMode(hin, newmode); SetConsoleMode(hin, newmode);
WriteFile(hout, prompt, strlen(prompt), &i, NULL); WriteFile(hout, prompt, strlen(prompt), &i, NULL);
ReadFile(hin, str, maxlen-1, &i, NULL); ReadFile(hin, str, maxlen - 1, &i, NULL);
SetConsoleMode(hin, savemode); SetConsoleMode(hin, savemode);
if ((int)i > maxlen) i = maxlen-1; else i = i - 2; if ((int) i > maxlen)
i = maxlen - 1;
else
i = i - 2;
str[i] = '\0'; str[i] = '\0';
if (is_pw) if (is_pw)
WriteFile(hout, "\r\n", 2, &i, NULL); WriteFile(hout, "\r\n", 2, &i, NULL);
} }
return 1; return 1;
@ -462,25 +476,26 @@ static void do_cmd(char *host, char *user, char *cmd)
do_defaults(host, &cfg); do_defaults(host, &cfg);
if (cfg.host[0] == '\0') { if (cfg.host[0] == '\0') {
/* No settings for this host; use defaults */ /* No settings for this host; use defaults */
do_defaults(NULL, &cfg); do_defaults(NULL, &cfg);
strncpy(cfg.host, host, sizeof(cfg.host)-1); strncpy(cfg.host, host, sizeof(cfg.host) - 1);
cfg.host[sizeof(cfg.host)-1] = '\0'; cfg.host[sizeof(cfg.host) - 1] = '\0';
cfg.port = 22; cfg.port = 22;
} }
/* Set username */ /* Set username */
if (user != NULL && user[0] != '\0') { if (user != NULL && user[0] != '\0') {
strncpy(cfg.username, user, sizeof(cfg.username)-1); strncpy(cfg.username, user, sizeof(cfg.username) - 1);
cfg.username[sizeof(cfg.username)-1] = '\0'; cfg.username[sizeof(cfg.username) - 1] = '\0';
} else if (cfg.username[0] == '\0') { } else if (cfg.username[0] == '\0') {
namelen = 0; namelen = 0;
if (GetUserName(user, &namelen) == FALSE) if (GetUserName(user, &namelen) == FALSE)
bump("Empty user name"); bump("Empty user name");
user = smalloc(namelen * sizeof(char)); user = smalloc(namelen * sizeof(char));
GetUserName(user, &namelen); GetUserName(user, &namelen);
if (verbose) tell_user(stderr, "Guessing user name: %s", user); if (verbose)
strncpy(cfg.username, user, sizeof(cfg.username)-1); tell_user(stderr, "Guessing user name: %s", user);
cfg.username[sizeof(cfg.username)-1] = '\0'; strncpy(cfg.username, user, sizeof(cfg.username) - 1);
cfg.username[sizeof(cfg.username) - 1] = '\0';
free(user); free(user);
} }
@ -491,7 +506,7 @@ static void do_cmd(char *host, char *user, char *cmd)
cfg.port = portnumber; cfg.port = portnumber;
strncpy(cfg.remote_cmd, cmd, sizeof(cfg.remote_cmd)); strncpy(cfg.remote_cmd, cmd, sizeof(cfg.remote_cmd));
cfg.remote_cmd[sizeof(cfg.remote_cmd)-1] = '\0'; cfg.remote_cmd[sizeof(cfg.remote_cmd) - 1] = '\0';
cfg.nopty = TRUE; cfg.nopty = TRUE;
back = &ssh_backend; back = &ssh_backend;
@ -508,7 +523,7 @@ static void do_cmd(char *host, char *user, char *cmd)
* Update statistic information about current file. * Update statistic information about current file.
*/ */
static void print_stats(char *name, unsigned long size, unsigned long done, static void print_stats(char *name, unsigned long size, unsigned long done,
time_t start, time_t now) time_t start, time_t now)
{ {
float ratebs; float ratebs;
unsigned long eta; unsigned long eta;
@ -517,8 +532,8 @@ static void print_stats(char *name, unsigned long size, unsigned long done,
/* GUI Adaptation - Sept 2000 */ /* GUI Adaptation - Sept 2000 */
if (gui_mode) if (gui_mode)
gui_update_stats(name, size, (int)(100 * (done*1.0/size)), gui_update_stats(name, size, (int) (100 * (done * 1.0 / size)),
(unsigned long)difftime(now, start)); (unsigned long) difftime(now, start));
else { else {
if (now > start) if (now > start)
ratebs = (float) done / (now - start); ratebs = (float) done / (now - start);
@ -535,8 +550,7 @@ static void print_stats(char *name, unsigned long size, unsigned long done,
pct = (int) (100.0 * (float) done / size); pct = (int) (100.0 * (float) done / size);
printf("\r%-25.25s | %10ld kB | %5.1f kB/s | ETA: %8s | %3d%%", printf("\r%-25.25s | %10ld kB | %5.1f kB/s | ETA: %8s | %3d%%",
name, done / 1024, ratebs / 1024.0, name, done / 1024, ratebs / 1024.0, etastr, pct);
etastr, pct);
if (done == size) if (done == size)
printf("\n"); printf("\n");
@ -547,19 +561,14 @@ static void print_stats(char *name, unsigned long size, unsigned long done,
* Find a colon in str and return a pointer to the colon. * Find a colon in str and return a pointer to the colon.
* This is used to separate hostname from filename. * This is used to separate hostname from filename.
*/ */
static char * colon(char *str) static char *colon(char *str)
{ {
/* We ignore a leading colon, since the hostname cannot be /* We ignore a leading colon, since the hostname cannot be
empty. We also ignore a colon as second character because empty. We also ignore a colon as second character because
of filenames like f:myfile.txt. */ of filenames like f:myfile.txt. */
if (str[0] == '\0' || if (str[0] == '\0' || str[0] == ':' || str[1] == ':')
str[0] == ':' ||
str[1] == ':')
return (NULL); return (NULL);
while (*str != '\0' && while (*str != '\0' && *str != ':' && *str != '/' && *str != '\\')
*str != ':' &&
*str != '/' &&
*str != '\\')
str++; str++;
if (*str == ':') if (*str == ':')
return (str); return (str);
@ -581,19 +590,19 @@ static int response(void)
p = 0; p = 0;
switch (resp) { switch (resp) {
case 0: /* ok */ case 0: /* ok */
return (0); return (0);
default: default:
rbuf[p++] = resp; rbuf[p++] = resp;
/* fallthrough */ /* fallthrough */
case 1: /* error */ case 1: /* error */
case 2: /* fatal error */ case 2: /* fatal error */
do { do {
if (ssh_scp_recv(&ch, 1) <= 0) if (ssh_scp_recv(&ch, 1) <= 0)
bump("Protocol error: Lost connection"); bump("Protocol error: Lost connection");
rbuf[p++] = ch; rbuf[p++] = ch;
} while (p < sizeof(rbuf) && ch != '\n'); } while (p < sizeof(rbuf) && ch != '\n');
rbuf[p-1] = '\0'; rbuf[p - 1] = '\0';
if (resp == 1) if (resp == 1)
tell_user(stderr, "%s\n", rbuf); tell_user(stderr, "%s\n", rbuf);
else else
@ -614,11 +623,11 @@ static void run_err(const char *fmt, ...)
va_start(ap, fmt); va_start(ap, fmt);
errs++; errs++;
strcpy(str, "scp: "); strcpy(str, "scp: ");
vsprintf(str+strlen(str), fmt, ap); vsprintf(str + strlen(str), fmt, ap);
strcat(str, "\n"); strcat(str, "\n");
back->send("\001", 1); /* scp protocol error prefix */ back->send("\001", 1); /* scp protocol error prefix */
back->send(str, strlen(str)); back->send(str, strlen(str));
tell_user(stderr, "%s",str); tell_user(stderr, "%s", str);
va_end(ap); va_end(ap);
} }
@ -637,31 +646,31 @@ static void source(char *src)
time_t stat_starttime, stat_lasttime; time_t stat_starttime, stat_lasttime;
attr = GetFileAttributes(src); attr = GetFileAttributes(src);
if (attr == (DWORD)-1) { if (attr == (DWORD) - 1) {
run_err("%s: No such file or directory", src); run_err("%s: No such file or directory", src);
return; return;
} }
if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
if (recursive) { if (recursive) {
/* /*
* Avoid . and .. directories. * Avoid . and .. directories.
*/ */
char *p; char *p;
p = strrchr(src, '/'); p = strrchr(src, '/');
if (!p) if (!p)
p = strrchr(src, '\\'); p = strrchr(src, '\\');
if (!p) if (!p)
p = src; p = src;
else else
p++; p++;
if (!strcmp(p, ".") || !strcmp(p, "..")) if (!strcmp(p, ".") || !strcmp(p, ".."))
/* skip . and .. */; /* skip . and .. */ ;
else else
rsource(src); rsource(src);
} else { } else {
run_err("%s: not a regular file", src); run_err("%s: not a regular file", src);
} }
return; return;
} }
@ -710,16 +719,17 @@ static void source(char *src)
for (i = 0; i < size; i += 4096) { for (i = 0; i < size; i += 4096) {
char transbuf[4096]; char transbuf[4096];
DWORD j, k = 4096; DWORD j, k = 4096;
if (i + k > size) k = size - i; if (i + k > size)
if (! ReadFile(f, transbuf, k, &j, NULL) || j != k) { k = size - i;
if (statistics) printf("\n"); if (!ReadFile(f, transbuf, k, &j, NULL) || j != k) {
if (statistics)
printf("\n");
bump("%s: Read error", src); bump("%s: Read error", src);
} }
back->send(transbuf, k); back->send(transbuf, k);
if (statistics) { if (statistics) {
stat_bytes += k; stat_bytes += k;
if (time(NULL) != stat_lasttime || if (time(NULL) != stat_lasttime || i + k == size) {
i + k == size) {
stat_lasttime = time(NULL); stat_lasttime = time(NULL);
print_stats(last, size, stat_bytes, print_stats(last, size, stat_bytes,
stat_starttime, stat_lasttime); stat_starttime, stat_lasttime);
@ -767,8 +777,7 @@ static void rsource(char *src)
while (ok) { while (ok) {
if (strcmp(fdat.cFileName, ".") == 0 || if (strcmp(fdat.cFileName, ".") == 0 ||
strcmp(fdat.cFileName, "..") == 0) { strcmp(fdat.cFileName, "..") == 0) {
} else if (strlen(src) + 1 + strlen(fdat.cFileName) >= } else if (strlen(src) + 1 + strlen(fdat.cFileName) >= sizeof(buf)) {
sizeof(buf)) {
run_err("%s/%s: Name too long", src, fdat.cFileName); run_err("%s/%s: Name too long", src, fdat.cFileName);
} else { } else {
sprintf(buf, "%s/%s", src, fdat.cFileName); sprintf(buf, "%s/%s", src, fdat.cFileName);
@ -805,7 +814,7 @@ static void sink(char *targ, char *src)
char *stat_name; char *stat_name;
attr = GetFileAttributes(targ); attr = GetFileAttributes(targ);
if (attr != (DWORD)-1 && (attr & FILE_ATTRIBUTE_DIRECTORY) != 0) if (attr != (DWORD) - 1 && (attr & FILE_ATTRIBUTE_DIRECTORY) != 0)
targisdir = 1; targisdir = 1;
if (targetshouldbedirectory && !targisdir) if (targetshouldbedirectory && !targisdir)
@ -814,7 +823,7 @@ static void sink(char *targ, char *src)
back->send("", 1); back->send("", 1);
while (1) { while (1) {
settime = 0; settime = 0;
gottime: gottime:
if (ssh_scp_recv(&ch, 1) <= 0) if (ssh_scp_recv(&ch, 1) <= 0)
return; return;
if (ch == '\n') if (ch == '\n')
@ -826,20 +835,19 @@ static void sink(char *targ, char *src)
bump("Lost connection"); bump("Lost connection");
buf[i++] = ch; buf[i++] = ch;
} while (i < sizeof(buf) && ch != '\n'); } while (i < sizeof(buf) && ch != '\n');
buf[i-1] = '\0'; buf[i - 1] = '\0';
switch (buf[0]) { switch (buf[0]) {
case '\01': /* error */ case '\01': /* error */
tell_user(stderr, "%s\n", buf+1); tell_user(stderr, "%s\n", buf + 1);
errs++; errs++;
continue; continue;
case '\02': /* fatal error */ case '\02': /* fatal error */
bump("%s", buf+1); bump("%s", buf + 1);
case 'E': case 'E':
back->send("", 1); back->send("", 1);
return; return;
case 'T': case 'T':
if (sscanf(buf, "T%ld %*d %ld %*d", if (sscanf(buf, "T%ld %*d %ld %*d", &mtime, &atime) == 2) {
&mtime, &atime) == 2) {
settime = 1; settime = 1;
back->send("", 1); back->send("", 1);
goto gottime; goto gottime;
@ -852,7 +860,7 @@ static void sink(char *targ, char *src)
bump("Protocol error: Expected control record"); bump("Protocol error: Expected control record");
} }
if (sscanf(buf+1, "%u %lu %[^\n]", &mode, &size, namebuf) != 3) if (sscanf(buf + 1, "%u %lu %[^\n]", &mode, &size, namebuf) != 3)
bump("Protocol error: Illegal file descriptor format"); bump("Protocol error: Illegal file descriptor format");
/* Security fix: ensure the file ends up where we asked for it. */ /* Security fix: ensure the file ends up where we asked for it. */
if (targisdir) { if (targisdir) {
@ -870,7 +878,7 @@ static void sink(char *targ, char *src)
strcpy(namebuf, targ); strcpy(namebuf, targ);
} }
attr = GetFileAttributes(namebuf); attr = GetFileAttributes(namebuf);
exists = (attr != (DWORD)-1); exists = (attr != (DWORD) - 1);
if (buf[0] == 'D') { if (buf[0] == 'D') {
if (exists && (attr & FILE_ATTRIBUTE_DIRECTORY) == 0) { if (exists && (attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
@ -878,9 +886,8 @@ static void sink(char *targ, char *src)
continue; continue;
} }
if (!exists) { if (!exists) {
if (! CreateDirectory(namebuf, NULL)) { if (!CreateDirectory(namebuf, NULL)) {
run_err("%s: Cannot create directory", run_err("%s: Cannot create directory", namebuf);
namebuf);
continue; continue;
} }
} }
@ -913,11 +920,13 @@ static void sink(char *targ, char *src)
for (i = 0; i < size; i += 4096) { for (i = 0; i < size; i += 4096) {
char transbuf[4096]; char transbuf[4096];
DWORD j, k = 4096; DWORD j, k = 4096;
if (i + k > size) k = size - i; if (i + k > size)
k = size - i;
if (ssh_scp_recv(transbuf, k) == 0) if (ssh_scp_recv(transbuf, k) == 0)
bump("Lost connection"); bump("Lost connection");
if (wrerror) continue; if (wrerror)
if (! WriteFile(f, transbuf, k, &j, NULL) || j != k) { continue;
if (!WriteFile(f, transbuf, k, &j, NULL) || j != k) {
wrerror = 1; wrerror = 1;
if (statistics) if (statistics)
printf("\r%-25.25s | %50s\n", printf("\r%-25.25s | %50s\n",
@ -927,8 +936,7 @@ static void sink(char *targ, char *src)
} }
if (statistics) { if (statistics) {
stat_bytes += k; stat_bytes += k;
if (time(NULL) > stat_lasttime || if (time(NULL) > stat_lasttime || i + k == size) {
i + k == size) {
stat_lasttime = time(NULL); stat_lasttime = time(NULL);
print_stats(stat_name, size, stat_bytes, print_stats(stat_name, size, stat_bytes,
stat_starttime, stat_lasttime); stat_starttime, stat_lasttime);
@ -962,7 +970,7 @@ static void toremote(int argc, char *argv[])
char *cmd; char *cmd;
int i; int i;
targ = argv[argc-1]; targ = argv[argc - 1];
/* Separate host from filename */ /* Separate host from filename */
host = targ; host = targ;
@ -988,7 +996,7 @@ static void toremote(int argc, char *argv[])
if (argc == 2) { if (argc == 2) {
/* Find out if the source filespec covers multiple files /* Find out if the source filespec covers multiple files
if so, we should set the targetshouldbedirectory flag */ if so, we should set the targetshouldbedirectory flag */
HANDLE fh; HANDLE fh;
WIN32_FIND_DATA fdat; WIN32_FIND_DATA fdat;
if (colon(argv[0]) != NULL) if (colon(argv[0]) != NULL)
@ -1006,8 +1014,7 @@ static void toremote(int argc, char *argv[])
verbose ? " -v" : "", verbose ? " -v" : "",
recursive ? " -r" : "", recursive ? " -r" : "",
preserve ? " -p" : "", preserve ? " -p" : "",
targetshouldbedirectory ? " -d" : "", targetshouldbedirectory ? " -d" : "", targ);
targ);
do_cmd(host, user, cmd); do_cmd(host, user, cmd);
sfree(cmd); sfree(cmd);
@ -1044,15 +1051,14 @@ static void toremote(int argc, char *argv[])
*/ */
int len = strlen(src), dlen = strlen(fdat.cFileName); int len = strlen(src), dlen = strlen(fdat.cFileName);
if (len == dlen && !strcmp(src, fdat.cFileName)) { if (len == dlen && !strcmp(src, fdat.cFileName)) {
/* ok */; /* ok */ ;
} else if (len > dlen+1 && src[len-dlen-1] == '\\' && } else if (len > dlen + 1 && src[len - dlen - 1] == '\\' &&
!strcmp(src+len-dlen, fdat.cFileName)) { !strcmp(src + len - dlen, fdat.cFileName)) {
/* ok */; /* ok */ ;
} else } else
continue; /* ignore this one */ continue; /* ignore this one */
} }
if (strlen(src) + strlen(fdat.cFileName) >= if (strlen(src) + strlen(fdat.cFileName) >= sizeof(namebuf)) {
sizeof(namebuf)) {
tell_user(stderr, "%s: Name too long", src); tell_user(stderr, "%s: Name too long", src);
continue; continue;
} }
@ -1113,8 +1119,7 @@ static void tolocal(int argc, char *argv[])
verbose ? " -v" : "", verbose ? " -v" : "",
recursive ? " -r" : "", recursive ? " -r" : "",
preserve ? " -p" : "", preserve ? " -p" : "",
targetshouldbedirectory ? " -d" : "", targetshouldbedirectory ? " -d" : "", src);
src);
do_cmd(host, user, cmd); do_cmd(host, user, cmd);
sfree(cmd); sfree(cmd);
@ -1154,12 +1159,15 @@ static void get_dir_list(int argc, char *argv[])
user = NULL; user = NULL;
} }
cmd = smalloc(4*strlen(src) + 100); cmd = smalloc(4 * strlen(src) + 100);
strcpy(cmd, "ls -la '"); strcpy(cmd, "ls -la '");
p = cmd + strlen(cmd); p = cmd + strlen(cmd);
for (q = src; *q; q++) { for (q = src; *q; q++) {
if (*q == '\'') { if (*q == '\'') {
*p++ = '\''; *p++ = '\\'; *p++ = '\''; *p++ = '\''; *p++ = '\'';
*p++ = '\\';
*p++ = '\'';
*p++ = '\'';
} else { } else {
*p++ = *q; *p++ = *q;
} }
@ -1185,8 +1193,7 @@ static void init_winsock(void)
winsock_ver = MAKEWORD(1, 1); winsock_ver = MAKEWORD(1, 1);
if (WSAStartup(winsock_ver, &wsadata)) if (WSAStartup(winsock_ver, &wsadata))
bump("Unable to initialise WinSock"); bump("Unable to initialise WinSock");
if (LOBYTE(wsadata.wVersion) != 1 || if (LOBYTE(wsadata.wVersion) != 1 || HIBYTE(wsadata.wVersion) != 1)
HIBYTE(wsadata.wVersion) != 1)
bump("WinSock version is incompatible with 1.1"); bump("WinSock version is incompatible with 1.1");
} }
@ -1198,7 +1205,8 @@ static void usage(void)
printf("PuTTY Secure Copy client\n"); printf("PuTTY Secure Copy client\n");
printf("%s\n", ver); printf("%s\n", ver);
printf("Usage: pscp [options] [user@]host:source target\n"); printf("Usage: pscp [options] [user@]host:source target\n");
printf(" pscp [options] source [source...] [user@]host:target\n"); printf
(" pscp [options] source [source...] [user@]host:target\n");
printf(" pscp [options] -ls user@host:filespec\n"); printf(" pscp [options] -ls user@host:filespec\n");
printf("Options:\n"); printf("Options:\n");
printf(" -p preserve file attributes\n"); printf(" -p preserve file attributes\n");
@ -1215,7 +1223,8 @@ static void usage(void)
* the command-line help. The only people who need to know * the command-line help. The only people who need to know
* about it are programmers, and they can read the source. * about it are programmers, and they can read the source.
*/ */
printf(" -gui hWnd GUI mode with the windows handle for receiving messages\n"); printf
(" -gui hWnd GUI mode with the windows handle for receiving messages\n");
#endif #endif
exit(1); exit(1);
} }
@ -1246,21 +1255,21 @@ int main(int argc, char *argv[])
preserve = 1; preserve = 1;
else if (strcmp(argv[i], "-q") == 0) else if (strcmp(argv[i], "-q") == 0)
statistics = 0; statistics = 0;
else if (strcmp(argv[i], "-h") == 0 || else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "-?") == 0)
strcmp(argv[i], "-?") == 0)
usage(); usage();
else if (strcmp(argv[i], "-P") == 0 && i+1 < argc) else if (strcmp(argv[i], "-P") == 0 && i + 1 < argc)
portnumber = atoi(argv[++i]); portnumber = atoi(argv[++i]);
else if (strcmp(argv[i], "-pw") == 0 && i+1 < argc) else if (strcmp(argv[i], "-pw") == 0 && i + 1 < argc)
password = argv[++i]; password = argv[++i];
else if (strcmp(argv[i], "-gui") == 0 && i+1 < argc) { else if (strcmp(argv[i], "-gui") == 0 && i + 1 < argc) {
gui_hwnd = argv[++i]; gui_hwnd = argv[++i];
gui_mode = 1; gui_mode = 1;
} else if (strcmp(argv[i], "-ls") == 0) } else if (strcmp(argv[i], "-ls") == 0)
list = 1; list = 1;
else if (strcmp(argv[i], "--") == 0) else if (strcmp(argv[i], "--") == 0) {
{ i++; break; } i++;
else break;
} else
usage(); usage();
} }
argc -= i; argc -= i;
@ -1279,7 +1288,7 @@ int main(int argc, char *argv[])
if (argc > 2) if (argc > 2)
targetshouldbedirectory = 1; targetshouldbedirectory = 1;
if (colon(argv[argc-1]) != NULL) if (colon(argv[argc - 1]) != NULL)
toremote(argc, argv); toremote(argc, argv);
else else
tolocal(argc, argv); tolocal(argc, argv);
@ -1296,9 +1305,11 @@ int main(int argc, char *argv[])
/* GUI Adaptation - August 2000 */ /* GUI Adaptation - August 2000 */
if (gui_mode) { if (gui_mode) {
unsigned int msg_id = WM_RET_ERR_CNT; unsigned int msg_id = WM_RET_ERR_CNT;
if (list) msg_id = WM_LS_RET_ERR_CNT; if (list)
while (!PostMessage( (HWND)atoi(gui_hwnd), msg_id, (WPARAM)errs, 0/*lParam*/ ) ) msg_id = WM_LS_RET_ERR_CNT;
SleepEx(1000,TRUE); while (!PostMessage
((HWND) atoi(gui_hwnd), msg_id, (WPARAM) errs,
0 /*lParam */ ))SleepEx(1000, TRUE);
} }
return (errs == 0 ? 0 : 1); return (errs == 0 ? 0 : 1);
} }

View File

@ -8,51 +8,54 @@
#include "putty.h" #include "putty.h"
#include "storage.h" #include "storage.h"
static void gpps(void *handle, char *name, char *def, char *val, int len) { static void gpps(void *handle, char *name, char *def, char *val, int len)
{
if (!read_setting_s(handle, name, val, len)) { if (!read_setting_s(handle, name, val, len)) {
strncpy(val, def, len); strncpy(val, def, len);
val[len-1] = '\0'; val[len - 1] = '\0';
} }
} }
static void gppi(void *handle, char *name, int def, int *i) { static void gppi(void *handle, char *name, int def, int *i)
{
*i = read_setting_i(handle, name, def); *i = read_setting_i(handle, name, def);
} }
void save_settings (char *section, int do_host, Config *cfg) { void save_settings(char *section, int do_host, Config * cfg)
{
int i; int i;
char *p; char *p;
void *sesskey; void *sesskey;
sesskey = open_settings_w(section); sesskey = open_settings_w(section);
if (!sesskey) if (!sesskey)
return; return;
write_setting_i (sesskey, "Present", 1); write_setting_i(sesskey, "Present", 1);
if (do_host) { if (do_host) {
write_setting_s (sesskey, "HostName", cfg->host); write_setting_s(sesskey, "HostName", cfg->host);
write_setting_i (sesskey, "PortNumber", cfg->port); write_setting_i(sesskey, "PortNumber", cfg->port);
write_setting_s (sesskey, "LogFileName", cfg->logfilename); write_setting_s(sesskey, "LogFileName", cfg->logfilename);
write_setting_i (sesskey, "LogType", cfg->logtype); write_setting_i(sesskey, "LogType", cfg->logtype);
write_setting_i (sesskey, "LogFileClash", cfg->logxfovr); write_setting_i(sesskey, "LogFileClash", cfg->logxfovr);
p = "raw"; p = "raw";
for (i = 0; backends[i].name != NULL; i++) for (i = 0; backends[i].name != NULL; i++)
if (backends[i].protocol == cfg->protocol) { if (backends[i].protocol == cfg->protocol) {
p = backends[i].name; p = backends[i].name;
break; break;
} }
write_setting_s (sesskey, "Protocol", p); write_setting_s(sesskey, "Protocol", p);
} }
write_setting_i (sesskey, "CloseOnExit", cfg->close_on_exit); write_setting_i(sesskey, "CloseOnExit", cfg->close_on_exit);
write_setting_i (sesskey, "WarnOnClose", !!cfg->warn_on_close); write_setting_i(sesskey, "WarnOnClose", !!cfg->warn_on_close);
write_setting_i (sesskey, "PingInterval", cfg->ping_interval / 60); /* minutes */ write_setting_i(sesskey, "PingInterval", cfg->ping_interval / 60); /* minutes */
write_setting_i (sesskey, "PingIntervalSecs", cfg->ping_interval % 60); /* seconds */ write_setting_i(sesskey, "PingIntervalSecs", cfg->ping_interval % 60); /* seconds */
write_setting_s (sesskey, "TerminalType", cfg->termtype); write_setting_s(sesskey, "TerminalType", cfg->termtype);
write_setting_s (sesskey, "TerminalSpeed", cfg->termspeed); write_setting_s(sesskey, "TerminalSpeed", cfg->termspeed);
{ {
char buf[2*sizeof(cfg->environmt)], *p, *q; char buf[2 * sizeof(cfg->environmt)], *p, *q;
p = buf; p = buf;
q = cfg->environmt; q = cfg->environmt;
while (*q) { while (*q) {
while (*q) { while (*q) {
int c = *q++; int c = *q++;
@ -66,143 +69,143 @@ void save_settings (char *section, int do_host, Config *cfg) {
q++; q++;
} }
*p = '\0'; *p = '\0';
write_setting_s (sesskey, "Environment", buf); write_setting_s(sesskey, "Environment", buf);
} }
write_setting_s (sesskey, "UserName", cfg->username); write_setting_s(sesskey, "UserName", cfg->username);
write_setting_s (sesskey, "LocalUserName", cfg->localusername); write_setting_s(sesskey, "LocalUserName", cfg->localusername);
write_setting_i (sesskey, "NoPTY", cfg->nopty); write_setting_i(sesskey, "NoPTY", cfg->nopty);
write_setting_i (sesskey, "Compression", cfg->compression); write_setting_i(sesskey, "Compression", cfg->compression);
write_setting_i (sesskey, "AgentFwd", cfg->agentfwd); write_setting_i(sesskey, "AgentFwd", cfg->agentfwd);
write_setting_s (sesskey, "Cipher", write_setting_s(sesskey, "Cipher",
cfg->cipher == CIPHER_BLOWFISH ? "blowfish" : cfg->cipher == CIPHER_BLOWFISH ? "blowfish" :
cfg->cipher == CIPHER_DES ? "des" : cfg->cipher == CIPHER_DES ? "des" :
cfg->cipher == CIPHER_AES ? "aes" : cfg->cipher == CIPHER_AES ? "aes" : "3des");
"3des"); write_setting_i(sesskey, "AuthTIS", cfg->try_tis_auth);
write_setting_i (sesskey, "AuthTIS", cfg->try_tis_auth); write_setting_i(sesskey, "SshProt", cfg->sshprot);
write_setting_i (sesskey, "SshProt", cfg->sshprot); write_setting_i(sesskey, "BuggyMAC", cfg->buggymac);
write_setting_i (sesskey, "BuggyMAC", cfg->buggymac); write_setting_s(sesskey, "PublicKeyFile", cfg->keyfile);
write_setting_s (sesskey, "PublicKeyFile", cfg->keyfile); write_setting_s(sesskey, "RemoteCommand", cfg->remote_cmd);
write_setting_s (sesskey, "RemoteCommand", cfg->remote_cmd); write_setting_i(sesskey, "RFCEnviron", cfg->rfc_environ);
write_setting_i (sesskey, "RFCEnviron", cfg->rfc_environ); write_setting_i(sesskey, "BackspaceIsDelete", cfg->bksp_is_delete);
write_setting_i (sesskey, "BackspaceIsDelete", cfg->bksp_is_delete); write_setting_i(sesskey, "RXVTHomeEnd", cfg->rxvt_homeend);
write_setting_i (sesskey, "RXVTHomeEnd", cfg->rxvt_homeend); write_setting_i(sesskey, "LinuxFunctionKeys", cfg->funky_type);
write_setting_i (sesskey, "LinuxFunctionKeys", cfg->funky_type); write_setting_i(sesskey, "NoApplicationKeys", cfg->no_applic_k);
write_setting_i (sesskey, "NoApplicationKeys", cfg->no_applic_k); write_setting_i(sesskey, "NoApplicationCursors", cfg->no_applic_c);
write_setting_i (sesskey, "NoApplicationCursors", cfg->no_applic_c); write_setting_i(sesskey, "ApplicationCursorKeys", cfg->app_cursor);
write_setting_i (sesskey, "ApplicationCursorKeys", cfg->app_cursor); write_setting_i(sesskey, "ApplicationKeypad", cfg->app_keypad);
write_setting_i (sesskey, "ApplicationKeypad", cfg->app_keypad); write_setting_i(sesskey, "NetHackKeypad", cfg->nethack_keypad);
write_setting_i (sesskey, "NetHackKeypad", cfg->nethack_keypad); write_setting_i(sesskey, "AltF4", cfg->alt_f4);
write_setting_i (sesskey, "AltF4", cfg->alt_f4); write_setting_i(sesskey, "AltSpace", cfg->alt_space);
write_setting_i (sesskey, "AltSpace", cfg->alt_space); write_setting_i(sesskey, "AltOnly", cfg->alt_only);
write_setting_i (sesskey, "AltOnly", cfg->alt_only); write_setting_i(sesskey, "ComposeKey", cfg->compose_key);
write_setting_i (sesskey, "ComposeKey", cfg->compose_key); write_setting_i(sesskey, "CtrlAltKeys", cfg->ctrlaltkeys);
write_setting_i (sesskey, "CtrlAltKeys", cfg->ctrlaltkeys); write_setting_i(sesskey, "LocalEcho", cfg->localecho);
write_setting_i (sesskey, "LocalEcho", cfg->localecho); write_setting_i(sesskey, "LocalEdit", cfg->localedit);
write_setting_i (sesskey, "LocalEdit", cfg->localedit); write_setting_s(sesskey, "Answerback", cfg->answerback);
write_setting_s (sesskey, "Answerback", cfg->answerback); write_setting_i(sesskey, "AlwaysOnTop", cfg->alwaysontop);
write_setting_i (sesskey, "AlwaysOnTop", cfg->alwaysontop); write_setting_i(sesskey, "HideMousePtr", cfg->hide_mouseptr);
write_setting_i (sesskey, "HideMousePtr", cfg->hide_mouseptr); write_setting_i(sesskey, "SunkenEdge", cfg->sunken_edge);
write_setting_i (sesskey, "SunkenEdge", cfg->sunken_edge); write_setting_i(sesskey, "CurType", cfg->cursor_type);
write_setting_i (sesskey, "CurType", cfg->cursor_type); write_setting_i(sesskey, "BlinkCur", cfg->blink_cur);
write_setting_i (sesskey, "BlinkCur", cfg->blink_cur); write_setting_i(sesskey, "Beep", cfg->beep);
write_setting_i (sesskey, "Beep", cfg->beep); write_setting_s(sesskey, "BellWaveFile", cfg->bell_wavefile);
write_setting_s (sesskey, "BellWaveFile", cfg->bell_wavefile); write_setting_i(sesskey, "BellOverload", cfg->bellovl);
write_setting_i (sesskey, "BellOverload", cfg->bellovl); write_setting_i(sesskey, "BellOverloadN", cfg->bellovl_n);
write_setting_i (sesskey, "BellOverloadN", cfg->bellovl_n); write_setting_i(sesskey, "BellOverloadT", cfg->bellovl_t);
write_setting_i (sesskey, "BellOverloadT", cfg->bellovl_t); write_setting_i(sesskey, "BellOverloadS", cfg->bellovl_s);
write_setting_i (sesskey, "BellOverloadS", cfg->bellovl_s); write_setting_i(sesskey, "ScrollbackLines", cfg->savelines);
write_setting_i (sesskey, "ScrollbackLines", cfg->savelines); write_setting_i(sesskey, "DECOriginMode", cfg->dec_om);
write_setting_i (sesskey, "DECOriginMode", cfg->dec_om); write_setting_i(sesskey, "AutoWrapMode", cfg->wrap_mode);
write_setting_i (sesskey, "AutoWrapMode", cfg->wrap_mode); write_setting_i(sesskey, "LFImpliesCR", cfg->lfhascr);
write_setting_i (sesskey, "LFImpliesCR", cfg->lfhascr); write_setting_i(sesskey, "WinNameAlways", cfg->win_name_always);
write_setting_i (sesskey, "WinNameAlways", cfg->win_name_always); write_setting_s(sesskey, "WinTitle", cfg->wintitle);
write_setting_s (sesskey, "WinTitle", cfg->wintitle); write_setting_i(sesskey, "TermWidth", cfg->width);
write_setting_i (sesskey, "TermWidth", cfg->width); write_setting_i(sesskey, "TermHeight", cfg->height);
write_setting_i (sesskey, "TermHeight", cfg->height); write_setting_s(sesskey, "Font", cfg->font);
write_setting_s (sesskey, "Font", cfg->font); write_setting_i(sesskey, "FontIsBold", cfg->fontisbold);
write_setting_i (sesskey, "FontIsBold", cfg->fontisbold); write_setting_i(sesskey, "FontCharSet", cfg->fontcharset);
write_setting_i (sesskey, "FontCharSet", cfg->fontcharset); write_setting_i(sesskey, "FontHeight", cfg->fontheight);
write_setting_i (sesskey, "FontHeight", cfg->fontheight); write_setting_i(sesskey, "FontVTMode", cfg->vtmode);
write_setting_i (sesskey, "FontVTMode", cfg->vtmode); write_setting_i(sesskey, "TryPalette", cfg->try_palette);
write_setting_i (sesskey, "TryPalette", cfg->try_palette); write_setting_i(sesskey, "BoldAsColour", cfg->bold_colour);
write_setting_i (sesskey, "BoldAsColour", cfg->bold_colour); for (i = 0; i < 22; i++) {
for (i=0; i<22; i++) {
char buf[20], buf2[30]; char buf[20], buf2[30];
sprintf(buf, "Colour%d", i); sprintf(buf, "Colour%d", i);
sprintf(buf2, "%d,%d,%d", cfg->colours[i][0], sprintf(buf2, "%d,%d,%d", cfg->colours[i][0],
cfg->colours[i][1], cfg->colours[i][2]); cfg->colours[i][1], cfg->colours[i][2]);
write_setting_s (sesskey, buf, buf2); write_setting_s(sesskey, buf, buf2);
} }
write_setting_i (sesskey, "RawCNP", cfg->rawcnp); write_setting_i(sesskey, "RawCNP", cfg->rawcnp);
write_setting_i (sesskey, "MouseIsXterm", cfg->mouse_is_xterm); write_setting_i(sesskey, "MouseIsXterm", cfg->mouse_is_xterm);
for (i=0; i<256; i+=32) { for (i = 0; i < 256; i += 32) {
char buf[20], buf2[256]; char buf[20], buf2[256];
int j; int j;
sprintf(buf, "Wordness%d", i); sprintf(buf, "Wordness%d", i);
*buf2 = '\0'; *buf2 = '\0';
for (j=i; j<i+32; j++) { for (j = i; j < i + 32; j++) {
sprintf(buf2+strlen(buf2), "%s%d", sprintf(buf2 + strlen(buf2), "%s%d",
(*buf2 ? "," : ""), cfg->wordness[j]); (*buf2 ? "," : ""), cfg->wordness[j]);
} }
write_setting_s (sesskey, buf, buf2); write_setting_s(sesskey, buf, buf2);
} }
write_setting_i (sesskey, "KoiWinXlat", cfg->xlat_enablekoiwin); write_setting_i(sesskey, "KoiWinXlat", cfg->xlat_enablekoiwin);
write_setting_i (sesskey, "88592Xlat", cfg->xlat_88592w1250); write_setting_i(sesskey, "88592Xlat", cfg->xlat_88592w1250);
write_setting_i (sesskey, "88592-CP852", cfg->xlat_88592cp852); write_setting_i(sesskey, "88592-CP852", cfg->xlat_88592cp852);
write_setting_i (sesskey, "CapsLockCyr", cfg->xlat_capslockcyr); write_setting_i(sesskey, "CapsLockCyr", cfg->xlat_capslockcyr);
write_setting_i (sesskey, "ScrollBar", cfg->scrollbar); write_setting_i(sesskey, "ScrollBar", cfg->scrollbar);
write_setting_i (sesskey, "ScrollOnKey", cfg->scroll_on_key); write_setting_i(sesskey, "ScrollOnKey", cfg->scroll_on_key);
write_setting_i (sesskey, "ScrollOnDisp", cfg->scroll_on_disp); write_setting_i(sesskey, "ScrollOnDisp", cfg->scroll_on_disp);
write_setting_i (sesskey, "LockSize", cfg->locksize); write_setting_i(sesskey, "LockSize", cfg->locksize);
write_setting_i (sesskey, "BCE", cfg->bce); write_setting_i(sesskey, "BCE", cfg->bce);
write_setting_i (sesskey, "BlinkText", cfg->blinktext); write_setting_i(sesskey, "BlinkText", cfg->blinktext);
write_setting_i (sesskey, "X11Forward", cfg->x11_forward); write_setting_i(sesskey, "X11Forward", cfg->x11_forward);
write_setting_s (sesskey, "X11Display", cfg->x11_display); write_setting_s(sesskey, "X11Display", cfg->x11_display);
close_settings_w(sesskey); close_settings_w(sesskey);
} }
void load_settings (char *section, int do_host, Config *cfg) { void load_settings(char *section, int do_host, Config * cfg)
{
int i; int i;
char prot[10]; char prot[10];
void *sesskey; void *sesskey;
sesskey = open_settings_r(section); sesskey = open_settings_r(section);
cfg->ssh_subsys = 0; /* FIXME: load this properly */ cfg->ssh_subsys = 0; /* FIXME: load this properly */
cfg->remote_cmd_ptr = cfg->remote_cmd; cfg->remote_cmd_ptr = cfg->remote_cmd;
gpps (sesskey, "HostName", "", cfg->host, sizeof(cfg->host)); gpps(sesskey, "HostName", "", cfg->host, sizeof(cfg->host));
gppi (sesskey, "PortNumber", default_port, &cfg->port); gppi(sesskey, "PortNumber", default_port, &cfg->port);
gpps (sesskey, "LogFileName", "putty.log", gpps(sesskey, "LogFileName", "putty.log",
cfg->logfilename, sizeof(cfg->logfilename)); cfg->logfilename, sizeof(cfg->logfilename));
gppi (sesskey, "LogType", 0, &cfg->logtype); gppi(sesskey, "LogType", 0, &cfg->logtype);
gppi (sesskey, "LogFileClash", LGXF_ASK, &cfg->logxfovr); gppi(sesskey, "LogFileClash", LGXF_ASK, &cfg->logxfovr);
gpps (sesskey, "Protocol", "default", prot, 10); gpps(sesskey, "Protocol", "default", prot, 10);
cfg->protocol = default_protocol; cfg->protocol = default_protocol;
for (i = 0; backends[i].name != NULL; i++) for (i = 0; backends[i].name != NULL; i++)
if (!strcmp(prot, backends[i].name)) { if (!strcmp(prot, backends[i].name)) {
cfg->protocol = backends[i].protocol; cfg->protocol = backends[i].protocol;
break; break;
} }
gppi (sesskey, "CloseOnExit", COE_NORMAL, &cfg->close_on_exit); gppi(sesskey, "CloseOnExit", COE_NORMAL, &cfg->close_on_exit);
gppi (sesskey, "WarnOnClose", 1, &cfg->warn_on_close); gppi(sesskey, "WarnOnClose", 1, &cfg->warn_on_close);
{ {
/* This is two values for backward compatibility with 0.50/0.51 */ /* This is two values for backward compatibility with 0.50/0.51 */
int pingmin, pingsec; int pingmin, pingsec;
gppi (sesskey, "PingInterval", 0, &pingmin); gppi(sesskey, "PingInterval", 0, &pingmin);
gppi (sesskey, "PingIntervalSecs", 0, &pingsec); gppi(sesskey, "PingIntervalSecs", 0, &pingsec);
cfg->ping_interval = pingmin*60 + pingsec; cfg->ping_interval = pingmin * 60 + pingsec;
} }
gpps (sesskey, "TerminalType", "xterm", cfg->termtype, gpps(sesskey, "TerminalType", "xterm", cfg->termtype,
sizeof(cfg->termtype)); sizeof(cfg->termtype));
gpps (sesskey, "TerminalSpeed", "38400,38400", cfg->termspeed, gpps(sesskey, "TerminalSpeed", "38400,38400", cfg->termspeed,
sizeof(cfg->termspeed)); sizeof(cfg->termspeed));
{ {
char buf[2*sizeof(cfg->environmt)], *p, *q; char buf[2 * sizeof(cfg->environmt)], *p, *q;
gpps (sesskey, "Environment", "", buf, sizeof(buf)); gpps(sesskey, "Environment", "", buf, sizeof(buf));
p = buf; p = buf;
q = cfg->environmt; q = cfg->environmt;
while (*p) { while (*p) {
@ -214,19 +217,21 @@ void load_settings (char *section, int do_host, Config *cfg) {
c = *p++; c = *p++;
*q++ = c; *q++ = c;
} }
if (*p == ',') p++; if (*p == ',')
p++;
*q++ = '\0'; *q++ = '\0';
} }
*q = '\0'; *q = '\0';
} }
gpps (sesskey, "UserName", "", cfg->username, sizeof(cfg->username)); gpps(sesskey, "UserName", "", cfg->username, sizeof(cfg->username));
gpps (sesskey, "LocalUserName", "", cfg->localusername, sizeof(cfg->localusername)); gpps(sesskey, "LocalUserName", "", cfg->localusername,
gppi (sesskey, "NoPTY", 0, &cfg->nopty); sizeof(cfg->localusername));
gppi (sesskey, "Compression", 0, &cfg->compression); gppi(sesskey, "NoPTY", 0, &cfg->nopty);
gppi (sesskey, "AgentFwd", 0, &cfg->agentfwd); gppi(sesskey, "Compression", 0, &cfg->compression);
gppi(sesskey, "AgentFwd", 0, &cfg->agentfwd);
{ {
char cipher[10]; char cipher[10];
gpps (sesskey, "Cipher", "3des", cipher, 10); gpps(sesskey, "Cipher", "3des", cipher, 10);
if (!strcmp(cipher, "blowfish")) if (!strcmp(cipher, "blowfish"))
cfg->cipher = CIPHER_BLOWFISH; cfg->cipher = CIPHER_BLOWFISH;
else if (!strcmp(cipher, "des")) else if (!strcmp(cipher, "des"))
@ -236,89 +241,90 @@ void load_settings (char *section, int do_host, Config *cfg) {
else else
cfg->cipher = CIPHER_3DES; cfg->cipher = CIPHER_3DES;
} }
gppi (sesskey, "SshProt", 1, &cfg->sshprot); gppi(sesskey, "SshProt", 1, &cfg->sshprot);
gppi (sesskey, "BuggyMAC", 0, &cfg->buggymac); gppi(sesskey, "BuggyMAC", 0, &cfg->buggymac);
gppi (sesskey, "AuthTIS", 0, &cfg->try_tis_auth); gppi(sesskey, "AuthTIS", 0, &cfg->try_tis_auth);
gpps (sesskey, "PublicKeyFile", "", cfg->keyfile, sizeof(cfg->keyfile)); gpps(sesskey, "PublicKeyFile", "", cfg->keyfile, sizeof(cfg->keyfile));
gpps (sesskey, "RemoteCommand", "", cfg->remote_cmd, gpps(sesskey, "RemoteCommand", "", cfg->remote_cmd,
sizeof(cfg->remote_cmd)); sizeof(cfg->remote_cmd));
gppi (sesskey, "RFCEnviron", 0, &cfg->rfc_environ); gppi(sesskey, "RFCEnviron", 0, &cfg->rfc_environ);
gppi (sesskey, "BackspaceIsDelete", 1, &cfg->bksp_is_delete); gppi(sesskey, "BackspaceIsDelete", 1, &cfg->bksp_is_delete);
gppi (sesskey, "RXVTHomeEnd", 0, &cfg->rxvt_homeend); gppi(sesskey, "RXVTHomeEnd", 0, &cfg->rxvt_homeend);
gppi (sesskey, "LinuxFunctionKeys", 0, &cfg->funky_type); gppi(sesskey, "LinuxFunctionKeys", 0, &cfg->funky_type);
gppi (sesskey, "NoApplicationKeys", 0, &cfg->no_applic_k); gppi(sesskey, "NoApplicationKeys", 0, &cfg->no_applic_k);
gppi (sesskey, "NoApplicationCursors", 0, &cfg->no_applic_c); gppi(sesskey, "NoApplicationCursors", 0, &cfg->no_applic_c);
gppi (sesskey, "ApplicationCursorKeys", 0, &cfg->app_cursor); gppi(sesskey, "ApplicationCursorKeys", 0, &cfg->app_cursor);
gppi (sesskey, "ApplicationKeypad", 0, &cfg->app_keypad); gppi(sesskey, "ApplicationKeypad", 0, &cfg->app_keypad);
gppi (sesskey, "NetHackKeypad", 0, &cfg->nethack_keypad); gppi(sesskey, "NetHackKeypad", 0, &cfg->nethack_keypad);
gppi (sesskey, "AltF4", 1, &cfg->alt_f4); gppi(sesskey, "AltF4", 1, &cfg->alt_f4);
gppi (sesskey, "AltSpace", 0, &cfg->alt_space); gppi(sesskey, "AltSpace", 0, &cfg->alt_space);
gppi (sesskey, "AltOnly", 0, &cfg->alt_only); gppi(sesskey, "AltOnly", 0, &cfg->alt_only);
gppi (sesskey, "ComposeKey", 0, &cfg->compose_key); gppi(sesskey, "ComposeKey", 0, &cfg->compose_key);
gppi (sesskey, "CtrlAltKeys", 1, &cfg->ctrlaltkeys); gppi(sesskey, "CtrlAltKeys", 1, &cfg->ctrlaltkeys);
gppi (sesskey, "LocalEcho", LD_BACKEND, &cfg->localecho); gppi(sesskey, "LocalEcho", LD_BACKEND, &cfg->localecho);
gppi (sesskey, "LocalEdit", LD_BACKEND, &cfg->localedit); gppi(sesskey, "LocalEdit", LD_BACKEND, &cfg->localedit);
gpps (sesskey, "Answerback", "PuTTY", cfg->answerback, sizeof(cfg->answerback)); gpps(sesskey, "Answerback", "PuTTY", cfg->answerback,
gppi (sesskey, "AlwaysOnTop", 0, &cfg->alwaysontop); sizeof(cfg->answerback));
gppi (sesskey, "HideMousePtr", 0, &cfg->hide_mouseptr); gppi(sesskey, "AlwaysOnTop", 0, &cfg->alwaysontop);
gppi (sesskey, "SunkenEdge", 0, &cfg->sunken_edge); gppi(sesskey, "HideMousePtr", 0, &cfg->hide_mouseptr);
gppi (sesskey, "CurType", 0, &cfg->cursor_type); gppi(sesskey, "SunkenEdge", 0, &cfg->sunken_edge);
gppi (sesskey, "BlinkCur", 0, &cfg->blink_cur); gppi(sesskey, "CurType", 0, &cfg->cursor_type);
gppi (sesskey, "Beep", 1, &cfg->beep); gppi(sesskey, "BlinkCur", 0, &cfg->blink_cur);
gpps (sesskey, "BellWaveFile", "", cfg->bell_wavefile, gppi(sesskey, "Beep", 1, &cfg->beep);
sizeof(cfg->bell_wavefile)); gpps(sesskey, "BellWaveFile", "", cfg->bell_wavefile,
gppi (sesskey, "BellOverload", 1, &cfg->bellovl); sizeof(cfg->bell_wavefile));
gppi (sesskey, "BellOverloadN", 5, &cfg->bellovl_n); gppi(sesskey, "BellOverload", 1, &cfg->bellovl);
gppi (sesskey, "BellOverloadT", 2000, &cfg->bellovl_t); gppi(sesskey, "BellOverloadN", 5, &cfg->bellovl_n);
gppi (sesskey, "BellOverloadS", 5000, &cfg->bellovl_s); gppi(sesskey, "BellOverloadT", 2000, &cfg->bellovl_t);
gppi (sesskey, "ScrollbackLines", 200, &cfg->savelines); gppi(sesskey, "BellOverloadS", 5000, &cfg->bellovl_s);
gppi (sesskey, "DECOriginMode", 0, &cfg->dec_om); gppi(sesskey, "ScrollbackLines", 200, &cfg->savelines);
gppi (sesskey, "AutoWrapMode", 1, &cfg->wrap_mode); gppi(sesskey, "DECOriginMode", 0, &cfg->dec_om);
gppi (sesskey, "LFImpliesCR", 0, &cfg->lfhascr); gppi(sesskey, "AutoWrapMode", 1, &cfg->wrap_mode);
gppi (sesskey, "WinNameAlways", 0, &cfg->win_name_always); gppi(sesskey, "LFImpliesCR", 0, &cfg->lfhascr);
gpps (sesskey, "WinTitle", "", cfg->wintitle, sizeof(cfg->wintitle)); gppi(sesskey, "WinNameAlways", 0, &cfg->win_name_always);
gppi (sesskey, "TermWidth", 80, &cfg->width); gpps(sesskey, "WinTitle", "", cfg->wintitle, sizeof(cfg->wintitle));
gppi (sesskey, "TermHeight", 24, &cfg->height); gppi(sesskey, "TermWidth", 80, &cfg->width);
gpps (sesskey, "Font", "Courier", cfg->font, sizeof(cfg->font)); gppi(sesskey, "TermHeight", 24, &cfg->height);
gppi (sesskey, "FontIsBold", 0, &cfg->fontisbold); gpps(sesskey, "Font", "Courier", cfg->font, sizeof(cfg->font));
gppi (sesskey, "FontCharSet", ANSI_CHARSET, &cfg->fontcharset); gppi(sesskey, "FontIsBold", 0, &cfg->fontisbold);
gppi (sesskey, "FontHeight", 10, &cfg->fontheight); gppi(sesskey, "FontCharSet", ANSI_CHARSET, &cfg->fontcharset);
gppi(sesskey, "FontHeight", 10, &cfg->fontheight);
if (cfg->fontheight < 0) { if (cfg->fontheight < 0) {
int oldh, newh; int oldh, newh;
HDC hdc = GetDC(NULL); HDC hdc = GetDC(NULL);
int logpix = GetDeviceCaps(hdc, LOGPIXELSY); int logpix = GetDeviceCaps(hdc, LOGPIXELSY);
ReleaseDC(NULL, hdc); ReleaseDC(NULL, hdc);
oldh = -cfg->fontheight; oldh = -cfg->fontheight;
newh = MulDiv(oldh, 72, logpix) + 1; newh = MulDiv(oldh, 72, logpix) + 1;
if (MulDiv(newh, logpix, 72) > oldh) if (MulDiv(newh, logpix, 72) > oldh)
newh--; newh--;
cfg->fontheight = newh; cfg->fontheight = newh;
} }
gppi (sesskey, "FontVTMode", VT_OEMANSI, (int *)&cfg->vtmode); gppi(sesskey, "FontVTMode", VT_OEMANSI, (int *) &cfg->vtmode);
gppi (sesskey, "TryPalette", 0, &cfg->try_palette); gppi(sesskey, "TryPalette", 0, &cfg->try_palette);
gppi (sesskey, "BoldAsColour", 1, &cfg->bold_colour); gppi(sesskey, "BoldAsColour", 1, &cfg->bold_colour);
for (i=0; i<22; i++) { for (i = 0; i < 22; i++) {
static char *defaults[] = { static char *defaults[] = {
"187,187,187", "255,255,255", "0,0,0", "85,85,85", "0,0,0", "187,187,187", "255,255,255", "0,0,0", "85,85,85", "0,0,0",
"0,255,0", "0,0,0", "85,85,85", "187,0,0", "255,85,85", "0,255,0", "0,0,0", "85,85,85", "187,0,0", "255,85,85",
"0,187,0", "85,255,85", "187,187,0", "255,255,85", "0,0,187", "0,187,0", "85,255,85", "187,187,0", "255,255,85", "0,0,187",
"85,85,255", "187,0,187", "255,85,255", "0,187,187", "85,85,255", "187,0,187", "255,85,255", "0,187,187",
"85,255,255", "187,187,187", "255,255,255" "85,255,255", "187,187,187", "255,255,255"
}; };
char buf[20], buf2[30]; char buf[20], buf2[30];
int c0, c1, c2; int c0, c1, c2;
sprintf(buf, "Colour%d", i); sprintf(buf, "Colour%d", i);
gpps (sesskey, buf, defaults[i], buf2, sizeof(buf2)); gpps(sesskey, buf, defaults[i], buf2, sizeof(buf2));
if(sscanf(buf2, "%d,%d,%d", &c0, &c1, &c2) == 3) { if (sscanf(buf2, "%d,%d,%d", &c0, &c1, &c2) == 3) {
cfg->colours[i][0] = c0; cfg->colours[i][0] = c0;
cfg->colours[i][1] = c1; cfg->colours[i][1] = c1;
cfg->colours[i][2] = c2; cfg->colours[i][2] = c2;
} }
} }
gppi (sesskey, "RawCNP", 0, &cfg->rawcnp); gppi(sesskey, "RawCNP", 0, &cfg->rawcnp);
gppi (sesskey, "MouseIsXterm", 0, &cfg->mouse_is_xterm); gppi(sesskey, "MouseIsXterm", 0, &cfg->mouse_is_xterm);
for (i=0; i<256; i+=32) { for (i = 0; i < 256; i += 32) {
static char *defaults[] = { static char *defaults[] = {
"0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0",
"0,1,2,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1", "0,1,2,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1,1",
@ -332,55 +338,60 @@ void load_settings (char *section, int do_host, Config *cfg) {
char buf[20], buf2[256], *p; char buf[20], buf2[256], *p;
int j; int j;
sprintf(buf, "Wordness%d", i); sprintf(buf, "Wordness%d", i);
gpps (sesskey, buf, defaults[i/32], buf2, sizeof(buf2)); gpps(sesskey, buf, defaults[i / 32], buf2, sizeof(buf2));
p = buf2; p = buf2;
for (j=i; j<i+32; j++) { for (j = i; j < i + 32; j++) {
char *q = p; char *q = p;
while (*p && *p != ',') p++; while (*p && *p != ',')
if (*p == ',') *p++ = '\0'; p++;
if (*p == ',')
*p++ = '\0';
cfg->wordness[j] = atoi(q); cfg->wordness[j] = atoi(q);
} }
} }
gppi (sesskey, "KoiWinXlat", 0, &cfg->xlat_enablekoiwin); gppi(sesskey, "KoiWinXlat", 0, &cfg->xlat_enablekoiwin);
gppi (sesskey, "88592Xlat", 0, &cfg->xlat_88592w1250); gppi(sesskey, "88592Xlat", 0, &cfg->xlat_88592w1250);
gppi (sesskey, "88592-CP852", 0, &cfg->xlat_88592cp852); gppi(sesskey, "88592-CP852", 0, &cfg->xlat_88592cp852);
gppi (sesskey, "CapsLockCyr", 0, &cfg->xlat_capslockcyr); gppi(sesskey, "CapsLockCyr", 0, &cfg->xlat_capslockcyr);
gppi (sesskey, "ScrollBar", 1, &cfg->scrollbar); gppi(sesskey, "ScrollBar", 1, &cfg->scrollbar);
gppi (sesskey, "ScrollOnKey", 0, &cfg->scroll_on_key); gppi(sesskey, "ScrollOnKey", 0, &cfg->scroll_on_key);
gppi (sesskey, "ScrollOnDisp", 1, &cfg->scroll_on_disp); gppi(sesskey, "ScrollOnDisp", 1, &cfg->scroll_on_disp);
gppi (sesskey, "LockSize", 0, &cfg->locksize); gppi(sesskey, "LockSize", 0, &cfg->locksize);
gppi (sesskey, "BCE", 0, &cfg->bce); gppi(sesskey, "BCE", 0, &cfg->bce);
gppi (sesskey, "BlinkText", 0, &cfg->blinktext); gppi(sesskey, "BlinkText", 0, &cfg->blinktext);
gppi (sesskey, "X11Forward", 0, &cfg->x11_forward); gppi(sesskey, "X11Forward", 0, &cfg->x11_forward);
gpps (sesskey, "X11Display", "localhost:0", cfg->x11_display, gpps(sesskey, "X11Display", "localhost:0", cfg->x11_display,
sizeof(cfg->x11_display)); sizeof(cfg->x11_display));
close_settings_r(sesskey); close_settings_r(sesskey);
} }
void do_defaults (char *session, Config *cfg) { void do_defaults(char *session, Config * cfg)
{
if (session) if (session)
load_settings (session, TRUE, cfg); load_settings(session, TRUE, cfg);
else else
load_settings ("Default Settings", FALSE, cfg); load_settings("Default Settings", FALSE, cfg);
} }
static int sessioncmp(const void *av, const void *bv) { static int sessioncmp(const void *av, const void *bv)
const char *a = *(const char *const *)av; {
const char *b = *(const char *const *)bv; const char *a = *(const char *const *) av;
const char *b = *(const char *const *) bv;
/* /*
* Alphabetical order, except that "Default Settings" is a * Alphabetical order, except that "Default Settings" is a
* special case and comes first. * special case and comes first.
*/ */
if (!strcmp(a, "Default Settings")) if (!strcmp(a, "Default Settings"))
return -1; /* a comes first */ return -1; /* a comes first */
if (!strcmp(b, "Default Settings")) if (!strcmp(b, "Default Settings"))
return +1; /* b comes first */ return +1; /* b comes first */
return strcmp(a, b); /* otherwise, compare normally */ return strcmp(a, b); /* otherwise, compare normally */
} }
void get_sesslist(int allocate) { void get_sesslist(int allocate)
{
static char otherbuf[2048]; static char otherbuf[2048];
static char *buffer; static char *buffer;
int buflen, bufsize, i; int buflen, bufsize, i;
@ -388,26 +399,26 @@ void get_sesslist(int allocate) {
void *handle; void *handle;
if (allocate) { if (allocate) {
if ((handle = enum_settings_start()) == NULL) if ((handle = enum_settings_start()) == NULL)
return; return;
buflen = bufsize = 0; buflen = bufsize = 0;
buffer = NULL; buffer = NULL;
do { do {
ret = enum_settings_next(handle, otherbuf, sizeof(otherbuf)); ret = enum_settings_next(handle, otherbuf, sizeof(otherbuf));
if (ret) { if (ret) {
int len = strlen(otherbuf)+1; int len = strlen(otherbuf) + 1;
if (bufsize < buflen+len) { if (bufsize < buflen + len) {
bufsize = buflen + len + 2048; bufsize = buflen + len + 2048;
buffer = srealloc(buffer, bufsize); buffer = srealloc(buffer, bufsize);
} }
strcpy(buffer+buflen, otherbuf); strcpy(buffer + buflen, otherbuf);
buflen += strlen(buffer+buflen)+1; buflen += strlen(buffer + buflen) + 1;
} }
} while (ret); } while (ret);
enum_settings_finish(handle); enum_settings_finish(handle);
buffer = srealloc(buffer, buflen+1); buffer = srealloc(buffer, buflen + 1);
buffer[buflen] = '\0'; buffer[buflen] = '\0';
/* /*
@ -419,26 +430,28 @@ void get_sesslist(int allocate) {
p = buffer; p = buffer;
nsessions = 1; /* "Default Settings" counts as one */ nsessions = 1; /* "Default Settings" counts as one */
while (*p) { while (*p) {
if (strcmp(p, "Default Settings")) if (strcmp(p, "Default Settings"))
nsessions++; nsessions++;
while (*p) p++; while (*p)
p++;
p++; p++;
} }
sessions = smalloc((nsessions+1) * sizeof(char *)); sessions = smalloc((nsessions + 1) * sizeof(char *));
sessions[0] = "Default Settings"; sessions[0] = "Default Settings";
p = buffer; p = buffer;
i = 1; i = 1;
while (*p) { while (*p) {
if (strcmp(p, "Default Settings")) if (strcmp(p, "Default Settings"))
sessions[i++] = p; sessions[i++] = p;
while (*p) p++; while (*p)
p++;
p++; p++;
} }
qsort(sessions, i, sizeof(char *), sessioncmp); qsort(sessions, i, sizeof(char *), sessioncmp);
} else { } else {
sfree (buffer); sfree(buffer);
sfree (sessions); sfree(sessions);
} }
} }

142
sftp.c
View File

@ -36,60 +36,70 @@ struct sftp_packet {
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
* SFTP packet construction functions. * SFTP packet construction functions.
*/ */
static void sftp_pkt_ensure(struct sftp_packet *pkt, int length) { static void sftp_pkt_ensure(struct sftp_packet *pkt, int length)
{
if (pkt->maxlen < length) { if (pkt->maxlen < length) {
pkt->maxlen = length + 256; pkt->maxlen = length + 256;
pkt->data = srealloc(pkt->data, pkt->maxlen); pkt->data = srealloc(pkt->data, pkt->maxlen);
} }
} }
static void sftp_pkt_adddata(struct sftp_packet *pkt, void *data, int len) { static void sftp_pkt_adddata(struct sftp_packet *pkt, void *data, int len)
{
pkt->length += len; pkt->length += len;
sftp_pkt_ensure(pkt, pkt->length); sftp_pkt_ensure(pkt, pkt->length);
memcpy(pkt->data+pkt->length-len, data, len); memcpy(pkt->data + pkt->length - len, data, len);
} }
static void sftp_pkt_addbyte(struct sftp_packet *pkt, unsigned char byte) { static void sftp_pkt_addbyte(struct sftp_packet *pkt, unsigned char byte)
{
sftp_pkt_adddata(pkt, &byte, 1); sftp_pkt_adddata(pkt, &byte, 1);
} }
static struct sftp_packet *sftp_pkt_init(int pkt_type) { static struct sftp_packet *sftp_pkt_init(int pkt_type)
{
struct sftp_packet *pkt; struct sftp_packet *pkt;
pkt = smalloc(sizeof(struct sftp_packet)); pkt = smalloc(sizeof(struct sftp_packet));
pkt->data = NULL; pkt->data = NULL;
pkt->savedpos = -1; pkt->savedpos = -1;
pkt->length = 0; pkt->length = 0;
pkt->maxlen = 0; pkt->maxlen = 0;
sftp_pkt_addbyte(pkt, (unsigned char)pkt_type); sftp_pkt_addbyte(pkt, (unsigned char) pkt_type);
return pkt; return pkt;
} }
static void sftp_pkt_addbool(struct sftp_packet *pkt, unsigned char value) { static void sftp_pkt_addbool(struct sftp_packet *pkt, unsigned char value)
{
sftp_pkt_adddata(pkt, &value, 1); sftp_pkt_adddata(pkt, &value, 1);
} }
static void sftp_pkt_adduint32(struct sftp_packet *pkt, unsigned long value) { static void sftp_pkt_adduint32(struct sftp_packet *pkt,
unsigned long value)
{
unsigned char x[4]; unsigned char x[4];
PUT_32BIT(x, value); PUT_32BIT(x, value);
sftp_pkt_adddata(pkt, x, 4); sftp_pkt_adddata(pkt, x, 4);
} }
static void sftp_pkt_adduint64(struct sftp_packet *pkt, uint64 value) { static void sftp_pkt_adduint64(struct sftp_packet *pkt, uint64 value)
{
unsigned char x[8]; unsigned char x[8];
PUT_32BIT(x, value.hi); PUT_32BIT(x, value.hi);
PUT_32BIT(x+4, value.lo); PUT_32BIT(x + 4, value.lo);
sftp_pkt_adddata(pkt, x, 8); sftp_pkt_adddata(pkt, x, 8);
} }
static void sftp_pkt_addstring_start(struct sftp_packet *pkt) { static void sftp_pkt_addstring_start(struct sftp_packet *pkt)
{
sftp_pkt_adduint32(pkt, 0); sftp_pkt_adduint32(pkt, 0);
pkt->savedpos = pkt->length; pkt->savedpos = pkt->length;
} }
static void sftp_pkt_addstring_str(struct sftp_packet *pkt, char *data) { static void sftp_pkt_addstring_str(struct sftp_packet *pkt, char *data)
{
sftp_pkt_adddata(pkt, data, strlen(data)); sftp_pkt_adddata(pkt, data, strlen(data));
PUT_32BIT(pkt->data + pkt->savedpos - 4, PUT_32BIT(pkt->data + pkt->savedpos - 4, pkt->length - pkt->savedpos);
pkt->length - pkt->savedpos);
} }
static void sftp_pkt_addstring_data(struct sftp_packet *pkt, static void sftp_pkt_addstring_data(struct sftp_packet *pkt,
char *data, int len) { char *data, int len)
{
sftp_pkt_adddata(pkt, data, len); sftp_pkt_adddata(pkt, data, len);
PUT_32BIT(pkt->data + pkt->savedpos - 4, PUT_32BIT(pkt->data + pkt->savedpos - 4, pkt->length - pkt->savedpos);
pkt->length - pkt->savedpos);
} }
static void sftp_pkt_addstring(struct sftp_packet *pkt, char *data) { static void sftp_pkt_addstring(struct sftp_packet *pkt, char *data)
{
sftp_pkt_addstring_start(pkt); sftp_pkt_addstring_start(pkt);
sftp_pkt_addstring_str(pkt, data); sftp_pkt_addstring_str(pkt, data);
} }
@ -98,35 +108,39 @@ static void sftp_pkt_addstring(struct sftp_packet *pkt, char *data) {
* SFTP packet decode functions. * SFTP packet decode functions.
*/ */
static unsigned char sftp_pkt_getbyte(struct sftp_packet *pkt) { static unsigned char sftp_pkt_getbyte(struct sftp_packet *pkt)
{
unsigned char value; unsigned char value;
if (pkt->length - pkt->savedpos < 1) if (pkt->length - pkt->savedpos < 1)
return 0; /* arrgh, no way to decline (FIXME?) */ return 0; /* arrgh, no way to decline (FIXME?) */
value = (unsigned char) pkt->data[pkt->savedpos]; value = (unsigned char) pkt->data[pkt->savedpos];
pkt->savedpos++; pkt->savedpos++;
return value; return value;
} }
static unsigned long sftp_pkt_getuint32(struct sftp_packet *pkt) { static unsigned long sftp_pkt_getuint32(struct sftp_packet *pkt)
{
unsigned long value; unsigned long value;
if (pkt->length - pkt->savedpos < 4) if (pkt->length - pkt->savedpos < 4)
return 0; /* arrgh, no way to decline (FIXME?) */ return 0; /* arrgh, no way to decline (FIXME?) */
value = GET_32BIT(pkt->data+pkt->savedpos); value = GET_32BIT(pkt->data + pkt->savedpos);
pkt->savedpos += 4; pkt->savedpos += 4;
return value; return value;
} }
static void sftp_pkt_getstring(struct sftp_packet *pkt, static void sftp_pkt_getstring(struct sftp_packet *pkt,
char **p, int *length) { char **p, int *length)
{
*p = NULL; *p = NULL;
if (pkt->length - pkt->savedpos < 4) if (pkt->length - pkt->savedpos < 4)
return; return;
*length = GET_32BIT(pkt->data+pkt->savedpos); *length = GET_32BIT(pkt->data + pkt->savedpos);
pkt->savedpos += 4; pkt->savedpos += 4;
if (pkt->length - pkt->savedpos < *length) if (pkt->length - pkt->savedpos < *length)
return; return;
*p = pkt->data+pkt->savedpos; *p = pkt->data + pkt->savedpos;
pkt->savedpos += *length; pkt->savedpos += *length;
} }
static struct fxp_attrs sftp_pkt_getattrs(struct sftp_packet *pkt) { static struct fxp_attrs sftp_pkt_getattrs(struct sftp_packet *pkt)
{
struct fxp_attrs ret; struct fxp_attrs ret;
ret.flags = sftp_pkt_getuint32(pkt); ret.flags = sftp_pkt_getuint32(pkt);
if (ret.flags & SSH_FILEXFER_ATTR_SIZE) { if (ret.flags & SSH_FILEXFER_ATTR_SIZE) {
@ -162,24 +176,27 @@ static struct fxp_attrs sftp_pkt_getattrs(struct sftp_packet *pkt) {
} }
return ret; return ret;
} }
static void sftp_pkt_free(struct sftp_packet *pkt) { static void sftp_pkt_free(struct sftp_packet *pkt)
if (pkt->data) sfree(pkt->data); {
if (pkt->data)
sfree(pkt->data);
sfree(pkt); sfree(pkt);
} }
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
* Send and receive packet functions. * Send and receive packet functions.
*/ */
int sftp_send(struct sftp_packet *pkt) { int sftp_send(struct sftp_packet *pkt)
{
int ret; int ret;
char x[4]; char x[4];
PUT_32BIT(x, pkt->length); PUT_32BIT(x, pkt->length);
ret = (sftp_senddata(x, 4) && ret = (sftp_senddata(x, 4) && sftp_senddata(pkt->data, pkt->length));
sftp_senddata(pkt->data, pkt->length));
sftp_pkt_free(pkt); sftp_pkt_free(pkt);
return ret; return ret;
} }
struct sftp_packet *sftp_recv(void) { struct sftp_packet *sftp_recv(void)
{
struct sftp_packet *pkt; struct sftp_packet *pkt;
char x[4]; char x[4];
@ -205,8 +222,9 @@ struct sftp_packet *sftp_recv(void) {
* String handling routines. * String handling routines.
*/ */
static char *mkstr(char *s, int len) { static char *mkstr(char *s, int len)
char *p = smalloc(len+1); {
char *p = smalloc(len + 1);
memcpy(p, s, len); memcpy(p, s, len);
p[len] = '\0'; p[len] = '\0';
return p; return p;
@ -224,7 +242,8 @@ static int fxp_errtype;
* SSH_FX_OK, 0 if SSH_FX_EOF, and -1 for anything else (error). * SSH_FX_OK, 0 if SSH_FX_EOF, and -1 for anything else (error).
* Also place the status into fxp_errtype. * Also place the status into fxp_errtype.
*/ */
static int fxp_got_status(struct sftp_packet *pktin) { static int fxp_got_status(struct sftp_packet *pktin)
{
static const char *const messages[] = { static const char *const messages[] = {
/* SSH_FX_OK. The only time we will display a _message_ for this /* SSH_FX_OK. The only time we will display a _message_ for this
* is if we were expecting something other than FXP_STATUS on * is if we were expecting something other than FXP_STATUS on
@ -246,8 +265,8 @@ static int fxp_got_status(struct sftp_packet *pktin) {
} else { } else {
fxp_errtype = sftp_pkt_getuint32(pktin); fxp_errtype = sftp_pkt_getuint32(pktin);
if (fxp_errtype < 0 || if (fxp_errtype < 0 ||
fxp_errtype >= sizeof(messages)/sizeof(*messages)) fxp_errtype >= sizeof(messages) / sizeof(*messages))
fxp_error_message = "unknown error code"; fxp_error_message = "unknown error code";
else else
fxp_error_message = messages[fxp_errtype]; fxp_error_message = messages[fxp_errtype];
} }
@ -260,23 +279,27 @@ static int fxp_got_status(struct sftp_packet *pktin) {
return -1; return -1;
} }
static void fxp_internal_error(char *msg) { static void fxp_internal_error(char *msg)
{
fxp_error_message = msg; fxp_error_message = msg;
fxp_errtype = -1; fxp_errtype = -1;
} }
const char *fxp_error(void) { const char *fxp_error(void)
{
return fxp_error_message; return fxp_error_message;
} }
int fxp_error_type(void) { int fxp_error_type(void)
{
return fxp_errtype; return fxp_errtype;
} }
/* /*
* Perform exchange of init/version packets. Return 0 on failure. * Perform exchange of init/version packets. Return 0 on failure.
*/ */
int fxp_init(void) { int fxp_init(void)
{
struct sftp_packet *pktout, *pktin; struct sftp_packet *pktout, *pktin;
int remotever; int remotever;
@ -295,7 +318,8 @@ int fxp_init(void) {
} }
remotever = sftp_pkt_getuint32(pktin); remotever = sftp_pkt_getuint32(pktin);
if (remotever > SFTP_PROTO_VERSION) { if (remotever > SFTP_PROTO_VERSION) {
fxp_internal_error("remote protocol is more advanced than we support"); fxp_internal_error
("remote protocol is more advanced than we support");
return 0; return 0;
} }
/* /*
@ -312,7 +336,8 @@ int fxp_init(void) {
/* /*
* Canonify a pathname. * Canonify a pathname.
*/ */
char *fxp_realpath(char *path) { char *fxp_realpath(char *path)
{
struct sftp_packet *pktin, *pktout; struct sftp_packet *pktin, *pktout;
int id; int id;
@ -354,7 +379,8 @@ char *fxp_realpath(char *path) {
/* /*
* Open a file. * Open a file.
*/ */
struct fxp_handle *fxp_open(char *path, int type) { struct fxp_handle *fxp_open(char *path, int type)
{
struct sftp_packet *pktin, *pktout; struct sftp_packet *pktin, *pktout;
int id; int id;
@ -394,7 +420,8 @@ struct fxp_handle *fxp_open(char *path, int type) {
/* /*
* Open a directory. * Open a directory.
*/ */
struct fxp_handle *fxp_opendir(char *path) { struct fxp_handle *fxp_opendir(char *path)
{
struct sftp_packet *pktin, *pktout; struct sftp_packet *pktin, *pktout;
int id; int id;
@ -432,7 +459,8 @@ struct fxp_handle *fxp_opendir(char *path) {
/* /*
* Close a file/dir. * Close a file/dir.
*/ */
void fxp_close(struct fxp_handle *handle) { void fxp_close(struct fxp_handle *handle)
{
struct sftp_packet *pktin, *pktout; struct sftp_packet *pktin, *pktout;
int id; int id;
@ -458,7 +486,9 @@ void fxp_close(struct fxp_handle *handle) {
* will return 0 on EOF, or return -1 and store SSH_FX_EOF in the * will return 0 on EOF, or return -1 and store SSH_FX_EOF in the
* error indicator. It might even depend on the SFTP server.) * error indicator. It might even depend on the SFTP server.)
*/ */
int fxp_read(struct fxp_handle *handle, char *buffer, uint64 offset, int len) { int fxp_read(struct fxp_handle *handle, char *buffer, uint64 offset,
int len)
{
struct sftp_packet *pktin, *pktout; struct sftp_packet *pktin, *pktout;
int id; int id;
@ -498,7 +528,8 @@ int fxp_read(struct fxp_handle *handle, char *buffer, uint64 offset, int len) {
/* /*
* Read from a directory. * Read from a directory.
*/ */
struct fxp_names *fxp_readdir(struct fxp_handle *handle) { struct fxp_names *fxp_readdir(struct fxp_handle *handle)
{
struct sftp_packet *pktin, *pktout; struct sftp_packet *pktin, *pktout;
int id; int id;
@ -538,7 +569,9 @@ struct fxp_names *fxp_readdir(struct fxp_handle *handle) {
/* /*
* Write to a file. Returns 0 on error, 1 on OK. * Write to a file. Returns 0 on error, 1 on OK.
*/ */
int fxp_write(struct fxp_handle *handle, char *buffer, uint64 offset, int len) { int fxp_write(struct fxp_handle *handle, char *buffer, uint64 offset,
int len)
{
struct sftp_packet *pktin, *pktout; struct sftp_packet *pktin, *pktout;
int id; int id;
@ -563,7 +596,8 @@ int fxp_write(struct fxp_handle *handle, char *buffer, uint64 offset, int len) {
/* /*
* Free up an fxp_names structure. * Free up an fxp_names structure.
*/ */
void fxp_free_names(struct fxp_names *names) { void fxp_free_names(struct fxp_names *names)
{
int i; int i;
for (i = 0; i < names->nnames; i++) { for (i = 0; i < names->nnames; i++) {

56
sftp.h
View File

@ -4,31 +4,31 @@
#include "int64.h" #include "int64.h"
#define SSH_FXP_INIT 1 /* 0x1 */ #define SSH_FXP_INIT 1 /* 0x1 */
#define SSH_FXP_VERSION 2 /* 0x2 */ #define SSH_FXP_VERSION 2 /* 0x2 */
#define SSH_FXP_OPEN 3 /* 0x3 */ #define SSH_FXP_OPEN 3 /* 0x3 */
#define SSH_FXP_CLOSE 4 /* 0x4 */ #define SSH_FXP_CLOSE 4 /* 0x4 */
#define SSH_FXP_READ 5 /* 0x5 */ #define SSH_FXP_READ 5 /* 0x5 */
#define SSH_FXP_WRITE 6 /* 0x6 */ #define SSH_FXP_WRITE 6 /* 0x6 */
#define SSH_FXP_LSTAT 7 /* 0x7 */ #define SSH_FXP_LSTAT 7 /* 0x7 */
#define SSH_FXP_FSTAT 8 /* 0x8 */ #define SSH_FXP_FSTAT 8 /* 0x8 */
#define SSH_FXP_SETSTAT 9 /* 0x9 */ #define SSH_FXP_SETSTAT 9 /* 0x9 */
#define SSH_FXP_FSETSTAT 10 /* 0xa */ #define SSH_FXP_FSETSTAT 10 /* 0xa */
#define SSH_FXP_OPENDIR 11 /* 0xb */ #define SSH_FXP_OPENDIR 11 /* 0xb */
#define SSH_FXP_READDIR 12 /* 0xc */ #define SSH_FXP_READDIR 12 /* 0xc */
#define SSH_FXP_REMOVE 13 /* 0xd */ #define SSH_FXP_REMOVE 13 /* 0xd */
#define SSH_FXP_MKDIR 14 /* 0xe */ #define SSH_FXP_MKDIR 14 /* 0xe */
#define SSH_FXP_RMDIR 15 /* 0xf */ #define SSH_FXP_RMDIR 15 /* 0xf */
#define SSH_FXP_REALPATH 16 /* 0x10 */ #define SSH_FXP_REALPATH 16 /* 0x10 */
#define SSH_FXP_STAT 17 /* 0x11 */ #define SSH_FXP_STAT 17 /* 0x11 */
#define SSH_FXP_RENAME 18 /* 0x12 */ #define SSH_FXP_RENAME 18 /* 0x12 */
#define SSH_FXP_STATUS 101 /* 0x65 */ #define SSH_FXP_STATUS 101 /* 0x65 */
#define SSH_FXP_HANDLE 102 /* 0x66 */ #define SSH_FXP_HANDLE 102 /* 0x66 */
#define SSH_FXP_DATA 103 /* 0x67 */ #define SSH_FXP_DATA 103 /* 0x67 */
#define SSH_FXP_NAME 104 /* 0x68 */ #define SSH_FXP_NAME 104 /* 0x68 */
#define SSH_FXP_ATTRS 105 /* 0x69 */ #define SSH_FXP_ATTRS 105 /* 0x69 */
#define SSH_FXP_EXTENDED 200 /* 0xc8 */ #define SSH_FXP_EXTENDED 200 /* 0xc8 */
#define SSH_FXP_EXTENDED_REPLY 201 /* 0xc9 */ #define SSH_FXP_EXTENDED_REPLY 201 /* 0xc9 */
#define SSH_FX_OK 0 #define SSH_FX_OK 0
#define SSH_FX_EOF 1 #define SSH_FX_EOF 1
@ -124,12 +124,14 @@ void fxp_close(struct fxp_handle *handle);
/* /*
* Read from a file. * Read from a file.
*/ */
int fxp_read(struct fxp_handle *handle, char *buffer, uint64 offset, int len); int fxp_read(struct fxp_handle *handle, char *buffer, uint64 offset,
int len);
/* /*
* Write to a file. Returns 0 on error, 1 on OK. * Write to a file. Returns 0 on error, 1 on OK.
*/ */
int fxp_write(struct fxp_handle *handle, char *buffer, uint64 offset, int len); int fxp_write(struct fxp_handle *handle, char *buffer, uint64 offset,
int len);
/* /*
* Read from a directory. * Read from a directory.

195
sizetip.c
View File

@ -14,75 +14,76 @@ static COLORREF tip_bg;
static COLORREF tip_text; static COLORREF tip_text;
static LRESULT CALLBACK SizeTipWndProc(HWND hWnd, UINT nMsg, static LRESULT CALLBACK SizeTipWndProc(HWND hWnd, UINT nMsg,
WPARAM wParam, LPARAM lParam) WPARAM wParam, LPARAM lParam)
{ {
switch (nMsg) { switch (nMsg) {
case WM_ERASEBKGND: case WM_ERASEBKGND:
return TRUE; return TRUE;
case WM_PAINT: case WM_PAINT:
{ {
HBRUSH hbr; HBRUSH hbr;
HGDIOBJ holdbr; HGDIOBJ holdbr;
RECT cr; RECT cr;
int wtlen; int wtlen;
LPTSTR wt; LPTSTR wt;
HDC hdc; HDC hdc;
PAINTSTRUCT ps; PAINTSTRUCT ps;
hdc = BeginPaint(hWnd, &ps); hdc = BeginPaint(hWnd, &ps);
SelectObject(hdc, tip_font); SelectObject(hdc, tip_font);
SelectObject(hdc, GetStockObject(BLACK_PEN)); SelectObject(hdc, GetStockObject(BLACK_PEN));
hbr = CreateSolidBrush(tip_bg); hbr = CreateSolidBrush(tip_bg);
holdbr = SelectObject(hdc, hbr); holdbr = SelectObject(hdc, hbr);
GetClientRect(hWnd, &cr); GetClientRect(hWnd, &cr);
Rectangle(hdc, cr.left, cr.top, cr.right, cr.bottom); Rectangle(hdc, cr.left, cr.top, cr.right, cr.bottom);
wtlen = GetWindowTextLength(hWnd); wtlen = GetWindowTextLength(hWnd);
wt = (LPTSTR)smalloc((wtlen+1)*sizeof(TCHAR)); wt = (LPTSTR) smalloc((wtlen + 1) * sizeof(TCHAR));
GetWindowText(hWnd, wt, wtlen+1); GetWindowText(hWnd, wt, wtlen + 1);
SetTextColor(hdc, tip_text); SetTextColor(hdc, tip_text);
SetBkColor(hdc, tip_bg); SetBkColor(hdc, tip_bg);
TextOut(hdc, cr.left+3, cr.top+3, wt, wtlen); TextOut(hdc, cr.left + 3, cr.top + 3, wt, wtlen);
sfree(wt); sfree(wt);
SelectObject(hdc, holdbr); SelectObject(hdc, holdbr);
DeleteObject(hbr); DeleteObject(hbr);
EndPaint(hWnd, &ps); EndPaint(hWnd, &ps);
} }
return 0; return 0;
case WM_NCHITTEST: case WM_NCHITTEST:
return HTTRANSPARENT; return HTTRANSPARENT;
case WM_DESTROY: case WM_DESTROY:
DeleteObject(tip_font); DeleteObject(tip_font);
tip_font = NULL; tip_font = NULL;
break; break;
case WM_SETTEXT: case WM_SETTEXT:
{ {
LPCTSTR str = (LPCTSTR)lParam; LPCTSTR str = (LPCTSTR) lParam;
SIZE sz; SIZE sz;
HDC hdc = CreateCompatibleDC(NULL); HDC hdc = CreateCompatibleDC(NULL);
SelectObject(hdc, tip_font); SelectObject(hdc, tip_font);
GetTextExtentPoint32(hdc, str, _tcslen(str), &sz); GetTextExtentPoint32(hdc, str, _tcslen(str), &sz);
SetWindowPos(hWnd, NULL, 0, 0, sz.cx+6, sz.cy+6, SWP_NOZORDER|SWP_NOMOVE|SWP_NOACTIVATE); SetWindowPos(hWnd, NULL, 0, 0, sz.cx + 6, sz.cy + 6,
InvalidateRect(hWnd, NULL, FALSE); SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
InvalidateRect(hWnd, NULL, FALSE);
DeleteDC(hdc); DeleteDC(hdc);
} }
break; break;
} }
return DefWindowProc(hWnd, nMsg, wParam, lParam); return DefWindowProc(hWnd, nMsg, wParam, lParam);
@ -95,46 +96,47 @@ void UpdateSizeTip(HWND src, int cx, int cy)
{ {
TCHAR str[32]; TCHAR str[32];
if (!tip_enabled) return; if (!tip_enabled)
return;
if (!tip_wnd) { if (!tip_wnd) {
NONCLIENTMETRICS nci; NONCLIENTMETRICS nci;
/* First make sure the window class is registered */ /* First make sure the window class is registered */
if (!tip_class) { if (!tip_class) {
WNDCLASS wc; WNDCLASS wc;
wc.style = CS_HREDRAW|CS_VREDRAW; wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = SizeTipWndProc; wc.lpfnWndProc = SizeTipWndProc;
wc.cbClsExtra = 0; wc.cbClsExtra = 0;
wc.cbWndExtra = 0; wc.cbWndExtra = 0;
wc.hInstance = hinst; wc.hInstance = hinst;
wc.hIcon = NULL; wc.hIcon = NULL;
wc.hCursor = NULL; wc.hCursor = NULL;
wc.hbrBackground = NULL; wc.hbrBackground = NULL;
wc.lpszMenuName = NULL; wc.lpszMenuName = NULL;
wc.lpszClassName = "SizeTipClass"; wc.lpszClassName = "SizeTipClass";
tip_class = RegisterClass(&wc);
}
tip_class = RegisterClass(&wc);
}
#if 0 #if 0
/* Default values based on Windows Standard color scheme */ /* Default values based on Windows Standard color scheme */
tip_font = GetStockObject(SYSTEM_FONT); tip_font = GetStockObject(SYSTEM_FONT);
tip_bg = RGB(255, 255, 225); tip_bg = RGB(255, 255, 225);
tip_text = RGB(0, 0, 0); tip_text = RGB(0, 0, 0);
#endif #endif
/* Prepare other GDI objects and drawing info */ /* Prepare other GDI objects and drawing info */
tip_bg = GetSysColor(COLOR_INFOBK); tip_bg = GetSysColor(COLOR_INFOBK);
tip_text = GetSysColor(COLOR_INFOTEXT); tip_text = GetSysColor(COLOR_INFOTEXT);
memset(&nci, 0, sizeof(NONCLIENTMETRICS)); memset(&nci, 0, sizeof(NONCLIENTMETRICS));
nci.cbSize = sizeof(NONCLIENTMETRICS); nci.cbSize = sizeof(NONCLIENTMETRICS);
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &nci, 0); SystemParametersInfo(SPI_GETNONCLIENTMETRICS,
tip_font = CreateFontIndirect(&nci.lfStatusFont); sizeof(NONCLIENTMETRICS), &nci, 0);
tip_font = CreateFontIndirect(&nci.lfStatusFont);
} }
/* Generate the tip text */ /* Generate the tip text */
@ -142,46 +144,49 @@ void UpdateSizeTip(HWND src, int cx, int cy)
sprintf(str, "%dx%d", cx, cy); sprintf(str, "%dx%d", cx, cy);
if (!tip_wnd) { if (!tip_wnd) {
HDC hdc; HDC hdc;
SIZE sz; SIZE sz;
RECT wr; RECT wr;
int ix, iy; int ix, iy;
/* calculate the tip's size */ /* calculate the tip's size */
hdc = CreateCompatibleDC(NULL); hdc = CreateCompatibleDC(NULL);
GetTextExtentPoint32(hdc, str, _tcslen(str), &sz); GetTextExtentPoint32(hdc, str, _tcslen(str), &sz);
DeleteDC(hdc); DeleteDC(hdc);
GetWindowRect(src, &wr); GetWindowRect(src, &wr);
ix = wr.left; ix = wr.left;
if (ix<16) ix = 16; if (ix < 16)
ix = 16;
iy = wr.top - sz.cy; iy = wr.top - sz.cy;
if (iy<16) iy = 16; if (iy < 16)
iy = 16;
/* Create the tip window */ /* Create the tip window */
tip_wnd = CreateWindowEx(WS_EX_TOOLWINDOW|WS_EX_TOPMOST, MAKEINTRESOURCE(tip_class), str, WS_POPUP, tip_wnd =
ix, iy, sz.cx, sz.cy, CreateWindowEx(WS_EX_TOOLWINDOW | WS_EX_TOPMOST,
NULL, NULL, hinst, NULL); MAKEINTRESOURCE(tip_class), str, WS_POPUP, ix,
iy, sz.cx, sz.cy, NULL, NULL, hinst, NULL);
ShowWindow(tip_wnd, SW_SHOWNOACTIVATE); ShowWindow(tip_wnd, SW_SHOWNOACTIVATE);
} else { } else {
/* Tip already exists, just set the text */ /* Tip already exists, just set the text */
SetWindowText(tip_wnd, str); SetWindowText(tip_wnd, str);
} }
} }
void EnableSizeTip(int bEnable) void EnableSizeTip(int bEnable)
{ {
if (tip_wnd && !bEnable) { if (tip_wnd && !bEnable) {
DestroyWindow(tip_wnd); DestroyWindow(tip_wnd);
tip_wnd = NULL; tip_wnd = NULL;
} }
tip_enabled = bEnable; tip_enabled = bEnable;

3815
ssh.c

File diff suppressed because it is too large Load Diff

106
ssh.h
View File

@ -76,7 +76,7 @@ struct MD5Context {
void MD5Init(struct MD5Context *context); void MD5Init(struct MD5Context *context);
void MD5Update(struct MD5Context *context, unsigned char const *buf, void MD5Update(struct MD5Context *context, unsigned char const *buf,
unsigned len); unsigned len);
void MD5Final(unsigned char digest[16], struct MD5Context *context); void MD5Final(unsigned char digest[16], struct MD5Context *context);
typedef struct { typedef struct {
@ -86,25 +86,25 @@ typedef struct {
uint32 lenhi, lenlo; uint32 lenhi, lenlo;
} SHA_State; } SHA_State;
void SHA_Init(SHA_State *s); void SHA_Init(SHA_State * s);
void SHA_Bytes(SHA_State *s, void *p, int len); void SHA_Bytes(SHA_State * s, void *p, int len);
void SHA_Final(SHA_State *s, unsigned char *output); void SHA_Final(SHA_State * s, unsigned char *output);
void SHA_Simple(void *p, int len, unsigned char *output); void SHA_Simple(void *p, int len, unsigned char *output);
struct ssh_cipher { struct ssh_cipher {
void (*sesskey)(unsigned char *key); /* for ssh 1 */ void (*sesskey) (unsigned char *key); /* for ssh 1 */
void (*encrypt)(unsigned char *blk, int len); void (*encrypt) (unsigned char *blk, int len);
void (*decrypt)(unsigned char *blk, int len); void (*decrypt) (unsigned char *blk, int len);
int blksize; int blksize;
}; };
struct ssh2_cipher { struct ssh2_cipher {
void (*setcsiv)(unsigned char *key); /* for ssh 2 */ void (*setcsiv) (unsigned char *key); /* for ssh 2 */
void (*setcskey)(unsigned char *key); /* for ssh 2 */ void (*setcskey) (unsigned char *key); /* for ssh 2 */
void (*setsciv)(unsigned char *key); /* for ssh 2 */ void (*setsciv) (unsigned char *key); /* for ssh 2 */
void (*setsckey)(unsigned char *key); /* for ssh 2 */ void (*setsckey) (unsigned char *key); /* for ssh 2 */
void (*encrypt)(unsigned char *blk, int len); void (*encrypt) (unsigned char *blk, int len);
void (*decrypt)(unsigned char *blk, int len); void (*decrypt) (unsigned char *blk, int len);
char *name; char *name;
int blksize; int blksize;
int keylen; int keylen;
@ -116,10 +116,10 @@ struct ssh2_ciphers {
}; };
struct ssh_mac { struct ssh_mac {
void (*setcskey)(unsigned char *key); void (*setcskey) (unsigned char *key);
void (*setsckey)(unsigned char *key); void (*setsckey) (unsigned char *key);
void (*generate)(unsigned char *blk, int len, unsigned long seq); void (*generate) (unsigned char *blk, int len, unsigned long seq);
int (*verify)(unsigned char *blk, int len, unsigned long seq); int (*verify) (unsigned char *blk, int len, unsigned long seq);
char *name; char *name;
int len; int len;
}; };
@ -136,32 +136,33 @@ struct ssh_kex {
}; };
struct ssh_signkey { struct ssh_signkey {
void *(*newkey)(char *data, int len); void *(*newkey) (char *data, int len);
void (*freekey)(void *key); void (*freekey) (void *key);
char *(*fmtkey)(void *key); char *(*fmtkey) (void *key);
unsigned char *(*public_blob)(void *key, int *len); unsigned char *(*public_blob) (void *key, int *len);
unsigned char *(*private_blob)(void *key, int *len); unsigned char *(*private_blob) (void *key, int *len);
void *(*createkey)(unsigned char *pub_blob, int pub_len, void *(*createkey) (unsigned char *pub_blob, int pub_len,
unsigned char *priv_blob, int priv_len); unsigned char *priv_blob, int priv_len);
void *(*openssh_createkey)(unsigned char **blob, int *len); void *(*openssh_createkey) (unsigned char **blob, int *len);
int (*openssh_fmtkey)(void *key, unsigned char *blob, int len); int (*openssh_fmtkey) (void *key, unsigned char *blob, int len);
char *(*fingerprint)(void *key); char *(*fingerprint) (void *key);
int (*verifysig)(void *key, char *sig, int siglen, int (*verifysig) (void *key, char *sig, int siglen,
char *data, int datalen); char *data, int datalen);
unsigned char *(*sign)(void *key, char *data, int datalen, int *siglen); unsigned char *(*sign) (void *key, char *data, int datalen,
int *siglen);
char *name; char *name;
char *keytype; /* for host key cache */ char *keytype; /* for host key cache */
}; };
struct ssh_compress { struct ssh_compress {
char *name; char *name;
void (*compress_init)(void); void (*compress_init) (void);
int (*compress)(unsigned char *block, int len, int (*compress) (unsigned char *block, int len,
unsigned char **outblock, int *outlen); unsigned char **outblock, int *outlen);
void (*decompress_init)(void); void (*decompress_init) (void);
int (*decompress)(unsigned char *block, int len, int (*decompress) (unsigned char *block, int len,
unsigned char **outblock, int *outlen); unsigned char **outblock, int *outlen);
int (*disable_compression)(void); int (*disable_compression) (void);
}; };
struct ssh2_userkey { struct ssh2_userkey {
@ -190,14 +191,14 @@ extern const struct ssh_mac ssh_sha1_buggy;
extern char sshver[]; extern char sshver[];
#ifndef MSCRYPTOAPI #ifndef MSCRYPTOAPI
void SHATransform(word32 *digest, word32 *data); void SHATransform(word32 * digest, word32 * data);
#endif #endif
int random_byte(void); int random_byte(void);
void random_add_noise(void *noise, int length); void random_add_noise(void *noise, int length);
void random_add_heavynoise(void *noise, int length); void random_add_heavynoise(void *noise, int length);
void logevent (char *); void logevent(char *);
Bignum copybn(Bignum b); Bignum copybn(Bignum b);
Bignum bn_power_2(int n); Bignum bn_power_2(int n);
@ -209,7 +210,7 @@ Bignum modmul(Bignum a, Bignum b, Bignum mod);
void decbn(Bignum n); void decbn(Bignum n);
extern Bignum Zero, One; extern Bignum Zero, One;
Bignum bignum_from_bytes(unsigned char *data, int nbytes); Bignum bignum_from_bytes(unsigned char *data, int nbytes);
int ssh1_read_bignum(unsigned char *data, Bignum *result); int ssh1_read_bignum(unsigned char *data, Bignum * result);
int bignum_bitcount(Bignum bn); int bignum_bitcount(Bignum bn);
int ssh1_bignum_length(Bignum bn); int ssh1_bignum_length(Bignum bn);
int ssh2_bignum_length(Bignum bn); int ssh2_bignum_length(Bignum bn);
@ -246,24 +247,29 @@ extern struct ssh2_userkey ssh2_wrong_passphrase;
int ssh2_userkey_encrypted(char *filename, char **comment); int ssh2_userkey_encrypted(char *filename, char **comment);
struct ssh2_userkey *ssh2_load_userkey(char *filename, char *passphrase); struct ssh2_userkey *ssh2_load_userkey(char *filename, char *passphrase);
char *ssh2_userkey_loadpub(char *filename, char **algorithm, int *pub_blob_len); char *ssh2_userkey_loadpub(char *filename, char **algorithm,
int ssh2_save_userkey(char *filename, struct ssh2_userkey *key, char *passphrase); int *pub_blob_len);
int ssh2_save_userkey(char *filename, struct ssh2_userkey *key,
char *passphrase);
int keyfile_version(char *filename); int keyfile_version(char *filename);
void des3_decrypt_pubkey(unsigned char *key, unsigned char *blk, int len); void des3_decrypt_pubkey(unsigned char *key, unsigned char *blk, int len);
void des3_encrypt_pubkey(unsigned char *key, unsigned char *blk, int len); void des3_encrypt_pubkey(unsigned char *key, unsigned char *blk, int len);
void aes256_encrypt_pubkey(unsigned char *key, unsigned char *blk, int len); void aes256_encrypt_pubkey(unsigned char *key, unsigned char *blk,
void aes256_decrypt_pubkey(unsigned char *key, unsigned char *blk, int len); int len);
void aes256_decrypt_pubkey(unsigned char *key, unsigned char *blk,
int len);
/* /*
* For progress updates in the key generation utility. * For progress updates in the key generation utility.
*/ */
typedef void (*progfn_t)(void *param, int phase, int progress); typedef void (*progfn_t) (void *param, int phase, int progress);
int rsa_generate(struct RSAKey *key, int bits, progfn_t pfn, void *pfnparam); int rsa_generate(struct RSAKey *key, int bits, progfn_t pfn,
Bignum primegen(int bits, int modulus, int residue, void *pfnparam);
int phase, progfn_t pfn, void *pfnparam); Bignum primegen(int bits, int modulus, int residue, int phase,
progfn_t pfn, void *pfnparam);
/* /*
* zlib compression. * zlib compression.
@ -284,7 +290,7 @@ int zlib_decompress_block(unsigned char *block, int len,
#define SSH1_AGENT_RSA_RESPONSE 4 #define SSH1_AGENT_RSA_RESPONSE 4
#define SSH1_AGENTC_ADD_RSA_IDENTITY 7 #define SSH1_AGENTC_ADD_RSA_IDENTITY 7
#define SSH1_AGENTC_REMOVE_RSA_IDENTITY 8 #define SSH1_AGENTC_REMOVE_RSA_IDENTITY 8
#define SSH1_AGENTC_REMOVE_ALL_RSA_IDENTITIES 9 /* openssh private? */ #define SSH1_AGENTC_REMOVE_ALL_RSA_IDENTITIES 9 /* openssh private? */
/* /*
* Messages common to SSH1 and OpenSSH's SSH2. * Messages common to SSH1 and OpenSSH's SSH2.

331
sshaes.c
View File

@ -53,10 +53,10 @@
typedef struct AESContext AESContext; typedef struct AESContext AESContext;
struct AESContext { struct AESContext {
word32 keysched[(MAX_NR+1) * MAX_NB]; word32 keysched[(MAX_NR + 1) * MAX_NB];
word32 invkeysched[(MAX_NR+1) * MAX_NB]; word32 invkeysched[(MAX_NR + 1) * MAX_NB];
void (*encrypt)(AESContext *ctx, word32 *block); void (*encrypt) (AESContext * ctx, word32 * block);
void (*decrypt)(AESContext *ctx, word32 *block); void (*decrypt) (AESContext * ctx, word32 * block);
word32 iv[MAX_NB]; word32 iv[MAX_NB];
int Nb, Nr; int Nb, Nr;
}; };
@ -96,59 +96,115 @@ static const word32 D0[256], D1[256], D2[256], D3[256];
* Core encrypt routines, expecting word32 inputs read big-endian * Core encrypt routines, expecting word32 inputs read big-endian
* from the byte-oriented input stream. * from the byte-oriented input stream.
*/ */
static void aes_encrypt_nb_4(AESContext *ctx, word32 *block) { static void aes_encrypt_nb_4(AESContext * ctx, word32 * block)
{
int i; int i;
static const int C1 = 1, C2 = 2, C3 = 3, Nb = 4; static const int C1 = 1, C2 = 2, C3 = 3, Nb = 4;
word32 *keysched = ctx->keysched; word32 *keysched = ctx->keysched;
word32 newstate[4]; word32 newstate[4];
for (i = 0; i < ctx->Nr-1; i++) { for (i = 0; i < ctx->Nr - 1; i++) {
ADD_ROUND_KEY_4; ADD_ROUND_KEY_4;
MAKEWORD(0); MAKEWORD(1); MAKEWORD(2); MAKEWORD(3); MAKEWORD(0);
MOVEWORD(0); MOVEWORD(1); MOVEWORD(2); MOVEWORD(3); MAKEWORD(1);
MAKEWORD(2);
MAKEWORD(3);
MOVEWORD(0);
MOVEWORD(1);
MOVEWORD(2);
MOVEWORD(3);
} }
ADD_ROUND_KEY_4; ADD_ROUND_KEY_4;
LASTWORD(0); LASTWORD(1); LASTWORD(2); LASTWORD(3); LASTWORD(0);
MOVEWORD(0); MOVEWORD(1); MOVEWORD(2); MOVEWORD(3); LASTWORD(1);
LASTWORD(2);
LASTWORD(3);
MOVEWORD(0);
MOVEWORD(1);
MOVEWORD(2);
MOVEWORD(3);
ADD_ROUND_KEY_4; ADD_ROUND_KEY_4;
} }
static void aes_encrypt_nb_6(AESContext *ctx, word32 *block) { static void aes_encrypt_nb_6(AESContext * ctx, word32 * block)
{
int i; int i;
static const int C1 = 1, C2 = 2, C3 = 3, Nb = 6; static const int C1 = 1, C2 = 2, C3 = 3, Nb = 6;
word32 *keysched = ctx->keysched; word32 *keysched = ctx->keysched;
word32 newstate[6]; word32 newstate[6];
for (i = 0; i < ctx->Nr-1; i++) { for (i = 0; i < ctx->Nr - 1; i++) {
ADD_ROUND_KEY_6; ADD_ROUND_KEY_6;
MAKEWORD(0); MAKEWORD(1); MAKEWORD(2); MAKEWORD(0);
MAKEWORD(3); MAKEWORD(4); MAKEWORD(5); MAKEWORD(1);
MOVEWORD(0); MOVEWORD(1); MOVEWORD(2); MAKEWORD(2);
MOVEWORD(3); MOVEWORD(4); MOVEWORD(5); MAKEWORD(3);
MAKEWORD(4);
MAKEWORD(5);
MOVEWORD(0);
MOVEWORD(1);
MOVEWORD(2);
MOVEWORD(3);
MOVEWORD(4);
MOVEWORD(5);
} }
ADD_ROUND_KEY_6; ADD_ROUND_KEY_6;
LASTWORD(0); LASTWORD(1); LASTWORD(2); LASTWORD(0);
LASTWORD(3); LASTWORD(4); LASTWORD(5); LASTWORD(1);
MOVEWORD(0); MOVEWORD(1); MOVEWORD(2); LASTWORD(2);
MOVEWORD(3); MOVEWORD(4); MOVEWORD(5); LASTWORD(3);
LASTWORD(4);
LASTWORD(5);
MOVEWORD(0);
MOVEWORD(1);
MOVEWORD(2);
MOVEWORD(3);
MOVEWORD(4);
MOVEWORD(5);
ADD_ROUND_KEY_6; ADD_ROUND_KEY_6;
} }
static void aes_encrypt_nb_8(AESContext *ctx, word32 *block) { static void aes_encrypt_nb_8(AESContext * ctx, word32 * block)
{
int i; int i;
static const int C1 = 1, C2 = 3, C3 = 4, Nb = 8; static const int C1 = 1, C2 = 3, C3 = 4, Nb = 8;
word32 *keysched = ctx->keysched; word32 *keysched = ctx->keysched;
word32 newstate[8]; word32 newstate[8];
for (i = 0; i < ctx->Nr-1; i++) { for (i = 0; i < ctx->Nr - 1; i++) {
ADD_ROUND_KEY_8; ADD_ROUND_KEY_8;
MAKEWORD(0); MAKEWORD(1); MAKEWORD(2); MAKEWORD(3); MAKEWORD(0);
MAKEWORD(4); MAKEWORD(5); MAKEWORD(6); MAKEWORD(7); MAKEWORD(1);
MOVEWORD(0); MOVEWORD(1); MOVEWORD(2); MOVEWORD(3); MAKEWORD(2);
MOVEWORD(4); MOVEWORD(5); MOVEWORD(6); MOVEWORD(7); MAKEWORD(3);
MAKEWORD(4);
MAKEWORD(5);
MAKEWORD(6);
MAKEWORD(7);
MOVEWORD(0);
MOVEWORD(1);
MOVEWORD(2);
MOVEWORD(3);
MOVEWORD(4);
MOVEWORD(5);
MOVEWORD(6);
MOVEWORD(7);
} }
ADD_ROUND_KEY_8; ADD_ROUND_KEY_8;
LASTWORD(0); LASTWORD(1); LASTWORD(2); LASTWORD(3); LASTWORD(0);
LASTWORD(4); LASTWORD(5); LASTWORD(6); LASTWORD(7); LASTWORD(1);
MOVEWORD(0); MOVEWORD(1); MOVEWORD(2); MOVEWORD(3); LASTWORD(2);
MOVEWORD(4); MOVEWORD(5); MOVEWORD(6); MOVEWORD(7); LASTWORD(3);
LASTWORD(4);
LASTWORD(5);
LASTWORD(6);
LASTWORD(7);
MOVEWORD(0);
MOVEWORD(1);
MOVEWORD(2);
MOVEWORD(3);
MOVEWORD(4);
MOVEWORD(5);
MOVEWORD(6);
MOVEWORD(7);
ADD_ROUND_KEY_8; ADD_ROUND_KEY_8;
} }
#undef MAKEWORD #undef MAKEWORD
#undef LASTWORD #undef LASTWORD
@ -169,59 +225,115 @@ static void aes_encrypt_nb_8(AESContext *ctx, word32 *block) {
* Core decrypt routines, expecting word32 inputs read big-endian * Core decrypt routines, expecting word32 inputs read big-endian
* from the byte-oriented input stream. * from the byte-oriented input stream.
*/ */
static void aes_decrypt_nb_4(AESContext *ctx, word32 *block) { static void aes_decrypt_nb_4(AESContext * ctx, word32 * block)
{
int i; int i;
static const int C1 = 4-1, C2 = 4-2, C3 = 4-3, Nb = 4; static const int C1 = 4 - 1, C2 = 4 - 2, C3 = 4 - 3, Nb = 4;
word32 *keysched = ctx->invkeysched; word32 *keysched = ctx->invkeysched;
word32 newstate[4]; word32 newstate[4];
for (i = 0; i < ctx->Nr-1; i++) { for (i = 0; i < ctx->Nr - 1; i++) {
ADD_ROUND_KEY_4; ADD_ROUND_KEY_4;
MAKEWORD(0); MAKEWORD(1); MAKEWORD(2); MAKEWORD(3); MAKEWORD(0);
MOVEWORD(0); MOVEWORD(1); MOVEWORD(2); MOVEWORD(3); MAKEWORD(1);
MAKEWORD(2);
MAKEWORD(3);
MOVEWORD(0);
MOVEWORD(1);
MOVEWORD(2);
MOVEWORD(3);
} }
ADD_ROUND_KEY_4; ADD_ROUND_KEY_4;
LASTWORD(0); LASTWORD(1); LASTWORD(2); LASTWORD(3); LASTWORD(0);
MOVEWORD(0); MOVEWORD(1); MOVEWORD(2); MOVEWORD(3); LASTWORD(1);
LASTWORD(2);
LASTWORD(3);
MOVEWORD(0);
MOVEWORD(1);
MOVEWORD(2);
MOVEWORD(3);
ADD_ROUND_KEY_4; ADD_ROUND_KEY_4;
} }
static void aes_decrypt_nb_6(AESContext *ctx, word32 *block) { static void aes_decrypt_nb_6(AESContext * ctx, word32 * block)
{
int i; int i;
static const int C1 = 6-1, C2 = 6-2, C3 = 6-3, Nb = 6; static const int C1 = 6 - 1, C2 = 6 - 2, C3 = 6 - 3, Nb = 6;
word32 *keysched = ctx->invkeysched; word32 *keysched = ctx->invkeysched;
word32 newstate[6]; word32 newstate[6];
for (i = 0; i < ctx->Nr-1; i++) { for (i = 0; i < ctx->Nr - 1; i++) {
ADD_ROUND_KEY_6; ADD_ROUND_KEY_6;
MAKEWORD(0); MAKEWORD(1); MAKEWORD(2); MAKEWORD(0);
MAKEWORD(3); MAKEWORD(4); MAKEWORD(5); MAKEWORD(1);
MOVEWORD(0); MOVEWORD(1); MOVEWORD(2); MAKEWORD(2);
MOVEWORD(3); MOVEWORD(4); MOVEWORD(5); MAKEWORD(3);
MAKEWORD(4);
MAKEWORD(5);
MOVEWORD(0);
MOVEWORD(1);
MOVEWORD(2);
MOVEWORD(3);
MOVEWORD(4);
MOVEWORD(5);
} }
ADD_ROUND_KEY_6; ADD_ROUND_KEY_6;
LASTWORD(0); LASTWORD(1); LASTWORD(2); LASTWORD(0);
LASTWORD(3); LASTWORD(4); LASTWORD(5); LASTWORD(1);
MOVEWORD(0); MOVEWORD(1); MOVEWORD(2); LASTWORD(2);
MOVEWORD(3); MOVEWORD(4); MOVEWORD(5); LASTWORD(3);
LASTWORD(4);
LASTWORD(5);
MOVEWORD(0);
MOVEWORD(1);
MOVEWORD(2);
MOVEWORD(3);
MOVEWORD(4);
MOVEWORD(5);
ADD_ROUND_KEY_6; ADD_ROUND_KEY_6;
} }
static void aes_decrypt_nb_8(AESContext *ctx, word32 *block) { static void aes_decrypt_nb_8(AESContext * ctx, word32 * block)
{
int i; int i;
static const int C1 = 8-1, C2 = 8-3, C3 = 8-4, Nb = 8; static const int C1 = 8 - 1, C2 = 8 - 3, C3 = 8 - 4, Nb = 8;
word32 *keysched = ctx->invkeysched; word32 *keysched = ctx->invkeysched;
word32 newstate[8]; word32 newstate[8];
for (i = 0; i < ctx->Nr-1; i++) { for (i = 0; i < ctx->Nr - 1; i++) {
ADD_ROUND_KEY_8; ADD_ROUND_KEY_8;
MAKEWORD(0); MAKEWORD(1); MAKEWORD(2); MAKEWORD(3); MAKEWORD(0);
MAKEWORD(4); MAKEWORD(5); MAKEWORD(6); MAKEWORD(7); MAKEWORD(1);
MOVEWORD(0); MOVEWORD(1); MOVEWORD(2); MOVEWORD(3); MAKEWORD(2);
MOVEWORD(4); MOVEWORD(5); MOVEWORD(6); MOVEWORD(7); MAKEWORD(3);
MAKEWORD(4);
MAKEWORD(5);
MAKEWORD(6);
MAKEWORD(7);
MOVEWORD(0);
MOVEWORD(1);
MOVEWORD(2);
MOVEWORD(3);
MOVEWORD(4);
MOVEWORD(5);
MOVEWORD(6);
MOVEWORD(7);
} }
ADD_ROUND_KEY_8; ADD_ROUND_KEY_8;
LASTWORD(0); LASTWORD(1); LASTWORD(2); LASTWORD(3); LASTWORD(0);
LASTWORD(4); LASTWORD(5); LASTWORD(6); LASTWORD(7); LASTWORD(1);
MOVEWORD(0); MOVEWORD(1); MOVEWORD(2); MOVEWORD(3); LASTWORD(2);
MOVEWORD(4); MOVEWORD(5); MOVEWORD(6); MOVEWORD(7); LASTWORD(3);
LASTWORD(4);
LASTWORD(5);
LASTWORD(6);
LASTWORD(7);
MOVEWORD(0);
MOVEWORD(1);
MOVEWORD(2);
MOVEWORD(3);
MOVEWORD(4);
MOVEWORD(5);
MOVEWORD(6);
MOVEWORD(7);
ADD_ROUND_KEY_8; ADD_ROUND_KEY_8;
} }
#undef MAKEWORD #undef MAKEWORD
#undef LASTWORD #undef LASTWORD
@ -829,8 +941,9 @@ static const word32 D3[256] = {
* bytes; each can be either 16 (128-bit), 24 (192-bit), or 32 * bytes; each can be either 16 (128-bit), 24 (192-bit), or 32
* (256-bit). * (256-bit).
*/ */
void aes_setup(AESContext *ctx, int blocklen, void aes_setup(AESContext * ctx, int blocklen,
unsigned char *key, int keylen) { unsigned char *key, int keylen)
{
int i, j, Nk, rconst; int i, j, Nk, rconst;
assert(blocklen == 16 || blocklen == 24 || blocklen == 32); assert(blocklen == 16 || blocklen == 24 || blocklen == 32);
@ -857,16 +970,16 @@ void aes_setup(AESContext *ctx, int blocklen,
* Now do the key setup itself. * Now do the key setup itself.
*/ */
rconst = 1; rconst = 1;
for (i = 0; i < (ctx->Nr+1) * ctx->Nb; i++) { for (i = 0; i < (ctx->Nr + 1) * ctx->Nb; i++) {
if (i < Nk) if (i < Nk)
ctx->keysched[i] = GET_32BIT_MSB_FIRST(key + 4*i); ctx->keysched[i] = GET_32BIT_MSB_FIRST(key + 4 * i);
else { else {
word32 temp = ctx->keysched[i-1]; word32 temp = ctx->keysched[i - 1];
if (i % Nk == 0) { if (i % Nk == 0) {
int a, b, c, d; int a, b, c, d;
a = (temp >> 16) & 0xFF; a = (temp >> 16) & 0xFF;
b = (temp >> 8) & 0xFF; b = (temp >> 8) & 0xFF;
c = (temp >> 0) & 0xFF; c = (temp >> 0) & 0xFF;
d = (temp >> 24) & 0xFF; d = (temp >> 24) & 0xFF;
temp = Sbox[a] ^ rconst; temp = Sbox[a] ^ rconst;
temp = (temp << 8) | Sbox[b]; temp = (temp << 8) | Sbox[b];
@ -877,14 +990,14 @@ void aes_setup(AESContext *ctx, int blocklen,
int a, b, c, d; int a, b, c, d;
a = (temp >> 24) & 0xFF; a = (temp >> 24) & 0xFF;
b = (temp >> 16) & 0xFF; b = (temp >> 16) & 0xFF;
c = (temp >> 8) & 0xFF; c = (temp >> 8) & 0xFF;
d = (temp >> 0) & 0xFF; d = (temp >> 0) & 0xFF;
temp = Sbox[a]; temp = Sbox[a];
temp = (temp << 8) | Sbox[b]; temp = (temp << 8) | Sbox[b];
temp = (temp << 8) | Sbox[c]; temp = (temp << 8) | Sbox[c];
temp = (temp << 8) | Sbox[d]; temp = (temp << 8) | Sbox[d];
} }
ctx->keysched[i] = ctx->keysched[i-Nk] ^ temp; ctx->keysched[i] = ctx->keysched[i - Nk] ^ temp;
} }
} }
@ -905,8 +1018,8 @@ void aes_setup(AESContext *ctx, int blocklen,
int a, b, c, d; int a, b, c, d;
a = (temp >> 24) & 0xFF; a = (temp >> 24) & 0xFF;
b = (temp >> 16) & 0xFF; b = (temp >> 16) & 0xFF;
c = (temp >> 8) & 0xFF; c = (temp >> 8) & 0xFF;
d = (temp >> 0) & 0xFF; d = (temp >> 0) & 0xFF;
temp = D0[Sbox[a]]; temp = D0[Sbox[a]];
temp ^= D1[Sbox[b]]; temp ^= D1[Sbox[b]];
temp ^= D2[Sbox[c]]; temp ^= D2[Sbox[c]];
@ -917,15 +1030,18 @@ void aes_setup(AESContext *ctx, int blocklen,
} }
} }
static void aes_encrypt(AESContext *ctx, word32 *block) { static void aes_encrypt(AESContext * ctx, word32 * block)
{
ctx->encrypt(ctx, block); ctx->encrypt(ctx, block);
} }
static void aes_decrypt(AESContext *ctx, word32 *block) { static void aes_decrypt(AESContext * ctx, word32 * block)
{
ctx->decrypt(ctx, block); ctx->decrypt(ctx, block);
} }
static void aes_encrypt_cbc(unsigned char *blk, int len, AESContext *ctx) { static void aes_encrypt_cbc(unsigned char *blk, int len, AESContext * ctx)
{
word32 iv[4]; word32 iv[4];
int i; int i;
@ -935,18 +1051,19 @@ static void aes_encrypt_cbc(unsigned char *blk, int len, AESContext *ctx) {
while (len > 0) { while (len > 0) {
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
iv[i] ^= GET_32BIT_MSB_FIRST(blk+4*i); iv[i] ^= GET_32BIT_MSB_FIRST(blk + 4 * i);
aes_encrypt(ctx, iv); aes_encrypt(ctx, iv);
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
PUT_32BIT_MSB_FIRST(blk+4*i, iv[i]); PUT_32BIT_MSB_FIRST(blk + 4 * i, iv[i]);
blk += 16; blk += 16;
len -= 16; len -= 16;
} }
memcpy(ctx->iv, iv, sizeof(iv)); memcpy(ctx->iv, iv, sizeof(iv));
} }
static void aes_decrypt_cbc(unsigned char *blk, int len, AESContext *ctx) { static void aes_decrypt_cbc(unsigned char *blk, int len, AESContext * ctx)
{
word32 iv[4], x[4], ct[4]; word32 iv[4], x[4], ct[4];
int i; int i;
@ -956,14 +1073,14 @@ static void aes_decrypt_cbc(unsigned char *blk, int len, AESContext *ctx) {
while (len > 0) { while (len > 0) {
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
x[i] = ct[i] = GET_32BIT_MSB_FIRST(blk+4*i); x[i] = ct[i] = GET_32BIT_MSB_FIRST(blk + 4 * i);
aes_decrypt(ctx, x); aes_decrypt(ctx, x);
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
PUT_32BIT_MSB_FIRST(blk+4*i, iv[i] ^ x[i]); PUT_32BIT_MSB_FIRST(blk + 4 * i, iv[i] ^ x[i]);
iv[i] = ct[i]; iv[i] = ct[i];
} }
blk += 16; blk += 16;
len -= 16; len -= 16;
} }
memcpy(ctx->iv, iv, sizeof(iv)); memcpy(ctx->iv, iv, sizeof(iv));
@ -971,64 +1088,76 @@ static void aes_decrypt_cbc(unsigned char *blk, int len, AESContext *ctx) {
static AESContext csctx, scctx; static AESContext csctx, scctx;
static void aes128_cskey(unsigned char *key) { static void aes128_cskey(unsigned char *key)
{
aes_setup(&csctx, 16, key, 16); aes_setup(&csctx, 16, key, 16);
logevent("Initialised AES-128 client->server encryption"); logevent("Initialised AES-128 client->server encryption");
} }
static void aes128_sckey(unsigned char *key) { static void aes128_sckey(unsigned char *key)
{
aes_setup(&scctx, 16, key, 16); aes_setup(&scctx, 16, key, 16);
logevent("Initialised AES-128 server->client encryption"); logevent("Initialised AES-128 server->client encryption");
} }
static void aes192_cskey(unsigned char *key) { static void aes192_cskey(unsigned char *key)
{
aes_setup(&csctx, 16, key, 24); aes_setup(&csctx, 16, key, 24);
logevent("Initialised AES-192 client->server encryption"); logevent("Initialised AES-192 client->server encryption");
} }
static void aes192_sckey(unsigned char *key) { static void aes192_sckey(unsigned char *key)
{
aes_setup(&scctx, 16, key, 24); aes_setup(&scctx, 16, key, 24);
logevent("Initialised AES-192 server->client encryption"); logevent("Initialised AES-192 server->client encryption");
} }
static void aes256_cskey(unsigned char *key) { static void aes256_cskey(unsigned char *key)
{
aes_setup(&csctx, 16, key, 32); aes_setup(&csctx, 16, key, 32);
logevent("Initialised AES-256 client->server encryption"); logevent("Initialised AES-256 client->server encryption");
} }
static void aes256_sckey(unsigned char *key) { static void aes256_sckey(unsigned char *key)
{
aes_setup(&scctx, 16, key, 32); aes_setup(&scctx, 16, key, 32);
logevent("Initialised AES-256 server->client encryption"); logevent("Initialised AES-256 server->client encryption");
} }
static void aes_csiv(unsigned char *iv) { static void aes_csiv(unsigned char *iv)
{
int i; int i;
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
csctx.iv[i] = GET_32BIT_MSB_FIRST(iv+4*i); csctx.iv[i] = GET_32BIT_MSB_FIRST(iv + 4 * i);
} }
static void aes_sciv(unsigned char *iv) { static void aes_sciv(unsigned char *iv)
{
int i; int i;
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
scctx.iv[i] = GET_32BIT_MSB_FIRST(iv+4*i); scctx.iv[i] = GET_32BIT_MSB_FIRST(iv + 4 * i);
} }
static void aes_ssh2_encrypt_blk(unsigned char *blk, int len) { static void aes_ssh2_encrypt_blk(unsigned char *blk, int len)
{
aes_encrypt_cbc(blk, len, &csctx); aes_encrypt_cbc(blk, len, &csctx);
} }
static void aes_ssh2_decrypt_blk(unsigned char *blk, int len) { static void aes_ssh2_decrypt_blk(unsigned char *blk, int len)
{
aes_decrypt_cbc(blk, len, &scctx); aes_decrypt_cbc(blk, len, &scctx);
} }
void aes256_encrypt_pubkey(unsigned char *key, unsigned char *blk, int len) { void aes256_encrypt_pubkey(unsigned char *key, unsigned char *blk, int len)
{
AESContext ctx; AESContext ctx;
aes_setup(&ctx, 16, key, 32); aes_setup(&ctx, 16, key, 32);
memset(ctx.iv, 0, sizeof(ctx.iv)); memset(ctx.iv, 0, sizeof(ctx.iv));
aes_encrypt_cbc(blk, len, &ctx); aes_encrypt_cbc(blk, len, &ctx);
} }
void aes256_decrypt_pubkey(unsigned char *key, unsigned char *blk, int len) { void aes256_decrypt_pubkey(unsigned char *key, unsigned char *blk, int len)
{
AESContext ctx; AESContext ctx;
aes_setup(&ctx, 16, key, 32); aes_setup(&ctx, 16, key, 32);
memset(ctx.iv, 0, sizeof(ctx.iv)); memset(ctx.iv, 0, sizeof(ctx.iv));

View File

@ -235,8 +235,9 @@ static const word32 sbox3[] = {
#define F(x) Fprime( ((x>>24)&0xFF), ((x>>16)&0xFF), ((x>>8)&0xFF), (x&0xFF) ) #define F(x) Fprime( ((x>>24)&0xFF), ((x>>16)&0xFF), ((x>>8)&0xFF), (x&0xFF) )
#define ROUND(n) ( xL ^= P[n], t = xL, xL = F(xL) ^ xR, xR = t ) #define ROUND(n) ( xL ^= P[n], t = xL, xL = F(xL) ^ xR, xR = t )
static void blowfish_encrypt(word32 xL, word32 xR, word32 *output, static void blowfish_encrypt(word32 xL, word32 xR, word32 * output,
BlowfishContext *ctx) { BlowfishContext * ctx)
{
word32 *S0 = ctx->S0; word32 *S0 = ctx->S0;
word32 *S1 = ctx->S1; word32 *S1 = ctx->S1;
word32 *S2 = ctx->S2; word32 *S2 = ctx->S2;
@ -267,8 +268,9 @@ static void blowfish_encrypt(word32 xL, word32 xR, word32 *output,
output[1] = xL; output[1] = xL;
} }
static void blowfish_decrypt(word32 xL, word32 xR, word32 *output, static void blowfish_decrypt(word32 xL, word32 xR, word32 * output,
BlowfishContext *ctx) { BlowfishContext * ctx)
{
word32 *S0 = ctx->S0; word32 *S0 = ctx->S0;
word32 *S1 = ctx->S1; word32 *S1 = ctx->S1;
word32 *S2 = ctx->S2; word32 *S2 = ctx->S2;
@ -300,107 +302,120 @@ static void blowfish_decrypt(word32 xL, word32 xR, word32 *output,
} }
static void blowfish_lsb_encrypt_cbc(unsigned char *blk, int len, static void blowfish_lsb_encrypt_cbc(unsigned char *blk, int len,
BlowfishContext *ctx) { BlowfishContext * ctx)
{
word32 xL, xR, out[2], iv0, iv1; word32 xL, xR, out[2], iv0, iv1;
assert((len & 7) == 0); assert((len & 7) == 0);
iv0 = ctx->iv0; iv1 = ctx->iv1; iv0 = ctx->iv0;
iv1 = ctx->iv1;
while (len > 0) { while (len > 0) {
xL = GET_32BIT_LSB_FIRST(blk); xL = GET_32BIT_LSB_FIRST(blk);
xR = GET_32BIT_LSB_FIRST(blk+4); xR = GET_32BIT_LSB_FIRST(blk + 4);
iv0 ^= xL; iv0 ^= xL;
iv1 ^= xR; iv1 ^= xR;
blowfish_encrypt(iv0, iv1, out, ctx); blowfish_encrypt(iv0, iv1, out, ctx);
iv0 = out[0]; iv0 = out[0];
iv1 = out[1]; iv1 = out[1];
PUT_32BIT_LSB_FIRST(blk, iv0); PUT_32BIT_LSB_FIRST(blk, iv0);
PUT_32BIT_LSB_FIRST(blk+4, iv1); PUT_32BIT_LSB_FIRST(blk + 4, iv1);
blk += 8; blk += 8;
len -= 8; len -= 8;
} }
ctx->iv0 = iv0; ctx->iv1 = iv1; ctx->iv0 = iv0;
ctx->iv1 = iv1;
} }
static void blowfish_lsb_decrypt_cbc(unsigned char *blk, int len, static void blowfish_lsb_decrypt_cbc(unsigned char *blk, int len,
BlowfishContext *ctx) { BlowfishContext * ctx)
{
word32 xL, xR, out[2], iv0, iv1; word32 xL, xR, out[2], iv0, iv1;
assert((len & 7) == 0); assert((len & 7) == 0);
iv0 = ctx->iv0; iv1 = ctx->iv1; iv0 = ctx->iv0;
iv1 = ctx->iv1;
while (len > 0) { while (len > 0) {
xL = GET_32BIT_LSB_FIRST(blk); xL = GET_32BIT_LSB_FIRST(blk);
xR = GET_32BIT_LSB_FIRST(blk+4); xR = GET_32BIT_LSB_FIRST(blk + 4);
blowfish_decrypt(xL, xR, out, ctx); blowfish_decrypt(xL, xR, out, ctx);
iv0 ^= out[0]; iv0 ^= out[0];
iv1 ^= out[1]; iv1 ^= out[1];
PUT_32BIT_LSB_FIRST(blk, iv0); PUT_32BIT_LSB_FIRST(blk, iv0);
PUT_32BIT_LSB_FIRST(blk+4, iv1); PUT_32BIT_LSB_FIRST(blk + 4, iv1);
iv0 = xL; iv0 = xL;
iv1 = xR; iv1 = xR;
blk += 8; blk += 8;
len -= 8; len -= 8;
} }
ctx->iv0 = iv0; ctx->iv1 = iv1; ctx->iv0 = iv0;
ctx->iv1 = iv1;
} }
static void blowfish_msb_encrypt_cbc(unsigned char *blk, int len, static void blowfish_msb_encrypt_cbc(unsigned char *blk, int len,
BlowfishContext *ctx) { BlowfishContext * ctx)
{
word32 xL, xR, out[2], iv0, iv1; word32 xL, xR, out[2], iv0, iv1;
assert((len & 7) == 0); assert((len & 7) == 0);
iv0 = ctx->iv0; iv1 = ctx->iv1; iv0 = ctx->iv0;
iv1 = ctx->iv1;
while (len > 0) { while (len > 0) {
xL = GET_32BIT_MSB_FIRST(blk); xL = GET_32BIT_MSB_FIRST(blk);
xR = GET_32BIT_MSB_FIRST(blk+4); xR = GET_32BIT_MSB_FIRST(blk + 4);
iv0 ^= xL; iv0 ^= xL;
iv1 ^= xR; iv1 ^= xR;
blowfish_encrypt(iv0, iv1, out, ctx); blowfish_encrypt(iv0, iv1, out, ctx);
iv0 = out[0]; iv0 = out[0];
iv1 = out[1]; iv1 = out[1];
PUT_32BIT_MSB_FIRST(blk, iv0); PUT_32BIT_MSB_FIRST(blk, iv0);
PUT_32BIT_MSB_FIRST(blk+4, iv1); PUT_32BIT_MSB_FIRST(blk + 4, iv1);
blk += 8; blk += 8;
len -= 8; len -= 8;
} }
ctx->iv0 = iv0; ctx->iv1 = iv1; ctx->iv0 = iv0;
ctx->iv1 = iv1;
} }
static void blowfish_msb_decrypt_cbc(unsigned char *blk, int len, static void blowfish_msb_decrypt_cbc(unsigned char *blk, int len,
BlowfishContext *ctx) { BlowfishContext * ctx)
{
word32 xL, xR, out[2], iv0, iv1; word32 xL, xR, out[2], iv0, iv1;
assert((len & 7) == 0); assert((len & 7) == 0);
iv0 = ctx->iv0; iv1 = ctx->iv1; iv0 = ctx->iv0;
iv1 = ctx->iv1;
while (len > 0) { while (len > 0) {
xL = GET_32BIT_MSB_FIRST(blk); xL = GET_32BIT_MSB_FIRST(blk);
xR = GET_32BIT_MSB_FIRST(blk+4); xR = GET_32BIT_MSB_FIRST(blk + 4);
blowfish_decrypt(xL, xR, out, ctx); blowfish_decrypt(xL, xR, out, ctx);
iv0 ^= out[0]; iv0 ^= out[0];
iv1 ^= out[1]; iv1 ^= out[1];
PUT_32BIT_MSB_FIRST(blk, iv0); PUT_32BIT_MSB_FIRST(blk, iv0);
PUT_32BIT_MSB_FIRST(blk+4, iv1); PUT_32BIT_MSB_FIRST(blk + 4, iv1);
iv0 = xL; iv0 = xL;
iv1 = xR; iv1 = xR;
blk += 8; blk += 8;
len -= 8; len -= 8;
} }
ctx->iv0 = iv0; ctx->iv1 = iv1; ctx->iv0 = iv0;
ctx->iv1 = iv1;
} }
static void blowfish_setkey(BlowfishContext *ctx, static void blowfish_setkey(BlowfishContext * ctx,
const unsigned char *key, short keybytes) { const unsigned char *key, short keybytes)
{
word32 *S0 = ctx->S0; word32 *S0 = ctx->S0;
word32 *S1 = ctx->S1; word32 *S1 = ctx->S1;
word32 *S2 = ctx->S2; word32 *S2 = ctx->S2;
@ -410,42 +425,50 @@ static void blowfish_setkey(BlowfishContext *ctx,
int i; int i;
for (i = 0; i < 18; i++) { for (i = 0; i < 18; i++) {
P[i] = parray[i]; P[i] = parray[i];
P[i] ^= ((word32)(unsigned char)(key[ (i*4+0) % keybytes ])) << 24; P[i] ^=
P[i] ^= ((word32)(unsigned char)(key[ (i*4+1) % keybytes ])) << 16; ((word32) (unsigned char) (key[(i * 4 + 0) % keybytes])) << 24;
P[i] ^= ((word32)(unsigned char)(key[ (i*4+2) % keybytes ])) << 8; P[i] ^=
P[i] ^= ((word32)(unsigned char)(key[ (i*4+3) % keybytes ])); ((word32) (unsigned char) (key[(i * 4 + 1) % keybytes])) << 16;
P[i] ^=
((word32) (unsigned char) (key[(i * 4 + 2) % keybytes])) << 8;
P[i] ^= ((word32) (unsigned char) (key[(i * 4 + 3) % keybytes]));
} }
for (i = 0; i < 256; i++) { for (i = 0; i < 256; i++) {
S0[i] = sbox0[i]; S0[i] = sbox0[i];
S1[i] = sbox1[i]; S1[i] = sbox1[i];
S2[i] = sbox2[i]; S2[i] = sbox2[i];
S3[i] = sbox3[i]; S3[i] = sbox3[i];
} }
str[0] = str[1] = 0; str[0] = str[1] = 0;
for (i = 0; i < 18; i += 2) { for (i = 0; i < 18; i += 2) {
blowfish_encrypt(str[0], str[1], str, ctx); blowfish_encrypt(str[0], str[1], str, ctx);
P[i] = str[0]; P[i+1] = str[1]; P[i] = str[0];
P[i + 1] = str[1];
} }
for (i = 0; i < 256; i += 2) { for (i = 0; i < 256; i += 2) {
blowfish_encrypt(str[0], str[1], str, ctx); blowfish_encrypt(str[0], str[1], str, ctx);
S0[i] = str[0]; S0[i+1] = str[1]; S0[i] = str[0];
S0[i + 1] = str[1];
} }
for (i = 0; i < 256; i += 2) { for (i = 0; i < 256; i += 2) {
blowfish_encrypt(str[0], str[1], str, ctx); blowfish_encrypt(str[0], str[1], str, ctx);
S1[i] = str[0]; S1[i+1] = str[1]; S1[i] = str[0];
S1[i + 1] = str[1];
} }
for (i = 0; i < 256; i += 2) { for (i = 0; i < 256; i += 2) {
blowfish_encrypt(str[0], str[1], str, ctx); blowfish_encrypt(str[0], str[1], str, ctx);
S2[i] = str[0]; S2[i+1] = str[1]; S2[i] = str[0];
S2[i + 1] = str[1];
} }
for (i = 0; i < 256; i += 2) { for (i = 0; i < 256; i += 2) {
blowfish_encrypt(str[0], str[1], str, ctx); blowfish_encrypt(str[0], str[1], str, ctx);
S3[i] = str[0]; S3[i+1] = str[1]; S3[i] = str[0];
S3[i + 1] = str[1];
} }
} }
@ -454,31 +477,31 @@ static void blowfish_setkey(BlowfishContext *ctx,
#define SSH_SESSION_KEY_LENGTH 32 #define SSH_SESSION_KEY_LENGTH 32
static BlowfishContext ectx, dctx; static BlowfishContext ectx, dctx;
static void blowfish_cskey(unsigned char *key) static void blowfish_cskey(unsigned char *key)
{ {
blowfish_setkey(&ectx, key, 16); blowfish_setkey(&ectx, key, 16);
logevent("Initialised Blowfish client->server encryption"); logevent("Initialised Blowfish client->server encryption");
} }
static void blowfish_sckey(unsigned char *key) static void blowfish_sckey(unsigned char *key)
{ {
blowfish_setkey(&dctx, key, 16); blowfish_setkey(&dctx, key, 16);
logevent("Initialised Blowfish server->client encryption"); logevent("Initialised Blowfish server->client encryption");
} }
static void blowfish_csiv(unsigned char *key) static void blowfish_csiv(unsigned char *key)
{ {
ectx.iv0 = GET_32BIT_MSB_FIRST(key); ectx.iv0 = GET_32BIT_MSB_FIRST(key);
ectx.iv1 = GET_32BIT_MSB_FIRST(key+4); ectx.iv1 = GET_32BIT_MSB_FIRST(key + 4);
} }
static void blowfish_sciv(unsigned char *key) static void blowfish_sciv(unsigned char *key)
{ {
dctx.iv0 = GET_32BIT_MSB_FIRST(key); dctx.iv0 = GET_32BIT_MSB_FIRST(key);
dctx.iv1 = GET_32BIT_MSB_FIRST(key+4); dctx.iv1 = GET_32BIT_MSB_FIRST(key + 4);
} }
static void blowfish_sesskey(unsigned char *key) static void blowfish_sesskey(unsigned char *key)
{ {
blowfish_setkey(&ectx, key, SSH_SESSION_KEY_LENGTH); blowfish_setkey(&ectx, key, SSH_SESSION_KEY_LENGTH);
ectx.iv0 = 0; ectx.iv0 = 0;

628
sshbn.c

File diff suppressed because it is too large Load Diff

View File

@ -89,7 +89,7 @@
#define POLY (0xEDB88320L) #define POLY (0xEDB88320L)
#ifdef GENPROGRAM #ifdef GENPROGRAM
#define INITFUNC /* the gen program needs the init func :-) */ #define INITFUNC /* the gen program needs the init func :-) */
#endif #endif
#ifdef INITFUNC #ifdef INITFUNC
@ -100,21 +100,22 @@
*/ */
static unsigned long crc32_table[256]; static unsigned long crc32_table[256];
void crc32_init(void) { void crc32_init(void)
{
unsigned long crcword; unsigned long crcword;
int i; int i;
for (i = 0; i < 256; i++) { for (i = 0; i < 256; i++) {
unsigned long newbyte, x32term; unsigned long newbyte, x32term;
int j; int j;
crcword = 0; crcword = 0;
newbyte = i; newbyte = i;
for (j = 0; j < 8; j++) { for (j = 0; j < 8; j++) {
x32term = (crcword ^ newbyte) & 1; x32term = (crcword ^ newbyte) & 1;
crcword = (crcword >> 1) ^ (x32term * POLY); crcword = (crcword >> 1) ^ (x32term * POLY);
newbyte >>= 1; newbyte >>= 1;
} }
crc32_table[i] = crcword; crc32_table[i] = crcword;
} }
} }
@ -193,29 +194,31 @@ static const unsigned long crc32_table[256] = {
#endif #endif
#ifdef GENPROGRAM #ifdef GENPROGRAM
int main(void) { int main(void)
{
unsigned long crcword; unsigned long crcword;
int i; int i;
crc32_init(); crc32_init();
for (i = 0; i < 256; i++) { for (i = 0; i < 256; i++) {
printf("%s0x%08XL%s", printf("%s0x%08XL%s",
(i % 4 == 0 ? " " : " "), (i % 4 == 0 ? " " : " "),
crc32_table[i], crc32_table[i],
(i % 4 == 3 ? (i == 255 ? "\n" : ",\n") : ",")); (i % 4 == 3 ? (i == 255 ? "\n" : ",\n") : ","));
} }
return 0; return 0;
} }
#endif #endif
unsigned long crc32(const void *buf, size_t len) { unsigned long crc32(const void *buf, size_t len)
{
unsigned long crcword = 0L; unsigned long crcword = 0L;
const unsigned char *p = (const unsigned char *) buf; const unsigned char *p = (const unsigned char *) buf;
while (len--) { while (len--) {
unsigned long newbyte = *p++; unsigned long newbyte = *p++;
newbyte ^= crcword & 0xFFL; newbyte ^= crcword & 0xFFL;
crcword = (crcword >> 8) ^ crc32_table[newbyte]; crcword = (crcword >> 8) ^ crc32_table[newbyte];
} }
return crcword; return crcword;
} }

533
sshdes.c
View File

@ -285,26 +285,28 @@ typedef struct {
#define rotl(x, c) ( (x << c) | (x >> (32-c)) ) #define rotl(x, c) ( (x << c) | (x >> (32-c)) )
#define rotl28(x, c) ( ( (x << c) | (x >> (28-c)) ) & 0x0FFFFFFF) #define rotl28(x, c) ( ( (x << c) | (x >> (28-c)) ) & 0x0FFFFFFF)
static word32 bitsel(word32 *input, const int *bitnums, int size) { static word32 bitsel(word32 * input, const int *bitnums, int size)
{
word32 ret = 0; word32 ret = 0;
while (size--) { while (size--) {
int bitpos = *bitnums++; int bitpos = *bitnums++;
ret <<= 1; ret <<= 1;
if (bitpos >= 0) if (bitpos >= 0)
ret |= 1 & (input[bitpos / 32] >> (bitpos % 32)); ret |= 1 & (input[bitpos / 32] >> (bitpos % 32));
} }
return ret; return ret;
} }
void des_key_setup(word32 key_msw, word32 key_lsw, DESContext *sched) { void des_key_setup(word32 key_msw, word32 key_lsw, DESContext * sched)
{
static const int PC1_Cbits[] = { static const int PC1_Cbits[] = {
7, 15, 23, 31, 39, 47, 55, 63, 6, 14, 22, 30, 38, 46, 7, 15, 23, 31, 39, 47, 55, 63, 6, 14, 22, 30, 38, 46,
54, 62, 5, 13, 21, 29, 37, 45, 53, 61, 4, 12, 20, 28 54, 62, 5, 13, 21, 29, 37, 45, 53, 61, 4, 12, 20, 28
}; };
static const int PC1_Dbits[] = { static const int PC1_Dbits[] = {
1, 9, 17, 25, 33, 41, 49, 57, 2, 10, 18, 26, 34, 42, 1, 9, 17, 25, 33, 41, 49, 57, 2, 10, 18, 26, 34, 42,
50, 58, 3, 11, 19, 27, 35, 43, 51, 59, 36, 44, 52, 60 50, 58, 3, 11, 19, 27, 35, 43, 51, 59, 36, 44, 52, 60
}; };
/* /*
* The bit numbers in the two lists below don't correspond to * The bit numbers in the two lists below don't correspond to
@ -315,14 +317,15 @@ void des_key_setup(word32 key_msw, word32 key_lsw, DESContext *sched) {
* 0 of C is addressed by writing `32' here. * 0 of C is addressed by writing `32' here.
*/ */
static const int PC2_0246[] = { static const int PC2_0246[] = {
49, 36, 59, 55, -1, -1, 37, 41, 48, 56, 34, 52, -1, -1, 15, 4, 49, 36, 59, 55, -1, -1, 37, 41, 48, 56, 34, 52, -1, -1, 15, 4,
25, 19, 9, 1, -1, -1, 12, 7, 17, 0, 22, 3, -1, -1, 46, 43 25, 19, 9, 1, -1, -1, 12, 7, 17, 0, 22, 3, -1, -1, 46, 43
}; };
static const int PC2_1357[] = { static const int PC2_1357[] = {
-1, -1, 57, 32, 45, 54, 39, 50, -1, -1, 44, 53, 33, 40, 47, 58, -1, -1, 57, 32, 45, 54, 39, 50, -1, -1, 44, 53, 33, 40, 47, 58,
-1, -1, 26, 16, 5, 11, 23, 8, -1, -1, 10, 14, 6, 20, 27, 24 -1, -1, 26, 16, 5, 11, 23, 8, -1, -1, 10, 14, 6, 20, 27, 24
}; };
static const int leftshifts[] = {1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1}; static const int leftshifts[] =
{ 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 };
word32 C, D; word32 C, D;
word32 buf[2]; word32 buf[2];
@ -335,154 +338,154 @@ void des_key_setup(word32 key_msw, word32 key_lsw, DESContext *sched) {
D = bitsel(buf, PC1_Dbits, 28); D = bitsel(buf, PC1_Dbits, 28);
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
C = rotl28(C, leftshifts[i]); C = rotl28(C, leftshifts[i]);
D = rotl28(D, leftshifts[i]); D = rotl28(D, leftshifts[i]);
buf[0] = D; buf[0] = D;
buf[1] = C; buf[1] = C;
sched->k0246[i] = bitsel(buf, PC2_0246, 32); sched->k0246[i] = bitsel(buf, PC2_0246, 32);
sched->k1357[i] = bitsel(buf, PC2_1357, 32); sched->k1357[i] = bitsel(buf, PC2_1357, 32);
} }
sched->eiv0 = sched->eiv1 = 0; sched->eiv0 = sched->eiv1 = 0;
sched->div0 = sched->div1 = 0; /* for good measure */ sched->div0 = sched->div1 = 0; /* for good measure */
} }
static const word32 SPboxes[8][64] = { static const word32 SPboxes[8][64] = {
{0x01010400, 0x00000000, 0x00010000, 0x01010404, {0x01010400, 0x00000000, 0x00010000, 0x01010404,
0x01010004, 0x00010404, 0x00000004, 0x00010000, 0x01010004, 0x00010404, 0x00000004, 0x00010000,
0x00000400, 0x01010400, 0x01010404, 0x00000400, 0x00000400, 0x01010400, 0x01010404, 0x00000400,
0x01000404, 0x01010004, 0x01000000, 0x00000004, 0x01000404, 0x01010004, 0x01000000, 0x00000004,
0x00000404, 0x01000400, 0x01000400, 0x00010400, 0x00000404, 0x01000400, 0x01000400, 0x00010400,
0x00010400, 0x01010000, 0x01010000, 0x01000404, 0x00010400, 0x01010000, 0x01010000, 0x01000404,
0x00010004, 0x01000004, 0x01000004, 0x00010004, 0x00010004, 0x01000004, 0x01000004, 0x00010004,
0x00000000, 0x00000404, 0x00010404, 0x01000000, 0x00000000, 0x00000404, 0x00010404, 0x01000000,
0x00010000, 0x01010404, 0x00000004, 0x01010000, 0x00010000, 0x01010404, 0x00000004, 0x01010000,
0x01010400, 0x01000000, 0x01000000, 0x00000400, 0x01010400, 0x01000000, 0x01000000, 0x00000400,
0x01010004, 0x00010000, 0x00010400, 0x01000004, 0x01010004, 0x00010000, 0x00010400, 0x01000004,
0x00000400, 0x00000004, 0x01000404, 0x00010404, 0x00000400, 0x00000004, 0x01000404, 0x00010404,
0x01010404, 0x00010004, 0x01010000, 0x01000404, 0x01010404, 0x00010004, 0x01010000, 0x01000404,
0x01000004, 0x00000404, 0x00010404, 0x01010400, 0x01000004, 0x00000404, 0x00010404, 0x01010400,
0x00000404, 0x01000400, 0x01000400, 0x00000000, 0x00000404, 0x01000400, 0x01000400, 0x00000000,
0x00010004, 0x00010400, 0x00000000, 0x01010004L}, 0x00010004, 0x00010400, 0x00000000, 0x01010004L},
{0x80108020, 0x80008000, 0x00008000, 0x00108020, {0x80108020, 0x80008000, 0x00008000, 0x00108020,
0x00100000, 0x00000020, 0x80100020, 0x80008020, 0x00100000, 0x00000020, 0x80100020, 0x80008020,
0x80000020, 0x80108020, 0x80108000, 0x80000000, 0x80000020, 0x80108020, 0x80108000, 0x80000000,
0x80008000, 0x00100000, 0x00000020, 0x80100020, 0x80008000, 0x00100000, 0x00000020, 0x80100020,
0x00108000, 0x00100020, 0x80008020, 0x00000000, 0x00108000, 0x00100020, 0x80008020, 0x00000000,
0x80000000, 0x00008000, 0x00108020, 0x80100000, 0x80000000, 0x00008000, 0x00108020, 0x80100000,
0x00100020, 0x80000020, 0x00000000, 0x00108000, 0x00100020, 0x80000020, 0x00000000, 0x00108000,
0x00008020, 0x80108000, 0x80100000, 0x00008020, 0x00008020, 0x80108000, 0x80100000, 0x00008020,
0x00000000, 0x00108020, 0x80100020, 0x00100000, 0x00000000, 0x00108020, 0x80100020, 0x00100000,
0x80008020, 0x80100000, 0x80108000, 0x00008000, 0x80008020, 0x80100000, 0x80108000, 0x00008000,
0x80100000, 0x80008000, 0x00000020, 0x80108020, 0x80100000, 0x80008000, 0x00000020, 0x80108020,
0x00108020, 0x00000020, 0x00008000, 0x80000000, 0x00108020, 0x00000020, 0x00008000, 0x80000000,
0x00008020, 0x80108000, 0x00100000, 0x80000020, 0x00008020, 0x80108000, 0x00100000, 0x80000020,
0x00100020, 0x80008020, 0x80000020, 0x00100020, 0x00100020, 0x80008020, 0x80000020, 0x00100020,
0x00108000, 0x00000000, 0x80008000, 0x00008020, 0x00108000, 0x00000000, 0x80008000, 0x00008020,
0x80000000, 0x80100020, 0x80108020, 0x00108000L}, 0x80000000, 0x80100020, 0x80108020, 0x00108000L},
{0x00000208, 0x08020200, 0x00000000, 0x08020008, {0x00000208, 0x08020200, 0x00000000, 0x08020008,
0x08000200, 0x00000000, 0x00020208, 0x08000200, 0x08000200, 0x00000000, 0x00020208, 0x08000200,
0x00020008, 0x08000008, 0x08000008, 0x00020000, 0x00020008, 0x08000008, 0x08000008, 0x00020000,
0x08020208, 0x00020008, 0x08020000, 0x00000208, 0x08020208, 0x00020008, 0x08020000, 0x00000208,
0x08000000, 0x00000008, 0x08020200, 0x00000200, 0x08000000, 0x00000008, 0x08020200, 0x00000200,
0x00020200, 0x08020000, 0x08020008, 0x00020208, 0x00020200, 0x08020000, 0x08020008, 0x00020208,
0x08000208, 0x00020200, 0x00020000, 0x08000208, 0x08000208, 0x00020200, 0x00020000, 0x08000208,
0x00000008, 0x08020208, 0x00000200, 0x08000000, 0x00000008, 0x08020208, 0x00000200, 0x08000000,
0x08020200, 0x08000000, 0x00020008, 0x00000208, 0x08020200, 0x08000000, 0x00020008, 0x00000208,
0x00020000, 0x08020200, 0x08000200, 0x00000000, 0x00020000, 0x08020200, 0x08000200, 0x00000000,
0x00000200, 0x00020008, 0x08020208, 0x08000200, 0x00000200, 0x00020008, 0x08020208, 0x08000200,
0x08000008, 0x00000200, 0x00000000, 0x08020008, 0x08000008, 0x00000200, 0x00000000, 0x08020008,
0x08000208, 0x00020000, 0x08000000, 0x08020208, 0x08000208, 0x00020000, 0x08000000, 0x08020208,
0x00000008, 0x00020208, 0x00020200, 0x08000008, 0x00000008, 0x00020208, 0x00020200, 0x08000008,
0x08020000, 0x08000208, 0x00000208, 0x08020000, 0x08020000, 0x08000208, 0x00000208, 0x08020000,
0x00020208, 0x00000008, 0x08020008, 0x00020200L}, 0x00020208, 0x00000008, 0x08020008, 0x00020200L},
{0x00802001, 0x00002081, 0x00002081, 0x00000080, {0x00802001, 0x00002081, 0x00002081, 0x00000080,
0x00802080, 0x00800081, 0x00800001, 0x00002001, 0x00802080, 0x00800081, 0x00800001, 0x00002001,
0x00000000, 0x00802000, 0x00802000, 0x00802081, 0x00000000, 0x00802000, 0x00802000, 0x00802081,
0x00000081, 0x00000000, 0x00800080, 0x00800001, 0x00000081, 0x00000000, 0x00800080, 0x00800001,
0x00000001, 0x00002000, 0x00800000, 0x00802001, 0x00000001, 0x00002000, 0x00800000, 0x00802001,
0x00000080, 0x00800000, 0x00002001, 0x00002080, 0x00000080, 0x00800000, 0x00002001, 0x00002080,
0x00800081, 0x00000001, 0x00002080, 0x00800080, 0x00800081, 0x00000001, 0x00002080, 0x00800080,
0x00002000, 0x00802080, 0x00802081, 0x00000081, 0x00002000, 0x00802080, 0x00802081, 0x00000081,
0x00800080, 0x00800001, 0x00802000, 0x00802081, 0x00800080, 0x00800001, 0x00802000, 0x00802081,
0x00000081, 0x00000000, 0x00000000, 0x00802000, 0x00000081, 0x00000000, 0x00000000, 0x00802000,
0x00002080, 0x00800080, 0x00800081, 0x00000001, 0x00002080, 0x00800080, 0x00800081, 0x00000001,
0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802001, 0x00002081, 0x00002081, 0x00000080,
0x00802081, 0x00000081, 0x00000001, 0x00002000, 0x00802081, 0x00000081, 0x00000001, 0x00002000,
0x00800001, 0x00002001, 0x00802080, 0x00800081, 0x00800001, 0x00002001, 0x00802080, 0x00800081,
0x00002001, 0x00002080, 0x00800000, 0x00802001, 0x00002001, 0x00002080, 0x00800000, 0x00802001,
0x00000080, 0x00800000, 0x00002000, 0x00802080L}, 0x00000080, 0x00800000, 0x00002000, 0x00802080L},
{0x00000100, 0x02080100, 0x02080000, 0x42000100, {0x00000100, 0x02080100, 0x02080000, 0x42000100,
0x00080000, 0x00000100, 0x40000000, 0x02080000, 0x00080000, 0x00000100, 0x40000000, 0x02080000,
0x40080100, 0x00080000, 0x02000100, 0x40080100, 0x40080100, 0x00080000, 0x02000100, 0x40080100,
0x42000100, 0x42080000, 0x00080100, 0x40000000, 0x42000100, 0x42080000, 0x00080100, 0x40000000,
0x02000000, 0x40080000, 0x40080000, 0x00000000, 0x02000000, 0x40080000, 0x40080000, 0x00000000,
0x40000100, 0x42080100, 0x42080100, 0x02000100, 0x40000100, 0x42080100, 0x42080100, 0x02000100,
0x42080000, 0x40000100, 0x00000000, 0x42000000, 0x42080000, 0x40000100, 0x00000000, 0x42000000,
0x02080100, 0x02000000, 0x42000000, 0x00080100, 0x02080100, 0x02000000, 0x42000000, 0x00080100,
0x00080000, 0x42000100, 0x00000100, 0x02000000, 0x00080000, 0x42000100, 0x00000100, 0x02000000,
0x40000000, 0x02080000, 0x42000100, 0x40080100, 0x40000000, 0x02080000, 0x42000100, 0x40080100,
0x02000100, 0x40000000, 0x42080000, 0x02080100, 0x02000100, 0x40000000, 0x42080000, 0x02080100,
0x40080100, 0x00000100, 0x02000000, 0x42080000, 0x40080100, 0x00000100, 0x02000000, 0x42080000,
0x42080100, 0x00080100, 0x42000000, 0x42080100, 0x42080100, 0x00080100, 0x42000000, 0x42080100,
0x02080000, 0x00000000, 0x40080000, 0x42000000, 0x02080000, 0x00000000, 0x40080000, 0x42000000,
0x00080100, 0x02000100, 0x40000100, 0x00080000, 0x00080100, 0x02000100, 0x40000100, 0x00080000,
0x00000000, 0x40080000, 0x02080100, 0x40000100L}, 0x00000000, 0x40080000, 0x02080100, 0x40000100L},
{0x20000010, 0x20400000, 0x00004000, 0x20404010, {0x20000010, 0x20400000, 0x00004000, 0x20404010,
0x20400000, 0x00000010, 0x20404010, 0x00400000, 0x20400000, 0x00000010, 0x20404010, 0x00400000,
0x20004000, 0x00404010, 0x00400000, 0x20000010, 0x20004000, 0x00404010, 0x00400000, 0x20000010,
0x00400010, 0x20004000, 0x20000000, 0x00004010, 0x00400010, 0x20004000, 0x20000000, 0x00004010,
0x00000000, 0x00400010, 0x20004010, 0x00004000, 0x00000000, 0x00400010, 0x20004010, 0x00004000,
0x00404000, 0x20004010, 0x00000010, 0x20400010, 0x00404000, 0x20004010, 0x00000010, 0x20400010,
0x20400010, 0x00000000, 0x00404010, 0x20404000, 0x20400010, 0x00000000, 0x00404010, 0x20404000,
0x00004010, 0x00404000, 0x20404000, 0x20000000, 0x00004010, 0x00404000, 0x20404000, 0x20000000,
0x20004000, 0x00000010, 0x20400010, 0x00404000, 0x20004000, 0x00000010, 0x20400010, 0x00404000,
0x20404010, 0x00400000, 0x00004010, 0x20000010, 0x20404010, 0x00400000, 0x00004010, 0x20000010,
0x00400000, 0x20004000, 0x20000000, 0x00004010, 0x00400000, 0x20004000, 0x20000000, 0x00004010,
0x20000010, 0x20404010, 0x00404000, 0x20400000, 0x20000010, 0x20404010, 0x00404000, 0x20400000,
0x00404010, 0x20404000, 0x00000000, 0x20400010, 0x00404010, 0x20404000, 0x00000000, 0x20400010,
0x00000010, 0x00004000, 0x20400000, 0x00404010, 0x00000010, 0x00004000, 0x20400000, 0x00404010,
0x00004000, 0x00400010, 0x20004010, 0x00000000, 0x00004000, 0x00400010, 0x20004010, 0x00000000,
0x20404000, 0x20000000, 0x00400010, 0x20004010L}, 0x20404000, 0x20000000, 0x00400010, 0x20004010L},
{0x00200000, 0x04200002, 0x04000802, 0x00000000, {0x00200000, 0x04200002, 0x04000802, 0x00000000,
0x00000800, 0x04000802, 0x00200802, 0x04200800, 0x00000800, 0x04000802, 0x00200802, 0x04200800,
0x04200802, 0x00200000, 0x00000000, 0x04000002, 0x04200802, 0x00200000, 0x00000000, 0x04000002,
0x00000002, 0x04000000, 0x04200002, 0x00000802, 0x00000002, 0x04000000, 0x04200002, 0x00000802,
0x04000800, 0x00200802, 0x00200002, 0x04000800, 0x04000800, 0x00200802, 0x00200002, 0x04000800,
0x04000002, 0x04200000, 0x04200800, 0x00200002, 0x04000002, 0x04200000, 0x04200800, 0x00200002,
0x04200000, 0x00000800, 0x00000802, 0x04200802, 0x04200000, 0x00000800, 0x00000802, 0x04200802,
0x00200800, 0x00000002, 0x04000000, 0x00200800, 0x00200800, 0x00000002, 0x04000000, 0x00200800,
0x04000000, 0x00200800, 0x00200000, 0x04000802, 0x04000000, 0x00200800, 0x00200000, 0x04000802,
0x04000802, 0x04200002, 0x04200002, 0x00000002, 0x04000802, 0x04200002, 0x04200002, 0x00000002,
0x00200002, 0x04000000, 0x04000800, 0x00200000, 0x00200002, 0x04000000, 0x04000800, 0x00200000,
0x04200800, 0x00000802, 0x00200802, 0x04200800, 0x04200800, 0x00000802, 0x00200802, 0x04200800,
0x00000802, 0x04000002, 0x04200802, 0x04200000, 0x00000802, 0x04000002, 0x04200802, 0x04200000,
0x00200800, 0x00000000, 0x00000002, 0x04200802, 0x00200800, 0x00000000, 0x00000002, 0x04200802,
0x00000000, 0x00200802, 0x04200000, 0x00000800, 0x00000000, 0x00200802, 0x04200000, 0x00000800,
0x04000002, 0x04000800, 0x00000800, 0x00200002L}, 0x04000002, 0x04000800, 0x00000800, 0x00200002L},
{0x10001040, 0x00001000, 0x00040000, 0x10041040, {0x10001040, 0x00001000, 0x00040000, 0x10041040,
0x10000000, 0x10001040, 0x00000040, 0x10000000, 0x10000000, 0x10001040, 0x00000040, 0x10000000,
0x00040040, 0x10040000, 0x10041040, 0x00041000, 0x00040040, 0x10040000, 0x10041040, 0x00041000,
0x10041000, 0x00041040, 0x00001000, 0x00000040, 0x10041000, 0x00041040, 0x00001000, 0x00000040,
0x10040000, 0x10000040, 0x10001000, 0x00001040, 0x10040000, 0x10000040, 0x10001000, 0x00001040,
0x00041000, 0x00040040, 0x10040040, 0x10041000, 0x00041000, 0x00040040, 0x10040040, 0x10041000,
0x00001040, 0x00000000, 0x00000000, 0x10040040, 0x00001040, 0x00000000, 0x00000000, 0x10040040,
0x10000040, 0x10001000, 0x00041040, 0x00040000, 0x10000040, 0x10001000, 0x00041040, 0x00040000,
0x00041040, 0x00040000, 0x10041000, 0x00001000, 0x00041040, 0x00040000, 0x10041000, 0x00001000,
0x00000040, 0x10040040, 0x00001000, 0x00041040, 0x00000040, 0x10040040, 0x00001000, 0x00041040,
0x10001000, 0x00000040, 0x10000040, 0x10040000, 0x10001000, 0x00000040, 0x10000040, 0x10040000,
0x10040040, 0x10000000, 0x00040000, 0x10001040, 0x10040040, 0x10000000, 0x00040000, 0x10001040,
0x00000000, 0x10041040, 0x00040040, 0x10000040, 0x00000000, 0x10041040, 0x00040040, 0x10000040,
0x10040000, 0x10001000, 0x10001040, 0x00000000, 0x10040000, 0x10001000, 0x10001040, 0x00000000,
0x10041040, 0x00041000, 0x00041000, 0x00001040, 0x10041040, 0x00041000, 0x00041000, 0x00001040,
0x00001040, 0x00040040, 0x10000000, 0x10041000L} 0x00001040, 0x00040040, 0x10000000, 0x10041000L}
}; };
#define f(R, K0246, K1357) (\ #define f(R, K0246, K1357) (\
@ -519,7 +522,8 @@ static const word32 SPboxes[8][64] = {
bitswap(R, L, 16, 0x0000FFFF), \ bitswap(R, L, 16, 0x0000FFFF), \
bitswap(R, L, 4, 0x0F0F0F0F)) bitswap(R, L, 4, 0x0F0F0F0F))
void des_encipher(word32 *output, word32 L, word32 R, DESContext *sched) { void des_encipher(word32 * output, word32 L, word32 R, DESContext * sched)
{
word32 swap, s0246, s1357; word32 swap, s0246, s1357;
IP(L, R); IP(L, R);
@ -527,16 +531,16 @@ void des_encipher(word32 *output, word32 L, word32 R, DESContext *sched) {
L = rotl(L, 1); L = rotl(L, 1);
R = rotl(R, 1); R = rotl(R, 1);
L ^= f(R, sched->k0246[ 0], sched->k1357[ 0]); L ^= f(R, sched->k0246[0], sched->k1357[0]);
R ^= f(L, sched->k0246[ 1], sched->k1357[ 1]); R ^= f(L, sched->k0246[1], sched->k1357[1]);
L ^= f(R, sched->k0246[ 2], sched->k1357[ 2]); L ^= f(R, sched->k0246[2], sched->k1357[2]);
R ^= f(L, sched->k0246[ 3], sched->k1357[ 3]); R ^= f(L, sched->k0246[3], sched->k1357[3]);
L ^= f(R, sched->k0246[ 4], sched->k1357[ 4]); L ^= f(R, sched->k0246[4], sched->k1357[4]);
R ^= f(L, sched->k0246[ 5], sched->k1357[ 5]); R ^= f(L, sched->k0246[5], sched->k1357[5]);
L ^= f(R, sched->k0246[ 6], sched->k1357[ 6]); L ^= f(R, sched->k0246[6], sched->k1357[6]);
R ^= f(L, sched->k0246[ 7], sched->k1357[ 7]); R ^= f(L, sched->k0246[7], sched->k1357[7]);
L ^= f(R, sched->k0246[ 8], sched->k1357[ 8]); L ^= f(R, sched->k0246[8], sched->k1357[8]);
R ^= f(L, sched->k0246[ 9], sched->k1357[ 9]); R ^= f(L, sched->k0246[9], sched->k1357[9]);
L ^= f(R, sched->k0246[10], sched->k1357[10]); L ^= f(R, sched->k0246[10], sched->k1357[10]);
R ^= f(L, sched->k0246[11], sched->k1357[11]); R ^= f(L, sched->k0246[11], sched->k1357[11]);
L ^= f(R, sched->k0246[12], sched->k1357[12]); L ^= f(R, sched->k0246[12], sched->k1357[12]);
@ -547,7 +551,9 @@ void des_encipher(word32 *output, word32 L, word32 R, DESContext *sched) {
L = rotl(L, 31); L = rotl(L, 31);
R = rotl(R, 31); R = rotl(R, 31);
swap = L; L = R; R = swap; swap = L;
L = R;
R = swap;
FP(L, R); FP(L, R);
@ -555,7 +561,8 @@ void des_encipher(word32 *output, word32 L, word32 R, DESContext *sched) {
output[1] = R; output[1] = R;
} }
void des_decipher(word32 *output, word32 L, word32 R, DESContext *sched) { void des_decipher(word32 * output, word32 L, word32 R, DESContext * sched)
{
word32 swap, s0246, s1357; word32 swap, s0246, s1357;
IP(L, R); IP(L, R);
@ -569,21 +576,23 @@ void des_decipher(word32 *output, word32 L, word32 R, DESContext *sched) {
R ^= f(L, sched->k0246[12], sched->k1357[12]); R ^= f(L, sched->k0246[12], sched->k1357[12]);
L ^= f(R, sched->k0246[11], sched->k1357[11]); L ^= f(R, sched->k0246[11], sched->k1357[11]);
R ^= f(L, sched->k0246[10], sched->k1357[10]); R ^= f(L, sched->k0246[10], sched->k1357[10]);
L ^= f(R, sched->k0246[ 9], sched->k1357[ 9]); L ^= f(R, sched->k0246[9], sched->k1357[9]);
R ^= f(L, sched->k0246[ 8], sched->k1357[ 8]); R ^= f(L, sched->k0246[8], sched->k1357[8]);
L ^= f(R, sched->k0246[ 7], sched->k1357[ 7]); L ^= f(R, sched->k0246[7], sched->k1357[7]);
R ^= f(L, sched->k0246[ 6], sched->k1357[ 6]); R ^= f(L, sched->k0246[6], sched->k1357[6]);
L ^= f(R, sched->k0246[ 5], sched->k1357[ 5]); L ^= f(R, sched->k0246[5], sched->k1357[5]);
R ^= f(L, sched->k0246[ 4], sched->k1357[ 4]); R ^= f(L, sched->k0246[4], sched->k1357[4]);
L ^= f(R, sched->k0246[ 3], sched->k1357[ 3]); L ^= f(R, sched->k0246[3], sched->k1357[3]);
R ^= f(L, sched->k0246[ 2], sched->k1357[ 2]); R ^= f(L, sched->k0246[2], sched->k1357[2]);
L ^= f(R, sched->k0246[ 1], sched->k1357[ 1]); L ^= f(R, sched->k0246[1], sched->k1357[1]);
R ^= f(L, sched->k0246[ 0], sched->k1357[ 0]); R ^= f(L, sched->k0246[0], sched->k1357[0]);
L = rotl(L, 31); L = rotl(L, 31);
R = rotl(R, 31); R = rotl(R, 31);
swap = L; L = R; R = swap; swap = L;
L = R;
R = swap;
FP(L, R); FP(L, R);
@ -604,7 +613,8 @@ void des_decipher(word32 *output, word32 L, word32 R, DESContext *sched) {
(cp)[0] = (value) >> 24; } while (0) (cp)[0] = (value) >> 24; } while (0)
static void des_cbc_encrypt(unsigned char *dest, const unsigned char *src, static void des_cbc_encrypt(unsigned char *dest, const unsigned char *src,
unsigned int len, DESContext *sched) { unsigned int len, DESContext * sched)
{
word32 out[2], iv0, iv1; word32 out[2], iv0, iv1;
unsigned int i; unsigned int i;
@ -613,20 +623,25 @@ static void des_cbc_encrypt(unsigned char *dest, const unsigned char *src,
iv0 = sched->eiv0; iv0 = sched->eiv0;
iv1 = sched->eiv1; iv1 = sched->eiv1;
for (i = 0; i < len; i += 8) { for (i = 0; i < len; i += 8) {
iv0 ^= GET_32BIT_MSB_FIRST(src); src += 4; iv0 ^= GET_32BIT_MSB_FIRST(src);
iv1 ^= GET_32BIT_MSB_FIRST(src); src += 4; src += 4;
des_encipher(out, iv0, iv1, sched); iv1 ^= GET_32BIT_MSB_FIRST(src);
iv0 = out[0]; src += 4;
iv1 = out[1]; des_encipher(out, iv0, iv1, sched);
PUT_32BIT_MSB_FIRST(dest, iv0); dest += 4; iv0 = out[0];
PUT_32BIT_MSB_FIRST(dest, iv1); dest += 4; iv1 = out[1];
PUT_32BIT_MSB_FIRST(dest, iv0);
dest += 4;
PUT_32BIT_MSB_FIRST(dest, iv1);
dest += 4;
} }
sched->eiv0 = iv0; sched->eiv0 = iv0;
sched->eiv1 = iv1; sched->eiv1 = iv1;
} }
static void des_cbc_decrypt(unsigned char *dest, const unsigned char *src, static void des_cbc_decrypt(unsigned char *dest, const unsigned char *src,
unsigned int len, DESContext *sched) { unsigned int len, DESContext * sched)
{
word32 out[2], iv0, iv1, xL, xR; word32 out[2], iv0, iv1, xL, xR;
unsigned int i; unsigned int i;
@ -635,29 +650,35 @@ static void des_cbc_decrypt(unsigned char *dest, const unsigned char *src,
iv0 = sched->div0; iv0 = sched->div0;
iv1 = sched->div1; iv1 = sched->div1;
for (i = 0; i < len; i += 8) { for (i = 0; i < len; i += 8) {
xL = GET_32BIT_MSB_FIRST(src); src += 4; xL = GET_32BIT_MSB_FIRST(src);
xR = GET_32BIT_MSB_FIRST(src); src += 4; src += 4;
des_decipher(out, xL, xR, sched); xR = GET_32BIT_MSB_FIRST(src);
iv0 ^= out[0]; src += 4;
iv1 ^= out[1]; des_decipher(out, xL, xR, sched);
PUT_32BIT_MSB_FIRST(dest, iv0); dest += 4; iv0 ^= out[0];
PUT_32BIT_MSB_FIRST(dest, iv1); dest += 4; iv1 ^= out[1];
iv0 = xL; PUT_32BIT_MSB_FIRST(dest, iv0);
iv1 = xR; dest += 4;
PUT_32BIT_MSB_FIRST(dest, iv1);
dest += 4;
iv0 = xL;
iv1 = xR;
} }
sched->div0 = iv0; sched->div0 = iv0;
sched->div1 = iv1; sched->div1 = iv1;
} }
static void des_3cbc_encrypt(unsigned char *dest, const unsigned char *src, static void des_3cbc_encrypt(unsigned char *dest, const unsigned char *src,
unsigned int len, DESContext *scheds) { unsigned int len, DESContext * scheds)
{
des_cbc_encrypt(dest, src, len, &scheds[0]); des_cbc_encrypt(dest, src, len, &scheds[0]);
des_cbc_decrypt(dest, src, len, &scheds[1]); des_cbc_decrypt(dest, src, len, &scheds[1]);
des_cbc_encrypt(dest, src, len, &scheds[2]); des_cbc_encrypt(dest, src, len, &scheds[2]);
} }
static void des_cbc3_encrypt(unsigned char *dest, const unsigned char *src, static void des_cbc3_encrypt(unsigned char *dest, const unsigned char *src,
unsigned int len, DESContext *scheds) { unsigned int len, DESContext * scheds)
{
word32 out[2], iv0, iv1; word32 out[2], iv0, iv1;
unsigned int i; unsigned int i;
@ -666,29 +687,35 @@ static void des_cbc3_encrypt(unsigned char *dest, const unsigned char *src,
iv0 = scheds->eiv0; iv0 = scheds->eiv0;
iv1 = scheds->eiv1; iv1 = scheds->eiv1;
for (i = 0; i < len; i += 8) { for (i = 0; i < len; i += 8) {
iv0 ^= GET_32BIT_MSB_FIRST(src); src += 4; iv0 ^= GET_32BIT_MSB_FIRST(src);
iv1 ^= GET_32BIT_MSB_FIRST(src); src += 4; src += 4;
des_encipher(out, iv0, iv1, &scheds[0]); iv1 ^= GET_32BIT_MSB_FIRST(src);
des_decipher(out, out[0], out[1], &scheds[1]); src += 4;
des_encipher(out, out[0], out[1], &scheds[2]); des_encipher(out, iv0, iv1, &scheds[0]);
iv0 = out[0]; des_decipher(out, out[0], out[1], &scheds[1]);
iv1 = out[1]; des_encipher(out, out[0], out[1], &scheds[2]);
PUT_32BIT_MSB_FIRST(dest, iv0); dest += 4; iv0 = out[0];
PUT_32BIT_MSB_FIRST(dest, iv1); dest += 4; iv1 = out[1];
PUT_32BIT_MSB_FIRST(dest, iv0);
dest += 4;
PUT_32BIT_MSB_FIRST(dest, iv1);
dest += 4;
} }
scheds->eiv0 = iv0; scheds->eiv0 = iv0;
scheds->eiv1 = iv1; scheds->eiv1 = iv1;
} }
static void des_3cbc_decrypt(unsigned char *dest, const unsigned char *src, static void des_3cbc_decrypt(unsigned char *dest, const unsigned char *src,
unsigned int len, DESContext *scheds) { unsigned int len, DESContext * scheds)
{
des_cbc_decrypt(dest, src, len, &scheds[2]); des_cbc_decrypt(dest, src, len, &scheds[2]);
des_cbc_encrypt(dest, src, len, &scheds[1]); des_cbc_encrypt(dest, src, len, &scheds[1]);
des_cbc_decrypt(dest, src, len, &scheds[0]); des_cbc_decrypt(dest, src, len, &scheds[0]);
} }
static void des_cbc3_decrypt(unsigned char *dest, const unsigned char *src, static void des_cbc3_decrypt(unsigned char *dest, const unsigned char *src,
unsigned int len, DESContext *scheds) { unsigned int len, DESContext * scheds)
{
word32 out[2], iv0, iv1, xL, xR; word32 out[2], iv0, iv1, xL, xR;
unsigned int i; unsigned int i;
@ -697,17 +724,21 @@ static void des_cbc3_decrypt(unsigned char *dest, const unsigned char *src,
iv0 = scheds->div0; iv0 = scheds->div0;
iv1 = scheds->div1; iv1 = scheds->div1;
for (i = 0; i < len; i += 8) { for (i = 0; i < len; i += 8) {
xL = GET_32BIT_MSB_FIRST(src); src += 4; xL = GET_32BIT_MSB_FIRST(src);
xR = GET_32BIT_MSB_FIRST(src); src += 4; src += 4;
des_decipher(out, xL, xR, &scheds[2]); xR = GET_32BIT_MSB_FIRST(src);
des_encipher(out, out[0], out[1], &scheds[1]); src += 4;
des_decipher(out, out[0], out[1], &scheds[0]); des_decipher(out, xL, xR, &scheds[2]);
iv0 ^= out[0]; des_encipher(out, out[0], out[1], &scheds[1]);
iv1 ^= out[1]; des_decipher(out, out[0], out[1], &scheds[0]);
PUT_32BIT_MSB_FIRST(dest, iv0); dest += 4; iv0 ^= out[0];
PUT_32BIT_MSB_FIRST(dest, iv1); dest += 4; iv1 ^= out[1];
iv0 = xL; PUT_32BIT_MSB_FIRST(dest, iv0);
iv1 = xR; dest += 4;
PUT_32BIT_MSB_FIRST(dest, iv1);
dest += 4;
iv0 = xL;
iv1 = xR;
} }
scheds->div0 = iv0; scheds->div0 = iv0;
scheds->div1 = iv1; scheds->div1 = iv1;
@ -715,78 +746,87 @@ static void des_cbc3_decrypt(unsigned char *dest, const unsigned char *src,
static DESContext cskeys[3], sckeys[3]; static DESContext cskeys[3], sckeys[3];
static void des3_cskey(unsigned char *key) { static void des3_cskey(unsigned char *key)
{
des_key_setup(GET_32BIT_MSB_FIRST(key), des_key_setup(GET_32BIT_MSB_FIRST(key),
GET_32BIT_MSB_FIRST(key+4), &cskeys[0]); GET_32BIT_MSB_FIRST(key + 4), &cskeys[0]);
des_key_setup(GET_32BIT_MSB_FIRST(key+8), des_key_setup(GET_32BIT_MSB_FIRST(key + 8),
GET_32BIT_MSB_FIRST(key+12), &cskeys[1]); GET_32BIT_MSB_FIRST(key + 12), &cskeys[1]);
des_key_setup(GET_32BIT_MSB_FIRST(key+16), des_key_setup(GET_32BIT_MSB_FIRST(key + 16),
GET_32BIT_MSB_FIRST(key+20), &cskeys[2]); GET_32BIT_MSB_FIRST(key + 20), &cskeys[2]);
logevent("Initialised triple-DES client->server encryption"); logevent("Initialised triple-DES client->server encryption");
} }
static void des3_csiv(unsigned char *key) { static void des3_csiv(unsigned char *key)
{
cskeys[0].eiv0 = GET_32BIT_MSB_FIRST(key); cskeys[0].eiv0 = GET_32BIT_MSB_FIRST(key);
cskeys[0].eiv1 = GET_32BIT_MSB_FIRST(key+4); cskeys[0].eiv1 = GET_32BIT_MSB_FIRST(key + 4);
} }
static void des3_sciv(unsigned char *key) { static void des3_sciv(unsigned char *key)
{
sckeys[0].div0 = GET_32BIT_MSB_FIRST(key); sckeys[0].div0 = GET_32BIT_MSB_FIRST(key);
sckeys[0].div1 = GET_32BIT_MSB_FIRST(key+4); sckeys[0].div1 = GET_32BIT_MSB_FIRST(key + 4);
} }
static void des3_sckey(unsigned char *key) { static void des3_sckey(unsigned char *key)
{
des_key_setup(GET_32BIT_MSB_FIRST(key), des_key_setup(GET_32BIT_MSB_FIRST(key),
GET_32BIT_MSB_FIRST(key+4), &sckeys[0]); GET_32BIT_MSB_FIRST(key + 4), &sckeys[0]);
des_key_setup(GET_32BIT_MSB_FIRST(key+8), des_key_setup(GET_32BIT_MSB_FIRST(key + 8),
GET_32BIT_MSB_FIRST(key+12), &sckeys[1]); GET_32BIT_MSB_FIRST(key + 12), &sckeys[1]);
des_key_setup(GET_32BIT_MSB_FIRST(key+16), des_key_setup(GET_32BIT_MSB_FIRST(key + 16),
GET_32BIT_MSB_FIRST(key+20), &sckeys[2]); GET_32BIT_MSB_FIRST(key + 20), &sckeys[2]);
logevent("Initialised triple-DES server->client encryption"); logevent("Initialised triple-DES server->client encryption");
} }
static void des3_sesskey(unsigned char *key) { static void des3_sesskey(unsigned char *key)
{
des3_cskey(key); des3_cskey(key);
des3_sckey(key); des3_sckey(key);
} }
static void des3_encrypt_blk(unsigned char *blk, int len) { static void des3_encrypt_blk(unsigned char *blk, int len)
{
des_3cbc_encrypt(blk, blk, len, cskeys); des_3cbc_encrypt(blk, blk, len, cskeys);
} }
static void des3_decrypt_blk(unsigned char *blk, int len) { static void des3_decrypt_blk(unsigned char *blk, int len)
{
des_3cbc_decrypt(blk, blk, len, sckeys); des_3cbc_decrypt(blk, blk, len, sckeys);
} }
static void des3_ssh2_encrypt_blk(unsigned char *blk, int len) { static void des3_ssh2_encrypt_blk(unsigned char *blk, int len)
{
des_cbc3_encrypt(blk, blk, len, cskeys); des_cbc3_encrypt(blk, blk, len, cskeys);
} }
static void des3_ssh2_decrypt_blk(unsigned char *blk, int len) { static void des3_ssh2_decrypt_blk(unsigned char *blk, int len)
{
des_cbc3_decrypt(blk, blk, len, sckeys); des_cbc3_decrypt(blk, blk, len, sckeys);
} }
void des3_decrypt_pubkey(unsigned char *key, void des3_decrypt_pubkey(unsigned char *key, unsigned char *blk, int len)
unsigned char *blk, int len) { {
DESContext ourkeys[3]; DESContext ourkeys[3];
des_key_setup(GET_32BIT_MSB_FIRST(key), des_key_setup(GET_32BIT_MSB_FIRST(key),
GET_32BIT_MSB_FIRST(key+4), &ourkeys[0]); GET_32BIT_MSB_FIRST(key + 4), &ourkeys[0]);
des_key_setup(GET_32BIT_MSB_FIRST(key+8), des_key_setup(GET_32BIT_MSB_FIRST(key + 8),
GET_32BIT_MSB_FIRST(key+12), &ourkeys[1]); GET_32BIT_MSB_FIRST(key + 12), &ourkeys[1]);
des_key_setup(GET_32BIT_MSB_FIRST(key), des_key_setup(GET_32BIT_MSB_FIRST(key),
GET_32BIT_MSB_FIRST(key+4), &ourkeys[2]); GET_32BIT_MSB_FIRST(key + 4), &ourkeys[2]);
des_3cbc_decrypt(blk, blk, len, ourkeys); des_3cbc_decrypt(blk, blk, len, ourkeys);
} }
void des3_encrypt_pubkey(unsigned char *key, void des3_encrypt_pubkey(unsigned char *key, unsigned char *blk, int len)
unsigned char *blk, int len) { {
DESContext ourkeys[3]; DESContext ourkeys[3];
des_key_setup(GET_32BIT_MSB_FIRST(key), des_key_setup(GET_32BIT_MSB_FIRST(key),
GET_32BIT_MSB_FIRST(key+4), &ourkeys[0]); GET_32BIT_MSB_FIRST(key + 4), &ourkeys[0]);
des_key_setup(GET_32BIT_MSB_FIRST(key+8), des_key_setup(GET_32BIT_MSB_FIRST(key + 8),
GET_32BIT_MSB_FIRST(key+12), &ourkeys[1]); GET_32BIT_MSB_FIRST(key + 12), &ourkeys[1]);
des_key_setup(GET_32BIT_MSB_FIRST(key), des_key_setup(GET_32BIT_MSB_FIRST(key),
GET_32BIT_MSB_FIRST(key+4), &ourkeys[2]); GET_32BIT_MSB_FIRST(key + 4), &ourkeys[2]);
des_3cbc_encrypt(blk, blk, len, ourkeys); des_3cbc_encrypt(blk, blk, len, ourkeys);
} }
@ -815,17 +855,20 @@ const struct ssh_cipher ssh_3des = {
8 8
}; };
static void des_sesskey(unsigned char *key) { static void des_sesskey(unsigned char *key)
{
des_key_setup(GET_32BIT_MSB_FIRST(key), des_key_setup(GET_32BIT_MSB_FIRST(key),
GET_32BIT_MSB_FIRST(key+4), &cskeys[0]); GET_32BIT_MSB_FIRST(key + 4), &cskeys[0]);
logevent("Initialised single-DES encryption"); logevent("Initialised single-DES encryption");
} }
static void des_encrypt_blk(unsigned char *blk, int len) { static void des_encrypt_blk(unsigned char *blk, int len)
{
des_cbc_encrypt(blk, blk, len, cskeys); des_cbc_encrypt(blk, blk, len, cskeys);
} }
static void des_decrypt_blk(unsigned char *blk, int len) { static void des_decrypt_blk(unsigned char *blk, int len)
{
des_cbc_decrypt(blk, blk, len, cskeys); des_cbc_decrypt(blk, blk, len, cskeys);
} }

21
sshdh.c
View File

@ -39,7 +39,8 @@ static int need_to_free_pg;
/* /*
* Common DH initialisation. * Common DH initialisation.
*/ */
static void dh_init(void) { static void dh_init(void)
{
q = bignum_rshift(p, 1); q = bignum_rshift(p, 1);
qmask = bignum_bitmask(q); qmask = bignum_bitmask(q);
} }
@ -47,7 +48,8 @@ static void dh_init(void) {
/* /*
* Initialise DH for the standard group1. * Initialise DH for the standard group1.
*/ */
void dh_setup_group1(void) { void dh_setup_group1(void)
{
p = bignum_from_bytes(P, sizeof(P)); p = bignum_from_bytes(P, sizeof(P));
g = bignum_from_bytes(G, sizeof(G)); g = bignum_from_bytes(G, sizeof(G));
dh_init(); dh_init();
@ -56,7 +58,8 @@ void dh_setup_group1(void) {
/* /*
* Initialise DH for an alternative group. * Initialise DH for an alternative group.
*/ */
void dh_setup_group(Bignum pval, Bignum gval) { void dh_setup_group(Bignum pval, Bignum gval)
{
p = copybn(pval); p = copybn(pval);
g = copybn(gval); g = copybn(gval);
dh_init(); dh_init();
@ -65,7 +68,8 @@ void dh_setup_group(Bignum pval, Bignum gval) {
/* /*
* Clean up. * Clean up.
*/ */
void dh_cleanup(void) { void dh_cleanup(void)
{
freebn(p); freebn(p);
freebn(g); freebn(g);
freebn(q); freebn(q);
@ -87,7 +91,8 @@ void dh_cleanup(void) {
* Advances in Cryptology: Proceedings of Eurocrypt '96 * Advances in Cryptology: Proceedings of Eurocrypt '96
* Springer-Verlag, May 1996. * Springer-Verlag, May 1996.
*/ */
Bignum dh_create_e(int nbits) { Bignum dh_create_e(int nbits)
{
int i; int i;
int nbytes; int nbytes;
@ -101,7 +106,8 @@ Bignum dh_create_e(int nbits) {
* Create a potential x, by ANDing a string of random bytes * Create a potential x, by ANDing a string of random bytes
* with qmask. * with qmask.
*/ */
if (x) freebn(x); if (x)
freebn(x);
if (nbits == 0 || nbits > bignum_bitcount(qmask)) { if (nbits == 0 || nbits > bignum_bitcount(qmask)) {
ssh1_write_bignum(buf, qmask); ssh1_write_bignum(buf, qmask);
for (i = 2; i < nbytes; i++) for (i = 2; i < nbytes; i++)
@ -134,7 +140,8 @@ Bignum dh_create_e(int nbits) {
/* /*
* DH stage 2: given a number f, compute K = f^x mod p. * DH stage 2: given a number f, compute K = f^x mod p.
*/ */
Bignum dh_find_K(Bignum f) { Bignum dh_find_K(Bignum f)
{
Bignum ret; Bignum ret;
ret = modpow(f, x, p); ret = modpow(f, x, p);
return ret; return ret;

220
sshdss.c
View File

@ -22,36 +22,42 @@
#define diagbn(x,y) #define diagbn(x,y)
#endif #endif
static void getstring(char **data, int *datalen, char **p, int *length) { static void getstring(char **data, int *datalen, char **p, int *length)
{
*p = NULL; *p = NULL;
if (*datalen < 4) if (*datalen < 4)
return; return;
*length = GET_32BIT(*data); *length = GET_32BIT(*data);
*datalen -= 4; *data += 4; *datalen -= 4;
*data += 4;
if (*datalen < *length) if (*datalen < *length)
return; return;
*p = *data; *p = *data;
*data += *length; *datalen -= *length; *data += *length;
*datalen -= *length;
} }
static Bignum getmp(char **data, int *datalen) { static Bignum getmp(char **data, int *datalen)
{
char *p; char *p;
int length; int length;
Bignum b; Bignum b;
getstring(data, datalen, &p, &length); getstring(data, datalen, &p, &length);
if (!p) if (!p)
return NULL; return NULL;
if (p[0] & 0x80) if (p[0] & 0x80)
return NULL; /* negative mp */ return NULL; /* negative mp */
b = bignum_from_bytes(p, length); b = bignum_from_bytes(p, length);
return b; return b;
} }
static Bignum get160(char **data, int *datalen) { static Bignum get160(char **data, int *datalen)
{
Bignum b; Bignum b;
b = bignum_from_bytes(*data, 20); b = bignum_from_bytes(*data, 20);
*data += 20; *datalen -= 20; *data += 20;
*datalen -= 20;
return b; return b;
} }
@ -60,22 +66,24 @@ struct dss_key {
Bignum p, q, g, y; Bignum p, q, g, y;
}; };
static void *dss_newkey(char *data, int len) { static void *dss_newkey(char *data, int len)
{
char *p; char *p;
int slen; int slen;
struct dss_key *dss; struct dss_key *dss;
dss = smalloc(sizeof(struct dss_key)); dss = smalloc(sizeof(struct dss_key));
if (!dss) return NULL; if (!dss)
return NULL;
getstring(&data, &len, &p, &slen); getstring(&data, &len, &p, &slen);
#ifdef DEBUG_DSS #ifdef DEBUG_DSS
{ {
int i; int i;
printf("key:"); printf("key:");
for (i=0;i<len;i++) for (i = 0; i < len; i++)
printf(" %02x", (unsigned char)(data[i])); printf(" %02x", (unsigned char) (data[i]));
printf("\n"); printf("\n");
} }
#endif #endif
@ -91,8 +99,9 @@ static void *dss_newkey(char *data, int len) {
return dss; return dss;
} }
static void dss_freekey(void *key) { static void dss_freekey(void *key)
struct dss_key *dss = (struct dss_key *)key; {
struct dss_key *dss = (struct dss_key *) key;
freebn(dss->p); freebn(dss->p);
freebn(dss->q); freebn(dss->q);
freebn(dss->g); freebn(dss->g);
@ -100,47 +109,62 @@ static void dss_freekey(void *key) {
sfree(dss); sfree(dss);
} }
static char *dss_fmtkey(void *key) { static char *dss_fmtkey(void *key)
struct dss_key *dss = (struct dss_key *)key; {
struct dss_key *dss = (struct dss_key *) key;
char *p; char *p;
int len, i, pos, nibbles; int len, i, pos, nibbles;
static const char hex[] = "0123456789abcdef"; static const char hex[] = "0123456789abcdef";
if (!dss->p) if (!dss->p)
return NULL; return NULL;
len = 8 + 4 + 1; /* 4 x "0x", punctuation, \0 */ len = 8 + 4 + 1; /* 4 x "0x", punctuation, \0 */
len += 4 * (bignum_bitcount(dss->p)+15)/16; len += 4 * (bignum_bitcount(dss->p) + 15) / 16;
len += 4 * (bignum_bitcount(dss->q)+15)/16; len += 4 * (bignum_bitcount(dss->q) + 15) / 16;
len += 4 * (bignum_bitcount(dss->g)+15)/16; len += 4 * (bignum_bitcount(dss->g) + 15) / 16;
len += 4 * (bignum_bitcount(dss->y)+15)/16; len += 4 * (bignum_bitcount(dss->y) + 15) / 16;
p = smalloc(len); p = smalloc(len);
if (!p) return NULL; if (!p)
return NULL;
pos = 0; pos = 0;
pos += sprintf(p+pos, "0x"); pos += sprintf(p + pos, "0x");
nibbles = (3 + bignum_bitcount(dss->p))/4; if (nibbles<1) nibbles=1; nibbles = (3 + bignum_bitcount(dss->p)) / 4;
for (i=nibbles; i-- ;) if (nibbles < 1)
p[pos++] = hex[(bignum_byte(dss->p, i/2) >> (4*(i%2))) & 0xF]; nibbles = 1;
pos += sprintf(p+pos, ",0x"); for (i = nibbles; i--;)
nibbles = (3 + bignum_bitcount(dss->q))/4; if (nibbles<1) nibbles=1; p[pos++] =
for (i=nibbles; i-- ;) hex[(bignum_byte(dss->p, i / 2) >> (4 * (i % 2))) & 0xF];
p[pos++] = hex[(bignum_byte(dss->q, i/2) >> (4*(i%2))) & 0xF]; pos += sprintf(p + pos, ",0x");
pos += sprintf(p+pos, ",0x"); nibbles = (3 + bignum_bitcount(dss->q)) / 4;
nibbles = (3 + bignum_bitcount(dss->g))/4; if (nibbles<1) nibbles=1; if (nibbles < 1)
for (i=nibbles; i-- ;) nibbles = 1;
p[pos++] = hex[(bignum_byte(dss->g, i/2) >> (4*(i%2))) & 0xF]; for (i = nibbles; i--;)
pos += sprintf(p+pos, ",0x"); p[pos++] =
nibbles = (3 + bignum_bitcount(dss->y))/4; if (nibbles<1) nibbles=1; hex[(bignum_byte(dss->q, i / 2) >> (4 * (i % 2))) & 0xF];
for (i=nibbles; i-- ;) pos += sprintf(p + pos, ",0x");
p[pos++] = hex[(bignum_byte(dss->y, i/2) >> (4*(i%2))) & 0xF]; nibbles = (3 + bignum_bitcount(dss->g)) / 4;
if (nibbles < 1)
nibbles = 1;
for (i = nibbles; i--;)
p[pos++] =
hex[(bignum_byte(dss->g, i / 2) >> (4 * (i % 2))) & 0xF];
pos += sprintf(p + pos, ",0x");
nibbles = (3 + bignum_bitcount(dss->y)) / 4;
if (nibbles < 1)
nibbles = 1;
for (i = nibbles; i--;)
p[pos++] =
hex[(bignum_byte(dss->y, i / 2) >> (4 * (i % 2))) & 0xF];
p[pos] = '\0'; p[pos] = '\0';
return p; return p;
} }
static char *dss_fingerprint(void *key) { static char *dss_fingerprint(void *key)
struct dss_key *dss = (struct dss_key *)key; {
struct dss_key *dss = (struct dss_key *) key;
struct MD5Context md5c; struct MD5Context md5c;
unsigned char digest[16], lenbuf[4]; unsigned char digest[16], lenbuf[4];
char buffer[16*3+40]; char buffer[16 * 3 + 40];
char *ret; char *ret;
int numlen, i; int numlen, i;
@ -164,16 +188,18 @@ static char *dss_fingerprint(void *key) {
sprintf(buffer, "ssh-dss %d ", bignum_bitcount(dss->p)); sprintf(buffer, "ssh-dss %d ", bignum_bitcount(dss->p));
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)
sprintf(buffer+strlen(buffer), "%s%02x", i?":":"", digest[i]); sprintf(buffer + strlen(buffer), "%s%02x", i ? ":" : "",
ret = smalloc(strlen(buffer)+1); digest[i]);
ret = smalloc(strlen(buffer) + 1);
if (ret) if (ret)
strcpy(ret, buffer); strcpy(ret, buffer);
return ret; return ret;
} }
static int dss_verifysig(void *key, char *sig, int siglen, static int dss_verifysig(void *key, char *sig, int siglen,
char *data, int datalen) { char *data, int datalen)
struct dss_key *dss = (struct dss_key *)key; {
struct dss_key *dss = (struct dss_key *) key;
char *p; char *p;
int slen; int slen;
char hash[20]; char hash[20];
@ -181,15 +207,15 @@ static int dss_verifysig(void *key, char *sig, int siglen,
int ret; int ret;
if (!dss->p) if (!dss->p)
return 0; return 0;
#ifdef DEBUG_DSS #ifdef DEBUG_DSS
{ {
int i; int i;
printf("sig:"); printf("sig:");
for (i=0;i<siglen;i++) for (i = 0; i < siglen; i++)
printf(" %02x", (unsigned char)(sig[i])); printf(" %02x", (unsigned char) (sig[i]));
printf("\n"); printf("\n");
} }
#endif #endif
/* /*
@ -203,12 +229,12 @@ static int dss_verifysig(void *key, char *sig, int siglen,
* the length: length 40 means the commercial-SSH bug, anything * the length: length 40 means the commercial-SSH bug, anything
* else is assumed to be IETF-compliant. * else is assumed to be IETF-compliant.
*/ */
if (siglen != 40) { /* bug not present; read admin fields */ if (siglen != 40) { /* bug not present; read admin fields */
getstring(&sig, &siglen, &p, &slen); getstring(&sig, &siglen, &p, &slen);
if (!p || slen != 7 || memcmp(p, "ssh-dss", 7)) { if (!p || slen != 7 || memcmp(p, "ssh-dss", 7)) {
return 0; return 0;
} }
sig += 4, siglen -= 4; /* skip yet another length field */ sig += 4, siglen -= 4; /* skip yet another length field */
} }
diagbn("p=", dss->p); diagbn("p=", dss->p);
diagbn("q=", dss->q); diagbn("q=", dss->q);
@ -219,7 +245,7 @@ static int dss_verifysig(void *key, char *sig, int siglen,
s = get160(&sig, &siglen); s = get160(&sig, &siglen);
diagbn("s=", s); diagbn("s=", s);
if (!r || !s) if (!r || !s)
return 0; return 0;
/* /*
* Step 1. w <- s^-1 mod q. * Step 1. w <- s^-1 mod q.
@ -231,7 +257,9 @@ static int dss_verifysig(void *key, char *sig, int siglen,
* Step 2. u1 <- SHA(message) * w mod q. * Step 2. u1 <- SHA(message) * w mod q.
*/ */
SHA_Simple(data, datalen, hash); SHA_Simple(data, datalen, hash);
p = hash; slen = 20; sha = get160(&p, &slen); p = hash;
slen = 20;
sha = get160(&p, &slen);
diagbn("sha=", sha); diagbn("sha=", sha);
u1 = modmul(sha, w, dss->q); u1 = modmul(sha, w, dss->q);
diagbn("u1=", u1); diagbn("u1=", u1);
@ -273,57 +301,73 @@ static int dss_verifysig(void *key, char *sig, int siglen,
return ret; return ret;
} }
static unsigned char *dss_public_blob(void *key, int *len) { static unsigned char *dss_public_blob(void *key, int *len)
struct dss_key *dss = (struct dss_key *)key; {
struct dss_key *dss = (struct dss_key *) key;
int plen, qlen, glen, ylen, bloblen; int plen, qlen, glen, ylen, bloblen;
int i; int i;
unsigned char *blob, *p; unsigned char *blob, *p;
plen = (bignum_bitcount(dss->p)+8)/8; plen = (bignum_bitcount(dss->p) + 8) / 8;
qlen = (bignum_bitcount(dss->q)+8)/8; qlen = (bignum_bitcount(dss->q) + 8) / 8;
glen = (bignum_bitcount(dss->g)+8)/8; glen = (bignum_bitcount(dss->g) + 8) / 8;
ylen = (bignum_bitcount(dss->y)+8)/8; ylen = (bignum_bitcount(dss->y) + 8) / 8;
/* /*
* string "ssh-dss", mpint p, mpint q, mpint g, mpint y. Total * string "ssh-dss", mpint p, mpint q, mpint g, mpint y. Total
* 27 + sum of lengths. (five length fields, 20+7=27). * 27 + sum of lengths. (five length fields, 20+7=27).
*/ */
bloblen = 27+plen+qlen+glen+ylen; bloblen = 27 + plen + qlen + glen + ylen;
blob = smalloc(bloblen); blob = smalloc(bloblen);
p = blob; p = blob;
PUT_32BIT(p, 7); p += 4; PUT_32BIT(p, 7);
memcpy(p, "ssh-dss", 7); p += 7; p += 4;
PUT_32BIT(p, plen); p += 4; memcpy(p, "ssh-dss", 7);
for (i = plen; i-- ;) *p++ = bignum_byte(dss->p, i); p += 7;
PUT_32BIT(p, qlen); p += 4; PUT_32BIT(p, plen);
for (i = qlen; i-- ;) *p++ = bignum_byte(dss->q, i); p += 4;
PUT_32BIT(p, glen); p += 4; for (i = plen; i--;)
for (i = glen; i-- ;) *p++ = bignum_byte(dss->g, i); *p++ = bignum_byte(dss->p, i);
PUT_32BIT(p, ylen); p += 4; PUT_32BIT(p, qlen);
for (i = ylen; i-- ;) *p++ = bignum_byte(dss->y, i); p += 4;
for (i = qlen; i--;)
*p++ = bignum_byte(dss->q, i);
PUT_32BIT(p, glen);
p += 4;
for (i = glen; i--;)
*p++ = bignum_byte(dss->g, i);
PUT_32BIT(p, ylen);
p += 4;
for (i = ylen; i--;)
*p++ = bignum_byte(dss->y, i);
assert(p == blob + bloblen); assert(p == blob + bloblen);
*len = bloblen; *len = bloblen;
return blob; return blob;
} }
static unsigned char *dss_private_blob(void *key, int *len) { static unsigned char *dss_private_blob(void *key, int *len)
{
return NULL; /* can't handle DSS private keys */ return NULL; /* can't handle DSS private keys */
} }
static void *dss_createkey(unsigned char *pub_blob, int pub_len, static void *dss_createkey(unsigned char *pub_blob, int pub_len,
unsigned char *priv_blob, int priv_len) { unsigned char *priv_blob, int priv_len)
{
return NULL; /* can't handle DSS private keys */ return NULL; /* can't handle DSS private keys */
} }
static void *dss_openssh_createkey(unsigned char **blob, int *len) { static void *dss_openssh_createkey(unsigned char **blob, int *len)
{
return NULL; /* can't handle DSS private keys */ return NULL; /* can't handle DSS private keys */
} }
static int dss_openssh_fmtkey(void *key, unsigned char *blob, int len) { static int dss_openssh_fmtkey(void *key, unsigned char *blob, int len)
{
return -1; /* can't handle DSS private keys */ return -1; /* can't handle DSS private keys */
} }
unsigned char *dss_sign(void *key, char *data, int datalen, int *siglen) { unsigned char *dss_sign(void *key, char *data, int datalen, int *siglen)
{
return NULL; /* can't handle DSS private keys */ return NULL; /* can't handle DSS private keys */
} }

146
sshmd5.c
View File

@ -19,17 +19,22 @@
#define subround(f,w,x,y,z,k,s,ti) \ #define subround(f,w,x,y,z,k,s,ti) \
w = x + rol(w + f(x,y,z) + block[k] + ti, s) w = x + rol(w + f(x,y,z) + block[k] + ti, s)
void MD5_Core_Init(MD5_Core_State *s) { void MD5_Core_Init(MD5_Core_State * s)
{
s->h[0] = 0x67452301; s->h[0] = 0x67452301;
s->h[1] = 0xefcdab89; s->h[1] = 0xefcdab89;
s->h[2] = 0x98badcfe; s->h[2] = 0x98badcfe;
s->h[3] = 0x10325476; s->h[3] = 0x10325476;
} }
void MD5_Block(MD5_Core_State *s, uint32 *block) { void MD5_Block(MD5_Core_State * s, uint32 * block)
uint32 a,b,c,d; {
uint32 a, b, c, d;
a = s->h[0]; b = s->h[1]; c = s->h[2]; d = s->h[3]; a = s->h[0];
b = s->h[1];
c = s->h[2];
d = s->h[3];
subround(F, a, b, c, d, 0, 7, 0xd76aa478); subround(F, a, b, c, d, 0, 7, 0xd76aa478);
subround(F, d, a, b, c, 1, 12, 0xe8c7b756); subround(F, d, a, b, c, 1, 12, 0xe8c7b756);
@ -96,7 +101,10 @@ void MD5_Block(MD5_Core_State *s, uint32 *block) {
subround(I, c, d, a, b, 2, 15, 0x2ad7d2bb); subround(I, c, d, a, b, 2, 15, 0x2ad7d2bb);
subround(I, b, c, d, a, 9, 21, 0xeb86d391); subround(I, b, c, d, a, 9, 21, 0xeb86d391);
s->h[0] += a; s->h[1] += b; s->h[2] += c; s->h[3] += d; s->h[0] += a;
s->h[1] += b;
s->h[2] += c;
s->h[3] += d;
} }
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
@ -107,15 +115,16 @@ void MD5_Block(MD5_Core_State *s, uint32 *block) {
#define BLKSIZE 64 #define BLKSIZE 64
void MD5Init(struct MD5Context *s) { void MD5Init(struct MD5Context *s)
{
MD5_Core_Init(&s->core); MD5_Core_Init(&s->core);
s->blkused = 0; s->blkused = 0;
s->lenhi = s->lenlo = 0; s->lenhi = s->lenlo = 0;
} }
void MD5Update(struct MD5Context *s, unsigned char const *p, void MD5Update(struct MD5Context *s, unsigned char const *p, unsigned len)
unsigned len) { {
unsigned char *q = (unsigned char *)p; unsigned char *q = (unsigned char *) p;
uint32 wordblock[16]; uint32 wordblock[16];
uint32 lenw = len; uint32 lenw = len;
int i; int i;
@ -126,48 +135,49 @@ void MD5Update(struct MD5Context *s, unsigned char const *p,
s->lenlo += lenw; s->lenlo += lenw;
s->lenhi += (s->lenlo < lenw); s->lenhi += (s->lenlo < lenw);
if (s->blkused+len < BLKSIZE) { if (s->blkused + len < BLKSIZE) {
/* /*
* Trivial case: just add to the block. * Trivial case: just add to the block.
*/ */
memcpy(s->block + s->blkused, q, len); memcpy(s->block + s->blkused, q, len);
s->blkused += len; s->blkused += len;
} else { } else {
/* /*
* We must complete and process at least one block. * We must complete and process at least one block.
*/ */
while (s->blkused + len >= BLKSIZE) { while (s->blkused + len >= BLKSIZE) {
memcpy(s->block + s->blkused, q, BLKSIZE - s->blkused); memcpy(s->block + s->blkused, q, BLKSIZE - s->blkused);
q += BLKSIZE - s->blkused; q += BLKSIZE - s->blkused;
len -= BLKSIZE - s->blkused; len -= BLKSIZE - s->blkused;
/* Now process the block. Gather bytes little-endian into words */ /* Now process the block. Gather bytes little-endian into words */
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
wordblock[i] = wordblock[i] =
( ((uint32)s->block[i*4+3]) << 24 ) | (((uint32) s->block[i * 4 + 3]) << 24) |
( ((uint32)s->block[i*4+2]) << 16 ) | (((uint32) s->block[i * 4 + 2]) << 16) |
( ((uint32)s->block[i*4+1]) << 8 ) | (((uint32) s->block[i * 4 + 1]) << 8) |
( ((uint32)s->block[i*4+0]) << 0 ); (((uint32) s->block[i * 4 + 0]) << 0);
} }
MD5_Block(&s->core, wordblock); MD5_Block(&s->core, wordblock);
s->blkused = 0; s->blkused = 0;
} }
memcpy(s->block, q, len); memcpy(s->block, q, len);
s->blkused = len; s->blkused = len;
} }
} }
void MD5Final(unsigned char output[16], struct MD5Context *s) { void MD5Final(unsigned char output[16], struct MD5Context *s)
{
int i; int i;
unsigned pad; unsigned pad;
unsigned char c[64]; unsigned char c[64];
uint32 lenhi, lenlo; uint32 lenhi, lenlo;
if (s->blkused >= 56) if (s->blkused >= 56)
pad = 56 + 64 - s->blkused; pad = 56 + 64 - s->blkused;
else else
pad = 56 - s->blkused; pad = 56 - s->blkused;
lenhi = (s->lenhi << 3) | (s->lenlo >> (32-3)); lenhi = (s->lenhi << 3) | (s->lenlo >> (32 - 3));
lenlo = (s->lenlo << 3); lenlo = (s->lenlo << 3);
memset(c, 0, pad); memset(c, 0, pad);
@ -176,20 +186,20 @@ void MD5Final(unsigned char output[16], struct MD5Context *s) {
c[7] = (lenhi >> 24) & 0xFF; c[7] = (lenhi >> 24) & 0xFF;
c[6] = (lenhi >> 16) & 0xFF; c[6] = (lenhi >> 16) & 0xFF;
c[5] = (lenhi >> 8) & 0xFF; c[5] = (lenhi >> 8) & 0xFF;
c[4] = (lenhi >> 0) & 0xFF; c[4] = (lenhi >> 0) & 0xFF;
c[3] = (lenlo >> 24) & 0xFF; c[3] = (lenlo >> 24) & 0xFF;
c[2] = (lenlo >> 16) & 0xFF; c[2] = (lenlo >> 16) & 0xFF;
c[1] = (lenlo >> 8) & 0xFF; c[1] = (lenlo >> 8) & 0xFF;
c[0] = (lenlo >> 0) & 0xFF; c[0] = (lenlo >> 0) & 0xFF;
MD5Update(s, c, 8); MD5Update(s, c, 8);
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
output[4*i+3] = (s->core.h[i] >> 24) & 0xFF; output[4 * i + 3] = (s->core.h[i] >> 24) & 0xFF;
output[4*i+2] = (s->core.h[i] >> 16) & 0xFF; output[4 * i + 2] = (s->core.h[i] >> 16) & 0xFF;
output[4*i+1] = (s->core.h[i] >> 8) & 0xFF; output[4 * i + 1] = (s->core.h[i] >> 8) & 0xFF;
output[4*i+0] = (s->core.h[i] >> 0) & 0xFF; output[4 * i + 0] = (s->core.h[i] >> 0) & 0xFF;
} }
} }
@ -202,61 +212,67 @@ static struct MD5Context md5_cs_mac_s1, md5_cs_mac_s2;
static struct MD5Context md5_sc_mac_s1, md5_sc_mac_s2; static struct MD5Context md5_sc_mac_s1, md5_sc_mac_s2;
static void md5_key(struct MD5Context *s1, struct MD5Context *s2, static void md5_key(struct MD5Context *s1, struct MD5Context *s2,
unsigned char *key, int len) { unsigned char *key, int len)
{
unsigned char foo[64]; unsigned char foo[64];
int i; int i;
memset(foo, 0x36, 64); memset(foo, 0x36, 64);
for (i = 0; i < len && i < 64; i++) for (i = 0; i < len && i < 64; i++)
foo[i] ^= key[i]; foo[i] ^= key[i];
MD5Init(s1); MD5Init(s1);
MD5Update(s1, foo, 64); MD5Update(s1, foo, 64);
memset(foo, 0x5C, 64); memset(foo, 0x5C, 64);
for (i = 0; i < len && i < 64; i++) for (i = 0; i < len && i < 64; i++)
foo[i] ^= key[i]; foo[i] ^= key[i];
MD5Init(s2); MD5Init(s2);
MD5Update(s2, foo, 64); MD5Update(s2, foo, 64);
memset(foo, 0, 64); /* burn the evidence */ memset(foo, 0, 64); /* burn the evidence */
} }
static void md5_cskey(unsigned char *key) { static void md5_cskey(unsigned char *key)
{
md5_key(&md5_cs_mac_s1, &md5_cs_mac_s2, key, 16); md5_key(&md5_cs_mac_s1, &md5_cs_mac_s2, key, 16);
} }
static void md5_sckey(unsigned char *key) { static void md5_sckey(unsigned char *key)
{
md5_key(&md5_sc_mac_s1, &md5_sc_mac_s2, key, 16); md5_key(&md5_sc_mac_s1, &md5_sc_mac_s2, key, 16);
} }
static void md5_do_hmac(struct MD5Context *s1, struct MD5Context *s2, static void md5_do_hmac(struct MD5Context *s1, struct MD5Context *s2,
unsigned char *blk, int len, unsigned long seq, unsigned char *blk, int len, unsigned long seq,
unsigned char *hmac) { unsigned char *hmac)
{
struct MD5Context s; struct MD5Context s;
unsigned char intermediate[16]; unsigned char intermediate[16];
intermediate[0] = (unsigned char)((seq >> 24) & 0xFF); intermediate[0] = (unsigned char) ((seq >> 24) & 0xFF);
intermediate[1] = (unsigned char)((seq >> 16) & 0xFF); intermediate[1] = (unsigned char) ((seq >> 16) & 0xFF);
intermediate[2] = (unsigned char)((seq >> 8) & 0xFF); intermediate[2] = (unsigned char) ((seq >> 8) & 0xFF);
intermediate[3] = (unsigned char)((seq ) & 0xFF); intermediate[3] = (unsigned char) ((seq) & 0xFF);
s = *s1; /* structure copy */ s = *s1; /* structure copy */
MD5Update(&s, intermediate, 4); MD5Update(&s, intermediate, 4);
MD5Update(&s, blk, len); MD5Update(&s, blk, len);
MD5Final(intermediate, &s); MD5Final(intermediate, &s);
s = *s2; /* structure copy */ s = *s2; /* structure copy */
MD5Update(&s, intermediate, 16); MD5Update(&s, intermediate, 16);
MD5Final(hmac, &s); MD5Final(hmac, &s);
} }
static void md5_generate(unsigned char *blk, int len, unsigned long seq) { static void md5_generate(unsigned char *blk, int len, unsigned long seq)
md5_do_hmac(&md5_cs_mac_s1, &md5_cs_mac_s2, blk, len, seq, blk+len); {
md5_do_hmac(&md5_cs_mac_s1, &md5_cs_mac_s2, blk, len, seq, blk + len);
} }
static int md5_verify(unsigned char *blk, int len, unsigned long seq) { static int md5_verify(unsigned char *blk, int len, unsigned long seq)
{
unsigned char correct[16]; unsigned char correct[16];
md5_do_hmac(&md5_sc_mac_s1, &md5_sc_mac_s2, blk, len, seq, correct); md5_do_hmac(&md5_sc_mac_s1, &md5_sc_mac_s2, blk, len, seq, correct);
return !memcmp(correct, blk+len, 16); return !memcmp(correct, blk + len, 16);
} }
const struct ssh_mac ssh_md5 = { const struct ssh_mac ssh_md5 = {

1790
sshprime.c

File diff suppressed because it is too large Load Diff

306
sshpubk.c
View File

@ -31,8 +31,9 @@
(x)=='+' ? 62 : \ (x)=='+' ? 62 : \
(x)=='/' ? 63 : 0 ) (x)=='/' ? 63 : 0 )
static int loadrsakey_main(FILE *fp, struct RSAKey *key, static int loadrsakey_main(FILE * fp, struct RSAKey *key,
char **commentptr, char *passphrase) { char **commentptr, char *passphrase)
{
unsigned char buf[16384]; unsigned char buf[16384];
unsigned char keybuf[16]; unsigned char keybuf[16];
int len; int len;
@ -45,70 +46,75 @@ static int loadrsakey_main(FILE *fp, struct RSAKey *key,
len = fread(buf, 1, sizeof(buf), fp); len = fread(buf, 1, sizeof(buf), fp);
fclose(fp); fclose(fp);
if (len < 0 || len == sizeof(buf)) if (len < 0 || len == sizeof(buf))
goto end; /* file too big or not read */ goto end; /* file too big or not read */
i = 0; i = 0;
/* /*
* A zero byte. (The signature includes a terminating NUL.) * A zero byte. (The signature includes a terminating NUL.)
*/ */
if (len-i < 1 || buf[i] != 0) if (len - i < 1 || buf[i] != 0)
goto end; goto end;
i++; i++;
/* One byte giving encryption type, and one reserved uint32. */ /* One byte giving encryption type, and one reserved uint32. */
if (len-i < 1) if (len - i < 1)
goto end; goto end;
ciphertype = buf[i]; ciphertype = buf[i];
if (ciphertype != 0 && ciphertype != SSH_CIPHER_3DES) if (ciphertype != 0 && ciphertype != SSH_CIPHER_3DES)
goto end; goto end;
i++; i++;
if (len-i < 4) if (len - i < 4)
goto end; /* reserved field not present */ goto end; /* reserved field not present */
if (buf[i] != 0 || buf[i+1] != 0 || buf[i+2] != 0 || buf[i+3] != 0) if (buf[i] != 0 || buf[i + 1] != 0 || buf[i + 2] != 0
goto end; /* reserved field nonzero, panic! */ || buf[i + 3] != 0) goto end; /* reserved field nonzero, panic! */
i += 4; i += 4;
/* Now the serious stuff. An ordinary SSH 1 public key. */ /* Now the serious stuff. An ordinary SSH 1 public key. */
i += makekey(buf+i, key, NULL, 1); i += makekey(buf + i, key, NULL, 1);
if (len-i < 0) if (len - i < 0)
goto end; /* overran */ goto end; /* overran */
/* Next, the comment field. */ /* Next, the comment field. */
j = GET_32BIT(buf+i); j = GET_32BIT(buf + i);
i += 4; i += 4;
if (len-i < j) goto end; if (len - i < j)
comment = smalloc(j+1); goto end;
comment = smalloc(j + 1);
if (comment) { if (comment) {
memcpy(comment, buf+i, j); memcpy(comment, buf + i, j);
comment[j] = '\0'; comment[j] = '\0';
} }
i += j; i += j;
if (commentptr) if (commentptr)
*commentptr = comment; *commentptr = comment;
if (key) if (key)
key->comment = comment; key->comment = comment;
if (!key) { if (!key) {
return ciphertype != 0; return ciphertype != 0;
} }
/* /*
* Decrypt remainder of buffer. * Decrypt remainder of buffer.
*/ */
if (ciphertype) { if (ciphertype) {
MD5Init(&md5c); MD5Init(&md5c);
MD5Update(&md5c, passphrase, strlen(passphrase)); MD5Update(&md5c, passphrase, strlen(passphrase));
MD5Final(keybuf, &md5c); MD5Final(keybuf, &md5c);
des3_decrypt_pubkey(keybuf, buf+i, (len-i+7)&~7); des3_decrypt_pubkey(keybuf, buf + i, (len - i + 7) & ~7);
memset(keybuf, 0, sizeof(keybuf)); /* burn the evidence */ memset(keybuf, 0, sizeof(keybuf)); /* burn the evidence */
} }
/* /*
* We are now in the secret part of the key. The first four * We are now in the secret part of the key. The first four
* bytes should be of the form a, b, a, b. * bytes should be of the form a, b, a, b.
*/ */
if (len-i < 4) goto end; if (len - i < 4)
if (buf[i] != buf[i+2] || buf[i+1] != buf[i+3]) { ret = -1; goto end; } goto end;
if (buf[i] != buf[i + 2] || buf[i + 1] != buf[i + 3]) {
ret = -1;
goto end;
}
i += 4; i += 4;
/* /*
@ -116,14 +122,18 @@ static int loadrsakey_main(FILE *fp, struct RSAKey *key,
* decryption exponent, and then the three auxiliary values * decryption exponent, and then the three auxiliary values
* (iqmp, q, p). * (iqmp, q, p).
*/ */
i += makeprivate(buf+i, key); i += makeprivate(buf + i, key);
if (len-i < 0) goto end; if (len - i < 0)
i += ssh1_read_bignum(buf+i, &key->iqmp); goto end;
if (len-i < 0) goto end; i += ssh1_read_bignum(buf + i, &key->iqmp);
i += ssh1_read_bignum(buf+i, &key->q); if (len - i < 0)
if (len-i < 0) goto end; goto end;
i += ssh1_read_bignum(buf+i, &key->p); i += ssh1_read_bignum(buf + i, &key->q);
if (len-i < 0) goto end; if (len - i < 0)
goto end;
i += ssh1_read_bignum(buf + i, &key->p);
if (len - i < 0)
goto end;
if (!rsa_verify(key)) { if (!rsa_verify(key)) {
freersakey(key); freersakey(key);
@ -131,26 +141,26 @@ static int loadrsakey_main(FILE *fp, struct RSAKey *key,
} else } else
ret = 1; ret = 1;
end: end:
memset(buf, 0, sizeof(buf)); /* burn the evidence */ memset(buf, 0, sizeof(buf)); /* burn the evidence */
return ret; return ret;
} }
int loadrsakey(char *filename, struct RSAKey *key, char *passphrase) { int loadrsakey(char *filename, struct RSAKey *key, char *passphrase)
{
FILE *fp; FILE *fp;
unsigned char buf[64]; unsigned char buf[64];
fp = fopen(filename, "rb"); fp = fopen(filename, "rb");
if (!fp) if (!fp)
return 0; /* doesn't even exist */ return 0; /* doesn't even exist */
/* /*
* Read the first line of the file and see if it's a v1 private * Read the first line of the file and see if it's a v1 private
* key file. * key file.
*/ */
if (fgets(buf, sizeof(buf), fp) && if (fgets(buf, sizeof(buf), fp) && !strcmp(buf, rsa_signature)) {
!strcmp(buf, rsa_signature)) { return loadrsakey_main(fp, key, NULL, passphrase);
return loadrsakey_main(fp, key, NULL, passphrase);
} }
/* /*
@ -164,30 +174,31 @@ int loadrsakey(char *filename, struct RSAKey *key, char *passphrase) {
* See whether an RSA key is encrypted. Return its comment field as * See whether an RSA key is encrypted. Return its comment field as
* well. * well.
*/ */
int rsakey_encrypted(char *filename, char **comment) { int rsakey_encrypted(char *filename, char **comment)
{
FILE *fp; FILE *fp;
unsigned char buf[64]; unsigned char buf[64];
fp = fopen(filename, "rb"); fp = fopen(filename, "rb");
if (!fp) if (!fp)
return 0; /* doesn't even exist */ return 0; /* doesn't even exist */
/* /*
* Read the first line of the file and see if it's a v1 private * Read the first line of the file and see if it's a v1 private
* key file. * key file.
*/ */
if (fgets(buf, sizeof(buf), fp) && if (fgets(buf, sizeof(buf), fp) && !strcmp(buf, rsa_signature)) {
!strcmp(buf, rsa_signature)) { return loadrsakey_main(fp, NULL, comment, NULL);
return loadrsakey_main(fp, NULL, comment, NULL);
} }
fclose(fp); fclose(fp);
return 0; /* wasn't the right kind of file */ return 0; /* wasn't the right kind of file */
} }
/* /*
* Save an RSA key file. Return nonzero on success. * Save an RSA key file. Return nonzero on success.
*/ */
int saversakey(char *filename, struct RSAKey *key, char *passphrase) { int saversakey(char *filename, struct RSAKey *key, char *passphrase)
{
unsigned char buf[16384]; unsigned char buf[16384];
unsigned char keybuf[16]; unsigned char keybuf[16];
struct MD5Context md5c; struct MD5Context md5c;
@ -206,14 +217,16 @@ int saversakey(char *filename, struct RSAKey *key, char *passphrase) {
* uint32. * uint32.
*/ */
*p++ = (passphrase ? SSH_CIPHER_3DES : 0); *p++ = (passphrase ? SSH_CIPHER_3DES : 0);
PUT_32BIT(p, 0); p += 4; PUT_32BIT(p, 0);
p += 4;
/* /*
* An ordinary SSH 1 public key consists of: a uint32 * An ordinary SSH 1 public key consists of: a uint32
* containing the bit count, then two bignums containing the * containing the bit count, then two bignums containing the
* modulus and exponent respectively. * modulus and exponent respectively.
*/ */
PUT_32BIT(p, bignum_bitcount(key->modulus)); p += 4; PUT_32BIT(p, bignum_bitcount(key->modulus));
p += 4;
p += ssh1_write_bignum(p, key->modulus); p += ssh1_write_bignum(p, key->modulus);
p += ssh1_write_bignum(p, key->exponent); p += ssh1_write_bignum(p, key->exponent);
@ -221,11 +234,13 @@ int saversakey(char *filename, struct RSAKey *key, char *passphrase) {
* A string containing the comment field. * A string containing the comment field.
*/ */
if (key->comment) { if (key->comment) {
PUT_32BIT(p, strlen(key->comment)); p += 4; PUT_32BIT(p, strlen(key->comment));
memcpy(p, key->comment, strlen(key->comment)); p += 4;
p += strlen(key->comment); memcpy(p, key->comment, strlen(key->comment));
p += strlen(key->comment);
} else { } else {
PUT_32BIT(p, 0); p += 4; PUT_32BIT(p, 0);
p += 4;
} }
/* /*
@ -238,7 +253,9 @@ int saversakey(char *filename, struct RSAKey *key, char *passphrase) {
*/ */
*p++ = random_byte(); *p++ = random_byte();
*p++ = random_byte(); *p++ = random_byte();
p[0] = p[-2]; p[1] = p[-1]; p += 2; p[0] = p[-2];
p[1] = p[-1];
p += 2;
/* /*
* Four more bignums: the decryption exponent, then iqmp, then * Four more bignums: the decryption exponent, then iqmp, then
@ -253,18 +270,18 @@ int saversakey(char *filename, struct RSAKey *key, char *passphrase) {
* Now write zeros until the encrypted portion is a multiple of * Now write zeros until the encrypted portion is a multiple of
* 8 bytes. * 8 bytes.
*/ */
while ((p-estart) % 8) while ((p - estart) % 8)
*p++ = '\0'; *p++ = '\0';
/* /*
* Now encrypt the encrypted portion. * Now encrypt the encrypted portion.
*/ */
if (passphrase) { if (passphrase) {
MD5Init(&md5c); MD5Init(&md5c);
MD5Update(&md5c, passphrase, strlen(passphrase)); MD5Update(&md5c, passphrase, strlen(passphrase));
MD5Final(keybuf, &md5c); MD5Final(keybuf, &md5c);
des3_encrypt_pubkey(keybuf, estart, p-estart); des3_encrypt_pubkey(keybuf, estart, p - estart);
memset(keybuf, 0, sizeof(keybuf)); /* burn the evidence */ memset(keybuf, 0, sizeof(keybuf)); /* burn the evidence */
} }
/* /*
@ -272,11 +289,11 @@ int saversakey(char *filename, struct RSAKey *key, char *passphrase) {
*/ */
fp = fopen(filename, "wb"); fp = fopen(filename, "wb");
if (fp) { if (fp) {
int ret = (fwrite(buf, 1, p-buf, fp) == (size_t)(p-buf)); int ret = (fwrite(buf, 1, p - buf, fp) == (size_t) (p - buf));
ret = ret && (fclose(fp) == 0); ret = ret && (fclose(fp) == 0);
return ret; return ret;
} else } else
return 0; return 0;
} }
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
@ -345,7 +362,8 @@ int saversakey(char *filename, struct RSAKey *key, char *passphrase) {
* section other than just x. * section other than just x.
*/ */
static int read_header(FILE *fp, char *header) { static int read_header(FILE * fp, char *header)
{
int len = 39; int len = 39;
int c; int c;
@ -368,7 +386,8 @@ static int read_header(FILE *fp, char *header) {
return 0; /* failure */ return 0; /* failure */
} }
static char *read_body(FILE *fp) { static char *read_body(FILE * fp)
{
char *text; char *text;
int len; int len;
int size; int size;
@ -400,12 +419,13 @@ static char *read_body(FILE *fp) {
} }
} }
int base64_decode_atom(char *atom, unsigned char *out) { int base64_decode_atom(char *atom, unsigned char *out)
{
int vals[4]; int vals[4];
int i, v, len; int i, v, len;
unsigned word; unsigned word;
char c; char c;
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
c = atom[i]; c = atom[i];
if (c >= 'A' && c <= 'Z') if (c >= 'A' && c <= 'Z')
@ -438,9 +458,7 @@ int base64_decode_atom(char *atom, unsigned char *out) {
len = 1; len = 1;
word = ((vals[0] << 18) | word = ((vals[0] << 18) |
(vals[1] << 12) | (vals[1] << 12) | ((vals[2] & 0x3F) << 6) | (vals[3] & 0x3F));
((vals[2] & 0x3F) << 6) |
(vals[3] & 0x3F));
out[0] = (word >> 16) & 0xFF; out[0] = (word >> 16) & 0xFF;
if (len > 1) if (len > 1)
out[1] = (word >> 8) & 0xFF; out[1] = (word >> 8) & 0xFF;
@ -449,7 +467,8 @@ int base64_decode_atom(char *atom, unsigned char *out) {
return len; return len;
} }
static char *read_blob(FILE *fp, int nlines, int *bloblen) { static char *read_blob(FILE * fp, int nlines, int *bloblen)
{
unsigned char *blob; unsigned char *blob;
char *line; char *line;
int linelen, len; int linelen, len;
@ -471,7 +490,7 @@ static char *read_blob(FILE *fp, int nlines, int *bloblen) {
return NULL; return NULL;
} }
for (j = 0; j < linelen; j += 4) { for (j = 0; j < linelen; j += 4) {
k = base64_decode_atom(line+j, blob+len); k = base64_decode_atom(line + j, blob + len);
if (!k) { if (!k) {
sfree(line); sfree(line);
sfree(blob); sfree(blob);
@ -492,7 +511,8 @@ struct ssh2_userkey ssh2_wrong_passphrase = {
NULL, NULL, NULL NULL, NULL, NULL
}; };
struct ssh2_userkey *ssh2_load_userkey(char *filename, char *passphrase) { struct ssh2_userkey *ssh2_load_userkey(char *filename, char *passphrase)
{
FILE *fp; FILE *fp;
char header[40], *b, *comment, *hash; char header[40], *b, *comment, *hash;
const struct ssh_signkey *alg; const struct ssh_signkey *alg;
@ -511,7 +531,8 @@ struct ssh2_userkey *ssh2_load_userkey(char *filename, char *passphrase) {
goto error; goto error;
/* Read the first header line which contains the key type. */ /* Read the first header line which contains the key type. */
if (!read_header(fp, header) || 0!=strcmp(header, "PuTTY-User-Key-File-1")) if (!read_header(fp, header)
|| 0 != strcmp(header, "PuTTY-User-Key-File-1"))
goto error; goto error;
if ((b = read_body(fp)) == NULL) if ((b = read_body(fp)) == NULL)
goto error; goto error;
@ -523,16 +544,18 @@ struct ssh2_userkey *ssh2_load_userkey(char *filename, char *passphrase) {
goto error; goto error;
} }
sfree(b); sfree(b);
/* Read the Encryption header line. */ /* Read the Encryption header line. */
if (!read_header(fp, header) || 0!=strcmp(header, "Encryption")) if (!read_header(fp, header) || 0 != strcmp(header, "Encryption"))
goto error; goto error;
if ((b = read_body(fp)) == NULL) if ((b = read_body(fp)) == NULL)
goto error; goto error;
if (!strcmp(b, "aes256-cbc")) { if (!strcmp(b, "aes256-cbc")) {
cipher = 1; cipherblk = 16; cipher = 1;
cipherblk = 16;
} else if (!strcmp(b, "none")) { } else if (!strcmp(b, "none")) {
cipher = 0; cipherblk = 1; cipher = 0;
cipherblk = 1;
} else { } else {
sfree(b); sfree(b);
goto error; goto error;
@ -540,13 +563,13 @@ struct ssh2_userkey *ssh2_load_userkey(char *filename, char *passphrase) {
sfree(b); sfree(b);
/* Read the Comment header line. */ /* Read the Comment header line. */
if (!read_header(fp, header) || 0!=strcmp(header, "Comment")) if (!read_header(fp, header) || 0 != strcmp(header, "Comment"))
goto error; goto error;
if ((comment = read_body(fp)) == NULL) if ((comment = read_body(fp)) == NULL)
goto error; goto error;
/* Read the Public-Lines header line and the public blob. */ /* Read the Public-Lines header line and the public blob. */
if (!read_header(fp, header) || 0!=strcmp(header, "Public-Lines")) if (!read_header(fp, header) || 0 != strcmp(header, "Public-Lines"))
goto error; goto error;
if ((b = read_body(fp)) == NULL) if ((b = read_body(fp)) == NULL)
goto error; goto error;
@ -556,7 +579,7 @@ struct ssh2_userkey *ssh2_load_userkey(char *filename, char *passphrase) {
goto error; goto error;
/* Read the Private-Lines header line and the Private blob. */ /* Read the Private-Lines header line and the Private blob. */
if (!read_header(fp, header) || 0!=strcmp(header, "Private-Lines")) if (!read_header(fp, header) || 0 != strcmp(header, "Private-Lines"))
goto error; goto error;
if ((b = read_body(fp)) == NULL) if ((b = read_body(fp)) == NULL)
goto error; goto error;
@ -566,7 +589,7 @@ struct ssh2_userkey *ssh2_load_userkey(char *filename, char *passphrase) {
goto error; goto error;
/* Read the Private-Hash header line. */ /* Read the Private-Hash header line. */
if (!read_header(fp, header) || 0!=strcmp(header, "Private-Hash")) if (!read_header(fp, header) || 0 != strcmp(header, "Private-Hash"))
goto error; goto error;
if ((hash = read_body(fp)) == NULL) if ((hash = read_body(fp)) == NULL)
goto error; goto error;
@ -592,11 +615,11 @@ struct ssh2_userkey *ssh2_load_userkey(char *filename, char *passphrase) {
SHA_Init(&s); SHA_Init(&s);
SHA_Bytes(&s, "\0\0\0\0", 4); SHA_Bytes(&s, "\0\0\0\0", 4);
SHA_Bytes(&s, passphrase, passlen); SHA_Bytes(&s, passphrase, passlen);
SHA_Final(&s, key+0); SHA_Final(&s, key + 0);
SHA_Init(&s); SHA_Init(&s);
SHA_Bytes(&s, "\0\0\0\1", 4); SHA_Bytes(&s, "\0\0\0\1", 4);
SHA_Bytes(&s, passphrase, passlen); SHA_Bytes(&s, passphrase, passlen);
SHA_Final(&s, key+20); SHA_Final(&s, key + 20);
aes256_decrypt_pubkey(key, private_blob, private_blob_len); aes256_decrypt_pubkey(key, private_blob, private_blob_len);
} }
@ -609,7 +632,7 @@ struct ssh2_userkey *ssh2_load_userkey(char *filename, char *passphrase) {
SHA_Simple(private_blob, private_blob_len, binary); SHA_Simple(private_blob, private_blob_len, binary);
for (i = 0; i < 20; i++) for (i = 0; i < 20; i++)
sprintf(realhash+2*i, "%02x", binary[i]); sprintf(realhash + 2 * i, "%02x", binary[i]);
if (strcmp(hash, realhash)) { if (strcmp(hash, realhash)) {
/* An incorrect hash is an unconditional Error if the key is /* An incorrect hash is an unconditional Error if the key is
@ -640,16 +663,23 @@ struct ssh2_userkey *ssh2_load_userkey(char *filename, char *passphrase) {
/* /*
* Error processing. * Error processing.
*/ */
error: error:
if (fp) fclose(fp); if (fp)
if (comment) sfree(comment); fclose(fp);
if (hash) sfree(hash); if (comment)
if (public_blob) sfree(public_blob); sfree(comment);
if (private_blob) sfree(private_blob); if (hash)
sfree(hash);
if (public_blob)
sfree(public_blob);
if (private_blob)
sfree(private_blob);
return ret; return ret;
} }
char *ssh2_userkey_loadpub(char *filename, char **algorithm, int *pub_blob_len) { char *ssh2_userkey_loadpub(char *filename, char **algorithm,
int *pub_blob_len)
{
FILE *fp; FILE *fp;
char header[40], *b; char header[40], *b;
const struct ssh_signkey *alg; const struct ssh_signkey *alg;
@ -664,7 +694,8 @@ char *ssh2_userkey_loadpub(char *filename, char **algorithm, int *pub_blob_len)
goto error; goto error;
/* Read the first header line which contains the key type. */ /* Read the first header line which contains the key type. */
if (!read_header(fp, header) || 0!=strcmp(header, "PuTTY-User-Key-File-1")) if (!read_header(fp, header)
|| 0 != strcmp(header, "PuTTY-User-Key-File-1"))
goto error; goto error;
if ((b = read_body(fp)) == NULL) if ((b = read_body(fp)) == NULL)
goto error; goto error;
@ -676,23 +707,23 @@ char *ssh2_userkey_loadpub(char *filename, char **algorithm, int *pub_blob_len)
goto error; goto error;
} }
sfree(b); sfree(b);
/* Read the Encryption header line. */ /* Read the Encryption header line. */
if (!read_header(fp, header) || 0!=strcmp(header, "Encryption")) if (!read_header(fp, header) || 0 != strcmp(header, "Encryption"))
goto error; goto error;
if ((b = read_body(fp)) == NULL) if ((b = read_body(fp)) == NULL)
goto error; goto error;
sfree(b); /* we don't care */ sfree(b); /* we don't care */
/* Read the Comment header line. */ /* Read the Comment header line. */
if (!read_header(fp, header) || 0!=strcmp(header, "Comment")) if (!read_header(fp, header) || 0 != strcmp(header, "Comment"))
goto error; goto error;
if ((b = read_body(fp)) == NULL) if ((b = read_body(fp)) == NULL)
goto error; goto error;
sfree(b); /* we don't care */ sfree(b); /* we don't care */
/* Read the Public-Lines header line and the public blob. */ /* Read the Public-Lines header line and the public blob. */
if (!read_header(fp, header) || 0!=strcmp(header, "Public-Lines")) if (!read_header(fp, header) || 0 != strcmp(header, "Public-Lines"))
goto error; goto error;
if ((b = read_body(fp)) == NULL) if ((b = read_body(fp)) == NULL)
goto error; goto error;
@ -709,46 +740,60 @@ char *ssh2_userkey_loadpub(char *filename, char **algorithm, int *pub_blob_len)
/* /*
* Error processing. * Error processing.
*/ */
error: error:
if (fp) fclose(fp); if (fp)
if (public_blob) sfree(public_blob); fclose(fp);
if (public_blob)
sfree(public_blob);
return NULL; return NULL;
} }
int ssh2_userkey_encrypted(char *filename, char **commentptr) { int ssh2_userkey_encrypted(char *filename, char **commentptr)
{
FILE *fp; FILE *fp;
char header[40], *b, *comment; char header[40], *b, *comment;
int ret; int ret;
if (commentptr) *commentptr = NULL; if (commentptr)
*commentptr = NULL;
fp = fopen(filename, "rb"); fp = fopen(filename, "rb");
if (!fp) if (!fp)
return 0; return 0;
if (!read_header(fp, header) || 0!=strcmp(header, "PuTTY-User-Key-File-1")) { if (!read_header(fp, header)
fclose(fp); return 0; || 0 != strcmp(header, "PuTTY-User-Key-File-1")) {
fclose(fp);
return 0;
} }
if ((b = read_body(fp)) == NULL) { if ((b = read_body(fp)) == NULL) {
fclose(fp); return 0; fclose(fp);
return 0;
} }
sfree(b); /* we don't care about key type here */ sfree(b); /* we don't care about key type here */
/* Read the Encryption header line. */ /* Read the Encryption header line. */
if (!read_header(fp, header) || 0!=strcmp(header, "Encryption")) { if (!read_header(fp, header) || 0 != strcmp(header, "Encryption")) {
fclose(fp); return 0; fclose(fp);
return 0;
} }
if ((b = read_body(fp)) == NULL) { if ((b = read_body(fp)) == NULL) {
fclose(fp); return 0; fclose(fp);
return 0;
} }
/* Read the Comment header line. */ /* Read the Comment header line. */
if (!read_header(fp, header) || 0!=strcmp(header, "Comment")) { if (!read_header(fp, header) || 0 != strcmp(header, "Comment")) {
fclose(fp); sfree(b); return 1; fclose(fp);
sfree(b);
return 1;
} }
if ((comment = read_body(fp)) == NULL) { if ((comment = read_body(fp)) == NULL) {
fclose(fp); sfree(b); return 1; fclose(fp);
sfree(b);
return 1;
} }
if (commentptr) *commentptr = comment; if (commentptr)
*commentptr = comment;
fclose(fp); fclose(fp);
if (!strcmp(b, "aes256-cbc")) if (!strcmp(b, "aes256-cbc"))
@ -759,12 +804,14 @@ int ssh2_userkey_encrypted(char *filename, char **commentptr) {
return ret; return ret;
} }
int base64_lines(int datalen) { int base64_lines(int datalen)
{
/* When encoding, we use 64 chars/line, which equals 48 real chars. */ /* When encoding, we use 64 chars/line, which equals 48 real chars. */
return (datalen+47) / 48; return (datalen + 47) / 48;
} }
void base64_encode_atom(unsigned char *data, int n, char *out) { void base64_encode_atom(unsigned char *data, int n, char *out)
{
static const char base64_chars[] = static const char base64_chars[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
@ -787,7 +834,8 @@ void base64_encode_atom(unsigned char *data, int n, char *out) {
out[3] = '='; out[3] = '=';
} }
void base64_encode(FILE *fp, unsigned char *data, int datalen) { void base64_encode(FILE * fp, unsigned char *data, int datalen)
{
int linelen = 0; int linelen = 0;
char out[4]; char out[4];
int n; int n;
@ -807,7 +855,9 @@ void base64_encode(FILE *fp, unsigned char *data, int datalen) {
fputc('\n', fp); fputc('\n', fp);
} }
int ssh2_save_userkey(char *filename, struct ssh2_userkey *key, char *passphrase) { int ssh2_save_userkey(char *filename, struct ssh2_userkey *key,
char *passphrase)
{
FILE *fp; FILE *fp;
unsigned char *pub_blob, *priv_blob, *priv_blob_encrypted; unsigned char *pub_blob, *priv_blob, *priv_blob_encrypted;
int pub_blob_len, priv_blob_len, priv_encrypted_len; int pub_blob_len, priv_blob_len, priv_encrypted_len;
@ -862,12 +912,13 @@ int ssh2_save_userkey(char *filename, struct ssh2_userkey *key, char *passphrase
SHA_Init(&s); SHA_Init(&s);
SHA_Bytes(&s, "\0\0\0\0", 4); SHA_Bytes(&s, "\0\0\0\0", 4);
SHA_Bytes(&s, passphrase, passlen); SHA_Bytes(&s, passphrase, passlen);
SHA_Final(&s, key+0); SHA_Final(&s, key + 0);
SHA_Init(&s); SHA_Init(&s);
SHA_Bytes(&s, "\0\0\0\1", 4); SHA_Bytes(&s, "\0\0\0\1", 4);
SHA_Bytes(&s, passphrase, passlen); SHA_Bytes(&s, passphrase, passlen);
SHA_Final(&s, key+20); SHA_Final(&s, key + 20);
aes256_encrypt_pubkey(key, priv_blob_encrypted, priv_encrypted_len); aes256_encrypt_pubkey(key, priv_blob_encrypted,
priv_encrypted_len);
} }
fp = fopen(filename, "w"); fp = fopen(filename, "w");
@ -892,7 +943,8 @@ int ssh2_save_userkey(char *filename, struct ssh2_userkey *key, char *passphrase
* A function to determine which version of SSH to try on a private * A function to determine which version of SSH to try on a private
* key file. Returns 0 on failure, 1 or 2 on success. * key file. Returns 0 on failure, 1 or 2 on success.
*/ */
int keyfile_version(char *filename) { int keyfile_version(char *filename)
{
FILE *fp; FILE *fp;
int i; int i;

View File

@ -41,14 +41,15 @@ struct RandPool {
static struct RandPool pool; static struct RandPool pool;
static int random_active = 0; static int random_active = 0;
void random_stir(void) { void random_stir(void)
word32 block[HASHINPUT/sizeof(word32)]; {
word32 digest[HASHSIZE/sizeof(word32)]; word32 block[HASHINPUT / sizeof(word32)];
word32 digest[HASHSIZE / sizeof(word32)];
int i, j, k; int i, j, k;
noise_get_light(random_add_noise); noise_get_light(random_add_noise);
SHATransform((word32 *)pool.incoming, (word32 *)pool.incomingb); SHATransform((word32 *) pool.incoming, (word32 *) pool.incomingb);
pool.incomingpos = 0; pool.incomingpos = 0;
/* /*
@ -77,14 +78,14 @@ void random_stir(void) {
* things will be that much less predictable that way * things will be that much less predictable that way
* round, when we subsequently return bytes ... * round, when we subsequently return bytes ...
*/ */
for (j = POOLSIZE; (j -= HASHSIZE) >= 0 ;) { for (j = POOLSIZE; (j -= HASHSIZE) >= 0;) {
/* /*
* XOR the bit of the pool we're processing into the * XOR the bit of the pool we're processing into the
* digest. * digest.
*/ */
for (k = 0; k < sizeof(digest)/sizeof(*digest); k++) for (k = 0; k < sizeof(digest) / sizeof(*digest); k++)
digest[k] ^= ((word32 *)(pool.pool+j))[k]; digest[k] ^= ((word32 *) (pool.pool + j))[k];
/* /*
* Munge our unrevealed first block of the pool into * Munge our unrevealed first block of the pool into
@ -96,8 +97,8 @@ void random_stir(void) {
* Stick the result back into the pool. * Stick the result back into the pool.
*/ */
for (k = 0; k < sizeof(digest)/sizeof(*digest); k++) for (k = 0; k < sizeof(digest) / sizeof(*digest); k++)
((word32 *)(pool.pool+j))[k] = digest[k]; ((word32 *) (pool.pool + j))[k] = digest[k];
} }
} }
@ -111,12 +112,13 @@ void random_stir(void) {
pool.poolpos = sizeof(pool.incoming); pool.poolpos = sizeof(pool.incoming);
} }
void random_add_noise(void *noise, int length) { void random_add_noise(void *noise, int length)
{
unsigned char *p = noise; unsigned char *p = noise;
int i; int i;
if (!random_active) if (!random_active)
return; return;
/* /*
* This function processes HASHINPUT bytes into only HASHSIZE * This function processes HASHINPUT bytes into only HASHSIZE
@ -128,14 +130,14 @@ void random_add_noise(void *noise, int length) {
HASHINPUT - pool.incomingpos); HASHINPUT - pool.incomingpos);
p += HASHINPUT - pool.incomingpos; p += HASHINPUT - pool.incomingpos;
length -= HASHINPUT - pool.incomingpos; length -= HASHINPUT - pool.incomingpos;
SHATransform((word32 *)pool.incoming, (word32 *)pool.incomingb); SHATransform((word32 *) pool.incoming, (word32 *) pool.incomingb);
for (i = 0; i < HASHSIZE; i++) { for (i = 0; i < HASHSIZE; i++) {
pool.pool[pool.poolpos++] ^= pool.incomingb[i]; pool.pool[pool.poolpos++] ^= pool.incomingb[i];
if (pool.poolpos >= POOLSIZE) if (pool.poolpos >= POOLSIZE)
pool.poolpos = 0; pool.poolpos = 0;
} }
if (pool.poolpos < HASHSIZE) if (pool.poolpos < HASHSIZE)
random_stir(); random_stir();
pool.incomingpos = 0; pool.incomingpos = 0;
} }
@ -144,40 +146,43 @@ void random_add_noise(void *noise, int length) {
pool.incomingpos += length; pool.incomingpos += length;
} }
void random_add_heavynoise(void *noise, int length) { void random_add_heavynoise(void *noise, int length)
{
unsigned char *p = noise; unsigned char *p = noise;
int i; int i;
while (length >= POOLSIZE) { while (length >= POOLSIZE) {
for (i = 0; i < POOLSIZE; i++) for (i = 0; i < POOLSIZE; i++)
pool.pool[i] ^= *p++; pool.pool[i] ^= *p++;
random_stir(); random_stir();
length -= POOLSIZE; length -= POOLSIZE;
} }
for (i = 0; i < length; i++) for (i = 0; i < length; i++)
pool.pool[i] ^= *p++; pool.pool[i] ^= *p++;
random_stir(); random_stir();
} }
static void random_add_heavynoise_bitbybit(void *noise, int length) { static void random_add_heavynoise_bitbybit(void *noise, int length)
{
unsigned char *p = noise; unsigned char *p = noise;
int i; int i;
while (length >= POOLSIZE - pool.poolpos) { while (length >= POOLSIZE - pool.poolpos) {
for (i = 0; i < POOLSIZE - pool.poolpos; i++) for (i = 0; i < POOLSIZE - pool.poolpos; i++)
pool.pool[pool.poolpos + i] ^= *p++; pool.pool[pool.poolpos + i] ^= *p++;
random_stir(); random_stir();
length -= POOLSIZE - pool.poolpos; length -= POOLSIZE - pool.poolpos;
pool.poolpos = 0; pool.poolpos = 0;
} }
for (i = 0; i < length; i++) for (i = 0; i < length; i++)
pool.pool[i] ^= *p++; pool.pool[i] ^= *p++;
pool.poolpos = i; pool.poolpos = i;
} }
void random_init(void) { void random_init(void)
{
memset(&pool, 0, sizeof(pool)); /* just to start with */ memset(&pool, 0, sizeof(pool)); /* just to start with */
random_active = 1; random_active = 1;
@ -186,15 +191,17 @@ void random_init(void) {
random_stir(); random_stir();
} }
int random_byte(void) { int random_byte(void)
{
if (pool.poolpos >= POOLSIZE) if (pool.poolpos >= POOLSIZE)
random_stir(); random_stir();
return pool.pool[pool.poolpos++]; return pool.pool[pool.poolpos++];
} }
void random_get_savedata(void **data, int *len) { void random_get_savedata(void **data, int *len)
{
random_stir(); random_stir();
*data = pool.pool+pool.poolpos; *data = pool.pool + pool.poolpos;
*len = POOLSIZE/2; *len = POOLSIZE / 2;
} }

331
sshrsa.c
View File

@ -14,16 +14,17 @@
int makekey(unsigned char *data, struct RSAKey *result, int makekey(unsigned char *data, struct RSAKey *result,
unsigned char **keystr, int order) { unsigned char **keystr, int order)
{
unsigned char *p = data; unsigned char *p = data;
int i; int i;
if (result) { if (result) {
result->bits = 0; result->bits = 0;
for (i=0; i<4; i++) for (i = 0; i < 4; i++)
result->bits = (result->bits << 8) + *p++; result->bits = (result->bits << 8) + *p++;
} else } else
p += 4; p += 4;
/* /*
* order=0 means exponent then modulus (the keys sent by the * order=0 means exponent then modulus (the keys sent by the
@ -32,68 +33,74 @@ int makekey(unsigned char *data, struct RSAKey *result,
*/ */
if (order == 0) if (order == 0)
p += ssh1_read_bignum(p, result ? &result->exponent : NULL); p += ssh1_read_bignum(p, result ? &result->exponent : NULL);
if (result) if (result)
result->bytes = (((p[0] << 8) + p[1]) + 7) / 8; result->bytes = (((p[0] << 8) + p[1]) + 7) / 8;
if (keystr) *keystr = p+2; if (keystr)
*keystr = p + 2;
p += ssh1_read_bignum(p, result ? &result->modulus : NULL); p += ssh1_read_bignum(p, result ? &result->modulus : NULL);
if (order == 1) if (order == 1)
p += ssh1_read_bignum(p, result ? &result->exponent : NULL); p += ssh1_read_bignum(p, result ? &result->exponent : NULL);
return p - data; return p - data;
} }
int makeprivate(unsigned char *data, struct RSAKey *result) { int makeprivate(unsigned char *data, struct RSAKey *result)
{
return ssh1_read_bignum(data, &result->private_exponent); return ssh1_read_bignum(data, &result->private_exponent);
} }
void rsaencrypt(unsigned char *data, int length, struct RSAKey *key) { void rsaencrypt(unsigned char *data, int length, struct RSAKey *key)
{
Bignum b1, b2; Bignum b1, b2;
int i; int i;
unsigned char *p; unsigned char *p;
memmove(data+key->bytes-length, data, length); memmove(data + key->bytes - length, data, length);
data[0] = 0; data[0] = 0;
data[1] = 2; data[1] = 2;
for (i = 2; i < key->bytes-length-1; i++) { for (i = 2; i < key->bytes - length - 1; i++) {
do { do {
data[i] = random_byte(); data[i] = random_byte();
} while (data[i] == 0); } while (data[i] == 0);
} }
data[key->bytes-length-1] = 0; data[key->bytes - length - 1] = 0;
b1 = bignum_from_bytes(data, key->bytes); b1 = bignum_from_bytes(data, key->bytes);
b2 = modpow(b1, key->exponent, key->modulus); b2 = modpow(b1, key->exponent, key->modulus);
p = data; p = data;
for (i=key->bytes; i-- ;) { for (i = key->bytes; i--;) {
*p++ = bignum_byte(b2, i); *p++ = bignum_byte(b2, i);
} }
freebn(b1); freebn(b1);
freebn(b2); freebn(b2);
} }
Bignum rsadecrypt(Bignum input, struct RSAKey *key) { Bignum rsadecrypt(Bignum input, struct RSAKey *key)
{
Bignum ret; Bignum ret;
ret = modpow(input, key->private_exponent, key->modulus); ret = modpow(input, key->private_exponent, key->modulus);
return ret; return ret;
} }
int rsastr_len(struct RSAKey *key) { int rsastr_len(struct RSAKey *key)
{
Bignum md, ex; Bignum md, ex;
int mdlen, exlen; int mdlen, exlen;
md = key->modulus; md = key->modulus;
ex = key->exponent; ex = key->exponent;
mdlen = (bignum_bitcount(md)+15) / 16; mdlen = (bignum_bitcount(md) + 15) / 16;
exlen = (bignum_bitcount(ex)+15) / 16; exlen = (bignum_bitcount(ex) + 15) / 16;
return 4 * (mdlen+exlen) + 20; return 4 * (mdlen + exlen) + 20;
} }
void rsastr_fmt(char *str, struct RSAKey *key) { void rsastr_fmt(char *str, struct RSAKey *key)
{
Bignum md, ex; Bignum md, ex;
int len = 0, i, nibbles; int len = 0, i, nibbles;
static const char hex[] = "0123456789abcdef"; static const char hex[] = "0123456789abcdef";
@ -101,17 +108,21 @@ void rsastr_fmt(char *str, struct RSAKey *key) {
md = key->modulus; md = key->modulus;
ex = key->exponent; ex = key->exponent;
len += sprintf(str+len, "0x"); len += sprintf(str + len, "0x");
nibbles = (3 + bignum_bitcount(ex))/4; if (nibbles<1) nibbles=1; nibbles = (3 + bignum_bitcount(ex)) / 4;
for (i=nibbles; i-- ;) if (nibbles < 1)
str[len++] = hex[(bignum_byte(ex, i/2) >> (4*(i%2))) & 0xF]; nibbles = 1;
for (i = nibbles; i--;)
str[len++] = hex[(bignum_byte(ex, i / 2) >> (4 * (i % 2))) & 0xF];
len += sprintf(str+len, ",0x"); len += sprintf(str + len, ",0x");
nibbles = (3 + bignum_bitcount(md))/4; if (nibbles<1) nibbles=1; nibbles = (3 + bignum_bitcount(md)) / 4;
for (i=nibbles; i-- ;) if (nibbles < 1)
str[len++] = hex[(bignum_byte(md, i/2) >> (4*(i%2))) & 0xF]; nibbles = 1;
for (i = nibbles; i--;)
str[len++] = hex[(bignum_byte(md, i / 2) >> (4 * (i % 2))) & 0xF];
str[len] = '\0'; str[len] = '\0';
} }
@ -120,34 +131,37 @@ void rsastr_fmt(char *str, struct RSAKey *key) {
* Generate a fingerprint string for the key. Compatible with the * Generate a fingerprint string for the key. Compatible with the
* OpenSSH fingerprint code. * OpenSSH fingerprint code.
*/ */
void rsa_fingerprint(char *str, int len, struct RSAKey *key) { void rsa_fingerprint(char *str, int len, struct RSAKey *key)
{
struct MD5Context md5c; struct MD5Context md5c;
unsigned char digest[16]; unsigned char digest[16];
char buffer[16*3+40]; char buffer[16 * 3 + 40];
int numlen, slen, i; int numlen, slen, i;
MD5Init(&md5c); MD5Init(&md5c);
numlen = ssh1_bignum_length(key->modulus) - 2; numlen = ssh1_bignum_length(key->modulus) - 2;
for (i = numlen; i-- ;) { for (i = numlen; i--;) {
unsigned char c = bignum_byte(key->modulus, i); unsigned char c = bignum_byte(key->modulus, i);
MD5Update(&md5c, &c, 1); MD5Update(&md5c, &c, 1);
} }
numlen = ssh1_bignum_length(key->exponent) - 2; numlen = ssh1_bignum_length(key->exponent) - 2;
for (i = numlen; i-- ;) { for (i = numlen; i--;) {
unsigned char c = bignum_byte(key->exponent, i); unsigned char c = bignum_byte(key->exponent, i);
MD5Update(&md5c, &c, 1); MD5Update(&md5c, &c, 1);
} }
MD5Final(digest, &md5c); MD5Final(digest, &md5c);
sprintf(buffer, "%d ", bignum_bitcount(key->modulus)); sprintf(buffer, "%d ", bignum_bitcount(key->modulus));
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)
sprintf(buffer+strlen(buffer), "%s%02x", i?":":"", digest[i]); sprintf(buffer + strlen(buffer), "%s%02x", i ? ":" : "",
strncpy(str, buffer, len); str[len-1] = '\0'; digest[i]);
strncpy(str, buffer, len);
str[len - 1] = '\0';
slen = strlen(str); slen = strlen(str);
if (key->comment && slen < len-1) { if (key->comment && slen < len - 1) {
str[slen] = ' '; str[slen] = ' ';
strncpy(str+slen+1, key->comment, len-slen-1); strncpy(str + slen + 1, key->comment, len - slen - 1);
str[len-1] = '\0'; str[len - 1] = '\0';
} }
} }
@ -156,7 +170,8 @@ void rsa_fingerprint(char *str, int len, struct RSAKey *key) {
* data. We also check the private data itself: we ensure that p > * data. We also check the private data itself: we ensure that p >
* q and that iqmp really is the inverse of q mod p. * q and that iqmp really is the inverse of q mod p.
*/ */
int rsa_verify(struct RSAKey *key) { int rsa_verify(struct RSAKey *key)
{
Bignum n, ed, pm1, qm1; Bignum n, ed, pm1, qm1;
int cmp; int cmp;
@ -188,7 +203,7 @@ int rsa_verify(struct RSAKey *key) {
* Ensure p > q. * Ensure p > q.
*/ */
if (bignum_cmp(key->p, key->q) <= 0) if (bignum_cmp(key->p, key->q) <= 0)
return 0; return 0;
/* /*
* Ensure iqmp * q is congruent to 1, modulo p. * Ensure iqmp * q is congruent to 1, modulo p.
@ -197,16 +212,21 @@ int rsa_verify(struct RSAKey *key) {
cmp = bignum_cmp(n, One); cmp = bignum_cmp(n, One);
sfree(n); sfree(n);
if (cmp != 0) if (cmp != 0)
return 0; return 0;
return 1; return 1;
} }
void freersakey(struct RSAKey *key) { void freersakey(struct RSAKey *key)
if (key->modulus) freebn(key->modulus); {
if (key->exponent) freebn(key->exponent); if (key->modulus)
if (key->private_exponent) freebn(key->private_exponent); freebn(key->modulus);
if (key->comment) sfree(key->comment); if (key->exponent)
freebn(key->exponent);
if (key->private_exponent)
freebn(key->private_exponent);
if (key->comment)
sfree(key->comment);
} }
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
@ -225,36 +245,42 @@ void freersakey(struct RSAKey *key) {
(cp)[2] = (unsigned char)((value) >> 8); \ (cp)[2] = (unsigned char)((value) >> 8); \
(cp)[3] = (unsigned char)(value); } (cp)[3] = (unsigned char)(value); }
static void getstring(char **data, int *datalen, char **p, int *length) { static void getstring(char **data, int *datalen, char **p, int *length)
{
*p = NULL; *p = NULL;
if (*datalen < 4) if (*datalen < 4)
return; return;
*length = GET_32BIT(*data); *length = GET_32BIT(*data);
*datalen -= 4; *data += 4; *datalen -= 4;
*data += 4;
if (*datalen < *length) if (*datalen < *length)
return; return;
*p = *data; *p = *data;
*data += *length; *datalen -= *length; *data += *length;
*datalen -= *length;
} }
static Bignum getmp(char **data, int *datalen) { static Bignum getmp(char **data, int *datalen)
{
char *p; char *p;
int length; int length;
Bignum b; Bignum b;
getstring(data, datalen, &p, &length); getstring(data, datalen, &p, &length);
if (!p) if (!p)
return NULL; return NULL;
b = bignum_from_bytes(p, length); b = bignum_from_bytes(p, length);
return b; return b;
} }
static void *rsa2_newkey(char *data, int len) { static void *rsa2_newkey(char *data, int len)
{
char *p; char *p;
int slen; int slen;
struct RSAKey *rsa; struct RSAKey *rsa;
rsa = smalloc(sizeof(struct RSAKey)); rsa = smalloc(sizeof(struct RSAKey));
if (!rsa) return NULL; if (!rsa)
return NULL;
getstring(&data, &len, &p, &slen); getstring(&data, &len, &p, &slen);
if (!p || slen != 7 || memcmp(p, "ssh-rsa", 7)) { if (!p || slen != 7 || memcmp(p, "ssh-rsa", 7)) {
@ -269,87 +295,106 @@ static void *rsa2_newkey(char *data, int len) {
return rsa; return rsa;
} }
static void rsa2_freekey(void *key) { static void rsa2_freekey(void *key)
struct RSAKey *rsa = (struct RSAKey *)key; {
struct RSAKey *rsa = (struct RSAKey *) key;
freersakey(rsa); freersakey(rsa);
sfree(rsa); sfree(rsa);
} }
static char *rsa2_fmtkey(void *key) { static char *rsa2_fmtkey(void *key)
struct RSAKey *rsa = (struct RSAKey *)key; {
struct RSAKey *rsa = (struct RSAKey *) key;
char *p; char *p;
int len; int len;
len = rsastr_len(rsa); len = rsastr_len(rsa);
p = smalloc(len); p = smalloc(len);
rsastr_fmt(p, rsa); rsastr_fmt(p, rsa);
return p; return p;
} }
static unsigned char *rsa2_public_blob(void *key, int *len) { static unsigned char *rsa2_public_blob(void *key, int *len)
struct RSAKey *rsa = (struct RSAKey *)key; {
struct RSAKey *rsa = (struct RSAKey *) key;
int elen, mlen, bloblen; int elen, mlen, bloblen;
int i; int i;
unsigned char *blob, *p; unsigned char *blob, *p;
elen = (bignum_bitcount(rsa->exponent)+8)/8; elen = (bignum_bitcount(rsa->exponent) + 8) / 8;
mlen = (bignum_bitcount(rsa->modulus)+8)/8; mlen = (bignum_bitcount(rsa->modulus) + 8) / 8;
/* /*
* string "ssh-rsa", mpint exp, mpint mod. Total 19+elen+mlen. * string "ssh-rsa", mpint exp, mpint mod. Total 19+elen+mlen.
* (three length fields, 12+7=19). * (three length fields, 12+7=19).
*/ */
bloblen = 19+elen+mlen; bloblen = 19 + elen + mlen;
blob = smalloc(bloblen); blob = smalloc(bloblen);
p = blob; p = blob;
PUT_32BIT(p, 7); p += 4; PUT_32BIT(p, 7);
memcpy(p, "ssh-rsa", 7); p += 7; p += 4;
PUT_32BIT(p, elen); p += 4; memcpy(p, "ssh-rsa", 7);
for (i = elen; i-- ;) *p++ = bignum_byte(rsa->exponent, i); p += 7;
PUT_32BIT(p, mlen); p += 4; PUT_32BIT(p, elen);
for (i = mlen; i-- ;) *p++ = bignum_byte(rsa->modulus, i); p += 4;
for (i = elen; i--;)
*p++ = bignum_byte(rsa->exponent, i);
PUT_32BIT(p, mlen);
p += 4;
for (i = mlen; i--;)
*p++ = bignum_byte(rsa->modulus, i);
assert(p == blob + bloblen); assert(p == blob + bloblen);
*len = bloblen; *len = bloblen;
return blob; return blob;
} }
static unsigned char *rsa2_private_blob(void *key, int *len) { static unsigned char *rsa2_private_blob(void *key, int *len)
struct RSAKey *rsa = (struct RSAKey *)key; {
struct RSAKey *rsa = (struct RSAKey *) key;
int dlen, plen, qlen, ulen, bloblen; int dlen, plen, qlen, ulen, bloblen;
int i; int i;
unsigned char *blob, *p; unsigned char *blob, *p;
dlen = (bignum_bitcount(rsa->private_exponent)+8)/8; dlen = (bignum_bitcount(rsa->private_exponent) + 8) / 8;
plen = (bignum_bitcount(rsa->p)+8)/8; plen = (bignum_bitcount(rsa->p) + 8) / 8;
qlen = (bignum_bitcount(rsa->q)+8)/8; qlen = (bignum_bitcount(rsa->q) + 8) / 8;
ulen = (bignum_bitcount(rsa->iqmp)+8)/8; ulen = (bignum_bitcount(rsa->iqmp) + 8) / 8;
/* /*
* mpint private_exp, mpint p, mpint q, mpint iqmp. Total 16 + * mpint private_exp, mpint p, mpint q, mpint iqmp. Total 16 +
* sum of lengths. * sum of lengths.
*/ */
bloblen = 16+dlen+plen+qlen+ulen; bloblen = 16 + dlen + plen + qlen + ulen;
blob = smalloc(bloblen); blob = smalloc(bloblen);
p = blob; p = blob;
PUT_32BIT(p, dlen); p += 4; PUT_32BIT(p, dlen);
for (i = dlen; i-- ;) *p++ = bignum_byte(rsa->private_exponent, i); p += 4;
PUT_32BIT(p, plen); p += 4; for (i = dlen; i--;)
for (i = plen; i-- ;) *p++ = bignum_byte(rsa->p, i); *p++ = bignum_byte(rsa->private_exponent, i);
PUT_32BIT(p, qlen); p += 4; PUT_32BIT(p, plen);
for (i = qlen; i-- ;) *p++ = bignum_byte(rsa->q, i); p += 4;
PUT_32BIT(p, ulen); p += 4; for (i = plen; i--;)
for (i = ulen; i-- ;) *p++ = bignum_byte(rsa->iqmp, i); *p++ = bignum_byte(rsa->p, i);
PUT_32BIT(p, qlen);
p += 4;
for (i = qlen; i--;)
*p++ = bignum_byte(rsa->q, i);
PUT_32BIT(p, ulen);
p += 4;
for (i = ulen; i--;)
*p++ = bignum_byte(rsa->iqmp, i);
assert(p == blob + bloblen); assert(p == blob + bloblen);
*len = bloblen; *len = bloblen;
return blob; return blob;
} }
static void *rsa2_createkey(unsigned char *pub_blob, int pub_len, static void *rsa2_createkey(unsigned char *pub_blob, int pub_len,
unsigned char *priv_blob, int priv_len) { unsigned char *priv_blob, int priv_len)
{
struct RSAKey *rsa; struct RSAKey *rsa;
char *pb = (char *)priv_blob; char *pb = (char *) priv_blob;
rsa = rsa2_newkey((char *)pub_blob, pub_len); rsa = rsa2_newkey((char *) pub_blob, pub_len);
rsa->private_exponent = getmp(&pb, &priv_len); rsa->private_exponent = getmp(&pb, &priv_len);
rsa->p = getmp(&pb, &priv_len); rsa->p = getmp(&pb, &priv_len);
rsa->q = getmp(&pb, &priv_len); rsa->q = getmp(&pb, &priv_len);
@ -363,12 +408,14 @@ static void *rsa2_createkey(unsigned char *pub_blob, int pub_len,
return rsa; return rsa;
} }
static void *rsa2_openssh_createkey(unsigned char **blob, int *len) { static void *rsa2_openssh_createkey(unsigned char **blob, int *len)
char **b = (char **)blob; {
char **b = (char **) blob;
struct RSAKey *rsa; struct RSAKey *rsa;
rsa = smalloc(sizeof(struct RSAKey)); rsa = smalloc(sizeof(struct RSAKey));
if (!rsa) return NULL; if (!rsa)
return NULL;
rsa->comment = NULL; rsa->comment = NULL;
rsa->modulus = getmp(b, len); rsa->modulus = getmp(b, len);
@ -393,8 +440,9 @@ static void *rsa2_openssh_createkey(unsigned char **blob, int *len) {
return rsa; return rsa;
} }
static int rsa2_openssh_fmtkey(void *key, unsigned char *blob, int len) { static int rsa2_openssh_fmtkey(void *key, unsigned char *blob, int len)
struct RSAKey *rsa = (struct RSAKey *)key; {
struct RSAKey *rsa = (struct RSAKey *) key;
int bloblen, i; int bloblen, i;
bloblen = bloblen =
@ -402,8 +450,7 @@ static int rsa2_openssh_fmtkey(void *key, unsigned char *blob, int len) {
ssh2_bignum_length(rsa->exponent) + ssh2_bignum_length(rsa->exponent) +
ssh2_bignum_length(rsa->private_exponent) + ssh2_bignum_length(rsa->private_exponent) +
ssh2_bignum_length(rsa->iqmp) + ssh2_bignum_length(rsa->iqmp) +
ssh2_bignum_length(rsa->p) + ssh2_bignum_length(rsa->p) + ssh2_bignum_length(rsa->q);
ssh2_bignum_length(rsa->q);
if (bloblen > len) if (bloblen > len)
return bloblen; return bloblen;
@ -422,11 +469,12 @@ static int rsa2_openssh_fmtkey(void *key, unsigned char *blob, int len) {
return bloblen; return bloblen;
} }
static char *rsa2_fingerprint(void *key) { static char *rsa2_fingerprint(void *key)
struct RSAKey *rsa = (struct RSAKey *)key; {
struct RSAKey *rsa = (struct RSAKey *) key;
struct MD5Context md5c; struct MD5Context md5c;
unsigned char digest[16], lenbuf[4]; unsigned char digest[16], lenbuf[4];
char buffer[16*3+40]; char buffer[16 * 3 + 40];
char *ret; char *ret;
int numlen, i; int numlen, i;
@ -448,10 +496,11 @@ static char *rsa2_fingerprint(void *key) {
sprintf(buffer, "ssh-rsa %d ", bignum_bitcount(rsa->modulus)); sprintf(buffer, "ssh-rsa %d ", bignum_bitcount(rsa->modulus));
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)
sprintf(buffer+strlen(buffer), "%s%02x", i?":":"", digest[i]); sprintf(buffer + strlen(buffer), "%s%02x", i ? ":" : "",
ret = smalloc(strlen(buffer)+1); digest[i]);
ret = smalloc(strlen(buffer) + 1);
if (ret) if (ret)
strcpy(ret, buffer); strcpy(ret, buffer);
return ret; return ret;
} }
@ -480,15 +529,16 @@ static char *rsa2_fingerprint(void *key) {
* algorithms(2) 26 } * algorithms(2) 26 }
*/ */
static unsigned char asn1_weird_stuff[] = { static unsigned char asn1_weird_stuff[] = {
0x00,0x30,0x21,0x30,0x09,0x06,0x05,0x2B, 0x00, 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B,
0x0E,0x03,0x02,0x1A,0x05,0x00,0x04,0x14, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14,
}; };
#define ASN1_LEN ( (int) sizeof(asn1_weird_stuff) ) #define ASN1_LEN ( (int) sizeof(asn1_weird_stuff) )
static int rsa2_verifysig(void *key, char *sig, int siglen, static int rsa2_verifysig(void *key, char *sig, int siglen,
char *data, int datalen) { char *data, int datalen)
struct RSAKey *rsa = (struct RSAKey *)key; {
struct RSAKey *rsa = (struct RSAKey *) key;
Bignum in, out; Bignum in, out;
char *p; char *p;
int slen; int slen;
@ -497,7 +547,7 @@ static int rsa2_verifysig(void *key, char *sig, int siglen,
getstring(&sig, &siglen, &p, &slen); getstring(&sig, &siglen, &p, &slen);
if (!p || slen != 7 || memcmp(p, "ssh-rsa", 7)) { if (!p || slen != 7 || memcmp(p, "ssh-rsa", 7)) {
return 0; return 0;
} }
in = getmp(&sig, &siglen); in = getmp(&sig, &siglen);
out = modpow(in, rsa->exponent, rsa->modulus); out = modpow(in, rsa->exponent, rsa->modulus);
@ -507,33 +557,34 @@ static int rsa2_verifysig(void *key, char *sig, int siglen,
bytes = bignum_bitcount(rsa->modulus) / 8; bytes = bignum_bitcount(rsa->modulus) / 8;
/* Top (partial) byte should be zero. */ /* Top (partial) byte should be zero. */
if (bignum_byte(out, bytes-1) != 0) if (bignum_byte(out, bytes - 1) != 0)
ret = 0; ret = 0;
/* First whole byte should be 1. */ /* First whole byte should be 1. */
if (bignum_byte(out, bytes-2) != 1) if (bignum_byte(out, bytes - 2) != 1)
ret = 0; ret = 0;
/* Most of the rest should be FF. */ /* Most of the rest should be FF. */
for (i = bytes-3; i >= 20 + ASN1_LEN; i--) { for (i = bytes - 3; i >= 20 + ASN1_LEN; i--) {
if (bignum_byte(out, i) != 0xFF) if (bignum_byte(out, i) != 0xFF)
ret = 0; ret = 0;
} }
/* Then we expect to see the asn1_weird_stuff. */ /* Then we expect to see the asn1_weird_stuff. */
for (i = 20 + ASN1_LEN - 1, j=0; i >= 20; i--,j++) { for (i = 20 + ASN1_LEN - 1, j = 0; i >= 20; i--, j++) {
if (bignum_byte(out, i) != asn1_weird_stuff[j]) if (bignum_byte(out, i) != asn1_weird_stuff[j])
ret = 0; ret = 0;
} }
/* Finally, we expect to see the SHA-1 hash of the signed data. */ /* Finally, we expect to see the SHA-1 hash of the signed data. */
SHA_Simple(data, datalen, hash); SHA_Simple(data, datalen, hash);
for (i = 19, j=0; i >= 0; i--,j++) { for (i = 19, j = 0; i >= 0; i--, j++) {
if (bignum_byte(out, i) != hash[j]) if (bignum_byte(out, i) != hash[j])
ret = 0; ret = 0;
} }
return ret; return ret;
} }
unsigned char *rsa2_sign(void *key, char *data, int datalen, int *siglen) { unsigned char *rsa2_sign(void *key, char *data, int datalen, int *siglen)
struct RSAKey *rsa = (struct RSAKey *)key; {
struct RSAKey *rsa = (struct RSAKey *) key;
unsigned char *bytes; unsigned char *bytes;
int nbytes; int nbytes;
unsigned char hash[20]; unsigned char hash[20];
@ -542,15 +593,15 @@ unsigned char *rsa2_sign(void *key, char *data, int datalen, int *siglen) {
SHA_Simple(data, datalen, hash); SHA_Simple(data, datalen, hash);
nbytes = (bignum_bitcount(rsa->modulus)-1) / 8; nbytes = (bignum_bitcount(rsa->modulus) - 1) / 8;
bytes = smalloc(nbytes); bytes = smalloc(nbytes);
bytes[0] = 1; bytes[0] = 1;
for (i = 1; i < nbytes-20-ASN1_LEN; i++) for (i = 1; i < nbytes - 20 - ASN1_LEN; i++)
bytes[i] = 0xFF; bytes[i] = 0xFF;
for (i = nbytes-20-ASN1_LEN, j=0; i < nbytes-20; i++,j++) for (i = nbytes - 20 - ASN1_LEN, j = 0; i < nbytes - 20; i++, j++)
bytes[i] = asn1_weird_stuff[j]; bytes[i] = asn1_weird_stuff[j];
for (i = nbytes-20, j=0; i < nbytes; i++,j++) for (i = nbytes - 20, j = 0; i < nbytes; i++, j++)
bytes[i] = hash[j]; bytes[i] = hash[j];
in = bignum_from_bytes(bytes, nbytes); in = bignum_from_bytes(bytes, nbytes);
@ -559,16 +610,16 @@ unsigned char *rsa2_sign(void *key, char *data, int datalen, int *siglen) {
out = modpow(in, rsa->private_exponent, rsa->modulus); out = modpow(in, rsa->private_exponent, rsa->modulus);
freebn(in); freebn(in);
nbytes = (bignum_bitcount(out)+7)/8; nbytes = (bignum_bitcount(out) + 7) / 8;
bytes = smalloc(4+7+4+nbytes); bytes = smalloc(4 + 7 + 4 + nbytes);
PUT_32BIT(bytes, 7); PUT_32BIT(bytes, 7);
memcpy(bytes+4, "ssh-rsa", 7); memcpy(bytes + 4, "ssh-rsa", 7);
PUT_32BIT(bytes+4+7, nbytes); PUT_32BIT(bytes + 4 + 7, nbytes);
for (i = 0; i < nbytes; i++) for (i = 0; i < nbytes; i++)
bytes[4+7+4+i] = bignum_byte(out, nbytes-1-i); bytes[4 + 7 + 4 + i] = bignum_byte(out, nbytes - 1 - i);
freebn(out); freebn(out);
*siglen = 4+7+4+nbytes; *siglen = 4 + 7 + 4 + nbytes;
return bytes; return bytes;
} }

View File

@ -4,26 +4,33 @@
#include "ssh.h" #include "ssh.h"
#define RSA_EXPONENT 37 /* we like this prime */ #define RSA_EXPONENT 37 /* we like this prime */
#if 0 /* bignum diagnostic function */ #if 0 /* bignum diagnostic function */
static void diagbn(char *prefix, Bignum md) { static void diagbn(char *prefix, Bignum md)
{
int i, nibbles, morenibbles; int i, nibbles, morenibbles;
static const char hex[] = "0123456789ABCDEF"; static const char hex[] = "0123456789ABCDEF";
printf("%s0x", prefix ? prefix : ""); printf("%s0x", prefix ? prefix : "");
nibbles = (3 + bignum_bitcount(md))/4; if (nibbles<1) nibbles=1; nibbles = (3 + bignum_bitcount(md)) / 4;
morenibbles = 4*md[0] - nibbles; if (nibbles < 1)
for (i=0; i<morenibbles; i++) putchar('-'); nibbles = 1;
for (i=nibbles; i-- ;) morenibbles = 4 * md[0] - nibbles;
putchar(hex[(bignum_byte(md, i/2) >> (4*(i%2))) & 0xF]); for (i = 0; i < morenibbles; i++)
putchar('-');
for (i = nibbles; i--;)
putchar(hex[(bignum_byte(md, i / 2) >> (4 * (i % 2))) & 0xF]);
if (prefix) putchar('\n'); if (prefix)
putchar('\n');
} }
#endif #endif
int rsa_generate(struct RSAKey *key, int bits, progfn_t pfn, void *pfnparam) { int rsa_generate(struct RSAKey *key, int bits, progfn_t pfn,
void *pfnparam)
{
Bignum pm1, qm1, phi_n; Bignum pm1, qm1, phi_n;
/* /*
@ -54,8 +61,8 @@ int rsa_generate(struct RSAKey *key, int bits, progfn_t pfn, void *pfnparam) {
* time. We do this in 16-bit fixed point, so 29.34 becomes * time. We do this in 16-bit fixed point, so 29.34 becomes
* 0x1D.57C4. * 0x1D.57C4.
*/ */
pfn(pfnparam, -1, -0x1D57C4/(bits/2)); pfn(pfnparam, -1, -0x1D57C4 / (bits / 2));
pfn(pfnparam, -2, -0x1D57C4/(bits-bits/2)); pfn(pfnparam, -2, -0x1D57C4 / (bits - bits / 2));
pfn(pfnparam, -3, 5); pfn(pfnparam, -3, 5);
/* /*
@ -70,16 +77,16 @@ int rsa_generate(struct RSAKey *key, int bits, progfn_t pfn, void *pfnparam) {
* general that's slightly more fiddly to arrange. By choosing * general that's slightly more fiddly to arrange. By choosing
* a prime e, we can simplify the criterion.) * a prime e, we can simplify the criterion.)
*/ */
key->p = primegen(bits/2, RSA_EXPONENT, 1, 1, pfn, pfnparam); key->p = primegen(bits / 2, RSA_EXPONENT, 1, 1, pfn, pfnparam);
key->q = primegen(bits - bits/2, RSA_EXPONENT, 1, 2, pfn, pfnparam); key->q = primegen(bits - bits / 2, RSA_EXPONENT, 1, 2, pfn, pfnparam);
/* /*
* Ensure p > q, by swapping them if not. * Ensure p > q, by swapping them if not.
*/ */
if (bignum_cmp(key->p, key->q) < 0) { if (bignum_cmp(key->p, key->q) < 0) {
Bignum t = key->p; Bignum t = key->p;
key->p = key->q; key->p = key->q;
key->q = t; key->q = t;
} }
/* /*

190
sshsha.c
View File

@ -13,7 +13,8 @@
#define rol(x,y) ( ((x) << (y)) | (((uint32)x) >> (32-y)) ) #define rol(x,y) ( ((x) << (y)) | (((uint32)x) >> (32-y)) )
void SHA_Core_Init(uint32 h[5]) { void SHA_Core_Init(uint32 h[5])
{
h[0] = 0x67452301; h[0] = 0x67452301;
h[1] = 0xefcdab89; h[1] = 0xefcdab89;
h[2] = 0x98badcfe; h[2] = 0x98badcfe;
@ -21,17 +22,18 @@ void SHA_Core_Init(uint32 h[5]) {
h[4] = 0xc3d2e1f0; h[4] = 0xc3d2e1f0;
} }
void SHATransform(word32 *digest, word32 *block) { void SHATransform(word32 * digest, word32 * block)
{
word32 w[80]; word32 w[80];
word32 a,b,c,d,e; word32 a, b, c, d, e;
int t; int t;
for (t = 0; t < 16; t++) for (t = 0; t < 16; t++)
w[t] = block[t]; w[t] = block[t];
for (t = 16; t < 80; t++) { for (t = 16; t < 80; t++) {
word32 tmp = w[t-3] ^ w[t-8] ^ w[t-14] ^ w[t-16]; word32 tmp = w[t - 3] ^ w[t - 8] ^ w[t - 14] ^ w[t - 16];
w[t] = rol(tmp, 1); w[t] = rol(tmp, 1);
} }
a = digest[0]; a = digest[0];
@ -41,20 +43,39 @@ void SHATransform(word32 *digest, word32 *block) {
e = digest[4]; e = digest[4];
for (t = 0; t < 20; t++) { for (t = 0; t < 20; t++) {
word32 tmp = rol(a, 5) + ( (b&c) | (d&~b) ) + e + w[t] + 0x5a827999; word32 tmp =
e = d; d = c; c = rol(b, 30); b = a; a = tmp; rol(a, 5) + ((b & c) | (d & ~b)) + e + w[t] + 0x5a827999;
e = d;
d = c;
c = rol(b, 30);
b = a;
a = tmp;
} }
for (t = 20; t < 40; t++) { for (t = 20; t < 40; t++) {
word32 tmp = rol(a, 5) + (b^c^d) + e + w[t] + 0x6ed9eba1; word32 tmp = rol(a, 5) + (b ^ c ^ d) + e + w[t] + 0x6ed9eba1;
e = d; d = c; c = rol(b, 30); b = a; a = tmp; e = d;
d = c;
c = rol(b, 30);
b = a;
a = tmp;
} }
for (t = 40; t < 60; t++) { for (t = 40; t < 60; t++) {
word32 tmp = rol(a, 5) + ( (b&c) | (b&d) | (c&d) ) + e + w[t] + 0x8f1bbcdc; word32 tmp = rol(a,
e = d; d = c; c = rol(b, 30); b = a; a = tmp; 5) + ((b & c) | (b & d) | (c & d)) + e + w[t] +
0x8f1bbcdc;
e = d;
d = c;
c = rol(b, 30);
b = a;
a = tmp;
} }
for (t = 60; t < 80; t++) { for (t = 60; t < 80; t++) {
word32 tmp = rol(a, 5) + (b^c^d) + e + w[t] + 0xca62c1d6; word32 tmp = rol(a, 5) + (b ^ c ^ d) + e + w[t] + 0xca62c1d6;
e = d; d = c; c = rol(b, 30); b = a; a = tmp; e = d;
d = c;
c = rol(b, 30);
b = a;
a = tmp;
} }
digest[0] += a; digest[0] += a;
@ -70,14 +91,16 @@ void SHATransform(word32 *digest, word32 *block) {
* the end, and pass those blocks to the core SHA algorithm. * the end, and pass those blocks to the core SHA algorithm.
*/ */
void SHA_Init(SHA_State *s) { void SHA_Init(SHA_State * s)
{
SHA_Core_Init(s->h); SHA_Core_Init(s->h);
s->blkused = 0; s->blkused = 0;
s->lenhi = s->lenlo = 0; s->lenhi = s->lenlo = 0;
} }
void SHA_Bytes(SHA_State *s, void *p, int len) { void SHA_Bytes(SHA_State * s, void *p, int len)
unsigned char *q = (unsigned char *)p; {
unsigned char *q = (unsigned char *) p;
uint32 wordblock[16]; uint32 wordblock[16];
uint32 lenw = len; uint32 lenw = len;
int i; int i;
@ -88,48 +111,49 @@ void SHA_Bytes(SHA_State *s, void *p, int len) {
s->lenlo += lenw; s->lenlo += lenw;
s->lenhi += (s->lenlo < lenw); s->lenhi += (s->lenlo < lenw);
if (s->blkused && s->blkused+len < 64) { if (s->blkused && s->blkused + len < 64) {
/* /*
* Trivial case: just add to the block. * Trivial case: just add to the block.
*/ */
memcpy(s->block + s->blkused, q, len); memcpy(s->block + s->blkused, q, len);
s->blkused += len; s->blkused += len;
} else { } else {
/* /*
* We must complete and process at least one block. * We must complete and process at least one block.
*/ */
while (s->blkused + len >= 64) { while (s->blkused + len >= 64) {
memcpy(s->block + s->blkused, q, 64 - s->blkused); memcpy(s->block + s->blkused, q, 64 - s->blkused);
q += 64 - s->blkused; q += 64 - s->blkused;
len -= 64 - s->blkused; len -= 64 - s->blkused;
/* Now process the block. Gather bytes big-endian into words */ /* Now process the block. Gather bytes big-endian into words */
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
wordblock[i] = wordblock[i] =
( ((uint32)s->block[i*4+0]) << 24 ) | (((uint32) s->block[i * 4 + 0]) << 24) |
( ((uint32)s->block[i*4+1]) << 16 ) | (((uint32) s->block[i * 4 + 1]) << 16) |
( ((uint32)s->block[i*4+2]) << 8 ) | (((uint32) s->block[i * 4 + 2]) << 8) |
( ((uint32)s->block[i*4+3]) << 0 ); (((uint32) s->block[i * 4 + 3]) << 0);
} }
SHATransform(s->h, wordblock); SHATransform(s->h, wordblock);
s->blkused = 0; s->blkused = 0;
} }
memcpy(s->block, q, len); memcpy(s->block, q, len);
s->blkused = len; s->blkused = len;
} }
} }
void SHA_Final(SHA_State *s, unsigned char *output) { void SHA_Final(SHA_State * s, unsigned char *output)
{
int i; int i;
int pad; int pad;
unsigned char c[64]; unsigned char c[64];
uint32 lenhi, lenlo; uint32 lenhi, lenlo;
if (s->blkused >= 56) if (s->blkused >= 56)
pad = 56 + 64 - s->blkused; pad = 56 + 64 - s->blkused;
else else
pad = 56 - s->blkused; pad = 56 - s->blkused;
lenhi = (s->lenhi << 3) | (s->lenlo >> (32-3)); lenhi = (s->lenhi << 3) | (s->lenlo >> (32 - 3));
lenlo = (s->lenlo << 3); lenlo = (s->lenlo << 3);
memset(c, 0, pad); memset(c, 0, pad);
@ -138,24 +162,25 @@ void SHA_Final(SHA_State *s, unsigned char *output) {
c[0] = (lenhi >> 24) & 0xFF; c[0] = (lenhi >> 24) & 0xFF;
c[1] = (lenhi >> 16) & 0xFF; c[1] = (lenhi >> 16) & 0xFF;
c[2] = (lenhi >> 8) & 0xFF; c[2] = (lenhi >> 8) & 0xFF;
c[3] = (lenhi >> 0) & 0xFF; c[3] = (lenhi >> 0) & 0xFF;
c[4] = (lenlo >> 24) & 0xFF; c[4] = (lenlo >> 24) & 0xFF;
c[5] = (lenlo >> 16) & 0xFF; c[5] = (lenlo >> 16) & 0xFF;
c[6] = (lenlo >> 8) & 0xFF; c[6] = (lenlo >> 8) & 0xFF;
c[7] = (lenlo >> 0) & 0xFF; c[7] = (lenlo >> 0) & 0xFF;
SHA_Bytes(s, &c, 8); SHA_Bytes(s, &c, 8);
for (i = 0; i < 5; i++) { for (i = 0; i < 5; i++) {
output[i*4 ] = (s->h[i] >> 24) & 0xFF; output[i * 4] = (s->h[i] >> 24) & 0xFF;
output[i*4+1] = (s->h[i] >> 16) & 0xFF; output[i * 4 + 1] = (s->h[i] >> 16) & 0xFF;
output[i*4+2] = (s->h[i] >> 8) & 0xFF; output[i * 4 + 2] = (s->h[i] >> 8) & 0xFF;
output[i*4+3] = (s->h[i] ) & 0xFF; output[i * 4 + 3] = (s->h[i]) & 0xFF;
} }
} }
void SHA_Simple(void *p, int len, unsigned char *output) { void SHA_Simple(void *p, int len, unsigned char *output)
{
SHA_State s; SHA_State s;
SHA_Init(&s); SHA_Init(&s);
@ -171,70 +196,79 @@ void SHA_Simple(void *p, int len, unsigned char *output) {
static SHA_State sha1_cs_mac_s1, sha1_cs_mac_s2; static SHA_State sha1_cs_mac_s1, sha1_cs_mac_s2;
static SHA_State sha1_sc_mac_s1, sha1_sc_mac_s2; static SHA_State sha1_sc_mac_s1, sha1_sc_mac_s2;
static void sha1_key(SHA_State *s1, SHA_State *s2, static void sha1_key(SHA_State * s1, SHA_State * s2,
unsigned char *key, int len) { unsigned char *key, int len)
{
unsigned char foo[64]; unsigned char foo[64];
int i; int i;
memset(foo, 0x36, 64); memset(foo, 0x36, 64);
for (i = 0; i < len && i < 64; i++) for (i = 0; i < len && i < 64; i++)
foo[i] ^= key[i]; foo[i] ^= key[i];
SHA_Init(s1); SHA_Init(s1);
SHA_Bytes(s1, foo, 64); SHA_Bytes(s1, foo, 64);
memset(foo, 0x5C, 64); memset(foo, 0x5C, 64);
for (i = 0; i < len && i < 64; i++) for (i = 0; i < len && i < 64; i++)
foo[i] ^= key[i]; foo[i] ^= key[i];
SHA_Init(s2); SHA_Init(s2);
SHA_Bytes(s2, foo, 64); SHA_Bytes(s2, foo, 64);
memset(foo, 0, 64); /* burn the evidence */ memset(foo, 0, 64); /* burn the evidence */
} }
static void sha1_cskey(unsigned char *key) { static void sha1_cskey(unsigned char *key)
{
sha1_key(&sha1_cs_mac_s1, &sha1_cs_mac_s2, key, 20); sha1_key(&sha1_cs_mac_s1, &sha1_cs_mac_s2, key, 20);
} }
static void sha1_sckey(unsigned char *key) { static void sha1_sckey(unsigned char *key)
{
sha1_key(&sha1_sc_mac_s1, &sha1_sc_mac_s2, key, 20); sha1_key(&sha1_sc_mac_s1, &sha1_sc_mac_s2, key, 20);
} }
static void sha1_cskey_buggy(unsigned char *key) { static void sha1_cskey_buggy(unsigned char *key)
{
sha1_key(&sha1_cs_mac_s1, &sha1_cs_mac_s2, key, 16); sha1_key(&sha1_cs_mac_s1, &sha1_cs_mac_s2, key, 16);
} }
static void sha1_sckey_buggy(unsigned char *key) { static void sha1_sckey_buggy(unsigned char *key)
{
sha1_key(&sha1_sc_mac_s1, &sha1_sc_mac_s2, key, 16); sha1_key(&sha1_sc_mac_s1, &sha1_sc_mac_s2, key, 16);
} }
static void sha1_do_hmac(SHA_State *s1, SHA_State *s2, static void sha1_do_hmac(SHA_State * s1, SHA_State * s2,
unsigned char *blk, int len, unsigned long seq, unsigned char *blk, int len, unsigned long seq,
unsigned char *hmac) { unsigned char *hmac)
{
SHA_State s; SHA_State s;
unsigned char intermediate[20]; unsigned char intermediate[20];
intermediate[0] = (unsigned char)((seq >> 24) & 0xFF); intermediate[0] = (unsigned char) ((seq >> 24) & 0xFF);
intermediate[1] = (unsigned char)((seq >> 16) & 0xFF); intermediate[1] = (unsigned char) ((seq >> 16) & 0xFF);
intermediate[2] = (unsigned char)((seq >> 8) & 0xFF); intermediate[2] = (unsigned char) ((seq >> 8) & 0xFF);
intermediate[3] = (unsigned char)((seq ) & 0xFF); intermediate[3] = (unsigned char) ((seq) & 0xFF);
s = *s1; /* structure copy */ s = *s1; /* structure copy */
SHA_Bytes(&s, intermediate, 4); SHA_Bytes(&s, intermediate, 4);
SHA_Bytes(&s, blk, len); SHA_Bytes(&s, blk, len);
SHA_Final(&s, intermediate); SHA_Final(&s, intermediate);
s = *s2; /* structure copy */ s = *s2; /* structure copy */
SHA_Bytes(&s, intermediate, 20); SHA_Bytes(&s, intermediate, 20);
SHA_Final(&s, hmac); SHA_Final(&s, hmac);
} }
static void sha1_generate(unsigned char *blk, int len, unsigned long seq) { static void sha1_generate(unsigned char *blk, int len, unsigned long seq)
sha1_do_hmac(&sha1_cs_mac_s1, &sha1_cs_mac_s2, blk, len, seq, blk+len); {
sha1_do_hmac(&sha1_cs_mac_s1, &sha1_cs_mac_s2, blk, len, seq,
blk + len);
} }
static int sha1_verify(unsigned char *blk, int len, unsigned long seq) { static int sha1_verify(unsigned char *blk, int len, unsigned long seq)
{
unsigned char correct[20]; unsigned char correct[20];
sha1_do_hmac(&sha1_sc_mac_s1, &sha1_sc_mac_s2, blk, len, seq, correct); sha1_do_hmac(&sha1_sc_mac_s1, &sha1_sc_mac_s2, blk, len, seq, correct);
return !memcmp(correct, blk+len, 20); return !memcmp(correct, blk + len, 20);
} }
const struct ssh_mac ssh_sha1 = { const struct ssh_mac ssh_sha1 = {

987
sshzlib.c

File diff suppressed because it is too large Load Diff

View File

@ -79,7 +79,7 @@ void store_host_key(char *hostname, int port, char *keytype, char *key);
* Functions to access PuTTY's random number seed file. * Functions to access PuTTY's random number seed file.
*/ */
typedef void (*noise_consumer_t)(void *data, int len); typedef void (*noise_consumer_t) (void *data, int len);
/* /*
* Read PuTTY's random seed file and pass its contents to a noise * Read PuTTY's random seed file and pass its contents to a noise

550
telnet.c
View File

@ -13,73 +13,73 @@
static Socket s = NULL; static Socket s = NULL;
#define IAC 255 /* interpret as command: */ #define IAC 255 /* interpret as command: */
#define DONT 254 /* you are not to use option */ #define DONT 254 /* you are not to use option */
#define DO 253 /* please, you use option */ #define DO 253 /* please, you use option */
#define WONT 252 /* I won't use option */ #define WONT 252 /* I won't use option */
#define WILL 251 /* I will use option */ #define WILL 251 /* I will use option */
#define SB 250 /* interpret as subnegotiation */ #define SB 250 /* interpret as subnegotiation */
#define SE 240 /* end sub negotiation */ #define SE 240 /* end sub negotiation */
#define GA 249 /* you may reverse the line */ #define GA 249 /* you may reverse the line */
#define EL 248 /* erase the current line */ #define EL 248 /* erase the current line */
#define EC 247 /* erase the current character */ #define EC 247 /* erase the current character */
#define AYT 246 /* are you there */ #define AYT 246 /* are you there */
#define AO 245 /* abort output--but let prog finish */ #define AO 245 /* abort output--but let prog finish */
#define IP 244 /* interrupt process--permanently */ #define IP 244 /* interrupt process--permanently */
#define BREAK 243 /* break */ #define BREAK 243 /* break */
#define DM 242 /* data mark--for connect. cleaning */ #define DM 242 /* data mark--for connect. cleaning */
#define NOP 241 /* nop */ #define NOP 241 /* nop */
#define EOR 239 /* end of record (transparent mode) */ #define EOR 239 /* end of record (transparent mode) */
#define ABORT 238 /* Abort process */ #define ABORT 238 /* Abort process */
#define SUSP 237 /* Suspend process */ #define SUSP 237 /* Suspend process */
#define xEOF 236 /* End of file: EOF is already used... */ #define xEOF 236 /* End of file: EOF is already used... */
#define TELOPT_BINARY 0 /* 8-bit data path */ #define TELOPT_BINARY 0 /* 8-bit data path */
#define TELOPT_ECHO 1 /* echo */ #define TELOPT_ECHO 1 /* echo */
#define TELOPT_RCP 2 /* prepare to reconnect */ #define TELOPT_RCP 2 /* prepare to reconnect */
#define TELOPT_SGA 3 /* suppress go ahead */ #define TELOPT_SGA 3 /* suppress go ahead */
#define TELOPT_NAMS 4 /* approximate message size */ #define TELOPT_NAMS 4 /* approximate message size */
#define TELOPT_STATUS 5 /* give status */ #define TELOPT_STATUS 5 /* give status */
#define TELOPT_TM 6 /* timing mark */ #define TELOPT_TM 6 /* timing mark */
#define TELOPT_RCTE 7 /* remote controlled transmission and echo */ #define TELOPT_RCTE 7 /* remote controlled transmission and echo */
#define TELOPT_NAOL 8 /* negotiate about output line width */ #define TELOPT_NAOL 8 /* negotiate about output line width */
#define TELOPT_NAOP 9 /* negotiate about output page size */ #define TELOPT_NAOP 9 /* negotiate about output page size */
#define TELOPT_NAOCRD 10 /* negotiate about CR disposition */ #define TELOPT_NAOCRD 10 /* negotiate about CR disposition */
#define TELOPT_NAOHTS 11 /* negotiate about horizontal tabstops */ #define TELOPT_NAOHTS 11 /* negotiate about horizontal tabstops */
#define TELOPT_NAOHTD 12 /* negotiate about horizontal tab disposition */ #define TELOPT_NAOHTD 12 /* negotiate about horizontal tab disposition */
#define TELOPT_NAOFFD 13 /* negotiate about formfeed disposition */ #define TELOPT_NAOFFD 13 /* negotiate about formfeed disposition */
#define TELOPT_NAOVTS 14 /* negotiate about vertical tab stops */ #define TELOPT_NAOVTS 14 /* negotiate about vertical tab stops */
#define TELOPT_NAOVTD 15 /* negotiate about vertical tab disposition */ #define TELOPT_NAOVTD 15 /* negotiate about vertical tab disposition */
#define TELOPT_NAOLFD 16 /* negotiate about output LF disposition */ #define TELOPT_NAOLFD 16 /* negotiate about output LF disposition */
#define TELOPT_XASCII 17 /* extended ascic character set */ #define TELOPT_XASCII 17 /* extended ascic character set */
#define TELOPT_LOGOUT 18 /* force logout */ #define TELOPT_LOGOUT 18 /* force logout */
#define TELOPT_BM 19 /* byte macro */ #define TELOPT_BM 19 /* byte macro */
#define TELOPT_DET 20 /* data entry terminal */ #define TELOPT_DET 20 /* data entry terminal */
#define TELOPT_SUPDUP 21 /* supdup protocol */ #define TELOPT_SUPDUP 21 /* supdup protocol */
#define TELOPT_SUPDUPOUTPUT 22 /* supdup output */ #define TELOPT_SUPDUPOUTPUT 22 /* supdup output */
#define TELOPT_SNDLOC 23 /* send location */ #define TELOPT_SNDLOC 23 /* send location */
#define TELOPT_TTYPE 24 /* terminal type */ #define TELOPT_TTYPE 24 /* terminal type */
#define TELOPT_EOR 25 /* end or record */ #define TELOPT_EOR 25 /* end or record */
#define TELOPT_TUID 26 /* TACACS user identification */ #define TELOPT_TUID 26 /* TACACS user identification */
#define TELOPT_OUTMRK 27 /* output marking */ #define TELOPT_OUTMRK 27 /* output marking */
#define TELOPT_TTYLOC 28 /* terminal location number */ #define TELOPT_TTYLOC 28 /* terminal location number */
#define TELOPT_3270REGIME 29 /* 3270 regime */ #define TELOPT_3270REGIME 29 /* 3270 regime */
#define TELOPT_X3PAD 30 /* X.3 PAD */ #define TELOPT_X3PAD 30 /* X.3 PAD */
#define TELOPT_NAWS 31 /* window size */ #define TELOPT_NAWS 31 /* window size */
#define TELOPT_TSPEED 32 /* terminal speed */ #define TELOPT_TSPEED 32 /* terminal speed */
#define TELOPT_LFLOW 33 /* remote flow control */ #define TELOPT_LFLOW 33 /* remote flow control */
#define TELOPT_LINEMODE 34 /* Linemode option */ #define TELOPT_LINEMODE 34 /* Linemode option */
#define TELOPT_XDISPLOC 35 /* X Display Location */ #define TELOPT_XDISPLOC 35 /* X Display Location */
#define TELOPT_OLD_ENVIRON 36 /* Old - Environment variables */ #define TELOPT_OLD_ENVIRON 36 /* Old - Environment variables */
#define TELOPT_AUTHENTICATION 37/* Authenticate */ #define TELOPT_AUTHENTICATION 37 /* Authenticate */
#define TELOPT_ENCRYPT 38 /* Encryption option */ #define TELOPT_ENCRYPT 38 /* Encryption option */
#define TELOPT_NEW_ENVIRON 39 /* New - Environment variables */ #define TELOPT_NEW_ENVIRON 39 /* New - Environment variables */
#define TELOPT_EXOPL 255 /* extended-options-list */ #define TELOPT_EXOPL 255 /* extended-options-list */
#define TELQUAL_IS 0 /* option is... */ #define TELQUAL_IS 0 /* option is... */
#define TELQUAL_SEND 1 /* send option */ #define TELQUAL_SEND 1 /* send option */
#define TELQUAL_INFO 2 /* ENVIRON: informational version of IS */ #define TELQUAL_INFO 2 /* ENVIRON: informational version of IS */
#define BSD_VAR 1 #define BSD_VAR 1
#define BSD_VALUE 0 #define BSD_VALUE 0
#define RFC_VAR 0 #define RFC_VAR 0
@ -91,15 +91,49 @@ static Socket s = NULL;
#define iswritable(x) ( (x) != IAC && (x) != CR ) #define iswritable(x) ( (x) != IAC && (x) != CR )
static char *telopt(int opt) { static char *telopt(int opt)
{
#define i(x) if (opt == TELOPT_ ## x) return #x; #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(BINARY);
i(NAOL); i(NAOP); i(NAOCRD); i(NAOHTS); i(NAOHTD); i(NAOFFD); i(NAOVTS); i(ECHO);
i(NAOVTD); i(NAOLFD); i(XASCII); i(LOGOUT); i(BM); i(DET); i(SUPDUP); i(RCP);
i(SUPDUPOUTPUT); i(SNDLOC); i(TTYPE); i(EOR); i(TUID); i(OUTMRK); i(SGA);
i(TTYLOC); i(X3PAD); i(NAWS); i(TSPEED); i(LFLOW); i(LINEMODE); i(NAMS);
i(XDISPLOC); i(OLD_ENVIRON); i(AUTHENTICATION); i(ENCRYPT); i(STATUS);
i(NEW_ENVIRON); i(EXOPL); 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 #undef i
return "<unknown>"; return "<unknown>";
} }
@ -116,16 +150,24 @@ struct Opt {
} state; } state;
}; };
static struct Opt o_naws = {WILL, WONT, DO, DONT, TELOPT_NAWS, REQUESTED}; static struct Opt o_naws =
static struct Opt o_tspeed = {WILL, WONT, DO, DONT, TELOPT_TSPEED, REQUESTED}; { WILL, WONT, DO, DONT, TELOPT_NAWS, REQUESTED };
static struct Opt o_ttype = {WILL, WONT, DO, DONT, TELOPT_TTYPE, REQUESTED}; static struct Opt o_tspeed =
static struct Opt o_oenv = {WILL, WONT, DO, DONT, TELOPT_OLD_ENVIRON, { WILL, WONT, DO, DONT, TELOPT_TSPEED, REQUESTED };
INACTIVE}; static struct Opt o_ttype =
static struct Opt o_nenv = {WILL, WONT, DO, DONT, TELOPT_NEW_ENVIRON, { WILL, WONT, DO, DONT, TELOPT_TTYPE, REQUESTED };
REQUESTED}; static struct Opt o_oenv = { WILL, WONT, DO, DONT, TELOPT_OLD_ENVIRON,
static struct Opt o_echo = {DO, DONT, WILL, WONT, TELOPT_ECHO, REQUESTED}; INACTIVE
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 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[] = { static struct Opt *opts[] = {
&o_naws, &o_tspeed, &o_ttype, &o_oenv, &o_nenv, &o_echo, &o_naws, &o_tspeed, &o_ttype, &o_oenv, &o_nenv, &o_echo,
@ -140,12 +182,14 @@ static char *sb_buf = NULL;
static int sb_size = 0; static int sb_size = 0;
#define SB_DELTA 1024 #define SB_DELTA 1024
static void c_write1(int c) { static void c_write1(int c)
char cc = (char)c; {
char cc = (char) c;
from_backend(0, &cc, 1); from_backend(0, &cc, 1);
} }
static void log_option (char *sender, int cmd, int option) { static void log_option(char *sender, int cmd, int option)
{
char buf[50]; char buf[50];
sprintf(buf, "%s:\t%s %s", sender, sprintf(buf, "%s:\t%s %s", sender,
(cmd == WILL ? "WILL" : cmd == WONT ? "WONT" : (cmd == WILL ? "WILL" : cmd == WONT ? "WONT" :
@ -154,32 +198,38 @@ static void log_option (char *sender, int cmd, int option) {
logevent(buf); logevent(buf);
} }
static void send_opt (int cmd, int option) { static void send_opt(int cmd, int option)
{
unsigned char b[3]; unsigned char b[3];
b[0] = IAC; b[1] = cmd; b[2] = option; b[0] = IAC;
b[1] = cmd;
b[2] = option;
sk_write(s, b, 3); sk_write(s, b, 3);
log_option("client", cmd, option); log_option("client", cmd, option);
} }
static void deactivate_option (struct Opt *o) { static void deactivate_option(struct Opt *o)
{
if (o->state == REQUESTED || o->state == ACTIVE) if (o->state == REQUESTED || o->state == ACTIVE)
send_opt (o->nsend, o->option); send_opt(o->nsend, o->option);
o->state = REALLY_INACTIVE; o->state = REALLY_INACTIVE;
} }
/* /*
* Generate side effects of enabling or disabling an option. * Generate side effects of enabling or disabling an option.
*/ */
static void option_side_effects(struct Opt *o, int enabled) { static void option_side_effects(struct Opt *o, int enabled)
{
if (o->option == TELOPT_ECHO && o->send == DO) if (o->option == TELOPT_ECHO && o->send == DO)
echoing = !enabled; echoing = !enabled;
else if (o->option == TELOPT_SGA && o->send == DO) else if (o->option == TELOPT_SGA && o->send == DO)
editing = !enabled; editing = !enabled;
ldisc_send(NULL, 0); /* cause ldisc to notice the change */ ldisc_send(NULL, 0); /* cause ldisc to notice the change */
} }
static void activate_option (struct Opt *o) { static void activate_option(struct Opt *o)
{
if (o->send == WILL && o->option == TELOPT_NAWS) if (o->send == WILL && o->option == TELOPT_NAWS)
telnet_size(); telnet_size();
if (o->send == WILL && if (o->send == WILL &&
@ -189,40 +239,43 @@ static void activate_option (struct Opt *o) {
* We may only have one kind of ENVIRON going at a time. * We may only have one kind of ENVIRON going at a time.
* This is a hack, but who cares. * This is a hack, but who cares.
*/ */
deactivate_option (o->option==TELOPT_NEW_ENVIRON ? &o_oenv : &o_nenv); deactivate_option(o->option ==
TELOPT_NEW_ENVIRON ? &o_oenv : &o_nenv);
} }
option_side_effects(o, 1); option_side_effects(o, 1);
} }
static void refused_option (struct Opt *o) { static void refused_option(struct Opt *o)
{
if (o->send == WILL && o->option == TELOPT_NEW_ENVIRON && if (o->send == WILL && o->option == TELOPT_NEW_ENVIRON &&
o_oenv.state == INACTIVE) { o_oenv.state == INACTIVE) {
send_opt (WILL, TELOPT_OLD_ENVIRON); send_opt(WILL, TELOPT_OLD_ENVIRON);
o_oenv.state = REQUESTED; o_oenv.state = REQUESTED;
} }
option_side_effects(o, 0); option_side_effects(o, 0);
} }
static void proc_rec_opt (int cmd, int option) { static void proc_rec_opt(int cmd, int option)
{
struct Opt **o; struct Opt **o;
log_option ("server", cmd, option); log_option("server", cmd, option);
for (o = opts; *o; o++) { for (o = opts; *o; o++) {
if ((*o)->option == option && (*o)->ack == cmd) { if ((*o)->option == option && (*o)->ack == cmd) {
switch ((*o)->state) { switch ((*o)->state) {
case REQUESTED: case REQUESTED:
(*o)->state = ACTIVE; (*o)->state = ACTIVE;
activate_option (*o); activate_option(*o);
break; break;
case ACTIVE: case ACTIVE:
break; break;
case INACTIVE: case INACTIVE:
(*o)->state = ACTIVE; (*o)->state = ACTIVE;
send_opt ((*o)->send, option); send_opt((*o)->send, option);
activate_option (*o); activate_option(*o);
break; break;
case REALLY_INACTIVE: case REALLY_INACTIVE:
send_opt ((*o)->nsend, option); send_opt((*o)->nsend, option);
break; break;
} }
return; return;
@ -230,12 +283,12 @@ static void proc_rec_opt (int cmd, int option) {
switch ((*o)->state) { switch ((*o)->state) {
case REQUESTED: case REQUESTED:
(*o)->state = INACTIVE; (*o)->state = INACTIVE;
refused_option (*o); refused_option(*o);
break; break;
case ACTIVE: case ACTIVE:
(*o)->state = INACTIVE; (*o)->state = INACTIVE;
send_opt ((*o)->nsend, option); send_opt((*o)->nsend, option);
option_side_effects(*o, 0); option_side_effects(*o, 0);
break; break;
case INACTIVE: case INACTIVE:
case REALLY_INACTIVE: case REALLY_INACTIVE:
@ -248,10 +301,11 @@ static void proc_rec_opt (int cmd, int option) {
* If we reach here, the option was one we weren't prepared to * If we reach here, the option was one we weren't prepared to
* cope with. So send a negative ack. * cope with. So send a negative ack.
*/ */
send_opt ((cmd == WILL ? DONT : WONT), option); send_opt((cmd == WILL ? DONT : WONT), option);
} }
static void process_subneg (void) { static void process_subneg(void)
{
unsigned char b[2048], *p, *q; unsigned char b[2048], *p, *q;
int var, value, n; int var, value, n;
char *e; char *e;
@ -259,45 +313,53 @@ static void process_subneg (void) {
switch (sb_opt) { switch (sb_opt) {
case TELOPT_TSPEED: case TELOPT_TSPEED:
if (sb_len == 1 && sb_buf[0] == TELQUAL_SEND) { if (sb_len == 1 && sb_buf[0] == TELQUAL_SEND) {
char logbuf[sizeof(cfg.termspeed)+80]; char logbuf[sizeof(cfg.termspeed) + 80];
b[0] = IAC; b[1] = SB; b[2] = TELOPT_TSPEED; b[0] = IAC;
b[1] = SB;
b[2] = TELOPT_TSPEED;
b[3] = TELQUAL_IS; b[3] = TELQUAL_IS;
strcpy(b+4, cfg.termspeed); strcpy(b + 4, cfg.termspeed);
n = 4 + strlen(cfg.termspeed); n = 4 + strlen(cfg.termspeed);
b[n] = IAC; b[n+1] = SE; b[n] = IAC;
sk_write(s, b, n+2); b[n + 1] = SE;
sk_write(s, b, n + 2);
logevent("server:\tSB TSPEED SEND"); logevent("server:\tSB TSPEED SEND");
sprintf(logbuf, "client:\tSB TSPEED IS %s", cfg.termspeed); sprintf(logbuf, "client:\tSB TSPEED IS %s", cfg.termspeed);
logevent (logbuf); logevent(logbuf);
} else } else
logevent ("server:\tSB TSPEED <something weird>"); logevent("server:\tSB TSPEED <something weird>");
break; break;
case TELOPT_TTYPE: case TELOPT_TTYPE:
if (sb_len == 1 && sb_buf[0] == TELQUAL_SEND) { if (sb_len == 1 && sb_buf[0] == TELQUAL_SEND) {
char logbuf[sizeof(cfg.termtype)+80]; char logbuf[sizeof(cfg.termtype) + 80];
b[0] = IAC; b[1] = SB; b[2] = TELOPT_TTYPE; b[0] = IAC;
b[1] = SB;
b[2] = TELOPT_TTYPE;
b[3] = TELQUAL_IS; b[3] = TELQUAL_IS;
for (n = 0; cfg.termtype[n]; n++) for (n = 0; cfg.termtype[n]; n++)
b[n+4] = (cfg.termtype[n] >= 'a' && cfg.termtype[n] <= 'z' ? b[n + 4] = (cfg.termtype[n] >= 'a'
cfg.termtype[n] + 'A'-'a' : cfg.termtype[n]); && cfg.termtype[n] <=
b[n+4] = IAC; b[n+5] = SE; 'z' ? cfg.termtype[n] + 'A' -
sk_write(s, b, n+6); 'a' : cfg.termtype[n]);
b[n+4] = 0; b[n + 4] = IAC;
b[n + 5] = SE;
sk_write(s, b, n + 6);
b[n + 4] = 0;
logevent("server:\tSB TTYPE SEND"); logevent("server:\tSB TTYPE SEND");
sprintf(logbuf, "client:\tSB TTYPE IS %s", b+4); sprintf(logbuf, "client:\tSB TTYPE IS %s", b + 4);
logevent(logbuf); logevent(logbuf);
} else } else
logevent("server:\tSB TTYPE <something weird>\r\n"); logevent("server:\tSB TTYPE <something weird>\r\n");
break; break;
case TELOPT_OLD_ENVIRON: case TELOPT_OLD_ENVIRON:
case TELOPT_NEW_ENVIRON: case TELOPT_NEW_ENVIRON:
p = sb_buf; p = sb_buf;
q = p + sb_len; q = p + sb_len;
if (p < q && *p == TELQUAL_SEND) { if (p < q && *p == TELQUAL_SEND) {
char logbuf[50]; char logbuf[50];
p++; p++;
sprintf (logbuf, "server:\tSB %s SEND", telopt(sb_opt)); sprintf(logbuf, "server:\tSB %s SEND", telopt(sb_opt));
logevent (logbuf); logevent(logbuf);
if (sb_opt == TELOPT_OLD_ENVIRON) { if (sb_opt == TELOPT_OLD_ENVIRON) {
if (cfg.rfc_environ) { if (cfg.rfc_environ) {
value = RFC_VALUE; value = RFC_VALUE;
@ -327,29 +389,40 @@ static void process_subneg (void) {
value = RFC_VALUE; value = RFC_VALUE;
var = RFC_VAR; var = RFC_VAR;
} }
b[0] = IAC; b[1] = SB; b[2] = sb_opt; b[0] = IAC;
b[1] = SB;
b[2] = sb_opt;
b[3] = TELQUAL_IS; b[3] = TELQUAL_IS;
n = 4; n = 4;
e = cfg.environmt; e = cfg.environmt;
while (*e) { while (*e) {
b[n++] = var; b[n++] = var;
while (*e && *e != '\t') b[n++] = *e++; while (*e && *e != '\t')
if (*e == '\t') e++; b[n++] = *e++;
if (*e == '\t')
e++;
b[n++] = value; b[n++] = value;
while (*e) b[n++] = *e++; while (*e)
b[n++] = *e++;
e++; e++;
} }
if (*cfg.username) { if (*cfg.username) {
b[n++] = var; b[n++] = 'U'; b[n++] = 'S'; b[n++] = var;
b[n++] = 'E'; b[n++] = 'R'; b[n++] = value; b[n++] = 'U';
b[n++] = 'S';
b[n++] = 'E';
b[n++] = 'R';
b[n++] = value;
e = cfg.username; e = cfg.username;
while (*e) b[n++] = *e++; while (*e)
b[n++] = *e++;
} }
b[n++] = IAC; b[n++] = SE; b[n++] = IAC;
b[n++] = SE;
sk_write(s, b, n); sk_write(s, b, n);
sprintf(logbuf, "client:\tSB %s IS %s", telopt(sb_opt), sprintf(logbuf, "client:\tSB %s IS %s", telopt(sb_opt),
n==6 ? "<nothing>" : "<stuff>"); n == 6 ? "<nothing>" : "<stuff>");
logevent (logbuf); logevent(logbuf);
} }
break; break;
} }
@ -360,7 +433,8 @@ static enum {
SEENSB, SUBNEGOT, SUBNEG_IAC, SEENCR SEENSB, SUBNEGOT, SUBNEG_IAC, SEENCR
} telnet_state = TOPLEVEL; } telnet_state = TOPLEVEL;
static void do_telnet_read (char *buf, int len) { static void do_telnet_read(char *buf, int len)
{
while (len--) { while (len--) {
int c = (unsigned char) *buf++; int c = (unsigned char) *buf++;
@ -385,7 +459,8 @@ static void do_telnet_read (char *buf, int len) {
* Oh well, we do get the DM in the right place so I'll * Oh well, we do get the DM in the right place so I'll
* just stop hiding on the next 0xf2 and hope for the best. * just stop hiding on the next 0xf2 and hope for the best.
*/ */
else if (c == DM) in_synch = 0; else if (c == DM)
in_synch = 0;
#endif #endif
if (c == CR) if (c == CR)
telnet_state = SEENCR; telnet_state = SEENCR;
@ -394,16 +469,20 @@ static void do_telnet_read (char *buf, int len) {
} }
break; break;
case SEENIAC: case SEENIAC:
if (c == DO) telnet_state = SEENDO; if (c == DO)
else if (c == DONT) telnet_state = SEENDONT; telnet_state = SEENDO;
else if (c == WILL) telnet_state = SEENWILL; else if (c == DONT)
else if (c == WONT) telnet_state = SEENWONT; telnet_state = SEENDONT;
else if (c == SB) telnet_state = SEENSB; else if (c == WILL)
telnet_state = SEENWILL;
else if (c == WONT)
telnet_state = SEENWONT;
else if (c == SB)
telnet_state = SEENSB;
else if (c == DM) { else if (c == DM) {
in_synch = 0; in_synch = 0;
telnet_state = TOPLEVEL; telnet_state = TOPLEVEL;
} } else {
else {
/* ignore everything else; print it if it's IAC */ /* ignore everything else; print it if it's IAC */
if (c == IAC) { if (c == IAC) {
c_write1(c); c_write1(c);
@ -412,19 +491,19 @@ static void do_telnet_read (char *buf, int len) {
} }
break; break;
case SEENWILL: case SEENWILL:
proc_rec_opt (WILL, c); proc_rec_opt(WILL, c);
telnet_state = TOPLEVEL; telnet_state = TOPLEVEL;
break; break;
case SEENWONT: case SEENWONT:
proc_rec_opt (WONT, c); proc_rec_opt(WONT, c);
telnet_state = TOPLEVEL; telnet_state = TOPLEVEL;
break; break;
case SEENDO: case SEENDO:
proc_rec_opt (DO, c); proc_rec_opt(DO, c);
telnet_state = TOPLEVEL; telnet_state = TOPLEVEL;
break; break;
case SEENDONT: case SEENDONT:
proc_rec_opt (DONT, c); proc_rec_opt(DONT, c);
telnet_state = TOPLEVEL; telnet_state = TOPLEVEL;
break; break;
case SEENSB: case SEENSB:
@ -436,7 +515,7 @@ static void do_telnet_read (char *buf, int len) {
if (c == IAC) if (c == IAC)
telnet_state = SUBNEG_IAC; telnet_state = SUBNEG_IAC;
else { else {
subneg_addchar: subneg_addchar:
if (sb_len >= sb_size) { if (sb_len >= sb_size) {
char *newbuf; char *newbuf;
sb_size += SB_DELTA; sb_size += SB_DELTA;
@ -450,7 +529,7 @@ static void do_telnet_read (char *buf, int len) {
} }
if (sb_len < sb_size) if (sb_len < sb_size)
sb_buf[sb_len++] = c; sb_buf[sb_len++] = c;
telnet_state = SUBNEGOT;/* in case we came here by goto */ telnet_state = SUBNEGOT; /* in case we came here by goto */
} }
break; break;
case SUBNEG_IAC: case SUBNEG_IAC:
@ -465,19 +544,23 @@ static void do_telnet_read (char *buf, int len) {
} }
} }
static int telnet_closing (Plug plug, char *error_msg, int error_code, int calling_back) { static int telnet_closing(Plug plug, char *error_msg, int error_code,
int calling_back)
{
sk_close(s); sk_close(s);
s = NULL; s = NULL;
if (error_msg) { if (error_msg) {
/* A socket error has occurred. */ /* A socket error has occurred. */
connection_fatal (error_msg); connection_fatal(error_msg);
} /* Otherwise, the remote side closed the connection normally. */ } /* Otherwise, the remote side closed the connection normally. */
return 0; return 0;
} }
static int telnet_receive(Plug plug, int urgent, char *data, int len) { static int telnet_receive(Plug plug, int urgent, char *data, int len)
if(urgent) in_synch = TRUE; {
do_telnet_read (data, len); if (urgent)
in_synch = TRUE;
do_telnet_read(data, len);
return 1; return 1;
} }
@ -488,7 +571,8 @@ static int telnet_receive(Plug plug, int urgent, char *data, int len) {
* *
* Also places the canonical host name into `realhost'. * Also places the canonical host name into `realhost'.
*/ */
static char *telnet_init (char *host, int port, char **realhost) { static char *telnet_init(char *host, int port, char **realhost)
{
static struct plug_function_table fn_table = { static struct plug_function_table fn_table = {
telnet_closing, telnet_closing,
telnet_receive telnet_receive
@ -501,7 +585,7 @@ static char *telnet_init (char *host, int port, char **realhost) {
* Try to find host. * Try to find host.
*/ */
addr = sk_namelookup(host, realhost); addr = sk_namelookup(host, realhost);
if ( (err = sk_addr_error(addr)) ) if ((err = sk_addr_error(addr)))
return err; return err;
if (port < 0) if (port < 0)
@ -511,7 +595,7 @@ static char *telnet_init (char *host, int port, char **realhost) {
* Open socket. * Open socket.
*/ */
s = sk_new(addr, port, 0, 1, &fn_table_ptr); s = sk_new(addr, port, 0, 1, &fn_table_ptr);
if ( (err = sk_socket_error(s)) ) if ((err = sk_socket_error(s)))
return err; return err;
sk_addr_free(addr); sk_addr_free(addr);
@ -524,7 +608,7 @@ static char *telnet_init (char *host, int port, char **realhost) {
for (o = opts; *o; o++) for (o = opts; *o; o++)
if ((*o)->state == REQUESTED) if ((*o)->state == REQUESTED)
send_opt ((*o)->send, (*o)->option); send_opt((*o)->send, (*o)->option);
} }
/* /*
@ -538,7 +622,8 @@ static char *telnet_init (char *host, int port, char **realhost) {
/* /*
* Called to send data down the Telnet connection. * Called to send data down the Telnet connection.
*/ */
static void telnet_send (char *buf, int len) { static void telnet_send(char *buf, int len)
{
char *p; char *p;
static unsigned char iac[2] = { IAC, IAC }; static unsigned char iac[2] = { IAC, IAC };
static unsigned char cr[2] = { CR, NUL }; static unsigned char cr[2] = { CR, NUL };
@ -548,14 +633,15 @@ static void telnet_send (char *buf, int len) {
return; return;
p = buf; p = buf;
while (p < buf+len) { while (p < buf + len) {
char *q = p; char *q = p;
while (iswritable((unsigned char)*p) && p < buf+len) p++; while (iswritable((unsigned char) *p) && p < buf + len)
sk_write(s, q, p-q); p++;
sk_write(s, q, p - q);
while (p < buf+len && !iswritable((unsigned char)*p)) { while (p < buf + len && !iswritable((unsigned char) *p)) {
sk_write(s, (unsigned char)*p == IAC ? iac : nl, 2); sk_write(s, (unsigned char) *p == IAC ? iac : nl, 2);
p++; p++;
} }
} }
@ -564,27 +650,34 @@ static void telnet_send (char *buf, int len) {
/* /*
* Called to set the size of the window from Telnet's POV. * Called to set the size of the window from Telnet's POV.
*/ */
static void telnet_size(void) { static void telnet_size(void)
{
unsigned char b[16]; unsigned char b[16];
char logbuf[50]; char logbuf[50];
if (s == NULL || o_naws.state != ACTIVE) if (s == NULL || o_naws.state != ACTIVE)
return; return;
b[0] = IAC; b[1] = SB; b[2] = TELOPT_NAWS; b[0] = IAC;
b[3] = cols >> 8; b[4] = cols & 0xFF; b[1] = SB;
b[5] = rows >> 8; b[6] = rows & 0xFF; b[2] = TELOPT_NAWS;
b[7] = IAC; b[8] = SE; b[3] = cols >> 8;
b[4] = cols & 0xFF;
b[5] = rows >> 8;
b[6] = rows & 0xFF;
b[7] = IAC;
b[8] = SE;
sk_write(s, b, 9); sk_write(s, b, 9);
sprintf(logbuf, "client:\tSB NAWS %d,%d", sprintf(logbuf, "client:\tSB NAWS %d,%d",
((unsigned char)b[3] << 8) + (unsigned char)b[4], ((unsigned char) b[3] << 8) + (unsigned char) b[4],
((unsigned char)b[5] << 8) + (unsigned char)b[6]); ((unsigned char) b[5] << 8) + (unsigned char) b[6]);
logevent (logbuf); logevent(logbuf);
} }
/* /*
* Send Telnet special codes. * Send Telnet special codes.
*/ */
static void telnet_special (Telnet_Special code) { static void telnet_special(Telnet_Special code)
{
unsigned char b[2]; unsigned char b[2];
if (s == NULL) if (s == NULL)
@ -592,51 +685,96 @@ static void telnet_special (Telnet_Special code) {
b[0] = IAC; b[0] = IAC;
switch (code) { switch (code) {
case TS_AYT: b[1] = AYT; sk_write(s, b, 2); break; case TS_AYT:
case TS_BRK: b[1] = BREAK; sk_write(s, b, 2); break; b[1] = AYT;
case TS_EC: b[1] = EC; sk_write(s, b, 2); break; sk_write(s, b, 2);
case TS_EL: b[1] = EL; sk_write(s, b, 2); break; break;
case TS_GA: b[1] = GA; sk_write(s, b, 2); break; case TS_BRK:
case TS_NOP: b[1] = NOP; sk_write(s, b, 2); break; b[1] = BREAK;
case TS_ABORT: b[1] = ABORT; sk_write(s, b, 2); break; sk_write(s, b, 2);
case TS_AO: b[1] = AO; sk_write(s, b, 2); break; break;
case TS_IP: b[1] = IP; sk_write(s, b, 2); break; case TS_EC:
case TS_SUSP: b[1] = SUSP; sk_write(s, b, 2); break; b[1] = EC;
case TS_EOR: b[1] = EOR; sk_write(s, b, 2); break; sk_write(s, b, 2);
case TS_EOF: b[1] = xEOF; sk_write(s, b, 2); break; break;
case TS_EL:
b[1] = EL;
sk_write(s, b, 2);
break;
case TS_GA:
b[1] = GA;
sk_write(s, b, 2);
break;
case TS_NOP:
b[1] = NOP;
sk_write(s, b, 2);
break;
case TS_ABORT:
b[1] = ABORT;
sk_write(s, b, 2);
break;
case TS_AO:
b[1] = AO;
sk_write(s, b, 2);
break;
case TS_IP:
b[1] = IP;
sk_write(s, b, 2);
break;
case TS_SUSP:
b[1] = SUSP;
sk_write(s, b, 2);
break;
case TS_EOR:
b[1] = EOR;
sk_write(s, b, 2);
break;
case TS_EOF:
b[1] = xEOF;
sk_write(s, b, 2);
break;
case TS_SYNCH: case TS_SYNCH:
b[1] = DM; b[1] = DM;
sk_write (s, b, 1); sk_write(s, b, 1);
sk_write_oob (s, b+1, 1); sk_write_oob(s, b + 1, 1);
break; break;
case TS_RECHO: case TS_RECHO:
if (o_echo.state == INACTIVE || o_echo.state == REALLY_INACTIVE) { if (o_echo.state == INACTIVE || o_echo.state == REALLY_INACTIVE) {
o_echo.state = REQUESTED; o_echo.state = REQUESTED;
send_opt (o_echo.send, o_echo.option); send_opt(o_echo.send, o_echo.option);
} }
break; break;
case TS_LECHO: case TS_LECHO:
if (o_echo.state == ACTIVE) { if (o_echo.state == ACTIVE) {
o_echo.state = REQUESTED; o_echo.state = REQUESTED;
send_opt (o_echo.nsend, o_echo.option); send_opt(o_echo.nsend, o_echo.option);
} }
break; break;
case TS_PING: case TS_PING:
if (o_they_sga.state == ACTIVE) { if (o_they_sga.state == ACTIVE) {
b[1] = NOP; b[1] = NOP;
sk_write(s, b, 2); sk_write(s, b, 2);
} }
break; break;
} }
} }
static Socket telnet_socket(void) { return s; } static Socket telnet_socket(void)
{
return s;
}
static int telnet_sendok(void) { return 1; } static int telnet_sendok(void)
{
return 1;
}
static int telnet_ldisc(int option) { static int telnet_ldisc(int option)
if (option == LD_ECHO) return echoing; {
if (option == LD_EDIT) return editing; if (option == LD_ECHO)
return echoing;
if (option == LD_EDIT)
return editing;
return FALSE; return FALSE;
} }

2621
terminal.c

File diff suppressed because it is too large Load Diff

660
tree234.c

File diff suppressed because it is too large Load Diff

View File

@ -33,7 +33,7 @@
*/ */
typedef struct tree234_Tag tree234; typedef struct tree234_Tag tree234;
typedef int (*cmpfn234)(void *, void *); typedef int (*cmpfn234) (void *, void *);
/* /*
* Create a 2-3-4 tree. If `cmp' is NULL, the tree is unsorted, and * Create a 2-3-4 tree. If `cmp' is NULL, the tree is unsorted, and
@ -45,13 +45,13 @@ tree234 *newtree234(cmpfn234 cmp);
/* /*
* Free a 2-3-4 tree (not including freeing the elements). * Free a 2-3-4 tree (not including freeing the elements).
*/ */
void freetree234(tree234 *t); void freetree234(tree234 * t);
/* /*
* Add an element e to a sorted 2-3-4 tree t. Returns e on success, * Add an element e to a sorted 2-3-4 tree t. Returns e on success,
* or if an existing element compares equal, returns that. * or if an existing element compares equal, returns that.
*/ */
void *add234(tree234 *t, void *e); void *add234(tree234 * t, void *e);
/* /*
* Add an element e to an unsorted 2-3-4 tree t. Returns e on * Add an element e to an unsorted 2-3-4 tree t. Returns e on
@ -61,7 +61,7 @@ void *add234(tree234 *t, void *e);
* Index range can be from 0 to the tree's current element count, * Index range can be from 0 to the tree's current element count,
* inclusive. * inclusive.
*/ */
void *addpos234(tree234 *t, void *e, int index); void *addpos234(tree234 * t, void *e, int index);
/* /*
* Look up the element at a given numeric index in a 2-3-4 tree. * Look up the element at a given numeric index in a 2-3-4 tree.
@ -81,7 +81,7 @@ void *addpos234(tree234 *t, void *e, int index);
* consume(p); * consume(p);
* } * }
*/ */
void *index234(tree234 *t, int index); void *index234(tree234 * t, int index);
/* /*
* Find an element e in a sorted 2-3-4 tree t. Returns NULL if not * Find an element e in a sorted 2-3-4 tree t. Returns NULL if not
@ -126,10 +126,10 @@ void *index234(tree234 *t, int index);
enum { enum {
REL234_EQ, REL234_LT, REL234_LE, REL234_GT, REL234_GE REL234_EQ, REL234_LT, REL234_LE, REL234_GT, REL234_GE
}; };
void *find234(tree234 *t, void *e, cmpfn234 cmp); void *find234(tree234 * t, void *e, cmpfn234 cmp);
void *findrel234(tree234 *t, void *e, cmpfn234 cmp, int relation); void *findrel234(tree234 * t, void *e, cmpfn234 cmp, int relation);
void *findpos234(tree234 *t, void *e, cmpfn234 cmp, int *index); void *findpos234(tree234 * t, void *e, cmpfn234 cmp, int *index);
void *findrelpos234(tree234 *t, void *e, cmpfn234 cmp, int relation, void *findrelpos234(tree234 * t, void *e, cmpfn234 cmp, int relation,
int *index); int *index);
/* /*
@ -149,12 +149,12 @@ void *findrelpos234(tree234 *t, void *e, cmpfn234 cmp, int relation,
* is out of range (delpos234) or the element is already not in the * is out of range (delpos234) or the element is already not in the
* tree (del234) then they return NULL. * tree (del234) then they return NULL.
*/ */
void *del234(tree234 *t, void *e); void *del234(tree234 * t, void *e);
void *delpos234(tree234 *t, int index); void *delpos234(tree234 * t, int index);
/* /*
* Return the total element count of a tree234. * Return the total element count of a tree234.
*/ */
int count234(tree234 *t); int count234(tree234 * t);
#endif /* TREE234_H */ #endif /* TREE234_H */

View File

@ -22,7 +22,8 @@
#define PROGBARHEIGHT 14 #define PROGBARHEIGHT 14
void ctlposinit(struct ctlpos *cp, HWND hwnd, void ctlposinit(struct ctlpos *cp, HWND hwnd,
int leftborder, int rightborder, int topborder) { int leftborder, int rightborder, int topborder)
{
RECT r, r2; RECT r, r2;
cp->hwnd = hwnd; cp->hwnd = hwnd;
cp->font = SendMessage(hwnd, WM_GETFONT, 0, 0); cp->font = SendMessage(hwnd, WM_GETFONT, 0, 0);
@ -33,14 +34,14 @@ void ctlposinit(struct ctlpos *cp, HWND hwnd,
r2.bottom = 8; r2.bottom = 8;
MapDialogRect(hwnd, &r2); MapDialogRect(hwnd, &r2);
cp->dlu4inpix = r2.right; cp->dlu4inpix = r2.right;
cp->width = (r.right * 4) / (r2.right) - 2*GAPBETWEEN; cp->width = (r.right * 4) / (r2.right) - 2 * GAPBETWEEN;
cp->xoff = leftborder; cp->xoff = leftborder;
cp->width -= leftborder + rightborder; cp->width -= leftborder + rightborder;
} }
void doctl(struct ctlpos *cp, RECT r, void doctl(struct ctlpos *cp, RECT r,
char *wclass, int wstyle, int exstyle, char *wclass, int wstyle, int exstyle, char *wtext, int wid)
char *wtext, int wid) { {
HWND ctl; HWND ctl;
/* /*
* Note nonstandard use of RECT. This is deliberate: by * Note nonstandard use of RECT. This is deliberate: by
@ -52,19 +53,22 @@ void doctl(struct ctlpos *cp, RECT r,
MapDialogRect(cp->hwnd, &r); MapDialogRect(cp->hwnd, &r);
ctl = CreateWindowEx(exstyle, wclass, wtext, wstyle, ctl = CreateWindowEx(exstyle, wclass, wtext, wstyle,
r.left, r.top, r.right, r.bottom, r.left, r.top, r.right, r.bottom,
cp->hwnd, (HMENU)wid, hinst, NULL); cp->hwnd, (HMENU) wid, hinst, NULL);
SendMessage(ctl, WM_SETFONT, cp->font, MAKELPARAM(TRUE, 0)); SendMessage(ctl, WM_SETFONT, cp->font, MAKELPARAM(TRUE, 0));
} }
/* /*
* A title bar across the top of a sub-dialog. * A title bar across the top of a sub-dialog.
*/ */
void bartitle(struct ctlpos *cp, char *name, int id) { void bartitle(struct ctlpos *cp, char *name, int id)
{
RECT r; RECT r;
r.left = GAPBETWEEN; r.right = cp->width; r.left = GAPBETWEEN;
r.top = cp->ypos; r.bottom = STATICHEIGHT; r.right = cp->width;
r.top = cp->ypos;
r.bottom = STATICHEIGHT;
cp->ypos += r.bottom + GAPBETWEEN; cp->ypos += r.bottom + GAPBETWEEN;
doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, name, id); doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, name, id);
} }
@ -72,14 +76,15 @@ void bartitle(struct ctlpos *cp, char *name, int id) {
/* /*
* Begin a grouping box, with or without a group title. * Begin a grouping box, with or without a group title.
*/ */
void beginbox(struct ctlpos *cp, char *name, int idbox) { void beginbox(struct ctlpos *cp, char *name, int idbox)
{
cp->boxystart = cp->ypos; cp->boxystart = cp->ypos;
if (!name) if (!name)
cp->boxystart -= STATICHEIGHT/2; cp->boxystart -= STATICHEIGHT / 2;
if (name) if (name)
cp->ypos += STATICHEIGHT; cp->ypos += STATICHEIGHT;
cp->ypos += GAPYBOX; cp->ypos += GAPYBOX;
cp->width -= 2*GAPXBOX; cp->width -= 2 * GAPXBOX;
cp->xoff += GAPXBOX; cp->xoff += GAPXBOX;
cp->boxid = idbox; cp->boxid = idbox;
cp->boxtext = name; cp->boxtext = name;
@ -88,15 +93,18 @@ void beginbox(struct ctlpos *cp, char *name, int idbox) {
/* /*
* End a grouping box. * End a grouping box.
*/ */
void endbox(struct ctlpos *cp) { void endbox(struct ctlpos *cp)
{
RECT r; RECT r;
cp->xoff -= GAPXBOX; cp->xoff -= GAPXBOX;
cp->width += 2*GAPXBOX; cp->width += 2 * GAPXBOX;
cp->ypos += GAPYBOX - GAPBETWEEN; cp->ypos += GAPYBOX - GAPBETWEEN;
r.left = GAPBETWEEN; r.right = cp->width; r.left = GAPBETWEEN;
r.top = cp->boxystart; r.bottom = cp->ypos - cp->boxystart; r.right = cp->width;
r.top = cp->boxystart;
r.bottom = cp->ypos - cp->boxystart;
doctl(cp, r, "BUTTON", BS_GROUPBOX | WS_CHILD | WS_VISIBLE, 0, doctl(cp, r, "BUTTON", BS_GROUPBOX | WS_CHILD | WS_VISIBLE, 0,
cp->boxtext ? cp->boxtext : "", cp->boxid); cp->boxtext ? cp->boxtext : "", cp->boxid);
cp->ypos += GAPYBOX; cp->ypos += GAPYBOX;
} }
@ -104,7 +112,8 @@ void endbox(struct ctlpos *cp) {
* Some edit boxes. Each one has a static above it. The percentages * Some edit boxes. Each one has a static above it. The percentages
* of the horizontal space are provided. * of the horizontal space are provided.
*/ */
void multiedit(struct ctlpos *cp, ...) { void multiedit(struct ctlpos *cp, ...)
{
RECT r; RECT r;
va_list ap; va_list ap;
int percent, xpos; int percent, xpos;
@ -112,31 +121,31 @@ void multiedit(struct ctlpos *cp, ...) {
percent = xpos = 0; percent = xpos = 0;
va_start(ap, cp); va_start(ap, cp);
while (1) { while (1) {
char *text; char *text;
int staticid, editid, pcwidth; int staticid, editid, pcwidth;
text = va_arg(ap, char *); text = va_arg(ap, char *);
if (!text) if (!text)
break; break;
staticid = va_arg(ap, int); staticid = va_arg(ap, int);
editid = va_arg(ap, int); editid = va_arg(ap, int);
pcwidth = va_arg(ap, int); pcwidth = va_arg(ap, int);
r.left = xpos + GAPBETWEEN; r.left = xpos + GAPBETWEEN;
percent += pcwidth; percent += pcwidth;
xpos = (cp->width + GAPBETWEEN) * percent / 100; xpos = (cp->width + GAPBETWEEN) * percent / 100;
r.right = xpos - r.left; r.right = xpos - r.left;
r.top = cp->ypos; r.bottom = STATICHEIGHT; r.top = cp->ypos;
doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, r.bottom = STATICHEIGHT;
text, staticid); doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, text, staticid);
r.top = cp->ypos + 8 + GAPWITHIN; r.bottom = EDITHEIGHT; r.top = cp->ypos + 8 + GAPWITHIN;
doctl(cp, r, "EDIT", r.bottom = EDITHEIGHT;
WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL, doctl(cp, r, "EDIT",
WS_EX_CLIENTEDGE, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL,
"", editid); WS_EX_CLIENTEDGE, "", editid);
} }
va_end(ap); va_end(ap);
cp->ypos += 8+GAPWITHIN+12+GAPBETWEEN; cp->ypos += 8 + GAPWITHIN + 12 + GAPBETWEEN;
} }
/* /*
@ -153,16 +162,18 @@ void multiedit(struct ctlpos *cp, ...) {
* *
* (*) Button1 (*) Button2 (*) ButtonWithReallyLongTitle * (*) Button1 (*) Button2 (*) ButtonWithReallyLongTitle
*/ */
void radioline(struct ctlpos *cp, void radioline(struct ctlpos *cp, char *text, int id, int nacross, ...)
char *text, int id, int nacross, ...) { {
RECT r; RECT r;
va_list ap; va_list ap;
int group; int group;
int i; int i;
char *btext; char *btext;
r.left = GAPBETWEEN; r.top = cp->ypos; r.left = GAPBETWEEN;
r.right = cp->width; r.bottom = STATICHEIGHT; r.top = cp->ypos;
r.right = cp->width;
r.bottom = STATICHEIGHT;
cp->ypos += r.bottom + GAPWITHIN; cp->ypos += r.bottom + GAPWITHIN;
doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, text, id); doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, text, id);
va_start(ap, nacross); va_start(ap, nacross);
@ -170,29 +181,30 @@ void radioline(struct ctlpos *cp,
i = 0; i = 0;
btext = va_arg(ap, char *); btext = va_arg(ap, char *);
while (1) { while (1) {
char *nextbtext; char *nextbtext;
int bid; int bid;
if (!btext) if (!btext)
break; break;
if (i==nacross) { if (i == nacross) {
cp->ypos += r.bottom + GAPBETWEEN; cp->ypos += r.bottom + GAPBETWEEN;
i=0; i = 0;
} }
bid = va_arg(ap, int); bid = va_arg(ap, int);
nextbtext = va_arg(ap, char *); nextbtext = va_arg(ap, char *);
r.left = GAPBETWEEN + i * (cp->width+GAPBETWEEN)/nacross; r.left = GAPBETWEEN + i * (cp->width + GAPBETWEEN) / nacross;
if (nextbtext) if (nextbtext)
r.right = (i+1) * (cp->width+GAPBETWEEN)/nacross - r.left; r.right =
else (i + 1) * (cp->width + GAPBETWEEN) / nacross - r.left;
r.right = cp->width - r.left; else
r.top = cp->ypos; r.bottom = RADIOHEIGHT; r.right = cp->width - r.left;
doctl(cp, r, "BUTTON", r.top = cp->ypos;
BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP | group, r.bottom = RADIOHEIGHT;
0, doctl(cp, r, "BUTTON",
btext, bid); BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP |
group = 0; group, 0, btext, bid);
i++; group = 0;
btext = nextbtext; i++;
btext = nextbtext;
} }
va_end(ap); va_end(ap);
cp->ypos += r.bottom + GAPBETWEEN; cp->ypos += r.bottom + GAPBETWEEN;
@ -202,32 +214,36 @@ void radioline(struct ctlpos *cp,
* A set of radio buttons on multiple lines, with a static above * A set of radio buttons on multiple lines, with a static above
* them. * them.
*/ */
void radiobig(struct ctlpos *cp, char *text, int id, ...) { void radiobig(struct ctlpos *cp, char *text, int id, ...)
{
RECT r; RECT r;
va_list ap; va_list ap;
int group; int group;
r.left = GAPBETWEEN; r.top = cp->ypos; r.left = GAPBETWEEN;
r.right = cp->width; r.bottom = STATICHEIGHT; r.top = cp->ypos;
r.right = cp->width;
r.bottom = STATICHEIGHT;
cp->ypos += r.bottom + GAPWITHIN; cp->ypos += r.bottom + GAPWITHIN;
doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, text, id); doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, text, id);
va_start(ap, id); va_start(ap, id);
group = WS_GROUP; group = WS_GROUP;
while (1) { while (1) {
char *btext; char *btext;
int bid; int bid;
btext = va_arg(ap, char *); btext = va_arg(ap, char *);
if (!btext) if (!btext)
break; break;
bid = va_arg(ap, int); bid = va_arg(ap, int);
r.left = GAPBETWEEN; r.top = cp->ypos; r.left = GAPBETWEEN;
r.right = cp->width; r.bottom = STATICHEIGHT; r.top = cp->ypos;
cp->ypos += r.bottom + GAPWITHIN; r.right = cp->width;
doctl(cp, r, "BUTTON", r.bottom = STATICHEIGHT;
BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP | group, cp->ypos += r.bottom + GAPWITHIN;
0, doctl(cp, r, "BUTTON",
btext, bid); BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP |
group = 0; group, 0, btext, bid);
group = 0;
} }
va_end(ap); va_end(ap);
cp->ypos += GAPBETWEEN - GAPWITHIN; cp->ypos += GAPBETWEEN - GAPWITHIN;
@ -236,25 +252,31 @@ void radiobig(struct ctlpos *cp, char *text, int id, ...) {
/* /*
* A single standalone checkbox. * A single standalone checkbox.
*/ */
void checkbox(struct ctlpos *cp, char *text, int id) { void checkbox(struct ctlpos *cp, char *text, int id)
{
RECT r; RECT r;
r.left = GAPBETWEEN; r.top = cp->ypos; r.left = GAPBETWEEN;
r.right = cp->width; r.bottom = CHECKBOXHEIGHT; r.top = cp->ypos;
r.right = cp->width;
r.bottom = CHECKBOXHEIGHT;
cp->ypos += r.bottom + GAPBETWEEN; cp->ypos += r.bottom + GAPBETWEEN;
doctl(cp, r, "BUTTON", doctl(cp, r, "BUTTON",
BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0, BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 0,
text, id); text, id);
} }
/* /*
* A single standalone static text control. * A single standalone static text control.
*/ */
void statictext(struct ctlpos *cp, char *text, int id) { void statictext(struct ctlpos *cp, char *text, int id)
{
RECT r; RECT r;
r.left = GAPBETWEEN; r.top = cp->ypos; r.left = GAPBETWEEN;
r.right = cp->width; r.bottom = STATICHEIGHT; r.top = cp->ypos;
r.right = cp->width;
r.bottom = STATICHEIGHT;
cp->ypos += r.bottom + GAPBETWEEN; cp->ypos += r.bottom + GAPBETWEEN;
doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, text, id); doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, text, id);
} }
@ -263,26 +285,30 @@ void statictext(struct ctlpos *cp, char *text, int id) {
* A button on the right hand side, with a static to its left. * A button on the right hand side, with a static to its left.
*/ */
void staticbtn(struct ctlpos *cp, char *stext, int sid, void staticbtn(struct ctlpos *cp, char *stext, int sid,
char *btext, int bid) { char *btext, int bid)
{
const int height = (PUSHBTNHEIGHT > STATICHEIGHT ? const int height = (PUSHBTNHEIGHT > STATICHEIGHT ?
PUSHBTNHEIGHT : STATICHEIGHT); PUSHBTNHEIGHT : STATICHEIGHT);
RECT r; RECT r;
int lwid, rwid, rpos; int lwid, rwid, rpos;
rpos = GAPBETWEEN + 3 * (cp->width + GAPBETWEEN) / 4; rpos = GAPBETWEEN + 3 * (cp->width + GAPBETWEEN) / 4;
lwid = rpos - 2*GAPBETWEEN; lwid = rpos - 2 * GAPBETWEEN;
rwid = cp->width + GAPBETWEEN - rpos; rwid = cp->width + GAPBETWEEN - rpos;
r.left = GAPBETWEEN; r.top = cp->ypos + (height-STATICHEIGHT)/2; r.left = GAPBETWEEN;
r.right = lwid; r.bottom = STATICHEIGHT; r.top = cp->ypos + (height - STATICHEIGHT) / 2;
r.right = lwid;
r.bottom = STATICHEIGHT;
doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid); doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid);
r.left = rpos; r.top = cp->ypos + (height-PUSHBTNHEIGHT)/2; r.left = rpos;
r.right = rwid; r.bottom = PUSHBTNHEIGHT; r.top = cp->ypos + (height - PUSHBTNHEIGHT) / 2;
r.right = rwid;
r.bottom = PUSHBTNHEIGHT;
doctl(cp, r, "BUTTON", doctl(cp, r, "BUTTON",
WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON, WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON,
0, 0, btext, bid);
btext, bid);
cp->ypos += height + GAPBETWEEN; cp->ypos += height + GAPBETWEEN;
} }
@ -291,38 +317,45 @@ void staticbtn(struct ctlpos *cp, char *stext, int sid,
* An edit control on the right hand side, with a static to its left. * An edit control on the right hand side, with a static to its left.
*/ */
static void staticedit_internal(struct ctlpos *cp, char *stext, static void staticedit_internal(struct ctlpos *cp, char *stext,
int sid, int eid, int percentedit, int sid, int eid, int percentedit,
int style) { int style)
{
const int height = (EDITHEIGHT > STATICHEIGHT ? const int height = (EDITHEIGHT > STATICHEIGHT ?
EDITHEIGHT : STATICHEIGHT); EDITHEIGHT : STATICHEIGHT);
RECT r; RECT r;
int lwid, rwid, rpos; int lwid, rwid, rpos;
rpos = GAPBETWEEN + (100-percentedit) * (cp->width + GAPBETWEEN) / 100; rpos =
lwid = rpos - 2*GAPBETWEEN; GAPBETWEEN + (100 - percentedit) * (cp->width + GAPBETWEEN) / 100;
lwid = rpos - 2 * GAPBETWEEN;
rwid = cp->width + GAPBETWEEN - rpos; rwid = cp->width + GAPBETWEEN - rpos;
r.left = GAPBETWEEN; r.top = cp->ypos + (height-STATICHEIGHT)/2; r.left = GAPBETWEEN;
r.right = lwid; r.bottom = STATICHEIGHT; r.top = cp->ypos + (height - STATICHEIGHT) / 2;
r.right = lwid;
r.bottom = STATICHEIGHT;
doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid); doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid);
r.left = rpos; r.top = cp->ypos + (height-EDITHEIGHT)/2; r.left = rpos;
r.right = rwid; r.bottom = EDITHEIGHT; r.top = cp->ypos + (height - EDITHEIGHT) / 2;
r.right = rwid;
r.bottom = EDITHEIGHT;
doctl(cp, r, "EDIT", doctl(cp, r, "EDIT",
WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL | style, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL | style,
WS_EX_CLIENTEDGE, WS_EX_CLIENTEDGE, "", eid);
"", eid);
cp->ypos += height + GAPBETWEEN; cp->ypos += height + GAPBETWEEN;
} }
void staticedit(struct ctlpos *cp, char *stext, void staticedit(struct ctlpos *cp, char *stext,
int sid, int eid, int percentedit) { int sid, int eid, int percentedit)
{
staticedit_internal(cp, stext, sid, eid, percentedit, 0); staticedit_internal(cp, stext, sid, eid, percentedit, 0);
} }
void staticpassedit(struct ctlpos *cp, char *stext, void staticpassedit(struct ctlpos *cp, char *stext,
int sid, int eid, int percentedit) { int sid, int eid, int percentedit)
{
staticedit_internal(cp, stext, sid, eid, percentedit, ES_PASSWORD); staticedit_internal(cp, stext, sid, eid, percentedit, ES_PASSWORD);
} }
@ -330,59 +363,67 @@ void staticpassedit(struct ctlpos *cp, char *stext,
* A big multiline edit control with a static labelling it. * A big multiline edit control with a static labelling it.
*/ */
void bigeditctrl(struct ctlpos *cp, char *stext, void bigeditctrl(struct ctlpos *cp, char *stext,
int sid, int eid, int lines) { int sid, int eid, int lines)
{
RECT r; RECT r;
r.left = GAPBETWEEN; r.top = cp->ypos; r.left = GAPBETWEEN;
r.right = cp->width; r.bottom = STATICHEIGHT; r.top = cp->ypos;
r.right = cp->width;
r.bottom = STATICHEIGHT;
cp->ypos += r.bottom + GAPWITHIN; cp->ypos += r.bottom + GAPWITHIN;
doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid); doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid);
r.left = GAPBETWEEN; r.top = cp->ypos; r.left = GAPBETWEEN;
r.right = cp->width; r.bottom = EDITHEIGHT + (lines-1) * STATICHEIGHT; r.top = cp->ypos;
r.right = cp->width;
r.bottom = EDITHEIGHT + (lines - 1) * STATICHEIGHT;
cp->ypos += r.bottom + GAPBETWEEN; cp->ypos += r.bottom + GAPBETWEEN;
doctl(cp, r, "EDIT", doctl(cp, r, "EDIT",
WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL | ES_MULTILINE, WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL | ES_MULTILINE,
WS_EX_CLIENTEDGE, WS_EX_CLIENTEDGE, "", eid);
"", eid);
} }
/* /*
* A tab-control substitute when a real tab control is unavailable. * A tab-control substitute when a real tab control is unavailable.
*/ */
void ersatztab(struct ctlpos *cp, char *stext, int sid, void ersatztab(struct ctlpos *cp, char *stext, int sid, int lid, int s2id)
int lid, int s2id) { {
const int height = (COMBOHEIGHT > STATICHEIGHT ? const int height = (COMBOHEIGHT > STATICHEIGHT ?
COMBOHEIGHT : STATICHEIGHT); COMBOHEIGHT : STATICHEIGHT);
RECT r; RECT r;
int bigwid, lwid, rwid, rpos; int bigwid, lwid, rwid, rpos;
static const int BIGGAP = 15; static const int BIGGAP = 15;
static const int MEDGAP = 3; static const int MEDGAP = 3;
bigwid = cp->width + 2*GAPBETWEEN - 2*BIGGAP; bigwid = cp->width + 2 * GAPBETWEEN - 2 * BIGGAP;
cp->ypos += MEDGAP; cp->ypos += MEDGAP;
rpos = BIGGAP + (bigwid + BIGGAP) / 2; rpos = BIGGAP + (bigwid + BIGGAP) / 2;
lwid = rpos - 2*BIGGAP; lwid = rpos - 2 * BIGGAP;
rwid = bigwid + BIGGAP - rpos; rwid = bigwid + BIGGAP - rpos;
r.left = BIGGAP; r.top = cp->ypos + (height-STATICHEIGHT)/2; r.left = BIGGAP;
r.right = lwid; r.bottom = STATICHEIGHT; r.top = cp->ypos + (height - STATICHEIGHT) / 2;
r.right = lwid;
r.bottom = STATICHEIGHT;
doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid); doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid);
r.left = rpos; r.top = cp->ypos + (height-COMBOHEIGHT)/2; r.left = rpos;
r.right = rwid; r.bottom = COMBOHEIGHT*10; r.top = cp->ypos + (height - COMBOHEIGHT) / 2;
r.right = rwid;
r.bottom = COMBOHEIGHT * 10;
doctl(cp, r, "COMBOBOX", doctl(cp, r, "COMBOBOX",
WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_CHILD | WS_VISIBLE | WS_TABSTOP |
CBS_DROPDOWNLIST | CBS_HASSTRINGS, CBS_DROPDOWNLIST | CBS_HASSTRINGS, WS_EX_CLIENTEDGE, "", lid);
WS_EX_CLIENTEDGE,
"", lid);
cp->ypos += height + MEDGAP + GAPBETWEEN; cp->ypos += height + MEDGAP + GAPBETWEEN;
r.left = GAPBETWEEN; r.top = cp->ypos; r.left = GAPBETWEEN;
r.right = cp->width; r.bottom = 2; r.top = cp->ypos;
r.right = cp->width;
r.bottom = 2;
doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE | SS_ETCHEDHORZ, doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE | SS_ETCHEDHORZ,
0, "", s2id); 0, "", s2id);
} }
/* /*
@ -390,34 +431,39 @@ void ersatztab(struct ctlpos *cp, char *stext, int sid,
* and a button on the right. * and a button on the right.
*/ */
void editbutton(struct ctlpos *cp, char *stext, int sid, void editbutton(struct ctlpos *cp, char *stext, int sid,
int eid, char *btext, int bid) { int eid, char *btext, int bid)
{
const int height = (EDITHEIGHT > PUSHBTNHEIGHT ? const int height = (EDITHEIGHT > PUSHBTNHEIGHT ?
EDITHEIGHT : PUSHBTNHEIGHT); EDITHEIGHT : PUSHBTNHEIGHT);
RECT r; RECT r;
int lwid, rwid, rpos; int lwid, rwid, rpos;
r.left = GAPBETWEEN; r.top = cp->ypos; r.left = GAPBETWEEN;
r.right = cp->width; r.bottom = STATICHEIGHT; r.top = cp->ypos;
r.right = cp->width;
r.bottom = STATICHEIGHT;
cp->ypos += r.bottom + GAPWITHIN; cp->ypos += r.bottom + GAPWITHIN;
doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid); doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid);
rpos = GAPBETWEEN + 3 * (cp->width + GAPBETWEEN) / 4; rpos = GAPBETWEEN + 3 * (cp->width + GAPBETWEEN) / 4;
lwid = rpos - 2*GAPBETWEEN; lwid = rpos - 2 * GAPBETWEEN;
rwid = cp->width + GAPBETWEEN - rpos; rwid = cp->width + GAPBETWEEN - rpos;
r.left = GAPBETWEEN; r.top = cp->ypos + (height-EDITHEIGHT)/2; r.left = GAPBETWEEN;
r.right = lwid; r.bottom = EDITHEIGHT; r.top = cp->ypos + (height - EDITHEIGHT) / 2;
r.right = lwid;
r.bottom = EDITHEIGHT;
doctl(cp, r, "EDIT", doctl(cp, r, "EDIT",
WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL,
WS_EX_CLIENTEDGE, WS_EX_CLIENTEDGE, "", eid);
"", eid);
r.left = rpos; r.top = cp->ypos + (height-PUSHBTNHEIGHT)/2; r.left = rpos;
r.right = rwid; r.bottom = PUSHBTNHEIGHT; r.top = cp->ypos + (height - PUSHBTNHEIGHT) / 2;
r.right = rwid;
r.bottom = PUSHBTNHEIGHT;
doctl(cp, r, "BUTTON", doctl(cp, r, "BUTTON",
WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON, WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON,
0, 0, btext, bid);
btext, bid);
cp->ypos += height + GAPBETWEEN; cp->ypos += height + GAPBETWEEN;
} }
@ -429,7 +475,8 @@ void editbutton(struct ctlpos *cp, char *stext, int sid,
* buttons. * buttons.
*/ */
void sesssaver(struct ctlpos *cp, char *text, void sesssaver(struct ctlpos *cp, char *text,
int staticid, int editid, int listid, ...) { int staticid, int editid, int listid, ...)
{
RECT r; RECT r;
va_list ap; va_list ap;
int lwid, rwid, rpos; int lwid, rwid, rpos;
@ -437,23 +484,26 @@ void sesssaver(struct ctlpos *cp, char *text,
const int LISTDEFHEIGHT = 66; const int LISTDEFHEIGHT = 66;
rpos = GAPBETWEEN + 3 * (cp->width + GAPBETWEEN) / 4; rpos = GAPBETWEEN + 3 * (cp->width + GAPBETWEEN) / 4;
lwid = rpos - 2*GAPBETWEEN; lwid = rpos - 2 * GAPBETWEEN;
rwid = cp->width + GAPBETWEEN - rpos; rwid = cp->width + GAPBETWEEN - rpos;
/* The static control. */ /* The static control. */
r.left = GAPBETWEEN; r.top = cp->ypos; r.left = GAPBETWEEN;
r.right = lwid; r.bottom = STATICHEIGHT; r.top = cp->ypos;
r.right = lwid;
r.bottom = STATICHEIGHT;
cp->ypos += r.bottom + GAPWITHIN; cp->ypos += r.bottom + GAPWITHIN;
doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, text, staticid); doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, text, staticid);
/* The edit control. */ /* The edit control. */
r.left = GAPBETWEEN; r.top = cp->ypos; r.left = GAPBETWEEN;
r.right = lwid; r.bottom = EDITHEIGHT; r.top = cp->ypos;
r.right = lwid;
r.bottom = EDITHEIGHT;
cp->ypos += r.bottom + GAPWITHIN; cp->ypos += r.bottom + GAPWITHIN;
doctl(cp, r, "EDIT", doctl(cp, r, "EDIT",
WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL, WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL,
WS_EX_CLIENTEDGE, WS_EX_CLIENTEDGE, "", editid);
"", editid);
/* /*
* The buttons (we should hold off on the list box until we * The buttons (we should hold off on the list box until we
@ -462,31 +512,34 @@ void sesssaver(struct ctlpos *cp, char *text,
va_start(ap, listid); va_start(ap, listid);
y = cp->ypos; y = cp->ypos;
while (1) { while (1) {
char *btext = va_arg(ap, char *); char *btext = va_arg(ap, char *);
int bid; int bid;
if (!btext) break; if (!btext)
bid = va_arg(ap, int); break;
r.left = rpos; r.top = y; bid = va_arg(ap, int);
r.right = rwid; r.bottom = PUSHBTNHEIGHT; r.left = rpos;
y += r.bottom + GAPWITHIN; r.top = y;
doctl(cp, r, "BUTTON", r.right = rwid;
WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON, r.bottom = PUSHBTNHEIGHT;
0, y += r.bottom + GAPWITHIN;
btext, bid); doctl(cp, r, "BUTTON",
WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON,
0, btext, bid);
} }
/* Compute list box height. LISTDEFHEIGHT, or height of buttons. */ /* Compute list box height. LISTDEFHEIGHT, or height of buttons. */
y -= cp->ypos; y -= cp->ypos;
y -= GAPWITHIN; y -= GAPWITHIN;
if (y < LISTDEFHEIGHT) y = LISTDEFHEIGHT; if (y < LISTDEFHEIGHT)
r.left = GAPBETWEEN; r.top = cp->ypos; y = LISTDEFHEIGHT;
r.right = lwid; r.bottom = y; r.left = GAPBETWEEN;
r.top = cp->ypos;
r.right = lwid;
r.bottom = y;
cp->ypos += y + GAPBETWEEN; cp->ypos += y + GAPBETWEEN;
doctl(cp, r, "LISTBOX", doctl(cp, r, "LISTBOX",
WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL |
LBS_NOTIFY | LBS_HASSTRINGS, LBS_NOTIFY | LBS_HASSTRINGS, WS_EX_CLIENTEDGE, "", listid);
WS_EX_CLIENTEDGE,
"", listid);
} }
/* /*
@ -495,66 +548,65 @@ void sesssaver(struct ctlpos *cp, char *text,
* statics, and two buttons; then a list box. * statics, and two buttons; then a list box.
*/ */
void envsetter(struct ctlpos *cp, char *stext, int sid, void envsetter(struct ctlpos *cp, char *stext, int sid,
char *e1stext, int e1sid, int e1id, char *e1stext, int e1sid, int e1id,
char *e2stext, int e2sid, int e2id, char *e2stext, int e2sid, int e2id,
int listid, int listid, char *b1text, int b1id, char *b2text, int b2id)
char *b1text, int b1id, char *b2text, int b2id) { {
RECT r; RECT r;
const int height = (STATICHEIGHT > EDITHEIGHT && STATICHEIGHT > PUSHBTNHEIGHT ? const int height = (STATICHEIGHT > EDITHEIGHT
STATICHEIGHT : && STATICHEIGHT >
EDITHEIGHT > PUSHBTNHEIGHT ? PUSHBTNHEIGHT ? STATICHEIGHT : EDITHEIGHT >
EDITHEIGHT : PUSHBTNHEIGHT); PUSHBTNHEIGHT ? EDITHEIGHT : PUSHBTNHEIGHT);
const static int percents[] = { 20, 35, 10, 25 }; const static int percents[] = { 20, 35, 10, 25 };
int i, j, xpos, percent; int i, j, xpos, percent;
const int LISTHEIGHT = 42; const int LISTHEIGHT = 42;
/* The static control. */ /* The static control. */
r.left = GAPBETWEEN; r.top = cp->ypos; r.left = GAPBETWEEN;
r.right = cp->width; r.bottom = STATICHEIGHT; r.top = cp->ypos;
r.right = cp->width;
r.bottom = STATICHEIGHT;
cp->ypos += r.bottom + GAPWITHIN; cp->ypos += r.bottom + GAPWITHIN;
doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid); doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid);
/* The statics+edits+buttons. */ /* The statics+edits+buttons. */
for (j = 0; j < 2; j++) { for (j = 0; j < 2; j++) {
percent = 10; percent = 10;
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
xpos = (cp->width + GAPBETWEEN) * percent / 100; xpos = (cp->width + GAPBETWEEN) * percent / 100;
r.left = xpos + GAPBETWEEN; r.left = xpos + GAPBETWEEN;
percent += percents[i]; percent += percents[i];
xpos = (cp->width + GAPBETWEEN) * percent / 100; xpos = (cp->width + GAPBETWEEN) * percent / 100;
r.right = xpos - r.left; r.right = xpos - r.left;
r.top = cp->ypos; r.top = cp->ypos;
r.bottom = (i==0 ? STATICHEIGHT : r.bottom = (i == 0 ? STATICHEIGHT :
i==1 ? EDITHEIGHT : i == 1 ? EDITHEIGHT : PUSHBTNHEIGHT);
PUSHBTNHEIGHT); r.top += (height - r.bottom) / 2;
r.top += (height-r.bottom)/2; if (i == 0) {
if (i==0) { doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0,
doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, j == 0 ? e1stext : e2stext, j == 0 ? e1sid : e2sid);
j==0 ? e1stext : e2stext, j==0 ? e1sid : e2sid); } else if (i == 1) {
} else if (i==1) { doctl(cp, r, "EDIT",
doctl(cp, r, "EDIT", WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL,
WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL, WS_EX_CLIENTEDGE, "", j == 0 ? e1id : e2id);
WS_EX_CLIENTEDGE, } else if (i == 3) {
"", j==0 ? e1id : e2id); doctl(cp, r, "BUTTON",
} else if (i==3) { WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON,
doctl(cp, r, "BUTTON", 0, j == 0 ? b1text : b2text, j == 0 ? b1id : b2id);
WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON, }
0, }
j==0 ? b1text : b2text, j==0 ? b1id : b2id); cp->ypos += height + GAPWITHIN;
}
}
cp->ypos += height + GAPWITHIN;
} }
/* The list box. */ /* The list box. */
r.left = GAPBETWEEN; r.top = cp->ypos; r.left = GAPBETWEEN;
r.right = cp->width; r.bottom = LISTHEIGHT; r.top = cp->ypos;
r.right = cp->width;
r.bottom = LISTHEIGHT;
cp->ypos += r.bottom + GAPBETWEEN; cp->ypos += r.bottom + GAPBETWEEN;
doctl(cp, r, "LISTBOX", doctl(cp, r, "LISTBOX",
WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL | LBS_HASSTRINGS | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL | LBS_HASSTRINGS
LBS_USETABSTOPS, | LBS_USETABSTOPS, WS_EX_CLIENTEDGE, "", listid);
WS_EX_CLIENTEDGE,
"", listid);
} }
/* /*
@ -563,56 +615,58 @@ void envsetter(struct ctlpos *cp, char *stext, int sid,
* button-and-static-and-edit. * button-and-static-and-edit.
*/ */
void charclass(struct ctlpos *cp, char *stext, int sid, int listid, void charclass(struct ctlpos *cp, char *stext, int sid, int listid,
char *btext, int bid, int eid, char *s2text, int s2id) { char *btext, int bid, int eid, char *s2text, int s2id)
{
RECT r; RECT r;
const int height = (STATICHEIGHT > EDITHEIGHT && STATICHEIGHT > PUSHBTNHEIGHT ? const int height = (STATICHEIGHT > EDITHEIGHT
STATICHEIGHT : && STATICHEIGHT >
EDITHEIGHT > PUSHBTNHEIGHT ? PUSHBTNHEIGHT ? STATICHEIGHT : EDITHEIGHT >
EDITHEIGHT : PUSHBTNHEIGHT); PUSHBTNHEIGHT ? EDITHEIGHT : PUSHBTNHEIGHT);
const static int percents[] = { 30, 40, 30 }; const static int percents[] = { 30, 40, 30 };
int i, xpos, percent; int i, xpos, percent;
const int LISTHEIGHT = 66; const int LISTHEIGHT = 66;
/* The static control. */ /* The static control. */
r.left = GAPBETWEEN; r.top = cp->ypos; r.left = GAPBETWEEN;
r.right = cp->width; r.bottom = STATICHEIGHT; r.top = cp->ypos;
r.right = cp->width;
r.bottom = STATICHEIGHT;
cp->ypos += r.bottom + GAPWITHIN; cp->ypos += r.bottom + GAPWITHIN;
doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid); doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid);
/* The list box. */ /* The list box. */
r.left = GAPBETWEEN; r.top = cp->ypos; r.left = GAPBETWEEN;
r.right = cp->width; r.bottom = LISTHEIGHT; r.top = cp->ypos;
r.right = cp->width;
r.bottom = LISTHEIGHT;
cp->ypos += r.bottom + GAPWITHIN; cp->ypos += r.bottom + GAPWITHIN;
doctl(cp, r, "LISTBOX", doctl(cp, r, "LISTBOX",
WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL | LBS_HASSTRINGS | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL | LBS_HASSTRINGS
LBS_USETABSTOPS, | LBS_USETABSTOPS, WS_EX_CLIENTEDGE, "", listid);
WS_EX_CLIENTEDGE,
"", listid);
/* The button+static+edit. */ /* The button+static+edit. */
percent = xpos = 0; percent = xpos = 0;
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
r.left = xpos + GAPBETWEEN; r.left = xpos + GAPBETWEEN;
percent += percents[i]; percent += percents[i];
xpos = (cp->width + GAPBETWEEN) * percent / 100; xpos = (cp->width + GAPBETWEEN) * percent / 100;
r.right = xpos - r.left; r.right = xpos - r.left;
r.top = cp->ypos; r.top = cp->ypos;
r.bottom = (i==0 ? PUSHBTNHEIGHT : r.bottom = (i == 0 ? PUSHBTNHEIGHT :
i==1 ? STATICHEIGHT : i == 1 ? STATICHEIGHT : EDITHEIGHT);
EDITHEIGHT); r.top += (height - r.bottom) / 2;
r.top += (height-r.bottom)/2; if (i == 0) {
if (i==0) { doctl(cp, r, "BUTTON",
doctl(cp, r, "BUTTON", WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON,
WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON, 0, btext, bid);
0, btext, bid); } else if (i == 1) {
} else if (i==1) { doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE | SS_CENTER,
doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE | SS_CENTER, 0, s2text, s2id);
0, s2text, s2id); } else if (i == 2) {
} else if (i==2) { doctl(cp, r, "EDIT",
doctl(cp, r, "EDIT", WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL,
WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL, WS_EX_CLIENTEDGE, "", eid);
WS_EX_CLIENTEDGE, "", eid); }
}
} }
cp->ypos += height + GAPBETWEEN; cp->ypos += height + GAPBETWEEN;
} }
@ -623,7 +677,8 @@ void charclass(struct ctlpos *cp, char *stext, int sid, int listid,
* two-part statics followed by a button. * two-part statics followed by a button.
*/ */
void colouredit(struct ctlpos *cp, char *stext, int sid, int listid, void colouredit(struct ctlpos *cp, char *stext, int sid, int listid,
char *btext, int bid, ...) { char *btext, int bid, ...)
{
RECT r; RECT r;
int y; int y;
va_list ap; va_list ap;
@ -631,49 +686,58 @@ void colouredit(struct ctlpos *cp, char *stext, int sid, int listid,
const int LISTHEIGHT = 66; const int LISTHEIGHT = 66;
/* The static control. */ /* The static control. */
r.left = GAPBETWEEN; r.top = cp->ypos; r.left = GAPBETWEEN;
r.right = cp->width; r.bottom = STATICHEIGHT; r.top = cp->ypos;
r.right = cp->width;
r.bottom = STATICHEIGHT;
cp->ypos += r.bottom + GAPWITHIN; cp->ypos += r.bottom + GAPWITHIN;
doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid); doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, stext, sid);
rpos = GAPBETWEEN + 2 * (cp->width + GAPBETWEEN) / 3; rpos = GAPBETWEEN + 2 * (cp->width + GAPBETWEEN) / 3;
lwid = rpos - 2*GAPBETWEEN; lwid = rpos - 2 * GAPBETWEEN;
rwid = cp->width + GAPBETWEEN - rpos; rwid = cp->width + GAPBETWEEN - rpos;
/* The list box. */ /* The list box. */
r.left = GAPBETWEEN; r.top = cp->ypos; r.left = GAPBETWEEN;
r.right = lwid; r.bottom = LISTHEIGHT; r.top = cp->ypos;
r.right = lwid;
r.bottom = LISTHEIGHT;
doctl(cp, r, "LISTBOX", doctl(cp, r, "LISTBOX",
WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL | LBS_HASSTRINGS | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_VSCROLL | LBS_HASSTRINGS
LBS_USETABSTOPS | LBS_NOTIFY, | LBS_USETABSTOPS | LBS_NOTIFY, WS_EX_CLIENTEDGE, "", listid);
WS_EX_CLIENTEDGE,
"", listid);
/* The statics. */ /* The statics. */
y = cp->ypos; y = cp->ypos;
va_start(ap, bid); va_start(ap, bid);
while (1) { while (1) {
char *ltext; char *ltext;
int lid, rid; int lid, rid;
ltext = va_arg(ap, char *); ltext = va_arg(ap, char *);
if (!ltext) break; if (!ltext)
lid = va_arg(ap, int); break;
rid = va_arg(ap, int); lid = va_arg(ap, int);
r.top = y; r.bottom = STATICHEIGHT; rid = va_arg(ap, int);
y += r.bottom + GAPWITHIN; r.top = y;
r.left = rpos; r.right = rwid/2; r.bottom = STATICHEIGHT;
doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, ltext, lid); y += r.bottom + GAPWITHIN;
r.left = rpos + r.right; r.right = rwid - r.right; r.left = rpos;
doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE | SS_RIGHT, 0, "", rid); r.right = rwid / 2;
doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE, 0, ltext, lid);
r.left = rpos + r.right;
r.right = rwid - r.right;
doctl(cp, r, "STATIC", WS_CHILD | WS_VISIBLE | SS_RIGHT, 0, "",
rid);
} }
va_end(ap); va_end(ap);
/* The button. */ /* The button. */
r.top = y + 2*GAPWITHIN; r.bottom = PUSHBTNHEIGHT; r.top = y + 2 * GAPWITHIN;
r.left = rpos; r.right = rwid; r.bottom = PUSHBTNHEIGHT;
r.left = rpos;
r.right = rwid;
doctl(cp, r, "BUTTON", doctl(cp, r, "BUTTON",
WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON, WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON,
0, btext, bid); 0, btext, bid);
cp->ypos += LISTHEIGHT + GAPBETWEEN; cp->ypos += LISTHEIGHT + GAPBETWEEN;
} }
@ -683,17 +747,19 @@ void colouredit(struct ctlpos *cp, char *stext, int sid, int listid,
* to be smooth and unbroken, without those ugly divisions; some * to be smooth and unbroken, without those ugly divisions; some
* older compilers may not support that, but that's life. * older compilers may not support that, but that's life.
*/ */
void progressbar(struct ctlpos *cp, int id) { void progressbar(struct ctlpos *cp, int id)
{
RECT r; RECT r;
r.left = GAPBETWEEN; r.top = cp->ypos; r.left = GAPBETWEEN;
r.right = cp->width; r.bottom = PROGBARHEIGHT; r.top = cp->ypos;
r.right = cp->width;
r.bottom = PROGBARHEIGHT;
cp->ypos += r.bottom + GAPBETWEEN; cp->ypos += r.bottom + GAPBETWEEN;
doctl(cp, r, PROGRESS_CLASS, doctl(cp, r, PROGRESS_CLASS, WS_CHILD | WS_VISIBLE
WS_CHILD | WS_VISIBLE
#ifdef PBS_SMOOTH #ifdef PBS_SMOOTH
| PBS_SMOOTH | PBS_SMOOTH
#endif #endif
, WS_EX_CLIENTEDGE, "", id); , WS_EX_CLIENTEDGE, "", id);
} }

3299
windlg.c

File diff suppressed because it is too large Load Diff

2468
window.c

File diff suppressed because it is too large Load Diff

578
winnet.c
View File

@ -82,7 +82,7 @@ typedef struct Socket_tag *Actual_Socket;
struct SockAddr_tag { struct SockAddr_tag {
char *error; char *error;
/* address family this belongs to, AF_INET for IPv4, AF_INET6 for IPv6. */ /* address family this belongs to, AF_INET for IPv4, AF_INET6 for IPv6. */
int family; int family;
unsigned long address; /* Address IPv4 style. */ unsigned long address; /* Address IPv4 style. */
#ifdef IPV6 #ifdef IPV6
struct addrinfo *ai; /* Address IPv6 style. */ struct addrinfo *ai; /* Address IPv6 style. */
@ -102,64 +102,109 @@ struct buffer {
static tree234 *sktree; static tree234 *sktree;
static int cmpfortree(void *av, void *bv) { static int cmpfortree(void *av, void *bv)
Actual_Socket a = (Actual_Socket)av, b = (Actual_Socket)bv; {
unsigned long as = (unsigned long)a->s, bs = (unsigned long)b->s; Actual_Socket a = (Actual_Socket) av, b = (Actual_Socket) bv;
if (as < bs) return -1; unsigned long as = (unsigned long) a->s, bs = (unsigned long) b->s;
if (as > bs) return +1; if (as < bs)
return -1;
if (as > bs)
return +1;
return 0; return 0;
} }
static int cmpforsearch(void *av, void *bv) { static int cmpforsearch(void *av, void *bv)
Actual_Socket b = (Actual_Socket)bv; {
unsigned long as = (unsigned long)av, bs = (unsigned long)b->s; Actual_Socket b = (Actual_Socket) bv;
if (as < bs) return -1; unsigned long as = (unsigned long) av, bs = (unsigned long) b->s;
if (as > bs) return +1; if (as < bs)
return -1;
if (as > bs)
return +1;
return 0; return 0;
} }
void sk_init(void) { void sk_init(void)
{
sktree = newtree234(cmpfortree); sktree = newtree234(cmpfortree);
} }
char *winsock_error_string(int error) { char *winsock_error_string(int error)
{
switch (error) { switch (error) {
case WSAEACCES: return "Network error: Permission denied"; case WSAEACCES:
case WSAEADDRINUSE: return "Network error: Address already in use"; return "Network error: Permission denied";
case WSAEADDRNOTAVAIL: return "Network error: Cannot assign requested address"; case WSAEADDRINUSE:
case WSAEAFNOSUPPORT: return "Network error: Address family not supported by protocol family"; return "Network error: Address already in use";
case WSAEALREADY: return "Network error: Operation already in progress"; case WSAEADDRNOTAVAIL:
case WSAECONNABORTED: return "Network error: Software caused connection abort"; return "Network error: Cannot assign requested address";
case WSAECONNREFUSED: return "Network error: Connection refused"; case WSAEAFNOSUPPORT:
case WSAECONNRESET: return "Network error: Connection reset by peer"; return
case WSAEDESTADDRREQ: return "Network error: Destination address required"; "Network error: Address family not supported by protocol family";
case WSAEFAULT: return "Network error: Bad address"; case WSAEALREADY:
case WSAEHOSTDOWN: return "Network error: Host is down"; return "Network error: Operation already in progress";
case WSAEHOSTUNREACH: return "Network error: No route to host"; case WSAECONNABORTED:
case WSAEINPROGRESS: return "Network error: Operation now in progress"; return "Network error: Software caused connection abort";
case WSAEINTR: return "Network error: Interrupted function call"; case WSAECONNREFUSED:
case WSAEINVAL: return "Network error: Invalid argument"; return "Network error: Connection refused";
case WSAEISCONN: return "Network error: Socket is already connected"; case WSAECONNRESET:
case WSAEMFILE: return "Network error: Too many open files"; return "Network error: Connection reset by peer";
case WSAEMSGSIZE: return "Network error: Message too long"; case WSAEDESTADDRREQ:
case WSAENETDOWN: return "Network error: Network is down"; return "Network error: Destination address required";
case WSAENETRESET: return "Network error: Network dropped connection on reset"; case WSAEFAULT:
case WSAENETUNREACH: return "Network error: Network is unreachable"; return "Network error: Bad address";
case WSAENOBUFS: return "Network error: No buffer space available"; case WSAEHOSTDOWN:
case WSAENOPROTOOPT: return "Network error: Bad protocol option"; return "Network error: Host is down";
case WSAENOTCONN: return "Network error: Socket is not connected"; case WSAEHOSTUNREACH:
case WSAENOTSOCK: return "Network error: Socket operation on non-socket"; return "Network error: No route to host";
case WSAEOPNOTSUPP: return "Network error: Operation not supported"; case WSAEINPROGRESS:
case WSAEPFNOSUPPORT: return "Network error: Protocol family not supported"; return "Network error: Operation now in progress";
case WSAEPROCLIM: return "Network error: Too many processes"; case WSAEINTR:
case WSAEPROTONOSUPPORT: return "Network error: Protocol not supported"; return "Network error: Interrupted function call";
case WSAEPROTOTYPE: return "Network error: Protocol wrong type for socket"; case WSAEINVAL:
case WSAESHUTDOWN: return "Network error: Cannot send after socket shutdown"; return "Network error: Invalid argument";
case WSAESOCKTNOSUPPORT: return "Network error: Socket type not supported"; case WSAEISCONN:
case WSAETIMEDOUT: return "Network error: Connection timed out"; return "Network error: Socket is already connected";
case WSAEWOULDBLOCK: return "Network error: Resource temporarily unavailable"; case WSAEMFILE:
case WSAEDISCON: return "Network error: Graceful shutdown in progress"; return "Network error: Too many open files";
default: return "Unknown network error"; case WSAEMSGSIZE:
return "Network error: Message too long";
case WSAENETDOWN:
return "Network error: Network is down";
case WSAENETRESET:
return "Network error: Network dropped connection on reset";
case WSAENETUNREACH:
return "Network error: Network is unreachable";
case WSAENOBUFS:
return "Network error: No buffer space available";
case WSAENOPROTOOPT:
return "Network error: Bad protocol option";
case WSAENOTCONN:
return "Network error: Socket is not connected";
case WSAENOTSOCK:
return "Network error: Socket operation on non-socket";
case WSAEOPNOTSUPP:
return "Network error: Operation not supported";
case WSAEPFNOSUPPORT:
return "Network error: Protocol family not supported";
case WSAEPROCLIM:
return "Network error: Too many processes";
case WSAEPROTONOSUPPORT:
return "Network error: Protocol not supported";
case WSAEPROTOTYPE:
return "Network error: Protocol wrong type for socket";
case WSAESHUTDOWN:
return "Network error: Cannot send after socket shutdown";
case WSAESOCKTNOSUPPORT:
return "Network error: Socket type not supported";
case WSAETIMEDOUT:
return "Network error: Connection timed out";
case WSAEWOULDBLOCK:
return "Network error: Resource temporarily unavailable";
case WSAEDISCON:
return "Network error: Graceful shutdown in progress";
default:
return "Unknown network error";
} }
} }
@ -174,54 +219,54 @@ SockAddr sk_namelookup(char *host, char **canonicalname)
ret->family = 0; /* We set this one when we have resolved the host. */ ret->family = 0; /* We set this one when we have resolved the host. */
*canonicalname = ret->realhost; /* This makes sure we always have a hostname to return. */ *canonicalname = ret->realhost; /* This makes sure we always have a hostname to return. */
if ( (a = inet_addr(host)) == (unsigned long) INADDR_NONE) if ((a = inet_addr(host)) == (unsigned long) INADDR_NONE) {
{
#ifdef IPV6 #ifdef IPV6
/* Try to get the getaddrinfo() function from wship6.dll */ /* Try to get the getaddrinfo() function from wship6.dll */
/* This way one doesn't need to have IPv6 dll's to use PuTTY and /* This way one doesn't need to have IPv6 dll's to use PuTTY and
* it will fallback to IPv4. */ * it will fallback to IPv4. */
typedef int (CALLBACK* FGETADDRINFO)(const char *nodename, typedef int (CALLBACK * FGETADDRINFO) (const char *nodename,
const char *servname, const char *servname,
const struct addrinfo *hints, const struct addrinfo *
struct addrinfo **res); hints,
struct addrinfo ** res);
FGETADDRINFO fGetAddrInfo = NULL; FGETADDRINFO fGetAddrInfo = NULL;
HINSTANCE dllWSHIP6 = LoadLibrary("wship6.dll"); HINSTANCE dllWSHIP6 = LoadLibrary("wship6.dll");
if (dllWSHIP6) if (dllWSHIP6)
fGetAddrInfo = (FGETADDRINFO)GetProcAddress(dllWSHIP6, fGetAddrInfo = (FGETADDRINFO) GetProcAddress(dllWSHIP6,
"getaddrinfo"); "getaddrinfo");
/* /*
* Use fGetAddrInfo when it's available (which usually also * Use fGetAddrInfo when it's available (which usually also
* means IPv6 is installed...) * means IPv6 is installed...)
*/ */
if (fGetAddrInfo) if (fGetAddrInfo) {
{
/*debug(("Resolving \"%s\" with getaddrinfo() (IPv4+IPv6 capable)...\n", host)); */ /*debug(("Resolving \"%s\" with getaddrinfo() (IPv4+IPv6 capable)...\n", host)); */
if (fGetAddrInfo(host, NULL, NULL, &ret->ai) == 0) if (fGetAddrInfo(host, NULL, NULL, &ret->ai) == 0)
ret->family = ret->ai->ai_family; ret->family = ret->ai->ai_family;
} } else
else
#endif #endif
{
/* /*
* Otherwise use the IPv4-only gethostbyname... * Otherwise use the IPv4-only gethostbyname...
* (NOTE: we don't use gethostbyname as a * (NOTE: we don't use gethostbyname as a
* fallback!) * fallback!)
*/ */
if (ret->family == 0) if (ret->family == 0) {
{ /*debug(("Resolving \"%s\" with gethostbyname() (IPv4 only)...\n", host)); */
/*debug(("Resolving \"%s\" with gethostbyname() (IPv4 only)...\n", host)); */ if (h = gethostbyname(host))
if (h = gethostbyname(host)) ret->family = AF_INET; ret->family = AF_INET;
}
} }
/*debug(("Done resolving...(family is %d) AF_INET = %d, AF_INET6 = %d\n", ret->family, AF_INET, AF_INET6)); */ /*debug(("Done resolving...(family is %d) AF_INET = %d, AF_INET6 = %d\n", ret->family, AF_INET, AF_INET6)); */
if (ret->family == 0) if (ret->family == 0) {
{
DWORD err = WSAGetLastError(); DWORD err = WSAGetLastError();
ret->error = (err == WSAENETDOWN ? "Network is down" : ret->error = (err == WSAENETDOWN ? "Network is down" :
err == WSAHOST_NOT_FOUND ? "Host does not exist" : err ==
err == WSATRY_AGAIN ? "Host not found" : WSAHOST_NOT_FOUND ? "Host does not exist" : err
== WSATRY_AGAIN ? "Host not found" :
#ifdef IPV6 #ifdef IPV6
fGetAddrInfo ? "getaddrinfo: unknown error" : fGetAddrInfo ? "getaddrinfo: unknown error" :
#endif #endif
@ -229,42 +274,46 @@ SockAddr sk_namelookup(char *host, char **canonicalname)
#ifdef DEBUG #ifdef DEBUG
{ {
LPVOID lpMsgBuf; LPVOID lpMsgBuf;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL); FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
/*debug(("Error %ld: %s (h=%lx)\n", err, lpMsgBuf, h));*/ FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) & lpMsgBuf, 0, NULL);
/*debug(("Error %ld: %s (h=%lx)\n", err, lpMsgBuf, h)); */
/* Free the buffer. */ /* Free the buffer. */
LocalFree(lpMsgBuf); LocalFree(lpMsgBuf);
} }
#endif #endif
} } else {
else
{
ret->error = NULL; ret->error = NULL;
#ifdef IPV6 #ifdef IPV6
/* If we got an address info use that... */ /* If we got an address info use that... */
if (ret->ai) if (ret->ai) {
{ typedef int (CALLBACK * FGETNAMEINFO)
typedef int (CALLBACK* FGETNAMEINFO) (const struct sockaddr FAR * sa, socklen_t salen,
(const struct sockaddr FAR *sa, socklen_t salen, char FAR * host, size_t hostlen, char FAR * serv,
char FAR * host, size_t hostlen, char FAR * serv, size_t servlen, int flags);
size_t servlen, int flags);
FGETNAMEINFO fGetNameInfo = NULL; FGETNAMEINFO fGetNameInfo = NULL;
/* Are we in IPv4 fallback mode? */ /* Are we in IPv4 fallback mode? */
/* We put the IPv4 address into the a variable so we can further-on use the IPv4 code... */ /* We put the IPv4 address into the a variable so we can further-on use the IPv4 code... */
if (ret->family == AF_INET) if (ret->family == AF_INET)
memcpy(&a, (char *)&((SOCKADDR_IN *)ret->ai->ai_addr)->sin_addr, sizeof(a)); memcpy(&a,
(char *) &((SOCKADDR_IN *) ret->ai->
ai_addr)->sin_addr, sizeof(a));
/* Now let's find that canonicalname... */ /* Now let's find that canonicalname... */
if ((dllWSHIP6) && (fGetNameInfo = (FGETNAMEINFO)GetProcAddress(dllWSHIP6, "getnameinfo"))) if ((dllWSHIP6)
{ && (fGetNameInfo =
if (fGetNameInfo((struct sockaddr *)ret->ai->ai_addr, (FGETNAMEINFO) GetProcAddress(dllWSHIP6,
ret->family == AF_INET ? "getnameinfo"))) {
sizeof(SOCKADDR_IN) : if (fGetNameInfo
sizeof(SOCKADDR_IN6), ret->realhost, ((struct sockaddr *) ret->ai->ai_addr,
sizeof(ret->realhost), NULL, ret->family ==
0, 0) != 0) AF_INET ? sizeof(SOCKADDR_IN) :
{ sizeof(SOCKADDR_IN6), ret->realhost,
sizeof(ret->realhost), NULL, 0, 0) != 0) {
strncpy(ret->realhost, host, strncpy(ret->realhost, host,
sizeof(ret->realhost)); sizeof(ret->realhost));
} }
@ -272,57 +321,57 @@ SockAddr sk_namelookup(char *host, char **canonicalname)
} }
/* We used the IPv4-only gethostbyname()... */ /* We used the IPv4-only gethostbyname()... */
else else
{
#endif #endif
{
memcpy(&a, h->h_addr, sizeof(a)); memcpy(&a, h->h_addr, sizeof(a));
/* This way we are always sure the h->h_name is valid :) */ /* This way we are always sure the h->h_name is valid :) */
strncpy(ret->realhost, h->h_name, sizeof(ret->realhost)); strncpy(ret->realhost, h->h_name, sizeof(ret->realhost));
#ifdef IPV6
} }
#endif
} }
#ifdef IPV6 #ifdef IPV6
FreeLibrary(dllWSHIP6); FreeLibrary(dllWSHIP6);
#endif #endif
} } else {
else
{
/* /*
* This must be a numeric IPv4 address because it caused a * This must be a numeric IPv4 address because it caused a
* success return from inet_addr. * success return from inet_addr.
*/ */
ret->family = AF_INET; ret->family = AF_INET;
*canonicalname = host; *canonicalname = host;
} }
ret->address = ntohl(a); ret->address = ntohl(a);
return ret; return ret;
} }
void sk_addr_free(SockAddr addr) { void sk_addr_free(SockAddr addr)
{
sfree(addr); sfree(addr);
} }
static Plug sk_tcp_plug (Socket sock, Plug p) { static Plug sk_tcp_plug(Socket sock, Plug p)
{
Actual_Socket s = (Actual_Socket) sock; Actual_Socket s = (Actual_Socket) sock;
Plug ret = s->plug; Plug ret = s->plug;
if (p) s->plug = p; if (p)
s->plug = p;
return ret; return ret;
} }
static void sk_tcp_flush (Socket s) { static void sk_tcp_flush(Socket s)
{
/* /*
* We send data to the socket as soon as we can anyway, * We send data to the socket as soon as we can anyway,
* so we don't need to do anything here. :-) * so we don't need to do anything here. :-)
*/ */
} }
void sk_tcp_close (Socket s); void sk_tcp_close(Socket s);
void sk_tcp_write (Socket s, char *data, int len); void sk_tcp_write(Socket s, char *data, int len);
void sk_tcp_write_oob (Socket s, char *data, int len); void sk_tcp_write_oob(Socket s, char *data, int len);
char *sk_tcp_socket_error(Socket s); char *sk_tcp_socket_error(Socket s);
Socket sk_new(SockAddr addr, int port, int privport, int oobinline, Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
Plug plug) Plug plug)
{ {
static struct socket_function_table fn_table = { static struct socket_function_table fn_table = {
sk_tcp_plug, sk_tcp_plug,
@ -363,69 +412,67 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
if (s == INVALID_SOCKET) { if (s == INVALID_SOCKET) {
err = WSAGetLastError(); err = WSAGetLastError();
ret->error = winsock_error_string(err); ret->error = winsock_error_string(err);
return (Socket) ret; return (Socket) ret;
} }
ret->oobinline = oobinline; ret->oobinline = oobinline;
if (oobinline) { if (oobinline) {
BOOL b = TRUE; BOOL b = TRUE;
setsockopt (s, SOL_SOCKET, SO_OOBINLINE, (void *)&b, sizeof(b)); setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (void *) &b, sizeof(b));
} }
/* /*
* Bind to local address. * Bind to local address.
*/ */
if (privport) if (privport)
localport = 1023; /* count from 1023 downwards */ localport = 1023; /* count from 1023 downwards */
else else
localport = 0; /* just use port 0 (ie winsock picks) */ localport = 0; /* just use port 0 (ie winsock picks) */
/* Loop round trying to bind */ /* Loop round trying to bind */
while (1) { while (1) {
int retcode; int retcode;
#ifdef IPV6 #ifdef IPV6
if (addr->family == AF_INET6) if (addr->family == AF_INET6) {
{ memset(&a6, 0, sizeof(a6));
memset(&a6,0,sizeof(a6)); a6.sin6_family = AF_INET6;
a6.sin6_family = AF_INET6; /*a6.sin6_addr = in6addr_any; *//* == 0 */
/*a6.sin6_addr = in6addr_any;*/ /* == 0 */ a6.sin6_port = htons(localport);
a6.sin6_port = htons(localport); } else
}
else
{
#endif #endif
a.sin_family = AF_INET; {
a.sin_addr.s_addr = htonl(INADDR_ANY); a.sin_family = AF_INET;
a.sin_port = htons(localport); a.sin_addr.s_addr = htonl(INADDR_ANY);
a.sin_port = htons(localport);
}
#ifdef IPV6 #ifdef IPV6
} retcode = bind(s, (addr->family == AF_INET6 ?
retcode = bind (s, (addr->family == AF_INET6 ? (struct sockaddr *) &a6 :
(struct sockaddr *)&a6 : (struct sockaddr *) &a),
(struct sockaddr *)&a), (addr->family ==
(addr->family == AF_INET6 ? sizeof(a6) : sizeof(a))); AF_INET6 ? sizeof(a6) : sizeof(a)));
#else #else
retcode = bind (s, (struct sockaddr *)&a, sizeof(a)); retcode = bind(s, (struct sockaddr *) &a, sizeof(a));
#endif #endif
if (retcode != SOCKET_ERROR) { if (retcode != SOCKET_ERROR) {
err = 0; err = 0;
break; /* done */ break; /* done */
} else { } else {
err = WSAGetLastError(); err = WSAGetLastError();
if (err != WSAEADDRINUSE) /* failed, for a bad reason */ if (err != WSAEADDRINUSE) /* failed, for a bad reason */
break; break;
} }
if (localport == 0) if (localport == 0)
break; /* we're only looping once */ break; /* we're only looping once */
localport--; localport--;
if (localport == 0) if (localport == 0)
break; /* we might have got to the end */ break; /* we might have got to the end */
} }
if (err) if (err) {
{
ret->error = winsock_error_string(err); ret->error = winsock_error_string(err);
return (Socket) ret; return (Socket) ret;
} }
@ -434,26 +481,28 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
* Connect to remote address. * Connect to remote address.
*/ */
#ifdef IPV6 #ifdef IPV6
if (addr->family == AF_INET6) if (addr->family == AF_INET6) {
{ memset(&a, 0, sizeof(a));
memset(&a,0,sizeof(a));
a6.sin6_family = AF_INET6; a6.sin6_family = AF_INET6;
a6.sin6_port = htons((short)port); a6.sin6_port = htons((short) port);
a6.sin6_addr = ((struct sockaddr_in6 *)addr->ai->ai_addr)->sin6_addr; a6.sin6_addr =
} ((struct sockaddr_in6 *) addr->ai->ai_addr)->sin6_addr;
else } else
{
#endif #endif
{
a.sin_family = AF_INET; a.sin_family = AF_INET;
a.sin_addr.s_addr = htonl(addr->address); a.sin_addr.s_addr = htonl(addr->address);
a.sin_port = htons((short)port); a.sin_port = htons((short) port);
#ifdef IPV6
} }
if (connect (s, (addr->family == AF_INET6) ? (struct sockaddr *)&a6 : (struct sockaddr *)&a, (addr->family == AF_INET6) ? sizeof(a6) : sizeof(a)) == SOCKET_ERROR) if ((
#ifdef IPV6
connect(s, ((addr->family == AF_INET6) ?
(struct sockaddr *) &a6 : (struct sockaddr *) &a),
(addr->family == AF_INET6) ? sizeof(a6) : sizeof(a))
#else #else
if (connect (s, (struct sockaddr *)&a, sizeof(a)) == SOCKET_ERROR) connect(s, (struct sockaddr *) &a, sizeof(a))
#endif #endif
{ ) == SOCKET_ERROR) {
err = WSAGetLastError(); err = WSAGetLastError();
ret->error = winsock_error_string(err); ret->error = winsock_error_string(err);
return (Socket) ret; return (Socket) ret;
@ -472,7 +521,8 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
return (Socket) ret; return (Socket) ret;
} }
static void sk_tcp_close(Socket sock) { static void sk_tcp_close(Socket sock)
{
extern char *do_select(SOCKET skt, int startup); extern char *do_select(SOCKET skt, int startup);
Actual_Socket s = (Actual_Socket) sock; Actual_Socket s = (Actual_Socket) sock;
@ -486,25 +536,27 @@ static void sk_tcp_close(Socket sock) {
* The function which tries to send on a socket once it's deemed * The function which tries to send on a socket once it's deemed
* writable. * writable.
*/ */
void try_send(Actual_Socket s) { void try_send(Actual_Socket s)
{
while (s->head) { while (s->head) {
int nsent; int nsent;
DWORD err; DWORD err;
int len, urgentflag; int len, urgentflag;
if (s->sending_oob) { if (s->sending_oob) {
urgentflag = MSG_OOB; urgentflag = MSG_OOB;
len = s->sending_oob; len = s->sending_oob;
} else { } else {
urgentflag = 0; urgentflag = 0;
len = s->head->buflen - s->head->bufpos; len = s->head->buflen - s->head->bufpos;
} }
nsent = send(s->s, s->head->buf + s->head->bufpos, len, urgentflag); nsent =
noise_ultralight(nsent); send(s->s, s->head->buf + s->head->bufpos, len, urgentflag);
noise_ultralight(nsent);
if (nsent <= 0) { if (nsent <= 0) {
err = (nsent < 0 ? WSAGetLastError() : 0); err = (nsent < 0 ? WSAGetLastError() : 0);
if ((err==0 && nsent < 0) || err == WSAEWOULDBLOCK) { if ((err == 0 && nsent < 0) || err == WSAEWOULDBLOCK) {
/* /*
* Perfectly normal: we've sent all we can for the moment. * Perfectly normal: we've sent all we can for the moment.
* *
@ -514,29 +566,28 @@ void try_send(Actual_Socket s) {
* and treat it just like WSAEWOULDBLOCK.) * and treat it just like WSAEWOULDBLOCK.)
*/ */
s->writable = FALSE; s->writable = FALSE;
return; return;
} else if (nsent == 0 || } else if (nsent == 0 ||
err == WSAECONNABORTED || err == WSAECONNABORTED || err == WSAECONNRESET) {
err == WSAECONNRESET) { /*
/* * FIXME. This will have to be done better when we
* FIXME. This will have to be done better when we * start managing multiple sockets (e.g. SSH port
* start managing multiple sockets (e.g. SSH port * forwarding), because if we get CONNRESET while
* forwarding), because if we get CONNRESET while * trying to write a particular forwarded socket
* trying to write a particular forwarded socket * then it isn't necessarily the end of the world.
* then it isn't necessarily the end of the world. * Ideally I'd like to pass the error code back to
* Ideally I'd like to pass the error code back to * somewhere the next select_result() will see it,
* somewhere the next select_result() will see it, * but that might be hard. Perhaps I should pass it
* but that might be hard. Perhaps I should pass it * back to be queued in the Windows front end bit.
* back to be queued in the Windows front end bit. */
*/ fatalbox(winsock_error_string(err));
fatalbox(winsock_error_string(err));
} else { } else {
fatalbox(winsock_error_string(err)); fatalbox(winsock_error_string(err));
} }
} else { } else {
s->head->bufpos += nsent; s->head->bufpos += nsent;
if (s->sending_oob) if (s->sending_oob)
s->sending_oob -= nsent; s->sending_oob -= nsent;
if (s->head->bufpos >= s->head->buflen) { if (s->head->bufpos >= s->head->buflen) {
struct buffer *tmp = s->head; struct buffer *tmp = s->head;
s->head = tmp->next; s->head = tmp->next;
@ -548,7 +599,8 @@ void try_send(Actual_Socket s) {
} }
} }
static void sk_tcp_write(Socket sock, char *buf, int len) { static void sk_tcp_write(Socket sock, char *buf, int len)
{
Actual_Socket s = (Actual_Socket) sock; Actual_Socket s = (Actual_Socket) sock;
/* /*
@ -585,7 +637,8 @@ static void sk_tcp_write(Socket sock, char *buf, int len) {
try_send(s); try_send(s);
} }
static void sk_tcp_write_oob(Socket sock, char *buf, int len) { static void sk_tcp_write_oob(Socket sock, char *buf, int len)
{
Actual_Socket s = (Actual_Socket) sock; Actual_Socket s = (Actual_Socket) sock;
/* /*
@ -594,12 +647,12 @@ static void sk_tcp_write_oob(Socket sock, char *buf, int len) {
if (!s->head) { if (!s->head) {
s->head = smalloc(sizeof(struct buffer)); s->head = smalloc(sizeof(struct buffer));
} else { } else {
struct buffer *walk = s->head->next; struct buffer *walk = s->head->next;
while (walk) { while (walk) {
struct buffer *tmp = walk; struct buffer *tmp = walk;
walk = tmp->next; walk = tmp->next;
sfree(tmp); sfree(tmp);
} }
} }
s->head->next = NULL; s->head->next = NULL;
s->tail = s->head; s->tail = s->head;
@ -618,7 +671,8 @@ static void sk_tcp_write_oob(Socket sock, char *buf, int len) {
try_send(s); try_send(s);
} }
int select_result(WPARAM wParam, LPARAM lParam) { int select_result(WPARAM wParam, LPARAM lParam)
{
int ret, open; int ret, open;
DWORD err; DWORD err;
char buf[20480]; /* nice big buffer for plenty of speed */ char buf[20480]; /* nice big buffer for plenty of speed */
@ -626,43 +680,43 @@ int select_result(WPARAM wParam, LPARAM lParam) {
u_long atmark; u_long atmark;
/* wParam is the socket itself */ /* wParam is the socket itself */
s = find234(sktree, (void *)wParam, cmpforsearch); s = find234(sktree, (void *) wParam, cmpforsearch);
if (!s) if (!s)
return 1; /* boggle */ return 1; /* boggle */
if ((err = WSAGETSELECTERROR(lParam)) != 0) { if ((err = WSAGETSELECTERROR(lParam)) != 0) {
/* /*
* An error has occurred on this socket. Pass it to the * An error has occurred on this socket. Pass it to the
* plug. * plug.
*/ */
return plug_closing (s->plug, winsock_error_string(err), err, 0); return plug_closing(s->plug, winsock_error_string(err), err, 0);
} }
noise_ultralight(lParam); noise_ultralight(lParam);
switch (WSAGETSELECTEVENT(lParam)) { switch (WSAGETSELECTEVENT(lParam)) {
case FD_READ: case FD_READ:
/* /*
* We have received data on the socket. For an oobinline * We have received data on the socket. For an oobinline
* socket, this might be data _before_ an urgent pointer, * socket, this might be data _before_ an urgent pointer,
* in which case we send it to the back end with type==1 * in which case we send it to the back end with type==1
* (data prior to urgent). * (data prior to urgent).
*/ */
if (s->oobinline) { if (s->oobinline) {
atmark = 1; atmark = 1;
ioctlsocket(s->s, SIOCATMARK, &atmark); ioctlsocket(s->s, SIOCATMARK, &atmark);
/* /*
* Avoid checking the return value from ioctlsocket(), * Avoid checking the return value from ioctlsocket(),
* on the grounds that some WinSock wrappers don't * on the grounds that some WinSock wrappers don't
* support it. If it does nothing, we get atmark==1, * support it. If it does nothing, we get atmark==1,
* which is equivalent to `no OOB pending', so the * which is equivalent to `no OOB pending', so the
* effect will be to non-OOB-ify any OOB data. * effect will be to non-OOB-ify any OOB data.
*/ */
} else } else
atmark = 1; atmark = 1;
ret = recv(s->s, buf, sizeof(buf), 0); ret = recv(s->s, buf, sizeof(buf), 0);
noise_ultralight(ret); noise_ultralight(ret);
if (ret < 0) { if (ret < 0) {
err = WSAGetLastError(); err = WSAGetLastError();
if (err == WSAEWOULDBLOCK) { if (err == WSAEWOULDBLOCK) {
@ -670,49 +724,53 @@ int select_result(WPARAM wParam, LPARAM lParam) {
} }
} }
if (ret < 0) { if (ret < 0) {
return plug_closing (s->plug, winsock_error_string(err), err, 0); return plug_closing(s->plug, winsock_error_string(err), err,
0);
} else if (0 == ret) { } else if (0 == ret) {
return plug_closing (s->plug, NULL, 0, 0); return plug_closing(s->plug, NULL, 0, 0);
} else { } else {
return plug_receive (s->plug, atmark ? 0 : 1, buf, ret); return plug_receive(s->plug, atmark ? 0 : 1, buf, ret);
} }
break; break;
case FD_OOB: case FD_OOB:
/* /*
* This will only happen on a non-oobinline socket. It * This will only happen on a non-oobinline socket. It
* indicates that we can immediately perform an OOB read * indicates that we can immediately perform an OOB read
* and get back OOB data, which we will send to the back * and get back OOB data, which we will send to the back
* end with type==2 (urgent data). * end with type==2 (urgent data).
*/ */
ret = recv(s->s, buf, sizeof(buf), MSG_OOB); ret = recv(s->s, buf, sizeof(buf), MSG_OOB);
noise_ultralight(ret); noise_ultralight(ret);
if (ret <= 0) { if (ret <= 0) {
fatalbox(ret == 0 ? "Internal networking trouble" : fatalbox(ret == 0 ? "Internal networking trouble" :
winsock_error_string(WSAGetLastError())); winsock_error_string(WSAGetLastError()));
} else { } else {
return plug_receive (s->plug, 2, buf, ret); return plug_receive(s->plug, 2, buf, ret);
} }
break; break;
case FD_WRITE: case FD_WRITE:
s->writable = 1; s->writable = 1;
try_send(s); try_send(s);
break; break;
case FD_CLOSE: case FD_CLOSE:
/* Signal a close on the socket. First read any outstanding data. */ /* Signal a close on the socket. First read any outstanding data. */
open = 1; open = 1;
do { do {
ret = recv(s->s, buf, sizeof(buf), 0); ret = recv(s->s, buf, sizeof(buf), 0);
if (ret < 0) { if (ret < 0) {
err = WSAGetLastError(); err = WSAGetLastError();
if (err == WSAEWOULDBLOCK) if (err == WSAEWOULDBLOCK)
break; break;
return plug_closing (s->plug, winsock_error_string(err), err, 0); return plug_closing(s->plug, winsock_error_string(err),
} else { err, 0);
if (ret) open &= plug_receive (s->plug, 0, buf, ret); } else {
else open &= plug_closing (s->plug, NULL, 0, 0); if (ret)
open &= plug_receive(s->plug, 0, buf, ret);
else
open &= plug_closing(s->plug, NULL, 0, 0);
} }
} while (ret > 0); } while (ret > 0);
return open; return open;
} }
return 1; return 1;
@ -722,11 +780,14 @@ int select_result(WPARAM wParam, LPARAM lParam) {
* Each socket abstraction contains a `void *' private field in * Each socket abstraction contains a `void *' private field in
* which the client can keep state. * which the client can keep state.
*/ */
void sk_set_private_ptr(Socket sock, void *ptr) { void sk_set_private_ptr(Socket sock, void *ptr)
{
Actual_Socket s = (Actual_Socket) sock; Actual_Socket s = (Actual_Socket) sock;
s->private_ptr = ptr; s->private_ptr = ptr;
} }
void *sk_get_private_ptr(Socket sock) {
void *sk_get_private_ptr(Socket sock)
{
Actual_Socket s = (Actual_Socket) sock; Actual_Socket s = (Actual_Socket) sock;
return s->private_ptr; return s->private_ptr;
} }
@ -736,10 +797,12 @@ void *sk_get_private_ptr(Socket sock) {
* if there's a problem. These functions extract an error message, * if there's a problem. These functions extract an error message,
* or return NULL if there's no problem. * or return NULL if there's no problem.
*/ */
char *sk_addr_error(SockAddr addr) { char *sk_addr_error(SockAddr addr)
{
return addr->error; return addr->error;
} }
static char *sk_tcp_socket_error(Socket sock) { static char *sk_tcp_socket_error(Socket sock)
{
Actual_Socket s = (Actual_Socket) sock; Actual_Socket s = (Actual_Socket) sock;
return s->error; return s->error;
} }
@ -747,13 +810,16 @@ static char *sk_tcp_socket_error(Socket sock) {
/* /*
* For Plink: enumerate all sockets currently active. * For Plink: enumerate all sockets currently active.
*/ */
SOCKET first_socket(int *state) { SOCKET first_socket(int *state)
{
Actual_Socket s; Actual_Socket s;
*state = 0; *state = 0;
s = index234(sktree, (*state)++); s = index234(sktree, (*state)++);
return s ? s->s : INVALID_SOCKET; return s ? s->s : INVALID_SOCKET;
} }
SOCKET next_socket(int *state) {
SOCKET next_socket(int *state)
{
Actual_Socket s = index234(sktree, (*state)++); Actual_Socket s = index234(sktree, (*state)++);
return s ? s->s : INVALID_SOCKET; return s ? s->s : INVALID_SOCKET;
} }

View File

@ -11,19 +11,21 @@
static const char *const puttystr = PUTTY_REG_POS "\\Sessions"; static const char *const puttystr = PUTTY_REG_POS "\\Sessions";
static char seedpath[2*MAX_PATH+10] = "\0"; static char seedpath[2 * MAX_PATH + 10] = "\0";
static char hex[16] = "0123456789ABCDEF"; static char hex[16] = "0123456789ABCDEF";
static void mungestr(char *in, char *out) { static void mungestr(char *in, char *out)
{
int candot = 0; int candot = 0;
while (*in) { while (*in) {
if (*in == ' ' || *in == '\\' || *in == '*' || *in == '?' || if (*in == ' ' || *in == '\\' || *in == '*' || *in == '?' ||
*in == '%' || *in < ' ' || *in > '~' || (*in == '.' && !candot)) { *in == '%' || *in < ' ' || *in > '~' || (*in == '.'
&& !candot)) {
*out++ = '%'; *out++ = '%';
*out++ = hex[((unsigned char)*in) >> 4]; *out++ = hex[((unsigned char) *in) >> 4];
*out++ = hex[((unsigned char)*in) & 15]; *out++ = hex[((unsigned char) *in) & 15];
} else } else
*out++ = *in; *out++ = *in;
in++; in++;
@ -33,67 +35,78 @@ static void mungestr(char *in, char *out) {
return; return;
} }
static void unmungestr(char *in, char *out, int outlen) { static void unmungestr(char *in, char *out, int outlen)
{
while (*in) { while (*in) {
if (*in == '%' && in[1] && in[2]) { if (*in == '%' && in[1] && in[2]) {
int i, j; int i, j;
i = in[1] - '0'; i -= (i > 9 ? 7 : 0); i = in[1] - '0';
j = in[2] - '0'; j -= (j > 9 ? 7 : 0); i -= (i > 9 ? 7 : 0);
j = in[2] - '0';
j -= (j > 9 ? 7 : 0);
*out++ = (i<<4) + j; *out++ = (i << 4) + j;
if (!--outlen) return; if (!--outlen)
return;
in += 3; in += 3;
} else { } else {
*out++ = *in++; *out++ = *in++;
if (!--outlen) return; if (!--outlen)
} return;
}
} }
*out = '\0'; *out = '\0';
return; return;
} }
void *open_settings_w(char *sessionname) { void *open_settings_w(char *sessionname)
{
HKEY subkey1, sesskey; HKEY subkey1, sesskey;
int ret; int ret;
char *p; char *p;
p = smalloc(3*strlen(sessionname)+1); p = smalloc(3 * strlen(sessionname) + 1);
mungestr(sessionname, p); mungestr(sessionname, p);
ret = RegCreateKey(HKEY_CURRENT_USER, puttystr, &subkey1); ret = RegCreateKey(HKEY_CURRENT_USER, puttystr, &subkey1);
if (ret != ERROR_SUCCESS) { if (ret != ERROR_SUCCESS) {
sfree(p); sfree(p);
return NULL; return NULL;
} }
ret = RegCreateKey(subkey1, p, &sesskey); ret = RegCreateKey(subkey1, p, &sesskey);
sfree(p); sfree(p);
RegCloseKey(subkey1); RegCloseKey(subkey1);
if (ret != ERROR_SUCCESS) if (ret != ERROR_SUCCESS)
return NULL; return NULL;
return (void *)sesskey; return (void *) sesskey;
} }
void write_setting_s(void *handle, char *key, char *value) { void write_setting_s(void *handle, char *key, char *value)
{
if (handle) if (handle)
RegSetValueEx((HKEY)handle, key, 0, REG_SZ, value, 1+strlen(value)); RegSetValueEx((HKEY) handle, key, 0, REG_SZ, value,
1 + strlen(value));
} }
void write_setting_i(void *handle, char *key, int value) { void write_setting_i(void *handle, char *key, int value)
{
if (handle) if (handle)
RegSetValueEx((HKEY)handle, key, 0, REG_DWORD, RegSetValueEx((HKEY) handle, key, 0, REG_DWORD,
(CONST BYTE *)&value, sizeof(value)); (CONST BYTE *) & value, sizeof(value));
} }
void close_settings_w(void *handle) { void close_settings_w(void *handle)
RegCloseKey((HKEY)handle); {
RegCloseKey((HKEY) handle);
} }
void *open_settings_r(char *sessionname) { void *open_settings_r(char *sessionname)
{
HKEY subkey1, sesskey; HKEY subkey1, sesskey;
char *p; char *p;
p = smalloc(3*strlen(sessionname)+1); p = smalloc(3 * strlen(sessionname) + 1);
mungestr(sessionname, p); mungestr(sessionname, p);
if (RegOpenKey(HKEY_CURRENT_USER, puttystr, &subkey1) != ERROR_SUCCESS) { if (RegOpenKey(HKEY_CURRENT_USER, puttystr, &subkey1) != ERROR_SUCCESS) {
@ -107,47 +120,50 @@ void *open_settings_r(char *sessionname) {
sfree(p); sfree(p);
return (void *)sesskey; return (void *) sesskey;
} }
char *read_setting_s(void *handle, char *key, char *buffer, int buflen) { char *read_setting_s(void *handle, char *key, char *buffer, int buflen)
{
DWORD type, size; DWORD type, size;
size = buflen; size = buflen;
if (!handle || if (!handle ||
RegQueryValueEx((HKEY)handle, key, 0, RegQueryValueEx((HKEY) handle, key, 0,
&type, buffer, &size) != ERROR_SUCCESS || &type, buffer, &size) != ERROR_SUCCESS ||
type != REG_SZ) type != REG_SZ) return NULL;
return NULL;
else else
return buffer; return buffer;
} }
int read_setting_i(void *handle, char *key, int defvalue) { int read_setting_i(void *handle, char *key, int defvalue)
{
DWORD type, val, size; DWORD type, val, size;
size = sizeof(val); size = sizeof(val);
if (!handle || if (!handle ||
RegQueryValueEx((HKEY)handle, key, 0, &type, RegQueryValueEx((HKEY) handle, key, 0, &type,
(BYTE *)&val, &size) != ERROR_SUCCESS || (BYTE *) & val, &size) != ERROR_SUCCESS ||
size != sizeof(val) || type != REG_DWORD) size != sizeof(val) || type != REG_DWORD)
return defvalue; return defvalue;
else else
return val; return val;
} }
void close_settings_r(void *handle) { void close_settings_r(void *handle)
RegCloseKey((HKEY)handle); {
RegCloseKey((HKEY) handle);
} }
void del_settings (char *sessionname) { void del_settings(char *sessionname)
{
HKEY subkey1; HKEY subkey1;
char *p; char *p;
if (RegOpenKey(HKEY_CURRENT_USER, puttystr, &subkey1) != ERROR_SUCCESS) if (RegOpenKey(HKEY_CURRENT_USER, puttystr, &subkey1) != ERROR_SUCCESS)
return; return;
p = smalloc(3*strlen(sessionname)+1); p = smalloc(3 * strlen(sessionname) + 1);
mungestr(sessionname, p); mungestr(sessionname, p);
RegDeleteKey(subkey1, p); RegDeleteKey(subkey1, p);
sfree(p); sfree(p);
@ -160,53 +176,58 @@ struct enumsettings {
int i; int i;
}; };
void *enum_settings_start(void) { void *enum_settings_start(void)
{
struct enumsettings *ret; struct enumsettings *ret;
HKEY key; HKEY key;
if (RegCreateKey(HKEY_CURRENT_USER, puttystr, &key) != ERROR_SUCCESS) if (RegCreateKey(HKEY_CURRENT_USER, puttystr, &key) != ERROR_SUCCESS)
return NULL; return NULL;
ret = smalloc(sizeof(*ret)); ret = smalloc(sizeof(*ret));
if (ret) { if (ret) {
ret->key = key; ret->key = key;
ret->i = 0; ret->i = 0;
} }
return ret; return ret;
} }
char *enum_settings_next(void *handle, char *buffer, int buflen) { char *enum_settings_next(void *handle, char *buffer, int buflen)
struct enumsettings *e = (struct enumsettings *)handle; {
struct enumsettings *e = (struct enumsettings *) handle;
char *otherbuf; char *otherbuf;
otherbuf = smalloc(3*buflen); otherbuf = smalloc(3 * buflen);
if (otherbuf && RegEnumKey(e->key, e->i++, otherbuf, if (otherbuf && RegEnumKey(e->key, e->i++, otherbuf,
3*buflen) == ERROR_SUCCESS) { 3 * buflen) == ERROR_SUCCESS) {
unmungestr(otherbuf, buffer, buflen); unmungestr(otherbuf, buffer, buflen);
sfree(otherbuf); sfree(otherbuf);
return buffer; return buffer;
} else } else
return NULL; return NULL;
} }
void enum_settings_finish(void *handle) { void enum_settings_finish(void *handle)
struct enumsettings *e = (struct enumsettings *)handle; {
struct enumsettings *e = (struct enumsettings *) handle;
RegCloseKey(e->key); RegCloseKey(e->key);
sfree(e); sfree(e);
} }
static void hostkey_regname(char *buffer, char *hostname, static void hostkey_regname(char *buffer, char *hostname,
int port, char *keytype) { int port, char *keytype)
{
int len; int len;
strcpy(buffer, keytype); strcpy(buffer, keytype);
strcat(buffer, "@"); strcat(buffer, "@");
len = strlen(buffer); len = strlen(buffer);
len += sprintf(buffer+len, "%d:", port); len += sprintf(buffer + len, "%d:", port);
mungestr(hostname, buffer + strlen(buffer)); mungestr(hostname, buffer + strlen(buffer));
} }
int verify_host_key(char *hostname, int port, char *keytype, char *key) { int verify_host_key(char *hostname, int port, char *keytype, char *key)
{
char *otherstr, *regname; char *otherstr, *regname;
int len; int len;
HKEY rkey; HKEY rkey;
@ -221,76 +242,77 @@ int verify_host_key(char *hostname, int port, char *keytype, char *key) {
* says. * says.
*/ */
otherstr = smalloc(len); otherstr = smalloc(len);
regname = smalloc(3*(strlen(hostname)+strlen(keytype))+15); regname = smalloc(3 * (strlen(hostname) + strlen(keytype)) + 15);
hostkey_regname(regname, hostname, port, keytype); hostkey_regname(regname, hostname, port, keytype);
if (RegCreateKey(HKEY_CURRENT_USER, PUTTY_REG_POS "\\SshHostKeys", if (RegCreateKey(HKEY_CURRENT_USER, PUTTY_REG_POS "\\SshHostKeys",
&rkey) != ERROR_SUCCESS) &rkey) != ERROR_SUCCESS)
return 1; /* key does not exist in registry */ return 1; /* key does not exist in registry */
readlen = len; readlen = len;
ret = RegQueryValueEx(rkey, regname, NULL, &type, otherstr, &readlen); ret = RegQueryValueEx(rkey, regname, NULL, &type, otherstr, &readlen);
if (ret != ERROR_SUCCESS && ret != ERROR_MORE_DATA && if (ret != ERROR_SUCCESS && ret != ERROR_MORE_DATA &&
!strcmp(keytype, "rsa")) { !strcmp(keytype, "rsa")) {
/* /*
* Key didn't exist. If the key type is RSA, we'll try * Key didn't exist. If the key type is RSA, we'll try
* another trick, which is to look up the _old_ key format * another trick, which is to look up the _old_ key format
* under just the hostname and translate that. * under just the hostname and translate that.
*/ */
char *justhost = regname + 1 + strcspn(regname, ":"); char *justhost = regname + 1 + strcspn(regname, ":");
char *oldstyle = smalloc(len + 10); /* safety margin */ char *oldstyle = smalloc(len + 10); /* safety margin */
readlen = len; readlen = len;
ret = RegQueryValueEx(rkey, justhost, NULL, &type, ret = RegQueryValueEx(rkey, justhost, NULL, &type,
oldstyle, &readlen); oldstyle, &readlen);
if (ret == ERROR_SUCCESS && type == REG_SZ) {
/*
* The old format is two old-style bignums separated by
* a slash. An old-style bignum is made of groups of
* four hex digits: digits are ordered in sensible
* (most to least significant) order within each group,
* but groups are ordered in silly (least to most)
* order within the bignum. The new format is two
* ordinary C-format hex numbers (0xABCDEFG...XYZ, with
* A nonzero except in the special case 0x0, which
* doesn't appear anyway in RSA keys) separated by a
* comma. All hex digits are lowercase in both formats.
*/
char *p = otherstr;
char *q = oldstyle;
int i, j;
for (i = 0; i < 2; i++) { if (ret == ERROR_SUCCESS && type == REG_SZ) {
int ndigits, nwords; /*
*p++ = '0'; *p++ = 'x'; * The old format is two old-style bignums separated by
ndigits = strcspn(q, "/"); /* find / or end of string */ * a slash. An old-style bignum is made of groups of
nwords = ndigits / 4; * four hex digits: digits are ordered in sensible
/* now trim ndigits to remove leading zeros */ * (most to least significant) order within each group,
while (q[ (ndigits-1) ^ 3 ] == '0' && ndigits > 1) * but groups are ordered in silly (least to most)
ndigits--; * order within the bignum. The new format is two
/* now move digits over to new string */ * ordinary C-format hex numbers (0xABCDEFG...XYZ, with
for (j = 0; j < ndigits; j++) * A nonzero except in the special case 0x0, which
p[ndigits-1-j] = q[j^3]; * doesn't appear anyway in RSA keys) separated by a
p += ndigits; * comma. All hex digits are lowercase in both formats.
q += nwords*4; */
if (*q) { char *p = otherstr;
q++; /* eat the slash */ char *q = oldstyle;
*p++ = ','; /* add a comma */ int i, j;
}
*p = '\0'; /* terminate the string */
}
/* for (i = 0; i < 2; i++) {
* Now _if_ this key matches, we'll enter it in the new int ndigits, nwords;
* format. If not, we'll assume something odd went *p++ = '0';
* wrong, and hyper-cautiously do nothing. *p++ = 'x';
*/ ndigits = strcspn(q, "/"); /* find / or end of string */
if (!strcmp(otherstr, key)) nwords = ndigits / 4;
RegSetValueEx(rkey, regname, 0, REG_SZ, otherstr, /* now trim ndigits to remove leading zeros */
strlen(otherstr)+1); while (q[(ndigits - 1) ^ 3] == '0' && ndigits > 1)
} ndigits--;
/* now move digits over to new string */
for (j = 0; j < ndigits; j++)
p[ndigits - 1 - j] = q[j ^ 3];
p += ndigits;
q += nwords * 4;
if (*q) {
q++; /* eat the slash */
*p++ = ','; /* add a comma */
}
*p = '\0'; /* terminate the string */
}
/*
* Now _if_ this key matches, we'll enter it in the new
* format. If not, we'll assume something odd went
* wrong, and hyper-cautiously do nothing.
*/
if (!strcmp(otherstr, key))
RegSetValueEx(rkey, regname, 0, REG_SZ, otherstr,
strlen(otherstr) + 1);
}
} }
RegCloseKey(rkey); RegCloseKey(rkey);
@ -301,40 +323,42 @@ int verify_host_key(char *hostname, int port, char *keytype, char *key) {
sfree(regname); sfree(regname);
if (ret == ERROR_MORE_DATA || if (ret == ERROR_MORE_DATA ||
(ret == ERROR_SUCCESS && type == REG_SZ && compare)) (ret == ERROR_SUCCESS && type == REG_SZ && compare))
return 2; /* key is different in registry */ return 2; /* key is different in registry */
else if (ret != ERROR_SUCCESS || type != REG_SZ) else if (ret != ERROR_SUCCESS || type != REG_SZ)
return 1; /* key does not exist in registry */ return 1; /* key does not exist in registry */
else else
return 0; /* key matched OK in registry */ return 0; /* key matched OK in registry */
} }
void store_host_key(char *hostname, int port, char *keytype, char *key) { void store_host_key(char *hostname, int port, char *keytype, char *key)
{
char *regname; char *regname;
HKEY rkey; HKEY rkey;
regname = smalloc(3*(strlen(hostname)+strlen(keytype))+15); regname = smalloc(3 * (strlen(hostname) + strlen(keytype)) + 15);
hostkey_regname(regname, hostname, port, keytype); hostkey_regname(regname, hostname, port, keytype);
if (RegCreateKey(HKEY_CURRENT_USER, PUTTY_REG_POS "\\SshHostKeys", if (RegCreateKey(HKEY_CURRENT_USER, PUTTY_REG_POS "\\SshHostKeys",
&rkey) != ERROR_SUCCESS) &rkey) != ERROR_SUCCESS)
return; /* key does not exist in registry */ return; /* key does not exist in registry */
RegSetValueEx(rkey, regname, 0, REG_SZ, key, RegSetValueEx(rkey, regname, 0, REG_SZ, key, strlen(key) + 1);
strlen(key)+1);
RegCloseKey(rkey); RegCloseKey(rkey);
} }
/* /*
* Find the random seed file path and store it in `seedpath'. * Find the random seed file path and store it in `seedpath'.
*/ */
static void get_seedpath(void) { static void get_seedpath(void)
{
HKEY rkey; HKEY rkey;
DWORD type, size; DWORD type, size;
size = sizeof(seedpath); size = sizeof(seedpath);
if (RegOpenKey(HKEY_CURRENT_USER, PUTTY_REG_POS, &rkey)==ERROR_SUCCESS) { if (RegOpenKey(HKEY_CURRENT_USER, PUTTY_REG_POS, &rkey) ==
ERROR_SUCCESS) {
int ret = RegQueryValueEx(rkey, "RandSeedFile", int ret = RegQueryValueEx(rkey, "RandSeedFile",
0, &type, seedpath, &size); 0, &type, seedpath, &size);
if (ret != ERROR_SUCCESS || type != REG_SZ) if (ret != ERROR_SUCCESS || type != REG_SZ)
@ -346,19 +370,23 @@ static void get_seedpath(void) {
if (!seedpath[0]) { if (!seedpath[0]) {
int len, ret; int len, ret;
len = GetEnvironmentVariable("HOMEDRIVE", seedpath, sizeof(seedpath)); len =
ret = GetEnvironmentVariable("HOMEPATH", seedpath+len, GetEnvironmentVariable("HOMEDRIVE", seedpath,
sizeof(seedpath)-len); sizeof(seedpath));
ret =
GetEnvironmentVariable("HOMEPATH", seedpath + len,
sizeof(seedpath) - len);
if (ret == 0) { /* probably win95; store in \WINDOWS */ if (ret == 0) { /* probably win95; store in \WINDOWS */
GetWindowsDirectory(seedpath, sizeof(seedpath)); GetWindowsDirectory(seedpath, sizeof(seedpath));
len = strlen(seedpath); len = strlen(seedpath);
} else } else
len += ret; len += ret;
strcpy(seedpath+len, "\\PUTTY.RND"); strcpy(seedpath + len, "\\PUTTY.RND");
} }
} }
void read_random_seed(noise_consumer_t consumer) { void read_random_seed(noise_consumer_t consumer)
{
HANDLE seedf; HANDLE seedf;
if (!seedpath[0]) if (!seedpath[0])
@ -374,7 +402,7 @@ void read_random_seed(noise_consumer_t consumer) {
DWORD len; DWORD len;
if (ReadFile(seedf, buf, sizeof(buf), &len, NULL) && len) if (ReadFile(seedf, buf, sizeof(buf), &len, NULL) && len)
consumer(buf, len); consumer(buf, len);
else else
break; break;
} }
@ -382,7 +410,8 @@ void read_random_seed(noise_consumer_t consumer) {
} }
} }
void write_random_seed(void *data, int len) { void write_random_seed(void *data, int len)
{
HANDLE seedf; HANDLE seedf;
if (!seedpath[0]) if (!seedpath[0])
@ -402,25 +431,27 @@ void write_random_seed(void *data, int len) {
/* /*
* Recursively delete a registry key and everything under it. * Recursively delete a registry key and everything under it.
*/ */
static void registry_recursive_remove(HKEY key) { static void registry_recursive_remove(HKEY key)
{
DWORD i; DWORD i;
char name[MAX_PATH+1]; char name[MAX_PATH + 1];
HKEY subkey; HKEY subkey;
i = 0; i = 0;
while (RegEnumKey(key, i, name, sizeof(name)) == ERROR_SUCCESS) { while (RegEnumKey(key, i, name, sizeof(name)) == ERROR_SUCCESS) {
if (RegOpenKey(key, name, &subkey) == ERROR_SUCCESS) { if (RegOpenKey(key, name, &subkey) == ERROR_SUCCESS) {
registry_recursive_remove(subkey); registry_recursive_remove(subkey);
RegCloseKey(subkey); RegCloseKey(subkey);
} }
RegDeleteKey(key, name); RegDeleteKey(key, name);
} }
} }
void cleanup_all(void) { void cleanup_all(void)
{
HKEY key; HKEY key;
int ret; int ret;
char name[MAX_PATH+1]; char name[MAX_PATH + 1];
/* ------------------------------------------------------------ /* ------------------------------------------------------------
* Wipe out the random seed file. * Wipe out the random seed file.
@ -436,9 +467,10 @@ void cleanup_all(void) {
/* /*
* Open the main PuTTY registry key and remove everything in it. * Open the main PuTTY registry key and remove everything in it.
*/ */
if (RegOpenKey(HKEY_CURRENT_USER, PUTTY_REG_POS, &key) == ERROR_SUCCESS) { if (RegOpenKey(HKEY_CURRENT_USER, PUTTY_REG_POS, &key) ==
registry_recursive_remove(key); ERROR_SUCCESS) {
RegCloseKey(key); registry_recursive_remove(key);
RegCloseKey(key);
} }
/* /*
* Now open the parent key and remove the PuTTY main key. Once * Now open the parent key and remove the PuTTY main key. Once
@ -446,22 +478,22 @@ void cleanup_all(void) {
* children. * children.
*/ */
if (RegOpenKey(HKEY_CURRENT_USER, PUTTY_REG_PARENT, if (RegOpenKey(HKEY_CURRENT_USER, PUTTY_REG_PARENT,
&key) == ERROR_SUCCESS) { &key) == ERROR_SUCCESS) {
RegDeleteKey(key, PUTTY_REG_PARENT_CHILD); RegDeleteKey(key, PUTTY_REG_PARENT_CHILD);
ret = RegEnumKey(key, 0, name, sizeof(name)); ret = RegEnumKey(key, 0, name, sizeof(name));
RegCloseKey(key); RegCloseKey(key);
/* /*
* If the parent key had no other children, we must delete * If the parent key had no other children, we must delete
* it in its turn. That means opening the _grandparent_ * it in its turn. That means opening the _grandparent_
* key. * key.
*/ */
if (ret != ERROR_SUCCESS) { if (ret != ERROR_SUCCESS) {
if (RegOpenKey(HKEY_CURRENT_USER, PUTTY_REG_GPARENT, if (RegOpenKey(HKEY_CURRENT_USER, PUTTY_REG_GPARENT,
&key) == ERROR_SUCCESS) { &key) == ERROR_SUCCESS) {
RegDeleteKey(key, PUTTY_REG_GPARENT_CHILD); RegDeleteKey(key, PUTTY_REG_GPARENT_CHILD);
RegCloseKey(key); RegCloseKey(key);
} }
} }
} }
/* /*
* Now we're done. * Now we're done.

View File

@ -30,40 +30,36 @@ struct ctlpos {
}; };
void ctlposinit(struct ctlpos *cp, HWND hwnd, void ctlposinit(struct ctlpos *cp, HWND hwnd,
int leftborder, int rightborder, int topborder); int leftborder, int rightborder, int topborder);
void doctl(struct ctlpos *cp, RECT r, void doctl(struct ctlpos *cp, RECT r,
char *wclass, int wstyle, int exstyle, char *wclass, int wstyle, int exstyle, char *wtext, int wid);
char *wtext, int wid);
void bartitle(struct ctlpos *cp, char *name, int id); void bartitle(struct ctlpos *cp, char *name, int id);
void beginbox(struct ctlpos *cp, char *name, int idbox); void beginbox(struct ctlpos *cp, char *name, int idbox);
void endbox(struct ctlpos *cp); void endbox(struct ctlpos *cp);
void multiedit(struct ctlpos *cp, ...); void multiedit(struct ctlpos *cp, ...);
void radioline(struct ctlpos *cp, void radioline(struct ctlpos *cp, char *text, int id, int nacross, ...);
char *text, int id, int nacross, ...);
void radiobig(struct ctlpos *cp, char *text, int id, ...); void radiobig(struct ctlpos *cp, char *text, int id, ...);
void checkbox(struct ctlpos *cp, char *text, int id); void checkbox(struct ctlpos *cp, char *text, int id);
void statictext(struct ctlpos *cp, char *text, int id); void statictext(struct ctlpos *cp, char *text, int id);
void staticbtn(struct ctlpos *cp, char *stext, int sid, void staticbtn(struct ctlpos *cp, char *stext, int sid,
char *btext, int bid); char *btext, int bid);
void staticedit(struct ctlpos *cp, char *stext, void staticedit(struct ctlpos *cp, char *stext,
int sid, int eid, int percentedit); int sid, int eid, int percentedit);
void staticpassedit(struct ctlpos *cp, char *stext, void staticpassedit(struct ctlpos *cp, char *stext,
int sid, int eid, int percentedit); int sid, int eid, int percentedit);
void bigeditctrl(struct ctlpos *cp, char *stext, void bigeditctrl(struct ctlpos *cp, char *stext,
int sid, int eid, int lines); int sid, int eid, int lines);
void ersatztab(struct ctlpos *cp, char *stext, int sid, void ersatztab(struct ctlpos *cp, char *stext, int sid, int lid, int s2id);
int lid, int s2id);
void editbutton(struct ctlpos *cp, char *stext, int sid, void editbutton(struct ctlpos *cp, char *stext, int sid,
int eid, char *btext, int bid); int eid, char *btext, int bid);
void sesssaver(struct ctlpos *cp, char *text, void sesssaver(struct ctlpos *cp, char *text,
int staticid, int editid, int listid, ...); int staticid, int editid, int listid, ...);
void envsetter(struct ctlpos *cp, char *stext, int sid, void envsetter(struct ctlpos *cp, char *stext, int sid,
char *e1stext, int e1sid, int e1id, char *e1stext, int e1sid, int e1id,
char *e2stext, int e2sid, int e2id, char *e2stext, int e2sid, int e2id,
int listid, int listid, char *b1text, int b1id, char *b2text, int b2id);
char *b1text, int b1id, char *b2text, int b2id);
void charclass(struct ctlpos *cp, char *stext, int sid, int listid, void charclass(struct ctlpos *cp, char *stext, int sid, int listid,
char *btext, int bid, int eid, char *s2text, int s2id); char *btext, int bid, int eid, char *s2text, int s2id);
void colouredit(struct ctlpos *cp, char *stext, int sid, int listid, void colouredit(struct ctlpos *cp, char *stext, int sid, int listid,
char *btext, int bid, ...); char *btext, int bid, ...);
void progressbar(struct ctlpos *cp, int id); void progressbar(struct ctlpos *cp, int id);

158
x11fwd.c
View File

@ -64,49 +64,53 @@ extern void sshfwd_write(void *, char *, int);
struct X11Private { struct X11Private {
struct plug_function_table *fn; struct plug_function_table *fn;
/* the above variable absolutely *must* be the first in this structure */ /* the above variable absolutely *must* be the first in this structure */
unsigned char firstpkt[12]; /* first X data packet */ unsigned char firstpkt[12]; /* first X data packet */
char *auth_protocol; char *auth_protocol;
unsigned char *auth_data; unsigned char *auth_data;
int data_read, auth_plen, auth_psize, auth_dlen, auth_dsize; int data_read, auth_plen, auth_psize, auth_dlen, auth_dsize;
int verified; int verified;
void *c; /* data used by ssh.c */ void *c; /* data used by ssh.c */
Socket s; Socket s;
}; };
void x11_close (Socket s); void x11_close(Socket s);
static unsigned char x11_authdata[64]; static unsigned char x11_authdata[64];
static int x11_authdatalen; static int x11_authdatalen;
void x11_invent_auth(char *proto, int protomaxlen, void x11_invent_auth(char *proto, int protomaxlen,
char *data, int datamaxlen) { char *data, int datamaxlen)
{
char ourdata[64]; char ourdata[64];
int i; int i;
/* MIT-MAGIC-COOKIE-1. Cookie size is 128 bits (16 bytes). */ /* MIT-MAGIC-COOKIE-1. Cookie size is 128 bits (16 bytes). */
x11_authdatalen = 16; x11_authdatalen = 16;
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)
x11_authdata[i] = random_byte(); x11_authdata[i] = random_byte();
/* Now format for the recipient. */ /* Now format for the recipient. */
strncpy(proto, "MIT-MAGIC-COOKIE-1", protomaxlen); strncpy(proto, "MIT-MAGIC-COOKIE-1", protomaxlen);
ourdata[0] = '\0'; ourdata[0] = '\0';
for (i = 0; i < x11_authdatalen; i++) for (i = 0; i < x11_authdatalen; i++)
sprintf(ourdata+strlen(ourdata), "%02x", x11_authdata[i]); sprintf(ourdata + strlen(ourdata), "%02x", x11_authdata[i]);
strncpy(data, ourdata, datamaxlen); strncpy(data, ourdata, datamaxlen);
} }
static int x11_verify(char *proto, unsigned char *data, int dlen) { static int x11_verify(char *proto, unsigned char *data, int dlen)
{
if (strcmp(proto, "MIT-MAGIC-COOKIE-1") != 0) if (strcmp(proto, "MIT-MAGIC-COOKIE-1") != 0)
return 0; /* wrong protocol attempted */ return 0; /* wrong protocol attempted */
if (dlen != x11_authdatalen) if (dlen != x11_authdatalen)
return 0; /* cookie was wrong length */ return 0; /* cookie was wrong length */
if (memcmp(x11_authdata, data, dlen) != 0) if (memcmp(x11_authdata, data, dlen) != 0)
return 0; /* cookie was wrong cookie! */ return 0; /* cookie was wrong cookie! */
return 1; return 1;
} }
static int x11_closing (Plug plug, char *error_msg, int error_code, int calling_back) { static int x11_closing(Plug plug, char *error_msg, int error_code,
int calling_back)
{
struct X11Private *pr = (struct X11Private *) plug; struct X11Private *pr = (struct X11Private *) plug;
/* /*
@ -119,7 +123,8 @@ static int x11_closing (Plug plug, char *error_msg, int error_code, int calling_
return 1; return 1;
} }
static int x11_receive (Plug plug, int urgent, char *data, int len) { static int x11_receive(Plug plug, int urgent, char *data, int len)
{
struct X11Private *pr = (struct X11Private *) plug; struct X11Private *pr = (struct X11Private *) plug;
sshfwd_write(pr->c, data, len); sshfwd_write(pr->c, data, len);
@ -132,7 +137,8 @@ static int x11_receive (Plug plug, int urgent, char *data, int len) {
* Returns an error message, or NULL on success. * Returns an error message, or NULL on success.
* also, fills the SocketsStructure * also, fills the SocketsStructure
*/ */
char *x11_init (Socket *s, char *display, void *c) { char *x11_init(Socket * s, char *display, void *c)
{
static struct plug_function_table fn_table = { static struct plug_function_table fn_table = {
x11_closing, x11_closing,
x11_receive x11_receive
@ -150,11 +156,11 @@ char *x11_init (Socket *s, char *display, void *c) {
*/ */
n = strcspn(display, ":"); n = strcspn(display, ":");
if (display[n]) if (display[n])
displaynum = atoi(display+n+1); displaynum = atoi(display + n + 1);
else else
displaynum = 0; /* sensible default */ displaynum = 0; /* sensible default */
if (n > sizeof(host)-1) if (n > sizeof(host) - 1)
n = sizeof(host)-1; n = sizeof(host) - 1;
strncpy(host, display, n); strncpy(host, display, n);
host[n] = '\0'; host[n] = '\0';
@ -162,7 +168,7 @@ char *x11_init (Socket *s, char *display, void *c) {
* Try to find host. * Try to find host.
*/ */
addr = sk_namelookup(host, &dummy_realhost); addr = sk_namelookup(host, &dummy_realhost);
if ( (err = sk_addr_error(addr)) ) if ((err = sk_addr_error(addr)))
return err; return err;
port = 6000 + displaynum; port = 6000 + displaynum;
@ -170,7 +176,7 @@ char *x11_init (Socket *s, char *display, void *c) {
/* /*
* Open socket. * Open socket.
*/ */
pr = (struct X11Private *)smalloc(sizeof(struct X11Private)); pr = (struct X11Private *) smalloc(sizeof(struct X11Private));
pr->fn = &fn_table; pr->fn = &fn_table;
pr->auth_protocol = NULL; pr->auth_protocol = NULL;
pr->verified = 0; pr->verified = 0;
@ -178,8 +184,8 @@ char *x11_init (Socket *s, char *display, void *c) {
pr->c = c; pr->c = c;
pr->s = *s = sk_new(addr, port, 0, 1, (Plug) pr); pr->s = *s = sk_new(addr, port, 0, 1, (Plug) pr);
if ( (err = sk_socket_error(*s)) ) { if ((err = sk_socket_error(*s))) {
sfree (pr); sfree(pr);
return err; return err;
} }
@ -188,15 +194,16 @@ char *x11_init (Socket *s, char *display, void *c) {
return NULL; return NULL;
} }
void x11_close (Socket s) { void x11_close(Socket s)
struct X11Private *pr; {
if (!s) struct X11Private *pr;
return; if (!s)
pr = (struct X11Private *)sk_get_private_ptr(s); return;
pr = (struct X11Private *) sk_get_private_ptr(s);
if (pr->auth_protocol) { if (pr->auth_protocol) {
sfree(pr->auth_protocol); sfree(pr->auth_protocol);
sfree(pr->auth_data); sfree(pr->auth_data);
} }
sfree(pr); sfree(pr);
@ -207,8 +214,9 @@ void x11_close (Socket s) {
/* /*
* Called to send data down the raw connection. * Called to send data down the raw connection.
*/ */
void x11_send (Socket s, char *data, int len) { void x11_send(Socket s, char *data, int len)
struct X11Private *pr = (struct X11Private *)sk_get_private_ptr(s); {
struct X11Private *pr = (struct X11Private *) sk_get_private_ptr(s);
if (s == NULL) if (s == NULL)
return; return;
@ -217,74 +225,74 @@ void x11_send (Socket s, char *data, int len) {
* Read the first packet. * Read the first packet.
*/ */
while (len > 0 && pr->data_read < 12) while (len > 0 && pr->data_read < 12)
pr->firstpkt[pr->data_read++] = (unsigned char)(len--, *data++); pr->firstpkt[pr->data_read++] = (unsigned char) (len--, *data++);
if (pr->data_read < 12) if (pr->data_read < 12)
return; return;
/* /*
* If we have not allocated the auth_protocol and auth_data * If we have not allocated the auth_protocol and auth_data
* strings, do so now. * strings, do so now.
*/ */
if (!pr->auth_protocol) { if (!pr->auth_protocol) {
pr->auth_plen = GET_16BIT(pr->firstpkt[0], pr->firstpkt+6); pr->auth_plen = GET_16BIT(pr->firstpkt[0], pr->firstpkt + 6);
pr->auth_dlen = GET_16BIT(pr->firstpkt[0], pr->firstpkt+8); pr->auth_dlen = GET_16BIT(pr->firstpkt[0], pr->firstpkt + 8);
pr->auth_psize = (pr->auth_plen + 3) &~ 3; pr->auth_psize = (pr->auth_plen + 3) & ~3;
pr->auth_dsize = (pr->auth_dlen + 3) &~ 3; pr->auth_dsize = (pr->auth_dlen + 3) & ~3;
/* Leave room for a terminating zero, to make our lives easier. */ /* Leave room for a terminating zero, to make our lives easier. */
pr->auth_protocol = (char *)smalloc(pr->auth_psize+1); pr->auth_protocol = (char *) smalloc(pr->auth_psize + 1);
pr->auth_data = (char *)smalloc(pr->auth_dsize); pr->auth_data = (char *) smalloc(pr->auth_dsize);
} }
/* /*
* Read the auth_protocol and auth_data strings. * Read the auth_protocol and auth_data strings.
*/ */
while (len > 0 && pr->data_read < 12 + pr->auth_psize) while (len > 0 && pr->data_read < 12 + pr->auth_psize)
pr->auth_protocol[pr->data_read++ - 12] = (len--, *data++); pr->auth_protocol[pr->data_read++ - 12] = (len--, *data++);
while (len > 0 && pr->data_read < 12 + pr->auth_psize + pr->auth_dsize) while (len > 0 && pr->data_read < 12 + pr->auth_psize + pr->auth_dsize)
pr->auth_data[pr->data_read++ - 12 - pr->auth_data[pr->data_read++ - 12 -
pr->auth_psize] = (unsigned char)(len--, *data++); pr->auth_psize] = (unsigned char) (len--, *data++);
if (pr->data_read < 12 + pr->auth_psize + pr->auth_dsize) if (pr->data_read < 12 + pr->auth_psize + pr->auth_dsize)
return; return;
/* /*
* If we haven't verified the authentication, do so now. * If we haven't verified the authentication, do so now.
*/ */
if (!pr->verified) { if (!pr->verified) {
int ret; int ret;
pr->auth_protocol[pr->auth_plen] = '\0'; /* ASCIZ */ pr->auth_protocol[pr->auth_plen] = '\0'; /* ASCIZ */
ret = x11_verify(pr->auth_protocol, pr->auth_data, pr->auth_dlen); ret = x11_verify(pr->auth_protocol, pr->auth_data, pr->auth_dlen);
/* /*
* If authentication failed, construct and send an error * If authentication failed, construct and send an error
* packet, then terminate the connection. * packet, then terminate the connection.
*/ */
if (!ret) { if (!ret) {
char message[] = "Authentication failed at PuTTY X11 proxy"; char message[] = "Authentication failed at PuTTY X11 proxy";
unsigned char reply[8 + sizeof(message) + 4]; unsigned char reply[8 + sizeof(message) + 4];
int msglen = sizeof(message)-1; /* skip zero byte */ int msglen = sizeof(message) - 1; /* skip zero byte */
int msgsize = (msglen+3) &~ 3; int msgsize = (msglen + 3) & ~3;
reply[0] = 0; /* failure */ reply[0] = 0; /* failure */
reply[1] = msglen; /* length of reason string */ reply[1] = msglen; /* length of reason string */
memcpy(reply+2, pr->firstpkt+2, 4); /* major/minor proto vsn */ memcpy(reply + 2, pr->firstpkt + 2, 4); /* major/minor proto vsn */
PUT_16BIT(pr->firstpkt[0], reply+6, msglen >> 2); /* data len */ PUT_16BIT(pr->firstpkt[0], reply + 6, msglen >> 2); /* data len */
memset(reply+8, 0, msgsize); memset(reply + 8, 0, msgsize);
memcpy(reply+8, message, msglen); memcpy(reply + 8, message, msglen);
sshfwd_write(pr->c, reply, 8+msgsize); sshfwd_write(pr->c, reply, 8 + msgsize);
sshfwd_close(pr->c); sshfwd_close(pr->c);
x11_close(s); x11_close(s);
return; return;
} }
/* /*
* Now we know we're going to accept the connection. Strip * Now we know we're going to accept the connection. Strip
* the auth data. (TODO: if we ever work out how, we should * the auth data. (TODO: if we ever work out how, we should
* replace some real auth data in here.) * replace some real auth data in here.)
*/ */
PUT_16BIT(pr->firstpkt[0], pr->firstpkt+6, 0); /* auth proto */ PUT_16BIT(pr->firstpkt[0], pr->firstpkt + 6, 0); /* auth proto */
PUT_16BIT(pr->firstpkt[0], pr->firstpkt+8, 0); /* auth data */ PUT_16BIT(pr->firstpkt[0], pr->firstpkt + 8, 0); /* auth data */
sk_write(s, pr->firstpkt, 12); sk_write(s, pr->firstpkt, 12);
pr->verified = 1; pr->verified = 1;
} }
/* /*

328
xlat.c
View File

@ -2,170 +2,232 @@
#include <stdio.h> #include <stdio.h>
#include "putty.h" #include "putty.h"
static unsigned char win2koi[] = static unsigned char win2koi[] = {
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, 111,
112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125,
128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, 126, 127,
144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
160,161,162,163,164,189,166,167,179,169,180,171,172,173,174,183, 142, 143,
176,177,182,166,173,181,182,183,163,185,164,187,188,189,190,167, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157,
225,226,247,231,228,229,246,250,233,234,235,236,237,238,239,240, 158, 159,
242,243,244,245,230,232,227,254,251,253,255,249,248,252,224,241, 160, 161, 162, 163, 164, 189, 166, 167, 179, 169, 180, 171, 172, 173,
193,194,215,199,196,197,214,218,201,202,203,204,205,206,207,208, 174, 183,
210,211,212,213,198,200,195,222,219,221,223,217,216,220,192,209 176, 177, 182, 166, 173, 181, 182, 183, 163, 185, 164, 187, 188, 189,
190, 167,
225, 226, 247, 231, 228, 229, 246, 250, 233, 234, 235, 236, 237, 238,
239, 240,
242, 243, 244, 245, 230, 232, 227, 254, 251, 253, 255, 249, 248, 252,
224, 241,
193, 194, 215, 199, 196, 197, 214, 218, 201, 202, 203, 204, 205, 206,
207, 208,
210, 211, 212, 213, 198, 200, 195, 222, 219, 221, 223, 217, 216, 220,
192, 209
}; };
static unsigned char koi2win[] = static unsigned char koi2win[] = {
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, 111,
112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125,
128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, 126, 127,
144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
160,161,162,184,186,165,179,191,168,169,170,171,172,180,174,175, 142, 143,
176,177,178,168,170,181,178,175,184,185,186,187,188,165,190,191, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157,
254,224,225,246,228,229,244,227,245,232,233,234,235,236,237,238, 158, 159,
239,255,240,241,242,243,230,226,252,251,231,248,253,249,247,250, 160, 161, 162, 184, 186, 165, 179, 191, 168, 169, 170, 171, 172, 180,
222,192,193,214,196,197,212,195,213,200,201,202,203,204,205,206, 174, 175,
207,223,208,209,210,211,198,194,220,219,199,216,221,217,215,218 176, 177, 178, 168, 170, 181, 178, 175, 184, 185, 186, 187, 188, 165,
190, 191,
254, 224, 225, 246, 228, 229, 244, 227, 245, 232, 233, 234, 235, 236,
237, 238,
239, 255, 240, 241, 242, 243, 230, 226, 252, 251, 231, 248, 253, 249,
247, 250,
222, 192, 193, 214, 196, 197, 212, 195, 213, 200, 201, 202, 203, 204,
205, 206,
207, 223, 208, 209, 210, 211, 198, 194, 220, 219, 199, 216, 221, 217,
215, 218
}; };
static unsigned char xlatWIN1250toISO88592[] = static unsigned char xlatWIN1250toISO88592[] = {
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, 111,
112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125,
128,129, 39,131, 34, 46,124,124,136, 47,169, 60,166,171,174,172, 126, 127,
144, 96, 39, 34, 34, 42, 45, 45,152, 84,185, 62,182,187,190,188, 128, 129, 39, 131, 34, 46, 124, 124, 136, 47, 169, 60, 166, 171, 174,
160,183,162,163,164,161,124,167,168, 99,170, 34, 39,173, 82,175, 172,
176, 63,178,179,180,117,182,255,184,177,186, 34,165,189,181,191, 144, 96, 39, 34, 34, 42, 45, 45, 152, 84, 185, 62, 182, 187, 190, 188,
192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, 160, 183, 162, 163, 164, 161, 124, 167, 168, 99, 170, 34, 39, 173, 82,
208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, 175,
224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, 176, 63, 178, 179, 180, 117, 182, 255, 184, 177, 186, 34, 165, 189,
240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 181, 191,
192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205,
206, 207,
208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221,
222, 223,
224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237,
238, 239,
240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253,
254, 255
}; };
static unsigned char xlatISO88592toWIN1250[] = static unsigned char xlatISO88592toWIN1250[] = {
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, 111,
112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125,
128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, 126, 127,
144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
160,165,162,163,164,188,140,167,168,138,170,141,143,173,142,175, 142, 143,
176,185,178,179,180,190,156,161,184,154,186,157,159,189,158,191, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157,
192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, 158, 159,
208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, 160, 165, 162, 163, 164, 188, 140, 167, 168, 138, 170, 141, 143, 173,
224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, 142, 175,
240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 176, 185, 178, 179, 180, 190, 156, 161, 184, 154, 186, 157, 159, 189,
158, 191,
192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205,
206, 207,
208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221,
222, 223,
224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237,
238, 239,
240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253,
254, 255
}; };
static unsigned char xlatISO88592toCP852[] = static unsigned char xlatISO88592toCP852[] = {
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, 111,
112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125,
242, 32, 34, 32, 34, 46, 43, 35, 32, 47,138, 60,151,141,166,141, 126, 127,
032, 34, 34, 34, 34,254, 45, 45, 32,126,154, 62,152,157,167,171, 242, 32, 34, 32, 34, 46, 43, 35, 32, 47, 138, 60, 151, 141, 166, 141,
255,164,244,157,207,149,151,245,249,230,184,155,141,240,166,189, 032, 34, 34, 34, 34, 254, 45, 45, 32, 126, 154, 62, 152, 157, 167, 171,
248,165,247,136,239,150,152,243,242,231,173,156,171,241,167,190, 255, 164, 244, 157, 207, 149, 151, 245, 249, 230, 184, 155, 141, 240,
232,181,182,198,142,145,143,128,172,144,168,211,183,214,215,210, 166, 189,
209,227,213,224,226,138,153,158,252,222,233,235,154,237,221,225, 248, 165, 247, 136, 239, 150, 152, 243, 242, 231, 173, 156, 171, 241,
234,160,131,199,132,146,134,135,159,130,169,137,216,161,140,212, 167, 190,
208,228,229,162,147,139,148,246,253,133,163,251,129,236,238,250, 232, 181, 182, 198, 142, 145, 143, 128, 172, 144, 168, 211, 183, 214,
215, 210,
209, 227, 213, 224, 226, 138, 153, 158, 252, 222, 233, 235, 154, 237,
221, 225,
234, 160, 131, 199, 132, 146, 134, 135, 159, 130, 169, 137, 216, 161,
140, 212,
208, 228, 229, 162, 147, 139, 148, 246, 253, 133, 163, 251, 129, 236,
238, 250,
}; };
static unsigned char xlatCP852toISO88592[] = static unsigned char xlatCP852toISO88592[] = {
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, 111,
112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125,
199,252,233,226,228,249,230,231,179,235,138,245,238,141,196,198, 126, 127,
201,197,229,244,246,165,181,140,156,214,154,171,187,157,215,232, 199, 252, 233, 226, 228, 249, 230, 231, 179, 235, 138, 245, 238, 141,
225,237,243,250,161,177,142,158,202,234,170,159,200,186,174,175, 196, 198,
176,177,178,179,180,193,194,204,170,185,186,187,188,175,191,191, 201, 197, 229, 244, 246, 165, 181, 140, 156, 214, 154, 171, 187, 157,
192,193,194,195,196,197,195,227,200,201,202,203,204,205,206,164, 215, 232,
240,208,207,203,239,210,205,206,236,217,218,219,220,222,217,223, 225, 237, 243, 250, 161, 177, 142, 158, 202, 234, 170, 159, 200, 186,
211,223,212,209,241,242,169,185,192,218,224,219,253,221,254,180, 174, 175,
173,189,128,183,162,167,247,178,176,168,255,251,216,248,149,160, 176, 177, 178, 179, 180, 193, 194, 204, 170, 185, 186, 187, 188, 175,
191, 191,
192, 193, 194, 195, 196, 197, 195, 227, 200, 201, 202, 203, 204, 205,
206, 164,
240, 208, 207, 203, 239, 210, 205, 206, 236, 217, 218, 219, 220, 222,
217, 223,
211, 223, 212, 209, 241, 242, 169, 185, 192, 218, 224, 219, 253, 221,
254, 180,
173, 189, 128, 183, 162, 167, 247, 178, 176, 168, 255, 251, 216, 248,
149, 160,
}; };
unsigned char xlat_kbd2tty(unsigned char c) unsigned char xlat_kbd2tty(unsigned char c)
{ {
if(cfg.xlat_enablekoiwin) if (cfg.xlat_enablekoiwin)
return win2koi[c]; return win2koi[c];
else if (cfg.xlat_88592w1250 || cfg.xlat_88592cp852) else if (cfg.xlat_88592w1250 || cfg.xlat_88592cp852)
return xlatWIN1250toISO88592[c]; return xlatWIN1250toISO88592[c];
return c; return c;
} }
unsigned char xlat_tty2scr(unsigned char c) unsigned char xlat_tty2scr(unsigned char c)
{ {
if(cfg.xlat_enablekoiwin) if (cfg.xlat_enablekoiwin)
return koi2win[c]; return koi2win[c];
else if (cfg.xlat_88592w1250) else if (cfg.xlat_88592w1250)
return xlatISO88592toWIN1250[c]; return xlatISO88592toWIN1250[c];
else if (cfg.xlat_88592cp852) else if (cfg.xlat_88592cp852)
return xlatISO88592toCP852[c]; return xlatISO88592toCP852[c];
return c; return c;
} }
static unsigned char latkbd2_win[]= static unsigned char latkbd2_win[] = {
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 221, 35, 36, 37, 38, 253, 40, 41, 42, 178, 225, 186, 254, 46,
32, 33,221, 35, 36, 37, 38,253, 40, 41, 42,178,225,186,254, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 198, 230, 193, 179, 222, 44,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57,198,230,193,179,222, 44, 64, 212, 200, 209, 194, 211, 192, 207, 208, 216, 206, 203, 196, 220,
64,212,200,209,194,211,192,207,208,216,206,203,196,220,210,217, 210, 217,
199,201,202,219,197,195,204,214,215,205,223,245,191,250, 94,170, 199, 201, 202, 219, 197, 195, 204, 214, 215, 205, 223, 245, 191, 250,
96,244,232,241,226,243,224,239,240,248,238,235,228,252,242,249, 94, 170,
231,233,234,251,229,227,236,246,247,237,255,213,175,218,126,127, 96, 244, 232, 241, 226, 243, 224, 239, 240, 248, 238, 235, 228, 252,
128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, 242, 249,
144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, 231, 233, 234, 251, 229, 227, 236, 246, 247, 237, 255, 213, 175, 218,
160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, 126, 127,
176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, 142, 143,
208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157,
224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, 158, 159,
240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173,
174, 175,
176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189,
190, 191,
192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205,
206, 207,
208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221,
222, 223,
224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237,
238, 239,
240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253,
254, 255
}; };
unsigned char xlat_latkbd2win(unsigned char c) unsigned char xlat_latkbd2win(unsigned char c)
{ {
if(cfg.xlat_capslockcyr) if (cfg.xlat_capslockcyr)
return latkbd2_win[c]; return latkbd2_win[c];
return c; return c;
} }