Commit f3310749 authored by Leigh B Stoller's avatar Leigh B Stoller

Minor change to credential verification and load.

Move the expiration test into verifygenicred. Change the invocation to
capture the output so that we can say something useful in the error
response, instead of what we do now which is just tell the user there
is an error.
parent a3027b65
......@@ -1376,7 +1376,7 @@ sub CheckCredential($;$)
my $credential = GeniCredential->CreateFromSigned($credstring);
if (!defined($credential)) {
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Could not create credential object");
$GeniCredential::CreateFromSignedError);
}
#
# Well formed credentials must now have URNs.
......
......@@ -5293,6 +5293,14 @@ sub CleanupDeadSlice($;$)
if (defined($experiment)) {
my $pid = $experiment->pid();
my $eid = $experiment->eid();
#
# Clear ports from shared vlans.
#
if ($experiment->ClearPortLans()) {
print STDERR "Could not clear portvlans\n";
return -1;
}
system("$SNMPIT -C -r $pid $eid");
if ($?) {
......@@ -5867,8 +5875,9 @@ sub CheckCredential($)
my $credential = GeniCredential->CreateFromSigned($_[0]);
if (!defined($credential)) {
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Could not create credential object");
$GeniCredential::CreateFromSignedError);
}
#
# Well formed credentials must now have URNs.
#
......@@ -5894,7 +5903,7 @@ sub CheckTicket($)
my $ticket = GeniTicket->CreateFromSignedTicket($_[0]);
if (!defined($ticket)) {
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Could not create ticket object");
$GeniTicket::CreateFromSignedError);
}
#
# Well formed tickets must now have URNs.
......
......@@ -1331,7 +1331,7 @@ sub UpdateTicket($)
my $ticket = GeniTicket->CreateFromSignedTicket($ticketstr);
if (!defined($ticket)) {
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Could not create GeniTicket object");
$GeniTicket::CreateFromSignedError);
}
#
# Make sure the ticket was issued to the caller.
......@@ -1466,7 +1466,7 @@ sub RedeemTicket($)
my $ticket = GeniTicket->CreateFromSignedTicket($ticketstr);
if (!defined($ticket)) {
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Could not create GeniTicket object");
$GeniTicket::CreateFromSignedError);
}
#
# Make sure the ticket was issued to the caller.
......@@ -1589,7 +1589,7 @@ sub ReleaseTicket($)
my $ticket = GeniTicket->CreateFromSignedTicket($ticketstr);
if (!defined($ticket)) {
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Could not create GeniTicket object");
$GeniTicket::CreateFromSignedError);
}
#
# If the ticket is not stored, it is not a ticket that needs
......@@ -2006,7 +2006,7 @@ sub CheckCredentials($)
my $credential = GeniCredential->CreateFromSigned($credentials[0]);
if (!defined($credential)) {
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Could not create credential object");
$GeniCredential::CreateFromSignedError);
}
#
# Well formed credentials must now have URNs.
......@@ -2033,7 +2033,7 @@ sub CheckCredential($)
my $credential = GeniCredential->CreateFromSigned($_[0]);
if (!defined($credential)) {
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Could not create credential object");
$GeniCredential::CreateFromSignedError);
}
#
# Well formed credentials must now have URNs.
......
......@@ -33,7 +33,8 @@ use Time::Local;
use overload ('""' => 'Stringify');
# Exported variables
use vars qw(@EXPORT_OK $LOCALSA_FLAG $LOCALCM_FLAG $LOCALMA_FLAG $CHECK_UUID);
use vars qw(@EXPORT_OK $LOCALSA_FLAG $LOCALCM_FLAG $LOCALMA_FLAG $CHECK_UUID
$CreateFromSignedError);
# Configure variables
my $TB = "@prefix@";
......@@ -354,9 +355,17 @@ my $find = sub
#
# Create a credential object from a signed credential string.
#
# We keep the error in a global variable for the caller if wanted.
# Certainly not ideal but I do not want to complicate things by
# using eval/die to mimic try/finally. We are not thread safe and
# never will be, so lets not get crazy.
#
$CreateFromSignedError = undef;
sub CreateFromSigned($$;$)
{
my ($class, $string, $nosig) = @_;
my $msg = undef;
#
# This flag is used to avoid verifying the signature since I do not
......@@ -369,14 +378,16 @@ sub CreateFromSigned($$;$)
# First verify the credential
if (! $nosig) {
my ($fh, $filename) = tempfile(UNLINK => 0);
return undef
if (!defined($fh));
if (!defined($fh)) {
$msg = "Error creating temporary file";
goto bad;
}
print $fh $string;
close($fh);
system("$VERIFYCRED $filename");
my $output = GeniUtil::ExecQuiet("$VERIFYCRED $filename");
if ($?) {
print STDERR "Credential in $filename did not verify\n";
return undef;
$msg = $output;
goto bad;
}
unlink($filename);
}
......@@ -388,12 +399,12 @@ sub CreateFromSigned($$;$)
$doc = $parser->parse_string($string);
};
if ($@) {
print STDERR "Failed to parse credential string: $@\n";
return undef;
$msg = "Failed to parse credential string: $@";
goto bad;
}
my $root = $doc->documentElement();
my $credential_el = &$find( $root, "credential" );
return undef unless defined( $credential_el );
goto bad unless defined( $credential_el );
# Dig out the entire credential structure to save it.
my ($credential) = $doc->getElementsByTagName("credential");
......@@ -408,7 +419,7 @@ sub CreateFromSigned($$;$)
# UUID of the credential.
my $uuid_node = &$find( $credential_el, "uuid" );
return undef
goto bad
if (!defined($uuid_node));
my $this_uuid = $uuid_node->to_literal();
$this_uuid = undef
......@@ -420,77 +431,77 @@ sub CreateFromSigned($$;$)
#
if (defined($this_uuid) &&
! ($this_uuid =~ /^\w+\-\w+\-\w+\-\w+\-\w+$/)) {
print STDERR "Invalid this_uuid in credential\n";
return undef;
$msg = "Invalid this_uuid in credential";
goto bad;
}
# Expiration
my $expires_node = &$find( $credential_el, "expires" );
if (!defined($expires_node)) {
print STDERR "Credential is missing expires node\n";
return undef;
$msg = "Credential is missing expires node";
goto bad;
}
my $expires = $expires_node->to_literal();
if (! ($expires =~ /^[-\w:.\/]+/)) {
print STDERR "Invalid expires date in credential\n";
return undef;
$msg = "Invalid expires date in credential";
goto bad;
}
# Convert to a localtime.
my $when = timegm(strptime($expires));
if (!defined($when)) {
print STDERR "Could not parse expires: '$expires'\n";
return undef;
$msg = "Could not parse expires: '$expires'";
goto bad;
}
$expires = POSIX::strftime("20%y-%m-%dT%H:%M:%S", localtime($when));
# Dig out the target certificate.
my $cert_node = &$find( $credential_el, "target_gid" );
return undef
goto bad
if (!defined($cert_node));
my $target_certificate =
GeniCertificate->LoadFromString($cert_node->to_literal());
return undef
goto bad
if (!defined($target_certificate));
if (!($target_certificate->uuid() =~ /^\w+\-\w+\-\w+\-\w+\-\w+$/)
&& $CHECK_UUID) {
print STDERR "Invalid target_uuid in credential\n";
return undef;
$msg = "Invalid target_uuid in credential";
goto bad;
}
if (!($target_certificate->hrn() =~ /^[-\w\.]+$/)) {
my $hrn = $target_certificate->hrn();
print STDERR "Invalid hrn $hrn in target of credential\n";
return undef;
$msg = "Invalid hrn $hrn in target of credential";
goto bad;
}
if (!GeniHRN::IsValid($target_certificate->urn())) {
print STDERR "Invalid urn in target certificate of credential\n";
return undef;
$msg = "Invalid urn in target certificate of credential";
goto bad;
}
# Dig out the owner certificate.
$cert_node = &$find( $credential_el, "owner_gid" );
return undef
goto bad
if (!defined($cert_node));
my $owner_certificate =
GeniCertificate->LoadFromString($cert_node->to_literal());
return undef
goto bad
if (!defined($owner_certificate));
if (!($owner_certificate->uuid() =~ /^\w+\-\w+\-\w+\-\w+\-\w+$/)
&& $CHECK_UUID) {
print STDERR "Invalid target_uuid in credential\n";
return undef;
$msg = "Invalid target_uuid in credential";
goto bad;
}
if (!($owner_certificate->hrn() =~ /^[-\w\.]+$/)) {
my $hrn = $owner_certificate->hrn();
print STDERR "Invalid hrn $hrn in owner of credential\n";
return undef;
$msg = "Invalid hrn $hrn in owner of credential";
goto bad;
}
if (!GeniHRN::IsValid($owner_certificate->urn())) {
print STDERR "Invalid urn in owner certificate of credential\n";
return undef;
$msg = "Invalid urn in owner certificate of credential";
goto bad;
}
# extract the signer certs
......@@ -529,8 +540,15 @@ sub CreateFromSigned($$;$)
$delegate->textContent());
}
}
return $self;
bad:
if (!defined($msg)) {
$msg = "Internal error creating credential object";
}
print STDERR "$msg\n";
$CreateFromSignedError = $msg;
return undef;
}
# Returns a NodeList for a given XPath using a given node as
......
#!/usr/bin/perl -wT
#
# GENIPUBLIC-COPYRIGHT
# Copyright (c) 2008-2011 University of Utah and the Flux Group.
# Copyright (c) 2008-2012 University of Utah and the Flux Group.
# All rights reserved.
#
package GeniEmulab;
......@@ -741,7 +741,7 @@ sub CheckCredentials($)
my $credential = GeniCredential->CreateFromSigned($credentials[0]);
if (!defined($credential)) {
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Could not create credential object");
$GeniCredential::CreateFromSignedError);
}
#
# Well formed credentials must now have URNs.
......
......@@ -35,9 +35,9 @@ my $FOAMURL = "http://10.4.1.69:69/something";
#
# AddSliverData
#
sub AddSliverData($$@)
sub AddSliverData($$$)
{
my ($slice, $user, @portlist) = @_;
my ($slice, $user, $portlist) = @_;
my $aggregate = GeniAggregate->SliceAggregate($slice);
return -1
if (!defined($aggregate));
......@@ -46,6 +46,7 @@ sub AddSliverData($$@)
"slice_urn" => $slice->urn(),
"user_urn" => $user->urn(),
"sliver_urn" => $aggregate->urn(),
"portlist" => $portlist,
"exp_date" => POSIX::strftime("20%y-%m-%dT%H:%M:%SZ",
gmtime(str2time($slice->expires())));
};
......@@ -135,3 +136,166 @@ sub DeleteSliverData($)
return 0;
}
#
# These are the functions called from the aggregate code to
# do the actual work.
#
sub FoamFindOpenFlowLans($$)
{
my ($aggregate, $pref) = @_;
my $experiment = Experiment->Lookup($aggregate->slice_uuid());
if (!defined($experiment)) {
print STDERR "FoamAddSliverData: No experiment for $aggregate\n";
return -1;
}
#
# These are all of the lans with a port in another vlan.
#
my @portlans = ();
if ($experiment->PortLanList(\@portlans)) {
print STDERR "FoamAddSliverData: Failed to get port lan list\n";
return -1;
}
#
# Go through the list of portlans and find the openflow ones.
#
my @openflow_lans = ();
foreach my $lan (@lans) {
my $target_lanid;
if ($lan->GetAttribute("target_lanid", \$target_lanid)) {
print STDERR
"FoamAddSliverData: Failed to lookup target lanid for $lan\n";
return -1;
}
my $portvlan = Lan->Lookup($target_lanid);
if (!defined($portvlan)) {
print STDERR
"FoamAddSliverData: Failed to lookup portvlan $target_lanid\n";
return -1;
}
# XXX Ick.
if ($portvlan->vname() ~= /^openflow/) {
push(@openflow_lans, [$lan, $portvlan->GetTag());
}
}
@$pref = @openflow_lans;
return 0;
}
sub FoamAddSliverData($)
{
my ($aggregate) = @_;
my $slice = $aggregate->GetSlice();
if (!defined($slice)) {
print STDERR "FoamAddSliverData: No slice for $aggregate\n";
return -1;
}
my $user = $aggregate->GetCreator();
if (!defined($user)) {
print STDERR "FoamAddSliverData: No creator for $aggregate\n";
return -1;
}
my @openflow_lans;
if (FoamFindOpenFlowLans(\@openflow_lans)) {
return -1;
}
return 0
if (!@openflow_lans);
#
# Notify FOAM. The portlist is in the form [[vlan, port], ...]
# where vlan is typical always the same cause we have just a single
# static vlan. Port is in A1-A24 format, which is easy to generate
# from the module.port we store in the wires table.
#
my @portlist = ();
foreach my $lan (@openflow_lans) {
my $target_lanid;
if ($lan->GetAttribute("target_lanid", \$target_lanid)) {
print STDERR
"FoamAddSliverData: Failed to lookup target lanid for $lan\n";
return -1;
}
my @members;
if ($lan->MemberList(\@members) != 0) {
print STDERR
"FoamAddSliverData: Could not get member list for $lan\n";
return -1;
}
foreach my $member (@members) {
my $interface = $member->GetInterface();
if (!defined($interface)) {
print STDERR "FoamAddSliverData: ".
"Could not get interface for $member in $lan\n";
return -1;
}
if (!$interface->wiredup()) {
print STDERR "FoamAddSliverData: ".
"No wire info for $interface ($member) in $lan\n";
return -1;
}
my $card = $interface->card2();
my $port = $interface->port2();
my $foamy = char($card + 64) . $port;
push(@portlist, [$target_lanid, $foamy]);
}
#
# Make the call.
#
if (FoamAddSliverData($slice, $user, \@portlist)) {
print STDERR "FoamAddSliverData: FOAMy is unhappy\n";
return -1;
}
}
return 0;
}
sub FoamRenewSliverData($)
{
my ($aggregate) = @_;
my $slice = $aggregate->GetSlice();
if (!defined($slice)) {
print STDERR "FoamRenewSliverData: No slice for $aggregate\n";
return -1;
}
my @openflow_lans;
if (FoamFindOpenFlowLans(\@openflow_lans)) {
return -1;
}
return 0
if (!@openflow_lans);
return -1
if (RenewSliverData($slice));
return 0;
}
sub FoamDeleteSliverData($)
{
my ($aggregate) = @_;
my $slice = $aggregate->GetSlice();
if (!defined($slice)) {
print STDERR "FoamDeleteSliverData: No slice for $aggregate\n";
return -1;
}
my @openflow_lans;
if (FoamFindOpenFlowLans(\@openflow_lans)) {
return -1;
}
return 0
if (!@openflow_lans);
return -1
if (DeleteSliverData($slice));
return 0;
}
......@@ -130,7 +130,7 @@ sub GetCredential($;$$)
}
$credential = GeniCredential->CreateFromSigned($response->value(), 1);
if (!defined($credential)) {
print STDERR "Could not parse credential from $authority\n";
print STDERR $GeniCredential::CreateFromSignedError . "\n";
return undef;
}
$credential->Store();
......@@ -573,7 +573,7 @@ sub GetCredential($;$$)
$clearinghousecred =
GeniCredential->CreateFromSigned($response->value(), 1);
if (!defined($clearinghousecred)) {
print STDERR "Could not parse credential from clearinghouse\n";
print STDERR $GeniCredential::CreateFromSignedError . "\n";
return undef;
}
if ($clearinghousecred->Store()) {
......
#!/usr/bin/perl -wT
#
# GENIPUBLIC-COPYRIGHT
# Copyright (c) 2008-2011 University of Utah and the Flux Group.
# Copyright (c) 2008-2012 University of Utah and the Flux Group.
# All rights reserved.
#
package GeniResource;
......@@ -762,7 +762,8 @@ sub GetTicket($$$$)
}
my $newticket = GeniTicket->CreateFromSignedTicket($response->value());
if (!defined($newticket)) {
print STDERR "*** Cannot create new ticket object from:\n";
print STDERR "*** Cannot create new ticket object:\n";
print STDERR "*** " . $GeniTicket::CreateFromSignedError . "\n";
print STDERR $response->value() . "\n";
return -1;
}
......@@ -983,6 +984,7 @@ sub RedeemTicket($$)
if (!defined($sliver_credential)) {
print STDERR
"** Could not create new credential from $credstring\n";
print STDERR "*** " . $GeniCredential::CreateFromSignedError . "\n";
return -1;
}
if ($sliver_credential->Store()) {
......@@ -1188,6 +1190,7 @@ sub CreateSliver($$$$)
if (!defined($sliver_credential)) {
print STDERR
"** Could not create new credential from $credstring\n";
print STDERR "*** " . $GeniCredential::CreateFromSignedError . "\n";
return -1;
}
if ($sliver_credential->Store()) {
......
......@@ -1208,8 +1208,9 @@ sub CheckCredential($;$)
my $credential = GeniCredential->CreateFromSigned($credstring);
if (!defined($credential)) {
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Could not create credential object");
$GeniCredential::CreateFromSignedError);
}
#
# Well formed credentials must now have URNs.
#
......
#!/usr/bin/perl -wT
#
# GENIPUBLIC-COPYRIGHT
# Copyright (c) 2008-2011 University of Utah and the Flux Group.
# Copyright (c) 2008-2012 University of Utah and the Flux Group.
# All rights reserved.
#
package GeniSES;
......@@ -75,7 +75,7 @@ sub Map($)
$credential = GeniCredential->CreateFromSigned($credential);
if (!defined($credential)) {
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Could not create GeniCredential object");
$GeniCredential::CreateFromSignedError);
}
# The credential owner/slice has to match what was provided.
if ($user_uuid ne $credential->owner_uuid()) {
......
......@@ -11,7 +11,7 @@ package GeniTicket;
#
use strict;
use Exporter;
use vars qw(@ISA @EXPORT);
use vars qw(@ISA @EXPORT $CreateFromSignedError);
@ISA = "Exporter";
@EXPORT = qw (TICKET_PURGED TICKET_EXPIRED TICKET_REDEEMED
......@@ -251,9 +251,17 @@ sub Flush($)
#
# Create a ticket object from a signed ticket string.
#
# We keep the error in a global variable for the caller if wanted.
# Certainly not ideal but I do not want to complicate things by
# using eval/die to mimic try/finally. We are not thread safe and
# never will be, so lets not get crazy.
#
$CreateFromSignedError = undef;
sub CreateFromSignedTicket($$;$)
{
my ($class, $ticket_string, $nosig) = @_;
my $msg = undef;
#
# This flag is used to avoid verifying the signature since I do not
......@@ -265,14 +273,16 @@ sub CreateFromSignedTicket($$;$)
if (! $nosig) {
my ($fh, $filename) = tempfile(UNLINK => 0);
return undef
if (!defined($fh));
if (!defined($fh)) {
$msg = "Error creating temporary file";
goto bad;
}
print $fh $ticket_string;
close($fh);
system("$VERIFYCRED $filename");
my $output = GeniUtil::ExecQuiet("$VERIFYCRED $filename");
if ($?) {
print STDERR "Ticket in $filename did not verify\n";
return undef;
$msg = $output;
goto bad;
}
unlink($filename);
}
......@@ -284,106 +294,106 @@ sub CreateFromSignedTicket($$;$)
$doc = $parser->parse_string($ticket_string);
};
if ($@) {
print STDERR "Failed to parse ticket string: $@\n";
return undef;
$msg = "Failed to parse ticket string: $@";
goto bad;
}
# Dig out the rspec.
my $rspec = GeniXML::FindFirst("//*[local-name()='rspec']",
$doc->documentElement());
if (!defined($rspec)) {
print STDERR "Ticket is missing rspec node\n";
return undef;
$msg = "Ticket is missing rspec node";
goto bad;
}
# Dig out the ticket uuid.
my ($uuid_node) = $doc->getElementsByTagName("uuid");
if (!defined($uuid_node)) {
print STDERR "Ticket is missing uuid node\n";
return undef;
$msg = "Ticket is missing uuid node";
goto bad;
}
my $ticket_uuid = $uuid_node->to_literal();
if (! ($ticket_uuid =~ /^\w+\-\w+\-\w+\-\w+\-\w+$/)) {
print STDERR "Invalid uuid in ticket\n";
return undef;
$msg = "Invalid uuid in ticket";
goto bad;
}
# Dig out the target certificate.
my ($cert_node) = $doc->getElementsByTagName("target_gid");
if (!defined($cert_node)) {
print STDERR "Ticket is missing target gid node\n";
return undef;
$msg = "Ticket is missing target gid node";
goto bad;
}
my $target_certificate =
GeniCertificate->LoadFromString($cert_node->to_literal());
if (!defined($target_certificate)) {
print STDERR "Could not get target certificate from string\n";
return undef;
$msg = "Could not get target certificate from string";
goto bad;
}
if (!($target_certificate->uuid() =~ /^\w+\-\w+\-\w+\-\w+\-\w+$/)) {
print STDERR "Invalid target_uuid in credential\n";
return undef;
$msg = "Invalid target_uuid in credential";
goto bad;
}
if (!($target_certificate->hrn() =~ /^[-\w\.]+$/)) {
my $hrn = $target_certificate->hrn();
print STDERR "Invalid hrn $hrn in target of ticket\n";
return undef;
$msg = "Invalid hrn $hrn in target of ticket";
goto bad;
}
# Dig out the owner certificate.
($cert_node) = $doc->getElementsByTagName("owner_gid");
if (!defined($cert_node)) {
print STDERR "Ticket is missing owner gid node\n";
return undef;
$msg = "Ticket is missing owner gid node";
goto bad;
}
my $owner_certificate =
GeniCertificate->LoadFromString($cert_node->to_literal());
if (!defined($target_certificate)) {
print STDERR "Could not get owner certificate from string\n";
return undef;
$msg = "Could not get owner certificate from string";
goto bad;
}
if (!($owner_certificate->uuid() =~ /^\w+\-\w+\-\w+\-\w+\-\w+$/)) {
print STDERR "Invalid target_uuid in credential\n";
return undef;
$msg = "Invalid target_uuid in credential";
goto bad;
}
if (!($owner_certificate->hrn() =~ /^[-\w\.]+$/)) {
my $hrn = $owner_certificate->hrn();
print STDERR "Invalid hrn $hrn in owner of ticket\n";
return undef;
$msg = "Invalid hrn $hrn in owner of ticket";
goto bad;
}
# Sequence number
my ($seqno_node) = $doc->getElementsByTagName("serial");
if (!defined($seqno_node)) {
print STDERR "Ticket is missing seqno node\n";
return undef;
$msg = "Ticket is missing seqno node";
goto bad;
}
my $seqno = $seqno_node->to_literal();
if (! ($seqno =~ /^\w+$/)) {
print STDERR "Invalid sequence number in ticket\n";
return undef;
$msg = "Invalid sequence number in ticket";
goto bad;
}