2 * Copyright (c) 1999-2005, 2008 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 */
35 # if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS)
40 # ifdef HAVE_STRINGS_H
43 #endif /* HAVE_STRING_H */
46 #endif /* HAVE_UNISTD_H */
52 #include "sudo_auth.h"
56 __unused static const char rcsid[] = "$Sudo: sudo_auth.c,v 1.38 2008/11/07 17:45:52 millert Exp $";
59 sudo_auth auth_switch[] = {
60 #ifdef AUTH_STANDALONE
63 # ifndef WITHOUT_PASSWD
64 AUTH_ENTRY(0, "passwd", passwd_init, NULL, passwd_verify, NULL)
66 # if defined(HAVE_GETPRPWNAM) && !defined(WITHOUT_PASSWD)
67 AUTH_ENTRY(0, "secureware", secureware_init, NULL, secureware_verify, NULL)
70 AUTH_ENTRY(0, "afs", NULL, NULL, afs_verify, NULL)
73 AUTH_ENTRY(0, "dce", NULL, NULL, dce_verify, NULL)
76 AUTH_ENTRY(0, "kerb4", kerb4_init, NULL, kerb4_verify, NULL)
79 AUTH_ENTRY(0, "kerb5", kerb5_init, NULL, kerb5_verify, kerb5_cleanup)
82 AUTH_ENTRY(0, "S/Key", NULL, rfc1938_setup, rfc1938_verify, NULL)
85 AUTH_ENTRY(0, "OPIE", NULL, rfc1938_setup, rfc1938_verify, NULL)
87 #endif /* AUTH_STANDALONE */
88 AUTH_ENTRY(0, NULL, NULL, NULL, NULL, NULL)
92 verify_user(pw, prompt)
96 int counter = def_passwd_tries + 1;
97 int success = AUTH_FAILURE;
104 /* Enable suspend during password entry. */
105 sigemptyset(&sa.sa_mask);
106 sa.sa_flags = SA_RESTART;
107 sa.sa_handler = SIG_DFL;
108 (void) sigaction(SIGTSTP, &sa, &osa);
110 /* Make sure we have at least one auth method. */
111 if (auth_switch[0].name == NULL)
112 log_error(0, "%s %s %s",
113 "There are no authentication methods compiled into sudo!",
114 "If you want to turn off authentication, use the",
115 "--disable-authentication configure option.");
117 /* Set FLAG_ONEANDONLY if there is only one auth method. */
118 if (auth_switch[1].name == NULL)
119 SET(auth_switch[0].flags, FLAG_ONEANDONLY);
121 /* Initialize auth methods and unconfigure the method if necessary. */
122 for (auth = auth_switch; auth->name; auth++) {
123 if (auth->init && IS_CONFIGURED(auth)) {
124 if (NEEDS_USER(auth))
125 set_perms(PERM_USER);
127 status = (auth->init)(pw, &prompt, auth);
128 if (status == AUTH_FAILURE)
129 CLR(auth->flags, FLAG_CONFIGURED);
130 else if (status == AUTH_FATAL) /* XXX log */
131 exit(1); /* assume error msg already printed */
133 if (NEEDS_USER(auth))
134 set_perms(PERM_ROOT);
139 /* Do any per-method setup and unconfigure the method if needed */
140 for (auth = auth_switch; auth->name; auth++) {
141 if (auth->setup && IS_CONFIGURED(auth)) {
142 if (NEEDS_USER(auth))
143 set_perms(PERM_USER);
145 status = (auth->setup)(pw, &prompt, auth);
146 if (status == AUTH_FAILURE)
147 CLR(auth->flags, FLAG_CONFIGURED);
148 else if (status == AUTH_FATAL) /* XXX log */
149 exit(1); /* assume error msg already printed */
151 if (NEEDS_USER(auth))
152 set_perms(PERM_ROOT);
156 /* Get the password unless the auth function will do it for us */
157 #ifdef AUTH_STANDALONE
160 p = (char *) tgetpass(prompt, def_passwd_timeout * 60,
162 #endif /* AUTH_STANDALONE */
164 /* Call authentication functions. */
165 for (auth = auth_switch; p && auth->name; auth++) {
166 if (!IS_CONFIGURED(auth))
169 if (NEEDS_USER(auth))
170 set_perms(PERM_USER);
172 success = auth->status = (auth->verify)(pw, (char *)p, auth);
174 if (NEEDS_USER(auth))
175 set_perms(PERM_ROOT);
177 if (auth->status != AUTH_FAILURE)
180 #ifndef AUTH_STANDALONE
182 zero_bytes(p, strlen(p));
184 if (!ISSET(tgetpass_flags, TGP_ASKPASS))
189 /* Call cleanup routines. */
190 for (auth = auth_switch; auth->name; auth++) {
191 if (auth->cleanup && IS_CONFIGURED(auth)) {
192 if (NEEDS_USER(auth))
193 set_perms(PERM_USER);
195 status = (auth->cleanup)(pw, auth);
196 if (status == AUTH_FATAL) /* XXX log */
197 exit(1); /* assume error msg already printed */
199 if (NEEDS_USER(auth))
200 set_perms(PERM_ROOT);
206 (void) sigaction(SIGTSTP, &osa, NULL);
210 if (counter != def_passwd_tries) {
211 if (def_mail_badpass || def_mail_always)
215 log_error(flags, "%d incorrect password attempt%s",
216 def_passwd_tries - counter,
217 (def_passwd_tries - counter == 1) ? "" : "s");
233 (void) fprintf(fp, "%s\n", INSULT);
236 (void) fprintf(fp, "%s\n", def_badpass_message);
244 (void) fputs("Authentication methods:", stdout);
245 for (auth = auth_switch; auth->name; auth++)
246 (void) printf(" '%s'", auth->name);
247 (void) putchar('\n');