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 <sys/param.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 #define UNKNOWN_CMD "???" 51 52 static au_event_t event; 53 static int audit_rexd_status = 0; 54 55 static char * 56 build_cmd(char **cmd) 57 { 58 int i, l; 59 char *r; 60 61 if (cmd == NULL) 62 return (NULL); 63 /* count the total length of command line */ 64 for (i = 0, l = 0; cmd[i] != NULL; i++) 65 l += strlen(cmd[i]) + 1; 66 67 if (l == 0) 68 return (NULL); 69 r = malloc(l); 70 if (r != NULL) { 71 for (i = 0; cmd[i] != NULL; i++) { 72 (void) strcat(r, cmd[i]); 73 if (cmd[i + 1] != NULL) 74 (void) strcat(r, " "); 75 } 76 } 77 return (r); 78 } 79 80 static int 81 selected(uid, user, event, sf) 82 uid_t uid; 83 char *user; 84 au_event_t event; 85 int sf; 86 { 87 int sorf; 88 struct au_mask mask; 89 90 mask.am_success = mask.am_failure = 0; 91 if (uid > MAXEPHUID) { 92 /* get non-attrib flags */ 93 (void) auditon(A_GETKMASK, (caddr_t)&mask, sizeof (mask)); 94 } else { 95 (void) au_user_mask(user, &mask); 96 } 97 98 if (sf == 0) { 99 sorf = AU_PRS_SUCCESS; 100 } else if (sf == -1) { 101 sorf = AU_PRS_FAILURE; 102 } else { 103 sorf = AU_PRS_BOTH; 104 } 105 106 return (au_preselect(event, &mask, sorf, AU_PRS_REREAD)); 107 } 108 109 void 110 audit_rexd_setup() 111 { 112 dprintf(("audit_rexd_setup()\n")); 113 114 event = AUE_rexd; 115 } 116 117 /* ARGSUSED */ 118 static void 119 audit_rexd_session_setup(char *name, char *mach, uid_t uid) 120 { 121 int rc; 122 au_mask_t mask; 123 struct auditinfo_addr info; 124 125 if (getaudit_addr(&info, sizeof (info)) < 0) { 126 perror("getaudit_addr"); 127 exit(1); 128 } 129 130 info.ai_auid = uid; 131 info.ai_asid = getpid(); 132 133 mask.am_success = 0; 134 mask.am_failure = 0; 135 136 (void) au_user_mask(name, &mask); 137 138 info.ai_mask.am_success = mask.am_success; 139 info.ai_mask.am_failure = mask.am_failure; 140 141 rc = setaudit_addr(&info, sizeof (info)); 142 if (rc < 0) { 143 perror("setaudit_addr"); 144 } 145 } 146 147 void 148 audit_rexd_fail(msg, hostname, user, uid, gid, shell, cmd) 149 char *msg; /* message containing failure information */ 150 char *hostname; /* hostname of machine requesting service */ 151 char *user; /* username of user requesting service */ 152 uid_t uid; /* user id of user requesting service */ 153 gid_t gid; /* group of user requesting service */ 154 char *shell; /* login shell of user requesting service */ 155 char **cmd; /* argv to be executed locally */ 156 { 157 int rd; /* audit record descriptor */ 158 char buf[256]; /* temporary buffer */ 159 char *tbuf; /* temporary buffer */ 160 int tlen; 161 const char *gtxt; /* gettext return value */ 162 pid_t pid; 163 char *cmdbuf; 164 char *audit_cmd[2] = {NULL, NULL}; 165 int dont_free = 0; 166 struct auditinfo_addr info; 167 168 dprintf(("audit_rexd_fail()\n")); 169 170 /* 171 * check if audit_rexd_fail() or audit_rexd_success() 172 * have been called already. 173 */ 174 if (audit_rexd_status == 1) { 175 return; 176 } 177 178 if (cannot_audit(0)) { 179 return; 180 } 181 182 /* 183 * set status to prevent multiple calls 184 * to audit_rexd_fail() and audit_rexd_success() 185 */ 186 audit_rexd_status = 1; 187 188 /* determine if we're preselected */ 189 if (!selected(uid, user, event, -1)) 190 return; 191 192 pid = getpid(); 193 194 if (getaudit_addr(&info, sizeof (info)) < 0) { 195 perror("getaudit_addr"); 196 exit(1); 197 } 198 199 rd = au_open(); 200 201 /* add subject token */ 202 (void) au_write(rd, 203 au_to_subject_ex(uid, uid, gid, uid, gid, pid, pid, 204 &info.ai_termid)); 205 if (is_system_labeled()) 206 (void) au_write(rd, au_to_mylabel()); 207 208 /* add reason for failure */ 209 (void) au_write(rd, au_to_text(msg)); 210 211 /* add hostname of machine requesting service */ 212 (void) snprintf(buf, sizeof (buf), dgettext(bsm_dom, 213 "Remote execution requested by: %s"), hostname); 214 (void) au_write(rd, au_to_text(buf)); 215 216 /* add username of user requesting service */ 217 if (user == NULL) 218 user = "???"; 219 (void) snprintf(buf, sizeof (buf), dgettext(bsm_dom, 220 "Username: %s"), user); 221 (void) au_write(rd, au_to_text(buf)); 222 223 (void) snprintf(buf, sizeof (buf), dgettext(bsm_dom, 224 "User id: %d"), uid); 225 (void) au_write(rd, au_to_text(buf)); 226 227 if (cmd == NULL) { 228 audit_cmd[0] = shell; 229 cmd = audit_cmd; 230 } 231 232 cmdbuf = build_cmd(cmd); 233 if (cmdbuf == NULL) { 234 cmdbuf = UNKNOWN_CMD; 235 dont_free = 1; 236 } 237 238 gtxt = dgettext(bsm_dom, "Command line: %s"); 239 /* over estimate of size of buffer needed (%s is replaced) */ 240 tlen = strlen(cmdbuf) + strlen(gtxt) + 1; 241 242 if ((tbuf = malloc(tlen)) == NULL) { 243 (void) au_close(rd, 0, 0); 244 return; 245 } 246 (void) snprintf(tbuf, tlen, gtxt, cmdbuf); 247 (void) au_write(rd, au_to_text(tbuf)); 248 (void) free(tbuf); 249 if (!dont_free) 250 (void) free(cmdbuf); 251 252 /* add return token */ 253 #ifdef _LP64 254 (void) au_write(rd, au_to_return64(-1, (int64_t)0)); 255 #else 256 (void) au_write(rd, au_to_return32(-1, (int32_t)0)); 257 #endif 258 259 /* write audit record */ 260 if (au_close(rd, 1, event) < 0) { 261 (void) au_close(rd, 0, 0); 262 return; 263 } 264 } 265 266 void 267 audit_rexd_success(hostname, user, uid, gid, shell, cmd) 268 char *hostname; /* hostname of machine requesting service */ 269 char *user; /* username of user requesting service, may be NULL */ 270 uid_t uid; /* user id of user requesting service */ 271 gid_t gid; /* group of user requesting service */ 272 char *shell; /* login shell of user requesting service */ 273 char **cmd; /* argv to be executed locally, may be NULL */ 274 { 275 int rd; /* audit record descriptor */ 276 char buf[256]; /* temporary buffer */ 277 char *tbuf; /* temporary buffer */ 278 int tlen; 279 const char *gtxt; 280 pid_t pid; 281 char *cmdbuf; 282 char *audit_cmd[2] = {NULL, NULL}; 283 int dont_free = 0; 284 struct auditinfo_addr info; 285 char *empty = ""; 286 287 dprintf(("audit_rexd_success()\n")); 288 289 /* 290 * check if audit_rexd_fail() or audit_rexd_success() 291 * have been called already. 292 */ 293 if (audit_rexd_status == 1) { 294 return; 295 } 296 297 if (cannot_audit(0)) { 298 return; 299 } 300 301 /* a little bullet proofing... */ 302 303 if (hostname == NULL) 304 hostname = empty; 305 if (shell == NULL) 306 shell = empty; 307 308 /* 309 * set status to prevent multiple calls 310 * to audit_rexd_fail() and audit_rexd_success() 311 */ 312 audit_rexd_status = 1; 313 314 /* determine if we're preselected */ 315 if (!selected(uid, user, event, 0)) 316 goto rexd_audit_session; 317 318 pid = getpid(); 319 320 if (getaudit_addr(&info, sizeof (info)) < 0) { 321 perror("getaudit_addr"); 322 exit(1); 323 } 324 325 rd = au_open(); 326 327 /* add subject token */ 328 (void) au_write(rd, 329 au_to_subject_ex(uid, uid, gid, uid, gid, pid, pid, 330 &info.ai_termid)); 331 if (is_system_labeled()) 332 (void) au_write(rd, au_to_mylabel()); 333 334 /* add hostname of machine requesting service */ 335 336 (void) snprintf(buf, sizeof (buf), dgettext(bsm_dom, 337 "Remote execution requested by: %s"), hostname); 338 (void) au_write(rd, au_to_text(buf)); 339 340 /* add username at machine requesting service */ 341 (void) snprintf(buf, sizeof (buf), dgettext(bsm_dom, 342 "Username: %s"), user); 343 (void) au_write(rd, au_to_text(buf)); 344 345 if (cmd == NULL) { 346 audit_cmd[0] = shell; 347 cmd = audit_cmd; 348 } 349 350 cmdbuf = build_cmd(cmd); 351 if (cmdbuf == NULL) { 352 cmdbuf = UNKNOWN_CMD; 353 dont_free = 1; 354 } 355 356 gtxt = dgettext(bsm_dom, "Command line: %s"); 357 tlen = strlen(cmdbuf) + strlen(gtxt) + 1; 358 359 if ((tbuf = malloc(tlen)) == NULL) { 360 (void) au_close(rd, 0, 0); 361 goto rexd_audit_session; 362 } 363 364 (void) snprintf(tbuf, tlen, gtxt, cmdbuf); 365 (void) au_write(rd, au_to_text(tbuf)); 366 (void) free(tbuf); 367 if (!dont_free) 368 (void) free(cmdbuf); 369 370 /* add return token */ 371 #ifdef _LP64 372 (void) au_write(rd, au_to_return64(0, (int64_t)0)); 373 #else 374 (void) au_write(rd, au_to_return32(0, (int32_t)0)); 375 #endif 376 377 /* write audit record */ 378 if (au_close(rd, 1, event) < 0) { 379 (void) au_close(rd, 0, 0); 380 } 381 382 rexd_audit_session: 383 audit_rexd_session_setup(user, hostname, uid); 384 } 385