use strict;
use Errno qw(:POSIX);
use File::Basename;
my $progname = basename ($0);
chdir '/' or die "chdir: $!\n";
if ($< != 0) {
print 'Error: '. $progname ." needs to be run by root\n";
exit EPERM();
}
umask 022;
my $system_keychain = '/Library/Keychains/System.keychain';
if (! -f $system_keychain) {
system '/usr/sbin/systemkeychain', '-C';
}
my $kdc_dir = '/var/db/krb5kdc';
my $kdc_conf = $kdc_dir .'/kdc.conf';
my $kdc_local = '/var/db/dslocal/nodes/Default/config/KerberosKDC.plist';
my $plist_set = 0;
my $make_keytab_flag = 0;
my $update_plists_flag = 0;
my @kdcsetup_args;
my $kdcmond_plist = '/System/Library/LaunchDaemons/com.apple.kdcmond.plist';
my $argc = scalar @ARGV;
my $i;
for ($i = 0; $i < $argc; ++$i) {
if ($ARGV[$i] eq '--plist') {
$plist_set = 1;
$make_keytab_flag = 0;
$update_plists_flag = 1;
} elsif ($ARGV[$i] eq '--target') {
die "Error: --target requires an argument\n" unless ++$i < $argc;
push @kdcsetup_args, '-F', $ARGV[$i];
} else {
die "Error: unknown argument $ARGV[$i]\n";
}
}
if (! -d $kdc_dir or ! -f $kdc_local) {
system '/usr/bin/certtool', 'C', 'com.apple.systemdefault', 'u', 'P', 'v';
system '/usr/bin/certtool', 'C', 'com.apple.kerberos.kdc', 'u', 'P', 'v';
system '/usr/sbin/kdcsetup', '-L', '-n', @kdcsetup_args;
system '/bin/launchctl', 'load', $kdcmond_plist;
unless ($plist_set) {
$make_keytab_flag = 1;
$update_plists_flag = 1;
}
}
if (not open (KDC_LOCAL, '/usr/libexec/PlistBuddy -c "Print :realname:" '. $kdc_local. '|')) {
print 'Error: '. $progname ." failed to find $kdc_local\n";
exit 1;
}
my $LKDC_realm = join ('', <KDC_LOCAL>);
$LKDC_realm =~ s/^.*(LKDC:SHA1\.[0-9A-F]{40}).*$/\1/s;
if ($LKDC_realm eq '') {
print 'Error: '. $progname ." cannot parse $kdc_local\n";
exit 1;
}
close KDC_LOCAL;
if (not open (KDC_CONF, '<', $kdc_conf)) {
print 'Error: '. $progname ." failed to find $kdc_conf\n";
exit 1;
}
my @default_realm = grep /default_realm/, <KDC_CONF>;
if (1 != scalar (@default_realm)) {
print 'Error: '. $progname ." cannot parse $kdc_conf\n";
exit 1;
}
my $default_realm = (split (/\s+/, $default_realm[0], 4))[3];
chomp $default_realm;
close KDC_CONF;
if ($default_realm !~ /^LKDC:/) {
$update_plists_flag = 0;
}
if ($make_keytab_flag or $update_plists_flag) {
my %afp_config = (service => 'afpserver', realm => $LKDC_realm,
prefs => '/Library/Preferences/com.apple.AppleFileServer',
key => 'kerberosPrincipal', format => '%s/%s@%2$s');
my %smb_config = (service => 'cifs', realm => $LKDC_realm,
prefs => '/Library/Preferences/SystemConfiguration/com.apple.smb.server',
key => 'LocalKerberosRealm', format => '%2$s');
my %ss_config = (service => 'vnc', realm => $LKDC_realm);
configure_service (\%afp_config, $make_keytab_flag, $update_plists_flag);
configure_service (\%smb_config, $make_keytab_flag, $update_plists_flag);
configure_service (\%ss_config, $make_keytab_flag, $update_plists_flag);
}
print $LKDC_realm . "\n";
my $rerun_plist = '/System/Library/LaunchDaemons/com.apple.configureLocalKDC.plist';
chomp (my $status = qx{/usr/libexec/PlistBuddy -c "Print :Disabled" $rerun_plist});
if ($status ne 'true') {
system '/usr/libexec/PlistBuddy', '-c', 'Add :Disabled bool True', $rerun_plist;
}
sub configure_service {
my $config = shift;
my $do_keytab = shift;
my $do_plist = shift;
my $realm = $config->{realm};
my $principal = sprintf "%s/%s@%s", $config->{service}, $realm, $realm;
if ($do_keytab) {
my $kadmin_local = '/usr/sbin/kadmin.local';
my @args = ('add_principal', '-randkey', $principal);
print $kadmin_local . join (' ', '-q', @args). "\n";
system $kadmin_local, '-q', join (' ', @args);
@args = ('ktadd', $principal);
print $kadmin_local . join (' ', '-q', @args). "\n";
system $kadmin_local, '-q', join (' ', @args);
}
if ($do_plist and defined ($config->{prefs})) {
my $value = sprintf $config->{format}, $config->{service}, $realm;
my @args = ('write', $config->{prefs}, $config->{key}, $value);
print '/usr/bin/defaults '. join (' ', @args). "\n";
system '/usr/bin/defaults', @args;
}
}