summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--Makefile18
-rw-r--r--config.def.h2
-rw-r--r--godzilla.c92
4 files changed, 115 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..3906454
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+*~
+config.h
+godzilla
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..15311e6
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,18 @@
+VERSION = 0.1
+
+CFLAGS += -Wall -Os -pedantic -std=c99
+CFLAGS += -DVERSION=\"${VERSION}\"
+
+all: godzilla
+
+again: clean all
+
+clean:
+ rm -f godzilla
+
+config.h:
+ cp config.def.h $@
+
+godzilla: config.h godzilla.c
+ ${CC} ${CFLAGS} -o godzilla godzilla.c -lcrypt
+
diff --git a/config.def.h b/config.def.h
new file mode 100644
index 0000000..b2d1b26
--- /dev/null
+++ b/config.def.h
@@ -0,0 +1,2 @@
+const char *script = "";
+const char *realm = "godzilla";
diff --git a/godzilla.c b/godzilla.c
new file mode 100644
index 0000000..002ed96
--- /dev/null
+++ b/godzilla.c
@@ -0,0 +1,92 @@
+#define _XOPEN_SOURCE
+#define _DEFAULT_SOURCE
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <shadow.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <grp.h>
+#include <sys/types.h>
+
+#include "config.h"
+
+extern char **environ;
+
+int unauthorized() {
+ printf("Status: 401\n");
+ printf("WWW-Authenticate: Basic realm=\"%s\"\n", realm);
+ printf("Content-Type: text/plain\n\n");
+ printf("ooooo\n");
+ return 1;
+}
+
+char b64[] ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
+char *d64(char *src, char *dec) {
+ char *tail;
+ while(1) {
+ unsigned char c[4];
+ int n = 0;
+ tail = src;
+ while(n < 4) {
+ char *p;
+ int ch;
+ do {
+ ch = *src;
+ if(ch == '\0') {
+ if(n == 0) {
+ tail = src;
+ }
+ goto ret;
+ }
+ src++;
+ p = strchr(b64, ch);
+ } while(!p);
+ ch = p - b64;
+ if(ch == 64)
+ break;
+ c[n] = ch;
+ n++;
+ }
+ if(n > 1)
+ *dec++ = c[0] << 2 | c[1] >> 4;
+ if(n > 2)
+ *dec++ = c[1] << 4 | c[2] >> 2;
+ if(n > 3)
+ *dec++ = c[2] << 6 | c[3];
+ }
+ret:
+ return tail;
+}
+
+int main(int argc, char **argv) {
+ char *auth, *raw, *login, *passw, *result;
+ struct spwd *s;
+ auth = getenv("HTTP_AUTHORIZATION");
+ if(!auth || !*auth) return unauthorized();
+ if(strncmp("Basic ", auth, 6)) return unauthorized();
+ auth = auth + 6;
+ raw = calloc(1, strlen(auth));
+ d64(auth, raw);
+ login = raw;
+ passw = strchr(raw, ':');
+ if(!login || !passw) return unauthorized();
+ *passw++ = '\0';
+ s = getspnam(login);
+ if(!s) return unauthorized();
+ result = crypt(passw, s->sp_pwdp);
+ if(!strcmp(result, s->sp_pwdp)) {
+ struct passwd *user = getpwnam(login);
+ setgid(user->pw_gid);
+ setuid(user->pw_uid);
+ seteuid(user->pw_uid);
+ initgroups(login, user->pw_gid);
+ setenv("REMOTE_USER", login, 1);
+ unsetenv("HTTP_AUTHORIZATION");
+ return execve(script, argv, environ);
+ }
+ return unauthorized();
+}
+