diff --git a/apt/APT_Geni.pm.in b/apt/APT_Geni.pm.in
index 4f96632b199d3c3d79a655b59b9b611d11b5a4d7..992248ff43142183af7bfa8fd03122de84472965 100644
--- a/apt/APT_Geni.pm.in
+++ b/apt/APT_Geni.pm.in
@@ -56,10 +56,10 @@ my $USEABACCREDS  = 0;
 #
 # Generate the credentials we need. 
 #
-sub GenCredentials($$;$)
+sub GenCredentials($$;$$)
 {
-    my ($target, $geniuser, $privs) = @_;
-    my ($speaksfor, $credential);
+    my ($target, $geniuser, $privs, $allowexpiredspeaksfor) = @_;
+    my ($speaksfor, $credential, $oldexpires);
     # If the caller does not want a speaksfor, do not generate.
     my $wantspeaksfor = wantarray;
 
@@ -72,11 +72,21 @@ sub GenCredentials($$;$)
     if (!$geniuser->IsLocal() && $MAINSITE) {
 	$speaker_signer = "/usr/testbed/etc/utah-apt.sa";
     }
-
+    my $cachetag = $target->urn() . "::" . $geniuser->urn();
+    
+    #
+    # If the target is a slice, and expired, change the expiration so
+    # that the credential we generate is not also expired (and invalid).
+    #
+    if (ref($target) eq "GeniSlice" && $target->IsExpired()) {
+	$oldexpires = $target->expires();
+	$target->SetExpiration(time() + 600);
+	delete($credcache{$cachetag})
+	    if (exists($credcache{$cachetag}));
+    }
     #
     # Check cache.
     #
-    my $cachetag = $target->urn() . "::" . $geniuser->urn();
     if (exists($credcache{$cachetag})) {
 	($credential,$speaksfor) = @{ $credcache{$cachetag} };
 	goto cached;
@@ -102,6 +112,25 @@ sub GenCredentials($$;$)
 		goto bad;
 	    }
 	}
+	#
+	# Ick, if the speaks for credential has expired, we cannot
+	# operate as the user. We have no choice but to throw away
+	# these credentials and generate a new one issued to the local
+	# SA instead of the user and not bother with a speaksfor.
+	#
+	if ($speaksfor->IsExpired()) {
+	    print STDERR "speaksfor credential for $geniuser has expired\n";
+	    goto bad
+		if (!$allowexpiredspeaksfor);
+	    
+	    print STDERR "-> Generating an SA credential instead\n";
+	    $credential = APT_Geni::GenAuthCredential($target, $privs);
+	    if (!defined($credential)) {
+		print STDERR "-> Could not generate SA credential!\n";
+		goto bad;
+	    }
+	    goto cached;
+	}
 	my $certificate =
 	    GeniCertificate->LoadFromString($certificate_string);
 	if (!defined($certificate)) {
@@ -167,11 +196,15 @@ sub GenCredentials($$;$)
 	$credcache{$cachetag} = [$credential, $speaksfor];
     }
   cached:
+    $target->SetExpiration($oldexpires)
+	if (defined($oldexpires));
     if (wantarray) {
 	return ($credential, $speaksfor);
     }
     return $credential;
   bad:
+    $target->SetExpiration($oldexpires)
+	if (defined($oldexpires));
     return ();
 }
 
