1/* 2 * This program is free software; you can redistribute it and/or 3 * modify it under the terms of the GNU General Public License as 4 * published by the Free Software Foundation; either version 2 of 5 * the License, or (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, 8 * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * GNU General Public License for more details. 11 * 12 * You should have received a copy of the GNU General Public License 13 * along with this program; if not, write to the Free Software 14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 15 * MA 02111-1307 USA 16 */ 17/* 18 * Part of Very Secure FTPd 19 * Licence: GPL v2 20 * Author: Chris Evans 21 * parseconf.c 22 * 23 * Routines and support to load in a file full of tunable variables and 24 * settings, populating corresponding runtime variables. 25 */ 26 27#include "parseconf.h" 28#include "tunables.h" 29#include "str.h" 30#include "filestr.h" 31#include "defs.h" 32#include "sysutil.h" 33#include "utility.h" 34 35static const char* s_p_saved_filename; 36static int s_strings_copied; 37 38/* File local functions */ 39static void handle_config_setting(struct mystr* p_setting_str, 40 struct mystr* p_value_str, 41 int errs_fatal); 42 43static void copy_string_settings(void); 44 45/* Tables mapping setting names to runtime variables */ 46/* Boolean settings */ 47static struct parseconf_bool_setting 48{ 49 const char* p_setting_name; 50 int* p_variable; 51} 52parseconf_bool_array[] = 53{ 54 { "anonymous_enable", &tunable_anonymous_enable }, 55 { "local_enable", &tunable_local_enable }, 56 { "pasv_enable", &tunable_pasv_enable }, 57 { "port_enable", &tunable_port_enable }, 58 { "chroot_local_user", &tunable_chroot_local_user }, 59 { "write_enable", &tunable_write_enable }, 60 { "anon_upload_enable", &tunable_anon_upload_enable }, 61 { "anon_mkdir_write_enable", &tunable_anon_mkdir_write_enable }, 62 { "anon_other_write_enable", &tunable_anon_other_write_enable }, 63 { "chown_uploads", &tunable_chown_uploads }, 64 { "connect_from_port_20", &tunable_connect_from_port_20 }, 65 { "xferlog_enable", &tunable_xferlog_enable }, 66 { "dirmessage_enable", &tunable_dirmessage_enable }, 67 { "anon_world_readable_only", &tunable_anon_world_readable_only }, 68 { "async_abor_enable", &tunable_async_abor_enable }, 69 { "ascii_upload_enable", &tunable_ascii_upload_enable }, 70 { "ascii_download_enable", &tunable_ascii_download_enable }, 71 { "one_process_model", &tunable_one_process_model }, 72 { "xferlog_std_format", &tunable_xferlog_std_format }, 73 { "pasv_promiscuous", &tunable_pasv_promiscuous }, 74 { "deny_email_enable", &tunable_deny_email_enable }, 75 { "chroot_list_enable", &tunable_chroot_list_enable }, 76 { "setproctitle_enable", &tunable_setproctitle_enable }, 77 { "text_userdb_names", &tunable_text_userdb_names }, 78 { "ls_recurse_enable", &tunable_ls_recurse_enable }, 79 { "log_ftp_protocol", &tunable_log_ftp_protocol }, 80 { "guest_enable", &tunable_guest_enable }, 81 { "userlist_enable", &tunable_userlist_enable }, 82 { "userlist_deny", &tunable_userlist_deny }, 83 { "use_localtime", &tunable_use_localtime }, 84 { "check_shell", &tunable_check_shell }, 85 { "hide_ids", &tunable_hide_ids }, 86 { "listen", &tunable_listen }, 87 { "port_promiscuous", &tunable_port_promiscuous }, 88 { "passwd_chroot_enable", &tunable_passwd_chroot_enable }, 89 { "no_anon_password", &tunable_no_anon_password }, 90 { "tcp_wrappers", &tunable_tcp_wrappers }, 91 { "use_sendfile", &tunable_use_sendfile }, 92 { "force_dot_files", &tunable_force_dot_files }, 93 { "listen_ipv6", &tunable_listen_ipv6 }, 94 { "dual_log_enable", &tunable_dual_log_enable }, 95 { "syslog_enable", &tunable_syslog_enable }, 96 { "background", &tunable_background }, 97 { "virtual_use_local_privs", &tunable_virtual_use_local_privs }, 98 { "session_support", &tunable_session_support }, 99 { "download_enable", &tunable_download_enable }, 100 { "dirlist_enable", &tunable_dirlist_enable }, 101 { "chmod_enable", &tunable_chmod_enable }, 102 { "secure_email_list_enable", &tunable_secure_email_list_enable }, 103 { "run_as_launching_user", &tunable_run_as_launching_user }, 104 { "no_log_lock", &tunable_no_log_lock }, 105 { "ssl_enable", &tunable_ssl_enable }, 106 { "allow_anon_ssl", &tunable_allow_anon_ssl }, 107 { "force_local_logins_ssl", &tunable_force_local_logins_ssl }, 108 { "force_local_data_ssl", &tunable_force_local_data_ssl }, 109 { "ssl_sslv2", &tunable_sslv2 }, 110 { "ssl_sslv3", &tunable_sslv3 }, 111 { "ssl_tlsv1", &tunable_tlsv1 }, 112 { "tilde_user_enable", &tunable_tilde_user_enable }, 113 { "enable_iconv", &tunable_enable_iconv }, // Jiahao 114 { "force_anon_logins_ssl", &tunable_force_anon_logins_ssl }, 115 { "force_anon_data_ssl", &tunable_force_anon_data_ssl }, 116 { "mdtm_write", &tunable_mdtm_write }, 117 { "lock_upload_files", &tunable_lock_upload_files }, 118 { "pasv_addr_resolve", &tunable_pasv_addr_resolve }, 119 { 0, 0 } 120}; 121 122static struct parseconf_uint_setting 123{ 124 const char* p_setting_name; 125 unsigned int* p_variable; 126} 127parseconf_uint_array[] = 128{ 129 { "accept_timeout", &tunable_accept_timeout }, 130 { "connect_timeout", &tunable_connect_timeout }, 131 { "local_umask", &tunable_local_umask }, 132 { "anon_umask", &tunable_anon_umask }, 133 { "ftp_data_port", &tunable_ftp_data_port }, 134 { "idle_session_timeout", &tunable_idle_session_timeout }, 135 { "data_connection_timeout", &tunable_data_connection_timeout }, 136 { "pasv_min_port", &tunable_pasv_min_port }, 137 { "pasv_max_port", &tunable_pasv_max_port }, 138 { "anon_max_rate", &tunable_anon_max_rate }, 139 { "local_max_rate", &tunable_local_max_rate }, 140 { "listen_port", &tunable_listen_port }, 141 { "max_clients", &tunable_max_clients }, 142 { "file_open_mode", &tunable_file_open_mode }, 143 { "max_per_ip", &tunable_max_per_ip }, 144 { "trans_chunk_size", &tunable_trans_chunk_size }, 145 { 0, 0 } 146}; 147 148static struct parseconf_str_setting 149{ 150 const char* p_setting_name; 151 const char** p_variable; 152} 153parseconf_str_array[] = 154{ 155 { "secure_chroot_dir", &tunable_secure_chroot_dir }, 156 { "ftp_username", &tunable_ftp_username }, 157 { "chown_username", &tunable_chown_username }, 158 { "xferlog_file", &tunable_xferlog_file }, 159 { "vsftpd_log_file", &tunable_vsftpd_log_file }, 160 { "message_file", &tunable_message_file }, 161 { "nopriv_user", &tunable_nopriv_user }, 162 { "ftpd_banner", &tunable_ftpd_banner }, 163 { "banned_email_file", &tunable_banned_email_file }, 164 { "chroot_list_file", &tunable_chroot_list_file }, 165 { "pam_service_name", &tunable_pam_service_name }, 166 { "guest_username", &tunable_guest_username }, 167 { "userlist_file", &tunable_userlist_file }, 168 { "anon_root", &tunable_anon_root }, 169 { "local_root", &tunable_local_root }, 170 { "banner_file", &tunable_banner_file }, 171 { "pasv_address", &tunable_pasv_address }, 172 { "listen_address", &tunable_listen_address }, 173 { "user_config_dir", &tunable_user_config_dir }, 174 { "listen_address6", &tunable_listen_address6 }, 175 { "cmds_allowed", &tunable_cmds_allowed }, 176 { "hide_file", &tunable_hide_file }, 177 { "deny_file", &tunable_deny_file }, 178 { "user_sub_token", &tunable_user_sub_token }, 179 { "email_password_file", &tunable_email_password_file }, 180 { "rsa_cert_file", &tunable_rsa_cert_file }, 181 { "dsa_cert_file", &tunable_dsa_cert_file }, 182 { "ssl_ciphers", &tunable_ssl_ciphers }, 183 { "local_charset", &tunable_local_charset }, // Jiahao 184 { "remote_charset", &tunable_remote_charset }, // Jiahao 185 { "rsa_private_key_file", &tunable_rsa_private_key_file }, 186 { "dsa_private_key_file", &tunable_dsa_private_key_file }, 187 { 0, 0 } 188}; 189 190void 191vsf_parseconf_load_file(const char* p_filename, int errs_fatal) 192{ 193 struct mystr config_file_str = INIT_MYSTR; 194 struct mystr config_setting_str = INIT_MYSTR; 195 struct mystr config_value_str = INIT_MYSTR; 196 unsigned int str_pos = 0; 197 int retval; 198 if (!p_filename) 199 { 200 p_filename = s_p_saved_filename; 201 } 202 else 203 { 204 if (s_p_saved_filename) 205 { 206 vsf_sysutil_free((char*)s_p_saved_filename); 207 } 208 s_p_saved_filename = vsf_sysutil_strdup(p_filename); 209 } 210 if (!p_filename) 211 { 212 bug("null filename in vsf_parseconf_load_file"); 213 } 214 if (!s_strings_copied) 215 { 216 s_strings_copied = 1; 217 /* A minor hack to make sure all strings are malloc()'ed so we can free 218 * them at some later date. Specifically handles strings embedded in the 219 * binary. 220 */ 221 copy_string_settings(); 222 } 223 retval = str_fileread(&config_file_str, p_filename, VSFTP_CONF_FILE_MAX); 224 if (vsf_sysutil_retval_is_error(retval)) 225 { 226 if (errs_fatal) 227 { 228 die2("cannot open config file:", p_filename); 229 } 230 else 231 { 232 return; 233 } 234 } 235 while (str_getline(&config_file_str, &config_setting_str, &str_pos)) 236 { 237 if (str_isempty(&config_setting_str) || 238 str_get_char_at(&config_setting_str, 0) == '#') 239 { 240 continue; 241 } 242 /* Split into name=value pair */ 243 str_split_char(&config_setting_str, &config_value_str, '='); 244 handle_config_setting(&config_setting_str, &config_value_str, errs_fatal); 245 } 246 str_free(&config_file_str); 247 str_free(&config_setting_str); 248 str_free(&config_value_str); 249} 250 251static void 252handle_config_setting(struct mystr* p_setting_str, struct mystr* p_value_str, 253 int errs_fatal) 254{ 255 /* Is it a string setting? */ 256 { 257 const struct parseconf_str_setting* p_str_setting = parseconf_str_array; 258 while (p_str_setting->p_setting_name != 0) 259 { 260 if (str_equal_text(p_setting_str, p_str_setting->p_setting_name)) 261 { 262 /* Got it */ 263 const char** p_curr_setting = p_str_setting->p_variable; 264 if (*p_curr_setting) 265 { 266 vsf_sysutil_free((char*)*p_curr_setting); 267 } 268 if (str_isempty(p_value_str)) 269 { 270 *p_curr_setting = 0; 271 } 272 else 273 { 274 *p_curr_setting = str_strdup(p_value_str); 275 } 276 return; 277 } 278 p_str_setting++; 279 } 280 } 281 if (str_isempty(p_value_str)) 282 { 283 if (errs_fatal) 284 { 285 die2("missing value in config file for: ", str_getbuf(p_setting_str)); 286 } 287 else 288 { 289 return; 290 } 291 } 292 /* Is it a boolean value? */ 293 { 294 const struct parseconf_bool_setting* p_bool_setting = parseconf_bool_array; 295 while (p_bool_setting->p_setting_name != 0) 296 { 297 if (str_equal_text(p_setting_str, p_bool_setting->p_setting_name)) 298 { 299 /* Got it */ 300 str_upper(p_value_str); 301 if (str_equal_text(p_value_str, "YES") || 302 str_equal_text(p_value_str, "TRUE") || 303 str_equal_text(p_value_str, "1")) 304 { 305 *(p_bool_setting->p_variable) = 1; 306 } 307 else if (str_equal_text(p_value_str, "NO") || 308 str_equal_text(p_value_str, "FALSE") || 309 str_equal_text(p_value_str, "0")) 310 { 311 *(p_bool_setting->p_variable) = 0; 312 } 313 else if (errs_fatal) 314 { 315 die2("bad bool value in config file for: ", 316 str_getbuf(p_setting_str)); 317 } 318 return; 319 } 320 p_bool_setting++; 321 } 322 } 323 /* Is it an unsigned integer setting? */ 324 { 325 const struct parseconf_uint_setting* p_uint_setting = parseconf_uint_array; 326 while (p_uint_setting->p_setting_name != 0) 327 { 328 if (str_equal_text(p_setting_str, p_uint_setting->p_setting_name)) 329 { 330 /* Got it */ 331 /* If the value starts with 0, assume it's an octal value */ 332 if (!str_isempty(p_value_str) && 333 str_get_char_at(p_value_str, 0) == '0') 334 { 335 *(p_uint_setting->p_variable) = str_octal_to_uint(p_value_str); 336 } 337 else 338 { 339 *(p_uint_setting->p_variable) = str_atoi(p_value_str); 340 } 341 return; 342 } 343 p_uint_setting++; 344 } 345 } 346 if (errs_fatal) 347 { 348 die2("unrecognised variable in config file: ", str_getbuf(p_setting_str)); 349 } 350} 351 352static void 353copy_string_settings(void) 354{ 355 const struct parseconf_str_setting* p_str_setting = parseconf_str_array; 356 while (p_str_setting->p_setting_name != 0) 357 { 358 if (*p_str_setting->p_variable != 0) 359 { 360 *p_str_setting->p_variable = 361 vsf_sysutil_strdup(*p_str_setting->p_variable); 362 } 363 p_str_setting++; 364 } 365} 366 367