map 0x0000041d include common # # Top row # section 0x29 onehalf 0x29 shift # 1 exclam 0x2 shift # 2 quotedbl 0x3 shift at 0x3 altgr # 3 numbersign 0x4 shift sterling 0x4 altgr # 4 currency 0x5 shift dollar 0x5 altgr # 5 percent 0x6 shift # 6 ampersand 0x7 shift # 7 slash 0x8 shift braceleft 0x8 altgr # 8 parenleft 0x9 shift bracketleft 0x9 altgr # 9 parenright 0xa shift bracketright 0xa altgr # 0 equal 0xb shift braceright 0xb altgr plus 0xc question 0xc shift backslash 0xc altgr acute 0xd dead_acute 0xd grave 0xd shift dead_grave 0xd shift # # QWERTY first row # EuroSign 0x12 altgr aring 0x1a Aring 0x1a shift dead_diaeresis 0x1b dead_circumflex 0x1b shift dead_tilde 0x1b altgr # # QWERTY second row # odiaeresis 0x27 Odiaeresis 0x27 shift adiaeresis 0x28 Adiaeresis 0x28 shift apostrophe 0x2b asterisk 0x2b shift # # QWERTY third row # less 0x56 greater 0x56 shift bar 0x56 altgr mu 0x32 altgr comma 0x33 semicolon 0x33 shift period 0x34 colon 0x34 shift minus 0x35 underscore 0x35 shift 9e655a3a187b4329d9'/> clone of mitm proxyJames
aboutsummaryrefslogtreecommitdiffstats
path: root/examples/complex/full_transparency_shim.c
blob: 923eea760ea60667bc7581fbfd53d4742220343c (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
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <sys/prctl.h>
#include <sys/types.h>
#include <sys/capability.h>
#include <unistd.h>
#include <errno.h>

/* This setuid wrapper can be used to run mitmproxy in full transparency mode, as a normal user.
 * It will set the required capabilities (CAP_NET_RAW), drop privileges, and will then run argv[1]
 * with the same capabilities.
 *
 * It can be compiled as follows:
 * gcc examples/mitmproxy_shim.c -o mitmproxy_shim -lcap
*/

int set_caps(cap_t cap_struct, cap_value_t *cap_list, size_t bufsize) {
	int cap_count = bufsize / sizeof(cap_list[0]);

	if (cap_set_flag(cap_struct, CAP_PERMITTED, cap_count, cap_list, CAP_SET) ||
            cap_set_flag(cap_struct, CAP_EFFECTIVE, cap_count, cap_list, CAP_SET) ||
            cap_set_flag(cap_struct, CAP_INHERITABLE, cap_count, cap_list, CAP_SET)) {
		if (cap_count < 2) {
			fprintf(stderr, "Cannot manipulate capability data structure as user: %s.\n", strerror(errno));
		} else {
			fprintf(stderr, "Cannot manipulate capability data structure as root: %s.\n", strerror(errno));
		}
		return -1;
	}

	if (cap_count < 2) {
		if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_NET_RAW, 0, 0)) {
			fprintf(stderr, "Failed to add CAP_NET_RAW to the ambient set: %s.\n", strerror(errno));
			return -2;
		}
	}

	if (cap_set_proc(cap_struct)) {
		if (cap_count < 2) {
			fprintf(stderr, "Cannot set capabilities as user: %s.\n", strerror(errno)); 
		} else {
			fprintf(stderr, "Cannot set capabilities as root: %s.\n", strerror(errno));
		}
		return -3;
	}

	if (cap_count > 1) {
		if (prctl(PR_SET_KEEPCAPS, 1L)) {
			fprintf(stderr, "Cannot keep capabilities after dropping privileges: %s.\n", strerror(errno));
			return -4;
		}
		if (cap_clear(cap_struct)) {
			fprintf(stderr, "Cannot clear capability data structure: %s.\n", strerror(errno));
			return -5;
		}
	}
}

int main(int argc, char **argv, char **envp) {
	cap_t cap_struct = cap_init();
	cap_value_t root_caps[2] = { CAP_NET_RAW, CAP_SETUID };
	cap_value_t user_caps[1] = { CAP_NET_RAW };
	uid_t user = getuid();
	int res;

	if (setresuid(0, 0, 0)) {
		fprintf(stderr, "Cannot switch to root: %s.\n", strerror(errno));
		return 1;
	}

	if (res = set_caps(cap_struct, root_caps, sizeof(root_caps)))
		return res;

	if (setresuid(user, user, user)) {
		fprintf(stderr, "Cannot drop root privileges: %s.\n", strerror(errno));
		return 2;
	}

	if (res = set_caps(cap_struct, user_caps, sizeof(user_caps)))
		return res;

	if (execve(argv[1], argv + 1, envp)) {
		fprintf(stderr, "Failed to execute %s: %s\n", argv[1], strerror(errno));
		return 3;
	}
}