diff options
-rw-r--r-- | .gitignore | 3 | ||||
-rw-r--r-- | Makefile | 18 | ||||
-rw-r--r-- | config.def.h | 2 | ||||
-rw-r--r-- | godzilla.c | 92 |
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(); +} + |