Annotation of embedaddon/sudo/plugins/sudoers/check.c, revision 1.1.1.5
1.1 misho 1: /*
1.1.1.4 misho 2: * Copyright (c) 1993-1996,1998-2005, 2007-2013
1.1 misho 3: * Todd C. Miller <Todd.Miller@courtesan.com>
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: * Sponsored in part by the Defense Advanced Research Projects
18: * Agency (DARPA) and Air Force Research Laboratory, Air Force
19: * Materiel Command, USAF, under agreement number F39502-99-1-0512.
20: */
21:
22: #include <config.h>
23:
24: #include <sys/types.h>
25: #include <sys/time.h>
26: #include <stdio.h>
27: #ifdef STDC_HEADERS
28: # include <stdlib.h>
29: # include <stddef.h>
30: #else
31: # ifdef HAVE_STDLIB_H
32: # include <stdlib.h>
33: # endif
34: #endif /* STDC_HEADERS */
35: #ifdef HAVE_STRING_H
36: # include <string.h>
37: #endif /* HAVE_STRING_H */
38: #ifdef HAVE_STRINGS_H
39: # include <strings.h>
40: #endif /* HAVE_STRINGS_H */
41: #ifdef HAVE_UNISTD_H
42: # include <unistd.h>
43: #endif /* HAVE_UNISTD_H */
44: #if TIME_WITH_SYS_TIME
45: # include <time.h>
46: #endif
47: #include <errno.h>
48: #include <fcntl.h>
49: #include <pwd.h>
50: #include <grp.h>
51:
52: #include "sudoers.h"
1.1.1.4 misho 53: #include "check.h"
1.1 misho 54:
1.1.1.4 misho 55: static bool display_lecture(int);
56: static struct passwd *get_authpw(void);
1.1 misho 57:
58: /*
1.1.1.4 misho 59: * Returns true if the user successfully authenticates, false if not
60: * or -1 on error.
1.1 misho 61: */
1.1.1.4 misho 62: static int
63: check_user_interactive(int validated, int mode, struct passwd *auth_pw)
64: {
65: int status, rval = true;
66: debug_decl(check_user_interactive, SUDO_DEBUG_AUTH)
67:
68: /* Always need a password when -k was specified with the command. */
69: if (ISSET(mode, MODE_IGNORE_TICKET))
70: SET(validated, FLAG_CHECK_USER);
71:
72: if (build_timestamp(auth_pw) == -1) {
73: rval = -1;
74: goto done;
75: }
76:
77: status = timestamp_status(auth_pw);
78:
79: if (status != TS_CURRENT || ISSET(validated, FLAG_CHECK_USER)) {
80: char *prompt;
81: bool lectured;
82:
83: /* Bail out if we are non-interactive and a password is required */
84: if (ISSET(mode, MODE_NONINTERACTIVE)) {
85: validated |= FLAG_NON_INTERACTIVE;
86: log_auth_failure(validated, 0);
87: rval = -1;
88: goto done;
89: }
90:
91: /* XXX - should not lecture if askpass helper is being used. */
92: lectured = display_lecture(status);
93:
94: /* Expand any escapes in the prompt. */
95: prompt = expand_prompt(user_prompt ? user_prompt : def_passprompt,
96: user_name, user_shost);
97:
98: rval = verify_user(auth_pw, prompt, validated);
99: if (rval == true && lectured)
100: set_lectured();
101: efree(prompt);
102: }
103: /* Only update timestamp if user was validated. */
104: if (rval == true && ISSET(validated, VALIDATE_OK) &&
105: !ISSET(mode, MODE_IGNORE_TICKET) && status != TS_ERROR)
106: update_timestamp(auth_pw);
107: done:
108: debug_return_bool(rval);
109: }
1.1 misho 110:
111: /*
1.1.1.3 misho 112: * Returns true if the user successfully authenticates, false if not
113: * or -1 on error.
1.1 misho 114: */
115: int
116: check_user(int validated, int mode)
117: {
118: struct passwd *auth_pw;
1.1.1.4 misho 119: int rval = true;
1.1.1.2 misho 120: debug_decl(check_user, SUDO_DEBUG_AUTH)
1.1 misho 121:
122: /*
123: * Init authentication system regardless of whether we need a password.
124: * Required for proper PAM session support.
125: */
126: auth_pw = get_authpw();
127: if (sudo_auth_init(auth_pw) == -1) {
128: rval = -1;
129: goto done;
130: }
131:
1.1.1.3 misho 132: /*
133: * Don't prompt for the root passwd or if the user is exempt.
134: * If the user is not changing uid/gid, no need for a password.
135: */
1.1.1.5 ! misho 136: if (!def_authenticate || user_is_exempt())
1.1 misho 137: goto done;
1.1.1.5 ! misho 138: if (user_uid == 0 || (user_uid == runas_pw->pw_uid &&
! 139: (!runas_gr || user_in_group(sudo_user.pw, runas_gr->gr_name)))) {
1.1.1.3 misho 140: #ifdef HAVE_SELINUX
141: if (user_role == NULL && user_type == NULL)
142: #endif
143: #ifdef HAVE_PRIV_SET
144: if (runas_privs == NULL && runas_limitprivs == NULL)
145: #endif
146: goto done;
147: }
148:
1.1.1.4 misho 149: rval = check_user_interactive(validated, mode, auth_pw);
1.1 misho 150:
151: done:
152: sudo_auth_cleanup(auth_pw);
1.1.1.3 misho 153: sudo_pw_delref(auth_pw);
1.1 misho 154:
1.1.1.2 misho 155: debug_return_bool(rval);
1.1 misho 156: }
157:
158: /*
1.1.1.4 misho 159: * Display sudo lecture (standard or custom).
160: * Returns true if the user was lectured, else false.
1.1 misho 161: */
1.1.1.4 misho 162: static bool
163: display_lecture(int status)
1.1 misho 164: {
165: FILE *fp;
166: char buf[BUFSIZ];
167: ssize_t nread;
168: struct sudo_conv_message msg;
169: struct sudo_conv_reply repl;
1.1.1.2 misho 170: debug_decl(lecture, SUDO_DEBUG_AUTH)
1.1 misho 171:
172: if (def_lecture == never ||
1.1.1.4 misho 173: (def_lecture == once && already_lectured(status)))
174: debug_return_bool(false);
1.1 misho 175:
176: memset(&msg, 0, sizeof(msg));
177: memset(&repl, 0, sizeof(repl));
178:
179: if (def_lecture_file && (fp = fopen(def_lecture_file, "r")) != NULL) {
180: while ((nread = fread(buf, sizeof(char), sizeof(buf) - 1, fp)) != 0) {
1.1.1.2 misho 181: buf[nread] = '\0';
1.1 misho 182: msg.msg_type = SUDO_CONV_ERROR_MSG;
183: msg.msg = buf;
184: sudo_conv(1, &msg, &repl);
185: }
186: fclose(fp);
187: } else {
188: msg.msg_type = SUDO_CONV_ERROR_MSG;
1.1.1.4 misho 189: msg.msg = _("\n"
190: "We trust you have received the usual lecture from the local System\n"
191: "Administrator. It usually boils down to these three things:\n\n"
192: " #1) Respect the privacy of others.\n"
193: " #2) Think before you type.\n"
194: " #3) With great power comes great responsibility.\n\n");
1.1 misho 195: sudo_conv(1, &msg, &repl);
196: }
1.1.1.4 misho 197: debug_return_bool(true);
1.1 misho 198: }
199:
200: /*
201: * Checks if the user is exempt from supplying a password.
202: */
1.1.1.2 misho 203: bool
1.1 misho 204: user_is_exempt(void)
205: {
1.1.1.2 misho 206: bool rval = false;
207: debug_decl(user_is_exempt, SUDO_DEBUG_AUTH)
208:
209: if (def_exempt_group)
210: rval = user_in_group(sudo_user.pw, def_exempt_group);
211: debug_return_bool(rval);
1.1 misho 212: }
213:
214: /*
215: * Get passwd entry for the user we are going to authenticate as.
216: * By default, this is the user invoking sudo. In the most common
217: * case, this matches sudo_user.pw or runas_pw.
218: */
219: static struct passwd *
220: get_authpw(void)
221: {
222: struct passwd *pw;
1.1.1.2 misho 223: debug_decl(get_authpw, SUDO_DEBUG_AUTH)
1.1 misho 224:
225: if (def_rootpw) {
226: if ((pw = sudo_getpwuid(ROOT_UID)) == NULL)
1.1.1.4 misho 227: log_fatal(0, N_("unknown uid: %u"), ROOT_UID);
1.1 misho 228: } else if (def_runaspw) {
229: if ((pw = sudo_getpwnam(def_runas_default)) == NULL)
1.1.1.4 misho 230: log_fatal(0, N_("unknown user: %s"), def_runas_default);
1.1 misho 231: } else if (def_targetpw) {
232: if (runas_pw->pw_name == NULL)
1.1.1.4 misho 233: log_fatal(NO_MAIL|MSG_ONLY, N_("unknown uid: %u"),
1.1 misho 234: (unsigned int) runas_pw->pw_uid);
1.1.1.3 misho 235: sudo_pw_addref(runas_pw);
1.1 misho 236: pw = runas_pw;
237: } else {
1.1.1.3 misho 238: sudo_pw_addref(sudo_user.pw);
1.1 misho 239: pw = sudo_user.pw;
240: }
241:
1.1.1.2 misho 242: debug_return_ptr(pw);
1.1 misho 243: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>