]> git.gag.com Git - debian/sudo/blob - auth/bsdauth.c
Imported Upstream version 1.6.6
[debian/sudo] / auth / bsdauth.c
1 /*
2  * Copyright (c) 2000-2001 Todd C. Miller <Todd.Miller@courtesan.com>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * 3. The name of the author may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission.
18  *
19  * 4. Products derived from this software may not be called "Sudo" nor
20  *    may "Sudo" appear in their names without specific prior written
21  *    permission from the author.
22  *
23  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
24  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
25  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
26  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
29  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
31  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
32  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34
35 #include "config.h"
36
37 #include <sys/types.h>
38 #include <sys/param.h>
39 #include <stdio.h>
40 #ifdef STDC_HEADERS
41 # include <stdlib.h>
42 # include <stddef.h>
43 #else
44 # ifdef HAVE_STDLIB_H
45 #  include <stdlib.h>
46 # endif
47 #endif /* STDC_HEADERS */
48 #ifdef HAVE_STRING_H
49 # include <string.h>
50 #else
51 # ifdef HAVE_STRINGS_H
52 #  include <strings.h>
53 # endif
54 #endif /* HAVE_STRING_H */
55 #ifdef HAVE_UNISTD_H
56 # include <unistd.h>
57 #endif /* HAVE_UNISTD_H */
58 #include <ctype.h>
59 #include <pwd.h>
60 #include <signal.h>
61
62 #include <login_cap.h>
63 #include <bsd_auth.h>
64
65 #include "sudo.h"
66 #include "sudo_auth.h"
67
68 #ifndef lint
69 static const char rcsid[] = "$Sudo: bsdauth.c,v 1.8 2002/01/22 03:37:55 millert Exp $";
70 #endif /* lint */
71
72 extern char *login_style;               /* from sudo.c */
73
74 int
75 bsdauth_init(pw, promptp, auth)
76     struct passwd *pw;
77     char **promptp;
78     sudo_auth *auth;
79 {
80     static auth_session_t *as;
81     extern login_cap_t *lc;                     /* from sudo.c */
82
83     if ((as = auth_open()) == NULL) {
84         log_error(USE_ERRNO|NO_EXIT|NO_MAIL, 
85             "unable to begin bsd authentication");
86         return(AUTH_FATAL);
87     }
88
89     /* XXX - maybe sanity check the auth style earlier? */
90     login_style = login_getstyle(lc, login_style, "auth-sudo");
91     if (login_style == NULL) {
92         log_error(NO_EXIT|NO_MAIL, "invalid authentication type");
93         auth_close(as);
94         return(AUTH_FATAL);
95     }
96
97      if (auth_setitem(as, AUTHV_STYLE, login_style) < 0 ||
98         auth_setitem(as, AUTHV_NAME, pw->pw_name) < 0 ||
99         auth_setitem(as, AUTHV_CLASS, login_class) < 0) {
100         log_error(NO_EXIT|NO_MAIL, "unable to setup authentication");
101         auth_close(as);
102         return(AUTH_FATAL);
103     }
104
105     auth->data = (VOID *) as;
106     return(AUTH_SUCCESS);
107 }
108
109 int
110 bsdauth_verify(pw, prompt, auth)
111     struct passwd *pw;
112     char *prompt;
113     sudo_auth *auth;
114 {
115     char *s, *pass;
116     size_t len;
117     int authok = 0;
118     sigaction_t sa, osa;
119     auth_session_t *as = (auth_session_t *) auth->data;
120     extern int nil_pw;
121
122     /* save old signal handler */
123     sigemptyset(&sa.sa_mask);
124     sa.sa_flags = SA_RESTART;
125     sa.sa_handler = SIG_DFL;
126     (void) sigaction(SIGCHLD, &sa, &osa);
127
128     /*
129      * If there is a challenge then print that instead of the normal
130      * prompt.  If the user just hits return we prompt again with echo
131      * turned on, which is useful for challenge/response things like
132      * S/Key.
133      */
134     if ((s = auth_challenge(as)) == NULL) {
135         pass = tgetpass(prompt, def_ival(I_PASSWD_TIMEOUT) * 60, tgetpass_flags);
136     } else {
137         pass = tgetpass(s, def_ival(I_PASSWD_TIMEOUT) * 60, tgetpass_flags);
138         if (pass && *pass == '\0') {
139             if ((prompt = strrchr(s, '\n')))
140                 prompt++;
141             else
142                 prompt = s;
143
144             /*
145              * Append '[echo on]' to the last line of the challenge and
146              * reprompt with echo turned on.
147              */
148             len = strlen(prompt) - 1;
149             while (isspace(prompt[len]) || prompt[len] == ':')
150                 prompt[len--] = '\0';
151             easprintf(&s, "%s [echo on]: ", prompt);
152             pass = tgetpass(s, def_ival(I_PASSWD_TIMEOUT) * 60,
153                 tgetpass_flags | TGP_ECHO);
154             free(s);
155         }
156     }
157
158     if (!pass || *pass == '\0')         /* ^C or empty password */
159         nil_pw = 1;
160
161     if (pass) {
162         authok = auth_userresponse(as, pass, 1);
163         memset(pass, 0, strlen(pass));
164     }
165
166     /* restore old signal handler */
167     (void) sigaction(SIGCHLD, &osa, NULL);
168
169     if (authok)
170         return(AUTH_SUCCESS);
171
172     if ((s = auth_getvalue(as, "errormsg")) != NULL)
173         log_error(NO_EXIT|NO_MAIL, "%s", s);
174     return(AUTH_FAILURE);
175 }
176
177 int
178 bsdauth_cleanup(pw, auth)
179     struct passwd *pw;
180     sudo_auth *auth;
181 {
182     auth_session_t *as = (auth_session_t *) auth->data;
183
184     auth_close(as);
185
186     return(AUTH_SUCCESS);
187 }