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