diff --git a/main.go b/main.go index 30cae65..e6e7666 100755 --- a/main.go +++ b/main.go @@ -40,6 +40,7 @@ import ( "flag" "fmt" "math" + "os" "os/user" "strings" "time" @@ -111,13 +112,14 @@ func decryptAESCBC(p string, enc string) (rv []byte, err error) { return } -func getEntriesFromFile(n string, p string) (*map[string]entry, error) { +func getEntriesFromFile(n string, p string) ([]entry, error) { var data string var db *sql.DB var err error var entries map[string]entry var pwddb string var s []byte + var i int if db, err = sql.Open("sqlite3", n); err != nil { return nil, err @@ -145,16 +147,18 @@ func getEntriesFromFile(n string, p string) (*map[string]entry, error) { delete(entries, "key") } - for k, v := range entries { - if v.Encrypted { + rv := make([]entry, len(entries)) + for _, v := range entries { + if v.Encrypted && pwddb != "" { if s, err = decryptAESCBC(pwddb, v.Secret); err == nil { v.Secret = string(s) v.Encrypted = false - entries[k] = v } } + rv[i] = v + i++ } - return &entries, err + return rv, err } func computeOTP(secret string) (uint32, error) { @@ -196,31 +200,61 @@ func getFirefoxSyncv2Path() (string, error) { return u.HomeDir + "/.mozilla/firefox/" + p + "/storage-sync-v2.sqlite", nil } +func getConfigurationFile() (entries []entry, err error) { + var u *user.User + var data []byte + var fname string + + if u, err = user.Current(); err != nil { + return + } + fname = u.HomeDir + "/.config/totp/config.json" + if err = os.Chmod(fname, 0600); err != nil { + return + } + if data, err = os.ReadFile(fname); err != nil { + return + } + if err = json.Unmarshal([]byte(data), &entries); err != nil { + return + } + return +} + func main() { var sentry string var dbf string var passwd string var err error - var entries *map[string]entry + var entries []entry + var firefox bool flag.StringVar(&dbf, "d", "", "Database file") flag.StringVar(&sentry, "e", "", "Select entry") + flag.BoolVar(&firefox, "f", false, "Get tokens from Firefox Authenticator Extension module") flag.StringVar(&passwd, "p", "", "Database file") flag.Parse() - if dbf == "" { - dbf, err = getFirefoxSyncv2Path() - if err != nil { + if firefox || dbf != "" { + if dbf == "" { + dbf, err = getFirefoxSyncv2Path() + if err != nil { + fmt.Printf("%s\n", err) + return + } + } + if entries, err = getEntriesFromFile(dbf, passwd); err != nil { + fmt.Printf("%s\n", err) + return + } + } else { + if entries, err = getConfigurationFile(); err != nil { fmt.Printf("%s\n", err) return } } - if entries, err = getEntriesFromFile(dbf, passwd); err != nil { - fmt.Printf("%s\n", err) - return - } - for _, v := range *entries { + for _, v := range entries { if v.Encrypted { continue }