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
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.
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]
23 * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright (c) 2016 by Delphix. All rights reserved.
28 #include <sys/types.h>
30 #include <sys/systeminfo.h>
31 #include <bsm/audit.h>
32 #include <bsm/libbsm.h>
33 #include <bsm/audit_uevents.h>
34 #include <bsm/audit_private.h>
43 #define AUDIT_GET_DIFFS_NO_CRONTAB 1
44 #define AUDIT_GET_DIFFS_CRONTAB 0
45 #define AUDIT_GET_DIFFS_ERR -1
46 #define AUDIT_GET_DIFFS_NO_DIFFS -2
48 static int audit_crontab_get_diffs(char *cf
, char *tmp_name
,
52 audit_crontab_modify(char *path
, char *tmp_path
, int sorf
)
57 if (cannot_audit(0)) {
64 if (getaudit_addr(&ai
, sizeof (ai
))) {
68 r
= audit_crontab_get_diffs(path
, tmp_path
, &diffs
);
70 if (r
== AUDIT_GET_DIFFS_NO_DIFFS
) {
73 if (diffs
!= NULL
&& r
!= AUDIT_GET_DIFFS_ERR
) {
78 if (r
== AUDIT_GET_DIFFS_NO_CRONTAB
) {
85 * create an ancilary file if audit characteristics exist
86 * else delete an ancilary if if one exists
89 anc_name
= audit_cron_make_anc_name(path
);
92 else if (audit_crontab_process_not_audited()) {
93 (void) unlink(anc_name
);
96 r
= audit_cron_setinfo(anc_name
, &ai
);
100 aug_save_auid(ai
.ai_auid
);
101 aug_save_euid(geteuid());
102 aug_save_egid(getegid());
103 aug_save_uid(getuid());
104 aug_save_gid(getgid());
105 aug_save_pid(getpid());
106 aug_save_asid(ai
.ai_asid
);
107 aug_save_tid_ex(ai
.ai_termid
.at_port
, ai
.ai_termid
.at_addr
,
108 ai
.ai_termid
.at_type
);
112 event
= (create
) ? AUE_crontab_create
: AUE_crontab_mod
;
113 aug_save_event(event
);
116 if (aug_audit() != 0)
123 audit_crontab_delete(char *path
, int sorf
)
127 if (cannot_audit(0)) {
131 anc_name
= audit_cron_make_anc_name(path
);
132 if (anc_name
!= NULL
) {
133 r
= unlink(anc_name
);
139 (void) aug_save_me();
142 aug_save_event(AUE_crontab_delete
);
144 if (aug_audit() != 0)
151 * gets differences between old and new crontab files.
153 * cf - name of crontab file
154 * tmp_name - name of new crontab file
155 * bufptr - pointer to an array of characters with
156 * either an error message or an output of "diff" command.
159 * AUDIT_GET_DIFFS_ERR - errors;
160 * file not exists (do not free *bufptr in this case)
161 * AUDIT_GET_DIFFS_NO_DIFFS - errors;
162 * file exists (do not free *bufptr in this case)
163 * AUDIT_GET_DIFFS_CRONTAB - OK, old crontab file exists.
164 * AUDIT_GET_DIFFS_NO_CRONTAB - OK. there is no crontab file.
167 audit_crontab_get_diffs(char *cf
, char *tmp_name
, char **bufptr
)
169 struct stat st
, st_tmp
;
171 int len
, r
= AUDIT_GET_DIFFS_CRONTAB
;
172 char *buf
= NULL
, err_buf
[128];
174 (void) memset(err_buf
, 0, 128);
176 if (seteuid(0) == -1) {
177 r
= AUDIT_GET_DIFFS_ERR
;
178 (void) snprintf(err_buf
, sizeof (err_buf
),
179 "crontab: seteuid: %s\n", strerror(errno
));
182 if (stat(cf
, &st
) == -1) {
183 if (errno
== ENOENT
) {
184 r
= AUDIT_GET_DIFFS_NO_CRONTAB
;
186 r
= AUDIT_GET_DIFFS_ERR
;
187 (void) snprintf(err_buf
, sizeof (err_buf
),
188 "crontab: %s: stat: %s\n",
189 cf
, strerror(errno
));
196 if (stat(tmp_name
, &st_tmp
) == -1) {
197 r
= AUDIT_GET_DIFFS_ERR
;
198 (void) snprintf(err_buf
, sizeof (err_buf
),
199 "crontab: %s: stat: %s\n",
200 tmp_name
, strerror(errno
));
204 if (st_tmp
.st_size
== 0 && len
== 0) {
205 /* there is no difference */
206 r
= AUDIT_GET_DIFFS_NO_DIFFS
;
212 /* return information on create or update crontab */
213 (void) seteuid(euid
);
215 case AUDIT_GET_DIFFS_ERR
:
219 case AUDIT_GET_DIFFS_NO_DIFFS
:
223 case AUDIT_GET_DIFFS_CRONTAB
:
225 if (strlen(buf
) != 0) {
228 r
= AUDIT_GET_DIFFS_NO_DIFFS
;
233 case AUDIT_GET_DIFFS_NO_CRONTAB
:
235 if (strlen(buf
) != 0) {
249 * audit_crontab_not_allowed determines if we have a case that should be audited
250 * but we can't. If auditing is enabled but the current process is not
251 * audited, then the ruid of the user doing the editing must be the owner
252 * id of the file to be edited.
254 * When audit_crontab_not_allowed is called, ruid is for the crontab file
255 * to be modified or created.
258 #define PWD_BUFFER_SIZE 512
261 audit_crontab_not_allowed(uid_t ruid
, char *user
) {
263 char buffer
[PWD_BUFFER_SIZE
];
264 int rc
= 0; /* 0 == allow */
265 struct passwd
*result
;
267 if (!cannot_audit(0)) { /* allow access if audit off */
268 getpwnam_r(user
, &pwd
, buffer
, PWD_BUFFER_SIZE
, &result
);
270 rc
= 1; /* deny access if invalid */
271 } else if (ruid
== pwd
.pw_uid
)
272 rc
= 0; /* editing their own crontab */
274 rc
= audit_crontab_process_not_audited();
280 audit_crontab_process_not_audited() {
281 struct auditpinfo_addr info
;
284 info
.ap_pid
= getpid();
285 if (auditon(A_GETPINFO_ADDR
, (caddr_t
)&info
, sizeof (info
)) != 0)
286 rc
= 0; /* audit failure: not enabled */
288 rc
= (info
.ap_auid
== AU_NOAUDITID
);