2 * Copyright (c) 1999-2005, 2008-2010 Todd C. Miller <Todd.Miller@courtesan.com>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 * Sponsored in part by the Defense Advanced Research Projects
17 * Agency (DARPA) and Air Force Research Laboratory, Air Force
18 * Materiel Command, USAF, under agreement number F39502-99-1-0512.
23 #include <sys/types.h>
24 #include <sys/param.h>
33 #endif /* STDC_HEADERS */
36 #endif /* HAVE_STRING_H */
39 #endif /* HAVE_STRINGS_H */
42 #endif /* HAVE_UNISTD_H */
48 #include "sudo_auth.h"
51 sudo_auth auth_switch[] = {
52 #ifdef AUTH_STANDALONE
55 # ifndef WITHOUT_PASSWD
56 AUTH_ENTRY(0, "passwd", passwd_init, NULL, passwd_verify, passwd_cleanup)
58 # if defined(HAVE_GETPRPWNAM) && !defined(WITHOUT_PASSWD)
59 AUTH_ENTRY(0, "secureware", secureware_init, NULL, secureware_verify, secureware_cleanup)
62 AUTH_ENTRY(0, "afs", NULL, NULL, afs_verify, NULL)
65 AUTH_ENTRY(0, "dce", NULL, NULL, dce_verify, NULL)
68 AUTH_ENTRY(0, "kerb4", kerb4_init, NULL, kerb4_verify, NULL)
71 AUTH_ENTRY(0, "kerb5", kerb5_init, NULL, kerb5_verify, kerb5_cleanup)
74 AUTH_ENTRY(0, "S/Key", NULL, rfc1938_setup, rfc1938_verify, NULL)
77 AUTH_ENTRY(0, "OPIE", NULL, rfc1938_setup, rfc1938_verify, NULL)
79 #endif /* AUTH_STANDALONE */
80 AUTH_ENTRY(0, NULL, NULL, NULL, NULL, NULL)
84 verify_user(pw, prompt)
88 int counter = def_passwd_tries + 1;
89 int success = AUTH_FAILURE;
96 extern char **NewArgv;
99 /* Enable suspend during password entry. */
100 sigemptyset(&sa.sa_mask);
101 sa.sa_flags = SA_RESTART;
102 sa.sa_handler = SIG_DFL;
103 (void) sigaction(SIGTSTP, &sa, &osa);
105 /* Make sure we have at least one auth method. */
106 if (auth_switch[0].name == NULL) {
107 #ifdef HAVE_BSM_AUDIT
108 audit_failure(NewArgv, "no authentication methods");
110 log_error(0, "%s %s %s",
111 "There are no authentication methods compiled into sudo!",
112 "If you want to turn off authentication, use the",
113 "--disable-authentication configure option.");
116 /* Set FLAG_ONEANDONLY if there is only one auth method. */
117 if (auth_switch[1].name == NULL)
118 SET(auth_switch[0].flags, FLAG_ONEANDONLY);
120 /* Initialize auth methods and unconfigure the method if necessary. */
121 for (auth = auth_switch; auth->name; auth++) {
122 if (auth->init && IS_CONFIGURED(auth)) {
123 if (NEEDS_USER(auth))
124 set_perms(PERM_USER);
126 status = (auth->init)(pw, &prompt, auth);
127 if (status == AUTH_FAILURE)
128 CLR(auth->flags, FLAG_CONFIGURED);
129 else if (status == AUTH_FATAL) { /* XXX log */
130 #ifdef HAVE_BSM_AUDIT
131 audit_failure(NewArgv, "authentication failure");
133 exit(1); /* assume error msg already printed */
136 if (NEEDS_USER(auth))
137 set_perms(PERM_ROOT);
142 /* Do any per-method setup and unconfigure the method if needed */
143 for (auth = auth_switch; auth->name; auth++) {
144 if (auth->setup && IS_CONFIGURED(auth)) {
145 if (NEEDS_USER(auth))
146 set_perms(PERM_USER);
148 status = (auth->setup)(pw, &prompt, auth);
149 if (status == AUTH_FAILURE)
150 CLR(auth->flags, FLAG_CONFIGURED);
151 else if (status == AUTH_FATAL) {/* XXX log */
152 #ifdef HAVE_BSM_AUDIT
153 audit_failure(NewArgv, "authentication failure");
155 exit(1); /* assume error msg already printed */
158 if (NEEDS_USER(auth))
159 set_perms(PERM_ROOT);
163 /* Get the password unless the auth function will do it for us */
164 #ifdef AUTH_STANDALONE
167 p = (char *) tgetpass(prompt, def_passwd_timeout * 60,
169 #endif /* AUTH_STANDALONE */
171 /* Call authentication functions. */
172 for (auth = auth_switch; p && auth->name; auth++) {
173 if (!IS_CONFIGURED(auth))
176 if (NEEDS_USER(auth))
177 set_perms(PERM_USER);
179 success = auth->status = (auth->verify)(pw, (char *)p, auth);
181 if (NEEDS_USER(auth))
182 set_perms(PERM_ROOT);
184 if (auth->status != AUTH_FAILURE)
187 #ifndef AUTH_STANDALONE
190 zero_bytes(p, strlen(p));
192 if (!ISSET(tgetpass_flags, TGP_ASKPASS))
197 /* Call cleanup routines. */
198 for (auth = auth_switch; auth->name; auth++) {
199 if (auth->cleanup && IS_CONFIGURED(auth)) {
200 if (NEEDS_USER(auth))
201 set_perms(PERM_USER);
203 status = (auth->cleanup)(pw, auth);
204 if (status == AUTH_FATAL) { /* XXX log */
205 #ifdef HAVE_BSM_AUDIT
206 audit_failure(NewArgv, "authentication failure");
208 exit(1); /* assume error msg already printed */
211 if (NEEDS_USER(auth))
212 set_perms(PERM_ROOT);
218 (void) sigaction(SIGTSTP, &osa, NULL);
222 if (counter != def_passwd_tries) {
223 if (def_mail_badpass || def_mail_always)
227 #ifdef HAVE_BSM_AUDIT
228 audit_failure(NewArgv, "authentication failure");
230 log_error(flags, "%d incorrect password attempt%s",
231 def_passwd_tries - counter,
232 (def_passwd_tries - counter == 1) ? "" : "s");
236 #ifdef HAVE_BSM_AUDIT
237 audit_failure(NewArgv, "authentication failure");
251 (void) fprintf(fp, "%s\n", INSULT);
254 (void) fprintf(fp, "%s\n", def_badpass_message);
262 (void) fputs("Authentication methods:", stdout);
263 for (auth = auth_switch; auth->name; auth++)
264 (void) printf(" '%s'", auth->name);
265 (void) putchar('\n');