~ubuntu-branches/ubuntu/quantal/sudo/quantal

« back to all changes in this revision

Viewing changes to plugins/sudoers/bsm_audit.c

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2011-11-20 12:07:45 UTC
  • mfrom: (1.3.17 sid)
  • Revision ID: package-import@ubuntu.com-20111120120745-o3qpklobmygytndc
Tags: 1.8.3p1-1ubuntu1
* Merge from debian/testing, remaining changes:
  - debian/patches/keep_home_by_default.patch:
    + Set HOME in initial_keepenv_table. (rebased for 1.8.3p1)
  - debian/patches/enable_badpass.patch: turn on "mail_badpass" by default:
    + attempting sudo without knowing a login password is as bad as not
      being listed in the sudoers file, especially if getting the password
      wrong means doing the access-check-email-notification never happens
      (rebased for 1.8.3p1)
  - debian/rules:
    + compile with --without-lecture --with-tty-tickets (Ubuntu specific)
    + install man/man8/sudo_root.8 (Ubuntu specific)
    + install apport hooks
    + The ubuntu-sudo-as-admin-successful.patch was taken upstream by
      Debian however it requires a --enable-admin-flag configure flag to
      actually enable it.
  - debian/sudoers: 
    + grant admin group sudo access
  - debian/sudo-ldap.dirs, debian/sudo.dirs: 
    + add usr/share/apport/package-hooks
  - debian/sudo.preinst:
    + avoid conffile prompt by checking for known default /etc/sudoers
      and if found installing the correct default /etc/sudoers file

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2009-2011 Todd C. Miller <Todd.Miller@courtesan.com>
 
3
 * Copyright (c) 2009 Christian S.J. Peron
 
4
 *
 
5
 * Permission to use, copy, modify, and distribute this software for any
 
6
 * purpose with or without fee is hereby granted, provided that the above
 
7
 * copyright notice and this permission notice appear in all copies.
 
8
 *
 
9
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 
10
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 
11
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 
12
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 
13
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 
14
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 
15
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
16
 */
 
17
 
 
18
#include <config.h>
 
19
 
 
20
#include <sys/types.h>
 
21
 
 
22
#include <bsm/audit.h>
 
23
#include <bsm/libbsm.h>
 
24
#include <bsm/audit_uevents.h>
 
25
 
 
26
#include <stdio.h>
 
27
#include <string.h>
 
28
#include <stdarg.h>
 
29
#include <pwd.h>
 
30
#include <errno.h>
 
31
#include <unistd.h>
 
32
 
 
33
#include "bsm_audit.h"
 
34
 
 
35
/*
 
36
 * Solaris auditon() returns EINVAL if BSM audit not configured.
 
37
 * OpenBSM returns ENOSYS for unimplemented options.
 
38
 */
 
39
#ifdef __sun
 
40
# define AUDIT_NOT_CONFIGURED   EINVAL
 
41
#else
 
42
# define AUDIT_NOT_CONFIGURED   ENOSYS
 
43
#endif
 
44
 
 
45
void log_error(int flags, const char *fmt, ...) __attribute__((__noreturn__));
 
46
 
 
47
static int
 
48
audit_sudo_selected(int sf)
 
49
{
 
50
        auditinfo_addr_t ainfo_addr;
 
51
        struct au_mask *mask;
 
52
        auditinfo_t ainfo;
 
53
        int rc, sorf;
 
54
 
 
55
        if (getaudit_addr(&ainfo_addr, sizeof(ainfo_addr)) < 0) {
 
56
                if (errno == ENOSYS) {
 
57
                        if (getaudit(&ainfo) < 0)
 
58
                                log_error(0, _("getaudit: failed"));
 
59
                        mask = &ainfo.ai_mask;
 
60
                } else
 
61
                        log_error(0, _("getaudit: failed"));
 
62
        } else
 
63
                mask = &ainfo_addr.ai_mask;
 
64
        sorf = (sf == 0) ? AU_PRS_SUCCESS : AU_PRS_FAILURE;
 
65
        rc = au_preselect(AUE_sudo, mask, sorf, AU_PRS_REREAD);
 
66
        return rc;
 
67
}
 
68
 
 
69
void
 
70
bsm_audit_success(char **exec_args)
 
