Roxen.git
/
server
/
plugins
/
protocols
/
ftp.pike
version
»
Context lines:
10
20
40
80
file
none
3
Roxen.git/server/plugins/protocols/ftp.pike:1:
// This is a roxen protocol module. // Copyright © 1997 - 2001, Roxen IS. /* * FTP protocol mk 2 *
-
* $Id: ftp.pike,v 2.
90
2004/05/17 13:
15
:
07
mani Exp $
+
* $Id: ftp.pike,v 2.
91
2004/05/17 13:
16
:
09
mani Exp $
* * Henrik Grubbström <grubba@roxen.com> */ /* * TODO: * * How much is supposed to be logged? */
Roxen.git/server/plugins/protocols/ftp.pike:26:
* RFC 1635 How to Use Anonymous FTP * * RFC's describing extra commands: * * RFC 683 FTPSRV - Tenex extension for paged files * RFC 737 FTP Extension: XSEN * RFC 743 FTP extension: XRSQ/XRCP * RFC 775 DIRECTORY ORIENTED FTP COMMANDS * RFC 949 FTP unique-named store command * RFC 1639 FTP Operation Over Big Address Records (FOOBAR)
+
* RFC 2228 FTP Security Extensions
* RFC 2428 FTP Extensions for IPv6 and NATs * * IETF draft 12 Extended Directory Listing, TVFS, * and Restart Mechanism for FTP * * RFC's with recomendations and discussions: * * RFC 607 Comments on the File Transfer Protocol * RFC 614 Response to RFC 607, "Comments on the File Transfer Protocol" * RFC 624 Comments on the File Transfer Protocol
Roxen.git/server/plugins/protocols/ftp.pike:1351:
"MDTM":"<sp> path-name (Modification time)", "SIZE":"<sp> path-name (Size)", "MLST":"<sp> path-name (Machine Processing List File)", "MLSD":"<sp> path-name (Machine Processing List Directory)", "OPTS":"<sp> command <sp> options (Set Command-specific Options)", // These are from RFC 2428 "EPRT":"<sp> <d>net-prt<d>net-addr<d>tcp-port<d> (Extended Address Port)", "EPSV":"[<sp> net-prt|ALL] (Extended Address Passive Mode)",
+
// These are from RFC 2228 (FTP Security Extensions)
+
"AUTH":"security-mechanism (Authentication/Security Mechanism)",
+
"ADAT":"security-data (Authentication/Security Data)",
+
"PBSZ":"<sp> size (Protection Buffer SiZe)",
+
"PROT":"<sp> [ C | S | E | P ] (Data Channel Protection Level)",
+
"CCC":"(Clear Command Channel)",
+
"MIC":"command (Integrity Protected Command)",
+
"CONF":"command (Confidentiality Protected Command)",
+
"ENC":"command (Privacy Protected Command)",
+
// These are in RFC 1639 "LPRT":"<sp> <long-host-port> (Long Port)", "LPSV":"(Long Passive)", // Commands in the order from RFC 959 // Login "USER":"<sp> username (Change user)", "PASS":"<sp> password (Change password)", "ACCT":"<sp> <account-information> (Account)",
Roxen.git/server/plugins/protocols/ftp.pike:1617:
/* * PASV handling */ static private object pasv_port; static private function(object, mixed:void) pasv_callback; static private mixed pasv_args; static private array(object) pasv_accepted = ({}); void pasv_accept_callback(mixed id) {
+
DWRITE("FTP: pasv_accept_callback(%O)...\n", id);
touch_me(); if(pasv_port) { object fd = pasv_port->accept(); if(fd) { // On a multihomed server host, the default data transfer port // (L-1) MUST be associated with the same local IP address as // the corresponding control connection to port L. // RFC 1123 4.1.2.12 array(string) remote = (fd->query_address()||"? ?")/" "; #ifdef FD_DEBUG mark_fd(fd->query_fd(), "ftp communication: -> "+remote[0]+":"+remote[1]); #endif
-
+
if (use_ssl) {
+
fd = SSL.sslfile(fd, port_obj->ctx);
+
DWRITE("FTP: Created an sslfile: %O\n", fd);
+
}
if(pasv_callback) { pasv_callback(fd, "", @pasv_args); pasv_callback = 0; } else { pasv_accepted += ({ fd }); } } } }
Roxen.git/server/plugins/protocols/ftp.pike:1704:
if (!f->open_socket()) { DWRITE("FTP: socket() failed. Out of sockets?\n"); fun(0, 0, @args); destruct(f); return; } } } privs = 0;
+
Stdio.File raw_connection = f;
+
+
if (use_ssl) {
+
f = (object)SSL.sslfile(f, port_obj->ctx, 1, 0);
+
}
+
f->set_nonblocking(lambda(mixed ignored, string data) { DWRITE("FTP: async_connect ok. Got data.\n"); f->set_nonblocking(0,0,0); fun(f, data, @args); }, lambda(mixed ignored) { DWRITE("FTP: async_connect ok.\n"); f->set_nonblocking(0,0,0); fun(f, "", @args); }, lambda(mixed ignored) { DWRITE("FTP: connect_and_send failed\n"); destruct(f); fun(0, 0, @args); }); #ifdef FD_DEBUG
-
mark_fd(
f
->query_fd(), sprintf("ftp communication: %s:%d -> %s:%d",
+
mark_fd(
raw_connection
->query_fd(),
+
sprintf("ftp communication: %s:%d -> %s:%d",
local_addr, local_port - 1, dataport_addr, dataport_port)); #endif
-
if(catch(
f
->connect(dataport_addr, dataport_port))) {
+
if(catch(
raw_connection
->connect(dataport_addr, dataport_port))) {
DWRITE("FTP: Illegal internet address in connect in async comm.\n"); destruct(f); fun(0, 0, @args); return; } } /* * Data connection handling */ static private void send_done_callback( object fd, object session, int amount ) { DWRITE("FTP: send_done_callback()\n"); if(fd) {
-
+
//DWRITE("FTP: fd: %O: %O\n", fd, mkmapping(indices(fd), values(fd)));
if (fd->set_blocking) { fd->set_blocking(); // Force close() to flush any buffers. }
-
BACKEND_CLOSE(fd);
+
call_out(fd->close, 0);
+
fd = 0;
+
//
BACKEND_CLOSE(fd);
} curr_pipe = 0; if (session && session->file) { session->file->len = amount; session->conf->log(session->file, session); session->file = 0; } send(226, ({ "Transfer complete." }));
Roxen.git/server/plugins/protocols/ftp.pike:2574:
return 1; } /* * FTP commands begin here */ // Set to 1 by EPSV ALL. int epsv_only;
+
// Set to 1 by PROT S,E and P, cleared by PROT C.
+
int use_ssl;
void ftp_REIN(string|int args) { logout(); // FIXME: What about EPSV ALL mode? RFC 2428 doesn't say. // I guess that it shouldn't be reset. // Compatibility... m_delete(master_session->misc, "home");
Roxen.git/server/plugins/protocols/ftp.pike:2865:
// Reinitialize the connection. ftp_REIN(1); } void ftp_BYE(string args) { ftp_QUIT(args); }
+
void ftp_PBSZ(string args)
+
{
+
if (!expect_argument("PROT", args)) return;
+
+
send(200, ({ "PBSZ=0" }));
+
}
+
+
void ftp_PROT(string args)
+
{
+
if (!expect_argument("PROT", args)) return;
+
+
args = upper_case(replace(args, ({ " ", "\t" }), ({ "", "" })));
+
switch(args) {
+
case "C": // Clear.
+
use_ssl = 0;
+
break;
+
case "S": // Safe.
+
case "E": // Confidential.
+
case "P": // Private.
+
if (!port_obj->ctx) {
+
send(536, ({ sprintf("Only supported over FTPS") }));
+
return;
+
}
+
use_ssl = 1;
+
break;
+
default:
+
send(504, ({ sprintf("Unknown protection level: %s", args) }));
+
return;
+
}
+
send(200, ({ "OK" }));
+
}
+
void ftp_PORT(string args) { if (epsv_only) { send(530, ({ "'PORT': Method not allowed in EPSV ALL mode." })); return; } int a, b, c, d, e, f; if (sscanf(args||"", "%d,%d,%d,%d,%d,%d", a, b, c, d, e, f)<6)
Roxen.git/server/plugins/protocols/ftp.pike:2995:
epsv_only = 1; send(200, ({ "Entering EPSV ALL mode." })); } else { // FIXME: No support for IPv6 yet. send(522, ({ "Network protocol not supported, use (1)" })); } return; } if (pasv_port) destruct(pasv_port);
+
pasv_port = Stdio.Port(0, pasv_accept_callback, local_addr); /* FIXME: Hmm, getting the address from an anonymous port seems not * to work on NT... */ int port=(int)((pasv_port->query_address()/" ")[1]); min = port_obj->query_option("passive_port_min"); max = port_obj->query_option("passive_port_max"); if ((port < min) || (port > max)) { if (max > 65535) max = 65535;