@@ -212,16 +245,25 @@ sub GeniContext()
 sub GenAuthCredential($;$)
 {
     my ($target, $privs) = @_;
+    my $oldexpires;
 
     my $owner = GeniCertificate->LoadFromFile($SACERT);
     if (!defined($owner)) {
 	print STDERR "Could not load certificate from $SACERT\n";
 	return undef;
     }
+    #
+    # If the target is a slice, and expired, change the expiration so
+    # that the credential we generate is not also expired (and invalid).
+    #
+    if (ref($target) eq "GeniSlice" && $target->IsExpired()) {
+	$oldexpires = $target->expires();
+	$target->SetExpiration(time() + 600);
+    }
     my $credential = GeniCredential->Create($target, $owner);
     if (!defined($credential)) {
 	print STDERR "Could not create credential for $target\n";
-	return undef;
+	goto bad;
     }
     # Add optional privs.
     if (defined($privs)) {
@@ -233,9 +275,15 @@ sub GenAuthCredential($;$)
     if ($credential->Sign($GeniCredential::LOCALSA_FLAG) != 0) {
 	$credential->Delete();
 	print STDERR "Could not sign $target credential\n";
-	return undef
+	goto bad;
     }
+    $target->SetExpiration($oldexpires)
+	if (defined($oldexpires));
     return $credential;
+  bad:
+    $target->SetExpiration($oldexpires)
+	if (defined($oldexpires));
+    return undef;
 }
 
 #
diff --git a/apt/APT_Instance.pm.in b/apt/APT_Instance.pm.in
index 197f365a761548a4bdbca2af88ba84facdc2a833..4dfa7ded1943cfc46f8964e6c54dd2cbba7a5c82 100644
--- a/apt/APT_Instance.pm.in
+++ b/apt/APT_Instance.pm.in
@@ -57,6 +57,7 @@ use Genixmlrpc;
 use GeniResponse;
 use GeniCertificate;
 use GeniCredential;
+use GeniUser;
 use GeniHRN;
 use GeniXML;
 use WebTask;
@@ -67,6 +68,7 @@ use overload ('""' => 'Stringify');
 my $TB		  = "@prefix@";
 my $TBOPS         = "@TBOPSEMAIL@";
 my $GENEXTENDCRED = "$TB/sbin/protogeni/genextendcred";
+my $GENIUSER      = "geniuser";
 
 # Cache of instances to avoid regenerating them.
 my %instances  = ();
@@ -80,7 +82,7 @@ sub devurl($)
 
     if ($usemydevtree) {
 	$cmurl =~ s/protogeni/protogeni\/stoller/;
-	$cmurl =~ s/12369/12396/;
+#	$cmurl =~ s/12369/12396/;
     }
     return $cmurl;
 }
@@ -1333,18 +1335,11 @@ sub Terminate($)
     my $geniuser  = $self->instance()->GetGeniUser();
     my $slice     = $self->instance()->GetGeniSlice();
     my $context   = APT_Geni::GeniContext();
+
     return undef
 	if (! (defined($geniuser) && defined($authority) &&
 	       defined($slice) && defined($context)));
 
-    #
-    # If the slice is expired, it is most likely gone at the cluster,
-    # but we want to make sure, so change the expiration so that the
-    # credential we generate is not also expired. 
-    #
-    if ($slice->IsExpired()) {
-	$slice->SetExpiration(time() + 3600);
-    }
     # We might change this below.
     my $cmurl = $authority->url();
 
