diff options
| author | Franklin Wei <frankhwei536@gmail.com> | 2016-06-14 16:14:06 -0400 |
|---|---|---|
| committer | Franklin Wei <frankhwei536@gmail.com> | 2016-06-14 16:14:06 -0400 |
| commit | 7f4861772b99e73aca7f312f2f3b92acdf9eaa9e (patch) | |
| tree | 47bdd74a4892506552cc3b0ccd7adf6ec5be6bfd /apps/plugins | |
| parent | c10f979a60a57d9b2ae810f9dc50ad7a40616082 (diff) | |
| download | rockbox-7f4861772b99e73aca7f312f2f3b92acdf9eaa9e.zip rockbox-7f4861772b99e73aca7f312f2f3b92acdf9eaa9e.tar.gz rockbox-7f4861772b99e73aca7f312f2f3b92acdf9eaa9e.tar.bz2 rockbox-7f4861772b99e73aca7f312f2f3b92acdf9eaa9e.tar.xz | |
OTP work
Change-Id: I36bf75218e8e032e6dbb67792c4f2ff40ceaadc3
Diffstat (limited to 'apps/plugins')
| -rw-r--r-- | apps/plugins/SUBDIRS | 2 | ||||
| -rw-r--r-- | apps/plugins/otp.c | 218 |
2 files changed, 135 insertions, 85 deletions
diff --git a/apps/plugins/SUBDIRS b/apps/plugins/SUBDIRS index c161a01..78f4c3a 100644 --- a/apps/plugins/SUBDIRS +++ b/apps/plugins/SUBDIRS @@ -99,7 +99,7 @@ mpegplayer lua #endif -wikiviewer +//wikiviewer #if defined(IRIVER_H300_SERIES) || (CONFIG_KEYPAD == IPOD_4G_PAD) || \ (CONFIG_KEYPAD == SANSA_FUZEPLUS_PAD) || \ diff --git a/apps/plugins/otp.c b/apps/plugins/otp.c index 23e7727..b4c9d8f 100644 --- a/apps/plugins/otp.c +++ b/apps/plugins/otp.c @@ -31,7 +31,7 @@ #include "lib/sha1.h" #define MAX_NAME 50 -#define SECRET_MAX 256 +#define SECRET_MAX 64 /* enough for a 512-bit secret */ #define URI_MAX 256 #define ACCT_FILE PLUGIN_APPS_DATA_DIR "/otp.dat" @@ -63,6 +63,8 @@ static int next_slot = 0; /* in SECONDS, asked for on first run */ static int time_offs = 0; +static void acct_menu(const char *title, void (*cb)(int acct)); + static int HOTP(unsigned char *secret, size_t sec_len, uint64_t ctr, int digits) { ctr = htobe64(ctr); @@ -410,7 +412,7 @@ static void add_acct_manual(void) } memset(accounts + next_slot, 0, sizeof(struct account_t)); - rb->splash(HZ * 1, "Enter account name."); + rb->splash(HZ * 1, "Enter account name:"); if(rb->kbd_input(accounts[next_slot].name, sizeof(accounts[next_slot].name)) < 0) return; @@ -420,7 +422,7 @@ static void add_acct_manual(void) return; } - rb->splash(HZ * 2, "Enter base32-encoded secret."); + rb->splash(HZ * 2, "Enter Base32-encoded secret:"); char temp_buf[SECRET_MAX * 2]; memset(temp_buf, 0, sizeof(temp_buf)); @@ -435,7 +437,7 @@ static void add_acct_manual(void) } #if CONFIG_RTC - const struct text_message prompt = { (const char*[]) {"Is this a TOTP account?", "The protocol can be determined from the URI."}, 2}; + const struct text_message prompt = { (const char*[]) {"Is this a TOTP (time-based) account?", "The protocol can be determined from the URI."}, 2}; enum yesno_res response = rb->gui_syncyesno_run(&prompt, NULL, NULL); if(response == YESNO_NO) accounts[next_slot].is_totp = false; @@ -447,12 +449,12 @@ static void add_acct_manual(void) if(!accounts[next_slot].is_totp) { - rb->splash(HZ * 2, "Enter counter (0 is normal)."); + rb->splash(HZ * 2, "Enter counter (0 is normal):"); temp_buf[0] = '0'; } else { - rb->splash(HZ * 2, "Enter time step (30 is normal)."); + rb->splash(HZ * 2, "Enter time step (30 is normal):"); temp_buf[0] = '3'; temp_buf[1] = '0'; } @@ -465,7 +467,7 @@ static void add_acct_manual(void) else accounts[next_slot].totp_period = rb->atoi(temp_buf); - rb->splash(HZ * 2, "Enter code length (6 is normal)."); + rb->splash(HZ * 2, "Enter code length (6 is normal):"); memset(temp_buf, 0, sizeof(temp_buf)); temp_buf[0] = '6'; @@ -490,8 +492,8 @@ static void add_acct_manual(void) static void add_acct(void) { - MENUITEM_STRINGLIST(menu, "Add Account", NULL, - "From URI on disk", + MENUITEM_STRINGLIST(menu, "Import Account(s)", NULL, + "From URI List", "Manual Entry", "Back"); int sel = 0; @@ -526,6 +528,7 @@ static int next_code(int acct) ++accounts[acct].hotp_counter; return ret; } +#if CONFIG_RTC else { return TOTP(accounts[acct].secret, @@ -533,6 +536,8 @@ static int next_code(int acct) accounts[acct].totp_period, accounts[acct].digits); } +#endif + return 0; } static void show_code(int acct) @@ -567,57 +572,7 @@ static void show_code(int acct) } save_accts(); - rb->lcd_clear_display(); -} - -static void acct_menu(const char *title, void (*cb)(int acct)) -{ - rb->lcd_clear_display(); - /* native menus don't seem to support dynamic names easily, so we - * roll our own */ - static const struct button_mapping *plugin_contexts[] = { pla_main_ctx }; - int idx = 0; - if(next_slot > 0) - { - rb->lcd_puts(0, 0, title); - rb->lcd_putsf(0, 1, "%s", accounts[0].name); - rb->lcd_update(); - } - else - { - rb->splash(HZ * 2, "No accounts configured!"); - return; - } - while(1) - { - int button = pluginlib_getaction(-1, plugin_contexts, ARRAYLEN(plugin_contexts)); - switch(button) - { - case PLA_LEFT: - --idx; - if(idx < 0) - idx = next_slot - 1; - break; - case PLA_RIGHT: - ++idx; - if(idx >= next_slot) - idx = 0; - break; - case PLA_SELECT: - cb(idx); - break; - case PLA_CANCEL: - case PLA_EXIT: - exit_on_usb(button); - return; - default: - break; - } - rb->lcd_clear_display(); - rb->lcd_puts(0, 0, title); - rb->lcd_putsf(0, 1, "%s", accounts[idx].name); - rb->lcd_update(); - } + rb->lcd_update(); } static void gen_codes(void) @@ -692,7 +647,7 @@ static void edit_menu(int acct) switch(rb->do_menu(menu, &sel, NULL, false)) { case 0: // rename - rb->splash(HZ, "Enter new name."); + rb->splash(HZ, "Enter new name:"); rb->strlcpy(data_buf, accounts[acct].name, sizeof(data_buf)); if(rb->kbd_input(data_buf, sizeof(data_buf)) < 0) break; @@ -718,7 +673,7 @@ static void edit_menu(int acct) break; case 2: // HOTP counter OR TOTP period if(accounts[acct].is_totp) - rb->snprintf(data_buf, sizeof(data_buf), "%d", (int)accounts[acct].hotp_counter); + rb->snprintf(data_buf, sizeof(data_buf), "%u", (unsigned int) accounts[acct].hotp_counter); else rb->snprintf(data_buf, sizeof(data_buf), "%d", accounts[acct].totp_period); @@ -831,7 +786,7 @@ static int get_time_seconds(const char *label) /* returns the offset in seconds associated with a time zone */ static int get_time_offs(void) { - MENUITEM_STRINGLIST(menu, "Select Time Offset", NULL, + MENUITEM_STRINGLIST(menu, "Select Time Zone", NULL, "UTC-12:00", // 0 "UTC-11:00", // 1 "UTC-10:00 (HAST)", // 2 @@ -954,13 +909,72 @@ static int get_time_offs(void) } #endif +static void export_uri_list(void) +{ + static char buf[MAX(MAX_PATH, SECRET_MAX * 2)]; + buf[0] = '/'; + buf[1] = '\0'; + rb->splash(HZ * 2, "Enter output filename:"); + if(rb->kbd_input(buf, sizeof(buf)) < 0) + return; + + if(rb->file_exists(buf)) + { + rb->splash(HZ, "File already exists!"); + return; + } + + int fd = rb->open(buf, O_WRONLY | O_CREAT | O_TRUNC); + if(fd < 0) + { + rb->splashf(HZ, "Couldn't open file."); + return; + } + + for(int i = 0; i < next_slot ; ++i) + { + base32_encode(accounts[i].secret, accounts[i].sec_len, buf, sizeof(buf)); + rb->fdprintf(fd, "otpauth://%s/%s?secret=%s&digits=%d", accounts[i].is_totp ? "totp" : "hotp", + accounts[i].name, buf, accounts[i].digits); + + if(accounts[i].is_totp) + rb->fdprintf(fd, "&period=%d", accounts[i].totp_period); + else + rb->fdprintf(fd, "&counter=%u", (unsigned) accounts[i].hotp_counter); + rb->fdprintf(fd, "\n"); + } + + rb->close(fd); + + rb->splash(HZ, "Success."); +} + +static void export_menu(void) +{ + MENUITEM_STRINGLIST(menu, "Export Accounts", NULL, + "To URI List", + "Back"); + + int sel = 0; + + switch(rb->do_menu(&menu, &sel, NULL, false)) + { + case 0: + export_uri_list(); + break; + case 1: + return; + } +} + static void adv_menu(void) { MENUITEM_STRINGLIST(menu, "Advanced", NULL, "Edit Account", - "Delete ALL accounts", + "Export Accounts", + "Delete ALL Accounts", #if CONFIG_RTC - "Change Time Offset", + "Select Time Zone", #endif "Back"); @@ -974,6 +988,9 @@ static void adv_menu(void) edit_accts(); break; case 1: + export_menu(); + break; + case 2: if(danger_confirm()) { next_slot = 0; @@ -984,12 +1001,12 @@ static void adv_menu(void) rb->splash(HZ, "Not confirmed."); break; #if CONFIG_RTC - case 2: + case 3: time_offs = get_time_offs(); break; - case 3: + case 4: #else - case 2: + case 3: #endif quit = 1; break; @@ -1039,7 +1056,7 @@ static bool wait_for_usb(void) { /* wait for a USB connection */ - rb->splash(0, "Waiting for USB, hold any button to cancel..."); + rb->splash(0, "Waiting for USB, hold any button to skip..."); int oldbutton = 0; int ticks_held = 0; @@ -1094,10 +1111,12 @@ static void type_code(int acct) rb->snprintf(buf, sizeof(buf), fmt_buf, code); char *ptr = buf; + /* check numlock led */ bool change_numlock = !(rb->usb_hid_leds() & 0x1); if(change_numlock) rb->usb_hid_send(HID_USAGE_PAGE_KEYBOARD_KEYPAD, HID_KEYPAD_NUM_LOCK_AND_CLEAR); + while(*ptr) { char c = *ptr++; @@ -1107,12 +1126,37 @@ static void type_code(int acct) rb->usb_hid_send(HID_USAGE_PAGE_KEYBOARD_KEYPAD, c - '1' + HID_KEYPAD_1_AND_END); rb->sleep(TYPE_DELAY); } + if(change_numlock) rb->usb_hid_send(HID_USAGE_PAGE_KEYBOARD_KEYPAD, HID_KEYPAD_NUM_LOCK_AND_CLEAR); + + rb->splash(0, "Press any key to continue."); + + /* wait a while to prevent accidental code generation */ + rb->sleep(HZ / 2); + while(1) + { + int button = rb->button_get(true); + if(button && !(button & BUTTON_REL)) + break; + rb->yield(); + } + + rb->lcd_update(); } static void type_codes(void) { + if(!rb->global_settings->usb_hid) + { + rb->splashf(HZ * 4, "Please enable USB HID."); + } + acct_menu("Type Code", type_code); +} +#endif + +static void acct_menu(const char *title, void (*cb)(int acct)) +{ rb->lcd_clear_display(); /* native menus don't seem to support dynamic names easily, so we * roll our own */ @@ -1120,7 +1164,7 @@ static void type_codes(void) int idx = 0; if(next_slot > 0) { - rb->lcd_putsf(0, 0, "Type Code Over USB"); + rb->lcd_puts(0, 0, title); rb->lcd_putsf(0, 1, "%s", accounts[0].name); rb->lcd_update(); } @@ -1145,22 +1189,25 @@ static void type_codes(void) idx = 0; break; case PLA_SELECT: - type_code(idx); + cb(idx); break; + case PLA_UP: case PLA_CANCEL: case PLA_EXIT: - exit_on_usb(button); return; default: +#ifdef USB_ENABLE_HID + if(cb != type_code) +#endif + exit_on_usb(button); break; } rb->lcd_clear_display(); - rb->lcd_putsf(0, 0, "Type Code Over USB"); + rb->lcd_puts(0, 0, title); rb->lcd_putsf(0, 1, "%s", accounts[idx].name); rb->lcd_update(); } } -#endif /* this is the plugin entry point */ enum plugin_status plugin_start(const void* parameter) @@ -1189,14 +1236,14 @@ enum plugin_status plugin_start(const void* parameter) #endif MENUITEM_STRINGLIST(menu, "One-Time Password Manager", NULL, - "Add Account", // 0 - "Generate Code", // 1 + "Generate Code", // 0 #ifdef USB_ENABLE_HID - "Type Code Over USB", // 2 + "Type Code", // 1 #endif - "Help", // 2/3 - "Advanced", // 3/4 - "Quit"); // 4/5 + "Import Account(s)", // 1,2 + "Help", // 2,3 + "Advanced", // 3,4 + "Quit"); // 4,5 bool quit = false; int sel = 0; @@ -1205,15 +1252,15 @@ enum plugin_status plugin_start(const void* parameter) switch(rb->do_menu(&menu, &sel, NULL, false)) { case 0: - add_acct(); - break; - case 1: gen_codes(); break; #ifdef USB_ENABLE_HID - case 2: + case 1: type_codes(); break; + case 2: + add_acct(); + break; case 3: show_help(); break; @@ -1224,6 +1271,9 @@ enum plugin_status plugin_start(const void* parameter) quit = 1; break; #else + case 1: + add_acct(); + break; case 2: show_help(); break; |