PHP ini file IO user restriction
authorJamie Cameron <jcameron@webmin.com>
Thu, 2 Jul 2009 23:51:56 +0000 (23:51 +0000)
committerJamie Cameron <jcameron@webmin.com>
Thu, 2 Jul 2009 23:51:56 +0000 (23:51 +0000)
16 files changed:
WebminCore.pm
phpini/CHANGELOG
phpini/acl_security.pl
phpini/defaultacl
phpini/edit_vars.cgi
phpini/lang/en
phpini/phpini-lib.pl
phpini/save_db.cgi
phpini/save_dirs.cgi
phpini/save_errors.cgi
phpini/save_limits.cgi
phpini/save_misc.cgi
phpini/save_safe.cgi
phpini/save_session.cgi
phpini/save_vars.cgi
web-lib-funcs.pl

index fe9fc7d..c94a749 100644 (file)
@@ -20,7 +20,7 @@ require Exporter;
 # Add functions in web-lib-funcs.pl
 # Generated with :
 # grep -h "^sub " web-lib-funcs.pl ui-lib.pl | sed -e 's/sub /\&/' | xargs echo
-@EXPORT = qw(&read_file &read_file_cached &write_file &html_escape &quote_escape &tempname &transname &trunc &indexof &indexoflc &sysprint &check_ipaddress &check_ip6address &generate_icon &urlize &un_urlize &include &copydata &ReadParseMime &ReadParse &read_fully &read_parse_mime_callback &read_parse_mime_javascript &PrintHeader &header &get_html_title &get_html_framed_title &get_html_status_line &popup_header &footer &popup_footer &load_theme_library &redirect &kill_byname &kill_byname_logged &find_byname &error &popup_error &error_setup &wait_for &fast_wait_for &has_command &make_date &file_chooser_button &popup_window_button &read_acl &acl_filename &acl_check &get_miniserv_config &put_miniserv_config &restart_miniserv &reload_miniserv &check_os_support &http_download &complete_http_download &ftp_download &ftp_upload &no_proxy &open_socket &download_timeout &ftp_command &to_ipaddress &icons_table &replace_file_line &read_file_lines &flush_file_lines &unflush_file_lines &unix_user_input &unix_group_input &hlink &user_chooser_button &group_chooser_button &foreign_check &foreign_exists &foreign_available &foreign_require &foreign_call &foreign_config &foreign_installed &foreign_defined &get_system_hostname &get_webmin_version &get_module_acl &get_group_module_acl &save_module_acl &save_group_module_acl &init_config &load_language &text_subs &text &encode_base64 &decode_base64 &get_module_info &get_all_module_infos &get_theme_info &list_languages &read_env_file &write_env_file &lock_file &unlock_file &test_lock &unlock_all_files &can_lock_file &webmin_log &additional_log &webmin_debug_log &system_logged &backquote_logged &backquote_with_timeout &backquote_command &kill_logged &rename_logged &rename_file &symlink_logged &symlink_file &link_file &make_dir &set_ownership_permissions &unlink_logged &unlink_file &copy_source_dest &remote_session_name &remote_foreign_require &remote_foreign_call &remote_foreign_check &remote_foreign_config &remote_eval &remote_write &remote_read &remote_finished &remote_error_setup &remote_rpc_call &remote_multi_callback &remote_multi_callback_error &serialise_variable &unserialise_variable &other_groups &date_chooser_button &help_file &seed_random &disk_usage_kb &recursive_disk_usage &help_search_link &make_http_connection &read_http_connection &write_http_connection &close_http_connection &clean_environment &reset_environment &progress_callback &switch_to_remote_user &switch_to_unix_user &create_user_config_dirs &create_missing_homedir &filter_javascript &resolve_links &simplify_path &same_file &flush_webmin_caches &list_usermods &available_usermods &get_available_module_infos &get_visible_module_infos &get_visible_modules_categories &is_under_directory &parse_http_url &check_clicks_function &load_entities_map &entities_to_ascii &get_product_name &get_charset &get_display_hostname &save_module_config &save_user_module_config &nice_size &get_perl_path &get_goto_module &select_all_link &select_invert_link &select_rows_link &check_pid_file &get_mod_lib &module_root_directory &list_mime_types &guess_mime_type &open_tempfile &close_tempfile &print_tempfile &is_selinux_enabled &get_clear_file_attributes &reset_file_attributes &cleanup_tempnames &open_lock_tempfile &END &month_to_number &number_to_month &get_rbac_module_acl &supports_rbac &use_rbac_module_acl &execute_command &open_readfile &open_execute_command &translate_filename &translate_command &register_filename_callback &register_command_callback &capture_function_output &capture_function_output_tempfile &modules_chooser_button &substitute_template &running_in_zone &running_in_vserver &running_in_xen &list_categories &is_readonly_mode &command_as_user &list_osdn_mirrors &convert_osdn_url &get_current_dir &supports_users &supports_symlinks &quote_path &get_windows_root &read_file_contents &unix_crypt &split_quoted_string &write_to_http_cache &check_in_http_cache &supports_javascript &ui_table_start &ui_table_end &ui_table_row &ui_table_hr &ui_table_span &ui_columns_start &ui_columns_row &ui_columns_header &ui_checked_columns_row &ui_radio_columns_row &ui_columns_end &ui_columns_table &ui_form_columns_table &ui_form_start &ui_form_end &ui_textbox &ui_filebox &ui_bytesbox &ui_upload &ui_password &ui_hidden &ui_select &ui_multi_select &ui_multi_select_javascript &ui_radio &ui_yesno_radio &ui_checkbox &ui_oneradio &ui_textarea &ui_user_textbox &ui_group_textbox &ui_opt_textbox &ui_submit &ui_reset &ui_button &ui_date_input &ui_buttons_start &ui_buttons_end &ui_buttons_row &ui_buttons_hr &ui_post_header &ui_pre_footer &ui_print_header &ui_print_unbuffered_header &ui_print_footer &ui_config_link &ui_print_endpage &ui_subheading &ui_links_row &ui_hidden_javascript &ui_hidden_start &ui_hidden_end &ui_hidden_table_row_start &ui_hidden_table_row_end &ui_hidden_table_start &ui_hidden_table_end &ui_tabs_start &ui_tabs_end &ui_tabs_start_tab &ui_tabs_start_tabletab &ui_tabs_end_tab &ui_tabs_end_tabletab &ui_max_text_width &ui_radio_selector &ui_radio_selector_javascript &ui_grid_table &ui_radio_table &ui_up_down_arrows &ui_hr &ui_nav_link &ui_confirmation_form &js_disable_inputs &ui_page_flipper &js_checkbox_disable &js_redirect &get_module_name clear_time_locale reset_time_locale);
+@EXPORT = qw(&read_file &read_file_cached &write_file &html_escape &quote_escape &tempname &transname &trunc &indexof &indexoflc &sysprint &check_ipaddress &check_ip6address &generate_icon &urlize &un_urlize &include &copydata &ReadParseMime &ReadParse &read_fully &read_parse_mime_callback &read_parse_mime_javascript &PrintHeader &header &get_html_title &get_html_framed_title &get_html_status_line &popup_header &footer &popup_footer &load_theme_library &redirect &kill_byname &kill_byname_logged &find_byname &error &popup_error &error_setup &wait_for &fast_wait_for &has_command &make_date &file_chooser_button &popup_window_button &read_acl &acl_filename &acl_check &get_miniserv_config &put_miniserv_config &restart_miniserv &reload_miniserv &check_os_support &http_download &complete_http_download &ftp_download &ftp_upload &no_proxy &open_socket &download_timeout &ftp_command &to_ipaddress &icons_table &replace_file_line &read_file_lines &flush_file_lines &unflush_file_lines &unix_user_input &unix_group_input &hlink &user_chooser_button &group_chooser_button &foreign_check &foreign_exists &foreign_available &foreign_require &foreign_call &foreign_config &foreign_installed &foreign_defined &get_system_hostname &get_webmin_version &get_module_acl &get_group_module_acl &save_module_acl &save_group_module_acl &init_config &load_language &text_subs &text &encode_base64 &decode_base64 &get_module_info &get_all_module_infos &get_theme_info &list_languages &read_env_file &write_env_file &lock_file &unlock_file &test_lock &unlock_all_files &can_lock_file &webmin_log &additional_log &webmin_debug_log &system_logged &backquote_logged &backquote_with_timeout &backquote_command &kill_logged &rename_logged &rename_file &symlink_logged &symlink_file &link_file &make_dir &set_ownership_permissions &unlink_logged &unlink_file &copy_source_dest &remote_session_name &remote_foreign_require &remote_foreign_call &remote_foreign_check &remote_foreign_config &remote_eval &remote_write &remote_read &remote_finished &remote_error_setup &remote_rpc_call &remote_multi_callback &remote_multi_callback_error &serialise_variable &unserialise_variable &other_groups &date_chooser_button &help_file &seed_random &disk_usage_kb &recursive_disk_usage &help_search_link &make_http_connection &read_http_connection &write_http_connection &close_http_connection &clean_environment &reset_environment &progress_callback &switch_to_remote_user &switch_to_unix_user &create_user_config_dirs &create_missing_homedir &filter_javascript &resolve_links &simplify_path &same_file &flush_webmin_caches &list_usermods &available_usermods &get_available_module_infos &get_visible_module_infos &get_visible_modules_categories &is_under_directory &parse_http_url &check_clicks_function &load_entities_map &entities_to_ascii &get_product_name &get_charset &get_display_hostname &save_module_config &save_user_module_config &nice_size &get_perl_path &get_goto_module &select_all_link &select_invert_link &select_rows_link &check_pid_file &get_mod_lib &module_root_directory &list_mime_types &guess_mime_type &open_tempfile &close_tempfile &print_tempfile &is_selinux_enabled &get_clear_file_attributes &reset_file_attributes &cleanup_tempnames &open_lock_tempfile &END &month_to_number &number_to_month &get_rbac_module_acl &supports_rbac &use_rbac_module_acl &execute_command &open_readfile &open_execute_command &translate_filename &translate_command &register_filename_callback &register_command_callback &capture_function_output &capture_function_output_tempfile &modules_chooser_button &substitute_template &running_in_zone &running_in_vserver &running_in_xen &list_categories &is_readonly_mode &command_as_user &list_osdn_mirrors &convert_osdn_url &get_current_dir &supports_users &supports_symlinks &quote_path &get_windows_root &read_file_contents &unix_crypt &split_quoted_string &write_to_http_cache &check_in_http_cache &supports_javascript &ui_table_start &ui_table_end &ui_table_row &ui_table_hr &ui_table_span &ui_columns_start &ui_columns_row &ui_columns_header &ui_checked_columns_row &ui_radio_columns_row &ui_columns_end &ui_columns_table &ui_form_columns_table &ui_form_start &ui_form_end &ui_textbox &ui_filebox &ui_bytesbox &ui_upload &ui_password &ui_hidden &ui_select &ui_multi_select &ui_multi_select_javascript &ui_radio &ui_yesno_radio &ui_checkbox &ui_oneradio &ui_textarea &ui_user_textbox &ui_group_textbox &ui_opt_textbox &ui_submit &ui_reset &ui_button &ui_date_input &ui_buttons_start &ui_buttons_end &ui_buttons_row &ui_buttons_hr &ui_post_header &ui_pre_footer &ui_print_header &ui_print_unbuffered_header &ui_print_footer &ui_config_link &ui_print_endpage &ui_subheading &ui_links_row &ui_hidden_javascript &ui_hidden_start &ui_hidden_end &ui_hidden_table_row_start &ui_hidden_table_row_end &ui_hidden_table_start &ui_hidden_table_end &ui_tabs_start &ui_tabs_end &ui_tabs_start_tab &ui_tabs_start_tabletab &ui_tabs_end_tab &ui_tabs_end_tabletab &ui_max_text_width &ui_radio_selector &ui_radio_selector_javascript &ui_grid_table &ui_radio_table &ui_up_down_arrows &ui_hr &ui_nav_link &ui_confirmation_form &js_disable_inputs &ui_page_flipper &js_checkbox_disable &js_redirect &get_module_name clear_time_locale reset_time_locale eval_as_unix_user);
 
 # Add global variables in web-lib.pl
 push(@EXPORT, qw(&unique));
