Commit d0cfcfc2 authored by Leigh Stoller's avatar Leigh Stoller

Changes to allow passing password hash from the portal master

to the portal peers.

Also add locking between the portal daemon and manageremote.
parent 80b9a586
#!/usr/bin/perl -w #!/usr/bin/perl -w
# #
# Copyright (c) 2010-2011 University of Utah and the Flux Group. # Copyright (c) 2010-2013 University of Utah and the Flux Group.
# #
# {{{EMULAB-LICENSE # {{{EMULAB-LICENSE
# #
...@@ -121,7 +121,7 @@ sub DumpUser($) ...@@ -121,7 +121,7 @@ sub DumpUser($)
"optional" => 0 }, "optional" => 0 },
"email" => {"tag" => "email", "email" => {"tag" => "email",
"optional" => 0 }, "optional" => 0 },
"pswd" => {"tag" => "password", "pswd" => {"tag" => "passhash",
"optional" => 0 }, "optional" => 0 },
"uid" => {"tag" => "uid", "uid" => {"tag" => "uid",
"optional" => 0 }, "optional" => 0 },
......
...@@ -49,10 +49,12 @@ sub usage() ...@@ -49,10 +49,12 @@ sub usage()
print " manageremote addgroup <remote> <gid>\n"; print " manageremote addgroup <remote> <gid>\n";
exit(1); exit(1);
} }
my $optlist = "dnf"; my $optlist = "dnfp";
my $debug = 0; my $debug = 0;
my $force = 0; my $force = 0;
my $impotent = 0; my $impotent = 0;
my $locked = 0;
my $fromdaemon = 0;
# #
# Function prototypes # Function prototypes
...@@ -121,8 +123,11 @@ if (defined($options{"f"})) { ...@@ -121,8 +123,11 @@ if (defined($options{"f"})) {
if (defined($options{"n"})) { if (defined($options{"n"})) {
$impotent = 1; $impotent = 1;
} }
if (defined($options{"p"})) {
$fromdaemon = 1;
}
usage() usage()
if (@ARGV < 2 || @ARGV > 4); if (@ARGV < 2 || @ARGV > 5);
my $cmd = shift(@ARGV); my $cmd = shift(@ARGV);
my $peername = shift(@ARGV); my $peername = shift(@ARGV);
...@@ -170,26 +175,36 @@ my $credential = GeniCredential->GetSelfCredential($me); ...@@ -170,26 +175,36 @@ my $credential = GeniCredential->GetSelfCredential($me);
if (!defined($credential)) { if (!defined($credential)) {
fatal("Could not create self credential for $me"); fatal("Could not create self credential for $me");
} }
my $authority;
# #
# All operations other then AddPeer require that the peer be # All operations other then AddPeer require that the peer be
# in the DB. # in the DB.
# #
if ($cmd eq "addpeer") { if ($cmd ne "addpeer") {
AddPeer();
exit(0);
}
else {
my $query_result = my $query_result =
DBQueryFatal("select name,urn from emulab_peers ". DBQueryFatal("select name,urn from emulab_peers ".
"where name='$peername' or urn='$peername'"); "where name='$peername' or urn='$peername'");
fatal("Unknown peer") fatal("Unknown peer")
if (!$query_result->numrows); if (!$query_result->numrows);
($peername,$peerurn) = $query_result->fetchrow_array(); ($peername,$peerurn) = $query_result->fetchrow_array();
$authority = GeniAuthority->CreateFromRegistry("sa", $peerurn);
if (!defined($authority)) {
fatal("Could not locate authority for $peername");
}
} }
my $authority = GeniAuthority->CreateFromRegistry("sa", $peerurn);
if (!defined($authority)) { #
fatal("Could not locate authority for $peername"); # All operations other then xlogin require locking to avoid a
# race with the portal_daemon.
#
if ($cmd ne "xlogin" && !$fromdaemon) {
while (TBScriptLock("portal_op", 0, 5) != TBSCRIPTLOCK_OKAY()) {
print "Could not get the lock; trying again ... ^C to stop trying.\n";
next;
}
$locked = 1;
} }
# #
...@@ -204,6 +219,10 @@ SWITCH: for ($cmd) { ...@@ -204,6 +219,10 @@ SWITCH: for ($cmd) {
AddUser(); AddUser();
last SWITCH; last SWITCH;
}; };
/^addpeer$/ && do {
AddPeer();
last SWITCH;
};
/^deluser$/ && do { /^deluser$/ && do {
DeleteUser(); DeleteUser();
last SWITCH; last SWITCH;
...@@ -230,8 +249,12 @@ SWITCH: for ($cmd) { ...@@ -230,8 +249,12 @@ SWITCH: for ($cmd) {
}; };
# Default # Default
TBScriptUnlock()
if ($locked);
usage(); usage();
} }
TBScriptUnlock()
if ($locked);
exit(0); exit(0);
# #
...@@ -315,7 +338,7 @@ sub AddUser(;$) ...@@ -315,7 +338,7 @@ sub AddUser(;$)
} }
my $urn = GeniHRN::Generate($OURDOMAIN, "user", $user->uid()); my $urn = GeniHRN::Generate($OURDOMAIN, "user", $user->uid());
my $xmlgoo = emutil::ExecQuiet("$DUMPUSER -p $uid"); my $xmlgoo = emutil::ExecQuiet("$DUMPUSER $uid");
if ($?) { if ($?) {
fatal("$DUMPUSER failed"); fatal("$DUMPUSER failed");
} }
...@@ -393,7 +416,7 @@ sub ModifyUser() ...@@ -393,7 +416,7 @@ sub ModifyUser()
} }
my $urn = GeniHRN::Generate($OURDOMAIN, "user", $user->uid()); my $urn = GeniHRN::Generate($OURDOMAIN, "user", $user->uid());
my $xmlgoo = emutil::ExecQuiet("$DUMPUSER -p $uid"); my $xmlgoo = emutil::ExecQuiet("$DUMPUSER $uid");
if ($?) { if ($?) {
fatal("$DUMPUSER failed"); fatal("$DUMPUSER failed");
} }
...@@ -568,9 +591,7 @@ sub AddProject() ...@@ -568,9 +591,7 @@ sub AddProject()
" exported=now(), updated=now(), ". " exported=now(), updated=now(), ".
" peer='$peername'"); " peer='$peername'");
if (!$leader_result->numrows) { SetGroups($leader_idx);
SetGroups($leader_idx);
}
return 0; return 0;
} }
......
#!/usr/bin/perl -w #!/usr/bin/perl -w
# #
# Copyright (c) 2000-2012 University of Utah and the Flux Group. # Copyright (c) 2000-2013 University of Utah and the Flux Group.
# #
# {{{EMULAB-LICENSE # {{{EMULAB-LICENSE
# #
...@@ -35,11 +35,12 @@ sub usage() ...@@ -35,11 +35,12 @@ sub usage()
print("Usage: newuser [-s] -t <type> <xmlfile>\n"); print("Usage: newuser [-s] -t <type> <xmlfile>\n");
exit(-1); exit(-1);
} }
my $optlist = "dt:ns"; my $optlist = "dt:nsp";
my $debug = 0; my $debug = 0;
my $impotent= 0; my $impotent= 0;
my $type = ""; my $type = "";
my $silent = 0; my $silent = 0;
my $portal = 0;
my @keyfiles = (); my @keyfiles = ();
# #
...@@ -213,6 +214,11 @@ foreach my $key (keys(%required)) { ...@@ -213,6 +214,11 @@ foreach my $key (keys(%required)) {
fatal("Missing required attribute '$key'") fatal("Missing required attribute '$key'")
if (! exists($xmlparse->{'attribute'}->{"$key"})); if (! exists($xmlparse->{'attribute'}->{"$key"}));
} }
#
# Always delete this. Used by the portal code but we ignore it.
#
delete($xmlparse->{'attribute'}->{"passhash"})
if (exists($xmlparse->{'attribute'}->{"passhash"}));
# #
# We build up an array of arguments to pass to User->Create() as we check # We build up an array of arguments to pass to User->Create() as we check
......
...@@ -735,6 +735,9 @@ sub UpdatePassword() ...@@ -735,6 +735,9 @@ sub UpdatePassword()
# #
return 0 return 0
if (getpwuid($UID) eq "nobody"); if (getpwuid($UID) eq "nobody");
return 0
if ($isnonlocal || $nocollabtools);
$EUID = $UID; $EUID = $UID;
# And the wiki if enabled. # And the wiki if enabled.
...@@ -882,6 +885,9 @@ sub UpdateUser(;$) ...@@ -882,6 +885,9 @@ sub UpdateUser(;$)
} }
$UID = $SAVEUID; $UID = $SAVEUID;
return 0
if ($isnonlocal || $nocollabtools);
$EUID = $UID; $EUID = $UID;
# Update elists in case email changed. # Update elists in case email changed.
system("$MMMODIFYUSER $user") system("$MMMODIFYUSER $user")
......
#!/usr/bin/perl -wT #!/usr/bin/perl -wT
# #
# Copyright (c) 2000-2012 University of Utah and the Flux Group. # Copyright (c) 2000-2013 University of Utah and the Flux Group.
# #
# {{{EMULAB-LICENSE # {{{EMULAB-LICENSE
# #
...@@ -183,6 +183,8 @@ my %xmlfields = ...@@ -183,6 +183,8 @@ my %xmlfields =
"user_interface" => ["user_interface", $SLOT_OPTIONAL], "user_interface" => ["user_interface", $SLOT_OPTIONAL],
"pubkeys" => ["pubkeys", $SLOT_SKIP], "pubkeys" => ["pubkeys", $SLOT_SKIP],
"wikiname" => ["pubkeys", $SLOT_SKIP], "wikiname" => ["pubkeys", $SLOT_SKIP],
# The portal code sets this, we ignore it here.
"passhash" => ["passhash", $SLOT_SKIP],
# These are alternates. # These are alternates.
"name" => ["usr_name", $SLOT_OPTIONAL], "name" => ["usr_name", $SLOT_OPTIONAL],
"title" => ["usr_title", $SLOT_OPTIONAL], "title" => ["usr_title", $SLOT_OPTIONAL],
......
...@@ -69,6 +69,7 @@ my $PGENIDOMAIN = "@PROTOGENI_DOMAIN@"; ...@@ -69,6 +69,7 @@ my $PGENIDOMAIN = "@PROTOGENI_DOMAIN@";
my $ELABINELAB = "@ELABINELAB@"; my $ELABINELAB = "@ELABINELAB@";
my $NEWUSER = "$TB/sbin/newuser"; my $NEWUSER = "$TB/sbin/newuser";
my $RMUSER = "$TB/sbin/rmuser"; my $RMUSER = "$TB/sbin/rmuser";
my $CHPASS = "$TB/sbin/tbacct passwd";
my $ADDUSER = "$TB/sbin/tbacct add"; my $ADDUSER = "$TB/sbin/tbacct add";
my $MODUSER = "$TB/bin/moduserinfo"; my $MODUSER = "$TB/bin/moduserinfo";
my $NEWPROJ = "$TB/sbin/newproj"; my $NEWPROJ = "$TB/sbin/newproj";
...@@ -100,6 +101,7 @@ sub AddUser($) ...@@ -100,6 +101,7 @@ sub AddUser($)
my $credentials = $argref->{'credentials'}; my $credentials = $argref->{'credentials'};
my $xmlgoo = $argref->{'xmlstring'}; my $xmlgoo = $argref->{'xmlstring'};
my $urn = $argref->{'urn'}; my $urn = $argref->{'urn'};
my $passhash;
if (! (defined($credentials) && defined($xmlgoo) && defined($urn))) { if (! (defined($credentials) && defined($xmlgoo) && defined($urn))) {
return GeniResponse->MalformedArgsResponse("Missing arguments"); return GeniResponse->MalformedArgsResponse("Missing arguments");
...@@ -135,6 +137,15 @@ sub AddUser($) ...@@ -135,6 +137,15 @@ sub AddUser($)
return GeniResponse->Create(GENIRESPONSE_BADARGS) return GeniResponse->Create(GENIRESPONSE_BADARGS)
if (! User->ValidUID($login)); if (! User->ValidUID($login));
if (exists($xmlparse->{'attribute'}->{"passhash"})) {
$passhash = $xmlparse->{'attribute'}->{"passhash"}->{'value'};
return GeniResponse->Create(GENIRESPONSE_BADARGS, undef,
"Invalid characters in password hash")
if (! ($passhash =~ /^\$\d\$\w*\$[\w\/\.]*$/ ||
$passhash =~ /^[\w\/\.]*$/));
}
my $user = User->Lookup($login); my $user = User->Lookup($login);
if (defined($user)) { if (defined($user)) {
return GeniResponse->Create(GENIRESPONSE_ALREADYEXISTS, undef, return GeniResponse->Create(GENIRESPONSE_ALREADYEXISTS, undef,
...@@ -182,6 +193,14 @@ sub AddUser($) ...@@ -182,6 +193,14 @@ sub AddUser($)
$user->SetStatus($User::USERSTATUS_ACTIVE); $user->SetStatus($User::USERSTATUS_ACTIVE);
$user->Update({"nocollabtools" => "1", $user->Update({"nocollabtools" => "1",
"manager_urn" => $credential->owner_urn()}); "manager_urn" => $credential->owner_urn()});
if (defined($passhash) &&
$user->SetPassword($passhash) != 0) {
GeniUtil::FlipToGeniUser();
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Internal error setting user password");
}
$output = GeniUtil::ExecQuiet("$WAP $ADDUSER $login"); $output = GeniUtil::ExecQuiet("$WAP $ADDUSER $login");
if ($?) { if ($?) {
$user->Delete(); $user->Delete();
...@@ -314,6 +333,37 @@ sub ModifyUser($) ...@@ -314,6 +333,37 @@ sub ModifyUser($)
"Internal error modifying user"); "Internal error modifying user");
} }
unlink($filename); unlink($filename);
#
# Look for password change. Need special treatment cause its a hash.
#
my $xmlparse = eval { XMLin($xmlgoo,
ForceArray => ["pubkeys"],
VarAttr => 'name',
ContentKey => '-content',
SuppressEmpty => undef); };
return GeniResponse->Create(GENIRESPONSE_ERROR, undef, "$@")
if ($@);
if (exists($xmlparse->{'attribute'}->{"passhash"})) {
my $hash = $xmlparse->{'attribute'}->{"passhash"}->{'value'};
return GeniResponse->Create(GENIRESPONSE_BADARGS, undef,
"Invalid characters in password hash")
if (! ($hash =~ /^\$\d\$\w*\$[\w\/\.]*$/ ||
$hash =~ /^[\w\/\.]*$/));
my $uid = $user->uid();
my $safe_encoding = User::escapeshellarg($hash);
$output = GeniUtil::ExecQuiet("$WAP $CHPASS $uid $safe_encoding");
if ($?) {
GeniUtil::FlipToGeniUser();
print STDERR $output;
return GeniResponse->Create(GENIRESPONSE_ERROR, undef,
"Internal error modifying user password");
}
}
GeniUtil::FlipToGeniUser(); GeniUtil::FlipToGeniUser();
return GeniResponse->Create(GENIRESPONSE_SUCCESS); return GeniResponse->Create(GENIRESPONSE_SUCCESS);
......
#!/usr/bin/perl -w #!/usr/bin/perl -w
# #
# Copyright (c) 2009-2011 University of Utah and the Flux Group. # Copyright (c) 2009-2013 University of Utah and the Flux Group.
# #
# {{{EMULAB-LICENSE # {{{EMULAB-LICENSE
# #
...@@ -49,7 +49,7 @@ my $PIDFILE = "/var/run/portal_daemon.pid"; ...@@ -49,7 +49,7 @@ my $PIDFILE = "/var/run/portal_daemon.pid";
my $SUDO = "/usr/local/bin/sudo"; my $SUDO = "/usr/local/bin/sudo";
my $PROTOUSER = "elabman"; my $PROTOUSER = "elabman";
my $WAP = "$TB/sbin/withadminprivs"; my $WAP = "$TB/sbin/withadminprivs";
my $MANAGEREMOTE = "$TB/sbin/manageremote"; my $MANAGEREMOTE = "$TB/sbin/manageremote -p";
my $PORTAL_ENABLE = @PORTAL_ENABLE@; my $PORTAL_ENABLE = @PORTAL_ENABLE@;
my $PORTAL_PRIMARY= @PORTAL_ISPRIMARY@; my $PORTAL_PRIMARY= @PORTAL_ISPRIMARY@;
...@@ -377,9 +377,17 @@ while (1) ...@@ -377,9 +377,17 @@ while (1)
next; next;
} }
logit("Running"); logit("Running");
#
# Lock, to avoid race with command line tool.
#
if (TBScriptLock("portal_op", 0, 30) != TBSCRIPTLOCK_OKAY()) {
logit("Could not get the lock after a long time. Trying again ...\n");
next;
}
ExportUsers(); ExportUsers();
ExportGroups(); ExportGroups();
UpdateUsers(); UpdateUsers();
TBScriptUnlock();
last last
if ($oneshot); if ($oneshot);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment