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