Our contest runs on DOMjudge and uses php session based authentication. We have to do this because we run multi-site and can’t use anything like IP based logins or something like that. A pain point we’ve had in the past is that we can’t give out the credentials to the teams otherwise there would be potential for them to share their login with someone else.

In the past this has meant we needed volunteers to go around to the team computers and manually log each team in at the beginning of the practice round, and again after the computers have been cleaned at the beginning of the real contest. In practice this also means we have to trust more people with the team passwords so we can get everyone logged in on time.

Solution

This year we finally came up with a solution. Each workstation runs a local squid proxy, which combined with SquidGuard is what we use to restrict access to the contestants on the internet.

Since all the team traffic passes through our local proxy, we can use it to inject the team’s credentials without them ever having access to them. Then we just have to configure each computer once, and squid will take care of actually logging them in after that.

From the team perspective, they click on login, see this page below, then just have to click on the “Log in using computer credentials” and they’re done. Autologin Page

The technical details

The way this works is squid watches for a certain url pattern(DOMjudge pages that require login) When it finds a pattern that matches it add a few extra headers to the request with the team login and password. So every time the team goes to a login page, DOMjudge will see these headers and be able to act on them to log the team in.

The relevant part of squid.conf looks like this:

acl autologin url_regex ^http://the.domjudge.server/team/
acl autologin url_regex ^http://the.domjudge.server/public/login.php$
include /etc/squid3/autologin.conf

And /etc/squid3/autologin.conf:

request_header_add X-DOMjudge-Autologin true autologin
request_header_add X-DOMjudge-Login "domjudge_teamname" autologin
request_header_add X-DOMjudge-Pass "base64-encoded-password" autologin

What this does is set up an acl(named autologin) to match pages where the login information might be needed, and then to add those 3 headers on any page that matches. The permissions on the /etc/squid3/autologin.conf file are 640 so that the team isn’t able to just go in and read them.

A few changes were also required on the DOMjudge side to check for credentials in the headers instead of the $_POST['user'] and $_POST['pass'] variables. See the short patch below based off the DOMjudge 5.0 branch.

---
 lib/www/auth.php | 21 +++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/lib/www/auth.php b/lib/www/auth.php
index 5e72263..5acfcb6 100644
--- a/lib/www/auth.php
+++ b/lib/www/auth.php
@@ -153,6 +153,17 @@ function show_loginpage()
 Please supply your credentials below, or contact a staff member for assistance.
 </p>

+<?php
+if (isset($_SERVER['HTTP_X_DOMJUDGE_AUTOLOGIN']) && $_SERVER['HTTP_X_DOMJUDGE_AUTOLOGIN']=='true'){ ?>
+<p>You can log in using credentials that have been configured by your administrator.</p>
+<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post">
+<input type="hidden" name="cmd" value="login" />
+<input type="hidden" name="autologin" value="true">
+<input type="submit" value="Log in using computer credentials">
+</form>
+<?php } // endif X_DOMJUDGE_AUTOLOGIN ?>
+
+
 <form action="<?php echo $_SERVER['PHP_SELF'] ?>" method="post">
 <input type="hidden" name="cmd" value="login" />
 <table>
@@ -243,8 +254,14 @@ function do_login()
 	// some specializations are handled by if-statements.
 	case 'IPADDRESS':
 	case 'PHP_SESSIONS':
-		$user = trim($_POST['login']);
-		$pass = trim($_POST['passwd']);
+		// Check for autologin headers
+		if (isset($_POST['autologin']) && isset($_SERVER['HTTP_X_DOMJUDGE_AUTOLOGIN']) && $_SERVER['HTTP_X_DOMJUDGE_AUTOLOGIN'] == 'true') {
+			$user = trim($_SERVER['HTTP_X_DOMJUDGE_LOGIN']);
+			$pass = base64_decode(trim($_SERVER['HTTP_X_DOMJUDGE_PASS']));
+		} else {
+			$user = trim($_POST['login']);
+			$pass = trim($_POST['passwd']);
+		}

 		$title = 'Authenticate user';
 		$menu = false;