Beispiel #1
0
static void
handle_mdtm(struct vsf_session* p_sess)
{
  static struct vsf_sysutil_statbuf* s_p_statbuf;
  int retval;
  if (!vsf_access_check_file(&p_sess->ftp_arg_str))
  {
    vsf_cmdio_write(p_sess, FTP_NOPERM, "Permission denied.");
    return;
  }
  retval = str_stat(&p_sess->ftp_arg_str, &s_p_statbuf);
  if (retval != 0 || !vsf_sysutil_statbuf_is_regfile(s_p_statbuf))
  {
    vsf_cmdio_write(p_sess, FTP_FILEFAIL,
                    "Could not get file modification time.");
  }
  else
  {
    static struct mystr s_mdtm_res_str;
    str_alloc_text(&s_mdtm_res_str,
                   vsf_sysutil_statbuf_get_numeric_date(
                     s_p_statbuf, tunable_use_localtime));
    vsf_cmdio_write_str(p_sess, FTP_MDTMOK, &s_mdtm_res_str);
  }
}
Beispiel #2
0
static void
handle_rnto(struct vsf_session* p_sess)
{
  int retval;
  /* If we didn't get a RNFR, throw a wobbly */
  if (str_isempty(&p_sess->rnfr_filename_str))
  {
    vsf_cmdio_write(p_sess, FTP_NEEDRNFR,
                    "RNFR required first.");
    return;
  }
  /* NOTE - might overwrite destination file. Not a concern because the same
   * could be accomplished with DELE.
   */
  retval = str_rename(&p_sess->rnfr_filename_str, &p_sess->ftp_arg_str);
  /* Clear the RNFR filename; start the two stage process again! */
  str_free(&p_sess->rnfr_filename_str);
  if (retval == 0)
  {
    vsf_cmdio_write(p_sess, FTP_RENAMEOK, "Rename successful.");
  }
  else
  {
    vsf_cmdio_write(p_sess, FTP_FILEFAIL, "Rename failed.");
  }
}
Beispiel #3
0
static struct vsf_transfer_ret
do_file_send_sendfile(struct vsf_session* p_sess, int net_fd, int file_fd,
                      filesize_t curr_file_offset, filesize_t bytes_to_send)
{
    int retval;
    unsigned int chunk_size = 0;
    struct vsf_transfer_ret ret_struct = { 0, 0 };
    filesize_t init_file_offset = curr_file_offset;
    filesize_t bytes_sent;
    if (p_sess->bw_rate_max)
    {
        chunk_size = get_chunk_size();
    }
    /* Just because I can ;-) */
    retval = vsf_sysutil_sendfile(net_fd, file_fd, &curr_file_offset,
                                  bytes_to_send, chunk_size);
    bytes_sent = curr_file_offset - init_file_offset;
    ret_struct.transferred = bytes_sent;
    if (vsf_sysutil_retval_is_error(retval))
    {
        vsf_cmdio_write(p_sess, FTP_BADSENDNET, "Failure writing network stream.");
        ret_struct.retval = -1;
        return ret_struct;
    }
    else if (bytes_sent != bytes_to_send)
    {
        vsf_cmdio_write(p_sess, FTP_BADSENDFILE,
                        "Failure writing network stream.");
        ret_struct.retval = -1;
        return ret_struct;
    }
    vsf_cmdio_write(p_sess, FTP_TRANSFEROK, "File send OK.");
    return ret_struct;
}
Beispiel #4
0
int
vsf_ftpdataio_get_pasv_fd(struct vsf_session* p_sess)
{
  int remote_fd;
  struct vsf_sysutil_sockaddr* p_accept_addr = 0;
  vsf_sysutil_sockaddr_alloc(&p_accept_addr);
  remote_fd = vsf_sysutil_accept_timeout(p_sess->pasv_listen_fd, p_accept_addr,
                                         tunable_accept_timeout);
  if (vsf_sysutil_retval_is_error(remote_fd))
  {
    vsf_cmdio_write(p_sess, FTP_BADSENDCONN,
                    "Failed to establish connection.");
    vsf_sysutil_sockaddr_clear(&p_accept_addr);
    return remote_fd;
  }
  /* SECURITY:
   * Reject the connection if it wasn't from the same IP as the
   * control connection.
   */
  if (!tunable_pasv_promiscuous)
  {
    if (!vsf_sysutil_sockaddr_addr_equal(p_sess->p_remote_addr, p_accept_addr))
    {
      vsf_cmdio_write(p_sess, FTP_BADSENDCONN, "Security: Bad IP connecting.");
      vsf_sysutil_close(remote_fd);
      vsf_sysutil_sockaddr_clear(&p_accept_addr);
      return -1;
    }
  }
  vsf_sysutil_sockaddr_clear(&p_accept_addr);
  init_data_sock_params(p_sess, remote_fd);
  vsf_sysutil_set_lfp(remote_fd);
  return remote_fd;
}
Beispiel #5
0
static void
handle_size(struct vsf_session* p_sess)
{
  /* Note - in ASCII mode, are supposed to return the size after taking into
   * account ASCII linefeed conversions. At least this is what wu-ftpd does in
   * version 2.6.1. Proftpd-1.2.0pre fails to do this.
   * I will not do it because it is a potential I/O DoS.
   */
  static struct vsf_sysutil_statbuf* s_p_statbuf;
  int retval;
  if (!vsf_access_check_file(&p_sess->ftp_arg_str))
  {
    vsf_cmdio_write(p_sess, FTP_NOPERM, "Permission denied.");
    return;
  }
  retval = str_stat(&p_sess->ftp_arg_str, &s_p_statbuf);
  if (retval != 0 || !vsf_sysutil_statbuf_is_regfile(s_p_statbuf))
  {
    vsf_cmdio_write(p_sess, FTP_FILEFAIL, "Could not get file size.");
  }
  else
  {
    static struct mystr s_size_res_str;
    str_alloc_filesize_t(&s_size_res_str,
                         vsf_sysutil_statbuf_get_size(s_p_statbuf));
    vsf_cmdio_write_str(p_sess, FTP_SIZEOK, &s_size_res_str);
  }
}
Beispiel #6
0
static void
handle_site(struct vsf_session* p_sess)
{
  static struct mystr s_site_args_str;
  /* What SITE sub-command is it? */
  str_split_char(&p_sess->ftp_arg_str, &s_site_args_str, ' ');
  str_upper(&p_sess->ftp_arg_str);
  if (tunable_write_enable &&
      tunable_chmod_enable &&
      str_equal_text(&p_sess->ftp_arg_str, "CHMOD"))
  {
    handle_site_chmod(p_sess, &s_site_args_str);
  }
  else if (str_equal_text(&p_sess->ftp_arg_str, "UMASK"))
  {
    handle_site_umask(p_sess, &s_site_args_str);
  }
  else if (str_equal_text(&p_sess->ftp_arg_str, "HELP"))
  {
    vsf_cmdio_write(p_sess, FTP_SITEHELP, "CHMOD UMASK HELP");
  }
  else
  {
    vsf_cmdio_write(p_sess, FTP_BADCMD, "Unknown SITE command.");
  }
}
Beispiel #7
0
void
handle_prot(struct vsf_session* p_sess)
{
  str_upper(&p_sess->ftp_arg_str);
  if (!p_sess->control_use_ssl)
  {
    vsf_cmdio_write(p_sess, FTP_BADPROT, "PROT needs a secure connection.");
  }
  else if (str_equal_text(&p_sess->ftp_arg_str, "C"))
  {
    p_sess->data_use_ssl = 0;
    vsf_cmdio_write(p_sess, FTP_PROTOK, "PROT now Clear.");
  }
  else if (str_equal_text(&p_sess->ftp_arg_str, "P"))
  {
    p_sess->data_use_ssl = 1;
    vsf_cmdio_write(p_sess, FTP_PROTOK, "PROT now Private.");
  }
  else if (str_equal_text(&p_sess->ftp_arg_str, "S") ||
           str_equal_text(&p_sess->ftp_arg_str, "E"))
  {
    vsf_cmdio_write(p_sess, FTP_NOHANDLEPROT, "PROT not supported.");
  }
  else
  {
    vsf_cmdio_write(p_sess, FTP_NOSUCHPROT, "PROT not recognized.");
  }
}
Beispiel #8
0
static void
handle_rnfr(struct vsf_session* p_sess)
{
  static struct vsf_sysutil_statbuf* p_statbuf;
  int retval;
  /* Clear old value */
  str_free(&p_sess->rnfr_filename_str);
  if (!vsf_access_check_file(&p_sess->ftp_arg_str))
  {
    vsf_cmdio_write(p_sess, FTP_NOPERM, "Permission denied.");
    return;
  }
  /* Does it exist? */
  retval = str_stat(&p_sess->ftp_arg_str, &p_statbuf);
  if (retval == 0)
  {
    /* Yes */
    str_copy(&p_sess->rnfr_filename_str, &p_sess->ftp_arg_str);
    vsf_cmdio_write(p_sess, FTP_RNFROK, "Ready for RNTO.");
  }
  else
  {
    vsf_cmdio_write(p_sess, FTP_FILEFAIL, "RNFR command failed.");
  }
}
Beispiel #9
0
void
handle_auth(struct vsf_session* p_sess)
{
  str_upper(&p_sess->ftp_arg_str);
  if (str_equal_text(&p_sess->ftp_arg_str, "TLS") ||
      str_equal_text(&p_sess->ftp_arg_str, "TLS-C") ||
      str_equal_text(&p_sess->ftp_arg_str, "SSL") ||
      str_equal_text(&p_sess->ftp_arg_str, "TLS-P"))
  {
    vsf_cmdio_write(p_sess, FTP_AUTHOK, "Proceed with negotiation.");
    if (!ssl_session_init(p_sess))
    {
      struct mystr err_str = INIT_MYSTR;
      str_alloc_text(&err_str, "Negotiation failed: ");
      str_append_text(&err_str, get_ssl_error());
      vsf_cmdio_write_str(p_sess, FTP_TLS_FAIL, &err_str);
      vsf_sysutil_exit(0);
    }
    p_sess->control_use_ssl = 1;
    if (str_equal_text(&p_sess->ftp_arg_str, "SSL") ||
        str_equal_text(&p_sess->ftp_arg_str, "TLS-P"))
    {
      p_sess->data_use_ssl = 1;
    }
  }
  else
  {
    vsf_cmdio_write(p_sess, FTP_BADAUTH, "Unknown AUTH type.");
  }
}
Beispiel #10
0
/* SSCN (set secured client negotiation) */
void
handle_sscn(struct vsf_session* p_sess)
{
  str_upper(&p_sess->ftp_arg_str);
  if (!p_sess->control_use_ssl)
  {
    vsf_cmdio_write(p_sess, FTP_BADSSCN, "SSCN needs a secure connection.");
  }
  else if (str_equal_text(&p_sess->ftp_arg_str, "ON"))
  {
    /* SSL mode: connect to the remote host */
    p_sess->is_ssl_client = 1;
    vsf_cmdio_write(p_sess, FTP_SSCNOK, "SSCN: Client method");
  }
  else if (str_equal_text(&p_sess->ftp_arg_str, "OFF"))
  {
    /* SSL mode: accept connection */
    p_sess->is_ssl_client = 0;
    vsf_cmdio_write(p_sess, FTP_SSCNOK, "SSCN: Server method");
  }
  else if (str_equal_text(&p_sess->ftp_arg_str, ""))
  {
    vsf_cmdio_write(p_sess, FTP_SSCNOK, p_sess->is_ssl_client ?
        "SSCN: Client method" :
        "SSCN: Server method");
  }
}
Beispiel #11
0
int
vsf_ftpdataio_get_pasv_fd(struct vsf_session* p_sess)
{
  int remote_fd;
  if (tunable_one_process_model)
  {
    remote_fd = vsf_one_process_get_pasv_fd(p_sess);
  }
  else
  {
    remote_fd = vsf_two_process_get_pasv_fd(p_sess);
  }
  /* Yes, yes, hardcoded bad I know. */
  if (remote_fd == -1)
  {
    vsf_cmdio_write(p_sess, FTP_BADSENDCONN,
                    "Failed to establish connection.");
    return remote_fd;
  }
  else if (remote_fd == -2)
  {
    vsf_cmdio_write(p_sess, FTP_BADSENDCONN, "Security: Bad IP connecting.");
    return -1;
  }
  init_data_sock_params(p_sess, remote_fd);
  return remote_fd;
}
Beispiel #12
0
static void
parse_username_password(struct vsf_session* p_sess)
{
  while (1)
  {
    /* Kitsune: update point */
		kitsune_update("prelogin.c"); /**DSU updatepoint */
    /* Kitsune */  
    vsf_sysutil_kitsune_set_update_point("prelogin.c");
    
    vsf_cmdio_get_cmd_and_arg(p_sess, &p_sess->ftp_cmd_str,
                              &p_sess->ftp_arg_str, 1);
    if (str_equal_text(&p_sess->ftp_cmd_str, "USER"))
    {
      handle_user_command(p_sess);
    }
    else if (str_equal_text(&p_sess->ftp_cmd_str, "PASS"))
    {
      handle_pass_command(p_sess);
    }
    else if (str_equal_text(&p_sess->ftp_cmd_str, "QUIT"))
    {
      vsf_cmdio_write(p_sess, FTP_GOODBYE, "Goodbye.");
      vsf_sysutil_exit(0);
    }
    else
    {
      vsf_cmdio_write(p_sess, FTP_LOGINERR,
                      "Please login with USER and PASS.");
    }
  }
}
Beispiel #13
0
static void
handle_pass_command(struct vsf_session* p_sess)
{
  if (str_isempty(&p_sess->user_str))
  {
    vsf_cmdio_write(p_sess, FTP_NEEDUSER, "Login with USER first.");
    return;
  }
  /* These login calls never return if successful */
  if (tunable_one_process_model)
  {
    vsf_one_process_login(p_sess, &p_sess->ftp_arg_str);
  }
  else
  {
    vsf_two_process_login(p_sess, &p_sess->ftp_arg_str);
  }
  vsf_cmdio_write(p_sess, FTP_LOGINERR, "Login incorrect.");
  if (++p_sess->login_fails >= tunable_max_login_fails)
  {
    vsf_sysutil_exit(0);
  }
  str_empty(&p_sess->user_str);
  /* FALLTHRU if login fails */
}
Beispiel #14
0
static void
handle_site_chmod(struct vsf_session* p_sess, struct mystr* p_arg_str)
{
  static struct mystr s_chmod_file_str;
  unsigned int perms;
  int retval;
  if (str_isempty(p_arg_str))
  {
    vsf_cmdio_write(p_sess, FTP_BADCMD, "SITE CHMOD needs 2 arguments.");
    return;
  }
  str_split_char(p_arg_str, &s_chmod_file_str, ' ');
  if (str_isempty(&s_chmod_file_str))
  {
    vsf_cmdio_write(p_sess, FTP_BADCMD, "SITE CHMOD needs 2 arguments.");
    return;
  }
  /* Don't worry - our chmod() implementation only allows 0 - 0777 */
  perms = str_octal_to_uint(p_arg_str);
  retval = str_chmod(&s_chmod_file_str, perms);
  if (vsf_sysutil_retval_is_error(retval))
  {
    vsf_cmdio_write(p_sess, FTP_FILEFAIL, "SITE CHMOD command failed.");
  }
  else
  {
    vsf_cmdio_write(p_sess, FTP_CHMODOK, "SITE CHMOD command ok.");
  }
}
Beispiel #15
0
static void
handle_user_command(struct vsf_session* p_sess)
{
  /* SECURITY: If we're in anonymous only-mode, immediately reject
   * non-anonymous usernames in the hope we save passwords going plaintext
   * over the network
   */
  int is_anon = 1;
  str_copy(&p_sess->user_str, &p_sess->ftp_arg_str);
  str_upper(&p_sess->ftp_arg_str);
  if (!str_equal_text(&p_sess->ftp_arg_str, "FTP") &&
      !str_equal_text(&p_sess->ftp_arg_str, "ANONYMOUS"))
  {
    is_anon = 0;
  }
  if (!tunable_local_enable && !is_anon)
  {
    vsf_cmdio_write(
      p_sess, FTP_LOGINERR, "This FTP server is anonymous only.");
    str_empty(&p_sess->user_str);
    return;
  }
  if (is_anon && p_sess->control_use_ssl && !tunable_allow_anon_ssl)
  {
    vsf_cmdio_write(
      p_sess, FTP_LOGINERR, "Anonymous sessions may not use encryption.");
    str_empty(&p_sess->user_str);
    return;
  }
  if (tunable_ssl_enable && !is_anon && !p_sess->control_use_ssl &&
      tunable_force_local_logins_ssl)
  {
    vsf_cmdio_write(
      p_sess, FTP_LOGINERR, "Non-anonymous sessions must use encryption.");
    str_empty(&p_sess->user_str);
    return;
  }
  if (!str_isempty(&p_sess->userlist_str))
  {
    int located = str_contains_line(&p_sess->userlist_str, &p_sess->user_str);
    if ((located && tunable_userlist_deny) ||
        (!located && !tunable_userlist_deny))
    {
      vsf_cmdio_write(p_sess, FTP_LOGINERR, "Permission denied.");
      str_empty(&p_sess->user_str);
      return;
    }
  }
  if (is_anon && tunable_no_anon_password)
  {
    /* Fake a password */
    str_alloc_text(&p_sess->ftp_arg_str, "<no password>");
    handle_pass_command(p_sess);
  }
  else
  {
    vsf_cmdio_write(p_sess, FTP_GIVEPWORD, "Please specify the password.");
  }
}
Beispiel #16
0
static void
handle_port(struct vsf_session* p_sess)
{
  static struct mystr s_tmp_str;
  unsigned short the_port;
  unsigned char vals[6];
  int i;
  pasv_cleanup(p_sess);
  port_cleanup(p_sess);
  str_copy(&s_tmp_str, &p_sess->ftp_arg_str);
  for (i=0; i<6; i++)
  {
    static struct mystr s_rhs_comma_str;
    int this_number;
    /* This puts a single , delimited field in tmp_str */
    str_split_char(&s_tmp_str, &s_rhs_comma_str, ',');
    /* Sanity - check for too many or two few commas! */
    if ( (i<5 && str_isempty(&s_rhs_comma_str)) ||
         (i==5 && !str_isempty(&s_rhs_comma_str)))
    {
      vsf_cmdio_write(p_sess, FTP_BADCMD, "Illegal PORT command.");
      return;
    }
    this_number = str_atoi(&s_tmp_str);
    if (this_number < 0 || this_number > 255)
    {
      vsf_cmdio_write(p_sess, FTP_BADCMD, "Illegal PORT command.");
      return;
    }
    /* If this truncates from int to uchar, we don't care */
    vals[i] = (unsigned char) this_number;
    /* The right hand side of the comma now becomes the new string to
     * breakdown
     */
    str_copy(&s_tmp_str, &s_rhs_comma_str);
  }
  the_port = vals[4] << 8;
  the_port |= vals[5];
  vsf_sysutil_sockaddr_alloc_ipv4(&p_sess->p_port_sockaddr);
  vsf_sysutil_sockaddr_set_ipv4addr(p_sess->p_port_sockaddr, vals);
  vsf_sysutil_sockaddr_set_port(p_sess->p_port_sockaddr, the_port);
  /* SECURITY:
   * 1) Reject requests not connecting to the control socket IP
   * 2) Reject connects to privileged ports
   */
  if (!tunable_port_promiscuous)
  {
    if (!vsf_sysutil_sockaddr_addr_equal(p_sess->p_remote_addr,
                                         p_sess->p_port_sockaddr) ||
        vsf_sysutil_is_port_reserved(the_port))
    {
      vsf_cmdio_write(p_sess, FTP_BADCMD, "Illegal PORT command.");
      port_cleanup(p_sess);
      return;
    }
  }
  vsf_cmdio_write(p_sess, FTP_PORTOK,
                  "PORT command successful. Consider using PASV.");
}
Beispiel #17
0
void
handle_pbsz(struct vsf_session* p_sess)
{
  if (!p_sess->control_use_ssl)
  {
    vsf_cmdio_write(p_sess, FTP_BADPBSZ, "PBSZ needs a secure connection.");
  }
  else
  {
    vsf_cmdio_write(p_sess, FTP_PBSZOK, "PBSZ set to 0.");
  }
}
Beispiel #18
0
void
handle_opts(struct vsf_session* p_sess)
{
  str_upper(&p_sess->ftp_arg_str);
  if (str_equal_text(&p_sess->ftp_arg_str, "UTF8 ON") && !strcmp(tunable_remote_charset, "utf8"))
  {
    vsf_cmdio_write(p_sess, FTP_OPTSOK, "Always in UTF8 mode.");
  }
  else
  {
    vsf_cmdio_write(p_sess, FTP_BADOPTS, "Option not understood.");
  }
}
Beispiel #19
0
static void
handle_cdup(struct vsf_session* p_sess)
{
  int retval = vsf_sysutil_chdir("..");
  if (retval == 0)
  {
    vsf_cmdio_write(p_sess, FTP_CWDOK, "Directory successfully changed.");
  }
  else
  {
    vsf_cmdio_write(p_sess, FTP_FILEFAIL, "Failed to change directory.");
  }
}
Beispiel #20
0
static void
handle_dele(struct vsf_session* p_sess)
{
  int retval = str_unlink(&p_sess->ftp_arg_str);
  if (retval != 0)
  {
    vsf_cmdio_write(p_sess, FTP_FILEFAIL, "Delete operation failed.");
  }
  else
  {
    vsf_cmdio_write(p_sess, FTP_DELEOK, "Delete operation successful.");
  }
}
Beispiel #21
0
static struct vsf_transfer_ret
do_file_recv(struct vsf_session* p_sess, int file_fd, int is_ascii)
{
    static char* p_recvbuf;
    unsigned int num_to_write;
    struct vsf_transfer_ret ret_struct = { 0, 0 };
    unsigned int chunk_size = get_chunk_size();
    if (p_recvbuf == 0)
    {
        vsf_secbuf_alloc(&p_recvbuf, VSFTP_DATA_BUFSIZE);
    }
    while (1)
    {
        int retval = ftp_read_data(p_sess, p_recvbuf, chunk_size);
        if (vsf_sysutil_retval_is_error(retval))
        {
            vsf_cmdio_write(p_sess, FTP_BADSENDNET,
                            "Failure reading network stream.");
            ret_struct.retval = -1;
            return ret_struct;
        }
        else if (retval == 0)
        {
            /* Transfer done, nifty */
            vsf_cmdio_write(p_sess, FTP_TRANSFEROK, "File receive OK.");
            return ret_struct;
        }
        num_to_write = (unsigned int) retval;
        ret_struct.transferred += num_to_write;
        if (is_ascii)
        {
            /* Handle ASCII conversion if we have to. Note that using the same
             * buffer for source and destination is safe, because the ASCII ->
             * binary transform only ever results in a smaller file.
             */
            num_to_write = vsf_ascii_ascii_to_bin(p_recvbuf, p_recvbuf,
                                                  num_to_write);
        }
        retval = vsf_sysutil_write_loop(file_fd, p_recvbuf, num_to_write);
        if (vsf_sysutil_retval_is_error(retval) ||
                (unsigned int) retval != num_to_write)
        {
            vsf_cmdio_write(p_sess, FTP_BADSENDFILE,
                            "Failure writing to local file.");
            ret_struct.retval = -1;
            return ret_struct;
        }
    }
}
Beispiel #22
0
static void
emit_greeting(struct vsf_session* p_sess)
{
  struct mystr str_log_line = INIT_MYSTR;
  /* Check for client limits (standalone mode only) */
  if (tunable_max_clients > 0 &&
      p_sess->num_clients > tunable_max_clients)
  {
    str_alloc_text(&str_log_line, "Connection refused: too many sessions.");
    vsf_log_line(p_sess, kVSFLogEntryConnection, &str_log_line);
    vsf_cmdio_write_noblock(p_sess, FTP_TOO_MANY_USERS,
                    "There are too many connected users, please try later.");
    vsf_sysutil_exit(0);
  }
  if (tunable_max_per_ip > 0 &&
      p_sess->num_this_ip > tunable_max_per_ip)
  {
    str_alloc_text(&str_log_line,
                   "Connection refused: too many sessions for this address.");
    vsf_log_line(p_sess, kVSFLogEntryConnection, &str_log_line);
    vsf_cmdio_write_noblock(p_sess, FTP_IP_LIMIT,
        "There are too many connections from your internet address.");
    vsf_sysutil_exit(0);
  }
  if (!p_sess->tcp_wrapper_ok)
  {
    str_alloc_text(&str_log_line,
                   "Connection refused: tcp_wrappers denial.");
    vsf_log_line(p_sess, kVSFLogEntryConnection, &str_log_line);
    vsf_cmdio_write_noblock(p_sess, FTP_IP_DENY, "Service not available.");
    vsf_sysutil_exit(0);
  }
  vsf_log_line(p_sess, kVSFLogEntryConnection, &str_log_line);
  if (!str_isempty(&p_sess->banner_str))
  {
    vsf_banner_write(p_sess, &p_sess->banner_str, FTP_GREET);
    str_free(&p_sess->banner_str);
    vsf_cmdio_write(p_sess, FTP_GREET, "");
  }
  else if (tunable_ftpd_banner == 0)
  {
    vsf_cmdio_write(p_sess, FTP_GREET, "(vsFTPd " VSF_VERSION 
                    ")");
  }
  else
  {
    vsf_cmdio_write(p_sess, FTP_GREET, tunable_ftpd_banner);
  }
}
Beispiel #23
0
static void
handle_rmd(struct vsf_session* p_sess)
{
  int retval = str_rmdir(&p_sess->ftp_arg_str);
  if (retval != 0)
  {
    vsf_cmdio_write(p_sess, FTP_FILEFAIL,
                    "Remove directory operation failed.");
  }
  else
  {
    vsf_cmdio_write(p_sess, FTP_RMDIROK,
                    "Remove directory operation successful.");
  }
}
Beispiel #24
0
static void
handle_cwd(struct vsf_session* p_sess)
{
  int retval = str_chdir(&p_sess->ftp_arg_str);
  if (retval == 0)
  {
    /* Handle any messages */
    vsf_banner_dir_changed(p_sess, FTP_CWDOK);
    vsf_cmdio_write(p_sess, FTP_CWDOK, "Directory successfully changed.");
  }
  else
  {
    vsf_cmdio_write(p_sess, FTP_FILEFAIL, "Failed to change directory.");
  }
}
Beispiel #25
0
static void
handle_mkd(struct vsf_session* p_sess)
{
  int retval;
  vsf_log_start_entry(p_sess, kVSFLogEntryMkdir);
  str_copy(&p_sess->log_str, &p_sess->ftp_arg_str);
  prepend_path_to_filename(&p_sess->log_str);
  /* NOTE! Actual permissions will be governed by the tunable umask */
  retval = str_mkdir(&p_sess->ftp_arg_str, 0777);
  if (retval != 0)
  {
    vsf_log_do_log(p_sess, 0);
    vsf_cmdio_write(p_sess, FTP_FILEFAIL,
                    "Create directory operation failed.");
    return;
  }
  vsf_log_do_log(p_sess, 1);
  {
    static struct mystr s_mkd_res;
    static struct mystr s_tmp_str;
    str_copy(&s_tmp_str, &p_sess->ftp_arg_str);
    prepend_path_to_filename(&s_tmp_str);
    /* Double up double quotes */
    str_replace_text(&s_tmp_str, "\"", "\"\"");
    /* Build result string */
    str_alloc_text(&s_mkd_res, "\"");
    str_append_str(&s_mkd_res, &s_tmp_str);
    str_append_text(&s_mkd_res, "\" created");
    vsf_cmdio_write_str(p_sess, FTP_MKDIROK, &s_mkd_res);
  }
}
Beispiel #26
0
void
handle_feat(struct vsf_session* p_sess)
{
  vsf_cmdio_write_hyphen(p_sess, FTP_FEAT, "Features:");
  if (tunable_ssl_enable)
  {
    vsf_cmdio_write_raw(p_sess, " AUTH SSL\r\n");
    vsf_cmdio_write_raw(p_sess, " AUTH TLS\r\n");
  }
  if (tunable_port_enable)
  {
    vsf_cmdio_write_raw(p_sess, " EPRT\r\n");
  }
  if (tunable_pasv_enable)
  {
    vsf_cmdio_write_raw(p_sess, " EPSV\r\n");
  }
  vsf_cmdio_write_raw(p_sess, " MDTM\r\n");
  if (tunable_pasv_enable)
  {
    vsf_cmdio_write_raw(p_sess, " PASV\r\n");
  }
  if (tunable_ssl_enable)
  {
    vsf_cmdio_write_raw(p_sess, " PBSZ\r\n");
    vsf_cmdio_write_raw(p_sess, " PROT\r\n");
  }
  vsf_cmdio_write_raw(p_sess, " REST STREAM\r\n");
  vsf_cmdio_write_raw(p_sess, " SIZE\r\n");
  vsf_cmdio_write_raw(p_sess, " TVFS\r\n");
  vsf_cmdio_write(p_sess, FTP_FEAT, "End");
}
Beispiel #27
0
int
vsf_ftpdataio_post_mark_connect(struct vsf_session* p_sess)
{
  int ret = 0;
  if (!p_sess->data_use_ssl)
  {
    return 1;
  }
  if (!p_sess->ssl_slave_active)
  {
    ret = ssl_accept(p_sess, p_sess->data_fd);
  }
  else
  {
    int sock_ret;
    priv_sock_send_cmd(p_sess->ssl_consumer_fd, PRIV_SOCK_DO_SSL_HANDSHAKE);
    priv_sock_send_fd(p_sess->ssl_consumer_fd, p_sess->data_fd);
    sock_ret = priv_sock_get_result(p_sess->ssl_consumer_fd);
    if (sock_ret == PRIV_SOCK_RESULT_OK)
    {
      ret = 1;
    }
  }
  if (ret != 1)
  {
    if (tunable_require_ssl_reuse)
    {
      vsf_cmdio_write_exit(p_sess, FTP_DATATLSBAD,
                           "SSL connection failed: session reuse required", 1);
    } else {
      vsf_cmdio_write(p_sess, FTP_DATATLSBAD, "SSL connection failed");
    }
  }
  return ret;
}
Beispiel #28
0
static void
parse_username_password(struct vsf_session* p_sess)
{
  while (1)
  {
    vsf_cmdio_get_cmd_and_arg(p_sess, &p_sess->ftp_cmd_str,
                              &p_sess->ftp_arg_str, 1);
    if (str_equal_text(&p_sess->ftp_cmd_str, "USER"))
    {
      handle_user_command(p_sess);
    }
    else if (str_equal_text(&p_sess->ftp_cmd_str, "PASS"))
    {
      handle_pass_command(p_sess);
    }
    else if (str_equal_text(&p_sess->ftp_cmd_str, "QUIT"))
    {
      vsf_cmdio_write(p_sess, FTP_GOODBYE, "Goodbye.");
      vsf_sysutil_exit(0);
    }
    else if (str_equal_text(&p_sess->ftp_cmd_str, "FEAT"))
    {
      handle_feat(p_sess);
    }
    else if (tunable_ssl_enable && str_equal_text(&p_sess->ftp_cmd_str, "AUTH"))
    {
      handle_auth(p_sess);
    }
    else if (tunable_ssl_enable && str_equal_text(&p_sess->ftp_cmd_str, "PBSZ"))
    {
      handle_pbsz(p_sess);
    }
    else if (tunable_ssl_enable && str_equal_text(&p_sess->ftp_cmd_str, "PROT"))
    {
      handle_prot(p_sess);
    }
    else
    {
      vsf_cmdio_write(p_sess, FTP_LOGINERR,
                      "Please login with USER and PASS.");
    }
  }
}
Beispiel #29
0
static void
emit_greeting(struct vsf_session* p_sess)
{
  if (!str_isempty(&p_sess->banner_str))
  {
    vsf_banner_write(p_sess, &p_sess->banner_str, FTP_GREET);
    str_free(&p_sess->banner_str);
    vsf_cmdio_write(p_sess, FTP_GREET, "");
  }
  else if (tunable_ftpd_banner == 0)
  {
    vsf_cmdio_write(p_sess, FTP_GREET, "(vsFTPd " VSF_VERSION 
                    ")");
  }
  else
  {
    vsf_cmdio_write(p_sess, FTP_GREET, tunable_ftpd_banner);
  }
}
Beispiel #30
0
static void
handle_dele(struct vsf_session* p_sess)
{
  int retval;
  if (!vsf_access_check_file(&p_sess->ftp_arg_str))
  {
    vsf_cmdio_write(p_sess, FTP_NOPERM, "Permission denied.");
    return;
  }
  retval = str_unlink(&p_sess->ftp_arg_str);
  if (retval != 0)
  {
    vsf_cmdio_write(p_sess, FTP_FILEFAIL, "Delete operation failed.");
  }
  else
  {
    vsf_cmdio_write(p_sess, FTP_DELEOK, "Delete operation successful.");
  }
}