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