#!/usr/bin/ruby

require 'fileutils'
require 'highline/import'

def run(*args)
  system(*args) \
    or raise "error running a system command: #{ args }"
end

Puavo_krb5kdc_dir = '/var/lib/krb5kdc/puavo'

Sentinel_file = "#{ Puavo_krb5kdc_dir }/init_kdc_slave_done"

if File.exist?(Sentinel_file) and not ARGV[0] == '--force' then
  warn "#{ Sentinel_file } exists, use the --force, Luke!"
  exit 1
end

ldap_binddn    = File.read('/etc/puavo/ldap/dn'      ).chomp
ldap_bindpw    = File.read('/etc/puavo/ldap/password').chomp
puavo_domain   = File.read('/etc/puavo/domain'       ).chomp
puavo_hostname = File.read('/etc/puavo/hostname'     ).chomp

kerberos_masterpw = ask('Kerberos master password? ') { |q| q.echo = false }

FileUtils.mkdir_p(Puavo_krb5kdc_dir)

Krb5_files_list = %w(cifs.keytab
                     cups.keytab
                     http.keytab
                     krb5.secrets
                     ldap_krb5.keytab
                     stash
                     system.keytab)
Krb5_files_list.each do |filename|
  FileUtils.rm_f("#{ Puavo_krb5kdc_dir }/#{ filename }")
end

FileUtils.rm_f('/etc/krb5.secrets')
cmd = [ '/usr/sbin/kdb5_ldap_util', 'stashsrvpw', '-f', '/etc/krb5.secrets', ldap_binddn ]
IO.popen(cmd, 'w') { |pipe| pipe.puts ldap_bindpw; pipe.puts ldap_bindpw }
raise "error running command #{ cmd }" unless $?.success?
FileUtils.cp('/etc/krb5.secrets', "#{ Puavo_krb5kdc_dir }/krb5.secrets")

# try several times before giving up, in case user accidentally
# types/copypastes wrong password
try_count = 5
try_count.times do |try_number|
  FileUtils.rm_f('/etc/krb5kdc/stash')
  cmd = [ 'kadmin.local', '-m', '-q', "ktadd -norandkey -k /etc/krb5kdc/stash K/M" ]
  IO.popen(cmd, 'w') { |pipe| pipe.puts kerberos_masterpw }
  break if $?.success?
  if (try_number+1) < try_count then
    tries_left = try_count - (try_number+1)
    warn "\nFAILED to initialize kerberos, #{ tries_left } tries left."
    kerberos_masterpw = ask('Kerberos master password? ') { |q| q.echo = false }
    next
  end
  warn "\nCould not initialize kerberos, giving up."
  exit(1)
end
FileUtils.cp('/etc/krb5kdc/stash', "#{ Puavo_krb5kdc_dir }/stash")

system('service', 'krb5-kdc', 'restart')

# setup samba/ldap auth
cmd = [ 'smbpasswd', '-W' ]
IO.popen(cmd, 'w') { |pipe| pipe.puts ldap_bindpw; pipe.puts ldap_bindpw; }
raise "error running command #{ cmd }" unless $?.success?

# init keytab files

puavo_fqdn = "#{ puavo_hostname }.#{ puavo_domain }"

run('kadmin.local', '-q',
     "ktadd -norandkey -k #{ Puavo_krb5kdc_dir }/cups.keytab IPP/#{ puavo_fqdn }")
run('kadmin.local', '-q',
    "ktadd -norandkey -k #{ Puavo_krb5kdc_dir }/http.keytab HTTP/#{ puavo_fqdn }")
run('kadmin.local', '-q',
    "ktadd -norandkey -k #{ Puavo_krb5kdc_dir }/ldap_krb5.keytab ldap/#{ puavo_fqdn }")
run('kadmin.local', '-q',
    "ktadd -norandkey -k #{ Puavo_krb5kdc_dir }/system.keytab host/#{ puavo_fqdn }")
run('kadmin.local', '-q',
    "ktadd -norandkey -k #{ Puavo_krb5kdc_dir }/system.keytab nfs/#{ puavo_fqdn }")
run('kadmin.local', '-q',
    "ktadd -norandkey -k #{ Puavo_krb5kdc_dir }/cifs.keytab cifs/#{ puavo_fqdn }")

FileUtils.touch(Sentinel_file)
