Esempio n. 1
0
int
main(int argc, char *argv[]) {
  int exit_code = EXIT_FAILURE;
  char *response = NULL;
  u2fh_devs *devs = NULL;
  u2fh_rc rc;
  OP *action = NULL;
  char device_state = 'u';
  u2fh_rc device_disappeared_rc = U2FH_OK;
  char *device_disappeared_msg = NULL;

  reset_quit_timer();

  rc = u2fh_global_init(0);
  if (rc != U2FH_OK) {
    report_error(rc, "global_init");
    exit(1);
  }

  rc = u2fh_devs_init(&devs);
  if (rc != U2FH_OK) {
    report_error(rc, "devs_init");
    goto done;
  }

  while (1) {
    int need_sleep = 1;
    rc = u2fh_devs_discover(devs, NULL);
    if (device_disappeared_rc != U2FH_OK && rc != U2FH_NO_U2F_DEVICE) {
      report_error(device_disappeared_rc, device_disappeared_msg);

      free(response);
      free(action);
      action = NULL;
    }
    if (rc != U2FH_OK && rc != U2FH_NO_U2F_DEVICE) {
      report_error(rc, "devs_discover");
      goto done;
    }

    if (rc == U2FH_OK && device_state == 'm') {
      printf("j");
      fflush(stdout);
      device_state = 'p';
      need_sleep = 0;
    }

    if (rc == U2FH_NO_U2F_DEVICE && device_state != 'm') {
      printf("i");
      fflush(stdout);
      device_state = 'm';
    }

    device_disappeared_rc = U2FH_OK;

    if (!action) {
      action = read_action(1000);
      if (action)
        reset_quit_timer();
    } else if (need_sleep)
      sleep(1);

    if (action && (rc == U2FH_OK || action->op == 'e')) {
      if (action->op == 'e')
        goto done;
      else if (action->op == 'r' || action->op == 's') {
        int requests_count = 0;
        do {
          int i = 0;
          do {
            if (action->op == 'r') {
              rc = u2fh_register(devs, action->challenges[i], action->domain,
                                 &response,
                                 U2FH_REQUEST_USER_PRESENCE | U2FH_REQUEST_NON_BLOCKING);
            } else {
              rc = u2fh_authenticate(devs, action->challenges[i], action->domain,
                                     &response,
                                     U2FH_REQUEST_USER_PRESENCE | U2FH_REQUEST_NON_BLOCKING);
            }
            i++;
          } while (action->challenges[i] && rc == U2FH_AUTHENTICATOR_ERROR);

          if (rc == U2FH_NOT_FINISHED_ERROR) {
            if (device_state != 'b') {
              printf("b");
              fflush(stdout);
              device_state = 'b';
            }
            sleep(1);
          } else
            break;
        } while (requests_count++ < 15);

        if (requests_count >= 15) {
          report_error(U2FH_TIMEOUT_ERROR, NULL);
        } else if (rc != U2FH_OK) {
          device_disappeared_rc = rc;
          device_disappeared_msg = action->op == 'r' ? "register" : "authenticate";
          continue;
        } else {
          printf("r%04lx%s", strlen(response), response);
          fflush(stdout);
        }

        free(response);
        free(action);
        action = NULL;
      } else {
        report_error(U2FH_TRANSPORT_ERROR, NULL);
        goto done;
      }
    }
  }

  done:
  u2fh_devs_done(devs);
  u2fh_global_done();

  exit(exit_code);
}
Esempio n. 2
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;
}