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 49 static au_event_t event; 50 static int audit_rexecd_status = 0; 51 52 static int 53 selected(uid, user, event, sf) 54 uid_t uid; 55 char *user; 56 au_event_t event; 57 int 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 81 void 82 audit_rexecd_setup() 83 { 84 dprintf(("audit_rexecd_setup()\n")); 85 86 event = AUE_rexecd; 87 } 88 89 90 static void 91 audit_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 126 void 127 audit_rexecd_fail(msg, hostname, user, cmdbuf) 128 char *msg; /* message containing failure information */ 129 char *hostname; /* hostname of machine requesting service */ 130 char *user; /* username of user requesting service */ 131 char *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 238 void 239 audit_rexecd_success(hostname, user, cmdbuf) 240 char *hostname; /* hostname of machine requesting service */ 241 char *user; /* username of user requesting service */ 242 char *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 344 rexecd_audit_session: 345 audit_rexecd_session_setup(user, hostname, uid); 346 } 347