index 14f05bf..3da89cc 100644 (file)
@@ -1,2 +1,4 @@
 ---- Changes since 1.310 ----
 First version of this module, which can edit the global PHP configuration file and other per-domain files.
+---- Changes since 1.480 ----
+Added an access control option to limit file IO to a particular Unix user.
index a09da8c..4f709e2 100644 (file)
@@ -17,6 +17,9 @@ print &ui_table_row($text{'acl_manual'},
 print &ui_table_row($text{'acl_inis'},
            &ui_textarea("inis", join("\n", split(/\t+/, $o->{'php_inis'})),
                         5, 70), 3);
+
+print &ui_table_row($text{'acl_user'},
+                   &ui_user_textbox("user", $o->{'user'}));
 }
 
 # acl_security_save(&options)
@@ -28,5 +31,6 @@ $o->{'global'} = $in{'global'};
 $o->{'anyfile'} = $in{'anyfile'};
 $o->{'manual'} = $in{'manual'};
 $o->{'php_inis'} = join("\t", split(/\n/, $in{'inis'}));
+$o->{'user'} = $in{'user'};
 }
 
index 3a69037..fc17b63 100644 (file)
@@ -1,3 +1,4 @@
 global=1
 anyfile=1
 manual=1
+user=root
index 2ad66f7..21d4f6a 100755 (executable)
@@ -4,7 +4,7 @@
 require './phpini-lib.pl';
 &ReadParse();
 &can_php_config($in{'file'}) || &error($text{'list_ecannot'});
