1 /*- 2 * Copyright (c) 2018 Christian S.J. Peron 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/types.h> 28 #include <sys/socket.h> 29 30 #include <bsm/audit.h> 31 #include <bsm/libbsm.h> 32 33 #include <netinet/in.h> 34 35 #include <err.h> 36 #include <netdb.h> 37 #include <pwd.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <unistd.h> 42 43 static void 44 usage(char *prog) 45 { 46 (void)fprintf(stderr, 47 "usage: %s [-46] [-a auid] [-m mask] [-s source] [-p port] command ...\n", 48 prog); 49 exit(1); 50 } 51 52 int 53 main(int argc, char *argv []) 54 { 55 struct sockaddr_in6 *sin6; 56 struct sockaddr_in *sin; 57 struct addrinfo hints; 58 auditinfo_addr_t aia; 59 struct addrinfo *res; 60 struct passwd *pwd; 61 char *aflag, *mflag, *sflag, *r, *prog; 62 int ch, error; 63 64 aflag = mflag = sflag = NULL; 65 66 prog = argv[0]; 67 bzero(&aia, sizeof(aia)); 68 bzero(&hints, sizeof(hints)); 69 aia.ai_termid.at_type = AU_IPv4; 70 hints.ai_family = PF_UNSPEC; 71 while ((ch = getopt(argc, argv, "46a:m:p:s:")) != -1) 72 switch (ch) { 73 case '4': 74 hints.ai_family = PF_INET; 75 break; 76 case '6': 77 hints.ai_family = PF_INET6; 78 break; 79 case 'a': 80 aflag = optarg; 81 break; 82 case 'm': 83 mflag = optarg; 84 break; 85 case 'p': 86 aia.ai_termid.at_port = htons(atoi(optarg)); 87 break; 88 case 's': 89 sflag = optarg; 90 break; 91 default: 92 usage(prog); 93 /* NOT REACHED */ 94 } 95 argc -= optind; 96 argv += optind; 97 if (argc == 0) 98 usage(prog); 99 if (aflag) { 100 pwd = getpwnam(aflag); 101 if (pwd == NULL) { 102 aia.ai_auid = strtoul(aflag, &r, 10); 103 if (r != NULL) 104 errx(1, "%s: invalid user", aflag); 105 } else 106 aia.ai_auid = pwd->pw_uid; 107 } 108 if (mflag) { 109 if (getauditflagsbin(mflag, &aia.ai_mask) < 0) 110 err(1, "getauditflagsbin"); 111 } 112 if (sflag) { 113 error = getaddrinfo(sflag, NULL, &hints, &res); 114 if (error) 115 errx(1, "%s", gai_strerror(error)); 116 switch (res->ai_family) { 117 case PF_INET6: 118 sin6 = (struct sockaddr_in6 *)(void *)res->ai_addr; 119 bcopy(&sin6->sin6_addr.s6_addr, 120 &aia.ai_termid.at_addr[0], 121 sizeof(struct in6_addr)); 122 aia.ai_termid.at_type = AU_IPv6; 123 break; 124 case PF_INET: 125 sin = (struct sockaddr_in *)(void *)res->ai_addr; 126 bcopy(&sin->sin_addr.s_addr, 127 &aia.ai_termid.at_addr[0], 128 sizeof(struct in_addr)); 129 aia.ai_termid.at_type = AU_IPv4; 130 break; 131 } 132 } 133 if (setaudit_addr(&aia, sizeof(aia)) < 0) { 134 err(1, "setaudit_addr"); 135 } 136 (void)execvp(*argv, argv); 137 err(1, "%s", *argv); 138 } 139