• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Shared library add-on to iptables to add OWNER matching support. */
2 #include <stdio.h>
3 #include <netdb.h>
4 #include <string.h>
5 #include <stdlib.h>
6 #include <getopt.h>
7 #include <pwd.h>
8 #include <grp.h>
9 
10 #include <iptables.h>
11 #include <linux/netfilter_ipv4/ipt_owner.h>
12 
13 /* Function which prints out usage message. */
14 static void
help(void)15 help(void)
16 {
17 #ifdef IPT_OWNER_COMM
18 	printf(
19 "OWNER match v%s options:\n"
20 "[!] --uid-owner userid     Match local uid\n"
21 "[!] --gid-owner groupid    Match local gid\n"
22 "[!] --pid-owner processid  Match local pid\n"
23 "[!] --sid-owner sessionid  Match local sid\n"
24 "[!] --cmd-owner name       Match local command name\n"
25 "NOTE: pid, sid and command matching are broken on SMP\n"
26 "\n",
27 IPTABLES_VERSION);
28 #else
29 	printf(
30 "OWNER match v%s options:\n"
31 "[!] --uid-owner userid     Match local uid\n"
32 "[!] --gid-owner groupid    Match local gid\n"
33 "[!] --pid-owner processid  Match local pid\n"
34 "[!] --sid-owner sessionid  Match local sid\n"
35 "NOTE: pid and sid matching are broken on SMP\n"
36 "\n",
37 IPTABLES_VERSION);
38 #endif /* IPT_OWNER_COMM */
39 }
40 
41 static struct option opts[] = {
42 	{ "uid-owner", 1, 0, '1' },
43 	{ "gid-owner", 1, 0, '2' },
44 	{ "pid-owner", 1, 0, '3' },
45 	{ "sid-owner", 1, 0, '4' },
46 #ifdef IPT_OWNER_COMM
47 	{ "cmd-owner", 1, 0, '5' },
48 #endif
49 	{0}
50 };
51 
52 /* Function which parses command options; returns true if it
53    ate an option */
54 static int
parse(int c,char ** argv,int invert,unsigned int * flags,const struct ipt_entry * entry,unsigned int * nfcache,struct ipt_entry_match ** match)55 parse(int c, char **argv, int invert, unsigned int *flags,
56       const struct ipt_entry *entry,
57       unsigned int *nfcache,
58       struct ipt_entry_match **match)
59 {
60 	struct ipt_owner_info *ownerinfo = (struct ipt_owner_info *)(*match)->data;
61 
62 	switch (c) {
63 		char *end;
64 		struct passwd *pwd;
65 		struct group *grp;
66 	case '1':
67 		check_inverse(optarg, &invert, &optind, 0);
68 		if ((pwd = getpwnam(optarg)))
69 			ownerinfo->uid = pwd->pw_uid;
70 		else {
71 			ownerinfo->uid = strtoul(optarg, &end, 0);
72 			if (*end != '\0' || end == optarg)
73 				exit_error(PARAMETER_PROBLEM, "Bad OWNER UID value `%s'", optarg);
74 		}
75 		if (invert)
76 			ownerinfo->invert |= IPT_OWNER_UID;
77 		ownerinfo->match |= IPT_OWNER_UID;
78 		*flags = 1;
79 		break;
80 
81 	case '2':
82 		check_inverse(optarg, &invert, &optind, 0);
83 		if ((grp = getgrnam(optarg)))
84 			ownerinfo->gid = grp->gr_gid;
85 		else {
86 			ownerinfo->gid = strtoul(optarg, &end, 0);
87 			if (*end != '\0' || end == optarg)
88 				exit_error(PARAMETER_PROBLEM, "Bad OWNER GID value `%s'", optarg);
89 		}
90 		if (invert)
91 			ownerinfo->invert |= IPT_OWNER_GID;
92 		ownerinfo->match |= IPT_OWNER_GID;
93 		*flags = 1;
94 		break;
95 
96 	case '3':
97 		check_inverse(optarg, &invert, &optind, 0);
98 		ownerinfo->pid = strtoul(optarg, &end, 0);
99 		if (*end != '\0' || end == optarg)
100 			exit_error(PARAMETER_PROBLEM, "Bad OWNER PID value `%s'", optarg);
101 		if (invert)
102 			ownerinfo->invert |= IPT_OWNER_PID;
103 		ownerinfo->match |= IPT_OWNER_PID;
104 		*flags = 1;
105 		break;
106 
107 	case '4':
108 		check_inverse(optarg, &invert, &optind, 0);
109 		ownerinfo->sid = strtoul(optarg, &end, 0);
110 		if (*end != '\0' || end == optarg)
111 			exit_error(PARAMETER_PROBLEM, "Bad OWNER SID value `%s'", optarg);
112 		if (invert)
113 			ownerinfo->invert |= IPT_OWNER_SID;
114 		ownerinfo->match |= IPT_OWNER_SID;
115 		*flags = 1;
116 		break;
117 
118 #ifdef IPT_OWNER_COMM
119 	case '5':
120 		check_inverse(optarg, &invert, &optind, 0);
121 		if(strlen(optarg) > sizeof(ownerinfo->comm))
122 			exit_error(PARAMETER_PROBLEM, "OWNER CMD `%s' too long, max %u characters", optarg, (unsigned int)sizeof(ownerinfo->comm));
123 
124 		strncpy(ownerinfo->comm, optarg, sizeof(ownerinfo->comm));
125 		ownerinfo->comm[sizeof(ownerinfo->comm)-1] = '\0';
126 
127 		if (invert)
128 			ownerinfo->invert |= IPT_OWNER_COMM;
129 		ownerinfo->match |= IPT_OWNER_COMM;
130 		*flags = 1;
131 		break;
132 #endif
133 
134 	default:
135 		return 0;
136 	}
137 	return 1;
138 }
139 
140 static void
print_item(struct ipt_owner_info * info,u_int8_t flag,int numeric,char * label)141 print_item(struct ipt_owner_info *info, u_int8_t flag, int numeric, char *label)
142 {
143 	if(info->match & flag) {
144 
145 		if (info->invert & flag)
146 			printf("! ");
147 
148 		printf(label);
149 
150 		switch(info->match & flag) {
151 		case IPT_OWNER_UID:
152 			if(!numeric) {
153 				struct passwd *pwd = getpwuid(info->uid);
154 
155 				if(pwd && pwd->pw_name) {
156 					printf("%s ", pwd->pw_name);
157 					break;
158 				}
159 				/* FALLTHROUGH */
160 			}
161 			printf("%u ", info->uid);
162 			break;
163 		case IPT_OWNER_GID:
164 			if(!numeric) {
165 				struct group *grp = getgrgid(info->gid);
166 
167 				if(grp && grp->gr_name) {
168 					printf("%s ", grp->gr_name);
169 					break;
170 				}
171 				/* FALLTHROUGH */
172 			}
173 			printf("%u ", info->gid);
174 			break;
175 		case IPT_OWNER_PID:
176 			printf("%u ", info->pid);
177 			break;
178 		case IPT_OWNER_SID:
179 			printf("%u ", info->sid);
180 			break;
181 #ifdef IPT_OWNER_COMM
182 		case IPT_OWNER_COMM:
183 			printf("%.*s ", (int)sizeof(info->comm), info->comm);
184 			break;
185 #endif
186 		default:
187 			break;
188 		}
189 	}
190 }
191 
192 /* Final check; must have specified --own. */
193 static void
final_check(unsigned int flags)194 final_check(unsigned int flags)
195 {
196 	if (!flags)
197 		exit_error(PARAMETER_PROBLEM,
198 			   "OWNER match: You must specify one or more options");
199 }
200 
201 /* Prints out the matchinfo. */
202 static void
print(const struct ipt_ip * ip,const struct ipt_entry_match * match,int numeric)203 print(const struct ipt_ip *ip,
204       const struct ipt_entry_match *match,
205       int numeric)
206 {
207 	struct ipt_owner_info *info = (struct ipt_owner_info *)match->data;
208 
209 	print_item(info, IPT_OWNER_UID, numeric, "OWNER UID match ");
210 	print_item(info, IPT_OWNER_GID, numeric, "OWNER GID match ");
211 	print_item(info, IPT_OWNER_PID, numeric, "OWNER PID match ");
212 	print_item(info, IPT_OWNER_SID, numeric, "OWNER SID match ");
213 #ifdef IPT_OWNER_COMM
214 	print_item(info, IPT_OWNER_COMM, numeric, "OWNER CMD match ");
215 #endif
216 }
217 
218 /* Saves the union ipt_matchinfo in parsable form to stdout. */
219 static void
save(const struct ipt_ip * ip,const struct ipt_entry_match * match)220 save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
221 {
222 	struct ipt_owner_info *info = (struct ipt_owner_info *)match->data;
223 
224 	print_item(info, IPT_OWNER_UID, 0, "--uid-owner ");
225 	print_item(info, IPT_OWNER_GID, 0, "--gid-owner ");
226 	print_item(info, IPT_OWNER_PID, 0, "--pid-owner ");
227 	print_item(info, IPT_OWNER_SID, 0, "--sid-owner ");
228 #ifdef IPT_OWNER_COMM
229 	print_item(info, IPT_OWNER_COMM, 0, "--cmd-owner ");
230 #endif
231 }
232 
233 static struct iptables_match owner = {
234 	.next		= NULL,
235 	.name		= "owner",
236 	.version	= IPTABLES_VERSION,
237 	.size		= IPT_ALIGN(sizeof(struct ipt_owner_info)),
238 	.userspacesize	= IPT_ALIGN(sizeof(struct ipt_owner_info)),
239 	.help		= &help,
240 	.parse		= &parse,
241 	.final_check	= &final_check,
242 	.print		= &print,
243 	.save		= &save,
244 	.extra_opts	= opts
245 };
246 
ipt_owner_init(void)247 void ipt_owner_init(void)
248 {
249 	register_match(&owner);
250 }
251