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 <stdbool.h> 39 #include <stdio.h> 40 #include <stdlib.h> 41 #include <string.h> 42 #include <unistd.h> 43 44 static void 45 usage(char *prog) 46 { 47 (void)fprintf(stderr, 48 "usage: %s [-46U] [-a auid] [-m mask] [-p port] [-s source] command ...\n", 49 prog); 50 exit(1); 51 } 52 53 int 54 main(int argc, char *argv []) 55 { 56 struct sockaddr_in6 *sin6; 57 struct sockaddr_in *sin; 58 struct addrinfo hints; 59 auditinfo_addr_t aia; 60 char *aflag, *mflag, *sflag, *prog; 61 dev_t term_port; 62 uint32_t term_type; 63 int ch, error; 64 bool Uflag; 65 66 aflag = mflag = sflag = NULL; 67 Uflag = false; 68 69 prog = argv[0]; 70 bzero(&aia, sizeof(aia)); 71 bzero(&hints, sizeof(hints)); 72 term_type = AU_IPv4; 73 hints.ai_family = PF_UNSPEC; 74 while ((ch = getopt(argc, argv, "46a:m:p:s:U")) != -1) 75 switch (ch) { 76 case '4': 77 hints.ai_family = PF_INET; 78 break; 79 case '6': 80 hints.ai_family = PF_INET6; 81 break; 82 case 'a': 83 aflag = optarg; 84 break; 85 case 'm': 86 mflag = optarg; 87 break; 88 case 'p': 89 term_port = htons(atoi(optarg)); 90 break; 91 case 's': 92 sflag = optarg; 93 break; 94 case 'U': 95 Uflag = true; 96 break; 97 default: 98 usage(prog); 99 /* NOT REACHED */ 100 } 101 argc -= optind; 102 argv += optind; 103 if (argc == 0) 104 usage(prog); 105 106 if (Uflag) { 107 if (getaudit_addr(&aia, sizeof(aia)) < 0) 108 err(1, "getaudit_addr"); 109 } 110 if (aflag) { 111 struct passwd *pwd; 112 113 pwd = getpwnam(aflag); 114 if (pwd == NULL) { 115 char *r; 116 117 aia.ai_auid = strtoul(aflag, &r, 10); 118 if (*r != '\0') 119 errx(1, "%s: invalid user", aflag); 120 } else 121 aia.ai_auid = pwd->pw_uid; 122 } 123 if (mflag) { 124 if (getauditflagsbin(mflag, &aia.ai_mask) < 0) 125 err(1, "getauditflagsbin"); 126 } 127 if (sflag) { 128 struct addrinfo *res; 129 130 error = getaddrinfo(sflag, NULL, &hints, &res); 131 if (error) 132 errx(1, "%s", gai_strerror(error)); 133 switch (res->ai_family) { 134 case PF_INET6: 135 sin6 = (struct sockaddr_in6 *)(void *)res->ai_addr; 136 bcopy(&sin6->sin6_addr.s6_addr, 137 &aia.ai_termid.at_addr[0], 138 sizeof(struct in6_addr)); 139 term_type = AU_IPv6; 140 break; 141 case PF_INET: 142 sin = (struct sockaddr_in *)(void *)res->ai_addr; 143 bcopy(&sin->sin_addr.s_addr, 144 &aia.ai_termid.at_addr[0], 145 sizeof(struct in_addr)); 146 term_type = AU_IPv4; 147 break; 148 } 149 } 150 if (!Uflag || sflag) { 151 aia.ai_termid.at_port = term_port; 152 aia.ai_termid.at_type = term_type; 153 } 154 if (setaudit_addr(&aia, sizeof(aia)) < 0) 155 err(1, "setaudit_addr"); 156 (void)execvp(*argv, argv); 157 err(1, "%s", *argv); 158 } 159