71
{
 
72
        auditinfo_addr_t ainfo_addr;
 
73
        auditinfo_t ainfo;
 
74
        token_t *tok;
 
75
        au_id_t auid;
 
76
        long au_cond;
 
77
        int aufd;
 
78
        pid_t pid;
 
79
 
 
80
        pid = getpid();
 
81
        /*
 
82
         * If we are not auditing, don't cut an audit record; just return.
 
83
         */
 
84
        if (auditon(A_GETCOND, (caddr_t)&au_cond, sizeof(long)) < 0) {
 
85
                if (errno == AUDIT_NOT_CONFIGURED)
 
86
                        return;
 
87
                log_error(0, _("Could not determine audit condition"));
 
88
        }
 
89
        if (au_cond == AUC_NOAUDIT)
 
90
                return;
 
91
        /*
 
92
         * Check to see if the preselection masks are interested in seeing
 
93
         * this event.
 
94
         */
 
95
        if (!audit_sudo_selected(0))
 
96
                return;
 
97
        if (getauid(&auid) < 0)
 
98
                log_error(0, _("getauid failed"));
 
99
        if ((aufd = au_open()) == -1)
 
100
                log_error(0, _("au_open: failed"));
 
101
        if (getaudit_addr(&ainfo_addr, sizeof(ainfo_addr)) == 0) {
 
102
                tok = au_to_subject_ex(auid, geteuid(), getegid(), getuid(),
 
103
                    getuid(), pid, pid, &ainfo_addr.ai_termid);
 
104
        } else if (errno == ENOSYS) {
 
105
                /*
 
106
                 * NB: We should probably watch out for ERANGE here.
 
107
                 */
 
108
                if (getaudit(&ainfo) < 0)
 
109
                        log_error(0, _("getaudit: failed"));
 
110
                tok = au_to_subject(auid, geteuid(), getegid(), getuid(),
 
111
                    getuid(), pid, pid, &ainfo.ai_termid);
 
112
        } else
 
113
                log_error(0, _("getaudit: failed"));
 
114
        if (tok == NULL)
 
115
                log_error(0, _("au_to_subject: failed"));
 
116
        au_write(aufd, tok);
 
117
        tok = au_to_exec_args(exec_args);
 
118
        if (tok == NULL)
 
119
                log_error(0, _("au_to_exec_args: failed"));
 
120
        au_write(aufd, tok);
 
121
        tok = au_to_return32(0, 0);
 
122
        if (tok == NULL)
 
123
                log_error(0, _("au_to_return32: failed"));
 
124
        au_write(aufd, tok);
 
125
        if (au_close(aufd, 1, AUE_sudo) == -1)
 
126
                log_error(0, _("unable to commit audit record"));
 
127
}
 
128
 
 
129
void
 
130
bsm_audit_failure(char **exec_args, char const *const fmt, va_list ap)
 
131
{
 
132
        auditinfo_addr_t ainfo_addr;
 
133
        auditinfo_t ainfo;
 
134
        char text[256];
 
135
        token_t *tok;
 
136
        long au_cond;
 
137
        au_id_t auid;
 
138
        pid_t pid;
 
139
        int aufd;
 
140
 
 
141
        pid = getpid();
 
142
        /*
 
143
         * If we are not auditing, don't cut an audit record; just return.
 
144
         */
 
145
        if (auditon(A_GETCOND, &au_cond, sizeof(long)) < 0) {
 
146
                if (errno == AUDIT_NOT_CONFIGURED)
 
147
                        return;
 
148
                log_error(0, _("Could not determine audit condition"));
 
149
        }
 
150
        if (au_cond == AUC_NOAUDIT)
 
151
                return;
 
152
        if (!audit_sudo_selected(1))
 
153
                return;
 
154
        if (getauid(&auid) < 0)
 
155
                log_error(0, _("getauid: failed"));
 
156
        if ((aufd = au_open()) == -1)
 
157
                log_error(0, _("au_open: failed"));
 
158
        if (getaudit_addr(&ainfo_addr, sizeof(ainfo_addr)) == 0) { 
 
159
                tok = au_to_subject_ex(auid, geteuid(), getegid(), getuid(),
 
160
                    getuid(), pid, pid, &ainfo_addr.ai_termid);
 
161
        } else if (errno == ENOSYS) {
 
162
                if (getaudit(&ainfo) < 0) 
 
163
                        log_error(0, _("getaudit: failed"));
 
164
                tok = au_to_subject(auid, geteuid(), getegid(), getuid(),
 
165
                    getuid(), pid, pid, &ainfo.ai_termid);
 
166
        } else
 
167
                log_error(0, _("getaudit: failed"));
 
168
        if (tok == NULL)
 
169
                log_error(0, _("au_to_subject: failed"));
 
170
        au_write(aufd, tok);
 
171
        tok = au_to_exec_args(exec_args);
 
172
        if (tok == NULL)
 
173
                log_error(0, _("au_to_exec_args: failed"));
 
174
        au_write(aufd, tok);
 
175
        (void) vsnprintf(text, sizeof(text), fmt, ap);
 
176
        tok = au_to_text(text);
 
177
        if (tok == NULL)
 
178
                log_error(0, _("au_to_text: failed"));
 
179
        au_write(aufd, tok);
 
180
        tok = au_to_return32(EPERM, 1);
 
181
        if (tok == NULL)
 
182
                log_error(0, _("au_to_return32: failed"));
 
183
        au_write(aufd, tok);
 
184
        if (au_close(aufd, 1, AUE_sudo) == -1)
 
185
                log_error(0, _("unable to commit audit record"));
 
186
}