diff --git a/controls/V-72049.rb b/controls/V-72049.rb index c6378310f..d19676708 100644 --- a/controls/V-72049.rb +++ b/controls/V-72049.rb @@ -1,5 +1,11 @@ # encoding: utf-8 # +non_interactive_shells = input( + 'non_interactive_shells', + description: 'These shells do not allow a user to login', + value: ["/sbin/nologin","/sbin/halt","/sbin/shutdown","/bin/false","/bin/sync", "/bin/true"] +) + control "V-72049" do title "The umask must be set to 077 for all local interactive user accounts." desc "The umask controls the default access mode assigned to newly created @@ -45,19 +51,71 @@ environment variables." tag "fix_id": "F-78401r1_fix" - # @todo - test for values more restrictive than 077 - file_lines = command('grep -i -s umask /home/*/.*').stdout.split("\n") - if !file_lines.nil? and !file_lines.empty? - file_lines.each do |curr_line| - file_name = curr_line.split(':').first - describe command("grep -i umask #{file_name}") do - its('stdout.strip') { should match %r{^umask\s+.*077} } - end + # Get all interactive users + ignore_shells = non_interactive_shells.join('|') + + # Get home directory for users with UID >= 1000 or UID == 0 and support interactive logins. + findings = Set[] + dotfiles = Set[] + umasks = {} + umask_findings = Set[] + + # Get UID_MIN from login.defs + uid_min = 1000 + if file("/etc/login.defs").exist? + uid_min_val = command("grep '^UID_MIN' /etc/login.defs | grep -Po '[0-9]+'").stdout.split("\n") + if !uid_min_val.empty? + uid_min = uid_min_val[0].to_i end - else - describe "No interactive files with a less restrictive umask were found." do - subject { file_lines.nil? or file_lines.empty? } - it { should eq true } + end + + interactive_users = users.where{ !shell.match(ignore_shells) && (uid >= uid_min || uid == 0)}.entries + + # For each user, build and execute a find command that identifies initialization files + # in a user's home directory. + interactive_users.each do |u| + + # Only check if the home directory is local + is_local = command("df -l #{u.home}").exit_status + + if is_local == 0 + # Get user's initialization files + dotfiles = dotfiles + command("find #{u.home} -xdev -maxdepth 2 ( -name '.*' ! -name '.bash_history' ) -type f").stdout.split("\n") + + # Get user's umask + umasks.store(u.username,command("su -c 'umask' -l #{u.username}").stdout.chomp("\n")) + + # Check all local initialization files to see whether or not they are less restrictive than 077. + dotfiles.each do |df| + if file(df).more_permissive_than?("0077") + findings = findings + df + end + end + + # Check umask for all interactive users + umasks.each do |key,value| + max_mode = ("0077").to_i(8) + inv_mode = 0777 ^ max_mode + if inv_mode & (value).to_i(8) != 0 + umask_findings = umask_findings + key + end + end + else + describe "This control skips non-local filesystems" do + skip "This control has skipped the #{u.home} home directory for #{u.username} because it is not a local filesystem." + end end end + + # Report on any interactive files that are less restrictive than 077. + describe "No interactive user initialization files with a less restrictive umask were found." do + subject { findings.empty? } + it { should eq true } + end + + # Report on any interactive users that have a umask less restrictive than 077. + describe "No users were found with a less restrictive umask were found." do + subject { umask_findings.empty? } + it { should eq true } + end end