#define _XOPEN_SOURCE #define _DEFAULT_SOURCE #include #include #include #include #include #include #include #include #include #include #include #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); cap_value_t cap_values[] = { CAP_SETUID, CAP_SETGID }; cap_t caps; caps = cap_get_proc(); cap_set_flag(caps, CAP_EFFECTIVE, 2, cap_values, CAP_SET); cap_set_proc(caps); prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0); cap_free(caps); setgid(user->pw_gid); initgroups(login, user->pw_gid); setuid(user->pw_uid); setenv("REMOTE_USER", login, 1); unsetenv("HTTP_AUTHORIZATION"); return execve(script, argv, environ); } return unauthorized(); }