2 * Copyright (c) 1990 - 1994, Julianne Frances Haugh
3 * Copyright (c) 1996 - 2000, Marek Michałkiewicz
4 * Copyright (c) 2002 - 2005, Tomasz Kłoczko
5 * Copyright (c) 2007 - 2008, Nicolas François
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the copyright holders or contributors may not be used to
17 * endorse or promote products derived from this software without
18 * specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 #include <sys/types.h>
40 #include "prototypes.h"
43 #define SUAUTHFILE "/etc/suauth"
53 /* Really, I could do with a few const char's here defining all the
54 * strings output to the user or the syslog. -- chris
56 static int applies (const char *, char *);
58 static int isgrp (const char *, const char *);
63 int check_su_auth (const char *actual_id,
64 const char *wanted_id,
68 const char field[] = ":";
75 if (!(authfile_fd = fopen (SUAUTHFILE, "r"))) {
78 * If the file doesn't exist - default to the standard su
79 * behaviour (no access control). If open fails for some
80 * other reason - maybe someone is trying to fool us with
81 * file descriptors limit etc., so deny access. --marekm
87 "could not open/read config file '%s': %s\n",
88 SUAUTHFILE, strerror (err)));
92 while (fgets (temp, sizeof (temp), authfile_fd) != NULL) {
95 if (temp[endline = strlen (temp) - 1] != '\n') {
97 "%s, line %d: line too long or missing newline",
102 while (endline > 0 && (temp[endline - 1] == ' '
103 || temp[endline - 1] == '\t'
104 || temp[endline - 1] == '\n'))
106 temp[endline] = '\0';
109 while (temp[posn] == ' ' || temp[posn] == '\t')
112 if (temp[posn] == '\n' || temp[posn] == '#'
113 || temp[posn] == '\0') {
116 if (!(to_users = strtok (temp + posn, field))
117 || !(from_users = strtok ((char *) NULL, field))
118 || !(action = strtok ((char *) NULL, field))
119 || strtok ((char *) NULL, field)) {
121 "%s, line %d. Bad number of fields.\n",
126 if (!applies (wanted_id, to_users))
128 if (!applies (actual_id, from_users))
130 if (!strcmp (action, "DENY")) {
131 SYSLOG ((su_to_root ? LOG_WARN : LOG_NOTICE,
132 "DENIED su from '%s' to '%s' (%s)\n",
133 actual_id, wanted_id, SUAUTHFILE));
134 fputs (_("Access to su to that account DENIED.\n"),
136 fclose (authfile_fd);
138 } else if (!strcmp (action, "NOPASS")) {
139 SYSLOG ((su_to_root ? LOG_NOTICE : LOG_INFO,
140 "NO password asked for su from '%s' to '%s' (%s)\n",
141 actual_id, wanted_id, SUAUTHFILE));
142 fputs (_("Password authentication bypassed.\n"),stderr);
143 fclose (authfile_fd);
145 } else if (!strcmp (action, "OWNPASS")) {
146 SYSLOG ((su_to_root ? LOG_NOTICE : LOG_INFO,
147 "su from '%s' to '%s': asking for user's own password (%s)\n",
148 actual_id, wanted_id, SUAUTHFILE));
149 fputs (_("Please enter your OWN password as authentication.\n"),
151 fclose (authfile_fd);
155 "%s, line %d: unrecognised action!\n",
159 fclose (authfile_fd);
163 static int applies (const char *single, char *list)
165 const char split[] = ", ";
170 for (tok = strtok (list, split); tok != NULL;
171 tok = strtok (NULL, split)) {
173 if (!strcmp (tok, "ALL")) {
176 "%s, line %d: ALL in bad place\n",
181 } else if (!strcmp (tok, "EXCEPT")) {
184 "%s, line %d: EXCEPT in bas place\n",
189 } else if (!strcmp (tok, "GROUP")) {
190 if ((state != 0) && (state != 2)) {
192 "%s, line %d: GROUP in bad place\n",
196 state = (state == 0) ? 3 : 4;
199 case 0: /* No control words yet */
200 if (!strcmp (tok, single))
205 "%s, line %d: expect another token after ALL\n",
208 case 2: /* All except */
209 if (!strcmp (tok, single))
213 if (isgrp (single, tok))
216 case 4: /* All except group */
217 if (isgrp (single, tok))
223 if ((state != 0) && (state != 3))
228 static int isgrp (const char *name, const char *group)
232 grp = getgrnam (group); /* local, no need for xgetgrnam */
234 if (!grp || !grp->gr_mem)
237 return is_on_list (grp->gr_mem, name);
239 #endif /* SU_ACCESS */