/* * Copyright (c) 1999-2005, 2007 Todd C. Miller * Copyright (c) 2002 Michael Stroucken * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Sponsored in part by the Defense Advanced Research Projects * Agency (DARPA) and Air Force Research Laboratory, Air Force * Materiel Command, USAF, under agreement number F39502-99-1-0512. */ #include #include #include #include #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif /* STDC_HEADERS */ #ifdef HAVE_STRING_H # include #else # ifdef HAVE_STRINGS_H # include # endif #endif /* HAVE_STRING_H */ #ifdef HAVE_UNISTD_H # include #endif /* HAVE_UNISTD_H */ #include /* Needed for SecurID v5.0 Authentication on UNIX */ #define UNIX 1 #include #include #include "sudo.h" #include "sudo_auth.h" /* * securid_init - Initialises communications with ACE server * Arguments in: * pw - UNUSED * promptp - UNUSED * auth - sudo authentication structure * * Results out: * auth - auth->data contains pointer to new SecurID handle * return code - Fatal if initialization unsuccessful, otherwise * success. */ int securid_init(pw, promptp, auth) struct passwd *pw; char **promptp; sudo_auth *auth; { static SDI_HANDLE sd_dat; /* SecurID handle */ auth->data = (void *) &sd_dat; /* For method-specific data */ /* Start communications */ if (AceInitialize() != SD_FALSE) return(AUTH_SUCCESS); warningx("failed to initialise the ACE API library"); return(AUTH_FATAL); } /* * securid_setup - Initialises a SecurID transaction and locks out other * ACE servers * * Arguments in: * pw - struct passwd for username * promptp - UNUSED * auth - sudo authentication structure for SecurID handle * * Results out: * return code - Success if transaction started correctly, fatal * otherwise */ int securid_setup(pw, promptp, auth) struct passwd *pw; char **promptp; sudo_auth *auth; { SDI_HANDLE *sd = (SDI_HANDLE *) auth->data; int retval; /* Re-initialize SecurID every time. */ if (SD_Init(sd) != ACM_OK) { warningx("unable to contact the SecurID server"); return(AUTH_FATAL); } /* Lock new PIN code */ retval = SD_Lock(*sd, pw->pw_name); switch (retval) { case ACM_OK: warningx("User ID locked for SecurID Authentication"); return(AUTH_SUCCESS); case ACE_UNDEFINED_USERNAME: warningx("invalid username length for SecurID"); return(AUTH_FATAL); case ACE_ERR_INVALID_HANDLE: warningx("invalid Authentication Handle for SecurID"); return(AUTH_FATAL); case ACM_ACCESS_DENIED: warningx("SecurID communication failed"); return(AUTH_FATAL); default: warningx("unknown SecurID error"); return(AUTH_FATAL); } } /* * securid_verify - Authenticates user and handles ACE responses * * Arguments in: * pw - struct passwd for username * pass - UNUSED * auth - sudo authentication structure for SecurID handle * * Results out: * return code - Success on successful authentication, failure on * incorrect authentication, fatal on errors */ int securid_verify(pw, pass, auth) struct passwd *pw; char *pass; sudo_auth *auth; { SDI_HANDLE *sd = (SDI_HANDLE *) auth->data; int rval; pass = (char *) tgetpass("Enter your PASSCODE: ", def_passwd_timeout * 60, tgetpass_flags); /* Have ACE verify password */ switch (SD_Check(*sd, pass, pw->pw_name)) { case ACM_OK: rval = AUTH_SUCESS; break; case ACE_UNDEFINED_PASSCODE: warningx("invalid passcode length for SecurID"); rval = AUTH_FATAL; break; case ACE_UNDEFINED_USERNAME: warningx("invalid username length for SecurID"); rval = AUTH_FATAL; break; case ACE_ERR_INVALID_HANDLE: warningx("invalid Authentication Handle for SecurID"); rval = AUTH_FATAL; break; case ACM_ACCESS_DENIED: rval = AUTH_FAILURE; break; case ACM_NEXT_CODE_REQUIRED: /* Sometimes (when current token close to expire?) ACE challenges for the next token displayed (entered without the PIN) */ pass = (char *) tgetpass("\ !!! ATTENTION !!!\n\ Wait for the token code to change, \n\ then enter the new token code.\n", \ def_passwd_timeout * 60, tgetpass_flags); if (SD_Next(*sd, pass) == ACM_OK) { rval = AUTH_SUCCESS; break; } rval = AUTH_FAILURE; break; case ACM_NEW_PIN_REQUIRED: /* * This user's SecurID has not been activated yet, * or the pin has been reset */ /* XXX - Is setting up a new PIN within sudo's scope? */ SD_Pin(*sd, ""); fprintf(stderr, "Your SecurID access has not yet been set up.\n"); fprintf(stderr, "Please set up a PIN before you try to authenticate.\n"); rval = AUTH_FATAL; break; default: warningx("unknown SecurID error"); rval = AUTH_FATAL; break; } /* Free resources */ SD_Close(*sd); /* Return stored state to calling process */ return(rval); }