blob: cf13cb970ba8c5ece54e7d1c30e25424c7fb7de0 [file] [log] [blame]
Marc Bouchere6869a82000-03-20 06:03:29 +00001/* 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. */
14static void
15help(void)
16{
Silvan Minghetti5cc4f7e2002-04-10 13:12:53 +000017#ifdef IPT_OWNER_COMM
Marc Bouchere6869a82000-03-20 06:03:29 +000018 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"
Marc Boucherf5c32d62002-01-19 12:46:04 +000024"[!] --cmd-owner name Match local command name\n"
Phil Oester2608b6e2004-10-01 21:32:39 +000025"NOTE: pid, sid and command matching are broken on SMP\n"
Marc Bouchere6869a82000-03-20 06:03:29 +000026"\n",
Harald Welte80fe35d2002-05-29 13:08:15 +000027IPTABLES_VERSION);
Silvan Minghetti5cc4f7e2002-04-10 13:12:53 +000028#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"
Phil Oester2608b6e2004-10-01 21:32:39 +000035"NOTE: pid and sid matching are broken on SMP\n"
Silvan Minghetti5cc4f7e2002-04-10 13:12:53 +000036"\n",
Harald Welte80fe35d2002-05-29 13:08:15 +000037IPTABLES_VERSION);
Silvan Minghetti5cc4f7e2002-04-10 13:12:53 +000038#endif /* IPT_OWNER_COMM */
Marc Bouchere6869a82000-03-20 06:03:29 +000039}
40
41static 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' },
Marc Boucherf5c32d62002-01-19 12:46:04 +000046#ifdef IPT_OWNER_COMM
47 { "cmd-owner", 1, 0, '5' },
48#endif
Marc Bouchere6869a82000-03-20 06:03:29 +000049 {0}
50};
51
Marc Bouchere6869a82000-03-20 06:03:29 +000052/* Function which parses command options; returns true if it
53 ate an option */
54static int
55parse(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':
Harald Welteb77f1da2002-03-14 11:35:58 +000067 check_inverse(optarg, &invert, &optind, 0);
Marc Bouchere6869a82000-03-20 06:03:29 +000068 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':
Harald Welteb77f1da2002-03-14 11:35:58 +000082 check_inverse(optarg, &invert, &optind, 0);
Marc Bouchere6869a82000-03-20 06:03:29 +000083 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':
Harald Welteb77f1da2002-03-14 11:35:58 +000097 check_inverse(optarg, &invert, &optind, 0);
Marc Bouchere6869a82000-03-20 06:03:29 +000098 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':
Harald Welteb77f1da2002-03-14 11:35:58 +0000108 check_inverse(optarg, &invert, &optind, 0);
Marc Bouchere6869a82000-03-20 06:03:29 +0000109 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
Marc Boucherf5c32d62002-01-19 12:46:04 +0000118#ifdef IPT_OWNER_COMM
119 case '5':
Harald Welteb77f1da2002-03-14 11:35:58 +0000120 check_inverse(optarg, &invert, &optind, 0);
Marc Boucherf5c32d62002-01-19 12:46:04 +0000121 if(strlen(optarg) > sizeof(ownerinfo->comm))
Martin Josefssona28d4952004-05-26 16:04:48 +0000122 exit_error(PARAMETER_PROBLEM, "OWNER CMD `%s' too long, max %u characters", optarg, (unsigned int)sizeof(ownerinfo->comm));
Marc Boucherf5c32d62002-01-19 12:46:04 +0000123
124 strncpy(ownerinfo->comm, optarg, sizeof(ownerinfo->comm));
Karsten Desler073df8f2004-01-31 15:33:55 +0000125 ownerinfo->comm[sizeof(ownerinfo->comm)-1] = '\0';
Marc Boucherf5c32d62002-01-19 12:46:04 +0000126
127 if (invert)
128 ownerinfo->invert |= IPT_OWNER_COMM;
129 ownerinfo->match |= IPT_OWNER_COMM;
130 *flags = 1;
131 break;
132#endif
133
Marc Bouchere6869a82000-03-20 06:03:29 +0000134 default:
135 return 0;
136 }
137 return 1;
138}
139
140static void
141print_item(struct ipt_owner_info *info, u_int8_t flag, int numeric, char *label)
142{
143 if(info->match & flag) {
144
Marc Bouchere6869a82000-03-20 06:03:29 +0000145 if (info->invert & flag)
Martin Josefsson93b7e702003-05-03 12:11:41 +0000146 printf("! ");
Marc Bouchere6869a82000-03-20 06:03:29 +0000147
Harald Welted0b0ca42003-01-06 12:40:33 +0000148 printf(label);
149
Marc Bouchere6869a82000-03-20 06:03:29 +0000150 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;
Marc Boucherf5c32d62002-01-19 12:46:04 +0000181#ifdef IPT_OWNER_COMM
182 case IPT_OWNER_COMM:
183 printf("%.*s ", (int)sizeof(info->comm), info->comm);
184 break;
185#endif
Marc Bouchere6869a82000-03-20 06:03:29 +0000186 default:
187 break;
188 }
189 }
190}
191
192/* Final check; must have specified --own. */
193static void
194final_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. */
202static void
203print(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 ");
Marc Boucherf5c32d62002-01-19 12:46:04 +0000213#ifdef IPT_OWNER_COMM
214 print_item(info, IPT_OWNER_COMM, numeric, "OWNER CMD match ");
215#endif
Marc Bouchere6869a82000-03-20 06:03:29 +0000216}
217
218/* Saves the union ipt_matchinfo in parsable form to stdout. */
219static void
220save(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 ");
Marc Boucherf5c32d62002-01-19 12:46:04 +0000228#ifdef IPT_OWNER_COMM
229 print_item(info, IPT_OWNER_COMM, 0, "--cmd-owner ");
230#endif
Marc Bouchere6869a82000-03-20 06:03:29 +0000231}
232
Pablo Neira8caee8b2004-12-28 13:11:59 +0000233static 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,
Pablo Neira8caee8b2004-12-28 13:11:59 +0000240 .parse = &parse,
241 .final_check = &final_check,
242 .print = &print,
243 .save = &save,
244 .extra_opts = opts
Marc Bouchere6869a82000-03-20 06:03:29 +0000245};
246
247void _init(void)
248{
249 register_match(&owner);
250}