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

Ftp客户端

开发平台:

C/C++

  1. /*
  2.  * Part of Very Secure FTPd
  3.  * Licence: GPL v2
  4.  * Author: Chris Evans
  5.  * parseconf.c
  6.  *
  7.  * Routines and support to load in a file full of tunable variables and
  8.  * settings, populating corresponding runtime variables.
  9.  */
  10. #include "parseconf.h"
  11. #include "tunables.h"
  12. #include "str.h"
  13. #include "filestr.h"
  14. #include "defs.h"
  15. #include "sysutil.h"
  16. #include "utility.h"
  17. static const char* s_p_saved_filename;
  18. /* Tables mapping setting names to runtime variables */
  19. /* Boolean settings */
  20. static struct parseconf_bool_setting
  21. {
  22.   const char* p_setting_name;
  23.   int* p_variable;
  24. }
  25. parseconf_bool_array[] =
  26. {
  27.   { "anonymous_enable", &tunable_anonymous_enable },
  28.   { "local_enable", &tunable_local_enable },
  29.   { "pasv_enable", &tunable_pasv_enable },
  30.   { "port_enable", &tunable_port_enable },
  31.   { "chroot_local_user", &tunable_chroot_local_user },
  32.   { "write_enable", &tunable_write_enable },
  33.   { "anon_upload_enable", &tunable_anon_upload_enable },
  34.   { "anon_mkdir_write_enable", &tunable_anon_mkdir_write_enable },
  35.   { "anon_other_write_enable", &tunable_anon_other_write_enable },
  36.   { "chown_uploads", &tunable_chown_uploads },
  37.   { "connect_from_port_20", &tunable_connect_from_port_20 },
  38.   { "xferlog_enable", &tunable_xferlog_enable },
  39.   { "dirmessage_enable", &tunable_dirmessage_enable },
  40.   { "anon_world_readable_only", &tunable_anon_world_readable_only },
  41.   { "async_abor_enable", &tunable_async_abor_enable },
  42.   { "ascii_upload_enable", &tunable_ascii_upload_enable },
  43.   { "ascii_download_enable", &tunable_ascii_download_enable },
  44.   { "one_process_model", &tunable_one_process_model },
  45.   { "xferlog_std_format", &tunable_xferlog_std_format },
  46.   { "pasv_promiscuous", &tunable_pasv_promiscuous },
  47.   { "deny_email_enable", &tunable_deny_email_enable },
  48.   { "chroot_list_enable", &tunable_chroot_list_enable },
  49.   { "setproctitle_enable", &tunable_setproctitle_enable },
  50.   { "text_userdb_names", &tunable_text_userdb_names },
  51.   { "ls_recurse_enable", &tunable_ls_recurse_enable },
  52.   { "log_ftp_protocol", &tunable_log_ftp_protocol },
  53.   { "guest_enable", &tunable_guest_enable },
  54.   { "userlist_enable", &tunable_userlist_enable },
  55.   { "userlist_deny", &tunable_userlist_deny },
  56.   { "use_localtime", &tunable_use_localtime },
  57.   { "check_shell", &tunable_check_shell },
  58.   { "hide_ids", &tunable_hide_ids },
  59.   { "listen", &tunable_listen },
  60.   { "port_promiscuous", &tunable_port_promiscuous },
  61.   { "passwd_chroot_enable", &tunable_passwd_chroot_enable },
  62.   { "no_anon_password", &tunable_no_anon_password },
  63.   { "tcp_wrappers", &tunable_tcp_wrappers },
  64.   { "use_sendfile", &tunable_use_sendfile },
  65.   { "force_dot_files", &tunable_force_dot_files },
  66.   { "listen_ipv6", &tunable_listen_ipv6 },
  67.   { "dual_log_enable", &tunable_dual_log_enable },
  68.   { "syslog_enable", &tunable_syslog_enable },
  69.   { "background", &tunable_background },
  70.   { "virtual_use_local_privs", &tunable_virtual_use_local_privs },
  71.   { "session_support", &tunable_session_support },
  72.   { "download_enable", &tunable_download_enable },
  73.   { "dirlist_enable", &tunable_dirlist_enable },
  74.   { "chmod_enable", &tunable_chmod_enable },
  75.   { "secure_email_list_enable", &tunable_secure_email_list_enable },
  76.   { "run_as_launching_user", &tunable_run_as_launching_user },
  77.   { "no_log_lock", &tunable_no_log_lock },
  78.   { "ssl_enable", &tunable_ssl_enable },
  79.   { "allow_anon_ssl", &tunable_allow_anon_ssl },
  80.   { "force_local_logins_ssl", &tunable_force_local_logins_ssl },
  81.   { "force_local_data_ssl", &tunable_force_local_data_ssl },
  82.   { "ssl_sslv2", &tunable_sslv2 },
  83.   { "ssl_sslv3", &tunable_sslv3 },
  84.   { "ssl_tlsv1", &tunable_tlsv1 },
  85.   { "tilde_user_enable", &tunable_tilde_user_enable },
  86.   { "force_anon_logins_ssl", &tunable_force_anon_logins_ssl },
  87.   { "force_anon_data_ssl", &tunable_force_anon_data_ssl },
  88.   { "mdtm_write", &tunable_mdtm_write },
  89.   { "lock_upload_files", &tunable_lock_upload_files },
  90.   { "pasv_addr_resolve", &tunable_pasv_addr_resolve },
  91.   { "debug_ssl", &tunable_debug_ssl },
  92.   { "require_cert", &tunable_require_cert },
  93.   { "validate_cert", &tunable_validate_cert },
  94.   { "strict_ssl_read_eof", &tunable_strict_ssl_read_eof },
  95.   { "strict_ssl_write_shutdown", &tunable_strict_ssl_write_shutdown },
  96.   { "ssl_request_cert", &tunable_ssl_request_cert },
  97.   { "delete_failed_uploads", &tunable_delete_failed_uploads },
  98.   { "implicit_ssl", &tunable_implicit_ssl },
  99.   { "sandbox", &tunable_sandbox },
  100.   { "require_ssl_reuse", &tunable_require_ssl_reuse },
  101.   { "isolate", &tunable_isolate },
  102.   { "isolate_network", &tunable_isolate_network },
  103.   { 0, 0 }
  104. };
  105. static struct parseconf_uint_setting
  106. {
  107.   const char* p_setting_name;
  108.   unsigned int* p_variable;
  109. }
  110. parseconf_uint_array[] =
  111. {
  112.   { "accept_timeout", &tunable_accept_timeout },
  113.   { "connect_timeout", &tunable_connect_timeout },
  114.   { "local_umask", &tunable_local_umask },
  115.   { "anon_umask", &tunable_anon_umask },
  116.   { "ftp_data_port", &tunable_ftp_data_port },
  117.   { "idle_session_timeout", &tunable_idle_session_timeout },
  118.   { "data_connection_timeout", &tunable_data_connection_timeout },
  119.   { "pasv_min_port", &tunable_pasv_min_port },
  120.   { "pasv_max_port", &tunable_pasv_max_port },
  121.   { "anon_max_rate", &tunable_anon_max_rate },
  122.   { "local_max_rate", &tunable_local_max_rate },
  123.   { "listen_port", &tunable_listen_port },
  124.   { "max_clients", &tunable_max_clients },
  125.   { "file_open_mode", &tunable_file_open_mode },
  126.   { "max_per_ip", &tunable_max_per_ip },
  127.   { "trans_chunk_size", &tunable_trans_chunk_size },
  128.   { "delay_failed_login", &tunable_delay_failed_login },
  129.   { "delay_successful_login", &tunable_delay_successful_login },
  130.   { "max_login_fails", &tunable_max_login_fails },
  131.   { "chown_upload_mode", &tunable_chown_upload_mode },
  132.   { 0, 0 }
  133. };
  134. static struct parseconf_str_setting
  135. {
  136.   const char* p_setting_name;
  137.   const char** p_variable;
  138. }
  139. parseconf_str_array[] =
  140. {
  141.   { "secure_chroot_dir", &tunable_secure_chroot_dir },
  142.   { "ftp_username", &tunable_ftp_username },
  143.   { "chown_username", &tunable_chown_username },
  144.   { "xferlog_file", &tunable_xferlog_file },
  145.   { "vsftpd_log_file", &tunable_vsftpd_log_file },
  146.   { "message_file", &tunable_message_file },
  147.   { "nopriv_user", &tunable_nopriv_user },
  148.   { "ftpd_banner", &tunable_ftpd_banner },
  149.   { "banned_email_file", &tunable_banned_email_file },
  150.   { "chroot_list_file", &tunable_chroot_list_file },
  151.   { "pam_service_name", &tunable_pam_service_name },
  152.   { "guest_username", &tunable_guest_username },
  153.   { "userlist_file", &tunable_userlist_file },
  154.   { "anon_root", &tunable_anon_root },
  155.   { "local_root", &tunable_local_root },
  156.   { "banner_file", &tunable_banner_file },
  157.   { "pasv_address", &tunable_pasv_address },
  158.   { "listen_address", &tunable_listen_address },
  159.   { "user_config_dir", &tunable_user_config_dir },
  160.   { "listen_address6", &tunable_listen_address6 },
  161.   { "cmds_allowed", &tunable_cmds_allowed },
  162.   { "hide_file", &tunable_hide_file },
  163.   { "deny_file", &tunable_deny_file },
  164.   { "user_sub_token", &tunable_user_sub_token },
  165.   { "email_password_file", &tunable_email_password_file },
  166.   { "rsa_cert_file", &tunable_rsa_cert_file },
  167.   { "dsa_cert_file", &tunable_dsa_cert_file },
  168.   { "ssl_ciphers", &tunable_ssl_ciphers },
  169.   { "rsa_private_key_file", &tunable_rsa_private_key_file },
  170.   { "dsa_private_key_file", &tunable_dsa_private_key_file },
  171.   { "ca_certs_file", &tunable_ca_certs_file },
  172.   { "cmds_denied", &tunable_cmds_denied },
  173.   { 0, 0 }
  174. };
  175. void
  176. vsf_parseconf_load_file(const char* p_filename, int errs_fatal)
  177. {
  178.   struct mystr config_file_str = INIT_MYSTR;
  179.   struct mystr config_setting_str = INIT_MYSTR;
  180.   struct mystr config_value_str = INIT_MYSTR;
  181.   unsigned int str_pos = 0;
  182.   int retval;
  183.   if (!p_filename)
  184.   {
  185.     p_filename = s_p_saved_filename;
  186.   }
  187.   else
  188.   {
  189.     if (s_p_saved_filename)
  190.     {
  191.       vsf_sysutil_free((char*)s_p_saved_filename);
  192.     }
  193.     s_p_saved_filename = vsf_sysutil_strdup(p_filename);
  194.   }
  195.   if (!p_filename)
  196.   {
  197.     bug("null filename in vsf_parseconf_load_file");
  198.   }
  199.   retval = str_fileread(&config_file_str, p_filename, VSFTP_CONF_FILE_MAX);
  200.   if (vsf_sysutil_retval_is_error(retval))
  201.   {
  202.     if (errs_fatal)
  203.     {
  204.       die2("cannot read config file: ", p_filename);
  205.     }
  206.     else
  207.     {
  208.       str_free(&config_file_str);
  209.       return;
  210.     }
  211.   }
  212.   {
  213.     struct vsf_sysutil_statbuf* p_statbuf = 0;
  214.     retval = vsf_sysutil_stat(p_filename, &p_statbuf);
  215.     /* Security: check current user owns the config file. These are sanity
  216.      * checks for the admin, and are NOT designed to be checks safe from
  217.      * race conditions.
  218.      */
  219.     if (vsf_sysutil_retval_is_error(retval) ||
  220.         vsf_sysutil_statbuf_get_uid(p_statbuf) != vsf_sysutil_getuid() ||
  221.         !vsf_sysutil_statbuf_is_regfile(p_statbuf))
  222.     {
  223.       die("config file not owned by correct user, or not a file");
  224.     }
  225.     vsf_sysutil_free(p_statbuf);
  226.   }
  227.   while (str_getline(&config_file_str, &config_setting_str, &str_pos))
  228.   {
  229.     if (str_isempty(&config_setting_str) ||
  230.         str_get_char_at(&config_setting_str, 0) == '#' ||
  231.         str_all_space(&config_setting_str))
  232.     {
  233.       continue;
  234.     }
  235.     vsf_parseconf_load_setting(str_getbuf(&config_setting_str), errs_fatal);
  236.   }
  237.   str_free(&config_file_str);
  238.   str_free(&config_setting_str);
  239.   str_free(&config_value_str);
  240. }
  241. void
  242. vsf_parseconf_load_setting(const char* p_setting, int errs_fatal)
  243. {
  244.   static struct mystr s_setting_str;
  245.   static struct mystr s_value_str;
  246.   while (vsf_sysutil_isspace(*p_setting))
  247.   {
  248.     p_setting++;
  249.   }
  250.   str_alloc_text(&s_setting_str, p_setting);
  251.   str_split_char(&s_setting_str, &s_value_str, '=');
  252.   /* Is it a string setting? */
  253.   {
  254.     const struct parseconf_str_setting* p_str_setting = parseconf_str_array;
  255.     while (p_str_setting->p_setting_name != 0)
  256.     {
  257.       if (str_equal_text(&s_setting_str, p_str_setting->p_setting_name))
  258.       {
  259.         /* Got it */
  260.         const char** p_curr_setting = p_str_setting->p_variable;
  261.         if (*p_curr_setting)
  262.         {
  263.           vsf_sysutil_free((char*) *p_curr_setting);
  264.         }
  265.         if (str_isempty(&s_value_str))
  266.         {
  267.           *p_curr_setting = 0;
  268.         }
  269.         else
  270.         {
  271.           *p_curr_setting = str_strdup(&s_value_str);
  272.         }
  273.         return;
  274.       }
  275.       p_str_setting++;
  276.     }
  277.   }
  278.   if (str_isempty(&s_value_str))
  279.   {
  280.     if (errs_fatal)
  281.     {
  282.       die2("missing value in config file for: ", str_getbuf(&s_setting_str));
  283.     }
  284.     else
  285.     {
  286.       return;
  287.     }
  288.   }
  289.   /* Is it a boolean value? */
  290.   {
  291.     const struct parseconf_bool_setting* p_bool_setting = parseconf_bool_array;
  292.     while (p_bool_setting->p_setting_name != 0)
  293.     {
  294.       if (str_equal_text(&s_setting_str, p_bool_setting->p_setting_name))
  295.       {
  296.         /* Got it */
  297.         str_upper(&s_value_str);
  298.         if (str_equal_text(&s_value_str, "YES") ||
  299.             str_equal_text(&s_value_str, "TRUE") ||
  300.             str_equal_text(&s_value_str, "1"))
  301.         {
  302.           *(p_bool_setting->p_variable) = 1;
  303.         }
  304.         else if (str_equal_text(&s_value_str, "NO") ||
  305.                  str_equal_text(&s_value_str, "FALSE") ||
  306.                  str_equal_text(&s_value_str, "0"))
  307.         {
  308.           *(p_bool_setting->p_variable) = 0;
  309.         }
  310.         else if (errs_fatal)
  311.         {
  312.           die2("bad bool value in config file for: ",
  313.                str_getbuf(&s_setting_str));
  314.         }
  315.         return;
  316.       }
  317.       p_bool_setting++;
  318.     }
  319.   }
  320.   /* Is it an unsigned integer setting? */
  321.   {
  322.     const struct parseconf_uint_setting* p_uint_setting = parseconf_uint_array;
  323.     while (p_uint_setting->p_setting_name != 0)
  324.     {
  325.       if (str_equal_text(&s_setting_str, p_uint_setting->p_setting_name))
  326.       {
  327.         /* Got it */
  328.         /* If the value starts with 0, assume it's an octal value */
  329.         if (!str_isempty(&s_value_str) &&
  330.             str_get_char_at(&s_value_str, 0) == '0')
  331.         {
  332.           *(p_uint_setting->p_variable) = str_octal_to_uint(&s_value_str);
  333.         }
  334.         else
  335.         {
  336.           *(p_uint_setting->p_variable) = str_atoi(&s_value_str);
  337.         }
  338.         return;
  339.       }
  340.       p_uint_setting++;
  341.     }
  342.   }
  343.   if (errs_fatal)
  344.   {
  345.     die2("unrecognised variable in config file: ", str_getbuf(&s_setting_str));
  346.   }
  347. }