-$conf = &get_config($in{'file'});
+$conf = &get_config_as_user($in{'file'});
 
 &ui_print_header("<tt>$in{'file'}</tt>", $text{'vars_title'}, "");
 
index 86995fe..064fc2a 100644 (file)
@@ -11,6 +11,7 @@ index_anyfile=Edit other PHP configuration file:
 index_return=configuration files
 
 file_global=Global PHP configuration
+file_eread=Failed to read $1 : $2
 
 manual_title=Edit Configuration Manually
 manual_desc=This page can be used to manually edit a PHP configuration file. This should be done carefully, as no syntax or other validity checking will be performed on your changes.
@@ -166,3 +167,4 @@ acl_global=Can edit global PHP configuration?
 acl_anyfile=Can edit any file as a PHP configuration?
 acl_manual=Can manually edit configuration files?
 acl_inis=Additional configuration files<br>(In <i>filename</i>=<i>description</i> format)
+acl_user=Read and write files as user
index 851b078..29601bf 100644 (file)
@@ -15,7 +15,7 @@ if (!defined($get_config_cache{$file})) {
        local @rv = ( );
        local $lnum = 0;
        local $section;
-       open(CONFIG, $file);
+       open(CONFIG, $file) || return undef;
        while(<CONFIG>) {
                s/\r|\n//g;
                s/\s+$//;
@@ -194,5 +194,37 @@ if (&foreign_installed("apache")) {
        }
 }
 
+# get_config_as_user([file])
+# Like get_config, but reads with permissions of the ACL user
+sub get_config_as_user
+{
+local ($file) = @_;
+if ($access{'user'} && $access{'user'} ne 'root' && $< == 0) {
+       local $rv = &eval_as_unix_user(
+               $access{'user'}, sub { &get_config($file) });
+       if ((!$rv || !@$rv) && $!) {
+               &error(&text('file_eread', &html_escape($file), $!));
+               }
+       return $rv;
+       }
+else {
+       return &get_config($file);
+       }
+}
+
+# flush_file_lines_as_user(file)
+# Writes out a file as the Unix user configured in this module's ACL
+sub flush_file_lines_as_user
+{
+local ($file) = @_;
+if ($access{'user'} && $access{'user'} ne 'root' && $< == 0) {
+       &eval_as_unix_user($access{'user'}, 
+               sub { &flush_file_lines($file) });
+       }
+else {
+       &flush_file_lines($file);
+       }
+}
+
 1;
 
index 084e131..f85fad0 100755 (executable)
@@ -89,7 +89,7 @@ else {
                        $in{"pgsql.max_links"});
        }
 
