vsftpd 2.0.7 - initial checkin.
[tomato.git] / release / src / router / vsftpd / parseconf.c
blob5055cb443121c14f3ae95afa33b369eddf4749eb
1 /*
2 * Part of Very Secure FTPd
3 * Licence: GPL v2
4 * Author: Chris Evans
5 * parseconf.c
7 * Routines and support to load in a file full of tunable variables and
8 * settings, populating corresponding runtime variables.
9 */
11 #include "parseconf.h"
12 #include "tunables.h"
13 #include "str.h"
14 #include "filestr.h"
15 #include "defs.h"
16 #include "sysutil.h"
17 #include "utility.h"
19 static const char* s_p_saved_filename;
20 static int s_strings_copied;
22 /* File local functions */
23 static void handle_config_setting(struct mystr* p_setting_str,
24 struct mystr* p_value_str,
25 int errs_fatal);
27 static void copy_string_settings(void);
29 /* Tables mapping setting names to runtime variables */
30 /* Boolean settings */
31 static struct parseconf_bool_setting
33 const char* p_setting_name;
34 int* p_variable;
36 parseconf_bool_array[] =
38 { "anonymous_enable", &tunable_anonymous_enable },
39 { "local_enable", &tunable_local_enable },
40 { "pasv_enable", &tunable_pasv_enable },
41 { "port_enable", &tunable_port_enable },
42 { "chroot_local_user", &tunable_chroot_local_user },
43 { "write_enable", &tunable_write_enable },
44 { "anon_upload_enable", &tunable_anon_upload_enable },
45 { "anon_mkdir_write_enable", &tunable_anon_mkdir_write_enable },
46 { "anon_other_write_enable", &tunable_anon_other_write_enable },
47 { "chown_uploads", &tunable_chown_uploads },
48 { "connect_from_port_20", &tunable_connect_from_port_20 },
49 { "xferlog_enable", &tunable_xferlog_enable },
50 { "dirmessage_enable", &tunable_dirmessage_enable },
51 { "anon_world_readable_only", &tunable_anon_world_readable_only },
52 { "async_abor_enable", &tunable_async_abor_enable },
53 { "ascii_upload_enable", &tunable_ascii_upload_enable },
54 { "ascii_download_enable", &tunable_ascii_download_enable },
55 { "one_process_model", &tunable_one_process_model },
56 { "xferlog_std_format", &tunable_xferlog_std_format },
57 { "pasv_promiscuous", &tunable_pasv_promiscuous },
58 { "deny_email_enable", &tunable_deny_email_enable },
59 { "chroot_list_enable", &tunable_chroot_list_enable },
60 { "setproctitle_enable", &tunable_setproctitle_enable },
61 { "text_userdb_names", &tunable_text_userdb_names },
62 { "ls_recurse_enable", &tunable_ls_recurse_enable },
63 { "log_ftp_protocol", &tunable_log_ftp_protocol },
64 { "guest_enable", &tunable_guest_enable },
65 { "userlist_enable", &tunable_userlist_enable },
66 { "userlist_deny", &tunable_userlist_deny },
67 { "use_localtime", &tunable_use_localtime },
68 { "check_shell", &tunable_check_shell },
69 { "hide_ids", &tunable_hide_ids },
70 { "listen", &tunable_listen },
71 { "port_promiscuous", &tunable_port_promiscuous },
72 { "passwd_chroot_enable", &tunable_passwd_chroot_enable },
73 { "no_anon_password", &tunable_no_anon_password },
74 { "tcp_wrappers", &tunable_tcp_wrappers },
75 { "use_sendfile", &tunable_use_sendfile },
76 { "force_dot_files", &tunable_force_dot_files },
77 { "listen_ipv6", &tunable_listen_ipv6 },
78 { "dual_log_enable", &tunable_dual_log_enable },
79 { "syslog_enable", &tunable_syslog_enable },
80 { "background", &tunable_background },
81 { "virtual_use_local_privs", &tunable_virtual_use_local_privs },
82 { "session_support", &tunable_session_support },
83 { "download_enable", &tunable_download_enable },
84 { "dirlist_enable", &tunable_dirlist_enable },
85 { "chmod_enable", &tunable_chmod_enable },
86 { "secure_email_list_enable", &tunable_secure_email_list_enable },
87 { "run_as_launching_user", &tunable_run_as_launching_user },
88 { "no_log_lock", &tunable_no_log_lock },
89 { "ssl_enable", &tunable_ssl_enable },
90 { "allow_anon_ssl", &tunable_allow_anon_ssl },
91 { "force_local_logins_ssl", &tunable_force_local_logins_ssl },
92 { "force_local_data_ssl", &tunable_force_local_data_ssl },
93 { "ssl_sslv2", &tunable_sslv2 },
94 { "ssl_sslv3", &tunable_sslv3 },
95 { "ssl_tlsv1", &tunable_tlsv1 },
96 { "tilde_user_enable", &tunable_tilde_user_enable },
97 { "force_anon_logins_ssl", &tunable_force_anon_logins_ssl },
98 { "force_anon_data_ssl", &tunable_force_anon_data_ssl },
99 { "mdtm_write", &tunable_mdtm_write },
100 { "lock_upload_files", &tunable_lock_upload_files },
101 { "pasv_addr_resolve", &tunable_pasv_addr_resolve },
102 { "debug_ssl", &tunable_debug_ssl },
103 { "require_cert", &tunable_require_cert },
104 { "validate_cert", &tunable_validate_cert },
105 { "strict_ssl_read_eof", &tunable_strict_ssl_read_eof },
106 { "strict_ssl_write_shutdown", &tunable_strict_ssl_write_shutdown },
107 { "ssl_request_cert", &tunable_ssl_request_cert },
108 { "delete_failed_uploads", &tunable_delete_failed_uploads },
109 { 0, 0 }
112 static struct parseconf_uint_setting
114 const char* p_setting_name;
115 unsigned int* p_variable;
117 parseconf_uint_array[] =
119 { "accept_timeout", &tunable_accept_timeout },
120 { "connect_timeout", &tunable_connect_timeout },
121 { "local_umask", &tunable_local_umask },
122 { "anon_umask", &tunable_anon_umask },
123 { "ftp_data_port", &tunable_ftp_data_port },
124 { "idle_session_timeout", &tunable_idle_session_timeout },
125 { "data_connection_timeout", &tunable_data_connection_timeout },
126 { "pasv_min_port", &tunable_pasv_min_port },
127 { "pasv_max_port", &tunable_pasv_max_port },
128 { "anon_max_rate", &tunable_anon_max_rate },
129 { "local_max_rate", &tunable_local_max_rate },
130 { "listen_port", &tunable_listen_port },
131 { "max_clients", &tunable_max_clients },
132 { "file_open_mode", &tunable_file_open_mode },
133 { "max_per_ip", &tunable_max_per_ip },
134 { "trans_chunk_size", &tunable_trans_chunk_size },
135 { "delay_failed_login", &tunable_delay_failed_login },
136 { "delay_successful_login", &tunable_delay_successful_login },
137 { "max_login_fails", &tunable_max_login_fails },
138 { "chown_upload_mode", &tunable_chown_upload_mode },
139 { 0, 0 }
142 static struct parseconf_str_setting
144 const char* p_setting_name;
145 const char** p_variable;
147 parseconf_str_array[] =
149 { "secure_chroot_dir", &tunable_secure_chroot_dir },
150 { "ftp_username", &tunable_ftp_username },
151 { "chown_username", &tunable_chown_username },
152 { "xferlog_file", &tunable_xferlog_file },
153 { "vsftpd_log_file", &tunable_vsftpd_log_file },
154 { "message_file", &tunable_message_file },
155 { "nopriv_user", &tunable_nopriv_user },
156 { "ftpd_banner", &tunable_ftpd_banner },
157 { "banned_email_file", &tunable_banned_email_file },
158 { "chroot_list_file", &tunable_chroot_list_file },
159 { "pam_service_name", &tunable_pam_service_name },
160 { "guest_username", &tunable_guest_username },
161 { "userlist_file", &tunable_userlist_file },
162 { "anon_root", &tunable_anon_root },
163 { "local_root", &tunable_local_root },
164 { "banner_file", &tunable_banner_file },
165 { "pasv_address", &tunable_pasv_address },
166 { "listen_address", &tunable_listen_address },
167 { "user_config_dir", &tunable_user_config_dir },
168 { "listen_address6", &tunable_listen_address6 },
169 { "cmds_allowed", &tunable_cmds_allowed },
170 { "hide_file", &tunable_hide_file },
171 { "deny_file", &tunable_deny_file },
172 { "user_sub_token", &tunable_user_sub_token },
173 { "email_password_file", &tunable_email_password_file },
174 { "rsa_cert_file", &tunable_rsa_cert_file },
175 { "dsa_cert_file", &tunable_dsa_cert_file },
176 { "ssl_ciphers", &tunable_ssl_ciphers },
177 { "rsa_private_key_file", &tunable_rsa_private_key_file },
178 { "dsa_private_key_file", &tunable_dsa_private_key_file },
179 { "ca_certs_file", &tunable_ca_certs_file },
180 { 0, 0 }
183 void
184 vsf_parseconf_load_file(const char* p_filename, int errs_fatal)
186 struct mystr config_file_str = INIT_MYSTR;
187 struct mystr config_setting_str = INIT_MYSTR;
188 struct mystr config_value_str = INIT_MYSTR;
189 unsigned int str_pos = 0;
190 int retval;
191 if (!p_filename)
193 p_filename = s_p_saved_filename;
195 else
197 if (s_p_saved_filename)
199 vsf_sysutil_free((char*)s_p_saved_filename);
201 s_p_saved_filename = vsf_sysutil_strdup(p_filename);
203 if (!p_filename)
205 bug("null filename in vsf_parseconf_load_file");
207 if (!s_strings_copied)
209 s_strings_copied = 1;
210 /* A minor hack to make sure all strings are malloc()'ed so we can free
211 * them at some later date. Specifically handles strings embedded in the
212 * binary.
214 copy_string_settings();
216 retval = str_fileread(&config_file_str, p_filename, VSFTP_CONF_FILE_MAX);
217 if (vsf_sysutil_retval_is_error(retval))
219 if (errs_fatal)
221 die2("cannot open config file:", p_filename);
223 else
225 return;
228 while (str_getline(&config_file_str, &config_setting_str, &str_pos))
230 if (str_isempty(&config_setting_str) ||
231 str_get_char_at(&config_setting_str, 0) == '#')
233 continue;
235 /* Split into name=value pair */
236 str_split_char(&config_setting_str, &config_value_str, '=');
237 handle_config_setting(&config_setting_str, &config_value_str, errs_fatal);
239 str_free(&config_file_str);
240 str_free(&config_setting_str);
241 str_free(&config_value_str);
244 static void
245 handle_config_setting(struct mystr* p_setting_str, struct mystr* p_value_str,
246 int errs_fatal)
248 /* Is it a string setting? */
250 const struct parseconf_str_setting* p_str_setting = parseconf_str_array;
251 while (p_str_setting->p_setting_name != 0)
253 if (str_equal_text(p_setting_str, p_str_setting->p_setting_name))
255 /* Got it */
256 const char** p_curr_setting = p_str_setting->p_variable;
257 if (*p_curr_setting)
259 vsf_sysutil_free((char*)*p_curr_setting);
261 if (str_isempty(p_value_str))
263 *p_curr_setting = 0;
265 else
267 *p_curr_setting = str_strdup(p_value_str);
269 return;
271 p_str_setting++;
274 if (str_isempty(p_value_str))
276 if (errs_fatal)
278 die2("missing value in config file for: ", str_getbuf(p_setting_str));
280 else
282 return;
285 /* Is it a boolean value? */
287 const struct parseconf_bool_setting* p_bool_setting = parseconf_bool_array;
288 while (p_bool_setting->p_setting_name != 0)
290 if (str_equal_text(p_setting_str, p_bool_setting->p_setting_name))
292 /* Got it */
293 str_upper(p_value_str);
294 if (str_equal_text(p_value_str, "YES") ||
295 str_equal_text(p_value_str, "TRUE") ||
296 str_equal_text(p_value_str, "1"))
298 *(p_bool_setting->p_variable) = 1;
300 else if (str_equal_text(p_value_str, "NO") ||
301 str_equal_text(p_value_str, "FALSE") ||
302 str_equal_text(p_value_str, "0"))
304 *(p_bool_setting->p_variable) = 0;
306 else if (errs_fatal)
308 die2("bad bool value in config file for: ",
309 str_getbuf(p_setting_str));
311 return;
313 p_bool_setting++;
316 /* Is it an unsigned integer setting? */
318 const struct parseconf_uint_setting* p_uint_setting = parseconf_uint_array;
319 while (p_uint_setting->p_setting_name != 0)
321 if (str_equal_text(p_setting_str, p_uint_setting->p_setting_name))
323 /* Got it */
324 /* If the value starts with 0, assume it's an octal value */
325 if (!str_isempty(p_value_str) &&
326 str_get_char_at(p_value_str, 0) == '0')
328 *(p_uint_setting->p_variable) = str_octal_to_uint(p_value_str);
330 else
332 *(p_uint_setting->p_variable) = str_atoi(p_value_str);
334 return;
336 p_uint_setting++;
339 if (errs_fatal)
341 die2("unrecognised variable in config file: ", str_getbuf(p_setting_str));
345 static void
346 copy_string_settings(void)
348 const struct parseconf_str_setting* p_str_setting = parseconf_str_array;
349 while (p_str_setting->p_setting_name != 0)
351 if (*p_str_setting->p_variable != 0)
353 *p_str_setting->p_variable =
354 vsf_sysutil_strdup(*p_str_setting->p_variable);
356 p_str_setting++;