summaryrefslogtreecommitdiff
path: root/godzilla.c
blob: 0c512eae5f345c1eff62d727660d37127a736256 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#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/capability.h>
#include <sys/prctl.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);
    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();
}