⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sysdeputil.c

📁 文件传输协议linux 下vsftpd2.1.0.tar.gz
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Part of Very Secure FTPd * Licence: GPL v2 * Author: Chris Evans * sysdeputil.c * * Highly system dependent utilities - e.g. authentication, capabilities. */#include "sysdeputil.h"#include "str.h"#include "sysutil.h"#include "utility.h"#include "secbuf.h"#include "defs.h"#include "tunables.h"#include "builddefs.h"/* For Linux, this adds nothing :-) */#include "port/porting_junk.h"#if (defined(__FreeBSD__) && __FreeBSD__ >= 3)  #define _FILE_OFFSET_BITS 64  #define _LARGEFILE_SOURCE 1  #define _LARGEFILE64_SOURCE 1#endif/* For INT_MAX */#include <limits.h>/* For fd passing */#include <sys/types.h>#include <sys/socket.h>/* For FreeBSD */#include <sys/param.h>#include <sys/uio.h>#include <sys/prctl.h>#include <signal.h>/* Configuration.. here are the possibilities */#undef VSF_SYSDEP_HAVE_CAPABILITIES#undef VSF_SYSDEP_HAVE_SETKEEPCAPS#undef VSF_SYSDEP_HAVE_SETPDEATHSIG#undef VSF_SYSDEP_HAVE_LINUX_SENDFILE#undef VSF_SYSDEP_HAVE_FREEBSD_SENDFILE#undef VSF_SYSDEP_HAVE_HPUX_SENDFILE#undef VSF_SYSDEP_HAVE_AIX_SENDFILE#undef VSF_SYSDEP_HAVE_SETPROCTITLE#undef VSF_SYSDEP_TRY_LINUX_SETPROCTITLE_HACK#undef VSF_SYSDEP_HAVE_HPUX_SETPROCTITLE#undef VSF_SYSDEP_HAVE_MAP_ANON#undef VSF_SYSDEP_NEED_OLD_FD_PASSING#ifdef VSF_BUILD_PAM  #define VSF_SYSDEP_HAVE_PAM#endif#define VSF_SYSDEP_HAVE_SHADOW#define VSF_SYSDEP_HAVE_USERSHELL#define VSF_SYSDEP_HAVE_LIBCAP#define VSF_SYSDEP_HAVE_UTMPX#define __USE_GNU#include <utmpx.h>/* BEGIN config */#if defined(__linux__) && !defined(__ia64__) && !defined(__s390__)  #define VSF_SYSDEP_TRY_LINUX_SETPROCTITLE_HACK  #include <linux/version.h>  #if defined(LINUX_VERSION_CODE) && defined(KERNEL_VERSION)    #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0))      #define VSF_SYSDEP_HAVE_CAPABILITIES      #define VSF_SYSDEP_HAVE_LINUX_SENDFILE      #ifdef PR_SET_KEEPCAPS        #define VSF_SYSDEP_HAVE_SETKEEPCAPS      #endif      #ifdef PR_SET_PDEATHSIG        #define VSF_SYSDEP_HAVE_SETPDEATHSIG      #endif    #endif  #endif#endif#if (defined(__FreeBSD__) && __FreeBSD__ >= 3)  #define VSF_SYSDEP_HAVE_FREEBSD_SENDFILE  #define VSF_SYSDEP_HAVE_SETPROCTITLE#endif#if defined(__NetBSD__)  #include <stdlib.h>  #define VSF_SYSDEP_HAVE_SETPROCTITLE  #include <sys/param.h>  #if __NetBSD_Version__ >= 106070000    #define WTMPX_FILE _PATH_WTMPX  #else    #undef VSF_SYSDEP_HAVE_UTMPX  #endif#endif#ifdef __hpux  #include <sys/socket.h>  #ifdef SF_DISCONNECT    #define VSF_SYSDEP_HAVE_HPUX_SENDFILE  #endif  #include <sys/param.h>  #include <sys/pstat.h>  #ifdef PSTAT_SETCMD    #define VSF_SYSDEP_HAVE_HPUX_SETPROCTITLE  #endif  #undef VSF_SYSDEP_HAVE_UTMPX#endif#include <unistd.h>#include <sys/mman.h>#ifdef MAP_ANON  #define VSF_SYSDEP_HAVE_MAP_ANON#endif#ifdef __sgi  #undef VSF_SYSDEP_HAVE_USERSHELL  #undef VSF_SYSDEP_HAVE_LIBCAP#endif#ifdef _AIX  #undef VSF_SYSDEP_HAVE_USERSHELL  #undef VSF_SYSDEP_HAVE_LIBCAP  #undef VSF_SYSDEP_HAVE_UTMPX  #undef VSF_SYSDEP_HAVE_PAM  #undef VSF_SYSDEP_HAVE_SHADOW  #undef VSF_SYSDEP_HAVE_SETPROCTITLE  #define VSF_SYSDEP_HAVE_AIX_SENDFILE  #define VSF_SYSDEP_TRY_LINUX_SETPROCTITLE_HACK  #define VSF_SYSDEP_HAVE_MAP_ANON#endif#ifdef __osf__  #undef VSF_SYSDEP_HAVE_USERSHELL#endif#if (defined(__sgi) || defined(__hpux) || defined(__osf__))  #define VSF_SYSDEP_NEED_OLD_FD_PASSING#endif#ifdef __sun  #define VSF_SYSDEP_HAVE_SOLARIS_SENDFILE#endif/* END config *//* PAM support - we include our own dummy version if the system lacks this */#include <security/pam_appl.h>/* No PAM? Try getspnam() with a getpwnam() fallback */#ifndef VSF_SYSDEP_HAVE_PAM/* This may hit our own "dummy" include and undef VSF_SYSDEP_HAVE_SHADOW */#include <shadow.h>#include <pwd.h>#include <unistd.h>#include <crypt.h>#endif/* Prefer libcap based capabilities over raw syscall capabilities */#include <sys/capability.h>#if defined(VSF_SYSDEP_HAVE_CAPABILITIES) && !defined(VSF_SYSDEP_HAVE_LIBCAP)#include <linux/unistd.h>#include <linux/capability.h>#include <errno.h>#include <syscall.h>int capset(cap_user_header_t header, const cap_user_data_t data){  return syscall(__NR_capset, header, data);}/* Gross HACK to avoid warnings - linux headers overlap glibc headers */#undef __NFDBITS#undef __FDMASK#endif /* VSF_SYSDEP_HAVE_CAPABILITIES */#if defined(VSF_SYSDEP_HAVE_LINUX_SENDFILE) || \    defined(VSF_SYSDEP_HAVE_SOLARIS_SENDFILE)#include <sys/sendfile.h>#elif defined(VSF_SYSDEP_HAVE_FREEBSD_SENDFILE)#include <sys/types.h>#include <sys/socket.h>#elif defined(VSF_SYSDEP_HAVE_HPUX_SENDFILE)#include <sys/socket.h>#else /* VSF_SYSDEP_HAVE_LINUX_SENDFILE */#include <unistd.h>#endif /* VSF_SYSDEP_HAVE_LINUX_SENDFILE */#ifdef VSF_SYSDEP_HAVE_SETPROCTITLE#include <sys/types.h>#include <unistd.h>#endif#ifdef VSF_SYSDEP_TRY_LINUX_SETPROCTITLE_HACKextern char** environ;static unsigned int s_proctitle_space = 0;static int s_proctitle_inited = 0;static char* s_p_proctitle = 0;#endif#ifndef VSF_SYSDEP_HAVE_MAP_ANON#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>static int s_zero_fd = -1;#endif/* File private functions/variables */static int do_sendfile(const int out_fd, const int in_fd,                       unsigned int num_send, filesize_t start_pos);static void vsf_sysutil_setproctitle_internal(const char* p_text);static struct mystr s_proctitle_prefix_str;/* These two aren't static to avoid OpenBSD build warnings. */void vsf_insert_uwtmp(const struct mystr* p_user_str,                      const struct mystr* p_host_str);void vsf_remove_uwtmp(void);#ifndef VSF_SYSDEP_HAVE_PAMintvsf_sysdep_check_auth(const struct mystr* p_user_str,                      const struct mystr* p_pass_str,                      const struct mystr* p_remote_host){  const char* p_crypted;  const struct passwd* p_pwd = getpwnam(str_getbuf(p_user_str));  (void) p_remote_host;  if (p_pwd == NULL)  {    return 0;  }  #ifdef VSF_SYSDEP_HAVE_USERSHELL  if (tunable_check_shell)  {    const char* p_shell;    while ((p_shell = getusershell()) != NULL)    {      if (!vsf_sysutil_strcmp(p_shell, p_pwd->pw_shell))      {        break;      }    }    endusershell();    if (p_shell == NULL)    {      return 0;    }  }  #endif  #ifdef VSF_SYSDEP_HAVE_SHADOW  {    const struct spwd* p_spwd = getspnam(str_getbuf(p_user_str));    if (p_spwd != NULL)    {      long curr_time;      int days;      vsf_sysutil_update_cached_time();      curr_time = vsf_sysutil_get_cached_time_sec();      days = curr_time / (60 * 60 * 24);      if (p_spwd->sp_expire > 0 && p_spwd->sp_expire < days)      {        return 0;      }      if (p_spwd->sp_lstchg > 0 && p_spwd->sp_max > 0 &&          p_spwd->sp_lstchg + p_spwd->sp_max < days)      {        return 0;      }      p_crypted = crypt(str_getbuf(p_pass_str), p_spwd->sp_pwdp);      if (!vsf_sysutil_strcmp(p_crypted, p_spwd->sp_pwdp))      {        return 1;      }    }  }  #endif /* VSF_SYSDEP_HAVE_SHADOW */  p_crypted = crypt(str_getbuf(p_pass_str), p_pwd->pw_passwd);  if (!vsf_sysutil_strcmp(p_crypted, p_pwd->pw_passwd))  {    return 1;  }  return 0;}#else /* VSF_SYSDEP_HAVE_PAM */static pam_handle_t* s_pamh;static struct mystr s_pword_str;static int pam_conv_func(int nmsg, const struct pam_message** p_msg,                         struct pam_response** p_reply, void* p_addata);static void vsf_auth_shutdown(void);intvsf_sysdep_check_auth(const struct mystr* p_user_str,                      const struct mystr* p_pass_str,                      const struct mystr* p_remote_host){  int retval;  struct pam_conv the_conv =  {    &pam_conv_func,    0  };  if (s_pamh != 0)  {    bug("vsf_sysdep_check_auth");  }  str_copy(&s_pword_str, p_pass_str);  retval = pam_start(tunable_pam_service_name,                     str_getbuf(p_user_str), &the_conv, &s_pamh);  if (retval != PAM_SUCCESS)  {    s_pamh = 0;    return 0;  }#ifdef PAM_RHOST  retval = pam_set_item(s_pamh, PAM_RHOST, str_getbuf(p_remote_host));  if (retval != PAM_SUCCESS)  {    (void) pam_end(s_pamh, retval);    s_pamh = 0;    return 0;  }#endif#ifdef PAM_TTY  retval = pam_set_item(s_pamh, PAM_TTY, "ftp");  if (retval != PAM_SUCCESS)  {    (void) pam_end(s_pamh, retval);    s_pamh = 0;    return 0;  }#endif#ifdef PAM_RUSER  retval = pam_set_item(s_pamh, PAM_RUSER, str_getbuf(p_user_str));  if (retval != PAM_SUCCESS)  {    (void) pam_end(s_pamh, retval);    s_pamh = 0;    return 0;  }#endif  retval = pam_authenticate(s_pamh, 0);  if (retval != PAM_SUCCESS)  {    (void) pam_end(s_pamh, retval);    s_pamh = 0;    return 0;  }  retval = pam_acct_mgmt(s_pamh, 0);  if (retval != PAM_SUCCESS)  {    (void) pam_end(s_pamh, retval);    s_pamh = 0;    return 0;  }  retval = pam_setcred(s_pamh, PAM_ESTABLISH_CRED);  if (retval != PAM_SUCCESS)  {    (void) pam_end(s_pamh, retval);    s_pamh = 0;    return 0;  }  if (!tunable_session_support)  {    /* You're in already! */    (void) pam_end(s_pamh, retval);    s_pamh = 0;    return 1;  }  /* Must do this BEFORE opening a session for pam_limits to count us */  vsf_insert_uwtmp(p_user_str, p_remote_host);  retval = pam_open_session(s_pamh, 0);  if (retval != PAM_SUCCESS)  {    vsf_remove_uwtmp();    (void) pam_setcred(s_pamh, PAM_DELETE_CRED);    (void) pam_end(s_pamh, retval);    s_pamh = 0;    return 0;  }  /* We MUST ensure the PAM session, utmp, wtmp etc. are cleaned up, however   * we exit.   */  vsf_sysutil_set_exit_func(vsf_auth_shutdown);  /* You're in dude */  return 1;}static voidvsf_auth_shutdown(void){  if (s_pamh == 0)  {    bug("vsf_auth_shutdown");  }  (void) pam_close_session(s_pamh, 0);  (void) pam_setcred(s_pamh, PAM_DELETE_CRED);  (void) pam_end(s_pamh, PAM_SUCCESS);  s_pamh = 0;  vsf_remove_uwtmp();}static intpam_conv_func(int nmsg, const struct pam_message** p_msg,              struct pam_response** p_reply, void* p_addata){  int i;  struct pam_response* p_resps = 0;  (void) p_addata;  if (nmsg < 0)  {    bug("dodgy nmsg in pam_conv_func");  }  p_resps = vsf_sysutil_malloc(sizeof(struct pam_response) * nmsg);  for (i=0; i<nmsg; i++)  {    switch (p_msg[i]->msg_style)    {      case PAM_PROMPT_ECHO_OFF:        p_resps[i].resp_retcode = PAM_SUCCESS;        p_resps[i].resp = (char*) str_strdup(&s_pword_str);        break;      case PAM_TEXT_INFO:      case PAM_ERROR_MSG:        p_resps[i].resp_retcode = PAM_SUCCESS;        p_resps[i].resp = 0;        break;      case PAM_PROMPT_ECHO_ON:      default:        vsf_sysutil_free(p_resps);        return PAM_CONV_ERR;        break;    }  }  *p_reply = p_resps;  return PAM_SUCCESS;}#endif /* VSF_SYSDEP_HAVE_PAM *//* Capabilities support (or lack thereof) */voidvsf_sysdep_keep_capabilities(void){  if (!vsf_sysdep_has_capabilities_as_non_root())  {    bug("asked to keep capabilities, but no support exists");  }#ifdef VSF_SYSDEP_HAVE_SETKEEPCAPS  {    int retval = prctl(PR_SET_KEEPCAPS, 1);    if (vsf_sysutil_retval_is_error(retval))    {      die("prctl");    }  }#endif /* VSF_SYSDEP_HAVE_SETKEEPCAPS */}#if !defined(VSF_SYSDEP_HAVE_CAPABILITIES) && !defined(VSF_SYSDEP_HAVE_LIBCAP)intvsf_sysdep_has_capabilities(void){  return 0;}intvsf_sysdep_has_capabilities_as_non_root(void){  return 0;}voidvsf_sysdep_adopt_capabilities(unsigned int caps){  (void) caps;  bug("asked to adopt capabilities, but no support exists");}#else /* VSF_SYSDEP_HAVE_CAPABILITIES || VSF_SYSDEP_HAVE_LIBCAP */static int do_checkcap(void);intvsf_sysdep_has_capabilities_as_non_root(void){  static int s_prctl_checked;  static int s_runtime_prctl_works;  if (!s_prctl_checked)  {  #ifdef VSF_SYSDEP_HAVE_SETKEEPCAPS    /* Clarity: note embedded call to prctl() syscall */    if (!vsf_sysutil_retval_is_error(prctl(PR_SET_KEEPCAPS, 0)))    {      s_runtime_prctl_works = 1;    }  #endif /* VSF_SYSDEP_HAVE_SETKEEPCAPS */    s_prctl_checked = 1;  }  return s_runtime_prctl_works;}intvsf_sysdep_has_capabilities(void){  /* Even though compiled with capabilities, the runtime system may lack them.   * Also, RH7.0 kernel headers advertise a 2.4.0 box, but on a 2.2.x kernel!   */  static int s_caps_checked;  static int s_runtime_has_caps;  if (!s_caps_checked)  {    s_runtime_has_caps = do_checkcap();    s_caps_checked = 1;  }  return s_runtime_has_caps;}    #ifndef VSF_SYSDEP_HAVE_LIBCAPstatic intdo_checkcap(void){  /* EFAULT (EINVAL if page 0 mapped) vs. ENOSYS */  int retval = capset(0, 0);  if (!vsf_sysutil_retval_is_error(retval) ||      vsf_sysutil_get_error() != kVSFSysUtilErrNOSYS)  {    return 1;  }  return 0;}voidvsf_sysdep_adopt_capabilities(unsigned int caps){  /* n.b. yes I know I should be using libcap!! */  int retval;  struct __user_cap_header_struct cap_head;  struct __user_cap_data_struct cap_data;  __u32 cap_mask = 0;  if (!caps)  {    bug("asked to adopt no capabilities");  }  vsf_sysutil_memclr(&cap_head, sizeof(cap_head));  vsf_sysutil_memclr(&cap_data, sizeof(cap_data));  cap_head.version = _LINUX_CAPABILITY_VERSION;  cap_head.pid = 0;  if (caps & kCapabilityCAP_CHOWN)  {    cap_mask |= (1 << CAP_CHOWN);  }  if (caps & kCapabilityCAP_NET_BIND_SERVICE)  {    cap_mask |= (1 << CAP_NET_BIND_SERVICE);  }  cap_data.effective = cap_data.permitted = cap_mask;  cap_data.inheritable = 0;  retval = capset(&cap_head, &cap_data);  if (retval != 0)  {    die("capset");  }}  #else /* VSF_SYSDEP_HAVE_LIBCAP */static intdo_checkcap(void){  cap_t current_caps = cap_get_proc();  cap_free(current_caps);  if (current_caps != NULL)  {    return 1;  }  return 0;}voidvsf_sysdep_adopt_capabilities(unsigned int caps){  int retval;  cap_value_t cap_value;  cap_t adopt_caps = cap_init();  if (caps & kCapabilityCAP_CHOWN)  {    cap_value = CAP_CHOWN;    cap_set_flag(adopt_caps, CAP_EFFECTIVE, 1, &cap_value, CAP_SET);    cap_set_flag(adopt_caps, CAP_PERMITTED, 1, &cap_value, CAP_SET);  }  if (caps & kCapabilityCAP_NET_BIND_SERVICE)  {    cap_value = CAP_NET_BIND_SERVICE;    cap_set_flag(adopt_caps, CAP_EFFECTIVE, 1, &cap_value, CAP_SET);    cap_set_flag(adopt_caps, CAP_PERMITTED, 1, &cap_value, CAP_SET);  }  retval = cap_set_proc(adopt_caps);  if (retval != 0)  {    die("cap_set_proc");  }  cap_free(adopt_caps);}  #endif /* !VSF_SYSDEP_HAVE_LIBCAP */#endif /* VSF_SYSDEP_HAVE_CAPABILITIES || VSF_SYSDEP_HAVE_LIBCAP */intvsf_sysutil_sendfile(const int out_fd, const int in_fd,                     filesize_t* p_offset, filesize_t num_send,                     unsigned int max_chunk)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -