Commit 3a9d0ae9 authored by Jonathon Duerig's avatar Jonathon Duerig

Merge branch 'master' of git-public.flux.utah.edu:/flux/git/emulab-devel

parents b937af9f fdbe7c05
VERSION export-subst
# Files that already had DOS-style line endings and those
# that require them should be added to the list below.
delay/linux/iptables_mods/iptables-1.3.6-imq.diff -crlf
......
......@@ -203,8 +203,24 @@ endif
subboss: client
@$(MAKE) -C utils subboss
subboss-install: subboss client-install
subboss-install: subboss
ifeq ($(EVENTSYS),1)
@$(MAKE) -C event client-install
endif
@$(MAKE) -C os client-install
ifneq ($(SYSTEM),CYGWIN_NT-5.1)
@$(MAKE) -C capture client-install
@$(MAKE) -C tip client-install
@$(MAKE) -C tools client-install
endif
@$(MAKE) -C sensors client-install
@$(MAKE) -C utils subboss-install
@$(MAKE) -C db subboss-install
@$(MAKE) -C tmcd subboss-install
@$(MAKE) -C rc.d subboss-install
# Hack: this should probably be done by a subboss-install
# script, but there isn't a huge need for that yet
@rm -f $(INSTALL_RCDIR)/isc-dhcpd
TARBALLDESTDIR = /var/tmp/emulab-client
......
......@@ -90,3 +90,5 @@ HAVE_ULXMLRPCPP = @HAVE_ULXMLRPCPP@
STANDALONE_CLEARINGHOUSE = @STANDALONE_CLEARINGHOUSE@
NODE_USAGE_SUPPORT = @NODE_USAGE_SUPPORT@
EXP_VIS_SUPPORT = @EXP_VIS_SUPPORT@
Version: $Format:%H %ci$
/*
* EMULAB-COPYRIGHT
* Copyright (c) 2000-2003, 2005, 2006, 2007 University of Utah and the Flux Group.
* Copyright (c) 2000-2010 University of Utah and the Flux Group.
* All rights reserved.
*/
......@@ -10,6 +10,7 @@
#include <arpa/inet.h>
#include <fcntl.h>
#include <stdio.h>
#include <paths.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
......@@ -19,6 +20,7 @@
#include <errno.h>
#include <mysql/mysql.h>
#include <sys/time.h>
#include <signal.h>
#include <grp.h>
#include "capdecls.h"
#include "config.h"
......@@ -29,6 +31,9 @@
static int debug = 0;
static int portnum = SERVERPORT;
static gid_t admingid;
char *Pidname;
void sigterm(int);
void cleanup(void);
char *usagestr =
"usage: capserver [-d] [-p #]\n"
......@@ -53,6 +58,8 @@ main(int argc, char **argv)
struct sockaddr_in name;
struct timeval timeout;
struct group *group;
struct sigaction sa;
sigset_t actionsigmask;
while ((ch = getopt(argc, argv, "dp:")) != -1)
switch(ch) {
......@@ -84,6 +91,15 @@ main(int argc, char **argv)
exit(1);
}
sigemptyset(&actionsigmask);
sigaddset(&actionsigmask, SIGINT);
sigaddset(&actionsigmask, SIGTERM);
memset(&sa, 0, sizeof sa);
sa.sa_handler = sigterm;
sa.sa_mask = actionsigmask;
sigaction(SIGINT, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
/*
* Grab the GID for the default group.
*/
......@@ -129,6 +145,19 @@ main(int argc, char **argv)
}
syslog(LOG_NOTICE, "listening on TCP port %d", ntohs(name.sin_port));
if (!getuid()) {
FILE *fp;
char mybuf[BUFSIZ];
sprintf(mybuf, "%s/capserver.pid", _PATH_VARRUN);
fp = fopen(mybuf, "w");
if (fp != NULL) {
fprintf(fp, "%d\n", getpid());
(void) fclose(fp);
Pidname = strdup(mybuf);
}
}
while (1) {
struct sockaddr_in client;
int clientsock, length = sizeof(client);
......@@ -295,6 +324,22 @@ main(int argc, char **argv)
}
close(tcpsock);
syslog(LOG_NOTICE, "daemon terminating");
cleanup();
exit(0);
}
void
sigterm(int sig)
{
cleanup();
exit(0);
}
void
cleanup(void)
{
syslog(LOG_NOTICE, "daemon exiting by signal");
if (Pidname)
(void) unlink(Pidname);
}
......@@ -12,6 +12,9 @@ SUBDIR = collab
include $(OBJDIR)/Makeconf
SUBDIRS = mailman cvstools jabber trac
ifeq ($(EXP_VIS_SUPPORT),1)
SUBDIRS += exp-vis
endif
all: all-subdirs
......@@ -31,6 +34,9 @@ post-install:
@$(MAKE) -C cvstools post-install
@$(MAKE) -C jabber post-install
@$(MAKE) -C trac post-install
ifeq ($(EXP_VIS_SUPPORT),1)
@$(MAKE) -C exp-vis post-install
endif
# How to recursively descend into subdirectories to make general
# targets such as `all'.
......
#
# EMULAB-COPYRIGHT
# Copyright (c) 2009 University of Utah and the Flux Group.
# All rights reserved.
#
SRCDIR = @srcdir@
TESTBED_SRCDIR = @top_srcdir@
OBJDIR = ../..
SUBDIR = collab/exp-vis
include $(OBJDIR)/Makeconf
CGI_SCRIPTS = fetch-vis
LIBEXEC_SCRIPTS = write-vis-auth
CTRL_LIBEXEC_SCRIPTS = write-vis-auth.proxy
SETUID_LIBX_SCRIPTS = write-vis-auth
#
# Force dependencies on the scripts so that they will be rerun through
# configure if the .in file is changed.
#
all: $(CGI_SCRIPTS) $(LIBEXEC_SCRIPTS) $(CTRL_LIBEXEC_SCRIPTS)
include $(TESTBED_SRCDIR)/GNUmakerules
install: \
$(addprefix $(INSTALL_LIBEXECDIR)/, $(LIBEXEC_SCRIPTS)) \
$(addprefix $(TBROOT)/opsdir/www/cgi-bin/, $(CGI_SCRIPTS)) \
$(addprefix $(INSTALL_DIR)/opsdir/libexec/, $(CTRL_LIBEXEC_SCRIPTS))
$(TBROOT)/opsdir/www/cgi-bin/fetch-vis: fetch-vis
-$(SUDO) mkdir -m 775 $(TBROOT)/opsdir/www/cgi-bin
$(SUDO) $(INSTALL) -o root -m 4775 $< $@
$(INSTALL_DIR)/opsdir/libexec/write-vis-auth.proxy: write-vis-auth.proxy
-mkdir -p $(INSTALL_DIR)/opsdir/libexec
$(INSTALL) $< $@
post-install:
clean:
#!/usr/bin/perl -T
#
#
#
use strict;
use warnings;
use POSIX qw(setuid setgid);
use Cwd qw(realpath);
use CGI;
use CGI::Cookie;
use HTTP::Date;
#use Data::Dumper;
#print "\n\n";
#print STDERR Dumper(\%ENV);
my $FSDIR_PROJ = "@FSDIR_PROJ@";
my $FSDIR_GROUPS = "@FSDIR_GROUPS@";
sub error($) {
print "Content-Type: text/plain\n";
print "Status: 404 Not Found\n\n";
print "$_[0]\n";
#die "$_[0]\n";
exit 1;
}
my $SCRIPT_URL = $ENV{REQUEST_URI};
# Parse URL
my ($proj,$group,$exp,$dir,$file);
local $_ = $SCRIPT_URL;
if (/^\/proj-vis\/([a-zA-Z0-9-]+)\/?(.*)$/) {
$proj = $1;
$group = $1;
$file = $2;
} elsif (/^\/group-vis\/([a-zA-Z0-9-]+)\/?([a-zA-Z0-9-]+)\/?(.*)$/) {
$proj = $1;
$group = $2;
$file = $3;
} elsif (/^\/exp-vis\/([a-zA-Z0-9-]+)\/?([a-zA-Z0-9-]+)\/?(.*)$/) {
$proj = $1;
$exp = $2;
$file = $3;
} else {
error("Malformed URL");
}
if (defined $exp) {
my $exp_dir = "/proj/$proj/exp/$exp";
local $_ = realpath $exp_dir;
if (/^$FSDIR_PROJ\/$proj\//) {
$group = $proj;
} elsif (/^$FSDIR_GROUPS\/$proj\/(.+?)\//) {
$group = $1;
}
$dir = "/groups/$proj/$group/www/exp-vis/$exp";
} else {
$dir = "/groups/$proj/$group/www/group-vis";
}
# Lookup up the Unix GID for the proj and the group
my (undef,undef,undef,undef,undef,$gid) = stat("/proj/$proj") or die;
my ($gid_name,undef,undef,$gid_members) = getgrgid($gid);
die "Error: Bad proj GID: $gid_name != $proj" unless $gid_name eq $proj;
my (undef,undef,undef,undef,undef,$gid2) = stat("/groups/$proj/$group") or die;
my ($gid2_name,undef,undef,$gid2_members) = getgrgid($gid2);
# For security remove any ".." from the path and abort if we would
# leave $dir
my @dirs = split /\//, $file;
my @res;
foreach my $d (@dirs) {
if ($d eq '' || $d eq '.') {
# nothing to do
} elsif ($d eq '..') {
error("Malformed URL") if @res == 0;
pop @res;
} else {
push @res, $d;
}
}
# Create the path
$file = join ('/', @res);
my $path = "$dir/$file";
if (-d $path) {
my $orig_path = $path;
$path .= "/index.html" if -e "$path/index.html";
$path .= "/index.htm" if -e "$path/index.htm";
error("Can't index dir: $path") unless $path ne $orig_path;
}
error("File Doesn't Exist: $path") unless -e $path;
# Make sure that the path, after resolving any symbolic links,
# still resides is /proj/<proj> or /groups/<proj>/<group>
my $realpath = realpath $path;
error("Invalid path: $realpath") unless $realpath =~ /^$FSDIR_PROJ\/$proj|^$FSDIR_GROUPS\/$proj\/$group/;
#
# Special rule for boss. Since we are bypassing authorization, don't
# show anything, just let boss know that the url is valid.
#
if ($ENV{REMOTE_ADDR} eq "@BOSSNODE_IP@") {
print "Content-Type: text/plain\n\n";
print "I exist!\n";
exit(0);
}
#
# Get session cookie and make sure user is logged in and authorized to
# view.
#
my %cookies = raw_fetch CGI::Cookie;
my $session_key = $cookies{exp_vis_session};
error("Not logged in.") unless defined $session_key;
my $user;
open F, "/var/run/exp-vis.auth" or die;
foreach (<F>) {
chop;
my ($key, $u) = split / /;
if ($key eq $session_key) {
$user = $u;
last;
}
}
error("Login Timed Out.") unless defined $user;
my (undef, undef, $uid, $user_gid) = getpwnam($user);
die if $user_gid == 0;
error("You do not have permission to view $proj files")
unless $gid == $user_gid || grep {$_ eq $user} split /\s+/, $gid_members;
error("You do not have permission to view $proj/$group files")
unless $gid2 == $user_gid || grep {$_ eq $user} split /\s+/, $gid2_members;
# OK, Now we are sure the user has permission to view this file.
# Now become a member of the GID for the proj and group and clear out
# any other GIDs
undef $!;
setgid($gid);
$) = "$gid $gid $gid2";
die $! if $!;
# Now drop privileges, using setuid to make sure the saved uid
# is also changes, ie, so that the change is permanent.
setuid($<) or die $!;
my %mime_map =
qw(html text/html htm text/html
txt text/plain
png image/png
gif image/gif
jpg image/jpeg jpeg image/jpeg
zip application/zip);
my ($ext) = $path =~ /\.([^.]+)$/;
$ext = lc $ext;
my $mime_type = $mime_map{$ext};
$/ = undef;
open F, "$path" or error "Can't read file: $path";
my ($dev,$ino,$mode,$nlink,undef,undef,$rdev,$size,
$atime,$mtime,$ctime,$blksize,$blocks) = stat F;
my $if_mod_since = 0;
$if_mod_since = str2time($ENV{HTTP_IF_MODIFIED_SINCE})
if defined $ENV{HTTP_IF_MODIFIED_SINCE};
if ($if_mod_since > 0 && $if_mod_since <= $mtime) {
print "Status: 304 Not Modified\n\n";
} else {
print "Content-Type: $mime_type\n" if defined $mime_type;
print "Content-Length: ", $size, "\n";
print "Last-Modified: ", time2str($mtime), "\n";
print "\n";
print <F> unless $ENV{REQUEST_METHOD} eq 'HEAD';
}
exit 0;
#!/usr/bin/perl -wT
#
# EMULAB-COPYRIGHT
# Copyright (c) 2000-2007 University of Utah and the Flux Group.
# All rights reserved.
#
use strict;
use Getopt::Std;
#
# Configure variables
#
my $TB = "@prefix@";
my $TBOPS = "@TBOPSEMAIL@";
my $USERNODE = "@USERNODE@";
my $SSH = "$TB/bin/sshtb -l root -host $USERNODE";
my $background = 0;
# un-taint path
$ENV{'PATH'} = '/bin:/usr/bin:/usr/local/bin';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
# Turn off line buffering on output
$| = 1;
#
# Capture stdout and stderr to a file so if we die we can mail the output to
# testbed-ops
#
# XXX: Don't hardcode
my $logfile = "/tmp/write-vis-auth.$$";
use vars qw(*OLDOUT *OLDERR);
open OLDOUT, ">&STDOUT" or die "Can't dup STDOUT $!";
open OLDERR, ">&STDERR" or die "Can't dup STDERR $!";
open STDOUT, ">$logfile" or die "Can't open $logfile: $!";
open STDERR, ">&STDOUT" or die "Can't dup STDERR $!";
$SIG{__DIE__} = sub {
return unless defined $^S; # In Parser
return if $^S; # In Eval Block
local $_ = $_[0];
open STDOUT, ">&OLDOUT";
open STDERR, ">&OLDERR";
SENDMAIL($TBOPS, "write-vis-auth failed", $_, undef, undef, $logfile);
unlink $logfile;
TBScriptUnlock();
print STDERR "write-vis-auth failed, see testbed-ops mail\n";
exit(1);
};
#
# Load the Testbed support stuff.
#
use lib "@prefix@/lib";
use libdb;
use libtestbed;
if ((my $locked = TBScriptLock("write-vis-auth", 1)) != TBSCRIPTLOCK_OKAY()) {
exit(0)
if ($locked == TBSCRIPTLOCK_IGNORE);
die("Could not get the lock after a long time!\n");
}
# become root, needed for ssh
$< = $>;
my $db_result =
DBQueryFatal("select opskey, uid from login");
open O, "| $SSH $TB/libexec/write-vis-auth.proxy"
or die "ssh to ops failed: $!\n";
my $prev_opskey = '';
while (my ($opskey,$uid) = $db_result->fetchrow_array) {
$opskey = "00000000000000000000000000000000" if $opskey eq '';
print O "$opskey $uid\n";
}
close O;
die "ssh to ops failed: $!\n" if $!;
die "ssh to ops failed with exit code $?\n" if $? != 0;
unlink $logfile;
TBScriptUnlock();
exit(0);
#!/bin/sh
set -e
if [ "$USER" != "root" ]; then
echo "Must be root." 1>&2
exit 1
fi
TEMPFILE=`mktemp /var/run/exp-vis.XXXXXX`
cat > $TEMPFILE
mv $TEMPFILE /var/run/exp-vis.auth
# Copyright (C) 2001-2003 by the Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
"""Posting moderation filter.
"""
import re
from email.MIMEMessage import MIMEMessage
from email.MIMEText import MIMEText
from Mailman import mm_cfg
from Mailman import Utils
from Mailman import Message
from Mailman import Errors
from Mailman.i18n import _
from Mailman.Handlers import Hold
from Mailman.Logging.Syslog import syslog
class ModeratedMemberPost(Hold.ModeratedPost):
# BAW: I wanted to use the reason below to differentiate between this
# situation and normal ModeratedPost reasons. Greg Ward and Stonewall
# Ballard thought the language was too harsh and mentioned offense taken
# by some list members. I'd still like this class's reason to be
# different than the base class's reason, but we'll use this until someone
# can come up with something more clever but inoffensive.
#
# reason = _('Posts by member are currently quarantined for moderation')
pass
def process(mlist, msg, msgdata):
if msgdata.get('approved') or msgdata.get('fromusenet'):
return
# First of all, is the poster a member or not?
for sender in msg.get_senders():
if mlist.isMember(sender):
break
else:
sender = None
if sender:
# If the member's moderation flag is on, then perform the moderation
# action.
if mlist.getMemberOption(sender, mm_cfg.Moderate):
# Note that for member_moderation_action, 0==Hold, 1=Reject,
# 2==Discard
if mlist.member_moderation_action == 0:
# Hold. BAW: WIBNI we could add the member_moderation_notice
# to the notice sent back to the sender?
msgdata['sender'] = sender
Hold.hold_for_approval(mlist, msg, msgdata,
ModeratedMemberPost)
elif mlist.member_moderation_action == 1:
# Reject
text = mlist.member_moderation_notice
if text:
text = Utils.wrap(text)
else:
# Use the default RejectMessage notice string
text = None
raise Errors.RejectMessage, text
elif mlist.member_moderation_action == 2:
# Discard. BAW: Again, it would be nice if we could send a
# discard notice to the sender
raise Errors.DiscardMessage
else:
assert 0, 'bad member_moderation_action'
# Should we do anything explict to mark this message as getting past
# this point? No, because further pipeline handlers will need to do
# their own thing.
return
else:
sender = msg.get_sender()
# From here on out, we're dealing with non-members.
#
# XXX Emulab change; look for X-Netbed header.
#
if msg.get('X-NetBed'):
return
if matches_p(sender, mlist.accept_these_nonmembers):
return
if matches_p(sender, mlist.hold_these_nonmembers):
Hold.hold_for_approval(mlist, msg, msgdata, Hold.NonMemberPost)
# No return