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