1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21/* 22 * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25#include <sys/types.h> 26#include <stdio.h> 27#include <unistd.h> 28#include <sys/fcntl.h> 29#include <bsm/audit.h> 30#include <bsm/audit_record.h> 31#include <bsm/audit_uevents.h> 32#include <bsm/libbsm.h> 33#include <bsm/audit_private.h> 34#include <stdlib.h> 35#include <string.h> 36#include <syslog.h> 37#include <pwd.h> 38#include <netinet/in.h> 39#include <tsol/label.h> 40#include <locale.h> 41#include "generic.h" 42 43#ifdef C2_DEBUG 44#define dprintf(x) { (void) printf x; } 45#else 46#define dprintf(x) 47#endif 48 49static au_event_t event; 50static int audit_rexecd_status = 0; 51 52static int 53selected(uid, user, event, sf) 54uid_t uid; 55char *user; 56au_event_t event; 57int sf; 58{ 59 int sorf; 60 struct au_mask mask; 61 62 mask.am_success = mask.am_failure = 0; 63 if (uid > MAXEPHUID) { 64 /* get non-attrib flags */ 65 (void) auditon(A_GETKMASK, (caddr_t)&mask, sizeof (mask)); 66 } else { 67 (void) au_user_mask(user, &mask); 68 } 69 70 if (sf == 0) { 71 sorf = AU_PRS_SUCCESS; 72 } else if (sf == -1) { 73 sorf = AU_PRS_FAILURE; 74 } else { 75 sorf = AU_PRS_BOTH; 76 } 77 78 return (au_preselect(event, &mask, sorf, AU_PRS_REREAD)); 79} 80 81void 82audit_rexecd_setup() 83{ 84 dprintf(("audit_rexecd_setup()\n")); 85 86 event = AUE_rexecd; 87} 88 89 90static void 91audit_rexecd_session_setup(char *name, char *mach, uid_t uid) 92{ 93 int rc; 94 au_mask_t mask; 95 struct auditinfo_addr info; 96 uint32_t addr[4], type; 97 98 info.ai_auid = uid; 99 info.ai_asid = getpid(); 100 101 mask.am_success = 0; 102 mask.am_failure = 0; 103 104 (void) au_user_mask(name, &mask); 105 106 info.ai_mask.am_success = mask.am_success; 107 info.ai_mask.am_failure = mask.am_failure; 108 109 rc = aug_get_machine(mach, addr, &type); 110 if (rc < 0) { 111 perror("get address"); 112 } 113 info.ai_termid.at_port = aug_get_port(); 114 info.ai_termid.at_type = type; 115 info.ai_termid.at_addr[0] = addr[0]; 116 info.ai_termid.at_addr[1] = addr[1]; 117 info.ai_termid.at_addr[2] = addr[2]; 118 info.ai_termid.at_addr[3] = addr[3]; 119 120 rc = setaudit_addr(&info, sizeof (info)); 121 if (rc < 0) { 122 perror("setaudit"); 123 } 124} 125 126void 127audit_rexecd_fail(msg, hostname, user, cmdbuf) 128char *msg; /* message containing failure information */ 129char *hostname; /* hostname of machine requesting service */ 130char *user; /* username of user requesting service */ 131char *cmdbuf; /* command line to be executed locally */ 132{ 133 int rd; /* audit record descriptor */ 134 char buf[256]; /* temporary buffer */ 135 char *tbuf; /* temporary buffer */ 136 int tlen; 137 const char *gtxt; 138 uid_t uid; 139 gid_t gid; 140 pid_t pid; 141 au_tid_addr_t tid; 142 struct passwd *pwd; 143 uint32_t addr[4], type; 144 int rc; 145 146 dprintf(("audit_rexecd_fail()\n")); 147 148 /* 149 * check if audit_rexecd_fail() or audit_rexecd_success() 150 * have been called already. 151 */ 152 if (audit_rexecd_status == 1) { 153 return; 154 } 155 156 if (cannot_audit(0)) { 157 return; 158 } 159 160 /* 161 * set status to prevent multiple calls 162 * to audit_rexecd_fail() and audit_rexecd_success() 163 */ 164 audit_rexecd_status = 1; 165 166 pwd = getpwnam(user); 167 if (pwd == NULL) { 168 uid = (uid_t)-1; 169 gid = (gid_t)-1; 170 } else { 171 uid = pwd->pw_uid; 172 gid = pwd->pw_gid; 173 } 174 175 /* determine if we're preselected */ 176 if (!selected(uid, user, event, -1)) 177 return; 178 179 pid = getpid(); 180 rc = aug_get_machine(hostname, addr, &type); 181 if (rc < 0) { 182 perror("get address"); 183 } 184 185 tid.at_port = aug_get_port(); 186 tid.at_addr[0] = addr[0]; 187 tid.at_addr[1] = addr[1]; 188 tid.at_addr[2] = addr[2]; 189 tid.at_addr[3] = addr[3]; 190 tid.at_type = type; 191 192 rd = au_open(); 193 194 /* add subject token */ 195 (void) au_write(rd, 196 au_to_subject_ex(uid, uid, gid, uid, gid, pid, pid, &tid)); 197 if (is_system_labeled()) 198 (void) au_write(rd, au_to_mylabel()); 199 200 /* add reason for failure */ 201 (void) au_write(rd, au_to_text(msg)); 202 203 /* add hostname of machine requesting service */ 204 (void) snprintf(buf, sizeof (buf), dgettext(bsm_dom, 205 "Remote execution requested by: %s"), hostname); 206 (void) au_write(rd, au_to_text(buf)); 207 208 /* add username of user requesting service */ 209 (void) snprintf(buf, sizeof (buf), dgettext(bsm_dom, 210 "Username: %s"), user); 211 (void) au_write(rd, au_to_text(buf)); 212 213 /* add command line to be executed locally */ 214 gtxt = dgettext(bsm_dom, "Command line: %s"); 215 tlen = strlen(gtxt) + strlen(cmdbuf) + 1; 216 if ((tbuf = malloc(tlen)) == NULL) { 217 (void) au_close(rd, 0, 0); 218 return; 219 } 220 (void) snprintf(tbuf, tlen, gtxt, cmdbuf); 221 (void) au_write(rd, au_to_text(tbuf)); 222 (void) free(tbuf); 223 224 /* add return token */ 225#ifdef _LP64 226 (void) au_write(rd, au_to_return64(-1, (int64_t)0)); 227#else 228 (void) au_write(rd, au_to_return32(-1, (int32_t)0)); 229#endif 230 231 /* write audit record */ 232 if (au_close(rd, 1, event) < 0) { 233 (void) au_close(rd, 0, 0); 234 return; 235 } 236} 237 238void 239audit_rexecd_success(hostname, user, cmdbuf) 240char *hostname; /* hostname of machine requesting service */ 241char *user; /* username of user requesting service */ 242char *cmdbuf; /* command line to be executed locally */ 243{ 244 int rd; /* audit record descriptor */ 245 char buf[256]; /* temporary buffer */ 246 char *tbuf; /* temporary buffer */ 247 int tlen; 248 const char *gtxt; 249 uid_t uid; 250 gid_t gid; 251 pid_t pid; 252 au_tid_addr_t tid; 253 struct passwd *pwd; 254 uint32_t addr[4], type; 255 int rc; 256 257 dprintf(("audit_rexecd_success()\n")); 258 259 /* 260 * check if audit_rexecd_fail() or audit_rexecd_success() 261 * have been called already. 262 */ 263 if (audit_rexecd_status == 1) { 264 return; 265 } 266 267 if (cannot_audit(0)) { 268 return; 269 } 270 271 /* 272 * set status to prevent multiple calls 273 * to audit_rexecd_fail() and audit_rexecd_success() 274 */ 275 audit_rexecd_status = 1; 276 277 pwd = getpwnam(user); 278 if (pwd == NULL) { 279 uid = (uid_t)-1; 280 gid = (gid_t)-1; 281 } else { 282 uid = pwd->pw_uid; 283 gid = pwd->pw_gid; 284 } 285 286 /* determine if we're preselected */ 287 if (!selected(uid, user, event, 0)) 288 goto rexecd_audit_session; 289 290 pid = getpid(); 291 rc = aug_get_machine(hostname, addr, &type); 292 if (rc < 0) { 293 perror("get address"); 294 } 295 296 tid.at_port = aug_get_port(); 297 tid.at_addr[0] = addr[0]; 298 tid.at_addr[1] = addr[1]; 299 tid.at_addr[2] = addr[2]; 300 tid.at_addr[3] = addr[3]; 301 tid.at_type = type; 302 303 rd = au_open(); 304 305 /* add subject token */ 306 (void) au_write(rd, 307 au_to_subject_ex(uid, uid, gid, uid, gid, pid, pid, &tid)); 308 if (is_system_labeled()) 309 (void) au_write(rd, au_to_mylabel()); 310 311 /* add hostname of machine requesting service */ 312 (void) snprintf(buf, sizeof (buf), dgettext(bsm_dom, 313 "Remote execution requested by: %s"), hostname); 314 (void) au_write(rd, au_to_text(buf)); 315 316 /* add username at machine requesting service */ 317 (void) snprintf(buf, sizeof (buf), dgettext(bsm_dom, 318 "Username: %s"), user); 319 (void) au_write(rd, au_to_text(buf)); 320 321 /* add command line to be executed locally */ 322 gtxt = dgettext(bsm_dom, "Command line: %s"); 323 tlen = strlen(gtxt) + strlen(cmdbuf) + 1; 324 if ((tbuf = malloc(tlen)) == NULL) { 325 (void) au_close(rd, 0, 0); 326 } else { 327 (void) snprintf(tbuf, tlen, gtxt, cmdbuf); 328 (void) au_write(rd, au_to_text(tbuf)); 329 (void) free(tbuf); 330 331 /* add return token */ 332#ifdef _LP64 333 (void) au_write(rd, au_to_return64(0, (int64_t)0)); 334#else 335 (void) au_write(rd, au_to_return32(0, (int32_t)0)); 336#endif 337 338 /* write audit record */ 339 if (au_close(rd, 1, event) < 0) { 340 (void) au_close(rd, 0, 0); 341 } 342 } 343 344rexecd_audit_session: 345 audit_rexecd_session_setup(user, hostname, uid); 346} 347