diff options
Diffstat (limited to 'perl/Wallet/Kadmin/Heimdal.pm')
-rw-r--r-- | perl/Wallet/Kadmin/Heimdal.pm | 314 |
1 files changed, 0 insertions, 314 deletions
diff --git a/perl/Wallet/Kadmin/Heimdal.pm b/perl/Wallet/Kadmin/Heimdal.pm deleted file mode 100644 index 42de8e0..0000000 --- a/perl/Wallet/Kadmin/Heimdal.pm +++ /dev/null @@ -1,314 +0,0 @@ -# Wallet::Kadmin::Heimdal -- Wallet Kerberos administration API for Heimdal. -# -# Written by Jon Robertson <jonrober@stanford.edu> -# Copyright 2009, 2010, 2014 -# The Board of Trustees of the Leland Stanford Junior University -# -# See LICENSE for licensing terms. - -############################################################################## -# Modules and declarations -############################################################################## - -package Wallet::Kadmin::Heimdal; -require 5.006; - -use strict; -use vars qw(@ISA $VERSION); - -use Heimdal::Kadm5 qw(KRB5_KDB_DISALLOW_ALL_TIX); -use Wallet::Config (); -use Wallet::Kadmin (); - -@ISA = qw(Wallet::Kadmin); - -# This version should be increased on any code change to this module. Always -# use two digits for the minor version with a leading zero if necessary so -# that it will sort properly. -$VERSION = '0.04'; - -############################################################################## -# Utility functions -############################################################################## - -# Add the realm to the end of the principal if no realm is currently present. -sub canonicalize_principal { - my ($self, $principal) = @_; - if ($Wallet::Config::KEYTAB_REALM && $principal !~ /\@/) { - $principal .= '@' . $Wallet::Config::KEYTAB_REALM; - } - return $principal; -} - -# Generate a long random password. -# -# Please note: This is not a cryptographically secure password! It's used -# only because the Heimdal kadmin interface requires a password on create. -# The keys will be set before the principal is ever set active, so it will -# never be possible to use the password. It just needs to be random in case -# password quality checks are applied to it. -# -# Make the password reasonably long and include a variety of character classes -# so that it should pass any password strength checking. -sub insecure_random_password { - my ($self) = @_; - my @classes = ( - 'abcdefghijklmnopqrstuvwxyz', - 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', - '0123456789', - '~`!@#$%^&*()-_+={[}]|:;<,>.?/' - ); - my $password = q{}; - for my $i (1..20) { - my $class = $i % scalar (@classes); - my $alphabet = $classes[$class]; - my $letter = substr ($alphabet, int (rand (length $alphabet)), 1); - $password .= $letter; - } - return $password; -} - -############################################################################## -# Public interfaces -############################################################################## - -# Check whether a given principal already exists in Kerberos. Returns true if -# so, false otherwise. -sub exists { - my ($self, $principal) = @_; - $principal = $self->canonicalize_principal ($principal); - my $kadmin = $self->{client}; - my $princdata = eval { $kadmin->getPrincipal ($principal) }; - if ($@) { - $self->error ("error getting principal: $@"); - return; - } - return $princdata ? 1 : 0; -} - -# Create a principal in Kerberos. If there is an error, return undef and set -# the error. Return 1 on success or the principal already existing. -sub create { - my ($self, $principal) = @_; - $principal = $self->canonicalize_principal ($principal); - my $exists = eval { $self->exists ($principal) }; - if ($@) { - $self->error ("error adding principal $principal: $@"); - return; - } - return 1 if $exists; - - # The way Heimdal::Kadm5 works, we create a principal object, create the - # actual principal set inactive, then randomize it and activate it. We - # have to set a password, even though we're about to replace it with - # random keys, but since the principal is created inactive, it doesn't - # have to be a very good one. - my $kadmin = $self->{client}; - eval { - my $princdata = $kadmin->makePrincipal ($principal); - my $attrs = $princdata->getAttributes; - $attrs |= KRB5_KDB_DISALLOW_ALL_TIX; - $princdata->setAttributes ($attrs); - my $password = $self->insecure_random_password; - $kadmin->createPrincipal ($princdata, $password, 0); - $kadmin->randKeyPrincipal ($principal); - $kadmin->enablePrincipal ($principal); - }; - if ($@) { - $self->error ("error adding principal $principal: $@"); - return; - } - return 1; -} - -# Create a keytab for a principal. Returns the keytab as binary data or undef -# on failure, setting the error. -sub keytab { - my ($self, $principal) = @_; - $principal = $self->canonicalize_principal ($principal); - my $kadmin = $self->{client}; - my $file = $Wallet::Config::KEYTAB_TMP . "/keytab.$$"; - unlink $file; - my $princdata = eval { $kadmin->getPrincipal ($principal) }; - if ($@) { - $self->error ("error creating keytab for $principal: $@"); - return; - } elsif (!$princdata) { - $self->error ("error creating keytab for $principal: principal does" - . " not exist"); - return; - } - eval { $kadmin->extractKeytab ($princdata, $file) }; - if ($@) { - $self->error ("error creating keytab for principal: $@"); - return; - } - return $self->read_keytab ($file); -} - -# Create a keytab for a principal, randomizing the keys for that principal at -# the same time. Takes the principal and an optional list of encryption types -# to which to limit the keytab. Return the keytab data on success and undef -# on failure. If the keytab creation fails, sets the error. -sub keytab_rekey { - my ($self, $principal, @enctypes) = @_; - $principal = $self->canonicalize_principal ($principal); - - # The way Heimdal works, you can only remove enctypes from a principal, - # not add them back in. So we need to run randkeyPrincipal first each - # time to restore all possible enctypes and then whittle them back down - # to those we have been asked for this time. - my $kadmin = $self->{client}; - eval { $kadmin->randKeyPrincipal ($principal) }; - if ($@) { - $self->error ("error creating keytab for $principal: could not" - . " reinit enctypes: $@"); - return; - } - my $princdata = eval { $kadmin->getPrincipal ($principal) }; - if ($@) { - $self->error ("error creating keytab for $principal: $@"); - return; - } elsif (!$princdata) { - $self->error ("error creating keytab for $principal: principal does" - . " not exist"); - return; - } - - # Now actually remove any non-requested enctypes, if we requested any. - if (@enctypes) { - my $alltypes = $princdata->getKeytypes; - my %wanted = map { $_ => 1 } @enctypes; - for my $key (@{ $alltypes }) { - my $keytype = $key->[0]; - next if exists $wanted{$keytype}; - eval { $princdata->delKeytypes ($keytype) }; - if ($@) { - $self->error ("error removing keytype $keytype from the" - . " keytab: $@"); - return; - } - } - eval { $kadmin->modifyPrincipal ($princdata) }; - if ($@) { - $self->error ("error saving principal modifications: $@"); - return; - } - } - - # Create the keytab. - my $file = $Wallet::Config::KEYTAB_TMP . "/keytab.$$"; - unlink $file; - eval { $kadmin->extractKeytab ($princdata, $file) }; - if ($@) { - $self->error ("error creating keytab for principal: $@"); - return; - } - return $self->read_keytab ($file); -} - -# Delete a principal from Kerberos. Return true if successful, false -# otherwise. If the deletion fails, sets the error. If the principal doesn't -# exist, return success; we're bringing reality in line with our expectations. -sub destroy { - my ($self, $principal) = @_; - $principal = $self->canonicalize_principal ($principal); - my $exists = eval { $self->exists ($principal) }; - if ($@) { - $self->error ("error checking principal existance: $@"); - return; - } elsif (not $exists) { - return 1; - } - my $kadmin = $self->{client}; - my $retval = eval { $kadmin->deletePrincipal ($principal) }; - if ($@) { - $self->error ("error deleting $principal: $@"); - return; - } - return 1; -} - -# Create a new Wallet::Kadmin::Heimdal object and its underlying -# Heimdal::Kadm5 object. -sub new { - my ($class) = @_; - unless (defined ($Wallet::Config::KEYTAB_PRINCIPAL) - and defined ($Wallet::Config::KEYTAB_FILE) - and defined ($Wallet::Config::KEYTAB_REALM)) { - die "keytab object implementation not configured\n"; - } - unless (defined ($Wallet::Config::KEYTAB_TMP)) { - die "KEYTAB_TMP configuration variable not set\n"; - } - my @options = (RaiseError => 1, - Principal => $Wallet::Config::KEYTAB_PRINCIPAL, - Realm => $Wallet::Config::KEYTAB_REALM, - Keytab => $Wallet::Config::KEYTAB_FILE); - if ($Wallet::Config::KEYTAB_HOST) { - push (@options, Server => $Wallet::Config::KEYTAB_HOST); - } - my $client = Heimdal::Kadm5::Client->new (@options); - my $self = { client => $client }; - bless ($self, $class); - return $self; -} - -1; -__END__ - -############################################################################## -# Documentation -############################################################################## - -=for stopwords -keytabs keytab kadmin KDC API Allbery Heimdal unlinked - -=head1 NAME - -Wallet::Kadmin::Heimdal - Wallet Kerberos administration API for Heimdal - -=head1 SYNOPSIS - - my $kadmin = Wallet::Kadmin::Heimdal->new; - $kadmin->create ('host/foo.example.com'); - $kadmin->keytab_rekey ('host/foo.example.com', 'keytab', - 'aes256-cts-hmac-sha1-96'); - my $data = $kadmin->keytab ('host/foo.example.com'); - my $exists = $kadmin->exists ('host/oldshell.example.com'); - $kadmin->destroy ('host/oldshell.example.com') if $exists; - -=head1 DESCRIPTION - -Wallet::Kadmin::Heimdal implements the Wallet::Kadmin API for Heimdal, -providing an interface to create and delete principals and create keytabs. -It provides the API documented in L<Wallet::Kadmin> for a Heimdal KDC. - -To use this class, several configuration parameters must be set. See -L<Wallet::Config/"KEYTAB OBJECT CONFIGURATION"> for details. - -=head1 FILES - -=over 4 - -=item KEYTAB_TMP/keytab.<pid> - -The keytab is created in this file and then read into memory. KEYTAB_TMP -is set in the wallet configuration, and <pid> is the process ID of the -current process. The file is unlinked after being read. - -=back - -=head1 SEE ALSO - -kadmin(8), Wallet::Config(3), Wallet::Kadmin(3), -Wallet::Object::Keytab(3), wallet-backend(8) - -This module is part of the wallet system. The current version is -available from L<http://www.eyrie.org/~eagle/software/wallet/>. - -=head1 AUTHORS - -Russ Allbery <eagle@eyrie.org> and Jon Robertson <jonrober@stanford.edu>. - -=cut |