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:
parent
93101b5a71
commit
3730ada5ce
12
be_nossh.c
12
be_nossh.c
@ -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
19
int64.c
@ -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
260
ldisc.c
@ -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
209
misc.c
@ -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
2
misc.h
@ -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);
|
||||||
|
215
mscrypto.c
215
mscrypto.c
@ -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;
|
||||||
|
61
network.h
61
network.h
@ -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
49
noise.c
@ -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(×, sizeof(times));
|
random_add_noise(×, sizeof(times));
|
||||||
GetProcessTimes(GetCurrentProcess(), times, times+1, times+2, times+3);
|
GetProcessTimes(GetCurrentProcess(), times, times + 1, times + 2,
|
||||||
|
times + 3);
|
||||||
random_add_noise(×, sizeof(times));
|
random_add_noise(×, 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;
|
||||||
|
|
||||||
|
41
pageantc.c
41
pageantc.c
@ -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
699
plink.c
@ -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
509
psftp.c
@ -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
118
putty.h
@ -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;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
930
puttygen.c
930
puttygen.c
File diff suppressed because it is too large
Load Diff
@ -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
47
raw.c
@ -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
126
rlogin.c
@ -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
531
scp.c
@ -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);
|
||||||
}
|
}
|
||||||
|
513
settings.c
513
settings.c
@ -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
142
sftp.c
@ -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
56
sftp.h
@ -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
195
sizetip.c
@ -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;
|
||||||
|
106
ssh.h
106
ssh.h
@ -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
331
sshaes.c
@ -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));
|
||||||
|
199
sshblowf.c
199
sshblowf.c
@ -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;
|
||||||
|
47
sshcrc.c
47
sshcrc.c
@ -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
533
sshdes.c
@ -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
21
sshdh.c
@ -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
220
sshdss.c
@ -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
146
sshmd5.c
@ -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
1790
sshprime.c
File diff suppressed because it is too large
Load Diff
306
sshpubk.c
306
sshpubk.c
@ -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;
|
||||||
|
|
||||||
|
73
sshrand.c
73
sshrand.c
@ -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
331
sshrsa.c
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
41
sshrsag.c
41
sshrsag.c
@ -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
190
sshsha.c
@ -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 = {
|
||||||
|
@ -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
550
telnet.c
@ -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
2621
terminal.c
File diff suppressed because it is too large
Load Diff
26
tree234.h
26
tree234.h
@ -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 */
|
||||||
|
650
winctrls.c
650
winctrls.c
@ -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);
|
||||||
}
|
}
|
||||||
|
578
winnet.c
578
winnet.c
@ -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;
|
||||||
}
|
}
|
||||||
|
358
winstore.c
358
winstore.c
@ -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.
|
||||||
|
34
winstuff.h
34
winstuff.h
@ -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
158
x11fwd.c
@ -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
328
xlat.c
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user