@@ -1360,30 +1355,13 @@ sub Terminate($)
     else {
 	my $credentials;
 	my ($slice_credential, $speaksfor_credential) =
-	    APT_Geni::GenCredentials($slice, $geniuser);
+	    APT_Geni::GenCredentials($slice, $geniuser, undef, 1);
 	return undef
-	    if (! (defined($speaksfor_credential) &&
-		   defined($slice_credential)));
-	#
-	# Special case; if the speaksfor_credential has expired cause it
-	# was for a nonlocal user, we have no choice but to throw away
-	# these credentials and generate a new one issued to the local SA
-	# instead of the user. 
-	#
-	if ($speaksfor_credential->IsExpired()) {
-	    print STDERR
-		"speaksfor credential has expired, generating a new one\n";
+	    if (!defined($slice_credential));
 
-	    $slice_credential = APT_Geni::GenAuthCredential($slice);
-	    if (!defined($slice_credential)) {
-		print STDERR "Could not generate slice credential\n";
-		return undef;
-	    }
-	    $credentials = [$slice_credential->asString()];
-	}
-	else {
-	    $credentials = [$slice_credential->asString(),
-			    $speaksfor_credential->asString()];
+	$credentials = [$slice_credential->asString()];
+	if (defined($speaksfor_credential)) {
+	    $credentials = [@$credentials, $speaksfor_credential->asString()];
 	}
 	$method = "DeleteSliver";
 	@params = ($slice->urn(), $credentials,
@@ -1464,31 +1442,15 @@ sub Extend($$)
     }
     else {
 	my ($slice_credential, $speaksfor_credential) =
-	    APT_Geni::GenCredentials($slice, $geniuser);
+	    APT_Geni::GenCredentials($slice, $geniuser, undef, 1);
 	return undef
-	    if (! (defined($speaksfor_credential) &&
-		   defined($slice_credential)));
-	
-	#
-	# Special case; if the speaksfor_credential has expired cause it
-	# was for a nonlocal user, we have no choice but to throw away
-	# these credentials and generate a new one issued to the local SA
-	# instead of the user. 
-	#
-	if ($speaksfor_credential->IsExpired()) {
-	    print STDERR "speaksfor credential expired, generating a new one\n";
+	    if (!defined($slice_credential));
 
-	    $slice_credential = APT_Geni::GenAuthCredential($slice);
-	    if (!defined($slice_credential)) {
-		print STDERR "Could not generate slice credential\n";
-		return undef;
-	    }
-	    $credentials = [$slice_credential->asString()];
-	}
-	else {
-	    $credentials = [$slice_credential->asString(),
-			    $speaksfor_credential->asString()];
+	$credentials = [$slice_credential->asString()];
+	if (defined($speaksfor_credential)) {
+	    $credentials = [@$credentials, $speaksfor_credential->asString()];
 	}
+	
 	#
 	# We need a special credentential in case the aggregate is enforcing
 	# limits (as do Utah aggregates).
@@ -1502,10 +1464,11 @@ sub Extend($$)
 	# But if a nonlocal user from Geni, then the user we have in
 	# the database is not in the same domain as the speaksfor, so
 	# we use the geni certificate that the trusted signer gave us
-	# and is stored in the DB.
-	#
+	# and is stored in the DB. Note that of the speaksfor was
+	# expired, it will not be defined (see above).
+	# 
 	if ($geniuser->IsLocal() && $geniuser->emulab_user()->IsNonLocal() &&
-	    !$speaksfor_credential->IsExpired()) {	
+	    defined($speaksfor_credential)) {
 	    my (undef, $certificate_string) =
 		$geniuser->emulab_user()->GetStoredCredential();
 	    if (! defined($certificate_string)) {
@@ -1583,28 +1546,25 @@ sub SliceStatus($)
     my $geniuser  = $self->instance()->GetGeniUser();
     my $slice     = $self->instance()->GetGeniSlice();
     my $context   = APT_Geni::GeniContext();
+    
     return undef
 	if (! (defined($geniuser) && defined($authority) &&
 	       defined($slice) && defined($context)));
 
+    #
+    # Use an SA credential here so that we can always get status.
+    #
+    my $slice_credential = APT_Geni::GenAuthCredential($slice);
+    if (!defined($slice_credential)) {
+	print STDERR "Could not generate slice credential\n";
+	return undef;
+    }
     if ($self->isAL2S()) {
-	my $slice_credential = APT_Geni::GenAuthCredential($slice);
-	if (!defined($slice_credential)) {
-	    print STDERR "Could not generate slice credential\n";
-	    return undef;
-	}
 	@params = ($slice->urn(), [$slice_credential->asString()], {});
     }
     else {
-	my ($slice_credential, $speaksfor_credential) =
-	    APT_Geni::GenCredentials($slice, $geniuser);
-	return undef
-	    if (! (defined($speaksfor_credential) &&
-		   defined($slice_credential)));
-
 	@params = ({"slice_urn"   => $slice->urn(),
-		    "credentials" => [$slice_credential->asString(),
-				      $speaksfor_credential->asString()],
+		    "credentials" => [$slice_credential->asString()],
 		   });
     }
     my $cmurl = $authority->url();
@@ -1639,8 +1599,8 @@ sub GetManifest($)
     my $method;
     my @params;
     my $authority = $self->GetGeniAuthority();
-    my $urn       = $self->aggregate_urn();
     my $geniuser  = $self->instance()->GetGeniUser();
+    my $urn       = $self->aggregate_urn();
     my $slice     = $self->instance()->GetGeniSlice();
     my $context   = APT_Geni::GeniContext();
     return undef
@@ -1664,16 +1624,20 @@ sub GetManifest($)
 		   });
     }
     else {
+	my $credentials;
+
 	my ($slice_credential, $speaksfor_credential) =
-	    APT_Geni::GenCredentials($slice, $geniuser);
+	    APT_Geni::GenCredentials($slice, $geniuser, undef, 1);
 	return undef
-	    if (! (defined($speaksfor_credential) &&
-		   defined($slice_credential)));
+	    if (!defined($slice_credential));
 
+	$credentials = [$slice_credential->asString()];
+	if (defined($speaksfor_credential)) {
+	    $credentials = [@$credentials, $speaksfor_credential->asString()];
+	}
 	$method = "Resolve";
 	@params = ({"urn"   => $slice->urn(),
-		    "credentials" => [$slice_credential->asString(),
-				      $speaksfor_credential->asString()]});
+		    "credentials" => $credentials});
     }
     my $cmurl = $authority->url();
     $cmurl = devurl($cmurl) if ($usemydevtree);
@@ -1721,7 +1685,7 @@ sub Provision($$$$)
 	       defined($slice) && defined($context)));
 
     my ($slice_credential, $speaksfor_credential) =
