Roxen.git / server / plugins / protocols / ftp.pike

version» Context lines:

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;