Skip to content

Instantly share code, notes, and snippets.

@danielrichman
Created April 10, 2012 19:24
Show Gist options
  • Save danielrichman/2353838 to your computer and use it in GitHub Desktop.
Save danielrichman/2353838 to your computer and use it in GitHub Desktop.
old habitat.habhub.org docs scripts

habitat.habhub.org miscellanea

The scripts here live and run on [[nessie.habhub.org]].

  • runas.c (compiles to runas): setugid CGI binary configured to be run by the web server whenever a certain url is fetched. This url is installed as a github post-receive hook. The setugid binary provides a secure way to go from running as www-data, to running as habitat-www in order to regenerate the sphinx documentation. Also locks a file to ensure that simultaneous updating isn't attempted.
  • update: bash script - pulls the latest git repo, builds the documentation, cleans the repo, generates a tarball, updates the homepage.
  • genhomepage: bash script - generates [[http://habitat.habhub.org/index.html]] with the latest commit message.
  • sanitise.py: utility for genhomepage - escapes xml special characters.
#!/bin/sh
# Copyright (C) 2010 Daniel Richman
#
# 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 3 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.
#
# For a full copy of the GNU General Public License,
# see <http://www.gnu.org/licenses/>.
cd $HABITAT
cat <<-EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>habitat</title>
<link href="http://habhub.org/simple.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="title">habitat</div>
<div id="page">
<p>
habitat is a system for uploading, processing, storing and displaying
telemetry and related information transmitted from high altitude balloons.
The back end is written in Python and is responsible for parsing incoming
data and storing it in the database, while the frontend is written
independently in JavaScript and HTML and communicates with CouchDB
directly to obtain data and display it.
</p>
<ul>
<li><a href="docs">Pretty documentation!</a></li>
<li>
<a href="http://github.com/ukhas/habitat">Browse habitat's source on github</a>
<span class="small"><a href="source">(mirror)</a></span>
</li>
<li><a href="https://www.pivotaltracker.com/projects/112268">habitat on Pivotal Tracker</a> (roadmap, etc.)</li>
<li><a href="http://ci.habhub.org/">habitat's continuous integration server</a></li>
<li>
<code>git clone git://github.com/ukhas/habitat.git</code>
<span class="small">(mirror at <code><a href="habitat.git">http://habitat.habhub.org/habitat.git</a></code>)</span>
</li>
<li>
Latest GIT snapshot available at <a href="https://github.com/ukhas/habitat/archives/develop">github</a>;
<span class="small"><a href="habitat.tar.gz">(mirror)</a></span>
</li>
</ul>
<p>
<a href='http://habhub.org/'>habhub.org</a>
</p>
<pre id="footnote">
EOF
echo -n "habitat.habhub.org last updated: "
date
echo
git log -1 | $SANITISER
cat <<-EOF
</pre>
</div>
</body>
</html>
EOF
/*
Copyright (C) 2010 Daniel Richman
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 3 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.
For a full copy of the GNU General Public License,
see <http://www.gnu.org/licenses/>.
*/
/*
* cd /var/www/
* mkdir hooks
* chown root:www-data hook
* chmod 750 hook
*
* gcc -D_GNU_SOURCE -Wall -pedantic -O2 runas.temp.c -o hook/runas
* chown habitat-www:habitat-www hook/runas
* chmod 755 hook/runas
* chmod ug+s hook/runas
*
* With the above setup, only users in the group www-data will be able to
* execute the binary, which only root will be able to modify, and it
* will allow user www-data to become user habitat-www in order to run
* only one command (controlled, see code below).
* Assumed: habitat has no write access to /var/www or it could move
* and replace the hooks directory
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <pwd.h>
#include <grp.h>
extern char **environ;
/* User to change to. Binary should be ug+s uname:gname */
#define uid 1013
#define gid 1013
#define uname "habitat-www"
#define gname "habitat-www"
/* The user that's allowed to run the binary */
#define huid 33
#define hgid 33
/* Command & lockfile names */
#define command "/home/habitat-www/update"
#define lockfile "/home/habitat-www/lockfile"
char *argv[] = {command};
#define exit_if(cond) do { if (cond) { exit(EXIT_FAILURE); } } while (0)
int main(int argc, char *argv[])
{
int i, j, k, l, m, n, o, p, q, r, s;
int tty_fd, devnull_fd, update_lock_fd, status;
uid_t ruid, euid, suid;
gid_t rgid, egid, sgid;
pid_t pid, pid2, pid3, pidr;
struct passwd *ubuf;
struct group *gbuf;
/* Check UIDs and GIDs */
r = getresuid(&ruid, &euid, &suid);
s = getresgid(&rgid, &egid, &sgid);
exit_if(r != 0 || s != 0);
exit_if(euid != uid || suid != uid || egid != gid || sgid != gid);
exit_if(ruid != huid || rgid != hgid);
/* Check user & group name */
gbuf = getgrgid(gid);
exit_if(gbuf == NULL || strcmp(gbuf->gr_name, uname) != 0);
ubuf = getpwuid(uid);
exit_if(ubuf == NULL || strcmp(ubuf->pw_name, gname) != 0);
/* Set real & effective uid & gid */
o = setresuid(uid, uid, uid);
n = setresgid(gid, gid, gid);
exit_if(o != 0 || n != 0);
/* CGI Response */
fprintf(stdout, "Content-Type: text/plain\r\n"
"\r\n"
"Moo?");
fflush(stdout);
/* The process exits after forking and the response will be sent then */
update_lock_fd = open(lockfile, O_WRONLY|O_CREAT|O_NONBLOCK, 0644);
exit_if(update_lock_fd == -1);
/* Assign it to fd 3 */
p = dup2(update_lock_fd, 3);
update_lock_fd = 3;
exit_if(p != 3);
q = flock(update_lock_fd, LOCK_EX | LOCK_NB);
/* If we failed to get the lock, just give up */
exit_if(q != 0);
/* flocks are automatically released if the file's descriptor closes,
* for example, upon exit. */
/* First fork */
pid = fork();
exit_if(pid < 0);
if (pid > 0)
{
/* Parent */
exit(EXIT_SUCCESS);
}
/* Start a new process group */
/* If setsid fails then we are already a process group leader */
setsid();
/* Second fork */
pid2 = fork();
exit_if(pid2 < 0);
if (pid2 > 0)
{
exit(EXIT_SUCCESS);
}
/* From start-stop-daemon.c (dpkg): sever any ties to the parent */
tty_fd = open("/dev/tty", O_RDWR);
devnull_fd = open("/dev/null", O_RDWR);
ioctl(tty_fd, TIOCNOTTY, 0);
close(tty_fd);
umask(022);
k = dup2(devnull_fd, 0);
l = dup2(devnull_fd, 1);
m = dup2(devnull_fd, 2);
exit_if(k == -1 || l == -1 || m == -1);
/* Keep fds 0, 1, 2, 3 */
for (i = getdtablesize() - 1; i >= 4; --i)
{
close(i);
}
j = chdir("/");
exit_if(j != 0);
/* Clear the environment */
clearenv();
/* Set $HOME and $PATH */
setenv("HOME", ubuf->pw_dir, 1);
setenv("PATH", "/usr/local/bin:/usr/bin:/bin", 1);
/* Fork off the command */
pid3 = fork();
exit_if(pid3 < 0);
if (pid3 == 0)
{
close(update_lock_fd);
/* Child: Do it */
execve(command, argv, environ);
/* execve only returns on failure */
exit(EXIT_FAILURE);
}
else
{
/* Parent: wait for it to finish */
for (;;)
{
pidr = waitpid(pid3, &status, 0);
exit_if(pidr < 0);
if (WIFEXITED(status) || WIFSIGNALED(status))
{
break;
}
}
exit(EXIT_SUCCESS);
}
}
#!/usr/bin/python
# Copyright (C) 2010 Daniel Richman
#
# 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 3 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.
#
# For a full copy of the GNU General Public License,
# see <http://www.gnu.org/licenses/>.
from xml.sax.saxutils import escape
import sys
for l in sys.stdin:
sys.stdout.write(escape(l))
#!/bin/sh
# Copyright (C) 2010 Daniel Richman
#
# 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 3 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.
#
# For a full copy of the GNU General Public License,
# see <http://www.gnu.org/licenses/>.
ROOT=/home/habitat-www
HABITAT=$ROOT/habitat
DOCS=$HABITAT/docs
OUTPUT=$ROOT/rendered-docs
TAR=$ROOT/habitat.tar
GENHOMEPAGE=$ROOT/genhomepage
HOMEPAGE=$ROOT/index.html
SANITISER="python $ROOT/sanitise.py"
cd $HABITAT
git fetch origin develop
git reset --hard FETCH_HEAD
git clean -fxd
sphinx-build -Eb html $DOCS $OUTPUT
git clean -fxd
git gc
git archive --format tar -o $TAR --prefix habitat/ HEAD
gzip -f -9 $TAR
export HABITAT
export SANITISER
$GENHOMEPAGE > $HOMEPAGE
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment