Exemplo n.º 1
0
int do_manual_authentication(const cfg_t *cfg, const device_t *devices,
                             const unsigned n_devs, pam_handle_t *pamh) {
  u2fs_ctx_t *ctx_arr[n_devs];
  u2fs_auth_res_t *auth_result;
  u2fs_rc s_rc;
  char *response = NULL;
  char prompt[MAX_PROMPT_LEN];
  char *buf;
  int retval = -2;
  unsigned i = 0;

  if (u2fs_global_init(0) != U2FS_OK) {
    if (cfg->debug)
      D(cfg->debug_file, "Unable to initialize libu2f-server");
    return retval;
  }

  for (i = 0; i < n_devs; ++i) {

    if (u2fs_init(ctx_arr + i) != U2FS_OK) {
      if (cfg->debug)
        D(cfg->debug_file, "Unable to initialize libu2f-server");
      return retval;
    }

    if ((s_rc = u2fs_set_origin(ctx_arr[i], cfg->origin)) != U2FS_OK) {
      if (cfg->debug)
        D(cfg->debug_file, "Unable to set origin: %s", u2fs_strerror(s_rc));
      return retval;
    }

    if ((s_rc = u2fs_set_appid(ctx_arr[i], cfg->appid)) != U2FS_OK) {
      if (cfg->debug)
        D(cfg->debug_file, "Unable to set appid: %s", u2fs_strerror(s_rc));
      return retval;
    }

    if (cfg->debug)
      D(cfg->debug_file, "Attempting authentication with device number %d", i + 1);

    if ((s_rc = u2fs_set_keyHandle(ctx_arr[i], devices[i].keyHandle)) !=
        U2FS_OK) {
      if (cfg->debug)
        D(cfg->debug_file, "Unable to set keyHandle: %s", u2fs_strerror(s_rc));
      return retval;
    }

    if ((s_rc = u2fs_set_publicKey(ctx_arr[i], devices[i].publicKey)) !=
        U2FS_OK) {
      if (cfg->debug)
        D(cfg->debug_file, "Unable to set publicKey %s", u2fs_strerror(s_rc));
      return retval;
    }

    if ((s_rc = u2fs_authentication_challenge(ctx_arr[i], &buf)) != U2FS_OK) {
      if (cfg->debug)
        D(cfg->debug_file, "Unable to produce authentication challenge: %s",
           u2fs_strerror(s_rc));
      return retval;
    }

    if (cfg->debug)
      D(cfg->debug_file, "Challenge: %s", buf);

    if (i == 0) {
      snprintf(prompt, sizeof(prompt),
                      "Now please copy-paste the below challenge(s) to "
                      "'u2f-host -aauthenticate -o %s'",
              cfg->origin);
      converse(pamh, PAM_TEXT_INFO, prompt);
    }
    converse(pamh, PAM_TEXT_INFO, buf);
    free(buf);
    buf = NULL;
  }

  converse(pamh, PAM_TEXT_INFO,
           "Now, please enter the response(s) below, one per line.");

  retval = -1;

  for (i = 0; i < n_devs; ++i) {
    snprintf(prompt, sizeof(prompt), "[%d]: ", i);
    response = converse(pamh, PAM_PROMPT_ECHO_ON, prompt);
    converse(pamh, PAM_TEXT_INFO, response);

    s_rc = u2fs_authentication_verify(ctx_arr[i], response, &auth_result);
    u2fs_free_auth_res(auth_result);
    if (s_rc == U2FS_OK) {
      retval = 1;
    }
    free(response);
    if (retval == 1) {
        break;
    }
  }

  for (i = 0; i < n_devs; ++i)
    u2fs_done(ctx_arr[i]);
  u2fs_global_done();

  return retval;
}
Exemplo n.º 2
0
int main(int argc, char *argv[])
{
  int exit_code = EXIT_FAILURE;
  struct gengetopt_args_info args_info;
  char buf[BUFSIZE];
  char *p;
  char *response;
  u2fs_ctx_t *ctx;
  u2fs_reg_res_t *reg_result;
  u2fs_rc s_rc;
  u2fh_rc h_rc;
  char *origin = NULL;
  char *appid = NULL;
  char *user = NULL;
  const char *kh = NULL;
  const char *pk = NULL;
  u2fh_devs *devs = NULL;
  unsigned i;
  unsigned max_index = 0;


  if (cmdline_parser(argc, argv, &args_info) != 0)
    exit(EXIT_FAILURE);

  if (args_info.help_given) {
    cmdline_parser_print_help();
    printf
        ("\nReport bugs at <https://github.com/Yubico/libu2f-server>.\n");
    exit(EXIT_SUCCESS);
  }

  s_rc = u2fs_global_init(args_info.debug_flag ? U2FS_DEBUG : 0);
  if (s_rc != U2FS_OK) {
    fprintf(stderr, "error: u2fs_global_init (%d): %s\n", s_rc,
            u2fs_strerror(s_rc));
    exit(EXIT_FAILURE);
  }

  s_rc = u2fs_init(&ctx);
  if (s_rc != U2FS_OK) {
    fprintf(stderr, "error: u2fs_init (%d): %s\n", s_rc,
            u2fs_strerror(s_rc));
    exit(EXIT_FAILURE);
  }

  if (args_info.origin_given)
    origin = args_info.origin_arg;
  else {
    if (!strcpy(buf, PAM_PREFIX))
      fprintf(stderr, "strcpy failed\n");
    if (gethostname(buf + strlen(PAM_PREFIX), BUFSIZE - strlen(PAM_PREFIX))
        == -1) {
      perror("gethostname");
      exit(EXIT_FAILURE);
    }
    origin = buf;
  }

  s_rc = u2fs_set_origin(ctx, origin);
  if (s_rc != U2FS_OK) {
    printf("error: u2fs_set_origin (%d): %s\n", s_rc, u2fs_strerror(s_rc));
    exit(EXIT_FAILURE);
  }

  if (args_info.appid_given)
    appid = args_info.appid_arg;
  else {
    if (args_info.origin_given) {
      if (!strcpy(buf, PAM_PREFIX))
        fprintf(stderr, "strcpy failed\n");
      if (gethostname
          (buf + strlen(PAM_PREFIX), BUFSIZE - strlen(PAM_PREFIX)) == -1) {
        perror("gethostname");
        exit(EXIT_FAILURE);
      }
    }
    appid = buf;
  }

  s_rc = u2fs_set_appid(ctx, appid);
  if (s_rc != U2FS_OK) {
    fprintf(stderr, "error: u2fs_set_appid (%d): %s\n", s_rc,
            u2fs_strerror(s_rc));
    exit(EXIT_FAILURE);
  }

  if (args_info.username_given)
    user = args_info.username_arg;
  else {
    user = getlogin();
    if (!user) {
      perror("getlogin");
      exit(EXIT_FAILURE);
    }
  }

  if (u2fh_global_init(args_info.debug_flag ? U2FS_DEBUG : 0) != U2FH_OK
      || u2fh_devs_init(&devs) != U2FH_OK) {
    fprintf(stderr, "Unable to initialize libu2f-host");
    exit(EXIT_FAILURE);
  }

  h_rc = u2fh_devs_discover(devs, &max_index);
  if (h_rc != U2FH_OK && h_rc != U2FH_NO_U2F_DEVICE) {
    fprintf(stderr, "Unable to discover device(s), %s (%d)",
            u2fh_strerror(h_rc), h_rc);
    exit(EXIT_FAILURE);
  }

  if (h_rc == U2FH_NO_U2F_DEVICE) {
    for (i = 0; i < TIMEOUT; i += FREQUENCY) {
      fprintf(stderr,
              "\rNo U2F device available, please insert one now, you have %2d seconds",
              TIMEOUT - i);
      fflush(stderr);
      sleep(FREQUENCY);

      h_rc = u2fh_devs_discover(devs, &max_index);
      if (h_rc == U2FH_OK) {
        fprintf(stderr, "\nDevice found!\n");
        break;
      }

      if (h_rc != U2FH_NO_U2F_DEVICE) {
        fprintf(stderr, "\nUnable to discover device(s), %s (%d)",
                u2fh_strerror(h_rc), h_rc);
        exit(EXIT_FAILURE);
      }
    }
  }

  if (h_rc != U2FH_OK) {
    fprintf(stderr,
            "\rNo device found. Aborting.                                         \n");
    exit(EXIT_FAILURE);
  }

  s_rc = u2fs_registration_challenge(ctx, &p);
  if (s_rc != U2FS_OK) {
    fprintf(stderr, "Unable to generate registration challenge, %s (%d)",
            u2fs_strerror(s_rc), s_rc);
    exit(EXIT_FAILURE);
  }

  h_rc =
      u2fh_register(devs, p, origin, &response,
                    U2FH_REQUEST_USER_PRESENCE);
  if (s_rc != U2FS_OK) {
    fprintf(stderr, "Unable to generate registration challenge, %s (%d)",
            u2fs_strerror(s_rc), s_rc);
    exit(EXIT_FAILURE);
  }

  s_rc = u2fs_registration_verify(ctx, response, &reg_result);
  if (s_rc != U2FS_OK) {
    fprintf(stderr, "error: (%d) %s\n", s_rc, u2fs_strerror(s_rc));
    exit(EXIT_FAILURE);
  }

  kh = u2fs_get_registration_keyHandle(reg_result);
  if (!kh) {
    fprintf(stderr, "Unable to extract keyHandle: (%d) %s\n", s_rc,
            u2fs_strerror(s_rc));
    exit(EXIT_FAILURE);
  }

  pk = u2fs_get_registration_publicKey(reg_result);
  if (!pk) {
    fprintf(stderr, "Unable to extract public key: (%d) %s\n", s_rc,
            u2fs_strerror(s_rc));
    exit(EXIT_FAILURE);
  }

  if (!args_info.nouser_given)
    printf("%s", user);

  printf(":%s,", kh);
  for (i = 0; i < U2FS_PUBLIC_KEY_LEN; i++) {
    printf("%02x", pk[i] & 0xFF);
  }

  exit_code = EXIT_SUCCESS;

  u2fs_done(ctx);
  u2fs_global_done();
  exit(exit_code);
}
Exemplo n.º 3
0
int do_authentication(const cfg_t *cfg, const device_t *devices,
                      const unsigned n_devs, pam_handle_t *pamh) {
  u2fs_ctx_t *ctx;
  u2fs_auth_res_t *auth_result;
  u2fs_rc s_rc;
  u2fh_rc h_rc;
  u2fh_devs *devs = NULL;
  char *response = NULL;
  char *buf;
  int retval = -2;
  int cued = 0;
  unsigned i = 0;
  unsigned max_index = 0;
  unsigned max_index_prev = 0;

  h_rc = u2fh_global_init(cfg->debug ? U2FH_DEBUG : 0);
  if (h_rc != U2FH_OK) {
    D(cfg->debug_file, "Unable to initialize libu2f-host: %s", u2fh_strerror(h_rc));
    return retval;
  }
  h_rc = u2fh_devs_init(&devs);
  if (h_rc != U2FH_OK) {
    D(cfg->debug_file, "Unable to initialize libu2f-host device handles: %s",
       u2fh_strerror(h_rc));
    return retval;
  }

  if ((h_rc = u2fh_devs_discover(devs, &max_index)) != U2FH_OK) {
    if (cfg->debug)
      D(cfg->debug_file, "Unable to discover device(s), %s", u2fh_strerror(h_rc));
    return retval;
  }
  max_index_prev = max_index;

  if (cfg->debug)
    D(cfg->debug_file, "Device max index is %u", max_index);

  s_rc = u2fs_global_init(cfg->debug ? U2FS_DEBUG : 0);
  if (s_rc != U2FS_OK) {
    D(cfg->debug_file, "Unable to initialize libu2f-server: %s", u2fs_strerror(s_rc));
    return retval;
  }
  s_rc = u2fs_init(&ctx);
  if (s_rc != U2FS_OK) {
    D(cfg->debug_file, "Unable to initialize libu2f-server context: %s", u2fs_strerror(s_rc));
    return retval;
  }

  if ((s_rc = u2fs_set_origin(ctx, cfg->origin)) != U2FS_OK) {
    if (cfg->debug)
      D(cfg->debug_file, "Unable to set origin: %s", u2fs_strerror(s_rc));
    return retval;
  }

  if ((s_rc = u2fs_set_appid(ctx, cfg->appid)) != U2FS_OK) {
    if (cfg->debug)
      D(cfg->debug_file, "Unable to set appid: %s", u2fs_strerror(s_rc));
    return retval;
  }

  if (cfg->nodetect && cfg->debug)
    D(cfg->debug_file, "nodetect option specified, suitable key detection will be skipped");

  i = 0;
  while (i < n_devs) {

    retval = -2;

    if (cfg->debug)
      D(cfg->debug_file, "Attempting authentication with device number %d", i + 1);

    if ((s_rc = u2fs_set_keyHandle(ctx, devices[i].keyHandle)) != U2FS_OK) {
      if (cfg->debug)
        D(cfg->debug_file, "Unable to set keyHandle: %s", u2fs_strerror(s_rc));
      return retval;
    }

    if ((s_rc = u2fs_set_publicKey(ctx, devices[i].publicKey)) != U2FS_OK) {
      if (cfg->debug)
        D(cfg->debug_file, "Unable to set publicKey %s", u2fs_strerror(s_rc));
      return retval;
    }

    if ((s_rc = u2fs_authentication_challenge(ctx, &buf)) != U2FS_OK) {
      if (cfg->debug)
        D(cfg->debug_file, "Unable to produce authentication challenge: %s",
           u2fs_strerror(s_rc));
      free(buf);
      buf = NULL;
      return retval;
    }

    if (cfg->debug)
      D(cfg->debug_file, "Challenge: %s", buf);

    if (cfg->nodetect || (h_rc = u2fh_authenticate(devs, buf, cfg->origin, &response, 0)) == U2FH_OK ) {

      if (cfg->manual == 0 && cfg->cue && !cued) {
        cued = 1;
        converse(pamh, PAM_TEXT_INFO, DEFAULT_CUE);
      }

      retval = -1;

      if ((h_rc = u2fh_authenticate(devs, buf, cfg->origin, &response, U2FH_REQUEST_USER_PRESENCE)) ==
          U2FH_OK) {
        if (cfg->debug)
          D(cfg->debug_file, "Response: %s", response);

        s_rc = u2fs_authentication_verify(ctx, response, &auth_result);
        u2fs_free_auth_res(auth_result);
        free(response);
        response = NULL;
        if (s_rc == U2FS_OK) {
          retval = 1;

          free(buf);
          buf = NULL;
          break;
        }
      } else {
        if (cfg->debug)
          D(cfg->debug_file, "Unable to communicate to the device, %s", u2fh_strerror(h_rc));
      }
    } else {
      if (cfg->debug)
        D(cfg->debug_file, "Device for this keyhandle is not present.");
    }
    free(buf);
    buf = NULL;

    i++;

    if (u2fh_devs_discover(devs, &max_index) != U2FH_OK) {
      if (cfg->debug)
        D(cfg->debug_file, "Unable to discover devices");
      return retval;
    }

    if (max_index > max_index_prev) {
      if (cfg->debug)
        D(cfg->debug_file, "Devices max_index has changed: %u (was %u). Starting over",
           max_index, max_index_prev);
      max_index_prev = max_index;
      i = 0;
    }
  }

  u2fh_devs_done(devs);
  u2fh_global_done();

  u2fs_done(ctx);
  u2fs_global_done();

  return retval;
}