ef9e2283fd811a123a7d3f082933da79fbc15d84
[debian/sudo] / auth / securid5.c
1 /*
2  * Copyright (c) 1999-2005, 2007, 2010
3  *      Todd C. Miller <Todd.Miller@courtesan.com>
4  * Copyright (c) 2002 Michael Stroucken <michael@stroucken.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
18  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
19  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
20  *
21  * Sponsored in part by the Defense Advanced Research Projects
22  * Agency (DARPA) and Air Force Research Laboratory, Air Force
23  * Materiel Command, USAF, under agreement number F39502-99-1-0512.
24  */
25
26 #include <config.h>
27
28 #include <sys/types.h>
29 #include <sys/param.h>
30 #include <stdio.h>
31 #ifdef STDC_HEADERS
32 # include <stdlib.h>
33 # include <stddef.h>
34 #else
35 # ifdef HAVE_STDLIB_H
36 #  include <stdlib.h>
37 # endif
38 #endif /* STDC_HEADERS */
39 #ifdef HAVE_STRING_H
40 # include <string.h>
41 #endif /* HAVE_STRING_H */
42 #ifdef HAVE_STRINGS_H
43 # include <strings.h>
44 #endif /* HAVE_STRINGS_H */
45 #ifdef HAVE_UNISTD_H
46 # include <unistd.h>
47 #endif /* HAVE_UNISTD_H */
48 #include <pwd.h>
49
50 /* Needed for SecurID v5.0 Authentication on UNIX */
51 #define UNIX 1
52 #include <acexport.h>
53 #include <sdacmvls.h>
54
55 #include "sudo.h"
56 #include "sudo_auth.h"
57
58 /*
59  * securid_init - Initialises communications with ACE server
60  * Arguments in:
61  *     pw - UNUSED
62  *     promptp - UNUSED
63  *     auth - sudo authentication structure
64  *
65  * Results out:
66  *     auth - auth->data contains pointer to new SecurID handle
67  *     return code - Fatal if initialization unsuccessful, otherwise
68  *                   success.
69  */
70 int
71 securid_init(pw, promptp, auth)
72     struct passwd *pw;
73     char **promptp;
74     sudo_auth *auth;
75 {
76     static SDI_HANDLE sd_dat;                   /* SecurID handle */
77
78     auth->data = (void *) &sd_dat;              /* For method-specific data */
79
80     /* Start communications */
81     if (AceInitialize() != SD_FALSE)
82         return(AUTH_SUCCESS);
83
84     warningx("failed to initialise the ACE API library");
85     return(AUTH_FATAL);
86 }
87
88 /*
89  * securid_setup - Initialises a SecurID transaction and locks out other
90  *     ACE servers
91  *
92  * Arguments in:
93  *     pw - struct passwd for username
94  *     promptp - UNUSED
95  *     auth - sudo authentication structure for SecurID handle
96  *
97  * Results out:
98  *     return code - Success if transaction started correctly, fatal
99  *                   otherwise
100  */
101 int
102 securid_setup(pw, promptp, auth)
103     struct passwd *pw;
104     char **promptp;
105     sudo_auth *auth;
106 {
107     SDI_HANDLE *sd = (SDI_HANDLE *) auth->data;
108     int retval;
109
110     /* Re-initialize SecurID every time. */
111     if (SD_Init(sd) != ACM_OK) {
112         warningx("unable to contact the SecurID server");
113         return(AUTH_FATAL);
114     }
115
116     /* Lock new PIN code */
117     retval = SD_Lock(*sd, pw->pw_name);
118
119     switch (retval) {
120         case ACM_OK:
121                 warningx("User ID locked for SecurID Authentication");
122                 return(AUTH_SUCCESS);
123
124         case ACE_UNDEFINED_USERNAME:
125                 warningx("invalid username length for SecurID");
126                 return(AUTH_FATAL);
127
128         case ACE_ERR_INVALID_HANDLE:
129                 warningx("invalid Authentication Handle for SecurID");
130                 return(AUTH_FATAL);
131
132         case ACM_ACCESS_DENIED:
133                 warningx("SecurID communication failed");
134                 return(AUTH_FATAL);
135
136         default:
137                 warningx("unknown SecurID error");
138                 return(AUTH_FATAL);
139         }
140 }
141
142 /*
143  * securid_verify - Authenticates user and handles ACE responses
144  *
145  * Arguments in:
146  *     pw - struct passwd for username
147  *     pass - UNUSED
148  *     auth - sudo authentication structure for SecurID handle
149  *
150  * Results out:
151  *     return code - Success on successful authentication, failure on
152  *                   incorrect authentication, fatal on errors
153  */
154 int
155 securid_verify(pw, pass, auth)
156     struct passwd *pw;
157     char *pass;
158     sudo_auth *auth;
159 {
160     SDI_HANDLE *sd = (SDI_HANDLE *) auth->data;
161     int rval;
162
163     pass = (char *) tgetpass("Enter your PASSCODE: ",
164         def_passwd_timeout * 60, tgetpass_flags);
165
166     /* Have ACE verify password */
167     switch (SD_Check(*sd, pass, pw->pw_name)) {
168         case ACM_OK:
169                 rval = AUTH_SUCESS;
170                 break;
171
172         case ACE_UNDEFINED_PASSCODE:
173                 warningx("invalid passcode length for SecurID");
174                 rval = AUTH_FATAL;
175                 break;
176
177         case ACE_UNDEFINED_USERNAME:
178                 warningx("invalid username length for SecurID");
179                 rval = AUTH_FATAL;
180                 break;
181
182         case ACE_ERR_INVALID_HANDLE:
183                 warningx("invalid Authentication Handle for SecurID");
184                 rval = AUTH_FATAL;
185                 break;
186
187         case ACM_ACCESS_DENIED:
188                 rval = AUTH_FAILURE;
189                 break;
190
191         case ACM_NEXT_CODE_REQUIRED:
192                 /* Sometimes (when current token close to expire?)
193                    ACE challenges for the next token displayed
194                    (entered without the PIN) */
195                 pass = (char *) tgetpass("\
196 !!! ATTENTION !!!\n\
197 Wait for the token code to change, \n\
198 then enter the new token code.\n", \
199                 def_passwd_timeout * 60, tgetpass_flags);
200
201                 if (SD_Next(*sd, pass) == ACM_OK) {
202                         rval = AUTH_SUCCESS;
203                         break;
204                 }
205
206                 rval = AUTH_FAILURE;
207                 break;
208
209         case ACM_NEW_PIN_REQUIRED:
210                 /*
211                  * This user's SecurID has not been activated yet,
212                  * or the pin has been reset
213                  */
214                 /* XXX - Is setting up a new PIN within sudo's scope? */
215                 SD_Pin(*sd, "");
216                 fprintf(stderr, "Your SecurID access has not yet been set up.\n");
217                 fprintf(stderr, "Please set up a PIN before you try to authenticate.\n");
218                 rval = AUTH_FATAL;
219                 break;
220
221         default:
222                 warningx("unknown SecurID error");
223                 rval = AUTH_FATAL;
224                 break;
225     }
226
227     /* Free resources */
228     SD_Close(*sd);
229
230     /* Return stored state to calling process */
231     return(rval);
232 }