-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathsup.c
114 lines (89 loc) · 2.19 KB
/
sup.c
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/* See LICENSE file for copyright and license details. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include "arg.h"
#include "sha256.h"
#define nelem(x) (sizeof (x) / sizeof *(x))
#define CHUNK 1048576 /* 1MiB */
struct rule_t {
const int uid;
const char *cmd;
const char *path;
const char *hash;
};
#include "config.h"
char *argv0;
static void die(char *msg)
{
fprintf(stderr, "%s\n", msg);
exit(1);
}
static uint32 getsha(const char *path, unsigned char *dest)
{
static sha256_context sha;
unsigned char buf[CHUNK];
uint32 len, tot = 0;
FILE *fd;
fd = fopen(path, "r");
if (!fd)
die("Can not read binary file.");
sha256_starts(&sha);
while ((len = fread(buf, 1, CHUNK, fd))) {
sha256_update(&sha, buf, len);
tot += len;
}
fclose(fd);
sha256_finish(&sha, dest);
return tot;
}
int main(int argc, char *argv[])
{
unsigned int c, i, lflag = 0;
unsigned char digest[32];
char output[65];
struct stat st;
ARGBEGIN {
case 'l':
lflag = 1;
break;
default:
die("Usage: sup [-l] command [ args ... ]");
} ARGEND;
if (lflag) {
printf("List of compiled authorizations:\n");
for (i = 0; i < nelem(rules); i++)
printf("\nuser: %d\ncmd: %s\nbinary: %s\nsha256: %s\n",
rules[i].uid, rules[i].cmd, rules[i].path,
rules[i].hash);
return 0;
}
if (argc < 1)
die("Usage: sup [-l] command [ args ... ]");
for (i = 0; i < nelem(rules); i++) {
if (!strcmp(argv[0], rules[i].cmd)) {
if (rules[i].uid != getuid() && rules[i].uid != -1)
die("Unauthorized user.");
if (stat(rules[i].path, &st) == -1)
die("Can not stat program.");
if (st.st_mode & 0022)
die("Can not run writable binaries.");
if (getsha(rules[i].path, digest) != st.st_size)
die("Binary file differs from size read.");
for (c = 0; c < 32; c++)
sprintf(output + (c * 2), "%02x", digest[c]);
output[64] = '\0';
if (strncmp(rules[i].hash, output, 64))
die("Checksums do not match.");
if (setgid(SETGID) < 0)
die("setgid failed");
if (setuid(SETUID) < 0)
die("setuid failed");
if (execv(rules[i].path, argv) < 0)
die("execv failed.");
}
}
die("Unauthorized command.");
}