#!@PERL@ # -*- perl -*- # # End-to-end tests for the wallet client. # # Written by Russ Allbery # Copyright 2018 Russ Allbery # Copyright 2008, 2010, 2014 # The Board of Trustees of the Leland Stanford Junior University # # See LICENSE for licensing terms. use strict; use warnings; # Point to our server configuration. This must be done before Wallet::Config # is loaded, and it's pulled in as a prerequisite for Wallet::Admin. BEGIN { $ENV{WALLET_CONFIG} = "$ENV{C_TAP_SOURCE}/data/wallet.conf" } use Test::More tests => 59; use lib "$ENV{C_TAP_SOURCE}/../perl/lib"; use Wallet::Admin; use lib "$ENV{C_TAP_SOURCE}/../perl/t/lib"; use Util; # Make a call to the wallet client. Takes the principal used by the server # and the command. Returns the standard output, the standard error, and the # exit status as a list. sub wallet { my ($principal, @command) = @_; my $pid = fork; if (not defined $pid) { die "cannot fork: $!\n"; } elsif ($pid == 0) { open (STDOUT, '>', 'wallet.out') or die "cannot create wallet.out: $!\n"; open (STDERR, '>', 'wallet.err') or die "cannot create wallet.err: $!\n"; exec ("$ENV{C_TAP_BUILD}/../client/wallet", '-k', $principal, '-p', '14373', '-s', 'localhost', @command) or die "cannot run $ENV{C_TAP_BUILD}/client/wallet: $!\n"; } else { waitpid ($pid, 0); } my $status = $?; local $/; open (OUT, '<', 'wallet.out') or die "cannot open wallet.out: $!\n"; my $output = ; close OUT; open (ERR, '<', 'wallet.err') or die "cannot open wallet.err: $!\n"; my $error = ; close ERR; unlink ('wallet.out', 'wallet.err'); return ($output, $error, $status); } # cd to the correct directory. chdir "$ENV{C_TAP_SOURCE}" or die "Cannot chdir to $ENV{C_TAP_SOURCE}: $!\n"; SKIP: { skip 'no keytab configuration', 59 unless -f "$ENV{C_TAP_BUILD}/config/keytab"; my $remctld = '@REMCTLD@'; skip 'remctld not found', 59 unless $remctld; # Spawn remctld and get local tickets. Don't destroy the user's Kerberos # ticket cache. unlink ('krb5cc_test', 'test-pid'); my $principal = contents ("$ENV{C_TAP_BUILD}/config/principal"); remctld_spawn ($remctld, $principal, "$ENV{C_TAP_BUILD}/config/keytab", "$ENV{C_TAP_SOURCE}/data/full.conf"); $ENV{KRB5CCNAME} = 'krb5cc_test'; getcreds ("$ENV{C_TAP_BUILD}/config/keytab", $principal); # Use Wallet::Admin to set up the database. db_setup; my $admin = eval { Wallet::Admin->new }; is ($@, '', 'Database connection succeeded'); is ($admin->reinitialize ($principal), 1, 'Database initialization succeeded'); my $dbh = $admin->dbh; # Create the file bucket. if (-d 'test-files') { system ('rm', '-r', 'test-files'); } mkdir ('test-files', 0777) or die "cannot create file-bucket: $!\n"; # Now, start testing. First, create an object, create an ACL, assign an # owner, store the contents, and then get the contents and make sure all # of that works as expected. my ($out, $err, $status) = wallet ($principal, 'create', 'file', 'test'); is ($status, 0, 'Object creation succeeds'); is ($out, '', ' with no output'); is ($err, '', ' and no error'); ($out, $err, $status) = wallet ($principal, 'acl', 'create', 'user/test'); is ($status, 0, 'ACL creation succeeds'); is ($out, '', ' with no output'); is ($err, '', ' and no error'); ($out, $err, $status) = wallet ($principal, 'acl', 'add', 'user/test', 'krb5', $principal); is ($status, 0, 'ACL population succeeds'); is ($out, '', ' with no output'); is ($err, '', ' and no error'); ($out, $err, $status) = wallet ($principal, 'acl', 'show', 'user/test'); is ($status, 0, 'ACL show succeeds'); is ($out, "Members of ACL user/test (id: 2) are:\n krb5 $principal\n", ' with the right output'); is ($err, '', ' and no error'); ($out, $err, $status) = wallet ($principal, 'owner', 'file', 'test', 'user/test'); is ($status, 0, 'Object owner succeeds'); is ($out, '', ' with no output'); is ($err, '', ' and no error'); ($out, $err, $status) = wallet ($principal, 'store', 'file', 'test', "foo\nbar\n"); is ($status, 0, 'Object store succeeds'); is ($out, '', ' with no output'); is ($err, '', ' and no error'); ($out, $err, $status) = wallet ($principal, 'get', 'file', 'test'); is ($status, 0, 'Object get succeeds'); is ($out, "foo\nbar\n", ' and returns the right data'); is ($err, '', ' and no error'); ($out, $err, $status) = wallet ($principal, 'store', 'file', 'test', ''); is ($status, 0, 'Store of empty object succeeds'); is ($out, '', ' with no output'); is ($err, '', ' and no error'); ($out, $err, $status) = wallet ($principal, 'get', 'file', 'test'); is ($status, 0, 'Get of empty object succeeds'); is ($out, '', ' and returns an empty object'); is ($err, '', ' with no error'); ($out, $err, $status) = wallet ($principal, 'destroy', 'file', 'test'); is ($status, 0, 'Object destroy succeeds'); is ($out, '', ' with no output'); is ($err, '', ' and no error'); ($out, $err, $status) = wallet ($principal, 'get', 'file', 'test'); isnt ($status, 0, 'Object get now fails'); is ($out, '', ' with no output'); is ($err, "wallet: $principal not authorized to create file:test\n", ' and the right error'); # Try auto-creation. ($out, $err, $status) = wallet ($principal, 'get', 'file', 'auto'); isnt ($status, 0, 'Object autocreation get fails'); is ($out, '', ' with no output'); is ($err, "wallet: cannot get file:auto: object has not been stored\n", ' and the right error'); ($out, $err, $status) = wallet ($principal, 'destroy', 'file', 'auto'); is ($status, 0, 'Object destroy succeeds'); is ($out, '', ' with no output'); is ($err, '', ' and no error'); ($out, $err, $status) = wallet ($principal, 'store', 'file', 'auto', "baz\nboo\n"); is ($status, 0, 'Object autocreation store succeeds'); is ($out, '', ' with no output'); is ($err, '', ' and no error'); ($out, $err, $status) = wallet ($principal, 'get', 'file', 'auto'); is ($status, 0, 'Object get now succeeds'); is ($out, "baz\nboo\n", ' with the right output'); is ($err, '', ' and no error'); # Store data beginning with a dash. ($out, $err, $status) = wallet ($principal, 'store', 'file', 'auto', '--', '-q'); is ($status, 0, 'Storing data that looks like an option succeeds'); is ($out, '', ' with no output'); is ($err, '', ' and no error'); ($out, $err, $status) = wallet ($principal, 'get', 'file', 'auto'); is ($status, 0, 'Object get succeeds'); is ($out, '-q', ' with the right output'); is ($err, '', ' and no error'); # Store data containing nul characters. my $data = "Some data\000with a nul"; open (IN, '>', 'tmp-file') or BAIL_OUT ("cannot create tmp-file: $!"); print IN $data; close IN; ($out, $err, $status) = wallet ($principal, '-f', 'tmp-file', 'store', 'file', 'auto'); unlink ('tmp-file'); is ($status, 0, 'Storing data with a nul succeeds'); is ($out, '', ' with no output'); is ($err, '', ' and no error'); ($out, $err, $status) = wallet ($principal, 'get', 'file', 'auto'); is ($status, 0, 'Object get succeeds'); is ($out, $data, ' with the right output'); is ($err, '', ' and no error'); # All done. remctld_stop; $admin->destroy; if (-d 'test-files') { system ('rm', '-r', 'test-files'); } } # Clean up the database and other test files at the end of the test. END { unlink ('wallet-db', 'krb5cc_test', 'test-pid'); }