-&flush_file_lines($in{'file'});
+&flush_file_lines_as_user($in{'file'});
 &unlock_file($in{'file'});
 &graceful_apache_restart();
 &webmin_log("db", undef, $in{'file'});
index d96c819..c5193de 100755 (executable)
@@ -27,7 +27,7 @@ $in{'ext_def'} || $in{'ext'} =~ /\S/ || &error($text{'dirs_eext'});
 $in{'utmp_def'} || -d $in{'utmp'} || &error($text{'dirs_eutmp'});
 &save_directive($conf, "upload_tmp_dir", $in{'utmp_def'} ? undef : $in{'utmp'});
 
-&flush_file_lines($in{'file'});
+&flush_file_lines_as_user($in{'file'});
 &unlock_file($in{'file'});
 &graceful_apache_restart();
 &webmin_log("dirs", undef, $in{'file'});
index 2ccf70c..df0581a 100755 (executable)
@@ -51,7 +51,7 @@ elsif ($in{"error_log_def"} == 2) {
        &save_directive($conf, "error_log", $in{"error_log"});
        }
 
-&flush_file_lines($in{'file'});
+&flush_file_lines_as_user($in{'file'});
 &unlock_file($in{'file'});
 &graceful_apache_restart();
 &webmin_log("errors", undef, $in{'file'});
