static void plain_global_init(void *pool, void *additional) { struct plain_cfg_st *config = additional; if (config == NULL) { fprintf(stderr, "plain: no configuration passed!\n"); exit(1); } #ifdef HAVE_LIBOATH oath_init(); #endif if (config->passwd) { password_file = talloc_strdup(pool, config->passwd); if (password_file == NULL) { fprintf(stderr, "plain: memory error\n"); exit(1); } } if (config->otp_file) { otp_file = talloc_strdup(pool, config->otp_file); if (otp_file == NULL) { fprintf(stderr, "plain: memory error\n"); exit(1); } } return; }
int main (void) { oath_rc rc; /* Check version. */ if (!oath_check_version (OATH_VERSION)) { printf ("oath_check_version (%s) failed [%s]\n", OATH_VERSION, oath_check_version (NULL)); return 1; } if (oath_check_version (NULL) == NULL) { printf ("oath_check_version (NULL) == NULL\n"); return 1; } if (oath_check_version ("999.999")) { printf ("oath_check_version (999.999) succeeded?!\n"); return 1; } /* Test initialization. */ rc = oath_init (); if (rc != OATH_OK) { printf ("oath_init: %d\n", rc); return 1; } /* Test deinitialization. */ rc = oath_done (); if (rc != OATH_OK) { printf ("oath_done: %d\n", rc); return 1; } return 0; }
int main (void) { oath_rc rc; char *hexsecret = "ABCDEF3435363738393031323334353637abcdef"; char secret[20]; size_t secretlen; if (!oath_check_version (OATH_VERSION)) { printf ("oath_check_version (%s) failed [%s]\n", OATH_VERSION, oath_check_version (NULL)); return 1; } if (oath_check_version (NULL) == NULL) { printf ("oath_check_version (NULL) == NULL\n"); return 1; } if (oath_check_version ("999.999")) { printf ("oath_check_version (999.999) succeeded?!\n"); return 1; } rc = oath_init (); if (rc != OATH_OK) { printf ("oath_init: %d\n", rc); return 1; } secretlen = 0; rc = oath_hex2bin (hexsecret, secret, &secretlen); if (rc != OATH_TOO_SMALL_BUFFER) { printf ("oath_hex2bin too small: %d\n", rc); return 1; } if (secretlen != 20) { printf ("oath_hex2bin too small: 20 != %d\n", secretlen); return 1; } rc = oath_hex2bin ("abcd", secret, &secretlen); if (rc != OATH_OK) { printf ("oath_hex2bin lower case failed: %d\n", rc); return 1; } rc = oath_hex2bin ("ABCD", secret, &secretlen); if (rc != OATH_OK) { printf ("oath_hex2bin upper case failed: %d\n", rc); return 1; } rc = oath_hex2bin ("ABC", secret, &secretlen); if (rc != OATH_INVALID_HEX) { printf ("oath_hex2bin too small failed: %d\n", rc); return 1; } rc = oath_hex2bin ("JUNK", secret, &secretlen); if (rc != OATH_INVALID_HEX) { printf ("oath_hex2bin junk failed: %d\n", rc); return 1; } secretlen = sizeof (secret); rc = oath_hex2bin (hexsecret, secret, &secretlen); if (rc != OATH_OK) { printf ("oath_hex2bin: %d\n", rc); return 1; } if (secretlen != 20) { printf ("oath_hex2bin: 20 != %d\n", secretlen); return 1; } if (memcmp (secret, "\xAB\xCD\xEF\x34\x35\x36\x37\x38\x39\x30" "\x31\x32\x33\x34\x35\x36\x37\xab\xcd\xef", 20) != 0) { printf ("oath_hex2bin: decode mismatch\n"); return 1; } rc = oath_done (); if (rc != OATH_OK) { printf ("oath_done: %d\n", rc); return 1; } return 0; }
int main (void) { oath_rc rc; time_t last_otp; struct stat ufstat1; struct stat ufstat2; if (!oath_check_version (OATH_VERSION)) { printf ("oath_check_version (%s) failed [%s]\n", OATH_VERSION, oath_check_version (NULL)); return 1; } rc = oath_init (); if (rc != OATH_OK) { printf ("oath_init: %s (%d)\n", oath_strerror_name (rc), rc); return 1; } rc = oath_authenticate_usersfile ("no-such-file", "joe", "755224", 0, "1234", &last_otp); if (rc != OATH_NO_SUCH_FILE) { printf ("oath_authenticate_usersfile[1]: %s (%d)\n", oath_strerror_name (rc), rc); return 1; } /* Record the current usersfile inode */ stat (CREDS, &ufstat1); rc = oath_authenticate_usersfile (CREDS, "joe", "755224", 0, "1234", &last_otp); if (rc != OATH_BAD_PASSWORD) { printf ("oath_authenticate_usersfile[2]: %s (%d)\n", oath_strerror_name (rc), rc); return 1; } /* Check that we do not update usersfile on not OATH_OK */ stat (CREDS, &ufstat2); if (ufstat1.st_ino != ufstat2.st_ino) { printf ("oath_authenticate_usersfile[26]: usersfile %s changed " "on OATH_BAD_PASSWORD\n", CREDS); return 1; } rc = oath_authenticate_usersfile (CREDS, "bob", "755224", 0, "1234", &last_otp); if (rc != OATH_BAD_PASSWORD) { printf ("oath_authenticate_usersfile[3]: %s (%d)\n", oath_strerror_name (rc), rc); return 1; } rc = oath_authenticate_usersfile (CREDS, "silver", "670691", 0, "4711", &last_otp); if (rc != OATH_OK) { printf ("oath_authenticate_usersfile[4]: %s (%d)\n", oath_strerror_name (rc), rc); return 1; } stat (CREDS, &ufstat2); if (ufstat1.st_ino == ufstat2.st_ino) { printf ("oath_authenticate_usersfile[27]: usersfile %s did not " "change on OATH_OK\n", CREDS); return 1; } rc = oath_authenticate_usersfile (CREDS, "silver", "599872", 1, "4711", &last_otp); if (rc != OATH_OK) { printf ("oath_authenticate_usersfile[5]: %s (%d)\n", oath_strerror_name (rc), rc); return 1; } rc = oath_authenticate_usersfile (CREDS, "silver", "072768", 1, "4711", &last_otp); if (rc != OATH_OK) { printf ("oath_authenticate_usersfile[6]: %s (%d)\n", oath_strerror_name (rc), rc); return 1; } stat (CREDS, &ufstat1); rc = oath_authenticate_usersfile (CREDS, "foo", "755224", 0, "8989", &last_otp); if (rc != OATH_REPLAYED_OTP) { printf ("oath_authenticate_usersfile[7]: %s (%d)\n", oath_strerror_name (rc), rc); return 1; } if (last_otp != 1260206742) { printf ("oath_authenticate_usersfile timestamp %ld != 1260203142\n", last_otp); return 1; } stat (CREDS, &ufstat2); if (ufstat1.st_ino != ufstat2.st_ino) { printf ("oath_authenticate_usersfile[28]: usersfile %s changed " "on OATH_REPLAYED_OTP\n", CREDS); return 1; } rc = oath_authenticate_usersfile (CREDS, "rms", "755224", 0, "4321", &last_otp); if (rc != OATH_BAD_PASSWORD) { printf ("oath_authenticate_usersfile[8]: %s (%d)\n", oath_strerror_name (rc), rc); return 1; } rc = oath_authenticate_usersfile (CREDS, "rms", "436521", 10, "6767", &last_otp); if (rc != OATH_OK) { printf ("oath_authenticate_usersfile[9]: %s (%d)\n", oath_strerror_name (rc), rc); return 1; } /* Run 'TZ=UTC oathtool --totp --now=2006-12-07 00 -w10' to generate: 963013 068866 734019 038980 630208 533058 042289 046988 047407 892423 619507 */ /* Test completely invalid OTP */ rc = oath_authenticate_usersfile (CREDS, "eve", "386397", 0, "4711", &last_otp); if (rc != OATH_BAD_PASSWORD) { printf ("oath_authenticate_usersfile[10]: %s (%d)\n", oath_strerror_name (rc), rc); return 1; } /* Test the next OTP but search window = 0. */ rc = oath_authenticate_usersfile (CREDS, "eve", "068866", 0, NULL, &last_otp); if (rc != OATH_INVALID_OTP) { printf ("oath_authenticate_usersfile[11]: %s (%d)\n", oath_strerror_name (rc), rc); return 1; } /* Test the next OTP with search window = 1. */ rc = oath_authenticate_usersfile (CREDS, "eve", "068866", 1, NULL, &last_otp); if (rc != OATH_OK) { printf ("oath_authenticate_usersfile[12]: %s (%d)\n", oath_strerror_name (rc), rc); return 1; } /* Test to replay last OTP. */ rc = oath_authenticate_usersfile (CREDS, "eve", "068866", 1, NULL, &last_otp); if (rc != OATH_REPLAYED_OTP) { printf ("oath_authenticate_usersfile[13]: %s (%d)\n", oath_strerror_name (rc), rc); return 1; } /* Test to replay previous OTP. */ rc = oath_authenticate_usersfile (CREDS, "eve", "963013", 1, NULL, &last_otp); if (rc != OATH_REPLAYED_OTP) { printf ("oath_authenticate_usersfile[14]: %s (%d)\n", oath_strerror_name (rc), rc); return 1; } /* Try an OTP in the future but outside search window. */ rc = oath_authenticate_usersfile (CREDS, "eve", "892423", 1, NULL, &last_otp); if (rc != OATH_INVALID_OTP) { printf ("oath_authenticate_usersfile[15]: %s (%d)\n", oath_strerror_name (rc), rc); return 1; } /* Try OTP in the future with good search window. */ rc = oath_authenticate_usersfile (CREDS, "eve", "892423", 10, NULL, &last_otp); if (rc != OATH_OK) { printf ("oath_authenticate_usersfile[16]: %s (%d)\n", oath_strerror_name (rc), rc); return 1; } /* Now try a rather old OTP within search window. */ rc = oath_authenticate_usersfile (CREDS, "eve", "630208", 10, NULL, &last_otp); if (rc != OATH_REPLAYED_OTP) { printf ("oath_authenticate_usersfile[17]: %s (%d)\n", oath_strerror_name (rc), rc); return 1; } /* Try OTP that matches user's second line. */ rc = oath_authenticate_usersfile (CREDS, "twouser", "874680", 10, NULL, &last_otp); if (rc != OATH_OK) { printf ("oath_authenticate_usersfile[18]: %s (%d)\n", oath_strerror_name (rc), rc); return 1; } /* Try OTP that matches user's third and final line. */ rc = oath_authenticate_usersfile (CREDS, "threeuser", "255509", 10, NULL, &last_otp); if (rc != OATH_OK) { printf ("oath_authenticate_usersfile[19]: %s (%d)\n", oath_strerror_name (rc), rc); return 1; } /* Try OTP that matches user's third and next-to-last line. */ rc = oath_authenticate_usersfile (CREDS, "fouruser", "663447", 10, NULL, &last_otp); if (rc != OATH_OK) { printf ("oath_authenticate_usersfile[19]: %s (%d)\n", oath_strerror_name (rc), rc); return 1; } /* Try incorrect OTP for user with five lines. */ rc = oath_authenticate_usersfile (CREDS, "fiveuser", "812658", 10, NULL, &last_otp); if (rc != OATH_INVALID_OTP) { printf ("oath_authenticate_usersfile[20]: %s (%d)\n", oath_strerror_name (rc), rc); return 1; } /* Try OTP that matches user's second line. */ rc = oath_authenticate_usersfile (CREDS, "fiveuser", "123001", 10, NULL, &last_otp); if (rc != OATH_OK) { printf ("oath_authenticate_usersfile[21]: %s (%d)\n", oath_strerror_name (rc), rc); return 1; } /* Try OTP that matches user's fourth line. */ rc = oath_authenticate_usersfile (CREDS, "fiveuser", "893841", 10, NULL, &last_otp); if (rc != OATH_OK) { printf ("oath_authenticate_usersfile[22]: %s (%d)\n", oath_strerror_name (rc), rc); return 1; } /* Try another OTP that matches user's second line. */ rc = oath_authenticate_usersfile (CREDS, "fiveuser", "746888", 10, NULL, &last_otp); if (rc != OATH_OK) { printf ("oath_authenticate_usersfile[23]: %s (%d)\n", oath_strerror_name (rc), rc); return 1; } /* Try another OTP that matches user's fifth line. */ rc = oath_authenticate_usersfile (CREDS, "fiveuser", "730790", 10, NULL, &last_otp); if (rc != OATH_OK) { printf ("oath_authenticate_usersfile[24]: %s (%d)\n", oath_strerror_name (rc), rc); return 1; } /* Try too old OTP for user's second line. */ rc = oath_authenticate_usersfile (CREDS, "fiveuser", "692901", 10, NULL, &last_otp); if (rc != OATH_INVALID_OTP) { printf ("oath_authenticate_usersfile[25]: %s (%d)\n", oath_strerror_name (rc), rc); return 1; } /* Test password field of + */ rc = oath_authenticate_usersfile (CREDS, "plus", "328482", 1, "4711", &last_otp); if (rc != OATH_OK) { printf ("oath_authenticate_usersfile[26]: %s (%d)\n", oath_strerror_name (rc), rc); return 1; } rc = oath_authenticate_usersfile (CREDS, "plus", "812658", 1, "4712", &last_otp); if (rc != OATH_OK) { printf ("oath_authenticate_usersfile[27]: %s (%d)\n", oath_strerror_name (rc), rc); return 1; } /* Test different tokens with different passwords for one user */ rc = oath_authenticate_usersfile (CREDS, "password", "898463", 5, NULL, &last_otp); if (rc != OATH_OK) { printf ("oath_authenticate_usersfile[28]: %s (%d)\n", oath_strerror_name (rc), rc); return 1; } rc = oath_authenticate_usersfile (CREDS, "password", "989803", 5, "test", &last_otp); if (rc != OATH_OK) { printf ("oath_authenticate_usersfile[29]: %s (%d)\n", oath_strerror_name (rc), rc); return 1; } rc = oath_authenticate_usersfile (CREDS, "password", "427517", 5, "darn", &last_otp); if (rc != OATH_OK) { printf ("oath_authenticate_usersfile[30]: %s (%d)\n", oath_strerror_name (rc), rc); return 1; } /* Valid OTP for first token but incorrect password. */ rc = oath_authenticate_usersfile (CREDS, "password", "917625", 5, "nope", &last_otp); if (rc != OATH_BAD_PASSWORD) { printf ("oath_authenticate_usersfile[31]: %s (%d)\n", oath_strerror_name (rc), rc); return 1; } /* Valid OTP for second token but incorrect password. */ rc = oath_authenticate_usersfile (CREDS, "password", "459145", 5, "nope", &last_otp); if (rc != OATH_BAD_PASSWORD) { printf ("oath_authenticate_usersfile[32]: %s (%d)\n", oath_strerror_name (rc), rc); return 1; } /* Valid OTP for first token but with password for second user. */ rc = oath_authenticate_usersfile (CREDS, "password", "917625", 5, "test", &last_otp); if (rc != OATH_BAD_PASSWORD) { printf ("oath_authenticate_usersfile[33]: %s (%d)\n", oath_strerror_name (rc), rc); return 1; } /* Valid OTP for second token but with password for first user. */ rc = oath_authenticate_usersfile (CREDS, "password", "459145", 5, "", &last_otp); if (rc != OATH_BAD_PASSWORD) { printf ("oath_authenticate_usersfile[34]: %s (%d)\n", oath_strerror_name (rc), rc); return 1; } /* Valid OTP for third token but with password for second user. */ rc = oath_authenticate_usersfile (CREDS, "password", "633070", 9, "test", &last_otp); if (rc != OATH_BAD_PASSWORD) { printf ("oath_authenticate_usersfile[35]: %s (%d)\n", oath_strerror_name (rc), rc); return 1; } rc = oath_done (); if (rc != OATH_OK) { printf ("oath_done: %s (%d)\n", oath_strerror_name (rc), rc); return 1; } return 0; }
int main (void) { oath_rc rc; char nulls[1] = "\x00"; char secret[32] = "\x31\x32\x33\x34\x35\x36\x37\x38\x39\x30" "\x31\x32\x33\x34\x35\x36\x37\x38\x39\x30" "\x31\x32\x33\x34\x35\x36\x37\x38\x39\x30\x31\x32"; size_t secretlen = 20; char otp[10]; uint64_t moving_factor; unsigned digits; rc = oath_init (); if (rc != OATH_OK) { printf ("oath_init: %d\n", rc); return 1; } moving_factor = 1099511627776ULL; rc = oath_hotp_generate (nulls, 1, moving_factor, 6, false, OATH_HOTP_DYNAMIC_TRUNCATION, otp); if (rc != OATH_OK) { printf ("oath_hotp_generate %llu: %d\n", (long long unsigned) moving_factor, rc); return 1; } if (strcmp ("363425", otp) != 0) { printf ("oath_hotp_generate got otp %s\n", otp); return 1; } for (digits = 6; digits <= 8; digits++) for (moving_factor = 0; moving_factor < MAX_ITER; moving_factor++) { rc = oath_hotp_generate (secret, secretlen, moving_factor, digits, false, OATH_HOTP_DYNAMIC_TRUNCATION, otp); if (rc != OATH_OK) { printf ("oath_hotp_generate: %d\n", rc); return 1; } #if DEBUG printf ("otp[%d]: %s\n", (unsigned) moving_factor, otp); #endif if (!expect[digits][moving_factor]) { printf ("no test vector for digits %d counter %ld\n", digits, (long) moving_factor); return 1; } if (strcmp (otp, expect[digits][moving_factor]) != 0) { printf ("otp[%d][%ld] got %s expected %s\n", digits, (long) moving_factor, otp, expect[digits][moving_factor]); return 1; } rc = oath_hotp_generate (secret, 32, moving_factor, digits, false, OATH_HOTP_DYNAMIC_TRUNCATION, otp); if (rc != OATH_OK) { printf ("oath_hotp_generate: %d\n", rc); return 1; } } for (digits = 0; digits < 6; digits++) { rc = oath_hotp_generate (secret, secretlen, moving_factor, digits, false, OATH_HOTP_DYNAMIC_TRUNCATION, otp); if (rc != OATH_INVALID_DIGITS) { printf ("oath_hotp_generate %d digits %d\n", digits, rc); return 1; } } for (digits = 9; digits < 15; digits++) { rc = oath_hotp_generate (secret, secretlen, moving_factor, digits, false, OATH_HOTP_DYNAMIC_TRUNCATION, otp); if (rc != OATH_INVALID_DIGITS) { printf ("oath_hotp_generate %d digits %d\n", digits, rc); return 1; } } rc = oath_done (); if (rc != OATH_OK) { printf ("oath_done: %d\n", rc); return 1; } return 0; }
int main() { gfxInitDefault(); consoleInit(GFX_BOTTOM, NULL); printf("%s %s by %s\n", APP_TITLE, APP_VERSION, APP_AUTHOR); printf("Build date: %s %s\n\n", __DATE__, __TIME__); //printf("Current time: %d\n\n", (int)time(NULL)); printf("Calculating time difference from UTC... make sure you are connected to the Internet. "); Result InitClockOffsetResult = InitializeClockOffset(); if (!InitClockOffsetResult) { printf("Error initializing time offset: %08x", InitClockOffsetResult); return 1; } printf("OK\n"); int ret = oath_init(); if(ret != OATH_OK) { printf("Error initializing liboath: %s\n", oath_strerror(ret)); return 1; } char encoded_secret[1024]; FILE *secretFile; signed short secretTxtDecLength; if((secretFile = fopen("secret.txt", "r")) == NULL) { printf("warning: Secret.txt not found in application directory (SD root if installed as CIA)"); /*while(aptMainLoop()) { gspWaitForVBlank(); hidScanInput(); unsigned long kDown = hidKeysDown(); if(kDown & KEY_A) break; gfxFlushBuffers(); gfxSwapBuffers(); } return 1;*/ }else{ printf("Opened secret.txt\n"); fscanf(secretFile, "%[^\n]", encoded_secret); fclose(secretFile); if(strlen(encoded_secret) < 1){ printf("warning: secret.txt exists but is empty.\n"); }else{ printf("Read secret.txt: %s\n", encoded_secret); ret = oath_base32_decode(&encoded_secret, strlen(&encoded_secret), NULL, &secretTxtDecLength); if(ret != OATH_OK) { printf("Error decoding secret.txt: %s\n", oath_strerror(ret)); memset(&encoded_secret[0], 0, sizeof(encoded_secret)); // wipe the copy we have in memory, to avoid prefilling the swkbd with undecodable stuff }else{ printf("Read secret.txt successfully."); } } } char inputSecret[1024]; bool quit = false; bool ask = false; printf("Press A to begin, or start to exit.\n\n"); // Main loop while (aptMainLoop()) { gspWaitForVBlank(); hidScanInput(); unsigned long kDown = hidKeysDown(); if (kDown & KEY_A) ask = true; if(ask && !quit) { static SwkbdState swkbd; static SwkbdStatusData swkbdStatus; SwkbdButton button = SWKBD_BUTTON_NONE; swkbdInit(&swkbd, SWKBD_TYPE_WESTERN, 2, 512); swkbdSetHintText(&swkbd, "Enter your TOTP secret."); swkbdSetButton(&swkbd, SWKBD_BUTTON_LEFT, "Quit", false); swkbdSetButton(&swkbd, SWKBD_BUTTON_MIDDLE, "Load txt", true); swkbdSetButton(&swkbd, SWKBD_BUTTON_RIGHT, "Go", true); swkbdSetInitialText(&swkbd, inputSecret); swkbdSetFeatures(&swkbd, SWKBD_DEFAULT_QWERTY); swkbdSetFilterCallback(&swkbd, swkbdCallbackThing, NULL); swkbdInputText(&swkbd, inputSecret, sizeof(inputSecret)); switch(button) { case SWKBD_BUTTON_LEFT: // quit quit = true; break; case SWKBD_BUTTON_MIDDLE: // read secret.txt strcpy(inputSecret, encoded_secret); break; case SWKBD_BUTTON_RIGHT: // go (this is handled in filter callback) break; default: break; } if(quit) break; // quit to HBL } if (kDown & KEY_START) { break; // break in order to return to hbmenu } // Flush and swap framebuffers gfxFlushBuffers(); gfxSwapBuffers(); } gfxExit(); return 0; }
PAM_EXTERN int pam_sm_authenticate (pam_handle_t * pamh, int flags, int argc, const char **argv) { int retval, rc; const char *user = NULL; const char *password = NULL; char otp[MAX_OTP_LEN + 1]; int password_len = 0; struct pam_conv *conv; struct pam_message *pmsg[1], msg[1]; struct pam_response *resp; int nargs = 1; struct cfg cfg; char *query_prompt = NULL; char *onlypasswd = strdup (""); /* empty passwords never match */ parse_cfg (flags, argc, argv, &cfg); retval = pam_get_user (pamh, &user, NULL); if (retval != PAM_SUCCESS) { DBG (("get user returned error: %s", pam_strerror (pamh, retval))); goto done; } DBG (("get user returned: %s", user)); if (cfg.try_first_pass || cfg.use_first_pass) { retval = pam_get_item (pamh, PAM_AUTHTOK, (const void **) &password); if (retval != PAM_SUCCESS) { DBG (("get password returned error: %s", pam_strerror (pamh, retval))); goto done; } DBG (("get password returned: %s", password)); } if (cfg.use_first_pass && password == NULL) { DBG (("use_first_pass set and no password, giving up")); retval = PAM_AUTH_ERR; goto done; } rc = oath_init (); if (rc != OATH_OK) { DBG (("oath_init() failed (%d)", rc)); retval = PAM_AUTHINFO_UNAVAIL; goto done; } if (password == NULL) { retval = pam_get_item (pamh, PAM_CONV, (const void **) &conv); if (retval != PAM_SUCCESS) { DBG (("get conv returned error: %s", pam_strerror (pamh, retval))); goto done; } pmsg[0] = &msg[0]; { const char *query_template = "One-time password (OATH) for `%s': "; size_t len = strlen (query_template) + strlen (user); size_t wrote; query_prompt = malloc (len); if (!query_prompt) { retval = PAM_BUF_ERR; goto done; } wrote = snprintf (query_prompt, len, query_template, user); if (wrote < 0 || wrote >= len) { retval = PAM_BUF_ERR; goto done; } msg[0].msg = query_prompt; } msg[0].msg_style = PAM_PROMPT_ECHO_OFF; resp = NULL; retval = conv->conv (nargs, (const struct pam_message **) pmsg, &resp, conv->appdata_ptr); free (query_prompt); query_prompt = NULL; if (retval != PAM_SUCCESS) { DBG (("conv returned error: %s", pam_strerror (pamh, retval))); goto done; } DBG (("conv returned: %s", resp->resp)); password = resp->resp; } if (password) password_len = strlen (password); else { DBG (("Could not read password")); retval = PAM_AUTH_ERR; goto done; } if (password_len < MIN_OTP_LEN) { DBG (("OTP too short: %s", password)); retval = PAM_AUTH_ERR; goto done; } else if (cfg.digits != 0 && password_len < cfg.digits) { DBG (("OTP shorter than digits=%d: %s", cfg.digits, password)); retval = PAM_AUTH_ERR; goto done; } else if (cfg.digits == 0 && password_len > MAX_OTP_LEN) { DBG (("OTP too long (and no digits=): %s", password)); retval = PAM_AUTH_ERR; goto done; } else if (cfg.digits != 0 && password_len > cfg.digits) { free (onlypasswd); onlypasswd = strdup (password); /* user entered their system password followed by generated OTP? */ onlypasswd[password_len - cfg.digits] = '\0'; DBG (("Password: %s ", onlypasswd)); memcpy (otp, password + password_len - cfg.digits, cfg.digits); otp[cfg.digits] = '\0'; retval = pam_set_item (pamh, PAM_AUTHTOK, onlypasswd); if (retval != PAM_SUCCESS) { DBG (("set_item returned error: %s", pam_strerror (pamh, retval))); goto done; } } else { strcpy (otp, password); password = NULL; } DBG (("OTP: %s", otp ? otp : "(null)")); { time_t last_otp; rc = oath_authenticate_usersfile (cfg.usersfile, user, otp, cfg.window, onlypasswd, &last_otp); DBG (("authenticate rc %d (%s: %s) last otp %s", rc, oath_strerror_name (rc) ? oath_strerror_name (rc) : "UNKNOWN", oath_strerror (rc), ctime (&last_otp))); } if (rc != OATH_OK) { DBG (("One-time password not authorized to login as user '%s'", user)); retval = PAM_AUTH_ERR; goto done; } retval = PAM_SUCCESS; done: oath_done (); free (query_prompt); free (onlypasswd); if (cfg.alwaysok && retval != PAM_SUCCESS) { DBG (("alwaysok needed (otherwise return with %d)", retval)); retval = PAM_SUCCESS; } DBG (("done. [%s]", pam_strerror (pamh, retval))); return retval; }
int main (int argc, char *argv[]) { struct gengetopt_args_info args_info; char *secret; size_t secretlen = 0; int rc; size_t window; uint64_t moving_factor; unsigned digits; char otp[10]; time_t now, when, t0, time_step_size; int totpflags = 0; set_program_name (argv[0]); if (cmdline_parser (argc, argv, &args_info) != 0) return EXIT_FAILURE; if (args_info.version_given) { char *p; int l = -1; if (strcmp (oath_check_version (NULL), OATH_VERSION) != 0) l = asprintf (&p, "OATH Toolkit liboath.so %s oath.h %s", oath_check_version (NULL), OATH_VERSION); else if (strcmp (OATH_VERSION, PACKAGE_VERSION) != 0) l = asprintf (&p, "OATH Toolkit %s", oath_check_version (NULL), OATH_VERSION); version_etc (stdout, "oathtool", l == -1 ? "OATH Toolkit" : p, PACKAGE_VERSION, "Simon Josefsson", (char *) NULL); if (l != -1) free (p); return EXIT_SUCCESS; } if (args_info.help_given) usage (EXIT_SUCCESS); if (args_info.inputs_num == 0) { cmdline_parser_print_help (); emit_bug_reporting_address (); return EXIT_SUCCESS; } rc = oath_init (); if (rc != OATH_OK) error (EXIT_FAILURE, 0, "liboath initialization failed: %s", oath_strerror (rc)); if (args_info.base32_flag) { rc = oath_base32_decode (args_info.inputs[0], strlen (args_info.inputs[0]), &secret, &secretlen); if (rc != OATH_OK) error (EXIT_FAILURE, 0, "base32 decoding failed: %s", oath_strerror (rc)); } else { secretlen = 1 + strlen (args_info.inputs[0]) / 2; secret = malloc (secretlen); if (!secret) error (EXIT_FAILURE, errno, "malloc"); rc = oath_hex2bin (args_info.inputs[0], secret, &secretlen); if (rc != OATH_OK) error (EXIT_FAILURE, 0, "hex decoding of secret key failed"); } if (args_info.counter_orig) moving_factor = args_info.counter_arg; else moving_factor = 0; if (args_info.digits_orig) digits = args_info.digits_arg; else digits = 6; if (args_info.window_orig) window = args_info.window_arg; else window = 0; if (digits != 6 && digits != 7 && digits != 8) error (EXIT_FAILURE, 0, "only digits 6, 7 and 8 are supported"); if (validate_otp_p (args_info.inputs_num) && !args_info.digits_orig) digits = strlen (args_info.inputs[1]); else if (validate_otp_p (args_info.inputs_num) && args_info.digits_orig && args_info.digits_arg != strlen (args_info.inputs[1])) error (EXIT_FAILURE, 0, "given one-time password has bad length %d != %ld", args_info.digits_arg, strlen (args_info.inputs[1])); if (args_info.inputs_num > 2) error (EXIT_FAILURE, 0, "too many parameters"); if (args_info.verbose_flag) { char *tmp; tmp = malloc (2 * secretlen + 1); if (!tmp) error (EXIT_FAILURE, errno, "malloc"); oath_bin2hex (secret, secretlen, tmp); printf ("Hex secret: %s\n", tmp); free (tmp); rc = oath_base32_encode (secret, secretlen, &tmp, NULL); if (rc != OATH_OK) error (EXIT_FAILURE, 0, "base32 encoding failed: %s", oath_strerror (rc)); printf ("Base32 secret: %s\n", tmp); free (tmp); if (args_info.inputs_num == 2) printf ("OTP: %s\n", args_info.inputs[1]); printf ("Digits: %d\n", digits); printf ("Window size: %ld\n", window); } if (args_info.totp_given) { now = time (NULL); when = parse_time (args_info.now_arg, now); t0 = parse_time (args_info.start_time_arg, now); time_step_size = parse_duration (args_info.time_step_size_arg); if (when == BAD_TIME) error (EXIT_FAILURE, 0, "cannot parse time `%s'", args_info.now_arg); if (t0 == BAD_TIME) error (EXIT_FAILURE, 0, "cannot parse time `%s'", args_info.start_time_arg); if (time_step_size == BAD_TIME) error (EXIT_FAILURE, 0, "cannot parse time `%s'", args_info.time_step_size_arg); if (strcmp (args_info.totp_arg, "sha256") == 0) totpflags = OATH_TOTP_HMAC_SHA256; else if (strcmp (args_info.totp_arg, "sha512") == 0) totpflags = OATH_TOTP_HMAC_SHA512; if (args_info.verbose_flag) verbose_totp (t0, time_step_size, when); } else { if (args_info.verbose_flag) verbose_hotp (moving_factor); } if (generate_otp_p (args_info.inputs_num) && !args_info.totp_given) { size_t iter = 0; do { rc = oath_hotp_generate (secret, secretlen, moving_factor + iter, digits, false, OATH_HOTP_DYNAMIC_TRUNCATION, otp); if (rc != OATH_OK) error (EXIT_FAILURE, 0, "generating one-time password failed (%d)", rc); printf ("%s\n", otp); } while (window - iter++ > 0); } else if (generate_otp_p (args_info.inputs_num) && args_info.totp_given) { size_t iter = 0; do { rc = oath_totp_generate2 (secret, secretlen, when + iter * time_step_size, time_step_size, t0, digits, totpflags, otp); if (rc != OATH_OK) error (EXIT_FAILURE, 0, "generating one-time password failed (%d)", rc); printf ("%s\n", otp); } while (window - iter++ > 0); } else if (validate_otp_p (args_info.inputs_num) && !args_info.totp_given) { rc = oath_hotp_validate (secret, secretlen, moving_factor, window, args_info.inputs[1]); if (rc == OATH_INVALID_OTP) error (EXIT_OTP_INVALID, 0, "password \"%s\" not found in range %ld .. %ld", args_info.inputs[1], (long) moving_factor, (long) moving_factor + window); else if (rc < 0) error (EXIT_FAILURE, 0, "validating one-time password failed (%d)", rc); printf ("%d\n", rc); } else if (validate_otp_p (args_info.inputs_num) && args_info.totp_given) { rc = oath_totp_validate4 (secret, secretlen, when, time_step_size, t0, window, NULL, NULL, totpflags, args_info.inputs[1]); if (rc == OATH_INVALID_OTP) error (EXIT_OTP_INVALID, 0, "password \"%s\" not found in range %ld .. %ld", args_info.inputs[1], (long) ((when - t0) / time_step_size - window / 2), (long) ((when - t0) / time_step_size + window / 2)); else if (rc < 0) error (EXIT_FAILURE, 0, "validating one-time password failed (%d)", rc); printf ("%d\n", rc); } free (secret); oath_done (); return EXIT_SUCCESS; }
/* * Initialise a HOTP authentication stack. * */ dynalogin_result_t dynalogin_init(dynalogin_session_t **session, apr_pool_t *pool, apr_hash_t *config) { apr_status_t ret; dynalogin_session_t *h; char *ds_module_name; char *ds_module_filename; char *ds_sym_name; *session = NULL; if(oath_init() != OATH_OK) { ERRMSG("libhotp init failed"); return DYNALOGIN_ERROR; } if(pool == NULL) { return DYNALOGIN_ERROR; } /* pool is not required, APR will create a root pool if it * is NULL. * Maybe we don't need a config and can run on defaults? */ if(config == NULL) { ERRMSG("no config"); return DYNALOGIN_ERROR; } if((h = (dynalogin_session_t *)apr_pcalloc(pool, sizeof(dynalogin_session_t))) == NULL) return DYNALOGIN_ERROR; h->pool = pool; syslog(LOG_DEBUG, "looking in %s for modules", PKGLIBDIR); GET_STRING_PARAM(ds_module_name, config, DYNALOGIN_PARAM_DSNAME) ds_module_filename = apr_psprintf(h->pool, "%s%c%s.so", PKGLIBDIR, DIR_SEPARATOR, ds_module_name); ds_sym_name = apr_psprintf(h->pool, "%s_module", ds_module_name); if(ds_module_filename==NULL || ds_sym_name==NULL) return DYNALOGIN_ERROR; if(apr_dso_load(&h->dso_handle, ds_module_filename, h->pool)!=APR_SUCCESS) return DYNALOGIN_ERROR; if(apr_dso_sym((apr_dso_handle_sym_t *)&(h->datasource), h->dso_handle, ds_sym_name) !=APR_SUCCESS) { apr_dso_unload(h->dso_handle); return DYNALOGIN_ERROR; } if(h->datasource->init != NULL) if(h->datasource->init(h->pool, config) != DYNALOGIN_SUCCESS) { apr_dso_unload(h->dso_handle); return DYNALOGIN_ERROR; } GET_INT_PARAM_DEF(h->hotp_digits, config, DYNALOGIN_PARAM_HOTP_DIGITS, DEFAULT_HOTP_DIGITS) GET_INT_PARAM_DEF(h->hotp_window, config, DYNALOGIN_PARAM_HOTP_WINDOW, DEFAULT_HOTP_WINDOW) GET_INT_PARAM_DEF(h->totp_digits, config, DYNALOGIN_PARAM_TOTP_DIGITS, DEFAULT_TOTP_DIGITS) GET_INT_PARAM_DEF(h->totp_window, config, DYNALOGIN_PARAM_TOTP_WINDOW, DEFAULT_TOTP_WINDOW) GET_INT_PARAM_DEF(h->totp_x, config, DYNALOGIN_PARAM_TOTP_X, DEFAULT_TOTP_X) GET_INT_PARAM_DEF(h->totp_t0, config, DYNALOGIN_PARAM_TOTP_T0, DEFAULT_TOTP_T0) *session = h; return DYNALOGIN_SUCCESS; }