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