2 * Copyright (c) 1999-2005, 2008-2009 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.40 2009/05/25 12:02:42 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;
103 #ifdef HAVE_BSM_AUDIT
104 extern char **NewArgv;
107 /* Enable suspend during password entry. */
108 sigemptyset(&sa.sa_mask);
109 sa.sa_flags = SA_RESTART;
110 sa.sa_handler = SIG_DFL;
111 (void) sigaction(SIGTSTP, &sa, &osa);
113 /* Make sure we have at least one auth method. */
114 if (auth_switch[0].name == NULL) {
115 #ifdef HAVE_BSM_AUDIT
116 audit_failure(NewArgv, "no authentication methods");
118 log_error(0, "%s %s %s",
119 "There are no authentication methods compiled into sudo!",
120 "If you want to turn off authentication, use the",
121 "--disable-authentication configure option.");
124 /* Set FLAG_ONEANDONLY if there is only one auth method. */
125 if (auth_switch[1].name == NULL)
126 SET(auth_switch[0].flags, FLAG_ONEANDONLY);
128 /* Initialize auth methods and unconfigure the method if necessary. */
129 for (auth = auth_switch; auth->name; auth++) {
130 if (auth->init && IS_CONFIGURED(auth)) {
131 if (NEEDS_USER(auth))
132 set_perms(PERM_USER);
134 status = (auth->init)(pw, &prompt, auth);
135 if (status == AUTH_FAILURE)
136 CLR(auth->flags, FLAG_CONFIGURED);
137 else if (status == AUTH_FATAL) { /* XXX log */
138 #ifdef HAVE_BSM_AUDIT
139 audit_failure(NewArgv, "authentication failure");
141 exit(1); /* assume error msg already printed */
144 if (NEEDS_USER(auth))
145 set_perms(PERM_ROOT);
150 /* Do any per-method setup and unconfigure the method if needed */
151 for (auth = auth_switch; auth->name; auth++) {
152 if (auth->setup && IS_CONFIGURED(auth)) {
153 if (NEEDS_USER(auth))
154 set_perms(PERM_USER);
156 status = (auth->setup)(pw, &prompt, auth);
157 if (status == AUTH_FAILURE)
158 CLR(auth->flags, FLAG_CONFIGURED);
159 else if (status == AUTH_FATAL) {/* XXX log */
160 #ifdef HAVE_BSM_AUDIT
161 audit_failure(NewArgv, "authentication failure");
163 exit(1); /* assume error msg already printed */
166 if (NEEDS_USER(auth))
167 set_perms(PERM_ROOT);
171 /* Get the password unless the auth function will do it for us */
172 #ifdef AUTH_STANDALONE
175 p = (char *) tgetpass(prompt, def_passwd_timeout * 60,
177 #endif /* AUTH_STANDALONE */
179 /* Call authentication functions. */
180 for (auth = auth_switch; p && auth->name; auth++) {
181 if (!IS_CONFIGURED(auth))
184 if (NEEDS_USER(auth))
185 set_perms(PERM_USER);
187 success = auth->status = (auth->verify)(pw, (char *)p, auth);
189 if (NEEDS_USER(auth))
190 set_perms(PERM_ROOT);
192 if (auth->status != AUTH_FAILURE)
195 #ifndef AUTH_STANDALONE
197 zero_bytes(p, strlen(p));
199 if (!ISSET(tgetpass_flags, TGP_ASKPASS))
204 /* Call cleanup routines. */
205 for (auth = auth_switch; auth->name; auth++) {
206 if (auth->cleanup && IS_CONFIGURED(auth)) {
207 if (NEEDS_USER(auth))
208 set_perms(PERM_USER);
210 status = (auth->cleanup)(pw, auth);
211 if (status == AUTH_FATAL) { /* XXX log */
212 #ifdef HAVE_BSM_AUDIT
213 audit_failure(NewArgv, "authentication failure");
215 exit(1); /* assume error msg already printed */
218 if (NEEDS_USER(auth))
219 set_perms(PERM_ROOT);
225 (void) sigaction(SIGTSTP, &osa, NULL);
229 if (counter != def_passwd_tries) {
230 if (def_mail_badpass || def_mail_always)
234 #ifdef HAVE_BSM_AUDIT
235 audit_failure(NewArgv, "authentication failure");
237 log_error(flags, "%d incorrect password attempt%s",
238 def_passwd_tries - counter,
239 (def_passwd_tries - counter == 1) ? "" : "s");
243 #ifdef HAVE_BSM_AUDIT
244 audit_failure(NewArgv, "authentication failure");
258 (void) fprintf(fp, "%s\n", INSULT);
261 (void) fprintf(fp, "%s\n", def_badpass_message);
269 (void) fputs("Authentication methods:", stdout);
270 for (auth = auth_switch; auth->name; auth++)
271 (void) printf(" '%s'", auth->name);
272 (void) putchar('\n');