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"
58 /* Really, I could do with a few const char's here defining all the
59 * strings output to the user or the syslog. -- chris
61 static int applies (const char *, char *);
63 static int isgrp (const char *, const char *);
68 int check_su_auth (const char *actual_id, const char *wanted_id)
71 const char field[] = ":";
78 if (!(authfile_fd = fopen (SUAUTHFILE, "r"))) {
81 * If the file doesn't exist - default to the standard su
82 * behaviour (no access control). If open fails for some
83 * other reason - maybe someone is trying to fool us with
84 * file descriptors limit etc., so deny access. --marekm
90 "could not open/read config file '%s': %s\n",
91 SUAUTHFILE, strerror (err)));
95 while (fgets (temp, sizeof (temp), authfile_fd) != NULL) {
98 if (temp[endline = strlen (temp) - 1] != '\n') {
100 "%s, line %d: line too long or missing newline",
105 while (endline > 0 && (temp[endline - 1] == ' '
106 || temp[endline - 1] == '\t'
107 || temp[endline - 1] == '\n'))
109 temp[endline] = '\0';
112 while (temp[posn] == ' ' || temp[posn] == '\t')
115 if (temp[posn] == '\n' || temp[posn] == '#'
116 || temp[posn] == '\0') {
119 if (!(to_users = strtok (temp + posn, field))
120 || !(from_users = strtok ((char *) NULL, field))
121 || !(action = strtok ((char *) NULL, field))
122 || strtok ((char *) NULL, field)) {
124 "%s, line %d. Bad number of fields.\n",
129 if (!applies (wanted_id, to_users))
131 if (!applies (actual_id, from_users))
133 if (!strcmp (action, "DENY")) {
134 SYSLOG ((pwent.pw_uid ? LOG_NOTICE : LOG_WARN,
135 "DENIED su from '%s' to '%s' (%s)\n",
136 actual_id, wanted_id, SUAUTHFILE));
137 fputs (_("Access to su to that account DENIED.\n"),
139 fclose (authfile_fd);
141 } else if (!strcmp (action, "NOPASS")) {
142 SYSLOG ((pwent.pw_uid ? LOG_INFO : LOG_NOTICE,
143 "NO password asked for su from '%s' to '%s' (%s)\n",
144 actual_id, wanted_id, SUAUTHFILE));
145 fputs (_("Password authentication bypassed.\n"),stderr);
146 fclose (authfile_fd);
148 } else if (!strcmp (action, "OWNPASS")) {
149 SYSLOG ((pwent.pw_uid ? LOG_INFO : LOG_NOTICE,
150 "su from '%s' to '%s': asking for user's own password (%s)\n",
151 actual_id, wanted_id, SUAUTHFILE));
152 fputs (_("Please enter your OWN password as authentication.\n"),
154 fclose (authfile_fd);
158 "%s, line %d: unrecognised action!\n",
162 fclose (authfile_fd);
166 static int applies (const char *single, char *list)
168 const char split[] = ", ";
173 for (tok = strtok (list, split); tok != NULL;
174 tok = strtok (NULL, split)) {
176 if (!strcmp (tok, "ALL")) {
179 "%s, line %d: ALL in bad place\n",
184 } else if (!strcmp (tok, "EXCEPT")) {
187 "%s, line %d: EXCEPT in bas place\n",
192 } else if (!strcmp (tok, "GROUP")) {
193 if ((state != 0) && (state != 2)) {
195 "%s, line %d: GROUP in bad place\n",
199 state = (state == 0) ? 3 : 4;
202 case 0: /* No control words yet */
203 if (!strcmp (tok, single))
208 "%s, line %d: expect another token after ALL\n",
211 case 2: /* All except */
212 if (!strcmp (tok, single))
216 if (isgrp (single, tok))
219 case 4: /* All except group */
220 if (isgrp (single, tok))
226 if ((state != 0) && (state != 3))
231 static int isgrp (const char *name, const char *group)
235 grp = getgrnam (group); /* local, no need for xgetgrnam */
237 if (!grp || !grp->gr_mem)
240 return is_on_list (grp->gr_mem, name);
242 #endif /* SU_ACCESS */