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 *
build_cmd(char ** cmd)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
selected(uid,user,event,sf)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
audit_rexd_setup()110 audit_rexd_setup()
111 {
112 dprintf(("audit_rexd_setup()\n"));
113
114 event = AUE_rexd;
115 }
116
117 /* ARGSUSED */
118 static void
audit_rexd_session_setup(char * name,char * mach,uid_t uid)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
audit_rexd_fail(msg,hostname,user,uid,gid,shell,cmd)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
audit_rexd_success(hostname,user,uid,gid,shell,cmd)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