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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <sys/types.h> 29 #include <stdio.h> 30 #include <unistd.h> 31 #include <sys/fcntl.h> 32 #include <bsm/audit.h> 33 #include <bsm/audit_record.h> 34 #include <bsm/audit_uevents.h> 35 #include <bsm/libbsm.h> 36 #include <bsm/audit_private.h> 37 #include <stdlib.h> 38 #include <string.h> 39 #include <syslog.h> 40 #include <pwd.h> 41 #include <netinet/in.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 201 /* add reason for failure */ 202 (void) au_write(rd, au_to_text(msg)); 203 204 /* add hostname of machine requesting service */ 205 (void) snprintf(buf, sizeof (buf), dgettext(bsm_dom, 206 "Remote execution requested by: %s"), hostname); 207 (void) au_write(rd, au_to_text(buf)); 208 209 /* add username of user requesting service */ 210 (void) snprintf(buf, sizeof (buf), dgettext(bsm_dom, 211 "Username: %s"), user); 212 (void) au_write(rd, au_to_text(buf)); 213 214 /* add command line to be executed locally */ 215 gtxt = dgettext(bsm_dom, "Command line: %s"); 216 tlen = strlen(gtxt) + strlen(cmdbuf) + 1; 217 if ((tbuf = malloc(tlen)) == NULL) { 218 (void) au_close(rd, 0, 0); 219 return; 220 } 221 (void) snprintf(tbuf, tlen, gtxt, cmdbuf); 222 (void) au_write(rd, au_to_text(tbuf)); 223 (void) free(tbuf); 224 225 /* add return token */ 226 #ifdef _LP64 227 (void) au_write(rd, au_to_return64(-1, (int64_t)0)); 228 #else 229 (void) au_write(rd, au_to_return32(-1, (int32_t)0)); 230 #endif 231 232 /* write audit record */ 233 if (au_close(rd, 1, event) < 0) { 234 (void) au_close(rd, 0, 0); 235 return; 236 } 237 } 238 239 void 240 audit_rexecd_success(hostname, user, cmdbuf) 241 char *hostname; /* hostname of machine requesting service */ 242 char *user; /* username of user requesting service */ 243 char *cmdbuf; /* command line to be executed locally */ 244 { 245 int rd; /* audit record descriptor */ 246 char buf[256]; /* temporary buffer */ 247 char *tbuf; /* temporary buffer */ 248 int tlen; 249 const char *gtxt; 250 uid_t uid; 251 gid_t gid; 252 pid_t pid; 253 au_tid_addr_t tid; 254 struct passwd *pwd; 255 uint32_t addr[4], type; 256 int rc; 257 258 dprintf(("audit_rexecd_success()\n")); 259 260 /* 261 * check if audit_rexecd_fail() or audit_rexecd_success() 262 * have been called already. 263 */ 264 if (audit_rexecd_status == 1) { 265 return; 266 } 267 268 if (cannot_audit(0)) { 269 return; 270 } 271 272 /* 273 * set status to prevent multiple calls 274 * to audit_rexecd_fail() and audit_rexecd_success() 275 */ 276 audit_rexecd_status = 1; 277 278 pwd = getpwnam(user); 279 if (pwd == NULL) { 280 uid = -1; 281 gid = -1; 282 } else { 283 uid = pwd->pw_uid; 284 gid = pwd->pw_gid; 285 } 286 287 /* determine if we're preselected */ 288 if (!selected(uid, user, event, 0)) 289 goto rexecd_audit_session; 290 291 pid = getpid(); 292 rc = aug_get_machine(hostname, addr, &type); 293 if (rc < 0) { 294 perror("get address"); 295 } 296 297 tid.at_port = aug_get_port(); 298 tid.at_addr[0] = addr[0]; 299 tid.at_addr[1] = addr[1]; 300 tid.at_addr[2] = addr[2]; 301 tid.at_addr[3] = addr[3]; 302 tid.at_type = type; 303 304 rd = au_open(); 305 306 /* add subject token */ 307 (void) au_write(rd, 308 au_to_subject_ex(uid, uid, gid, uid, gid, pid, pid, &tid)); 309 310 /* add hostname of machine requesting service */ 311 (void) snprintf(buf, sizeof (buf), dgettext(bsm_dom, 312 "Remote execution requested by: %s"), hostname); 313 (void) au_write(rd, au_to_text(buf)); 314 315 /* add username at machine requesting service */ 316 (void) snprintf(buf, sizeof (buf), dgettext(bsm_dom, 317 "Username: %s"), user); 318 (void) au_write(rd, au_to_text(buf)); 319 320 /* add command line to be executed locally */ 321 gtxt = dgettext(bsm_dom, "Command line: %s"); 322 tlen = strlen(gtxt) + strlen(cmdbuf) + 1; 323 if ((tbuf = malloc(tlen)) == NULL) { 324 (void) au_close(rd, 0, 0); 325 } else { 326 (void) snprintf(tbuf, tlen, gtxt, cmdbuf); 327 (void) au_write(rd, au_to_text(tbuf)); 328 (void) free(tbuf); 329 330 /* add return token */ 331 #ifdef _LP64 332 (void) au_write(rd, au_to_return64(0, (int64_t)0)); 333 #else 334 (void) au_write(rd, au_to_return32(0, (int32_t)0)); 335 #endif 336 337 /* write audit record */ 338 if (au_close(rd, 1, event) < 0) { 339 (void) au_close(rd, 0, 0); 340 } 341 } 342 343 rexecd_audit_session: 344 audit_rexecd_session_setup(user, hostname, uid); 345 } 346