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. */ 14static void 15help(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", 27IPTABLES_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", 37IPTABLES_VERSION); 38#endif /* IPT_OWNER_COMM */ 39} 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' }, 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 */ 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': 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 140static void 141print_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. */ 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 "); 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. */ 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 "); 228#ifdef IPT_OWNER_COMM 229 print_item(info, IPT_OWNER_COMM, 0, "--cmd-owner "); 230#endif 231} 232 233static 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 247void ipt_owner_init(void) 248{ 249 register_match(&owner); 250} 251