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