iptables-1.2.9-2.3.1.src.rpm
[iptables.git] / extensions / libip6t_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 <ip6tables.h>
11 #include <linux/netfilter_ipv6/ip6t_owner.h>
12
13 /* Function which prints out usage message. */
14 static void
15 help(void)
16 {
17 #ifdef IP6T_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 "\n",
26 IPTABLES_VERSION);
27 #else
28         printf(
29 "OWNER match v%s options:\n"
30 "[!] --uid-owner userid     Match local uid\n"
31 "[!] --gid-owner groupid    Match local gid\n"
32 "[!] --pid-owner processid  Match local pid\n"
33 "[!] --sid-owner sessionid  Match local sid\n"
34 "\n",
35 IPTABLES_VERSION);
36 #endif /* IP6T_OWNER_COMM */
37 }
38
39 static struct option opts[] = {
40         { "uid-owner", 1, 0, '1' },
41         { "gid-owner", 1, 0, '2' },
42         { "pid-owner", 1, 0, '3' },
43         { "sid-owner", 1, 0, '4' },
44 #ifdef IP6T_OWNER_COMM
45         { "cmd-owner", 1, 0, '5' },
46 #endif
47         {0}
48 };
49
50 /* Initialize the match. */
51 static void
52 init(struct ip6t_entry_match *m, unsigned int *nfcache)
53 {
54         /* Can't cache this. */
55         *nfcache |= NFC_UNKNOWN;
56 }
57
58 /* Function which parses command options; returns true if it
59    ate an option */
60 static int
61 parse(int c, char **argv, int invert, unsigned int *flags,
62       const struct ip6t_entry *entry,
63       unsigned int *nfcache,
64       struct ip6t_entry_match **match)
65 {
66         struct ip6t_owner_info *ownerinfo = (struct ip6t_owner_info *)(*match)->data;
67
68         switch (c) {
69                 char *end;
70                 struct passwd *pwd;
71                 struct group *grp;
72         case '1':
73                 check_inverse(optarg, &invert, &optind, 0);
74
75                 if ((pwd = getpwnam(optarg)))
76                         ownerinfo->uid = pwd->pw_uid;
77                 else {
78                         ownerinfo->uid = strtoul(optarg, &end, 0);
79                         if (*end != '\0' || end == optarg)
80                                 exit_error(PARAMETER_PROBLEM, "Bad OWNER UID value `%s'", optarg);
81                 }
82                 if (invert)
83                         ownerinfo->invert |= IP6T_OWNER_UID;
84                 ownerinfo->match |= IP6T_OWNER_UID;
85                 *flags = 1;
86                 break;
87
88         case '2':
89                 check_inverse(optarg, &invert, &optind, 0);
90                 if ((grp = getgrnam(optarg)))
91                         ownerinfo->gid = grp->gr_gid;
92                 else {
93                         ownerinfo->gid = strtoul(optarg, &end, 0);
94                         if (*end != '\0' || end == optarg)
95                                 exit_error(PARAMETER_PROBLEM, "Bad OWNER GID value `%s'", optarg);
96                 }
97                 if (invert)
98                         ownerinfo->invert |= IP6T_OWNER_GID;
99                 ownerinfo->match |= IP6T_OWNER_GID;
100                 *flags = 1;
101                 break;
102
103         case '3':
104                 check_inverse(optarg, &invert, &optind, 0);
105                 ownerinfo->pid = strtoul(optarg, &end, 0);
106                 if (*end != '\0' || end == optarg)
107                         exit_error(PARAMETER_PROBLEM, "Bad OWNER PID value `%s'", optarg);
108                 if (invert)
109                         ownerinfo->invert |= IP6T_OWNER_PID;
110                 ownerinfo->match |= IP6T_OWNER_PID;
111                 *flags = 1;
112                 break;
113
114         case '4':
115                 check_inverse(optarg, &invert, &optind, 0);
116                 ownerinfo->sid = strtoul(optarg, &end, 0);
117                 if (*end != '\0' || end == optarg)
118                         exit_error(PARAMETER_PROBLEM, "Bad OWNER SID value `%s'", optarg);
119                 if (invert)
120                         ownerinfo->invert |= IP6T_OWNER_SID;
121                 ownerinfo->match |= IP6T_OWNER_SID;
122                 *flags = 1;
123                 break;
124
125 #ifdef IP6T_OWNER_COMM
126         case '5':
127                 check_inverse(optarg, &invert, &optind, 0);
128                 if(strlen(optarg) > sizeof(ownerinfo->comm))
129                         exit_error(PARAMETER_PROBLEM, "OWNER CMD `%s' too long, max %d characters", optarg, sizeof(ownerinfo->comm));
130                 
131                 strncpy(ownerinfo->comm, optarg, sizeof(ownerinfo->comm));
132
133                 if (invert)
134                         ownerinfo->invert |= IP6T_OWNER_COMM;
135                 ownerinfo->match |= IP6T_OWNER_COMM;
136                 *flags = 1;
137                 break;
138 #endif
139                 
140         default:
141                 return 0;
142         }
143         return 1;
144 }
145
146 static void
147 print_item(struct ip6t_owner_info *info, u_int8_t flag, int numeric, char *label)
148 {
149         if(info->match & flag) {
150
151                 printf(label);
152
153                 if (info->invert & flag)
154                         printf("! ");
155
156                 switch(info->match & flag) {
157                 case IP6T_OWNER_UID:
158                         if(!numeric) {
159                                 struct passwd *pwd = getpwuid(info->uid);
160
161                                 if(pwd && pwd->pw_name) {
162                                         printf("%s ", pwd->pw_name);
163                                         break;
164                                 }
165                                 /* FALLTHROUGH */
166                         }
167                         printf("%u ", info->uid);
168                         break;
169                 case IP6T_OWNER_GID:
170                         if(!numeric) {
171                                 struct group *grp = getgrgid(info->gid);
172
173                                 if(grp && grp->gr_name) {
174                                         printf("%s ", grp->gr_name);
175                                         break;
176                                 }
177                                 /* FALLTHROUGH */
178                         }
179                         printf("%u ", info->gid);
180                         break;
181                 case IP6T_OWNER_PID:
182                         printf("%u ", info->pid);
183                         break;
184                 case IP6T_OWNER_SID:
185                         printf("%u ", info->sid);
186                         break;
187 #ifdef IP6T_OWNER_COMM
188                 case IP6T_OWNER_COMM:
189                         printf("%.*s ", (int)sizeof(info->comm), info->comm);
190                         break;
191 #endif
192                 default:
193                         break;
194                 }
195         }
196 }
197
198 /* Final check; must have specified --own. */
199 static void
200 final_check(unsigned int flags)
201 {
202         if (!flags)
203                 exit_error(PARAMETER_PROBLEM,
204                            "OWNER match: You must specify one or more options");
205 }
206
207 /* Prints out the matchinfo. */
208 static void
209 print(const struct ip6t_ip6 *ip,
210       const struct ip6t_entry_match *match,
211       int numeric)
212 {
213         struct ip6t_owner_info *info = (struct ip6t_owner_info *)match->data;
214
215         print_item(info, IP6T_OWNER_UID, numeric, "OWNER UID match ");
216         print_item(info, IP6T_OWNER_GID, numeric, "OWNER GID match ");
217         print_item(info, IP6T_OWNER_PID, numeric, "OWNER PID match ");
218         print_item(info, IP6T_OWNER_SID, numeric, "OWNER SID match ");
219 #ifdef IP6T_OWNER_COMM
220         print_item(info, IP6T_OWNER_COMM, numeric, "OWNER CMD match ");
221 #endif
222 }
223
224 /* Saves the union ip6t_matchinfo in parsable form to stdout. */
225 static void
226 save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
227 {
228         struct ip6t_owner_info *info = (struct ip6t_owner_info *)match->data;
229
230         print_item(info, IP6T_OWNER_UID, 0, "--uid-owner ");
231         print_item(info, IP6T_OWNER_GID, 0, "--gid-owner ");
232         print_item(info, IP6T_OWNER_PID, 0, "--pid-owner ");
233         print_item(info, IP6T_OWNER_SID, 0, "--sid-owner ");
234 #ifdef IP6T_OWNER_COMM
235         print_item(info, IP6T_OWNER_COMM, 0, "--cmd-owner ");
236 #endif
237 }
238
239 static
240 struct ip6tables_match owner
241 = { NULL,
242     "owner",
243     IPTABLES_VERSION,
244     IP6T_ALIGN(sizeof(struct ip6t_owner_info)),
245     IP6T_ALIGN(sizeof(struct ip6t_owner_info)),
246     &help,
247     &init,
248     &parse,
249     &final_check,
250     &print,
251     &save,
252     opts
253 };
254
255 void _init(void)
256 {
257         register_match6(&owner);
258 }