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