зеркало из https://github.com/github/putty.git
Remove the special hooks in ssh.c for pscp. pscp now uses the standard
interface to the outside of the ssh module. This means pscp now works without change in SSH2. [originally from svn r638]
This commit is contained in:
Родитель
355cdbd5e8
Коммит
0fed43e9f4
2
Makefile
2
Makefile
|
@ -204,7 +204,7 @@ sshdh.$(OBJ): sshdh.c ssh.h
|
|||
sshdss.$(OBJ): sshdss.c ssh.h
|
||||
sshbn.$(OBJ): sshbn.c ssh.h
|
||||
sshpubk.$(OBJ): sshpubk.c ssh.h
|
||||
scp.$(OBJ): scp.c putty.h scp.h
|
||||
scp.$(OBJ): scp.c putty.h
|
||||
version.$(OBJ): version.c
|
||||
be_all.$(OBJ): be_all.c
|
||||
be_nossh.$(OBJ): be_nossh.c
|
||||
|
|
153
scp.c
153
scp.c
|
@ -26,7 +26,6 @@
|
|||
|
||||
#define PUTTY_DO_GLOBALS
|
||||
#include "putty.h"
|
||||
#include "scp.h"
|
||||
|
||||
#define TIME_POSIX_TO_WIN(t, ft) (*(LONGLONG*)&(ft) = \
|
||||
((LONGLONG) (t) + (LONGLONG) 11644473600) * (LONGLONG) 10000000)
|
||||
|
@ -77,7 +76,6 @@ static void gui_update_stats(char *name, unsigned long size, int percentage, tim
|
|||
* These functions are needed to link with other modules, but
|
||||
* (should) never get called.
|
||||
*/
|
||||
void term_out(void) { abort(); }
|
||||
void begin_session(void) { }
|
||||
void write_clip (void *data, int len) { }
|
||||
void term_deselect(void) { }
|
||||
|
@ -178,6 +176,120 @@ void connection_fatal(char *fmt, ...)
|
|||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Receive a block of data from the SSH link. Block until all data
|
||||
* is available.
|
||||
*
|
||||
* To do this, we repeatedly call the SSH protocol module, with our
|
||||
* own trap in term_out() to catch the data that comes back. We do
|
||||
* this until we have enough data.
|
||||
*/
|
||||
static unsigned char *outptr; /* where to put the data */
|
||||
static unsigned outlen; /* how much data required */
|
||||
static unsigned char *pending = NULL; /* any spare data */
|
||||
static unsigned pendlen=0, pendsize=0; /* length and phys. size of buffer */
|
||||
void term_out(void) {
|
||||
/*
|
||||
* Here we must deal with a block of data, in `inbuf', size
|
||||
* `inbuf_head'.
|
||||
*/
|
||||
unsigned char *p = inbuf;
|
||||
unsigned len = inbuf_head;
|
||||
|
||||
inbuf_head = 0;
|
||||
|
||||
/*
|
||||
* If this is before the real session begins, just return.
|
||||
*/
|
||||
if (!outptr)
|
||||
return;
|
||||
|
||||
if (outlen > 0) {
|
||||
unsigned used = outlen;
|
||||
if (used > len) used = len;
|
||||
memcpy(outptr, p, used);
|
||||
outptr += used; outlen -= used;
|
||||
p += used; len -= used;
|
||||
}
|
||||
|
||||
if (len > 0) {
|
||||
if (pendsize < pendlen + len) {
|
||||
pendsize = pendlen + len + 4096;
|
||||
pending = (pending ? realloc(pending, pendsize) :
|
||||
malloc(pendsize));
|
||||
if (!pending)
|
||||
fatalbox("Out of memory");
|
||||
}
|
||||
memcpy(pending+pendlen, p, len);
|
||||
pendlen += len;
|
||||
}
|
||||
}
|
||||
static int ssh_scp_recv(unsigned char *buf, int len) {
|
||||
SOCKET s;
|
||||
|
||||
outptr = buf;
|
||||
outlen = len;
|
||||
|
||||
/*
|
||||
* See if the pending-input block contains some of what we
|
||||
* need.
|
||||
*/
|
||||
if (pendlen > 0) {
|
||||
unsigned pendused = pendlen;
|
||||
if (pendused > outlen)
|
||||
pendused = outlen;
|
||||
memcpy(outptr, pending, pendused);
|
||||
memmove(pending, pending+pendused, pendlen-pendused);
|
||||
outptr += pendused;
|
||||
outlen -= pendused;
|
||||
pendlen -= pendused;
|
||||
if (pendlen == 0) {
|
||||
pendsize = 0;
|
||||
free(pending);
|
||||
pending = NULL;
|
||||
}
|
||||
if (outlen == 0)
|
||||
return len;
|
||||
}
|
||||
|
||||
while (outlen > 0) {
|
||||
fd_set readfds;
|
||||
s = back->socket();
|
||||
if (s == INVALID_SOCKET) {
|
||||
connection_open = FALSE;
|
||||
return 0;
|
||||
}
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(s, &readfds);
|
||||
if (select(1, &readfds, NULL, NULL, NULL) < 0)
|
||||
return 0; /* doom */
|
||||
back->msg(0, FD_READ);
|
||||
term_out();
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Loop through the ssh connection and authentication process.
|
||||
*/
|
||||
static void ssh_scp_init(void) {
|
||||
SOCKET s;
|
||||
|
||||
s = back->socket();
|
||||
if (s == INVALID_SOCKET)
|
||||
return;
|
||||
while (!back->sendok()) {
|
||||
fd_set readfds;
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(s, &readfds);
|
||||
if (select(1, &readfds, NULL, NULL, NULL) < 0)
|
||||
return; /* doom */
|
||||
back->msg(0, FD_READ);
|
||||
term_out();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Print an error message and exit after closing the SSH link.
|
||||
*/
|
||||
|
@ -194,7 +306,7 @@ static void bump(char *fmt, ...)
|
|||
|
||||
if (connection_open) {
|
||||
char ch;
|
||||
ssh_scp_send_eof();
|
||||
back->special(TS_EOF);
|
||||
ssh_scp_recv(&ch, 1);
|
||||
}
|
||||
exit(1);
|
||||
|
@ -278,9 +390,16 @@ static void do_cmd(char *host, char *user, char *cmd)
|
|||
if (portnumber)
|
||||
cfg.port = portnumber;
|
||||
|
||||
err = ssh_scp_init(cfg.host, cfg.port, cmd, &realhost);
|
||||
strncpy(cfg.remote_cmd, cmd, sizeof(cfg.remote_cmd));
|
||||
cfg.remote_cmd[sizeof(cfg.remote_cmd)-1] = '\0';
|
||||
cfg.nopty = TRUE;
|
||||
|
||||
back = &ssh_backend;
|
||||
|
||||
err = back->init(NULL, cfg.host, cfg.port, &realhost);
|
||||
if (err != NULL)
|
||||
bump("ssh_init: %s", err);
|
||||
ssh_scp_init();
|
||||
if (verbose && realhost != NULL)
|
||||
tell_user(stderr, "Connected to %s\n", realhost);
|
||||
|
||||
|
@ -398,7 +517,7 @@ static void run_err(const char *fmt, ...)
|
|||
strcpy(str, "\01scp: ");
|
||||
vsprintf(str+strlen(str), fmt, ap);
|
||||
strcat(str, "\n");
|
||||
ssh_scp_send(str, strlen(str));
|
||||
back->send(str, strlen(str));
|
||||
tell_user(stderr, "%s",str);
|
||||
va_end(ap);
|
||||
}
|
||||
|
@ -469,7 +588,7 @@ static void source(char *src)
|
|||
TIME_WIN_TO_POSIX(actime, atime);
|
||||
TIME_WIN_TO_POSIX(wrtime, mtime);
|
||||
sprintf(buf, "T%lu 0 %lu 0\n", mtime, atime);
|
||||
ssh_scp_send(buf, strlen(buf));
|
||||
back->send(buf, strlen(buf));
|
||||
if (response())
|
||||
return;
|
||||
}
|
||||
|
@ -478,7 +597,7 @@ static void source(char *src)
|
|||
sprintf(buf, "C0644 %lu %s\n", size, last);
|
||||
if (verbose)
|
||||
tell_user(stderr, "Sending file modes: %s", buf);
|
||||
ssh_scp_send(buf, strlen(buf));
|
||||
back->send(buf, strlen(buf));
|
||||
if (response())
|
||||
return;
|
||||
|
||||
|
@ -496,7 +615,7 @@ static void source(char *src)
|
|||
if (statistics) printf("\n");
|
||||
bump("%s: Read error", src);
|
||||
}
|
||||
ssh_scp_send(transbuf, k);
|
||||
back->send(transbuf, k);
|
||||
if (statistics) {
|
||||
stat_bytes += k;
|
||||
if (time(NULL) != stat_lasttime ||
|
||||
|
@ -509,7 +628,7 @@ static void source(char *src)
|
|||
}
|
||||
CloseHandle(f);
|
||||
|
||||
ssh_scp_send("", 1);
|
||||
back->send("", 1);
|
||||
(void) response();
|
||||
}
|
||||
|
||||
|
@ -538,7 +657,7 @@ static void rsource(char *src)
|
|||
sprintf(buf, "D0755 0 %s\n", last);
|
||||
if (verbose)
|
||||
tell_user(stderr, "Entering directory: %s", buf);
|
||||
ssh_scp_send(buf, strlen(buf));
|
||||
back->send(buf, strlen(buf));
|
||||
if (response())
|
||||
return;
|
||||
|
||||
|
@ -560,7 +679,7 @@ static void rsource(char *src)
|
|||
FindClose(dir);
|
||||
|
||||
sprintf(buf, "E\n");
|
||||
ssh_scp_send(buf, strlen(buf));
|
||||
back->send(buf, strlen(buf));
|
||||
(void) response();
|
||||
}
|
||||
|
||||
|
@ -592,7 +711,7 @@ static void sink(char *targ)
|
|||
if (targetshouldbedirectory && !targisdir)
|
||||
bump("%s: Not a directory", targ);
|
||||
|
||||
ssh_scp_send("", 1);
|
||||
back->send("", 1);
|
||||
while (1) {
|
||||
settime = 0;
|
||||
gottime:
|
||||
|
@ -616,13 +735,13 @@ static void sink(char *targ)
|
|||
case '\02': /* fatal error */
|
||||
bump("%s", buf+1);
|
||||
case 'E':
|
||||
ssh_scp_send("", 1);
|
||||
back->send("", 1);
|
||||
return;
|
||||
case 'T':
|
||||
if (sscanf(buf, "T%ld %*d %ld %*d",
|
||||
&mtime, &atime) == 2) {
|
||||
settime = 1;
|
||||
ssh_scp_send("", 1);
|
||||
back->send("", 1);
|
||||
goto gottime;
|
||||
}
|
||||
bump("Protocol error: Illegal time format");
|
||||
|
@ -672,7 +791,7 @@ static void sink(char *targ)
|
|||
continue;
|
||||
}
|
||||
|
||||
ssh_scp_send("", 1);
|
||||
back->send("", 1);
|
||||
|
||||
if (statistics) {
|
||||
stat_bytes = 0;
|
||||
|
@ -725,7 +844,7 @@ static void sink(char *targ)
|
|||
run_err("%s: Write error", namebuf);
|
||||
continue;
|
||||
}
|
||||
ssh_scp_send("", 1);
|
||||
back->send("", 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1032,7 +1151,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
if (connection_open) {
|
||||
char ch;
|
||||
ssh_scp_send_eof();
|
||||
back->special(TS_EOF);
|
||||
ssh_scp_recv(&ch, 1);
|
||||
}
|
||||
WSACleanup();
|
||||
|
|
12
scp.h
12
scp.h
|
@ -1,12 +0,0 @@
|
|||
/*
|
||||
* scp.h
|
||||
* Joris van Rantwijk, Aug 1999, Jun 2000.
|
||||
*/
|
||||
|
||||
/* Exported from ssh.c */
|
||||
extern int scp_flags;
|
||||
char * ssh_scp_init(char *host, int port, char *cmd, char **realhost);
|
||||
int ssh_scp_recv(unsigned char *buf, int len);
|
||||
void ssh_scp_send(unsigned char *buf, int len);
|
||||
void ssh_scp_send_eof(void);
|
||||
|
177
ssh.c
177
ssh.c
|
@ -13,7 +13,6 @@
|
|||
#include "putty.h"
|
||||
#include "tree234.h"
|
||||
#include "ssh.h"
|
||||
#include "scp.h"
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
|
@ -291,6 +290,11 @@ static void c_write (char *buf, int len) {
|
|||
c_write1(*buf++);
|
||||
}
|
||||
|
||||
static void c_writedata (char *buf, int len) {
|
||||
while (len--)
|
||||
c_write1(*buf++);
|
||||
}
|
||||
|
||||
struct Packet {
|
||||
long length;
|
||||
int type;
|
||||
|
@ -1645,7 +1649,7 @@ static void ssh1_protocol(unsigned char *in, int inlen, int ispkt) {
|
|||
if (pktin.type == SSH1_SMSG_STDOUT_DATA ||
|
||||
pktin.type == SSH1_SMSG_STDERR_DATA) {
|
||||
long len = GET_32BIT(pktin.body);
|
||||
c_write(pktin.body+4, len);
|
||||
c_writedata(pktin.body+4, len);
|
||||
} else if (pktin.type == SSH1_MSG_DISCONNECT) {
|
||||
ssh_state = SSH_STATE_CLOSED;
|
||||
logevent("Received disconnect request");
|
||||
|
@ -2176,7 +2180,7 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt)
|
|||
|
||||
if (!(flags & FLAG_INTERACTIVE)) {
|
||||
char prompt[200];
|
||||
sprintf(prompt, "%s@%s's password: ", cfg.username, savedhost);
|
||||
sprintf(prompt, "%.90s@%.90s's password: ", cfg.username, savedhost);
|
||||
if (!ssh_get_password(prompt, password, sizeof(password))) {
|
||||
/*
|
||||
* get_password failed to get a password (for
|
||||
|
@ -2365,7 +2369,7 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt)
|
|||
continue; /* extended but not stderr */
|
||||
ssh2_pkt_getstring(&data, &length);
|
||||
if (data) {
|
||||
c_write(data, length);
|
||||
c_writedata(data, length);
|
||||
/*
|
||||
* Enlarge the window again at the remote side,
|
||||
* just in case it ever runs down and they fail
|
||||
|
@ -2592,171 +2596,6 @@ static void ssh_special (Telnet_Special code) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read and decrypt one incoming SSH packet.
|
||||
* (only used by pSCP)
|
||||
*/
|
||||
static void get_packet(void)
|
||||
{
|
||||
unsigned char buf[4096], *p;
|
||||
long to_read;
|
||||
int len;
|
||||
|
||||
p = NULL;
|
||||
len = 0;
|
||||
|
||||
while ((to_read = s_rdpkt(&p, &len)) > 0) {
|
||||
if (to_read > sizeof(buf)) to_read = sizeof(buf);
|
||||
len = s_read(buf, to_read);
|
||||
if (len != to_read) {
|
||||
closesocket(s);
|
||||
s = INVALID_SOCKET;
|
||||
return;
|
||||
}
|
||||
p = buf;
|
||||
}
|
||||
|
||||
assert(len == 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Receive a block of data over the SSH link. Block until
|
||||
* all data is available. Return nr of bytes read (0 if lost connection).
|
||||
* (only used by pSCP)
|
||||
*/
|
||||
int ssh_scp_recv(unsigned char *buf, int len)
|
||||
{
|
||||
static int pending_input_len = 0;
|
||||
static unsigned char *pending_input_ptr;
|
||||
int to_read = len;
|
||||
|
||||
if (pending_input_len >= to_read) {
|
||||
memcpy(buf, pending_input_ptr, to_read);
|
||||
pending_input_ptr += to_read;
|
||||
pending_input_len -= to_read;
|
||||
return len;
|
||||
}
|
||||
|
||||
if (pending_input_len > 0) {
|
||||
memcpy(buf, pending_input_ptr, pending_input_len);
|
||||
buf += pending_input_len;
|
||||
to_read -= pending_input_len;
|
||||
pending_input_len = 0;
|
||||
}
|
||||
|
||||
if (s == INVALID_SOCKET)
|
||||
return 0;
|
||||
while (to_read > 0) {
|
||||
get_packet();
|
||||
if (s == INVALID_SOCKET)
|
||||
return 0;
|
||||
if (pktin.type == SSH1_SMSG_STDOUT_DATA) {
|
||||
int plen = GET_32BIT(pktin.body);
|
||||
if (plen <= to_read) {
|
||||
memcpy(buf, pktin.body + 4, plen);
|
||||
buf += plen;
|
||||
to_read -= plen;
|
||||
} else {
|
||||
memcpy(buf, pktin.body + 4, to_read);
|
||||
pending_input_len = plen - to_read;
|
||||
pending_input_ptr = pktin.body + 4 + to_read;
|
||||
to_read = 0;
|
||||
}
|
||||
} else if (pktin.type == SSH1_SMSG_STDERR_DATA) {
|
||||
int plen = GET_32BIT(pktin.body);
|
||||
fwrite(pktin.body + 4, plen, 1, stderr);
|
||||
} else if (pktin.type == SSH1_MSG_DISCONNECT) {
|
||||
logevent("Received disconnect request");
|
||||
} else if (pktin.type == SSH1_SMSG_SUCCESS ||
|
||||
pktin.type == SSH1_SMSG_FAILURE) {
|
||||
/* ignore */
|
||||
} else if (pktin.type == SSH1_SMSG_EXIT_STATUS) {
|
||||
char logbuf[100];
|
||||
sprintf(logbuf, "Remote exit status: %d", GET_32BIT(pktin.body));
|
||||
logevent(logbuf);
|
||||
send_packet(SSH1_CMSG_EXIT_CONFIRMATION, PKT_END);
|
||||
logevent("Closing connection");
|
||||
closesocket(s);
|
||||
s = INVALID_SOCKET;
|
||||
} else {
|
||||
bombout(("Strange packet received: type %d", pktin.type));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a block of data over the SSH link.
|
||||
* Block until all data is sent.
|
||||
* (only used by pSCP)
|
||||
*/
|
||||
void ssh_scp_send(unsigned char *buf, int len)
|
||||
{
|
||||
if (s == INVALID_SOCKET)
|
||||
return;
|
||||
send_packet(SSH1_CMSG_STDIN_DATA,
|
||||
PKT_INT, len, PKT_DATA, buf, len, PKT_END);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send an EOF notification to the server.
|
||||
* (only used by pSCP)
|
||||
*/
|
||||
void ssh_scp_send_eof(void)
|
||||
{
|
||||
if (s == INVALID_SOCKET)
|
||||
return;
|
||||
send_packet(SSH1_CMSG_EOF, PKT_END);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up the connection, login on the remote host and
|
||||
* start execution of a command.
|
||||
* Returns an error message, or NULL on success.
|
||||
* (only used by pSCP)
|
||||
*/
|
||||
char *ssh_scp_init(char *host, int port, char *cmd, char **realhost)
|
||||
{
|
||||
char buf[160], *p;
|
||||
|
||||
#ifdef MSCRYPTOAPI
|
||||
if (crypto_startup() == 0)
|
||||
return "Microsoft high encryption pack not installed!";
|
||||
#endif
|
||||
|
||||
p = connect_to_host(host, port, realhost);
|
||||
if (p != NULL)
|
||||
return p;
|
||||
|
||||
random_init();
|
||||
|
||||
if (!do_ssh_init())
|
||||
return "Protocol initialisation error";
|
||||
|
||||
/* Exchange keys and login */
|
||||
do {
|
||||
get_packet();
|
||||
if (s == INVALID_SOCKET)
|
||||
return "Connection closed by remote host";
|
||||
} while (!do_ssh1_login(NULL, 0, 1));
|
||||
|
||||
if (ssh_state == SSH_STATE_CLOSED) {
|
||||
closesocket(s);
|
||||
s = INVALID_SOCKET;
|
||||
return "Session initialisation error";
|
||||
}
|
||||
|
||||
/* Execute command */
|
||||
sprintf(buf, "Sending command: %.100s", cmd);
|
||||
logevent(buf);
|
||||
send_packet(SSH1_CMSG_EXEC_CMD, PKT_STR, cmd, PKT_END);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static SOCKET ssh_socket(void) { return s; }
|
||||
|
||||
static int ssh_sendok(void) { return ssh_send_ok; }
|
||||
|
|
Загрузка…
Ссылка в новой задаче