checking in all the old panacean stuff
This commit is contained in:
16
sFTPlugins/psftp/BE_NONE.C
Normal file
16
sFTPlugins/psftp/BE_NONE.C
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Linking module for PSCP: list the available backends, but
|
||||
* without accompanying function suites. Used only for name
|
||||
* lookups.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "putty.h"
|
||||
|
||||
struct backend_list backends[] = {
|
||||
{PROT_SSH, "ssh", NULL},
|
||||
{PROT_TELNET, "telnet", NULL},
|
||||
{PROT_RLOGIN, "rlogin", NULL},
|
||||
{PROT_RAW, "raw", NULL},
|
||||
{0, NULL}
|
||||
};
|
||||
154
sFTPlugins/psftp/CHARSET/CHARSET.H
Normal file
154
sFTPlugins/psftp/CHARSET/CHARSET.H
Normal file
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* charset.h - header file for general character set conversion
|
||||
* routines.
|
||||
*/
|
||||
|
||||
#ifndef charset_charset_h
|
||||
#define charset_charset_h
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/*
|
||||
* Enumeration that lists all the multibyte or single-byte
|
||||
* character sets known to this library.
|
||||
*/
|
||||
typedef enum {
|
||||
CS_NONE, /* used for reporting errors, etc */
|
||||
CS_ISO8859_1,
|
||||
CS_ISO8859_1_X11, /* X font encoding with VT100 glyphs */
|
||||
CS_ISO8859_2,
|
||||
CS_ISO8859_3,
|
||||
CS_ISO8859_4,
|
||||
CS_ISO8859_5,
|
||||
CS_ISO8859_6,
|
||||
CS_ISO8859_7,
|
||||
CS_ISO8859_8,
|
||||
CS_ISO8859_9,
|
||||
CS_ISO8859_10,
|
||||
CS_ISO8859_11,
|
||||
CS_ISO8859_13,
|
||||
CS_ISO8859_14,
|
||||
CS_ISO8859_15,
|
||||
CS_ISO8859_16,
|
||||
CS_CP437,
|
||||
CS_CP850,
|
||||
CS_CP866,
|
||||
CS_CP1250,
|
||||
CS_CP1251,
|
||||
CS_CP1252,
|
||||
CS_CP1253,
|
||||
CS_CP1254,
|
||||
CS_CP1255,
|
||||
CS_CP1256,
|
||||
CS_CP1257,
|
||||
CS_CP1258,
|
||||
CS_KOI8_R,
|
||||
CS_KOI8_U,
|
||||
CS_MAC_ROMAN,
|
||||
CS_MAC_TURKISH,
|
||||
CS_MAC_CROATIAN,
|
||||
CS_MAC_ICELAND,
|
||||
CS_MAC_ROMANIAN,
|
||||
CS_MAC_GREEK,
|
||||
CS_MAC_CYRILLIC,
|
||||
CS_MAC_THAI,
|
||||
CS_MAC_CENTEURO,
|
||||
CS_MAC_SYMBOL,
|
||||
CS_MAC_DINGBATS,
|
||||
CS_MAC_ROMAN_OLD,
|
||||
CS_MAC_CROATIAN_OLD,
|
||||
CS_MAC_ICELAND_OLD,
|
||||
CS_MAC_ROMANIAN_OLD,
|
||||
CS_MAC_GREEK_OLD,
|
||||
CS_MAC_CYRILLIC_OLD,
|
||||
CS_MAC_UKRAINE,
|
||||
CS_MAC_VT100,
|
||||
CS_MAC_VT100_OLD,
|
||||
CS_VISCII,
|
||||
CS_HP_ROMAN8,
|
||||
CS_DEC_MCS,
|
||||
CS_UTF8
|
||||
} charset_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned long s0;
|
||||
} charset_state;
|
||||
|
||||
/*
|
||||
* Routine to convert a MB/SB character set to Unicode.
|
||||
*
|
||||
* This routine accepts some number of bytes, updates a state
|
||||
* variable, and outputs some number of Unicode characters. There
|
||||
* are no guarantees. You can't even guarantee that at most one
|
||||
* Unicode character will be output per byte you feed in; for
|
||||
* example, suppose you're reading UTF-8, you've seen E1 80, and
|
||||
* then you suddenly see FE. Now you need to output _two_ error
|
||||
* characters - one for the incomplete sequence E1 80, and one for
|
||||
* the completely invalid UTF-8 byte FE.
|
||||
*
|
||||
* Returns the number of wide characters output; will never output
|
||||
* more than the size of the buffer (as specified on input).
|
||||
* Advances the `input' pointer and decrements `inlen', to indicate
|
||||
* how far along the input string it got.
|
||||
*
|
||||
* The sequence of `errlen' wide characters pointed to by `errstr'
|
||||
* will be used to indicate a conversion error. If `errstr' is
|
||||
* NULL, `errlen' will be ignored, and the library will choose
|
||||
* something sensible to do on its own. For Unicode, this will be
|
||||
* U+FFFD (REPLACEMENT CHARACTER).
|
||||
*/
|
||||
|
||||
int charset_to_unicode(char **input, int *inlen, wchar_t *output, int outlen,
|
||||
int charset, charset_state *state,
|
||||
const wchar_t *errstr, int errlen);
|
||||
|
||||
/*
|
||||
* Routine to convert Unicode to an MB/SB character set.
|
||||
*
|
||||
* This routine accepts some number of Unicode characters, updates
|
||||
* a state variable, and outputs some number of bytes.
|
||||
*
|
||||
* Returns the number of bytes characters output; will never output
|
||||
* more than the size of the buffer (as specified on input), and
|
||||
* will never output a partial MB character. Advances the `input'
|
||||
* pointer and decrements `inlen', to indicate how far along the
|
||||
* input string it got.
|
||||
*
|
||||
* The sequence of `errlen' characters pointed to by `errstr' will
|
||||
* be used to indicate a conversion error. If `errstr' is NULL,
|
||||
* `errlen' will be ignored, and the library will choose something
|
||||
* sensible to do on its own (which will vary depending on the
|
||||
* output charset).
|
||||
*/
|
||||
|
||||
int charset_from_unicode(wchar_t **input, int *inlen, char *output, int outlen,
|
||||
int charset, charset_state *state,
|
||||
const char *errstr, int errlen);
|
||||
|
||||
/*
|
||||
* Convert X11 encoding names to and from our charset identifiers.
|
||||
*/
|
||||
const char *charset_to_xenc(int charset);
|
||||
int charset_from_xenc(const char *name);
|
||||
|
||||
/*
|
||||
* Convert MIME encoding names to and from our charset identifiers.
|
||||
*/
|
||||
const char *charset_to_mimeenc(int charset);
|
||||
int charset_from_mimeenc(const char *name);
|
||||
|
||||
/*
|
||||
* Convert our own encoding names to and from our charset
|
||||
* identifiers.
|
||||
*/
|
||||
const char *charset_to_localenc(int charset);
|
||||
int charset_from_localenc(const char *name);
|
||||
int charset_localenc_nth(int n);
|
||||
|
||||
/*
|
||||
* Convert Mac OS script/region/font to our charset identifiers.
|
||||
*/
|
||||
int charset_from_macenc(int script, int region, int sysvers,
|
||||
const char *fontname);
|
||||
|
||||
#endif /* charset_charset_h */
|
||||
442
sFTPlugins/psftp/CMDLINE.C
Normal file
442
sFTPlugins/psftp/CMDLINE.C
Normal file
@@ -0,0 +1,442 @@
|
||||
/*
|
||||
* cmdline.c - command-line parsing shared between many of the
|
||||
* PuTTY applications
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include "putty.h"
|
||||
|
||||
/*
|
||||
* Some command-line parameters need to be saved up until after
|
||||
* we've loaded the saved session which will form the basis of our
|
||||
* eventual running configuration. For this we use the macro
|
||||
* SAVEABLE, which notices if the `need_save' parameter is set and
|
||||
* saves the parameter and value on a list.
|
||||
*
|
||||
* We also assign priorities to saved parameters, just to slightly
|
||||
* ameliorate silly ordering problems. For example, if you specify
|
||||
* a saved session to load, it will be loaded _before_ all your
|
||||
* local modifications such as -L are evaluated; and if you specify
|
||||
* a protocol and a port, the protocol is set up first so that the
|
||||
* port can override its choice of port number.
|
||||
*
|
||||
* (In fact -load is not saved at all, since in at least Plink the
|
||||
* processing of further command-line options depends on whether or
|
||||
* not the loaded session contained a hostname. So it must be
|
||||
* executed immediately.)
|
||||
*/
|
||||
|
||||
#define NPRIORITIES 2
|
||||
|
||||
struct cmdline_saved_param {
|
||||
char *p, *value;
|
||||
};
|
||||
struct cmdline_saved_param_set {
|
||||
struct cmdline_saved_param *params;
|
||||
int nsaved, savesize;
|
||||
};
|
||||
|
||||
/*
|
||||
* C guarantees this structure will be initialised to all zero at
|
||||
* program start, which is exactly what we want.
|
||||
*/
|
||||
static struct cmdline_saved_param_set saves[NPRIORITIES];
|
||||
|
||||
static void cmdline_save_param(char *p, char *value, int pri)
|
||||
{
|
||||
if (saves[pri].nsaved >= saves[pri].savesize) {
|
||||
saves[pri].savesize = saves[pri].nsaved + 32;
|
||||
saves[pri].params = sresize(saves[pri].params, saves[pri].savesize,
|
||||
struct cmdline_saved_param);
|
||||
}
|
||||
saves[pri].params[saves[pri].nsaved].p = p;
|
||||
saves[pri].params[saves[pri].nsaved].value = value;
|
||||
saves[pri].nsaved++;
|
||||
}
|
||||
|
||||
void cmdline_cleanup(void)
|
||||
{
|
||||
int pri;
|
||||
|
||||
for (pri = 0; pri < NPRIORITIES; pri++)
|
||||
sfree(saves[pri].params);
|
||||
}
|
||||
|
||||
#define SAVEABLE(pri) do { \
|
||||
if (need_save) { cmdline_save_param(p, value, pri); return ret; } \
|
||||
} while (0)
|
||||
|
||||
static char *cmdline_password = NULL;
|
||||
|
||||
/*
|
||||
* Similar interface to get_userpass_input(), except that here a -1
|
||||
* return means that we aren't capable of processing the prompt and
|
||||
* someone else should do it.
|
||||
*/
|
||||
int cmdline_get_passwd_input(prompts_t *p, unsigned char *in, int inlen) {
|
||||
|
||||
static int tried_once = 0;
|
||||
|
||||
/*
|
||||
* We only handle prompts which don't echo (which we assume to be
|
||||
* passwords), and (currently) we only cope with a password prompt
|
||||
* that comes in a prompt-set on its own.
|
||||
*/
|
||||
if (!cmdline_password || in || p->n_prompts != 1 || p->prompts[0]->echo) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we've tried once, return utter failure (no more passwords left
|
||||
* to try).
|
||||
*/
|
||||
if (tried_once)
|
||||
return 0;
|
||||
|
||||
strncpy(p->prompts[0]->result, cmdline_password,
|
||||
p->prompts[0]->result_len);
|
||||
p->prompts[0]->result[p->prompts[0]->result_len-1] = '\0';
|
||||
memset(cmdline_password, 0, strlen(cmdline_password));
|
||||
tried_once = 1;
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Here we have a flags word which describes the capabilities of
|
||||
* the particular tool on whose behalf we're running. We will
|
||||
* refuse certain command-line options if a particular tool
|
||||
* inherently can't do anything sensible. For example, the file
|
||||
* transfer tools (psftp, pscp) can't do a great deal with protocol
|
||||
* selections (ever tried running scp over telnet?) or with port
|
||||
* forwarding (even if it wasn't a hideously bad idea, they don't
|
||||
* have the select() infrastructure to make them work).
|
||||
*/
|
||||
int cmdline_tooltype = 0;
|
||||
|
||||
static int cmdline_check_unavailable(int flag, char *p)
|
||||
{
|
||||
if (cmdline_tooltype & flag) {
|
||||
cmdline_error("option \"%s\" not available in this tool", p);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define UNAVAILABLE_IN(flag) do { \
|
||||
if (cmdline_check_unavailable(flag, p)) return ret; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Process a standard command-line parameter. `p' is the parameter
|
||||
* in question; `value' is the subsequent element of argv, which
|
||||
* may or may not be required as an operand to the parameter.
|
||||
* If `need_save' is 1, arguments which need to be saved as
|
||||
* described at this top of this file are, for later execution;
|
||||
* if 0, they are processed normally. (-1 is a special value used
|
||||
* by pterm to count arguments for a preliminary pass through the
|
||||
* argument list; it causes immediate return with an appropriate
|
||||
* value with no action taken.)
|
||||
* Return value is 2 if both arguments were used; 1 if only p was
|
||||
* used; 0 if the parameter wasn't one we recognised; -2 if it
|
||||
* should have been 2 but value was NULL.
|
||||
*/
|
||||
|
||||
#define RETURN(x) do { \
|
||||
if ((x) == 2 && !value) return -2; \
|
||||
ret = x; \
|
||||
if (need_save < 0) return x; \
|
||||
} while (0)
|
||||
|
||||
int cmdline_process_param(char *p, char *value, int need_save, Config *cfg)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (!strcmp(p, "-load")) {
|
||||
RETURN(2);
|
||||
/* This parameter must be processed immediately rather than being
|
||||
* saved. */
|
||||
do_defaults(value, cfg);
|
||||
loaded_session = TRUE;
|
||||
return 2;
|
||||
}
|
||||
if (!strcmp(p, "-ssh")) {
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
default_protocol = cfg->protocol = PROT_SSH;
|
||||
default_port = cfg->port = 22;
|
||||
return 1;
|
||||
}
|
||||
if (!strcmp(p, "-telnet")) {
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
default_protocol = cfg->protocol = PROT_TELNET;
|
||||
default_port = cfg->port = 23;
|
||||
return 1;
|
||||
}
|
||||
if (!strcmp(p, "-rlogin")) {
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
default_protocol = cfg->protocol = PROT_RLOGIN;
|
||||
default_port = cfg->port = 513;
|
||||
return 1;
|
||||
}
|
||||
if (!strcmp(p, "-raw")) {
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
default_protocol = cfg->protocol = PROT_RAW;
|
||||
}
|
||||
if (!strcmp(p, "-v")) {
|
||||
RETURN(1);
|
||||
flags |= FLAG_VERBOSE;
|
||||
}
|
||||
if (!strcmp(p, "-l")) {
|
||||
RETURN(2);
|
||||
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
strncpy(cfg->username, value, sizeof(cfg->username));
|
||||
cfg->username[sizeof(cfg->username) - 1] = '\0';
|
||||
}
|
||||
if ((!strcmp(p, "-L") || !strcmp(p, "-R") || !strcmp(p, "-D"))) {
|
||||
char *fwd, *ptr, *q, *qq;
|
||||
int dynamic, i=0;
|
||||
RETURN(2);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
dynamic = !strcmp(p, "-D");
|
||||
fwd = value;
|
||||
ptr = cfg->portfwd;
|
||||
/* if existing forwards, find end of list */
|
||||
while (*ptr) {
|
||||
while (*ptr)
|
||||
ptr++;
|
||||
ptr++;
|
||||
}
|
||||
i = ptr - cfg->portfwd;
|
||||
ptr[0] = p[1]; /* insert a 'L', 'R' or 'D' at the start */
|
||||
ptr++;
|
||||
if (1 + strlen(fwd) + 2 > sizeof(cfg->portfwd) - i) {
|
||||
cmdline_error("out of space for port forwardings");
|
||||
return ret;
|
||||
}
|
||||
strncpy(ptr, fwd, sizeof(cfg->portfwd) - i - 2);
|
||||
if (!dynamic) {
|
||||
/*
|
||||
* We expect _at least_ two colons in this string. The
|
||||
* possible formats are `sourceport:desthost:destport',
|
||||
* or `sourceip:sourceport:desthost:destport' if you're
|
||||
* specifying a particular loopback address. We need to
|
||||
* replace the one between source and dest with a \t;
|
||||
* this means we must find the second-to-last colon in
|
||||
* the string.
|
||||
*/
|
||||
q = qq = strchr(ptr, ':');
|
||||
while (qq) {
|
||||
char *qqq = strchr(qq+1, ':');
|
||||
if (qqq)
|
||||
q = qq;
|
||||
qq = qqq;
|
||||
}
|
||||
if (q) *q = '\t'; /* replace second-last colon with \t */
|
||||
}
|
||||
cfg->portfwd[sizeof(cfg->portfwd) - 1] = '\0';
|
||||
cfg->portfwd[sizeof(cfg->portfwd) - 2] = '\0';
|
||||
ptr[strlen(ptr)+1] = '\000'; /* append 2nd '\000' */
|
||||
}
|
||||
if ((!strcmp(p, "-nc"))) {
|
||||
char *host, *portp;
|
||||
|
||||
RETURN(2);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
|
||||
host = portp = value;
|
||||
while (*portp && *portp != ':')
|
||||
portp++;
|
||||
if (*portp) {
|
||||
unsigned len = portp - host;
|
||||
if (len >= sizeof(cfg->ssh_nc_host))
|
||||
len = sizeof(cfg->ssh_nc_host) - 1;
|
||||
strncpy(cfg->ssh_nc_host, value, len);
|
||||
cfg->ssh_nc_host[sizeof(cfg->ssh_nc_host) - 1] = '\0';
|
||||
cfg->ssh_nc_port = atoi(portp+1);
|
||||
} else {
|
||||
cmdline_error("-nc expects argument of form 'host:port'");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
if (!strcmp(p, "-m")) {
|
||||
char *filename, *command;
|
||||
int cmdlen, cmdsize;
|
||||
FILE *fp;
|
||||
int c, d;
|
||||
|
||||
RETURN(2);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
|
||||
filename = value;
|
||||
|
||||
cmdlen = cmdsize = 0;
|
||||
command = NULL;
|
||||
fp = fopen(filename, "r");
|
||||
if (!fp) {
|
||||
cmdline_error("unable to open command "
|
||||
"file \"%s\"", filename);
|
||||
return ret;
|
||||
}
|
||||
do {
|
||||
c = fgetc(fp);
|
||||
d = c;
|
||||
if (c == EOF)
|
||||
d = 0;
|
||||
if (cmdlen >= cmdsize) {
|
||||
cmdsize = cmdlen + 512;
|
||||
command = sresize(command, cmdsize, char);
|
||||
}
|
||||
command[cmdlen++] = d;
|
||||
} while (c != EOF);
|
||||
cfg->remote_cmd_ptr = command;
|
||||
cfg->remote_cmd_ptr2 = NULL;
|
||||
cfg->nopty = TRUE; /* command => no terminal */
|
||||
}
|
||||
if (!strcmp(p, "-P")) {
|
||||
RETURN(2);
|
||||
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(1); /* lower priority than -ssh,-telnet */
|
||||
cfg->port = atoi(value);
|
||||
}
|
||||
if (!strcmp(p, "-pw")) {
|
||||
RETURN(2);
|
||||
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(1);
|
||||
/* We delay evaluating this until after the protocol is decided,
|
||||
* so that we can warn if it's of no use with the selected protocol */
|
||||
if (cfg->protocol != PROT_SSH)
|
||||
cmdline_error("the -pw option can only be used with the "
|
||||
"SSH protocol");
|
||||
else {
|
||||
cmdline_password = dupstr(value);
|
||||
/* Assuming that `value' is directly from argv, make a good faith
|
||||
* attempt to trample it, to stop it showing up in `ps' output
|
||||
* on Unix-like systems. Not guaranteed, of course. */
|
||||
memset(value, 0, strlen(value));
|
||||
}
|
||||
}
|
||||
|
||||
if (!strcmp(p, "-agent") || !strcmp(p, "-pagent") ||
|
||||
!strcmp(p, "-pageant")) {
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
cfg->tryagent = TRUE;
|
||||
}
|
||||
if (!strcmp(p, "-noagent") || !strcmp(p, "-nopagent") ||
|
||||
!strcmp(p, "-nopageant")) {
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
cfg->tryagent = FALSE;
|
||||
}
|
||||
|
||||
if (!strcmp(p, "-A")) {
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
cfg->agentfwd = 1;
|
||||
}
|
||||
if (!strcmp(p, "-a")) {
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
cfg->agentfwd = 0;
|
||||
}
|
||||
|
||||
if (!strcmp(p, "-X")) {
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
cfg->x11_forward = 1;
|
||||
}
|
||||
if (!strcmp(p, "-x")) {
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
cfg->x11_forward = 0;
|
||||
}
|
||||
|
||||
if (!strcmp(p, "-t")) {
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(1); /* lower priority than -m */
|
||||
cfg->nopty = 0;
|
||||
}
|
||||
if (!strcmp(p, "-T")) {
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(1);
|
||||
cfg->nopty = 1;
|
||||
}
|
||||
|
||||
if (!strcmp(p, "-N")) {
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_FILETRANSFER | TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
cfg->ssh_no_shell = 1;
|
||||
}
|
||||
|
||||
if (!strcmp(p, "-C")) {
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
cfg->compression = 1;
|
||||
}
|
||||
|
||||
if (!strcmp(p, "-1")) {
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
cfg->sshprot = 0; /* ssh protocol 1 only */
|
||||
}
|
||||
if (!strcmp(p, "-2")) {
|
||||
RETURN(1);
|
||||
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
cfg->sshprot = 3; /* ssh protocol 2 only */
|
||||
}
|
||||
|
||||
if (!strcmp(p, "-i")) {
|
||||
RETURN(2);
|
||||
UNAVAILABLE_IN(TOOLTYPE_NONNETWORK);
|
||||
SAVEABLE(0);
|
||||
cfg->keyfile = filename_from_str(value);
|
||||
}
|
||||
|
||||
if (!strcmp(p, "-4") || !strcmp(p, "-ipv4")) {
|
||||
RETURN(1);
|
||||
SAVEABLE(1);
|
||||
cfg->addressfamily = ADDRTYPE_IPV4;
|
||||
}
|
||||
if (!strcmp(p, "-6") || !strcmp(p, "-ipv6")) {
|
||||
RETURN(1);
|
||||
SAVEABLE(1);
|
||||
cfg->addressfamily = ADDRTYPE_IPV6;
|
||||
}
|
||||
|
||||
return ret; /* unrecognised */
|
||||
}
|
||||
|
||||
void cmdline_run_saved(Config *cfg)
|
||||
{
|
||||
int pri, i;
|
||||
for (pri = 0; pri < NPRIORITIES; pri++)
|
||||
for (i = 0; i < saves[pri].nsaved; i++)
|
||||
cmdline_process_param(saves[pri].params[i].p,
|
||||
saves[pri].params[i].value, 0, cfg);
|
||||
}
|
||||
190
sFTPlugins/psftp/CPROXY.C
Normal file
190
sFTPlugins/psftp/CPROXY.C
Normal file
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Routines to do cryptographic interaction with proxies in PuTTY.
|
||||
* This is in a separate module from proxy.c, so that it can be
|
||||
* conveniently removed in PuTTYtel by replacing this module with
|
||||
* the stub version nocproxy.c.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
#define DEFINE_PLUG_METHOD_MACROS
|
||||
#include "putty.h"
|
||||
#include "ssh.h" /* For MD5 support */
|
||||
#include "network.h"
|
||||
#include "proxy.h"
|
||||
|
||||
static void hmacmd5_chap(const unsigned char *challenge, int challen,
|
||||
const char *passwd, unsigned char *response)
|
||||
{
|
||||
void *hmacmd5_ctx;
|
||||
int pwlen;
|
||||
|
||||
hmacmd5_ctx = hmacmd5_make_context();
|
||||
|
||||
pwlen = strlen(passwd);
|
||||
if (pwlen>64) {
|
||||
unsigned char md5buf[16];
|
||||
MD5Simple(passwd, pwlen, md5buf);
|
||||
hmacmd5_key(hmacmd5_ctx, md5buf, 16);
|
||||
} else {
|
||||
hmacmd5_key(hmacmd5_ctx, passwd, pwlen);
|
||||
}
|
||||
|
||||
hmacmd5_do_hmac(hmacmd5_ctx, challenge, challen, response);
|
||||
hmacmd5_free_context(hmacmd5_ctx);
|
||||
}
|
||||
|
||||
void proxy_socks5_offerencryptedauth(char *command, int *len)
|
||||
{
|
||||
command[*len] = 0x03; /* CHAP */
|
||||
(*len)++;
|
||||
}
|
||||
|
||||
int proxy_socks5_handlechap (Proxy_Socket p)
|
||||
{
|
||||
|
||||
/* CHAP authentication reply format:
|
||||
* version number (1 bytes) = 1
|
||||
* number of commands (1 byte)
|
||||
*
|
||||
* For each command:
|
||||
* command identifier (1 byte)
|
||||
* data length (1 byte)
|
||||
*/
|
||||
unsigned char data[260];
|
||||
unsigned char outbuf[20];
|
||||
|
||||
while(p->chap_num_attributes == 0 ||
|
||||
p->chap_num_attributes_processed < p->chap_num_attributes) {
|
||||
if (p->chap_num_attributes == 0 ||
|
||||
p->chap_current_attribute == -1) {
|
||||
/* CHAP normally reads in two bytes, either at the
|
||||
* beginning or for each attribute/value pair. But if
|
||||
* we're waiting for the value's data, we might not want
|
||||
* to read 2 bytes.
|
||||
*/
|
||||
|
||||
if (bufchain_size(&p->pending_input_data) < 2)
|
||||
return 1; /* not got anything yet */
|
||||
|
||||
/* get the response */
|
||||
bufchain_fetch(&p->pending_input_data, data, 2);
|
||||
bufchain_consume(&p->pending_input_data, 2);
|
||||
}
|
||||
|
||||
if (p->chap_num_attributes == 0) {
|
||||
/* If there are no attributes, this is our first msg
|
||||
* with the server, where we negotiate version and
|
||||
* number of attributes
|
||||
*/
|
||||
if (data[0] != 0x01) {
|
||||
plug_closing(p->plug, "Proxy error: SOCKS proxy wants"
|
||||
" a different CHAP version",
|
||||
PROXY_ERROR_GENERAL, 0);
|
||||
return 1;
|
||||
}
|
||||
if (data[1] == 0x00) {
|
||||
plug_closing(p->plug, "Proxy error: SOCKS proxy won't"
|
||||
" negotiate CHAP with us",
|
||||
PROXY_ERROR_GENERAL, 0);
|
||||
return 1;
|
||||
}
|
||||
p->chap_num_attributes = data[1];
|
||||
} else {
|
||||
if (p->chap_current_attribute == -1) {
|
||||
/* We have to read in each attribute/value pair -
|
||||
* those we don't understand can be ignored, but
|
||||
* there are a few we'll need to handle.
|
||||
*/
|
||||
p->chap_current_attribute = data[0];
|
||||
p->chap_current_datalen = data[1];
|
||||
}
|
||||
if (bufchain_size(&p->pending_input_data) <
|
||||
p->chap_current_datalen)
|
||||
return 1; /* not got everything yet */
|
||||
|
||||
/* get the response */
|
||||
bufchain_fetch(&p->pending_input_data, data,
|
||||
p->chap_current_datalen);
|
||||
|
||||
bufchain_consume(&p->pending_input_data,
|
||||
p->chap_current_datalen);
|
||||
|
||||
switch (p->chap_current_attribute) {
|
||||
case 0x00:
|
||||
/* Successful authentication */
|
||||
if (data[0] == 0x00)
|
||||
p->state = 2;
|
||||
else {
|
||||
plug_closing(p->plug, "Proxy error: SOCKS proxy"
|
||||
" refused CHAP authentication",
|
||||
PROXY_ERROR_GENERAL, 0);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 0x03:
|
||||
outbuf[0] = 0x01; /* Version */
|
||||
outbuf[1] = 0x01; /* One attribute */
|
||||
outbuf[2] = 0x04; /* Response */
|
||||
outbuf[3] = 0x10; /* Length */
|
||||
hmacmd5_chap(data, p->chap_current_datalen,
|
||||
p->cfg.proxy_password, &outbuf[4]);
|
||||
sk_write(p->sub_socket, (char *)outbuf, 20);
|
||||
break;
|
||||
case 0x11:
|
||||
/* Chose a protocol */
|
||||
if (data[0] != 0x85) {
|
||||
plug_closing(p->plug, "Proxy error: Server chose "
|
||||
"CHAP of other than HMAC-MD5 but we "
|
||||
"didn't offer it!",
|
||||
PROXY_ERROR_GENERAL, 0);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
p->chap_current_attribute = -1;
|
||||
p->chap_num_attributes_processed++;
|
||||
}
|
||||
if (p->state == 8 &&
|
||||
p->chap_num_attributes_processed >= p->chap_num_attributes) {
|
||||
p->chap_num_attributes = 0;
|
||||
p->chap_num_attributes_processed = 0;
|
||||
p->chap_current_datalen = 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int proxy_socks5_selectchap(Proxy_Socket p)
|
||||
{
|
||||
if (p->cfg.proxy_username[0] || p->cfg.proxy_password[0]) {
|
||||
char chapbuf[514];
|
||||
int ulen;
|
||||
chapbuf[0] = '\x01'; /* Version */
|
||||
chapbuf[1] = '\x02'; /* Number of attributes sent */
|
||||
chapbuf[2] = '\x11'; /* First attribute - algorithms list */
|
||||
chapbuf[3] = '\x01'; /* Only one CHAP algorithm */
|
||||
chapbuf[4] = '\x85'; /* ...and it's HMAC-MD5, the core one */
|
||||
chapbuf[5] = '\x02'; /* Second attribute - username */
|
||||
|
||||
ulen = strlen(p->cfg.proxy_username);
|
||||
if (ulen > 255) ulen = 255; if (ulen < 1) ulen = 1;
|
||||
|
||||
chapbuf[6] = ulen;
|
||||
memcpy(chapbuf+7, p->cfg.proxy_username, ulen);
|
||||
|
||||
sk_write(p->sub_socket, chapbuf, ulen + 7);
|
||||
p->chap_num_attributes = 0;
|
||||
p->chap_num_attributes_processed = 0;
|
||||
p->chap_current_attribute = -1;
|
||||
p->chap_current_datalen = 0;
|
||||
|
||||
p->state = 8;
|
||||
} else
|
||||
plug_closing(p->plug, "Proxy error: Server chose "
|
||||
"CHAP authentication but we didn't offer it!",
|
||||
PROXY_ERROR_GENERAL, 0);
|
||||
return 1;
|
||||
}
|
||||
130
sFTPlugins/psftp/INT64.C
Normal file
130
sFTPlugins/psftp/INT64.C
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Handling of the int64 and uint64 types. Done in 32-bit integers,
|
||||
* for (pre-C99) portability. Hopefully once C99 becomes widespread
|
||||
* we can kiss this lot goodbye...
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "int64.h"
|
||||
|
||||
uint64 uint64_div10(uint64 x, int *remainder)
|
||||
{
|
||||
uint64 y;
|
||||
int rem, r2;
|
||||
y.hi = x.hi / 10;
|
||||
y.lo = x.lo / 10;
|
||||
rem = x.lo % 10;
|
||||
/*
|
||||
* Now we have to add in the remainder left over from x.hi.
|
||||
*/
|
||||
r2 = x.hi % 10;
|
||||
y.lo += r2 * 2 * (0x80000000 / 10);
|
||||
rem += r2 * 2 * (0x80000000 % 10);
|
||||
y.lo += rem / 10;
|
||||
rem %= 10;
|
||||
|
||||
if (remainder)
|
||||
*remainder = rem;
|
||||
return y;
|
||||
}
|
||||
|
||||
void uint64_decimal(uint64 x, char *buffer)
|
||||
{
|
||||
char buf[20];
|
||||
int start = 20;
|
||||
int d;
|
||||
|
||||
do {
|
||||
x = uint64_div10(x, &d);
|
||||
assert(start > 0);
|
||||
buf[--start] = d + '0';
|
||||
} while (x.hi || x.lo);
|
||||
|
||||
memcpy(buffer, buf + start, sizeof(buf) - start);
|
||||
buffer[sizeof(buf) - start] = '\0';
|
||||
}
|
||||
|
||||
uint64 uint64_make(unsigned long hi, unsigned long lo)
|
||||
{
|
||||
uint64 y;
|
||||
y.hi = hi;
|
||||
y.lo = lo;
|
||||
return y;
|
||||
}
|
||||
|
||||
uint64 uint64_add(uint64 x, uint64 y)
|
||||
{
|
||||
x.lo += y.lo;
|
||||
x.hi += y.hi + (x.lo < y.lo ? 1 : 0);
|
||||
return x;
|
||||
}
|
||||
|
||||
uint64 uint64_add32(uint64 x, unsigned long y)
|
||||
{
|
||||
uint64 yy;
|
||||
yy.hi = 0;
|
||||
yy.lo = y;
|
||||
return uint64_add(x, yy);
|
||||
}
|
||||
|
||||
int uint64_compare(uint64 x, uint64 y)
|
||||
{
|
||||
if (x.hi != y.hi)
|
||||
return x.hi < y.hi ? -1 : +1;
|
||||
if (x.lo != y.lo)
|
||||
return x.lo < y.lo ? -1 : +1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64 uint64_subtract(uint64 x, uint64 y)
|
||||
{
|
||||
x.lo -= y.lo;
|
||||
x.hi -= y.hi + (x.lo > ~y.lo ? 1 : 0);
|
||||
return x;
|
||||
}
|
||||
|
||||
double uint64_to_double(uint64 x)
|
||||
{
|
||||
return (4294967296.0 * x.hi) + (double)x.lo;
|
||||
}
|
||||
|
||||
uint64 uint64_shift_right(uint64 x, int shift)
|
||||
{
|
||||
if (shift < 32) {
|
||||
x.lo >>= shift;
|
||||
x.lo |= (x.hi << (32-shift));
|
||||
x.hi >>= shift;
|
||||
} else {
|
||||
x.lo = x.hi >> (shift-32);
|
||||
x.hi = 0;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
uint64 uint64_shift_left(uint64 x, int shift)
|
||||
{
|
||||
if (shift < 32) {
|
||||
x.hi <<= shift;
|
||||
x.hi |= (x.lo >> (32-shift));
|
||||
x.lo <<= shift;
|
||||
} else {
|
||||
x.hi = x.lo << (shift-32);
|
||||
x.lo = 0;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
uint64 uint64_from_decimal(char *str)
|
||||
{
|
||||
uint64 ret;
|
||||
ret.hi = ret.lo = 0;
|
||||
while (*str >= '0' && *str <= '9') {
|
||||
ret = uint64_add(uint64_shift_left(ret, 3),
|
||||
uint64_shift_left(ret, 1));
|
||||
ret = uint64_add32(ret, *str - '0');
|
||||
str++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
24
sFTPlugins/psftp/INT64.H
Normal file
24
sFTPlugins/psftp/INT64.H
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Header for int64.c.
|
||||
*/
|
||||
|
||||
#ifndef PUTTY_INT64_H
|
||||
#define PUTTY_INT64_H
|
||||
|
||||
typedef struct {
|
||||
unsigned long hi, lo;
|
||||
} uint64;
|
||||
|
||||
uint64 uint64_div10(uint64 x, int *remainder);
|
||||
void uint64_decimal(uint64 x, char *buffer);
|
||||
uint64 uint64_make(unsigned long hi, unsigned long lo);
|
||||
uint64 uint64_add(uint64 x, uint64 y);
|
||||
uint64 uint64_add32(uint64 x, unsigned long y);
|
||||
int uint64_compare(uint64 x, uint64 y);
|
||||
uint64 uint64_subtract(uint64 x, uint64 y);
|
||||
double uint64_to_double(uint64 x);
|
||||
uint64 uint64_shift_right(uint64 x, int shift);
|
||||
uint64 uint64_shift_left(uint64 x, int shift);
|
||||
uint64 uint64_from_decimal(char *str);
|
||||
|
||||
#endif
|
||||
415
sFTPlugins/psftp/LOGGING.C
Normal file
415
sFTPlugins/psftp/LOGGING.C
Normal file
@@ -0,0 +1,415 @@
|
||||
/*
|
||||
* Session logging.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "putty.h"
|
||||
|
||||
/* log session to file stuff ... */
|
||||
struct LogContext {
|
||||
FILE *lgfp;
|
||||
enum { L_CLOSED, L_OPENING, L_OPEN, L_ERROR } state;
|
||||
bufchain queue;
|
||||
Filename currlogfilename;
|
||||
void *frontend;
|
||||
Config cfg;
|
||||
};
|
||||
|
||||
static void xlatlognam(Filename *d, Filename s, char *hostname, struct tm *tm);
|
||||
|
||||
/*
|
||||
* Internal wrapper function which must be called for _all_ output
|
||||
* to the log file. It takes care of opening the log file if it
|
||||
* isn't open, buffering data if it's in the process of being
|
||||
* opened asynchronously, etc.
|
||||
*/
|
||||
static void logwrite(struct LogContext *ctx, void *data, int len)
|
||||
{
|
||||
/*
|
||||
* In state L_CLOSED, we call logfopen, which will set the state
|
||||
* to one of L_OPENING, L_OPEN or L_ERROR. Hence we process all of
|
||||
* those three _after_ processing L_CLOSED.
|
||||
*/
|
||||
if (ctx->state == L_CLOSED)
|
||||
logfopen(ctx);
|
||||
|
||||
if (ctx->state == L_OPENING) {
|
||||
bufchain_add(&ctx->queue, data, len);
|
||||
} else if (ctx->state == L_OPEN) {
|
||||
assert(ctx->lgfp);
|
||||
fwrite(data, 1, len, ctx->lgfp);
|
||||
} /* else L_ERROR, so ignore the write */
|
||||
}
|
||||
|
||||
/*
|
||||
* Convenience wrapper on logwrite() which printf-formats the
|
||||
* string.
|
||||
*/
|
||||
static void logprintf(struct LogContext *ctx, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char *data;
|
||||
|
||||
va_start(ap, fmt);
|
||||
data = dupvprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
logwrite(ctx, data, strlen(data));
|
||||
sfree(data);
|
||||
}
|
||||
|
||||
/*
|
||||
* Flush any open log file.
|
||||
*/
|
||||
void logflush(void *handle) {
|
||||
struct LogContext *ctx = (struct LogContext *)handle;
|
||||
if (ctx->cfg.logtype > 0)
|
||||
if (ctx->state == L_OPEN)
|
||||
fflush(ctx->lgfp);
|
||||
}
|
||||
|
||||
static void logfopen_callback(void *handle, int mode)
|
||||
{
|
||||
struct LogContext *ctx = (struct LogContext *)handle;
|
||||
char buf[256], *event;
|
||||
struct tm tm;
|
||||
const char *fmode;
|
||||
|
||||
if (mode == 0) {
|
||||
ctx->state = L_ERROR; /* disable logging */
|
||||
} else {
|
||||
fmode = (mode == 1 ? "ab" : "wb");
|
||||
ctx->lgfp = f_open(ctx->currlogfilename, fmode, TRUE);
|
||||
if (ctx->lgfp)
|
||||
ctx->state = L_OPEN;
|
||||
else
|
||||
ctx->state = L_ERROR;
|
||||
}
|
||||
|
||||
if (ctx->state == L_OPEN) {
|
||||
/* Write header line into log file. */
|
||||
tm = ltime();
|
||||
strftime(buf, 24, "%Y.%m.%d %H:%M:%S", &tm);
|
||||
logprintf(ctx, "=~=~=~=~=~=~=~=~=~=~=~= PuTTY log %s"
|
||||
" =~=~=~=~=~=~=~=~=~=~=~=\r\n", buf);
|
||||
}
|
||||
|
||||
event = dupprintf("%s session log (%s mode) to file: %s",
|
||||
(mode == 0 ? "Disabled writing" :
|
||||
mode == 1 ? "Appending" : "Writing new"),
|
||||
(ctx->cfg.logtype == LGTYP_ASCII ? "ASCII" :
|
||||
ctx->cfg.logtype == LGTYP_DEBUG ? "raw" :
|
||||
ctx->cfg.logtype == LGTYP_PACKETS ? "SSH packets" :
|
||||
ctx->cfg.logtype == LGTYP_SSHRAW ? "SSH raw data" :
|
||||
"unknown"),
|
||||
filename_to_str(&ctx->currlogfilename));
|
||||
logevent(ctx->frontend, event);
|
||||
sfree(event);
|
||||
|
||||
/*
|
||||
* Having either succeeded or failed in opening the log file,
|
||||
* we should write any queued data out.
|
||||
*/
|
||||
assert(ctx->state != L_OPENING); /* make _sure_ it won't be requeued */
|
||||
while (bufchain_size(&ctx->queue)) {
|
||||
void *data;
|
||||
int len;
|
||||
bufchain_prefix(&ctx->queue, &data, &len);
|
||||
logwrite(ctx, data, len);
|
||||
bufchain_consume(&ctx->queue, len);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Open the log file. Takes care of detecting an already-existing
|
||||
* file and asking the user whether they want to append, overwrite
|
||||
* or cancel logging.
|
||||
*/
|
||||
void logfopen(void *handle)
|
||||
{
|
||||
struct LogContext *ctx = (struct LogContext *)handle;
|
||||
struct tm tm;
|
||||
int mode;
|
||||
|
||||
/* Prevent repeat calls */
|
||||
if (ctx->state != L_CLOSED)
|
||||
return;
|
||||
|
||||
if (!ctx->cfg.logtype)
|
||||
return;
|
||||
|
||||
tm = ltime();
|
||||
|
||||
/* substitute special codes in file name */
|
||||
xlatlognam(&ctx->currlogfilename, ctx->cfg.logfilename,ctx->cfg.host, &tm);
|
||||
|
||||
ctx->lgfp = f_open(ctx->currlogfilename, "r", FALSE); /* file already present? */
|
||||
if (ctx->lgfp) {
|
||||
fclose(ctx->lgfp);
|
||||
if (ctx->cfg.logxfovr != LGXF_ASK) {
|
||||
mode = ((ctx->cfg.logxfovr == LGXF_OVR) ? 2 : 1);
|
||||
} else
|
||||
mode = askappend(ctx->frontend, ctx->currlogfilename,
|
||||
logfopen_callback, ctx);
|
||||
} else
|
||||
mode = 2; /* create == overwrite */
|
||||
|
||||
if (mode < 0)
|
||||
ctx->state = L_OPENING;
|
||||
else
|
||||
logfopen_callback(ctx, mode); /* open the file */
|
||||
}
|
||||
|
||||
void logfclose(void *handle)
|
||||
{
|
||||
struct LogContext *ctx = (struct LogContext *)handle;
|
||||
if (ctx->lgfp) {
|
||||
fclose(ctx->lgfp);
|
||||
ctx->lgfp = NULL;
|
||||
}
|
||||
ctx->state = L_CLOSED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Log session traffic.
|
||||
*/
|
||||
void logtraffic(void *handle, unsigned char c, int logmode)
|
||||
{
|
||||
struct LogContext *ctx = (struct LogContext *)handle;
|
||||
if (ctx->cfg.logtype > 0) {
|
||||
if (ctx->cfg.logtype == logmode)
|
||||
logwrite(ctx, &c, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Log an Event Log entry. Used in SSH packet logging mode; this is
|
||||
* also as convenient a place as any to put the output of Event Log
|
||||
* entries to stderr when a command-line tool is in verbose mode.
|
||||
* (In particular, this is a better place to put it than in the
|
||||
* front ends, because it only has to be done once for all
|
||||
* platforms. Platforms which don't have a meaningful stderr can
|
||||
* just avoid defining FLAG_STDERR.
|
||||
*/
|
||||
void log_eventlog(void *handle, const char *event)
|
||||
{
|
||||
struct LogContext *ctx = (struct LogContext *)handle;
|
||||
if ((flags & FLAG_STDERR) && (flags & FLAG_VERBOSE)) {
|
||||
fprintf(stderr, "%s\n", event);
|
||||
fflush(stderr);
|
||||
}
|
||||
/* If we don't have a context yet (eg winnet.c init) then skip entirely */
|
||||
if (!ctx)
|
||||
return;
|
||||
if (ctx->cfg.logtype != LGTYP_PACKETS &&
|
||||
ctx->cfg.logtype != LGTYP_SSHRAW)
|
||||
return;
|
||||
logprintf(ctx, "Event Log: %s\r\n", event);
|
||||
logflush(ctx);
|
||||
}
|
||||
|
||||
/*
|
||||
* Log an SSH packet.
|
||||
* If n_blanks != 0, blank or omit some parts.
|
||||
* Set of blanking areas must be in increasing order.
|
||||
*/
|
||||
void log_packet(void *handle, int direction, int type,
|
||||
char *texttype, void *data, int len,
|
||||
int n_blanks, const struct logblank_t *blanks)
|
||||
{
|
||||
struct LogContext *ctx = (struct LogContext *)handle;
|
||||
char dumpdata[80], smalldata[5];
|
||||
int p = 0, b = 0, omitted = 0;
|
||||
int output_pos = 0; /* NZ if pending output in dumpdata */
|
||||
|
||||
if (!(ctx->cfg.logtype == LGTYP_SSHRAW ||
|
||||
(ctx->cfg.logtype == LGTYP_PACKETS && texttype)))
|
||||
return;
|
||||
|
||||
/* Packet header. */
|
||||
if (texttype)
|
||||
logprintf(ctx, "%s packet type %d / 0x%02x (%s)\r\n",
|
||||
direction == PKT_INCOMING ? "Incoming" : "Outgoing",
|
||||
type, type, texttype);
|
||||
else
|
||||
logprintf(ctx, "%s raw data\r\n",
|
||||
direction == PKT_INCOMING ? "Incoming" : "Outgoing");
|
||||
|
||||
/*
|
||||
* Output a hex/ASCII dump of the packet body, blanking/omitting
|
||||
* parts as specified.
|
||||
*/
|
||||
while (p < len) {
|
||||
int blktype;
|
||||
|
||||
/* Move to a current entry in the blanking array. */
|
||||
while ((b < n_blanks) &&
|
||||
(p >= blanks[b].offset + blanks[b].len))
|
||||
b++;
|
||||
/* Work out what type of blanking to apply to
|
||||
* this byte. */
|
||||
blktype = PKTLOG_EMIT; /* default */
|
||||
if ((b < n_blanks) &&
|
||||
(p >= blanks[b].offset) &&
|
||||
(p < blanks[b].offset + blanks[b].len))
|
||||
blktype = blanks[b].type;
|
||||
|
||||
/* If we're about to stop omitting, it's time to say how
|
||||
* much we omitted. */
|
||||
if ((blktype != PKTLOG_OMIT) && omitted) {
|
||||
logprintf(ctx, " (%d byte%s omitted)\r\n",
|
||||
omitted, (omitted==1?"":"s"));
|
||||
omitted = 0;
|
||||
}
|
||||
|
||||
/* (Re-)initialise dumpdata as necessary
|
||||
* (start of row, or if we've just stopped omitting) */
|
||||
if (!output_pos && !omitted)
|
||||
sprintf(dumpdata, " %08x%*s\r\n", p-(p%16), 1+3*16+2+16, "");
|
||||
|
||||
/* Deal with the current byte. */
|
||||
if (blktype == PKTLOG_OMIT) {
|
||||
omitted++;
|
||||
} else {
|
||||
int c;
|
||||
if (blktype == PKTLOG_BLANK) {
|
||||
c = 'X';
|
||||
sprintf(smalldata, "XX");
|
||||
} else { /* PKTLOG_EMIT */
|
||||
c = ((unsigned char *)data)[p];
|
||||
sprintf(smalldata, "%02x", c);
|
||||
}
|
||||
dumpdata[10+2+3*(p%16)] = smalldata[0];
|
||||
dumpdata[10+2+3*(p%16)+1] = smalldata[1];
|
||||
dumpdata[10+1+3*16+2+(p%16)] = (isprint(c) ? c : '.');
|
||||
output_pos = (p%16) + 1;
|
||||
}
|
||||
|
||||
p++;
|
||||
|
||||
/* Flush row if necessary */
|
||||
if (((p % 16) == 0) || (p == len) || omitted) {
|
||||
if (output_pos) {
|
||||
strcpy(dumpdata + 10+1+3*16+2+output_pos, "\r\n");
|
||||
logwrite(ctx, dumpdata, strlen(dumpdata));
|
||||
output_pos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Tidy up */
|
||||
if (omitted)
|
||||
logprintf(ctx, " (%d byte%s omitted)\r\n",
|
||||
omitted, (omitted==1?"":"s"));
|
||||
logflush(ctx);
|
||||
}
|
||||
|
||||
void *log_init(void *frontend, Config *cfg)
|
||||
{
|
||||
struct LogContext *ctx = snew(struct LogContext);
|
||||
ctx->lgfp = NULL;
|
||||
ctx->state = L_CLOSED;
|
||||
ctx->frontend = frontend;
|
||||
ctx->cfg = *cfg; /* STRUCTURE COPY */
|
||||
bufchain_init(&ctx->queue);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void log_free(void *handle)
|
||||
{
|
||||
struct LogContext *ctx = (struct LogContext *)handle;
|
||||
|
||||
logfclose(ctx);
|
||||
bufchain_clear(&ctx->queue);
|
||||
sfree(ctx);
|
||||
}
|
||||
|
||||
void log_reconfig(void *handle, Config *cfg)
|
||||
{
|
||||
struct LogContext *ctx = (struct LogContext *)handle;
|
||||
int reset_logging;
|
||||
|
||||
if (!filename_equal(ctx->cfg.logfilename, cfg->logfilename) ||
|
||||
ctx->cfg.logtype != cfg->logtype)
|
||||
reset_logging = TRUE;
|
||||
else
|
||||
reset_logging = FALSE;
|
||||
|
||||
if (reset_logging)
|
||||
logfclose(ctx);
|
||||
|
||||
ctx->cfg = *cfg; /* STRUCTURE COPY */
|
||||
|
||||
if (reset_logging)
|
||||
logfopen(ctx);
|
||||
}
|
||||
|
||||
/*
|
||||
* translate format codes into time/date strings
|
||||
* and insert them into log file name
|
||||
*
|
||||
* "&Y":YYYY "&m":MM "&d":DD "&T":hhmmss "&h":<hostname> "&&":&
|
||||
*/
|
||||
static void xlatlognam(Filename *dest, Filename src,
|
||||
char *hostname, struct tm *tm) {
|
||||
char buf[10], *bufp;
|
||||
int size;
|
||||
char buffer[FILENAME_MAX];
|
||||
int len = sizeof(buffer)-1;
|
||||
char *d;
|
||||
const char *s;
|
||||
|
||||
d = buffer;
|
||||
s = filename_to_str(&src);
|
||||
|
||||
while (*s) {
|
||||
/* Let (bufp, len) be the string to append. */
|
||||
bufp = buf; /* don't usually override this */
|
||||
if (*s == '&') {
|
||||
char c;
|
||||
s++;
|
||||
size = 0;
|
||||
if (*s) switch (c = *s++, tolower(c)) {
|
||||
case 'y':
|
||||
size = strftime(buf, sizeof(buf), "%Y", tm);
|
||||
break;
|
||||
case 'm':
|
||||
size = strftime(buf, sizeof(buf), "%m", tm);
|
||||
break;
|
||||
case 'd':
|
||||
size = strftime(buf, sizeof(buf), "%d", tm);
|
||||
break;
|
||||
case 't':
|
||||
size = strftime(buf, sizeof(buf), "%H%M%S", tm);
|
||||
break;
|
||||
case 'h':
|
||||
bufp = hostname;
|
||||
size = strlen(bufp);
|
||||
break;
|
||||
default:
|
||||
buf[0] = '&';
|
||||
size = 1;
|
||||
if (c != '&')
|
||||
buf[size++] = c;
|
||||
}
|
||||
} else {
|
||||
buf[0] = *s++;
|
||||
size = 1;
|
||||
}
|
||||
if (size > len)
|
||||
size = len;
|
||||
memcpy(d, bufp, size);
|
||||
d += size;
|
||||
len -= size;
|
||||
}
|
||||
*d = '\0';
|
||||
|
||||
*dest = filename_from_str(buffer);
|
||||
}
|
||||
69
sFTPlugins/psftp/MAC/MACSTUFF.H
Normal file
69
sFTPlugins/psftp/MAC/MACSTUFF.H
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* macstuff.h -- Mac-specific definitions visible to the rest of PuTTY.
|
||||
*/
|
||||
|
||||
typedef void *Context; /* FIXME */
|
||||
|
||||
#include <MacTypes.h>
|
||||
#include <Files.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include "charset.h"
|
||||
|
||||
struct Filename {
|
||||
FSSpec fss;
|
||||
};
|
||||
|
||||
extern FILE * f_open(struct Filename, char const *, int);
|
||||
|
||||
/* Suspiciously similar to an ICFontRecord */
|
||||
struct FontSpec {
|
||||
short size;
|
||||
Style face;
|
||||
char pad;
|
||||
Str255 name;
|
||||
};
|
||||
|
||||
/*
|
||||
* On the Mac, Unicode text copied to the clipboard has U+2028 line separators.
|
||||
* Non-Unicode text will have these converted to CR along with the rest of the
|
||||
* content.
|
||||
*/
|
||||
#define SEL_NL { 0x2028 }
|
||||
|
||||
#include <MacTypes.h>
|
||||
#include <Events.h> /* Timing related goo */
|
||||
|
||||
#define GETTICKCOUNT TickCount
|
||||
#define CURSORBLINK GetCaretTime()
|
||||
#define TICKSPERSEC 60
|
||||
|
||||
#define DEFAULT_CODEPAGE 0 /* FIXME: no idea how to do this */
|
||||
|
||||
#define WCHAR wchar_t
|
||||
#define BYTE UInt8
|
||||
#define DWORD UInt32
|
||||
|
||||
#define OPTIMISE_SCROLL
|
||||
|
||||
/*
|
||||
* sk_getxdmdata() does not exist under the Mac (SGT: I have no
|
||||
* idea whatsoever how to write it, and furthermore I'm unconvinced
|
||||
* it's necessary), so it's a macro which always returns NULL.
|
||||
*/
|
||||
#define sk_getxdmdata(socket, lenp) (NULL)
|
||||
|
||||
/* To make it compile */
|
||||
|
||||
#include <stdarg.h>
|
||||
extern int vsnprintf(char *, size_t, char const *, va_list);
|
||||
|
||||
extern int stricmp(char const *, char const *);
|
||||
extern int strnicmp(char const *, char const *, size_t);
|
||||
|
||||
#define HELPCTX(foo) I(0)
|
||||
|
||||
#define FILTER_KEY_FILES "pAgt.PPK"
|
||||
|
||||
#define CP_UTF8 CS_UTF8 /* from libcharset */
|
||||
|
||||
34
sFTPlugins/psftp/MACOSX/OSX.H
Normal file
34
sFTPlugins/psftp/MACOSX/OSX.H
Normal file
@@ -0,0 +1,34 @@
|
||||
#ifndef PUTTY_OSX_H
|
||||
#define PUTTY_OSX_H
|
||||
|
||||
/*
|
||||
* Cocoa defines `FontSpec' itself, so we must change its name.
|
||||
* (Arrgh.)
|
||||
*/
|
||||
#define FontSpec FontSpec_OSX_Proof
|
||||
|
||||
/*
|
||||
* Define the various compatibility symbols to make uxpty.c compile
|
||||
* correctly on OS X.
|
||||
*/
|
||||
#define BSD_PTYS
|
||||
#define OMIT_UTMP
|
||||
#define HAVE_NO_SETRESUID
|
||||
#define NOT_X_WINDOWS
|
||||
|
||||
/*
|
||||
* OS X is largely just Unix, so we can include most of this
|
||||
* unchanged.
|
||||
*/
|
||||
#include "unix.h"
|
||||
|
||||
/*
|
||||
* Functions exported by osxsel.m. (Both of these functions are
|
||||
* expected to be called in the _main_ thread: the select subthread
|
||||
* is an implementation detail of osxsel.m and ideally should not
|
||||
* be visible at all outside it.)
|
||||
*/
|
||||
void osxsel_init(void); /* call this to kick things off */
|
||||
void osxsel_process_results(void); /* call this on receipt of a netevent */
|
||||
|
||||
#endif
|
||||
655
sFTPlugins/psftp/MISC.C
Normal file
655
sFTPlugins/psftp/MISC.C
Normal file
@@ -0,0 +1,655 @@
|
||||
/*
|
||||
* Platform-independent routines shared between all PuTTY programs.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <limits.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
#include "putty.h"
|
||||
|
||||
/*
|
||||
* Parse a string block size specification. This is approximately a
|
||||
* subset of the block size specs supported by GNU fileutils:
|
||||
* "nk" = n kilobytes
|
||||
* "nM" = n megabytes
|
||||
* "nG" = n gigabytes
|
||||
* All numbers are decimal, and suffixes refer to powers of two.
|
||||
* Case-insensitive.
|
||||
*/
|
||||
unsigned long parse_blocksize(const char *bs)
|
||||
{
|
||||
char *suf;
|
||||
unsigned long r = strtoul(bs, &suf, 10);
|
||||
if (*suf != '\0') {
|
||||
while (*suf && isspace((unsigned char)*suf)) suf++;
|
||||
switch (*suf) {
|
||||
case 'k': case 'K':
|
||||
r *= 1024ul;
|
||||
break;
|
||||
case 'm': case 'M':
|
||||
r *= 1024ul * 1024ul;
|
||||
break;
|
||||
case 'g': case 'G':
|
||||
r *= 1024ul * 1024ul * 1024ul;
|
||||
break;
|
||||
case '\0':
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a ^C style character specification.
|
||||
* Returns NULL in `next' if we didn't recognise it as a control character,
|
||||
* in which case `c' should be ignored.
|
||||
* The precise current parsing is an oddity inherited from the terminal
|
||||
* answerback-string parsing code. All sequences start with ^; all except
|
||||
* ^<123> are two characters. The ones that are worth keeping are probably:
|
||||
* ^? 127
|
||||
* ^@A-Z[\]^_ 0-31
|
||||
* a-z 1-26
|
||||
* <num> specified by number (decimal, 0octal, 0xHEX)
|
||||
* ~ ^ escape
|
||||
*/
|
||||
char ctrlparse(char *s, char **next)
|
||||
{
|
||||
char c = 0;
|
||||
if (*s != '^') {
|
||||
*next = NULL;
|
||||
} else {
|
||||
s++;
|
||||
if (*s == '\0') {
|
||||
*next = NULL;
|
||||
} else if (*s == '<') {
|
||||
s++;
|
||||
c = (char)strtol(s, next, 0);
|
||||
if ((*next == s) || (**next != '>')) {
|
||||
c = 0;
|
||||
*next = NULL;
|
||||
} else
|
||||
(*next)++;
|
||||
} else if (*s >= 'a' && *s <= 'z') {
|
||||
c = (*s - ('a' - 1));
|
||||
*next = s+1;
|
||||
} else if ((*s >= '@' && *s <= '_') || *s == '?' || (*s & 0x80)) {
|
||||
c = ('@' ^ *s);
|
||||
*next = s+1;
|
||||
} else if (*s == '~') {
|
||||
c = '^';
|
||||
*next = s+1;
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
prompts_t *new_prompts(void *frontend)
|
||||
{
|
||||
prompts_t *p = snew(prompts_t);
|
||||
p->prompts = NULL;
|
||||
p->n_prompts = 0;
|
||||
p->frontend = frontend;
|
||||
p->data = NULL;
|
||||
p->to_server = TRUE; /* to be on the safe side */
|
||||
p->name = p->instruction = NULL;
|
||||
p->name_reqd = p->instr_reqd = FALSE;
|
||||
return p;
|
||||
}
|
||||
void add_prompt(prompts_t *p, char *promptstr, int echo, size_t len)
|
||||
{
|
||||
prompt_t *pr = snew(prompt_t);
|
||||
char *result = snewn(len, char);
|
||||
pr->prompt = promptstr;
|
||||
pr->echo = echo;
|
||||
pr->result = result;
|
||||
pr->result_len = len;
|
||||
p->n_prompts++;
|
||||
p->prompts = sresize(p->prompts, p->n_prompts, prompt_t *);
|
||||
p->prompts[p->n_prompts-1] = pr;
|
||||
}
|
||||
void free_prompts(prompts_t *p)
|
||||
{
|
||||
size_t i;
|
||||
for (i=0; i < p->n_prompts; i++) {
|
||||
prompt_t *pr = p->prompts[i];
|
||||
memset(pr->result, 0, pr->result_len); /* burn the evidence */
|
||||
sfree(pr->result);
|
||||
sfree(pr->prompt);
|
||||
sfree(pr);
|
||||
}
|
||||
sfree(p->prompts);
|
||||
sfree(p->name);
|
||||
sfree(p->instruction);
|
||||
sfree(p);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* String handling routines.
|
||||
*/
|
||||
|
||||
char *dupstr(const char *s)
|
||||
{
|
||||
char *p = NULL;
|
||||
if (s) {
|
||||
int len = strlen(s);
|
||||
p = snewn(len + 1, char);
|
||||
strcpy(p, s);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/* Allocate the concatenation of N strings. Terminate arg list with NULL. */
|
||||
char *dupcat(const char *s1, ...)
|
||||
{
|
||||
int len;
|
||||
char *p, *q, *sn;
|
||||
va_list ap;
|
||||
|
||||
len = strlen(s1);
|
||||
va_start(ap, s1);
|
||||
while (1) {
|
||||
sn = va_arg(ap, char *);
|
||||
if (!sn)
|
||||
break;
|
||||
len += strlen(sn);
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
p = snewn(len + 1, char);
|
||||
strcpy(p, s1);
|
||||
q = p + strlen(p);
|
||||
|
||||
va_start(ap, s1);
|
||||
while (1) {
|
||||
sn = va_arg(ap, char *);
|
||||
if (!sn)
|
||||
break;
|
||||
strcpy(q, sn);
|
||||
q += strlen(q);
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do an sprintf(), but into a custom-allocated buffer.
|
||||
*
|
||||
* Currently I'm doing this via vsnprintf. This has worked so far,
|
||||
* but it's not good, because vsnprintf is not available on all
|
||||
* platforms. There's an ifdef to use `_vsnprintf', which seems
|
||||
* to be the local name for it on Windows. Other platforms may
|
||||
* lack it completely, in which case it'll be time to rewrite
|
||||
* this function in a totally different way.
|
||||
*
|
||||
* The only `properly' portable solution I can think of is to
|
||||
* implement my own format string scanner, which figures out an
|
||||
* upper bound for the length of each formatting directive,
|
||||
* allocates the buffer as it goes along, and calls sprintf() to
|
||||
* actually process each directive. If I ever need to actually do
|
||||
* this, some caveats:
|
||||
*
|
||||
* - It's very hard to find a reliable upper bound for
|
||||
* floating-point values. %f, in particular, when supplied with
|
||||
* a number near to the upper or lower limit of representable
|
||||
* numbers, could easily take several hundred characters. It's
|
||||
* probably feasible to predict this statically using the
|
||||
* constants in <float.h>, or even to predict it dynamically by
|
||||
* looking at the exponent of the specific float provided, but
|
||||
* it won't be fun.
|
||||
*
|
||||
* - Don't forget to _check_, after calling sprintf, that it's
|
||||
* used at most the amount of space we had available.
|
||||
*
|
||||
* - Fault any formatting directive we don't fully understand. The
|
||||
* aim here is to _guarantee_ that we never overflow the buffer,
|
||||
* because this is a security-critical function. If we see a
|
||||
* directive we don't know about, we should panic and die rather
|
||||
* than run any risk.
|
||||
*/
|
||||
char *dupprintf(const char *fmt, ...)
|
||||
{
|
||||
char *ret;
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
ret = dupvprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
return ret;
|
||||
}
|
||||
char *dupvprintf(const char *fmt, va_list ap)
|
||||
{
|
||||
char *buf;
|
||||
int len, size;
|
||||
|
||||
buf = snewn(512, char);
|
||||
size = 512;
|
||||
|
||||
while (1) {
|
||||
#ifdef _WINDOWS
|
||||
#define vsnprintf _vsnprintf
|
||||
#endif
|
||||
#ifdef va_copy
|
||||
/* Use the `va_copy' macro mandated by C99, if present.
|
||||
* XXX some environments may have this as __va_copy() */
|
||||
va_list aq;
|
||||
va_copy(aq, ap);
|
||||
len = vsnprintf(buf, size, fmt, aq);
|
||||
va_end(aq);
|
||||
#else
|
||||
/* Ugh. No va_copy macro, so do something nasty.
|
||||
* Technically, you can't reuse a va_list like this: it is left
|
||||
* unspecified whether advancing a va_list pointer modifies its
|
||||
* value or something it points to, so on some platforms calling
|
||||
* vsnprintf twice on the same va_list might fail hideously
|
||||
* (indeed, it has been observed to).
|
||||
* XXX the autoconf manual suggests that using memcpy() will give
|
||||
* "maximum portability". */
|
||||
len = vsnprintf(buf, size, fmt, ap);
|
||||
#endif
|
||||
if (len >= 0 && len < size) {
|
||||
/* This is the C99-specified criterion for snprintf to have
|
||||
* been completely successful. */
|
||||
return buf;
|
||||
} else if (len > 0) {
|
||||
/* This is the C99 error condition: the returned length is
|
||||
* the required buffer size not counting the NUL. */
|
||||
size = len + 1;
|
||||
} else {
|
||||
/* This is the pre-C99 glibc error condition: <0 means the
|
||||
* buffer wasn't big enough, so we enlarge it a bit and hope. */
|
||||
size += 512;
|
||||
}
|
||||
buf = sresize(buf, size, char);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read an entire line of text from a file. Return a buffer
|
||||
* malloced to be as big as necessary (caller must free).
|
||||
*/
|
||||
char *fgetline(FILE *fp)
|
||||
{
|
||||
char *ret = snewn(512, char);
|
||||
int size = 512, len = 0;
|
||||
while (fgets(ret + len, size - len, fp)) {
|
||||
len += strlen(ret + len);
|
||||
if (ret[len-1] == '\n')
|
||||
break; /* got a newline, we're done */
|
||||
size = len + 512;
|
||||
ret = sresize(ret, size, char);
|
||||
}
|
||||
if (len == 0) { /* first fgets returned NULL */
|
||||
sfree(ret);
|
||||
return NULL;
|
||||
}
|
||||
ret[len] = '\0';
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* Base64 encoding routine. This is required in public-key writing
|
||||
* but also in HTTP proxy handling, so it's centralised here.
|
||||
*/
|
||||
|
||||
void base64_encode_atom(unsigned char *data, int n, char *out)
|
||||
{
|
||||
static const char base64_chars[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
unsigned word;
|
||||
|
||||
word = data[0] << 16;
|
||||
if (n > 1)
|
||||
word |= data[1] << 8;
|
||||
if (n > 2)
|
||||
word |= data[2];
|
||||
out[0] = base64_chars[(word >> 18) & 0x3F];
|
||||
out[1] = base64_chars[(word >> 12) & 0x3F];
|
||||
if (n > 1)
|
||||
out[2] = base64_chars[(word >> 6) & 0x3F];
|
||||
else
|
||||
out[2] = '=';
|
||||
if (n > 2)
|
||||
out[3] = base64_chars[word & 0x3F];
|
||||
else
|
||||
out[3] = '=';
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* Generic routines to deal with send buffers: a linked list of
|
||||
* smallish blocks, with the operations
|
||||
*
|
||||
* - add an arbitrary amount of data to the end of the list
|
||||
* - remove the first N bytes from the list
|
||||
* - return a (pointer,length) pair giving some initial data in
|
||||
* the list, suitable for passing to a send or write system
|
||||
* call
|
||||
* - retrieve a larger amount of initial data from the list
|
||||
* - return the current size of the buffer chain in bytes
|
||||
*/
|
||||
|
||||
#define BUFFER_GRANULE 512
|
||||
|
||||
struct bufchain_granule {
|
||||
struct bufchain_granule *next;
|
||||
int buflen, bufpos;
|
||||
char buf[BUFFER_GRANULE];
|
||||
};
|
||||
|
||||
void bufchain_init(bufchain *ch)
|
||||
{
|
||||
ch->head = ch->tail = NULL;
|
||||
ch->buffersize = 0;
|
||||
}
|
||||
|
||||
void bufchain_clear(bufchain *ch)
|
||||
{
|
||||
struct bufchain_granule *b;
|
||||
while (ch->head) {
|
||||
b = ch->head;
|
||||
ch->head = ch->head->next;
|
||||
sfree(b);
|
||||
}
|
||||
ch->tail = NULL;
|
||||
ch->buffersize = 0;
|
||||
}
|
||||
|
||||
int bufchain_size(bufchain *ch)
|
||||
{
|
||||
return ch->buffersize;
|
||||
}
|
||||
|
||||
void bufchain_add(bufchain *ch, const void *data, int len)
|
||||
{
|
||||
const char *buf = (const char *)data;
|
||||
|
||||
if (len == 0) return;
|
||||
|
||||
ch->buffersize += len;
|
||||
|
||||
if (ch->tail && ch->tail->buflen < BUFFER_GRANULE) {
|
||||
int copylen = min(len, BUFFER_GRANULE - ch->tail->buflen);
|
||||
memcpy(ch->tail->buf + ch->tail->buflen, buf, copylen);
|
||||
buf += copylen;
|
||||
len -= copylen;
|
||||
ch->tail->buflen += copylen;
|
||||
}
|
||||
while (len > 0) {
|
||||
int grainlen = min(len, BUFFER_GRANULE);
|
||||
struct bufchain_granule *newbuf;
|
||||
newbuf = snew(struct bufchain_granule);
|
||||
newbuf->bufpos = 0;
|
||||
newbuf->buflen = grainlen;
|
||||
memcpy(newbuf->buf, buf, grainlen);
|
||||
buf += grainlen;
|
||||
len -= grainlen;
|
||||
if (ch->tail)
|
||||
ch->tail->next = newbuf;
|
||||
else
|
||||
ch->head = ch->tail = newbuf;
|
||||
newbuf->next = NULL;
|
||||
ch->tail = newbuf;
|
||||
}
|
||||
}
|
||||
|
||||
void bufchain_consume(bufchain *ch, int len)
|
||||
{
|
||||
struct bufchain_granule *tmp;
|
||||
|
||||
assert(ch->buffersize >= len);
|
||||
while (len > 0) {
|
||||
int remlen = len;
|
||||
assert(ch->head != NULL);
|
||||
if (remlen >= ch->head->buflen - ch->head->bufpos) {
|
||||
remlen = ch->head->buflen - ch->head->bufpos;
|
||||
tmp = ch->head;
|
||||
ch->head = tmp->next;
|
||||
sfree(tmp);
|
||||
if (!ch->head)
|
||||
ch->tail = NULL;
|
||||
} else
|
||||
ch->head->bufpos += remlen;
|
||||
ch->buffersize -= remlen;
|
||||
len -= remlen;
|
||||
}
|
||||
}
|
||||
|
||||
void bufchain_prefix(bufchain *ch, void **data, int *len)
|
||||
{
|
||||
*len = ch->head->buflen - ch->head->bufpos;
|
||||
*data = ch->head->buf + ch->head->bufpos;
|
||||
}
|
||||
|
||||
void bufchain_fetch(bufchain *ch, void *data, int len)
|
||||
{
|
||||
struct bufchain_granule *tmp;
|
||||
char *data_c = (char *)data;
|
||||
|
||||
tmp = ch->head;
|
||||
|
||||
assert(ch->buffersize >= len);
|
||||
while (len > 0) {
|
||||
int remlen = len;
|
||||
|
||||
assert(tmp != NULL);
|
||||
if (remlen >= tmp->buflen - tmp->bufpos)
|
||||
remlen = tmp->buflen - tmp->bufpos;
|
||||
memcpy(data_c, tmp->buf + tmp->bufpos, remlen);
|
||||
|
||||
tmp = tmp->next;
|
||||
len -= remlen;
|
||||
data_c += remlen;
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* My own versions of malloc, realloc and free. Because I want
|
||||
* malloc and realloc to bomb out and exit the program if they run
|
||||
* out of memory, realloc to reliably call malloc if passed a NULL
|
||||
* pointer, and free to reliably do nothing if passed a NULL
|
||||
* pointer. We can also put trace printouts in, if we need to; and
|
||||
* we can also replace the allocator with an ElectricFence-like
|
||||
* one.
|
||||
*/
|
||||
|
||||
#ifdef MINEFIELD
|
||||
void *minefield_c_malloc(size_t size);
|
||||
void minefield_c_free(void *p);
|
||||
void *minefield_c_realloc(void *p, size_t size);
|
||||
#endif
|
||||
|
||||
#ifdef MALLOC_LOG
|
||||
static FILE *fp = NULL;
|
||||
|
||||
static char *mlog_file = NULL;
|
||||
static int mlog_line = 0;
|
||||
|
||||
void mlog(char *file, int line)
|
||||
{
|
||||
mlog_file = file;
|
||||
mlog_line = line;
|
||||
if (!fp) {
|
||||
fp = fopen("putty_mem.log", "w");
|
||||
setvbuf(fp, NULL, _IONBF, BUFSIZ);
|
||||
}
|
||||
if (fp)
|
||||
fprintf(fp, "%s:%d: ", file, line);
|
||||
}
|
||||
#endif
|
||||
|
||||
void *safemalloc(size_t n, size_t size)
|
||||
{
|
||||
void *p;
|
||||
|
||||
if (n > INT_MAX / size) {
|
||||
p = NULL;
|
||||
} else {
|
||||
size *= n;
|
||||
if (size == 0) size = 1;
|
||||
#ifdef MINEFIELD
|
||||
p = minefield_c_malloc(size);
|
||||
#else
|
||||
p = malloc(size);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!p) {
|
||||
char str[200];
|
||||
#ifdef MALLOC_LOG
|
||||
sprintf(str, "Out of memory! (%s:%d, size=%d)",
|
||||
mlog_file, mlog_line, size);
|
||||
fprintf(fp, "*** %s\n", str);
|
||||
fclose(fp);
|
||||
#else
|
||||
strcpy(str, "Out of memory!");
|
||||
#endif
|
||||
modalfatalbox(str);
|
||||
}
|
||||
#ifdef MALLOC_LOG
|
||||
if (fp)
|
||||
fprintf(fp, "malloc(%d) returns %p\n", size, p);
|
||||
#endif
|
||||
return p;
|
||||
}
|
||||
|
||||
void *saferealloc(void *ptr, size_t n, size_t size)
|
||||
{
|
||||
void *p;
|
||||
|
||||
if (n > INT_MAX / size) {
|
||||
p = NULL;
|
||||
} else {
|
||||
size *= n;
|
||||
if (!ptr) {
|
||||
#ifdef MINEFIELD
|
||||
p = minefield_c_malloc(size);
|
||||
#else
|
||||
p = malloc(size);
|
||||
#endif
|
||||
} else {
|
||||
#ifdef MINEFIELD
|
||||
p = minefield_c_realloc(ptr, size);
|
||||
#else
|
||||
p = realloc(ptr, size);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (!p) {
|
||||
char str[200];
|
||||
#ifdef MALLOC_LOG
|
||||
sprintf(str, "Out of memory! (%s:%d, size=%d)",
|
||||
mlog_file, mlog_line, size);
|
||||
fprintf(fp, "*** %s\n", str);
|
||||
fclose(fp);
|
||||
#else
|
||||
strcpy(str, "Out of memory!");
|
||||
#endif
|
||||
modalfatalbox(str);
|
||||
}
|
||||
#ifdef MALLOC_LOG
|
||||
if (fp)
|
||||
fprintf(fp, "realloc(%p,%d) returns %p\n", ptr, size, p);
|
||||
#endif
|
||||
return p;
|
||||
}
|
||||
|
||||
void safefree(void *ptr)
|
||||
{
|
||||
if (ptr) {
|
||||
#ifdef MALLOC_LOG
|
||||
if (fp)
|
||||
fprintf(fp, "free(%p)\n", ptr);
|
||||
#endif
|
||||
#ifdef MINEFIELD
|
||||
minefield_c_free(ptr);
|
||||
#else
|
||||
free(ptr);
|
||||
#endif
|
||||
}
|
||||
#ifdef MALLOC_LOG
|
||||
else if (fp)
|
||||
fprintf(fp, "freeing null pointer - no action taken\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* Debugging routines.
|
||||
*/
|
||||
|
||||
#ifdef DEBUG
|
||||
extern void dputs(char *); /* defined in per-platform *misc.c */
|
||||
|
||||
void debug_printf(char *fmt, ...)
|
||||
{
|
||||
char *buf;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
buf = dupvprintf(fmt, ap);
|
||||
dputs(buf);
|
||||
sfree(buf);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
|
||||
void debug_memdump(void *buf, int len, int L)
|
||||
{
|
||||
int i;
|
||||
unsigned char *p = buf;
|
||||
char foo[17];
|
||||
if (L) {
|
||||
int delta;
|
||||
debug_printf("\t%d (0x%x) bytes:\n", len, len);
|
||||
delta = 15 & (int) p;
|
||||
p -= delta;
|
||||
len += delta;
|
||||
}
|
||||
for (; 0 < len; p += 16, len -= 16) {
|
||||
dputs(" ");
|
||||
if (L)
|
||||
debug_printf("%p: ", p);
|
||||
strcpy(foo, "................"); /* sixteen dots */
|
||||
for (i = 0; i < 16 && i < len; ++i) {
|
||||
if (&p[i] < (unsigned char *) buf) {
|
||||
dputs(" "); /* 3 spaces */
|
||||
foo[i] = ' ';
|
||||
} else {
|
||||
debug_printf("%c%02.2x",
|
||||
&p[i] != (unsigned char *) buf
|
||||
&& i % 4 ? '.' : ' ', p[i]
|
||||
);
|
||||
if (p[i] >= ' ' && p[i] <= '~')
|
||||
foo[i] = (char) p[i];
|
||||
}
|
||||
}
|
||||
foo[i] = '\0';
|
||||
debug_printf("%*s%s\n", (16 - i) * 3 + 2, "", foo);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* def DEBUG */
|
||||
|
||||
/*
|
||||
* Determine whether or not a Config structure represents a session
|
||||
* which can sensibly be launched right now.
|
||||
*/
|
||||
int cfg_launchable(const Config *cfg)
|
||||
{
|
||||
if (cfg->protocol == PROT_SERIAL)
|
||||
return cfg->serline[0] != 0;
|
||||
else
|
||||
return cfg->host[0] != 0;
|
||||
}
|
||||
|
||||
char const *cfg_dest(const Config *cfg)
|
||||
{
|
||||
if (cfg->protocol == PROT_SERIAL)
|
||||
return cfg->serline;
|
||||
else
|
||||
return cfg->host;
|
||||
}
|
||||
132
sFTPlugins/psftp/MISC.H
Normal file
132
sFTPlugins/psftp/MISC.H
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Header for misc.c.
|
||||
*/
|
||||
|
||||
#ifndef PUTTY_MISC_H
|
||||
#define PUTTY_MISC_H
|
||||
|
||||
#include "puttymem.h"
|
||||
|
||||
#include <stdio.h> /* for FILE * */
|
||||
#include <stdarg.h> /* for va_list */
|
||||
#include <time.h> /* for struct tm */
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
typedef struct Filename Filename;
|
||||
typedef struct FontSpec FontSpec;
|
||||
|
||||
unsigned long parse_blocksize(const char *bs);
|
||||
char ctrlparse(char *s, char **next);
|
||||
|
||||
char *dupstr(const char *s);
|
||||
char *dupcat(const char *s1, ...);
|
||||
char *dupprintf(const char *fmt, ...);
|
||||
char *dupvprintf(const char *fmt, va_list ap);
|
||||
|
||||
char *fgetline(FILE *fp);
|
||||
|
||||
void base64_encode_atom(unsigned char *data, int n, char *out);
|
||||
|
||||
struct bufchain_granule;
|
||||
typedef struct bufchain_tag {
|
||||
struct bufchain_granule *head, *tail;
|
||||
int buffersize; /* current amount of buffered data */
|
||||
} bufchain;
|
||||
|
||||
void bufchain_init(bufchain *ch);
|
||||
void bufchain_clear(bufchain *ch);
|
||||
int bufchain_size(bufchain *ch);
|
||||
void bufchain_add(bufchain *ch, const void *data, int len);
|
||||
void bufchain_prefix(bufchain *ch, void **data, int *len);
|
||||
void bufchain_consume(bufchain *ch, int len);
|
||||
void bufchain_fetch(bufchain *ch, void *data, int len);
|
||||
|
||||
struct tm ltime(void);
|
||||
|
||||
/*
|
||||
* Debugging functions.
|
||||
*
|
||||
* Output goes to debug.log
|
||||
*
|
||||
* debug(()) (note the double brackets) is like printf().
|
||||
*
|
||||
* dmemdump() and dmemdumpl() both do memory dumps. The difference
|
||||
* is that dmemdumpl() is more suited for when the memory address is
|
||||
* important (say because you'll be recording pointer values later
|
||||
* on). dmemdump() is more concise.
|
||||
*/
|
||||
|
||||
#ifdef DEBUG
|
||||
void debug_printf(char *fmt, ...);
|
||||
void debug_memdump(void *buf, int len, int L);
|
||||
#define debug(x) (debug_printf x)
|
||||
#define dmemdump(buf,len) debug_memdump (buf, len, 0);
|
||||
#define dmemdumpl(buf,len) debug_memdump (buf, len, 1);
|
||||
#else
|
||||
#define debug(x)
|
||||
#define dmemdump(buf,len)
|
||||
#define dmemdumpl(buf,len)
|
||||
#endif
|
||||
|
||||
#ifndef lenof
|
||||
#define lenof(x) ( (sizeof((x))) / (sizeof(*(x))))
|
||||
#endif
|
||||
|
||||
#ifndef min
|
||||
#define min(x,y) ( (x) < (y) ? (x) : (y) )
|
||||
#endif
|
||||
#ifndef max
|
||||
#define max(x,y) ( (x) > (y) ? (x) : (y) )
|
||||
#endif
|
||||
|
||||
#define GET_32BIT_LSB_FIRST(cp) \
|
||||
(((unsigned long)(unsigned char)(cp)[0]) | \
|
||||
((unsigned long)(unsigned char)(cp)[1] << 8) | \
|
||||
((unsigned long)(unsigned char)(cp)[2] << 16) | \
|
||||
((unsigned long)(unsigned char)(cp)[3] << 24))
|
||||
|
||||
#define PUT_32BIT_LSB_FIRST(cp, value) ( \
|
||||
(cp)[0] = (unsigned char)(value), \
|
||||
(cp)[1] = (unsigned char)((value) >> 8), \
|
||||
(cp)[2] = (unsigned char)((value) >> 16), \
|
||||
(cp)[3] = (unsigned char)((value) >> 24) )
|
||||
|
||||
#define GET_16BIT_LSB_FIRST(cp) \
|
||||
(((unsigned long)(unsigned char)(cp)[0]) | \
|
||||
((unsigned long)(unsigned char)(cp)[1] << 8))
|
||||
|
||||
#define PUT_16BIT_LSB_FIRST(cp, value) ( \
|
||||
(cp)[0] = (unsigned char)(value), \
|
||||
(cp)[1] = (unsigned char)((value) >> 8) )
|
||||
|
||||
#define GET_32BIT_MSB_FIRST(cp) \
|
||||
(((unsigned long)(unsigned char)(cp)[0] << 24) | \
|
||||
((unsigned long)(unsigned char)(cp)[1] << 16) | \
|
||||
((unsigned long)(unsigned char)(cp)[2] << 8) | \
|
||||
((unsigned long)(unsigned char)(cp)[3]))
|
||||
|
||||
#define GET_32BIT(cp) GET_32BIT_MSB_FIRST(cp)
|
||||
|
||||
#define PUT_32BIT_MSB_FIRST(cp, value) ( \
|
||||
(cp)[0] = (unsigned char)((value) >> 24), \
|
||||
(cp)[1] = (unsigned char)((value) >> 16), \
|
||||
(cp)[2] = (unsigned char)((value) >> 8), \
|
||||
(cp)[3] = (unsigned char)(value) )
|
||||
|
||||
#define PUT_32BIT(cp, value) PUT_32BIT_MSB_FIRST(cp, value)
|
||||
|
||||
#define GET_16BIT_MSB_FIRST(cp) \
|
||||
(((unsigned long)(unsigned char)(cp)[0] << 8) | \
|
||||
((unsigned long)(unsigned char)(cp)[1]))
|
||||
|
||||
#define PUT_16BIT_MSB_FIRST(cp, value) ( \
|
||||
(cp)[0] = (unsigned char)((value) >> 8), \
|
||||
(cp)[1] = (unsigned char)(value) )
|
||||
|
||||
#endif
|
||||
235
sFTPlugins/psftp/NETWORK.H
Normal file
235
sFTPlugins/psftp/NETWORK.H
Normal file
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* Networking abstraction in PuTTY.
|
||||
*
|
||||
* The way this works is: a back end can choose to open any number
|
||||
* of sockets - including zero, which might be necessary in some.
|
||||
* It can register a bunch of callbacks (most notably for when
|
||||
* data is received) for each socket, and it can call the networking
|
||||
* abstraction to send data without having to worry about blocking.
|
||||
* The stuff behind the abstraction takes care of selects and
|
||||
* nonblocking writes and all that sort of painful gubbins.
|
||||
*/
|
||||
|
||||
#ifndef PUTTY_NETWORK_H
|
||||
#define PUTTY_NETWORK_H
|
||||
|
||||
#ifndef DONE_TYPEDEFS
|
||||
#define DONE_TYPEDEFS
|
||||
typedef struct config_tag Config;
|
||||
typedef struct backend_tag Backend;
|
||||
typedef struct terminal_tag Terminal;
|
||||
#endif
|
||||
|
||||
typedef struct SockAddr_tag *SockAddr;
|
||||
/* pay attention to levels of indirection */
|
||||
typedef struct socket_function_table **Socket;
|
||||
typedef struct plug_function_table **Plug;
|
||||
|
||||
#ifndef OSSOCKET_DEFINED
|
||||
typedef void *OSSocket;
|
||||
#endif
|
||||
|
||||
struct socket_function_table {
|
||||
Plug(*plug) (Socket s, Plug p);
|
||||
/* use a different plug (return the old one) */
|
||||
/* if p is NULL, it doesn't change the plug */
|
||||
/* but it does return the one it's using */
|
||||
void (*close) (Socket s);
|
||||
int (*write) (Socket s, const char *data, int len);
|
||||
int (*write_oob) (Socket s, const char *data, int len);
|
||||
void (*flush) (Socket s);
|
||||
void (*set_private_ptr) (Socket s, void *ptr);
|
||||
void *(*get_private_ptr) (Socket s);
|
||||
void (*set_frozen) (Socket s, int is_frozen);
|
||||
/* ignored by tcp, but vital for ssl */
|
||||
const char *(*socket_error) (Socket s);
|
||||
};
|
||||
|
||||
struct plug_function_table {
|
||||
void (*log)(Plug p, int type, SockAddr addr, int port,
|
||||
const char *error_msg, int error_code);
|
||||
/*
|
||||
* Passes the client progress reports on the process of setting
|
||||
* up the connection.
|
||||
*
|
||||
* - type==0 means we are about to try to connect to address
|
||||
* `addr' (error_msg and error_code are ignored)
|
||||
* - type==1 means we have failed to connect to address `addr'
|
||||
* (error_msg and error_code are supplied). This is not a
|
||||
* fatal error - we may well have other candidate addresses
|
||||
* to fall back to. When it _is_ fatal, the closing()
|
||||
* function will be called.
|
||||
*/
|
||||
int (*closing)
|
||||
(Plug p, const char *error_msg, int error_code, int calling_back);
|
||||
/* error_msg is NULL iff it is not an error (ie it closed normally) */
|
||||
/* calling_back != 0 iff there is a Plug function */
|
||||
/* currently running (would cure the fixme in try_send()) */
|
||||
int (*receive) (Plug p, int urgent, char *data, int len);
|
||||
/*
|
||||
* - urgent==0. `data' points to `len' bytes of perfectly
|
||||
* ordinary data.
|
||||
*
|
||||
* - urgent==1. `data' points to `len' bytes of data,
|
||||
* which were read from before an Urgent pointer.
|
||||
*
|
||||
* - urgent==2. `data' points to `len' bytes of data,
|
||||
* the first of which was the one at the Urgent mark.
|
||||
*/
|
||||
void (*sent) (Plug p, int bufsize);
|
||||
/*
|
||||
* The `sent' function is called when the pending send backlog
|
||||
* on a socket is cleared or partially cleared. The new backlog
|
||||
* size is passed in the `bufsize' parameter.
|
||||
*/
|
||||
int (*accepting)(Plug p, OSSocket sock);
|
||||
/*
|
||||
* returns 0 if the host at address addr is a valid host for connecting or error
|
||||
*/
|
||||
};
|
||||
|
||||
/* proxy indirection layer */
|
||||
/* NB, control of 'addr' is passed via new_connection, which takes
|
||||
* responsibility for freeing it */
|
||||
Socket new_connection(SockAddr addr, char *hostname,
|
||||
int port, int privport,
|
||||
int oobinline, int nodelay, int keepalive,
|
||||
Plug plug, const Config *cfg);
|
||||
Socket new_listener(char *srcaddr, int port, Plug plug, int local_host_only,
|
||||
const Config *cfg, int addressfamily);
|
||||
SockAddr name_lookup(char *host, int port, char **canonicalname,
|
||||
const Config *cfg, int addressfamily);
|
||||
|
||||
/* platform-dependent callback from new_connection() */
|
||||
/* (same caveat about addr as new_connection()) */
|
||||
Socket platform_new_connection(SockAddr addr, char *hostname,
|
||||
int port, int privport,
|
||||
int oobinline, int nodelay, int keepalive,
|
||||
Plug plug, const Config *cfg);
|
||||
|
||||
/* socket functions */
|
||||
|
||||
void sk_init(void); /* called once at program startup */
|
||||
void sk_cleanup(void); /* called just before program exit */
|
||||
|
||||
SockAddr sk_namelookup(const char *host, char **canonicalname, int address_family);
|
||||
SockAddr sk_nonamelookup(const char *host);
|
||||
void sk_getaddr(SockAddr addr, char *buf, int buflen);
|
||||
int sk_hostname_is_local(char *name);
|
||||
int sk_address_is_local(SockAddr addr);
|
||||
int sk_addrtype(SockAddr addr);
|
||||
void sk_addrcopy(SockAddr addr, char *buf);
|
||||
void sk_addr_free(SockAddr addr);
|
||||
|
||||
/* NB, control of 'addr' is passed via sk_new, which takes responsibility
|
||||
* for freeing it, as for new_connection() */
|
||||
Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
|
||||
int nodelay, int keepalive, Plug p);
|
||||
|
||||
Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only, int address_family);
|
||||
|
||||
Socket sk_register(OSSocket sock, Plug plug);
|
||||
|
||||
#define sk_plug(s,p) (((*s)->plug) (s, p))
|
||||
#define sk_close(s) (((*s)->close) (s))
|
||||
#define sk_write(s,buf,len) (((*s)->write) (s, buf, len))
|
||||
#define sk_write_oob(s,buf,len) (((*s)->write_oob) (s, buf, len))
|
||||
#define sk_flush(s) (((*s)->flush) (s))
|
||||
|
||||
#ifdef DEFINE_PLUG_METHOD_MACROS
|
||||
#define plug_log(p,type,addr,port,msg,code) (((*p)->log) (p, type, addr, port, msg, code))
|
||||
#define plug_closing(p,msg,code,callback) (((*p)->closing) (p, msg, code, callback))
|
||||
#define plug_receive(p,urgent,buf,len) (((*p)->receive) (p, urgent, buf, len))
|
||||
#define plug_sent(p,bufsize) (((*p)->sent) (p, bufsize))
|
||||
#define plug_accepting(p, sock) (((*p)->accepting)(p, sock))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Each socket abstraction contains a `void *' private field in
|
||||
* which the client can keep state.
|
||||
*
|
||||
* This is perhaps unnecessary now that we have the notion of a plug,
|
||||
* but there is some existing code that uses it, so it stays.
|
||||
*/
|
||||
#define sk_set_private_ptr(s, ptr) (((*s)->set_private_ptr) (s, ptr))
|
||||
#define sk_get_private_ptr(s) (((*s)->get_private_ptr) (s))
|
||||
|
||||
/*
|
||||
* Special error values are returned from sk_namelookup and sk_new
|
||||
* if there's a problem. These functions extract an error message,
|
||||
* or return NULL if there's no problem.
|
||||
*/
|
||||
const char *sk_addr_error(SockAddr addr);
|
||||
#define sk_socket_error(s) (((*s)->socket_error) (s))
|
||||
|
||||
/*
|
||||
* Set the `frozen' flag on a socket. A frozen socket is one in
|
||||
* which all READABLE notifications are ignored, so that data is
|
||||
* not accepted from the peer until the socket is unfrozen. This
|
||||
* exists for two purposes:
|
||||
*
|
||||
* - Port forwarding: when a local listening port receives a
|
||||
* connection, we do not want to receive data from the new
|
||||
* socket until we have somewhere to send it. Hence, we freeze
|
||||
* the socket until its associated SSH channel is ready; then we
|
||||
* unfreeze it and pending data is delivered.
|
||||
*
|
||||
* - Socket buffering: if an SSH channel (or the whole connection)
|
||||
* backs up or presents a zero window, we must freeze the
|
||||
* associated local socket in order to avoid unbounded buffer
|
||||
* growth.
|
||||
*/
|
||||
#define sk_set_frozen(s, is_frozen) (((*s)->set_frozen) (s, is_frozen))
|
||||
|
||||
/*
|
||||
* Call this after an operation that might have tried to send on a
|
||||
* socket, to clean up any pending network errors.
|
||||
*/
|
||||
void net_pending_errors(void);
|
||||
|
||||
/*
|
||||
* Simple wrapper on getservbyname(), needed by ssh.c. Returns the
|
||||
* port number, in host byte order (suitable for printf and so on).
|
||||
* Returns 0 on failure. Any platform not supporting getservbyname
|
||||
* can just return 0 - this function is not required to handle
|
||||
* numeric port specifications.
|
||||
*/
|
||||
int net_service_lookup(char *service);
|
||||
|
||||
/********** SSL stuff **********/
|
||||
|
||||
/*
|
||||
* This section is subject to change, but you get the general idea
|
||||
* of what it will eventually look like.
|
||||
*/
|
||||
|
||||
typedef struct certificate *Certificate;
|
||||
typedef struct our_certificate *Our_Certificate;
|
||||
/* to be defined somewhere else, somehow */
|
||||
|
||||
typedef struct ssl_client_socket_function_table **SSL_Client_Socket;
|
||||
typedef struct ssl_client_plug_function_table **SSL_Client_Plug;
|
||||
|
||||
struct ssl_client_socket_function_table {
|
||||
struct socket_function_table base;
|
||||
void (*renegotiate) (SSL_Client_Socket s);
|
||||
/* renegotiate the cipher spec */
|
||||
};
|
||||
|
||||
struct ssl_client_plug_function_table {
|
||||
struct plug_function_table base;
|
||||
int (*refuse_cert) (SSL_Client_Plug p, Certificate cert[]);
|
||||
/* do we accept this certificate chain? If not, why not? */
|
||||
/* cert[0] is the server's certificate, cert[] is NULL-terminated */
|
||||
/* the last certificate may or may not be the root certificate */
|
||||
Our_Certificate(*client_cert) (SSL_Client_Plug p);
|
||||
/* the server wants us to identify ourselves */
|
||||
/* may return NULL if we want anonymity */
|
||||
};
|
||||
|
||||
SSL_Client_Socket sk_ssl_client_over(Socket s, /* pre-existing (tcp) connection */
|
||||
SSL_Client_Plug p);
|
||||
|
||||
#define sk_renegotiate(s) (((*s)->renegotiate) (s))
|
||||
|
||||
#endif
|
||||
71
sFTPlugins/psftp/PINGER.C
Normal file
71
sFTPlugins/psftp/PINGER.C
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* pinger.c: centralised module that deals with sending TS_PING
|
||||
* keepalives, to avoid replicating this code in multiple backends.
|
||||
*/
|
||||
|
||||
#include "putty.h"
|
||||
|
||||
struct pinger_tag {
|
||||
int interval;
|
||||
int pending;
|
||||
long next;
|
||||
Backend *back;
|
||||
void *backhandle;
|
||||
};
|
||||
|
||||
static void pinger_schedule(Pinger pinger);
|
||||
|
||||
static void pinger_timer(void *ctx, long now)
|
||||
{
|
||||
Pinger pinger = (Pinger)ctx;
|
||||
|
||||
if (pinger->pending && now - pinger->next >= 0) {
|
||||
pinger->back->special(pinger->backhandle, TS_PING);
|
||||
pinger->pending = FALSE;
|
||||
pinger_schedule(pinger);
|
||||
}
|
||||
}
|
||||
|
||||
static void pinger_schedule(Pinger pinger)
|
||||
{
|
||||
int next;
|
||||
|
||||
if (!pinger->interval) {
|
||||
pinger->pending = FALSE; /* cancel any pending ping */
|
||||
return;
|
||||
}
|
||||
|
||||
next = schedule_timer(pinger->interval * TICKSPERSEC,
|
||||
pinger_timer, pinger);
|
||||
if (!pinger->pending || next < pinger->next) {
|
||||
pinger->next = next;
|
||||
pinger->pending = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
Pinger pinger_new(Config *cfg, Backend *back, void *backhandle)
|
||||
{
|
||||
Pinger pinger = snew(struct pinger_tag);
|
||||
|
||||
pinger->interval = cfg->ping_interval;
|
||||
pinger->pending = FALSE;
|
||||
pinger->back = back;
|
||||
pinger->backhandle = backhandle;
|
||||
pinger_schedule(pinger);
|
||||
|
||||
return pinger;
|
||||
}
|
||||
|
||||
void pinger_reconfig(Pinger pinger, Config *oldcfg, Config *newcfg)
|
||||
{
|
||||
if (oldcfg->ping_interval != newcfg->ping_interval) {
|
||||
pinger->interval = newcfg->ping_interval;
|
||||
pinger_schedule(pinger);
|
||||
}
|
||||
}
|
||||
|
||||
void pinger_free(Pinger pinger)
|
||||
{
|
||||
expire_timer_context(pinger);
|
||||
sfree(pinger);
|
||||
}
|
||||
555
sFTPlugins/psftp/PORTFWD.C
Normal file
555
sFTPlugins/psftp/PORTFWD.C
Normal file
@@ -0,0 +1,555 @@
|
||||
/*
|
||||
* SSH port forwarding.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "putty.h"
|
||||
#include "ssh.h"
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
struct PFwdPrivate {
|
||||
const struct plug_function_table *fn;
|
||||
/* the above variable absolutely *must* be the first in this structure */
|
||||
void *c; /* (channel) data used by ssh.c */
|
||||
void *backhandle; /* instance of SSH backend itself */
|
||||
/* Note that backhandle need not be filled in if c is non-NULL */
|
||||
Socket s;
|
||||
int throttled, throttle_override;
|
||||
int ready;
|
||||
/*
|
||||
* `dynamic' does double duty. It's set to 0 for an ordinary
|
||||
* forwarded port, and nonzero for SOCKS-style dynamic port
|
||||
* forwarding; but it also represents the state of the SOCKS
|
||||
* exchange.
|
||||
*/
|
||||
int dynamic;
|
||||
/*
|
||||
* `hostname' and `port' are the real hostname and port, once
|
||||
* we know what we're connecting to; they're unused for this
|
||||
* purpose while conducting a local SOCKS exchange, which means
|
||||
* we can also use them as a buffer and pointer for reading
|
||||
* data from the SOCKS client.
|
||||
*/
|
||||
char hostname[256+8];
|
||||
int port;
|
||||
/*
|
||||
* When doing dynamic port forwarding, we can receive
|
||||
* connection data before we are actually able to send it; so
|
||||
* we may have to temporarily hold some in a dynamically
|
||||
* allocated buffer here.
|
||||
*/
|
||||
void *buffer;
|
||||
int buflen;
|
||||
};
|
||||
|
||||
static void pfd_log(Plug plug, int type, SockAddr addr, int port,
|
||||
const char *error_msg, int error_code)
|
||||
{
|
||||
/* we have to dump these since we have no interface to logging.c */
|
||||
}
|
||||
|
||||
static int pfd_closing(Plug plug, const char *error_msg, int error_code,
|
||||
int calling_back)
|
||||
{
|
||||
struct PFwdPrivate *pr = (struct PFwdPrivate *) plug;
|
||||
|
||||
/*
|
||||
* We have no way to communicate down the forwarded connection,
|
||||
* so if an error occurred on the socket, we just ignore it
|
||||
* and treat it like a proper close.
|
||||
*/
|
||||
if (pr->c)
|
||||
sshfwd_close(pr->c);
|
||||
pfd_close(pr->s);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int pfd_receive(Plug plug, int urgent, char *data, int len)
|
||||
{
|
||||
struct PFwdPrivate *pr = (struct PFwdPrivate *) plug;
|
||||
if (pr->dynamic) {
|
||||
while (len--) {
|
||||
/*
|
||||
* Throughout SOCKS negotiation, "hostname" is re-used as a
|
||||
* random protocol buffer with "port" storing the length.
|
||||
*/
|
||||
if (pr->port >= lenof(pr->hostname)) {
|
||||
/* Request too long. */
|
||||
if ((pr->dynamic >> 12) == 4) {
|
||||
/* Send back a SOCKS 4 error before closing. */
|
||||
char data[8];
|
||||
memset(data, 0, sizeof(data));
|
||||
data[1] = 91; /* generic `request rejected' */
|
||||
sk_write(pr->s, data, 8);
|
||||
}
|
||||
pfd_close(pr->s);
|
||||
return 1;
|
||||
}
|
||||
pr->hostname[pr->port++] = *data++;
|
||||
|
||||
/*
|
||||
* Now check what's in the buffer to see if it's a
|
||||
* valid and complete message in the SOCKS exchange.
|
||||
*/
|
||||
if ((pr->dynamic == 1 || (pr->dynamic >> 12) == 4) &&
|
||||
pr->hostname[0] == 4) {
|
||||
/*
|
||||
* SOCKS 4.
|
||||
*/
|
||||
if (pr->dynamic == 1)
|
||||
pr->dynamic = 0x4000;
|
||||
if (pr->port < 2) continue;/* don't have command code yet */
|
||||
if (pr->hostname[1] != 1) {
|
||||
/* Not CONNECT. */
|
||||
/* Send back a SOCKS 4 error before closing. */
|
||||
char data[8];
|
||||
memset(data, 0, sizeof(data));
|
||||
data[1] = 91; /* generic `request rejected' */
|
||||
sk_write(pr->s, data, 8);
|
||||
pfd_close(pr->s);
|
||||
return 1;
|
||||
}
|
||||
if (pr->port <= 8) continue; /* haven't started user/hostname */
|
||||
if (pr->hostname[pr->port-1] != 0)
|
||||
continue; /* haven't _finished_ user/hostname */
|
||||
/*
|
||||
* Now we have a full SOCKS 4 request. Check it to
|
||||
* see if it's a SOCKS 4A request.
|
||||
*/
|
||||
if (pr->hostname[4] == 0 && pr->hostname[5] == 0 &&
|
||||
pr->hostname[6] == 0 && pr->hostname[7] != 0) {
|
||||
/*
|
||||
* It's SOCKS 4A. So if we haven't yet
|
||||
* collected the host name, we should continue
|
||||
* waiting for data in order to do so; if we
|
||||
* have, we can go ahead.
|
||||
*/
|
||||
int len;
|
||||
if (pr->dynamic == 0x4000) {
|
||||
pr->dynamic = 0x4001;
|
||||
pr->port = 8; /* reset buffer to overwrite name */
|
||||
continue;
|
||||
}
|
||||
pr->hostname[0] = 0; /* reply version code */
|
||||
pr->hostname[1] = 90; /* request granted */
|
||||
sk_write(pr->s, pr->hostname, 8);
|
||||
len= pr->port - 8;
|
||||
pr->port = GET_16BIT_MSB_FIRST(pr->hostname+2);
|
||||
memmove(pr->hostname, pr->hostname + 8, len);
|
||||
goto connect;
|
||||
} else {
|
||||
/*
|
||||
* It's SOCKS 4, which means we should format
|
||||
* the IP address into the hostname string and
|
||||
* then just go.
|
||||
*/
|
||||
pr->hostname[0] = 0; /* reply version code */
|
||||
pr->hostname[1] = 90; /* request granted */
|
||||
sk_write(pr->s, pr->hostname, 8);
|
||||
pr->port = GET_16BIT_MSB_FIRST(pr->hostname+2);
|
||||
sprintf(pr->hostname, "%d.%d.%d.%d",
|
||||
(unsigned char)pr->hostname[4],
|
||||
(unsigned char)pr->hostname[5],
|
||||
(unsigned char)pr->hostname[6],
|
||||
(unsigned char)pr->hostname[7]);
|
||||
goto connect;
|
||||
}
|
||||
}
|
||||
|
||||
if ((pr->dynamic == 1 || (pr->dynamic >> 12) == 5) &&
|
||||
pr->hostname[0] == 5) {
|
||||
/*
|
||||
* SOCKS 5.
|
||||
*/
|
||||
if (pr->dynamic == 1)
|
||||
pr->dynamic = 0x5000;
|
||||
|
||||
if (pr->dynamic == 0x5000) {
|
||||
int i, method;
|
||||
char data[2];
|
||||
/*
|
||||
* We're receiving a set of method identifiers.
|
||||
*/
|
||||
if (pr->port < 2) continue;/* no method count yet */
|
||||
if (pr->port < 2 + (unsigned char)pr->hostname[1])
|
||||
continue; /* no methods yet */
|
||||
method = 0xFF; /* invalid */
|
||||
for (i = 0; i < (unsigned char)pr->hostname[1]; i++)
|
||||
if (pr->hostname[2+i] == 0) {
|
||||
method = 0;/* no auth */
|
||||
break;
|
||||
}
|
||||
data[0] = 5;
|
||||
data[1] = method;
|
||||
sk_write(pr->s, data, 2);
|
||||
pr->dynamic = 0x5001;
|
||||
pr->port = 0; /* re-empty the buffer */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (pr->dynamic == 0x5001) {
|
||||
/*
|
||||
* We're receiving a SOCKS request.
|
||||
*/
|
||||
unsigned char reply[10]; /* SOCKS5 atyp=1 reply */
|
||||
int atype, alen = 0;
|
||||
|
||||
/*
|
||||
* Pre-fill reply packet.
|
||||
* In all cases, we set BND.{HOST,ADDR} to 0.0.0.0:0
|
||||
* (atyp=1) in the reply; if we succeed, we don't know
|
||||
* the right answers, and if we fail, they should be
|
||||
* ignored.
|
||||
*/
|
||||
memset(reply, 0, lenof(reply));
|
||||
reply[0] = 5; /* VER */
|
||||
reply[3] = 1; /* ATYP = 1 (IPv4, 0.0.0.0:0) */
|
||||
|
||||
if (pr->port < 6) continue;
|
||||
atype = (unsigned char)pr->hostname[3];
|
||||
if (atype == 1) /* IPv4 address */
|
||||
alen = 4;
|
||||
if (atype == 4) /* IPv6 address */
|
||||
alen = 16;
|
||||
if (atype == 3) /* domain name has leading length */
|
||||
alen = 1 + (unsigned char)pr->hostname[4];
|
||||
if (pr->port < 6 + alen) continue;
|
||||
if (pr->hostname[1] != 1 || pr->hostname[2] != 0) {
|
||||
/* Not CONNECT or reserved field nonzero - error */
|
||||
reply[1] = 1; /* generic failure */
|
||||
sk_write(pr->s, (char *) reply, lenof(reply));
|
||||
pfd_close(pr->s);
|
||||
return 1;
|
||||
}
|
||||
/*
|
||||
* Now we have a viable connect request. Switch
|
||||
* on atype.
|
||||
*/
|
||||
pr->port = GET_16BIT_MSB_FIRST(pr->hostname+4+alen);
|
||||
if (atype == 1) {
|
||||
/* REP=0 (success) already */
|
||||
sk_write(pr->s, (char *) reply, lenof(reply));
|
||||
sprintf(pr->hostname, "%d.%d.%d.%d",
|
||||
(unsigned char)pr->hostname[4],
|
||||
(unsigned char)pr->hostname[5],
|
||||
(unsigned char)pr->hostname[6],
|
||||
(unsigned char)pr->hostname[7]);
|
||||
goto connect;
|
||||
} else if (atype == 3) {
|
||||
/* REP=0 (success) already */
|
||||
sk_write(pr->s, (char *) reply, lenof(reply));
|
||||
memmove(pr->hostname, pr->hostname + 5, alen-1);
|
||||
pr->hostname[alen-1] = '\0';
|
||||
goto connect;
|
||||
} else {
|
||||
/*
|
||||
* Unknown address type. (FIXME: support IPv6!)
|
||||
*/
|
||||
reply[1] = 8; /* atype not supported */
|
||||
sk_write(pr->s, (char *) reply, lenof(reply));
|
||||
pfd_close(pr->s);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If we get here without either having done `continue'
|
||||
* or `goto connect', it must be because there is no
|
||||
* sensible interpretation of what's in our buffer. So
|
||||
* close the connection rudely.
|
||||
*/
|
||||
pfd_close(pr->s);
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* We come here when we're ready to make an actual
|
||||
* connection.
|
||||
*/
|
||||
connect:
|
||||
|
||||
pr->c = new_sock_channel(pr->backhandle, pr->s);
|
||||
if (pr->c == NULL) {
|
||||
pfd_close(pr->s);
|
||||
return 1;
|
||||
} else {
|
||||
/* asks to forward to the specified host/port for this */
|
||||
ssh_send_port_open(pr->c, pr->hostname, pr->port, "forwarding");
|
||||
}
|
||||
pr->dynamic = 0;
|
||||
|
||||
/*
|
||||
* Now freeze the socket until the SSH server confirms the
|
||||
* connection.
|
||||
*/
|
||||
sk_set_frozen(pr->s, 1);
|
||||
/*
|
||||
* If there's any data remaining in our current buffer,
|
||||
* save it to be sent on pfd_confirm().
|
||||
*/
|
||||
if (len > 0) {
|
||||
pr->buffer = snewn(len, char);
|
||||
memcpy(pr->buffer, data, len);
|
||||
pr->buflen = len;
|
||||
}
|
||||
}
|
||||
if (pr->ready) {
|
||||
if (sshfwd_write(pr->c, data, len) > 0) {
|
||||
pr->throttled = 1;
|
||||
sk_set_frozen(pr->s, 1);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void pfd_sent(Plug plug, int bufsize)
|
||||
{
|
||||
struct PFwdPrivate *pr = (struct PFwdPrivate *) plug;
|
||||
|
||||
if (pr->c)
|
||||
sshfwd_unthrottle(pr->c, bufsize);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called when receiving a PORT OPEN from the server
|
||||
*/
|
||||
const char *pfd_newconnect(Socket *s, char *hostname, int port,
|
||||
void *c, const Config *cfg, int addressfamily)
|
||||
{
|
||||
static const struct plug_function_table fn_table = {
|
||||
pfd_log,
|
||||
pfd_closing,
|
||||
pfd_receive,
|
||||
pfd_sent,
|
||||
NULL
|
||||
};
|
||||
|
||||
SockAddr addr;
|
||||
const char *err;
|
||||
char *dummy_realhost;
|
||||
struct PFwdPrivate *pr;
|
||||
|
||||
/*
|
||||
* Try to find host.
|
||||
*/
|
||||
addr = name_lookup(hostname, port, &dummy_realhost, cfg, addressfamily);
|
||||
if ((err = sk_addr_error(addr)) != NULL) {
|
||||
sk_addr_free(addr);
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Open socket.
|
||||
*/
|
||||
pr = snew(struct PFwdPrivate);
|
||||
pr->buffer = NULL;
|
||||
pr->fn = &fn_table;
|
||||
pr->throttled = pr->throttle_override = 0;
|
||||
pr->ready = 1;
|
||||
pr->c = c;
|
||||
pr->backhandle = NULL; /* we shouldn't need this */
|
||||
pr->dynamic = 0;
|
||||
|
||||
pr->s = *s = new_connection(addr, dummy_realhost, port,
|
||||
0, 1, 0, 0, (Plug) pr, cfg);
|
||||
if ((err = sk_socket_error(*s)) != NULL) {
|
||||
sfree(pr);
|
||||
return err;
|
||||
}
|
||||
|
||||
sk_set_private_ptr(*s, pr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
called when someone connects to the local port
|
||||
*/
|
||||
|
||||
static int pfd_accepting(Plug p, OSSocket sock)
|
||||
{
|
||||
static const struct plug_function_table fn_table = {
|
||||
pfd_log,
|
||||
pfd_closing,
|
||||
pfd_receive,
|
||||
pfd_sent,
|
||||
NULL
|
||||
};
|
||||
struct PFwdPrivate *pr, *org;
|
||||
Socket s;
|
||||
const char *err;
|
||||
|
||||
org = (struct PFwdPrivate *)p;
|
||||
pr = snew(struct PFwdPrivate);
|
||||
pr->buffer = NULL;
|
||||
pr->fn = &fn_table;
|
||||
|
||||
pr->c = NULL;
|
||||
pr->backhandle = org->backhandle;
|
||||
|
||||
pr->s = s = sk_register(sock, (Plug) pr);
|
||||
if ((err = sk_socket_error(s)) != NULL) {
|
||||
sfree(pr);
|
||||
return err != NULL;
|
||||
}
|
||||
|
||||
sk_set_private_ptr(s, pr);
|
||||
|
||||
pr->throttled = pr->throttle_override = 0;
|
||||
pr->ready = 0;
|
||||
|
||||
if (org->dynamic) {
|
||||
pr->dynamic = 1;
|
||||
pr->port = 0; /* "hostname" buffer is so far empty */
|
||||
sk_set_frozen(s, 0); /* we want to receive SOCKS _now_! */
|
||||
} else {
|
||||
pr->dynamic = 0;
|
||||
strcpy(pr->hostname, org->hostname);
|
||||
pr->port = org->port;
|
||||
pr->c = new_sock_channel(org->backhandle, s);
|
||||
|
||||
if (pr->c == NULL) {
|
||||
sfree(pr);
|
||||
return 1;
|
||||
} else {
|
||||
/* asks to forward to the specified host/port for this */
|
||||
ssh_send_port_open(pr->c, pr->hostname, pr->port, "forwarding");
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Add a new forwarding from port -> desthost:destport
|
||||
sets up a listener on the local machine on (srcaddr:)port
|
||||
*/
|
||||
const char *pfd_addforward(char *desthost, int destport, char *srcaddr,
|
||||
int port, void *backhandle, const Config *cfg,
|
||||
void **sockdata, int address_family)
|
||||
{
|
||||
static const struct plug_function_table fn_table = {
|
||||
pfd_log,
|
||||
pfd_closing,
|
||||
pfd_receive, /* should not happen... */
|
||||
pfd_sent, /* also should not happen */
|
||||
pfd_accepting
|
||||
};
|
||||
|
||||
const char *err;
|
||||
struct PFwdPrivate *pr;
|
||||
Socket s;
|
||||
|
||||
/*
|
||||
* Open socket.
|
||||
*/
|
||||
pr = snew(struct PFwdPrivate);
|
||||
pr->buffer = NULL;
|
||||
pr->fn = &fn_table;
|
||||
pr->c = NULL;
|
||||
if (desthost) {
|
||||
strcpy(pr->hostname, desthost);
|
||||
pr->port = destport;
|
||||
pr->dynamic = 0;
|
||||
} else
|
||||
pr->dynamic = 1;
|
||||
pr->throttled = pr->throttle_override = 0;
|
||||
pr->ready = 0;
|
||||
pr->backhandle = backhandle;
|
||||
|
||||
pr->s = s = new_listener(srcaddr, port, (Plug) pr,
|
||||
!cfg->lport_acceptall, cfg, address_family);
|
||||
if ((err = sk_socket_error(s)) != NULL) {
|
||||
sfree(pr);
|
||||
return err;
|
||||
}
|
||||
|
||||
sk_set_private_ptr(s, pr);
|
||||
|
||||
*sockdata = (void *)s;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void pfd_close(Socket s)
|
||||
{
|
||||
struct PFwdPrivate *pr;
|
||||
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
pr = (struct PFwdPrivate *) sk_get_private_ptr(s);
|
||||
|
||||
sfree(pr->buffer);
|
||||
sfree(pr);
|
||||
|
||||
sk_close(s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Terminate a listener.
|
||||
*/
|
||||
void pfd_terminate(void *sv)
|
||||
{
|
||||
pfd_close((Socket)sv);
|
||||
}
|
||||
|
||||
void pfd_unthrottle(Socket s)
|
||||
{
|
||||
struct PFwdPrivate *pr;
|
||||
if (!s)
|
||||
return;
|
||||
pr = (struct PFwdPrivate *) sk_get_private_ptr(s);
|
||||
|
||||
pr->throttled = 0;
|
||||
sk_set_frozen(s, pr->throttled || pr->throttle_override);
|
||||
}
|
||||
|
||||
void pfd_override_throttle(Socket s, int enable)
|
||||
{
|
||||
struct PFwdPrivate *pr;
|
||||
if (!s)
|
||||
return;
|
||||
pr = (struct PFwdPrivate *) sk_get_private_ptr(s);
|
||||
|
||||
pr->throttle_override = enable;
|
||||
sk_set_frozen(s, pr->throttled || pr->throttle_override);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called to send data down the raw connection.
|
||||
*/
|
||||
int pfd_send(Socket s, char *data, int len)
|
||||
{
|
||||
if (s == NULL)
|
||||
return 0;
|
||||
return sk_write(s, data, len);
|
||||
}
|
||||
|
||||
|
||||
void pfd_confirm(Socket s)
|
||||
{
|
||||
struct PFwdPrivate *pr;
|
||||
|
||||
if (s == NULL)
|
||||
return;
|
||||
|
||||
pr = (struct PFwdPrivate *) sk_get_private_ptr(s);
|
||||
pr->ready = 1;
|
||||
sk_set_frozen(s, 0);
|
||||
sk_write(s, NULL, 0);
|
||||
if (pr->buffer) {
|
||||
sshfwd_write(pr->c, pr->buffer, pr->buflen);
|
||||
sfree(pr->buffer);
|
||||
pr->buffer = NULL;
|
||||
}
|
||||
}
|
||||
1478
sFTPlugins/psftp/PROXY.C
Normal file
1478
sFTPlugins/psftp/PROXY.C
Normal file
File diff suppressed because it is too large
Load Diff
123
sFTPlugins/psftp/PROXY.H
Normal file
123
sFTPlugins/psftp/PROXY.H
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Network proxy abstraction in PuTTY
|
||||
*
|
||||
* A proxy layer, if necessary, wedges itself between the
|
||||
* network code and the higher level backend.
|
||||
*
|
||||
* Supported proxies: HTTP CONNECT, generic telnet, SOCKS 4 & 5
|
||||
*/
|
||||
|
||||
#ifndef PUTTY_PROXY_H
|
||||
#define PUTTY_PROXY_H
|
||||
|
||||
#define PROXY_ERROR_GENERAL 8000
|
||||
#define PROXY_ERROR_UNEXPECTED 8001
|
||||
|
||||
typedef struct Socket_proxy_tag * Proxy_Socket;
|
||||
|
||||
struct Socket_proxy_tag {
|
||||
const struct socket_function_table *fn;
|
||||
/* the above variable absolutely *must* be the first in this structure */
|
||||
|
||||
char * error;
|
||||
|
||||
Socket sub_socket;
|
||||
Plug plug;
|
||||
SockAddr remote_addr;
|
||||
int remote_port;
|
||||
|
||||
bufchain pending_output_data;
|
||||
bufchain pending_oob_output_data;
|
||||
int pending_flush;
|
||||
bufchain pending_input_data;
|
||||
|
||||
#define PROXY_STATE_NEW -1
|
||||
#define PROXY_STATE_ACTIVE 0
|
||||
|
||||
int state; /* proxy states greater than 0 are implementation
|
||||
* dependent, but represent various stages/states
|
||||
* of the initialization/setup/negotiation with the
|
||||
* proxy server.
|
||||
*/
|
||||
int freeze; /* should we freeze the underlying socket when
|
||||
* we are done with the proxy negotiation? this
|
||||
* simply caches the value of sk_set_frozen calls.
|
||||
*/
|
||||
|
||||
#define PROXY_CHANGE_NEW -1
|
||||
#define PROXY_CHANGE_CLOSING 0
|
||||
#define PROXY_CHANGE_SENT 1
|
||||
#define PROXY_CHANGE_RECEIVE 2
|
||||
#define PROXY_CHANGE_ACCEPTING 3
|
||||
|
||||
/* something has changed (a call from the sub socket
|
||||
* layer into our Proxy Plug layer, or we were just
|
||||
* created, etc), so the proxy layer needs to handle
|
||||
* this change (the type of which is the second argument)
|
||||
* and further the proxy negotiation process.
|
||||
*/
|
||||
|
||||
int (*negotiate) (Proxy_Socket /* this */, int /* change type */);
|
||||
|
||||
/* current arguments of plug handlers
|
||||
* (for use by proxy's negotiate function)
|
||||
*/
|
||||
|
||||
/* closing */
|
||||
const char *closing_error_msg;
|
||||
int closing_error_code;
|
||||
int closing_calling_back;
|
||||
|
||||
/* receive */
|
||||
int receive_urgent;
|
||||
char *receive_data;
|
||||
int receive_len;
|
||||
|
||||
/* sent */
|
||||
int sent_bufsize;
|
||||
|
||||
/* accepting */
|
||||
OSSocket accepting_sock;
|
||||
|
||||
/* configuration, used to look up proxy settings */
|
||||
Config cfg;
|
||||
|
||||
/* CHAP transient data */
|
||||
int chap_num_attributes;
|
||||
int chap_num_attributes_processed;
|
||||
int chap_current_attribute;
|
||||
int chap_current_datalen;
|
||||
};
|
||||
|
||||
typedef struct Plug_proxy_tag * Proxy_Plug;
|
||||
|
||||
struct Plug_proxy_tag {
|
||||
const struct plug_function_table *fn;
|
||||
/* the above variable absolutely *must* be the first in this structure */
|
||||
|
||||
Proxy_Socket proxy_socket;
|
||||
|
||||
};
|
||||
|
||||
extern void proxy_activate (Proxy_Socket);
|
||||
|
||||
extern int proxy_http_negotiate (Proxy_Socket, int);
|
||||
extern int proxy_telnet_negotiate (Proxy_Socket, int);
|
||||
extern int proxy_socks4_negotiate (Proxy_Socket, int);
|
||||
extern int proxy_socks5_negotiate (Proxy_Socket, int);
|
||||
|
||||
/*
|
||||
* This may be reused by local-command proxies on individual
|
||||
* platforms.
|
||||
*/
|
||||
char *format_telnet_command(SockAddr addr, int port, const Config *cfg);
|
||||
|
||||
/*
|
||||
* These are implemented in cproxy.c or nocproxy.c, depending on
|
||||
* whether encrypted proxy authentication is available.
|
||||
*/
|
||||
extern void proxy_socks5_offerencryptedauth(char *command, int *len);
|
||||
extern int proxy_socks5_handlechap (Proxy_Socket p);
|
||||
extern int proxy_socks5_selectchap(Proxy_Socket p);
|
||||
|
||||
#endif
|
||||
3002
sFTPlugins/psftp/PSFTP.C
Normal file
3002
sFTPlugins/psftp/PSFTP.C
Normal file
File diff suppressed because it is too large
Load Diff
178
sFTPlugins/psftp/PSFTP.H
Normal file
178
sFTPlugins/psftp/PSFTP.H
Normal file
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* psftp.h: interface between psftp.c / scp.c and each
|
||||
* platform-specific SFTP module.
|
||||
*/
|
||||
|
||||
#include "int64.h"
|
||||
|
||||
#ifndef PUTTY_PSFTP_H
|
||||
#define PUTTY_PSFTP_H
|
||||
|
||||
/*
|
||||
* psftp_getcwd returns the local current directory. The returned
|
||||
* string must be freed by the caller.
|
||||
*/
|
||||
char *psftp_getcwd(void);
|
||||
|
||||
/*
|
||||
* psftp_lcd changes the local current directory. The return value
|
||||
* is NULL on success, or else an error message which must be freed
|
||||
* by the caller.
|
||||
*/
|
||||
char *psftp_lcd(char *newdir);
|
||||
|
||||
/*
|
||||
* Retrieve file times on a local file. Must return two unsigned
|
||||
* longs in POSIX time_t format.
|
||||
*/
|
||||
void get_file_times(char *filename, unsigned long *mtime,
|
||||
unsigned long *atime);
|
||||
|
||||
/*
|
||||
* One iteration of the PSFTP event loop: wait for network data and
|
||||
* process it, once.
|
||||
*/
|
||||
int ssh_sftp_loop_iteration(void);
|
||||
|
||||
/*
|
||||
* Read a command line for PSFTP from standard input. Caller must
|
||||
* free.
|
||||
*
|
||||
* If `backend_required' is TRUE, should also listen for activity
|
||||
* at the backend (rekeys, clientalives, unexpected closures etc)
|
||||
* and respond as necessary, and if the backend closes it should
|
||||
* treat this as a failure condition. If `backend_required' is
|
||||
* FALSE, a back end is not (intentionally) active at all (e.g.
|
||||
* psftp before an `open' command).
|
||||
*/
|
||||
char *ssh_sftp_get_cmdline(char *prompt, int backend_required);
|
||||
|
||||
/*
|
||||
* The main program in psftp.c. Called from main() in the platform-
|
||||
* specific code, after doing any platform-specific initialisation.
|
||||
*/
|
||||
int psftp_main(int argc, char *argv[]);
|
||||
|
||||
/*
|
||||
* These functions are used by PSCP to transmit progress updates
|
||||
* and error information to a GUI window managing it. This will
|
||||
* probably only ever be supported on Windows, so these functions
|
||||
* can safely be stubs on all other platforms.
|
||||
*/
|
||||
void gui_update_stats(char *name, unsigned long size,
|
||||
int percentage, unsigned long elapsed,
|
||||
unsigned long done, unsigned long eta,
|
||||
unsigned long ratebs);
|
||||
void gui_send_errcount(int list, int errs);
|
||||
void gui_send_char(int is_stderr, int c);
|
||||
void gui_enable(char *arg);
|
||||
|
||||
/*
|
||||
* It's likely that a given platform's implementation of file
|
||||
* transfer utilities is going to want to do things with them that
|
||||
* aren't present in stdio. Hence we supply an alternative
|
||||
* abstraction for file access functions.
|
||||
*
|
||||
* This abstraction tells you the size and access times when you
|
||||
* open an existing file (platforms may choose the meaning of the
|
||||
* file times if it's not clear; whatever they choose will be what
|
||||
* PSCP sends to the server as mtime and atime), and lets you set
|
||||
* the times when saving a new file.
|
||||
*
|
||||
* On the other hand, the abstraction is pretty simple: it supports
|
||||
* only opening a file and reading it, or creating a file and writing
|
||||
* it. None of this read-and-write, seeking-back-and-forth stuff.
|
||||
*/
|
||||
typedef struct RFile RFile;
|
||||
typedef struct WFile WFile;
|
||||
/* Output params size, mtime and atime can all be NULL if desired */
|
||||
RFile *open_existing_file(char *name, uint64 *size,
|
||||
unsigned long *mtime, unsigned long *atime);
|
||||
WFile *open_existing_wfile(char *name, uint64 *size);
|
||||
/* Returns <0 on error, 0 on eof, or number of bytes read, as usual */
|
||||
int read_from_file(RFile *f, void *buffer, int length);
|
||||
/* Closes and frees the RFile */
|
||||
void close_rfile(RFile *f);
|
||||
WFile *open_new_file(char *name);
|
||||
/* Returns <0 on error, 0 on eof, or number of bytes written, as usual */
|
||||
int write_to_file(WFile *f, void *buffer, int length);
|
||||
void set_file_times(WFile *f, unsigned long mtime, unsigned long atime);
|
||||
/* Closes and frees the WFile */
|
||||
void close_wfile(WFile *f);
|
||||
/* Seek offset bytes through file */
|
||||
enum { FROM_START, FROM_CURRENT, FROM_END };
|
||||
int seek_file(WFile *f, uint64 offset, int whence);
|
||||
/* Get file position */
|
||||
uint64 get_file_posn(WFile *f);
|
||||
/*
|
||||
* Determine the type of a file: nonexistent, file, directory or
|
||||
* weird. `weird' covers anything else - named pipes, Unix sockets,
|
||||
* device files, fish, badgers, you name it. Things marked `weird'
|
||||
* will be skipped over in recursive file transfers, so the only
|
||||
* real reason for not lumping them in with `nonexistent' is that
|
||||
* it allows a slightly more sane error message.
|
||||
*/
|
||||
enum {
|
||||
FILE_TYPE_NONEXISTENT, FILE_TYPE_FILE, FILE_TYPE_DIRECTORY, FILE_TYPE_WEIRD
|
||||
};
|
||||
int file_type(char *name);
|
||||
|
||||
/*
|
||||
* Read all the file names out of a directory.
|
||||
*/
|
||||
typedef struct DirHandle DirHandle;
|
||||
DirHandle *open_directory(char *name);
|
||||
/* The string returned from this will need freeing if not NULL */
|
||||
char *read_filename(DirHandle *dir);
|
||||
void close_directory(DirHandle *dir);
|
||||
|
||||
/*
|
||||
* Test a filespec to see whether it's a local wildcard or not.
|
||||
* Return values:
|
||||
*
|
||||
* - WCTYPE_WILDCARD (this is a wildcard).
|
||||
* - WCTYPE_FILENAME (this is a single file name).
|
||||
* - WCTYPE_NONEXISTENT (whichever it was, nothing of that name exists).
|
||||
*
|
||||
* Some platforms may choose not to support local wildcards when
|
||||
* they come from the command line; in this case they simply never
|
||||
* return WCTYPE_WILDCARD, but still test the file's existence.
|
||||
* (However, all platforms will probably want to support wildcards
|
||||
* inside the PSFTP CLI.)
|
||||
*/
|
||||
enum {
|
||||
WCTYPE_NONEXISTENT, WCTYPE_FILENAME, WCTYPE_WILDCARD
|
||||
};
|
||||
int test_wildcard(char *name, int cmdline);
|
||||
|
||||
/*
|
||||
* Actually return matching file names for a local wildcard.
|
||||
*/
|
||||
typedef struct WildcardMatcher WildcardMatcher;
|
||||
WildcardMatcher *begin_wildcard_matching(char *name);
|
||||
/* The string returned from this will need freeing if not NULL */
|
||||
char *wildcard_get_filename(WildcardMatcher *dir);
|
||||
void finish_wildcard_matching(WildcardMatcher *dir);
|
||||
|
||||
/*
|
||||
* Vet a filename returned from the remote host, to ensure it isn't
|
||||
* in some way malicious. The idea is that this function is applied
|
||||
* to filenames returned from FXP_READDIR, which means we can panic
|
||||
* if we see _anything_ resembling a directory separator.
|
||||
*
|
||||
* Returns TRUE if the filename is kosher, FALSE if dangerous.
|
||||
*/
|
||||
int vet_filename(char *name);
|
||||
|
||||
/*
|
||||
* Create a directory. Returns 0 on error, !=0 on success.
|
||||
*/
|
||||
int create_directory(char *name);
|
||||
|
||||
/*
|
||||
* Concatenate a directory name and a file name. The way this is
|
||||
* done will depend on the OS.
|
||||
*/
|
||||
char *dir_file_cat(char *dir, char *file);
|
||||
|
||||
#endif /* PUTTY_PSFTP_H */
|
||||
1214
sFTPlugins/psftp/PUTTY.H
Normal file
1214
sFTPlugins/psftp/PUTTY.H
Normal file
File diff suppressed because it is too large
Load Diff
42
sFTPlugins/psftp/PUTTYMEM.H
Normal file
42
sFTPlugins/psftp/PUTTYMEM.H
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* PuTTY memory-handling header.
|
||||
*/
|
||||
|
||||
#ifndef PUTTY_PUTTYMEM_H
|
||||
#define PUTTY_PUTTYMEM_H
|
||||
|
||||
#include <stddef.h> /* for size_t */
|
||||
#include <string.h> /* for memcpy() */
|
||||
|
||||
|
||||
/* #define MALLOC_LOG do this if you suspect putty of leaking memory */
|
||||
#ifdef MALLOC_LOG
|
||||
#define smalloc(z) (mlog(__FILE__,__LINE__), safemalloc(z,1))
|
||||
#define snmalloc(z,s) (mlog(__FILE__,__LINE__), safemalloc(z,s))
|
||||
#define srealloc(y,z) (mlog(__FILE__,__LINE__), saferealloc(y,z,1))
|
||||
#define snrealloc(y,z,s) (mlog(__FILE__,__LINE__), saferealloc(y,z,s))
|
||||
#define sfree(z) (mlog(__FILE__,__LINE__), safefree(z))
|
||||
void mlog(char *, int);
|
||||
#else
|
||||
#define smalloc(z) safemalloc(z,1)
|
||||
#define snmalloc safemalloc
|
||||
#define srealloc(y,z) saferealloc(y,z,1)
|
||||
#define snrealloc saferealloc
|
||||
#define sfree safefree
|
||||
#endif
|
||||
|
||||
void *safemalloc(size_t, size_t);
|
||||
void *saferealloc(void *, size_t, size_t);
|
||||
void safefree(void *);
|
||||
|
||||
/*
|
||||
* Direct use of smalloc within the code should be avoided where
|
||||
* possible, in favour of these type-casting macros which ensure
|
||||
* you don't mistakenly allocate enough space for one sort of
|
||||
* structure and assign it to a different sort of pointer.
|
||||
*/
|
||||
#define snew(type) ((type *)snmalloc(1, sizeof(type)))
|
||||
#define snewn(n, type) ((type *)snmalloc((n), sizeof(type)))
|
||||
#define sresize(ptr, n, type) ((type *)snrealloc((ptr), (n), sizeof(type)))
|
||||
|
||||
#endif
|
||||
26
sFTPlugins/psftp/PUTTYPS.H
Normal file
26
sFTPlugins/psftp/PUTTYPS.H
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Find the platform-specific header for this platform.
|
||||
*/
|
||||
|
||||
#ifndef PUTTY_PUTTYPS_H
|
||||
#define PUTTY_PUTTYPS_H
|
||||
|
||||
#ifdef _WINDOWS
|
||||
|
||||
#include "winstuff.h"
|
||||
|
||||
#elif defined(macintosh)
|
||||
|
||||
#include "macstuff.h"
|
||||
|
||||
#elif defined(MACOSX)
|
||||
|
||||
#include "osx.h"
|
||||
|
||||
#else
|
||||
|
||||
#include "unix.h"
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
869
sFTPlugins/psftp/SETTINGS.C
Normal file
869
sFTPlugins/psftp/SETTINGS.C
Normal file
@@ -0,0 +1,869 @@
|
||||
/*
|
||||
* settings.c: read and write saved sessions. (platform-independent)
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "putty.h"
|
||||
#include "storage.h"
|
||||
|
||||
/*
|
||||
* Tables of string <-> enum value mappings
|
||||
*/
|
||||
struct keyval { char *s; int v; };
|
||||
|
||||
/* The cipher order given here is the default order. */
|
||||
static const struct keyval ciphernames[] = {
|
||||
{ "aes", CIPHER_AES },
|
||||
{ "blowfish", CIPHER_BLOWFISH },
|
||||
{ "3des", CIPHER_3DES },
|
||||
{ "WARN", CIPHER_WARN },
|
||||
{ "arcfour", CIPHER_ARCFOUR },
|
||||
{ "des", CIPHER_DES }
|
||||
};
|
||||
|
||||
static const struct keyval kexnames[] = {
|
||||
{ "dh-gex-sha1", KEX_DHGEX },
|
||||
{ "dh-group14-sha1", KEX_DHGROUP14 },
|
||||
{ "dh-group1-sha1", KEX_DHGROUP1 },
|
||||
{ "WARN", KEX_WARN }
|
||||
};
|
||||
|
||||
/*
|
||||
* All the terminal modes that we know about for the "TerminalModes"
|
||||
* setting. (Also used by config.c for the drop-down list.)
|
||||
* This is currently precisely the same as the set in ssh.c, but could
|
||||
* in principle differ if other backends started to support tty modes
|
||||
* (e.g., the pty backend).
|
||||
*/
|
||||
const char *const ttymodes[] = {
|
||||
"INTR", "QUIT", "ERASE", "KILL", "EOF",
|
||||
"EOL", "EOL2", "START", "STOP", "SUSP",
|
||||
"DSUSP", "REPRINT", "WERASE", "LNEXT", "FLUSH",
|
||||
"SWTCH", "STATUS", "DISCARD", "IGNPAR", "PARMRK",
|
||||
"INPCK", "ISTRIP", "INLCR", "IGNCR", "ICRNL",
|
||||
"IUCLC", "IXON", "IXANY", "IXOFF", "IMAXBEL",
|
||||
"ISIG", "ICANON", "XCASE", "ECHO", "ECHOE",
|
||||
"ECHOK", "ECHONL", "NOFLSH", "TOSTOP", "IEXTEN",
|
||||
"ECHOCTL", "ECHOKE", "PENDIN", "OPOST", "OLCUC",
|
||||
"ONLCR", "OCRNL", "ONOCR", "ONLRET", "CS7",
|
||||
"CS8", "PARENB", "PARODD", NULL
|
||||
};
|
||||
|
||||
static void gpps(void *handle, const char *name, const char *def,
|
||||
char *val, int len)
|
||||
{
|
||||
if (!read_setting_s(handle, name, val, len)) {
|
||||
char *pdef;
|
||||
|
||||
pdef = platform_default_s(name);
|
||||
if (pdef) {
|
||||
strncpy(val, pdef, len);
|
||||
sfree(pdef);
|
||||
} else {
|
||||
strncpy(val, def, len);
|
||||
}
|
||||
|
||||
val[len - 1] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* gppfont and gppfile cannot have local defaults, since the very
|
||||
* format of a Filename or Font is platform-dependent. So the
|
||||
* platform-dependent functions MUST return some sort of value.
|
||||
*/
|
||||
static void gppfont(void *handle, const char *name, FontSpec *result)
|
||||
{
|
||||
if (!read_setting_fontspec(handle, name, result))
|
||||
*result = platform_default_fontspec(name);
|
||||
}
|
||||
static void gppfile(void *handle, const char *name, Filename *result)
|
||||
{
|
||||
if (!read_setting_filename(handle, name, result))
|
||||
*result = platform_default_filename(name);
|
||||
}
|
||||
|
||||
static void gppi(void *handle, char *name, int def, int *i)
|
||||
{
|
||||
def = platform_default_i(name, def);
|
||||
*i = read_setting_i(handle, name, def);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a set of name-value pairs in the format we occasionally use:
|
||||
* NAME\tVALUE\0NAME\tVALUE\0\0 in memory
|
||||
* NAME=VALUE,NAME=VALUE, in storage
|
||||
* `def' is in the storage format.
|
||||
*/
|
||||
static void gppmap(void *handle, char *name, char *def, char *val, int len)
|
||||
{
|
||||
char *buf = snewn(2*len, char), *p, *q;
|
||||
gpps(handle, name, def, buf, 2*len);
|
||||
p = buf;
|
||||
q = val;
|
||||
while (*p) {
|
||||
while (*p && *p != ',') {
|
||||
int c = *p++;
|
||||
if (c == '=')
|
||||
c = '\t';
|
||||
if (c == '\\')
|
||||
c = *p++;
|
||||
*q++ = c;
|
||||
}
|
||||
if (*p == ',')
|
||||
p++;
|
||||
*q++ = '\0';
|
||||
}
|
||||
*q = '\0';
|
||||
sfree(buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a set of name/value pairs in the above format.
|
||||
*/
|
||||
static void wmap(void *handle, char const *key, char const *value, int len)
|
||||
{
|
||||
char *buf = snewn(2*len, char), *p;
|
||||
const char *q;
|
||||
p = buf;
|
||||
q = value;
|
||||
while (*q) {
|
||||
while (*q) {
|
||||
int c = *q++;
|
||||
if (c == '=' || c == ',' || c == '\\')
|
||||
*p++ = '\\';
|
||||
if (c == '\t')
|
||||
c = '=';
|
||||
*p++ = c;
|
||||
}
|
||||
*p++ = ',';
|
||||
q++;
|
||||
}
|
||||
*p = '\0';
|
||||
write_setting_s(handle, key, buf);
|
||||
sfree(buf);
|
||||
}
|
||||
|
||||
static int key2val(const struct keyval *mapping, int nmaps, char *key)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < nmaps; i++)
|
||||
if (!strcmp(mapping[i].s, key)) return mapping[i].v;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static const char *val2key(const struct keyval *mapping, int nmaps, int val)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < nmaps; i++)
|
||||
if (mapping[i].v == val) return mapping[i].s;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper function to parse a comma-separated list of strings into
|
||||
* a preference list array of values. Any missing values are added
|
||||
* to the end and duplicates are weeded.
|
||||
* XXX: assumes vals in 'mapping' are small +ve integers
|
||||
*/
|
||||
static void gprefs(void *sesskey, char *name, char *def,
|
||||
const struct keyval *mapping, int nvals,
|
||||
int *array)
|
||||
{
|
||||
char commalist[80];
|
||||
char *tokarg = commalist;
|
||||
int n;
|
||||
unsigned long seen = 0; /* bitmap for weeding dups etc */
|
||||
gpps(sesskey, name, def, commalist, sizeof(commalist));
|
||||
|
||||
/* Grotty parsing of commalist. */
|
||||
n = 0;
|
||||
do {
|
||||
int v;
|
||||
char *key;
|
||||
key = strtok(tokarg, ","); /* sorry */
|
||||
tokarg = NULL;
|
||||
if (!key) break;
|
||||
if (((v = key2val(mapping, nvals, key)) != -1) &&
|
||||
!(seen & 1<<v)) {
|
||||
array[n] = v;
|
||||
n++;
|
||||
seen |= 1<<v;
|
||||
}
|
||||
} while (n < nvals);
|
||||
/* Add any missing values (backward compatibility ect). */
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < nvals; i++) {
|
||||
assert(mapping[i].v < 32);
|
||||
if (!(seen & 1<<mapping[i].v)) {
|
||||
array[n] = mapping[i].v;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Write out a preference list.
|
||||
*/
|
||||
static void wprefs(void *sesskey, char *name,
|
||||
const struct keyval *mapping, int nvals,
|
||||
int *array)
|
||||
{
|
||||
char buf[80] = ""; /* XXX assumed big enough */
|
||||
int l = sizeof(buf)-1, i;
|
||||
buf[l] = '\0';
|
||||
for (i = 0; l > 0 && i < nvals; i++) {
|
||||
const char *s = val2key(mapping, nvals, array[i]);
|
||||
if (s) {
|
||||
int sl = strlen(s);
|
||||
if (i > 0) {
|
||||
strncat(buf, ",", l);
|
||||
l--;
|
||||
}
|
||||
strncat(buf, s, l);
|
||||
l -= sl;
|
||||
}
|
||||
}
|
||||
write_setting_s(sesskey, name, buf);
|
||||
}
|
||||
|
||||
char *save_settings(char *section, Config * cfg)
|
||||
{
|
||||
void *sesskey;
|
||||
char *errmsg;
|
||||
|
||||
sesskey = open_settings_w(section, &errmsg);
|
||||
if (!sesskey)
|
||||
return errmsg;
|
||||
save_open_settings(sesskey, cfg);
|
||||
close_settings_w(sesskey);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void save_open_settings(void *sesskey, Config *cfg)
|
||||
{
|
||||
int i;
|
||||
char *p;
|
||||
|
||||
write_setting_i(sesskey, "Present", 1);
|
||||
write_setting_s(sesskey, "HostName", cfg->host);
|
||||
write_setting_filename(sesskey, "LogFileName", cfg->logfilename);
|
||||
write_setting_i(sesskey, "LogType", cfg->logtype);
|
||||
write_setting_i(sesskey, "LogFileClash", cfg->logxfovr);
|
||||
write_setting_i(sesskey, "LogFlush", cfg->logflush);
|
||||
write_setting_i(sesskey, "SSHLogOmitPasswords", cfg->logomitpass);
|
||||
write_setting_i(sesskey, "SSHLogOmitData", cfg->logomitdata);
|
||||
p = "raw";
|
||||
for (i = 0; backends[i].name != NULL; i++)
|
||||
if (backends[i].protocol == cfg->protocol) {
|
||||
p = backends[i].name;
|
||||
break;
|
||||
}
|
||||
write_setting_s(sesskey, "Protocol", p);
|
||||
write_setting_i(sesskey, "PortNumber", cfg->port);
|
||||
/* The CloseOnExit numbers are arranged in a different order from
|
||||
* the standard FORCE_ON / FORCE_OFF / AUTO. */
|
||||
write_setting_i(sesskey, "CloseOnExit", (cfg->close_on_exit+2)%3);
|
||||
write_setting_i(sesskey, "WarnOnClose", !!cfg->warn_on_close);
|
||||
write_setting_i(sesskey, "PingInterval", cfg->ping_interval / 60); /* minutes */
|
||||
write_setting_i(sesskey, "PingIntervalSecs", cfg->ping_interval % 60); /* seconds */
|
||||
write_setting_i(sesskey, "TCPNoDelay", cfg->tcp_nodelay);
|
||||
write_setting_i(sesskey, "TCPKeepalives", cfg->tcp_keepalives);
|
||||
write_setting_s(sesskey, "TerminalType", cfg->termtype);
|
||||
write_setting_s(sesskey, "TerminalSpeed", cfg->termspeed);
|
||||
wmap(sesskey, "TerminalModes", cfg->ttymodes, lenof(cfg->ttymodes));
|
||||
|
||||
/* Address family selection */
|
||||
write_setting_i(sesskey, "AddressFamily", cfg->addressfamily);
|
||||
|
||||
/* proxy settings */
|
||||
write_setting_s(sesskey, "ProxyExcludeList", cfg->proxy_exclude_list);
|
||||
write_setting_i(sesskey, "ProxyDNS", (cfg->proxy_dns+2)%3);
|
||||
write_setting_i(sesskey, "ProxyLocalhost", cfg->even_proxy_localhost);
|
||||
write_setting_i(sesskey, "ProxyMethod", cfg->proxy_type);
|
||||
write_setting_s(sesskey, "ProxyHost", cfg->proxy_host);
|
||||
write_setting_i(sesskey, "ProxyPort", cfg->proxy_port);
|
||||
write_setting_s(sesskey, "ProxyUsername", cfg->proxy_username);
|
||||
write_setting_s(sesskey, "ProxyPassword", cfg->proxy_password);
|
||||
write_setting_s(sesskey, "ProxyTelnetCommand", cfg->proxy_telnet_command);
|
||||
wmap(sesskey, "Environment", cfg->environmt, lenof(cfg->environmt));
|
||||
write_setting_s(sesskey, "UserName", cfg->username);
|
||||
write_setting_s(sesskey, "LocalUserName", cfg->localusername);
|
||||
write_setting_i(sesskey, "NoPTY", cfg->nopty);
|
||||
write_setting_i(sesskey, "Compression", cfg->compression);
|
||||
write_setting_i(sesskey, "TryAgent", cfg->tryagent);
|
||||
write_setting_i(sesskey, "AgentFwd", cfg->agentfwd);
|
||||
write_setting_i(sesskey, "ChangeUsername", cfg->change_username);
|
||||
wprefs(sesskey, "Cipher", ciphernames, CIPHER_MAX,
|
||||
cfg->ssh_cipherlist);
|
||||
wprefs(sesskey, "KEX", kexnames, KEX_MAX, cfg->ssh_kexlist);
|
||||
write_setting_i(sesskey, "RekeyTime", cfg->ssh_rekey_time);
|
||||
write_setting_s(sesskey, "RekeyBytes", cfg->ssh_rekey_data);
|
||||
write_setting_i(sesskey, "SshNoAuth", cfg->ssh_no_userauth);
|
||||
write_setting_i(sesskey, "AuthTIS", cfg->try_tis_auth);
|
||||
write_setting_i(sesskey, "AuthKI", cfg->try_ki_auth);
|
||||
write_setting_i(sesskey, "SshNoShell", cfg->ssh_no_shell);
|
||||
write_setting_i(sesskey, "SshProt", cfg->sshprot);
|
||||
write_setting_i(sesskey, "SSH2DES", cfg->ssh2_des_cbc);
|
||||
write_setting_filename(sesskey, "PublicKeyFile", cfg->keyfile);
|
||||
write_setting_s(sesskey, "RemoteCommand", cfg->remote_cmd);
|
||||
write_setting_i(sesskey, "RFCEnviron", cfg->rfc_environ);
|
||||
write_setting_i(sesskey, "PassiveTelnet", cfg->passive_telnet);
|
||||
write_setting_i(sesskey, "BackspaceIsDelete", cfg->bksp_is_delete);
|
||||
write_setting_i(sesskey, "RXVTHomeEnd", cfg->rxvt_homeend);
|
||||
write_setting_i(sesskey, "LinuxFunctionKeys", cfg->funky_type);
|
||||
write_setting_i(sesskey, "NoApplicationKeys", cfg->no_applic_k);
|
||||
write_setting_i(sesskey, "NoApplicationCursors", cfg->no_applic_c);
|
||||
write_setting_i(sesskey, "NoMouseReporting", cfg->no_mouse_rep);
|
||||
write_setting_i(sesskey, "NoRemoteResize", cfg->no_remote_resize);
|
||||
write_setting_i(sesskey, "NoAltScreen", cfg->no_alt_screen);
|
||||
write_setting_i(sesskey, "NoRemoteWinTitle", cfg->no_remote_wintitle);
|
||||
write_setting_i(sesskey, "RemoteQTitleAction", cfg->remote_qtitle_action);
|
||||
write_setting_i(sesskey, "NoDBackspace", cfg->no_dbackspace);
|
||||
write_setting_i(sesskey, "NoRemoteCharset", cfg->no_remote_charset);
|
||||
write_setting_i(sesskey, "ApplicationCursorKeys", cfg->app_cursor);
|
||||
write_setting_i(sesskey, "ApplicationKeypad", cfg->app_keypad);
|
||||
write_setting_i(sesskey, "NetHackKeypad", cfg->nethack_keypad);
|
||||
write_setting_i(sesskey, "AltF4", cfg->alt_f4);
|
||||
write_setting_i(sesskey, "AltSpace", cfg->alt_space);
|
||||
write_setting_i(sesskey, "AltOnly", cfg->alt_only);
|
||||
write_setting_i(sesskey, "ComposeKey", cfg->compose_key);
|
||||
write_setting_i(sesskey, "CtrlAltKeys", cfg->ctrlaltkeys);
|
||||
write_setting_i(sesskey, "TelnetKey", cfg->telnet_keyboard);
|
||||
write_setting_i(sesskey, "TelnetRet", cfg->telnet_newline);
|
||||
write_setting_i(sesskey, "LocalEcho", cfg->localecho);
|
||||
write_setting_i(sesskey, "LocalEdit", cfg->localedit);
|
||||
write_setting_s(sesskey, "Answerback", cfg->answerback);
|
||||
write_setting_i(sesskey, "AlwaysOnTop", cfg->alwaysontop);
|
||||
write_setting_i(sesskey, "FullScreenOnAltEnter", cfg->fullscreenonaltenter);
|
||||
write_setting_i(sesskey, "HideMousePtr", cfg->hide_mouseptr);
|
||||
write_setting_i(sesskey, "SunkenEdge", cfg->sunken_edge);
|
||||
write_setting_i(sesskey, "WindowBorder", cfg->window_border);
|
||||
write_setting_i(sesskey, "CurType", cfg->cursor_type);
|
||||
write_setting_i(sesskey, "BlinkCur", cfg->blink_cur);
|
||||
write_setting_i(sesskey, "Beep", cfg->beep);
|
||||
write_setting_i(sesskey, "BeepInd", cfg->beep_ind);
|
||||
write_setting_filename(sesskey, "BellWaveFile", cfg->bell_wavefile);
|
||||
write_setting_i(sesskey, "BellOverload", cfg->bellovl);
|
||||
write_setting_i(sesskey, "BellOverloadN", cfg->bellovl_n);
|
||||
write_setting_i(sesskey, "BellOverloadT", cfg->bellovl_t
|
||||
#ifdef PUTTY_UNIX_H
|
||||
* 1000
|
||||
#endif
|
||||
);
|
||||
write_setting_i(sesskey, "BellOverloadS", cfg->bellovl_s
|
||||
#ifdef PUTTY_UNIX_H
|
||||
* 1000
|
||||
#endif
|
||||
);
|
||||
write_setting_i(sesskey, "ScrollbackLines", cfg->savelines);
|
||||
write_setting_i(sesskey, "DECOriginMode", cfg->dec_om);
|
||||
write_setting_i(sesskey, "AutoWrapMode", cfg->wrap_mode);
|
||||
write_setting_i(sesskey, "LFImpliesCR", cfg->lfhascr);
|
||||
write_setting_i(sesskey, "DisableArabicShaping", cfg->arabicshaping);
|
||||
write_setting_i(sesskey, "DisableBidi", cfg->bidi);
|
||||
write_setting_i(sesskey, "WinNameAlways", cfg->win_name_always);
|
||||
write_setting_s(sesskey, "WinTitle", cfg->wintitle);
|
||||
write_setting_i(sesskey, "TermWidth", cfg->width);
|
||||
write_setting_i(sesskey, "TermHeight", cfg->height);
|
||||
write_setting_fontspec(sesskey, "Font", cfg->font);
|
||||
write_setting_i(sesskey, "FontQuality", cfg->font_quality);
|
||||
write_setting_i(sesskey, "FontVTMode", cfg->vtmode);
|
||||
write_setting_i(sesskey, "UseSystemColours", cfg->system_colour);
|
||||
write_setting_i(sesskey, "TryPalette", cfg->try_palette);
|
||||
write_setting_i(sesskey, "ANSIColour", cfg->ansi_colour);
|
||||
write_setting_i(sesskey, "Xterm256Colour", cfg->xterm_256_colour);
|
||||
write_setting_i(sesskey, "BoldAsColour", cfg->bold_colour);
|
||||
|
||||
for (i = 0; i < 22; i++) {
|
||||
char buf[20], buf2[30];
|
||||
sprintf(buf, "Colour%d", i);
|
||||
sprintf(buf2, "%d,%d,%d", cfg->colours[i][0],
|
||||
cfg->colours[i][1], cfg->colours[i][2]);
|
||||
write_setting_s(sesskey, buf, buf2);
|
||||
}
|
||||
write_setting_i(sesskey, "RawCNP", cfg->rawcnp);
|
||||
write_setting_i(sesskey, "PasteRTF", cfg->rtf_paste);
|
||||
write_setting_i(sesskey, "MouseIsXterm", cfg->mouse_is_xterm);
|
||||
write_setting_i(sesskey, "RectSelect", cfg->rect_select);
|
||||
write_setting_i(sesskey, "MouseOverride", cfg->mouse_override);
|
||||
for (i = 0; i < 256; i += 32) {
|
||||
char buf[20], buf2[256];
|
||||
int j;
|
||||
sprintf(buf, "Wordness%d", i);
|
||||
*buf2 = '\0';
|
||||
for (j = i; j < i + 32; j++) {
|
||||
sprintf(buf2 + strlen(buf2), "%s%d",
|
||||
(*buf2 ? "," : ""), cfg->wordness[j]);
|
||||
}
|
||||
write_setting_s(sesskey, buf, buf2);
|
||||
}
|
||||
write_setting_s(sesskey, "LineCodePage", cfg->line_codepage);
|
||||
write_setting_i(sesskey, "CJKAmbigWide", cfg->cjk_ambig_wide);
|
||||
write_setting_i(sesskey, "UTF8Override", cfg->utf8_override);
|
||||
write_setting_s(sesskey, "Printer", cfg->printer);
|
||||
write_setting_i(sesskey, "CapsLockCyr", cfg->xlat_capslockcyr);
|
||||
write_setting_i(sesskey, "ScrollBar", cfg->scrollbar);
|
||||
write_setting_i(sesskey, "ScrollBarFullScreen", cfg->scrollbar_in_fullscreen);
|
||||
write_setting_i(sesskey, "ScrollOnKey", cfg->scroll_on_key);
|
||||
write_setting_i(sesskey, "ScrollOnDisp", cfg->scroll_on_disp);
|
||||
write_setting_i(sesskey, "EraseToScrollback", cfg->erase_to_scrollback);
|
||||
write_setting_i(sesskey, "LockSize", cfg->resize_action);
|
||||
write_setting_i(sesskey, "BCE", cfg->bce);
|
||||
write_setting_i(sesskey, "BlinkText", cfg->blinktext);
|
||||
write_setting_i(sesskey, "X11Forward", cfg->x11_forward);
|
||||
write_setting_s(sesskey, "X11Display", cfg->x11_display);
|
||||
write_setting_i(sesskey, "X11AuthType", cfg->x11_auth);
|
||||
write_setting_i(sesskey, "LocalPortAcceptAll", cfg->lport_acceptall);
|
||||
write_setting_i(sesskey, "RemotePortAcceptAll", cfg->rport_acceptall);
|
||||
wmap(sesskey, "PortForwardings", cfg->portfwd, lenof(cfg->portfwd));
|
||||
write_setting_i(sesskey, "BugIgnore1", 2-cfg->sshbug_ignore1);
|
||||
write_setting_i(sesskey, "BugPlainPW1", 2-cfg->sshbug_plainpw1);
|
||||
write_setting_i(sesskey, "BugRSA1", 2-cfg->sshbug_rsa1);
|
||||
write_setting_i(sesskey, "BugHMAC2", 2-cfg->sshbug_hmac2);
|
||||
write_setting_i(sesskey, "BugDeriveKey2", 2-cfg->sshbug_derivekey2);
|
||||
write_setting_i(sesskey, "BugRSAPad2", 2-cfg->sshbug_rsapad2);
|
||||
write_setting_i(sesskey, "BugPKSessID2", 2-cfg->sshbug_pksessid2);
|
||||
write_setting_i(sesskey, "BugRekey2", 2-cfg->sshbug_rekey2);
|
||||
write_setting_i(sesskey, "StampUtmp", cfg->stamp_utmp);
|
||||
write_setting_i(sesskey, "LoginShell", cfg->login_shell);
|
||||
write_setting_i(sesskey, "ScrollbarOnLeft", cfg->scrollbar_on_left);
|
||||
write_setting_fontspec(sesskey, "BoldFont", cfg->boldfont);
|
||||
write_setting_fontspec(sesskey, "WideFont", cfg->widefont);
|
||||
write_setting_fontspec(sesskey, "WideBoldFont", cfg->wideboldfont);
|
||||
write_setting_i(sesskey, "ShadowBold", cfg->shadowbold);
|
||||
write_setting_i(sesskey, "ShadowBoldOffset", cfg->shadowboldoffset);
|
||||
write_setting_s(sesskey, "SerialLine", cfg->serline);
|
||||
write_setting_i(sesskey, "SerialSpeed", cfg->serspeed);
|
||||
write_setting_i(sesskey, "SerialDataBits", cfg->serdatabits);
|
||||
write_setting_i(sesskey, "SerialStopHalfbits", cfg->serstopbits);
|
||||
write_setting_i(sesskey, "SerialParity", cfg->serparity);
|
||||
write_setting_i(sesskey, "SerialFlowControl", cfg->serflow);
|
||||
}
|
||||
|
||||
void load_settings(char *section, Config * cfg)
|
||||
{
|
||||
void *sesskey;
|
||||
|
||||
sesskey = open_settings_r(section);
|
||||
load_open_settings(sesskey, cfg);
|
||||
close_settings_r(sesskey);
|
||||
}
|
||||
|
||||
void load_open_settings(void *sesskey, Config *cfg)
|
||||
{
|
||||
int i;
|
||||
char prot[10];
|
||||
|
||||
cfg->ssh_subsys = 0; /* FIXME: load this properly */
|
||||
cfg->remote_cmd_ptr = NULL;
|
||||
cfg->remote_cmd_ptr2 = NULL;
|
||||
cfg->ssh_nc_host[0] = '\0';
|
||||
|
||||
gpps(sesskey, "HostName", "", cfg->host, sizeof(cfg->host));
|
||||
gppfile(sesskey, "LogFileName", &cfg->logfilename);
|
||||
gppi(sesskey, "LogType", 0, &cfg->logtype);
|
||||
gppi(sesskey, "LogFileClash", LGXF_ASK, &cfg->logxfovr);
|
||||
gppi(sesskey, "LogFlush", 1, &cfg->logflush);
|
||||
gppi(sesskey, "SSHLogOmitPasswords", 1, &cfg->logomitpass);
|
||||
gppi(sesskey, "SSHLogOmitData", 0, &cfg->logomitdata);
|
||||
|
||||
gpps(sesskey, "Protocol", "default", prot, 10);
|
||||
cfg->protocol = default_protocol;
|
||||
cfg->port = default_port;
|
||||
for (i = 0; backends[i].name != NULL; i++)
|
||||
if (!strcmp(prot, backends[i].name)) {
|
||||
cfg->protocol = backends[i].protocol;
|
||||
gppi(sesskey, "PortNumber", default_port, &cfg->port);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Address family selection */
|
||||
gppi(sesskey, "AddressFamily", ADDRTYPE_UNSPEC, &cfg->addressfamily);
|
||||
|
||||
/* The CloseOnExit numbers are arranged in a different order from
|
||||
* the standard FORCE_ON / FORCE_OFF / AUTO. */
|
||||
gppi(sesskey, "CloseOnExit", 1, &i); cfg->close_on_exit = (i+1)%3;
|
||||
gppi(sesskey, "WarnOnClose", 1, &cfg->warn_on_close);
|
||||
{
|
||||
/* This is two values for backward compatibility with 0.50/0.51 */
|
||||
int pingmin, pingsec;
|
||||
gppi(sesskey, "PingInterval", 0, &pingmin);
|
||||
gppi(sesskey, "PingIntervalSecs", 0, &pingsec);
|
||||
cfg->ping_interval = pingmin * 60 + pingsec;
|
||||
}
|
||||
gppi(sesskey, "TCPNoDelay", 1, &cfg->tcp_nodelay);
|
||||
gppi(sesskey, "TCPKeepalives", 0, &cfg->tcp_keepalives);
|
||||
gpps(sesskey, "TerminalType", "xterm", cfg->termtype,
|
||||
sizeof(cfg->termtype));
|
||||
gpps(sesskey, "TerminalSpeed", "38400,38400", cfg->termspeed,
|
||||
sizeof(cfg->termspeed));
|
||||
{
|
||||
/* This hardcodes a big set of defaults in any new saved
|
||||
* sessions. Let's hope we don't change our mind. */
|
||||
int i;
|
||||
char *def = dupstr("");
|
||||
/* Default: all set to "auto" */
|
||||
for (i = 0; ttymodes[i]; i++) {
|
||||
char *def2 = dupprintf("%s%s=A,", def, ttymodes[i]);
|
||||
sfree(def);
|
||||
def = def2;
|
||||
}
|
||||
gppmap(sesskey, "TerminalModes", def,
|
||||
cfg->ttymodes, lenof(cfg->ttymodes));
|
||||
sfree(def);
|
||||
}
|
||||
|
||||
/* proxy settings */
|
||||
gpps(sesskey, "ProxyExcludeList", "", cfg->proxy_exclude_list,
|
||||
sizeof(cfg->proxy_exclude_list));
|
||||
gppi(sesskey, "ProxyDNS", 1, &i); cfg->proxy_dns = (i+1)%3;
|
||||
gppi(sesskey, "ProxyLocalhost", 0, &cfg->even_proxy_localhost);
|
||||
gppi(sesskey, "ProxyMethod", -1, &cfg->proxy_type);
|
||||
if (cfg->proxy_type == -1) {
|
||||
int i;
|
||||
gppi(sesskey, "ProxyType", 0, &i);
|
||||
if (i == 0)
|
||||
cfg->proxy_type = PROXY_NONE;
|
||||
else if (i == 1)
|
||||
cfg->proxy_type = PROXY_HTTP;
|
||||
else if (i == 3)
|
||||
cfg->proxy_type = PROXY_TELNET;
|
||||
else if (i == 4)
|
||||
cfg->proxy_type = PROXY_CMD;
|
||||
else {
|
||||
gppi(sesskey, "ProxySOCKSVersion", 5, &i);
|
||||
if (i == 5)
|
||||
cfg->proxy_type = PROXY_SOCKS5;
|
||||
else
|
||||
cfg->proxy_type = PROXY_SOCKS4;
|
||||
}
|
||||
}
|
||||
gpps(sesskey, "ProxyHost", "proxy", cfg->proxy_host,
|
||||
sizeof(cfg->proxy_host));
|
||||
gppi(sesskey, "ProxyPort", 80, &cfg->proxy_port);
|
||||
gpps(sesskey, "ProxyUsername", "", cfg->proxy_username,
|
||||
sizeof(cfg->proxy_username));
|
||||
gpps(sesskey, "ProxyPassword", "", cfg->proxy_password,
|
||||
sizeof(cfg->proxy_password));
|
||||
gpps(sesskey, "ProxyTelnetCommand", "connect %host %port\\n",
|
||||
cfg->proxy_telnet_command, sizeof(cfg->proxy_telnet_command));
|
||||
gppmap(sesskey, "Environment", "", cfg->environmt, lenof(cfg->environmt));
|
||||
gpps(sesskey, "UserName", "", cfg->username, sizeof(cfg->username));
|
||||
gpps(sesskey, "LocalUserName", "", cfg->localusername,
|
||||
sizeof(cfg->localusername));
|
||||
gppi(sesskey, "NoPTY", 0, &cfg->nopty);
|
||||
gppi(sesskey, "Compression", 0, &cfg->compression);
|
||||
gppi(sesskey, "TryAgent", 1, &cfg->tryagent);
|
||||
gppi(sesskey, "AgentFwd", 0, &cfg->agentfwd);
|
||||
gppi(sesskey, "ChangeUsername", 0, &cfg->change_username);
|
||||
gprefs(sesskey, "Cipher", "\0",
|
||||
ciphernames, CIPHER_MAX, cfg->ssh_cipherlist);
|
||||
{
|
||||
/* Backward-compatibility: we used to have an option to
|
||||
* disable gex under the "bugs" panel after one report of
|
||||
* a server which offered it then choked, but we never got
|
||||
* a server version string or any other reports. */
|
||||
char *default_kexes;
|
||||
gppi(sesskey, "BugDHGEx2", 0, &i); i = 2-i;
|
||||
if (i == FORCE_ON)
|
||||
default_kexes = "dh-group14-sha1,dh-group1-sha1,WARN,dh-gex-sha1";
|
||||
else
|
||||
default_kexes = "dh-gex-sha1,dh-group14-sha1,dh-group1-sha1,WARN";
|
||||
gprefs(sesskey, "KEX", default_kexes,
|
||||
kexnames, KEX_MAX, cfg->ssh_kexlist);
|
||||
}
|
||||
gppi(sesskey, "RekeyTime", 60, &cfg->ssh_rekey_time);
|
||||
gpps(sesskey, "RekeyBytes", "1G", cfg->ssh_rekey_data,
|
||||
sizeof(cfg->ssh_rekey_data));
|
||||
gppi(sesskey, "SshProt", 2, &cfg->sshprot);
|
||||
gppi(sesskey, "SSH2DES", 0, &cfg->ssh2_des_cbc);
|
||||
gppi(sesskey, "SshNoAuth", 0, &cfg->ssh_no_userauth);
|
||||
gppi(sesskey, "AuthTIS", 0, &cfg->try_tis_auth);
|
||||
gppi(sesskey, "AuthKI", 1, &cfg->try_ki_auth);
|
||||
gppi(sesskey, "SshNoShell", 0, &cfg->ssh_no_shell);
|
||||
gppfile(sesskey, "PublicKeyFile", &cfg->keyfile);
|
||||
gpps(sesskey, "RemoteCommand", "", cfg->remote_cmd,
|
||||
sizeof(cfg->remote_cmd));
|
||||
gppi(sesskey, "RFCEnviron", 0, &cfg->rfc_environ);
|
||||
gppi(sesskey, "PassiveTelnet", 0, &cfg->passive_telnet);
|
||||
gppi(sesskey, "BackspaceIsDelete", 1, &cfg->bksp_is_delete);
|
||||
gppi(sesskey, "RXVTHomeEnd", 0, &cfg->rxvt_homeend);
|
||||
gppi(sesskey, "LinuxFunctionKeys", 0, &cfg->funky_type);
|
||||
gppi(sesskey, "NoApplicationKeys", 0, &cfg->no_applic_k);
|
||||
gppi(sesskey, "NoApplicationCursors", 0, &cfg->no_applic_c);
|
||||
gppi(sesskey, "NoMouseReporting", 0, &cfg->no_mouse_rep);
|
||||
gppi(sesskey, "NoRemoteResize", 0, &cfg->no_remote_resize);
|
||||
gppi(sesskey, "NoAltScreen", 0, &cfg->no_alt_screen);
|
||||
gppi(sesskey, "NoRemoteWinTitle", 0, &cfg->no_remote_wintitle);
|
||||
{
|
||||
/* Backward compatibility */
|
||||
int no_remote_qtitle;
|
||||
gppi(sesskey, "NoRemoteQTitle", 1, &no_remote_qtitle);
|
||||
/* We deliberately interpret the old setting of "no response" as
|
||||
* "empty string". This changes the behaviour, but hopefully for
|
||||
* the better; the user can always recover the old behaviour. */
|
||||
gppi(sesskey, "RemoteQTitleAction",
|
||||
no_remote_qtitle ? TITLE_EMPTY : TITLE_REAL,
|
||||
&cfg->remote_qtitle_action);
|
||||
}
|
||||
gppi(sesskey, "NoDBackspace", 0, &cfg->no_dbackspace);
|
||||
gppi(sesskey, "NoRemoteCharset", 0, &cfg->no_remote_charset);
|
||||
gppi(sesskey, "ApplicationCursorKeys", 0, &cfg->app_cursor);
|
||||
gppi(sesskey, "ApplicationKeypad", 0, &cfg->app_keypad);
|
||||
gppi(sesskey, "NetHackKeypad", 0, &cfg->nethack_keypad);
|
||||
gppi(sesskey, "AltF4", 1, &cfg->alt_f4);
|
||||
gppi(sesskey, "AltSpace", 0, &cfg->alt_space);
|
||||
gppi(sesskey, "AltOnly", 0, &cfg->alt_only);
|
||||
gppi(sesskey, "ComposeKey", 0, &cfg->compose_key);
|
||||
gppi(sesskey, "CtrlAltKeys", 1, &cfg->ctrlaltkeys);
|
||||
gppi(sesskey, "TelnetKey", 0, &cfg->telnet_keyboard);
|
||||
gppi(sesskey, "TelnetRet", 1, &cfg->telnet_newline);
|
||||
gppi(sesskey, "LocalEcho", AUTO, &cfg->localecho);
|
||||
gppi(sesskey, "LocalEdit", AUTO, &cfg->localedit);
|
||||
gpps(sesskey, "Answerback", "PuTTY", cfg->answerback,
|
||||
sizeof(cfg->answerback));
|
||||
gppi(sesskey, "AlwaysOnTop", 0, &cfg->alwaysontop);
|
||||
gppi(sesskey, "FullScreenOnAltEnter", 0, &cfg->fullscreenonaltenter);
|
||||
gppi(sesskey, "HideMousePtr", 0, &cfg->hide_mouseptr);
|
||||
gppi(sesskey, "SunkenEdge", 0, &cfg->sunken_edge);
|
||||
gppi(sesskey, "WindowBorder", 1, &cfg->window_border);
|
||||
gppi(sesskey, "CurType", 0, &cfg->cursor_type);
|
||||
gppi(sesskey, "BlinkCur", 0, &cfg->blink_cur);
|
||||
/* pedantic compiler tells me I can't use &cfg->beep as an int * :-) */
|
||||
gppi(sesskey, "Beep", 1, &cfg->beep);
|
||||
gppi(sesskey, "BeepInd", 0, &cfg->beep_ind);
|
||||
gppfile(sesskey, "BellWaveFile", &cfg->bell_wavefile);
|
||||
gppi(sesskey, "BellOverload", 1, &cfg->bellovl);
|
||||
gppi(sesskey, "BellOverloadN", 5, &cfg->bellovl_n);
|
||||
gppi(sesskey, "BellOverloadT", 2*TICKSPERSEC, &i);
|
||||
cfg->bellovl_t = i
|
||||
#ifdef PUTTY_UNIX_H
|
||||
/ 1000
|
||||
#endif
|
||||
;
|
||||
gppi(sesskey, "BellOverloadS", 5*TICKSPERSEC, &i);
|
||||
cfg->bellovl_s = i
|
||||
#ifdef PUTTY_UNIX_H
|
||||
/ 1000
|
||||
#endif
|
||||
;
|
||||
gppi(sesskey, "ScrollbackLines", 200, &cfg->savelines);
|
||||
gppi(sesskey, "DECOriginMode", 0, &cfg->dec_om);
|
||||
gppi(sesskey, "AutoWrapMode", 1, &cfg->wrap_mode);
|
||||
gppi(sesskey, "LFImpliesCR", 0, &cfg->lfhascr);
|
||||
gppi(sesskey, "DisableArabicShaping", 0, &cfg->arabicshaping);
|
||||
gppi(sesskey, "DisableBidi", 0, &cfg->bidi);
|
||||
gppi(sesskey, "WinNameAlways", 1, &cfg->win_name_always);
|
||||
gpps(sesskey, "WinTitle", "", cfg->wintitle, sizeof(cfg->wintitle));
|
||||
gppi(sesskey, "TermWidth", 80, &cfg->width);
|
||||
gppi(sesskey, "TermHeight", 24, &cfg->height);
|
||||
gppfont(sesskey, "Font", &cfg->font);
|
||||
gppi(sesskey, "FontQuality", FQ_DEFAULT, &cfg->font_quality);
|
||||
gppi(sesskey, "FontVTMode", VT_UNICODE, (int *) &cfg->vtmode);
|
||||
gppi(sesskey, "UseSystemColours", 0, &cfg->system_colour);
|
||||
gppi(sesskey, "TryPalette", 0, &cfg->try_palette);
|
||||
gppi(sesskey, "ANSIColour", 1, &cfg->ansi_colour);
|
||||
gppi(sesskey, "Xterm256Colour", 1, &cfg->xterm_256_colour);
|
||||
gppi(sesskey, "BoldAsColour", 1, &cfg->bold_colour);
|
||||
|
||||
for (i = 0; i < 22; i++) {
|
||||
static const char *const defaults[] = {
|
||||
"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,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,255,255", "187,187,187", "255,255,255"
|
||||
};
|
||||
char buf[20], buf2[30];
|
||||
int c0, c1, c2;
|
||||
sprintf(buf, "Colour%d", i);
|
||||
gpps(sesskey, buf, defaults[i], buf2, sizeof(buf2));
|
||||
if (sscanf(buf2, "%d,%d,%d", &c0, &c1, &c2) == 3) {
|
||||
cfg->colours[i][0] = c0;
|
||||
cfg->colours[i][1] = c1;
|
||||
cfg->colours[i][2] = c2;
|
||||
}
|
||||
}
|
||||
gppi(sesskey, "RawCNP", 0, &cfg->rawcnp);
|
||||
gppi(sesskey, "PasteRTF", 0, &cfg->rtf_paste);
|
||||
gppi(sesskey, "MouseIsXterm", 0, &cfg->mouse_is_xterm);
|
||||
gppi(sesskey, "RectSelect", 0, &cfg->rect_select);
|
||||
gppi(sesskey, "MouseOverride", 1, &cfg->mouse_override);
|
||||
for (i = 0; i < 256; i += 32) {
|
||||
static const char *const 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,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",
|
||||
"1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,2",
|
||||
"1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,1,1,1,1",
|
||||
"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1",
|
||||
"1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1",
|
||||
"2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2",
|
||||
"2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,2,2,2,2,2,2,2,2"
|
||||
};
|
||||
char buf[20], buf2[256], *p;
|
||||
int j;
|
||||
sprintf(buf, "Wordness%d", i);
|
||||
gpps(sesskey, buf, defaults[i / 32], buf2, sizeof(buf2));
|
||||
p = buf2;
|
||||
for (j = i; j < i + 32; j++) {
|
||||
char *q = p;
|
||||
while (*p && *p != ',')
|
||||
p++;
|
||||
if (*p == ',')
|
||||
*p++ = '\0';
|
||||
cfg->wordness[j] = atoi(q);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* The empty default for LineCodePage will be converted later
|
||||
* into a plausible default for the locale.
|
||||
*/
|
||||
gpps(sesskey, "LineCodePage", "", cfg->line_codepage,
|
||||
sizeof(cfg->line_codepage));
|
||||
gppi(sesskey, "CJKAmbigWide", 0, &cfg->cjk_ambig_wide);
|
||||
gppi(sesskey, "UTF8Override", 1, &cfg->utf8_override);
|
||||
gpps(sesskey, "Printer", "", cfg->printer, sizeof(cfg->printer));
|
||||
gppi (sesskey, "CapsLockCyr", 0, &cfg->xlat_capslockcyr);
|
||||
gppi(sesskey, "ScrollBar", 1, &cfg->scrollbar);
|
||||
gppi(sesskey, "ScrollBarFullScreen", 0, &cfg->scrollbar_in_fullscreen);
|
||||
gppi(sesskey, "ScrollOnKey", 0, &cfg->scroll_on_key);
|
||||
gppi(sesskey, "ScrollOnDisp", 1, &cfg->scroll_on_disp);
|
||||
gppi(sesskey, "EraseToScrollback", 1, &cfg->erase_to_scrollback);
|
||||
gppi(sesskey, "LockSize", 0, &cfg->resize_action);
|
||||
gppi(sesskey, "BCE", 1, &cfg->bce);
|
||||
gppi(sesskey, "BlinkText", 0, &cfg->blinktext);
|
||||
gppi(sesskey, "X11Forward", 0, &cfg->x11_forward);
|
||||
gpps(sesskey, "X11Display", "", cfg->x11_display,
|
||||
sizeof(cfg->x11_display));
|
||||
gppi(sesskey, "X11AuthType", X11_MIT, &cfg->x11_auth);
|
||||
|
||||
gppi(sesskey, "LocalPortAcceptAll", 0, &cfg->lport_acceptall);
|
||||
gppi(sesskey, "RemotePortAcceptAll", 0, &cfg->rport_acceptall);
|
||||
gppmap(sesskey, "PortForwardings", "", cfg->portfwd, lenof(cfg->portfwd));
|
||||
gppi(sesskey, "BugIgnore1", 0, &i); cfg->sshbug_ignore1 = 2-i;
|
||||
gppi(sesskey, "BugPlainPW1", 0, &i); cfg->sshbug_plainpw1 = 2-i;
|
||||
gppi(sesskey, "BugRSA1", 0, &i); cfg->sshbug_rsa1 = 2-i;
|
||||
{
|
||||
int i;
|
||||
gppi(sesskey, "BugHMAC2", 0, &i); cfg->sshbug_hmac2 = 2-i;
|
||||
if (cfg->sshbug_hmac2 == AUTO) {
|
||||
gppi(sesskey, "BuggyMAC", 0, &i);
|
||||
if (i == 1)
|
||||
cfg->sshbug_hmac2 = FORCE_ON;
|
||||
}
|
||||
}
|
||||
gppi(sesskey, "BugDeriveKey2", 0, &i); cfg->sshbug_derivekey2 = 2-i;
|
||||
gppi(sesskey, "BugRSAPad2", 0, &i); cfg->sshbug_rsapad2 = 2-i;
|
||||
gppi(sesskey, "BugPKSessID2", 0, &i); cfg->sshbug_pksessid2 = 2-i;
|
||||
gppi(sesskey, "BugRekey2", 0, &i); cfg->sshbug_rekey2 = 2-i;
|
||||
gppi(sesskey, "StampUtmp", 1, &cfg->stamp_utmp);
|
||||
gppi(sesskey, "LoginShell", 1, &cfg->login_shell);
|
||||
gppi(sesskey, "ScrollbarOnLeft", 0, &cfg->scrollbar_on_left);
|
||||
gppi(sesskey, "ShadowBold", 0, &cfg->shadowbold);
|
||||
gppfont(sesskey, "BoldFont", &cfg->boldfont);
|
||||
gppfont(sesskey, "WideFont", &cfg->widefont);
|
||||
gppfont(sesskey, "WideBoldFont", &cfg->wideboldfont);
|
||||
gppi(sesskey, "ShadowBoldOffset", 1, &cfg->shadowboldoffset);
|
||||
gpps(sesskey, "SerialLine", "", cfg->serline, sizeof(cfg->serline));
|
||||
gppi(sesskey, "SerialSpeed", 9600, &cfg->serspeed);
|
||||
gppi(sesskey, "SerialDataBits", 8, &cfg->serdatabits);
|
||||
gppi(sesskey, "SerialStopHalfbits", 2, &cfg->serstopbits);
|
||||
gppi(sesskey, "SerialParity", SER_PAR_NONE, &cfg->serparity);
|
||||
gppi(sesskey, "SerialFlowControl", SER_FLOW_XONXOFF, &cfg->serflow);
|
||||
}
|
||||
|
||||
void do_defaults(char *session, Config * cfg)
|
||||
{
|
||||
load_settings(session, cfg);
|
||||
}
|
||||
|
||||
static int sessioncmp(const void *av, const void *bv)
|
||||
{
|
||||
const char *a = *(const char *const *) av;
|
||||
const char *b = *(const char *const *) bv;
|
||||
|
||||
/*
|
||||
* Alphabetical order, except that "Default Settings" is a
|
||||
* special case and comes first.
|
||||
*/
|
||||
if (!strcmp(a, "Default Settings"))
|
||||
return -1; /* a comes first */
|
||||
if (!strcmp(b, "Default Settings"))
|
||||
return +1; /* b comes first */
|
||||
/*
|
||||
* FIXME: perhaps we should ignore the first & in determining
|
||||
* sort order.
|
||||
*/
|
||||
return strcmp(a, b); /* otherwise, compare normally */
|
||||
}
|
||||
|
||||
void get_sesslist(struct sesslist *list, int allocate)
|
||||
{
|
||||
char otherbuf[2048];
|
||||
int buflen, bufsize, i;
|
||||
char *p, *ret;
|
||||
void *handle;
|
||||
|
||||
if (allocate) {
|
||||
|
||||
buflen = bufsize = 0;
|
||||
list->buffer = NULL;
|
||||
if ((handle = enum_settings_start()) != NULL) {
|
||||
do {
|
||||
ret = enum_settings_next(handle, otherbuf, sizeof(otherbuf));
|
||||
if (ret) {
|
||||
int len = strlen(otherbuf) + 1;
|
||||
if (bufsize < buflen + len) {
|
||||
bufsize = buflen + len + 2048;
|
||||
list->buffer = sresize(list->buffer, bufsize, char);
|
||||
}
|
||||
strcpy(list->buffer + buflen, otherbuf);
|
||||
buflen += strlen(list->buffer + buflen) + 1;
|
||||
}
|
||||
} while (ret);
|
||||
enum_settings_finish(handle);
|
||||
}
|
||||
list->buffer = sresize(list->buffer, buflen + 1, char);
|
||||
list->buffer[buflen] = '\0';
|
||||
|
||||
/*
|
||||
* Now set up the list of sessions. Note that "Default
|
||||
* Settings" must always be claimed to exist, even if it
|
||||
* doesn't really.
|
||||
*/
|
||||
|
||||
p = list->buffer;
|
||||
list->nsessions = 1; /* "Default Settings" counts as one */
|
||||
while (*p) {
|
||||
if (strcmp(p, "Default Settings"))
|
||||
list->nsessions++;
|
||||
while (*p)
|
||||
p++;
|
||||
p++;
|
||||
}
|
||||
|
||||
list->sessions = snewn(list->nsessions + 1, char *);
|
||||
list->sessions[0] = "Default Settings";
|
||||
p = list->buffer;
|
||||
i = 1;
|
||||
while (*p) {
|
||||
if (strcmp(p, "Default Settings"))
|
||||
list->sessions[i++] = p;
|
||||
while (*p)
|
||||
p++;
|
||||
p++;
|
||||
}
|
||||
|
||||
qsort(list->sessions, i, sizeof(char *), sessioncmp);
|
||||
} else {
|
||||
sfree(list->buffer);
|
||||
sfree(list->sessions);
|
||||
list->buffer = NULL;
|
||||
list->sessions = NULL;
|
||||
}
|
||||
}
|
||||
1422
sFTPlugins/psftp/SFTP.C
Normal file
1422
sFTPlugins/psftp/SFTP.C
Normal file
File diff suppressed because it is too large
Load Diff
248
sFTPlugins/psftp/SFTP.H
Normal file
248
sFTPlugins/psftp/SFTP.H
Normal file
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* sftp.h: definitions for SFTP and the sftp.c routines.
|
||||
*/
|
||||
|
||||
#include "int64.h"
|
||||
|
||||
#define SSH_FXP_INIT 1 /* 0x1 */
|
||||
#define SSH_FXP_VERSION 2 /* 0x2 */
|
||||
#define SSH_FXP_OPEN 3 /* 0x3 */
|
||||
#define SSH_FXP_CLOSE 4 /* 0x4 */
|
||||
#define SSH_FXP_READ 5 /* 0x5 */
|
||||
#define SSH_FXP_WRITE 6 /* 0x6 */
|
||||
#define SSH_FXP_LSTAT 7 /* 0x7 */
|
||||
#define SSH_FXP_FSTAT 8 /* 0x8 */
|
||||
#define SSH_FXP_SETSTAT 9 /* 0x9 */
|
||||
#define SSH_FXP_FSETSTAT 10 /* 0xa */
|
||||
#define SSH_FXP_OPENDIR 11 /* 0xb */
|
||||
#define SSH_FXP_READDIR 12 /* 0xc */
|
||||
#define SSH_FXP_REMOVE 13 /* 0xd */
|
||||
#define SSH_FXP_MKDIR 14 /* 0xe */
|
||||
#define SSH_FXP_RMDIR 15 /* 0xf */
|
||||
#define SSH_FXP_REALPATH 16 /* 0x10 */
|
||||
#define SSH_FXP_STAT 17 /* 0x11 */
|
||||
#define SSH_FXP_RENAME 18 /* 0x12 */
|
||||
#define SSH_FXP_STATUS 101 /* 0x65 */
|
||||
#define SSH_FXP_HANDLE 102 /* 0x66 */
|
||||
#define SSH_FXP_DATA 103 /* 0x67 */
|
||||
#define SSH_FXP_NAME 104 /* 0x68 */
|
||||
#define SSH_FXP_ATTRS 105 /* 0x69 */
|
||||
#define SSH_FXP_EXTENDED 200 /* 0xc8 */
|
||||
#define SSH_FXP_EXTENDED_REPLY 201 /* 0xc9 */
|
||||
|
||||
#define SSH_FX_OK 0
|
||||
#define SSH_FX_EOF 1
|
||||
#define SSH_FX_NO_SUCH_FILE 2
|
||||
#define SSH_FX_PERMISSION_DENIED 3
|
||||
#define SSH_FX_FAILURE 4
|
||||
#define SSH_FX_BAD_MESSAGE 5
|
||||
#define SSH_FX_NO_CONNECTION 6
|
||||
#define SSH_FX_CONNECTION_LOST 7
|
||||
#define SSH_FX_OP_UNSUPPORTED 8
|
||||
|
||||
#define SSH_FILEXFER_ATTR_SIZE 0x00000001
|
||||
#define SSH_FILEXFER_ATTR_UIDGID 0x00000002
|
||||
#define SSH_FILEXFER_ATTR_PERMISSIONS 0x00000004
|
||||
#define SSH_FILEXFER_ATTR_ACMODTIME 0x00000008
|
||||
#define SSH_FILEXFER_ATTR_EXTENDED 0x80000000
|
||||
|
||||
#define SSH_FXF_READ 0x00000001
|
||||
#define SSH_FXF_WRITE 0x00000002
|
||||
#define SSH_FXF_APPEND 0x00000004
|
||||
#define SSH_FXF_CREAT 0x00000008
|
||||
#define SSH_FXF_TRUNC 0x00000010
|
||||
#define SSH_FXF_EXCL 0x00000020
|
||||
|
||||
#define SFTP_PROTO_VERSION 3
|
||||
|
||||
/*
|
||||
* External references. The sftp client module sftp.c expects to be
|
||||
* able to get at these functions.
|
||||
*
|
||||
* sftp_recvdata must never return less than len. It either blocks
|
||||
* until len is available, or it returns failure.
|
||||
*
|
||||
* Both functions return 1 on success, 0 on failure.
|
||||
*/
|
||||
int sftp_senddata(char *data, int len);
|
||||
int sftp_recvdata(char *data, int len);
|
||||
|
||||
/*
|
||||
* Free sftp_requests
|
||||
*/
|
||||
void sftp_cleanup_request(void);
|
||||
|
||||
struct fxp_attrs {
|
||||
unsigned long flags;
|
||||
uint64 size;
|
||||
unsigned long uid;
|
||||
unsigned long gid;
|
||||
unsigned long permissions;
|
||||
unsigned long atime;
|
||||
unsigned long mtime;
|
||||
};
|
||||
|
||||
struct fxp_handle {
|
||||
char *hstring;
|
||||
int hlen;
|
||||
};
|
||||
|
||||
struct fxp_name {
|
||||
char *filename, *longname;
|
||||
struct fxp_attrs attrs;
|
||||
};
|
||||
|
||||
struct fxp_names {
|
||||
int nnames;
|
||||
struct fxp_name *names;
|
||||
};
|
||||
|
||||
struct sftp_request;
|
||||
struct sftp_packet;
|
||||
|
||||
const char *fxp_error(void);
|
||||
int fxp_error_type(void);
|
||||
|
||||
/*
|
||||
* Perform exchange of init/version packets. Return 0 on failure.
|
||||
*/
|
||||
int fxp_init(void);
|
||||
|
||||
/*
|
||||
* Canonify a pathname. Concatenate the two given path elements
|
||||
* with a separating slash, unless the second is NULL.
|
||||
*/
|
||||
struct sftp_request *fxp_realpath_send(char *path);
|
||||
char *fxp_realpath_recv(struct sftp_packet *pktin, struct sftp_request *req);
|
||||
|
||||
/*
|
||||
* Open a file.
|
||||
*/
|
||||
struct sftp_request *fxp_open_send(char *path, int type);
|
||||
struct fxp_handle *fxp_open_recv(struct sftp_packet *pktin,
|
||||
struct sftp_request *req);
|
||||
|
||||
/*
|
||||
* Open a directory.
|
||||
*/
|
||||
struct sftp_request *fxp_opendir_send(char *path);
|
||||
struct fxp_handle *fxp_opendir_recv(struct sftp_packet *pktin,
|
||||
struct sftp_request *req);
|
||||
|
||||
/*
|
||||
* Close a file/dir.
|
||||
*/
|
||||
struct sftp_request *fxp_close_send(struct fxp_handle *handle);
|
||||
void fxp_close_recv(struct sftp_packet *pktin, struct sftp_request *req);
|
||||
|
||||
/*
|
||||
* Make a directory.
|
||||
*/
|
||||
struct sftp_request *fxp_mkdir_send(char *path);
|
||||
int fxp_mkdir_recv(struct sftp_packet *pktin, struct sftp_request *req);
|
||||
|
||||
/*
|
||||
* Remove a directory.
|
||||
*/
|
||||
struct sftp_request *fxp_rmdir_send(char *path);
|
||||
int fxp_rmdir_recv(struct sftp_packet *pktin, struct sftp_request *req);
|
||||
|
||||
/*
|
||||
* Remove a file.
|
||||
*/
|
||||
struct sftp_request *fxp_remove_send(char *fname);
|
||||
int fxp_remove_recv(struct sftp_packet *pktin, struct sftp_request *req);
|
||||
|
||||
/*
|
||||
* Rename a file.
|
||||
*/
|
||||
struct sftp_request *fxp_rename_send(char *srcfname, char *dstfname);
|
||||
int fxp_rename_recv(struct sftp_packet *pktin, struct sftp_request *req);
|
||||
|
||||
/*
|
||||
* Return file attributes.
|
||||
*/
|
||||
struct sftp_request *fxp_stat_send(char *fname);
|
||||
int fxp_stat_recv(struct sftp_packet *pktin, struct sftp_request *req,
|
||||
struct fxp_attrs *attrs);
|
||||
struct sftp_request *fxp_fstat_send(struct fxp_handle *handle);
|
||||
int fxp_fstat_recv(struct sftp_packet *pktin, struct sftp_request *req,
|
||||
struct fxp_attrs *attrs);
|
||||
|
||||
/*
|
||||
* Set file attributes.
|
||||
*/
|
||||
struct sftp_request *fxp_setstat_send(char *fname, struct fxp_attrs attrs);
|
||||
int fxp_setstat_recv(struct sftp_packet *pktin, struct sftp_request *req);
|
||||
struct sftp_request *fxp_fsetstat_send(struct fxp_handle *handle,
|
||||
struct fxp_attrs attrs);
|
||||
int fxp_fsetstat_recv(struct sftp_packet *pktin, struct sftp_request *req);
|
||||
|
||||
/*
|
||||
* Read from a file.
|
||||
*/
|
||||
struct sftp_request *fxp_read_send(struct fxp_handle *handle,
|
||||
uint64 offset, int len);
|
||||
int fxp_read_recv(struct sftp_packet *pktin, struct sftp_request *req,
|
||||
char *buffer, int len);
|
||||
|
||||
/*
|
||||
* Write to a file. Returns 0 on error, 1 on OK.
|
||||
*/
|
||||
struct sftp_request *fxp_write_send(struct fxp_handle *handle,
|
||||
char *buffer, uint64 offset, int len);
|
||||
int fxp_write_recv(struct sftp_packet *pktin, struct sftp_request *req);
|
||||
|
||||
/*
|
||||
* Read from a directory.
|
||||
*/
|
||||
struct sftp_request *fxp_readdir_send(struct fxp_handle *handle);
|
||||
struct fxp_names *fxp_readdir_recv(struct sftp_packet *pktin,
|
||||
struct sftp_request *req);
|
||||
|
||||
/*
|
||||
* Free up an fxp_names structure.
|
||||
*/
|
||||
void fxp_free_names(struct fxp_names *names);
|
||||
|
||||
/*
|
||||
* Duplicate and free fxp_name structures.
|
||||
*/
|
||||
struct fxp_name *fxp_dup_name(struct fxp_name *name);
|
||||
void fxp_free_name(struct fxp_name *name);
|
||||
|
||||
/*
|
||||
* Store user data in an sftp_request structure.
|
||||
*/
|
||||
void *fxp_get_userdata(struct sftp_request *req);
|
||||
void fxp_set_userdata(struct sftp_request *req, void *data);
|
||||
|
||||
/*
|
||||
* These functions might well be temporary placeholders to be
|
||||
* replaced with more useful similar functions later. They form the
|
||||
* main dispatch loop for processing incoming SFTP responses.
|
||||
*/
|
||||
void sftp_register(struct sftp_request *req);
|
||||
struct sftp_request *sftp_find_request(struct sftp_packet *pktin);
|
||||
struct sftp_packet *sftp_recv(void);
|
||||
|
||||
/*
|
||||
* A wrapper to go round fxp_read_* and fxp_write_*, which manages
|
||||
* the queueing of multiple read/write requests.
|
||||
*/
|
||||
|
||||
struct fxp_xfer;
|
||||
|
||||
struct fxp_xfer *xfer_download_init(struct fxp_handle *fh, uint64 offset);
|
||||
void xfer_download_queue(struct fxp_xfer *xfer);
|
||||
int xfer_download_gotpkt(struct fxp_xfer *xfer, struct sftp_packet *pktin);
|
||||
int xfer_download_data(struct fxp_xfer *xfer, void **buf, int *len);
|
||||
|
||||
struct fxp_xfer *xfer_upload_init(struct fxp_handle *fh, uint64 offset);
|
||||
int xfer_upload_ready(struct fxp_xfer *xfer);
|
||||
void xfer_upload_data(struct fxp_xfer *xfer, char *buffer, int len);
|
||||
int xfer_upload_gotpkt(struct fxp_xfer *xfer, struct sftp_packet *pktin);
|
||||
|
||||
int xfer_done(struct fxp_xfer *xfer);
|
||||
void xfer_set_error(struct fxp_xfer *xfer);
|
||||
void xfer_cleanup(struct fxp_xfer *xfer);
|
||||
9033
sFTPlugins/psftp/SSH.C
Normal file
9033
sFTPlugins/psftp/SSH.C
Normal file
File diff suppressed because it is too large
Load Diff
511
sFTPlugins/psftp/SSH.H
Normal file
511
sFTPlugins/psftp/SSH.H
Normal file
@@ -0,0 +1,511 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "puttymem.h"
|
||||
#include "network.h"
|
||||
#include "int64.h"
|
||||
#include "misc.h"
|
||||
|
||||
struct ssh_channel;
|
||||
|
||||
extern void sshfwd_close(struct ssh_channel *c);
|
||||
extern int sshfwd_write(struct ssh_channel *c, char *, int);
|
||||
extern void sshfwd_unthrottle(struct ssh_channel *c, int bufsize);
|
||||
|
||||
/*
|
||||
* Useful thing.
|
||||
*/
|
||||
#ifndef lenof
|
||||
#define lenof(x) ( (sizeof((x))) / (sizeof(*(x))))
|
||||
#endif
|
||||
|
||||
#define SSH_CIPHER_IDEA 1
|
||||
#define SSH_CIPHER_DES 2
|
||||
#define SSH_CIPHER_3DES 3
|
||||
#define SSH_CIPHER_BLOWFISH 6
|
||||
|
||||
#ifdef MSCRYPTOAPI
|
||||
#define APIEXTRA 8
|
||||
#else
|
||||
#define APIEXTRA 0
|
||||
#endif
|
||||
|
||||
#ifndef BIGNUM_INTERNAL
|
||||
typedef void *Bignum;
|
||||
#endif
|
||||
|
||||
struct RSAKey {
|
||||
int bits;
|
||||
int bytes;
|
||||
#ifdef MSCRYPTOAPI
|
||||
unsigned long exponent;
|
||||
unsigned char *modulus;
|
||||
#else
|
||||
Bignum modulus;
|
||||
Bignum exponent;
|
||||
Bignum private_exponent;
|
||||
Bignum p;
|
||||
Bignum q;
|
||||
Bignum iqmp;
|
||||
#endif
|
||||
char *comment;
|
||||
};
|
||||
|
||||
struct dss_key {
|
||||
Bignum p, q, g, y, x;
|
||||
};
|
||||
|
||||
int makekey(unsigned char *data, int len, struct RSAKey *result,
|
||||
unsigned char **keystr, int order);
|
||||
int makeprivate(unsigned char *data, int len, struct RSAKey *result);
|
||||
int rsaencrypt(unsigned char *data, int length, struct RSAKey *key);
|
||||
Bignum rsadecrypt(Bignum input, struct RSAKey *key);
|
||||
void rsasign(unsigned char *data, int length, struct RSAKey *key);
|
||||
void rsasanitise(struct RSAKey *key);
|
||||
int rsastr_len(struct RSAKey *key);
|
||||
void rsastr_fmt(char *str, struct RSAKey *key);
|
||||
void rsa_fingerprint(char *str, int len, struct RSAKey *key);
|
||||
int rsa_verify(struct RSAKey *key);
|
||||
unsigned char *rsa_public_blob(struct RSAKey *key, int *len);
|
||||
int rsa_public_blob_len(void *data, int maxlen);
|
||||
void freersakey(struct RSAKey *key);
|
||||
|
||||
typedef unsigned int word32;
|
||||
typedef unsigned int uint32;
|
||||
|
||||
unsigned long crc32_compute(const void *s, size_t len);
|
||||
unsigned long crc32_update(unsigned long crc_input, const void *s, size_t len);
|
||||
|
||||
/* SSH CRC compensation attack detector */
|
||||
void *crcda_make_context(void);
|
||||
void crcda_free_context(void *handle);
|
||||
int detect_attack(void *handle, unsigned char *buf, uint32 len,
|
||||
unsigned char *IV);
|
||||
|
||||
typedef struct {
|
||||
uint32 h[4];
|
||||
} MD5_Core_State;
|
||||
|
||||
struct MD5Context {
|
||||
#ifdef MSCRYPTOAPI
|
||||
unsigned long hHash;
|
||||
#else
|
||||
MD5_Core_State core;
|
||||
unsigned char block[64];
|
||||
int blkused;
|
||||
uint32 lenhi, lenlo;
|
||||
#endif
|
||||
};
|
||||
|
||||
void MD5Init(struct MD5Context *context);
|
||||
void MD5Update(struct MD5Context *context, unsigned char const *buf,
|
||||
unsigned len);
|
||||
void MD5Final(unsigned char digest[16], struct MD5Context *context);
|
||||
void MD5Simple(void const *p, unsigned len, unsigned char output[16]);
|
||||
|
||||
void *hmacmd5_make_context(void);
|
||||
void hmacmd5_free_context(void *handle);
|
||||
void hmacmd5_key(void *handle, void const *key, int len);
|
||||
void hmacmd5_do_hmac(void *handle, unsigned char const *blk, int len,
|
||||
unsigned char *hmac);
|
||||
|
||||
typedef struct {
|
||||
uint32 h[5];
|
||||
unsigned char block[64];
|
||||
int blkused;
|
||||
uint32 lenhi, lenlo;
|
||||
} SHA_State;
|
||||
void SHA_Init(SHA_State * s);
|
||||
void SHA_Bytes(SHA_State * s, void *p, int len);
|
||||
void SHA_Final(SHA_State * s, unsigned char *output);
|
||||
void SHA_Simple(void *p, int len, unsigned char *output);
|
||||
|
||||
void hmac_sha1_simple(void *key, int keylen, void *data, int datalen,
|
||||
unsigned char *output);
|
||||
typedef struct {
|
||||
uint32 h[8];
|
||||
unsigned char block[64];
|
||||
int blkused;
|
||||
uint32 lenhi, lenlo;
|
||||
} SHA256_State;
|
||||
void SHA256_Init(SHA256_State * s);
|
||||
void SHA256_Bytes(SHA256_State * s, const void *p, int len);
|
||||
void SHA256_Final(SHA256_State * s, unsigned char *output);
|
||||
void SHA256_Simple(const void *p, int len, unsigned char *output);
|
||||
|
||||
typedef struct {
|
||||
uint64 h[8];
|
||||
unsigned char block[128];
|
||||
int blkused;
|
||||
uint32 len[4];
|
||||
} SHA512_State;
|
||||
void SHA512_Init(SHA512_State * s);
|
||||
void SHA512_Bytes(SHA512_State * s, const void *p, int len);
|
||||
void SHA512_Final(SHA512_State * s, unsigned char *output);
|
||||
void SHA512_Simple(const void *p, int len, unsigned char *output);
|
||||
|
||||
struct ssh_cipher {
|
||||
void *(*make_context)(void);
|
||||
void (*free_context)(void *);
|
||||
void (*sesskey) (void *, unsigned char *key); /* for SSH-1 */
|
||||
void (*encrypt) (void *, unsigned char *blk, int len);
|
||||
void (*decrypt) (void *, unsigned char *blk, int len);
|
||||
int blksize;
|
||||
char *text_name;
|
||||
};
|
||||
|
||||
struct ssh2_cipher {
|
||||
void *(*make_context)(void);
|
||||
void (*free_context)(void *);
|
||||
void (*setiv) (void *, unsigned char *key); /* for SSH-2 */
|
||||
void (*setkey) (void *, unsigned char *key);/* for SSH-2 */
|
||||
void (*encrypt) (void *, unsigned char *blk, int len);
|
||||
void (*decrypt) (void *, unsigned char *blk, int len);
|
||||
char *name;
|
||||
int blksize;
|
||||
int keylen;
|
||||
unsigned int flags;
|
||||
#define SSH_CIPHER_IS_CBC 1
|
||||
char *text_name;
|
||||
};
|
||||
|
||||
struct ssh2_ciphers {
|
||||
int nciphers;
|
||||
const struct ssh2_cipher *const *list;
|
||||
};
|
||||
|
||||
struct ssh_mac {
|
||||
void *(*make_context)(void);
|
||||
void (*free_context)(void *);
|
||||
void (*setkey) (void *, unsigned char *key);
|
||||
void (*generate) (void *, unsigned char *blk, int len, unsigned long seq);
|
||||
int (*verify) (void *, unsigned char *blk, int len, unsigned long seq);
|
||||
char *name;
|
||||
int len;
|
||||
char *text_name;
|
||||
};
|
||||
|
||||
struct ssh_hash {
|
||||
void *(*init)(void); /* also allocates context */
|
||||
void (*bytes)(void *, void *, int);
|
||||
void (*final)(void *, unsigned char *); /* also frees context */
|
||||
int hlen; /* output length in bytes */
|
||||
char *text_name;
|
||||
};
|
||||
|
||||
struct ssh_kex {
|
||||
/*
|
||||
* Plugging in another KEX algorithm requires structural chaos,
|
||||
* so it's hard to abstract them into nice little structures
|
||||
* like this. Fortunately, all our KEXes are basically
|
||||
* Diffie-Hellman at the moment, so in this structure I simply
|
||||
* parametrise the DH exchange a bit.
|
||||
*/
|
||||
char *name, *groupname;
|
||||
const unsigned char *pdata, *gdata;/* NULL means use group exchange */
|
||||
int plen, glen;
|
||||
const struct ssh_hash *hash;
|
||||
};
|
||||
|
||||
struct ssh_kexes {
|
||||
int nkexes;
|
||||
const struct ssh_kex *const *list;
|
||||
};
|
||||
|
||||
struct ssh_signkey {
|
||||
void *(*newkey) (char *data, int len);
|
||||
void (*freekey) (void *key);
|
||||
char *(*fmtkey) (void *key);
|
||||
unsigned char *(*public_blob) (void *key, int *len);
|
||||
unsigned char *(*private_blob) (void *key, int *len);
|
||||
void *(*createkey) (unsigned char *pub_blob, int pub_len,
|
||||
unsigned char *priv_blob, int priv_len);
|
||||
void *(*openssh_createkey) (unsigned char **blob, int *len);
|
||||
int (*openssh_fmtkey) (void *key, unsigned char *blob, int len);
|
||||
int (*pubkey_bits) (void *blob, int len);
|
||||
char *(*fingerprint) (void *key);
|
||||
int (*verifysig) (void *key, char *sig, int siglen,
|
||||
char *data, int datalen);
|
||||
unsigned char *(*sign) (void *key, char *data, int datalen,
|
||||
int *siglen);
|
||||
char *name;
|
||||
char *keytype; /* for host key cache */
|
||||
};
|
||||
|
||||
struct ssh_compress {
|
||||
char *name;
|
||||
void *(*compress_init) (void);
|
||||
void (*compress_cleanup) (void *);
|
||||
int (*compress) (void *, unsigned char *block, int len,
|
||||
unsigned char **outblock, int *outlen);
|
||||
void *(*decompress_init) (void);
|
||||
void (*decompress_cleanup) (void *);
|
||||
int (*decompress) (void *, unsigned char *block, int len,
|
||||
unsigned char **outblock, int *outlen);
|
||||
int (*disable_compression) (void *);
|
||||
char *text_name;
|
||||
};
|
||||
|
||||
struct ssh2_userkey {
|
||||
const struct ssh_signkey *alg; /* the key algorithm */
|
||||
void *data; /* the key data */
|
||||
char *comment; /* the key comment */
|
||||
};
|
||||
|
||||
/* The maximum length of any hash algorithm used in kex. (bytes) */
|
||||
#define SSH2_KEX_MAX_HASH_LEN (32) /* SHA-256 */
|
||||
|
||||
extern const struct ssh_cipher ssh_3des;
|
||||
extern const struct ssh_cipher ssh_des;
|
||||
extern const struct ssh_cipher ssh_blowfish_ssh1;
|
||||
extern const struct ssh2_ciphers ssh2_3des;
|
||||
extern const struct ssh2_ciphers ssh2_des;
|
||||
extern const struct ssh2_ciphers ssh2_aes;
|
||||
extern const struct ssh2_ciphers ssh2_blowfish;
|
||||
extern const struct ssh2_ciphers ssh2_arcfour;
|
||||
extern const struct ssh_hash ssh_sha1;
|
||||
extern const struct ssh_hash ssh_sha256;
|
||||
extern const struct ssh_kexes ssh_diffiehellman_group1;
|
||||
extern const struct ssh_kexes ssh_diffiehellman_group14;
|
||||
extern const struct ssh_kexes ssh_diffiehellman_gex;
|
||||
extern const struct ssh_signkey ssh_dss;
|
||||
extern const struct ssh_signkey ssh_rsa;
|
||||
extern const struct ssh_mac ssh_hmac_md5;
|
||||
extern const struct ssh_mac ssh_hmac_sha1;
|
||||
extern const struct ssh_mac ssh_hmac_sha1_buggy;
|
||||
extern const struct ssh_mac ssh_hmac_sha1_96;
|
||||
extern const struct ssh_mac ssh_hmac_sha1_96_buggy;
|
||||
|
||||
|
||||
/*
|
||||
* PuTTY version number formatted as an SSH version string.
|
||||
*/
|
||||
extern char sshver[];
|
||||
|
||||
/*
|
||||
* Gross hack: pscp will try to start SFTP but fall back to scp1 if
|
||||
* that fails. This variable is the means by which scp.c can reach
|
||||
* into the SSH code and find out which one it got.
|
||||
*/
|
||||
extern int ssh_fallback_cmd(void *handle);
|
||||
|
||||
#ifndef MSCRYPTOAPI
|
||||
void SHATransform(word32 * digest, word32 * data);
|
||||
#endif
|
||||
|
||||
int random_byte(void);
|
||||
void random_add_noise(void *noise, int length);
|
||||
void random_add_heavynoise(void *noise, int length);
|
||||
|
||||
void logevent(void *, const char *);
|
||||
|
||||
/* Allocate and register a new channel for port forwarding */
|
||||
void *new_sock_channel(void *handle, Socket s);
|
||||
void ssh_send_port_open(void *channel, char *hostname, int port, char *org);
|
||||
|
||||
/* Exports from portfwd.c */
|
||||
extern const char *pfd_newconnect(Socket * s, char *hostname, int port,
|
||||
void *c, const Config *cfg,
|
||||
int addressfamily);
|
||||
/* desthost == NULL indicates dynamic (SOCKS) port forwarding */
|
||||
extern const char *pfd_addforward(char *desthost, int destport, char *srcaddr,
|
||||
int port, void *backhandle,
|
||||
const Config *cfg, void **sockdata,
|
||||
int address_family);
|
||||
extern void pfd_close(Socket s);
|
||||
extern void pfd_terminate(void *sockdata);
|
||||
extern int pfd_send(Socket s, char *data, int len);
|
||||
extern void pfd_confirm(Socket s);
|
||||
extern void pfd_unthrottle(Socket s);
|
||||
extern void pfd_override_throttle(Socket s, int enable);
|
||||
|
||||
/* Exports from x11fwd.c */
|
||||
extern const char *x11_init(Socket *, char *, void *, void *, const char *,
|
||||
int, const Config *);
|
||||
extern void x11_close(Socket);
|
||||
extern int x11_send(Socket, char *, int);
|
||||
extern void *x11_invent_auth(char *, int, char *, int, int);
|
||||
extern void x11_free_auth(void *);
|
||||
extern void x11_unthrottle(Socket s);
|
||||
extern void x11_override_throttle(Socket s, int enable);
|
||||
extern int x11_get_screen_number(char *display);
|
||||
void x11_get_real_auth(void *authv, char *display);
|
||||
char *x11_display(const char *display);
|
||||
|
||||
/* Platform-dependent X11 functions */
|
||||
extern void platform_get_x11_auth(char *display, int *proto,
|
||||
unsigned char *data, int *datalen);
|
||||
extern const char platform_x11_best_transport[];
|
||||
/* best X11 hostname for this platform if none specified */
|
||||
SockAddr platform_get_x11_unix_address(int displaynum, char **canonicalname);
|
||||
/* make up a SockAddr naming the address for displaynum */
|
||||
char *platform_get_x_display(void);
|
||||
/* allocated local X display string, if any */
|
||||
|
||||
Bignum copybn(Bignum b);
|
||||
Bignum bn_power_2(int n);
|
||||
void bn_restore_invariant(Bignum b);
|
||||
Bignum bignum_from_long(unsigned long n);
|
||||
void freebn(Bignum b);
|
||||
Bignum modpow(Bignum base, Bignum exp, Bignum mod);
|
||||
Bignum modmul(Bignum a, Bignum b, Bignum mod);
|
||||
void decbn(Bignum n);
|
||||
extern Bignum Zero, One;
|
||||
Bignum bignum_from_bytes(const unsigned char *data, int nbytes);
|
||||
int ssh1_read_bignum(const unsigned char *data, int len, Bignum * result);
|
||||
int bignum_bitcount(Bignum bn);
|
||||
int ssh1_bignum_length(Bignum bn);
|
||||
int ssh2_bignum_length(Bignum bn);
|
||||
int bignum_byte(Bignum bn, int i);
|
||||
int bignum_bit(Bignum bn, int i);
|
||||
void bignum_set_bit(Bignum bn, int i, int value);
|
||||
int ssh1_write_bignum(void *data, Bignum bn);
|
||||
Bignum biggcd(Bignum a, Bignum b);
|
||||
unsigned short bignum_mod_short(Bignum number, unsigned short modulus);
|
||||
Bignum bignum_add_long(Bignum number, unsigned long addend);
|
||||
Bignum bigmul(Bignum a, Bignum b);
|
||||
Bignum bigmuladd(Bignum a, Bignum b, Bignum addend);
|
||||
Bignum bigdiv(Bignum a, Bignum b);
|
||||
Bignum bigmod(Bignum a, Bignum b);
|
||||
Bignum modinv(Bignum number, Bignum modulus);
|
||||
Bignum bignum_bitmask(Bignum number);
|
||||
Bignum bignum_rshift(Bignum number, int shift);
|
||||
int bignum_cmp(Bignum a, Bignum b);
|
||||
char *bignum_decimal(Bignum x);
|
||||
|
||||
#ifdef DEBUG
|
||||
void diagbn(char *prefix, Bignum md);
|
||||
#endif
|
||||
|
||||
void *dh_setup_group(const struct ssh_kex *kex);
|
||||
void *dh_setup_gex(Bignum pval, Bignum gval);
|
||||
void dh_cleanup(void *);
|
||||
Bignum dh_create_e(void *, int nbits);
|
||||
Bignum dh_find_K(void *, Bignum f);
|
||||
|
||||
int loadrsakey(const Filename *filename, struct RSAKey *key,
|
||||
char *passphrase, const char **errorstr);
|
||||
int rsakey_encrypted(const Filename *filename, char **comment);
|
||||
int rsakey_pubblob(const Filename *filename, void **blob, int *bloblen,
|
||||
char **commentptr, const char **errorstr);
|
||||
|
||||
int saversakey(const Filename *filename, struct RSAKey *key, char *passphrase);
|
||||
|
||||
extern int base64_decode_atom(char *atom, unsigned char *out);
|
||||
extern int base64_lines(int datalen);
|
||||
extern void base64_encode_atom(unsigned char *data, int n, char *out);
|
||||
extern void base64_encode(FILE *fp, unsigned char *data, int datalen, int cpl);
|
||||
|
||||
/* ssh2_load_userkey can return this as an error */
|
||||
extern struct ssh2_userkey ssh2_wrong_passphrase;
|
||||
#define SSH2_WRONG_PASSPHRASE (&ssh2_wrong_passphrase)
|
||||
|
||||
int ssh2_userkey_encrypted(const Filename *filename, char **comment);
|
||||
struct ssh2_userkey *ssh2_load_userkey(const Filename *filename,
|
||||
char *passphrase, const char **errorstr);
|
||||
unsigned char *ssh2_userkey_loadpub(const Filename *filename, char **algorithm,
|
||||
int *pub_blob_len, char **commentptr,
|
||||
const char **errorstr);
|
||||
int ssh2_save_userkey(const Filename *filename, struct ssh2_userkey *key,
|
||||
char *passphrase);
|
||||
const struct ssh_signkey *find_pubkey_alg(const char *name);
|
||||
|
||||
enum {
|
||||
SSH_KEYTYPE_UNOPENABLE,
|
||||
SSH_KEYTYPE_UNKNOWN,
|
||||
SSH_KEYTYPE_SSH1, SSH_KEYTYPE_SSH2,
|
||||
SSH_KEYTYPE_OPENSSH, SSH_KEYTYPE_SSHCOM
|
||||
};
|
||||
int key_type(const Filename *filename);
|
||||
char *key_type_to_str(int type);
|
||||
|
||||
int import_possible(int type);
|
||||
int import_target_type(int type);
|
||||
int import_encrypted(const Filename *filename, int type, char **comment);
|
||||
int import_ssh1(const Filename *filename, int type,
|
||||
struct RSAKey *key, char *passphrase, const char **errmsg_p);
|
||||
struct ssh2_userkey *import_ssh2(const Filename *filename, int type,
|
||||
char *passphrase, const char **errmsg_p);
|
||||
int export_ssh1(const Filename *filename, int type,
|
||||
struct RSAKey *key, char *passphrase);
|
||||
int export_ssh2(const Filename *filename, int type,
|
||||
struct ssh2_userkey *key, char *passphrase);
|
||||
|
||||
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_decrypt_pubkey_ossh(unsigned char *key, unsigned char *iv,
|
||||
unsigned char *blk, int len);
|
||||
void des3_encrypt_pubkey_ossh(unsigned char *key, unsigned char *iv,
|
||||
unsigned char *blk, int len);
|
||||
void aes256_encrypt_pubkey(unsigned char *key, unsigned char *blk,
|
||||
int len);
|
||||
void aes256_decrypt_pubkey(unsigned char *key, unsigned char *blk,
|
||||
int len);
|
||||
|
||||
void des_encrypt_xdmauth(unsigned char *key, unsigned char *blk, int len);
|
||||
void des_decrypt_xdmauth(unsigned char *key, unsigned char *blk, int len);
|
||||
|
||||
/*
|
||||
* For progress updates in the key generation utility.
|
||||
*/
|
||||
#define PROGFN_INITIALISE 1
|
||||
#define PROGFN_LIN_PHASE 2
|
||||
#define PROGFN_EXP_PHASE 3
|
||||
#define PROGFN_PHASE_EXTENT 4
|
||||
#define PROGFN_READY 5
|
||||
#define PROGFN_PROGRESS 6
|
||||
typedef void (*progfn_t) (void *param, int action, int phase, int progress);
|
||||
|
||||
int rsa_generate(struct RSAKey *key, int bits, progfn_t pfn,
|
||||
void *pfnparam);
|
||||
int dsa_generate(struct dss_key *key, int bits, progfn_t pfn,
|
||||
void *pfnparam);
|
||||
Bignum primegen(int bits, int modulus, int residue, Bignum factor,
|
||||
int phase, progfn_t pfn, void *pfnparam);
|
||||
|
||||
|
||||
/*
|
||||
* zlib compression.
|
||||
*/
|
||||
void *zlib_compress_init(void);
|
||||
void zlib_compress_cleanup(void *);
|
||||
void *zlib_decompress_init(void);
|
||||
void zlib_decompress_cleanup(void *);
|
||||
int zlib_compress_block(void *, unsigned char *block, int len,
|
||||
unsigned char **outblock, int *outlen);
|
||||
int zlib_decompress_block(void *, unsigned char *block, int len,
|
||||
unsigned char **outblock, int *outlen);
|
||||
|
||||
/*
|
||||
* SSH-1 agent messages.
|
||||
*/
|
||||
#define SSH1_AGENTC_REQUEST_RSA_IDENTITIES 1
|
||||
#define SSH1_AGENT_RSA_IDENTITIES_ANSWER 2
|
||||
#define SSH1_AGENTC_RSA_CHALLENGE 3
|
||||
#define SSH1_AGENT_RSA_RESPONSE 4
|
||||
#define SSH1_AGENTC_ADD_RSA_IDENTITY 7
|
||||
#define SSH1_AGENTC_REMOVE_RSA_IDENTITY 8
|
||||
#define SSH1_AGENTC_REMOVE_ALL_RSA_IDENTITIES 9 /* openssh private? */
|
||||
|
||||
/*
|
||||
* Messages common to SSH-1 and OpenSSH's SSH-2.
|
||||
*/
|
||||
#define SSH_AGENT_FAILURE 5
|
||||
#define SSH_AGENT_SUCCESS 6
|
||||
|
||||
/*
|
||||
* OpenSSH's SSH-2 agent messages.
|
||||
*/
|
||||
#define SSH2_AGENTC_REQUEST_IDENTITIES 11
|
||||
#define SSH2_AGENT_IDENTITIES_ANSWER 12
|
||||
#define SSH2_AGENTC_SIGN_REQUEST 13
|
||||
#define SSH2_AGENT_SIGN_RESPONSE 14
|
||||
#define SSH2_AGENTC_ADD_IDENTITY 17
|
||||
#define SSH2_AGENTC_REMOVE_IDENTITY 18
|
||||
#define SSH2_AGENTC_REMOVE_ALL_IDENTITIES 19
|
||||
|
||||
/*
|
||||
* Need this to warn about support for the original SSH-2 keyfile
|
||||
* format.
|
||||
*/
|
||||
void old_keyfile_warning(void);
|
||||
1234
sFTPlugins/psftp/SSHAES.C
Normal file
1234
sFTPlugins/psftp/SSHAES.C
Normal file
File diff suppressed because it is too large
Load Diff
123
sFTPlugins/psftp/SSHARCF.C
Normal file
123
sFTPlugins/psftp/SSHARCF.C
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Arcfour (RC4) implementation for PuTTY.
|
||||
*
|
||||
* Coded from Schneier.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include "ssh.h"
|
||||
|
||||
typedef struct {
|
||||
unsigned char i, j, s[256];
|
||||
} ArcfourContext;
|
||||
|
||||
static void arcfour_block(void *handle, unsigned char *blk, int len)
|
||||
{
|
||||
ArcfourContext *ctx = (ArcfourContext *)handle;
|
||||
unsigned k;
|
||||
unsigned char tmp, i, j, *s;
|
||||
|
||||
s = ctx->s;
|
||||
i = ctx->i; j = ctx->j;
|
||||
for (k = 0; (int)k < len; k++) {
|
||||
i = (i + 1) & 0xff;
|
||||
j = (j + s[i]) & 0xff;
|
||||
tmp = s[i]; s[i] = s[j]; s[j] = tmp;
|
||||
blk[k] ^= s[(s[i]+s[j]) & 0xff];
|
||||
}
|
||||
ctx->i = i; ctx->j = j;
|
||||
}
|
||||
|
||||
static void arcfour_setkey(ArcfourContext *ctx, unsigned char const *key,
|
||||
unsigned keybytes)
|
||||
{
|
||||
unsigned char tmp, k[256], *s;
|
||||
unsigned i, j;
|
||||
|
||||
s = ctx->s;
|
||||
assert(keybytes <= 256);
|
||||
ctx->i = ctx->j = 0;
|
||||
for (i = 0; i < 256; i++) {
|
||||
s[i] = i;
|
||||
k[i] = key[i % keybytes];
|
||||
}
|
||||
j = 0;
|
||||
for (i = 0; i < 256; i++) {
|
||||
j = (j + s[i] + k[i]) & 0xff;
|
||||
tmp = s[i]; s[i] = s[j]; s[j] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
/* -- Interface with PuTTY -- */
|
||||
|
||||
/*
|
||||
* We don't implement Arcfour in SSH-1 because it's utterly insecure in
|
||||
* several ways. See CERT Vulnerability Notes VU#25309, VU#665372,
|
||||
* and VU#565052.
|
||||
*
|
||||
* We don't implement the "arcfour" algorithm in SSH-2 because it doesn't
|
||||
* stir the cipher state before emitting keystream, and hence is likely
|
||||
* to leak data about the key.
|
||||
*/
|
||||
|
||||
static void *arcfour_make_context(void)
|
||||
{
|
||||
return snew(ArcfourContext);
|
||||
}
|
||||
|
||||
static void arcfour_free_context(void *handle)
|
||||
{
|
||||
sfree(handle);
|
||||
}
|
||||
|
||||
static void arcfour_stir(ArcfourContext *ctx)
|
||||
{
|
||||
unsigned char *junk = snewn(1536, unsigned char);
|
||||
memset(junk, 0, 1536);
|
||||
arcfour_block(ctx, junk, 1536);
|
||||
memset(junk, 0, 1536);
|
||||
sfree(junk);
|
||||
}
|
||||
|
||||
static void arcfour128_key(void *handle, unsigned char *key)
|
||||
{
|
||||
ArcfourContext *ctx = (ArcfourContext *)handle;
|
||||
arcfour_setkey(ctx, key, 16);
|
||||
arcfour_stir(ctx);
|
||||
}
|
||||
|
||||
static void arcfour256_key(void *handle, unsigned char *key)
|
||||
{
|
||||
ArcfourContext *ctx = (ArcfourContext *)handle;
|
||||
arcfour_setkey(ctx, key, 32);
|
||||
arcfour_stir(ctx);
|
||||
}
|
||||
|
||||
static void arcfour_iv(void *handle, unsigned char *key)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
const struct ssh2_cipher ssh_arcfour128_ssh2 = {
|
||||
arcfour_make_context, arcfour_free_context, arcfour_iv, arcfour128_key,
|
||||
arcfour_block, arcfour_block,
|
||||
"arcfour128",
|
||||
1, 128, 0, "Arcfour-128"
|
||||
};
|
||||
|
||||
const struct ssh2_cipher ssh_arcfour256_ssh2 = {
|
||||
arcfour_make_context, arcfour_free_context, arcfour_iv, arcfour256_key,
|
||||
arcfour_block, arcfour_block,
|
||||
"arcfour256",
|
||||
1, 256, 0, "Arcfour-256"
|
||||
};
|
||||
|
||||
static const struct ssh2_cipher *const arcfour_list[] = {
|
||||
&ssh_arcfour256_ssh2,
|
||||
&ssh_arcfour128_ssh2,
|
||||
};
|
||||
|
||||
const struct ssh2_ciphers ssh2_arcfour = {
|
||||
sizeof(arcfour_list) / sizeof(*arcfour_list),
|
||||
arcfour_list
|
||||
};
|
||||
588
sFTPlugins/psftp/SSHBLOWF.C
Normal file
588
sFTPlugins/psftp/SSHBLOWF.C
Normal file
@@ -0,0 +1,588 @@
|
||||
/*
|
||||
* Blowfish implementation for PuTTY.
|
||||
*
|
||||
* Coded from scratch from the algorithm description.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include "ssh.h"
|
||||
|
||||
typedef struct {
|
||||
word32 S0[256], S1[256], S2[256], S3[256], P[18];
|
||||
word32 iv0, iv1; /* for CBC mode */
|
||||
} BlowfishContext;
|
||||
|
||||
/*
|
||||
* The Blowfish init data: hex digits of the fractional part of pi.
|
||||
* (ie pi as a hex fraction is 3.243F6A8885A308D3...)
|
||||
*/
|
||||
static const word32 parray[] = {
|
||||
0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344, 0xA4093822, 0x299F31D0,
|
||||
0x082EFA98, 0xEC4E6C89, 0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C,
|
||||
0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917, 0x9216D5D9, 0x8979FB1B,
|
||||
};
|
||||
|
||||
static const word32 sbox0[] = {
|
||||
0xD1310BA6, 0x98DFB5AC, 0x2FFD72DB, 0xD01ADFB7, 0xB8E1AFED, 0x6A267E96,
|
||||
0xBA7C9045, 0xF12C7F99, 0x24A19947, 0xB3916CF7, 0x0801F2E2, 0x858EFC16,
|
||||
0x636920D8, 0x71574E69, 0xA458FEA3, 0xF4933D7E, 0x0D95748F, 0x728EB658,
|
||||
0x718BCD58, 0x82154AEE, 0x7B54A41D, 0xC25A59B5, 0x9C30D539, 0x2AF26013,
|
||||
0xC5D1B023, 0x286085F0, 0xCA417918, 0xB8DB38EF, 0x8E79DCB0, 0x603A180E,
|
||||
0x6C9E0E8B, 0xB01E8A3E, 0xD71577C1, 0xBD314B27, 0x78AF2FDA, 0x55605C60,
|
||||
0xE65525F3, 0xAA55AB94, 0x57489862, 0x63E81440, 0x55CA396A, 0x2AAB10B6,
|
||||
0xB4CC5C34, 0x1141E8CE, 0xA15486AF, 0x7C72E993, 0xB3EE1411, 0x636FBC2A,
|
||||
0x2BA9C55D, 0x741831F6, 0xCE5C3E16, 0x9B87931E, 0xAFD6BA33, 0x6C24CF5C,
|
||||
0x7A325381, 0x28958677, 0x3B8F4898, 0x6B4BB9AF, 0xC4BFE81B, 0x66282193,
|
||||
0x61D809CC, 0xFB21A991, 0x487CAC60, 0x5DEC8032, 0xEF845D5D, 0xE98575B1,
|
||||
0xDC262302, 0xEB651B88, 0x23893E81, 0xD396ACC5, 0x0F6D6FF3, 0x83F44239,
|
||||
0x2E0B4482, 0xA4842004, 0x69C8F04A, 0x9E1F9B5E, 0x21C66842, 0xF6E96C9A,
|
||||
0x670C9C61, 0xABD388F0, 0x6A51A0D2, 0xD8542F68, 0x960FA728, 0xAB5133A3,
|
||||
0x6EEF0B6C, 0x137A3BE4, 0xBA3BF050, 0x7EFB2A98, 0xA1F1651D, 0x39AF0176,
|
||||
0x66CA593E, 0x82430E88, 0x8CEE8619, 0x456F9FB4, 0x7D84A5C3, 0x3B8B5EBE,
|
||||
0xE06F75D8, 0x85C12073, 0x401A449F, 0x56C16AA6, 0x4ED3AA62, 0x363F7706,
|
||||
0x1BFEDF72, 0x429B023D, 0x37D0D724, 0xD00A1248, 0xDB0FEAD3, 0x49F1C09B,
|
||||
0x075372C9, 0x80991B7B, 0x25D479D8, 0xF6E8DEF7, 0xE3FE501A, 0xB6794C3B,
|
||||
0x976CE0BD, 0x04C006BA, 0xC1A94FB6, 0x409F60C4, 0x5E5C9EC2, 0x196A2463,
|
||||
0x68FB6FAF, 0x3E6C53B5, 0x1339B2EB, 0x3B52EC6F, 0x6DFC511F, 0x9B30952C,
|
||||
0xCC814544, 0xAF5EBD09, 0xBEE3D004, 0xDE334AFD, 0x660F2807, 0x192E4BB3,
|
||||
0xC0CBA857, 0x45C8740F, 0xD20B5F39, 0xB9D3FBDB, 0x5579C0BD, 0x1A60320A,
|
||||
0xD6A100C6, 0x402C7279, 0x679F25FE, 0xFB1FA3CC, 0x8EA5E9F8, 0xDB3222F8,
|
||||
0x3C7516DF, 0xFD616B15, 0x2F501EC8, 0xAD0552AB, 0x323DB5FA, 0xFD238760,
|
||||
0x53317B48, 0x3E00DF82, 0x9E5C57BB, 0xCA6F8CA0, 0x1A87562E, 0xDF1769DB,
|
||||
0xD542A8F6, 0x287EFFC3, 0xAC6732C6, 0x8C4F5573, 0x695B27B0, 0xBBCA58C8,
|
||||
0xE1FFA35D, 0xB8F011A0, 0x10FA3D98, 0xFD2183B8, 0x4AFCB56C, 0x2DD1D35B,
|
||||
0x9A53E479, 0xB6F84565, 0xD28E49BC, 0x4BFB9790, 0xE1DDF2DA, 0xA4CB7E33,
|
||||
0x62FB1341, 0xCEE4C6E8, 0xEF20CADA, 0x36774C01, 0xD07E9EFE, 0x2BF11FB4,
|
||||
0x95DBDA4D, 0xAE909198, 0xEAAD8E71, 0x6B93D5A0, 0xD08ED1D0, 0xAFC725E0,
|
||||
0x8E3C5B2F, 0x8E7594B7, 0x8FF6E2FB, 0xF2122B64, 0x8888B812, 0x900DF01C,
|
||||
0x4FAD5EA0, 0x688FC31C, 0xD1CFF191, 0xB3A8C1AD, 0x2F2F2218, 0xBE0E1777,
|
||||
0xEA752DFE, 0x8B021FA1, 0xE5A0CC0F, 0xB56F74E8, 0x18ACF3D6, 0xCE89E299,
|
||||
0xB4A84FE0, 0xFD13E0B7, 0x7CC43B81, 0xD2ADA8D9, 0x165FA266, 0x80957705,
|
||||
0x93CC7314, 0x211A1477, 0xE6AD2065, 0x77B5FA86, 0xC75442F5, 0xFB9D35CF,
|
||||
0xEBCDAF0C, 0x7B3E89A0, 0xD6411BD3, 0xAE1E7E49, 0x00250E2D, 0x2071B35E,
|
||||
0x226800BB, 0x57B8E0AF, 0x2464369B, 0xF009B91E, 0x5563911D, 0x59DFA6AA,
|
||||
0x78C14389, 0xD95A537F, 0x207D5BA2, 0x02E5B9C5, 0x83260376, 0x6295CFA9,
|
||||
0x11C81968, 0x4E734A41, 0xB3472DCA, 0x7B14A94A, 0x1B510052, 0x9A532915,
|
||||
0xD60F573F, 0xBC9BC6E4, 0x2B60A476, 0x81E67400, 0x08BA6FB5, 0x571BE91F,
|
||||
0xF296EC6B, 0x2A0DD915, 0xB6636521, 0xE7B9F9B6, 0xFF34052E, 0xC5855664,
|
||||
0x53B02D5D, 0xA99F8FA1, 0x08BA4799, 0x6E85076A,
|
||||
};
|
||||
|
||||
static const word32 sbox1[] = {
|
||||
0x4B7A70E9, 0xB5B32944, 0xDB75092E, 0xC4192623, 0xAD6EA6B0, 0x49A7DF7D,
|
||||
0x9CEE60B8, 0x8FEDB266, 0xECAA8C71, 0x699A17FF, 0x5664526C, 0xC2B19EE1,
|
||||
0x193602A5, 0x75094C29, 0xA0591340, 0xE4183A3E, 0x3F54989A, 0x5B429D65,
|
||||
0x6B8FE4D6, 0x99F73FD6, 0xA1D29C07, 0xEFE830F5, 0x4D2D38E6, 0xF0255DC1,
|
||||
0x4CDD2086, 0x8470EB26, 0x6382E9C6, 0x021ECC5E, 0x09686B3F, 0x3EBAEFC9,
|
||||
0x3C971814, 0x6B6A70A1, 0x687F3584, 0x52A0E286, 0xB79C5305, 0xAA500737,
|
||||
0x3E07841C, 0x7FDEAE5C, 0x8E7D44EC, 0x5716F2B8, 0xB03ADA37, 0xF0500C0D,
|
||||
0xF01C1F04, 0x0200B3FF, 0xAE0CF51A, 0x3CB574B2, 0x25837A58, 0xDC0921BD,
|
||||
0xD19113F9, 0x7CA92FF6, 0x94324773, 0x22F54701, 0x3AE5E581, 0x37C2DADC,
|
||||
0xC8B57634, 0x9AF3DDA7, 0xA9446146, 0x0FD0030E, 0xECC8C73E, 0xA4751E41,
|
||||
0xE238CD99, 0x3BEA0E2F, 0x3280BBA1, 0x183EB331, 0x4E548B38, 0x4F6DB908,
|
||||
0x6F420D03, 0xF60A04BF, 0x2CB81290, 0x24977C79, 0x5679B072, 0xBCAF89AF,
|
||||
0xDE9A771F, 0xD9930810, 0xB38BAE12, 0xDCCF3F2E, 0x5512721F, 0x2E6B7124,
|
||||
0x501ADDE6, 0x9F84CD87, 0x7A584718, 0x7408DA17, 0xBC9F9ABC, 0xE94B7D8C,
|
||||
0xEC7AEC3A, 0xDB851DFA, 0x63094366, 0xC464C3D2, 0xEF1C1847, 0x3215D908,
|
||||
0xDD433B37, 0x24C2BA16, 0x12A14D43, 0x2A65C451, 0x50940002, 0x133AE4DD,
|
||||
0x71DFF89E, 0x10314E55, 0x81AC77D6, 0x5F11199B, 0x043556F1, 0xD7A3C76B,
|
||||
0x3C11183B, 0x5924A509, 0xF28FE6ED, 0x97F1FBFA, 0x9EBABF2C, 0x1E153C6E,
|
||||
0x86E34570, 0xEAE96FB1, 0x860E5E0A, 0x5A3E2AB3, 0x771FE71C, 0x4E3D06FA,
|
||||
0x2965DCB9, 0x99E71D0F, 0x803E89D6, 0x5266C825, 0x2E4CC978, 0x9C10B36A,
|
||||
0xC6150EBA, 0x94E2EA78, 0xA5FC3C53, 0x1E0A2DF4, 0xF2F74EA7, 0x361D2B3D,
|
||||
0x1939260F, 0x19C27960, 0x5223A708, 0xF71312B6, 0xEBADFE6E, 0xEAC31F66,
|
||||
0xE3BC4595, 0xA67BC883, 0xB17F37D1, 0x018CFF28, 0xC332DDEF, 0xBE6C5AA5,
|
||||
0x65582185, 0x68AB9802, 0xEECEA50F, 0xDB2F953B, 0x2AEF7DAD, 0x5B6E2F84,
|
||||
0x1521B628, 0x29076170, 0xECDD4775, 0x619F1510, 0x13CCA830, 0xEB61BD96,
|
||||
0x0334FE1E, 0xAA0363CF, 0xB5735C90, 0x4C70A239, 0xD59E9E0B, 0xCBAADE14,
|
||||
0xEECC86BC, 0x60622CA7, 0x9CAB5CAB, 0xB2F3846E, 0x648B1EAF, 0x19BDF0CA,
|
||||
0xA02369B9, 0x655ABB50, 0x40685A32, 0x3C2AB4B3, 0x319EE9D5, 0xC021B8F7,
|
||||
0x9B540B19, 0x875FA099, 0x95F7997E, 0x623D7DA8, 0xF837889A, 0x97E32D77,
|
||||
0x11ED935F, 0x16681281, 0x0E358829, 0xC7E61FD6, 0x96DEDFA1, 0x7858BA99,
|
||||
0x57F584A5, 0x1B227263, 0x9B83C3FF, 0x1AC24696, 0xCDB30AEB, 0x532E3054,
|
||||
0x8FD948E4, 0x6DBC3128, 0x58EBF2EF, 0x34C6FFEA, 0xFE28ED61, 0xEE7C3C73,
|
||||
0x5D4A14D9, 0xE864B7E3, 0x42105D14, 0x203E13E0, 0x45EEE2B6, 0xA3AAABEA,
|
||||
0xDB6C4F15, 0xFACB4FD0, 0xC742F442, 0xEF6ABBB5, 0x654F3B1D, 0x41CD2105,
|
||||
0xD81E799E, 0x86854DC7, 0xE44B476A, 0x3D816250, 0xCF62A1F2, 0x5B8D2646,
|
||||
0xFC8883A0, 0xC1C7B6A3, 0x7F1524C3, 0x69CB7492, 0x47848A0B, 0x5692B285,
|
||||
0x095BBF00, 0xAD19489D, 0x1462B174, 0x23820E00, 0x58428D2A, 0x0C55F5EA,
|
||||
0x1DADF43E, 0x233F7061, 0x3372F092, 0x8D937E41, 0xD65FECF1, 0x6C223BDB,
|
||||
0x7CDE3759, 0xCBEE7460, 0x4085F2A7, 0xCE77326E, 0xA6078084, 0x19F8509E,
|
||||
0xE8EFD855, 0x61D99735, 0xA969A7AA, 0xC50C06C2, 0x5A04ABFC, 0x800BCADC,
|
||||
0x9E447A2E, 0xC3453484, 0xFDD56705, 0x0E1E9EC9, 0xDB73DBD3, 0x105588CD,
|
||||
0x675FDA79, 0xE3674340, 0xC5C43465, 0x713E38D8, 0x3D28F89E, 0xF16DFF20,
|
||||
0x153E21E7, 0x8FB03D4A, 0xE6E39F2B, 0xDB83ADF7,
|
||||
};
|
||||
|
||||
static const word32 sbox2[] = {
|
||||
0xE93D5A68, 0x948140F7, 0xF64C261C, 0x94692934, 0x411520F7, 0x7602D4F7,
|
||||
0xBCF46B2E, 0xD4A20068, 0xD4082471, 0x3320F46A, 0x43B7D4B7, 0x500061AF,
|
||||
0x1E39F62E, 0x97244546, 0x14214F74, 0xBF8B8840, 0x4D95FC1D, 0x96B591AF,
|
||||
0x70F4DDD3, 0x66A02F45, 0xBFBC09EC, 0x03BD9785, 0x7FAC6DD0, 0x31CB8504,
|
||||
0x96EB27B3, 0x55FD3941, 0xDA2547E6, 0xABCA0A9A, 0x28507825, 0x530429F4,
|
||||
0x0A2C86DA, 0xE9B66DFB, 0x68DC1462, 0xD7486900, 0x680EC0A4, 0x27A18DEE,
|
||||
0x4F3FFEA2, 0xE887AD8C, 0xB58CE006, 0x7AF4D6B6, 0xAACE1E7C, 0xD3375FEC,
|
||||
0xCE78A399, 0x406B2A42, 0x20FE9E35, 0xD9F385B9, 0xEE39D7AB, 0x3B124E8B,
|
||||
0x1DC9FAF7, 0x4B6D1856, 0x26A36631, 0xEAE397B2, 0x3A6EFA74, 0xDD5B4332,
|
||||
0x6841E7F7, 0xCA7820FB, 0xFB0AF54E, 0xD8FEB397, 0x454056AC, 0xBA489527,
|
||||
0x55533A3A, 0x20838D87, 0xFE6BA9B7, 0xD096954B, 0x55A867BC, 0xA1159A58,
|
||||
0xCCA92963, 0x99E1DB33, 0xA62A4A56, 0x3F3125F9, 0x5EF47E1C, 0x9029317C,
|
||||
0xFDF8E802, 0x04272F70, 0x80BB155C, 0x05282CE3, 0x95C11548, 0xE4C66D22,
|
||||
0x48C1133F, 0xC70F86DC, 0x07F9C9EE, 0x41041F0F, 0x404779A4, 0x5D886E17,
|
||||
0x325F51EB, 0xD59BC0D1, 0xF2BCC18F, 0x41113564, 0x257B7834, 0x602A9C60,
|
||||
0xDFF8E8A3, 0x1F636C1B, 0x0E12B4C2, 0x02E1329E, 0xAF664FD1, 0xCAD18115,
|
||||
0x6B2395E0, 0x333E92E1, 0x3B240B62, 0xEEBEB922, 0x85B2A20E, 0xE6BA0D99,
|
||||
0xDE720C8C, 0x2DA2F728, 0xD0127845, 0x95B794FD, 0x647D0862, 0xE7CCF5F0,
|
||||
0x5449A36F, 0x877D48FA, 0xC39DFD27, 0xF33E8D1E, 0x0A476341, 0x992EFF74,
|
||||
0x3A6F6EAB, 0xF4F8FD37, 0xA812DC60, 0xA1EBDDF8, 0x991BE14C, 0xDB6E6B0D,
|
||||
0xC67B5510, 0x6D672C37, 0x2765D43B, 0xDCD0E804, 0xF1290DC7, 0xCC00FFA3,
|
||||
0xB5390F92, 0x690FED0B, 0x667B9FFB, 0xCEDB7D9C, 0xA091CF0B, 0xD9155EA3,
|
||||
0xBB132F88, 0x515BAD24, 0x7B9479BF, 0x763BD6EB, 0x37392EB3, 0xCC115979,
|
||||
0x8026E297, 0xF42E312D, 0x6842ADA7, 0xC66A2B3B, 0x12754CCC, 0x782EF11C,
|
||||
0x6A124237, 0xB79251E7, 0x06A1BBE6, 0x4BFB6350, 0x1A6B1018, 0x11CAEDFA,
|
||||
0x3D25BDD8, 0xE2E1C3C9, 0x44421659, 0x0A121386, 0xD90CEC6E, 0xD5ABEA2A,
|
||||
0x64AF674E, 0xDA86A85F, 0xBEBFE988, 0x64E4C3FE, 0x9DBC8057, 0xF0F7C086,
|
||||
0x60787BF8, 0x6003604D, 0xD1FD8346, 0xF6381FB0, 0x7745AE04, 0xD736FCCC,
|
||||
0x83426B33, 0xF01EAB71, 0xB0804187, 0x3C005E5F, 0x77A057BE, 0xBDE8AE24,
|
||||
0x55464299, 0xBF582E61, 0x4E58F48F, 0xF2DDFDA2, 0xF474EF38, 0x8789BDC2,
|
||||
0x5366F9C3, 0xC8B38E74, 0xB475F255, 0x46FCD9B9, 0x7AEB2661, 0x8B1DDF84,
|
||||
0x846A0E79, 0x915F95E2, 0x466E598E, 0x20B45770, 0x8CD55591, 0xC902DE4C,
|
||||
0xB90BACE1, 0xBB8205D0, 0x11A86248, 0x7574A99E, 0xB77F19B6, 0xE0A9DC09,
|
||||
0x662D09A1, 0xC4324633, 0xE85A1F02, 0x09F0BE8C, 0x4A99A025, 0x1D6EFE10,
|
||||
0x1AB93D1D, 0x0BA5A4DF, 0xA186F20F, 0x2868F169, 0xDCB7DA83, 0x573906FE,
|
||||
0xA1E2CE9B, 0x4FCD7F52, 0x50115E01, 0xA70683FA, 0xA002B5C4, 0x0DE6D027,
|
||||
0x9AF88C27, 0x773F8641, 0xC3604C06, 0x61A806B5, 0xF0177A28, 0xC0F586E0,
|
||||
0x006058AA, 0x30DC7D62, 0x11E69ED7, 0x2338EA63, 0x53C2DD94, 0xC2C21634,
|
||||
0xBBCBEE56, 0x90BCB6DE, 0xEBFC7DA1, 0xCE591D76, 0x6F05E409, 0x4B7C0188,
|
||||
0x39720A3D, 0x7C927C24, 0x86E3725F, 0x724D9DB9, 0x1AC15BB4, 0xD39EB8FC,
|
||||
0xED545578, 0x08FCA5B5, 0xD83D7CD3, 0x4DAD0FC4, 0x1E50EF5E, 0xB161E6F8,
|
||||
0xA28514D9, 0x6C51133C, 0x6FD5C7E7, 0x56E14EC4, 0x362ABFCE, 0xDDC6C837,
|
||||
0xD79A3234, 0x92638212, 0x670EFA8E, 0x406000E0,
|
||||
};
|
||||
|
||||
static const word32 sbox3[] = {
|
||||
0x3A39CE37, 0xD3FAF5CF, 0xABC27737, 0x5AC52D1B, 0x5CB0679E, 0x4FA33742,
|
||||
0xD3822740, 0x99BC9BBE, 0xD5118E9D, 0xBF0F7315, 0xD62D1C7E, 0xC700C47B,
|
||||
0xB78C1B6B, 0x21A19045, 0xB26EB1BE, 0x6A366EB4, 0x5748AB2F, 0xBC946E79,
|
||||
0xC6A376D2, 0x6549C2C8, 0x530FF8EE, 0x468DDE7D, 0xD5730A1D, 0x4CD04DC6,
|
||||
0x2939BBDB, 0xA9BA4650, 0xAC9526E8, 0xBE5EE304, 0xA1FAD5F0, 0x6A2D519A,
|
||||
0x63EF8CE2, 0x9A86EE22, 0xC089C2B8, 0x43242EF6, 0xA51E03AA, 0x9CF2D0A4,
|
||||
0x83C061BA, 0x9BE96A4D, 0x8FE51550, 0xBA645BD6, 0x2826A2F9, 0xA73A3AE1,
|
||||
0x4BA99586, 0xEF5562E9, 0xC72FEFD3, 0xF752F7DA, 0x3F046F69, 0x77FA0A59,
|
||||
0x80E4A915, 0x87B08601, 0x9B09E6AD, 0x3B3EE593, 0xE990FD5A, 0x9E34D797,
|
||||
0x2CF0B7D9, 0x022B8B51, 0x96D5AC3A, 0x017DA67D, 0xD1CF3ED6, 0x7C7D2D28,
|
||||
0x1F9F25CF, 0xADF2B89B, 0x5AD6B472, 0x5A88F54C, 0xE029AC71, 0xE019A5E6,
|
||||
0x47B0ACFD, 0xED93FA9B, 0xE8D3C48D, 0x283B57CC, 0xF8D56629, 0x79132E28,
|
||||
0x785F0191, 0xED756055, 0xF7960E44, 0xE3D35E8C, 0x15056DD4, 0x88F46DBA,
|
||||
0x03A16125, 0x0564F0BD, 0xC3EB9E15, 0x3C9057A2, 0x97271AEC, 0xA93A072A,
|
||||
0x1B3F6D9B, 0x1E6321F5, 0xF59C66FB, 0x26DCF319, 0x7533D928, 0xB155FDF5,
|
||||
0x03563482, 0x8ABA3CBB, 0x28517711, 0xC20AD9F8, 0xABCC5167, 0xCCAD925F,
|
||||
0x4DE81751, 0x3830DC8E, 0x379D5862, 0x9320F991, 0xEA7A90C2, 0xFB3E7BCE,
|
||||
0x5121CE64, 0x774FBE32, 0xA8B6E37E, 0xC3293D46, 0x48DE5369, 0x6413E680,
|
||||
0xA2AE0810, 0xDD6DB224, 0x69852DFD, 0x09072166, 0xB39A460A, 0x6445C0DD,
|
||||
0x586CDECF, 0x1C20C8AE, 0x5BBEF7DD, 0x1B588D40, 0xCCD2017F, 0x6BB4E3BB,
|
||||
0xDDA26A7E, 0x3A59FF45, 0x3E350A44, 0xBCB4CDD5, 0x72EACEA8, 0xFA6484BB,
|
||||
0x8D6612AE, 0xBF3C6F47, 0xD29BE463, 0x542F5D9E, 0xAEC2771B, 0xF64E6370,
|
||||
0x740E0D8D, 0xE75B1357, 0xF8721671, 0xAF537D5D, 0x4040CB08, 0x4EB4E2CC,
|
||||
0x34D2466A, 0x0115AF84, 0xE1B00428, 0x95983A1D, 0x06B89FB4, 0xCE6EA048,
|
||||
0x6F3F3B82, 0x3520AB82, 0x011A1D4B, 0x277227F8, 0x611560B1, 0xE7933FDC,
|
||||
0xBB3A792B, 0x344525BD, 0xA08839E1, 0x51CE794B, 0x2F32C9B7, 0xA01FBAC9,
|
||||
0xE01CC87E, 0xBCC7D1F6, 0xCF0111C3, 0xA1E8AAC7, 0x1A908749, 0xD44FBD9A,
|
||||
0xD0DADECB, 0xD50ADA38, 0x0339C32A, 0xC6913667, 0x8DF9317C, 0xE0B12B4F,
|
||||
0xF79E59B7, 0x43F5BB3A, 0xF2D519FF, 0x27D9459C, 0xBF97222C, 0x15E6FC2A,
|
||||
0x0F91FC71, 0x9B941525, 0xFAE59361, 0xCEB69CEB, 0xC2A86459, 0x12BAA8D1,
|
||||
0xB6C1075E, 0xE3056A0C, 0x10D25065, 0xCB03A442, 0xE0EC6E0E, 0x1698DB3B,
|
||||
0x4C98A0BE, 0x3278E964, 0x9F1F9532, 0xE0D392DF, 0xD3A0342B, 0x8971F21E,
|
||||
0x1B0A7441, 0x4BA3348C, 0xC5BE7120, 0xC37632D8, 0xDF359F8D, 0x9B992F2E,
|
||||
0xE60B6F47, 0x0FE3F11D, 0xE54CDA54, 0x1EDAD891, 0xCE6279CF, 0xCD3E7E6F,
|
||||
0x1618B166, 0xFD2C1D05, 0x848FD2C5, 0xF6FB2299, 0xF523F357, 0xA6327623,
|
||||
0x93A83531, 0x56CCCD02, 0xACF08162, 0x5A75EBB5, 0x6E163697, 0x88D273CC,
|
||||
0xDE966292, 0x81B949D0, 0x4C50901B, 0x71C65614, 0xE6C6C7BD, 0x327A140A,
|
||||
0x45E1D006, 0xC3F27B9A, 0xC9AA53FD, 0x62A80F00, 0xBB25BFE2, 0x35BDD2F6,
|
||||
0x71126905, 0xB2040222, 0xB6CBCF7C, 0xCD769C2B, 0x53113EC0, 0x1640E3D3,
|
||||
0x38ABBD60, 0x2547ADF0, 0xBA38209C, 0xF746CE76, 0x77AFA1C5, 0x20756060,
|
||||
0x85CBFE4E, 0x8AE88DD8, 0x7AAAF9B0, 0x4CF9AA7E, 0x1948C25C, 0x02FB8A8C,
|
||||
0x01C36AE4, 0xD6EBE1F9, 0x90D4F869, 0xA65CDEA0, 0x3F09252D, 0xC208E69F,
|
||||
0xB74E6132, 0xCE77E25B, 0x578FDFE3, 0x3AC372E6,
|
||||
};
|
||||
|
||||
#define Fprime(a,b,c,d) ( ( (S0[a] + S1[b]) ^ S2[c] ) + S3[d] )
|
||||
#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 )
|
||||
|
||||
static void blowfish_encrypt(word32 xL, word32 xR, word32 * output,
|
||||
BlowfishContext * ctx)
|
||||
{
|
||||
word32 *S0 = ctx->S0;
|
||||
word32 *S1 = ctx->S1;
|
||||
word32 *S2 = ctx->S2;
|
||||
word32 *S3 = ctx->S3;
|
||||
word32 *P = ctx->P;
|
||||
word32 t;
|
||||
|
||||
ROUND(0);
|
||||
ROUND(1);
|
||||
ROUND(2);
|
||||
ROUND(3);
|
||||
ROUND(4);
|
||||
ROUND(5);
|
||||
ROUND(6);
|
||||
ROUND(7);
|
||||
ROUND(8);
|
||||
ROUND(9);
|
||||
ROUND(10);
|
||||
ROUND(11);
|
||||
ROUND(12);
|
||||
ROUND(13);
|
||||
ROUND(14);
|
||||
ROUND(15);
|
||||
xL ^= P[16];
|
||||
xR ^= P[17];
|
||||
|
||||
output[0] = xR;
|
||||
output[1] = xL;
|
||||
}
|
||||
|
||||
static void blowfish_decrypt(word32 xL, word32 xR, word32 * output,
|
||||
BlowfishContext * ctx)
|
||||
{
|
||||
word32 *S0 = ctx->S0;
|
||||
word32 *S1 = ctx->S1;
|
||||
word32 *S2 = ctx->S2;
|
||||
word32 *S3 = ctx->S3;
|
||||
word32 *P = ctx->P;
|
||||
word32 t;
|
||||
|
||||
ROUND(17);
|
||||
ROUND(16);
|
||||
ROUND(15);
|
||||
ROUND(14);
|
||||
ROUND(13);
|
||||
ROUND(12);
|
||||
ROUND(11);
|
||||
ROUND(10);
|
||||
ROUND(9);
|
||||
ROUND(8);
|
||||
ROUND(7);
|
||||
ROUND(6);
|
||||
ROUND(5);
|
||||
ROUND(4);
|
||||
ROUND(3);
|
||||
ROUND(2);
|
||||
xL ^= P[1];
|
||||
xR ^= P[0];
|
||||
|
||||
output[0] = xR;
|
||||
output[1] = xL;
|
||||
}
|
||||
|
||||
static void blowfish_lsb_encrypt_cbc(unsigned char *blk, int len,
|
||||
BlowfishContext * ctx)
|
||||
{
|
||||
word32 xL, xR, out[2], iv0, iv1;
|
||||
|
||||
assert((len & 7) == 0);
|
||||
|
||||
iv0 = ctx->iv0;
|
||||
iv1 = ctx->iv1;
|
||||
|
||||
while (len > 0) {
|
||||
xL = GET_32BIT_LSB_FIRST(blk);
|
||||
xR = GET_32BIT_LSB_FIRST(blk + 4);
|
||||
iv0 ^= xL;
|
||||
iv1 ^= xR;
|
||||
blowfish_encrypt(iv0, iv1, out, ctx);
|
||||
iv0 = out[0];
|
||||
iv1 = out[1];
|
||||
PUT_32BIT_LSB_FIRST(blk, iv0);
|
||||
PUT_32BIT_LSB_FIRST(blk + 4, iv1);
|
||||
blk += 8;
|
||||
len -= 8;
|
||||
}
|
||||
|
||||
ctx->iv0 = iv0;
|
||||
ctx->iv1 = iv1;
|
||||
}
|
||||
|
||||
static void blowfish_lsb_decrypt_cbc(unsigned char *blk, int len,
|
||||
BlowfishContext * ctx)
|
||||
{
|
||||
word32 xL, xR, out[2], iv0, iv1;
|
||||
|
||||
assert((len & 7) == 0);
|
||||
|
||||
iv0 = ctx->iv0;
|
||||
iv1 = ctx->iv1;
|
||||
|
||||
while (len > 0) {
|
||||
xL = GET_32BIT_LSB_FIRST(blk);
|
||||
xR = GET_32BIT_LSB_FIRST(blk + 4);
|
||||
blowfish_decrypt(xL, xR, out, ctx);
|
||||
iv0 ^= out[0];
|
||||
iv1 ^= out[1];
|
||||
PUT_32BIT_LSB_FIRST(blk, iv0);
|
||||
PUT_32BIT_LSB_FIRST(blk + 4, iv1);
|
||||
iv0 = xL;
|
||||
iv1 = xR;
|
||||
blk += 8;
|
||||
len -= 8;
|
||||
}
|
||||
|
||||
ctx->iv0 = iv0;
|
||||
ctx->iv1 = iv1;
|
||||
}
|
||||
|
||||
static void blowfish_msb_encrypt_cbc(unsigned char *blk, int len,
|
||||
BlowfishContext * ctx)
|
||||
{
|
||||
word32 xL, xR, out[2], iv0, iv1;
|
||||
|
||||
assert((len & 7) == 0);
|
||||
|
||||
iv0 = ctx->iv0;
|
||||
iv1 = ctx->iv1;
|
||||
|
||||
while (len > 0) {
|
||||
xL = GET_32BIT_MSB_FIRST(blk);
|
||||
xR = GET_32BIT_MSB_FIRST(blk + 4);
|
||||
iv0 ^= xL;
|
||||
iv1 ^= xR;
|
||||
blowfish_encrypt(iv0, iv1, out, ctx);
|
||||
iv0 = out[0];
|
||||
iv1 = out[1];
|
||||
PUT_32BIT_MSB_FIRST(blk, iv0);
|
||||
PUT_32BIT_MSB_FIRST(blk + 4, iv1);
|
||||
blk += 8;
|
||||
len -= 8;
|
||||
}
|
||||
|
||||
ctx->iv0 = iv0;
|
||||
ctx->iv1 = iv1;
|
||||
}
|
||||
|
||||
static void blowfish_msb_decrypt_cbc(unsigned char *blk, int len,
|
||||
BlowfishContext * ctx)
|
||||
{
|
||||
word32 xL, xR, out[2], iv0, iv1;
|
||||
|
||||
assert((len & 7) == 0);
|
||||
|
||||
iv0 = ctx->iv0;
|
||||
iv1 = ctx->iv1;
|
||||
|
||||
while (len > 0) {
|
||||
xL = GET_32BIT_MSB_FIRST(blk);
|
||||
xR = GET_32BIT_MSB_FIRST(blk + 4);
|
||||
blowfish_decrypt(xL, xR, out, ctx);
|
||||
iv0 ^= out[0];
|
||||
iv1 ^= out[1];
|
||||
PUT_32BIT_MSB_FIRST(blk, iv0);
|
||||
PUT_32BIT_MSB_FIRST(blk + 4, iv1);
|
||||
iv0 = xL;
|
||||
iv1 = xR;
|
||||
blk += 8;
|
||||
len -= 8;
|
||||
}
|
||||
|
||||
ctx->iv0 = iv0;
|
||||
ctx->iv1 = iv1;
|
||||
}
|
||||
|
||||
static void blowfish_msb_sdctr(unsigned char *blk, int len,
|
||||
BlowfishContext * ctx)
|
||||
{
|
||||
word32 b[2], iv0, iv1, tmp;
|
||||
|
||||
assert((len & 7) == 0);
|
||||
|
||||
iv0 = ctx->iv0;
|
||||
iv1 = ctx->iv1;
|
||||
|
||||
while (len > 0) {
|
||||
blowfish_encrypt(iv0, iv1, b, ctx);
|
||||
tmp = GET_32BIT_MSB_FIRST(blk);
|
||||
PUT_32BIT_MSB_FIRST(blk, tmp ^ b[0]);
|
||||
tmp = GET_32BIT_MSB_FIRST(blk + 4);
|
||||
PUT_32BIT_MSB_FIRST(blk + 4, tmp ^ b[1]);
|
||||
if ((iv1 = (iv1 + 1) & 0xffffffff) == 0)
|
||||
iv0 = (iv0 + 1) & 0xffffffff;
|
||||
blk += 8;
|
||||
len -= 8;
|
||||
}
|
||||
|
||||
ctx->iv0 = iv0;
|
||||
ctx->iv1 = iv1;
|
||||
}
|
||||
|
||||
static void blowfish_setkey(BlowfishContext * ctx,
|
||||
const unsigned char *key, short keybytes)
|
||||
{
|
||||
word32 *S0 = ctx->S0;
|
||||
word32 *S1 = ctx->S1;
|
||||
word32 *S2 = ctx->S2;
|
||||
word32 *S3 = ctx->S3;
|
||||
word32 *P = ctx->P;
|
||||
word32 str[2];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 18; i++) {
|
||||
P[i] = parray[i];
|
||||
P[i] ^=
|
||||
((word32) (unsigned char) (key[(i * 4 + 0) % keybytes])) << 24;
|
||||
P[i] ^=
|
||||
((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++) {
|
||||
S0[i] = sbox0[i];
|
||||
S1[i] = sbox1[i];
|
||||
S2[i] = sbox2[i];
|
||||
S3[i] = sbox3[i];
|
||||
}
|
||||
|
||||
str[0] = str[1] = 0;
|
||||
|
||||
for (i = 0; i < 18; i += 2) {
|
||||
blowfish_encrypt(str[0], str[1], str, ctx);
|
||||
P[i] = str[0];
|
||||
P[i + 1] = str[1];
|
||||
}
|
||||
|
||||
for (i = 0; i < 256; i += 2) {
|
||||
blowfish_encrypt(str[0], str[1], str, ctx);
|
||||
S0[i] = str[0];
|
||||
S0[i + 1] = str[1];
|
||||
}
|
||||
for (i = 0; i < 256; i += 2) {
|
||||
blowfish_encrypt(str[0], str[1], str, ctx);
|
||||
S1[i] = str[0];
|
||||
S1[i + 1] = str[1];
|
||||
}
|
||||
for (i = 0; i < 256; i += 2) {
|
||||
blowfish_encrypt(str[0], str[1], str, ctx);
|
||||
S2[i] = str[0];
|
||||
S2[i + 1] = str[1];
|
||||
}
|
||||
for (i = 0; i < 256; i += 2) {
|
||||
blowfish_encrypt(str[0], str[1], str, ctx);
|
||||
S3[i] = str[0];
|
||||
S3[i + 1] = str[1];
|
||||
}
|
||||
}
|
||||
|
||||
/* -- Interface with PuTTY -- */
|
||||
|
||||
#define SSH_SESSION_KEY_LENGTH 32
|
||||
|
||||
static void *blowfish_make_context(void)
|
||||
{
|
||||
return snew(BlowfishContext);
|
||||
}
|
||||
|
||||
static void *blowfish_ssh1_make_context(void)
|
||||
{
|
||||
/* In SSH-1, need one key for each direction */
|
||||
return snewn(2, BlowfishContext);
|
||||
}
|
||||
|
||||
static void blowfish_free_context(void *handle)
|
||||
{
|
||||
sfree(handle);
|
||||
}
|
||||
|
||||
static void blowfish_key(void *handle, unsigned char *key)
|
||||
{
|
||||
BlowfishContext *ctx = (BlowfishContext *)handle;
|
||||
blowfish_setkey(ctx, key, 16);
|
||||
}
|
||||
|
||||
static void blowfish256_key(void *handle, unsigned char *key)
|
||||
{
|
||||
BlowfishContext *ctx = (BlowfishContext *)handle;
|
||||
blowfish_setkey(ctx, key, 32);
|
||||
}
|
||||
|
||||
static void blowfish_iv(void *handle, unsigned char *key)
|
||||
{
|
||||
BlowfishContext *ctx = (BlowfishContext *)handle;
|
||||
ctx->iv0 = GET_32BIT_MSB_FIRST(key);
|
||||
ctx->iv1 = GET_32BIT_MSB_FIRST(key + 4);
|
||||
}
|
||||
|
||||
static void blowfish_sesskey(void *handle, unsigned char *key)
|
||||
{
|
||||
BlowfishContext *ctx = (BlowfishContext *)handle;
|
||||
blowfish_setkey(ctx, key, SSH_SESSION_KEY_LENGTH);
|
||||
ctx->iv0 = 0;
|
||||
ctx->iv1 = 0;
|
||||
ctx[1] = ctx[0]; /* structure copy */
|
||||
}
|
||||
|
||||
static void blowfish_ssh1_encrypt_blk(void *handle, unsigned char *blk,
|
||||
int len)
|
||||
{
|
||||
BlowfishContext *ctx = (BlowfishContext *)handle;
|
||||
blowfish_lsb_encrypt_cbc(blk, len, ctx);
|
||||
}
|
||||
|
||||
static void blowfish_ssh1_decrypt_blk(void *handle, unsigned char *blk,
|
||||
int len)
|
||||
{
|
||||
BlowfishContext *ctx = (BlowfishContext *)handle;
|
||||
blowfish_lsb_decrypt_cbc(blk, len, ctx+1);
|
||||
}
|
||||
|
||||
static void blowfish_ssh2_encrypt_blk(void *handle, unsigned char *blk,
|
||||
int len)
|
||||
{
|
||||
BlowfishContext *ctx = (BlowfishContext *)handle;
|
||||
blowfish_msb_encrypt_cbc(blk, len, ctx);
|
||||
}
|
||||
|
||||
static void blowfish_ssh2_decrypt_blk(void *handle, unsigned char *blk,
|
||||
int len)
|
||||
{
|
||||
BlowfishContext *ctx = (BlowfishContext *)handle;
|
||||
blowfish_msb_decrypt_cbc(blk, len, ctx);
|
||||
}
|
||||
|
||||
static void blowfish_ssh2_sdctr(void *handle, unsigned char *blk,
|
||||
int len)
|
||||
{
|
||||
BlowfishContext *ctx = (BlowfishContext *)handle;
|
||||
blowfish_msb_sdctr(blk, len, ctx);
|
||||
}
|
||||
|
||||
const struct ssh_cipher ssh_blowfish_ssh1 = {
|
||||
blowfish_ssh1_make_context, blowfish_free_context, blowfish_sesskey,
|
||||
blowfish_ssh1_encrypt_blk, blowfish_ssh1_decrypt_blk,
|
||||
8, "Blowfish-128 CBC"
|
||||
};
|
||||
|
||||
static const struct ssh2_cipher ssh_blowfish_ssh2 = {
|
||||
blowfish_make_context, blowfish_free_context, blowfish_iv, blowfish_key,
|
||||
blowfish_ssh2_encrypt_blk, blowfish_ssh2_decrypt_blk,
|
||||
"blowfish-cbc",
|
||||
8, 128, SSH_CIPHER_IS_CBC, "Blowfish-128 CBC"
|
||||
};
|
||||
|
||||
static const struct ssh2_cipher ssh_blowfish_ssh2_ctr = {
|
||||
blowfish_make_context, blowfish_free_context, blowfish_iv, blowfish256_key,
|
||||
blowfish_ssh2_sdctr, blowfish_ssh2_sdctr,
|
||||
"blowfish-ctr",
|
||||
8, 256, 0, "Blowfish-256 SDCTR"
|
||||
};
|
||||
|
||||
static const struct ssh2_cipher *const blowfish_list[] = {
|
||||
&ssh_blowfish_ssh2_ctr,
|
||||
&ssh_blowfish_ssh2
|
||||
};
|
||||
|
||||
const struct ssh2_ciphers ssh2_blowfish = {
|
||||
sizeof(blowfish_list) / sizeof(*blowfish_list),
|
||||
blowfish_list
|
||||
};
|
||||
1092
sFTPlugins/psftp/SSHBN.C
Normal file
1092
sFTPlugins/psftp/SSHBN.C
Normal file
File diff suppressed because it is too large
Load Diff
230
sFTPlugins/psftp/SSHCRC.C
Normal file
230
sFTPlugins/psftp/SSHCRC.C
Normal file
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* CRC32 implementation.
|
||||
*
|
||||
* The basic concept of a CRC is that you treat your bit-string
|
||||
* abcdefg... as a ludicrously long polynomial M=a+bx+cx^2+dx^3+...
|
||||
* over Z[2]. You then take a modulus polynomial P, and compute the
|
||||
* remainder of M on division by P. Thus, an erroneous message N
|
||||
* will only have the same CRC if the difference E = M-N is an
|
||||
* exact multiple of P. (Note that as we are working over Z[2], M-N
|
||||
* = N-M = M+N; but that's not very important.)
|
||||
*
|
||||
* What makes the CRC good is choosing P to have good properties:
|
||||
*
|
||||
* - If its first and last terms are both nonzero then it cannot
|
||||
* be a factor of any single term x^i. Therefore if M and N
|
||||
* differ by exactly one bit their CRCs will guaranteeably
|
||||
* be distinct.
|
||||
*
|
||||
* - If it has a prime (irreducible) factor with three terms then
|
||||
* it cannot divide a polynomial of the form x^i(1+x^j).
|
||||
* Therefore if M and N differ by exactly _two_ bits they will
|
||||
* have different CRCs.
|
||||
*
|
||||
* - If it has a factor (x+1) then it cannot divide a polynomial
|
||||
* with an odd number of terms. Therefore if M and N differ by
|
||||
* _any odd_ number of bits they will have different CRCs.
|
||||
*
|
||||
* - If the error term E is of the form x^i*B(x) where B(x) has
|
||||
* order less than P (i.e. a short _burst_ of errors) then P
|
||||
* cannot divide E (since no polynomial can divide a shorter
|
||||
* one), so any such error burst will be spotted.
|
||||
*
|
||||
* The CRC32 standard polynomial is
|
||||
* x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x^1+x^0
|
||||
*
|
||||
* In fact, we don't compute M mod P; we compute M*x^32 mod P.
|
||||
*
|
||||
* The concrete implementation of the CRC is this: we maintain at
|
||||
* all times a 32-bit word which is the current remainder of the
|
||||
* polynomial mod P. Whenever we receive an extra bit, we multiply
|
||||
* the existing remainder by x, add (XOR) the x^32 term thus
|
||||
* generated to the new x^32 term caused by the incoming bit, and
|
||||
* remove the resulting combined x^32 term if present by replacing
|
||||
* it with (P-x^32).
|
||||
*
|
||||
* Bit 0 of the word is the x^31 term and bit 31 is the x^0 term.
|
||||
* Thus, multiplying by x means shifting right. So the actual
|
||||
* algorithm goes like this:
|
||||
*
|
||||
* x32term = (crcword & 1) ^ newbit;
|
||||
* crcword = (crcword >> 1) ^ (x32term * 0xEDB88320);
|
||||
*
|
||||
* In practice, we pre-compute what will happen to crcword on any
|
||||
* given sequence of eight incoming bits, and store that in a table
|
||||
* which we then use at run-time to do the job:
|
||||
*
|
||||
* outgoingplusnew = (crcword & 0xFF) ^ newbyte;
|
||||
* crcword = (crcword >> 8) ^ table[outgoingplusnew];
|
||||
*
|
||||
* where table[outgoingplusnew] is computed by setting crcword=0
|
||||
* and then iterating the first code fragment eight times (taking
|
||||
* the incoming byte low bit first).
|
||||
*
|
||||
* Note that all shifts are rightward and thus no assumption is
|
||||
* made about exact word length! (Although word length must be at
|
||||
* _least_ 32 bits, but ANSI C guarantees this for `unsigned long'
|
||||
* anyway.)
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "ssh.h"
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* Multi-function module. Can be compiled three ways.
|
||||
*
|
||||
* - Compile with no special #defines. Will generate a table
|
||||
* that's already initialised at compile time, and one function
|
||||
* crc32_compute(buf,len) that uses it. Normal usage.
|
||||
*
|
||||
* - Compile with INITFUNC defined. Will generate an uninitialised
|
||||
* array as the table, and as well as crc32_compute(buf,len) it
|
||||
* will also generate void crc32_init(void) which sets up the
|
||||
* table at run time. Useful if binary size is important.
|
||||
*
|
||||
* - Compile with GENPROGRAM defined. Will create a standalone
|
||||
* program that does the initialisation and outputs the table as
|
||||
* C code.
|
||||
*/
|
||||
|
||||
#define POLY (0xEDB88320L)
|
||||
|
||||
#ifdef GENPROGRAM
|
||||
#define INITFUNC /* the gen program needs the init func :-) */
|
||||
#endif
|
||||
|
||||
#ifdef INITFUNC
|
||||
|
||||
/*
|
||||
* This variant of the code generates the table at run-time from an
|
||||
* init function.
|
||||
*/
|
||||
static unsigned long crc32_table[256];
|
||||
|
||||
void crc32_init(void)
|
||||
{
|
||||
unsigned long crcword;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
unsigned long newbyte, x32term;
|
||||
int j;
|
||||
crcword = 0;
|
||||
newbyte = i;
|
||||
for (j = 0; j < 8; j++) {
|
||||
x32term = (crcword ^ newbyte) & 1;
|
||||
crcword = (crcword >> 1) ^ (x32term * POLY);
|
||||
newbyte >>= 1;
|
||||
}
|
||||
crc32_table[i] = crcword;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* This variant of the code has the data already prepared.
|
||||
*/
|
||||
static const unsigned long crc32_table[256] = {
|
||||
0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL,
|
||||
0x076DC419L, 0x706AF48FL, 0xE963A535L, 0x9E6495A3L,
|
||||
0x0EDB8832L, 0x79DCB8A4L, 0xE0D5E91EL, 0x97D2D988L,
|
||||
0x09B64C2BL, 0x7EB17CBDL, 0xE7B82D07L, 0x90BF1D91L,
|
||||
0x1DB71064L, 0x6AB020F2L, 0xF3B97148L, 0x84BE41DEL,
|
||||
0x1ADAD47DL, 0x6DDDE4EBL, 0xF4D4B551L, 0x83D385C7L,
|
||||
0x136C9856L, 0x646BA8C0L, 0xFD62F97AL, 0x8A65C9ECL,
|
||||
0x14015C4FL, 0x63066CD9L, 0xFA0F3D63L, 0x8D080DF5L,
|
||||
0x3B6E20C8L, 0x4C69105EL, 0xD56041E4L, 0xA2677172L,
|
||||
0x3C03E4D1L, 0x4B04D447L, 0xD20D85FDL, 0xA50AB56BL,
|
||||
0x35B5A8FAL, 0x42B2986CL, 0xDBBBC9D6L, 0xACBCF940L,
|
||||
0x32D86CE3L, 0x45DF5C75L, 0xDCD60DCFL, 0xABD13D59L,
|
||||
0x26D930ACL, 0x51DE003AL, 0xC8D75180L, 0xBFD06116L,
|
||||
0x21B4F4B5L, 0x56B3C423L, 0xCFBA9599L, 0xB8BDA50FL,
|
||||
0x2802B89EL, 0x5F058808L, 0xC60CD9B2L, 0xB10BE924L,
|
||||
0x2F6F7C87L, 0x58684C11L, 0xC1611DABL, 0xB6662D3DL,
|
||||
0x76DC4190L, 0x01DB7106L, 0x98D220BCL, 0xEFD5102AL,
|
||||
0x71B18589L, 0x06B6B51FL, 0x9FBFE4A5L, 0xE8B8D433L,
|
||||
0x7807C9A2L, 0x0F00F934L, 0x9609A88EL, 0xE10E9818L,
|
||||
0x7F6A0DBBL, 0x086D3D2DL, 0x91646C97L, 0xE6635C01L,
|
||||
0x6B6B51F4L, 0x1C6C6162L, 0x856530D8L, 0xF262004EL,
|
||||
0x6C0695EDL, 0x1B01A57BL, 0x8208F4C1L, 0xF50FC457L,
|
||||
0x65B0D9C6L, 0x12B7E950L, 0x8BBEB8EAL, 0xFCB9887CL,
|
||||
0x62DD1DDFL, 0x15DA2D49L, 0x8CD37CF3L, 0xFBD44C65L,
|
||||
0x4DB26158L, 0x3AB551CEL, 0xA3BC0074L, 0xD4BB30E2L,
|
||||
0x4ADFA541L, 0x3DD895D7L, 0xA4D1C46DL, 0xD3D6F4FBL,
|
||||
0x4369E96AL, 0x346ED9FCL, 0xAD678846L, 0xDA60B8D0L,
|
||||
0x44042D73L, 0x33031DE5L, 0xAA0A4C5FL, 0xDD0D7CC9L,
|
||||
0x5005713CL, 0x270241AAL, 0xBE0B1010L, 0xC90C2086L,
|
||||
0x5768B525L, 0x206F85B3L, 0xB966D409L, 0xCE61E49FL,
|
||||
0x5EDEF90EL, 0x29D9C998L, 0xB0D09822L, 0xC7D7A8B4L,
|
||||
0x59B33D17L, 0x2EB40D81L, 0xB7BD5C3BL, 0xC0BA6CADL,
|
||||
0xEDB88320L, 0x9ABFB3B6L, 0x03B6E20CL, 0x74B1D29AL,
|
||||
0xEAD54739L, 0x9DD277AFL, 0x04DB2615L, 0x73DC1683L,
|
||||
0xE3630B12L, 0x94643B84L, 0x0D6D6A3EL, 0x7A6A5AA8L,
|
||||
0xE40ECF0BL, 0x9309FF9DL, 0x0A00AE27L, 0x7D079EB1L,
|
||||
0xF00F9344L, 0x8708A3D2L, 0x1E01F268L, 0x6906C2FEL,
|
||||
0xF762575DL, 0x806567CBL, 0x196C3671L, 0x6E6B06E7L,
|
||||
0xFED41B76L, 0x89D32BE0L, 0x10DA7A5AL, 0x67DD4ACCL,
|
||||
0xF9B9DF6FL, 0x8EBEEFF9L, 0x17B7BE43L, 0x60B08ED5L,
|
||||
0xD6D6A3E8L, 0xA1D1937EL, 0x38D8C2C4L, 0x4FDFF252L,
|
||||
0xD1BB67F1L, 0xA6BC5767L, 0x3FB506DDL, 0x48B2364BL,
|
||||
0xD80D2BDAL, 0xAF0A1B4CL, 0x36034AF6L, 0x41047A60L,
|
||||
0xDF60EFC3L, 0xA867DF55L, 0x316E8EEFL, 0x4669BE79L,
|
||||
0xCB61B38CL, 0xBC66831AL, 0x256FD2A0L, 0x5268E236L,
|
||||
0xCC0C7795L, 0xBB0B4703L, 0x220216B9L, 0x5505262FL,
|
||||
0xC5BA3BBEL, 0xB2BD0B28L, 0x2BB45A92L, 0x5CB36A04L,
|
||||
0xC2D7FFA7L, 0xB5D0CF31L, 0x2CD99E8BL, 0x5BDEAE1DL,
|
||||
0x9B64C2B0L, 0xEC63F226L, 0x756AA39CL, 0x026D930AL,
|
||||
0x9C0906A9L, 0xEB0E363FL, 0x72076785L, 0x05005713L,
|
||||
0x95BF4A82L, 0xE2B87A14L, 0x7BB12BAEL, 0x0CB61B38L,
|
||||
0x92D28E9BL, 0xE5D5BE0DL, 0x7CDCEFB7L, 0x0BDBDF21L,
|
||||
0x86D3D2D4L, 0xF1D4E242L, 0x68DDB3F8L, 0x1FDA836EL,
|
||||
0x81BE16CDL, 0xF6B9265BL, 0x6FB077E1L, 0x18B74777L,
|
||||
0x88085AE6L, 0xFF0F6A70L, 0x66063BCAL, 0x11010B5CL,
|
||||
0x8F659EFFL, 0xF862AE69L, 0x616BFFD3L, 0x166CCF45L,
|
||||
0xA00AE278L, 0xD70DD2EEL, 0x4E048354L, 0x3903B3C2L,
|
||||
0xA7672661L, 0xD06016F7L, 0x4969474DL, 0x3E6E77DBL,
|
||||
0xAED16A4AL, 0xD9D65ADCL, 0x40DF0B66L, 0x37D83BF0L,
|
||||
0xA9BCAE53L, 0xDEBB9EC5L, 0x47B2CF7FL, 0x30B5FFE9L,
|
||||
0xBDBDF21CL, 0xCABAC28AL, 0x53B39330L, 0x24B4A3A6L,
|
||||
0xBAD03605L, 0xCDD70693L, 0x54DE5729L, 0x23D967BFL,
|
||||
0xB3667A2EL, 0xC4614AB8L, 0x5D681B02L, 0x2A6F2B94L,
|
||||
0xB40BBE37L, 0xC30C8EA1L, 0x5A05DF1BL, 0x2D02EF8DL
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef GENPROGRAM
|
||||
int main(void)
|
||||
{
|
||||
unsigned long crcword;
|
||||
int i;
|
||||
|
||||
crc32_init();
|
||||
for (i = 0; i < 256; i++) {
|
||||
printf("%s0x%08XL%s",
|
||||
(i % 4 == 0 ? " " : " "),
|
||||
crc32_table[i],
|
||||
(i % 4 == 3 ? (i == 255 ? "\n" : ",\n") : ","));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
unsigned long crc32_update(unsigned long crcword, const void *buf, size_t len)
|
||||
{
|
||||
const unsigned char *p = (const unsigned char *) buf;
|
||||
while (len--) {
|
||||
unsigned long newbyte = *p++;
|
||||
newbyte ^= crcword & 0xFFL;
|
||||
crcword = (crcword >> 8) ^ crc32_table[newbyte];
|
||||
}
|
||||
return crcword;
|
||||
}
|
||||
|
||||
unsigned long crc32_compute(const void *buf, size_t len)
|
||||
{
|
||||
return crc32_update(0L, buf, len);
|
||||
}
|
||||
172
sFTPlugins/psftp/SSHCRCDA.C
Normal file
172
sFTPlugins/psftp/SSHCRCDA.C
Normal file
@@ -0,0 +1,172 @@
|
||||
/* $OpenBSD: deattack.c,v 1.14 2001/06/23 15:12:18 itojun Exp $ */
|
||||
|
||||
/*
|
||||
* Cryptographic attack detector for ssh - source code
|
||||
*
|
||||
* Copyright (c) 1998 CORE SDI S.A., Buenos Aires, Argentina.
|
||||
*
|
||||
* All rights reserved. Redistribution and use in source and binary
|
||||
* forms, with or without modification, are permitted provided that
|
||||
* this copyright notice is retained.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES ARE DISCLAIMED. IN NO EVENT SHALL CORE SDI S.A. BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY OR
|
||||
* CONSEQUENTIAL DAMAGES RESULTING FROM THE USE OR MISUSE OF THIS
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Ariel Futoransky <futo@core-sdi.com>
|
||||
* <http://www.core-sdi.com>
|
||||
*
|
||||
* Modified for use in PuTTY by Simon Tatham
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include "misc.h"
|
||||
#include "ssh.h"
|
||||
|
||||
typedef unsigned char uchar;
|
||||
typedef unsigned short uint16;
|
||||
|
||||
/* SSH Constants */
|
||||
#define SSH_MAXBLOCKS (32 * 1024)
|
||||
#define SSH_BLOCKSIZE (8)
|
||||
|
||||
/* Hashing constants */
|
||||
#define HASH_MINSIZE (8 * 1024)
|
||||
#define HASH_ENTRYSIZE (sizeof(uint16))
|
||||
#define HASH_FACTOR(x) ((x)*3/2)
|
||||
#define HASH_UNUSEDCHAR (0xff)
|
||||
#define HASH_UNUSED (0xffff)
|
||||
#define HASH_IV (0xfffe)
|
||||
|
||||
#define HASH_MINBLOCKS (7*SSH_BLOCKSIZE)
|
||||
|
||||
/* Hash function (Input keys are cipher results) */
|
||||
#define HASH(x) GET_32BIT_MSB_FIRST(x)
|
||||
|
||||
#define CMP(a, b) (memcmp(a, b, SSH_BLOCKSIZE))
|
||||
|
||||
uchar ONE[4] = { 1, 0, 0, 0 };
|
||||
uchar ZERO[4] = { 0, 0, 0, 0 };
|
||||
|
||||
struct crcda_ctx {
|
||||
uint16 *h;
|
||||
uint32 n;
|
||||
};
|
||||
|
||||
void *crcda_make_context(void)
|
||||
{
|
||||
struct crcda_ctx *ret = snew(struct crcda_ctx);
|
||||
ret->h = NULL;
|
||||
ret->n = HASH_MINSIZE / HASH_ENTRYSIZE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void crcda_free_context(void *handle)
|
||||
{
|
||||
struct crcda_ctx *ctx = (struct crcda_ctx *)handle;
|
||||
if (ctx) {
|
||||
sfree(ctx->h);
|
||||
ctx->h = NULL;
|
||||
sfree(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
static void crc_update(uint32 *a, void *b)
|
||||
{
|
||||
*a = crc32_update(*a, b, 4);
|
||||
}
|
||||
|
||||
/* detect if a block is used in a particular pattern */
|
||||
static int check_crc(uchar *S, uchar *buf, uint32 len, uchar *IV)
|
||||
{
|
||||
uint32 crc;
|
||||
uchar *c;
|
||||
|
||||
crc = 0;
|
||||
if (IV && !CMP(S, IV)) {
|
||||
crc_update(&crc, ONE);
|
||||
crc_update(&crc, ZERO);
|
||||
}
|
||||
for (c = buf; c < buf + len; c += SSH_BLOCKSIZE) {
|
||||
if (!CMP(S, c)) {
|
||||
crc_update(&crc, ONE);
|
||||
crc_update(&crc, ZERO);
|
||||
} else {
|
||||
crc_update(&crc, ZERO);
|
||||
crc_update(&crc, ZERO);
|
||||
}
|
||||
}
|
||||
return (crc == 0);
|
||||
}
|
||||
|
||||
/* Detect a crc32 compensation attack on a packet */
|
||||
int detect_attack(void *handle, uchar *buf, uint32 len, uchar *IV)
|
||||
{
|
||||
struct crcda_ctx *ctx = (struct crcda_ctx *)handle;
|
||||
register uint32 i, j;
|
||||
uint32 l;
|
||||
register uchar *c;
|
||||
uchar *d;
|
||||
|
||||
assert(!(len > (SSH_MAXBLOCKS * SSH_BLOCKSIZE) ||
|
||||
len % SSH_BLOCKSIZE != 0));
|
||||
for (l = ctx->n; l < HASH_FACTOR(len / SSH_BLOCKSIZE); l = l << 2)
|
||||
;
|
||||
|
||||
if (ctx->h == NULL) {
|
||||
ctx->n = l;
|
||||
ctx->h = snewn(ctx->n, uint16);
|
||||
} else {
|
||||
if (l > ctx->n) {
|
||||
ctx->n = l;
|
||||
ctx->h = sresize(ctx->h, ctx->n, uint16);
|
||||
}
|
||||
}
|
||||
|
||||
if (len <= HASH_MINBLOCKS) {
|
||||
for (c = buf; c < buf + len; c += SSH_BLOCKSIZE) {
|
||||
if (IV && (!CMP(c, IV))) {
|
||||
if ((check_crc(c, buf, len, IV)))
|
||||
return 1; /* attack detected */
|
||||
else
|
||||
break;
|
||||
}
|
||||
for (d = buf; d < c; d += SSH_BLOCKSIZE) {
|
||||
if (!CMP(c, d)) {
|
||||
if ((check_crc(c, buf, len, IV)))
|
||||
return 1; /* attack detected */
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0; /* ok */
|
||||
}
|
||||
memset(ctx->h, HASH_UNUSEDCHAR, ctx->n * HASH_ENTRYSIZE);
|
||||
|
||||
if (IV)
|
||||
ctx->h[HASH(IV) & (ctx->n - 1)] = HASH_IV;
|
||||
|
||||
for (c = buf, j = 0; c < (buf + len); c += SSH_BLOCKSIZE, j++) {
|
||||
for (i = HASH(c) & (ctx->n - 1); ctx->h[i] != HASH_UNUSED;
|
||||
i = (i + 1) & (ctx->n - 1)) {
|
||||
if (ctx->h[i] == HASH_IV) {
|
||||
if (!CMP(c, IV)) {
|
||||
if (check_crc(c, buf, len, IV))
|
||||
return 1; /* attack detected */
|
||||
else
|
||||
break;
|
||||
}
|
||||
} else if (!CMP(c, buf + ctx->h[i] * SSH_BLOCKSIZE)) {
|
||||
if (check_crc(c, buf, len, IV))
|
||||
return 1; /* attack detected */
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
ctx->h[i] = j;
|
||||
}
|
||||
return 0; /* ok */
|
||||
}
|
||||
1031
sFTPlugins/psftp/SSHDES.C
Normal file
1031
sFTPlugins/psftp/SSHDES.C
Normal file
File diff suppressed because it is too large
Load Diff
230
sFTPlugins/psftp/SSHDH.C
Normal file
230
sFTPlugins/psftp/SSHDH.C
Normal file
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* Diffie-Hellman implementation for PuTTY.
|
||||
*/
|
||||
|
||||
#include "ssh.h"
|
||||
|
||||
/*
|
||||
* The primes used in the group1 and group14 key exchange.
|
||||
*/
|
||||
static const unsigned char P1[] = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
|
||||
0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
|
||||
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
|
||||
0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
|
||||
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
|
||||
0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
|
||||
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
|
||||
0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
|
||||
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
|
||||
0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
|
||||
};
|
||||
static const unsigned char P14[] = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
|
||||
0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
|
||||
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
|
||||
0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
|
||||
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
|
||||
0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
|
||||
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
|
||||
0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
|
||||
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
|
||||
0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
|
||||
0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
|
||||
0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
|
||||
0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
|
||||
0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
|
||||
0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
|
||||
0xCA, 0x18, 0x21, 0x7C, 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
|
||||
0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03, 0x9B, 0x27, 0x83, 0xA2,
|
||||
0xEC, 0x07, 0xA2, 0x8F, 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
|
||||
0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18, 0x39, 0x95, 0x49, 0x7C,
|
||||
0xEA, 0x95, 0x6A, 0xE5, 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
|
||||
0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF
|
||||
};
|
||||
|
||||
/*
|
||||
* The generator g = 2 (used for both group1 and group14).
|
||||
*/
|
||||
static const unsigned char G[] = { 2 };
|
||||
|
||||
static const struct ssh_kex ssh_diffiehellman_group1_sha1 = {
|
||||
"diffie-hellman-group1-sha1", "group1",
|
||||
P1, G, lenof(P1), lenof(G), &ssh_sha1
|
||||
};
|
||||
|
||||
static const struct ssh_kex *const group1_list[] = {
|
||||
&ssh_diffiehellman_group1_sha1
|
||||
};
|
||||
|
||||
const struct ssh_kexes ssh_diffiehellman_group1 = {
|
||||
sizeof(group1_list) / sizeof(*group1_list),
|
||||
group1_list
|
||||
};
|
||||
|
||||
static const struct ssh_kex ssh_diffiehellman_group14_sha1 = {
|
||||
"diffie-hellman-group14-sha1", "group14",
|
||||
P14, G, lenof(P14), lenof(G), &ssh_sha1
|
||||
};
|
||||
|
||||
static const struct ssh_kex *const group14_list[] = {
|
||||
&ssh_diffiehellman_group14_sha1
|
||||
};
|
||||
|
||||
const struct ssh_kexes ssh_diffiehellman_group14 = {
|
||||
sizeof(group14_list) / sizeof(*group14_list),
|
||||
group14_list
|
||||
};
|
||||
|
||||
static const struct ssh_kex ssh_diffiehellman_gex_sha256 = {
|
||||
"diffie-hellman-group-exchange-sha256", NULL,
|
||||
NULL, NULL, 0, 0, &ssh_sha256
|
||||
};
|
||||
|
||||
static const struct ssh_kex ssh_diffiehellman_gex_sha1 = {
|
||||
"diffie-hellman-group-exchange-sha1", NULL,
|
||||
NULL, NULL, 0, 0, &ssh_sha1
|
||||
};
|
||||
|
||||
static const struct ssh_kex *const gex_list[] = {
|
||||
&ssh_diffiehellman_gex_sha256,
|
||||
&ssh_diffiehellman_gex_sha1
|
||||
};
|
||||
|
||||
const struct ssh_kexes ssh_diffiehellman_gex = {
|
||||
sizeof(gex_list) / sizeof(*gex_list),
|
||||
gex_list
|
||||
};
|
||||
|
||||
/*
|
||||
* Variables.
|
||||
*/
|
||||
struct dh_ctx {
|
||||
Bignum x, e, p, q, qmask, g;
|
||||
};
|
||||
|
||||
/*
|
||||
* Common DH initialisation.
|
||||
*/
|
||||
static void dh_init(struct dh_ctx *ctx)
|
||||
{
|
||||
ctx->q = bignum_rshift(ctx->p, 1);
|
||||
ctx->qmask = bignum_bitmask(ctx->q);
|
||||
ctx->x = ctx->e = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialise DH for a standard group.
|
||||
*/
|
||||
void *dh_setup_group(const struct ssh_kex *kex)
|
||||
{
|
||||
struct dh_ctx *ctx = snew(struct dh_ctx);
|
||||
ctx->p = bignum_from_bytes(kex->pdata, kex->plen);
|
||||
ctx->g = bignum_from_bytes(kex->gdata, kex->glen);
|
||||
dh_init(ctx);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialise DH for a server-supplied group.
|
||||
*/
|
||||
void *dh_setup_gex(Bignum pval, Bignum gval)
|
||||
{
|
||||
struct dh_ctx *ctx = snew(struct dh_ctx);
|
||||
ctx->p = copybn(pval);
|
||||
ctx->g = copybn(gval);
|
||||
dh_init(ctx);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clean up and free a context.
|
||||
*/
|
||||
void dh_cleanup(void *handle)
|
||||
{
|
||||
struct dh_ctx *ctx = (struct dh_ctx *)handle;
|
||||
freebn(ctx->x);
|
||||
freebn(ctx->e);
|
||||
freebn(ctx->p);
|
||||
freebn(ctx->g);
|
||||
freebn(ctx->q);
|
||||
freebn(ctx->qmask);
|
||||
sfree(ctx);
|
||||
}
|
||||
|
||||
/*
|
||||
* DH stage 1: invent a number x between 1 and q, and compute e =
|
||||
* g^x mod p. Return e.
|
||||
*
|
||||
* If `nbits' is greater than zero, it is used as an upper limit
|
||||
* for the number of bits in x. This is safe provided that (a) you
|
||||
* use twice as many bits in x as the number of bits you expect to
|
||||
* use in your session key, and (b) the DH group is a safe prime
|
||||
* (which SSH demands that it must be).
|
||||
*
|
||||
* P. C. van Oorschot, M. J. Wiener
|
||||
* "On Diffie-Hellman Key Agreement with Short Exponents".
|
||||
* Advances in Cryptology: Proceedings of Eurocrypt '96
|
||||
* Springer-Verlag, May 1996.
|
||||
*/
|
||||
Bignum dh_create_e(void *handle, int nbits)
|
||||
{
|
||||
struct dh_ctx *ctx = (struct dh_ctx *)handle;
|
||||
int i;
|
||||
|
||||
int nbytes;
|
||||
unsigned char *buf;
|
||||
|
||||
nbytes = ssh1_bignum_length(ctx->qmask);
|
||||
buf = snewn(nbytes, unsigned char);
|
||||
|
||||
do {
|
||||
/*
|
||||
* Create a potential x, by ANDing a string of random bytes
|
||||
* with qmask.
|
||||
*/
|
||||
if (ctx->x)
|
||||
freebn(ctx->x);
|
||||
if (nbits == 0 || nbits > bignum_bitcount(ctx->qmask)) {
|
||||
ssh1_write_bignum(buf, ctx->qmask);
|
||||
for (i = 2; i < nbytes; i++)
|
||||
buf[i] &= random_byte();
|
||||
ssh1_read_bignum(buf, nbytes, &ctx->x); /* can't fail */
|
||||
} else {
|
||||
int b, nb;
|
||||
ctx->x = bn_power_2(nbits);
|
||||
b = nb = 0;
|
||||
for (i = 0; i < nbits; i++) {
|
||||
if (nb == 0) {
|
||||
nb = 8;
|
||||
b = random_byte();
|
||||
}
|
||||
bignum_set_bit(ctx->x, i, b & 1);
|
||||
b >>= 1;
|
||||
nb--;
|
||||
}
|
||||
}
|
||||
} while (bignum_cmp(ctx->x, One) <= 0 || bignum_cmp(ctx->x, ctx->q) >= 0);
|
||||
|
||||
sfree(buf);
|
||||
|
||||
/*
|
||||
* Done. Now compute e = g^x mod p.
|
||||
*/
|
||||
ctx->e = modpow(ctx->g, ctx->x, ctx->p);
|
||||
|
||||
return ctx->e;
|
||||
}
|
||||
|
||||
/*
|
||||
* DH stage 2: given a number f, compute K = f^x mod p.
|
||||
*/
|
||||
Bignum dh_find_K(void *handle, Bignum f)
|
||||
{
|
||||
struct dh_ctx *ctx = (struct dh_ctx *)handle;
|
||||
Bignum ret;
|
||||
ret = modpow(f, ctx->x, ctx->p);
|
||||
return ret;
|
||||
}
|
||||
643
sFTPlugins/psftp/SSHDSS.C
Normal file
643
sFTPlugins/psftp/SSHDSS.C
Normal file
@@ -0,0 +1,643 @@
|
||||
/*
|
||||
* Digital Signature Standard implementation for PuTTY.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "ssh.h"
|
||||
#include "misc.h"
|
||||
|
||||
static void sha_mpint(SHA_State * s, Bignum b)
|
||||
{
|
||||
unsigned char lenbuf[4];
|
||||
int len;
|
||||
len = (bignum_bitcount(b) + 8) / 8;
|
||||
PUT_32BIT(lenbuf, len);
|
||||
SHA_Bytes(s, lenbuf, 4);
|
||||
while (len-- > 0) {
|
||||
lenbuf[0] = bignum_byte(b, len);
|
||||
SHA_Bytes(s, lenbuf, 1);
|
||||
}
|
||||
memset(lenbuf, 0, sizeof(lenbuf));
|
||||
}
|
||||
|
||||
static void sha512_mpint(SHA512_State * s, Bignum b)
|
||||
{
|
||||
unsigned char lenbuf[4];
|
||||
int len;
|
||||
len = (bignum_bitcount(b) + 8) / 8;
|
||||
PUT_32BIT(lenbuf, len);
|
||||
SHA512_Bytes(s, lenbuf, 4);
|
||||
while (len-- > 0) {
|
||||
lenbuf[0] = bignum_byte(b, len);
|
||||
SHA512_Bytes(s, lenbuf, 1);
|
||||
}
|
||||
memset(lenbuf, 0, sizeof(lenbuf));
|
||||
}
|
||||
|
||||
static void getstring(char **data, int *datalen, char **p, int *length)
|
||||
{
|
||||
*p = NULL;
|
||||
if (*datalen < 4)
|
||||
return;
|
||||
*length = GET_32BIT(*data);
|
||||
*datalen -= 4;
|
||||
*data += 4;
|
||||
if (*datalen < *length)
|
||||
return;
|
||||
*p = *data;
|
||||
*data += *length;
|
||||
*datalen -= *length;
|
||||
}
|
||||
static Bignum getmp(char **data, int *datalen)
|
||||
{
|
||||
char *p;
|
||||
int length;
|
||||
Bignum b;
|
||||
|
||||
getstring(data, datalen, &p, &length);
|
||||
if (!p)
|
||||
return NULL;
|
||||
if (p[0] & 0x80)
|
||||
return NULL; /* negative mp */
|
||||
b = bignum_from_bytes((unsigned char *)p, length);
|
||||
return b;
|
||||
}
|
||||
|
||||
static Bignum get160(char **data, int *datalen)
|
||||
{
|
||||
Bignum b;
|
||||
|
||||
b = bignum_from_bytes((unsigned char *)*data, 20);
|
||||
*data += 20;
|
||||
*datalen -= 20;
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
static void *dss_newkey(char *data, int len)
|
||||
{
|
||||
char *p;
|
||||
int slen;
|
||||
struct dss_key *dss;
|
||||
|
||||
dss = snew(struct dss_key);
|
||||
if (!dss)
|
||||
return NULL;
|
||||
getstring(&data, &len, &p, &slen);
|
||||
|
||||
#ifdef DEBUG_DSS
|
||||
{
|
||||
int i;
|
||||
printf("key:");
|
||||
for (i = 0; i < len; i++)
|
||||
printf(" %02x", (unsigned char) (data[i]));
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!p || memcmp(p, "ssh-dss", 7)) {
|
||||
sfree(dss);
|
||||
return NULL;
|
||||
}
|
||||
dss->p = getmp(&data, &len);
|
||||
dss->q = getmp(&data, &len);
|
||||
dss->g = getmp(&data, &len);
|
||||
dss->y = getmp(&data, &len);
|
||||
|
||||
return dss;
|
||||
}
|
||||
|
||||
static void dss_freekey(void *key)
|
||||
{
|
||||
struct dss_key *dss = (struct dss_key *) key;
|
||||
freebn(dss->p);
|
||||
freebn(dss->q);
|
||||
freebn(dss->g);
|
||||
freebn(dss->y);
|
||||
sfree(dss);
|
||||
}
|
||||
|
||||
static char *dss_fmtkey(void *key)
|
||||
{
|
||||
struct dss_key *dss = (struct dss_key *) key;
|
||||
char *p;
|
||||
int len, i, pos, nibbles;
|
||||
static const char hex[] = "0123456789abcdef";
|
||||
if (!dss->p)
|
||||
return NULL;
|
||||
len = 8 + 4 + 1; /* 4 x "0x", punctuation, \0 */
|
||||
len += 4 * (bignum_bitcount(dss->p) + 15) / 16;
|
||||
len += 4 * (bignum_bitcount(dss->q) + 15) / 16;
|
||||
len += 4 * (bignum_bitcount(dss->g) + 15) / 16;
|
||||
len += 4 * (bignum_bitcount(dss->y) + 15) / 16;
|
||||
p = snewn(len, char);
|
||||
if (!p)
|
||||
return NULL;
|
||||
|
||||
pos = 0;
|
||||
pos += sprintf(p + pos, "0x");
|
||||
nibbles = (3 + bignum_bitcount(dss->p)) / 4;
|
||||
if (nibbles < 1)
|
||||
nibbles = 1;
|
||||
for (i = nibbles; i--;)
|
||||
p[pos++] =
|
||||
hex[(bignum_byte(dss->p, i / 2) >> (4 * (i % 2))) & 0xF];
|
||||
pos += sprintf(p + pos, ",0x");
|
||||
nibbles = (3 + bignum_bitcount(dss->q)) / 4;
|
||||
if (nibbles < 1)
|
||||
nibbles = 1;
|
||||
for (i = nibbles; i--;)
|
||||
p[pos++] =
|
||||
hex[(bignum_byte(dss->q, i / 2) >> (4 * (i % 2))) & 0xF];
|
||||
pos += sprintf(p + pos, ",0x");
|
||||
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';
|
||||
return p;
|
||||
}
|
||||
|
||||
static char *dss_fingerprint(void *key)
|
||||
{
|
||||
struct dss_key *dss = (struct dss_key *) key;
|
||||
struct MD5Context md5c;
|
||||
unsigned char digest[16], lenbuf[4];
|
||||
char buffer[16 * 3 + 40];
|
||||
char *ret;
|
||||
int numlen, i;
|
||||
|
||||
MD5Init(&md5c);
|
||||
MD5Update(&md5c, (unsigned char *)"\0\0\0\7ssh-dss", 11);
|
||||
|
||||
#define ADD_BIGNUM(bignum) \
|
||||
numlen = (bignum_bitcount(bignum)+8)/8; \
|
||||
PUT_32BIT(lenbuf, numlen); MD5Update(&md5c, lenbuf, 4); \
|
||||
for (i = numlen; i-- ;) { \
|
||||
unsigned char c = bignum_byte(bignum, i); \
|
||||
MD5Update(&md5c, &c, 1); \
|
||||
}
|
||||
ADD_BIGNUM(dss->p);
|
||||
ADD_BIGNUM(dss->q);
|
||||
ADD_BIGNUM(dss->g);
|
||||
ADD_BIGNUM(dss->y);
|
||||
#undef ADD_BIGNUM
|
||||
|
||||
MD5Final(digest, &md5c);
|
||||
|
||||
sprintf(buffer, "ssh-dss %d ", bignum_bitcount(dss->p));
|
||||
for (i = 0; i < 16; i++)
|
||||
sprintf(buffer + strlen(buffer), "%s%02x", i ? ":" : "",
|
||||
digest[i]);
|
||||
ret = snewn(strlen(buffer) + 1, char);
|
||||
if (ret)
|
||||
strcpy(ret, buffer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dss_verifysig(void *key, char *sig, int siglen,
|
||||
char *data, int datalen)
|
||||
{
|
||||
struct dss_key *dss = (struct dss_key *) key;
|
||||
char *p;
|
||||
int slen;
|
||||
char hash[20];
|
||||
Bignum r, s, w, gu1p, yu2p, gu1yu2p, u1, u2, sha, v;
|
||||
int ret;
|
||||
|
||||
if (!dss->p)
|
||||
return 0;
|
||||
|
||||
#ifdef DEBUG_DSS
|
||||
{
|
||||
int i;
|
||||
printf("sig:");
|
||||
for (i = 0; i < siglen; i++)
|
||||
printf(" %02x", (unsigned char) (sig[i]));
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* Commercial SSH (2.0.13) and OpenSSH disagree over the format
|
||||
* of a DSA signature. OpenSSH is in line with the IETF drafts:
|
||||
* it uses a string "ssh-dss", followed by a 40-byte string
|
||||
* containing two 160-bit integers end-to-end. Commercial SSH
|
||||
* can't be bothered with the header bit, and considers a DSA
|
||||
* signature blob to be _just_ the 40-byte string containing
|
||||
* the two 160-bit integers. We tell them apart by measuring
|
||||
* the length: length 40 means the commercial-SSH bug, anything
|
||||
* else is assumed to be IETF-compliant.
|
||||
*/
|
||||
if (siglen != 40) { /* bug not present; read admin fields */
|
||||
getstring(&sig, &siglen, &p, &slen);
|
||||
if (!p || slen != 7 || memcmp(p, "ssh-dss", 7)) {
|
||||
return 0;
|
||||
}
|
||||
sig += 4, siglen -= 4; /* skip yet another length field */
|
||||
}
|
||||
r = get160(&sig, &siglen);
|
||||
s = get160(&sig, &siglen);
|
||||
if (!r || !s)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Step 1. w <- s^-1 mod q.
|
||||
*/
|
||||
w = modinv(s, dss->q);
|
||||
|
||||
/*
|
||||
* Step 2. u1 <- SHA(message) * w mod q.
|
||||
*/
|
||||
SHA_Simple(data, datalen, (unsigned char *)hash);
|
||||
p = hash;
|
||||
slen = 20;
|
||||
sha = get160(&p, &slen);
|
||||
u1 = modmul(sha, w, dss->q);
|
||||
|
||||
/*
|
||||
* Step 3. u2 <- r * w mod q.
|
||||
*/
|
||||
u2 = modmul(r, w, dss->q);
|
||||
|
||||
/*
|
||||
* Step 4. v <- (g^u1 * y^u2 mod p) mod q.
|
||||
*/
|
||||
gu1p = modpow(dss->g, u1, dss->p);
|
||||
yu2p = modpow(dss->y, u2, dss->p);
|
||||
gu1yu2p = modmul(gu1p, yu2p, dss->p);
|
||||
v = modmul(gu1yu2p, One, dss->q);
|
||||
|
||||
/*
|
||||
* Step 5. v should now be equal to r.
|
||||
*/
|
||||
|
||||
ret = !bignum_cmp(v, r);
|
||||
|
||||
freebn(w);
|
||||
freebn(sha);
|
||||
freebn(gu1p);
|
||||
freebn(yu2p);
|
||||
freebn(gu1yu2p);
|
||||
freebn(v);
|
||||
freebn(r);
|
||||
freebn(s);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static unsigned char *dss_public_blob(void *key, int *len)
|
||||
{
|
||||
struct dss_key *dss = (struct dss_key *) key;
|
||||
int plen, qlen, glen, ylen, bloblen;
|
||||
int i;
|
||||
unsigned char *blob, *p;
|
||||
|
||||
plen = (bignum_bitcount(dss->p) + 8) / 8;
|
||||
qlen = (bignum_bitcount(dss->q) + 8) / 8;
|
||||
glen = (bignum_bitcount(dss->g) + 8) / 8;
|
||||
ylen = (bignum_bitcount(dss->y) + 8) / 8;
|
||||
|
||||
/*
|
||||
* string "ssh-dss", mpint p, mpint q, mpint g, mpint y. Total
|
||||
* 27 + sum of lengths. (five length fields, 20+7=27).
|
||||
*/
|
||||
bloblen = 27 + plen + qlen + glen + ylen;
|
||||
blob = snewn(bloblen, unsigned char);
|
||||
p = blob;
|
||||
PUT_32BIT(p, 7);
|
||||
p += 4;
|
||||
memcpy(p, "ssh-dss", 7);
|
||||
p += 7;
|
||||
PUT_32BIT(p, plen);
|
||||
p += 4;
|
||||
for (i = plen; i--;)
|
||||
*p++ = bignum_byte(dss->p, i);
|
||||
PUT_32BIT(p, qlen);
|
||||
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);
|
||||
*len = bloblen;
|
||||
return blob;
|
||||
}
|
||||
|
||||
static unsigned char *dss_private_blob(void *key, int *len)
|
||||
{
|
||||
struct dss_key *dss = (struct dss_key *) key;
|
||||
int xlen, bloblen;
|
||||
int i;
|
||||
unsigned char *blob, *p;
|
||||
|
||||
xlen = (bignum_bitcount(dss->x) + 8) / 8;
|
||||
|
||||
/*
|
||||
* mpint x, string[20] the SHA of p||q||g. Total 4 + xlen.
|
||||
*/
|
||||
bloblen = 4 + xlen;
|
||||
blob = snewn(bloblen, unsigned char);
|
||||
p = blob;
|
||||
PUT_32BIT(p, xlen);
|
||||
p += 4;
|
||||
for (i = xlen; i--;)
|
||||
*p++ = bignum_byte(dss->x, i);
|
||||
assert(p == blob + bloblen);
|
||||
*len = bloblen;
|
||||
return blob;
|
||||
}
|
||||
|
||||
static void *dss_createkey(unsigned char *pub_blob, int pub_len,
|
||||
unsigned char *priv_blob, int priv_len)
|
||||
{
|
||||
struct dss_key *dss;
|
||||
char *pb = (char *) priv_blob;
|
||||
char *hash;
|
||||
int hashlen;
|
||||
SHA_State s;
|
||||
unsigned char digest[20];
|
||||
Bignum ytest;
|
||||
|
||||
dss = dss_newkey((char *) pub_blob, pub_len);
|
||||
dss->x = getmp(&pb, &priv_len);
|
||||
|
||||
/*
|
||||
* Check the obsolete hash in the old DSS key format.
|
||||
*/
|
||||
hashlen = -1;
|
||||
getstring(&pb, &priv_len, &hash, &hashlen);
|
||||
if (hashlen == 20) {
|
||||
SHA_Init(&s);
|
||||
sha_mpint(&s, dss->p);
|
||||
sha_mpint(&s, dss->q);
|
||||
sha_mpint(&s, dss->g);
|
||||
SHA_Final(&s, digest);
|
||||
if (0 != memcmp(hash, digest, 20)) {
|
||||
dss_freekey(dss);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Now ensure g^x mod p really is y.
|
||||
*/
|
||||
ytest = modpow(dss->g, dss->x, dss->p);
|
||||
if (0 != bignum_cmp(ytest, dss->y)) {
|
||||
dss_freekey(dss);
|
||||
return NULL;
|
||||
}
|
||||
freebn(ytest);
|
||||
|
||||
return dss;
|
||||
}
|
||||
|
||||
static void *dss_openssh_createkey(unsigned char **blob, int *len)
|
||||
{
|
||||
char **b = (char **) blob;
|
||||
struct dss_key *dss;
|
||||
|
||||
dss = snew(struct dss_key);
|
||||
if (!dss)
|
||||
return NULL;
|
||||
|
||||
dss->p = getmp(b, len);
|
||||
dss->q = getmp(b, len);
|
||||
dss->g = getmp(b, len);
|
||||
dss->y = getmp(b, len);
|
||||
dss->x = getmp(b, len);
|
||||
|
||||
if (!dss->p || !dss->q || !dss->g || !dss->y || !dss->x) {
|
||||
sfree(dss->p);
|
||||
sfree(dss->q);
|
||||
sfree(dss->g);
|
||||
sfree(dss->y);
|
||||
sfree(dss->x);
|
||||
sfree(dss);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return dss;
|
||||
}
|
||||
|
||||
static int dss_openssh_fmtkey(void *key, unsigned char *blob, int len)
|
||||
{
|
||||
struct dss_key *dss = (struct dss_key *) key;
|
||||
int bloblen, i;
|
||||
|
||||
bloblen =
|
||||
ssh2_bignum_length(dss->p) +
|
||||
ssh2_bignum_length(dss->q) +
|
||||
ssh2_bignum_length(dss->g) +
|
||||
ssh2_bignum_length(dss->y) +
|
||||
ssh2_bignum_length(dss->x);
|
||||
|
||||
if (bloblen > len)
|
||||
return bloblen;
|
||||
|
||||
bloblen = 0;
|
||||
#define ENC(x) \
|
||||
PUT_32BIT(blob+bloblen, ssh2_bignum_length((x))-4); bloblen += 4; \
|
||||
for (i = ssh2_bignum_length((x))-4; i-- ;) blob[bloblen++]=bignum_byte((x),i);
|
||||
ENC(dss->p);
|
||||
ENC(dss->q);
|
||||
ENC(dss->g);
|
||||
ENC(dss->y);
|
||||
ENC(dss->x);
|
||||
|
||||
return bloblen;
|
||||
}
|
||||
|
||||
static int dss_pubkey_bits(void *blob, int len)
|
||||
{
|
||||
struct dss_key *dss;
|
||||
int ret;
|
||||
|
||||
dss = dss_newkey((char *) blob, len);
|
||||
ret = bignum_bitcount(dss->p);
|
||||
dss_freekey(dss);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static unsigned char *dss_sign(void *key, char *data, int datalen, int *siglen)
|
||||
{
|
||||
/*
|
||||
* The basic DSS signing algorithm is:
|
||||
*
|
||||
* - invent a random k between 1 and q-1 (exclusive).
|
||||
* - Compute r = (g^k mod p) mod q.
|
||||
* - Compute s = k^-1 * (hash + x*r) mod q.
|
||||
*
|
||||
* This has the dangerous properties that:
|
||||
*
|
||||
* - if an attacker in possession of the public key _and_ the
|
||||
* signature (for example, the host you just authenticated
|
||||
* to) can guess your k, he can reverse the computation of s
|
||||
* and work out x = r^-1 * (s*k - hash) mod q. That is, he
|
||||
* can deduce the private half of your key, and masquerade
|
||||
* as you for as long as the key is still valid.
|
||||
*
|
||||
* - since r is a function purely of k and the public key, if
|
||||
* the attacker only has a _range of possibilities_ for k
|
||||
* it's easy for him to work through them all and check each
|
||||
* one against r; he'll never be unsure of whether he's got
|
||||
* the right one.
|
||||
*
|
||||
* - if you ever sign two different hashes with the same k, it
|
||||
* will be immediately obvious because the two signatures
|
||||
* will have the same r, and moreover an attacker in
|
||||
* possession of both signatures (and the public key of
|
||||
* course) can compute k = (hash1-hash2) * (s1-s2)^-1 mod q,
|
||||
* and from there deduce x as before.
|
||||
*
|
||||
* - the Bleichenbacher attack on DSA makes use of methods of
|
||||
* generating k which are significantly non-uniformly
|
||||
* distributed; in particular, generating a 160-bit random
|
||||
* number and reducing it mod q is right out.
|
||||
*
|
||||
* For this reason we must be pretty careful about how we
|
||||
* generate our k. Since this code runs on Windows, with no
|
||||
* particularly good system entropy sources, we can't trust our
|
||||
* RNG itself to produce properly unpredictable data. Hence, we
|
||||
* use a totally different scheme instead.
|
||||
*
|
||||
* What we do is to take a SHA-512 (_big_) hash of the private
|
||||
* key x, and then feed this into another SHA-512 hash that
|
||||
* also includes the message hash being signed. That is:
|
||||
*
|
||||
* proto_k = SHA512 ( SHA512(x) || SHA160(message) )
|
||||
*
|
||||
* This number is 512 bits long, so reducing it mod q won't be
|
||||
* noticeably non-uniform. So
|
||||
*
|
||||
* k = proto_k mod q
|
||||
*
|
||||
* This has the interesting property that it's _deterministic_:
|
||||
* signing the same hash twice with the same key yields the
|
||||
* same signature.
|
||||
*
|
||||
* Despite this determinism, it's still not predictable to an
|
||||
* attacker, because in order to repeat the SHA-512
|
||||
* construction that created it, the attacker would have to
|
||||
* know the private key value x - and by assumption he doesn't,
|
||||
* because if he knew that he wouldn't be attacking k!
|
||||
*
|
||||
* (This trick doesn't, _per se_, protect against reuse of k.
|
||||
* Reuse of k is left to chance; all it does is prevent
|
||||
* _excessively high_ chances of reuse of k due to entropy
|
||||
* problems.)
|
||||
*
|
||||
* Thanks to Colin Plumb for the general idea of using x to
|
||||
* ensure k is hard to guess, and to the Cambridge University
|
||||
* Computer Security Group for helping to argue out all the
|
||||
* fine details.
|
||||
*/
|
||||
struct dss_key *dss = (struct dss_key *) key;
|
||||
SHA512_State ss;
|
||||
unsigned char digest[20], digest512[64];
|
||||
Bignum proto_k, k, gkp, hash, kinv, hxr, r, s;
|
||||
unsigned char *bytes;
|
||||
int nbytes, i;
|
||||
|
||||
SHA_Simple(data, datalen, digest);
|
||||
|
||||
/*
|
||||
* Hash some identifying text plus x.
|
||||
*/
|
||||
SHA512_Init(&ss);
|
||||
SHA512_Bytes(&ss, "DSA deterministic k generator", 30);
|
||||
sha512_mpint(&ss, dss->x);
|
||||
SHA512_Final(&ss, digest512);
|
||||
|
||||
/*
|
||||
* Now hash that digest plus the message hash.
|
||||
*/
|
||||
SHA512_Init(&ss);
|
||||
SHA512_Bytes(&ss, digest512, sizeof(digest512));
|
||||
SHA512_Bytes(&ss, digest, sizeof(digest));
|
||||
SHA512_Final(&ss, digest512);
|
||||
|
||||
memset(&ss, 0, sizeof(ss));
|
||||
|
||||
/*
|
||||
* Now convert the result into a bignum, and reduce it mod q.
|
||||
*/
|
||||
proto_k = bignum_from_bytes(digest512, 64);
|
||||
k = bigmod(proto_k, dss->q);
|
||||
freebn(proto_k);
|
||||
|
||||
memset(digest512, 0, sizeof(digest512));
|
||||
|
||||
/*
|
||||
* Now we have k, so just go ahead and compute the signature.
|
||||
*/
|
||||
gkp = modpow(dss->g, k, dss->p); /* g^k mod p */
|
||||
r = bigmod(gkp, dss->q); /* r = (g^k mod p) mod q */
|
||||
freebn(gkp);
|
||||
|
||||
hash = bignum_from_bytes(digest, 20);
|
||||
kinv = modinv(k, dss->q); /* k^-1 mod q */
|
||||
hxr = bigmuladd(dss->x, r, hash); /* hash + x*r */
|
||||
s = modmul(kinv, hxr, dss->q); /* s = k^-1 * (hash + x*r) mod q */
|
||||
freebn(hxr);
|
||||
freebn(kinv);
|
||||
freebn(hash);
|
||||
|
||||
/*
|
||||
* Signature blob is
|
||||
*
|
||||
* string "ssh-dss"
|
||||
* string two 20-byte numbers r and s, end to end
|
||||
*
|
||||
* i.e. 4+7 + 4+40 bytes.
|
||||
*/
|
||||
nbytes = 4 + 7 + 4 + 40;
|
||||
bytes = snewn(nbytes, unsigned char);
|
||||
PUT_32BIT(bytes, 7);
|
||||
memcpy(bytes + 4, "ssh-dss", 7);
|
||||
PUT_32BIT(bytes + 4 + 7, 40);
|
||||
for (i = 0; i < 20; i++) {
|
||||
bytes[4 + 7 + 4 + i] = bignum_byte(r, 19 - i);
|
||||
bytes[4 + 7 + 4 + 20 + i] = bignum_byte(s, 19 - i);
|
||||
}
|
||||
freebn(r);
|
||||
freebn(s);
|
||||
|
||||
*siglen = nbytes;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
const struct ssh_signkey ssh_dss = {
|
||||
dss_newkey,
|
||||
dss_freekey,
|
||||
dss_fmtkey,
|
||||
dss_public_blob,
|
||||
dss_private_blob,
|
||||
dss_createkey,
|
||||
dss_openssh_createkey,
|
||||
dss_openssh_fmtkey,
|
||||
dss_pubkey_bits,
|
||||
dss_fingerprint,
|
||||
dss_verifysig,
|
||||
dss_sign,
|
||||
"ssh-dss",
|
||||
"dss"
|
||||
};
|
||||
317
sFTPlugins/psftp/SSHMD5.C
Normal file
317
sFTPlugins/psftp/SSHMD5.C
Normal file
@@ -0,0 +1,317 @@
|
||||
#include "ssh.h"
|
||||
|
||||
/*
|
||||
* MD5 implementation for PuTTY. Written directly from the spec by
|
||||
* Simon Tatham.
|
||||
*/
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* Core MD5 algorithm: processes 16-word blocks into a message digest.
|
||||
*/
|
||||
|
||||
#define F(x,y,z) ( ((x) & (y)) | ((~(x)) & (z)) )
|
||||
#define G(x,y,z) ( ((x) & (z)) | ((~(z)) & (y)) )
|
||||
#define H(x,y,z) ( (x) ^ (y) ^ (z) )
|
||||
#define I(x,y,z) ( (y) ^ ( (x) | ~(z) ) )
|
||||
|
||||
#define rol(x,y) ( ((x) << (y)) | (((uint32)x) >> (32-y)) )
|
||||
|
||||
#define subround(f,w,x,y,z,k,s,ti) \
|
||||
w = x + rol(w + f(x,y,z) + block[k] + ti, s)
|
||||
|
||||
static void MD5_Core_Init(MD5_Core_State * s)
|
||||
{
|
||||
s->h[0] = 0x67452301;
|
||||
s->h[1] = 0xefcdab89;
|
||||
s->h[2] = 0x98badcfe;
|
||||
s->h[3] = 0x10325476;
|
||||
}
|
||||
|
||||
static void MD5_Block(MD5_Core_State * s, uint32 * block)
|
||||
{
|
||||
uint32 a, b, c, d;
|
||||
|
||||
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, d, a, b, c, 1, 12, 0xe8c7b756);
|
||||
subround(F, c, d, a, b, 2, 17, 0x242070db);
|
||||
subround(F, b, c, d, a, 3, 22, 0xc1bdceee);
|
||||
subround(F, a, b, c, d, 4, 7, 0xf57c0faf);
|
||||
subround(F, d, a, b, c, 5, 12, 0x4787c62a);
|
||||
subround(F, c, d, a, b, 6, 17, 0xa8304613);
|
||||
subround(F, b, c, d, a, 7, 22, 0xfd469501);
|
||||
subround(F, a, b, c, d, 8, 7, 0x698098d8);
|
||||
subround(F, d, a, b, c, 9, 12, 0x8b44f7af);
|
||||
subround(F, c, d, a, b, 10, 17, 0xffff5bb1);
|
||||
subround(F, b, c, d, a, 11, 22, 0x895cd7be);
|
||||
subround(F, a, b, c, d, 12, 7, 0x6b901122);
|
||||
subround(F, d, a, b, c, 13, 12, 0xfd987193);
|
||||
subround(F, c, d, a, b, 14, 17, 0xa679438e);
|
||||
subround(F, b, c, d, a, 15, 22, 0x49b40821);
|
||||
subround(G, a, b, c, d, 1, 5, 0xf61e2562);
|
||||
subround(G, d, a, b, c, 6, 9, 0xc040b340);
|
||||
subround(G, c, d, a, b, 11, 14, 0x265e5a51);
|
||||
subround(G, b, c, d, a, 0, 20, 0xe9b6c7aa);
|
||||
subround(G, a, b, c, d, 5, 5, 0xd62f105d);
|
||||
subround(G, d, a, b, c, 10, 9, 0x02441453);
|
||||
subround(G, c, d, a, b, 15, 14, 0xd8a1e681);
|
||||
subround(G, b, c, d, a, 4, 20, 0xe7d3fbc8);
|
||||
subround(G, a, b, c, d, 9, 5, 0x21e1cde6);
|
||||
subround(G, d, a, b, c, 14, 9, 0xc33707d6);
|
||||
subround(G, c, d, a, b, 3, 14, 0xf4d50d87);
|
||||
subround(G, b, c, d, a, 8, 20, 0x455a14ed);
|
||||
subround(G, a, b, c, d, 13, 5, 0xa9e3e905);
|
||||
subround(G, d, a, b, c, 2, 9, 0xfcefa3f8);
|
||||
subround(G, c, d, a, b, 7, 14, 0x676f02d9);
|
||||
subround(G, b, c, d, a, 12, 20, 0x8d2a4c8a);
|
||||
subround(H, a, b, c, d, 5, 4, 0xfffa3942);
|
||||
subround(H, d, a, b, c, 8, 11, 0x8771f681);
|
||||
subround(H, c, d, a, b, 11, 16, 0x6d9d6122);
|
||||
subround(H, b, c, d, a, 14, 23, 0xfde5380c);
|
||||
subround(H, a, b, c, d, 1, 4, 0xa4beea44);
|
||||
subround(H, d, a, b, c, 4, 11, 0x4bdecfa9);
|
||||
subround(H, c, d, a, b, 7, 16, 0xf6bb4b60);
|
||||
subround(H, b, c, d, a, 10, 23, 0xbebfbc70);
|
||||
subround(H, a, b, c, d, 13, 4, 0x289b7ec6);
|
||||
subround(H, d, a, b, c, 0, 11, 0xeaa127fa);
|
||||
subround(H, c, d, a, b, 3, 16, 0xd4ef3085);
|
||||
subround(H, b, c, d, a, 6, 23, 0x04881d05);
|
||||
subround(H, a, b, c, d, 9, 4, 0xd9d4d039);
|
||||
subround(H, d, a, b, c, 12, 11, 0xe6db99e5);
|
||||
subround(H, c, d, a, b, 15, 16, 0x1fa27cf8);
|
||||
subround(H, b, c, d, a, 2, 23, 0xc4ac5665);
|
||||
subround(I, a, b, c, d, 0, 6, 0xf4292244);
|
||||
subround(I, d, a, b, c, 7, 10, 0x432aff97);
|
||||
subround(I, c, d, a, b, 14, 15, 0xab9423a7);
|
||||
subround(I, b, c, d, a, 5, 21, 0xfc93a039);
|
||||
subround(I, a, b, c, d, 12, 6, 0x655b59c3);
|
||||
subround(I, d, a, b, c, 3, 10, 0x8f0ccc92);
|
||||
subround(I, c, d, a, b, 10, 15, 0xffeff47d);
|
||||
subround(I, b, c, d, a, 1, 21, 0x85845dd1);
|
||||
subround(I, a, b, c, d, 8, 6, 0x6fa87e4f);
|
||||
subround(I, d, a, b, c, 15, 10, 0xfe2ce6e0);
|
||||
subround(I, c, d, a, b, 6, 15, 0xa3014314);
|
||||
subround(I, b, c, d, a, 13, 21, 0x4e0811a1);
|
||||
subround(I, a, b, c, d, 4, 6, 0xf7537e82);
|
||||
subround(I, d, a, b, c, 11, 10, 0xbd3af235);
|
||||
subround(I, c, d, a, b, 2, 15, 0x2ad7d2bb);
|
||||
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;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* Outer MD5 algorithm: take an arbitrary length byte string,
|
||||
* convert it into 16-word blocks with the prescribed padding at
|
||||
* the end, and pass those blocks to the core MD5 algorithm.
|
||||
*/
|
||||
|
||||
#define BLKSIZE 64
|
||||
|
||||
void MD5Init(struct MD5Context *s)
|
||||
{
|
||||
MD5_Core_Init(&s->core);
|
||||
s->blkused = 0;
|
||||
s->lenhi = s->lenlo = 0;
|
||||
}
|
||||
|
||||
void MD5Update(struct MD5Context *s, unsigned char const *p, unsigned len)
|
||||
{
|
||||
unsigned char *q = (unsigned char *) p;
|
||||
uint32 wordblock[16];
|
||||
uint32 lenw = len;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Update the length field.
|
||||
*/
|
||||
s->lenlo += lenw;
|
||||
s->lenhi += (s->lenlo < lenw);
|
||||
|
||||
if (s->blkused + len < BLKSIZE) {
|
||||
/*
|
||||
* Trivial case: just add to the block.
|
||||
*/
|
||||
memcpy(s->block + s->blkused, q, len);
|
||||
s->blkused += len;
|
||||
} else {
|
||||
/*
|
||||
* We must complete and process at least one block.
|
||||
*/
|
||||
while (s->blkused + len >= BLKSIZE) {
|
||||
memcpy(s->block + s->blkused, q, BLKSIZE - s->blkused);
|
||||
q += BLKSIZE - s->blkused;
|
||||
len -= BLKSIZE - s->blkused;
|
||||
/* Now process the block. Gather bytes little-endian into words */
|
||||
for (i = 0; i < 16; i++) {
|
||||
wordblock[i] =
|
||||
(((uint32) s->block[i * 4 + 3]) << 24) |
|
||||
(((uint32) s->block[i * 4 + 2]) << 16) |
|
||||
(((uint32) s->block[i * 4 + 1]) << 8) |
|
||||
(((uint32) s->block[i * 4 + 0]) << 0);
|
||||
}
|
||||
MD5_Block(&s->core, wordblock);
|
||||
s->blkused = 0;
|
||||
}
|
||||
memcpy(s->block, q, len);
|
||||
s->blkused = len;
|
||||
}
|
||||
}
|
||||
|
||||
void MD5Final(unsigned char output[16], struct MD5Context *s)
|
||||
{
|
||||
int i;
|
||||
unsigned pad;
|
||||
unsigned char c[64];
|
||||
uint32 lenhi, lenlo;
|
||||
|
||||
if (s->blkused >= 56)
|
||||
pad = 56 + 64 - s->blkused;
|
||||
else
|
||||
pad = 56 - s->blkused;
|
||||
|
||||
lenhi = (s->lenhi << 3) | (s->lenlo >> (32 - 3));
|
||||
lenlo = (s->lenlo << 3);
|
||||
|
||||
memset(c, 0, pad);
|
||||
c[0] = 0x80;
|
||||
MD5Update(s, c, pad);
|
||||
|
||||
c[7] = (lenhi >> 24) & 0xFF;
|
||||
c[6] = (lenhi >> 16) & 0xFF;
|
||||
c[5] = (lenhi >> 8) & 0xFF;
|
||||
c[4] = (lenhi >> 0) & 0xFF;
|
||||
c[3] = (lenlo >> 24) & 0xFF;
|
||||
c[2] = (lenlo >> 16) & 0xFF;
|
||||
c[1] = (lenlo >> 8) & 0xFF;
|
||||
c[0] = (lenlo >> 0) & 0xFF;
|
||||
|
||||
MD5Update(s, c, 8);
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
output[4 * i + 3] = (s->core.h[i] >> 24) & 0xFF;
|
||||
output[4 * i + 2] = (s->core.h[i] >> 16) & 0xFF;
|
||||
output[4 * i + 1] = (s->core.h[i] >> 8) & 0xFF;
|
||||
output[4 * i + 0] = (s->core.h[i] >> 0) & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
void MD5Simple(void const *p, unsigned len, unsigned char output[16])
|
||||
{
|
||||
struct MD5Context s;
|
||||
|
||||
MD5Init(&s);
|
||||
MD5Update(&s, (unsigned char const *)p, len);
|
||||
MD5Final(output, &s);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* The above is the MD5 algorithm itself. Now we implement the
|
||||
* HMAC wrapper on it.
|
||||
*
|
||||
* Some of these functions are exported directly, because they are
|
||||
* useful elsewhere (SOCKS5 CHAP authentication uses HMAC-MD5).
|
||||
*/
|
||||
|
||||
void *hmacmd5_make_context(void)
|
||||
{
|
||||
return snewn(2, struct MD5Context);
|
||||
}
|
||||
|
||||
void hmacmd5_free_context(void *handle)
|
||||
{
|
||||
sfree(handle);
|
||||
}
|
||||
|
||||
void hmacmd5_key(void *handle, void const *keyv, int len)
|
||||
{
|
||||
struct MD5Context *keys = (struct MD5Context *)handle;
|
||||
unsigned char foo[64];
|
||||
unsigned char const *key = (unsigned char const *)keyv;
|
||||
int i;
|
||||
|
||||
memset(foo, 0x36, 64);
|
||||
for (i = 0; i < len && i < 64; i++)
|
||||
foo[i] ^= key[i];
|
||||
MD5Init(&keys[0]);
|
||||
MD5Update(&keys[0], foo, 64);
|
||||
|
||||
memset(foo, 0x5C, 64);
|
||||
for (i = 0; i < len && i < 64; i++)
|
||||
foo[i] ^= key[i];
|
||||
MD5Init(&keys[1]);
|
||||
MD5Update(&keys[1], foo, 64);
|
||||
|
||||
memset(foo, 0, 64); /* burn the evidence */
|
||||
}
|
||||
|
||||
static void hmacmd5_key_16(void *handle, unsigned char *key)
|
||||
{
|
||||
hmacmd5_key(handle, key, 16);
|
||||
}
|
||||
|
||||
static void hmacmd5_do_hmac_internal(void *handle,
|
||||
unsigned char const *blk, int len,
|
||||
unsigned char const *blk2, int len2,
|
||||
unsigned char *hmac)
|
||||
{
|
||||
struct MD5Context *keys = (struct MD5Context *)handle;
|
||||
struct MD5Context s;
|
||||
unsigned char intermediate[16];
|
||||
|
||||
s = keys[0]; /* structure copy */
|
||||
MD5Update(&s, blk, len);
|
||||
if (blk2) MD5Update(&s, blk2, len2);
|
||||
MD5Final(intermediate, &s);
|
||||
s = keys[1]; /* structure copy */
|
||||
MD5Update(&s, intermediate, 16);
|
||||
MD5Final(hmac, &s);
|
||||
}
|
||||
|
||||
void hmacmd5_do_hmac(void *handle, unsigned char const *blk, int len,
|
||||
unsigned char *hmac)
|
||||
{
|
||||
hmacmd5_do_hmac_internal(handle, blk, len, NULL, 0, hmac);
|
||||
}
|
||||
|
||||
static void hmacmd5_do_hmac_ssh(void *handle, unsigned char const *blk, int len,
|
||||
unsigned long seq, unsigned char *hmac)
|
||||
{
|
||||
unsigned char seqbuf[16];
|
||||
|
||||
seqbuf[0] = (unsigned char) ((seq >> 24) & 0xFF);
|
||||
seqbuf[1] = (unsigned char) ((seq >> 16) & 0xFF);
|
||||
seqbuf[2] = (unsigned char) ((seq >> 8) & 0xFF);
|
||||
seqbuf[3] = (unsigned char) ((seq) & 0xFF);
|
||||
|
||||
hmacmd5_do_hmac_internal(handle, seqbuf, 4, blk, len, hmac);
|
||||
}
|
||||
|
||||
static void hmacmd5_generate(void *handle, unsigned char *blk, int len,
|
||||
unsigned long seq)
|
||||
{
|
||||
hmacmd5_do_hmac_ssh(handle, blk, len, seq, blk + len);
|
||||
}
|
||||
|
||||
static int hmacmd5_verify(void *handle, unsigned char *blk, int len,
|
||||
unsigned long seq)
|
||||
{
|
||||
unsigned char correct[16];
|
||||
hmacmd5_do_hmac_ssh(handle, blk, len, seq, correct);
|
||||
return !memcmp(correct, blk + len, 16);
|
||||
}
|
||||
|
||||
const struct ssh_mac ssh_hmac_md5 = {
|
||||
hmacmd5_make_context, hmacmd5_free_context, hmacmd5_key_16,
|
||||
hmacmd5_generate, hmacmd5_verify,
|
||||
"hmac-md5",
|
||||
16,
|
||||
"HMAC-MD5"
|
||||
};
|
||||
1219
sFTPlugins/psftp/SSHPUBK.C
Normal file
1219
sFTPlugins/psftp/SSHPUBK.C
Normal file
File diff suppressed because it is too large
Load Diff
246
sFTPlugins/psftp/SSHRAND.C
Normal file
246
sFTPlugins/psftp/SSHRAND.C
Normal file
@@ -0,0 +1,246 @@
|
||||
/*
|
||||
* cryptographic random number generator for PuTTY's ssh client
|
||||
*/
|
||||
|
||||
#include "putty.h"
|
||||
#include "ssh.h"
|
||||
|
||||
/* Collect environmental noise every 5 minutes */
|
||||
#define NOISE_REGULAR_INTERVAL (5*60*TICKSPERSEC)
|
||||
|
||||
void noise_get_heavy(void (*func) (void *, int));
|
||||
void noise_get_light(void (*func) (void *, int));
|
||||
|
||||
/*
|
||||
* `pool' itself is a pool of random data which we actually use: we
|
||||
* return bytes from `pool', at position `poolpos', until `poolpos'
|
||||
* reaches the end of the pool. At this point we generate more
|
||||
* random data, by adding noise, stirring well, and resetting
|
||||
* `poolpos' to point to just past the beginning of the pool (not
|
||||
* _the_ beginning, since otherwise we'd give away the whole
|
||||
* contents of our pool, and attackers would just have to guess the
|
||||
* next lot of noise).
|
||||
*
|
||||
* `incomingb' buffers acquired noise data, until it gets full, at
|
||||
* which point the acquired noise is SHA'ed into `incoming' and
|
||||
* `incomingb' is cleared. The noise in `incoming' is used as part
|
||||
* of the noise for each stirring of the pool, in addition to local
|
||||
* time, process listings, and other such stuff.
|
||||
*/
|
||||
|
||||
#define HASHINPUT 64 /* 64 bytes SHA input */
|
||||
#define HASHSIZE 20 /* 160 bits SHA output */
|
||||
#define POOLSIZE 1200 /* size of random pool */
|
||||
|
||||
struct RandPool {
|
||||
unsigned char pool[POOLSIZE];
|
||||
int poolpos;
|
||||
|
||||
unsigned char incoming[HASHSIZE];
|
||||
|
||||
unsigned char incomingb[HASHINPUT];
|
||||
int incomingpos;
|
||||
|
||||
int stir_pending;
|
||||
};
|
||||
|
||||
static struct RandPool pool;
|
||||
int random_active = 0;
|
||||
long next_noise_collection;
|
||||
|
||||
static void random_stir(void)
|
||||
{
|
||||
word32 block[HASHINPUT / sizeof(word32)];
|
||||
word32 digest[HASHSIZE / sizeof(word32)];
|
||||
int i, j, k;
|
||||
|
||||
/*
|
||||
* noise_get_light will call random_add_noise, which may call
|
||||
* back to here. Prevent recursive stirs.
|
||||
*/
|
||||
if (pool.stir_pending)
|
||||
return;
|
||||
pool.stir_pending = TRUE;
|
||||
|
||||
noise_get_light(random_add_noise);
|
||||
|
||||
SHATransform((word32 *) pool.incoming, (word32 *) pool.incomingb);
|
||||
pool.incomingpos = 0;
|
||||
|
||||
/*
|
||||
* Chunks of this code are blatantly endianness-dependent, but
|
||||
* as it's all random bits anyway, WHO CARES?
|
||||
*/
|
||||
memcpy(digest, pool.incoming, sizeof(digest));
|
||||
|
||||
/*
|
||||
* Make two passes over the pool.
|
||||
*/
|
||||
for (i = 0; i < 2; i++) {
|
||||
|
||||
/*
|
||||
* We operate SHA in CFB mode, repeatedly adding the same
|
||||
* block of data to the digest. But we're also fiddling
|
||||
* with the digest-so-far, so this shouldn't be Bad or
|
||||
* anything.
|
||||
*/
|
||||
memcpy(block, pool.pool, sizeof(block));
|
||||
|
||||
/*
|
||||
* Each pass processes the pool backwards in blocks of
|
||||
* HASHSIZE, just so that in general we get the output of
|
||||
* SHA before the corresponding input, in the hope that
|
||||
* things will be that much less predictable that way
|
||||
* round, when we subsequently return bytes ...
|
||||
*/
|
||||
for (j = POOLSIZE; (j -= HASHSIZE) >= 0;) {
|
||||
/*
|
||||
* XOR the bit of the pool we're processing into the
|
||||
* digest.
|
||||
*/
|
||||
|
||||
for (k = 0; k < sizeof(digest) / sizeof(*digest); k++)
|
||||
digest[k] ^= ((word32 *) (pool.pool + j))[k];
|
||||
|
||||
/*
|
||||
* Munge our unrevealed first block of the pool into
|
||||
* it.
|
||||
*/
|
||||
SHATransform(digest, block);
|
||||
|
||||
/*
|
||||
* Stick the result back into the pool.
|
||||
*/
|
||||
|
||||
for (k = 0; k < sizeof(digest) / sizeof(*digest); k++)
|
||||
((word32 *) (pool.pool + j))[k] = digest[k];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Might as well save this value back into `incoming', just so
|
||||
* there'll be some extra bizarreness there.
|
||||
*/
|
||||
SHATransform(digest, block);
|
||||
memcpy(pool.incoming, digest, sizeof(digest));
|
||||
|
||||
pool.poolpos = sizeof(pool.incoming);
|
||||
|
||||
pool.stir_pending = FALSE;
|
||||
}
|
||||
|
||||
void random_add_noise(void *noise, int length)
|
||||
{
|
||||
unsigned char *p = noise;
|
||||
int i;
|
||||
|
||||
if (!random_active)
|
||||
return;
|
||||
|
||||
/*
|
||||
* This function processes HASHINPUT bytes into only HASHSIZE
|
||||
* bytes, so _if_ we were getting incredibly high entropy
|
||||
* sources then we would be throwing away valuable stuff.
|
||||
*/
|
||||
while (length >= (HASHINPUT - pool.incomingpos)) {
|
||||
memcpy(pool.incomingb + pool.incomingpos, p,
|
||||
HASHINPUT - pool.incomingpos);
|
||||
p += HASHINPUT - pool.incomingpos;
|
||||
length -= HASHINPUT - pool.incomingpos;
|
||||
SHATransform((word32 *) pool.incoming, (word32 *) pool.incomingb);
|
||||
for (i = 0; i < HASHSIZE; i++) {
|
||||
pool.pool[pool.poolpos++] ^= pool.incomingb[i];
|
||||
if (pool.poolpos >= POOLSIZE)
|
||||
pool.poolpos = 0;
|
||||
}
|
||||
if (pool.poolpos < HASHSIZE)
|
||||
random_stir();
|
||||
|
||||
pool.incomingpos = 0;
|
||||
}
|
||||
|
||||
memcpy(pool.incomingb + pool.incomingpos, p, length);
|
||||
pool.incomingpos += length;
|
||||
}
|
||||
|
||||
void random_add_heavynoise(void *noise, int length)
|
||||
{
|
||||
unsigned char *p = noise;
|
||||
int i;
|
||||
|
||||
while (length >= POOLSIZE) {
|
||||
for (i = 0; i < POOLSIZE; i++)
|
||||
pool.pool[i] ^= *p++;
|
||||
random_stir();
|
||||
length -= POOLSIZE;
|
||||
}
|
||||
|
||||
for (i = 0; i < length; i++)
|
||||
pool.pool[i] ^= *p++;
|
||||
random_stir();
|
||||
}
|
||||
|
||||
static void random_add_heavynoise_bitbybit(void *noise, int length)
|
||||
{
|
||||
unsigned char *p = noise;
|
||||
int i;
|
||||
|
||||
while (length >= POOLSIZE - pool.poolpos) {
|
||||
for (i = 0; i < POOLSIZE - pool.poolpos; i++)
|
||||
pool.pool[pool.poolpos + i] ^= *p++;
|
||||
random_stir();
|
||||
length -= POOLSIZE - pool.poolpos;
|
||||
pool.poolpos = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < length; i++)
|
||||
pool.pool[i] ^= *p++;
|
||||
pool.poolpos = i;
|
||||
}
|
||||
|
||||
static void random_timer(void *ctx, long now)
|
||||
{
|
||||
if (random_active > 0 && now - next_noise_collection >= 0) {
|
||||
noise_regular();
|
||||
next_noise_collection =
|
||||
schedule_timer(NOISE_REGULAR_INTERVAL, random_timer, &pool);
|
||||
}
|
||||
}
|
||||
|
||||
void random_ref(void)
|
||||
{
|
||||
if (!random_active) {
|
||||
memset(&pool, 0, sizeof(pool)); /* just to start with */
|
||||
|
||||
noise_get_heavy(random_add_heavynoise_bitbybit);
|
||||
random_stir();
|
||||
|
||||
next_noise_collection =
|
||||
schedule_timer(NOISE_REGULAR_INTERVAL, random_timer, &pool);
|
||||
}
|
||||
|
||||
random_active++;
|
||||
}
|
||||
|
||||
void random_unref(void)
|
||||
{
|
||||
random_active--;
|
||||
}
|
||||
|
||||
int random_byte(void)
|
||||
{
|
||||
if (pool.poolpos >= POOLSIZE)
|
||||
random_stir();
|
||||
|
||||
return pool.pool[pool.poolpos++];
|
||||
}
|
||||
|
||||
void random_get_savedata(void **data, int *len)
|
||||
{
|
||||
void *buf = snewn(POOLSIZE / 2, char);
|
||||
random_stir();
|
||||
memcpy(buf, pool.pool + pool.poolpos, POOLSIZE / 2);
|
||||
*len = POOLSIZE / 2;
|
||||
*data = buf;
|
||||
random_stir();
|
||||
}
|
||||
838
sFTPlugins/psftp/SSHRSA.C
Normal file
838
sFTPlugins/psftp/SSHRSA.C
Normal file
@@ -0,0 +1,838 @@
|
||||
/*
|
||||
* RSA implementation for PuTTY.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "ssh.h"
|
||||
#include "misc.h"
|
||||
|
||||
int makekey(unsigned char *data, int len, struct RSAKey *result,
|
||||
unsigned char **keystr, int order)
|
||||
{
|
||||
unsigned char *p = data;
|
||||
int i, n;
|
||||
|
||||
if (len < 4)
|
||||
return -1;
|
||||
|
||||
if (result) {
|
||||
result->bits = 0;
|
||||
for (i = 0; i < 4; i++)
|
||||
result->bits = (result->bits << 8) + *p++;
|
||||
} else
|
||||
p += 4;
|
||||
|
||||
len -= 4;
|
||||
|
||||
/*
|
||||
* order=0 means exponent then modulus (the keys sent by the
|
||||
* server). order=1 means modulus then exponent (the keys
|
||||
* stored in a keyfile).
|
||||
*/
|
||||
|
||||
if (order == 0) {
|
||||
n = ssh1_read_bignum(p, len, result ? &result->exponent : NULL);
|
||||
if (n < 0) return -1;
|
||||
p += n;
|
||||
len -= n;
|
||||
}
|
||||
|
||||
n = ssh1_read_bignum(p, len, result ? &result->modulus : NULL);
|
||||
if (n < 0 || (result && bignum_bitcount(result->modulus) == 0)) return -1;
|
||||
if (result)
|
||||
result->bytes = n - 2;
|
||||
if (keystr)
|
||||
*keystr = p + 2;
|
||||
p += n;
|
||||
len -= n;
|
||||
|
||||
if (order == 1) {
|
||||
n = ssh1_read_bignum(p, len, result ? &result->exponent : NULL);
|
||||
if (n < 0) return -1;
|
||||
p += n;
|
||||
len -= n;
|
||||
}
|
||||
return p - data;
|
||||
}
|
||||
|
||||
int makeprivate(unsigned char *data, int len, struct RSAKey *result)
|
||||
{
|
||||
return ssh1_read_bignum(data, len, &result->private_exponent);
|
||||
}
|
||||
|
||||
int rsaencrypt(unsigned char *data, int length, struct RSAKey *key)
|
||||
{
|
||||
Bignum b1, b2;
|
||||
int i;
|
||||
unsigned char *p;
|
||||
|
||||
if (key->bytes < length + 4)
|
||||
return 0; /* RSA key too short! */
|
||||
|
||||
memmove(data + key->bytes - length, data, length);
|
||||
data[0] = 0;
|
||||
data[1] = 2;
|
||||
|
||||
for (i = 2; i < key->bytes - length - 1; i++) {
|
||||
do {
|
||||
data[i] = random_byte();
|
||||
} while (data[i] == 0);
|
||||
}
|
||||
data[key->bytes - length - 1] = 0;
|
||||
|
||||
b1 = bignum_from_bytes(data, key->bytes);
|
||||
|
||||
b2 = modpow(b1, key->exponent, key->modulus);
|
||||
|
||||
p = data;
|
||||
for (i = key->bytes; i--;) {
|
||||
*p++ = bignum_byte(b2, i);
|
||||
}
|
||||
|
||||
freebn(b1);
|
||||
freebn(b2);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void sha512_mpint(SHA512_State * s, Bignum b)
|
||||
{
|
||||
unsigned char lenbuf[4];
|
||||
int len;
|
||||
len = (bignum_bitcount(b) + 8) / 8;
|
||||
PUT_32BIT(lenbuf, len);
|
||||
SHA512_Bytes(s, lenbuf, 4);
|
||||
while (len-- > 0) {
|
||||
lenbuf[0] = bignum_byte(b, len);
|
||||
SHA512_Bytes(s, lenbuf, 1);
|
||||
}
|
||||
memset(lenbuf, 0, sizeof(lenbuf));
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is a wrapper on modpow(). It has the same effect
|
||||
* as modpow(), but employs RSA blinding to protect against timing
|
||||
* attacks.
|
||||
*/
|
||||
static Bignum rsa_privkey_op(Bignum input, struct RSAKey *key)
|
||||
{
|
||||
Bignum random, random_encrypted, random_inverse;
|
||||
Bignum input_blinded, ret_blinded;
|
||||
Bignum ret;
|
||||
|
||||
SHA512_State ss;
|
||||
unsigned char digest512[64];
|
||||
int digestused = lenof(digest512);
|
||||
int hashseq = 0;
|
||||
|
||||
/*
|
||||
* Start by inventing a random number chosen uniformly from the
|
||||
* range 2..modulus-1. (We do this by preparing a random number
|
||||
* of the right length and retrying if it's greater than the
|
||||
* modulus, to prevent any potential Bleichenbacher-like
|
||||
* attacks making use of the uneven distribution within the
|
||||
* range that would arise from just reducing our number mod n.
|
||||
* There are timing implications to the potential retries, of
|
||||
* course, but all they tell you is the modulus, which you
|
||||
* already knew.)
|
||||
*
|
||||
* To preserve determinism and avoid Pageant needing to share
|
||||
* the random number pool, we actually generate this `random'
|
||||
* number by hashing stuff with the private key.
|
||||
*/
|
||||
while (1) {
|
||||
int bits, byte, bitsleft, v;
|
||||
random = copybn(key->modulus);
|
||||
/*
|
||||
* Find the topmost set bit. (This function will return its
|
||||
* index plus one.) Then we'll set all bits from that one
|
||||
* downwards randomly.
|
||||
*/
|
||||
bits = bignum_bitcount(random);
|
||||
byte = 0;
|
||||
bitsleft = 0;
|
||||
while (bits--) {
|
||||
if (bitsleft <= 0) {
|
||||
bitsleft = 8;
|
||||
/*
|
||||
* Conceptually the following few lines are equivalent to
|
||||
* byte = random_byte();
|
||||
*/
|
||||
if (digestused >= lenof(digest512)) {
|
||||
unsigned char seqbuf[4];
|
||||
PUT_32BIT(seqbuf, hashseq);
|
||||
SHA512_Init(&ss);
|
||||
SHA512_Bytes(&ss, "RSA deterministic blinding", 26);
|
||||
SHA512_Bytes(&ss, seqbuf, sizeof(seqbuf));
|
||||
sha512_mpint(&ss, key->private_exponent);
|
||||
SHA512_Final(&ss, digest512);
|
||||
hashseq++;
|
||||
|
||||
/*
|
||||
* Now hash that digest plus the signature
|
||||
* input.
|
||||
*/
|
||||
SHA512_Init(&ss);
|
||||
SHA512_Bytes(&ss, digest512, sizeof(digest512));
|
||||
sha512_mpint(&ss, input);
|
||||
SHA512_Final(&ss, digest512);
|
||||
|
||||
digestused = 0;
|
||||
}
|
||||
byte = digest512[digestused++];
|
||||
}
|
||||
v = byte & 1;
|
||||
byte >>= 1;
|
||||
bitsleft--;
|
||||
bignum_set_bit(random, bits, v);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now check that this number is strictly greater than
|
||||
* zero, and strictly less than modulus.
|
||||
*/
|
||||
if (bignum_cmp(random, Zero) <= 0 ||
|
||||
bignum_cmp(random, key->modulus) >= 0) {
|
||||
freebn(random);
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* RSA blinding relies on the fact that (xy)^d mod n is equal
|
||||
* to (x^d mod n) * (y^d mod n) mod n. We invent a random pair
|
||||
* y and y^d; then we multiply x by y, raise to the power d mod
|
||||
* n as usual, and divide by y^d to recover x^d. Thus an
|
||||
* attacker can't correlate the timing of the modpow with the
|
||||
* input, because they don't know anything about the number
|
||||
* that was input to the actual modpow.
|
||||
*
|
||||
* The clever bit is that we don't have to do a huge modpow to
|
||||
* get y and y^d; we will use the number we just invented as
|
||||
* _y^d_, and use the _public_ exponent to compute (y^d)^e = y
|
||||
* from it, which is much faster to do.
|
||||
*/
|
||||
random_encrypted = modpow(random, key->exponent, key->modulus);
|
||||
random_inverse = modinv(random, key->modulus);
|
||||
input_blinded = modmul(input, random_encrypted, key->modulus);
|
||||
ret_blinded = modpow(input_blinded, key->private_exponent, key->modulus);
|
||||
ret = modmul(ret_blinded, random_inverse, key->modulus);
|
||||
|
||||
freebn(ret_blinded);
|
||||
freebn(input_blinded);
|
||||
freebn(random_inverse);
|
||||
freebn(random_encrypted);
|
||||
freebn(random);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Bignum rsadecrypt(Bignum input, struct RSAKey *key)
|
||||
{
|
||||
return rsa_privkey_op(input, key);
|
||||
}
|
||||
|
||||
int rsastr_len(struct RSAKey *key)
|
||||
{
|
||||
Bignum md, ex;
|
||||
int mdlen, exlen;
|
||||
|
||||
md = key->modulus;
|
||||
ex = key->exponent;
|
||||
mdlen = (bignum_bitcount(md) + 15) / 16;
|
||||
exlen = (bignum_bitcount(ex) + 15) / 16;
|
||||
return 4 * (mdlen + exlen) + 20;
|
||||
}
|
||||
|
||||
void rsastr_fmt(char *str, struct RSAKey *key)
|
||||
{
|
||||
Bignum md, ex;
|
||||
int len = 0, i, nibbles;
|
||||
static const char hex[] = "0123456789abcdef";
|
||||
|
||||
md = key->modulus;
|
||||
ex = key->exponent;
|
||||
|
||||
len += sprintf(str + len, "0x");
|
||||
|
||||
nibbles = (3 + bignum_bitcount(ex)) / 4;
|
||||
if (nibbles < 1)
|
||||
nibbles = 1;
|
||||
for (i = nibbles; i--;)
|
||||
str[len++] = hex[(bignum_byte(ex, i / 2) >> (4 * (i % 2))) & 0xF];
|
||||
|
||||
len += sprintf(str + len, ",0x");
|
||||
|
||||
nibbles = (3 + bignum_bitcount(md)) / 4;
|
||||
if (nibbles < 1)
|
||||
nibbles = 1;
|
||||
for (i = nibbles; i--;)
|
||||
str[len++] = hex[(bignum_byte(md, i / 2) >> (4 * (i % 2))) & 0xF];
|
||||
|
||||
str[len] = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate a fingerprint string for the key. Compatible with the
|
||||
* OpenSSH fingerprint code.
|
||||
*/
|
||||
void rsa_fingerprint(char *str, int len, struct RSAKey *key)
|
||||
{
|
||||
struct MD5Context md5c;
|
||||
unsigned char digest[16];
|
||||
char buffer[16 * 3 + 40];
|
||||
int numlen, slen, i;
|
||||
|
||||
MD5Init(&md5c);
|
||||
numlen = ssh1_bignum_length(key->modulus) - 2;
|
||||
for (i = numlen; i--;) {
|
||||
unsigned char c = bignum_byte(key->modulus, i);
|
||||
MD5Update(&md5c, &c, 1);
|
||||
}
|
||||
numlen = ssh1_bignum_length(key->exponent) - 2;
|
||||
for (i = numlen; i--;) {
|
||||
unsigned char c = bignum_byte(key->exponent, i);
|
||||
MD5Update(&md5c, &c, 1);
|
||||
}
|
||||
MD5Final(digest, &md5c);
|
||||
|
||||
sprintf(buffer, "%d ", bignum_bitcount(key->modulus));
|
||||
for (i = 0; i < 16; i++)
|
||||
sprintf(buffer + strlen(buffer), "%s%02x", i ? ":" : "",
|
||||
digest[i]);
|
||||
strncpy(str, buffer, len);
|
||||
str[len - 1] = '\0';
|
||||
slen = strlen(str);
|
||||
if (key->comment && slen < len - 1) {
|
||||
str[slen] = ' ';
|
||||
strncpy(str + slen + 1, key->comment, len - slen - 1);
|
||||
str[len - 1] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that the public data in an RSA key matches the private
|
||||
* data. We also check the private data itself: we ensure that p >
|
||||
* q and that iqmp really is the inverse of q mod p.
|
||||
*/
|
||||
int rsa_verify(struct RSAKey *key)
|
||||
{
|
||||
Bignum n, ed, pm1, qm1;
|
||||
int cmp;
|
||||
|
||||
/* n must equal pq. */
|
||||
n = bigmul(key->p, key->q);
|
||||
cmp = bignum_cmp(n, key->modulus);
|
||||
freebn(n);
|
||||
if (cmp != 0)
|
||||
return 0;
|
||||
|
||||
/* e * d must be congruent to 1, modulo (p-1) and modulo (q-1). */
|
||||
pm1 = copybn(key->p);
|
||||
decbn(pm1);
|
||||
ed = modmul(key->exponent, key->private_exponent, pm1);
|
||||
cmp = bignum_cmp(ed, One);
|
||||
sfree(ed);
|
||||
if (cmp != 0)
|
||||
return 0;
|
||||
|
||||
qm1 = copybn(key->q);
|
||||
decbn(qm1);
|
||||
ed = modmul(key->exponent, key->private_exponent, qm1);
|
||||
cmp = bignum_cmp(ed, One);
|
||||
sfree(ed);
|
||||
if (cmp != 0)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Ensure p > q.
|
||||
*/
|
||||
if (bignum_cmp(key->p, key->q) <= 0)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Ensure iqmp * q is congruent to 1, modulo p.
|
||||
*/
|
||||
n = modmul(key->iqmp, key->q, key->p);
|
||||
cmp = bignum_cmp(n, One);
|
||||
sfree(n);
|
||||
if (cmp != 0)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Public key blob as used by Pageant: exponent before modulus. */
|
||||
unsigned char *rsa_public_blob(struct RSAKey *key, int *len)
|
||||
{
|
||||
int length, pos;
|
||||
unsigned char *ret;
|
||||
|
||||
length = (ssh1_bignum_length(key->modulus) +
|
||||
ssh1_bignum_length(key->exponent) + 4);
|
||||
ret = snewn(length, unsigned char);
|
||||
|
||||
PUT_32BIT(ret, bignum_bitcount(key->modulus));
|
||||
pos = 4;
|
||||
pos += ssh1_write_bignum(ret + pos, key->exponent);
|
||||
pos += ssh1_write_bignum(ret + pos, key->modulus);
|
||||
|
||||
*len = length;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Given a public blob, determine its length. */
|
||||
int rsa_public_blob_len(void *data, int maxlen)
|
||||
{
|
||||
unsigned char *p = (unsigned char *)data;
|
||||
int n;
|
||||
|
||||
if (maxlen < 4)
|
||||
return -1;
|
||||
p += 4; /* length word */
|
||||
maxlen -= 4;
|
||||
|
||||
n = ssh1_read_bignum(p, maxlen, NULL); /* exponent */
|
||||
if (n < 0)
|
||||
return -1;
|
||||
p += n;
|
||||
|
||||
n = ssh1_read_bignum(p, maxlen, NULL); /* modulus */
|
||||
if (n < 0)
|
||||
return -1;
|
||||
p += n;
|
||||
|
||||
return p - (unsigned char *)data;
|
||||
}
|
||||
|
||||
void freersakey(struct RSAKey *key)
|
||||
{
|
||||
if (key->modulus)
|
||||
freebn(key->modulus);
|
||||
if (key->exponent)
|
||||
freebn(key->exponent);
|
||||
if (key->private_exponent)
|
||||
freebn(key->private_exponent);
|
||||
if (key->comment)
|
||||
sfree(key->comment);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* Implementation of the ssh-rsa signing key type.
|
||||
*/
|
||||
|
||||
static void getstring(char **data, int *datalen, char **p, int *length)
|
||||
{
|
||||
*p = NULL;
|
||||
if (*datalen < 4)
|
||||
return;
|
||||
*length = GET_32BIT(*data);
|
||||
*datalen -= 4;
|
||||
*data += 4;
|
||||
if (*datalen < *length)
|
||||
return;
|
||||
*p = *data;
|
||||
*data += *length;
|
||||
*datalen -= *length;
|
||||
}
|
||||
static Bignum getmp(char **data, int *datalen)
|
||||
{
|
||||
char *p;
|
||||
int length;
|
||||
Bignum b;
|
||||
|
||||
getstring(data, datalen, &p, &length);
|
||||
if (!p)
|
||||
return NULL;
|
||||
b = bignum_from_bytes((unsigned char *)p, length);
|
||||
return b;
|
||||
}
|
||||
|
||||
static void *rsa2_newkey(char *data, int len)
|
||||
{
|
||||
char *p;
|
||||
int slen;
|
||||
struct RSAKey *rsa;
|
||||
|
||||
rsa = snew(struct RSAKey);
|
||||
if (!rsa)
|
||||
return NULL;
|
||||
getstring(&data, &len, &p, &slen);
|
||||
|
||||
if (!p || slen != 7 || memcmp(p, "ssh-rsa", 7)) {
|
||||
sfree(rsa);
|
||||
return NULL;
|
||||
}
|
||||
rsa->exponent = getmp(&data, &len);
|
||||
rsa->modulus = getmp(&data, &len);
|
||||
rsa->private_exponent = NULL;
|
||||
rsa->comment = NULL;
|
||||
|
||||
return rsa;
|
||||
}
|
||||
|
||||
static void rsa2_freekey(void *key)
|
||||
{
|
||||
struct RSAKey *rsa = (struct RSAKey *) key;
|
||||
freersakey(rsa);
|
||||
sfree(rsa);
|
||||
}
|
||||
|
||||
static char *rsa2_fmtkey(void *key)
|
||||
{
|
||||
struct RSAKey *rsa = (struct RSAKey *) key;
|
||||
char *p;
|
||||
int len;
|
||||
|
||||
len = rsastr_len(rsa);
|
||||
p = snewn(len, char);
|
||||
rsastr_fmt(p, rsa);
|
||||
return p;
|
||||
}
|
||||
|
||||
static unsigned char *rsa2_public_blob(void *key, int *len)
|
||||
{
|
||||
struct RSAKey *rsa = (struct RSAKey *) key;
|
||||
int elen, mlen, bloblen;
|
||||
int i;
|
||||
unsigned char *blob, *p;
|
||||
|
||||
elen = (bignum_bitcount(rsa->exponent) + 8) / 8;
|
||||
mlen = (bignum_bitcount(rsa->modulus) + 8) / 8;
|
||||
|
||||
/*
|
||||
* string "ssh-rsa", mpint exp, mpint mod. Total 19+elen+mlen.
|
||||
* (three length fields, 12+7=19).
|
||||
*/
|
||||
bloblen = 19 + elen + mlen;
|
||||
blob = snewn(bloblen, unsigned char);
|
||||
p = blob;
|
||||
PUT_32BIT(p, 7);
|
||||
p += 4;
|
||||
memcpy(p, "ssh-rsa", 7);
|
||||
p += 7;
|
||||
PUT_32BIT(p, elen);
|
||||
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);
|
||||
*len = bloblen;
|
||||
return blob;
|
||||
}
|
||||
|
||||
static unsigned char *rsa2_private_blob(void *key, int *len)
|
||||
{
|
||||
struct RSAKey *rsa = (struct RSAKey *) key;
|
||||
int dlen, plen, qlen, ulen, bloblen;
|
||||
int i;
|
||||
unsigned char *blob, *p;
|
||||
|
||||
dlen = (bignum_bitcount(rsa->private_exponent) + 8) / 8;
|
||||
plen = (bignum_bitcount(rsa->p) + 8) / 8;
|
||||
qlen = (bignum_bitcount(rsa->q) + 8) / 8;
|
||||
ulen = (bignum_bitcount(rsa->iqmp) + 8) / 8;
|
||||
|
||||
/*
|
||||
* mpint private_exp, mpint p, mpint q, mpint iqmp. Total 16 +
|
||||
* sum of lengths.
|
||||
*/
|
||||
bloblen = 16 + dlen + plen + qlen + ulen;
|
||||
blob = snewn(bloblen, unsigned char);
|
||||
p = blob;
|
||||
PUT_32BIT(p, dlen);
|
||||
p += 4;
|
||||
for (i = dlen; i--;)
|
||||
*p++ = bignum_byte(rsa->private_exponent, i);
|
||||
PUT_32BIT(p, plen);
|
||||
p += 4;
|
||||
for (i = plen; 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);
|
||||
*len = bloblen;
|
||||
return blob;
|
||||
}
|
||||
|
||||
static void *rsa2_createkey(unsigned char *pub_blob, int pub_len,
|
||||
unsigned char *priv_blob, int priv_len)
|
||||
{
|
||||
struct RSAKey *rsa;
|
||||
char *pb = (char *) priv_blob;
|
||||
|
||||
rsa = rsa2_newkey((char *) pub_blob, pub_len);
|
||||
rsa->private_exponent = getmp(&pb, &priv_len);
|
||||
rsa->p = getmp(&pb, &priv_len);
|
||||
rsa->q = getmp(&pb, &priv_len);
|
||||
rsa->iqmp = getmp(&pb, &priv_len);
|
||||
|
||||
if (!rsa_verify(rsa)) {
|
||||
rsa2_freekey(rsa);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return rsa;
|
||||
}
|
||||
|
||||
static void *rsa2_openssh_createkey(unsigned char **blob, int *len)
|
||||
{
|
||||
char **b = (char **) blob;
|
||||
struct RSAKey *rsa;
|
||||
|
||||
rsa = snew(struct RSAKey);
|
||||
if (!rsa)
|
||||
return NULL;
|
||||
rsa->comment = NULL;
|
||||
|
||||
rsa->modulus = getmp(b, len);
|
||||
rsa->exponent = getmp(b, len);
|
||||
rsa->private_exponent = getmp(b, len);
|
||||
rsa->iqmp = getmp(b, len);
|
||||
rsa->p = getmp(b, len);
|
||||
rsa->q = getmp(b, len);
|
||||
|
||||
if (!rsa->modulus || !rsa->exponent || !rsa->private_exponent ||
|
||||
!rsa->iqmp || !rsa->p || !rsa->q) {
|
||||
sfree(rsa->modulus);
|
||||
sfree(rsa->exponent);
|
||||
sfree(rsa->private_exponent);
|
||||
sfree(rsa->iqmp);
|
||||
sfree(rsa->p);
|
||||
sfree(rsa->q);
|
||||
sfree(rsa);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return rsa;
|
||||
}
|
||||
|
||||
static int rsa2_openssh_fmtkey(void *key, unsigned char *blob, int len)
|
||||
{
|
||||
struct RSAKey *rsa = (struct RSAKey *) key;
|
||||
int bloblen, i;
|
||||
|
||||
bloblen =
|
||||
ssh2_bignum_length(rsa->modulus) +
|
||||
ssh2_bignum_length(rsa->exponent) +
|
||||
ssh2_bignum_length(rsa->private_exponent) +
|
||||
ssh2_bignum_length(rsa->iqmp) +
|
||||
ssh2_bignum_length(rsa->p) + ssh2_bignum_length(rsa->q);
|
||||
|
||||
if (bloblen > len)
|
||||
return bloblen;
|
||||
|
||||
bloblen = 0;
|
||||
#define ENC(x) \
|
||||
PUT_32BIT(blob+bloblen, ssh2_bignum_length((x))-4); bloblen += 4; \
|
||||
for (i = ssh2_bignum_length((x))-4; i-- ;) blob[bloblen++]=bignum_byte((x),i);
|
||||
ENC(rsa->modulus);
|
||||
ENC(rsa->exponent);
|
||||
ENC(rsa->private_exponent);
|
||||
ENC(rsa->iqmp);
|
||||
ENC(rsa->p);
|
||||
ENC(rsa->q);
|
||||
|
||||
return bloblen;
|
||||
}
|
||||
|
||||
static int rsa2_pubkey_bits(void *blob, int len)
|
||||
{
|
||||
struct RSAKey *rsa;
|
||||
int ret;
|
||||
|
||||
rsa = rsa2_newkey((char *) blob, len);
|
||||
ret = bignum_bitcount(rsa->modulus);
|
||||
rsa2_freekey(rsa);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char *rsa2_fingerprint(void *key)
|
||||
{
|
||||
struct RSAKey *rsa = (struct RSAKey *) key;
|
||||
struct MD5Context md5c;
|
||||
unsigned char digest[16], lenbuf[4];
|
||||
char buffer[16 * 3 + 40];
|
||||
char *ret;
|
||||
int numlen, i;
|
||||
|
||||
MD5Init(&md5c);
|
||||
MD5Update(&md5c, (unsigned char *)"\0\0\0\7ssh-rsa", 11);
|
||||
|
||||
#define ADD_BIGNUM(bignum) \
|
||||
numlen = (bignum_bitcount(bignum)+8)/8; \
|
||||
PUT_32BIT(lenbuf, numlen); MD5Update(&md5c, lenbuf, 4); \
|
||||
for (i = numlen; i-- ;) { \
|
||||
unsigned char c = bignum_byte(bignum, i); \
|
||||
MD5Update(&md5c, &c, 1); \
|
||||
}
|
||||
ADD_BIGNUM(rsa->exponent);
|
||||
ADD_BIGNUM(rsa->modulus);
|
||||
#undef ADD_BIGNUM
|
||||
|
||||
MD5Final(digest, &md5c);
|
||||
|
||||
sprintf(buffer, "ssh-rsa %d ", bignum_bitcount(rsa->modulus));
|
||||
for (i = 0; i < 16; i++)
|
||||
sprintf(buffer + strlen(buffer), "%s%02x", i ? ":" : "",
|
||||
digest[i]);
|
||||
ret = snewn(strlen(buffer) + 1, char);
|
||||
if (ret)
|
||||
strcpy(ret, buffer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the magic ASN.1/DER prefix that goes in the decoded
|
||||
* signature, between the string of FFs and the actual SHA hash
|
||||
* value. The meaning of it is:
|
||||
*
|
||||
* 00 -- this marks the end of the FFs; not part of the ASN.1 bit itself
|
||||
*
|
||||
* 30 21 -- a constructed SEQUENCE of length 0x21
|
||||
* 30 09 -- a constructed sub-SEQUENCE of length 9
|
||||
* 06 05 -- an object identifier, length 5
|
||||
* 2B 0E 03 02 1A -- object id { 1 3 14 3 2 26 }
|
||||
* (the 1,3 comes from 0x2B = 43 = 40*1+3)
|
||||
* 05 00 -- NULL
|
||||
* 04 14 -- a primitive OCTET STRING of length 0x14
|
||||
* [0x14 bytes of hash data follows]
|
||||
*
|
||||
* The object id in the middle there is listed as `id-sha1' in
|
||||
* ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1d2.asn (the
|
||||
* ASN module for PKCS #1) and its expanded form is as follows:
|
||||
*
|
||||
* id-sha1 OBJECT IDENTIFIER ::= {
|
||||
* iso(1) identified-organization(3) oiw(14) secsig(3)
|
||||
* algorithms(2) 26 }
|
||||
*/
|
||||
static const unsigned char asn1_weird_stuff[] = {
|
||||
0x00, 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B,
|
||||
0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14,
|
||||
};
|
||||
|
||||
#define ASN1_LEN ( (int) sizeof(asn1_weird_stuff) )
|
||||
|
||||
static int rsa2_verifysig(void *key, char *sig, int siglen,
|
||||
char *data, int datalen)
|
||||
{
|
||||
struct RSAKey *rsa = (struct RSAKey *) key;
|
||||
Bignum in, out;
|
||||
char *p;
|
||||
int slen;
|
||||
int bytes, i, j, ret;
|
||||
unsigned char hash[20];
|
||||
|
||||
getstring(&sig, &siglen, &p, &slen);
|
||||
if (!p || slen != 7 || memcmp(p, "ssh-rsa", 7)) {
|
||||
return 0;
|
||||
}
|
||||
in = getmp(&sig, &siglen);
|
||||
out = modpow(in, rsa->exponent, rsa->modulus);
|
||||
freebn(in);
|
||||
|
||||
ret = 1;
|
||||
|
||||
bytes = (bignum_bitcount(rsa->modulus)+7) / 8;
|
||||
/* Top (partial) byte should be zero. */
|
||||
if (bignum_byte(out, bytes - 1) != 0)
|
||||
ret = 0;
|
||||
/* First whole byte should be 1. */
|
||||
if (bignum_byte(out, bytes - 2) != 1)
|
||||
ret = 0;
|
||||
/* Most of the rest should be FF. */
|
||||
for (i = bytes - 3; i >= 20 + ASN1_LEN; i--) {
|
||||
if (bignum_byte(out, i) != 0xFF)
|
||||
ret = 0;
|
||||
}
|
||||
/* Then we expect to see the asn1_weird_stuff. */
|
||||
for (i = 20 + ASN1_LEN - 1, j = 0; i >= 20; i--, j++) {
|
||||
if (bignum_byte(out, i) != asn1_weird_stuff[j])
|
||||
ret = 0;
|
||||
}
|
||||
/* Finally, we expect to see the SHA-1 hash of the signed data. */
|
||||
SHA_Simple(data, datalen, hash);
|
||||
for (i = 19, j = 0; i >= 0; i--, j++) {
|
||||
if (bignum_byte(out, i) != hash[j])
|
||||
ret = 0;
|
||||
}
|
||||
freebn(out);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static unsigned char *rsa2_sign(void *key, char *data, int datalen,
|
||||
int *siglen)
|
||||
{
|
||||
struct RSAKey *rsa = (struct RSAKey *) key;
|
||||
unsigned char *bytes;
|
||||
int nbytes;
|
||||
unsigned char hash[20];
|
||||
Bignum in, out;
|
||||
int i, j;
|
||||
|
||||
SHA_Simple(data, datalen, hash);
|
||||
|
||||
nbytes = (bignum_bitcount(rsa->modulus) - 1) / 8;
|
||||
assert(1 <= nbytes - 20 - ASN1_LEN);
|
||||
bytes = snewn(nbytes, unsigned char);
|
||||
|
||||
bytes[0] = 1;
|
||||
for (i = 1; i < nbytes - 20 - ASN1_LEN; i++)
|
||||
bytes[i] = 0xFF;
|
||||
for (i = nbytes - 20 - ASN1_LEN, j = 0; i < nbytes - 20; i++, j++)
|
||||
bytes[i] = asn1_weird_stuff[j];
|
||||
for (i = nbytes - 20, j = 0; i < nbytes; i++, j++)
|
||||
bytes[i] = hash[j];
|
||||
|
||||
in = bignum_from_bytes(bytes, nbytes);
|
||||
sfree(bytes);
|
||||
|
||||
out = rsa_privkey_op(in, rsa);
|
||||
freebn(in);
|
||||
|
||||
nbytes = (bignum_bitcount(out) + 7) / 8;
|
||||
bytes = snewn(4 + 7 + 4 + nbytes, unsigned char);
|
||||
PUT_32BIT(bytes, 7);
|
||||
memcpy(bytes + 4, "ssh-rsa", 7);
|
||||
PUT_32BIT(bytes + 4 + 7, nbytes);
|
||||
for (i = 0; i < nbytes; i++)
|
||||
bytes[4 + 7 + 4 + i] = bignum_byte(out, nbytes - 1 - i);
|
||||
freebn(out);
|
||||
|
||||
*siglen = 4 + 7 + 4 + nbytes;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
const struct ssh_signkey ssh_rsa = {
|
||||
rsa2_newkey,
|
||||
rsa2_freekey,
|
||||
rsa2_fmtkey,
|
||||
rsa2_public_blob,
|
||||
rsa2_private_blob,
|
||||
rsa2_createkey,
|
||||
rsa2_openssh_createkey,
|
||||
rsa2_openssh_fmtkey,
|
||||
rsa2_pubkey_bits,
|
||||
rsa2_fingerprint,
|
||||
rsa2_verifysig,
|
||||
rsa2_sign,
|
||||
"ssh-rsa",
|
||||
"rsa2"
|
||||
};
|
||||
269
sFTPlugins/psftp/SSHSH256.C
Normal file
269
sFTPlugins/psftp/SSHSH256.C
Normal file
@@ -0,0 +1,269 @@
|
||||
/*
|
||||
* SHA-256 algorithm as described at
|
||||
*
|
||||
* http://csrc.nist.gov/cryptval/shs.html
|
||||
*/
|
||||
|
||||
#include "ssh.h"
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* Core SHA256 algorithm: processes 16-word blocks into a message digest.
|
||||
*/
|
||||
|
||||
#define ror(x,y) ( ((x) << (32-y)) | (((uint32)(x)) >> (y)) )
|
||||
#define shr(x,y) ( (((uint32)(x)) >> (y)) )
|
||||
#define Ch(x,y,z) ( ((x) & (y)) ^ (~(x) & (z)) )
|
||||
#define Maj(x,y,z) ( ((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)) )
|
||||
#define bigsigma0(x) ( ror((x),2) ^ ror((x),13) ^ ror((x),22) )
|
||||
#define bigsigma1(x) ( ror((x),6) ^ ror((x),11) ^ ror((x),25) )
|
||||
#define smallsigma0(x) ( ror((x),7) ^ ror((x),18) ^ shr((x),3) )
|
||||
#define smallsigma1(x) ( ror((x),17) ^ ror((x),19) ^ shr((x),10) )
|
||||
|
||||
void SHA256_Core_Init(SHA256_State *s) {
|
||||
s->h[0] = 0x6a09e667;
|
||||
s->h[1] = 0xbb67ae85;
|
||||
s->h[2] = 0x3c6ef372;
|
||||
s->h[3] = 0xa54ff53a;
|
||||
s->h[4] = 0x510e527f;
|
||||
s->h[5] = 0x9b05688c;
|
||||
s->h[6] = 0x1f83d9ab;
|
||||
s->h[7] = 0x5be0cd19;
|
||||
}
|
||||
|
||||
void SHA256_Block(SHA256_State *s, uint32 *block) {
|
||||
uint32 w[80];
|
||||
uint32 a,b,c,d,e,f,g,h;
|
||||
static const int k[] = {
|
||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
|
||||
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
||||
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
||||
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
||||
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
|
||||
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
|
||||
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
||||
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
||||
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
||||
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
|
||||
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
|
||||
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
||||
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
||||
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
|
||||
};
|
||||
|
||||
int t;
|
||||
|
||||
for (t = 0; t < 16; t++)
|
||||
w[t] = block[t];
|
||||
|
||||
for (t = 16; t < 64; t++)
|
||||
w[t] = smallsigma1(w[t-2]) + w[t-7] + smallsigma0(w[t-15]) + w[t-16];
|
||||
|
||||
a = s->h[0]; b = s->h[1]; c = s->h[2]; d = s->h[3];
|
||||
e = s->h[4]; f = s->h[5]; g = s->h[6]; h = s->h[7];
|
||||
|
||||
for (t = 0; t < 64; t+=8) {
|
||||
uint32 t1, t2;
|
||||
|
||||
#define ROUND(j,a,b,c,d,e,f,g,h) \
|
||||
t1 = h + bigsigma1(e) + Ch(e,f,g) + k[j] + w[j]; \
|
||||
t2 = bigsigma0(a) + Maj(a,b,c); \
|
||||
d = d + t1; h = t1 + t2;
|
||||
|
||||
ROUND(t+0, a,b,c,d,e,f,g,h);
|
||||
ROUND(t+1, h,a,b,c,d,e,f,g);
|
||||
ROUND(t+2, g,h,a,b,c,d,e,f);
|
||||
ROUND(t+3, f,g,h,a,b,c,d,e);
|
||||
ROUND(t+4, e,f,g,h,a,b,c,d);
|
||||
ROUND(t+5, d,e,f,g,h,a,b,c);
|
||||
ROUND(t+6, c,d,e,f,g,h,a,b);
|
||||
ROUND(t+7, b,c,d,e,f,g,h,a);
|
||||
}
|
||||
|
||||
s->h[0] += a; s->h[1] += b; s->h[2] += c; s->h[3] += d;
|
||||
s->h[4] += e; s->h[5] += f; s->h[6] += g; s->h[7] += h;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* Outer SHA256 algorithm: take an arbitrary length byte string,
|
||||
* convert it into 16-word blocks with the prescribed padding at
|
||||
* the end, and pass those blocks to the core SHA256 algorithm.
|
||||
*/
|
||||
|
||||
#define BLKSIZE 64
|
||||
|
||||
void SHA256_Init(SHA256_State *s) {
|
||||
SHA256_Core_Init(s);
|
||||
s->blkused = 0;
|
||||
s->lenhi = s->lenlo = 0;
|
||||
}
|
||||
|
||||
void SHA256_Bytes(SHA256_State *s, const void *p, int len) {
|
||||
unsigned char *q = (unsigned char *)p;
|
||||
uint32 wordblock[16];
|
||||
uint32 lenw = len;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Update the length field.
|
||||
*/
|
||||
s->lenlo += lenw;
|
||||
s->lenhi += (s->lenlo < lenw);
|
||||
|
||||
if (s->blkused && s->blkused+len < BLKSIZE) {
|
||||
/*
|
||||
* Trivial case: just add to the block.
|
||||
*/
|
||||
memcpy(s->block + s->blkused, q, len);
|
||||
s->blkused += len;
|
||||
} else {
|
||||
/*
|
||||
* We must complete and process at least one block.
|
||||
*/
|
||||
while (s->blkused + len >= BLKSIZE) {
|
||||
memcpy(s->block + s->blkused, q, BLKSIZE - s->blkused);
|
||||
q += BLKSIZE - s->blkused;
|
||||
len -= BLKSIZE - s->blkused;
|
||||
/* Now process the block. Gather bytes big-endian into words */
|
||||
for (i = 0; i < 16; i++) {
|
||||
wordblock[i] =
|
||||
( ((uint32)s->block[i*4+0]) << 24 ) |
|
||||
( ((uint32)s->block[i*4+1]) << 16 ) |
|
||||
( ((uint32)s->block[i*4+2]) << 8 ) |
|
||||
( ((uint32)s->block[i*4+3]) << 0 );
|
||||
}
|
||||
SHA256_Block(s, wordblock);
|
||||
s->blkused = 0;
|
||||
}
|
||||
memcpy(s->block, q, len);
|
||||
s->blkused = len;
|
||||
}
|
||||
}
|
||||
|
||||
void SHA256_Final(SHA256_State *s, unsigned char *digest) {
|
||||
int i;
|
||||
int pad;
|
||||
unsigned char c[64];
|
||||
uint32 lenhi, lenlo;
|
||||
|
||||
if (s->blkused >= 56)
|
||||
pad = 56 + 64 - s->blkused;
|
||||
else
|
||||
pad = 56 - s->blkused;
|
||||
|
||||
lenhi = (s->lenhi << 3) | (s->lenlo >> (32-3));
|
||||
lenlo = (s->lenlo << 3);
|
||||
|
||||
memset(c, 0, pad);
|
||||
c[0] = 0x80;
|
||||
SHA256_Bytes(s, &c, pad);
|
||||
|
||||
c[0] = (lenhi >> 24) & 0xFF;
|
||||
c[1] = (lenhi >> 16) & 0xFF;
|
||||
c[2] = (lenhi >> 8) & 0xFF;
|
||||
c[3] = (lenhi >> 0) & 0xFF;
|
||||
c[4] = (lenlo >> 24) & 0xFF;
|
||||
c[5] = (lenlo >> 16) & 0xFF;
|
||||
c[6] = (lenlo >> 8) & 0xFF;
|
||||
c[7] = (lenlo >> 0) & 0xFF;
|
||||
|
||||
SHA256_Bytes(s, &c, 8);
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
digest[i*4+0] = (s->h[i] >> 24) & 0xFF;
|
||||
digest[i*4+1] = (s->h[i] >> 16) & 0xFF;
|
||||
digest[i*4+2] = (s->h[i] >> 8) & 0xFF;
|
||||
digest[i*4+3] = (s->h[i] >> 0) & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
void SHA256_Simple(const void *p, int len, unsigned char *output) {
|
||||
SHA256_State s;
|
||||
|
||||
SHA256_Init(&s);
|
||||
SHA256_Bytes(&s, p, len);
|
||||
SHA256_Final(&s, output);
|
||||
}
|
||||
|
||||
/*
|
||||
* Thin abstraction for things where hashes are pluggable.
|
||||
*/
|
||||
|
||||
static void *sha256_init(void)
|
||||
{
|
||||
SHA256_State *s;
|
||||
|
||||
s = snew(SHA256_State);
|
||||
SHA256_Init(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
static void sha256_bytes(void *handle, void *p, int len)
|
||||
{
|
||||
SHA256_State *s = handle;
|
||||
|
||||
SHA256_Bytes(s, p, len);
|
||||
}
|
||||
|
||||
static void sha256_final(void *handle, unsigned char *output)
|
||||
{
|
||||
SHA256_State *s = handle;
|
||||
|
||||
SHA256_Final(s, output);
|
||||
sfree(s);
|
||||
}
|
||||
|
||||
const struct ssh_hash ssh_sha256 = {
|
||||
sha256_init, sha256_bytes, sha256_final, 32, "SHA-256"
|
||||
};
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
int main(void) {
|
||||
unsigned char digest[32];
|
||||
int i, j, errors;
|
||||
|
||||
struct {
|
||||
const char *teststring;
|
||||
unsigned char digest[32];
|
||||
} tests[] = {
|
||||
{ "abc", {
|
||||
0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
|
||||
0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
|
||||
0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
|
||||
0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad,
|
||||
} },
|
||||
{ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", {
|
||||
0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,
|
||||
0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
|
||||
0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,
|
||||
0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1,
|
||||
} },
|
||||
};
|
||||
|
||||
errors = 0;
|
||||
|
||||
for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) {
|
||||
SHA256_Simple(tests[i].teststring,
|
||||
strlen(tests[i].teststring), digest);
|
||||
for (j = 0; j < 32; j++) {
|
||||
if (digest[j] != tests[i].digest[j]) {
|
||||
fprintf(stderr,
|
||||
"\"%s\" digest byte %d should be 0x%02x, is 0x%02x\n",
|
||||
tests[i].teststring, j, tests[i].digest[j], digest[j]);
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("%d errors\n", errors);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
358
sFTPlugins/psftp/SSHSH512.C
Normal file
358
sFTPlugins/psftp/SSHSH512.C
Normal file
@@ -0,0 +1,358 @@
|
||||
/*
|
||||
* SHA-512 algorithm as described at
|
||||
*
|
||||
* http://csrc.nist.gov/cryptval/shs.html
|
||||
*/
|
||||
|
||||
#include "ssh.h"
|
||||
|
||||
#define BLKSIZE 128
|
||||
|
||||
/*
|
||||
* Arithmetic implementations. Note that AND, XOR and NOT can
|
||||
* overlap destination with one source, but the others can't.
|
||||
*/
|
||||
#define add(r,x,y) ( r.lo = y.lo + x.lo, \
|
||||
r.hi = y.hi + x.hi + (r.lo < y.lo) )
|
||||
#define rorB(r,x,y) ( r.lo = (x.hi >> ((y)-32)) | (x.lo << (64-(y))), \
|
||||
r.hi = (x.lo >> ((y)-32)) | (x.hi << (64-(y))) )
|
||||
#define rorL(r,x,y) ( r.lo = (x.lo >> (y)) | (x.hi << (32-(y))), \
|
||||
r.hi = (x.hi >> (y)) | (x.lo << (32-(y))) )
|
||||
#define shrB(r,x,y) ( r.lo = x.hi >> ((y)-32), r.hi = 0 )
|
||||
#define shrL(r,x,y) ( r.lo = (x.lo >> (y)) | (x.hi << (32-(y))), \
|
||||
r.hi = x.hi >> (y) )
|
||||
#define and(r,x,y) ( r.lo = x.lo & y.lo, r.hi = x.hi & y.hi )
|
||||
#define xor(r,x,y) ( r.lo = x.lo ^ y.lo, r.hi = x.hi ^ y.hi )
|
||||
#define not(r,x) ( r.lo = ~x.lo, r.hi = ~x.hi )
|
||||
#define INIT(h,l) { h, l }
|
||||
#define BUILD(r,h,l) ( r.hi = h, r.lo = l )
|
||||
#define EXTRACT(h,l,r) ( h = r.hi, l = r.lo )
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* Core SHA512 algorithm: processes 16-doubleword blocks into a
|
||||
* message digest.
|
||||
*/
|
||||
|
||||
#define Ch(r,t,x,y,z) ( not(t,x), and(r,t,z), and(t,x,y), xor(r,r,t) )
|
||||
#define Maj(r,t,x,y,z) ( and(r,x,y), and(t,x,z), xor(r,r,t), \
|
||||
and(t,y,z), xor(r,r,t) )
|
||||
#define bigsigma0(r,t,x) ( rorL(r,x,28), rorB(t,x,34), xor(r,r,t), \
|
||||
rorB(t,x,39), xor(r,r,t) )
|
||||
#define bigsigma1(r,t,x) ( rorL(r,x,14), rorL(t,x,18), xor(r,r,t), \
|
||||
rorB(t,x,41), xor(r,r,t) )
|
||||
#define smallsigma0(r,t,x) ( rorL(r,x,1), rorL(t,x,8), xor(r,r,t), \
|
||||
shrL(t,x,7), xor(r,r,t) )
|
||||
#define smallsigma1(r,t,x) ( rorL(r,x,19), rorB(t,x,61), xor(r,r,t), \
|
||||
shrL(t,x,6), xor(r,r,t) )
|
||||
|
||||
static void SHA512_Core_Init(SHA512_State *s) {
|
||||
static const uint64 iv[] = {
|
||||
INIT(0x6a09e667, 0xf3bcc908),
|
||||
INIT(0xbb67ae85, 0x84caa73b),
|
||||
INIT(0x3c6ef372, 0xfe94f82b),
|
||||
INIT(0xa54ff53a, 0x5f1d36f1),
|
||||
INIT(0x510e527f, 0xade682d1),
|
||||
INIT(0x9b05688c, 0x2b3e6c1f),
|
||||
INIT(0x1f83d9ab, 0xfb41bd6b),
|
||||
INIT(0x5be0cd19, 0x137e2179),
|
||||
};
|
||||
int i;
|
||||
for (i = 0; i < 8; i++)
|
||||
s->h[i] = iv[i];
|
||||
}
|
||||
|
||||
static void SHA512_Block(SHA512_State *s, uint64 *block) {
|
||||
uint64 w[80];
|
||||
uint64 a,b,c,d,e,f,g,h;
|
||||
static const uint64 k[] = {
|
||||
INIT(0x428a2f98, 0xd728ae22), INIT(0x71374491, 0x23ef65cd),
|
||||
INIT(0xb5c0fbcf, 0xec4d3b2f), INIT(0xe9b5dba5, 0x8189dbbc),
|
||||
INIT(0x3956c25b, 0xf348b538), INIT(0x59f111f1, 0xb605d019),
|
||||
INIT(0x923f82a4, 0xaf194f9b), INIT(0xab1c5ed5, 0xda6d8118),
|
||||
INIT(0xd807aa98, 0xa3030242), INIT(0x12835b01, 0x45706fbe),
|
||||
INIT(0x243185be, 0x4ee4b28c), INIT(0x550c7dc3, 0xd5ffb4e2),
|
||||
INIT(0x72be5d74, 0xf27b896f), INIT(0x80deb1fe, 0x3b1696b1),
|
||||
INIT(0x9bdc06a7, 0x25c71235), INIT(0xc19bf174, 0xcf692694),
|
||||
INIT(0xe49b69c1, 0x9ef14ad2), INIT(0xefbe4786, 0x384f25e3),
|
||||
INIT(0x0fc19dc6, 0x8b8cd5b5), INIT(0x240ca1cc, 0x77ac9c65),
|
||||
INIT(0x2de92c6f, 0x592b0275), INIT(0x4a7484aa, 0x6ea6e483),
|
||||
INIT(0x5cb0a9dc, 0xbd41fbd4), INIT(0x76f988da, 0x831153b5),
|
||||
INIT(0x983e5152, 0xee66dfab), INIT(0xa831c66d, 0x2db43210),
|
||||
INIT(0xb00327c8, 0x98fb213f), INIT(0xbf597fc7, 0xbeef0ee4),
|
||||
INIT(0xc6e00bf3, 0x3da88fc2), INIT(0xd5a79147, 0x930aa725),
|
||||
INIT(0x06ca6351, 0xe003826f), INIT(0x14292967, 0x0a0e6e70),
|
||||
INIT(0x27b70a85, 0x46d22ffc), INIT(0x2e1b2138, 0x5c26c926),
|
||||
INIT(0x4d2c6dfc, 0x5ac42aed), INIT(0x53380d13, 0x9d95b3df),
|
||||
INIT(0x650a7354, 0x8baf63de), INIT(0x766a0abb, 0x3c77b2a8),
|
||||
INIT(0x81c2c92e, 0x47edaee6), INIT(0x92722c85, 0x1482353b),
|
||||
INIT(0xa2bfe8a1, 0x4cf10364), INIT(0xa81a664b, 0xbc423001),
|
||||
INIT(0xc24b8b70, 0xd0f89791), INIT(0xc76c51a3, 0x0654be30),
|
||||
INIT(0xd192e819, 0xd6ef5218), INIT(0xd6990624, 0x5565a910),
|
||||
INIT(0xf40e3585, 0x5771202a), INIT(0x106aa070, 0x32bbd1b8),
|
||||
INIT(0x19a4c116, 0xb8d2d0c8), INIT(0x1e376c08, 0x5141ab53),
|
||||
INIT(0x2748774c, 0xdf8eeb99), INIT(0x34b0bcb5, 0xe19b48a8),
|
||||
INIT(0x391c0cb3, 0xc5c95a63), INIT(0x4ed8aa4a, 0xe3418acb),
|
||||
INIT(0x5b9cca4f, 0x7763e373), INIT(0x682e6ff3, 0xd6b2b8a3),
|
||||
INIT(0x748f82ee, 0x5defb2fc), INIT(0x78a5636f, 0x43172f60),
|
||||
INIT(0x84c87814, 0xa1f0ab72), INIT(0x8cc70208, 0x1a6439ec),
|
||||
INIT(0x90befffa, 0x23631e28), INIT(0xa4506ceb, 0xde82bde9),
|
||||
INIT(0xbef9a3f7, 0xb2c67915), INIT(0xc67178f2, 0xe372532b),
|
||||
INIT(0xca273ece, 0xea26619c), INIT(0xd186b8c7, 0x21c0c207),
|
||||
INIT(0xeada7dd6, 0xcde0eb1e), INIT(0xf57d4f7f, 0xee6ed178),
|
||||
INIT(0x06f067aa, 0x72176fba), INIT(0x0a637dc5, 0xa2c898a6),
|
||||
INIT(0x113f9804, 0xbef90dae), INIT(0x1b710b35, 0x131c471b),
|
||||
INIT(0x28db77f5, 0x23047d84), INIT(0x32caab7b, 0x40c72493),
|
||||
INIT(0x3c9ebe0a, 0x15c9bebc), INIT(0x431d67c4, 0x9c100d4c),
|
||||
INIT(0x4cc5d4be, 0xcb3e42b6), INIT(0x597f299c, 0xfc657e2a),
|
||||
INIT(0x5fcb6fab, 0x3ad6faec), INIT(0x6c44198c, 0x4a475817),
|
||||
};
|
||||
|
||||
int t;
|
||||
|
||||
for (t = 0; t < 16; t++)
|
||||
w[t] = block[t];
|
||||
|
||||
for (t = 16; t < 80; t++) {
|
||||
uint64 p, q, r, tmp;
|
||||
smallsigma1(p, tmp, w[t-2]);
|
||||
smallsigma0(q, tmp, w[t-15]);
|
||||
add(r, p, q);
|
||||
add(p, r, w[t-7]);
|
||||
add(w[t], p, w[t-16]);
|
||||
}
|
||||
|
||||
a = s->h[0]; b = s->h[1]; c = s->h[2]; d = s->h[3];
|
||||
e = s->h[4]; f = s->h[5]; g = s->h[6]; h = s->h[7];
|
||||
|
||||
for (t = 0; t < 80; t+=8) {
|
||||
uint64 tmp, p, q, r;
|
||||
|
||||
#define ROUND(j,a,b,c,d,e,f,g,h) \
|
||||
bigsigma1(p, tmp, e); \
|
||||
Ch(q, tmp, e, f, g); \
|
||||
add(r, p, q); \
|
||||
add(p, r, k[j]) ; \
|
||||
add(q, p, w[j]); \
|
||||
add(r, q, h); \
|
||||
bigsigma0(p, tmp, a); \
|
||||
Maj(tmp, q, a, b, c); \
|
||||
add(q, tmp, p); \
|
||||
add(p, r, d); \
|
||||
d = p; \
|
||||
add(h, q, r);
|
||||
|
||||
ROUND(t+0, a,b,c,d,e,f,g,h);
|
||||
ROUND(t+1, h,a,b,c,d,e,f,g);
|
||||
ROUND(t+2, g,h,a,b,c,d,e,f);
|
||||
ROUND(t+3, f,g,h,a,b,c,d,e);
|
||||
ROUND(t+4, e,f,g,h,a,b,c,d);
|
||||
ROUND(t+5, d,e,f,g,h,a,b,c);
|
||||
ROUND(t+6, c,d,e,f,g,h,a,b);
|
||||
ROUND(t+7, b,c,d,e,f,g,h,a);
|
||||
}
|
||||
|
||||
{
|
||||
uint64 tmp;
|
||||
#define UPDATE(state, local) ( tmp = state, add(state, tmp, local) )
|
||||
UPDATE(s->h[0], a); UPDATE(s->h[1], b);
|
||||
UPDATE(s->h[2], c); UPDATE(s->h[3], d);
|
||||
UPDATE(s->h[4], e); UPDATE(s->h[5], f);
|
||||
UPDATE(s->h[6], g); UPDATE(s->h[7], h);
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* Outer SHA512 algorithm: take an arbitrary length byte string,
|
||||
* convert it into 16-doubleword blocks with the prescribed padding
|
||||
* at the end, and pass those blocks to the core SHA512 algorithm.
|
||||
*/
|
||||
|
||||
void SHA512_Init(SHA512_State *s) {
|
||||
int i;
|
||||
SHA512_Core_Init(s);
|
||||
s->blkused = 0;
|
||||
for (i = 0; i < 4; i++)
|
||||
s->len[i] = 0;
|
||||
}
|
||||
|
||||
void SHA512_Bytes(SHA512_State *s, const void *p, int len) {
|
||||
unsigned char *q = (unsigned char *)p;
|
||||
uint64 wordblock[16];
|
||||
uint32 lenw = len;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Update the length field.
|
||||
*/
|
||||
for (i = 0; i < 4; i++) {
|
||||
s->len[i] += lenw;
|
||||
lenw = (s->len[i] < lenw);
|
||||
}
|
||||
|
||||
if (s->blkused && s->blkused+len < BLKSIZE) {
|
||||
/*
|
||||
* Trivial case: just add to the block.
|
||||
*/
|
||||
memcpy(s->block + s->blkused, q, len);
|
||||
s->blkused += len;
|
||||
} else {
|
||||
/*
|
||||
* We must complete and process at least one block.
|
||||
*/
|
||||
while (s->blkused + len >= BLKSIZE) {
|
||||
memcpy(s->block + s->blkused, q, BLKSIZE - s->blkused);
|
||||
q += BLKSIZE - s->blkused;
|
||||
len -= BLKSIZE - s->blkused;
|
||||
/* Now process the block. Gather bytes big-endian into words */
|
||||
for (i = 0; i < 16; i++) {
|
||||
uint32 h, l;
|
||||
h = ( ((uint32)s->block[i*8+0]) << 24 ) |
|
||||
( ((uint32)s->block[i*8+1]) << 16 ) |
|
||||
( ((uint32)s->block[i*8+2]) << 8 ) |
|
||||
( ((uint32)s->block[i*8+3]) << 0 );
|
||||
l = ( ((uint32)s->block[i*8+4]) << 24 ) |
|
||||
( ((uint32)s->block[i*8+5]) << 16 ) |
|
||||
( ((uint32)s->block[i*8+6]) << 8 ) |
|
||||
( ((uint32)s->block[i*8+7]) << 0 );
|
||||
BUILD(wordblock[i], h, l);
|
||||
}
|
||||
SHA512_Block(s, wordblock);
|
||||
s->blkused = 0;
|
||||
}
|
||||
memcpy(s->block, q, len);
|
||||
s->blkused = len;
|
||||
}
|
||||
}
|
||||
|
||||
void SHA512_Final(SHA512_State *s, unsigned char *digest) {
|
||||
int i;
|
||||
int pad;
|
||||
unsigned char c[BLKSIZE];
|
||||
uint32 len[4];
|
||||
|
||||
if (s->blkused >= BLKSIZE-16)
|
||||
pad = (BLKSIZE-16) + BLKSIZE - s->blkused;
|
||||
else
|
||||
pad = (BLKSIZE-16) - s->blkused;
|
||||
|
||||
for (i = 4; i-- ;) {
|
||||
uint32 lenhi = s->len[i];
|
||||
uint32 lenlo = i > 0 ? s->len[i-1] : 0;
|
||||
len[i] = (lenhi << 3) | (lenlo >> (32-3));
|
||||
}
|
||||
|
||||
memset(c, 0, pad);
|
||||
c[0] = 0x80;
|
||||
SHA512_Bytes(s, &c, pad);
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
c[i*4+0] = (len[3-i] >> 24) & 0xFF;
|
||||
c[i*4+1] = (len[3-i] >> 16) & 0xFF;
|
||||
c[i*4+2] = (len[3-i] >> 8) & 0xFF;
|
||||
c[i*4+3] = (len[3-i] >> 0) & 0xFF;
|
||||
}
|
||||
|
||||
SHA512_Bytes(s, &c, 16);
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
uint32 h, l;
|
||||
EXTRACT(h, l, s->h[i]);
|
||||
digest[i*8+0] = (h >> 24) & 0xFF;
|
||||
digest[i*8+1] = (h >> 16) & 0xFF;
|
||||
digest[i*8+2] = (h >> 8) & 0xFF;
|
||||
digest[i*8+3] = (h >> 0) & 0xFF;
|
||||
digest[i*8+4] = (l >> 24) & 0xFF;
|
||||
digest[i*8+5] = (l >> 16) & 0xFF;
|
||||
digest[i*8+6] = (l >> 8) & 0xFF;
|
||||
digest[i*8+7] = (l >> 0) & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
void SHA512_Simple(const void *p, int len, unsigned char *output) {
|
||||
SHA512_State s;
|
||||
|
||||
SHA512_Init(&s);
|
||||
SHA512_Bytes(&s, p, len);
|
||||
SHA512_Final(&s, output);
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
int main(void) {
|
||||
unsigned char digest[64];
|
||||
int i, j, errors;
|
||||
|
||||
struct {
|
||||
const char *teststring;
|
||||
unsigned char digest512[64];
|
||||
} tests[] = {
|
||||
{ "abc", {
|
||||
0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba,
|
||||
0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31,
|
||||
0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2,
|
||||
0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a,
|
||||
0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8,
|
||||
0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,
|
||||
0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e,
|
||||
0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f,
|
||||
} },
|
||||
{ "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
|
||||
"hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", {
|
||||
0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda,
|
||||
0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f,
|
||||
0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1,
|
||||
0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18,
|
||||
0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4,
|
||||
0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a,
|
||||
0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54,
|
||||
0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09,
|
||||
} },
|
||||
{ NULL, {
|
||||
0xe7, 0x18, 0x48, 0x3d, 0x0c, 0xe7, 0x69, 0x64,
|
||||
0x4e, 0x2e, 0x42, 0xc7, 0xbc, 0x15, 0xb4, 0x63,
|
||||
0x8e, 0x1f, 0x98, 0xb1, 0x3b, 0x20, 0x44, 0x28,
|
||||
0x56, 0x32, 0xa8, 0x03, 0xaf, 0xa9, 0x73, 0xeb,
|
||||
0xde, 0x0f, 0xf2, 0x44, 0x87, 0x7e, 0xa6, 0x0a,
|
||||
0x4c, 0xb0, 0x43, 0x2c, 0xe5, 0x77, 0xc3, 0x1b,
|
||||
0xeb, 0x00, 0x9c, 0x5c, 0x2c, 0x49, 0xaa, 0x2e,
|
||||
0x4e, 0xad, 0xb2, 0x17, 0xad, 0x8c, 0xc0, 0x9b,
|
||||
} },
|
||||
};
|
||||
|
||||
errors = 0;
|
||||
|
||||
for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) {
|
||||
if (tests[i].teststring) {
|
||||
SHA512_Simple(tests[i].teststring,
|
||||
strlen(tests[i].teststring), digest);
|
||||
} else {
|
||||
SHA512_State s;
|
||||
int n;
|
||||
SHA512_Init(&s);
|
||||
for (n = 0; n < 1000000 / 40; n++)
|
||||
SHA512_Bytes(&s, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
40);
|
||||
SHA512_Final(&s, digest);
|
||||
}
|
||||
for (j = 0; j < 64; j++) {
|
||||
if (digest[j] != tests[i].digest512[j]) {
|
||||
fprintf(stderr,
|
||||
"\"%s\" digest512 byte %d should be 0x%02x, is 0x%02x\n",
|
||||
tests[i].teststring, j, tests[i].digest512[j],
|
||||
digest[j]);
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
printf("%d errors\n", errors);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
363
sFTPlugins/psftp/SSHSHA.C
Normal file
363
sFTPlugins/psftp/SSHSHA.C
Normal file
@@ -0,0 +1,363 @@
|
||||
/*
|
||||
* SHA1 hash algorithm. Used in SSH-2 as a MAC, and the transform is
|
||||
* also used as a `stirring' function for the PuTTY random number
|
||||
* pool. Implemented directly from the specification by Simon
|
||||
* Tatham.
|
||||
*/
|
||||
|
||||
#include "ssh.h"
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* Core SHA algorithm: processes 16-word blocks into a message digest.
|
||||
*/
|
||||
|
||||
#define rol(x,y) ( ((x) << (y)) | (((uint32)x) >> (32-y)) )
|
||||
|
||||
static void SHA_Core_Init(uint32 h[5])
|
||||
{
|
||||
h[0] = 0x67452301;
|
||||
h[1] = 0xefcdab89;
|
||||
h[2] = 0x98badcfe;
|
||||
h[3] = 0x10325476;
|
||||
h[4] = 0xc3d2e1f0;
|
||||
}
|
||||
|
||||
void SHATransform(word32 * digest, word32 * block)
|
||||
{
|
||||
word32 w[80];
|
||||
word32 a, b, c, d, e;
|
||||
int t;
|
||||
|
||||
for (t = 0; t < 16; t++)
|
||||
w[t] = block[t];
|
||||
|
||||
for (t = 16; t < 80; t++) {
|
||||
word32 tmp = w[t - 3] ^ w[t - 8] ^ w[t - 14] ^ w[t - 16];
|
||||
w[t] = rol(tmp, 1);
|
||||
}
|
||||
|
||||
a = digest[0];
|
||||
b = digest[1];
|
||||
c = digest[2];
|
||||
d = digest[3];
|
||||
e = digest[4];
|
||||
|
||||
for (t = 0; t < 20; t++) {
|
||||
word32 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++) {
|
||||
word32 tmp = rol(a, 5) + (b ^ c ^ d) + e + w[t] + 0x6ed9eba1;
|
||||
e = d;
|
||||
d = c;
|
||||
c = rol(b, 30);
|
||||
b = a;
|
||||
a = tmp;
|
||||
}
|
||||
for (t = 40; t < 60; t++) {
|
||||
word32 tmp = rol(a,
|
||||
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++) {
|
||||
word32 tmp = rol(a, 5) + (b ^ c ^ d) + e + w[t] + 0xca62c1d6;
|
||||
e = d;
|
||||
d = c;
|
||||
c = rol(b, 30);
|
||||
b = a;
|
||||
a = tmp;
|
||||
}
|
||||
|
||||
digest[0] += a;
|
||||
digest[1] += b;
|
||||
digest[2] += c;
|
||||
digest[3] += d;
|
||||
digest[4] += e;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* Outer SHA algorithm: take an arbitrary length byte string,
|
||||
* convert it into 16-word blocks with the prescribed padding at
|
||||
* the end, and pass those blocks to the core SHA algorithm.
|
||||
*/
|
||||
|
||||
void SHA_Init(SHA_State * s)
|
||||
{
|
||||
SHA_Core_Init(s->h);
|
||||
s->blkused = 0;
|
||||
s->lenhi = s->lenlo = 0;
|
||||
}
|
||||
|
||||
void SHA_Bytes(SHA_State * s, void *p, int len)
|
||||
{
|
||||
unsigned char *q = (unsigned char *) p;
|
||||
uint32 wordblock[16];
|
||||
uint32 lenw = len;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Update the length field.
|
||||
*/
|
||||
s->lenlo += lenw;
|
||||
s->lenhi += (s->lenlo < lenw);
|
||||
|
||||
if (s->blkused && s->blkused + len < 64) {
|
||||
/*
|
||||
* Trivial case: just add to the block.
|
||||
*/
|
||||
memcpy(s->block + s->blkused, q, len);
|
||||
s->blkused += len;
|
||||
} else {
|
||||
/*
|
||||
* We must complete and process at least one block.
|
||||
*/
|
||||
while (s->blkused + len >= 64) {
|
||||
memcpy(s->block + s->blkused, q, 64 - s->blkused);
|
||||
q += 64 - s->blkused;
|
||||
len -= 64 - s->blkused;
|
||||
/* Now process the block. Gather bytes big-endian into words */
|
||||
for (i = 0; i < 16; i++) {
|
||||
wordblock[i] =
|
||||
(((uint32) s->block[i * 4 + 0]) << 24) |
|
||||
(((uint32) s->block[i * 4 + 1]) << 16) |
|
||||
(((uint32) s->block[i * 4 + 2]) << 8) |
|
||||
(((uint32) s->block[i * 4 + 3]) << 0);
|
||||
}
|
||||
SHATransform(s->h, wordblock);
|
||||
s->blkused = 0;
|
||||
}
|
||||
memcpy(s->block, q, len);
|
||||
s->blkused = len;
|
||||
}
|
||||
}
|
||||
|
||||
void SHA_Final(SHA_State * s, unsigned char *output)
|
||||
{
|
||||
int i;
|
||||
int pad;
|
||||
unsigned char c[64];
|
||||
uint32 lenhi, lenlo;
|
||||
|
||||
if (s->blkused >= 56)
|
||||
pad = 56 + 64 - s->blkused;
|
||||
else
|
||||
pad = 56 - s->blkused;
|
||||
|
||||
lenhi = (s->lenhi << 3) | (s->lenlo >> (32 - 3));
|
||||
lenlo = (s->lenlo << 3);
|
||||
|
||||
memset(c, 0, pad);
|
||||
c[0] = 0x80;
|
||||
SHA_Bytes(s, &c, pad);
|
||||
|
||||
c[0] = (lenhi >> 24) & 0xFF;
|
||||
c[1] = (lenhi >> 16) & 0xFF;
|
||||
c[2] = (lenhi >> 8) & 0xFF;
|
||||
c[3] = (lenhi >> 0) & 0xFF;
|
||||
c[4] = (lenlo >> 24) & 0xFF;
|
||||
c[5] = (lenlo >> 16) & 0xFF;
|
||||
c[6] = (lenlo >> 8) & 0xFF;
|
||||
c[7] = (lenlo >> 0) & 0xFF;
|
||||
|
||||
SHA_Bytes(s, &c, 8);
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
output[i * 4] = (s->h[i] >> 24) & 0xFF;
|
||||
output[i * 4 + 1] = (s->h[i] >> 16) & 0xFF;
|
||||
output[i * 4 + 2] = (s->h[i] >> 8) & 0xFF;
|
||||
output[i * 4 + 3] = (s->h[i]) & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
void SHA_Simple(void *p, int len, unsigned char *output)
|
||||
{
|
||||
SHA_State s;
|
||||
|
||||
SHA_Init(&s);
|
||||
SHA_Bytes(&s, p, len);
|
||||
SHA_Final(&s, output);
|
||||
}
|
||||
|
||||
/*
|
||||
* Thin abstraction for things where hashes are pluggable.
|
||||
*/
|
||||
|
||||
static void *sha1_init(void)
|
||||
{
|
||||
SHA_State *s;
|
||||
|
||||
s = snew(SHA_State);
|
||||
SHA_Init(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
static void sha1_bytes(void *handle, void *p, int len)
|
||||
{
|
||||
SHA_State *s = handle;
|
||||
|
||||
SHA_Bytes(s, p, len);
|
||||
}
|
||||
|
||||
static void sha1_final(void *handle, unsigned char *output)
|
||||
{
|
||||
SHA_State *s = handle;
|
||||
|
||||
SHA_Final(s, output);
|
||||
sfree(s);
|
||||
}
|
||||
|
||||
const struct ssh_hash ssh_sha1 = {
|
||||
sha1_init, sha1_bytes, sha1_final, 20, "SHA-1"
|
||||
};
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* The above is the SHA-1 algorithm itself. Now we implement the
|
||||
* HMAC wrapper on it.
|
||||
*/
|
||||
|
||||
static void *sha1_make_context(void)
|
||||
{
|
||||
return snewn(2, SHA_State);
|
||||
}
|
||||
|
||||
static void sha1_free_context(void *handle)
|
||||
{
|
||||
sfree(handle);
|
||||
}
|
||||
|
||||
static void sha1_key_internal(void *handle, unsigned char *key, int len)
|
||||
{
|
||||
SHA_State *keys = (SHA_State *)handle;
|
||||
unsigned char foo[64];
|
||||
int i;
|
||||
|
||||
memset(foo, 0x36, 64);
|
||||
for (i = 0; i < len && i < 64; i++)
|
||||
foo[i] ^= key[i];
|
||||
SHA_Init(&keys[0]);
|
||||
SHA_Bytes(&keys[0], foo, 64);
|
||||
|
||||
memset(foo, 0x5C, 64);
|
||||
for (i = 0; i < len && i < 64; i++)
|
||||
foo[i] ^= key[i];
|
||||
SHA_Init(&keys[1]);
|
||||
SHA_Bytes(&keys[1], foo, 64);
|
||||
|
||||
memset(foo, 0, 64); /* burn the evidence */
|
||||
}
|
||||
|
||||
static void sha1_key(void *handle, unsigned char *key)
|
||||
{
|
||||
sha1_key_internal(handle, key, 20);
|
||||
}
|
||||
|
||||
static void sha1_key_buggy(void *handle, unsigned char *key)
|
||||
{
|
||||
sha1_key_internal(handle, key, 16);
|
||||
}
|
||||
|
||||
static void sha1_do_hmac(void *handle, unsigned char *blk, int len,
|
||||
unsigned long seq, unsigned char *hmac)
|
||||
{
|
||||
SHA_State *keys = (SHA_State *)handle;
|
||||
SHA_State s;
|
||||
unsigned char intermediate[20];
|
||||
|
||||
intermediate[0] = (unsigned char) ((seq >> 24) & 0xFF);
|
||||
intermediate[1] = (unsigned char) ((seq >> 16) & 0xFF);
|
||||
intermediate[2] = (unsigned char) ((seq >> 8) & 0xFF);
|
||||
intermediate[3] = (unsigned char) ((seq) & 0xFF);
|
||||
|
||||
s = keys[0]; /* structure copy */
|
||||
SHA_Bytes(&s, intermediate, 4);
|
||||
SHA_Bytes(&s, blk, len);
|
||||
SHA_Final(&s, intermediate);
|
||||
s = keys[1]; /* structure copy */
|
||||
SHA_Bytes(&s, intermediate, 20);
|
||||
SHA_Final(&s, hmac);
|
||||
}
|
||||
|
||||
static void sha1_generate(void *handle, unsigned char *blk, int len,
|
||||
unsigned long seq)
|
||||
{
|
||||
sha1_do_hmac(handle, blk, len, seq, blk + len);
|
||||
}
|
||||
|
||||
static int sha1_verify(void *handle, unsigned char *blk, int len,
|
||||
unsigned long seq)
|
||||
{
|
||||
unsigned char correct[20];
|
||||
sha1_do_hmac(handle, blk, len, seq, correct);
|
||||
return !memcmp(correct, blk + len, 20);
|
||||
}
|
||||
|
||||
static void sha1_96_generate(void *handle, unsigned char *blk, int len,
|
||||
unsigned long seq)
|
||||
{
|
||||
unsigned char full[20];
|
||||
sha1_do_hmac(handle, blk, len, seq, full);
|
||||
memcpy(blk + len, full, 12);
|
||||
}
|
||||
|
||||
static int sha1_96_verify(void *handle, unsigned char *blk, int len,
|
||||
unsigned long seq)
|
||||
{
|
||||
unsigned char correct[20];
|
||||
sha1_do_hmac(handle, blk, len, seq, correct);
|
||||
return !memcmp(correct, blk + len, 12);
|
||||
}
|
||||
|
||||
void hmac_sha1_simple(void *key, int keylen, void *data, int datalen,
|
||||
unsigned char *output) {
|
||||
SHA_State states[2];
|
||||
unsigned char intermediate[20];
|
||||
|
||||
sha1_key_internal(states, key, keylen);
|
||||
SHA_Bytes(&states[0], data, datalen);
|
||||
SHA_Final(&states[0], intermediate);
|
||||
|
||||
SHA_Bytes(&states[1], intermediate, 20);
|
||||
SHA_Final(&states[1], output);
|
||||
}
|
||||
|
||||
const struct ssh_mac ssh_hmac_sha1 = {
|
||||
sha1_make_context, sha1_free_context, sha1_key,
|
||||
sha1_generate, sha1_verify,
|
||||
"hmac-sha1",
|
||||
20,
|
||||
"HMAC-SHA1"
|
||||
};
|
||||
|
||||
const struct ssh_mac ssh_hmac_sha1_96 = {
|
||||
sha1_make_context, sha1_free_context, sha1_key,
|
||||
sha1_96_generate, sha1_96_verify,
|
||||
"hmac-sha1-96",
|
||||
12,
|
||||
"HMAC-SHA1-96"
|
||||
};
|
||||
|
||||
const struct ssh_mac ssh_hmac_sha1_buggy = {
|
||||
sha1_make_context, sha1_free_context, sha1_key_buggy,
|
||||
sha1_generate, sha1_verify,
|
||||
"hmac-sha1",
|
||||
20,
|
||||
"bug-compatible HMAC-SHA1"
|
||||
};
|
||||
|
||||
const struct ssh_mac ssh_hmac_sha1_96_buggy = {
|
||||
sha1_make_context, sha1_free_context, sha1_key_buggy,
|
||||
sha1_96_generate, sha1_96_verify,
|
||||
"hmac-sha1-96",
|
||||
12,
|
||||
"bug-compatible HMAC-SHA1-96"
|
||||
};
|
||||
1382
sFTPlugins/psftp/SSHZLIB.C
Normal file
1382
sFTPlugins/psftp/SSHZLIB.C
Normal file
File diff suppressed because it is too large
Load Diff
115
sFTPlugins/psftp/STORAGE.H
Normal file
115
sFTPlugins/psftp/STORAGE.H
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* storage.h: interface defining functions for storage and recovery
|
||||
* of PuTTY's persistent data.
|
||||
*/
|
||||
|
||||
#ifndef PUTTY_STORAGE_H
|
||||
#define PUTTY_STORAGE_H
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* Functions to save and restore PuTTY sessions. Note that this is
|
||||
* only the low-level code to do the reading and writing. The
|
||||
* higher-level code that translates a Config structure into a set
|
||||
* of (key,value) pairs is elsewhere, since it doesn't (mostly)
|
||||
* change between platforms.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Write a saved session. The caller is expected to call
|
||||
* open_setting_w() to get a `void *' handle, then pass that to a
|
||||
* number of calls to write_setting_s() and write_setting_i(), and
|
||||
* then close it using close_settings_w(). At the end of this call
|
||||
* sequence the settings should have been written to the PuTTY
|
||||
* persistent storage area.
|
||||
*
|
||||
* A given key will be written at most once while saving a session.
|
||||
* Keys may be up to 255 characters long. String values have no length
|
||||
* limit.
|
||||
*
|
||||
* Any returned error message must be freed after use.
|
||||
*/
|
||||
void *open_settings_w(const char *sessionname, char **errmsg);
|
||||
void write_setting_s(void *handle, const char *key, const char *value);
|
||||
void write_setting_i(void *handle, const char *key, int value);
|
||||
void write_setting_filename(void *handle, const char *key, Filename value);
|
||||
void write_setting_fontspec(void *handle, const char *key, FontSpec font);
|
||||
void close_settings_w(void *handle);
|
||||
|
||||
/*
|
||||
* Read a saved session. The caller is expected to call
|
||||
* open_setting_r() to get a `void *' handle, then pass that to a
|
||||
* number of calls to read_setting_s() and read_setting_i(), and
|
||||
* then close it using close_settings_r().
|
||||
*
|
||||
* read_setting_s() writes into the provided buffer and returns a
|
||||
* pointer to the same buffer.
|
||||
*
|
||||
* If a particular string setting is not present in the session,
|
||||
* read_setting_s() can return NULL, in which case the caller
|
||||
* should invent a sensible default. If an integer setting is not
|
||||
* present, read_setting_i() returns its provided default.
|
||||
*
|
||||
* read_setting_filename() and read_setting_fontspec() each read into
|
||||
* the provided buffer, and return zero if they failed to.
|
||||
*/
|
||||
void *open_settings_r(const char *sessionname);
|
||||
char *read_setting_s(void *handle, const char *key, char *buffer, int buflen);
|
||||
int read_setting_i(void *handle, const char *key, int defvalue);
|
||||
int read_setting_filename(void *handle, const char *key, Filename *value);
|
||||
int read_setting_fontspec(void *handle, const char *key, FontSpec *font);
|
||||
void close_settings_r(void *handle);
|
||||
|
||||
/*
|
||||
* Delete a whole saved session.
|
||||
*/
|
||||
void del_settings(const char *sessionname);
|
||||
|
||||
/*
|
||||
* Enumerate all saved sessions.
|
||||
*/
|
||||
void *enum_settings_start(void);
|
||||
char *enum_settings_next(void *handle, char *buffer, int buflen);
|
||||
void enum_settings_finish(void *handle);
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* Functions to access PuTTY's host key database.
|
||||
*/
|
||||
|
||||
/*
|
||||
* See if a host key matches the database entry. Return values can
|
||||
* be 0 (entry matches database), 1 (entry is absent in database),
|
||||
* or 2 (entry exists in database and is different).
|
||||
*/
|
||||
int verify_host_key(const char *hostname, int port,
|
||||
const char *keytype, const char *key);
|
||||
|
||||
/*
|
||||
* Write a host key into the database, overwriting any previous
|
||||
* entry that might have been there.
|
||||
*/
|
||||
void store_host_key(const char *hostname, int port,
|
||||
const char *keytype, const char *key);
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* Functions to access PuTTY's random number seed file.
|
||||
*/
|
||||
|
||||
typedef void (*noise_consumer_t) (void *data, int len);
|
||||
|
||||
/*
|
||||
* Read PuTTY's random seed file and pass its contents to a noise
|
||||
* consumer function.
|
||||
*/
|
||||
void read_random_seed(noise_consumer_t consumer);
|
||||
|
||||
/*
|
||||
* Write PuTTY's random seed file from a given chunk of noise.
|
||||
*/
|
||||
void write_random_seed(void *data, int len);
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* Cleanup function: remove all of PuTTY's persistent state.
|
||||
*/
|
||||
void cleanup_all(void);
|
||||
|
||||
#endif
|
||||
243
sFTPlugins/psftp/TIMING.C
Normal file
243
sFTPlugins/psftp/TIMING.C
Normal file
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
* timing.c
|
||||
*
|
||||
* This module tracks any timers set up by schedule_timer(). It
|
||||
* keeps all the currently active timers in a list; it informs the
|
||||
* front end of when the next timer is due to go off if that
|
||||
* changes; and, very importantly, it tracks the context pointers
|
||||
* passed to schedule_timer(), so that if a context is freed all
|
||||
* the timers associated with it can be immediately annulled.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "putty.h"
|
||||
#include "tree234.h"
|
||||
|
||||
struct timer {
|
||||
timer_fn_t fn;
|
||||
void *ctx;
|
||||
long now;
|
||||
};
|
||||
|
||||
static tree234 *timers = NULL;
|
||||
static tree234 *timer_contexts = NULL;
|
||||
static long now = 0L;
|
||||
|
||||
static int compare_timers(void *av, void *bv)
|
||||
{
|
||||
struct timer *a = (struct timer *)av;
|
||||
struct timer *b = (struct timer *)bv;
|
||||
long at = a->now - now;
|
||||
long bt = b->now - now;
|
||||
|
||||
if (at < bt)
|
||||
return -1;
|
||||
else if (at > bt)
|
||||
return +1;
|
||||
|
||||
/*
|
||||
* Failing that, compare on the other two fields, just so that
|
||||
* we don't get unwanted equality.
|
||||
*/
|
||||
#ifdef __LCC__
|
||||
/* lcc won't let us compare function pointers. Legal, but annoying. */
|
||||
{
|
||||
int c = memcmp(&a->fn, &b->fn, sizeof(a->fn));
|
||||
if (c < 0)
|
||||
return -1;
|
||||
else if (c > 0)
|
||||
return +1;
|
||||
}
|
||||
#else
|
||||
if (a->fn < b->fn)
|
||||
return -1;
|
||||
else if (a->fn > b->fn)
|
||||
return +1;
|
||||
#endif
|
||||
|
||||
if (a->ctx < b->ctx)
|
||||
return -1;
|
||||
else if (a->ctx > b->ctx)
|
||||
return +1;
|
||||
|
||||
/*
|
||||
* Failing _that_, the two entries genuinely are equal, and we
|
||||
* never have a need to store them separately in the tree.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int compare_timer_contexts(void *av, void *bv)
|
||||
{
|
||||
char *a = (char *)av;
|
||||
char *b = (char *)bv;
|
||||
if (a < b)
|
||||
return -1;
|
||||
else if (a > b)
|
||||
return +1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void init_timers(void)
|
||||
{
|
||||
if (!timers) {
|
||||
timers = newtree234(compare_timers);
|
||||
timer_contexts = newtree234(compare_timer_contexts);
|
||||
now = GETTICKCOUNT();
|
||||
}
|
||||
}
|
||||
|
||||
long schedule_timer(int ticks, timer_fn_t fn, void *ctx)
|
||||
{
|
||||
long when;
|
||||
struct timer *t, *first;
|
||||
|
||||
init_timers();
|
||||
|
||||
when = ticks + GETTICKCOUNT();
|
||||
|
||||
/*
|
||||
* Just in case our various defences against timing skew fail
|
||||
* us: if we try to schedule a timer that's already in the
|
||||
* past, we instead schedule it for the immediate future.
|
||||
*/
|
||||
if (when - now <= 0)
|
||||
when = now + 1;
|
||||
|
||||
t = snew(struct timer);
|
||||
t->fn = fn;
|
||||
t->ctx = ctx;
|
||||
t->now = when;
|
||||
|
||||
if (t != add234(timers, t)) {
|
||||
sfree(t); /* identical timer already exists */
|
||||
} else {
|
||||
add234(timer_contexts, t->ctx);/* don't care if this fails */
|
||||
}
|
||||
|
||||
first = (struct timer *)index234(timers, 0);
|
||||
if (first == t) {
|
||||
/*
|
||||
* This timer is the very first on the list, so we must
|
||||
* notify the front end.
|
||||
*/
|
||||
timer_change_notify(first->now);
|
||||
}
|
||||
|
||||
return when;
|
||||
}
|
||||
|
||||
/*
|
||||
* Call to run any timers whose time has reached the present.
|
||||
* Returns the time (in ticks) expected until the next timer after
|
||||
* that triggers.
|
||||
*/
|
||||
int run_timers(long anow, long *next)
|
||||
{
|
||||
struct timer *first;
|
||||
|
||||
init_timers();
|
||||
|
||||
#ifdef TIMING_SYNC
|
||||
/*
|
||||
* In this ifdef I put some code which deals with the
|
||||
* possibility that `anow' disagrees with GETTICKCOUNT by a
|
||||
* significant margin. Our strategy for dealing with it differs
|
||||
* depending on platform, because on some platforms
|
||||
* GETTICKCOUNT is more likely to be right whereas on others
|
||||
* `anow' is a better gold standard.
|
||||
*/
|
||||
{
|
||||
long tnow = GETTICKCOUNT();
|
||||
|
||||
if (tnow + TICKSPERSEC/50 - anow < 0 ||
|
||||
anow + TICKSPERSEC/50 - tnow < 0
|
||||
) {
|
||||
#if defined TIMING_SYNC_ANOW
|
||||
/*
|
||||
* If anow is accurate and the tick count is wrong,
|
||||
* this is likely to be because the tick count is
|
||||
* derived from the system clock which has changed (as
|
||||
* can occur on Unix). Therefore, we resolve this by
|
||||
* inventing an offset which is used to adjust all
|
||||
* future output from GETTICKCOUNT.
|
||||
*
|
||||
* A platform which defines TIMING_SYNC_ANOW is
|
||||
* expected to have also defined this offset variable
|
||||
* in (its platform-specific adjunct to) putty.h.
|
||||
* Therefore we can simply reference it here and assume
|
||||
* that it will exist.
|
||||
*/
|
||||
tickcount_offset += anow - tnow;
|
||||
#elif defined TIMING_SYNC_TICKCOUNT
|
||||
/*
|
||||
* If the tick count is more likely to be accurate, we
|
||||
* simply use that as our time value, which may mean we
|
||||
* run no timers in this call (because we got called
|
||||
* early), or alternatively it may mean we run lots of
|
||||
* timers in a hurry because we were called late.
|
||||
*/
|
||||
anow = tnow;
|
||||
#else
|
||||
/*
|
||||
* Any platform which defines TIMING_SYNC must also define one of the two
|
||||
* auxiliary symbols TIMING_SYNC_ANOW and TIMING_SYNC_TICKCOUNT, to
|
||||
* indicate which measurement to trust when the two disagree.
|
||||
*/
|
||||
#error TIMING_SYNC definition incomplete
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
now = anow;
|
||||
|
||||
while (1) {
|
||||
first = (struct timer *)index234(timers, 0);
|
||||
|
||||
if (!first)
|
||||
return FALSE; /* no timers remaining */
|
||||
|
||||
if (find234(timer_contexts, first->ctx, NULL) == NULL) {
|
||||
/*
|
||||
* This timer belongs to a context that has been
|
||||
* expired. Delete it without running.
|
||||
*/
|
||||
delpos234(timers, 0);
|
||||
sfree(first);
|
||||
} else if (first->now - now <= 0) {
|
||||
/*
|
||||
* This timer is active and has reached its running
|
||||
* time. Run it.
|
||||
*/
|
||||
delpos234(timers, 0);
|
||||
first->fn(first->ctx, first->now);
|
||||
sfree(first);
|
||||
} else {
|
||||
/*
|
||||
* This is the first still-active timer that is in the
|
||||
* future. Return how long it has yet to go.
|
||||
*/
|
||||
*next = first->now;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Call to expire all timers associated with a given context.
|
||||
*/
|
||||
void expire_timer_context(void *ctx)
|
||||
{
|
||||
init_timers();
|
||||
|
||||
/*
|
||||
* We don't bother to check the return value; if the context
|
||||
* already wasn't in the tree (presumably because no timers
|
||||
* ever actually got scheduled for it) then that's fine and we
|
||||
* simply don't need to do anything.
|
||||
*/
|
||||
del234(timer_contexts, ctx);
|
||||
}
|
||||
1479
sFTPlugins/psftp/TREE234.C
Normal file
1479
sFTPlugins/psftp/TREE234.C
Normal file
File diff suppressed because it is too large
Load Diff
160
sFTPlugins/psftp/TREE234.H
Normal file
160
sFTPlugins/psftp/TREE234.H
Normal file
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* tree234.h: header defining functions in tree234.c.
|
||||
*
|
||||
* This file is copyright 1999-2001 Simon Tatham.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL SIMON TATHAM BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef TREE234_H
|
||||
#define TREE234_H
|
||||
|
||||
/*
|
||||
* This typedef is opaque outside tree234.c itself.
|
||||
*/
|
||||
typedef struct tree234_Tag tree234;
|
||||
|
||||
typedef int (*cmpfn234) (void *, void *);
|
||||
|
||||
/*
|
||||
* Create a 2-3-4 tree. If `cmp' is NULL, the tree is unsorted, and
|
||||
* lookups by key will fail: you can only look things up by numeric
|
||||
* index, and you have to use addpos234() and delpos234().
|
||||
*/
|
||||
tree234 *newtree234(cmpfn234 cmp);
|
||||
|
||||
/*
|
||||
* Free a 2-3-4 tree (not including freeing the elements).
|
||||
*/
|
||||
void freetree234(tree234 * t);
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
void *add234(tree234 * t, void *e);
|
||||
|
||||
/*
|
||||
* Add an element e to an unsorted 2-3-4 tree t. Returns e on
|
||||
* success, NULL on failure. (Failure should only occur if the
|
||||
* index is out of range or the tree is sorted.)
|
||||
*
|
||||
* Index range can be from 0 to the tree's current element count,
|
||||
* inclusive.
|
||||
*/
|
||||
void *addpos234(tree234 * t, void *e, int index);
|
||||
|
||||
/*
|
||||
* Look up the element at a given numeric index in a 2-3-4 tree.
|
||||
* Returns NULL if the index is out of range.
|
||||
*
|
||||
* One obvious use for this function is in iterating over the whole
|
||||
* of a tree (sorted or unsorted):
|
||||
*
|
||||
* for (i = 0; (p = index234(tree, i)) != NULL; i++) consume(p);
|
||||
*
|
||||
* or
|
||||
*
|
||||
* int maxcount = count234(tree);
|
||||
* for (i = 0; i < maxcount; i++) {
|
||||
* p = index234(tree, i);
|
||||
* assert(p != NULL);
|
||||
* consume(p);
|
||||
* }
|
||||
*/
|
||||
void *index234(tree234 * t, int index);
|
||||
|
||||
/*
|
||||
* Find an element e in a sorted 2-3-4 tree t. Returns NULL if not
|
||||
* found. e is always passed as the first argument to cmp, so cmp
|
||||
* can be an asymmetric function if desired. cmp can also be passed
|
||||
* as NULL, in which case the compare function from the tree proper
|
||||
* will be used.
|
||||
*
|
||||
* Three of these functions are special cases of findrelpos234. The
|
||||
* non-`pos' variants lack the `index' parameter: if the parameter
|
||||
* is present and non-NULL, it must point to an integer variable
|
||||
* which will be filled with the numeric index of the returned
|
||||
* element.
|
||||
*
|
||||
* The non-`rel' variants lack the `relation' parameter. This
|
||||
* parameter allows you to specify what relation the element you
|
||||
* provide has to the element you're looking for. This parameter
|
||||
* can be:
|
||||
*
|
||||
* REL234_EQ - find only an element that compares equal to e
|
||||
* REL234_LT - find the greatest element that compares < e
|
||||
* REL234_LE - find the greatest element that compares <= e
|
||||
* REL234_GT - find the smallest element that compares > e
|
||||
* REL234_GE - find the smallest element that compares >= e
|
||||
*
|
||||
* Non-`rel' variants assume REL234_EQ.
|
||||
*
|
||||
* If `rel' is REL234_GT or REL234_LT, the `e' parameter may be
|
||||
* NULL. In this case, REL234_GT will return the smallest element
|
||||
* in the tree, and REL234_LT will return the greatest. This gives
|
||||
* an alternative means of iterating over a sorted tree, instead of
|
||||
* using index234:
|
||||
*
|
||||
* // to loop forwards
|
||||
* for (p = NULL; (p = findrel234(tree, p, NULL, REL234_GT)) != NULL ;)
|
||||
* consume(p);
|
||||
*
|
||||
* // to loop backwards
|
||||
* for (p = NULL; (p = findrel234(tree, p, NULL, REL234_LT)) != NULL ;)
|
||||
* consume(p);
|
||||
*/
|
||||
enum {
|
||||
REL234_EQ, REL234_LT, REL234_LE, REL234_GT, REL234_GE
|
||||
};
|
||||
void *find234(tree234 * t, void *e, cmpfn234 cmp);
|
||||
void *findrel234(tree234 * t, void *e, cmpfn234 cmp, int relation);
|
||||
void *findpos234(tree234 * t, void *e, cmpfn234 cmp, int *index);
|
||||
void *findrelpos234(tree234 * t, void *e, cmpfn234 cmp, int relation,
|
||||
int *index);
|
||||
|
||||
/*
|
||||
* Delete an element e in a 2-3-4 tree. Does not free the element,
|
||||
* merely removes all links to it from the tree nodes.
|
||||
*
|
||||
* delpos234 deletes the element at a particular tree index: it
|
||||
* works on both sorted and unsorted trees.
|
||||
*
|
||||
* del234 deletes the element passed to it, so it only works on
|
||||
* sorted trees. (It's equivalent to using findpos234 to determine
|
||||
* the index of an element, and then passing that index to
|
||||
* delpos234.)
|
||||
*
|
||||
* Both functions return a pointer to the element they delete, for
|
||||
* the user to free or pass on elsewhere or whatever. If the index
|
||||
* is out of range (delpos234) or the element is already not in the
|
||||
* tree (del234) then they return NULL.
|
||||
*/
|
||||
void *del234(tree234 * t, void *e);
|
||||
void *delpos234(tree234 * t, int index);
|
||||
|
||||
/*
|
||||
* Return the total element count of a tree234.
|
||||
*/
|
||||
int count234(tree234 * t);
|
||||
|
||||
#endif /* TREE234_H */
|
||||
160
sFTPlugins/psftp/UNIX/UNIX.H
Normal file
160
sFTPlugins/psftp/UNIX/UNIX.H
Normal file
@@ -0,0 +1,160 @@
|
||||
#ifndef PUTTY_UNIX_H
|
||||
#define PUTTY_UNIX_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "uxconfig.h" /* Space to hide it from mkfiles.pl */
|
||||
#endif
|
||||
|
||||
#include <stdio.h> /* for FILENAME_MAX */
|
||||
#include "charset.h"
|
||||
|
||||
struct Filename {
|
||||
char path[FILENAME_MAX];
|
||||
};
|
||||
FILE *f_open(struct Filename, char const *, int);
|
||||
|
||||
struct FontSpec {
|
||||
char name[256];
|
||||
};
|
||||
|
||||
typedef void *Context; /* FIXME: probably needs changing */
|
||||
|
||||
typedef int OSSocket;
|
||||
#define OSSOCKET_DEFINED /* stop network.h using its default */
|
||||
|
||||
extern Backend pty_backend;
|
||||
|
||||
/*
|
||||
* Under GTK, we send MA_CLICK _and_ MA_2CLK, or MA_CLICK _and_
|
||||
* MA_3CLK, when a button is pressed for the second or third time.
|
||||
*/
|
||||
#define MULTICLICK_ONLY_EVENT 0
|
||||
|
||||
/*
|
||||
* Under GTK, there is no context help available.
|
||||
*/
|
||||
#define HELPCTX(x) P(NULL)
|
||||
#define FILTER_KEY_FILES NULL /* FIXME */
|
||||
|
||||
/*
|
||||
* Under X, selection data must not be NUL-terminated.
|
||||
*/
|
||||
#define SELECTION_NUL_TERMINATED 0
|
||||
|
||||
/*
|
||||
* Under X, copying to the clipboard terminates lines with just LF.
|
||||
*/
|
||||
#define SEL_NL { 10 }
|
||||
|
||||
/* Simple wraparound timer function */
|
||||
unsigned long getticks(void); /* based on gettimeofday(2) */
|
||||
#define GETTICKCOUNT getticks
|
||||
#define TICKSPERSEC 1000 /* we choose to use milliseconds */
|
||||
#define CURSORBLINK 450 /* no standard way to set this */
|
||||
/* getticks() works using gettimeofday(), so it's vulnerable to system clock
|
||||
* changes causing chaos. Therefore, we provide a compensation mechanism. */
|
||||
#define TIMING_SYNC
|
||||
#define TIMING_SYNC_ANOW
|
||||
extern long tickcount_offset;
|
||||
|
||||
#define WCHAR wchar_t
|
||||
#define BYTE unsigned char
|
||||
|
||||
/* Things pty.c needs from pterm.c */
|
||||
char *get_x_display(void *frontend);
|
||||
int font_dimension(void *frontend, int which);/* 0 for width, 1 for height */
|
||||
long get_windowid(void *frontend);
|
||||
|
||||
/* Things gtkdlg.c needs from pterm.c */
|
||||
void *get_window(void *frontend); /* void * to avoid depending on gtk.h */
|
||||
|
||||
/* Things pterm.c needs from gtkdlg.c */
|
||||
int do_config_box(const char *title, Config *cfg,
|
||||
int midsession, int protcfginfo);
|
||||
void fatal_message_box(void *window, char *msg);
|
||||
void about_box(void *window);
|
||||
void *eventlogstuff_new(void);
|
||||
void showeventlog(void *estuff, void *parentwin);
|
||||
void logevent_dlg(void *estuff, const char *string);
|
||||
int reallyclose(void *frontend);
|
||||
|
||||
/* Things pterm.c needs from {ptermm,uxputty}.c */
|
||||
char *make_default_wintitle(char *hostname);
|
||||
int process_nonoption_arg(char *arg, Config *cfg, int *allow_launch);
|
||||
|
||||
/* pterm.c needs this special function in xkeysym.c */
|
||||
int keysym_to_unicode(int keysym);
|
||||
|
||||
/* Things uxstore.c needs from pterm.c */
|
||||
char *x_get_default(const char *key);
|
||||
|
||||
/* Things uxstore.c provides to pterm.c */
|
||||
void provide_xrm_string(char *string);
|
||||
|
||||
/* The interface used by uxsel.c */
|
||||
void uxsel_init(void);
|
||||
typedef int (*uxsel_callback_fn)(int fd, int event);
|
||||
void uxsel_set(int fd, int rwx, uxsel_callback_fn callback);
|
||||
void uxsel_del(int fd);
|
||||
int select_result(int fd, int event);
|
||||
int first_fd(int *state, int *rwx);
|
||||
int next_fd(int *state, int *rwx);
|
||||
/* The following are expected to be provided _to_ uxsel.c by the frontend */
|
||||
int uxsel_input_add(int fd, int rwx); /* returns an id */
|
||||
void uxsel_input_remove(int id);
|
||||
|
||||
/* uxcfg.c */
|
||||
struct controlbox;
|
||||
void unix_setup_config_box(struct controlbox *b, int midsession, int protocol);
|
||||
|
||||
/* gtkcfg.c */
|
||||
void gtk_setup_config_box(struct controlbox *b, int midsession, void *window);
|
||||
|
||||
/*
|
||||
* In the Unix Unicode layer, DEFAULT_CODEPAGE is a special value
|
||||
* which causes mb_to_wc and wc_to_mb to call _libc_ rather than
|
||||
* libcharset. That way, we can interface the various charsets
|
||||
* supported by libcharset with the one supported by mbstowcs and
|
||||
* wcstombs (which will be the character set in which stuff read
|
||||
* from the command line or config files is assumed to be encoded).
|
||||
*/
|
||||
#define DEFAULT_CODEPAGE 0xFFFF
|
||||
#define CP_UTF8 CS_UTF8 /* from libcharset */
|
||||
|
||||
#define strnicmp strncasecmp
|
||||
#define stricmp strcasecmp
|
||||
|
||||
/* BSD-semantics version of signal(), and another helpful function */
|
||||
void (*putty_signal(int sig, void (*func)(int)))(int);
|
||||
void block_signal(int sig, int block_it);
|
||||
|
||||
/* uxmisc.c */
|
||||
int cloexec(int);
|
||||
|
||||
/*
|
||||
* Exports from unicode.c.
|
||||
*/
|
||||
struct unicode_data;
|
||||
int init_ucs(struct unicode_data *ucsdata, char *line_codepage,
|
||||
int utf8_override, int font_charset, int vtmode);
|
||||
|
||||
/*
|
||||
* Spare function exported directly from uxnet.c.
|
||||
*/
|
||||
void *sk_getxdmdata(void *sock, int *lenp);
|
||||
|
||||
/*
|
||||
* General helpful Unix stuff: more helpful version of the FD_SET
|
||||
* macro, which also handles maxfd.
|
||||
*/
|
||||
#define FD_SET_MAX(fd, max, set) do { \
|
||||
FD_SET(fd, &set); \
|
||||
if (max < fd + 1) max = fd + 1; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Exports from winser.c.
|
||||
*/
|
||||
extern Backend serial_backend;
|
||||
|
||||
#endif
|
||||
42
sFTPlugins/psftp/VERSION.C
Normal file
42
sFTPlugins/psftp/VERSION.C
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* PuTTY version numbering
|
||||
*/
|
||||
|
||||
#define STR1(x) #x
|
||||
#define STR(x) STR1(x)
|
||||
|
||||
#if defined SNAPSHOT
|
||||
|
||||
#if defined SVN_REV
|
||||
#define SNAPSHOT_TEXT STR(SNAPSHOT) ":r" STR(SVN_REV)
|
||||
#else
|
||||
#define SNAPSHOT_TEXT STR(SNAPSHOT)
|
||||
#endif
|
||||
|
||||
char ver[] = "Development snapshot " SNAPSHOT_TEXT;
|
||||
char sshver[] = "PuTTY-Snapshot-" SNAPSHOT_TEXT;
|
||||
|
||||
#undef SNAPSHOT_TEXT
|
||||
|
||||
#elif defined RELEASE
|
||||
|
||||
char ver[] = "Release " STR(RELEASE);
|
||||
char sshver[] = "PuTTY-Release-" STR(RELEASE);
|
||||
|
||||
#elif defined SVN_REV
|
||||
|
||||
char ver[] = "Custom build r" STR(SVN_REV);
|
||||
char sshver[] = "PuTTY-Custom-r" STR(SVN_REV);
|
||||
|
||||
#else
|
||||
|
||||
char ver[] = "Unidentified build, " __DATE__ " " __TIME__;
|
||||
char sshver[] = "PuTTY-Local: " __DATE__ " " __TIME__;
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* SSH local version string MUST be under 40 characters. Here's a
|
||||
* compile time assertion to verify this.
|
||||
*/
|
||||
enum { vorpal_sword = 1 / (sizeof(sshver) <= 40) };
|
||||
472
sFTPlugins/psftp/WILDCARD.C
Normal file
472
sFTPlugins/psftp/WILDCARD.C
Normal file
@@ -0,0 +1,472 @@
|
||||
/*
|
||||
* Wildcard matching engine for use with SFTP-based file transfer
|
||||
* programs (PSFTP, new-look PSCP): since SFTP has no notion of
|
||||
* getting the remote side to do globbing (and rightly so) we have
|
||||
* to do it locally, by retrieving all the filenames in a directory
|
||||
* and checking each against the wildcard pattern.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "putty.h"
|
||||
|
||||
/*
|
||||
* Definition of wildcard syntax:
|
||||
*
|
||||
* - * matches any sequence of characters, including zero.
|
||||
* - ? matches exactly one character which can be anything.
|
||||
* - [abc] matches exactly one character which is a, b or c.
|
||||
* - [a-f] matches anything from a through f.
|
||||
* - [^a-f] matches anything _except_ a through f.
|
||||
* - [-_] matches - or _; [^-_] matches anything else. (The - is
|
||||
* non-special if it occurs immediately after the opening
|
||||
* bracket or ^.)
|
||||
* - [a^] matches an a or a ^. (The ^ is non-special if it does
|
||||
* _not_ occur immediately after the opening bracket.)
|
||||
* - \*, \?, \[, \], \\ match the single characters *, ?, [, ], \.
|
||||
* - All other characters are non-special and match themselves.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Some notes on differences from POSIX globs (IEEE Std 1003.1, 2003 ed.):
|
||||
* - backslashes act as escapes even within [] bracket expressions
|
||||
* - does not support [!...] for non-matching list (POSIX are weird);
|
||||
* NB POSIX allows [^...] as well via "A bracket expression starting
|
||||
* with an unquoted circumflex character produces unspecified
|
||||
* results". If we wanted to allow [!...] we might want to define
|
||||
* [^!] as having its literal meaning (match '^' or '!').
|
||||
* - none of the scary [[:class:]] stuff, etc
|
||||
*/
|
||||
|
||||
/*
|
||||
* The wildcard matching technique we use is very simple and
|
||||
* potentially O(N^2) in running time, but I don't anticipate it
|
||||
* being that bad in reality (particularly since N will be the size
|
||||
* of a filename, which isn't all that much). Perhaps one day, once
|
||||
* PuTTY has grown a regexp matcher for some other reason, I might
|
||||
* come back and reimplement wildcards by translating them into
|
||||
* regexps or directly into NFAs; but for the moment, in the
|
||||
* absence of any other need for the NFA->DFA translation engine,
|
||||
* anything more than the simplest possible wildcard matcher is
|
||||
* vast code-size overkill.
|
||||
*
|
||||
* Essentially, these wildcards are much simpler than regexps in
|
||||
* that they consist of a sequence of rigid fragments (? and [...]
|
||||
* can never match more or less than one character) separated by
|
||||
* asterisks. It is therefore extremely simple to look at a rigid
|
||||
* fragment and determine whether or not it begins at a particular
|
||||
* point in the test string; so we can search along the string
|
||||
* until we find each fragment, then search for the next. As long
|
||||
* as we find each fragment in the _first_ place it occurs, there
|
||||
* will never be a danger of having to backpedal and try to find it
|
||||
* again somewhere else.
|
||||
*/
|
||||
|
||||
enum {
|
||||
WC_TRAILINGBACKSLASH = 1,
|
||||
WC_UNCLOSEDCLASS,
|
||||
WC_INVALIDRANGE
|
||||
};
|
||||
|
||||
/*
|
||||
* Error reporting is done by returning various negative values
|
||||
* from the wildcard routines. Passing any such value to wc_error
|
||||
* will give a human-readable message.
|
||||
*/
|
||||
const char *wc_error(int value)
|
||||
{
|
||||
value = abs(value);
|
||||
switch (value) {
|
||||
case WC_TRAILINGBACKSLASH:
|
||||
return "'\' occurred at end of string (expected another character)";
|
||||
case WC_UNCLOSEDCLASS:
|
||||
return "expected ']' to close character class";
|
||||
case WC_INVALIDRANGE:
|
||||
return "character range was not terminated (']' just after '-')";
|
||||
}
|
||||
return "INTERNAL ERROR: unrecognised wildcard error number";
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the routine that tests a target string to see if an
|
||||
* initial substring of it matches a fragment. If successful, it
|
||||
* returns 1, and advances both `fragment' and `target' past the
|
||||
* fragment and matching substring respectively. If unsuccessful it
|
||||
* returns zero. If the wildcard fragment suffers a syntax error,
|
||||
* it returns <0 and the precise value indexes into wc_error.
|
||||
*/
|
||||
static int wc_match_fragment(const char **fragment, const char **target)
|
||||
{
|
||||
const char *f, *t;
|
||||
|
||||
f = *fragment;
|
||||
t = *target;
|
||||
/*
|
||||
* The fragment terminates at either the end of the string, or
|
||||
* the first (unescaped) *.
|
||||
*/
|
||||
while (*f && *f != '*' && *t) {
|
||||
/*
|
||||
* Extract one character from t, and one character's worth
|
||||
* of pattern from f, and step along both. Return 0 if they
|
||||
* fail to match.
|
||||
*/
|
||||
if (*f == '\\') {
|
||||
/*
|
||||
* Backslash, which means f[1] is to be treated as a
|
||||
* literal character no matter what it is. It may not
|
||||
* be the end of the string.
|
||||
*/
|
||||
if (!f[1])
|
||||
return -WC_TRAILINGBACKSLASH; /* error */
|
||||
if (f[1] != *t)
|
||||
return 0; /* failed to match */
|
||||
f += 2;
|
||||
} else if (*f == '?') {
|
||||
/*
|
||||
* Question mark matches anything.
|
||||
*/
|
||||
f++;
|
||||
} else if (*f == '[') {
|
||||
int invert = 0;
|
||||
int matched = 0;
|
||||
/*
|
||||
* Open bracket introduces a character class.
|
||||
*/
|
||||
f++;
|
||||
if (*f == '^') {
|
||||
invert = 1;
|
||||
f++;
|
||||
}
|
||||
while (*f != ']') {
|
||||
if (*f == '\\')
|
||||
f++; /* backslashes still work */
|
||||
if (!*f)
|
||||
return -WC_UNCLOSEDCLASS; /* error again */
|
||||
if (f[1] == '-') {
|
||||
int lower, upper, ourchr;
|
||||
lower = (unsigned char) *f++;
|
||||
f++; /* eat the minus */
|
||||
if (*f == ']')
|
||||
return -WC_INVALIDRANGE; /* different error! */
|
||||
if (*f == '\\')
|
||||
f++; /* backslashes _still_ work */
|
||||
if (!*f)
|
||||
return -WC_UNCLOSEDCLASS; /* error again */
|
||||
upper = (unsigned char) *f++;
|
||||
ourchr = (unsigned char) *t;
|
||||
if (lower > upper) {
|
||||
int t = lower; lower = upper; upper = t;
|
||||
}
|
||||
if (ourchr >= lower && ourchr <= upper)
|
||||
matched = 1;
|
||||
} else {
|
||||
matched |= (*t == *f++);
|
||||
}
|
||||
}
|
||||
if (invert == matched)
|
||||
return 0; /* failed to match character class */
|
||||
f++; /* eat the ] */
|
||||
} else {
|
||||
/*
|
||||
* Non-special character matches itself.
|
||||
*/
|
||||
if (*f != *t)
|
||||
return 0;
|
||||
f++;
|
||||
}
|
||||
/*
|
||||
* Now we've done that, increment t past the character we
|
||||
* matched.
|
||||
*/
|
||||
t++;
|
||||
}
|
||||
if (!*f || *f == '*') {
|
||||
/*
|
||||
* We have reached the end of f without finding a mismatch;
|
||||
* so we're done. Update the caller pointers and return 1.
|
||||
*/
|
||||
*fragment = f;
|
||||
*target = t;
|
||||
return 1;
|
||||
}
|
||||
/*
|
||||
* Otherwise, we must have reached the end of t before we
|
||||
* reached the end of f; so we've failed. Return 0.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the real wildcard matching routine. It returns 1 for a
|
||||
* successful match, 0 for an unsuccessful match, and <0 for a
|
||||
* syntax error in the wildcard.
|
||||
*/
|
||||
int wc_match(const char *wildcard, const char *target)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Every time we see a '*' _followed_ by a fragment, we just
|
||||
* search along the string for a location at which the fragment
|
||||
* matches. The only special case is when we see a fragment
|
||||
* right at the start, in which case we just call the matching
|
||||
* routine once and give up if it fails.
|
||||
*/
|
||||
if (*wildcard != '*') {
|
||||
ret = wc_match_fragment(&wildcard, &target);
|
||||
if (ret <= 0)
|
||||
return ret; /* pass back failure or error alike */
|
||||
}
|
||||
|
||||
while (*wildcard) {
|
||||
assert(*wildcard == '*');
|
||||
while (*wildcard == '*')
|
||||
wildcard++;
|
||||
|
||||
/*
|
||||
* It's possible we've just hit the end of the wildcard
|
||||
* after seeing a *, in which case there's no need to
|
||||
* bother searching any more because we've won.
|
||||
*/
|
||||
if (!*wildcard)
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* Now `wildcard' points at the next fragment. So we
|
||||
* attempt to match it against `target', and if that fails
|
||||
* we increment `target' and try again, and so on. When we
|
||||
* find we're about to try matching against the empty
|
||||
* string, we give up and return 0.
|
||||
*/
|
||||
ret = 0;
|
||||
while (*target) {
|
||||
const char *save_w = wildcard, *save_t = target;
|
||||
|
||||
ret = wc_match_fragment(&wildcard, &target);
|
||||
|
||||
if (ret < 0)
|
||||
return ret; /* syntax error */
|
||||
|
||||
if (ret > 0 && !*wildcard && *target) {
|
||||
/*
|
||||
* Final special case - literally.
|
||||
*
|
||||
* This situation arises when we are matching a
|
||||
* _terminal_ fragment of the wildcard (that is,
|
||||
* there is nothing after it, e.g. "*a"), and it
|
||||
* has matched _too early_. For example, matching
|
||||
* "*a" against "parka" will match the "a" fragment
|
||||
* against the _first_ a, and then (if it weren't
|
||||
* for this special case) matching would fail
|
||||
* because we're at the end of the wildcard but not
|
||||
* at the end of the target string.
|
||||
*
|
||||
* In this case what we must do is measure the
|
||||
* length of the fragment in the target (which is
|
||||
* why we saved `target'), jump straight to that
|
||||
* distance from the end of the string using
|
||||
* strlen, and match the same fragment again there
|
||||
* (which is why we saved `wildcard'). Then we
|
||||
* return whatever that operation returns.
|
||||
*/
|
||||
target = save_t + strlen(save_t) - (target - save_t);
|
||||
wildcard = save_w;
|
||||
return wc_match_fragment(&wildcard, &target);
|
||||
}
|
||||
|
||||
if (ret > 0)
|
||||
break;
|
||||
target++;
|
||||
}
|
||||
if (ret > 0)
|
||||
continue;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we reach here, it must be because we successfully matched
|
||||
* a fragment and then found ourselves right at the end of the
|
||||
* wildcard. Hence, we return 1 if and only if we are also
|
||||
* right at the end of the target.
|
||||
*/
|
||||
return (*target ? 0 : 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Another utility routine that translates a non-wildcard string
|
||||
* into its raw equivalent by removing any escaping backslashes.
|
||||
* Expects a target string buffer of anything up to the length of
|
||||
* the original wildcard. You can also pass NULL as the output
|
||||
* buffer if you're only interested in the return value.
|
||||
*
|
||||
* Returns 1 on success, or 0 if a wildcard character was
|
||||
* encountered. In the latter case the output string MAY not be
|
||||
* zero-terminated and you should not use it for anything!
|
||||
*/
|
||||
int wc_unescape(char *output, const char *wildcard)
|
||||
{
|
||||
while (*wildcard) {
|
||||
if (*wildcard == '\\') {
|
||||
wildcard++;
|
||||
/* We are lenient about trailing backslashes in non-wildcards. */
|
||||
if (*wildcard) {
|
||||
if (output)
|
||||
*output++ = *wildcard;
|
||||
wildcard++;
|
||||
}
|
||||
} else if (*wildcard == '*' || *wildcard == '?' ||
|
||||
*wildcard == '[' || *wildcard == ']') {
|
||||
return 0; /* it's a wildcard! */
|
||||
} else {
|
||||
if (output)
|
||||
*output++ = *wildcard;
|
||||
wildcard++;
|
||||
}
|
||||
}
|
||||
*output = '\0';
|
||||
return 1; /* it's clean */
|
||||
}
|
||||
|
||||
#ifdef TESTMODE
|
||||
|
||||
struct test {
|
||||
const char *wildcard;
|
||||
const char *target;
|
||||
int expected_result;
|
||||
};
|
||||
|
||||
const struct test fragment_tests[] = {
|
||||
/*
|
||||
* We exhaustively unit-test the fragment matching routine
|
||||
* itself, which should save us the need to test all its
|
||||
* intricacies during the full wildcard tests.
|
||||
*/
|
||||
{"abc", "abc", 1},
|
||||
{"abc", "abd", 0},
|
||||
{"abc", "abcd", 1},
|
||||
{"abcd", "abc", 0},
|
||||
{"ab[cd]", "abc", 1},
|
||||
{"ab[cd]", "abd", 1},
|
||||
{"ab[cd]", "abe", 0},
|
||||
{"ab[^cd]", "abc", 0},
|
||||
{"ab[^cd]", "abd", 0},
|
||||
{"ab[^cd]", "abe", 1},
|
||||
{"ab\\", "abc", -WC_TRAILINGBACKSLASH},
|
||||
{"ab\\*", "ab*", 1},
|
||||
{"ab\\?", "ab*", 0},
|
||||
{"ab?", "abc", 1},
|
||||
{"ab?", "ab", 0},
|
||||
{"ab[", "abc", -WC_UNCLOSEDCLASS},
|
||||
{"ab[c-", "abb", -WC_UNCLOSEDCLASS},
|
||||
{"ab[c-]", "abb", -WC_INVALIDRANGE},
|
||||
{"ab[c-e]", "abb", 0},
|
||||
{"ab[c-e]", "abc", 1},
|
||||
{"ab[c-e]", "abd", 1},
|
||||
{"ab[c-e]", "abe", 1},
|
||||
{"ab[c-e]", "abf", 0},
|
||||
{"ab[e-c]", "abb", 0},
|
||||
{"ab[e-c]", "abc", 1},
|
||||
{"ab[e-c]", "abd", 1},
|
||||
{"ab[e-c]", "abe", 1},
|
||||
{"ab[e-c]", "abf", 0},
|
||||
{"ab[^c-e]", "abb", 1},
|
||||
{"ab[^c-e]", "abc", 0},
|
||||
{"ab[^c-e]", "abd", 0},
|
||||
{"ab[^c-e]", "abe", 0},
|
||||
{"ab[^c-e]", "abf", 1},
|
||||
{"ab[^e-c]", "abb", 1},
|
||||
{"ab[^e-c]", "abc", 0},
|
||||
{"ab[^e-c]", "abd", 0},
|
||||
{"ab[^e-c]", "abe", 0},
|
||||
{"ab[^e-c]", "abf", 1},
|
||||
{"ab[a^]", "aba", 1},
|
||||
{"ab[a^]", "ab^", 1},
|
||||
{"ab[a^]", "abb", 0},
|
||||
{"ab[^a^]", "aba", 0},
|
||||
{"ab[^a^]", "ab^", 0},
|
||||
{"ab[^a^]", "abb", 1},
|
||||
{"ab[-c]", "ab-", 1},
|
||||
{"ab[-c]", "abc", 1},
|
||||
{"ab[-c]", "abd", 0},
|
||||
{"ab[^-c]", "ab-", 0},
|
||||
{"ab[^-c]", "abc", 0},
|
||||
{"ab[^-c]", "abd", 1},
|
||||
{"ab[\\[-\\]]", "abZ", 0},
|
||||
{"ab[\\[-\\]]", "ab[", 1},
|
||||
{"ab[\\[-\\]]", "ab\\", 1},
|
||||
{"ab[\\[-\\]]", "ab]", 1},
|
||||
{"ab[\\[-\\]]", "ab^", 0},
|
||||
{"ab[^\\[-\\]]", "abZ", 1},
|
||||
{"ab[^\\[-\\]]", "ab[", 0},
|
||||
{"ab[^\\[-\\]]", "ab\\", 0},
|
||||
{"ab[^\\[-\\]]", "ab]", 0},
|
||||
{"ab[^\\[-\\]]", "ab^", 1},
|
||||
{"ab[a-fA-F]", "aba", 1},
|
||||
{"ab[a-fA-F]", "abF", 1},
|
||||
{"ab[a-fA-F]", "abZ", 0},
|
||||
};
|
||||
|
||||
const struct test full_tests[] = {
|
||||
{"a", "argh", 0},
|
||||
{"a", "ba", 0},
|
||||
{"a", "a", 1},
|
||||
{"a*", "aardvark", 1},
|
||||
{"a*", "badger", 0},
|
||||
{"*a", "park", 0},
|
||||
{"*a", "pArka", 1},
|
||||
{"*a", "parka", 1},
|
||||
{"*a*", "park", 1},
|
||||
{"*a*", "perk", 0},
|
||||
{"?b*r?", "abracadabra", 1},
|
||||
{"?b*r?", "abracadabr", 0},
|
||||
{"?b*r?", "abracadabzr", 0},
|
||||
};
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int i;
|
||||
int fails, passes;
|
||||
|
||||
fails = passes = 0;
|
||||
|
||||
for (i = 0; i < sizeof(fragment_tests)/sizeof(*fragment_tests); i++) {
|
||||
const char *f, *t;
|
||||
int eret, aret;
|
||||
f = fragment_tests[i].wildcard;
|
||||
t = fragment_tests[i].target;
|
||||
eret = fragment_tests[i].expected_result;
|
||||
aret = wc_match_fragment(&f, &t);
|
||||
if (aret != eret) {
|
||||
printf("failed test: /%s/ against /%s/ returned %d not %d\n",
|
||||
fragment_tests[i].wildcard, fragment_tests[i].target,
|
||||
aret, eret);
|
||||
fails++;
|
||||
} else
|
||||
passes++;
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(full_tests)/sizeof(*full_tests); i++) {
|
||||
const char *f, *t;
|
||||
int eret, aret;
|
||||
f = full_tests[i].wildcard;
|
||||
t = full_tests[i].target;
|
||||
eret = full_tests[i].expected_result;
|
||||
aret = wc_match(f, t);
|
||||
if (aret != eret) {
|
||||
printf("failed test: /%s/ against /%s/ returned %d not %d\n",
|
||||
full_tests[i].wildcard, full_tests[i].target,
|
||||
aret, eret);
|
||||
fails++;
|
||||
} else
|
||||
passes++;
|
||||
}
|
||||
|
||||
printf("passed %d, failed %d\n", passes, fails);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/CL.read.1.tlog
Normal file
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/CL.read.1.tlog
Normal file
Binary file not shown.
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/CL.write.1.tlog
Normal file
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/CL.write.1.tlog
Normal file
Binary file not shown.
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/be_none.obj
Normal file
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/be_none.obj
Normal file
Binary file not shown.
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/cl.command.1.tlog
Normal file
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/cl.command.1.tlog
Normal file
Binary file not shown.
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/cmdline.obj
Normal file
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/cmdline.obj
Normal file
Binary file not shown.
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/cproxy.obj
Normal file
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/cproxy.obj
Normal file
Binary file not shown.
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/int64.obj
Normal file
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/int64.obj
Normal file
Binary file not shown.
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/link.command.1.tlog
Normal file
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/link.command.1.tlog
Normal file
Binary file not shown.
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/link.read.1.tlog
Normal file
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/link.read.1.tlog
Normal file
Binary file not shown.
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/link.write.1.tlog
Normal file
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/link.write.1.tlog
Normal file
Binary file not shown.
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/logging.obj
Normal file
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/logging.obj
Normal file
Binary file not shown.
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/misc.obj
Normal file
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/misc.obj
Normal file
Binary file not shown.
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/mt.command.1.tlog
Normal file
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/mt.command.1.tlog
Normal file
Binary file not shown.
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/mt.read.1.tlog
Normal file
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/mt.read.1.tlog
Normal file
Binary file not shown.
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/mt.write.1.tlog
Normal file
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/mt.write.1.tlog
Normal file
Binary file not shown.
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/pinger.obj
Normal file
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/pinger.obj
Normal file
Binary file not shown.
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/portfwd.obj
Normal file
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/portfwd.obj
Normal file
Binary file not shown.
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/proxy.obj
Normal file
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/proxy.obj
Normal file
Binary file not shown.
@@ -0,0 +1,69 @@
|
||||
C:\_ROOT_\PanaceanTech\sFTPlugins\psftp\WINDOWS\MSVC\PSFTP\.\Release\psftp.dll
|
||||
C:\_ROOT_\PanaceanTech\sFTPlugins\psftp\WINDOWS\MSVC\PSFTP\.\Release\psftp.dll.intermediate.manifest
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\BE_NONE.OBJ
|
||||
C:\_ROOT_\PanaceanTech\sFTPlugins\psftp\WINDOWS\MSVC\PSFTP\Release\cl.command.1.tlog
|
||||
C:\_ROOT_\PanaceanTech\sFTPlugins\psftp\WINDOWS\MSVC\PSFTP\Release\CL.read.1.tlog
|
||||
C:\_ROOT_\PanaceanTech\sFTPlugins\psftp\WINDOWS\MSVC\PSFTP\Release\CL.write.1.tlog
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\CMDLINE.OBJ
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\CPROXY.OBJ
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\INT64.OBJ
|
||||
C:\_ROOT_\PanaceanTech\sFTPlugins\psftp\WINDOWS\MSVC\PSFTP\Release\link.command.1.tlog
|
||||
C:\_ROOT_\PanaceanTech\sFTPlugins\psftp\WINDOWS\MSVC\PSFTP\Release\link.read.1.tlog
|
||||
C:\_ROOT_\PanaceanTech\sFTPlugins\psftp\WINDOWS\MSVC\PSFTP\Release\link.write.1.tlog
|
||||
C:\_ROOT_\PanaceanTech\sFTPlugins\psftp\WINDOWS\MSVC\PSFTP\Release\link-cvtres.read.1.tlog
|
||||
C:\_ROOT_\PanaceanTech\sFTPlugins\psftp\WINDOWS\MSVC\PSFTP\Release\link-cvtres.write.1.tlog
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\LOGGING.OBJ
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\MISC.OBJ
|
||||
C:\_ROOT_\PanaceanTech\sFTPlugins\psftp\WINDOWS\MSVC\PSFTP\Release\mt.command.1.tlog
|
||||
C:\_ROOT_\PanaceanTech\sFTPlugins\psftp\WINDOWS\MSVC\PSFTP\Release\mt.read.1.tlog
|
||||
C:\_ROOT_\PanaceanTech\sFTPlugins\psftp\WINDOWS\MSVC\PSFTP\Release\mt.write.1.tlog
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\PINGER.OBJ
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\PORTFWD.OBJ
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\PROXY.OBJ
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\PSFTP.DLL
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\PSFTP.DLL.INTERMEDIATE.MANIFEST
|
||||
C:\_ROOT_\PanaceanTech\sFTPlugins\psftp\WINDOWS\MSVC\PSFTP\Release\psftp.exp
|
||||
C:\_ROOT_\PanaceanTech\sFTPlugins\psftp\WINDOWS\MSVC\PSFTP\Release\psftp.lib
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\PSFTP.OBJ
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\PSFTP.RES
|
||||
C:\_ROOT_\PanaceanTech\sFTPlugins\psftp\WINDOWS\MSVC\PSFTP\Release\psftp.write.1.tlog
|
||||
C:\_ROOT_\PanaceanTech\sFTPlugins\psftp\WINDOWS\MSVC\PSFTP\Release\rc.command.1.tlog
|
||||
C:\_ROOT_\PanaceanTech\sFTPlugins\psftp\WINDOWS\MSVC\PSFTP\Release\rc.read.1.tlog
|
||||
C:\_ROOT_\PanaceanTech\sFTPlugins\psftp\WINDOWS\MSVC\PSFTP\Release\rc.write.1.tlog
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\SETTINGS.OBJ
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\SFTP.OBJ
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\SSH.OBJ
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\SSHAES.OBJ
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\SSHARCF.OBJ
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\SSHBLOWF.OBJ
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\SSHBN.OBJ
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\SSHCRC.OBJ
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\SSHCRCDA.OBJ
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\SSHDES.OBJ
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\SSHDH.OBJ
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\SSHDSS.OBJ
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\SSHMD5.OBJ
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\SSHPUBK.OBJ
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\SSHRAND.OBJ
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\SSHRSA.OBJ
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\SSHSH256.OBJ
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\SSHSH512.OBJ
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\SSHSHA.OBJ
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\SSHZLIB.OBJ
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\TIMING.OBJ
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\TREE234.OBJ
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\VC100.PDB
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\VERSION.OBJ
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\WILDCARD.OBJ
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\WINCONS.OBJ
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\WINDEFS.OBJ
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\WINHANDL.OBJ
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\WINMISC.OBJ
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\WINNET.OBJ
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\WINNOISE.OBJ
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\WINPGNTC.OBJ
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\WINPROXY.OBJ
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\WINSFTP.OBJ
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\WINSTORE.OBJ
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\WINTIME.OBJ
|
||||
C:\_ROOT_\PANACEANTECH\SFTPLUGINS\PSFTP\WINDOWS\MSVC\PSFTP\RELEASE\X11FWD.OBJ
|
||||
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/psftp.dll
Normal file
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/psftp.dll
Normal file
Binary file not shown.
@@ -0,0 +1,10 @@
|
||||
<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
|
||||
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<security>
|
||||
<requestedPrivileges>
|
||||
<requestedExecutionLevel level='asInvoker' uiAccess='false' />
|
||||
</requestedPrivileges>
|
||||
</security>
|
||||
</trustInfo>
|
||||
</assembly>
|
||||
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/psftp.exp
Normal file
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/psftp.exp
Normal file
Binary file not shown.
@@ -0,0 +1,2 @@
|
||||
#v4.0:v100
|
||||
Release|Win32|C:\_ROOT_\PanaceanTech\sFTPlugins\|
|
||||
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/psftp.lib
Normal file
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/psftp.lib
Normal file
Binary file not shown.
350
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/psftp.log
Normal file
350
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/psftp.log
Normal file
@@ -0,0 +1,350 @@
|
||||
Build started 6/8/2011 2:32:21 AM.
|
||||
Project "C:\_ROOT_\PanaceanTech\sFTPlugins\psftp\WINDOWS\MSVC\PSFTP\psftp.vcxproj" on node 2 (rebuild target(s)).
|
||||
_PrepareForClean:
|
||||
Deleting file ".\Release\psftp.lastbuildstate".
|
||||
InitializeBuildStatus:
|
||||
Creating ".\Release\psftp.unsuccessfulbuild" because "AlwaysCreate" was specified.
|
||||
ClCompile:
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\CL.exe /c /I..\..\..\./ /I..\..\..\charset/ /I..\..\..\windows/ /I..\..\..\unix/ /I..\..\..\mac/ /I..\..\..\macosx/ /Zi /nologo /W3 /WX- /O2 /Ob1 /Oy- /D WIN32 /D NDEBUG /D _WINDOWS /D _VC80_UPGRADE=0x0600 /D _WINDLL /D _MBCS /GF /Gm- /EHsc /MT /GS /Gy /fp:precise /Zc:wchar_t /Zc:forScope /Fo".\Release\\" /Fd".\Release\vc100.pdb" /Gd /TC /analyze- /errorReport:prompt ..\..\..\be_none.c ..\..\..\cmdline.c ..\..\..\cproxy.c ..\..\..\int64.c ..\..\..\logging.c ..\..\..\misc.c ..\..\..\pinger.c ..\..\..\portfwd.c ..\..\..\proxy.c ..\..\..\psftp.c ..\..\..\settings.c ..\..\..\sftp.c ..\..\..\ssh.c ..\..\..\sshaes.c ..\..\..\ssharcf.c ..\..\..\sshblowf.c ..\..\..\sshbn.c ..\..\..\sshcrc.c ..\..\..\sshcrcda.c ..\..\..\sshdes.c ..\..\..\sshdh.c ..\..\..\sshdss.c ..\..\..\sshmd5.c ..\..\..\sshpubk.c ..\..\..\sshrand.c ..\..\..\sshrsa.c ..\..\..\sshsh256.c ..\..\..\sshsh512.c ..\..\..\sshsha.c ..\..\..\sshzlib.c ..\..\..\timing.c ..\..\..\tree234.c ..\..\..\version.c ..\..\..\wildcard.c ..\..\wincons.c ..\..\windefs.c ..\..\winhandl.c ..\..\winmisc.c ..\..\winnet.c ..\..\winnoise.c ..\..\winpgntc.c ..\..\winproxy.c ..\..\winsftp.c ..\..\winstore.c ..\..\wintime.c ..\..\..\x11fwd.c
|
||||
be_none.c
|
||||
cmdline.c
|
||||
..\..\..\cmdline.c(99): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(188) : see declaration of 'strncpy'
|
||||
..\..\..\cmdline.c(203): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(188) : see declaration of 'strncpy'
|
||||
..\..\..\cmdline.c(228): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(188) : see declaration of 'strncpy'
|
||||
..\..\..\cmdline.c(266): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(188) : see declaration of 'strncpy'
|
||||
..\..\..\cmdline.c(288): warning C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(234) : see declaration of 'fopen'
|
||||
cproxy.c
|
||||
int64.c
|
||||
logging.c
|
||||
..\..\..\logging.c(88): warning C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(234) : see declaration of 'fopen'
|
||||
..\..\..\logging.c(152): warning C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(234) : see declaration of 'fopen'
|
||||
..\..\..\logging.c(274): warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
|
||||
..\..\..\logging.c(283): warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
|
||||
..\..\..\logging.c(286): warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
|
||||
..\..\..\logging.c(299): warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
misc.c
|
||||
..\..\..\misc.c(140): warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
..\..\..\misc.c(163): warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
..\..\..\misc.c(171): warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
..\..\..\misc.c(251): warning C4996: '_vsnprintf': This function or variable may be unsafe. Consider using _vsnprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(363) : see declaration of '_vsnprintf'
|
||||
..\..\..\misc.c(508): warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
..\..\..\misc.c(550): warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
pinger.c
|
||||
portfwd.c
|
||||
..\..\..\portfwd.c(162): warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
|
||||
..\..\..\portfwd.c(244): warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
|
||||
..\..\..\portfwd.c(416): warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
..\..\..\portfwd.c(460): warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
proxy.c
|
||||
..\..\..\proxy.c(318): warning C4996: 'strnicmp': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _strnicmp. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(248) : see declaration of 'strnicmp'
|
||||
..\..\..\proxy.c(325): warning C4996: 'strnicmp': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _strnicmp. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(248) : see declaration of 'strnicmp'
|
||||
..\..\..\proxy.c(333): warning C4996: 'strnicmp': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _strnicmp. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(248) : see declaration of 'strnicmp'
|
||||
..\..\..\proxy.c(335): warning C4996: 'strnicmp': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _strnicmp. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(248) : see declaration of 'strnicmp'
|
||||
..\..\..\proxy.c(540): warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
|
||||
..\..\..\proxy.c(542): warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
|
||||
..\..\..\proxy.c(546): warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
..\..\..\proxy.c(620): warning C4996: 'sscanf': This function or variable may be unsafe. Consider using sscanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(325) : see declaration of 'sscanf'
|
||||
..\..\..\proxy.c(733): warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
..\..\..\proxy.c(1099): warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
..\..\..\proxy.c(1102): warning C4996: 'strcat': This function or variable may be unsafe. Consider using strcat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
..\..\..\proxy.c(1103): warning C4996: 'strcat': This function or variable may be unsafe. Consider using strcat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
..\..\..\proxy.c(1104): warning C4996: 'strcat': This function or variable may be unsafe. Consider using strcat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
..\..\..\proxy.c(1105): warning C4996: 'strcat': This function or variable may be unsafe. Consider using strcat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
..\..\..\proxy.c(1106): warning C4996: 'strcat': This function or variable may be unsafe. Consider using strcat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
..\..\..\proxy.c(1107): warning C4996: 'strcat': This function or variable may be unsafe. Consider using strcat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
..\..\..\proxy.c(1108): warning C4996: 'strcat': This function or variable may be unsafe. Consider using strcat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
..\..\..\proxy.c(1109): warning C4996: 'strcat': This function or variable may be unsafe. Consider using strcat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
..\..\..\proxy.c(1112): warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
|
||||
..\..\..\proxy.c(1336): warning C4996: 'strnicmp': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _strnicmp. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(248) : see declaration of 'strnicmp'
|
||||
..\..\..\proxy.c(1347): warning C4996: 'strnicmp': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _strnicmp. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(248) : see declaration of 'strnicmp'
|
||||
..\..\..\proxy.c(1349): warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
|
||||
..\..\..\proxy.c(1356): warning C4996: 'strnicmp': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _strnicmp. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(248) : see declaration of 'strnicmp'
|
||||
..\..\..\proxy.c(1364): warning C4996: 'strnicmp': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _strnicmp. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(248) : see declaration of 'strnicmp'
|
||||
..\..\..\proxy.c(1372): warning C4996: 'strnicmp': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _strnicmp. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(248) : see declaration of 'strnicmp'
|
||||
..\..\..\proxy.c(1380): warning C4996: 'strnicmp': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _strnicmp. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(248) : see declaration of 'strnicmp'
|
||||
..\..\..\proxy.c(1383): warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
|
||||
psftp.c
|
||||
..\..\..\psftp.c(1714): warning C4996: 'sscanf': This function or variable may be unsafe. Consider using sscanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(325) : see declaration of 'sscanf'
|
||||
..\..\..\psftp.c(2404): warning C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(234) : see declaration of 'fopen'
|
||||
..\..\..\psftp.c(2708): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(188) : see declaration of 'strncpy'
|
||||
..\..\..\psftp.c(2713): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(188) : see declaration of 'strncpy'
|
||||
..\..\..\psftp.c(2754): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(188) : see declaration of 'strncpy'
|
||||
..\..\..\psftp.c(2783): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(188) : see declaration of 'strncpy'
|
||||
..\..\..\psftp.c(2800): warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
settings.c
|
||||
..\..\..\settings.c(62): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(188) : see declaration of 'strncpy'
|
||||
..\..\..\settings.c(65): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(188) : see declaration of 'strncpy'
|
||||
..\..\..\settings.c(186): warning C4996: 'strtok': This function or variable may be unsafe. Consider using strtok_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(197) : see declaration of 'strtok'
|
||||
..\..\..\settings.c(224): warning C4996: 'strncat': This function or variable may be unsafe. Consider using strncat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(175) : see declaration of 'strncat'
|
||||
..\..\..\settings.c(227): warning C4996: 'strncat': This function or variable may be unsafe. Consider using strncat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(175) : see declaration of 'strncat'
|
||||
..\..\..\settings.c(384): warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
|
||||
..\..\..\settings.c(386): warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
|
||||
..\..\..\settings.c(397): warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
|
||||
..\..\..\settings.c(401): warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
|
||||
..\..\..\settings.c(684): warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
|
||||
..\..\..\settings.c(686): warning C4996: 'sscanf': This function or variable may be unsafe. Consider using sscanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(325) : see declaration of 'sscanf'
|
||||
..\..\..\settings.c(710): warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
|
||||
..\..\..\settings.c(825): warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
sftp.c
|
||||
ssh.c
|
||||
..\..\..\ssh.c(268): warning C4996: 'stricmp': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _stricmp. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(246) : see declaration of 'stricmp'
|
||||
..\..\..\ssh.c(273): warning C4996: 'stricmp': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _stricmp. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(246) : see declaration of 'stricmp'
|
||||
..\..\..\ssh.c(908): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(188) : see declaration of 'strncpy'
|
||||
..\..\..\ssh.c(2404): warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
..\..\..\ssh.c(2762): warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
..\..\..\ssh.c(3006): warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
..\..\..\ssh.c(3250): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(188) : see declaration of 'strncpy'
|
||||
..\..\..\ssh.c(3853): warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
..\..\..\ssh.c(4132): warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
..\..\..\ssh.c(4347): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(188) : see declaration of 'strncpy'
|
||||
..\..\..\ssh.c(4818): warning C4996: 'sscanf': This function or variable may be unsafe. Consider using sscanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(325) : see declaration of 'sscanf'
|
||||
..\..\..\ssh.c(6908): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(188) : see declaration of 'strncpy'
|
||||
..\..\..\ssh.c(7982): warning C4996: 'sscanf': This function or variable may be unsafe. Consider using sscanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(325) : see declaration of 'sscanf'
|
||||
sshaes.c
|
||||
ssharcf.c
|
||||
sshblowf.c
|
||||
sshbn.c
|
||||
sshcrc.c
|
||||
sshcrcda.c
|
||||
sshdes.c
|
||||
Generating Code...
|
||||
Compiling...
|
||||
sshdh.c
|
||||
sshdss.c
|
||||
..\..\..\sshdss.c(141): warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
|
||||
..\..\..\sshdss.c(148): warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
|
||||
..\..\..\sshdss.c(155): warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
|
||||
..\..\..\sshdss.c(162): warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
|
||||
..\..\..\sshdss.c(200): warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
|
||||
..\..\..\sshdss.c(203): warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
|
||||
..\..\..\sshdss.c(206): warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
sshmd5.c
|
||||
sshpubk.c
|
||||
..\..\..\sshpubk.c(165): warning C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(234) : see declaration of 'fopen'
|
||||
..\..\..\sshpubk.c(206): warning C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(234) : see declaration of 'fopen'
|
||||
..\..\..\sshpubk.c(244): warning C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(234) : see declaration of 'fopen'
|
||||
..\..\..\sshpubk.c(367): warning C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(234) : see declaration of 'fopen'
|
||||
..\..\..\sshpubk.c(637): warning C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(234) : see declaration of 'fopen'
|
||||
..\..\..\sshpubk.c(811): warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
|
||||
..\..\..\sshpubk.c(886): warning C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(234) : see declaration of 'fopen'
|
||||
..\..\..\sshpubk.c(967): warning C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(234) : see declaration of 'fopen'
|
||||
..\..\..\sshpubk.c(1148): warning C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(234) : see declaration of 'fopen'
|
||||
..\..\..\sshpubk.c(1184): warning C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(234) : see declaration of 'fopen'
|
||||
sshrand.c
|
||||
sshrsa.c
|
||||
..\..\..\sshrsa.c(262): warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
|
||||
..\..\..\sshrsa.c(270): warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
|
||||
..\..\..\sshrsa.c(305): warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
|
||||
..\..\..\sshrsa.c(308): warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
|
||||
..\..\..\sshrsa.c(309): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(188) : see declaration of 'strncpy'
|
||||
..\..\..\sshrsa.c(314): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(188) : see declaration of 'strncpy'
|
||||
..\..\..\sshrsa.c(691): warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
|
||||
..\..\..\sshrsa.c(694): warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
|
||||
..\..\..\sshrsa.c(697): warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
sshsh256.c
|
||||
sshsh512.c
|
||||
sshsha.c
|
||||
sshzlib.c
|
||||
timing.c
|
||||
tree234.c
|
||||
version.c
|
||||
wildcard.c
|
||||
wincons.c
|
||||
windefs.c
|
||||
..\..\windefs.c(13): warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
..\..\windefs.c(27): warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
winhandl.c
|
||||
winmisc.c
|
||||
..\..\winmisc.c(21): warning C4996: 'getenv': This function or variable may be unsafe. Consider using _dupenv_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdlib.h(433) : see declaration of 'getenv'
|
||||
..\..\winmisc.c(27): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(188) : see declaration of 'strncpy'
|
||||
winnet.c
|
||||
..\..\winnet.c(469): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(188) : see declaration of 'strncpy'
|
||||
..\..\winnet.c(471): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(188) : see declaration of 'strncpy'
|
||||
..\..\winnet.c(488): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(188) : see declaration of 'strncpy'
|
||||
..\..\winnet.c(501): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(188) : see declaration of 'strncpy'
|
||||
..\..\winnet.c(505): warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
..\..\winnet.c(519): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(188) : see declaration of 'strncpy'
|
||||
..\..\winnet.c(552): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(188) : see declaration of 'strncpy'
|
||||
..\..\winnet.c(559): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(188) : see declaration of 'strncpy'
|
||||
..\..\winnet.c(562): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(188) : see declaration of 'strncpy'
|
||||
winnoise.c
|
||||
..\..\winnoise.c(26): warning C4996: 'strcat': This function or variable may be unsafe. Consider using strcat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
Generating Code...
|
||||
Compiling...
|
||||
winpgntc.c
|
||||
winproxy.c
|
||||
winsftp.c
|
||||
winstore.c
|
||||
..\..\winstore.c(297): warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
..\..\winstore.c(298): warning C4996: 'strcat': This function or variable may be unsafe. Consider using strcat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
..\..\winstore.c(300): warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
|
||||
..\..\winstore.c(510): warning C4996: 'strcat': This function or variable may be unsafe. Consider using strcat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
..\..\winstore.c(517): warning C4996: 'strcat': This function or variable may be unsafe. Consider using strcat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
..\..\winstore.c(537): warning C4996: 'strcat': This function or variable may be unsafe. Consider using strcat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
..\..\winstore.c(547): warning C4996: 'strcat': This function or variable may be unsafe. Consider using strcat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
wintime.c
|
||||
x11fwd.c
|
||||
..\..\..\x11fwd.c(87): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(188) : see declaration of 'strncpy'
|
||||
..\..\..\x11fwd.c(90): warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
|
||||
..\..\..\x11fwd.c(91): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(188) : see declaration of 'strncpy'
|
||||
..\..\..\x11fwd.c(161): warning C4244: 'function' : conversion from 'time_t' to 'int', possible loss of data
|
||||
..\..\..\x11fwd.c(300): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(188) : see declaration of 'strncpy'
|
||||
..\..\..\x11fwd.c(347): warning C4996: 'sscanf': This function or variable may be unsafe. Consider using sscanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(325) : see declaration of 'sscanf'
|
||||
Generating Code...
|
||||
ResourceCompile:
|
||||
C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\rc.exe /D NDEBUG /D _VC80_UPGRADE=0x0600 /l"0x0809" /I"\Users\Administrator\Documents\Visual Studio 2010\Projects\puttysrc\windows" /nologo /fo".\Release\psftp.res" ..\..\psftp.rc
|
||||
Link:
|
||||
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\link.exe /ERRORREPORT:PROMPT /OUT:".\Release\psftp.dll" /INCREMENTAL:NO /NOLOGO comctl32.lib imm32.lib winmm.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /MANIFEST /ManifestFile:".\Release\psftp.dll.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /PDB:"C:\_ROOT_\PanaceanTech\sFTPlugins\psftp\WINDOWS\MSVC\PSFTP\Release\psftp.pdb" /SUBSYSTEM:CONSOLE /TLBID:1 /DYNAMICBASE /NXCOMPAT /IMPLIB:".\Release\psftp.lib" /MACHINE:X86 /DLL .\Release\psftp.res
|
||||
.\Release\be_none.obj
|
||||
.\Release\cmdline.obj
|
||||
.\Release\cproxy.obj
|
||||
.\Release\int64.obj
|
||||
.\Release\logging.obj
|
||||
.\Release\misc.obj
|
||||
.\Release\pinger.obj
|
||||
.\Release\portfwd.obj
|
||||
.\Release\proxy.obj
|
||||
.\Release\psftp.obj
|
||||
.\Release\settings.obj
|
||||
.\Release\sftp.obj
|
||||
.\Release\ssh.obj
|
||||
.\Release\sshaes.obj
|
||||
.\Release\ssharcf.obj
|
||||
.\Release\sshblowf.obj
|
||||
.\Release\sshbn.obj
|
||||
.\Release\sshcrc.obj
|
||||
.\Release\sshcrcda.obj
|
||||
.\Release\sshdes.obj
|
||||
.\Release\sshdh.obj
|
||||
.\Release\sshdss.obj
|
||||
.\Release\sshmd5.obj
|
||||
.\Release\sshpubk.obj
|
||||
.\Release\sshrand.obj
|
||||
.\Release\sshrsa.obj
|
||||
.\Release\sshsh256.obj
|
||||
.\Release\sshsh512.obj
|
||||
.\Release\sshsha.obj
|
||||
.\Release\sshzlib.obj
|
||||
.\Release\timing.obj
|
||||
.\Release\tree234.obj
|
||||
.\Release\version.obj
|
||||
.\Release\wildcard.obj
|
||||
.\Release\wincons.obj
|
||||
.\Release\windefs.obj
|
||||
.\Release\winhandl.obj
|
||||
.\Release\winmisc.obj
|
||||
.\Release\winnet.obj
|
||||
.\Release\winnoise.obj
|
||||
.\Release\winpgntc.obj
|
||||
.\Release\winproxy.obj
|
||||
.\Release\winsftp.obj
|
||||
.\Release\winstore.obj
|
||||
.\Release\wintime.obj
|
||||
.\Release\x11fwd.obj
|
||||
Creating library .\Release\psftp.lib and object .\Release\psftp.exp
|
||||
psftp.vcxproj -> C:\_ROOT_\PanaceanTech\sFTPlugins\psftp\WINDOWS\MSVC\PSFTP\.\Release\psftp.dll
|
||||
Manifest:
|
||||
C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\mt.exe /nologo /verbose /outputresource:".\Release\psftp.dll;#2" /manifest .\Release\psftp.dll.intermediate.manifest
|
||||
FinalizeBuildStatus:
|
||||
Deleting file ".\Release\psftp.unsuccessfulbuild".
|
||||
Touching ".\Release\psftp.lastbuildstate".
|
||||
Done Building Project "C:\_ROOT_\PanaceanTech\sFTPlugins\psftp\WINDOWS\MSVC\PSFTP\psftp.vcxproj" (rebuild target(s)).
|
||||
|
||||
Build succeeded.
|
||||
|
||||
Time Elapsed 00:00:15.13
|
||||
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/psftp.obj
Normal file
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/psftp.obj
Normal file
Binary file not shown.
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/psftp.res
Normal file
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/psftp.res
Normal file
Binary file not shown.
@@ -0,0 +1,5 @@
|
||||
^C:\_ROOT_\PanaceanTech\sFTPlugins\psftp\WINDOWS\MSVC\PSFTP\psftp.vcxproj
|
||||
C:\_ROOT_\PanaceanTech\sFTPlugins\psftp\WINDOWS\MSVC\PSFTP\Release\psftp.lib
|
||||
C:\_ROOT_\PanaceanTech\sFTPlugins\psftp\WINDOWS\MSVC\PSFTP\Release\psftp.lib
|
||||
C:\_ROOT_\PanaceanTech\sFTPlugins\psftp\WINDOWS\MSVC\PSFTP\Release\psftp.exp
|
||||
C:\_ROOT_\PanaceanTech\sFTPlugins\psftp\WINDOWS\MSVC\PSFTP\Release\psftp.exp
|
||||
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/rc.command.1.tlog
Normal file
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/rc.command.1.tlog
Normal file
Binary file not shown.
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/rc.read.1.tlog
Normal file
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/rc.read.1.tlog
Normal file
Binary file not shown.
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/rc.write.1.tlog
Normal file
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/rc.write.1.tlog
Normal file
Binary file not shown.
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/settings.obj
Normal file
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/settings.obj
Normal file
Binary file not shown.
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/sftp.obj
Normal file
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/sftp.obj
Normal file
Binary file not shown.
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/ssh.obj
Normal file
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/ssh.obj
Normal file
Binary file not shown.
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/sshaes.obj
Normal file
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/sshaes.obj
Normal file
Binary file not shown.
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/ssharcf.obj
Normal file
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/ssharcf.obj
Normal file
Binary file not shown.
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/sshblowf.obj
Normal file
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/sshblowf.obj
Normal file
Binary file not shown.
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/sshbn.obj
Normal file
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/sshbn.obj
Normal file
Binary file not shown.
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/sshcrc.obj
Normal file
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/sshcrc.obj
Normal file
Binary file not shown.
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/sshcrcda.obj
Normal file
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/sshcrcda.obj
Normal file
Binary file not shown.
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/sshdes.obj
Normal file
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/sshdes.obj
Normal file
Binary file not shown.
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/sshdh.obj
Normal file
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/sshdh.obj
Normal file
Binary file not shown.
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/sshdss.obj
Normal file
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/sshdss.obj
Normal file
Binary file not shown.
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/sshmd5.obj
Normal file
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/sshmd5.obj
Normal file
Binary file not shown.
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/sshpubk.obj
Normal file
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/sshpubk.obj
Normal file
Binary file not shown.
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/sshrand.obj
Normal file
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/sshrand.obj
Normal file
Binary file not shown.
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/sshrsa.obj
Normal file
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/sshrsa.obj
Normal file
Binary file not shown.
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/sshsh256.obj
Normal file
BIN
sFTPlugins/psftp/WINDOWS/MSVC/PSFTP/Release/sshsh256.obj
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user