2 * libxt_owner - iptables addon for xt_owner
4 * Copyright © CC Computer Consultants GmbH, 2007 - 2008
5 * Jan Engelhardt <jengelh@computergmbh.de>
18 #include <linux/netfilter/xt_owner.h>
19 #include <linux/netfilter_ipv4/ipt_owner.h>
20 #include <linux/netfilter_ipv6/ip6t_owner.h>
23 * Note: "UINT32_MAX - 1" is used in the code because -1 is a reserved
24 * UID/GID value anyway.
28 FLAG_UID_OWNER
= 1 << 0,
29 FLAG_GID_OWNER
= 1 << 1,
30 FLAG_SOCKET_EXISTS
= 1 << 2,
31 FLAG_PID_OWNER
= 1 << 3,
32 FLAG_SID_OWNER
= 1 << 4,
36 static void owner_mt_help_v0(void)
40 "owner match options:\n"
41 "[!] --uid-owner userid Match local UID\n"
42 "[!] --gid-owner groupid Match local GID\n"
43 "[!] --pid-owner processid Match local PID\n"
44 "[!] --sid-owner sessionid Match local SID\n"
45 "[!] --cmd-owner name Match local command name\n"
46 "NOTE: PID, SID and command matching are broken on SMP\n");
49 "owner match options:\n"
50 "[!] --uid-owner userid Match local UID\n"
51 "[!] --gid-owner groupid Match local GID\n"
52 "[!] --pid-owner processid Match local PID\n"
53 "[!] --sid-owner sessionid Match local SID\n"
54 "NOTE: PID and SID matching are broken on SMP\n");
55 #endif /* IPT_OWNER_COMM */
58 static void owner_mt6_help_v0(void)
61 "owner match options:\n"
62 "[!] --uid-owner userid Match local UID\n"
63 "[!] --gid-owner groupid Match local GID\n"
64 "[!] --pid-owner processid Match local PID\n"
65 "[!] --sid-owner sessionid Match local SID\n"
66 "NOTE: PID and SID matching are broken on SMP\n");
69 static void owner_mt_help(void)
72 "owner match options:\n"
73 "[!] --uid-owner userid[-userid] Match local UID\n"
74 "[!] --gid-owner groupid[-groupid] Match local GID\n"
75 "[!] --socket-exists Match if socket exists\n");
78 static const struct option owner_mt_opts_v0
[] = {
79 {.name
= "uid-owner", .has_arg
= true, .val
= 'u'},
80 {.name
= "gid-owner", .has_arg
= true, .val
= 'g'},
81 {.name
= "pid-owner", .has_arg
= true, .val
= 'p'},
82 {.name
= "sid-owner", .has_arg
= true, .val
= 's'},
84 {.name
= "cmd-owner", .has_arg
= true, .val
= 'c'},
89 static const struct option owner_mt6_opts_v0
[] = {
90 {.name
= "uid-owner", .has_arg
= true, .val
= 'u'},
91 {.name
= "gid-owner", .has_arg
= true, .val
= 'g'},
92 {.name
= "pid-owner", .has_arg
= true, .val
= 'p'},
93 {.name
= "sid-owner", .has_arg
= true, .val
= 's'},
97 static const struct option owner_mt_opts
[] = {
98 {.name
= "uid-owner", .has_arg
= true, .val
= 'u'},
99 {.name
= "gid-owner", .has_arg
= true, .val
= 'g'},
100 {.name
= "socket-exists", .has_arg
= false, .val
= 'k'},
105 owner_mt_parse_v0(int c
, char **argv
, int invert
, unsigned int *flags
,
106 const void *entry
, struct xt_entry_match
**match
)
108 struct ipt_owner_info
*info
= (void *)(*match
)->data
;
115 xtables_param_act(XTF_ONLY_ONCE
, "owner", "--uid-owner", *flags
& FLAG_UID_OWNER
);
116 if ((pwd
= getpwnam(optarg
)) != NULL
)
118 else if (!xtables_strtoui(optarg
, NULL
, &id
, 0, UINT32_MAX
- 1))
119 xtables_param_act(XTF_BAD_VALUE
, "owner", "--uid-owner", optarg
);
121 info
->invert
|= IPT_OWNER_UID
;
122 info
->match
|= IPT_OWNER_UID
;
124 *flags
|= FLAG_UID_OWNER
;
128 xtables_param_act(XTF_ONLY_ONCE
, "owner", "--gid-owner", *flags
& FLAG_GID_OWNER
);
129 if ((grp
= getgrnam(optarg
)) != NULL
)
131 else if (!xtables_strtoui(optarg
, NULL
, &id
, 0, UINT32_MAX
- 1))
132 xtables_param_act(XTF_BAD_VALUE
, "owner", "--gid-owner", optarg
);
134 info
->invert
|= IPT_OWNER_GID
;
135 info
->match
|= IPT_OWNER_GID
;
137 *flags
|= FLAG_GID_OWNER
;
141 xtables_param_act(XTF_ONLY_ONCE
, "owner", "--pid-owner", *flags
& FLAG_PID_OWNER
);
142 if (!xtables_strtoui(optarg
, NULL
, &id
, 0, INT_MAX
))
143 xtables_param_act(XTF_BAD_VALUE
, "owner", "--pid-owner", optarg
);
145 info
->invert
|= IPT_OWNER_PID
;
146 info
->match
|= IPT_OWNER_PID
;
148 *flags
|= FLAG_PID_OWNER
;
152 xtables_param_act(XTF_ONLY_ONCE
, "owner", "--sid-owner", *flags
& FLAG_SID_OWNER
);
153 if (!xtables_strtoui(optarg
, NULL
, &id
, 0, INT_MAX
))
154 xtables_param_act(XTF_BAD_VALUE
, "owner", "--sid-value", optarg
);
156 info
->invert
|= IPT_OWNER_SID
;
157 info
->match
|= IPT_OWNER_SID
;
159 *flags
|= FLAG_SID_OWNER
;
162 #ifdef IPT_OWNER_COMM
164 xtables_param_act(XTF_ONLY_ONCE
, "owner", "--cmd-owner", *flags
& FLAG_COMM
);
165 if (strlen(optarg
) > sizeof(info
->comm
))
166 xtables_error(PARAMETER_PROBLEM
, "owner match: command "
167 "\"%s\" too long, max. %zu characters",
168 optarg
, sizeof(info
->comm
));
170 info
->comm
[sizeof(info
->comm
)-1] = '\0';
171 strncpy(info
->comm
, optarg
, sizeof(info
->comm
));
174 info
->invert
|= IPT_OWNER_COMM
;
175 info
->match
|= IPT_OWNER_COMM
;
184 owner_mt6_parse_v0(int c
, char **argv
, int invert
, unsigned int *flags
,
185 const void *entry
, struct xt_entry_match
**match
)
187 struct ip6t_owner_info
*info
= (void *)(*match
)->data
;
194 xtables_param_act(XTF_ONLY_ONCE
, "owner", "--uid-owner",
195 *flags
& FLAG_UID_OWNER
);
196 if ((pwd
= getpwnam(optarg
)) != NULL
)
198 else if (!xtables_strtoui(optarg
, NULL
, &id
, 0, UINT32_MAX
- 1))
199 xtables_param_act(XTF_BAD_VALUE
, "owner", "--uid-owner", optarg
);
201 info
->invert
|= IP6T_OWNER_UID
;
202 info
->match
|= IP6T_OWNER_UID
;
204 *flags
|= FLAG_UID_OWNER
;
208 xtables_param_act(XTF_ONLY_ONCE
, "owner", "--gid-owner",
209 *flags
& FLAG_GID_OWNER
);
210 if ((grp
= getgrnam(optarg
)) != NULL
)
212 else if (!xtables_strtoui(optarg
, NULL
, &id
, 0, UINT32_MAX
- 1))
213 xtables_param_act(XTF_BAD_VALUE
, "owner", "--gid-owner", optarg
);
215 info
->invert
|= IP6T_OWNER_GID
;
216 info
->match
|= IP6T_OWNER_GID
;
218 *flags
|= FLAG_GID_OWNER
;
222 xtables_param_act(XTF_ONLY_ONCE
, "owner", "--pid-owner",
223 *flags
& FLAG_PID_OWNER
);
224 if (!xtables_strtoui(optarg
, NULL
, &id
, 0, INT_MAX
))
225 xtables_param_act(XTF_BAD_VALUE
, "owner", "--pid-owner", optarg
);
227 info
->invert
|= IP6T_OWNER_PID
;
228 info
->match
|= IP6T_OWNER_PID
;
230 *flags
|= FLAG_PID_OWNER
;
234 xtables_param_act(XTF_ONLY_ONCE
, "owner", "--sid-owner",
235 *flags
& FLAG_SID_OWNER
);
236 if (!xtables_strtoui(optarg
, NULL
, &id
, 0, INT_MAX
))
237 xtables_param_act(XTF_BAD_VALUE
, "owner", "--sid-owner", optarg
);
239 info
->invert
|= IP6T_OWNER_SID
;
240 info
->match
|= IP6T_OWNER_SID
;
242 *flags
|= FLAG_SID_OWNER
;
248 static void owner_parse_range(const char *s
, unsigned int *from
,
249 unsigned int *to
, const char *opt
)
253 /* -1 is reversed, so the max is one less than that. */
254 if (!xtables_strtoui(s
, &end
, from
, 0, UINT32_MAX
- 1))
255 xtables_param_act(XTF_BAD_VALUE
, "owner", opt
, s
);
257 if (*end
== '-' || *end
== ':')
258 if (!xtables_strtoui(end
+ 1, &end
, to
, 0, UINT32_MAX
- 1))
259 xtables_param_act(XTF_BAD_VALUE
, "owner", opt
, s
);
261 xtables_param_act(XTF_BAD_VALUE
, "owner", opt
, s
);
264 static int owner_mt_parse(int c
, char **argv
, int invert
, unsigned int *flags
,
265 const void *entry
, struct xt_entry_match
**match
)
267 struct xt_owner_match_info
*info
= (void *)(*match
)->data
;
270 unsigned int from
, to
;
274 xtables_param_act(XTF_ONLY_ONCE
, "owner", "--uid-owner",
275 *flags
& FLAG_UID_OWNER
);
276 if ((pwd
= getpwnam(optarg
)) != NULL
)
277 from
= to
= pwd
->pw_uid
;
279 owner_parse_range(optarg
, &from
, &to
, "--uid-owner");
281 info
->invert
|= XT_OWNER_UID
;
282 info
->match
|= XT_OWNER_UID
;
283 info
->uid_min
= from
;
285 *flags
|= FLAG_UID_OWNER
;
289 xtables_param_act(XTF_ONLY_ONCE
, "owner", "--gid-owner",
290 *flags
& FLAG_GID_OWNER
);
291 if ((grp
= getgrnam(optarg
)) != NULL
)
292 from
= to
= grp
->gr_gid
;
294 owner_parse_range(optarg
, &from
, &to
, "--gid-owner");
296 info
->invert
|= XT_OWNER_GID
;
297 info
->match
|= XT_OWNER_GID
;
298 info
->gid_min
= from
;
300 *flags
|= FLAG_GID_OWNER
;
304 xtables_param_act(XTF_ONLY_ONCE
, "owner", "--socket-exists",
305 *flags
& FLAG_SOCKET_EXISTS
);
307 info
->invert
|= XT_OWNER_SOCKET
;
308 info
->match
|= XT_OWNER_SOCKET
;
309 *flags
|= FLAG_SOCKET_EXISTS
;
316 static void owner_mt_check(unsigned int flags
)
319 xtables_error(PARAMETER_PROBLEM
, "owner: At least one of "
320 "--uid-owner, --gid-owner or --socket-exists "
325 owner_mt_print_item_v0(const struct ipt_owner_info
*info
, const char *label
,
326 u_int8_t flag
, bool numeric
)
328 if (!(info
->match
& flag
))
330 if (info
->invert
& flag
)
332 printf("%s ", label
);
334 switch (info
->match
& flag
) {
337 struct passwd
*pwd
= getpwuid(info
->uid
);
339 if (pwd
!= NULL
&& pwd
->pw_name
!= NULL
) {
340 printf("%s ", pwd
->pw_name
);
344 printf("%u ", (unsigned int)info
->uid
);
349 struct group
*grp
= getgrgid(info
->gid
);
351 if (grp
!= NULL
&& grp
->gr_name
!= NULL
) {
352 printf("%s ", grp
->gr_name
);
356 printf("%u ", (unsigned int)info
->gid
);
360 printf("%u ", (unsigned int)info
->pid
);
364 printf("%u ", (unsigned int)info
->sid
);
367 #ifdef IPT_OWNER_COMM
369 printf("%.*s ", (int)sizeof(info
->comm
), info
->comm
);
376 owner_mt6_print_item_v0(const struct ip6t_owner_info
*info
, const char *label
,
377 u_int8_t flag
, bool numeric
)
379 if (!(info
->match
& flag
))
381 if (info
->invert
& flag
)
383 printf("%s ", label
);
385 switch (info
->match
& flag
) {
388 struct passwd
*pwd
= getpwuid(info
->uid
);
390 if (pwd
!= NULL
&& pwd
->pw_name
!= NULL
) {
391 printf("%s ", pwd
->pw_name
);
395 printf("%u ", (unsigned int)info
->uid
);
400 struct group
*grp
= getgrgid(info
->gid
);
402 if (grp
!= NULL
&& grp
->gr_name
!= NULL
) {
403 printf("%s ", grp
->gr_name
);
407 printf("%u ", (unsigned int)info
->gid
);
411 printf("%u ", (unsigned int)info
->pid
);
415 printf("%u ", (unsigned int)info
->sid
);
421 owner_mt_print_item(const struct xt_owner_match_info
*info
, const char *label
,
422 u_int8_t flag
, bool numeric
)
424 if (!(info
->match
& flag
))
426 if (info
->invert
& flag
)
428 printf("%s ", label
);
430 switch (info
->match
& flag
) {
432 if (info
->uid_min
!= info
->uid_max
) {
433 printf("%u-%u ", (unsigned int)info
->uid_min
,
434 (unsigned int)info
->uid_max
);
436 } else if (!numeric
) {
437 const struct passwd
*pwd
= getpwuid(info
->uid_min
);
439 if (pwd
!= NULL
&& pwd
->pw_name
!= NULL
) {
440 printf("%s ", pwd
->pw_name
);
444 printf("%u ", (unsigned int)info
->uid_min
);
448 if (info
->gid_min
!= info
->gid_max
) {
449 printf("%u-%u ", (unsigned int)info
->gid_min
,
450 (unsigned int)info
->gid_max
);
452 } else if (!numeric
) {
453 const struct group
*grp
= getgrgid(info
->gid_min
);
455 if (grp
!= NULL
&& grp
->gr_name
!= NULL
) {
456 printf("%s ", grp
->gr_name
);
460 printf("%u ", (unsigned int)info
->gid_min
);
466 owner_mt_print_v0(const void *ip
, const struct xt_entry_match
*match
,
469 const struct ipt_owner_info
*info
= (void *)match
->data
;
471 owner_mt_print_item_v0(info
, "owner UID match", IPT_OWNER_UID
, numeric
);
472 owner_mt_print_item_v0(info
, "owner GID match", IPT_OWNER_GID
, numeric
);
473 owner_mt_print_item_v0(info
, "owner PID match", IPT_OWNER_PID
, numeric
);
474 owner_mt_print_item_v0(info
, "owner SID match", IPT_OWNER_SID
, numeric
);
475 #ifdef IPT_OWNER_COMM
476 owner_mt_print_item_v0(info
, "owner CMD match", IPT_OWNER_COMM
, numeric
);
481 owner_mt6_print_v0(const void *ip
, const struct xt_entry_match
*match
,
484 const struct ip6t_owner_info
*info
= (void *)match
->data
;
486 owner_mt6_print_item_v0(info
, "owner UID match", IPT_OWNER_UID
, numeric
);
487 owner_mt6_print_item_v0(info
, "owner GID match", IPT_OWNER_GID
, numeric
);
488 owner_mt6_print_item_v0(info
, "owner PID match", IPT_OWNER_PID
, numeric
);
489 owner_mt6_print_item_v0(info
, "owner SID match", IPT_OWNER_SID
, numeric
);
492 static void owner_mt_print(const void *ip
, const struct xt_entry_match
*match
,
495 const struct xt_owner_match_info
*info
= (void *)match
->data
;
497 owner_mt_print_item(info
, "owner socket exists", XT_OWNER_SOCKET
, numeric
);
498 owner_mt_print_item(info
, "owner UID match", XT_OWNER_UID
, numeric
);
499 owner_mt_print_item(info
, "owner GID match", XT_OWNER_GID
, numeric
);
503 owner_mt_save_v0(const void *ip
, const struct xt_entry_match
*match
)
505 const struct ipt_owner_info
*info
= (void *)match
->data
;
507 owner_mt_print_item_v0(info
, "--uid-owner", IPT_OWNER_UID
, true);
508 owner_mt_print_item_v0(info
, "--gid-owner", IPT_OWNER_GID
, true);
509 owner_mt_print_item_v0(info
, "--pid-owner", IPT_OWNER_PID
, true);
510 owner_mt_print_item_v0(info
, "--sid-owner", IPT_OWNER_SID
, true);
511 #ifdef IPT_OWNER_COMM
512 owner_mt_print_item_v0(info
, "--cmd-owner", IPT_OWNER_COMM
, true);
517 owner_mt6_save_v0(const void *ip
, const struct xt_entry_match
*match
)
519 const struct ip6t_owner_info
*info
= (void *)match
->data
;
521 owner_mt6_print_item_v0(info
, "--uid-owner", IPT_OWNER_UID
, true);
522 owner_mt6_print_item_v0(info
, "--gid-owner", IPT_OWNER_GID
, true);
523 owner_mt6_print_item_v0(info
, "--pid-owner", IPT_OWNER_PID
, true);
524 owner_mt6_print_item_v0(info
, "--sid-owner", IPT_OWNER_SID
, true);
527 static void owner_mt_save(const void *ip
, const struct xt_entry_match
*match
)
529 const struct xt_owner_match_info
*info
= (void *)match
->data
;
531 owner_mt_print_item(info
, "--socket-exists", XT_OWNER_SOCKET
, false);
532 owner_mt_print_item(info
, "--uid-owner", XT_OWNER_UID
, false);
533 owner_mt_print_item(info
, "--gid-owner", XT_OWNER_GID
, false);
536 static struct xtables_match owner_mt_reg_v0
= {
537 .version
= XTABLES_VERSION
,
540 .family
= NFPROTO_IPV4
,
541 .size
= XT_ALIGN(sizeof(struct ipt_owner_info
)),
542 .userspacesize
= XT_ALIGN(sizeof(struct ipt_owner_info
)),
543 .help
= owner_mt_help_v0
,
544 .parse
= owner_mt_parse_v0
,
545 .final_check
= owner_mt_check
,
546 .print
= owner_mt_print_v0
,
547 .save
= owner_mt_save_v0
,
548 .extra_opts
= owner_mt_opts_v0
,
551 static struct xtables_match owner_mt6_reg_v0
= {
552 .version
= XTABLES_VERSION
,
555 .family
= NFPROTO_IPV6
,
556 .size
= XT_ALIGN(sizeof(struct ip6t_owner_info
)),
557 .userspacesize
= XT_ALIGN(sizeof(struct ip6t_owner_info
)),
558 .help
= owner_mt6_help_v0
,
559 .parse
= owner_mt6_parse_v0
,
560 .final_check
= owner_mt_check
,
561 .print
= owner_mt6_print_v0
,
562 .save
= owner_mt6_save_v0
,
563 .extra_opts
= owner_mt6_opts_v0
,
566 static struct xtables_match owner_mt_reg
= {
567 .version
= XTABLES_VERSION
,
570 .family
= NFPROTO_IPV4
,
571 .size
= XT_ALIGN(sizeof(struct xt_owner_match_info
)),
572 .userspacesize
= XT_ALIGN(sizeof(struct xt_owner_match_info
)),
573 .help
= owner_mt_help
,
574 .parse
= owner_mt_parse
,
575 .final_check
= owner_mt_check
,
576 .print
= owner_mt_print
,
577 .save
= owner_mt_save
,
578 .extra_opts
= owner_mt_opts
,
581 static struct xtables_match owner_mt6_reg
= {
582 .version
= XTABLES_VERSION
,
585 .family
= NFPROTO_IPV6
,
586 .size
= XT_ALIGN(sizeof(struct xt_owner_match_info
)),
587 .userspacesize
= XT_ALIGN(sizeof(struct xt_owner_match_info
)),
588 .help
= owner_mt_help
,
589 .parse
= owner_mt_parse
,
590 .final_check
= owner_mt_check
,
591 .print
= owner_mt_print
,
592 .save
= owner_mt_save
,
593 .extra_opts
= owner_mt_opts
,
598 xtables_register_match(&owner_mt_reg_v0
);
599 xtables_register_match(&owner_mt6_reg_v0
);
600 xtables_register_match(&owner_mt_reg
);
601 xtables_register_match(&owner_mt6_reg
);