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