|
30 | 30 | ['0.0.0.0'] |
31 | 31 | end |
32 | 32 |
|
| 33 | +# some internal definitions |
| 34 | +cache_dir = ::File.join(Chef::Config[:file_cache_path], cookbook_name.to_s) |
| 35 | +dh_moduli_file = '/etc/ssh/moduli' |
| 36 | + |
| 37 | +# create a cache dir for this cookbook |
| 38 | +# we use it for storing of lock files or selinux files |
| 39 | +directory cache_dir |
| 40 | + |
33 | 41 | # installs package name |
34 | 42 | package 'openssh-server' do |
35 | 43 | package_name node['ssh-hardening']['sshserver']['package'] |
36 | 44 | end |
37 | 45 |
|
38 | 46 | # Handle addional SELinux policy on RHEL/Fedora for different UsePAM options |
39 | 47 | if %w(fedora rhel).include?(node['platform_family']) |
40 | | - policy_dir = ::File.join(Chef::Config[:file_cache_path], cookbook_name.to_s) |
41 | | - policy_file = ::File.join(policy_dir, 'ssh_password.te') |
42 | | - module_file = ::File.join(policy_dir, 'ssh_password.mod') |
43 | | - package_file = ::File.join(policy_dir, 'ssh_password.pp') |
| 48 | + policy_file = ::File.join(cache_dir, 'ssh_password.te') |
| 49 | + module_file = ::File.join(cache_dir, 'ssh_password.mod') |
| 50 | + package_file = ::File.join(cache_dir, 'ssh_password.pp') |
44 | 51 |
|
45 | 52 | package 'policycoreutils-python' |
46 | 53 | # on fedora we need an addtional package for semodule_package |
|
56 | 63 | else |
57 | 64 | # UsePAM no: enable and install the additional SELinux policy |
58 | 65 |
|
59 | | - directory policy_dir |
60 | | - |
61 | 66 | cookbook_file policy_file do |
62 | 67 | source 'ssh_password.te' |
63 | 68 | end |
|
73 | 78 | end |
74 | 79 | end |
75 | 80 |
|
| 81 | +# handle Diffie-Hellman moduli |
| 82 | +# build own moduli file if required |
| 83 | +own_primes_lock_file = ::File.join(cache_dir, 'moduli.lock') |
| 84 | +bash 'build own primes for DH' do |
| 85 | + code <<-EOS |
| 86 | + set -e |
| 87 | + tempdir=$(mktemp -d) |
| 88 | + ssh-keygen -G $tempdir/moduli.all -b #{node['ssh-hardening']['ssh']['server']['dh_build_primes_size']} |
| 89 | + ssh-keygen -T $tempdir/moduli.safe -f $tempdir/moduli.all |
| 90 | + cp $tempdir/moduli.safe #{dh_moduli_file} |
| 91 | + rm -rf $tempdir |
| 92 | + touch #{own_primes_lock_file} |
| 93 | + EOS |
| 94 | + only_if { node['ssh-hardening']['ssh']['server']['dh_build_primes'] } |
| 95 | + not_if { ::File.exist?(own_primes_lock_file) } |
| 96 | + notifies :restart, 'service[sshd]' |
| 97 | +end |
| 98 | + |
| 99 | +# remove all small primes |
| 100 | +# https://stribika.github.io/2015/01/04/secure-secure-shell.html |
| 101 | +dh_min_prime_size = node['ssh-hardening']['ssh']['server']['dh_min_prime_size'].to_i - 1 # 4096 is 4095 in the moduli file |
| 102 | +ruby_block 'remove small primes from DH moduli' do # ~FC014 |
| 103 | + block do |
| 104 | + tmp_file = "#{dh_moduli_file}.tmp" |
| 105 | + ::File.open(tmp_file, 'w') do |new_file| |
| 106 | + ::File.readlines(dh_moduli_file).each do |line| |
| 107 | + unless line_match = line.match(/^(\d+ ){4}(\d+) \d+ \h+$/) # rubocop:disable Lint/AssignmentInCondition |
| 108 | + # some line without expected data structure, e.g. comment line |
| 109 | + # write it and go to the next data |
| 110 | + new_file.write(line) |
| 111 | + next |
| 112 | + end |
| 113 | + |
| 114 | + # lets compare the bits and do not write the lines with small bit size |
| 115 | + bits = line_match[2] |
| 116 | + new_file.write(line) unless bits.to_i < dh_min_prime_size |
| 117 | + end |
| 118 | + end |
| 119 | + |
| 120 | + # we use cp&rm to preserve the permissions of existing file |
| 121 | + FileUtils.cp(tmp_file, dh_moduli_file) |
| 122 | + FileUtils.rm(tmp_file) |
| 123 | + end |
| 124 | + not_if "test $(awk '$5 < #{dh_min_prime_size} && $5 ~ /^[0-9]+$/ { print $5 }' #{dh_moduli_file} | uniq | wc -c) -eq 0" |
| 125 | + notifies :restart, 'service[sshd]' |
| 126 | +end |
| 127 | + |
76 | 128 | # defines the sshd service |
77 | 129 | service 'sshd' do |
78 | 130 | # use upstart for ubuntu, otherwise chef uses init |
|
0 commit comments