main.c
上传用户:ig0539
上传日期:2022-05-21
资源大小:181k
文件大小:9k
源码类别:

Ftp客户端

开发平台:

C/C++

  1. /*
  2.  * Part of Very Secure FTPd
  3.  * Licence: GPL v2
  4.  * Author: Chris Evans
  5.  * main.c
  6.  */
  7. #include "session.h"
  8. #include "utility.h"
  9. #include "tunables.h"
  10. #include "logging.h"
  11. #include "str.h"
  12. #include "filestr.h"
  13. #include "ftpcmdio.h"
  14. #include "sysutil.h"
  15. #include "sysdeputil.h"
  16. #include "defs.h"
  17. #include "parseconf.h"
  18. #include "oneprocess.h"
  19. #include "twoprocess.h"
  20. #include "standalone.h"
  21. #include "tcpwrap.h"
  22. #include "vsftpver.h"
  23. #include "ssl.h"
  24. /*
  25.  * Forward decls of helper functions
  26.  */
  27. static void die_unless_privileged(void);
  28. static void do_sanity_checks(void);
  29. static void session_init(struct vsf_session* p_sess);
  30. static void env_init(void);
  31. static void limits_init(void);
  32. int
  33. main(int argc, const char* argv[])
  34. {
  35.   struct vsf_session the_session =
  36.   {
  37.     /* Control connection */
  38.     0, 0, 0,
  39.     /* Data connection */
  40.     -1, 0, -1, 0, 0, 0, 0,
  41.     /* Login */
  42.     1, 0, INIT_MYSTR, INIT_MYSTR,
  43.     /* Protocol state */
  44.     0, 1, INIT_MYSTR, 0, 0,
  45.     /* Session state */
  46.     0,
  47.     /* Userids */
  48.     -1, -1, -1,
  49.     /* Pre-chroot() cache */
  50.     INIT_MYSTR, INIT_MYSTR, INIT_MYSTR, INIT_MYSTR, 1,
  51.     /* Logging */
  52.     -1, -1, INIT_MYSTR, 0, 0, 0, INIT_MYSTR, 0,
  53.     /* Buffers */
  54.     INIT_MYSTR, INIT_MYSTR,
  55.     /* Parent <-> child comms */
  56.     -1, -1,
  57.     /* Number of clients */
  58.     0, 0,
  59.     /* Home directory */
  60.     INIT_MYSTR,
  61.     /* Secure connection state */
  62.     0, 0, 0, 0, 0, INIT_MYSTR, 0, -1, -1,
  63.     /* Login fails */
  64.     0
  65.   };
  66.   int config_loaded = 0;
  67.   int i;
  68.   tunables_load_defaults();
  69.   /* This might need to open /dev/zero on systems lacking MAP_ANON. Needs
  70.    * to be done early (i.e. before config file parse, which may use
  71.    * anonymous pages
  72.    */
  73.   vsf_sysutil_map_anon_pages_init();
  74.   /* Argument parsing. Any argument not starting with "-" is a config file,
  75.    * loaded in the order encountered. -o opt=value options are loading in the
  76.    * order encountered, including correct ordering with respect intermingled
  77.    * config files.
  78.    * If we see -v (version) or an unknown option, parsing bails and exits.
  79.    */
  80.   if (argc == 0)
  81.   {
  82.     die("vsftpd: missing argv[0]");
  83.   }
  84.   for (i = 1; i < argc; ++i)
  85.   {
  86.     const char* p_arg = argv[i];
  87.     if (p_arg[0] != '-')
  88.     {
  89.       config_loaded = 1;
  90.       vsf_parseconf_load_file(p_arg, 1);
  91.     }
  92.     else
  93.     {
  94.       if (p_arg[1] == 'v')
  95.       {
  96.         vsf_exit("vsftpd: version " VSF_VERSION "n");
  97.       }
  98.       else if (p_arg[1] == 'o')
  99.       {
  100.         vsf_parseconf_load_setting(&p_arg[2], 1);
  101.       }
  102.       else
  103.       {
  104.         die2("unrecognise option: ", p_arg);
  105.       }
  106.     }
  107.   }
  108.   /* Parse default config file if necessary */
  109.   if (!config_loaded) {
  110.     struct vsf_sysutil_statbuf* p_statbuf = 0;
  111.     int retval = vsf_sysutil_stat(VSFTP_DEFAULT_CONFIG, &p_statbuf);
  112.     if (!vsf_sysutil_retval_is_error(retval))
  113.     {
  114.       vsf_parseconf_load_file(VSFTP_DEFAULT_CONFIG, 1);
  115.     }
  116.     vsf_sysutil_free(p_statbuf);
  117.   }
  118.   /* Resolve pasv_address if required */
  119.   if (tunable_pasv_address && tunable_pasv_addr_resolve)
  120.   {
  121.     struct vsf_sysutil_sockaddr* p_addr = 0;
  122.     const char* p_numeric_addr;
  123.     vsf_sysutil_dns_resolve(&p_addr, tunable_pasv_address);
  124.     vsf_sysutil_free((char*) tunable_pasv_address);
  125.     p_numeric_addr = vsf_sysutil_inet_ntop(p_addr);
  126.     tunable_pasv_address = vsf_sysutil_strdup(p_numeric_addr);
  127.     vsf_sysutil_free(p_addr);
  128.   }
  129.   if (!tunable_run_as_launching_user)
  130.   {
  131.     /* Just get out unless we start with requisite privilege */
  132.     die_unless_privileged();
  133.   }
  134.   if (tunable_setproctitle_enable)
  135.   {
  136.     /* Warning -- warning -- may nuke argv, environ */
  137.     vsf_sysutil_setproctitle_init(argc, argv);
  138.   }
  139.   /* Initialize the SSL system here if needed - saves the overhead of each
  140.    * child doing this itself.
  141.    */
  142.   if (tunable_ssl_enable)
  143.   {
  144.     ssl_init(&the_session);
  145.   }
  146.   if (tunable_listen || tunable_listen_ipv6)
  147.   {
  148.     /* Standalone mode */
  149.     struct vsf_client_launch ret = vsf_standalone_main();
  150.     the_session.num_clients = ret.num_children;
  151.     the_session.num_this_ip = ret.num_this_ip;
  152.   }
  153.   if (tunable_tcp_wrappers)
  154.   {
  155.     the_session.tcp_wrapper_ok = vsf_tcp_wrapper_ok(VSFTP_COMMAND_FD);
  156.   }
  157.   {
  158.     const char* p_load_conf = vsf_sysutil_getenv("VSFTPD_LOAD_CONF");
  159.     if (p_load_conf)
  160.     {
  161.       vsf_parseconf_load_file(p_load_conf, 1);
  162.     }
  163.   }
  164.   /* Sanity checks - exit with a graceful error message if our STDIN is not
  165.    * a socket. Also check various config options don't collide.
  166.    */
  167.   do_sanity_checks();
  168.   /* Initializes session globals - e.g. IP addr's etc. */
  169.   session_init(&the_session);
  170.   /* Set up "environment", e.g. process group etc. */
  171.   env_init();
  172.   /* Set up resource limits. */
  173.   limits_init();
  174.   /* Set up logging - must come after global init because we need the remote
  175.    * address to convert into text
  176.    */
  177.   vsf_log_init(&the_session);
  178.   str_alloc_text(&the_session.remote_ip_str,
  179.                  vsf_sysutil_inet_ntop(the_session.p_remote_addr));
  180.   /* Set up options on the command socket */
  181.   vsf_cmdio_sock_setup();
  182.   if (tunable_setproctitle_enable)
  183.   {
  184.     vsf_sysutil_set_proctitle_prefix(&the_session.remote_ip_str);
  185.     vsf_sysutil_setproctitle("connected");
  186.   }
  187.   /* We might chroot() very soon (one process model), so we need to open
  188.    * any required config files here.
  189.    */
  190.   /* SSL may have been enabled by a per-IP configuration.. */
  191.   if (tunable_ssl_enable)
  192.   {
  193.     ssl_init(&the_session);
  194.     ssl_add_entropy(&the_session);
  195.   }
  196.   if (tunable_deny_email_enable)
  197.   {
  198.     int retval = str_fileread(&the_session.banned_email_str,
  199.                               tunable_banned_email_file, VSFTP_CONF_FILE_MAX);
  200.     if (vsf_sysutil_retval_is_error(retval))
  201.     {
  202.       die2("cannot read anon e-mail list file:", tunable_banned_email_file);
  203.     }
  204.   }
  205.   if (tunable_banner_file)
  206.   {
  207.     int retval = str_fileread(&the_session.banner_str, tunable_banner_file,
  208.                               VSFTP_CONF_FILE_MAX);
  209.     if (vsf_sysutil_retval_is_error(retval))
  210.     {
  211.       die2("cannot read banner file:", tunable_banner_file);
  212.     }
  213.   }
  214.   if (tunable_secure_email_list_enable)
  215.   {
  216.     int retval = str_fileread(&the_session.email_passwords_str,
  217.                               tunable_email_password_file,
  218.                               VSFTP_CONF_FILE_MAX);
  219.     if (vsf_sysutil_retval_is_error(retval))
  220.     {
  221.       die2("cannot read email passwords file:", tunable_email_password_file);
  222.     }
  223.   }
  224.   if (tunable_run_as_launching_user)
  225.   {
  226.     tunable_one_process_model = 1;
  227.     if (!vsf_sysutil_running_as_root())
  228.     {
  229.       tunable_connect_from_port_20 = 0;
  230.       tunable_chown_uploads = 0;
  231.     }
  232.   }
  233.   if (tunable_one_process_model)
  234.   {
  235.     vsf_one_process_start(&the_session);
  236.   }
  237.   else
  238.   {
  239.     vsf_two_process_start(&the_session);
  240.   }
  241.   /* NOTREACHED */
  242.   bug("should not get here: main");
  243.   return 1;
  244. }
  245. static void
  246. die_unless_privileged(void)
  247. {
  248.   if (!vsf_sysutil_running_as_root())
  249.   {
  250.     die("vsftpd: must be started as root (see run_as_launching_user option)");
  251.   }
  252. }
  253. static void
  254. do_sanity_checks(void)
  255. {
  256.   {
  257.     struct vsf_sysutil_statbuf* p_statbuf = 0;
  258.     vsf_sysutil_fstat(VSFTP_COMMAND_FD, &p_statbuf);
  259.     if (!vsf_sysutil_statbuf_is_socket(p_statbuf))
  260.     {
  261.       die("vsftpd: not configured for standalone, must be started from inetd");
  262.     }
  263.     vsf_sysutil_free(p_statbuf);
  264.   }
  265.   if (tunable_one_process_model)
  266.   {
  267.     if (tunable_local_enable)
  268.     {
  269.       die("vsftpd: security: 'one_process_model' is anonymous only");
  270.     }
  271.     if (!vsf_sysdep_has_capabilities_as_non_root())
  272.     {
  273.       die("vsftpd: security: 'one_process_model' needs a better OS");
  274.     }
  275.   }
  276.   if (!tunable_local_enable && !tunable_anonymous_enable)
  277.   {
  278.     die("vsftpd: both local and anonymous access disabled!");
  279.   }
  280. }
  281. static void
  282. env_init(void)
  283. {
  284.   vsf_sysutil_make_session_leader();
  285.   /* Set up a secure umask - we'll set the proper one after login */
  286.   vsf_sysutil_set_umask(VSFTP_SECURE_UMASK);
  287.   /* Fire up libc's timezone initialisation, before we chroot()! */
  288.   vsf_sysutil_tzset();
  289.   /* Signals. We'll always take -EPIPE rather than a rude signal, thanks */
  290.   vsf_sysutil_install_null_sighandler(kVSFSysUtilSigPIPE);
  291. }
  292. static void
  293. limits_init(void)
  294. {
  295.   vsf_sysutil_set_address_space_limit(VSFTP_AS_LIMIT);
  296. }
  297. static void
  298. session_init(struct vsf_session* p_sess)
  299. {
  300.   /* Get the addresses of the control connection */
  301.   vsf_sysutil_getpeername(VSFTP_COMMAND_FD, &p_sess->p_remote_addr);
  302.   vsf_sysutil_getsockname(VSFTP_COMMAND_FD, &p_sess->p_local_addr);
  303.   /* If anonymous mode is active, fetch the uid of the anonymous user */
  304.   if (tunable_anonymous_enable)
  305.   {
  306.     const struct vsf_sysutil_user* p_user =
  307.       vsf_sysutil_getpwnam(tunable_ftp_username);
  308.     if (p_user == 0)
  309.     {
  310.       die2("vsftpd: cannot locate user specified in 'ftp_username':",
  311.            tunable_ftp_username);
  312.     }
  313.     p_sess->anon_ftp_uid = vsf_sysutil_user_getuid(p_user);
  314.   }
  315.   if (tunable_guest_enable)
  316.   {
  317.     const struct vsf_sysutil_user* p_user =
  318.       vsf_sysutil_getpwnam(tunable_guest_username);
  319.     if (p_user == 0)
  320.     {
  321.       die2("vsftpd: cannot locate user specified in 'guest_username':",
  322.            tunable_guest_username);
  323.     }
  324.     p_sess->guest_user_uid = vsf_sysutil_user_getuid(p_user);
  325.   }
  326.   if (tunable_chown_uploads)
  327.   {
  328.     const struct vsf_sysutil_user* p_user =
  329.       vsf_sysutil_getpwnam(tunable_chown_username);
  330.     if (p_user == 0)
  331.     {
  332.       die2("vsftpd: cannot locate user specified in 'chown_username':",
  333.            tunable_chown_username);
  334.     }
  335.     p_sess->anon_upload_chown_uid = vsf_sysutil_user_getuid(p_user);
  336.   }
  337. }