File: ifppc_down.setuid.cc

package info (click to toggle)
pearpc 0.3.1%2B1-2
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 5,004 kB
  • ctags: 10,086
  • sloc: cpp: 57,086; ansic: 8,780; sh: 5,930; asm: 1,939; lex: 321; makefile: 291; yacc: 195
file content (73 lines) | stat: -rw-r--r-- 1,922 bytes parent folder | download | duplicates (4)
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
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <unistd.h>

int canonicalize(char *buf, int bufsize, char *cwd, char *fn)
{
	int cwdsize = strlen(cwd);
	int fnsize = strlen(fn);
	if (fn[0] == '/') {
		if (fnsize +1 > bufsize) return ERANGE;
		strcpy(buf, fn);
		return 0;
	}
	if (cwdsize + 1 + fnsize + 1 > bufsize) return ERANGE;
	strcpy(buf, cwd);
	strcat(buf, "/");
	strcat(buf, fn);
	return 0;
}

int main(int argc, char *argv[])
{
	setuid(0);
	char *relfilename = "ifppc_down";
	int relfilenamesize = strlen(relfilename);
	char cwdbuf[2048];
	if (!getcwd(cwdbuf, sizeof cwdbuf)) {
		printf("CWD name too long (>%d bytes). move to a higher level directory.\n", sizeof cwdbuf);
		return 1;
	}
	char filename[2048+128];
	if (canonicalize(filename, sizeof filename, cwdbuf, argv[0])) {
		printf("unable to determine absolute executable filename. "
			"probably absolute filename too long (>%d bytes). "
			"move to a higher level directory.\n", sizeof cwdbuf);
		return 1;
	}
	char *bs = strrchr(filename, '/');
	if (!bs) {
		printf("???\n");
		return 1;
	}
	int pathsize = bs-filename;
	if (pathsize + 1 + relfilenamesize + 1 > sizeof filename) {
		printf("absolute pathname too long (>%d bytes). "
			"move to a higher level directory.\n", sizeof cwdbuf);
		return 1;
	}
	strcpy(bs+1, relfilename);
	printf("filename = %s\n", filename);
	struct stat s;
	if (stat(filename, &s)) {
		printf("can't stat file '%s': %s\n", filename, strerror(errno));
		return 1;
	}
	if (s.st_uid != 0) {
		printf("script '%s' must be owned by root (UID %d instead)\n", filename, s.st_uid);
		return 1;
	}
	if (s.st_mode & S_IWGRP) {
		printf("script '%s' must not be group-writable\n", filename);
		return 1;
	}
	if (s.st_mode & S_IWOTH) {
		printf("script '%s' must not be world-writable\n", filename);
		return 1;
	}
	execl("/bin/sh", "/bin/sh", filename, 0);
	return 0;
}