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 #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 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 332 /* add hostname of machine requesting service */ 333 334 (void) snprintf(buf, sizeof (buf), dgettext(bsm_dom, 335 "Remote execution requested by: %s"), hostname); 336 (void) au_write(rd, au_to_text(buf)); 337 338 /* add username at machine requesting service */ 339 (void) snprintf(buf, sizeof (buf), dgettext(bsm_dom, 340 "Username: %s"), user); 341 (void) au_write(rd, au_to_text(buf)); 342 343 if (cmd == NULL) { 344 audit_cmd[0] = shell; 345 cmd = audit_cmd; 346 } 347 348 cmdbuf = build_cmd(cmd); 349 if (cmdbuf == NULL) { 350 cmdbuf = UNKNOWN_CMD; 351 dont_free = 1; 352 } 353 354 gtxt = dgettext(bsm_dom, "Command line: %s"); 355 tlen = strlen(cmdbuf) + strlen(gtxt) + 1; 356 357 if ((tbuf = malloc(tlen)) == NULL) { 358 (void) au_close(rd, 0, 0); 359 goto rexd_audit_session; 360 } 361 362 (void) snprintf(tbuf, tlen, gtxt, cmdbuf); 363 (void) au_write(rd, au_to_text(tbuf)); 364 (void) free(tbuf); 365 if (!dont_free) 366 (void) free(cmdbuf); 367 368 /* add return token */ 369 #ifdef _LP64 370 (void) au_write(rd, au_to_return64(0, (int64_t)0)); 371 #else 372 (void) au_write(rd, au_to_return32(0, (int32_t)0)); 373 #endif 374 375 /* write audit record */ 376 if (au_close(rd, 1, event) < 0) { 377 (void) au_close(rd, 0, 0); 378 } 379 380 rexd_audit_session: 381 audit_rexd_session_setup(user, hostname, uid); 382 } 383