Esempio n. 1
0
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);
}
Esempio n. 2
0
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);
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
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;
}