summaryrefslogtreecommitdiff
path: root/apps/plugins
diff options
context:
space:
mode:
authorFranklin Wei <frankhwei536@gmail.com>2016-06-14 16:14:06 -0400
committerFranklin Wei <frankhwei536@gmail.com>2016-06-14 16:14:06 -0400
commit7f4861772b99e73aca7f312f2f3b92acdf9eaa9e (patch)
tree47bdd74a4892506552cc3b0ccd7adf6ec5be6bfd /apps/plugins
parentc10f979a60a57d9b2ae810f9dc50ad7a40616082 (diff)
downloadrockbox-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/SUBDIRS2
-rw-r--r--apps/plugins/otp.c218
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;