-	APT_Geni::GenCredentials($slice, $geniuser);
+	APT_Geni::GenCredentials($slice, $geniuser, undef, 0);
     return -1
 	if (! (defined($speaksfor_credential) &&
 	       defined($slice_credential)));
@@ -1786,24 +1750,26 @@ sub ConsoleInfo($$)
 {
     my ($self, $sliver_urn) = @_;
     my $authority = $self->GetGeniAuthority();
-    my $geniuser  = $self->instance()->GetGeniUser();
     my $slice     = $self->instance()->GetGeniSlice();
     my $context   = APT_Geni::GeniContext();
+    my $geniuser  = $self->instance()->GetGeniUser();
     return undef
 	if (! (defined($geniuser) && defined($authority) &&
 	       defined($slice) && defined($context)));
 
     my ($slice_credential, $speaksfor_credential) =
-	APT_Geni::GenCredentials($slice, $geniuser);
+	APT_Geni::GenCredentials($slice, $geniuser, undef, 1);
     return undef
-	if (! (defined($speaksfor_credential) &&
-	       defined($slice_credential)));
+	if (! defined($slice_credential));
 
+    my $credentials = [$slice_credential->asString()];
+    if (defined($speaksfor_credential)) {
+	$credentials = [@$credentials, $speaksfor_credential->asString()];
+    }
     my $args = {
 	"slice_urn"   => $slice->urn(),
 	"sliver_urn"  => $sliver_urn,
-	"credentials" => [$slice_credential->asString(),
-			  $speaksfor_credential->asString()],
+	"credentials" => $credentials,
     };
     my $cmurl = $authority->url();
     $cmurl = devurl($cmurl) if ($usemydevtree);
@@ -1826,16 +1792,18 @@ sub ConsoleURL($$)
 	       defined($slice) && defined($context)));
 
     my ($slice_credential, $speaksfor_credential) =
-	APT_Geni::GenCredentials($slice, $geniuser);
+	APT_Geni::GenCredentials($slice, $geniuser, undef, 1);
     return undef
-	if (! (defined($speaksfor_credential) &&
-	       defined($slice_credential)));
+	if (!defined($slice_credential));
 
+    my $credentials = [$slice_credential->asString()];
+    if (defined($speaksfor_credential)) {
+	$credentials = [@$credentials, $speaksfor_credential->asString()];
+    }
     my $args = {
 	"slice_urn"   => $slice->urn(),
 	"sliver_urn"  => $sliver_urn,
-	"credentials" => [$slice_credential->asString(),
-			  $speaksfor_credential->asString()],
+	"credentials" => $credentials,
     };
     my $cmurl = $authority->url();
     $cmurl = devurl($cmurl) if ($usemydevtree);
@@ -1851,15 +1819,19 @@ sub CreateImage($$$$;$$$)
     my ($self, $sliver_urn, $imagename, $update_prepare,
 	$copyback_uuid, $bsname) = @_;
     my $authority = $self->GetGeniAuthority();
-    my $geniuser  = $self->instance()->GetGeniUser();
+    my$geniuser   = $self->instance()->GetGeniUser();
     my $slice     = $self->instance()->GetGeniSlice();
     my $context   = APT_Geni::GeniContext();
     return undef
 	if (! (defined($geniuser) && defined($authority) &&
 	       defined($slice) && defined($context)));
 
