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. */ 14static void 15help(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", 26IPTABLES_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", 35IPTABLES_VERSION); 36#endif /* IP6T_OWNER_COMM */ 37} 38 39static 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 */ 52static int 53parse(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 139static void 140print_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. */ 192static void 193final_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. */ 201static void 202print(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. */ 218static void 219save(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 232static 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 245void _init(void) 246{ 247 register_match6(&owner); 248} 249