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); }
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, ®_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); }