1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-07-02 03:52:49 -05:00

Provide Uppity with a built-in old-style scp server.

Like the SFTP server, this is implemented in-process rather than by
invoking a separate scp server binary.

It also uses the internal SftpServer abstraction for access to the
server's filesystem, which means that when (or if) I implement an
alternative SftpServer implementing a dummy file system for test suite
purposes, this scp server should automatically start using it too.

As a bonus, the new scpserver.c contains a large comment documenting
my understanding of the SCP protocol, which I previously didn't have
even a de-facto or post-hoc spec for. I don't claim it's authoritative
- it's all reverse-engineered from my own code and observing other
implementations in action - but at least it'll make it easier to
refresh my own memory of what's going on the next time I need to do
something to either this code or PSCP.
This commit is contained in:
Simon Tatham
2018-10-20 11:19:17 +01:00
parent 18d7998008
commit 8a60fdaa57
4 changed files with 1515 additions and 1 deletions

40
sftp.h
View File

@ -56,6 +56,8 @@
#define SFTP_PROTO_VERSION 3
#define PERMS_DIRECTORY 040000
/*
* External references. The sftp client module sftp.c expects to be
* able to get at these functions.
@ -477,3 +479,41 @@ struct DefaultSftpReplyBuilder {
*/
struct sftp_packet *sftp_handle_request(
SftpServer *srv, struct sftp_packet *request);
/* ----------------------------------------------------------------------
* Not exactly SFTP-related, but here's a system that implements an
* old-fashioned SCP server module, given an SftpServer vtable to use
* as its underlying filesystem access.
*/
typedef struct ScpServer ScpServer;
typedef struct ScpServerVtable ScpServerVtable;
struct ScpServer {
const struct ScpServerVtable *vt;
};
struct ScpServerVtable {
void (*free)(ScpServer *s);
int (*send)(ScpServer *s, const void *data, size_t length);
void (*throttle)(ScpServer *s, int throttled);
void (*eof)(ScpServer *s);
};
#define scp_free(s) ((s)->vt->free(s))
#define scp_send(s, data, len) ((s)->vt->send(s, data, len))
#define scp_throttle(s, th) ((s)->vt->throttle(s, th))
#define scp_eof(s) ((s)->vt->eof(s))
/*
* Create an ScpServer by calling this function, giving it the command
* you received from the SSH client to execute. If that command is
* recognised as an scp command, it will construct an ScpServer object
* and return it; otherwise, it will return NULL, and you should
* execute the command in whatever way you normally would.
*
* The ScpServer will generate output for the client by writing it to
* the provided SshChannel using sshfwd_write; you pass it input using
* the send method in its own vtable.
*/
ScpServer *scp_recognise_exec(
SshChannel *sc, const SftpServerVtable *sftpserver_vt, ptrlen command);