Imported Upstream version 1.8.2
[debian/sudo] / plugins / sudoers / auth / securid5.c
1 /*
2  * Copyright (c) 1999-2005, 2007, 2010-2011
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 "sudoers.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(struct passwd *pw, char **promptp, sudo_auth *auth)
72 {
73     static SDI_HANDLE sd_dat;                   /* SecurID handle */
74
75     auth->data = (void *) &sd_dat;              /* For method-specific data */
76
77     /* Start communications */
78     if (AceInitialize() != SD_FALSE)
79         return AUTH_SUCCESS;
80
81     warningx(_("failed to initialise the ACE API library"));
82     return AUTH_FATAL;
83 }
84
85 /*
86  * securid_setup - Initialises a SecurID transaction and locks out other
87  *     ACE servers
88  *
89  * Arguments in:
90  *     pw - struct passwd for username
91  *     promptp - UNUSED
92  *     auth - sudo authentication structure for SecurID handle
93  *
94  * Results out:
95  *     return code - Success if transaction started correctly, fatal
96  *                   otherwise
97  */
98 int
99 securid_setup(struct passwd *pw, char **promptp, sudo_auth *auth)
100 {
101     SDI_HANDLE *sd = (SDI_HANDLE *) auth->data;
102     int retval;
103
104     /* Re-initialize SecurID every time. */
105     if (SD_Init(sd) != ACM_OK) {
106         warningx(_("unable to contact the SecurID server"));
107         return AUTH_FATAL;
108     }
109
110     /* Lock new PIN code */
111     retval = SD_Lock(*sd, pw->pw_name);
112
113     switch (retval) {
114         case ACM_OK:
115                 warningx(_("User ID locked for SecurID Authentication"));
116                 return AUTH_SUCCESS;
117
118         case ACE_UNDEFINED_USERNAME:
119                 warningx(_("invalid username length for SecurID"));
120                 return AUTH_FATAL;
121
122         case ACE_ERR_INVALID_HANDLE:
123                 warningx(_("invalid Authentication Handle for SecurID"));
124                 return AUTH_FATAL;
125
126         case ACM_ACCESS_DENIED:
127                 warningx(_("SecurID communication failed"));
128                 return AUTH_FATAL;
129
130         default:
131                 warningx(_("unknown SecurID error"));
132                 return AUTH_FATAL;
133         }
134 }
135
136 /*
137  * securid_verify - Authenticates user and handles ACE responses
138  *
139  * Arguments in:
140  *     pw - struct passwd for username
141  *     pass - UNUSED
142  *     auth - sudo authentication structure for SecurID handle
143  *
144  * Results out:
145  *     return code - Success on successful authentication, failure on
146  *                   incorrect authentication, fatal on errors
147  */
148 int
149 securid_verify(struct passwd *pw, char *pass, sudo_auth *auth)
150 {
151     SDI_HANDLE *sd = (SDI_HANDLE *) auth->data;
152     int rval;
153
154     pass = auth_getpass("Enter your PASSCODE: ",
155         def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_OFF);
156
157     /* Have ACE verify password */
158     switch (SD_Check(*sd, pass, pw->pw_name)) {
159         case ACM_OK:
160                 rval = AUTH_SUCESS;
161                 break;
162
163         case ACE_UNDEFINED_PASSCODE:
164                 warningx(_("invalid passcode length for SecurID"));
165                 rval = AUTH_FATAL;
166                 break;
167
168         case ACE_UNDEFINED_USERNAME:
169                 warningx(_("invalid username length for SecurID"));
170                 rval = AUTH_FATAL;
171                 break;
172
173         case ACE_ERR_INVALID_HANDLE:
174                 warningx(_("invalid Authentication Handle for SecurID"));
175                 rval = AUTH_FATAL;
176                 break;
177
178         case ACM_ACCESS_DENIED:
179                 rval = AUTH_FAILURE;
180                 break;
181
182         case ACM_NEXT_CODE_REQUIRED:
183                 /* Sometimes (when current token close to expire?)
184                    ACE challenges for the next token displayed
185                    (entered without the PIN) */
186                 pass = auth_getpass("\
187 !!! ATTENTION !!!\n\
188 Wait for the token code to change, \n\
189 then enter the new token code.\n", \
190                 def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_OFF);
191
192                 if (SD_Next(*sd, pass) == ACM_OK) {
193                         rval = AUTH_SUCCESS;
194                         break;
195                 }
196
197                 rval = AUTH_FAILURE;
198                 break;
199
200         case ACM_NEW_PIN_REQUIRED:
201                 /*
202                  * This user's SecurID has not been activated yet,
203                  * or the pin has been reset
204                  */
205                 /* XXX - Is setting up a new PIN within sudo's scope? */
206                 SD_Pin(*sd, "");
207                 fprintf(stderr, "Your SecurID access has not yet been set up.\n");
208                 fprintf(stderr, "Please set up a PIN before you try to authenticate.\n");
209                 rval = AUTH_FATAL;
210                 break;
211
212         default:
213                 warningx(_("unknown SecurID error"));
214                 rval = AUTH_FATAL;
215                 break;
216     }
217
218     /* Free resources */
219     SD_Close(*sd);
220
221     /* Return stored state to calling process */
222     return rval;
223 }