summaryrefslogtreecommitdiff
path: root/perl/Wallet/Server.pm
diff options
context:
space:
mode:
authorRuss Allbery <rra@stanford.edu>2007-11-20 02:01:27 +0000
committerRuss Allbery <rra@stanford.edu>2007-11-20 02:01:27 +0000
commit66da128c39971f9a40553af9351b489f1ad186e1 (patch)
tree43522aaa63f8d290ab605322d20892b8a4bc0bb5 /perl/Wallet/Server.pm
parent96d4c0b4dbf8b2ff4649f418bd170d1242910b10 (diff)
Add support for running a user-defined function whenever an object is
created by a non-ADMIN user and using the default owner ACL returned by that function provided that the calling user is authorized by that ACL. This permits dynamic creation of new objects based on a default owner ACL programmatically determined from the name of the object.
Diffstat (limited to 'perl/Wallet/Server.pm')
-rw-r--r--perl/Wallet/Server.pm87
1 files changed, 79 insertions, 8 deletions
diff --git a/perl/Wallet/Server.pm b/perl/Wallet/Server.pm
index 41072a8..bb1a90c 100644
--- a/perl/Wallet/Server.pm
+++ b/perl/Wallet/Server.pm
@@ -133,11 +133,73 @@ sub DESTROY {
# Object methods
##############################################################################
+# Given an object which doesn't currently exist, check whether a default_owner
+# function is defined and, if so, if it returns an ACL for that object. If
+# so, create the ACL and check if the current user is authorized by that ACL.
+# Returns true if so, false if not, setting the internal error as appropriate.
+#
+# This leaves those new ACLs in the database, which may not be the best
+# behavior, but it's the simplest given the current Wallet::ACL API. This
+# should probably be revisited later.
+sub create_check {
+ my ($self, $type, $name) = @_;
+ my $user = $self->{user};
+ my $host = $self->{host};
+ my $dbh = $self->{dbh};
+ unless (defined (&Wallet::Config::default_owner)) {
+ $self->error ("$user not authorized to create ${type}:${name}");
+ return;
+ }
+ my ($aname, @acl) = Wallet::Config::default_owner ($type, $name);
+ unless (defined $aname) {
+ $self->error ("$user not authorized to create ${type}:${name}");
+ return;
+ }
+ my $acl = eval { Wallet::ACL->new ($aname, $dbh) };
+ if ($@) {
+ $acl = eval { Wallet::ACL->create ($aname, $dbh, $user, $host) };
+ if ($@) {
+ $self->error ($@);
+ return;
+ }
+ for my $entry (@acl) {
+ unless ($acl->add ($entry->[0], $entry->[1], $user, $host)) {
+ $self->error ($acl->error);
+ return;
+ }
+ }
+ } else {
+ my @entries = $acl->list;
+ if (not @entries and $acl->error) {
+ $self->error ($acl->error);
+ return;
+ }
+ @entries = sort { $$a[0] cmp $$b[0] && $$a[1] cmp $$b[1] } @entries;
+ @acl = sort { $$a[0] cmp $$b[0] && $$a[1] cmp $$b[1] } @acl;
+ my $okay = 1;
+ if (@entries != @acl) {
+ $okay = 0;
+ } else {
+ for my $i (0 .. $#entries) {
+ $okay = 0 unless ($entries[$i][0] eq $acl[$i][0]);
+ $okay = 0 unless ($entries[$i][1] eq $acl[$i][1]);
+ }
+ }
+ unless ($okay) {
+ $self->error ("ACL $aname exists and doesn't match default");
+ return;
+ }
+ }
+ if ($acl->check ($user)) {
+ return $aname;
+ } else {
+ $self->error ("$user not authorized to create ${type}:${name}");
+ return;
+ }
+}
+
# Create a new object and returns that object. On error, returns undef and
# sets the internal error.
-#
-# For the time being, we hard-code an ACL named ADMIN to use to authorize
-# object creation. This needs more work later.
sub create {
my ($self, $type, $name) = @_;
unless ($MAPPING{$type}) {
@@ -148,15 +210,20 @@ sub create {
my $dbh = $self->{dbh};
my $user = $self->{user};
my $host = $self->{host};
+ my $acl;
unless ($self->{admin}->check ($user)) {
- $self->error ("$user not authorized to create ${type}:${name}");
- return undef;
+ $acl = $self->create_check ($type, $name);
+ return unless $acl;
}
my $object = eval { $class->create ($type, $name, $dbh, $user, $host) };
if ($@) {
$self->error ($@);
- return undef;
+ return;
} else {
+ if ($acl and not $object->owner ($acl, $user, $host)) {
+ $self->error ($object->error);
+ return;
+ }
return 1;
}
}
@@ -780,10 +847,14 @@ if set, or the owner ACL if the store ACL is not set.
=item create(TYPE, NAME)
Creates a new object of type TYPE and name NAME. TYPE must be a recognized
-type for which the wallet system has a backend implementation. To create an
-object, the current user must be authorized by the ADMIN ACL. Returns true
+type for which the wallet system has a backend implementation. Returns true
on success and false on failure.
+To create an object, the current user must either be authorized by the ADMIN
+ACL or authorized by the default owner as determined by the wallet
+configuration. For more information on how to map new objects to default
+owners, see Wallet::Config(3).
+
=item destroy(TYPE, NAME)
Destroys the object identified by TYPE and NAME. This destroys any data