index 5d76463..ceae6f6 100755 (executable)
@@ -41,7 +41,7 @@ $in{"max_input_time_def"} || $in{"max_input_time"} =~ /^\d+$/ ||
 &save_directive($conf, "max_input_time",
        $in{"max_input_time_def"} ? undef : $in{"max_input_time"});
 
-&flush_file_lines($in{'file'});
+&flush_file_lines_as_user($in{'file'});
 &unlock_file($in{'file'});
 &graceful_apache_restart();
 &webmin_log("limits", undef, $in{'file'});
index d9e0613..b842b7e 100755 (executable)
@@ -45,7 +45,7 @@ else {
        &save_directive($conf, "sendmail_path", $in{"sendmail_path"});
        }
 
-&flush_file_lines($in{'file'});
+&flush_file_lines_as_user($in{'file'});
 &unlock_file($in{'file'});
 &graceful_apache_restart();
 &webmin_log("misc", undef, $in{'file'});
index c5c7a27..2faafa5 100755 (executable)
@@ -25,7 +25,7 @@ foreach $d ([ "safe_mode_include_dir", "safe_einclude" ],
                }
        }
 
-&flush_file_lines($in{'file'});
+&flush_file_lines_as_user($in{'file'});
 &unlock_file($in{'file'});
 &graceful_apache_restart();
 &webmin_log("safe", undef, $in{'file'});
index 0ff10b1..164b3eb 100755 (executable)
@@ -43,7 +43,7 @@ else {
                        $in{"session.gc_maxlifetime"});
        }
 
-&flush_file_lines($in{'file'});
+&flush_file_lines_as_user($in{'file'});
 &unlock_file($in{'file'});
 &graceful_apache_restart();
 &webmin_log("session", undef, $in{'file'});
index 21902e7..4aebcb6 100755 (executable)
@@ -14,7 +14,7 @@ foreach $v ("magic_quotes_gpc", "magic_quotes_runtime",
            "register_argc_argv") {
        &save_directive($conf, $v, $in{$v} || undef);
        }
-&flush_file_lines($in{'file'});
+&flush_file_lines_as_user($in{'file'});
 &unlock_file($in{'file'});
 &graceful_apache_restart();
 &webmin_log("vars", undef, $in{'file'});
index 909ba0d..6e4e7af 100755 (executable)
@@ -6342,6 +6342,35 @@ if ($< != $uinfo->[2] || $> != $uinfo->[2]) {
        }
 }
 
+=head2 eval_as_unix_user(username, &code)
+
+Runs some code fragment with the effective UID and GID switch to that
+of the given Unix user, so that file IO takes place with his permissions.
+
+=cut
+
+sub eval_as_unix_user
+{
+my ($user, $code) = @_;
+my @uinfo = getpwnam($user);
+defined(@uinfo) || &error("eval_as_unix_user called with invalid user $user");
+$) = $uinfo[3]." ".join(" ", $uinfo[3], &other_groups($user));
+$> = $uinfo[2];
+my @rv;
+eval {
+       local $main::error_must_die = 1;
+       @rv = &$code();
+       };
+my $err = $@;
+$) = 0;
+$> = 0;
+if ($err) {
+       $err =~ s/\s+at\s+(\/\S+)\s+line\s+(\d+)\.?//;
+       &error($err);
+       }
+return wantarray ? @rv : $rv[0];
+}
+
 =head2 create_user_config_dirs
 
 Creates per-user config directories and sets $user_config_directory and