+    #
+    # Only the creator is allowed to do this, so if the speaksfor is
+    # expired, a permission check went wrong.
+    #
     my ($slice_credential, $speaksfor_credential) =
-	APT_Geni::GenCredentials($slice, $geniuser);
+	APT_Geni::GenCredentials($slice, $geniuser, undef, 0);
     return undef
 	if (! (defined($speaksfor_credential) &&
 	       defined($slice_credential)));
@@ -1888,14 +1860,14 @@ sub CreateImage($$$$;$$$)
 #
 # Reboot some nodes
 #
-sub SliverAction($$$@)
+sub SliverAction($$$;@)
 {
     my ($self, $perrmsg, $which, @slivers) = @_;
     my $method    = ($which eq "reboot" ? "RestartSliver" :
 		     ($which eq "start" ? "StartSliver" : "ReloadSliver"));
     my $authority = $self->GetGeniAuthority();
-    my $urn       = $self->aggregate_urn();
     my $geniuser  = $self->instance()->GetGeniUser();
+    my $urn       = $self->aggregate_urn();
     my $slice     = $self->instance()->GetGeniSlice();
     my $context   = APT_Geni::GeniContext();
     return undef
@@ -1903,14 +1875,16 @@ sub SliverAction($$$@)
 	       defined($slice) && defined($context)));
 
     my ($slice_credential, $speaksfor_credential) =
-	APT_Geni::GenCredentials($slice, $geniuser);
+	APT_Geni::GenCredentials($slice, $geniuser, undef, 1);
     return undef
-	if (! (defined($speaksfor_credential) &&
-	       defined($slice_credential)));
+	if (!defined($slice_credential));
 
+    my $credentials = [$slice_credential->asString()];
+    if (defined($speaksfor_credential)) {
+	$credentials = [@$credentials, $speaksfor_credential->asString()];
+    }
     my $args = {
-	"credentials" => [$slice_credential->asString(),
-			  $speaksfor_credential->asString()],
+	"credentials" => $credentials,
     };
     if (@slivers) {
 	$args->{"sliver_urns"} = \@slivers;
@@ -1960,15 +1934,6 @@ sub Lockdown($$)
 	if (! (defined($authority) &&
 	       defined($slice) && defined($context)));
 
-    #
-    # If the slice is expired, then the credential we generate will
-    # not be valid. So extend the slice so we can clear the lockdown.
-    #
-    if ($clear && $slice->IsExpired()) {
-	$oldexpires = $slice->expires();
-	$slice->SetExpiration(time() + 3600);
-    }
-
     my $slice_credential = APT_Geni::GenAuthCredential($slice);
     goto bad
 	if (! defined($slice_credential));
@@ -2001,22 +1966,12 @@ sub Panic($$)
     my $authority = $self->GetGeniAuthority();
     my $slice     = $self->instance()->GetGeniSlice();
     my $context   = APT_Geni::GeniContext();
-    my $oldexpires;
     return undef
 	if (! (defined($authority) &&
 	       defined($slice) && defined($context)));
 
-    #
-    # If the slice is expired, then the credential we generate will
-    # not be valid. So extend the slice so we can clear the panic.
-    #
-    if ($clear && $slice->IsExpired()) {
-	$oldexpires = $slice->expires();
-	$slice->SetExpiration(time() + 3600);
-    }
-
     my $slice_credential = APT_Geni::GenAuthCredential($slice);
-    goto bad
+    return undef
 	if (! defined($slice_credential));
 
     my $args = {
@@ -2029,13 +1984,7 @@ sub Panic($$)
     $cmurl = devurl($cmurl) if ($usemydevtree);
 
     my $response = Genixmlrpc::CallMethod($cmurl, $context, "Panic", $args);
-    $slice->SetExpiration($oldexpires)
-	if (defined($oldexpires));
     return $response;
-  bad:
-    $slice->SetExpiration($oldexpires)
-	if (defined($oldexpires));
-    return undef;
 }
 
 #
@@ -2045,8 +1994,8 @@ sub RunLinktest($$$)
 {
     my ($self, $action, $level) = @_;
     my $authority = $self->GetGeniAuthority();
-    my $urn       = $self->aggregate_urn();
     my $geniuser  = $self->instance()->GetGeniUser();
+    my $urn       = $self->aggregate_urn();
     my $slice     = $self->instance()->GetGeniSlice();
     my $context   = APT_Geni::GeniContext();
     return undef
@@ -2054,15 +2003,17 @@ sub RunLinktest($$$)
 	       defined($slice) && defined($context)));
 
     my ($slice_credential, $speaksfor_credential) =
