iptables-1.3.2-20050720
[iptables.git] / extensions / libipt_owner.c
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
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
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
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
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
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
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
247 void _init(void)
248 {
249         register_match(&owner);
250 }