Roxen.git / server / protocols / ftp.pike

version» Context lines:

Roxen.git/server/protocols/ftp.pike:2058:    if (!file) {    file = ([ "error":404 ]);    }    send(550, ({ sprintf(LOCALE(94, "'%s': %s: No such file or directory."),    cmd, f) }));    break;    }    session->conf->log(file, session);    }    +  private void send_welcome() +  { +  string s = port_obj->query_option("FTPWelcome"); +  +  s = replace(s, +  ({ "$roxen_version", "$roxen_build", "$full_version", +  "$pike_version", "$ident", +  "$site", }), +  ({ roxen->roxen_ver, roxen->roxen_build, +  roxen->real_version, version(), roxen->version(), +  conf->query_name(), })); +  +  send(220, s/"\n", 1); +  } +     private mapping open_file(string fname, object session, string cmd)    {    object|array|mapping file;       file = stat_file(fname, session);       // The caller is assumed to have made a new session object for us    // but not to set not_query in it..    session->not_query = fname;   
Roxen.git/server/protocols/ftp.pike:2963:       if (session_limit <= 0) return 1;       if (session_limit <= (port_obj->ftp_sessions[user])) {    return 0; // Session limit reached.    }       return 1;    }    +  Configuration find_conf() +  //! Return the conf for the first default server we find. +  //! If no default server is found, return the first conf found. +  { +  Configuration conf; +  foreach(port_obj->sorted_urls, string url) { +  mapping(string:mixed) port_info = port_obj->urls[url]; +  if (!port_info) { +  continue; +  } +  if (!conf) { +  conf = port_info->conf; +  } +  if (port_info->conf->query("default_server")) { +  conf = port_info->conf; +  return conf; +  } +  } +  return conf; +  } +  +  Configuration find_conf_for_host(string hostname) +  { +  if (!hostname) { +  return 0; +  } +  hostname = lower_case(hostname); +  foreach(port_obj->sorted_urls, string url) { +  mapping(string:mixed) port_info = port_obj->urls[url]; +  if (!port_info) { +  continue; +  } +  if (glob(lower_case(port_info->hostname) + "*", hostname)) { +  return port_info->conf; +  } +  } +  // Try again different approach. +  // NB: Don't merge this loop with the one above since we want to try glob() +  // on all confiured hostnames (globs or not) before trying with +  // has_prefix(). +  foreach(port_obj->sorted_urls, string url) { +  mapping(string:mixed) port_info = port_obj->urls[url]; +  if (!port_info) { +  continue; +  } +  if (has_prefix(lower_case(port_info->hostname), hostname)) { +  return port_info->conf; +  } +  } +  return 0; +  } +     /*    * FTP commands begin here    */       // Set to 1 by EPSV ALL.    int epsv_only;       void ftp_REIN(string|int args)    {    logout();
Roxen.git/server/protocols/ftp.pike:2990:    dataport_addr = 0;    dataport_port = 0;    mode = "A";    cwd = "/";    auth_user = 0;    user = password = 0;    curr_pipe = 0;    restart_point = 0;    logged_in = 0;    roxen.set_locale(); +  m_delete(master_session->misc, "host");    m_delete(master_session->misc, "accept-language"); -  +  master_session->cached_url_base = 0;    master_session->misc->pref_languages->languages = ({}); -  +  master_session->conf = conf = find_conf();    if (pasv_port) {    destruct(pasv_port);    pasv_port = 0;    }    if (args != 1) {    // Not called by QUIT or AUTH.    low_send(220, ({ LOCALE(106, "Server ready for new user.") }));       // RFC 4217 13:    // When this command is processed by the server, the TLS    // session(s) MUST be cleared and the control and data    // connections revert to unprotected, clear communications.    to_send->put(2); // End TLS marker.    use_ssl = SSL_NONE;       busy = 0;    next_cmd();    }    }    -  +  void ftp_HOST(string args) +  { +  if (!expect_argument("HOST", args)) return; +  +  if (logged_in) { +  // RFC 7151 3: +  // Server-FTP processes MUST treat a situation in which the +  // HOST command is issued after the user has been +  // authenticated as an erroneous sequence of commands and +  // return a 503 reply. +  send(503, ({ LOCALE(204, "HOST not allowed after login.") })); +  return; +  } +  +  if (args[0] == '[') { +  // IPv6 literal address. +  if (args[-1] != ']') { +  send(501, ({ LOCALE(205, "Invalid HOST syntax.") })); +  return; +  } +  } else if (has_value(args, ":")) { +  send(501, ({ LOCALE(205, "Invalid HOST syntax.") })); +  return; +  } +  +  // FIXME: For IPv4 and IPv6 literal addresses, validate that +  // the address matches our port. +  // +  // RFC 7151 3.1: +  // That being said, if the IPv4 or IPv6 literal address +  // specified by the client does not match the literal address +  // for the server, the server MUST respond with a 504 reply to +  // indicate that the IPv4 or IPv6 literal address is not valid. +  +  if (!roxen.is_ip(args)) { +  args = lower_case(args); +  +  Configuration new_conf = find_conf_for_host(args); +  +  if (!new_conf) { +  send(504, ({ LOCALE(206, "Unknown host.") })); +  return; +  } +  master_session->conf = conf = new_conf; +  master_session->misc->host = args; +  master_session->cached_url_base = 0; +  +  // Support delayed loading. +  if (!conf->inited) { +  conf->enable_all_modules(); +  } +  } +  +  send_welcome(); +  } +     void ftp_AUTH(string args)    {    if (!expect_argument("AUTH", args)) return;       args = upper_case(replace(args, ({ " ", "\t" }), ({ "", "" })));       // RFC 4217 17:    // To request the TLS protocol in accordance with this document,    // the client MUST use 'TLS'    //
Roxen.git/server/protocols/ftp.pike:3533:    if ((((int)segments[3]) <= 0) || (((int)segments[3]) > 65535)) {    send(501, ({ sprintf(LOCALE(146, "Bad port number: '%s'"), segments[3]) }));    return;    }    dataport_addr = segments[2];    dataport_port = (int)segments[3];       if (pasv_port) {    destruct(pasv_port);    } -  send(200, ({ sprintf(LOCALE(147, "EPRT command ok (%d port %d)"), +  send(200, ({ sprintf(LOCALE(147, "EPRT command ok (%s port %d)"),    dataport_addr, dataport_port) }));    }       void ftp_PASV(string args)    {    // Required by RFC 1123 4.1.2.6    int min;    int max;       if (epsv_only) {
Roxen.git/server/protocols/ftp.pike:4484: Inside #if 0
   } else if (!conf->extra_statistics->ftp->commands) {    conf->extra_statistics->ftp->commands = ([ cmd:1 ]);    } else {    conf->extra_statistics->ftp->commands[cmd]++;    }   #endif /* 0 */       if (cmd_help[cmd]) {    if (!logged_in) {    if (!(< "REIN", "USER", "PASS", "SYST", "AUTH", -  "ACCT", "QUIT", "ABOR", "HELP", "FEAT" >)[cmd]) { +  "ACCT", "QUIT", "ABOR", "HELP", "FEAT", "HOST" >)[cmd]) {    send(530, ({ LOCALE(200, "You need to login first.") }));       return;    }    }    if (!port_obj->query_option("rfc2428_support") &&    (< "EPRT", "EPSV" >)[cmd]) {    send(502, ({ sprintf(LOCALE(201, "support for '%s' is disabled."), cmd) }));    return;    }
Roxen.git/server/protocols/ftp.pike:4605:    port_obj->sessions--;    if (master_session) {    destruct(master_session);    }    }       void create(object fd, object c)    {    port_obj = c;    -  // FIXME: Only supports one configuration! -  conf = port_obj->urls[port_obj->sorted_urls[0]]->conf; +  conf = find_conf();       // Support delayed loading.    if (!conf->inited) {    conf->enable_all_modules();    }      #if 0    werror("FTP: conf:%O\n"    "FTP:urls:%O\n",    mkmapping(indices(conf), values(conf)), port_obj->urls);
Roxen.git/server/protocols/ftp.pike:4640:    master_session->misc->pref_languages = PrefLanguages();    ::create(fd, got_command, 0, con_closed, ([]));       array a = fd->query_address(1)/" ";    local_addr = a[0];    local_port = (int)a[1];    e_mode = has_value(local_addr, ":")?"2":"1";       call_out(timeout, FTP2_TIMEOUT);    -  string s = c->query_option("FTPWelcome"); -  -  s = replace(s, -  ({ "$roxen_version", "$roxen_build", "$full_version", -  "$pike_version", "$ident", }), -  ({ roxen->roxen_ver, roxen->roxen_build, -  roxen->real_version, version(), roxen->version() })); -  -  send(220, s/"\n", 1); +  send_welcome();    }   };      void create(object f, object c)   {    if (f)    {    c->sessions++;    c->ftp_users++;    if (f->set_keepalive) {    // Try to keep stupid firewalls from killing    // the connection during long uploads.    f->set_keepalive(1);    }    FTPSession(f, c);    }   }