int main(int argc, char **argv) { YK_KEY *yk = NULL; bool error = true; int exit_code = 0; /* Options */ bool verbose = false; char *action = ACTION_ADD_HMAC_CHALRESP; int slot = 1; ykp_errno = 0; yk_errno = 0; if (! parse_args(argc, argv, &slot, &verbose, &action, &exit_code)) goto err; exit_code = 1; if (! strcmp(action, ACTION_ADD_HMAC_CHALRESP)) { /* * Set up challenge-response login authentication */ if (! init_yubikey (&yk)) goto err; if (! check_firmware_version(yk, verbose, false)) goto err; if (! do_add_hmac_chalresp (yk, slot, verbose, NULL, &exit_code)) goto err; } else { fprintf (stderr, "Unknown action '%s'\n", action); goto err; } exit_code = 0; error = false; err: if (error || exit_code != 0) { report_yk_error (); } if (yk && !yk_close_key (yk)) { report_yk_error (); exit_code = 2; } if (!yk_release ()) { report_yk_error (); exit_code = 2; } exit (exit_code); }
int main(int argc, char **argv) { YK_KEY *yk = NULL; bool error = true; int exit_code = 0; /* Options */ bool verbose = false; char action[ACTION_MAX_LEN]; char *ptr = action; char *output_dir = NULL; int slot = 1; unsigned int iterations = CR_DEFAULT_ITERATIONS; ykp_errno = 0; yk_errno = 0; strcpy (action, ACTION_ADD_HMAC_CHALRESP); if (! parse_args(argc, argv, &slot, &verbose, &ptr, &output_dir, &iterations)) goto err; exit_code = 1; if (! strncmp(action, ACTION_ADD_HMAC_CHALRESP, ACTION_MAX_LEN)) { /* * Set up challenge-response login authentication */ if (! init_yubikey (&yk)) goto err; if (! check_firmware_version(yk, verbose, false)) goto err; if (! do_add_hmac_chalresp (yk, slot, verbose, output_dir, iterations, &exit_code)) goto err; } else { fprintf (stderr, "Unknown action '%s'\n", action); goto err; } exit_code = 0; error = false; err: if (error || exit_code != 0) { report_yk_error (); } if (yk && !yk_close_key (yk)) { report_yk_error (); exit_code = 2; } if (!yk_release ()) { report_yk_error (); exit_code = 2; } exit (exit_code); }
int main(int argc, char* argv[], char* envp[]){ // arguments sanity check if (argc != 3 || strlen(argv[1]) < 1 || strlen(argv[2]) < 1) { printf("Usage %s [DEVICENAME] [NAME]\n", argv[0]); return EXIT_FAILURE; } // check for root if(geteuid()) { printf("luks requires super user privileges.\n"); return EXIT_FAILURE; } YK_KEY *yk; char *password; unsigned int password_len; unsigned int retry_counter = 0; query_credentials: // TODO: check if call on already initialized structure is safe // initialize yubikey while (!init_yubikey(&yk)) { sleep(1); } // query password password_len = -1; password = getpass("Enter FDE password: "******"Could not unlock device with provided credentials, please try again\n"); // failed to unlock device, retry to query password memset(password, 0, strlen(password)); if (retry_counter < MAX_RETRIES) { retry_counter++; goto query_credentials; } } memset(password, 0, strlen(password)); free(password); return EXIT_SUCCESS; }
static int do_challenge_response(pam_handle_t *pamh, struct cfg *cfg, const char *username) { char *userfile = NULL, *tmpfile = NULL; FILE *f = NULL; unsigned char buf[CR_RESPONSE_SIZE + 16], response_hex[CR_RESPONSE_SIZE * 2 + 1]; int ret; unsigned int flags = 0; unsigned int response_len = 0; unsigned int expect_bytes = 0; YK_KEY *yk = NULL; CR_STATE state; int len; char *errstr = NULL; ret = PAM_AUTH_ERR; flags |= YK_FLAG_MAYBLOCK; if (! init_yubikey(&yk)) { D(("Failed initializing YubiKey")); goto out; } if (! check_firmware_version(yk, false, true)) { D(("YubiKey does not support Challenge-Response (version 2.2 required)")); goto out; } if (! get_user_challenge_file (yk, cfg->chalresp_path, username, &userfile)) { D(("Failed getting user challenge file for user %s", username)); goto out; } DBG(("Loading challenge from file %s", userfile)); /* XXX should drop root privileges before opening file in user's home directory */ f = fopen(userfile, "r"); if (! load_chalresp_state(f, &state)) goto out; if (fclose(f) < 0) { f = NULL; goto out; } if (! challenge_response(yk, state.slot, state.challenge, state.challenge_len, true, flags, false, buf, sizeof(buf), &response_len)) { D(("Challenge-response FAILED")); goto out; } /* * Check YubiKey response against the expected response */ yubikey_hex_encode(response_hex, (char *)buf, response_len); if (memcmp(buf, state.response, response_len) == 0) { ret = PAM_SUCCESS; } else { D(("Unexpected C/R response : %s", response_hex)); goto out; } DBG(("Got the expected response, generating new challenge (%i bytes).", CR_CHALLENGE_SIZE)); errstr = "Error generating new challenge, please check syslog or contact your system administrator"; if (generate_random(state.challenge, sizeof(state.challenge))) { D(("Failed generating new challenge!")); goto out; } errstr = "Error communicating with Yubikey, please check syslog or contact your system administrator"; if (! challenge_response(yk, state.slot, state.challenge, CR_CHALLENGE_SIZE, true, flags, false, buf, sizeof(buf), &response_len)) { D(("Second challenge-response FAILED")); goto out; } /* the yk_* functions leave 'junk' in errno */ errno = 0; /* * Write the challenge and response we will expect the next time to the state file. */ if (response_len > sizeof(state.response)) { D(("Got too long response ??? (%i/%i)", response_len, sizeof(state.response))); goto out; } memcpy (state.response, buf, response_len); state.response_len = response_len; /* Write out the new file */ tmpfile = malloc(strlen(userfile) + 1 + 4); if (! tmpfile) goto out; strcpy(tmpfile, userfile); strcat(tmpfile, ".tmp"); f = fopen(tmpfile, "w"); if (! f) goto out; errstr = "Error updating Yubikey challenge, please check syslog or contact your system administrator"; if (! write_chalresp_state (f, &state)) goto out; if (fclose(f) < 0) { f = NULL; goto out; } f = NULL; if (rename(tmpfile, userfile) < 0) { goto out; } DBG(("Challenge-response success!")); errstr = NULL; out: if (yk_errno) { if (yk_errno == YK_EUSBERR) { syslog(LOG_ERR, "USB error: %s", yk_usb_strerror()); D(("USB error: %s", yk_usb_strerror())); } else { syslog(LOG_ERR, "Yubikey core error: %s", yk_strerror(yk_errno)); D(("Yubikey core error: %s", yk_strerror(yk_errno))); } } if (errstr) display_error(pamh, errstr); if (errno) { syslog(LOG_ERR, "Challenge response failed: %s", strerror(errno)); D(("Challenge response failed: %s", strerror(errno))); } if (yk) yk_close_key(yk); yk_release(); if (f) fclose(f); free(userfile); free(tmpfile); return ret; }
static int do_challenge_response(pam_handle_t *pamh, struct cfg *cfg, const char *username) { char *userfile = NULL, *tmpfile = NULL; FILE *f = NULL; char buf[CR_RESPONSE_SIZE + 16], response_hex[CR_RESPONSE_SIZE * 2 + 1]; int ret, fd; unsigned int flags = 0; unsigned int response_len = 0; YK_KEY *yk = NULL; CR_STATE state; char *errstr = NULL; struct passwd *p; struct stat st; ret = PAM_AUTH_ERR; flags |= YK_FLAG_MAYBLOCK; if (! init_yubikey(&yk)) { D(("Failed initializing YubiKey")); goto out; } if (! check_firmware_version(yk, false, true)) { D(("YubiKey does not support Challenge-Response (version 2.2 required)")); goto out; } if (! get_user_challenge_file (yk, cfg->chalresp_path, username, &userfile)) { D(("Failed getting user challenge file for user %s", username)); goto out; } DBG(("Loading challenge from file %s", userfile)); p = getpwnam (username); if (p == NULL) { DBG (("getpwnam: %s", strerror(errno))); goto out; } /* Drop privileges before opening user file. */ if (drop_privileges(p, pamh) < 0) { D (("could not drop privileges")); goto out; } fd = open(userfile, O_RDONLY, 0); if (fd < 0) { DBG (("Cannot open file: %s (%s)", userfile, strerror(errno))); goto out; } if (fstat(fd, &st) < 0) { DBG (("Cannot stat file: %s (%s)", userfile, strerror(errno))); close(fd); goto out; } if (!S_ISREG(st.st_mode)) { DBG (("%s is not a regular file", userfile)); close(fd); goto out; } f = fdopen(fd, "r"); if (f == NULL) { DBG (("fdopen: %s", strerror(errno))); close(fd); goto out; } if (! load_chalresp_state(f, &state, cfg->debug)) goto out; if (fclose(f) < 0) { f = NULL; goto out; } f = NULL; if (restore_privileges(pamh) < 0) { DBG (("could not restore privileges")); goto out; } if (! challenge_response(yk, state.slot, state.challenge, state.challenge_len, true, flags, false, buf, sizeof(buf), &response_len)) { D(("Challenge-response FAILED")); goto out; } /* * Check YubiKey response against the expected response */ yubikey_hex_encode(response_hex, buf, response_len); if (memcmp(buf, state.response, response_len) == 0) { ret = PAM_SUCCESS; } else { D(("Unexpected C/R response : %s", response_hex)); goto out; } DBG(("Got the expected response, generating new challenge (%i bytes).", CR_CHALLENGE_SIZE)); errstr = "Error generating new challenge, please check syslog or contact your system administrator"; if (generate_random(state.challenge, sizeof(state.challenge))) { D(("Failed generating new challenge!")); goto out; } errstr = "Error communicating with Yubikey, please check syslog or contact your system administrator"; if (! challenge_response(yk, state.slot, state.challenge, CR_CHALLENGE_SIZE, true, flags, false, buf, sizeof(buf), &response_len)) { D(("Second challenge-response FAILED")); goto out; } /* There is a bug that makes the YubiKey 2.2 send the same response for all challenges unless HMAC_LT64 is set, check for that here */ if (memcmp(buf, state.response, response_len) == 0) { errstr = "Same response for second challenge, YubiKey should be reconfigured with the option HMAC_LT64"; goto out; } /* the yk_* functions leave 'junk' in errno */ errno = 0; /* * Write the challenge and response we will expect the next time to the state file. */ if (response_len > sizeof(state.response)) { D(("Got too long response ??? (%u/%lu)", response_len, (unsigned long) sizeof(state.response))); goto out; } memcpy (state.response, buf, response_len); state.response_len = response_len; /* Drop privileges before creating new challenge file. */ if (drop_privileges(p, pamh) < 0) { D (("could not drop privileges")); goto out; } /* Write out the new file */ tmpfile = malloc(strlen(userfile) + 1 + 4); if (! tmpfile) goto out; strcpy(tmpfile, userfile); strcat(tmpfile, ".tmp"); fd = open(tmpfile, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); if (fd < 0) { DBG (("Cannot open file: %s (%s)", tmpfile, strerror(errno))); goto out; } f = fdopen(fd, "w"); if (! f) { close(fd); goto out; } errstr = "Error updating Yubikey challenge, please check syslog or contact your system administrator"; if (! write_chalresp_state (f, &state)) goto out; if (fclose(f) < 0) { f = NULL; goto out; } f = NULL; if (rename(tmpfile, userfile) < 0) { goto out; } if (restore_privileges(pamh) < 0) { DBG (("could not restore privileges")); goto out; } DBG(("Challenge-response success!")); errstr = NULL; errno = 0; out: if (yk_errno) { if (yk_errno == YK_EUSBERR) { syslog(LOG_ERR, "USB error: %s", yk_usb_strerror()); D(("USB error: %s", yk_usb_strerror())); } else { syslog(LOG_ERR, "Yubikey core error: %s", yk_strerror(yk_errno)); D(("Yubikey core error: %s", yk_strerror(yk_errno))); } } if (errstr) display_error(pamh, errstr); if (errno) { syslog(LOG_ERR, "Challenge response failed: %s", strerror(errno)); D(("Challenge response failed: %s", strerror(errno))); } if (yk) yk_close_key(yk); yk_release(); if (f) fclose(f); free(userfile); free(tmpfile); return ret; }