Exemple #1
0
int get_transfer_fd(session_t *pses)
{
    int iret = 0;
    //可能是主动模式,或者被动模式
    //检测是否收到PORT命令或者PASV命令
    if((port_active(pses) < 0) && (pasv_active(pses) < 0))
    {
        ftp_reply(pses->ctrl_fd, FTP_BADSENDCONN, "Use PORT or PASV first.");
        iret = -1;
        return iret;
    }

    //主动模式
    if(port_active(pses) == 0)
    {
        //向nobody进程发送命令
        priv_sock_send_cmd(pses->child_fd, PRIV_SOCK_GET_DATA_SOCK);
        unsigned short port = ntohs(pses->port_addr->sin_port);
        char *ip = inet_ntoa(pses->port_addr->sin_addr);
        //发送port
        priv_sock_send_int(pses->child_fd, (int)port);
        //发送ip
        priv_sock_send_buf(pses->child_fd, ip, strlen(ip));

        //接收应答
        char res = priv_sock_get_result(pses->child_fd);
        if(res == PRIV_SOCK_RESULT_BAD)
        {
            iret = -1;
        }
        else if(res == PRIV_SOCK_RESULT_OK)
        {
            //接收文件描述符
            pses->data_fd = priv_sock_recv_fd(pses->child_fd);
        }
    }
    else if(pasv_active(pses) == 0)//被动模式
    {
        //发送命令给nobody进程,完成客户端和服务端的连接
        priv_sock_send_cmd(pses->child_fd, PRIV_SOCK_PASV_ACCEPT);
        //接收nobody进程的应答
        char res = priv_sock_get_result(pses->child_fd);
        if(res == PRIV_SOCK_RESULT_BAD)
        {
            iret = -1;
        }
        else if(res == PRIV_SOCK_RESULT_OK)
        {
            pses->data_fd = priv_sock_recv_fd(pses->child_fd);
        }
    }
    //连接成功后,该内存空间就不需要了
    if(pses->port_addr != NULL)
    {
        free(pses->port_addr);
        pses->port_addr = NULL;
    }
    return iret;
}
int
ftp_write_str(const struct vsf_session* p_sess, const struct mystr* p_str,
              enum EVSFRWTarget target)
{
  if (target == kVSFRWData)
  {
    if (p_sess->data_use_ssl)
    {
      return ssl_write_str(p_sess->p_data_ssl, p_str);
    }
    else
    {
      return str_netfd_write(p_str, p_sess->data_fd);
    }
  }
  else
  {
    if (p_sess->control_use_ssl && p_sess->ssl_slave_active)
    {
      priv_sock_send_cmd(p_sess->ssl_consumer_fd, PRIV_SOCK_WRITE_USER_RESP);
      priv_sock_send_str(p_sess->ssl_consumer_fd, p_str);
      return priv_sock_get_int(p_sess->ssl_consumer_fd);
    }
    else if (p_sess->control_use_ssl)
    {
      return ssl_write_str(p_sess->p_control_ssl, p_str);
    }
    else
    {
      return str_netfd_write(p_str, VSFTP_COMMAND_FD);
    }
  }
}
Exemple #3
0
int
ftp_getline(struct vsf_session* p_sess, struct mystr* p_str, char* p_buf)
{
    if (p_sess->control_use_ssl && p_sess->ssl_slave_active)
    {
        int ret;
        priv_sock_send_cmd(p_sess->ssl_consumer_fd, PRIV_SOCK_GET_USER_CMD);
        ret = priv_sock_get_int(p_sess->ssl_consumer_fd);
        if (ret >= 0)
        {
            priv_sock_get_str(p_sess->ssl_consumer_fd, p_str);
        }
        return ret;
    }
    else
    {
        str_netfd_read_t p_peek = plain_peek_adapter;
        str_netfd_read_t p_read = plain_read_adapter;
        if (p_sess->control_use_ssl)
        {
            p_peek = ssl_peek_adapter;
            p_read = ssl_read_adapter;
        }
        return str_netfd_alloc(p_sess,
                               p_str,
                               '\n',
                               p_buf,
                               VSFTP_MAX_COMMAND_LINE,
                               p_peek,
                               p_read);
    }
}
Exemple #4
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;
}
void
vsf_two_process_login(struct vsf_session* p_sess,
                      const struct mystr* p_pass_str)
{
  char result;
  priv_sock_send_cmd(p_sess, PRIV_SOCK_LOGIN);
  priv_sock_send_str(p_sess, &p_sess->user_str);
  priv_sock_send_str(p_sess, p_pass_str);
  result = priv_sock_get_result(p_sess);
  if (result == PRIV_SOCK_RESULT_OK)
  {
    /* Miracle. We don't emit the success message here. That is left to
     * process_post_login().
     * Exit normally, parent will wait for this and launch new child
     */
    vsf_sysutil_exit(0);
  }
  else if (result == PRIV_SOCK_RESULT_BAD)
  {
    /* Continue the processing loop.. */
    return;
  }
  else
  {
    die("priv_sock_get_result");
  }
}
Exemple #6
0
static void _handle_pasv(session_t *sess)
{
	if (!sess->is_login) {
		ftp_cmdio_write(sess->ctrl_fd, FTP_NLOGIN,
			"Please login first.");
		return;
	}

	if (sess->cliaddr != NULL) {
		free(sess->cliaddr);
		sess->cliaddr = NULL;
	}

	priv_sock_send_cmd(sess->child_fd, PRIV_SOCK_LISTEN);

	uint16_t port = priv_sock_recv_int(sess->child_fd);
	char c[6] = {0};
	union {
		char cs[2];
		uint16_t nport;
	} port_union;
	port_union.nport = htons(port);
	c[4] = port_union.cs[1];
	c[5] = port_union.cs[0];
	sscanf(tunable_listen_addr, "%c.%c.%c.%c", &c[0], &c[1], &c[2], &c[3]);

	char msg[1024] = {0};
	sprintf(msg, "Entering Passive Mode (%c,%c,%c,%c,%c,%c).", c[0], c[1],
		c[2], c[3], c[4], c[5]);
	ftp_cmdio_write(sess->ctrl_fd, FTP_PASV, msg);
}
Exemple #7
0
static void _handle_port(session_t *sess)
{
	if (!sess->is_login) {
		ftp_cmdio_write(sess->ctrl_fd, FTP_NLOGIN,
			"Please login first.");
		return;
	}

	// first check whether pasv is on, 0->null, 1->pasv
	priv_sock_send_cmd(sess->child_fd, PRIV_SOCK_CHECK);
	int res = priv_sock_recv_res(sess->child_fd);
	if (res == 1) {
		priv_sock_send_cmd(sess->child_fd, PRIV_SOCK_CLOSE);
		if (priv_sock_recv_res(sess->child_fd) == -1)
			ftp_cmdio_write(sess->ctrl_fd, FTP_NEXEC, "Port not succeed.");
		close(sess->data_fd);
		sess->data_fd = -1;
	}

	if (sess->cliaddr != NULL) {
		free(sess->cliaddr);
		sess->cliaddr = NULL;
	}

	char c[6] = {0};
	if (sscanf(sess->ftp_cmd_arg, "%c,%c,%c,%c,%c,%c", &c[0], &c[1], &c[2],
		&c[3], &c[4], &c[5]) != 6) {
		ftp_cmdio_write(sess->ctrl_fd, FTP_ARGE, "Argument error.");
		return;
	}

	sess->cliaddr = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in));
	memset(sess->cliaddr, 0, sizeof(struct sockaddr_in));

	char *ip = (char *)&sess->cliaddr->sin_addr.s_addr;
	ip[0] = c[0];
	ip[1] = c[1];
	ip[2] = c[2];
	ip[3] = c[3];

	char *port = (char *)&sess->cliaddr->sin_port;
	port[0] = c[5];
	port[1] = c[4];

	ftp_cmdio_write(sess->ctrl_fd, FTP_SUCCESS, "Port command successful.");
}
void
vsf_two_process_pasv_cleanup(struct vsf_session* p_sess)
{
  char res;
  priv_sock_send_cmd(p_sess->child_fd, PRIV_SOCK_PASV_CLEANUP);
  res = priv_sock_get_result(p_sess->child_fd);
  if (res != PRIV_SOCK_RESULT_OK)
  {
    die("could not clean up socket");
  }
}
void
vsf_two_process_chown_upload(struct vsf_session* p_sess, int fd)
{
  char res;
  priv_sock_send_cmd(p_sess, PRIV_SOCK_CHOWN);
  priv_sock_child_send_fd(p_sess, fd);
  res = priv_sock_get_result(p_sess);
  if (res != PRIV_SOCK_RESULT_OK)
  {
    die("unexpected failure in vsf_two_process_chown_upload");
  }
}
Exemple #10
0
int
vsf_ftpdataio_dispose_transfer_fd(struct vsf_session* p_sess)
{
  int dispose_ret = 1;
  int retval;
  if (p_sess->data_fd == -1)
  {
    bug("no data descriptor in vsf_ftpdataio_dispose_transfer_fd");
  }
  vsf_sysutil_uninstall_io_handler();
  if (p_sess->data_use_ssl && p_sess->ssl_slave_active)
  {
    char result;
    start_data_alarm(p_sess);
    priv_sock_send_cmd(p_sess->ssl_consumer_fd, PRIV_SOCK_DO_SSL_CLOSE);
    result = priv_sock_get_result(p_sess->ssl_consumer_fd);
    if (result != PRIV_SOCK_RESULT_OK)
    {
      dispose_ret = 0;
    }
  }
  else if (p_sess->p_data_ssl)
  {
    start_data_alarm(p_sess);
    dispose_ret = ssl_data_close(p_sess);
  }
  if (!p_sess->abor_received && !p_sess->data_timeout && dispose_ret == 1)
  {
    /* If we didn't get a failure, linger on the close() in order to get more
     * accurate transfer times.
     */
    start_data_alarm(p_sess);
    vsf_sysutil_activate_linger(p_sess->data_fd);
  }
  /* This close() blocks because we set SO_LINGER */
  retval = vsf_sysutil_close_failok(p_sess->data_fd);
  if (vsf_sysutil_retval_is_error(retval))
  {
    /* Do it again without blocking. */
    vsf_sysutil_deactivate_linger_failok(p_sess->data_fd);
    (void) vsf_sysutil_close_failok(p_sess->data_fd);
  }
  p_sess->data_fd = -1;
  if (tunable_data_connection_timeout > 0)
  {
    vsf_sysutil_clear_alarm();
  }
  if (p_sess->abor_received || p_sess->data_timeout)
  {
    dispose_ret = 0;
  }
  return dispose_ret;
}
int
vsf_two_process_get_priv_data_sock(struct vsf_session* p_sess)
{
  char res;
  priv_sock_send_cmd(p_sess, PRIV_SOCK_GET_DATA_SOCK);
  res = priv_sock_get_result(p_sess);
  if (res != PRIV_SOCK_RESULT_OK)
  {
    die("could not get privileged socket");
  }
  return priv_sock_child_recv_fd(p_sess);
}
Exemple #12
0
int get_pasv_fd(session_t* sess)
{
	priv_sock_send_cmd(sess->child_fd, PRIV_SOCK_PASV_ACCEPT);
	char res = priv_sock_get_result(sess->child_fd);
	
	if(res == PRIV_SOCK_RESULT_BAD)
		return 0;
		
	else if(res == PRIV_SOCK_RESULT_OK)
		sess->data_fd = priv_sock_recv_fd(sess->child_fd);

	return 1;
}
Exemple #13
0
int pasv_active(session_t* sess)
{
	priv_sock_send_cmd(sess->child_fd, PRIV_SOCK_PASV_ACTIVE);
	int active = priv_sock_get_int(sess->child_fd);
	
	if(active)
	{
		if(port_active(sess))
                {
                        fprintf(stderr, "both port and pasv are active");
                        exit(EXIT_FAILURE);
                }
                return 1;
	}
	return 0;
}
int
vsf_two_process_get_pasv_fd(struct vsf_session* p_sess)
{
  char res;
  priv_sock_send_cmd(p_sess->child_fd, PRIV_SOCK_PASV_ACCEPT);
  res = priv_sock_get_result(p_sess->child_fd);
  if (res == PRIV_SOCK_RESULT_BAD)
  {
    return priv_sock_get_int(p_sess->child_fd);
  }
  else if (res != PRIV_SOCK_RESULT_OK)
  {
    die("could not accept on listening socket");
  }
  return priv_sock_recv_fd(p_sess->child_fd);
}
Exemple #15
0
static void do_pasv(session_t *sess)
{
	char ip[16] = {0};
	getlocalip(ip);

	priv_sock_send_cmd(sess->child_fd, PRIV_SOCK_PASV_LISTEN);
	unsigned short port = (unsigned short)priv_sock_get_int(sess->child_fd);

	unsigned int v[4];
	sscanf(ip, "%u.%u.%u.%u", &v[0], &v[1], &v[2], &v[3]);

	char text[1024] = {0};
	sprintf(text, "Entering Passive Mode (%u,%u,%u,%u,%u,%u).", 
	v[0], v[1], v[2], v[3], port >> 8, port & 0xFF);		
	
	ftp_reply(sess, FTP_PASVOK, text);
}
Exemple #16
0
int get_port_fd(session_t* sess)
{
	priv_sock_send_cmd(sess->child_fd, PRIV_SOCK_GET_DATA_SOCK);
        unsigned short port = ntohs(sess->port_addr->sin_port);
        char* ip = inet_ntoa(sess->port_addr->sin_addr);

        priv_sock_send_int(sess->child_fd, (int)port);
        priv_sock_send_buf(sess->child_fd, ip, strlen(ip));

        char res = priv_sock_get_result(sess->child_fd);
        if(res == PRIV_SOCK_RESULT_BAD)
         	return 0;

        else if(res == PRIV_SOCK_RESULT_OK)
                sess->data_fd = priv_sock_recv_fd(sess->child_fd);
	
	return 1;
}
Exemple #17
0
void
ftp_getline(const struct vsf_session* p_sess, struct mystr* p_str, char* p_buf)
{
  if (p_sess->control_use_ssl && p_sess->ssl_slave_active)
  {
    priv_sock_send_cmd(p_sess->ssl_consumer_fd, PRIV_SOCK_GET_USER_CMD);
    priv_sock_get_str(p_sess->ssl_consumer_fd, p_str);
  }
  else if (p_sess->control_use_ssl)
  {
    ssl_getline(p_sess, p_str, '\n', p_buf, VSFTP_MAX_COMMAND_LINE);
  }
  else
  {
    str_netfd_alloc(
      p_str, VSFTP_COMMAND_FD, '\n', p_buf, VSFTP_MAX_COMMAND_LINE);
  }
}
int
vsf_two_process_get_priv_data_sock(struct vsf_session* p_sess)
{
  char res;
  unsigned short port = vsf_sysutil_sockaddr_get_port(p_sess->p_port_sockaddr);
  priv_sock_send_cmd(p_sess->child_fd, PRIV_SOCK_GET_DATA_SOCK);
  priv_sock_send_int(p_sess->child_fd, port);
  res = priv_sock_get_result(p_sess->child_fd);
  if (res == PRIV_SOCK_RESULT_BAD)
  {
    return -1;
  }
  else if (res != PRIV_SOCK_RESULT_OK)
  {
    die("could not get privileged socket");
  }
  return priv_sock_recv_fd(p_sess->child_fd);
}
void
vsf_two_process_login(struct vsf_session* p_sess,
                      const struct mystr* p_pass_str)
{
  char result;
  priv_sock_send_cmd(p_sess->child_fd, PRIV_SOCK_LOGIN);
  priv_sock_send_str(p_sess->child_fd, &p_sess->user_str);
  priv_sock_send_str(p_sess->child_fd, p_pass_str);
  priv_sock_send_int(p_sess->child_fd, p_sess->control_use_ssl);
  priv_sock_send_int(p_sess->child_fd, p_sess->data_use_ssl);
  result = priv_sock_get_result(p_sess->child_fd);
  if (result == PRIV_SOCK_RESULT_OK)
  {
    /* Miracle. We don't emit the success message here. That is left to
     * process_post_login().
     * Exit normally, unless we are remaining as the SSL read / write child.
     */
    if (!p_sess->control_use_ssl)
    {
      vsf_sysutil_exit(0);
    }
    else
    {
      vsf_sysutil_clear_alarm();
      vsf_sysutil_close(p_sess->child_fd);
      if (tunable_setproctitle_enable)
      {
        vsf_sysutil_setproctitle("SSL handler");
      }
      process_ssl_slave_req(p_sess);
    }
    /* NOTREACHED */
  }
  else if (result == PRIV_SOCK_RESULT_BAD)
  {
    /* Continue the processing loop.. */
    return;
  }
  else
  {
    die("priv_sock_get_result");
  }
}
Exemple #20
0
int pasv_active(session_t *pses)
{
    //向nobody进程发送命令,看看是否创建了监听套接字,如果是,被动模式处于激活状态
    priv_sock_send_cmd(pses->child_fd, PRIV_SOCK_PASV_ACTIVE);
    int iret = priv_sock_get_int(pses->child_fd);

    if(iret != -1)
    {
        if(port_active(pses) == 0) //主被动模式不能同时处于激活状态
        {
            handle_error_str("both port and pasv are active.");
        }
        return 0;
    }
    else
    {
        return -1;
    }
}
Exemple #21
0
int
vsf_ftpdataio_dispose_transfer_fd(struct vsf_session* p_sess)
{
  int dispose_ret = 1;
  int retval;
  if (p_sess->data_fd == -1)
  {
    bug("no data descriptor in vsf_ftpdataio_dispose_transfer_fd");
  }
  /* Reset the data connection alarm so it runs anew with the blocking close */
  start_data_alarm(p_sess);
  vsf_sysutil_uninstall_io_handler();
  if (p_sess->data_use_ssl && p_sess->ssl_slave_active)
  {
    char result;
    priv_sock_send_cmd(p_sess->ssl_consumer_fd, PRIV_SOCK_DO_SSL_CLOSE);
    result = priv_sock_get_result(p_sess->ssl_consumer_fd);
    if (result != PRIV_SOCK_RESULT_OK)
    {
      dispose_ret = 0;
    }
  }
  else if (p_sess->p_data_ssl)
  {
    dispose_ret = ssl_data_close(p_sess);
  }
  /* This close() blocks because we set SO_LINGER */
  retval = vsf_sysutil_close_failok(p_sess->data_fd);
  if (vsf_sysutil_retval_is_error(retval))
  {
    /* Do it again without blocking. */
    vsf_sysutil_deactivate_linger_failok(p_sess->data_fd);
    (void) vsf_sysutil_close_failok(p_sess->data_fd);
  }
  if (tunable_data_connection_timeout > 0)
  {
    vsf_sysutil_clear_alarm();
  }
  p_sess->data_fd = -1;
  return dispose_ret;
}
Exemple #22
0
int
ftp_read_data(struct vsf_session* p_sess, char* p_buf, unsigned int len)
{
    if (p_sess->data_use_ssl && p_sess->ssl_slave_active)
    {
        int ret;
        priv_sock_send_cmd(p_sess->ssl_consumer_fd, PRIV_SOCK_DO_SSL_READ);
        ret = priv_sock_get_int(p_sess->ssl_consumer_fd);
        priv_sock_recv_buf(p_sess->ssl_consumer_fd, p_buf, len);
        /* Need to do this here too because it is useless in the slave process. */
        vsf_sysutil_check_pending_actions(kVSFSysUtilIO, ret, p_sess->data_fd);
        return ret;
    }
    else if (p_sess->data_use_ssl)
    {
        return ssl_read(p_sess, p_sess->p_data_ssl, p_buf, len);
    }
    else
    {
        return vsf_sysutil_read(p_sess->data_fd, p_buf, len);
    }
}
Exemple #23
0
void do_cmd_pasv(session_t *pses)
{
    char localip[16] = {0};
    if(getlocalip(localip) < 0)
    {
        handle_error("getlocalip");
    }


    //向nobody进程发送请求
    priv_sock_send_cmd(pses->child_fd, PRIV_SOCK_PASV_LISTEN);
    //接收nobody进程返回的端口号
    unsigned short port = (unsigned short)priv_sock_get_int(pses->child_fd);

    unsigned int v[4] = {0};
    sscanf(localip, "%u.%u.%u.%u",&v[0],&v[1],&v[2],&v[3]);
    char iptext[1024] = {0};
    sprintf(iptext, "Entering Passive Mode (%u,%u,%u,%u,%u,%u).",
            v[0],v[1],v[2],v[3],port>>8,port & 0xFF);

    ftp_reply(pses->ctrl_fd, FTP_PASVOK, iptext);

}
Exemple #24
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)
  {
    static struct mystr s_err_msg;
    str_alloc_text(&s_err_msg, "SSL connection failed");
    if (tunable_require_ssl_reuse)
    {
      str_append_text(&s_err_msg, "; session reuse required");
      str_append_text(
          &s_err_msg, ": see require_ssl_reuse option in vsftpd.conf man page");
    }
    vsf_cmdio_write_str(p_sess, FTP_DATATLSBAD, &s_err_msg);
  }
  return ret;
}
unsigned short
vsf_two_process_listen(struct vsf_session* p_sess)
{
  priv_sock_send_cmd(p_sess->child_fd, PRIV_SOCK_PASV_LISTEN);
  return (unsigned short) priv_sock_get_int(p_sess->child_fd);
}
int
vsf_two_process_pasv_active(struct vsf_session* p_sess)
{
  priv_sock_send_cmd(p_sess->child_fd, PRIV_SOCK_PASV_ACTIVE);
  return priv_sock_get_int(p_sess->child_fd);
}