Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • alex_orange/emulab-devel
  • hakasapl/emulab-devel
  • cecchet/emulab-devel
  • srirams/emulab-devel
  • chuck/emulab-devel
  • crd/emulab-devel
  • kwebb/emulab-devel
  • moate/emulab-devel
  • grubb/emulab-devel
  • nasir/emulab-devel
  • asydney/emulab-devel
  • kdownie/emulab-devel
  • wvdemeer/emulab-devel
  • anilmr/emulab-devel
  • bvermeul/emulab-devel
  • emulab/emulab-devel
16 results
Show changes
Commits on Source (13456)
Showing with 2443 additions and 384 deletions
VERSION export-subst
# Files that already had DOS-style line endings and those
# that require them should be added to the list below.
clientside/sensors/slothd/idlemon.vbs -crlf
clientside/tmcc/cygwinseven/SetupComplete.cmd -crlf
clientside/tmcc/cygwinseven/unattend-x86.xml.in -crlf
clientside/tmcc/cygwinxp/cygwin-tcsh.bat -crlf
clientside/tmcc/cygwinxp/resolv.conf -crlf
clientside/tmcc/cygwinxp/site-lisp/cygwin-mount.el -crlf
clientside/tmcc/cygwinxp/site-lisp/site-start.el -crlf
clientside/tmcc/cygwinxp/sysprep.inf -crlf
delay/linux/iptables_mods/iptables-1.3.6-imq.diff -crlf
hyperviewer/hv.dsp -crlf
hyperviewer/hv.dsw -crlf
......@@ -64,16 +72,10 @@ protogeni/demo/src/RequestSliverStart.as -crlf
protogeni/demo/src/RequestSliverUpdate.as -crlf
protogeni/demo/src/SimpleNodeClip.as -crlf
protogeni/demo/src/SliceWait.as -crlf
sensors/slothd/idlemon.vbs -crlf
tbsetup/ipassign/dre/prepass/pistream.h -crlf
tbsetup/ipassign/dre/prepass/postream.h -crlf
tbsetup/ipassign/etc/autocheck.conf -crlf
tbsetup/plab/libdslice/xmlrpcserver.py -crlf
tmcd/cygwinxp/cygwin-tcsh.bat -crlf
tmcd/cygwinxp/resolv.conf -crlf
tmcd/cygwinxp/site-lisp/cygwin-mount.el -crlf
tmcd/cygwinxp/site-lisp/site-start.el -crlf
tmcd/cygwinxp/sysprep.inf -crlf
www/csshover.htc -crlf
www/cssmenu.css -crlf
www/cssmenu-new.css -crlf
......
.merge-build
clientside/tmcc/cygwinseven/unattend-7pro-x86.xml.in
extendCMV
\ No newline at end of file
......@@ -10,6 +10,7 @@ clientside/os/imagezip/fat
clientside/os/imagezip/ntfs/liblocale
clientside/lib/event/event_wrap*
clientside/tmcc/cygwinxp/site-lisp
clientside/tmcc/freebsd/init
clientside/tmcc/plab
os/shd
www/cvsweb
......@@ -49,3 +50,8 @@ LGPL-COPYING
AGPL-COPYING
TODO.plab
MOVED-TO-WIKI
VERSION
protogeni/flack/js/forge
protogeni/flack/src/com/hurlant
protogeni/flack/src/com/mattism
protogeni/protogeniflash/src/com/mattism
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2012 University of Utah and the Flux Group.
# All rights reserved.
# Copyright (c) 2000-2021 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
# This file is part of the Emulab network testbed software.
#
# This file is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
#
# This file is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
# License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this file. If not, see <http://www.gnu.org/licenses/>.
#
# }}}
#
# Testbed Makefile
#
......@@ -14,6 +31,8 @@ EVENTSYS = @EVENTSYS@
PELABSUPPORT = @PELABSUPPORT@
PGENISUPPORT = @PROTOGENI_SUPPORT@
ISMAINSITE = @TBMAINSITE@
SPEWFROMOPS = @SPEWFROMOPS@
MOBILESUPPORT = @MOBILESUPPORT@
SYSTEM := $(shell uname -s)
include Makeconf
......@@ -26,21 +45,21 @@ include Makeconf
# @optional_subdirs@ (has event)
# ipod os security sensors
# Then things that only depend on stuff we've done:
# pxe tbsetup tmcd utils backend www tip capture vis
# pxe tbsetup tmcd utils backend www tip vis
# Then things that depend on stuff we just did:
#
ifeq ($(STANDALONE_CLEARINGHOUSE),0)
SUBDIRS = \
clientside/lib \
db assign www @optional_subdirs@ clientside ipod security sensors \
pxe tbsetup account tmcd utils backend tip capture ipod vis \
sensors os xmlrpc install/newnode_sshkeys mote tools/whol \
tools/svn wiki bugdb collab node_usage install
pxe tbsetup account tmcd utils wbstore backend ipod vis \
sensors os xmlrpc autofs install/newnode_sshkeys \
tools/svn collab/exp-vis node_usage install
ifeq ($(ISMAINSITE),1)
SUBDIRS += tools/rmanage
SUBDIRS += tools/whol
endif
ifeq ($(PGENISUPPORT),1)
SUBDIRS += protogeni
SUBDIRS += protogeni apt powder
endif
else
SUBDIRS = db tbsetup account protogeni
......@@ -89,7 +108,8 @@ boss-install-noupdatecheck: install-schemacheck \
install-setbuildinfo
# Only the checks:
install-checks: install-updatecheck \
install-checks: \
install-updatecheck \
install-schemacheck \
install-sitevarscheck \
install-dbfillcheck install-genischemacheck
......@@ -109,10 +129,10 @@ post-install:
ifeq ($(EVENTSYS),1)
@$(MAKE) -C event post-install
endif
@$(MAKE) -C mote post-install
ifeq ($(MOBILESUPPORT),1)
@$(MAKE) -C mobile
endif
@$(MAKE) -C tools post-install
@$(MAKE) -C wiki post-install
@$(MAKE) -C bugdb post-install
@$(MAKE) -C collab post-install
@$(MAKE) -C utils post-install
ifeq ($(NODE_USAGE_SUPPORT),1)
......@@ -128,29 +148,33 @@ ops-install:
-chmod 770 $(INSTALL_TOPDIR)/log/mysql
-chown mysql $(INSTALL_TOPDIR)/log/mysql
-chgrp mysql $(INSTALL_TOPDIR)/log/mysql
-mkdir -p $(INSTALL_TOPDIR)/log/logfiles
-chmod 777 $(INSTALL_TOPDIR)/log/logfiles
@$(MAKE) -C rc.d control-install
@$(MAKE) -C tbsetup control-install
@$(MAKE) -C security control-install
@$(MAKE) -C tip control-install
@$(MAKE) -C db control-install
@$(MAKE) -C utils control-install
@$(MAKE) -C clientside control-install
ifeq ($(EVENTSYS),1)
@$(MAKE) -C event control-install
endif
@$(MAKE) -C xmlrpc control-install
@$(MAKE) -C account control-install
ifeq ($(PELABSUPPORT),1)
@$(MAKE) -C pelab control-install
endif
fs-install:
@$(MAKE) -C rc.d fs-install
@$(MAKE) -C tbsetup fs-install
@$(MAKE) -C clientside fs-install
@$(MAKE) -C sensors fs-install
opsfs-install: ops-install fs-install
@echo "Combined ops/fs install done."
install-mkdirs:
-mkdir -p $(INSTALL_TOPDIR)/db
-mkdir -p $(INSTALL_TOPDIR)/locks
-mkdir -p $(INSTALL_TOPDIR)/log
-mkdir -p $(INSTALL_TOPDIR)/log/mysql
......@@ -175,7 +199,7 @@ ifeq ($(STANDALONE_CLEARINGHOUSE),0)
-chmod 777 $(INSTALL_TOPDIR)/exparchive/Archive
-mkdir -p $(INSTALL_TOPDIR)/images
-chmod 775 $(INSTALL_TOPDIR)/images
-ln -s /usr/testbed/bin/nse $(INSTALL_TOPDIR)/bin
-ln -sf /usr/testbed/bin/nse $(INSTALL_TOPDIR)/bin
endif
just-builddirs:
......@@ -185,8 +209,8 @@ just-builddirs:
tipserv-install:
-mkdir -p $(INSTALL_TOPDIR)/log/tiplogs
-mkdir -p $(INSTALL_TOPDIR)/etc
@$(MAKE) -C tip tipserv-install
@$(MAKE) -C capture tipserv-install
@$(MAKE) -C clientside/tip tipserv-install
@$(MAKE) -C clientside/os/capture tipserv-install
@$(MAKE) -C tbsetup tipserv-install
client-mkdirs:
......@@ -196,33 +220,24 @@ client-mkdirs:
client:
@$(MAKE) -C clientside client
@$(MAKE) -C os client
ifneq ($(SYSTEM),CYGWIN_NT-5.1)
@$(MAKE) -C capture client
@$(MAKE) -C tip client
endif
client-install: client client-mkdirs
@$(MAKE) -C clientside client-install
@$(MAKE) -C os client-install
ifneq ($(SYSTEM),CYGWIN_NT-5.1)
@$(MAKE) -C capture client-install
@$(MAKE) -C tip client-install
endif
subboss: client
subboss:
@$(MAKE) -C clientside subboss
@$(MAKE) -C tbsetup subboss
@$(MAKE) -C db subboss
@$(MAKE) -C os subboss
@$(MAKE) -C utils subboss
subboss-install: subboss
@$(MAKE) -C clientside client-install
ifneq ($(SYSTEM),CYGWIN_NT-5.1)
@$(MAKE) -C capture client-install
@$(MAKE) -C tip client-install
endif
@$(MAKE) -C utils subboss-install
@$(MAKE) -C clientside subboss-install
@$(MAKE) -C tbsetup subboss-install
@$(MAKE) -C os subboss-install
@$(MAKE) -C utils subboss-install
@$(MAKE) -C db subboss-install
@$(MAKE) -C clientside/tmcc subboss-install
@$(MAKE) -C rc.d subboss-install
@$(MAKE) -C dhcpd subboss-install
# Hack: this should probably be done by a subboss-install
......@@ -241,7 +256,7 @@ client-src-tarball:
# This is not finished yet.
client-shadow-rpm:
-$(RM) -rf rpmbuild
$(MKDIR_P) rpmbuild/SOURCES rpmbuild/SRPMS
mkdir -p rpmbuild/SOURCES rpmbuild/SRPMS
$(CP) emulab-client-src.tar.gz rpmbuild/SOURCES
$(RPM) -v -bs --nodeps --define='_topdir $(TOPDIR)/rpmbuild' \
clientside/shadow.spec
......@@ -263,41 +278,41 @@ mfsoscheck:
fi
mfs: mfsoscheck
@$(MAKE) -C os mfs
@$(MAKE) -C clientside mfs
mfs-nostatic: mfsoscheck
@NOSTATIC=1 $(MAKE) -C os mfs
@NOSTATIC=1 $(MAKE) -C clientside mfs
mfs-install: destdircheck mfs client-mkdirs
@$(MAKE) -C os mfs-install
@$(MAKE) -C clientside mfs-install
mfs-nostatic-install: destdircheck mfs-nostatic client-mkdirs
@$(MAKE) -C os mfs-install
@$(MAKE) -C clientside mfs-install
frisbee-mfs: mfsoscheck
@$(MAKE) -C cdrom/groklilo client
@$(MAKE) -C os frisbee-mfs
@$(MAKE) -C clientside frisbee-mfs
frisbee-mfs-nostatic: mfsoscheck
@NOSTATIC=1 $(MAKE) -C cdrom/groklilo client
@NOSTATIC=1 $(MAKE) -C os frisbee-mfs
@NOSTATIC=1 $(MAKE) -C clientside frisbee-mfs
frisbee-mfs-install: destdircheck frisbee-mfs
@CLIENT_BINDIR=/etc/testbed $(MAKE) -e -C cdrom/groklilo client-install
@$(MAKE) -C os frisbee-mfs-install
@$(MAKE) -C clientside frisbee-mfs-install
frisbee-mfs-nostatic-install: destdircheck frisbee-mfs-nostatic
@CLIENT_BINDIR=/etc/testbed $(MAKE) -e -C cdrom/groklilo client-install
@$(MAKE) -C os frisbee-mfs-install
@$(MAKE) -C clientside frisbee-mfs-install
newnode-mfs: mfsoscheck
@$(MAKE) -C clientside newnode-mfs
newnode-mfs-nostatic: mfsoscheck
@NOSTATIC=1 $(MAKE) -C clientside newnode-mfs
newnode-mfs-install: destdircheck newnode-mfs client-mkdirs
@$(MAKE) -C clientside newnode-mfs-install
newnode-mfs-nostatic-install: destdircheck newnode-mfs-nostatic client-mkdirs
@$(MAKE) -C clientside newnode-mfs-install
cdboot: mfsoscheck client
@echo "CD/Dongle files built"
......@@ -396,6 +411,19 @@ ifeq ($(PGENISUPPORT),1)
endif
@echo "Done"
BRANCHCHECK=
BRANCHECHO= @echo "Skipping branch check since not the Mothership"
ifeq ($(ISMAINSITE),1)
ifeq ($(TBROOT),/usr/testbed)
BRANCHCHECK= cd $(SRCDIR) && \
git status --porcelain -s -b | head -1 | grep -q -s current
BRANCHECHO= @echo "Checking to make sure you are on the mothership branch"
endif
endif
install-branchcheck:
$(BRANCHECHO)
$(BRANCHCHECK)
# We use separate src and obj trees in Emulab, so the traditional distclean to
# clean "made" files from a mingled source-and-obj tree is unnecessary.
# However, this may be useful if you mistakenly configure and make a src tree.
......@@ -403,6 +431,25 @@ clean: clean-subdirs
distclean: distclean-subdirs
rm -f Makeconf GNUmakefile config.h config.status config.cache config.log
rm -f $(DISTCLEAN_FILES)
#
# Be careful, do not run these unless you are updating your installation
# with a new IP subnet or domain name.
#
boss-updateip-clean: clean
@$(MAKE) -C rc.d clean
@$(MAKE) -C apache clean
@$(MAKE) -C named clean
@$(MAKE) -C dhcpd clean
ops-updateip-clean: clean
@$(MAKE) -C rc.d clean
@$(MAKE) -C apache clean
update-rcd:
@$(MAKE) -C rc.d all
@$(MAKE) -C rc.d install
#
# Here's a different approch to recover from just configure problems. It cleans
# all files from an obj tree that have a corresponding .in file in the src tree.
......@@ -410,15 +457,45 @@ undo-configure:
find $SRCDIR -name '*.in' -a -not -name configure.in | \
sed -e "s;$SRCDIR;$OBJDIR;" -e 's;[.]in$;;' | xargs rm -f
elabinelab:
#
# XXX a "temporary" hack for scripts that were evolving fast.
# We didn't want to have to remake the client image whenever we changed these.
# They are copied over to the embryonic boss and ops during setup.
#
elabinelab-scripts:
mkdir -p $(INSTALL_TOPDIR)/etc
cp -f $(SRCDIR)/clientside/tmcc/freebsd/mkextrafs.pl $(INSTALL_TOPDIR)/etc/
cp -f $(SRCDIR)/clientside/tmcc/common/config/rc.mkelab $(INSTALL_TOPDIR)/etc/
ifeq ($(SPEWFROMOPS),1)
elabinelab-nogit: elabinelab-scripts
-mkdir -p /share/emulab
rm -f /share/emulab/emulab-src.tar.gz
tar czf /share/emulab/emulab-src.tar.gz -C $(SRCDIR) --exclude=.git .
elabinelab-git: elabinelab-scripts
-mkdir -p /share/emulab
rm -f /share/emulab/emulab-src.tar.gz
(cd $(SRCDIR); \
git archive HEAD > /share/emulab/emulab-src.tar)
tar rf /share/emulab/emulab-src.tar -C $(SRCDIR) \
--exclude=.git protogeni/rspec-geni
gzip /share/emulab/emulab-src.tar
else
elabinelab-nogit: elabinelab-scripts
-mkdir -p $(INSTALL_TOPDIR)/src
rm -f $(INSTALL_TOPDIR)/src/emulab-src.tar.gz
tar czf $(INSTALL_TOPDIR)/src/emulab-src.tar.gz -C $(SRCDIR) --exclude=.git .
elabinelab-git:
elabinelab-git: elabinelab-scripts
-mkdir -p $(INSTALL_TOPDIR)/src
rm -f $(INSTALL_TOPDIR)/src/emulab-src.tar.gz
git archive --prefix=testbed/ | gzip -c > $(INSTALL_TOPDIR)/src/emulab-src.tar.gz
(cd $(SRCDIR); \
git archive HEAD > $(INSTALL_TOPDIR)/src/emulab-src.tar)
tar rf $(INSTALL_TOPDIR)/src/emulab-src.tar -C $(SRCDIR) \
--exclude=.git protogeni/rspec-geni
gzip $(INSTALL_TOPDIR)/src/emulab-src.tar
endif
# How to recursively descend into subdirectories to make general
# targets such as `all'.
......
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2012 University of Utah and the Flux Group.
# All rights reserved.
# Copyright (c) 2000-2012, 2016 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
# This file is part of the Emulab network testbed software.
#
# This file is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
#
# This file is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
# License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this file. If not, see <http://www.gnu.org/licenses/>.
#
# }}}
# Get rid of a bunch of nasty built-in implicit rules,
# to avoid bogus circular dependencies and make things go faster.
......@@ -91,6 +108,21 @@ distclean: default-clean
default-clean:
rm -f GNUmakefile
# This is to avoid warnings about duplicate targets.
default-install-notusing:
ifeq ($(ISMAINSITE),1)
ifeq ($(TBROOT),/usr/testbed)
(cd $(SRCDIR) ; \
git status --porcelain -s -b | head -1 | grep -q -s current)
else
/usr/bin/true
endif
else
/usr/bin/true
endif
#install: default-install
#
# Where to find source files.
# Using specific patterns instead of the catch-all VPATH variable
......
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2012 University of Utah and the Flux Group.
# All rights reserved.
# Copyright (c) 2000-2016 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
# This file is part of the Emulab network testbed software.
#
# This file is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
#
# This file is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
# License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this file. If not, see <http://www.gnu.org/licenses/>.
#
# }}}
#
# Most of the configure-substitution magic is done here.
# All the other makefiles in the NodeOS include
......@@ -27,6 +44,7 @@ export JAR = @JAR@
prefix = @prefix@
exec_prefix = @exec_prefix@
ISMAINSITE = @TBMAINSITE@
TBROOT = @prefix@
TBDEFS = @TBDEFS@
TBDBNAME = @TBDBNAME@
......@@ -103,4 +121,4 @@ MERGE_BUILD_SANDBOX = @MERGE_BUILD_SANDBOX@
EXP_VIS_SUPPORT = @EXP_VIS_SUPPORT@
TESTBED_LIBSRCDIR = ${TESTBED_SRCDIR}/clientside/lib
TESTBED_LIBOBJDIR = ${OBJDIR}/clientside/lib
TESTBED_IMAGEZIPSRCDIR = ${OBJDIR}/clientside/os/imagezip
TESTBED_IMAGEZIPSRCDIR = ${TESTBED_SRCDIR}/clientside/os/imagezip
#!/usr/bin/perl -w
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2007 University of Utah and the Flux Group.
# All rights reserved.
#
# {{{EMULAB-LICENSE
#
# This file is part of the Emulab network testbed software.
#
# This file is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
#
# This file is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
# License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this file. If not, see <http://www.gnu.org/licenses/>.
#
# }}}
#
use English;
......
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2011 University of Utah and the Flux Group.
# All rights reserved.
# Copyright (c) 2000-2024 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
# This file is part of the Emulab network testbed software.
#
# This file is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
#
# This file is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
# License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this file. If not, see <http://www.gnu.org/licenses/>.
#
# }}}
#
SRCDIR = @srcdir@
......@@ -14,10 +31,10 @@ include $(OBJDIR)/Makeconf
SBIN_STUFF = tbacct addsfskey addpubkey mkusercert quotamail genpubkeys \
newuser newproj mksyscert spewcert dumpuser dumpproject \
manageremote
manageremote regencerts
LIBEXEC_STUFF = webtbacct webaddsfskey webaddpubkey webmkusercert \
webnewuser webnewproj webspewcert webmanageremote
CTRLSBIN_STUFF = adduserhook
CTRLSBIN_STUFF = adduserhook accountsetup
# These scripts installed setuid, with sudo.
SETUID_BIN_SCRIPTS =
......@@ -57,7 +74,8 @@ boss-install: all script-install
@echo "Don't forget to do a post-install as root"
script-install: $(addprefix $(INSTALL_SBINDIR)/, $(SBIN_STUFF)) \
$(addprefix $(INSTALL_LIBEXECDIR)/, $(LIBEXEC_STUFF))
$(addprefix $(INSTALL_LIBEXECDIR)/, $(LIBEXEC_STUFF)) \
$(addprefix $(INSTALL_DIR)/opsdir/sbin/, $(CTRLSBIN_STUFF))
post-install:
chmod 775 $(INSTALL_BINDIR)
......
This diff is collapsed.
#!/usr/bin/perl -wT
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2012 University of Utah and the Flux Group.
# All rights reserved.
# Copyright (c) 2000-2020 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
# This file is part of the Emulab network testbed software.
#
# This file is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
#
# This file is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
# License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this file. If not, see <http://www.gnu.org/licenses/>.
#
# }}}
#
use English;
use Getopt::Std;
use XML::Simple;
use File::Temp qw(tempfile :POSIX );
#
# Parse ssh public keys and enter into the DB. The default format is
......@@ -31,7 +49,7 @@ sub usage()
print " -r Force a regenerate of initial key for user\n";
exit(-1);
}
my $optlist = "dkniwfu:rX:sRNC:S:";
my $optlist = "dkniwfu:rX:sRNC:S:Ia";
my $iskey = 0;
my $verify = 0;
my $initmode = 0;
......@@ -41,6 +59,8 @@ my $nobody = 0;
my $noemail = 0;
my $remove = 0;
my $nodelete = 0;
my $internal = 0;
my $isaptkey = 0;
my $Comment;
my $xmlfile;
......@@ -51,7 +71,11 @@ my $TB = "@prefix@";
my $TBOPS = "@TBOPSEMAIL@";
my $TBAUDIT = "@TBAUDITEMAIL@";
my $OURDOMAIN = "@OURDOMAIN@";
my $CONTROL = "@USERNODE@";
my $KEYGEN = "/usr/bin/ssh-keygen";
my $ACCOUNTPROXY= "$TB/sbin/accountsetup";
my $SSH = "$TB/bin/sshtb";
my $SAVEUID = $UID;
my $USERUID;
# Locals
......@@ -66,6 +90,7 @@ my $user_name;
my $user_email;
my $user_dbid;
my $user_uid;
my $user_gid;
my $debug = 0;
#
......@@ -76,6 +101,9 @@ use libaudit;
use libdb;
use libtestbed;
use User;
if (@PROTOGENI_SUPPORT@) {
require APT_Utility;
}
#
# Function prototypes
......@@ -138,6 +166,9 @@ if (! getopts($optlist, \%options)) {
if (defined($options{"d"})) {
$debug = 1;
}
if (defined($options{"a"})) {
$isaptkey = 1;
}
if (defined($options{"k"})) {
$iskey = 1;
}
......@@ -153,6 +184,9 @@ if (defined($options{"i"})) {
if (defined($options{"N"})) {
$nodelete = 1;
}
if (defined($options{"I"})) {
$internal = 1;
}
if (defined($options{"r"})) {
$force = 1;
}
......@@ -231,6 +265,18 @@ if (defined($user)) {
$user_dbid = $target_user->dbid();
$user_uid = $target_user->uid();
$USERUID = $target_user->unix_uid();
my $firstproject;
if ($target_user->FirstApprovedProject(\$firstproject) < 0) {
fatal("Could not determine first approved project");
}
if (defined($firstproject)) {
$user_gid = $firstproject->unix_gid();
}
else {
$user_gid = "guest";
}
}
#
......@@ -256,18 +302,16 @@ else {
}
#
# Initmode or genmode, do it and exit. Eventually get rid of the switch
# to the target user.
# Initmode or genmode, do it and exit.
#
if ($initmode) {
# Drop root privs, switch to target user.
$EUID = $UID = $USERUID;
exit InitUser();
}
if ($genmode) {
# Drop root privs, switch to target user.
$EUID = $UID = $USERUID;
exit GenerateKeyFile();
if ($initmode || $genmode) {
if ($initmode) {
exit(InitUser());
}
if ($genmode) {
exit(GenerateKeyFile());
}
exit(1);
}
# Else, key parse mode ...
......@@ -290,7 +334,23 @@ else {
if (! -e $keyfile) {
fatal("No such file: $keyfile\n");
}
$keyline = `head -1 $keyfile`;
open(KEY, "$keyfile")
or fatal("Could not open $keyfile to read");
#
# Ick, look at first line to see if it looks like an openssh key,
# and if so we want to remove the embedded newlines.
#
$keyline = <KEY>;
my $chompit = 0;
if ($keyline =~ /^ssh/ || $keyline =~ /^\d+\s+\d+/) {
$chompit = 1;
}
while (<KEY>) {
chomp($_) if ($chompit);
$keyline .= $_;
}
close(KEY);
}
#
......@@ -303,18 +363,11 @@ if (!$verify) {
!$nodelete) {
fatal("You are not allowed to set pubkeys for $target_user\n");
}
if (-d "$HOMEDIR/$user_uid/.ssh") {
if ($target_user->SameUser($this_user) && $this_user->active()) {
# Drop root privs, switch to target user.
$EUID = $UID = $USERUID;
$genmode = 1;
}
#
# This script is audited when not in verify mode. Since all keys are first
# checked with verify mode, this should not cause any extra email from bad
# keys.
#
AuditStart(0);
}
#
......@@ -357,7 +410,7 @@ sub ParseKey($) {
return 0;
}
if ($keyline =~ /^(\d*\s\d*\s[0-9a-zA-Z]*) ([-\w\@\.:\ ]*)\s*$/) {
if ($keyline =~ /^(\d*\s\d*\s[0-9a-zA-Z]*) ([-\\\w\@\.:\ ]*)\s*$/) {
# Protocol 1
$type = "ssh-rsa1";
$key = $1;
......@@ -369,21 +422,20 @@ sub ParseKey($) {
$key = $1;
}
elsif ($keyline =~
/^(ssh-rsa|ssh-dss) ([-\w\.\@\+\/\=]*) ([-\w\@\.:\ ]*)$/) {
/^(ssh-rsa|ssh-ed25519) ([-\w\.\@\+\/\=]*) ([-\\\w\@\.:\ ]*)$/) {
# Protocol 2
$type = $1;
$key = "$1 $2";
$comment = $3;
}
elsif ($keyline =~ /^(ssh-rsa|ssh-dss) ([-\w\.\@\+\/\=:]*)$/) {
elsif ($keyline =~ /^(ssh-rsa|ssh-ed25519) ([-\w\.\@\+\/\=:]*)$/) {
# Protocol 2 but no comment field
$type = $1;
$key = "$1 $2";
}
if (!defined($key)) {
print "Key cannot be parsed!\n";
print "Key: $keyline\n";
print STDERR "Key cannot be parsed, we accept rsa and ed25519 only!\n";
return 0;
}
......@@ -407,17 +459,24 @@ sub ParseKey($) {
DBQueryFatal("delete from user_pubkeys ".
"where uid_idx='$user_dbid' and comment=$safe_comment");
}
# Only one APT key allowed
if ($isaptkey) {
DBQueryFatal("delete from user_pubkeys ".
"where uid_idx='$user_dbid' and isaptkey=1");
}
DBQueryFatal("replace into user_pubkeys set ".
" uid='$user_uid', uid_idx='$user_dbid', ".
" internal='0', nodelete='$nodelete', ".
" idx=NULL, stamp=now(), ".
" internal='$internal', nodelete='$nodelete', ".
" isaptkey='$isaptkey',idx=NULL, stamp=now(), ".
" pubkey=$safe_key, comment=$safe_comment");
#
# Mark user record as modified so nodes are updated.
#
TBNodeUpdateAccountsByUID($user_uid);
if (@PROTOGENI_SUPPORT@) {
APT_Utility::UpdateInstancesByUser($target_user);
}
my $chunked = "";
while (length($key)) {
......@@ -440,7 +499,7 @@ sub ParseKey($) {
"SSH Public Key for '$user_uid' added:\n".
"\n".
"$chunked\n",
"$TBOPS");
"$TBOPS", "Bcc: $TBAUDIT");
}
return 1;
}
......@@ -452,98 +511,47 @@ sub ParseKey($) {
#
sub InitUser()
{
my $sshdir = "$HOMEDIR/$user_uid/.ssh";
#
# Set up the ssh key, but only if not done so already.
# Want to delete existing keys from DB, but not the sslcert key.
#
if (! -e "$sshdir") {
mkdir("$sshdir", 0700) or
fatal("Could not mkdir $sshdir: $!");
}
if (! -e "$sshdir/identity" || $force) {
print "Creating ssh protocol 1 key for $user.\n";
#
# Want to delete existing key from DB.
#
if (-e "$sshdir/identity") {
my $ident = `cat $sshdir/identity.pub`;
if ($ident =~ /(\d*\s\d*\s[0-9a-zA-Z]*)\s([-\w\@\.]*)/) {
DBQueryFatal("delete from user_pubkeys ".
"where uid_idx='$user_dbid' and pubkey='$1 $2'");
}
unlink("$sshdir/identity");
}
# Hmm, need to use -C option so comment field makes sense.
if (system("$KEYGEN -t rsa1 -P '' ".
"-C '${user}" . "\@" . ${OURDOMAIN} . "' ".
"-f $sshdir/identity")) {
fatal("Failure in ssh-keygen!");
}
#
# Grab a copy for the DB.
#
my $ident = `cat $sshdir/identity.pub`;
if ($ident =~ /(\d*\s\d*\s[0-9a-zA-Z]*)\s([-\w\@\.]*)/) {
DBQueryFatal("replace into user_pubkeys set ".
" uid='$user_uid', uid_idx='$user_dbid', ".
" internal='1', nodelete='1', idx=NULL, stamp=now(), ".
" pubkey='$1 $2', comment='$2'");
}
else {
fatal("Bad protocol 1 public key: $ident\n");
}
}
#
# Moving to V2 keys ...
#
if (! -e "$sshdir/id_rsa" || $force) {
print "Creating ssh protocol 2 key for $user.\n";
#
# Want to delete existing key from DB.
#
if (-e "$sshdir/id_rsa") {
my $ident = `cat $sshdir/id_rsa.pub`;
if ($ident =~
/^(ssh-rsa [-\w\.\@\+\/\=]*) ([-\w\@\.\ ]*)$/) {
DBQueryFatal("delete from user_pubkeys ".
"where uid_idx='$user_dbid' and pubkey='$1 $2'");
}
unlink("$sshdir/id_rsa");
}
# Hmm, need to use -C option so comment field makes sense.
DBQueryFatal("delete from user_pubkeys ".
"where uid_idx='$user_dbid' and ".
" (internal=1 or comment like '%\@${OURDOMAIN}' or ".
" comment like '%\@boss.${OURDOMAIN}') and ".
" isaptkey=0 and comment not like 'sslcert:%'");
# Redirect pub key to file, redirect STDERR to STDIN for display.
my $outfile = tmpnam();
my $command = "$ACCOUNTPROXY createsshkey $user_uid $user_gid ";
$UID = 0;
open ERR, "$SSH -host $CONTROL '$command rsa' 2>&1 > $outfile |";
$UID = $SAVEUID;
$errs = "";
while (<ERR>) {
$errs .= $_;
}
close(ERR);
print STDERR $errs;
if ($?) {
unlink($outfile);
fatal("Could not create rsa key");
}
$pubkey = `cat $outfile`;
chomp($pubkey);
$safe_pubkey = DBQuoteSpecial($pubkey);
$comment = "rsa\@${OURDOMAIN}";
if (system("$KEYGEN -t rsa -P '' ".
"-C '${user}" . "\@" . ${OURDOMAIN} . "' ".
"-f $sshdir/id_rsa")) {
fatal("Failure in ssh-keygen!");
}
#
# Grab a copy for the DB.
#
my $ident = `cat $sshdir/id_rsa.pub`;
if ($ident =~
/^(ssh-rsa [-\w\.\@\+\/\=]*) ([-\w\@\.\ ]*)$/) {
DBQueryFatal("replace into user_pubkeys set ".
" uid='$user_uid', uid_idx='$user_dbid', ".
" internal='1', nodelete='1', idx=NULL, stamp=now(), ".
" pubkey='$1 $2', comment='$2'");
}
else {
fatal("Bad protocol 2 public key: $ident\n");
}
}
if (! DBQueryWarn("replace into user_pubkeys set ".
" uid='$user_uid', uid_idx='$user_dbid', ".
" internal='1', nodelete='1', idx=NULL, stamp=now(), ".
" pubkey=$safe_pubkey, comment='$comment'")) {
unlink($outfile);
fatal("Could not add rsa key to database");
}
unlink($outfile);
return GenerateKeyFile();
}
......@@ -554,15 +562,9 @@ sub InitUser()
sub GenerateKeyFile()
{
my @pkeys = ();
my $outfile = tmpnam();
my $sshdir = "$HOMEDIR/$user_uid/.ssh";
my $keyfile = "$sshdir/authorized_keys";
if (! -e $sshdir) {
if (! mkdir($sshdir, 0700)) {
warn("*** WARNING: Could not mkdir $sshdir: $!\n");
return -1;
}
}
my $query_result =
DBQueryFatal("select pubkey from user_pubkeys ".
"where uid_idx='$user_dbid'");
......@@ -571,15 +573,14 @@ sub GenerateKeyFile()
push(@pkeys, $key);
}
print "Generating $keyfile ...\n";
if (!open(AUTHKEYS, "> ${keyfile}.new")) {
warn("*** WARNING: Could not open ${keyfile}.new: $!\n");
print "Generating authorized_keys ...\n";
if (!open(AUTHKEYS, "> $outfile")) {
warn("*** WARNING: Could not open $outfile: $!\n");
return -1;
}
print AUTHKEYS "#\n";
print AUTHKEYS "# DO NOT EDIT! This file auto generated by ".
"Emulab.Net account software.\n";
"Emulab account software.\n";
print AUTHKEYS "#\n";
print AUTHKEYS "# Please use the web interface to edit your ".
"public key list.\n";
......@@ -590,28 +591,17 @@ sub GenerateKeyFile()
}
close(AUTHKEYS);
if (!chmod(0600, "${keyfile}.new")) {
warn("*** WARNING: Could not chmod ${keyfile}.new: $!\n");
return -1;
}
if (-e "${keyfile}") {
if (system("cp -p -f ${keyfile} ${keyfile}.old")) {
warn("*** Could not save off ${keyfile}: $!\n");
return -1;
}
if (!chmod(0600, "${keyfile}.old")) {
warn("*** Could not chmod ${keyfile}.old: $!\n");
}
}
if (system("mv -f ${keyfile}.new ${keyfile}")) {
warn("*** Could not mv ${keyfile} to ${keyfile}.new: $!\n");
}
elsif (-e "$sshdir/authorized_keys2") {
#
# Save to remove deprecated authorized_keys2 file at this point.
#
unlink("$sshdir/authorized_keys2");
$EUID = $UID = 0;
system("$SSH -host $CONTROL ".
"'$ACCOUNTPROXY dropfile $user_uid $user_gid 0600 $sshdir ".
"authorized_keys' < $outfile");
$EUID = $UID = $SAVEUID;
if ($?) {
unlink($outfile);
fatal("Could not copy authorized_keys file to $CONTROL");
}
unlink($outfile);
return 0;
}
......
#!/usr/bin/perl -wT
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2004, 2006 University of Utah and the Flux Group.
# All rights reserved.
#
# {{{EMULAB-LICENSE
#
# This file is part of the Emulab network testbed software.
#
# This file is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
#
# This file is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
# License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this file. If not, see <http://www.gnu.org/licenses/>.
#
# }}}
#
use English;
use Getopt::Std;
......
#!/usr/bin/perl -w
#
# EMULAB-COPYRIGHT
# Copyright (c) 2008 University of Utah and the Flux Group.
# All rights reserved.
#
# {{{EMULAB-LICENSE
#
# This file is part of the Emulab network testbed software.
#
# This file is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
#
# This file is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
# License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this file. If not, see <http://www.gnu.org/licenses/>.
#
# }}}
#
use strict;
use English;
......
#!/usr/bin/perl -w
#
# EMULAB-COPYRIGHT
# Copyright (c) 2010-2011 University of Utah and the Flux Group.
# All rights reserved.
#
# {{{EMULAB-LICENSE
#
# This file is part of the Emulab network testbed software.
#
# This file is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
#
# This file is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
# License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this file. If not, see <http://www.gnu.org/licenses/>.
#
# }}}
#
use English;
use strict;
......
#!/usr/bin/perl -w
#
# EMULAB-COPYRIGHT
# Copyright (c) 2010-2011 University of Utah and the Flux Group.
# All rights reserved.
# Copyright (c) 2010-2020 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
# This file is part of the Emulab network testbed software.
#
# This file is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
#
# This file is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
# License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this file. If not, see <http://www.gnu.org/licenses/>.
#
# }}}
#
use English;
use strict;
......@@ -104,14 +121,14 @@ sub DumpUser($)
"optional" => 0 },
"email" => {"tag" => "email",
"optional" => 0 },
"pswd" => {"tag" => "password",
"pswd" => {"tag" => "passhash",
"optional" => 0 },
"uid" => {"tag" => "uid",
"optional" => 0 },
"URL" => {"tag" => "URL",
"optional" => 1 },
"addr" => {"tag" => "address",
"optional" => 0 },
"optional" => 1 },
"addr2" => {"tag" => "address2",
"optional" => 1 },
"city" => {"tag" => "city",
......@@ -119,13 +136,13 @@ sub DumpUser($)
"state" => {"tag" => "state",
"optional" => 0 },
"zip" => {"tag" => "zip",
"optional" => 0 },
"optional" => 1 },
"country" => {"tag" => "country",
"optional" => 0 },
"phone" => {"tag" => "phone",
"optional" => 0 },
"optional" => 1 },
"title" => {"tag" => "title",
"optional" => 0 },
"optional" => 1 },
"affil" => {"tag" => "affiliation",
"optional" => 0 },
"shell" => {"tag" => "shell",
......@@ -161,6 +178,9 @@ sub DumpUser($)
# Pubkeys are special.
if (@keys) {
foreach my $key (@keys) {
next
if ($key =~ /^ssh-dss/);
print "<pubkeys>$key</pubkeys>\n";
}
}
......
#!/usr/bin/perl -w
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2005 University of Utah and the Flux Group.
# All rights reserved.
#
# {{{EMULAB-LICENSE
#
# This file is part of the Emulab network testbed software.
#
# This file is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
#
# This file is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
# License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this file. If not, see <http://www.gnu.org/licenses/>.
#
# }}}
#
use English;
use Getopt::Std;
......
#!/usr/bin/perl -w
#
# Copyright (c) 2005-2022 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
# This file is part of the Emulab network testbed software.
#
# This file is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
#
# This file is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
# License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this file. If not, see <http://www.gnu.org/licenses/>.
#
# }}}
#
use English;
use strict;
use Getopt::Std;
use Data::Dumper;
use File::Temp qw(tempfile);
use JSON;
#
# Ask https://ipinfo.io/ for IP info
#
# select cc.country,sum(t.count) as count from
# (select country,count(distinct(uid)) as count from login_history
# where IP is not null and location is not null and portal='cloudlab'
# group by country,uid) as t
# left join ccodes.ccodes as cc on cc.code=t.country
# group by cc.country order by count desc;
#
#select region,sum(t.count) as count from
# (select region,count(distinct(uid)) as count from login_history
# where IP is not null and location is not null and country='US' and
# portal='cloudlab'
# group by region,uid) as t
#group by region order by count desc;
#
#
sub usage()
{
print "Usage: getipinfo [-n]\n";
print " getipinfo [-n] -p portal\n";
exit(1);
}
my $optlist = "ndp:";
my $impotent = 0;
my $debug = 0;
my $limit = 200;
#
# Configure variables
#
my $TB = "@prefix@";
my $token = "850749cc3b77dc";
my $URL = "http://ipinfo.io/batch?token=${token}";
my $CURL = "/usr/local/bin/curl";
# Load the Testbed support stuff.
use lib "@prefix@/lib";
use emdb;
use User;
use emutil;
# Protos
sub fatal($);
sub WriteResults($);
#
# Turn off line buffering on output
#
$| = 1;
my %options = ();
if (! getopts($optlist, \%options)) {
usage();
}
if (defined($options{"n"})) {
$impotent++;
}
if (defined($options{"d"})) {
$debug++;
}
if (defined($options{"p"})) {
my $portal = $options{"p"};
if ($portal ne "cloudlab" && $portal ne "powder") {
fatal("Only cloudlab or powder portal please");
}
exit(WriteResults($portal));
}
#
# Find unmatched IPs in the login_history table and batch them up
# for the request.
#
my $count = 0;
while ($limit) {
$limit--;
my $query_result =
DBQueryFatal("select distinct IP from login_history ".
"where location is null and IP is not null ".
"limit 100");
last
if ($query_result->numrows == 0);
my %IPs = ();
while (my ($IP) = $query_result->fetchrow_array()) {
$IPs{$IP} = $IP;
}
if (keys(%IPs)) {
# Create a temporary files for curl
my ($fpIn, $fnameIn) = tempfile("/tmp/iplistInXXXXX", UNLINK => 0);
if (!defined($fpIn)) {
fatal("Could not create temp file for IPs");
}
my ($fpOut, $fnameOut) = tempfile("/tmp/iplistOutXXXXX", UNLINK => 0);
if (!defined($fpOut)) {
fatal("Could not create temp file for IPs");
}
foreach my $IP (keys(%IPs)) {
print $fpIn "$IP\n";
}
my $command =
"$CURL -s -o $fnameOut -XPOST --data-binary \@${fnameIn} $URL";
if ($debug) {
print "$command\n";
}
system($command);
if ($?) {
fatal("curl failure: '$command'\n");
}
my $json = emutil::ReadFile($fnameOut);
if (!$json || $json eq "") {
fatal("No json received");
}
my $results = eval { decode_json($json) };
if ($@) {
fatal("Could not decode json data");
}
if ($debug) {
print Dumper($results);
}
foreach my $IP (keys(%IPs)) {
my $ref = $results->{$IP};
if (!defined($ref)) {
print STDERR "No data for $IP\n";
next;
}
my $loc = $ref->{'loc'};
my $country = $ref->{'country'};
my $region = $ref->{'region'};
if (!defined($loc)) {
print STDERR "No data for $IP\n";
DBQueryFatal("update login_history set ".
" location='' ".
"where IP='$IP'");
next;
}
$count++;
if ($impotent) {
print "Would set $IP: $loc,$country,$region\n";
next;
}
else {
print "$IP: $loc,$country,$region\n";
DBQueryFatal("update login_history set ".
" location=" . DBQuoteSpecial($loc) . ", ".
" country=" . DBQuoteSpecial($country) . ", ".
" region=" . DBQuoteSpecial($region) . " ".
"where IP='$IP'");
}
}
unlink($fnameIn);
unlink($fnameOut);
}
print "$count IPs completed\n";
last
if (!$count);
sleep(10);
}
exit(0);
#
# Write per portal results files. Queries take a while.
#
sub WriteResults($)
{
my ($portal) = @_;
print "These queries take time, get a cup of coffee.\n";
my $query_result =
DBQueryFatal("select cc.country,sum(t.count) as count from ".
" (select country,count(distinct(uid)) as count ".
" from login_history ".
" where IP is not null and location is not null and ".
" portal='$portal' ".
" group by country,uid) as t ".
"left join ccodes.ccodes as cc on cc.code=t.country ".
"group by cc.country order by count desc");
my $fname = "world-counts-${portal}.csv";
print "Writing $fname ... \n";
if (open(WORLD, ">$fname")) {
print WORLD "name,count\n";
while (my ($country,$count) = $query_result->fetchrow_array()) {
next
if (!defined($country));
$country = "USA"
if ($country eq "United States");
print WORLD "$country,$count\n";
}
close(WORLD);
}
else {
fatal("Could not open $fname for writing: $!\n");
}
$query_result =
DBQueryFatal("select region,sum(t.count) as count from ".
" (select region,count(distinct(uid)) as count ".
" from login_history ".
" where IP is not null and location is not null and ".
" country='US' and portal='$portal' ".
" group by region,uid) as t ".
"group by region order by count desc");
$fname = "us-counts-${portal}.csv";
print "Writing $fname ... \n";
if (open(STATES, ">$fname")) {
print STATES "name,count\n";
while (my ($region,$count) = $query_result->fetchrow_array()) {
next
if (!defined($region));
print STATES "$region,$count\n";
}
close(STATES);
}
else {
fatal("Could not open $fname for writing: $!\n");
}
exit(0);
}
sub fatal($) {
my($mesg) = $_[0];
die("*** $0:\n".
" $mesg\n");
}
#!/usr/bin/perl -w
#
# GENIPUBLIC-COPYRIGHT
# Copyright (c) 2010-2011 University of Utah and the Flux Group.
# All rights reserved.
# Copyright (c) 2010-2016, 2019 University of Utah and the Flux Group.
#
# {{{GENIPUBLIC-LICENSE
#
# GENI Public License
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and/or hardware specification (the "Work") to
# deal in the Work without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Work, and to permit persons to whom the Work
# is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Work.
#
# THE WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE WORK OR THE USE OR OTHER DEALINGS
# IN THE WORK.
#
# }}}
#
use strict;
use English;
......@@ -26,10 +49,12 @@ sub usage()
print " manageremote addgroup <remote> <gid>\n";
exit(1);
}
my $optlist = "dnf";
my $optlist = "dnfp";
my $debug = 0;
my $force = 0;
my $impotent = 0;
my $locked = 0;
my $fromdaemon = 0;
#
# Function prototypes
......@@ -39,7 +64,7 @@ sub AddUser(;$);
sub AddPeer();
sub DeleteUser();
sub ModifyUser();
sub SetGroups();
sub SetGroups(;$);
sub CrossLogin();
sub AddProject();
sub AddGroup();
......@@ -53,8 +78,8 @@ my $TB = "@prefix@";
my $TBOPS = "@TBOPSEMAIL@";
my $TBLOGS = "@TBLOGSEMAIL@";
my $PGENISUPPORT = @PROTOGENI_SUPPORT@;
my $PORTAL_ENABLE = @PORTAL_ENABLE@;
my $PORTAL_PRIMARY= @PORTAL_ISPRIMARY@;
my $PEER_ENABLE = @PEER_ENABLE@;
my $PEER_PRIMARY = @PEER_ISPRIMARY@;
my $OURDOMAIN = "@OURDOMAIN@";
my $DUMPUSER = "$TB/sbin/dumpuser";
my $DUMPPROJ = "$TB/sbin/dumpproject";
......@@ -98,17 +123,20 @@ if (defined($options{"f"})) {
if (defined($options{"n"})) {
$impotent = 1;
}
if (defined($options{"p"})) {
$fromdaemon = 1;
}
usage()
if (@ARGV < 2 || @ARGV > 4);
if (@ARGV < 2 || @ARGV > 5);
my $cmd = shift(@ARGV);
my $peername = shift(@ARGV);
my $peerurn;
if (! $PORTAL_ENABLE) {
fatal("Portal mode is not enabled");
if (! $PEER_ENABLE) {
fatal("Peer mode is not enabled");
}
if (! ($PORTAL_PRIMARY || $cmd eq "addpeer")) {
if (! ($PEER_PRIMARY || $cmd eq "addpeer")) {
fatal("You can only run addpeer on this boss");
}
......@@ -147,26 +175,36 @@ my $credential = GeniCredential->GetSelfCredential($me);
if (!defined($credential)) {
fatal("Could not create self credential for $me");
}
my $authority;
#
# All operations other then AddPeer require that the peer be
# in the DB.
#
if ($cmd eq "addpeer") {
AddPeer();
exit(0);
}
else {
if ($cmd ne "addpeer") {
my $query_result =
DBQueryFatal("select name,urn from emulab_peers ".
"where name='$peername' or urn='$peername'");
fatal("Unknown peer")
if (!$query_result->numrows);
($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 peer_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;
}
#
......@@ -181,6 +219,10 @@ SWITCH: for ($cmd) {
AddUser();
last SWITCH;
};
/^addpeer$/ && do {
AddPeer();
last SWITCH;
};
/^deluser$/ && do {
DeleteUser();
last SWITCH;
......@@ -207,8 +249,12 @@ SWITCH: for ($cmd) {
};
# Default
TBScriptUnlock()
if ($locked);
usage();
}
TBScriptUnlock()
if ($locked);
exit(0);
#
......@@ -292,8 +338,9 @@ sub AddUser(;$)
}
my $urn = GeniHRN::Generate($OURDOMAIN, "user", $user->uid());
my $xmlgoo = emutil::ExecQuiet("$DUMPUSER -p $uid");
my $xmlgoo = emutil::ExecQuiet("$DUMPUSER $uid");
if ($?) {
print STDERR "$xmlgoo";
fatal("$DUMPUSER failed");
}
my $args = {"xmlstring" => $xmlgoo,
......@@ -370,7 +417,7 @@ sub ModifyUser()
}
my $urn = GeniHRN::Generate($OURDOMAIN, "user", $user->uid());
my $xmlgoo = emutil::ExecQuiet("$DUMPUSER -p $uid");
my $xmlgoo = emutil::ExecQuiet("$DUMPUSER $uid");
if ($?) {
fatal("$DUMPUSER failed");
}
......@@ -545,9 +592,7 @@ sub AddProject()
" exported=now(), updated=now(), ".
" peer='$peername'");
if (!$leader_result->numrows) {
SetGroups($leader_idx);
}
SetGroups($leader_idx);
return 0;
}
......
#!/usr/bin/perl -w
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2011 University of Utah and the Flux Group.
# All rights reserved.
# Copyright (c) 2000-2024 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
# This file is part of the Emulab network testbed software.
#
# This file is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
#
# This file is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
# License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this file. If not, see <http://www.gnu.org/licenses/>.
#
# }}}
#
use strict;
use English;
use Getopt::Long;
use Getopt::Long qw(:config no_ignore_case);
use POSIX qw(strftime);
use Date::Parse;
#
# Load the Testbed support stuff.
......@@ -24,7 +42,7 @@ sub usage()
{
print("Usage: mksyscert [-d] [-o file] [-p password] [-e email] ".
"[-u url] [-i urn] [-k keyfile] [-a authority] <orgunit> " .
"[-n] [uuid]\n");
"[-n] [-U] [uuid]\n");
exit(-1);
}
my $debug = 0;
......@@ -37,6 +55,8 @@ my $urn;
my $oldkeyfile;
my $authority;
my $notca = 0;
my $days = 2000;
my $include_uuid = 0;
my %optlist = ( "debug" => \$debug,
"password=s" => \$password,
"output=s" => \$outfile,
......@@ -46,6 +66,7 @@ my %optlist = ( "debug" => \$debug,
"identifier=s" => \$urn,
"keyfile=s" => \$oldkeyfile,
"authority=s" => \$authority,
"UUID" => \$include_uuid,
"notca" => \$notca );
#
......@@ -66,6 +87,7 @@ my $EMULAB_CERT = "$TB/etc/emulab.pem";
my $EMULAB_KEY = "$TB/etc/emulab.key";
my $OPENSSL = "/usr/bin/openssl";
my $WORKDIR = "$TB/ssl";
my $RANDFILE = "./.rnd";
my $SAVEUID = $UID;
my $certfile = $EMULAB_CERT;
my $keyfile = $EMULAB_KEY;
......@@ -186,6 +208,22 @@ if (!defined($email)) {
chdir("$WORKDIR") or
fatal("Could not chdir to $WORKDIR: $!");
#
# Some sillyness to deal with changes to .rnd file handling across
# versions of openssl.
#
if (! -e $RANDFILE) {
system("/bin/dd if=/dev/urandom of=${RANDFILE} bs=256 count=4");
if ($?) {
fatal("Could not generate $RANDFILE");
}
}
#
# Older versions of openssl ignore -rand option, but use this environment
# variable. New versions ignore the environment variable but use -rand.
#
$ENV{"RANDFILE"} = $RANDFILE;
#
# Need an index file, which is the openssl version of the DB.
#
......@@ -230,7 +268,9 @@ if (@urls) {
# unregistered OID 2.25.305821105408246119474742976030998643995
# (corresponding to UUID e61300a0-c4c5-11de-b14e-0002a5d5c51b)
# is used to indicate generic ProtoGENI XMLRPC servers.
print TEMP "authorityInfoAccess=2.25.305821105408246119474742976030998643995;URI:$_\n";
# print TEMP "authorityInfoAccess=2.25.305821105408246119474742976030998643995;URI:$_\n";
print TEMP
"authorityInfoAccess=2.25.305821105.408246119.47474297.603099864.3995;URI:$_\n";
}
}
......@@ -247,7 +287,10 @@ print TEMP "emailAddress\t= $email\n";
if (defined($urn)) {
print TEMP "\n";
print TEMP "[ req_altname ]\n";
print TEMP "URI=$urn\n";
print TEMP "URI.1=$urn\n";
if( $include_uuid ) {
print TEMP "URI.2=urn:uuid:$uuid\n";
}
print TEMP "\n";
}
......@@ -265,15 +308,29 @@ if( defined( $oldkeyfile ) ) {
($encrypted ? " -passout 'pass:${sh_password}' " : " -nodes ") .
" -out syscert_req.pem $outline") == 0
or fatal("Could not create certificate request");
system("cp $oldkeyfile syscert_key.pem");
system("$OPENSSL rsa -in $oldkeyfile -out syscert_key.pem $outline") == 0
or fatal("Could not suck key out of old keyfile");
} else {
#
# Create a client side private key and certificate request.
#
system("$OPENSSL req -text -new -config syscert.cnf ".
($encrypted ? " -passout 'pass:${sh_password}' " : " -nodes ") .
" -keyout syscert_key.pem -out syscert_req.pem $outline") == 0
or fatal("Could not create certificate request");
my $genopts = " -rand $RANDFILE " .
($encrypted ? " -passout 'pass:${sh_password}' -des3 " : "");
my $output =
emutil::ExecQuiet("$OPENSSL genrsa $genopts -out syscert_key.pem 2048");
if ($?) {
print STDERR $output;
fatal("Could generate new key");
}
$output =
emutil::ExecQuiet("$OPENSSL req -text -new -config syscert.cnf ".
($encrypted ? " -passin 'pass:${sh_password}' " : "") .
" -key syscert_key.pem -out syscert_req.pem $outline");
if ($?) {
print STDERR $output;
fatal("Could not create certificate request");
}
}
#
......@@ -283,8 +340,45 @@ if( defined( $oldkeyfile ) ) {
#
my $startdate = POSIX::strftime("%y%m%d%H%M%SZ", gmtime(time() - 3600));
#
# Check the expiration on the CA cert, we do not want the new
# certificate to expire after the CA (signer) cert expires.
#
$UID = 0;
my $expires = `$OPENSSL x509 -enddate -noout -in $certfile`;
if ($?) {
fatal("Could not get expiration from $certfile");
}
if ($expires =~ /^notAfter=(.*)$/i) {
my $tmp = str2time($1);
if (!defined($tmp)) {
fatal("Could not convert $certfile expiration to time: $1");
}
$expires = $tmp;
}
else {
fatal("Could not parse $certfile expiration: $expires");
}
if ($expires < time()) {
fatal("$certfile certificate has expired!");
}
# If the CA expires in less then 30 days, grind to a halt.
my $daystoexpire = int(($expires - time()) / (3600 * 24));
if ($daystoexpire <= 30) {
fatal("Refusing to sign new certificate; the $certfile expires in less ".
"then 30 days!");
}
if ($debug) {
print "CA certificate expires in $daystoexpire days.\n";
}
if ($days > $daystoexpire) {
$days = $daystoexpire - 1;
print "Shortening certificate expiration to $days days\n";
}
system("$OPENSSL ca -batch -policy policy_sslxmlrpc -startdate $startdate ".
" -days $days ".
" -name CA_syscerts -config $CACONFIG ".
" -out syscert_cert.pem -cert $certfile -keyfile $keyfile ".
" -infiles syscert_req.pem $outline") == 0
......
#!/usr/bin/perl -wT
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2012 University of Utah and the Flux Group.
# All rights reserved.
# Copyright (c) 2000-2024 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
# This file is part of the Emulab network testbed software.
#
# This file is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
#
# This file is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
# License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this file. If not, see <http://www.gnu.org/licenses/>.
#
# }}}
#
use strict;
use English;
use Getopt::Std;
use Date::Parse;
#
# Load the Testbed support stuff.
......@@ -26,7 +44,7 @@ sub usage()
print("Usage: mkusercert [-d] [-o] [-r] [-g] [-p password] <user>\n");
exit(-1);
}
my $optlist = "dp:ogrc:";
my $optlist = "dp:ogrc:CPG";
my $debug = 0;
my $output = 0;
my $password = "";
......@@ -46,6 +64,7 @@ my $PGENISUPPORT= @PROTOGENI_SUPPORT@;
my $CONTROL = "@USERNODE@";
my $BOSSNODE = "@BOSSNODE@";
my $OU = "sslxmlrpc"; # orgunit
my $RANDFILE = "./.rnd";
# Locals
my $USERDIR = USERROOT();
......@@ -57,6 +76,8 @@ my $EMULAB_KEY = "$TB/etc/emulab.key";
my $OPENSSL = "/usr/bin/openssl";
my $KEYGEN = "/usr/bin/ssh-keygen";
my $ADDKEY = "$TB/sbin/addpubkey";
my $SSH = "$TB/bin/sshtb";
my $ACCOUNTPROXY= "$TB/sbin/accountsetup";
my $WORKDIR = "$TB/ssl";
my $SAVEUID = $UID;
......@@ -131,38 +152,8 @@ if (defined($options{"r"})) {
if (defined($options{"g"})) {
$geniflag = 1;
}
if (defined($options{"p"})) {
$password = $options{"p"};
#
# Make sure its all escaped since any printable char is allowed.
#
if ($password =~ /^([\040-\176]*)$/) {
$password = $1;
}
else {
die("Tainted argument: $password\n");
}
$db_password = DBQuoteSpecial($password);
$sh_password = $password;
$sh_password =~ s/\'/\'\\\'\'/g;
$sh_password = "$sh_password";
if (defined($options{"p"}) || defined($options{"P"})) {
$encrypted = 1;
$days = 365;
}
if (defined($options{"c"})) {
$old_password = $options{"c"};
#
# Make sure its all escaped since any printable char is allowed.
#
if ($old_password =~ /^([\040-\176]*)$/) {
$old_password = $1;
}
else {
die("Tainted argument: $old_password\n");
}
$old_password =~ s/\'/\'\\\'\'/g;
}
if (@ARGV != 1) {
usage();
......@@ -185,6 +176,15 @@ else {
die("Tainted argument: $user\n");
}
# Figure out what version of OpenSSL
my $sslversion = `$OPENSSL version`;
if ($sslversion =~ /^OpenSSL\s+(\d+)\.(\d+)\./) {
$sslversion = "$1.$2";
} else {
print STDERR "Cannot parse OpenSSL version, assuming 1.0\n";
$sslversion = "1.0";
}
# Map target user to object.
my $target_user = User->Lookup($user);
if (! defined($target_user)) {
......@@ -197,6 +197,61 @@ if (! defined($this_user)) {
fatal("You ($UID) do not exist!");
}
if (defined($options{"p"}) || defined($options{"P"})) {
if (defined($options{"p"})) {
$password = $options{"p"};
}
elsif ($target_user->SSLPassPhrase(1, \$password)) {
if (defined($options{"G"})) {
$password = substr(TBGenSecretKey(), 0, 12);
if (!defined($password) || $password eq "") {
fatal("Could not generate a random passphrase for -P -G");
}
}
else {
fatal("No stored passphrase for -P option");
}
}
#
# Make sure its all escaped since any printable char is allowed.
#
if ($password =~ /^([\040-\176]*)$/) {
$password = $1;
}
else {
die("Tainted argument: $password\n");
}
$db_password = DBQuoteSpecial($password);
$sh_password = $password;
$sh_password =~ s/\'/\'\\\'\'/g;
$sh_password = "$sh_password";
}
# This option is for changing the passphrase on existing key.
# Might need the target user (-C options).
if (defined($options{"c"}) || defined($options{"C"})) {
if (defined($options{"c"})) {
$old_password = $options{"c"};
}
elsif ($target_user->SSLPassPhrase(1, \$old_password)) {
$old_password = undef;
}
if (defined($old_password)) {
#
# Make sure its all escaped since any printable char is allowed.
#
if ($old_password =~ /^([\040-\176]*)$/) {
$old_password = $1;
}
else {
fatal("Tainted password: $old_password");
}
$old_password =~ s/\'/\'\\\'\'/g;
}
}
#
# CD to the workdir, and then serialize on the lock file since there is
# some shared goop that the ssl tools muck with (serial number, index, etc.).
......@@ -207,6 +262,22 @@ chdir("$WORKDIR") or
TBScriptLock("mkusercert") == 0 or
fatal("Could not get the lock!");
#
# Some sillyness to deal with changes to .rnd file handling across
# versions of openssl.
#
if (! -e $RANDFILE) {
system("/bin/dd if=/dev/urandom of=${RANDFILE} bs=256 count=4");
if ($?) {
fatal("Could not generate $RANDFILE");
}
}
#
# Older versions of openssl ignore -rand option, but use this environment
# variable. New versions ignore the environment variable but use -rand.
#
$ENV{"RANDFILE"} = $RANDFILE;
#
# Create a client side cert. Reuse the original key if are told to,
# and it actually exists, and the password is valid.
......@@ -241,11 +312,7 @@ if ($reusekey) {
UserFatal("Cannot decrypt private key. Correct pass phrase?");
}
$reqargs = "-key usercert_key.pem -passin 'pass:${sh_password}' ";
}
else {
newkey:
$reqargs = "-keyout usercert_key.pem";
$reqargs .= ($encrypted ? " -passout 'pass:${sh_password}' " : " -nodes ")
}
#
......@@ -326,7 +393,7 @@ sub CreateNewCert() {
# (corresponding to UUID e61300a0-c4c5-11de-b14e-0002a5d5c51b)
# is used to indicate generic ProtoGENI XMLRPC servers.
print TEMP
"authorityInfoAccess=2.25.305821105408246119474742976030998643995;URI:$url\n";
"authorityInfoAccess=2.25.305821105.408246119.47474297.603099864.3995;URI:$url\n";
}
print TEMP "\n";
......@@ -345,8 +412,10 @@ sub CreateNewCert() {
print TEMP "CN\t\t= $user_uuid\n";
print TEMP "emailAddress\t= $user_uid" . "\@" . "$OURDOMAIN\n";
print TEMP "\n[ req_altname ]\nURI=urn:publicid:IDN+$OURDOMAIN" .
"+user+$user_uid\nemail=$user_uid" . "\@" . "$OURDOMAIN\n\n";
print TEMP "\n[ req_altname ]\nURI.1=urn:publicid:IDN+$OURDOMAIN" .
"+user+$user_uid\n" .
"email=$user_uid" . "\@" . "$OURDOMAIN\n" .
"URI.2=urn:uuid:$user_uuid\n\n";
close(TEMP)
or fatal("Could not close usercert.cnf: $!");
......@@ -354,14 +423,59 @@ sub CreateNewCert() {
#
# Create a client side private key and certificate request.
#
system("$OPENSSL req -new -config usercert.cnf ".
"$reqargs -out usercert_req.pem") == 0
or fatal("Could not create certificate request");
if (!$reusekey) {
my $genopts = " -rand $RANDFILE " .
($encrypted ? " -passout 'pass:${sh_password}' -des3 " : "");
system("$OPENSSL genrsa $genopts -out usercert_key.pem 2048")
== 0 or fatal("Could not generate new key");
}
my $reqopts = ($encrypted ? "-passin 'pass:${sh_password}' " : "");
system("$OPENSSL req $reqopts -new -config usercert.cnf ".
"-key usercert_key.pem -out usercert_req.pem")
== 0 or fatal("Could not create certificate request");
#
# Sign the client cert request, creating a client certificate.
# Check the expiration on the CA cert, we do not want the new
# certificate to expire after the CA (signer) cert expires.
#
$UID = 0;
my $expires = `$OPENSSL x509 -enddate -noout -in $EMULAB_CERT`;
if ($?) {
fatal("Could not get expiration from $EMULAB_CERT");
}
if ($expires =~ /^notAfter=(.*)$/i) {
my $tmp = str2time($1);
if (!defined($tmp)) {
fatal("Could not convert CA expiration to time: $1");
}
$expires = $tmp;
}
else {
fatal("Could not parse CA expiration: $expires");
}
if ($expires < time()) {
fatal("CA certificate has expired!");
}
# If the CA expires in less then 30 days, grind to a halt.
my $daystoexpire = int(($expires - time()) / (3600 * 24));
if ($daystoexpire <= 30) {
fatal("Refusing to sign new certificate; the CA expires in less ".
"then 30 days!");
}
if ($debug) {
print "CA certificate expires in $daystoexpire days.\n";
}
if ($days > $daystoexpire) {
$days = $daystoexpire - 1;
print "Shortening certificate expiration to $days days\n";
}
#
# Sign the client cert request, creating a client certificate.
#
system("$OPENSSL ca -batch -policy policy_sslxmlrpc -days $days ".
" -name CA_usercerts -config $CACONFIG ".
" -out usercert_cert.pem -cert $EMULAB_CERT -keyfile $EMULAB_KEY ".
......@@ -373,9 +487,13 @@ sub CreateNewCert() {
# We store the DN in the DB too, for creating the crl index file without
# having to reparse all the certs.
#
my $DN = `$OPENSSL x509 -subject -noout -in usercert_cert.pem`;
my $args = "-subject -noout";
if ($sslversion > 1.0) {
$args .= " -nameopt=compat";
}
my $DN = `$OPENSSL x509 $args -in usercert_cert.pem`;
chomp($DN);
if ($DN =~ /^subject=\s*(\/[-\/\=\w\@\.\s]+)$/) {
if ($DN =~ /^subject=\s*(\/[-\/\=\w\@\.,\s]+)$/) {
$DN = $1;
}
else {
......@@ -547,32 +665,15 @@ else {
CreateNewCert();
}
#
# Copy the certificate to the users .ssl directory.
#
# Drop the file into the user .ssl directory.
my $ssldir = "$USERDIR/$user_uid/.ssl";
if (! -d $ssldir) {
mkdir($ssldir, 0700) or
fatal("Could not mkdir $ssldir: $!");
chown($user_number, $default_groupgid, $ssldir)
or fatal("Could not chown $ssldir: $!");
}
my $target;
if ($encrypted) {
$target = "$ssldir/encrypted.pem";
}
else {
$target = "$ssldir/emulab.pem";
}
system("cp -f usercert.pem $target") == 0
or fatal("Could not copy usercert.pem to $target");
chown($user_number, $default_groupgid, "$target")
or fatal("Could not chown $target: $!");
$UID = $EUID;
system("$SSH -host $CONTROL ".
"'$ACCOUNTPROXY dropfile $user_uid $default_groupgid 0600 $ssldir ".
($encrypted ? "encrypted.pem" : "emulab.pem") . "' < usercert.pem") == 0
or fatal("Could not copy certificate file to $CONTROL");
$UID = $SAVEUID;
if ($encrypted) {
#
......@@ -581,25 +682,25 @@ if ($encrypted) {
#
system("$OPENSSL pkcs12 -export -in usercert.pem -des3 ".
"-passin 'pass:${sh_password}' -passout 'pass:${sh_password}' ".
"-out usercert.p12 -rand ./.rnd")
"-out usercert.p12 -rand $RANDFILE")
== 0 or fatal("Could not create usercert.p12");
$target = "$ssldir/encrypted.p12";
system("cp -f usercert.p12 $target") == 0
or fatal("Could not copy usercert.p12 to $target");
chown($user_number, $default_groupgid, "$target")
or fatal("Could not chown $target: $!");
# Drop the file into the user .ssl directory.
$UID = $EUID;
system("$SSH -host $CONTROL ".
"'$ACCOUNTPROXY dropfile $user_uid $default_groupgid 0600 $ssldir ".
"encrypted.p12' < usercert.p12")
== 0 or fatal("Could not copy .p12 file to $CONTROL");
$UID = $SAVEUID;
chmod(0600, $target)
or fatal("Could not chmod $target: $!");
goto skipssh
if ($target_user->IsNonLocal());
#
# Create an SSH key from the private key. Mostly for geni users,
# who tend not to know how to do such things.
#
my $pemfile = "$ssldir/encrypted.pem";
my $pemfile = "usercert.pem";
my $sshdir = "$USERDIR/$user_uid/.ssh";
my $pphrase = User::escapeshellarg($password);
# This comment is special. It functions as a cross table reference
......@@ -613,10 +714,12 @@ if ($encrypted) {
#
# The key format is identical to openssh, so just copy it over.
#
system("/bin/cp usercert_key.pem $sshdir/encrypted.key") == 0
or fatal("Could not copy private key to $sshdir/encrypted.key: $!");
chmod(0600, "$sshdir/encrypted.key")
or fatal("Could not chmod $sshdir/encrypted.key: $!");
$UID = $EUID;
system("$SSH -host $CONTROL '$ACCOUNTPROXY ".
" dropfile $user_uid $default_groupgid 0600 $sshdir ".
" encrypted.key' < usercert_key.pem")
== 0 or fatal("Could not copy ssh key file to $CONTROL");
$UID = $SAVEUID;
#
# No need to do this when just changing the passphrase.
......@@ -625,19 +728,35 @@ if ($encrypted) {
#
# Extract a public key.
#
system("$KEYGEN -P $pphrase -y -f $pemfile > $sshdir/encrypted.pub")
system("$KEYGEN -P $pphrase -y -f $pemfile > encrypted.pub")
== 0
or fatal("Could not extract ssh pubkey from $pemfile");
$UID = $EUID;
system("$SSH -host $CONTROL '$ACCOUNTPROXY ".
" dropfile $user_uid $default_groupgid 0644 $sshdir ".
" encrypted.pub' < encrypted.pub")
== 0 or fatal("Could not copy ssh pub key file to $CONTROL");
$UID = $SAVEUID;
#
# Need to remove the current ssh pubkey from the database, but we just
# updated the new serial number so the comment is no longer valid for
# lookup.
#
$target_user->DeleteSSLCertSSHKey();
#
# And add the pubkey to the DB. Mark it as nodelete and that it should
# remove existing key with same comment.
# And add the pubkey to the DB. Mark it as nodelete and
# as internal since we do not want to delete these except when
# creating a new certificate.
#
$EUID = $UID;
system("$ADDKEY -s -N -R -C $comment -u $user_uid ".
" -f $sshdir/encrypted.pub")
== 0 or fatal("Could not add pubkey $sshdir/encrypted.pub");
system("$ADDKEY -s -N -I -C $comment -u $user_uid ".
" -f encrypted.pub")
== 0 or fatal("Could not add ssh pubkey");
}
skipssh:
}
TBScriptUnlock();
......
#!/usr/bin/perl -wT
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2011 University of Utah and the Flux Group.
# All rights reserved.
# Copyright (c) 2000-2021, 2024 University of Utah and the Flux Group.
#
# {{{EMULAB-LICENSE
#
# This file is part of the Emulab network testbed software.
#
# This file is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at
# your option) any later version.
#
# This file is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
# License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this file. If not, see <http://www.gnu.org/licenses/>.
#
# }}}
#
use English;
use strict;
use Getopt::Std;
use XML::Simple;
use Data::Dumper;
use Cwd qw(realpath);
#
# Create a new user from a XML description.
......@@ -24,7 +42,10 @@ my $debug = 0;
my $nonlocal= 0;
my $impotent= 0;
my $silent = 0;
my $portal;
my $resend;
my %licenses = ();
my %nsf_awards = ();
#
# Configure variables
......@@ -34,6 +55,7 @@ my $TBOPS = "@TBOPSEMAIL@";
my $TBAUDIT = "@TBAUDITEMAIL@";
my $TBBASE = "@TBBASE@";
my $TBWWW = "@TBWWW@";
my $LICENSES = "$TB/sbin/manage_licenses";
#
# This script is setuid, so please do not run it as root. Hard to track
......@@ -63,6 +85,7 @@ use libdb;
use libtestbed;
use Project;
use User;
use Brand;
# Protos
sub fatal($);
......@@ -150,7 +173,7 @@ if (! defined($this_user)) {
}
# Use realpath to resolve any symlinks.
my $translated = `realpath $xmlfile`;
my $translated = realpath($xmlfile);
if ($translated =~ /^(\/tmp\/[-\w\.\/]+)$/) {
$xmlfile = $1;
}
......@@ -185,8 +208,13 @@ my %optional = ("newuser_xml" => "newuser_xml",
"members" => "num_members",
"ron" => "num_ron",
"plab" => "num_pcplab",
"class" => "forClass",
"whynotpublic" => "public_whynot",
"user_interface" => "default_user_interface");
"user_interface" => "default_user_interface",
"nsf_funded" => "nsf_funded",
"nsf_awards" => "nsf_awards",
"nsf_supplement" => "nsf_supplement",
);
#
# This script is not audited cause we want the output to be sent back
......@@ -204,12 +232,37 @@ my $xmlparse = eval { XMLin($xmlfile,
fatal($@)
if ($@);
# APT flag. Notice and delete.
if (exists($xmlparse->{'attribute'}->{"portal"})) {
$portal = $xmlparse->{'attribute'}->{"portal"}->{'value'};
delete($xmlparse->{'attribute'}->{"portal"});
my $brand = Brand->Create($portal);
if (!defined($brand)) {
fatal("Bad portal: $portal");
}
}
# Licenses. Save for later, but need to delete.
foreach my $key (keys(%{ $xmlparse->{'attribute'} })) {
if ($key =~ /^license_([-\w]+)$/) {
my $value = $xmlparse->{'attribute'}->{"$key"}->{'value'};
my $name = $1;
if (lc($value) eq "yes") {
system("$LICENSES show $name");
if ($?) {
fatal("Invalid license name: $name");
}
$licenses{$name} = $name;
print "requested license $name\n";
}
delete($xmlparse->{'attribute'}->{"$key"});
}
}
#
# Make sure all the required arguments were provided.
#
foreach my $key (keys(%required)) {
fatal("Missing required attribute '$key'")
if (! exists($xmlparse->{'attribute'}->{"$key"}));
}
......@@ -287,7 +340,7 @@ if (exists($newproj_args{'newuser_xml'})) {
}
# Use realpath to resolve any symlinks.
my $translated = `realpath $newuser_xml`;
my $translated = realpath($newuser_xml);
if ($translated =~ /^(\/tmp\/[-\w\.\/]+)$/) {
$newuser_xml = $1;
}
......@@ -309,8 +362,12 @@ if (exists($newproj_args{'newuser_xml'})) {
print $cmd . "\n"
if ($debug);
my $cmd_out = `$cmd`;
UserError("Transient Error: (3, $?, $cmd) $cmd_out")
if ($?);
if ($?) {
if (($? >> 8) > 0) {
UserError($cmd_out);
}
fatal("Error creating new user: (3, $?, $cmd) $cmd_out");
}
#
# Parse the last line of output. Ick.
......@@ -322,16 +379,45 @@ if (exists($newproj_args{'newuser_xml'})) {
$newproj_args{'head_uid'} = $2;
}
# NSF award. Only one allowed. Change later.
if (exists($newproj_args{'nsf_funded'})) {
my $funded = $newproj_args{'nsf_funded'};
if ($funded == 1) {
my $award = $newproj_args{'nsf_awards'};
my $sup = $newproj_args{'nsf_supplement'};
$nsf_awards{$award} = $sup;
}
delete($newproj_args{'nsf_funded'});
delete($newproj_args{'nsf_awards'});
delete($newproj_args{'nsf_supplement'});
}
if (exists($newproj_args{'forClass'}) && $newproj_args{'forClass'} == 1) {
$newproj_args{'shared_reservations'} = 1;
}
else {
$newproj_args{'shared_reservations'} = 0;
}
#
# Now do special checks.
#
UserError("Project already exists; pick another name!")
if (Project->Lookup($newproj_args{'pid'}));
my $leader = User->Lookup($newproj_args{'head_uid'});
UserError("Project leader does not exist!")
if (!defined($leader));
#
# Need a big lock to avoid double click errors, too much stuff going on in
# Project->Create() to lock tables. This lock is automatically dropped.
#
my $lock_result = DBQueryWarn("select GET_LOCK('NewProjectLock', 60)");
if (!$lock_result ||
!$lock_result->numrows) {
fatal("Could not get the new project lock for a long time");
}
UserError("Project already exists; pick another name!")
if (Project->Lookup($newproj_args{'pid'}));
exit(0)
if ($impotent);
......@@ -343,12 +429,35 @@ exit(0)
my $new_pid = $newproj_args{'pid'};
delete($newproj_args{'pid'});
delete($newproj_args{'head_uid'});
# Portal (Emulab, APT, CloudLab, or PhantomNet)
$newproj_args{'portal'} = $portal
if (defined($portal));
my $newproj = Project->Create($new_pid, $leader, \%newproj_args);
if (!defined($newproj)) {
fatal("Could not create new project!");
}
my $new_idx = $newproj->pid_idx();
DBQueryWarn("select RELEASE_LOCK('NewProjectLock')");
#
# Add any licenses.
#
if (keys(%licenses)) {
foreach my $name (keys(%licenses)) {
system("$LICENSES require $name $new_pid");
if ($?) {
fatal("Invalid license name: $name");
}
}
}
# And NSF awards
if (keys(%nsf_awards)) {
foreach my $award (keys(%nsf_awards)) {
my $sup = $nsf_awards{$award};
$newproj->AddNSFAward($award, $sup);
}
}
#
# See if we are in an initial Emulab setup. If so, no email sent.
......