summaryrefslogtreecommitdiff
path: root/perl
diff options
context:
space:
mode:
Diffstat (limited to 'perl')
-rw-r--r--perl/Wallet/Config.pm83
-rw-r--r--perl/Wallet/Object/Keytab.pm349
-rw-r--r--perl/Wallet/Schema.pm10
-rwxr-xr-xperl/t/config.t6
-rwxr-xr-xperl/t/keytab.t217
-rwxr-xr-xperl/t/schema.t2
6 files changed, 78 insertions, 589 deletions
diff --git a/perl/Wallet/Config.pm b/perl/Wallet/Config.pm
index 3f52cf0..7198c07 100644
--- a/perl/Wallet/Config.pm
+++ b/perl/Wallet/Config.pm
@@ -1,7 +1,7 @@
# Wallet::Config -- Configuration handling for the wallet server.
#
# Written by Russ Allbery <rra@stanford.edu>
-# Copyright 2007, 2008 Board of Trustees, Leland Stanford Jr. University
+# Copyright 2007, 2008, 2010 Board of Trustees, Leland Stanford Jr. University
#
# See LICENSE for licensing terms.
@@ -14,7 +14,7 @@ use vars qw($PATH $VERSION);
# 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.03';
+$VERSION = '0.04';
# Path to the config file to load.
$PATH = $ENV{WALLET_CONFIG} || '/etc/wallet/wallet.conf';
@@ -351,85 +351,6 @@ our $KEYTAB_REMCTL_PORT;
=back
-=head2 Synchronization with AFS kaserver
-
-The keytab backend optionally supports synchronizing keys between the
-Kerberos v5 realm and a Kerberos v4 realm using kaserver. This
-synchronization is done using B<kasetkey> and is controlled by the C<sync>
-attribute on keytab objects. To configure that support, set the following
-variables.
-
-=over 4
-
-=item KEYTAB_AFS_ADMIN
-
-The Kerberos v4 principal to use for authentication to the AFS kaserver. If
-this principal is not in the default local Kerberos v4 realm, it must be
-fully qualified. A srvtab for this principal must be stored in the path set
-in $KEYTAB_AFS_SRVTAB. This principal must have the ADMIN flag set in the
-AFS kaserver so that it can create and remove principals. This variable
-must be set to use the kaserver synchronization support.
-
-=cut
-
-our $KEYTAB_AFS_ADMIN;
-
-=item KEYTAB_AFS_DESTROY
-
-If this variable, which is false by default, is set to a true value, each
-time a keytab object that is not configured to be synchronized with the AFS
-kaserver, the corresponding Kerberos v4 principal will be deleted from the
-AFS kaserver. Use this with caution; it will cause the AFS kaserver realm
-to be slowly stripped of principals. This is intended for use with
-migration from Kerberos v4 to Kerberos v5, where the old principals should
-be deleted out of Kerberos v4 whenever not requested from the wallet to aid
-in tracking down and removing any systems with lingering Kerberos v4
-dependencies.
-
-Be aware that multiple Kerberos v5 principals map to the same Kerberos v4
-principal since in Kerberos v4 the domain name is stripped from the
-principal for machine principals. If you create a keytab named
-host/foo.example.com and mark it synchronized, and then create another
-keytab named host/foo.example.net and don't mark it synchronized,
-downloading the second will destroy the Kerberos v4 principal of the first
-if this variable is set.
-
-=cut
-
-our $KEYTAB_AFS_DESTROY;
-
-=item KEYTAB_AFS_KASETKEY
-
-The path to the B<kasetkey> command-line client. The default value is
-C<kasetkey>, which will cause the wallet to search for B<kasetkey> on its
-default PATH.
-
-=cut
-
-our $KEYTAB_AFS_KASETKEY = 'kasetkey';
-
-=item KEYTAB_AFS_REALM
-
-The name of the Kerberos v4 realm with which to synchronize keys. This is a
-realm, not a cell, so it should be in all uppercase. If this variable is
-not set, the default is the realm determined from the local cell name.
-
-=cut
-
-our $KEYTAB_AFS_REALM;
-
-=item KEYTAB_AFS_SRVTAB
-
-The path to a srvtab used to authenticate to the AFS kaserver. This srvtab
-should be for the principal set in $KEYTAB_AFS_ADMIN. This variable must be
-set to use the kaserver synchronization support.
-
-=cut
-
-our $KEYTAB_AFS_SRVTAB;
-
-=back
-
=head1 NETDB ACL CONFIGURATION
These configuration variables are only needed if you intend to use the
diff --git a/perl/Wallet/Object/Keytab.pm b/perl/Wallet/Object/Keytab.pm
index 9fece80..b604907 100644
--- a/perl/Wallet/Object/Keytab.pm
+++ b/perl/Wallet/Object/Keytab.pm
@@ -1,7 +1,8 @@
# Wallet::Object::Keytab -- Keytab object implementation for the wallet.
#
# Written by Russ Allbery <rra@stanford.edu>
-# Copyright 2007, 2008, 2009 Board of Trustees, Leland Stanford Jr. University
+# Copyright 2007, 2008, 2009, 2010
+# Board of Trustees, Leland Stanford Jr. University
#
# See LICENSE for licensing terms.
@@ -24,230 +25,7 @@ use 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.07';
-
-##############################################################################
-# AFS kaserver synchronization
-##############################################################################
-
-# Given a Kerberos v5 principal name, convert it to a Kerberos v4 principal
-# name. Returns undef if it can't convert the name for some reason (right
-# now, only if the principal has more than two parts). Note that this mapping
-# does not guarantee a unique result; multiple hosts in different domains can
-# be mapped to the same Kerberos v4 principal name using this function.
-sub kaserver_name {
- my ($self, $k5) = @_;
- my %host = map { $_ => 1 } qw(host ident imap pop smtp);
- $k5 =~ s/\@.*//;
- my @parts = split ('/', $k5);
- if (@parts > 2) {
- return;
- } elsif (@parts == 2 and $host{$parts[0]}) {
- $parts[1] =~ s/\..*//;
- $parts[0] = 'rcmd' if $parts[0] eq 'host';
- }
- my $k4 = join ('.', @parts);
- if ($Wallet::Config::KEYTAB_AFS_REALM) {
- $k4 .= '@' . $Wallet::Config::KEYTAB_AFS_REALM;
- }
- return $k4;
-}
-
-# Run kasetkey with the given arguments. Returns true on success and false on
-# failure. On failure, sets the internal error to the error from kasetkey.
-sub kaserver_kasetkey {
- my ($self, @args) = @_;
- my $admin = $Wallet::Config::KEYTAB_AFS_ADMIN;
- my $admin_srvtab = $Wallet::Config::KEYTAB_AFS_SRVTAB;
- my $kasetkey = $Wallet::Config::KEYTAB_AFS_KASETKEY;
- unless ($kasetkey and $admin and $admin_srvtab) {
- $self->error ('kaserver synchronization not configured');
- return;
- }
- my $pid = open (KASETKEY, '-|');
- if (not defined $pid) {
- $self->error ("cannot fork: $!");
- return;
- } elsif ($pid == 0) {
- # Don't use die here; it will get trapped as an exception. Also be
- # careful about our database handles. (We still lose if there's some
- # other database handle open we don't know about.)
- $self->{dbh}->{InactiveDestroy} = 1;
- unless (open (STDERR, '>&STDOUT')) {
- warn "cannot redirect stderr: $!\n";
- exit 1;
- }
- unless (exec ($kasetkey, '-k', $admin_srvtab, '-a', $admin, @args)) {
- warn "cannot exec $kasetkey: $!\n";
- exit 1;
- }
- } else {
- local $/;
- my $output = <KASETKEY>;
- close KASETKEY;
- if ($? != 0) {
- $output =~ s/\s+\z//;
- $output =~ s/\n/, /g;
- $output = ': ' . $output if $output;
- $self->error ("cannot synchronize key with kaserver$output");
- return;
- }
- }
- return 1;
-}
-
-# Given a keytab file name, the Kerberos v5 principal that's stored in that
-# keytab, a srvtab file name, and the corresponding Kerberos v4 principal,
-# write out a srvtab file containing the DES key in that keytab. Fails if
-# there is no DES key in the keytab.
-sub kaserver_srvtab {
- my ($self, $keytab, $k5, $srvtab, $k4) = @_;
-
- # Gah. Someday I will write Perl bindings for Kerberos that are less
- # broken.
- eval { require Authen::Krb5 };
- if ($@) {
- $self->error ("kaserver synchronization support not available: $@");
- return;
- }
- eval { Authen::Krb5::init_context() };
- if ($@ and not $@ =~ /^Authen::Krb5 already initialized/) {
- $self->error ('Kerberos initialization failed');
- return;
- }
- undef $@;
-
- # Do the interface dance. We call kt_read_service_key with 0 for the kvno
- # to get any kvno, which works with MIT Kerberos at least. Assume a DES
- # enctype of 1. This code won't work with any enctype other than
- # des-cbc-crc.
- my $princ = Authen::Krb5::parse_name ($k5);
- unless (defined $princ) {
- my $error = Authen::Krb5::error();
- $self->error ("cannot parse $k5: $error");
- return;
- }
- my $key = Authen::Krb5::kt_read_service_key ($keytab, $princ, 0, 1);
- unless (defined $key) {
- my $error = Authen::Krb5::error();
- $self->error ("cannot find des-cbc-crc key in $keytab: $error");
- return;
- }
- unless (open (SRVTAB, '>', $srvtab)) {
- $self->error ("cannot create $srvtab: $!");
- return;
- }
-
- # srvtab format is nul-terminated name, nul-terminated instance,
- # nul-terminated realm, single character kvno (which we always set to 0),
- # and DES keyblock.
- my ($principal, $realm) = split ('@', $k4);
- $realm ||= '';
- my ($name, $inst) = split (/\./, $principal, 2);
- $inst ||= '';
- my $data = join ("\0", $name, $inst, $realm);
- $data .= "\0\0" . $key->contents;
- print SRVTAB $data;
- unless (close SRVTAB) {
- unlink $srvtab;
- $self->error ("cannot write to $srvtab: $!");
- return;
- }
- return 1;
-}
-
-# Given a principal name and a path to the keytab, synchronizes the key with a
-# principal in an AFS kaserver. Returns true on success and false on failure.
-# On failure, sets the internal error.
-sub kaserver_sync {
- my ($self, $principal, $keytab) = @_;
- if ($Wallet::Config::KEYTAB_REALM) {
- $principal .= '@' . $Wallet::Config::KEYTAB_REALM;
- }
- my $k4 = $self->kaserver_name ($principal);
- if (not defined $k4) {
- $self->error ("cannot convert $principal to Kerberos v4");
- return;
- }
- my $srvtab = $Wallet::Config::KEYTAB_TMP . "/srvtab.$$";
- unless ($self->kaserver_srvtab ($keytab, $principal, $srvtab, $k4)) {
- return;
- }
- unless ($self->kaserver_kasetkey ('-c', $srvtab, '-s', $k4)) {
- unlink $srvtab;
- return;
- }
- unlink $srvtab;
- return 1;
-}
-
-# Given a principal name, destroy the corresponding principal in the AFS
-# kaserver. Returns true on success and false on failure, setting the object
-# error if it fails.
-sub kaserver_destroy {
- my ($self, $principal) = @_;
- my $k4 = $self->kaserver_name ($principal);
- if (not defined $k4) {
- $self->error ("cannot convert $principal to Kerberos v4");
- return;
- }
- return $self->kaserver_kasetkey ('-D', $k4);
-}
-
-# Set the kaserver sync attribute. Called by attr(). Returns true on success
-# and false on failure, setting the object error if it fails.
-sub kaserver_set {
- my ($self, $user, $host, $time) = @_;
- $time ||= time;
- my @trace = ($user, $host, $time);
- my $name = $self->{name};
- eval {
- my $sql = "select ks_name from keytab_sync where ks_name = ? and
- ks_target = 'kaserver'";
- my $result = $self->{dbh}->selectrow_array ($sql, undef, $name);
- if ($result) {
- die "kaserver synchronization already set\n";
- }
- $sql = "insert into keytab_sync (ks_name, ks_target)
- values (?, 'kaserver')";
- $self->{dbh}->do ($sql, undef, $name);
- $self->log_set ('type_data sync', undef, 'kaserver', @trace);
- $self->{dbh}->commit;
- };
- if ($@) {
- $self->error ($@);
- $self->{dbh}->rollback;
- return;
- }
- return 1;
-}
-
-# Clear the kaserver sync attribute. Called by attr(). Returns true on
-# success and false on failure, setting the object error if it fails.
-sub kaserver_clear {
- my ($self, $user, $host, $time) = @_;
- $time ||= time;
- my @trace = ($user, $host, $time);
- my $name = $self->{name};
- eval {
- my $sql = "select ks_name from keytab_sync where ks_name = ? and
- ks_target = 'kaserver'";
- my $result = $self->{dbh}->selectrow_array ($sql, undef, $name);
- unless ($result) {
- die "kaserver synchronization not set\n";
- }
- $sql = 'delete from keytab_sync where ks_name = ?';
- $self->{dbh}->do ($sql, undef, $name);
- $self->log_set ('type_data sync', 'kaserver', undef, @trace);
- $self->{dbh}->commit;
- };
- if ($@) {
- $self->error ($@);
- $self->{dbh}->rollback;
- return;
- }
- return 1;
-}
+$VERSION = '0.08';
##############################################################################
# Enctype restriction
@@ -379,9 +157,14 @@ sub keytab_retrieve {
# Core methods
##############################################################################
-# Override attr to support setting the enctypes and sync attributes.
+# Override attr to support setting the enctypes and sync attributes. Note
+# that the sync attribute has no supported targets at present and hence will
+# always return an error, but the code is still here so that it doesn't have
+# to be rewritten once a new sync target is added.
sub attr {
my ($self, $attribute, $values, $user, $host, $time) = @_;
+ $time ||= time;
+ my @trace = ($user, $host, $time);
my %known = map { $_ => 1 } qw(enctypes sync);
undef $self->{error};
unless ($known{$attribute}) {
@@ -395,14 +178,25 @@ sub attr {
if (@$values > 1) {
$self->error ('only one synchronization target supported');
return;
- } elsif (@$values and $values->[0] ne 'kaserver') {
+ } elsif (@$values) {
my $target = $values->[0];
$self->error ("unsupported synchronization target $target");
return;
- } elsif (@$values) {
- return $self->kaserver_set ($user, $host, $time);
} else {
- return $self->kaserver_clear ($user, $host, $time);
+ eval {
+ my $sql = 'select ks_target from keytab_sync where
+ ks_name = ?';
+ my $dbh = $self->{dbh};
+ my $name = $self->{name};
+ my ($result) = $dbh->selectrow_array ($sql, undef, $name);
+ if ($result) {
+ my $sql = 'delete from keytab_sync where ks_name = ?';
+ $self->{dbh}->do ($sql, undef, $name);
+ $self->log_set ('type_data sync', $result, undef,
+ @trace);
+ }
+ $self->{dbh}->commit;
+ }
}
}
} else {
@@ -511,12 +305,6 @@ sub destroy {
$self->error ("cannot destroy $id: object is locked");
return;
}
- my @sync = $self->attr ('sync');
- if (grep { $_ eq 'kaserver' } @sync) {
- unless ($self->kaserver_destroy ($self->{name})) {
- return;
- }
- }
eval {
my $sql = 'delete from keytab_sync where ks_name = ?';
$self->{dbh}->do ($sql, undef, $self->{name});
@@ -582,15 +370,6 @@ sub get {
return;
}
close KEYTAB;
- my @sync = $self->attr ('sync');
- if (grep { $_ eq 'kaserver' } @sync) {
- unless ($self->kaserver_sync ($self->{name}, $file)) {
- unlink $file;
- return;
- }
- } elsif ($Wallet::Config::KEYTAB_AFS_DESTROY) {
- $self->kaserver_destroy ($self->{name});
- }
unlink $file;
$self->log_action ('get', $user, $host, $time);
return $data;
@@ -646,7 +425,7 @@ methods that are overridden or behave specially for this implementation.
=item attr(ATTRIBUTE [, VALUES, PRINCIPAL, HOSTNAME [, DATETIME]])
-Sets or retrieves a given object attribute. The following attributes are
+Sets or retrieves a given object attribute. The following attribute is
supported:
=over 4
@@ -655,40 +434,21 @@ supported:
Restricts the generated keytab to a specific set of encryption types. The
values of this attribute must be enctype strings recognized by Kerberos
-(strings like C<aes256-cts> or C<des-cbc-crc>). Encryption types must also
-be present in the list of supported enctypes stored in the database database
-or the attr() method will reject them. Note that the salt should not be
-included; since the salt is irrelevant for keytab keys, it will always be
-set to C<normal> by the wallet.
+(strings like C<aes256-cts-hmac-sha1-96> or C<des-cbc-crc>). Encryption
+types must also be present in the list of supported enctypes stored in the
+database database or the attr() method will reject them. Note that the
+salt should not be included; since the salt is irrelevant for keytab keys,
+it will always be set to the default by the wallet.
-If this attribute is set, the specified enctype list will be passed to
-ktadd when get() is called for that keytab. If it is not set, the default
-set in the KDC will be used.
+If this attribute is set, the principal will be restricted to that
+specific enctype list when get() is called for that keytab. If it is not
+set, the default set in the KDC will be used.
This attribute is ignored if the C<unchanging> flag is set on a keytab.
Keytabs retrieved with C<unchanging> set will contain all keys present in
the KDC for that Kerberos principal and therefore may contain different
enctypes than those requested by this attribute.
-=item sync
-
-Sets the external systems to which the key of a given principal is
-synchronized. The only supported value for this attribute is C<kaserver>,
-which says to synchronize the key with an AFS Kerberos v4 kaserver.
-
-If this attribute is set on a keytab, whenever get() is called for that
-keytab, the new DES key will be extracted from that keytab and set in the
-configured AFS kaserver. The Kerberos v4 principal name will be the same as
-the Kerberos v5 principal name except that the components are separated by
-C<.> instead of C</>; the second component is truncated after the first C<.>
-if the first component is one of C<host>, C<ident>, C<imap>, C<pop>, or
-C<smtp>; and the first component is C<rcmd> if the Kerberos v5 principal
-component is C<host>. The principal name must not contain more than two
-components.
-
-If this attribute is set, calling destroy() will also destroy the principal
-from the AFS kaserver, with a principal mapping determined as above.
-
=back
If no other arguments besides ATTRIBUTE are given, returns the values of
@@ -716,11 +476,11 @@ used.
When a new keytab object is created, the Kerberos principal designated by
NAME is also created in the Kerberos realm determined from the wallet
-configuration. If the principal already exists, create() still succeeds (so
-that a previously unmanaged principal can be imported into the wallet).
-Otherwise, if the Kerberos principal could not be created, create() fails.
-The principal is created with the C<-randkey> option to randomize its keys.
-NAME must not contain the realm; instead, the KEYTAB_REALM configuration
+configuration. If the principal already exists, create() still succeeds
+(so that a previously unmanaged principal can be imported into the
+wallet). Otherwise, if the Kerberos principal could not be created,
+create() fails. The principal is created with the randomized keys. NAME
+must not contain the realm; instead, the KEYTAB_REALM configuration
variable should be set. See Wallet::Config(3) for more information.
If create() fails, it throws an exception.
@@ -738,18 +498,14 @@ destroying the object. If DATETIME isn't given, the current time is used.
=item get(PRINCIPAL, HOSTNAME [, DATETIME])
-Retrieves a keytab for this object and returns the keytab data or undef
-on error. The caller should call error() to get the error message if
-get() returns undef. The keytab is created with C<ktadd>, invalidating
-any existing keytabs for that principal, unless the unchanging flag is set
-on the object. PRINCIPAL, HOSTNAME, and DATETIME are stored as history
-information. PRINCIPAL should be the user who is downloading the keytab.
-If DATETIME isn't given, the current time is used.
-
-If the configuration variable $KEYTAB_AFS_DESTROY is set and the C<sync>
-attribute is not set to C<kaserver>, calling get() on a keytab object will
-cause the corresponding Kerberos v4 principal to be destroyed. This
-variable is not set by default.
+Retrieves a keytab for this object and returns the keytab data or undef on
+error. The caller should call error() to get the error message if get()
+returns undef. The keytab is created with new randomized keys,
+invalidating any existing keytabs for that principal, unless the
+unchanging flag is set on the object. PRINCIPAL, HOSTNAME, and DATETIME
+are stored as history information. PRINCIPAL should be the user who is
+downloading the keytab. If DATETIME isn't given, the current time is
+used.
=back
@@ -767,15 +523,14 @@ of the current process. The file is unlinked after being read.
=head1 LIMITATIONS
-Currently, this implementation only supports MIT Kerberos and needs
-modifications to support Heimdal. It calls an external B<kadmin> program
-rather than using a native Perl module and therefore requires B<kadmin> be
-installed and parses its output. It may miss some error conditions if the
-output of B<kadmin> ever changes.
+Currently, when used with MIT Kerberos, this implementation calls an
+external B<kadmin> program rather than using a native Perl module and
+therefore requires B<kadmin> be installed and parses its output. It may
+miss some error conditions if the output of B<kadmin> ever changes.
Only one Kerberos realm is supported for a given wallet implementation and
-all keytab objects stored must be in that realm. Keytab names in the wallet
-database do not have realm information.
+all keytab objects stored must be in that realm. Keytab names in the
+wallet database do not have realm information.
=head1 SEE ALSO
diff --git a/perl/Wallet/Schema.pm b/perl/Wallet/Schema.pm
index 2b256a2..252da03 100644
--- a/perl/Wallet/Schema.pm
+++ b/perl/Wallet/Schema.pm
@@ -1,7 +1,7 @@
# Wallet::Schema -- Database schema for the wallet system.
#
# Written by Russ Allbery <rra@stanford.edu>
-# Copyright 2007, 2008 Board of Trustees, Leland Stanford Jr. University
+# Copyright 2007, 2008, 2010 Board of Trustees, Leland Stanford Jr. University
#
# See LICENSE for licensing terms.
@@ -20,7 +20,7 @@ use DBI;
# 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.05';
+$VERSION = '0.06';
##############################################################################
# Data manipulation
@@ -372,12 +372,12 @@ change was made.
=head2 Keytab Backend Data
-The keytab backend supports synchronizing keys with an external system. The
-permitted external systems are listed in a normalization table:
+The keytab backend has stub support for synchronizing keys with an
+external system, although no external systems are currently supported.
+The permitted external systems are listed in a normalization table:
create table sync_targets
(st_name varchar(255) primary key);
- insert into sync_targets (st_name) values ('kaserver');
and then the synchronization targets for a given keytab are stored in this
table:
diff --git a/perl/t/config.t b/perl/t/config.t
index d60d7e7..1377cb8 100755
--- a/perl/t/config.t
+++ b/perl/t/config.t
@@ -3,11 +3,11 @@
# t/config.t -- Tests for the wallet server configuration.
#
# Written by Russ Allbery <rra@stanford.edu>
-# Copyright 2008 Board of Trustees, Leland Stanford Jr. University
+# Copyright 2008, 2010 Board of Trustees, Leland Stanford Jr. University
#
# See LICENSE for licensing terms.
-use Test::More tests => 7;
+use Test::More tests => 6;
# Silence warnings since we're not using use.
package Wallet::Config;
@@ -25,8 +25,6 @@ is ($Wallet::Config::KEYTAB_FLAGS, '-clearpolicy',
' and KEYTAB_FLAGS is correct');
is ($Wallet::Config::KEYTAB_KADMIN, 'kadmin',
' and KEYTAB_KADMIN is correct');
-is ($Wallet::Config::KEYTAB_AFS_KASETKEY, 'kasetkey',
- ' and KEYTAB_AFS_KASETKEY is correct');
is ($Wallet::Config::DB_DRIVER, undef, ' and DB_DRIVER is unset');
# Create a configuration file with a single setting.
diff --git a/perl/t/keytab.t b/perl/t/keytab.t
index 93df51c..e5a68be 100755
--- a/perl/t/keytab.t
+++ b/perl/t/keytab.t
@@ -9,7 +9,7 @@
# See LICENSE for licensing terms.
use POSIX qw(strftime);
-use Test::More tests => 213;
+use Test::More tests => 125;
use Wallet::Admin;
use Wallet::Config;
@@ -147,24 +147,6 @@ sub enctypes {
return sort @enctypes;
}
-# Given a Wallet::Object::Keytab object, the keytab data, the Kerberos v5
-# principal, and the Kerberos v4 principal, write the keytab to a file,
-# generate a srvtab, and try authenticating using k4start.
-sub valid_srvtab {
- my ($object, $keytab, $k5, $k4) = @_;
- open (KEYTAB, '>', 'keytab') or die "cannot create keytab: $!\n";
- print KEYTAB $keytab;
- close KEYTAB;
- unless ($object->kaserver_srvtab ('keytab', $k5, 'srvtab', $k4)) {
- warn "cannot write srvtab: ", $object->error, "\n";
- return 0;
- }
- $ENV{KRBTKFILE} = 'krb4cc_temp';
- system ("k4start -f srvtab $k4 2>&1 >/dev/null </dev/null");
- unlink 'keytab', 'srvtab', 'krb4cc_temp';
- return ($? == 0) ? 1 : 0;
-}
-
# Use Wallet::Admin to set up the database.
unlink ('krb5cc_temp', 'krb5cc_test', 'test-acl', 'test-pid');
db_setup;
@@ -474,55 +456,18 @@ EOO
is ($one->history, $history, 'History is correct to this point');
}
-# Tests for kaserver synchronization support.
+# Tests for synchronization support. This code is deactivated at present
+# since no synchronization targets are supported, but we want to still test
+# the basic stub code.
SKIP: {
skip 'no keytab configuration', 106 unless -f 't/data/test.keytab';
- # Test the principal mapping. We can do this without having a kaserver
- # configuration. We only need a basic keytab object configuration. Do
- # this as white-box testing since we don't want to fill the test realm
- # with a bunch of random principals.
+ # Test setting synchronization attributes, which can also be done without
+ # configuration.
my $one = eval {
Wallet::Object::Keytab->create ('keytab', 'wallet/one', $dbh, @trace)
};
ok (defined ($one), 'Creating wallet/one succeeds');
- my %princs =
- (foo => 'foo',
- host => 'host',
- rcmd => 'rcmd',
- 'rcmd.foo' => 'rcmd.foo',
- 'host/foo.example.org' => 'rcmd.foo',
- 'ident/foo.example.org' => 'ident.foo',
- 'imap/foo.example.org' => 'imap.foo',
- 'pop/foo.example.org' => 'pop.foo',
- 'smtp/foo.example.org' => 'smtp.foo',
- 'service/foo' => 'service.foo',
- 'foo/bar' => 'foo.bar');
- for my $princ (sort keys %princs) {
- my $result = $princs{$princ};
- is ($one->kaserver_name ($princ), $result, "Name mapping: $princ");
- is ($one->kaserver_name ("$princ\@EXAMPLE.ORG"), $result,
- ' with K5 realm');
- $Wallet::Config::KEYTAB_AFS_REALM = 'AFS.EXAMPLE.ORG';
- is ($one->kaserver_name ($princ), "$result\@AFS.EXAMPLE.ORG",
- ' with K4 realm');
- is ($one->kaserver_name ("$princ\@EXAMPLE.ORG"),
- "$result\@AFS.EXAMPLE.ORG", ' with K5 and K4 realm');
- undef $Wallet::Config::KEYTAB_AFS_REALM;
- }
- for my $princ (qw{service/foo/bar foo/bar/baz}) {
- is ($one->kaserver_name ($princ), undef, "Name mapping: $princ");
- is ($one->kaserver_name ("$princ\@EXAMPLE.ORG"), undef,
- ' with K5 realm');
- $Wallet::Config::KEYTAB_AFS_REALM = 'AFS.EXAMPLE.ORG';
- is ($one->kaserver_name ($princ), undef, ' with K4 realm');
- is ($one->kaserver_name ("$princ\@EXAMPLE.ORG"), undef,
- ' with K5 and K4 realm');
- undef $Wallet::Config::KEYTAB_AFS_REALM;
- }
-
- # Test setting synchronization attributes, which can also be done without
- # configuration.
my $expected = <<"EOO";
Type: keytab
Name: wallet/one
@@ -537,16 +482,20 @@ EOO
my @targets = $one->attr ('foo');
is (scalar (@targets), 0, ' and getting an unknown attribute fails');
is ($one->error, 'unknown attribute foo', ' with the right error');
- is ($one->attr ('sync', [ 'foo' ], @trace), undef,
+ is ($one->attr ('sync', [ 'kaserver' ], @trace), undef,
' and setting an unknown sync target fails');
- is ($one->error, 'unsupported synchronization target foo',
+ is ($one->error, 'unsupported synchronization target kaserver',
' with the right error');
is ($one->attr ('sync', [ 'kaserver', 'bar' ], @trace), undef,
' and setting two targets fails');
is ($one->error, 'only one synchronization target supported',
' with the right error');
- is ($one->attr ('sync', [ 'kaserver' ], @trace), 1,
- ' but setting only kaserver works');
+
+ # Create a synchronization manually so that we can test the display and
+ # removal code.
+ my $sql = "insert into keytab_sync (ks_name, ks_target) values
+ ('wallet/one', 'kaserver')";
+ $dbh->do ($sql);
@targets = $one->attr ('sync');
is (scalar (@targets), 1, ' and now one target is set');
is ($targets[0], 'kaserver', ' and it is correct');
@@ -563,15 +512,10 @@ EOO
$history .= <<"EOO";
$date create
by $user from $host
-$date add kaserver to attribute sync
- by $user from $host
EOO
is ($one->history, $history, ' and history is correct for attributes');
- is ($one->destroy (@trace), undef, 'Destroying wallet/one fails');
- is ($one->error, 'kaserver synchronization not configured',
- ' because kaserver support is not configured');
is ($one->attr ('sync', [], @trace), 1,
- ' but removing the kaserver sync attribute works');
+ 'Removing the kaserver sync attribute works');
is ($one->destroy (@trace),1, ' and then destroying wallet/one works');
$history .= <<"EOO";
$date remove kaserver from attribute sync
@@ -579,136 +523,7 @@ $date remove kaserver from attribute sync
$date destroy
by $user from $host
EOO
-
- # Set up our configuration.
- skip 'no AFS kaserver configuration', 34 unless -f 't/data/test.srvtab';
- skip 'no kaserver support', 34 unless -x '../kasetkey/kasetkey';
- $Wallet::Config::KEYTAB_FILE = 't/data/test.keytab';
- $Wallet::Config::KEYTAB_PRINCIPAL = contents ('t/data/test.principal');
- $Wallet::Config::KEYTAB_REALM = contents ('t/data/test.realm');
- $Wallet::Config::KEYTAB_KRBTYPE = contents ('t/data/test.krbtype');
- $Wallet::Config::KEYTAB_TMP = '.';
- $Wallet::Config::KEYTAB_AFS_KASETKEY = '../kasetkey/kasetkey';
- my $realm = $Wallet::Config::KEYTAB_REALM;
- my $k5 = "wallet/one\@$realm";
-
- # Recreate and reconfigure the object.
- $one = eval {
- Wallet::Object::Keytab->create ('keytab', 'wallet/one', $dbh, @trace)
- };
- ok (defined ($one), 'Creating wallet/one succeeds');
- is ($one->attr ('sync', [ 'kaserver' ], @trace), 1,
- ' and setting the kaserver sync attribute works');
-
- # Finally, we can test.
- is ($one->get (@trace), undef, 'Get without configuration fails');
- is ($one->error, 'kaserver synchronization not configured',
- ' with the right error');
- $Wallet::Config::KEYTAB_AFS_ADMIN = contents ('t/data/test.admin');
- my $k4_realm = $Wallet::Config::KEYTAB_AFS_ADMIN;
- $k4_realm =~ s/^[^\@]+\@//;
- $Wallet::Config::KEYTAB_AFS_REALM = $k4_realm;
- my $k4 = "wallet.one\@$k4_realm";
- is ($one->get (@trace), undef, ' and still fails with just admin');
- is ($one->error, 'kaserver synchronization not configured',
- ' with the right error');
- $Wallet::Config::KEYTAB_AFS_SRVTAB = 't/data/test.srvtab';
- my $keytab = $one->get (@trace);
- if (defined ($keytab)) {
- ok (1, ' and now get works');
- } else {
- is ($one->error, '', ' and now get works');
- }
- ok (valid_srvtab ($one, $keytab, $k5, $k4), ' and the srvtab is valid');
- ok (! -f "./srvtab.$$", ' and the temporary file was cleaned up');
-
- # Now remove the sync attribute and make sure things aren't synced.
- is ($one->attr ('sync', [], @trace), 1, 'Clearing sync works');
- @targets = $one->attr ('sync');
- is (scalar (@targets), 0, ' and now there is no attribute');
- is ($one->error, undef, ' and no error');
- my $new_keytab = $one->get (@trace);
- ok (defined ($new_keytab), ' and get still works');
- ok (! valid_srvtab ($one, $new_keytab, $k5, $k4),
- ' but the srvtab does not');
- ok (valid_srvtab ($one, $keytab, $k5, $k4), ' and the old one does');
- is ($one->destroy (@trace), 1, ' and destroying wallet/one works');
- ok (valid_srvtab ($one, $keytab, $k5, $k4),
- ' and the principal is still there');
-
- # Test KEYTAB_AFS_DESTROY.
- $one = eval {
- Wallet::Object::Keytab->create ('keytab', 'wallet/one', $dbh, @trace)
- };
- ok (defined ($one), 'Creating wallet/one succeeds');
- $Wallet::Config::KEYTAB_AFS_DESTROY = 1;
- $new_keytab = $one->get (@trace);
- ok (defined ($new_keytab), ' and get works');
- ok (! valid_srvtab ($one, $new_keytab, $k5, $k4),
- ' but the srvtab does not');
- ok (! valid_srvtab ($one, $keytab, $k5, $k4),
- ' and now neither does the old one');
- $Wallet::Config::KEYTAB_AFS_DESTROY = 0;
-
- # Put it back and make sure it works again.
- is ($one->attr ('sync', [ 'kaserver' ], @trace), 1, 'Setting sync works');
- $keytab = $one->get (@trace);
- ok (defined ($keytab), ' and get works');
- ok (valid_srvtab ($one, $keytab, $k5, $k4), ' and the srvtab is valid');
- $Wallet::Config::KEYTAB_AFS_KASETKEY = '/path/to/nonexistent/file';
- $new_keytab = $one->get (@trace);
- ok (! defined ($new_keytab),
- ' but it fails if we mess up the kasetkey path');
- like ($one->error, qr{^cannot synchronize key with kaserver: },
- ' with the right error message');
- ok (! -f "keytab.$$", ' and the temporary file was cleaned up');
- $Wallet::Config::KEYTAB_AFS_KASETKEY = '../kasetkey/kasetkey';
-
- # Destroy the principal and recreate it and make sure we cleaned up.
- is ($one->destroy (@trace), 1, 'Destroying wallet/one works');
- ok (! valid_srvtab ($one, $keytab, $k5, $k4),
- ' and the principal is gone');
- $one = eval {
- Wallet::Object::Keytab->create ('keytab', 'wallet/one', $dbh, @trace)
- };
- ok (defined ($one), ' and recreating it succeeds');
- @targets = $one->attr ('sync');
- is (scalar (@targets), 0, ' and now there is no attribute');
- is ($one->error, undef, ' and no error');
-
- # Now destroy it for good.
- is ($one->destroy (@trace), 1, 'Destroying wallet/one works');
-
- # Check that history is still correct.
- $history .= <<"EOO";
-$date create
- by $user from $host
-$date add kaserver to attribute sync
- by $user from $host
-$date get
- by $user from $host
-$date remove kaserver from attribute sync
- by $user from $host
-$date get
- by $user from $host
-$date destroy
- by $user from $host
-$date create
- by $user from $host
-$date get
- by $user from $host
-$date add kaserver to attribute sync
- by $user from $host
-$date get
- by $user from $host
-$date destroy
- by $user from $host
-$date create
- by $user from $host
-$date destroy
- by $user from $host
-EOO
- is ($one->history, $history, 'History is correct to this point');
+ is ($one->history, $history, ' and history is correct for removal');
}
# Tests for enctype restriction.
diff --git a/perl/t/schema.t b/perl/t/schema.t
index 01d5dac..559ece4 100755
--- a/perl/t/schema.t
+++ b/perl/t/schema.t
@@ -21,7 +21,7 @@ ok (defined $schema, 'Wallet::Schema creation');
ok ($schema->isa ('Wallet::Schema'), ' and class verification');
my @sql = $schema->sql;
ok (@sql > 0, 'sql() returns something');
-is (scalar (@sql), 29, ' and returns the right number of statements');
+is (scalar (@sql), 28, ' and returns the right number of statements');
# Connect to a database and test create.
db_setup;