Ejemplo n.º 1
0
void
vsf_insert_uwtmp(const struct mystr* p_user_str,
                 const struct mystr* p_host_str)
{
  if (sizeof(s_utent.ut_line) < 16)
  {
    return;
  }
  if (s_uwtmp_inserted)
  {
    bug("vsf_insert_uwtmp");
  }
  {
    struct mystr line_str = INIT_MYSTR;
    str_alloc_text(&line_str, VSF_PROJECT ":");
    str_append_ulong(&line_str, vsf_sysutil_getpid());
    if (str_getlen(&line_str) >= sizeof(s_utent.ut_line))
    {
      str_free(&line_str);
      return;
    }
    vsf_sysutil_strcpy(s_utent.ut_line, str_getbuf(&line_str),
                       sizeof(s_utent.ut_line));
    str_free(&line_str);
  }
  s_uwtmp_inserted = 1;
  s_utent.ut_type = USER_PROCESS;
  s_utent.ut_pid = vsf_sysutil_getpid();
  vsf_sysutil_strcpy(s_utent.ut_user, str_getbuf(p_user_str),
                     sizeof(s_utent.ut_user));
  vsf_sysutil_strcpy(s_utent.ut_host, str_getbuf(p_host_str),
                     sizeof(s_utent.ut_host));
  s_utent.ut_tv.tv_sec = vsf_sysutil_get_time_sec();
  setutxent();
  (void) pututxline(&s_utent);
  endutxent();
#ifdef VSF_SYSDEP_HAVE_UPDWTMPX
  updwtmpx(WTMPX_FILE, &s_utent);
#endif
}
Ejemplo n.º 2
0
static void
vsf_log_do_log_vsftpd_format(struct vsf_session* p_sess, struct mystr* p_str,
                             int succeeded, enum EVSFLogEntryType what,
                             const struct mystr* p_log_str)
{
  /* Date - vsf_sysutil_get_current_date updates cached time */
  str_alloc_text(p_str, vsf_sysutil_get_current_date());
  /* Pid */
  str_append_text(p_str, " [pid ");
  str_append_ulong(p_str, vsf_sysutil_getpid());
  str_append_text(p_str, "] ");
  /* User */
  if (!str_isempty(&p_sess->user_str))
  {
    str_append_char(p_str, '[');
    str_append_str(p_str, &p_sess->user_str);
    str_append_text(p_str, "] ");
  }
  /* And the action */
  if (what != kVSFLogEntryFTPInput && what != kVSFLogEntryFTPOutput &&
      what != kVSFLogEntryConnection)
  {
    if (succeeded)
    {
      str_append_text(p_str, "OK ");
    }
    else
    {
      str_append_text(p_str, "FAIL ");
    }
  }
  switch (what)
  {
    case kVSFLogEntryDownload:
      str_append_text(p_str, "DOWNLOAD");
      break;
    case kVSFLogEntryUpload:
      str_append_text(p_str, "UPLOAD");
      break;
    case kVSFLogEntryMkdir:
      str_append_text(p_str, "MKDIR");
      break;
    case kVSFLogEntryLogin:
      str_append_text(p_str, "LOGIN");
      break;
    case kVSFLogEntryFTPInput:
      str_append_text(p_str, "FTP command");
      break;
    case kVSFLogEntryFTPOutput:
      str_append_text(p_str, "FTP response");
      break;
    case kVSFLogEntryConnection:
      str_append_text(p_str, "CONNECT");
      break;
    case kVSFLogEntryDelete:
      str_append_text(p_str, "DELETE");
      break;
    case kVSFLogEntryRename:
      str_append_text(p_str, "RENAME");
      break;
    case kVSFLogEntryRmdir:
      str_append_text(p_str, "RMDIR");
      break;
    case kVSFLogEntryChmod:
      str_append_text(p_str, "CHMOD");
      break;
    default:
      bug("bad entry_type in vsf_log_do_log");
      break;
  }
  str_append_text(p_str, ": Client \"");
  str_append_str(p_str, &p_sess->remote_ip_str);
  str_append_char(p_str, '"');
  if (what == kVSFLogEntryLogin && !str_isempty(&p_sess->anon_pass_str))
  {
    str_append_text(p_str, ", anon password \"");
    str_append_str(p_str, &p_sess->anon_pass_str);
    str_append_char(p_str, '"');
  }
  if (!str_isempty(p_log_str))
  {
    str_append_text(p_str, ", \"");
    str_append_str(p_str, p_log_str);
    str_append_char(p_str, '"');
  }
  if (what != kVSFLogEntryFTPInput && what != kVSFLogEntryFTPOutput)
  {
    if (p_sess->transfer_size)
    {
      str_append_text(p_str, ", ");
      str_append_filesize_t(p_str, p_sess->transfer_size);
      str_append_text(p_str, " bytes");
    }
    if (vsf_log_type_is_transfer(what))
    {
      long delta_sec = vsf_sysutil_get_cached_time_sec() -
                       p_sess->log_start_sec;
      long delta_usec = vsf_sysutil_get_cached_time_usec() -
                        p_sess->log_start_usec;
      double time_delta = (double) delta_sec + ((double) delta_usec /
                                                (double) 1000000);
      double kbyte_rate =
        ((double) p_sess->transfer_size / time_delta) / (double) 1024;
      str_append_text(p_str, ", ");
      str_append_double(p_str, kbyte_rate);
      str_append_text(p_str, "Kbyte/sec");
    }
  }
}
Ejemplo n.º 3
0
void
seccomp_sandbox_setup_postlogin(const struct vsf_session* p_sess)
{
  int is_anon = p_sess->is_anonymous;
  int open_flag = kOpenFlags;
  if (tunable_write_enable)
  {
    open_flag |= O_ACCMODE;
  }

  /* Put lstat() first because it is a very hot syscall for large directory
   * listings. And the current BPF only allows a linear scan of allowed
   * syscalls.
   */
  allow_nr(__NR_lstat);

  /* Allow all the simple pre-login things and then expand upon them. */
  seccomp_sandbox_setup_prelogin(p_sess);

  /* Simple file descriptor-based operations. */
  if (tunable_xferlog_enable || tunable_dual_log_enable ||
      tunable_lock_upload_files)
  {
    allow_nr_1_arg_match(__NR_fcntl, 2, F_SETLKW);
    allow_nr_1_arg_match(__NR_fcntl, 2, F_SETLK);
  }
  if (tunable_async_abor_enable)
  {
    allow_nr_2_arg_match(__NR_fcntl, 2, F_SETOWN, 3, vsf_sysutil_getpid());
  }
  allow_nr_2_arg_match(__NR_setsockopt, 2, SOL_SOCKET, 3, SO_KEEPALIVE);
  allow_nr_2_arg_match(__NR_setsockopt, 2, SOL_SOCKET, 3, SO_LINGER);
  allow_nr_2_arg_match(__NR_setsockopt, 2, IPPROTO_IP, 3, IP_TOS);
  allow_nr(__NR_fstat);
  allow_nr(__NR_lseek);
  /* Since we use chroot() to restrict filesystem access, we can just blanket
   * allow open().
   */
  allow_nr_1_arg_mask(__NR_open, 2, open_flag);
  allow_nr_1_arg_mask(__NR_openat, 3, open_flag);
  /* Other pathname-based metadata queries. */
  allow_nr(__NR_stat);
  allow_nr(__NR_readlink);
  /* Directory handling: query, change, read. */
  allow_nr(__NR_getcwd);
  allow_nr(__NR_chdir);
  allow_nr(__NR_getdents);
  /* Misc */
  allow_nr(__NR_umask);

  /* Config-dependent items follow. */
  if (tunable_use_sendfile)
  {
    allow_nr(__NR_sendfile);
  }
  if (tunable_idle_session_timeout > 0 ||
      tunable_data_connection_timeout > 0 ||
      tunable_async_abor_enable)
  {
    allow_nr(__NR_rt_sigaction);
  }
  if (tunable_idle_session_timeout > 0 || tunable_data_connection_timeout > 0)
  {
    allow_nr(__NR_alarm);
  }

  if (tunable_one_process_model)
  {
    seccomp_sandbox_setup_data_connections();
    if (is_anon && tunable_chown_uploads)
    {
      allow_nr(__NR_fchmod);
      allow_nr(__NR_fchown);
    }
  }
  else
  {
    /* Need to receieve file descriptors from privileged broker. */
    allow_nr_1_arg_match(__NR_recvmsg, 3, 0);
    if ((is_anon && tunable_chown_uploads) || tunable_ssl_enable)
    {
      /* Need to send file descriptors to privileged broker. */
      allow_nr_1_arg_match(__NR_sendmsg, 3, 0);
    }
  }

  if (tunable_syslog_enable)
  {
    /* The ability to pass an address spec isn't needed so disable it. We ensure
     * the 6th arg (socklen) is 0. We could have checked the 5th arg (sockptr)
     * but I don't know if 64-bit compares work in the kernel filter, so we're
     * happy to check the socklen arg, which is 32 bits.
     */
    allow_nr_1_arg_match(__NR_sendto, 6, 0);
  }

  if (tunable_text_userdb_names)
  {
    reject_nr(__NR_socket, EACCES);
    allow_nr_2_arg_match(__NR_mmap, 3, PROT_READ, 4, MAP_SHARED);
  }

  if (tunable_write_enable)
  {
    if (!is_anon || tunable_anon_mkdir_write_enable)
    {
      allow_nr(__NR_mkdir);
    }
    if (!is_anon ||
        tunable_anon_other_write_enable ||
        tunable_delete_failed_uploads)
    {
      allow_nr(__NR_unlink);
    }
    if (!is_anon || tunable_anon_other_write_enable)
    {
      allow_nr(__NR_rmdir);
      allow_nr(__NR_rename);
      allow_nr(__NR_ftruncate);
      if (tunable_mdtm_write)
      {
        allow_nr(__NR_utime);
        allow_nr(__NR_utimes);
      }
    }
    if (!is_anon && tunable_chmod_enable)
    {
      allow_nr(__NR_chmod);
    }
  }
}