Commit 90cdfb60 authored by Leigh B. Stoller's avatar Leigh B. Stoller

Checkpoint Chat Support stuff; mostly working but still needs work.

Ready for local people to play with.

The current implementation is that we munge the mysql DB on ops directly,
underneath jabberd. We add/del users from the authreg table, and set up
buddy lists in the roster-items and roster-groups tables. modgroups will
invoke the modjabberbuddies whenever a user is added or removed from a
group, although currently I am building buddy lists for just the top level
projects.

The "My IM" link in the collaboration menu will tell the user their
jabber ID on the Emulab chat server (jabber.emulab.net) and also give
them their plain text password to plug into their chat client.

I also installed a java applet (Jeti) that is a simple chat client that
I found off the jabberware page. Like all applets, it exhibits a degree
of flakiness, but I really do not expect too many people to use it.
parent bd9aff96
......@@ -42,6 +42,7 @@ my $BOSSNODE = "@BOSSNODE@";
my $WITHSFS = @SFSSUPPORT@;
my $WIKISUPPORT = @WIKISUPPORT@;
my $BUGDBSUPPORT= @BUGDBSUPPORT@;
my $CHATSUPPORT = @CHATSUPPORT@;
my $PROTOUSER = 'elabman';
my $SAMBANODE = "fs"; # DNS makes this do the right thing in E-in-E.
......@@ -65,6 +66,8 @@ my $ADDWIKIUSER = "$TB/sbin/addwikiuser";
my $DELWIKIUSER = "$TB/sbin/delwikiuser";
my $ADDBUGDBUSER= "$TB/sbin/addbugdbuser";
my $DELBUGDBUSER= "$TB/sbin/delbugdbuser";
my $ADDCHATUSER = "$TB/sbin/addjabberuser";
my $DELCHATUSER = "$TB/sbin/deljabberuser";
my $NOLOGIN = "/sbin/nologin";
my $SSH = "$TB/bin/sshtb";
my $SAVEUID = $UID;
......@@ -360,10 +363,14 @@ sub AddUser()
system("$ADDWIKIUSER $user")
if ($WIKISUPPORT && !$batch && $user ne $PROTOUSER);
# And to the bugdn if enabled.
# And to the bugdb if enabled.
system("$ADDBUGDBUSER $user")
if ($BUGDBSUPPORT && !$batch && $user ne $PROTOUSER);
# And to the chat server if enabled.
system("$ADDCHATUSER $user")
if ($CHATSUPPORT && !$batch && $user ne $PROTOUSER);
# Generate the SSL cert for the user.
system("$MKUSERCERT $user");
......@@ -444,6 +451,10 @@ sub DelUser()
system("$DELWIKIUSER $user")
if ($WIKISUPPORT);
# And the chat server if enabled.
system("$DELCHATUSER $user")
if ($CHATSUPPORT);
$EUID = 0;
$sfsupdate = 1;
......@@ -486,6 +497,7 @@ sub UpdatePassword()
# And to the bugdb if enabled.
system("$ADDBUGDBUSER -m $user")
if ($BUGDBSUPPORT && $user ne $PROTOUSER);
$EUID = 0;
return 0;
......
......@@ -11,7 +11,7 @@ SUBDIR = collab
include $(OBJDIR)/Makeconf
SUBDIRS = mailman cvs
SUBDIRS = mailman cvs jabber
all: all-subdirs
......
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2005 University of Utah and the Flux Group.
# All rights reserved.
#
SRCDIR = @srcdir@
TESTBED_SRCDIR = @top_srcdir@
OBJDIR = ../..
SUBDIR = collab/jabber
include $(OBJDIR)/Makeconf
SBIN_SCRIPTS = jabbersetup addjabberuser deljabberuser \
modjabberbuddies
LIBEXEC_SCRIPTS =
CTRL_LIBEXEC_SCRIPTS =
CTRL_LIB_FILES =
CTRL_SBIN_SCRIPTS = jabberproxy
#
# Force dependencies on the scripts so that they will be rerun through
# configure if the .in file is changed.
#
all: $(SBIN_SCRIPTS) $(CTRL_SBIN_SCRIPTS) $(CTRL_LIBEXEC_SCRIPTS) \
$(CTRL_LIB_FILES) $(LIBEXEC_SCRIPTS)
include $(TESTBED_SRCDIR)/GNUmakerules
install: $(addprefix $(INSTALL_SBINDIR)/, $(SBIN_SCRIPTS)) \
$(addprefix $(INSTALL_LIBEXECDIR)/, $(LIBEXEC_SCRIPTS)) \
$(addprefix $(INSTALL_DIR)/opsdir/libexec/jabber/, $(CTRL_LIBEXEC_SCRIPTS)) \
$(addprefix $(INSTALL_DIR)/opsdir/sbin/, $(CTRL_SBIN_SCRIPTS)) \
$(addprefix $(INSTALL_DIR)/opsdir/lib/jabber/, $(CTRL_LIB_FILES))
boss-install: install
post-install:
chown root $(INSTALL_SBINDIR)/addjabberuser
chmod u+s $(INSTALL_SBINDIR)/addjabberuser
chown root $(INSTALL_SBINDIR)/deljabberuser
chmod u+s $(INSTALL_SBINDIR)/deljabberuser
chown root $(INSTALL_SBINDIR)/modjabberbuddies
chmod u+s $(INSTALL_SBINDIR)/modjabberbuddies
#
# Control node installation (okay, plastic)
#
control-install: \
$(addprefix $(INSTALL_SBINDIR)/, $(CTRL_SBIN_SCRIPTS)) \
$(addprefix $(INSTALL_LIBDIR)/jabber/, $(CTRL_LIB_FILES)) \
$(addprefix $(INSTALL_LIBEXECDIR)/jabber/, $(CTRL_LIBEXEC_FILES))
clean:
rm -f *.o core
$(INSTALL_DIR)/opsdir/sbin/%: %
@echo "Installing $<"
-mkdir -p $(INSTALL_DIR)/opsdir/sbin
$(INSTALL) $< $@
$(INSTALL_DIR)/opsdir/lib/jabber/%: %
@echo "Installing $<"
-mkdir -p $(INSTALL_DIR)/opsdir/lib/jabber
$(INSTALL_DATA) $< $@
$(INSTALL_DIR)/opsdir/libexec/jabber/%: %
@echo "Installing $<"
-mkdir -p $(INSTALL_DIR)/opsdir/libexec/jabber
$(INSTALL) $< $@
#!/usr/bin/perl -wT
#
# EMULAB-COPYRIGHT
# Copyright (c) 2005 University of Utah and the Flux Group.
# All rights reserved.
#
use English;
use Getopt::Std;
use Fcntl ':flock';
#
# Add a user to the jabber DB on ops.
#
sub usage()
{
print STDOUT "Usage: addjabberuser <uid>\n";
exit(-1);
}
my $optlist = "d";
my $debug = 0;
#
# Configure variables
#
my $TB = "@prefix@";
my $TBOPS = "@TBOPSEMAIL@";
my $CONTROL = "@USERNODE@";
my $BOSSNODE = "@BOSSNODE@";
my $CHATSUPPORT = @CHATSUPPORT@;
my $SSH = "$TB/bin/sshtb";
my $JABBERPROXY = "$TB/sbin/jabberproxy";
#
# Untaint the path
#
$ENV{'PATH'} = "/bin:/usr/bin";
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
#
# Turn off line buffering on output
#
$| = 1;
#
# Load the Testbed support stuff.
#
use lib "@prefix@/lib";
use libdb;
use libtestbed;
#
# We don't want to run this script unless its the real version.
#
if ($EUID != 0) {
die("*** $0:\n".
" Must be setuid! Maybe its a development version?\n");
}
#
# This script is setuid, so please do not run it as root. Hard to track
# what has happened.
#
if ($UID == 0) {
die("*** $0:\n".
" Please do not run this as root! Its already setuid!\n");
}
#
# If no chat support, just exit.
#
if (! $CHATSUPPORT) {
print "CHAT support is not enabled. Exit ...\n";
exit(0);
}
#
# Parse command arguments. Once we return from getopts, all that should be
# left are the required arguments.
#
%options = ();
if (! getopts($optlist, \%options)) {
usage();
}
if (defined($options{"d"})) {
$debug = 1;
}
if (@ARGV != 1) {
usage();
}
my $user = $ARGV[0];
#
# Untaint args.
#
if ($user =~ /^([-\w]+)$/) {
$user = $1;
}
else {
die("Bad data in user: $user.");
}
#
# This script always does the right thing, so no permission checks.
# In fact, all it does it call over to ops to run a script over there.
# Note that adduser will just update the password if the user already
# exist in the wiki.
#
#
# Look in the DB to see if there is already a wikiname defined. If
# we use that. Otherwise have to form one from the user name. Ick.
#
my $query_result =
DBQueryFatal("select mailman_password ".
"from users where uid='$user'");
if (!$query_result->numrows) {
fatal("No such user $user in the DB!");
}
my ($password) = $query_result->fetchrow_array();
if (!defined($password)) {
fatal("No password defined for $user!");
}
#
# For ssh.
#
$UID = $EUID;
if ($CONTROL ne $BOSSNODE) {
my $optarg = ($debug ? "-d" : "");
print "Adding user $user to the jabber DB on $CONTROL.\n";
system("echo '$password' | ".
"$SSH -host $CONTROL $JABBERPROXY $optarg adduser $user");
if ($?) {
if ($? >> 8 == EEXIST()) {
# Not an error.
exit(0);
}
fatal("$JABBERPROXY failed on $CONTROL!");
}
}
exit(0);
sub fatal($)
{
my($mesg) = $_[0];
die("*** $0:\n".
" $mesg\n");
}
#!/usr/bin/perl -wT
#
# EMULAB-COPYRIGHT
# Copyright (c) 2005 University of Utah and the Flux Group.
# All rights reserved.
#
use English;
use Getopt::Std;
use Fcntl ':flock';
#
# Delete a user from the jabber DB on ops.
#
sub usage()
{
print STDOUT "Usage: deljabberuser <uid>\n";
exit(-1);
}
my $optlist = "d";
my $debug = 0;
#
# Configure variables
#
my $TB = "@prefix@";
my $TBOPS = "@TBOPSEMAIL@";
my $CONTROL = "@USERNODE@";
my $BOSSNODE = "@BOSSNODE@";
my $CHATSUPPORT = @CHATSUPPORT@;
my $SSH = "$TB/bin/sshtb";
my $JABBERPROXY = "$TB/sbin/jabberproxy";
#
# Untaint the path
#
$ENV{'PATH'} = "/bin:/usr/bin";
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
#
# Turn off line buffering on output
#
$| = 1;
#
# Load the Testbed support stuff.
#
use lib "@prefix@/lib";
use libdb;
use libtestbed;
#
# We don't want to run this script unless its the real version.
#
if ($EUID != 0) {
die("*** $0:\n".
" Must be setuid! Maybe its a development version?\n");
}
#
# This script is setuid, so please do not run it as root. Hard to track
# what has happened.
#
if ($UID == 0) {
die("*** $0:\n".
" Please do not run this as root! Its already setuid!\n");
}
#
# If no chat support, just exit.
#
if (! $CHATSUPPORT) {
print "CHAT support is not enabled. Exit ...\n";
exit(0);
}
#
# Parse command arguments. Once we return from getopts, all that should be
# left are the required arguments.
#
%options = ();
if (! getopts($optlist, \%options)) {
usage();
}
if (defined($options{"d"})) {
$debug = 1;
}
if (@ARGV != 1) {
usage();
}
my $user = $ARGV[0];
#
# Untaint args.
#
if ($user =~ /^([-\w]+)$/) {
$user = $1;
}
else {
die("Bad data in user: $user.");
}
#
# For ssh.
#
$UID = $EUID;
if ($CONTROL ne $BOSSNODE) {
my $optarg = ($debug ? "-d" : "");
print "Removing user $user from the jabber DB on $CONTROL.\n";
system("$SSH -host $CONTROL $JABBERPROXY $optarg deluser $user");
if ($?) {
fatal("$JABBERPROXY failed on $CONTROL!");
}
}
exit(0);
sub fatal($)
{
my($mesg) = $_[0];
die("*** $0:\n".
" $mesg\n");
}
#!/usr/bin/perl -w
#
# EMULAB-COPYRIGHT
# Copyright (c) 2005 University of Utah and the Flux Group.
# All rights reserved.
#
use English;
use Getopt::Std;
use Errno;
use XML::Simple;
use Digest::SHA1 qw(sha1_hex);
#
# A wrapper for messing with the Bug DB from boss.
#
sub usage()
{
print "Usage: jabberproxy adduser [-m] <uid> or\n";
print " jabberproxy deluser <uid> or\n";
print " jabberproxy addbuddies <uid> <buddy><group> ... or\n";
print " jabberproxy delbuddies <uid> <buddy><group> ... or\n";
exit(-1);
}
my $optlist = "d";
my $debug = 0;
#
# Configure variables
#
my $TB = "@prefix@";
my $TBOPS = "@TBOPSEMAIL@";
my $OURDOMAIN = "@OURDOMAIN@";
my $REALM = "jabber.${OURDOMAIN}";
my $JABBERCONF = "/usr/local/etc/jabberd/sm.xml";
#
# Turn off line buffering on output
#
$| = 1;
#
# Untaint the path
#
$ENV{'PATH'} = "/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin";
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
#
# Only real root, cause the script has to read/write a pid file that
# cannot be accessed by the user.
#
if ($UID != 0) {
die("*** $0:\n".
" Must be root to run this script!\n");
}
#
# Testbed Support libraries
#
use lib "@prefix@/lib";
use libtestbed;
use libtbdb;
# Locals
my $dbname;
my $dbuser;
my $dbpass;
# Protos
sub JabberUser($;$);
sub AddUser(@);
sub DelUser(@);
sub AddBuddies(@);
sub DelBuddies(@);
sub fatal($);
#
# Parse command arguments. Once we return from getopts, all that should be
# left are the required arguments.
#
%options = ();
if (! getopts($optlist, \%options)) {
usage();
}
if (defined($options{"d"})) {
$debug = 1;
}
if (! @ARGV) {
usage();
}
#
# The DB user/passwd are stored in this XML file. Parse it.
#
my $parse = XMLin($JABBERCONF);
$dbuser = $parse->{'storage'}->{'mysql'}->{'user'};
$dbname = $parse->{'storage'}->{'mysql'}->{'dbname'};
$dbpass = $parse->{'storage'}->{'mysql'}->{'pass'};
# Make sure we have everything we need.
if (!defined($dbname) ||
!defined($dbuser) ||
!defined($dbpass)) {
fatal("Could not find db parameters in $JABBERCONF!");
}
if (TBDBConnect($dbname, $dbuser, $dbpass) < 0) {
fatal("Could not connect to flyspray database!");
}
my $action = shift(@ARGV);
if ($action eq "adduser") {
exit(AddUser(@ARGV));
}
elsif ($action eq "deluser") {
exit(DelUser(@ARGV));
}
elsif ($action eq "addbuddies") {
exit(AddBuddies(@ARGV));
}
elsif ($action eq "delbuddies") {
exit(DelBuddies(@ARGV));
}
else {
die("*** $0:\n".
" Do not know what to do with '$action'!\n");
}
exit(0);
#
# Utility function to get the flyspray user_id for an Emulab user.
#
sub JabberUser($;$)
{
my ($user, $rowref) = @_;
my $query_result =
DBQueryFatal("select * from authreg where username='$user'");
return -1
if (!$query_result->numrows);
$$rowref = $query_result->fetchrow_hashref()
if (defined($rowref));
return 0;
}
#
# Add entry (or update password) for a user.
#
sub AddUser(@)
{
my ($user) = @_;
my ($password, $rowref) = ();
usage()
if (@_ != 1);
# Other info for list comes in from STDIN.
$_ = <STDIN>;
usage()
if (!defined($_));
if ($_ =~ /^(.*)$/) {
$password = DBQuoteSpecial($1);
}
else {
fatal("AddUser: Bad line in input: $_");
}
#
# If user exists, we are done.
#
if (JabberUser($user, \$rowref) == 0) {
print "User '$user' already exists in Jabber user list!\n";
return 0;
}
#
# Grab the gcos field from the password file.
#
my (undef, undef, undef, undef, undef, undef, $gcos) = getpwnam($user);
fatal("Could not get gcos field for user $user!")
if (!defined($gcos));
$gcos = DBQuoteSpecial($gcos);
my $seq = 500;
my $token = sprintf "%X", time();
my $hash = sha1_hex(sha1_hex($password) . $token);
for (my $i = 0; $i < $seq; $i++) {
$hash = sha1_hex($hash);
}
# And insert.
DBQueryFatal("insert into authreg set ".
" username='$user', ".
" realm='$REALM', ".
" password=$password, ".
" token='$token', ".
" sequence='$seq', ".
" hash='$hash'");
my $owner = "${user}\@${REALM}";
if (! DBQueryWarn("insert into active set ".
" `collection-owner`='$owner', ".
" `object-sequence`=NULL, ".
" time=UNIX_TIMESTAMP(now())")) {
DBQueryFatal("delete from authreg where username='$user'");
return -1;
}
return 0;
}
#
# Delete entry for a user. Okay, cannot really delete a user cause there
# might be entries in other tables cross referenced (say, a bug report).
# Instead, just rename the user and disable the account. Allow for a -force
# option though, to totally get rid of it.
#
sub DelUser(@)
{
my ($user) = @_;
usage()
if (@_ != 1);
if (JabberUser($user) != 0) {
print "User '$user' does not exist in Jabber user list!\n";
return 0;
}
my $owner = "${user}\@${REALM}";