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