-	APT_Geni::GenCredentials($slice, $geniuser);
+	APT_Geni::GenCredentials($slice, $geniuser, undef, 1);
     return undef
-	if (! (defined($speaksfor_credential) &&
-	       defined($slice_credential)));
-
+	if (!defined($slice_credential));
+    
+    my $credentials = [$slice_credential->asString()];
+    if (defined($speaksfor_credential)) {
+	$credentials = [@$credentials, $speaksfor_credential->asString()];
+    }
     my $args = {
 	"slice_urn"   => $slice->urn(),
-	"credentials" => [$slice_credential->asString(),
-			  $speaksfor_credential->asString()],
+	"credentials" => $credentials,
     };
     if ($action eq "stop") {
 	$args->{"action"} = "stop";
@@ -2100,15 +2051,17 @@ sub ImageInfo($$)
 	       defined($slice) && defined($context)));
 
     my ($slice_credential, $speaksfor_credential) =
-	APT_Geni::GenCredentials($slice, $geniuser);
+	APT_Geni::GenCredentials($slice, $geniuser, undef, 1);
     return undef
-	if (! (defined($speaksfor_credential) &&
-	       defined($slice_credential)));
+	if (!defined($slice_credential));
 
+    my $credentials = [$slice_credential->asString()];
+    if (defined($speaksfor_credential)) {
+	$credentials = [@$credentials, $speaksfor_credential->asString()];
+    }
     my $args = {
 	"image_urn"   => $image_urn,
-	"credentials" => [$slice_credential->asString(),
-			  $speaksfor_credential->asString()],
+	"credentials" => $credentials,
     };
     my $cmurl = $authority->url();
     $cmurl = devurl($cmurl) if ($usemydevtree);
@@ -2123,8 +2076,8 @@ sub UpdateKeys($$)
 {
     my ($self, $users) = @_;
     my $authority = $self->GetGeniAuthority();
-    my $urn       = $self->aggregate_urn();
     my $geniuser  = $self->instance()->GetGeniUser();
+    my $urn       = $self->aggregate_urn();
     my $slice     = $self->instance()->GetGeniSlice();
     my $context   = APT_Geni::GeniContext();
     return -1
@@ -2132,28 +2085,30 @@ sub UpdateKeys($$)
 	       defined($slice) && defined($context)));
 
     my ($slice_credential, $speaksfor_credential) =
-	APT_Geni::GenCredentials($slice, $geniuser);
+	APT_Geni::GenCredentials($slice, $geniuser, undef, 1);
     return -1
-	if (! (defined($speaksfor_credential) &&
-	       defined($slice_credential)));
+	if (!defined($slice_credential));
+
+    my $options = {"geni_users" => $users};
+    my $credentials = [{"geni_type" => "geni_sfa",
+			"geni_version" => 3,
+			"geni_value" => $slice_credential->asString()}];
+    if (defined($speaksfor_credential)) {
+	$credentials = [{"geni_type" => "geni_sfa",
+			 "geni_version" => 3,
+			 "geni_value" => $speaksfor_credential->asString()},
+			@$credentials];
+	$options->{"speaking_for"} = $geniuser->urn();
+	$options->{"geni_speaking_for"} = $geniuser->urn();
+    }
 
     #
     # AM V3 API.
     #
     my @params = ([$slice->urn()],
-		  [{"geni_type" => "geni_sfa",
-		    "geni_version" => 3,
-		    "geni_value" => $speaksfor_credential->asString()},
-		   {"geni_type" => "geni_sfa",
-		    "geni_version" => 3,
-		    "geni_value" => $slice_credential->asString()},
-		  ],
+		  $credentials,
 		  "geni_update_users",
-		  # Options array.
-		  {"speaking_for" => $geniuser->urn(),
-		   "geni_speaking_for" => $geniuser->urn(),
-		   "geni_users"       => $users,
-		  });
+		  $options);
  
     my $cmurl = $authority->url();
     # Convert URL.
