]> granicus.if.org Git - sudo/blob - plugins/sudoers/auth/securid5.c
ca75c5650ff71d550e944f2474f76ef98c310c03
[sudo] / plugins / sudoers / auth / securid5.c
1 /*
2  * Copyright (c) 1999-2005, 2007, 2010-2012, 2014-2016
3  *      Todd C. Miller <Todd.Miller@sudo.ws>
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  *
18  * Sponsored in part by the Defense Advanced Research Projects
19  * Agency (DARPA) and Air Force Research Laboratory, Air Force
20  * Materiel Command, USAF, under agreement number F39502-99-1-0512.
21  */
22
23 /*
24  * This is an open source non-commercial project. Dear PVS-Studio, please check it.
25  * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
26  */
27
28 #include <config.h>
29
30 #ifdef HAVE_SECURID
31
32 #include <sys/types.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #ifdef HAVE_STRING_H
36 # include <string.h>
37 #endif /* HAVE_STRING_H */
38 #ifdef HAVE_STRINGS_H
39 # include <strings.h>
40 #endif /* HAVE_STRINGS_H */
41 #include <unistd.h>
42 #include <pwd.h>
43
44 /* Needed for SecurID v5.0 Authentication on UNIX */
45 #define UNIX 1
46 #include <acexport.h>
47 #include <sdacmvls.h>
48
49 #include "sudoers.h"
50 #include "sudo_auth.h"
51
52 /*
53  * securid_init - Initialises communications with ACE server
54  * Arguments in:
55  *     pw - UNUSED
56  *     auth - sudo authentication structure
57  *
58  * Results out:
59  *     auth - auth->data contains pointer to new SecurID handle
60  *     return code - Fatal if initialization unsuccessful, otherwise
61  *                   success.
62  */
63 int
64 sudo_securid_init(struct passwd *pw, sudo_auth *auth)
65 {
66     static SDI_HANDLE sd_dat;                   /* SecurID handle */
67     debug_decl(sudo_securid_init, SUDOERS_DEBUG_AUTH)
68
69     auth->data = (void *) &sd_dat;              /* For method-specific data */
70
71     /* Start communications */
72     if (AceInitialize() != SD_FALSE)
73         debug_return_int(AUTH_SUCCESS);
74
75     sudo_warnx(U_("failed to initialise the ACE API library"));
76     debug_return_int(AUTH_FATAL);
77 }
78
79 /*
80  * securid_setup - Initialises a SecurID transaction and locks out other
81  *     ACE servers
82  *
83  * Arguments in:
84  *     pw - struct passwd for username
85  *     promptp - UNUSED
86  *     auth - sudo authentication structure for SecurID handle
87  *
88  * Results out:
89  *     return code - Success if transaction started correctly, fatal
90  *                   otherwise
91  */
92 int
93 sudo_securid_setup(struct passwd *pw, char **promptp, sudo_auth *auth)
94 {
95     SDI_HANDLE *sd = (SDI_HANDLE *) auth->data;
96     int retval;
97     debug_decl(sudo_securid_setup, SUDOERS_DEBUG_AUTH)
98
99     /* Re-initialize SecurID every time. */
100     if (SD_Init(sd) != ACM_OK) {
101         sudo_warnx(U_("unable to contact the SecurID server"));
102         debug_return_int(AUTH_FATAL);
103     }
104
105     /* Lock new PIN code */
106     retval = SD_Lock(*sd, pw->pw_name);
107
108     switch (retval) {
109         case ACM_OK:
110                 sudo_warnx(U_("User ID locked for SecurID Authentication"));
111                 debug_return_int(AUTH_SUCCESS);
112
113         case ACE_UNDEFINED_USERNAME:
114                 sudo_warnx(U_("invalid username length for SecurID"));
115                 debug_return_int(AUTH_FATAL);
116
117         case ACE_ERR_INVALID_HANDLE:
118                 sudo_warnx(U_("invalid Authentication Handle for SecurID"));
119                 debug_return_int(AUTH_FATAL);
120
121         case ACM_ACCESS_DENIED:
122                 sudo_warnx(U_("SecurID communication failed"));
123                 debug_return_int(AUTH_FATAL);
124
125         default:
126                 sudo_warnx(U_("unknown SecurID error"));
127                 debug_return_int(AUTH_FATAL);
128         }
129 }
130
131 /*
132  * securid_verify - Authenticates user and handles ACE responses
133  *
134  * Arguments in:
135  *     pw - struct passwd for username
136  *     pass - UNUSED
137  *     auth - sudo authentication structure for SecurID handle
138  *
139  * Results out:
140  *     return code - Success on successful authentication, failure on
141  *                   incorrect authentication, fatal on errors
142  */
143 int
144 sudo_securid_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_conv_callback *callback)
145 {
146     SDI_HANDLE *sd = (SDI_HANDLE *) auth->data;
147     int ret;
148     debug_decl(sudo_securid_verify, SUDOERS_DEBUG_AUTH)
149
150     pass = auth_getpass("Enter your PASSCODE: ", SUDO_CONV_PROMPT_ECHO_OFF,
151         callback);
152
153     /* Have ACE verify password */
154     switch (SD_Check(*sd, pass, pw->pw_name)) {
155         case ACM_OK:
156                 ret = AUTH_SUCESS;
157                 break;
158
159         case ACE_UNDEFINED_PASSCODE:
160                 sudo_warnx(U_("invalid passcode length for SecurID"));
161                 ret = AUTH_FATAL;
162                 break;
163
164         case ACE_UNDEFINED_USERNAME:
165                 sudo_warnx(U_("invalid username length for SecurID"));
166                 ret = AUTH_FATAL;
167                 break;
168
169         case ACE_ERR_INVALID_HANDLE:
170                 sudo_warnx(U_("invalid Authentication Handle for SecurID"));
171                 ret = AUTH_FATAL;
172                 break;
173
174         case ACM_ACCESS_DENIED:
175                 ret = AUTH_FAILURE;
176                 break;
177
178         case ACM_NEXT_CODE_REQUIRED:
179                 /* Sometimes (when current token close to expire?)
180                    ACE challenges for the next token displayed
181                    (entered without the PIN) */
182                 if (pass != NULL) {
183                     memset_s(pass, SUDO_PASS_MAX, 0, strlen(pass));
184                     free(pass);
185                 }
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                 SUDO_CONV_PROMPT_ECHO_OFF, callback);
191
192                 if (SD_Next(*sd, pass) == ACM_OK) {
193                         ret = AUTH_SUCCESS;
194                         break;
195                 }
196
197                 ret = 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                 sudo_printf(SUDO_CONV_ERROR_MSG, 
208                     "Your SecurID access has not yet been set up.\n");
209                 sudo_printf(SUDO_CONV_ERROR_MSG, 
210                     "Please set up a PIN before you try to authenticate.\n");
211                 ret = AUTH_FATAL;
212                 break;
213
214         default:
215                 sudo_warnx(U_("unknown SecurID error"));
216                 ret = AUTH_FATAL;
217                 break;
218     }
219
220     /* Free resources */
221     SD_Close(*sd);
222
223     if (pass != NULL) {
224         memset_s(pass, SUDO_PASS_MAX, 0, strlen(pass));
225         free(pass);
226     }
227
228     /* Return stored state to calling process */
229     debug_return_int(ret);
230 }
231
232 #endif /* HAVE_SECURID */