Imported Upstream version 1.8.7
[debian/sudo] / plugins / sudoers / auth / securid5.c
1 /*
2  * Copyright (c) 1999-2005, 2007, 2010-2012
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 <stdio.h>
30 #ifdef STDC_HEADERS
31 # include <stdlib.h>
32 # include <stddef.h>
33 #else
34 # ifdef HAVE_STDLIB_H
35 #  include <stdlib.h>
36 # endif
37 #endif /* STDC_HEADERS */
38 #ifdef HAVE_STRING_H
39 # include <string.h>
40 #endif /* HAVE_STRING_H */
41 #ifdef HAVE_STRINGS_H
42 # include <strings.h>
43 #endif /* HAVE_STRINGS_H */
44 #ifdef HAVE_UNISTD_H
45 # include <unistd.h>
46 #endif /* HAVE_UNISTD_H */
47 #include <pwd.h>
48
49 /* Needed for SecurID v5.0 Authentication on UNIX */
50 #define UNIX 1
51 #include <acexport.h>
52 #include <sdacmvls.h>
53
54 #include "sudoers.h"
55 #include "sudo_auth.h"
56
57 /*
58  * securid_init - Initialises communications with ACE server
59  * Arguments in:
60  *     pw - UNUSED
61  *     auth - sudo authentication structure
62  *
63  * Results out:
64  *     auth - auth->data contains pointer to new SecurID handle
65  *     return code - Fatal if initialization unsuccessful, otherwise
66  *                   success.
67  */
68 int
69 sudo_securid_init(struct passwd *pw, sudo_auth *auth)
70 {
71     static SDI_HANDLE sd_dat;                   /* SecurID handle */
72     debug_decl(sudo_securid_init, SUDO_DEBUG_AUTH)
73
74     auth->data = (void *) &sd_dat;              /* For method-specific data */
75
76     /* Start communications */
77     if (AceInitialize() != SD_FALSE)
78         debug_return_int(AUTH_SUCCESS);
79
80     warningx(_("failed to initialise the ACE API library"));
81     debug_return_int(AUTH_FATAL);
82 }
83
84 /*
85  * securid_setup - Initialises a SecurID transaction and locks out other
86  *     ACE servers
87  *
88  * Arguments in:
89  *     pw - struct passwd for username
90  *     promptp - UNUSED
91  *     auth - sudo authentication structure for SecurID handle
92  *
93  * Results out:
94  *     return code - Success if transaction started correctly, fatal
95  *                   otherwise
96  */
97 int
98 sudo_securid_setup(struct passwd *pw, char **promptp, sudo_auth *auth)
99 {
100     SDI_HANDLE *sd = (SDI_HANDLE *) auth->data;
101     int retval;
102     debug_decl(sudo_securid_setup, SUDO_DEBUG_AUTH)
103
104     /* Re-initialize SecurID every time. */
105     if (SD_Init(sd) != ACM_OK) {
106         warningx(_("unable to contact the SecurID server"));
107         debug_return_int(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                 debug_return_int(AUTH_SUCCESS);
117
118         case ACE_UNDEFINED_USERNAME:
119                 warningx(_("invalid username length for SecurID"));
120                 debug_return_int(AUTH_FATAL);
121
122         case ACE_ERR_INVALID_HANDLE:
123                 warningx(_("invalid Authentication Handle for SecurID"));
124                 debug_return_int(AUTH_FATAL);
125
126         case ACM_ACCESS_DENIED:
127                 warningx(_("SecurID communication failed"));
128                 debug_return_int(AUTH_FATAL);
129
130         default:
131                 warningx(_("unknown SecurID error"));
132                 debug_return_int(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 sudo_securid_verify(struct passwd *pw, char *pass, sudo_auth *auth)
150 {
151     SDI_HANDLE *sd = (SDI_HANDLE *) auth->data;
152     int rval;
153     debug_decl(sudo_securid_verify, SUDO_DEBUG_AUTH)
154
155     pass = auth_getpass("Enter your PASSCODE: ",
156         def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_OFF);
157
158     /* Have ACE verify password */
159     switch (SD_Check(*sd, pass, pw->pw_name)) {
160         case ACM_OK:
161                 rval = AUTH_SUCESS;
162                 break;
163
164         case ACE_UNDEFINED_PASSCODE:
165                 warningx(_("invalid passcode length for SecurID"));
166                 rval = AUTH_FATAL;
167                 break;
168
169         case ACE_UNDEFINED_USERNAME:
170                 warningx(_("invalid username length for SecurID"));
171                 rval = AUTH_FATAL;
172                 break;
173
174         case ACE_ERR_INVALID_HANDLE:
175                 warningx(_("invalid Authentication Handle for SecurID"));
176                 rval = AUTH_FATAL;
177                 break;
178
179         case ACM_ACCESS_DENIED:
180                 rval = AUTH_FAILURE;
181                 break;
182
183         case ACM_NEXT_CODE_REQUIRED:
184                 /* Sometimes (when current token close to expire?)
185                    ACE challenges for the next token displayed
186                    (entered without the PIN) */
187                 pass = auth_getpass("\
188 !!! ATTENTION !!!\n\
189 Wait for the token code to change, \n\
190 then enter the new token code.\n", \
191                 def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_OFF);
192
193                 if (SD_Next(*sd, pass) == ACM_OK) {
194                         rval = AUTH_SUCCESS;
195                         break;
196                 }
197
198                 rval = AUTH_FAILURE;
199                 break;
200
201         case ACM_NEW_PIN_REQUIRED:
202                 /*
203                  * This user's SecurID has not been activated yet,
204                  * or the pin has been reset
205                  */
206                 /* XXX - Is setting up a new PIN within sudo's scope? */
207                 SD_Pin(*sd, "");
208                 fprintf(stderr, "Your SecurID access has not yet been set up.\n");
209                 fprintf(stderr, "Please set up a PIN before you try to authenticate.\n");
210                 rval = AUTH_FATAL;
211                 break;
212
213         default:
214                 warningx(_("unknown SecurID error"));
215                 rval = AUTH_FATAL;
216                 break;
217     }
218
219     /* Free resources */
220     SD_Close(*sd);
221
222     /* Return stored state to calling process */
223     debug_return_int(rval);
224 }