diff --git a/apt/create_instance.in b/apt/create_instance.in
index c4b9370a949f871ea3961a6cc97a9ab372a2620f..33b6e08e4523ae6517609c7ceeaa76aa319b2009 100755
--- a/apt/create_instance.in
+++ b/apt/create_instance.in
@@ -682,7 +682,7 @@ if ($tmp) {
 # Generate credentials we need.
 #
 my ($slice_credential, $speaksfor_credential) =
-    APT_Geni::GenCredentials($slice, $geniuser);
+    APT_Geni::GenCredentials($slice, $geniuser, undef, 0);
 if (! (defined($speaksfor_credential) &&
        defined($slice_credential))) {
     fatal("Could not generate credentials");
diff --git a/apt/manage_dataset.in b/apt/manage_dataset.in
index 33445ff5bb0656819f52f95af0f789c6707e10b5..1a5afd946c68789af79bbf20db5bc69df690d4df 100644
--- a/apt/manage_dataset.in
+++ b/apt/manage_dataset.in
@@ -46,6 +46,8 @@ my $optlist     = "dt:";
 my $debug       = 0;
 my $webtask_id;
 my $webtask;
+my $this_user;
+my $geniuser;
 
 #
 # Configure variables
@@ -80,6 +82,7 @@ use WebTask;
 use Blockstore;
 use GeniResponse;
 use GeniXML;
+use GeniUser;
 
 # Protos
 sub fatal($);
@@ -117,16 +120,19 @@ if (defined($options{"t"})) {
 if (@ARGV < 1) {
     usage();
 }
+my $action = shift(@ARGV);
 
-# The web interface (and in the future the xmlrpc interface) sets this.
-my $this_user = User->ImpliedUser();
-if (! defined($this_user)) {
+if (getpwuid($UID) eq "nobody") {
+    $this_user = User->ImpliedUser();
+}
+else  {
     $this_user = User->ThisUser();
-    if (!defined($this_user)) {
-	fatal("You ($UID) do not exist!");
-    }
 }
-my $action = shift(@ARGV);
+# No guests allowed.
+if (! defined($this_user)) {
+    fatal("You ($UID) do not exist!");
+}
+$geniuser = GeniUser->CreateFromLocal($this_user);
 
 if ($action eq "create") {
     exit(DoCreate());
diff --git a/apt/manage_instance.in b/apt/manage_instance.in
index 1893b99a00b846c303d3bd06e3cb8aa9d87476ed..34e5d80adbfe8900cba0883ae9fe6e5cabb5c2fd 100644
--- a/apt/manage_instance.in
+++ b/apt/manage_instance.in
@@ -56,6 +56,8 @@ my $debug       = 0;
 my $silent      = 0;
 my $webtask_id;
 my $webtask;
+my $this_user;
+my $geniuser;
 
 #
 # Configure variables
@@ -101,6 +103,7 @@ use EmulabFeatures;
 
 # Protos
 sub fatal($);
+sub UserError($);
 sub DoSnapshot();
 sub DoConsole();
 sub DoTerminate();
@@ -147,6 +150,16 @@ if (!defined($instance)) {
 if (!defined($instance)) {
     fatal("No such instance $uuid");
 }
+if (getpwuid($UID) eq "nobody") {
+    $this_user = User->ImpliedUser();
+}
+else  {
+    $this_user = User->ThisUser();
+}
+# If a guest user, we will not have an actual user, which is okay.
+if (defined($this_user)) {
+    $geniuser = GeniUser->CreateFromLocal($this_user);
+}
 
 if ($action eq "snapshot") {
     DoSnapshot();
@@ -252,15 +265,6 @@ sub DoSnapshot()
 	fatal("No slice for quick VM: $uuid");
     }
     
-    # The web interface (and in the future the xmlrpc interface) sets this.
-    my $this_user = User->ImpliedUser();
-    if (! defined($this_user)) {
-	$this_user = User->ThisUser();
-	if (!defined($this_user)) {
-	    fatal("You ($UID) do not exist!");
-	}
-    }
-    
     #
     # Might be a clone (manage_profile).
     #
@@ -1183,11 +1187,6 @@ sub DoExtend()
     if (!defined($slice)) {
 	fatal("No slice for instance!");
     }
-    # The web interface (and in the future the xmlrpc interface) sets this.
-    my $this_user = User->ImpliedUser();
-    if (! defined($this_user)) {
-	$this_user = User->ThisUser();
-    }
 
     #
     # Lock the slice in case it is doing something else, like taking
@@ -1795,12 +1794,6 @@ sub DoLockdownInternal($$)
 {
     my ($setclr,$which) = @_;
 
-    # The web interface (and in the future the xmlrpc interface) sets this.
-    my $this_user = User->ImpliedUser();
-    if (! defined($this_user)) {
-	$this_user = User->ThisUser();
-    }
-    
     my $slice = $instance->GetGeniSlice();
     if (!defined($slice)) {
 	fatal("No slice for instance");
@@ -2021,11 +2014,6 @@ sub DoLinktest()
     if (!defined($slice)) {
 	fatal("No slice for instance!");
     }
-    # The web interface (and in the future the xmlrpc interface) sets this.
-    my $this_user = User->ImpliedUser();
-    if (! defined($this_user)) {
-	$this_user = User->ThisUser();
-    }
 
     #
     # Lock the slice in case it is doing something else, like taking
@@ -2232,11 +2220,6 @@ sub DoUpdateKeys()
     if (!defined($slice)) {
 	fatal("No slice for instance!");
     }
-    # The web interface (and in the future the xmlrpc interface) sets this.
-    my $this_user = User->ImpliedUser();
-    if (! defined($this_user)) {
-	$this_user = User->ThisUser();
-    }
 
     # This returns in CM format.
     my $sshkeys;
@@ -2369,6 +2352,19 @@ sub fatal($)
     exit(-1);
 }
 
+sub UserError($)
+{
+    my ($mesg) = @_;
+
+    if (defined($webtask)) {
+	$webtask->output($mesg);
+	$webtask->code(1);
+    }
+    print STDERR "*** $0:\n".
+	         "    $mesg\n";
+    exit(1);
+}
+
 sub escapeshellarg($)
 {
     my ($str) = @_;
diff --git a/www/aptui/status.ajax b/www/aptui/status.ajax
index b685c53ef9e29336cab1fe9a385b1198c3d53bcd..187d27ae17dbd9054af8926acc8e19d2108d1995 100644
--- a/www/aptui/status.ajax
+++ b/www/aptui/status.ajax
@@ -934,15 +934,11 @@ function Do_Refresh()
     #
     # Guest users can do this.
     #
-    if (StatusSetupAjax(1)) {
+    if (StatusSetupAjax(0)) {
 	return;
     }
     $this_idx = $this_user->uid_idx();
     $uuid = $ajax_args["uuid"];
-    if ($this_idx != $instance->creator_idx() && !ISADMIN()) {
-	SPITAJAX_ERROR(1, "Not enough permission. Maybe Clone instead?");
-	return;
-    }
     #
     # Call out to the backend.
     #
@@ -1014,7 +1010,7 @@ function Do_RebootOrReload($which)
     # Call out to the backend.
     #
     $webtask_id = WebTask::GenerateID();
-    $retval = SUEXEC($this_user->uid(), "nobody",
+    $retval = SUEXEC("nobody", "nobody",
 		     "webmanage_instance -t $webtask_id -- ".
                      "  $which $uuid " . escapeshellarg($node_id), 
 		     SUEXEC_ACTION_IGNORE);
@@ -1243,7 +1239,7 @@ function Do_Linktest()
             return;
         }
         $webtask_id = WebTask::GenerateID();
-        $retval = SUEXEC($this_user->uid(), "nobody",
+        $retval = SUEXEC("nobody", "nobody",
                          "webmanage_instance -t $webtask_id -- ".
                          "linktest $uuid $level",
                          SUEXEC_ACTION_IGNORE);
@@ -1296,7 +1292,7 @@ function Do_Linktest()
             return;
         }
         $webtask_id = WebTask::GenerateID();
-        $retval = SUEXEC($this_user->uid(), "nobody",
+        $retval = SUEXEC("nobody", "nobody",
                          "webmanage_instance -t $webtask_id -- ".
                          "linktest $uuid -k",
                          SUEXEC_ACTION_IGNORE);