eeze.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. package main
  2. import (
  3. "notabug.org/apiote/next-eeze/agent"
  4. "notabug.org/apiote/next-eeze/config"
  5. "notabug.org/apiote/next-eeze/fido"
  6. "notabug.org/apiote/next-eeze/fs"
  7. "notabug.org/apiote/next-eeze/operation"
  8. "notabug.org/apiote/next-eeze/server"
  9. "encoding/hex"
  10. "fmt"
  11. "log"
  12. "os"
  13. "golang.org/x/crypto/ssh/terminal"
  14. "git.sr.ht/~sircmpwn/getopt"
  15. )
  16. func readMasterPassword() (string, error) {
  17. present, err := fs.IsFidoCredentialPresent()
  18. if err != nil {
  19. fmt.Println(err)
  20. return "", err
  21. }
  22. if present {
  23. return readMasterPasswordFido()
  24. } else {
  25. return readMasterPasswordStdin()
  26. }
  27. }
  28. func readMasterPasswordFido() (string, error) {
  29. c, err := fs.ReadFidoCredential()
  30. if err != nil {
  31. return "", err
  32. }
  33. // todo memguard
  34. secret := fido.GetHmacSecret("next-eeze", "", c.Cdh, c.Salt, c.CredID) // todo pin
  35. return hex.EncodeToString(secret), nil
  36. }
  37. func readMasterPasswordStdin() (string, error) {
  38. fmt.Print("Master password: ")
  39. // todo memguard
  40. masterPass_b, err := terminal.ReadPassword(int(os.Stdin.Fd()))
  41. if err != nil {
  42. return "", err
  43. }
  44. // todo memguard
  45. masterPassword := string(masterPass_b)
  46. fmt.Print("\n")
  47. return masterPassword, nil
  48. }
  49. func main() {
  50. C := getopt.Bool("C", false, "Config")
  51. S := getopt.Bool("S", false, "Sync")
  52. L := getopt.Bool("L", false, "List")
  53. G := getopt.Bool("G", false, "Get")
  54. P := getopt.Bool("P", false, "Put")
  55. var u string
  56. getopt.StringVar(&u, "u", "", "filter Get by username")
  57. var l string
  58. getopt.StringVar(&l, "l", "", "filter Get by label")
  59. var s string
  60. getopt.StringVar(&s, "s", "", "filter Get by url (service/server)")
  61. f := getopt.Bool("f", false, "show full entry in Get, instead of just username/password")
  62. p := getopt.Bool("p", false, "show just password in Get")
  63. i := getopt.Bool("i", false, "in Config: set server, username, password (initialise)")
  64. r := getopt.Bool("r", false, "in Config: reëncrypt (change master password)")
  65. fido2 := getopt.Bool("2", false, "in Config, reëncrypt: use fido2 device")
  66. n := getopt.Bool("n", false, "do not ask for anything, fail if password cannot be obtained from agent")
  67. b := getopt.Bool("b", false, "block until password can be received from agent")
  68. err := getopt.Parse()
  69. if err != nil {
  70. log.Println("Error parsing opts. ", err)
  71. return
  72. }
  73. if *P {
  74. masterPassword, _ := readMasterPassword()
  75. agent.GiveMasterPassword(masterPassword)
  76. return
  77. }
  78. masterPassword, err := agent.GetMasterPassword(*b)
  79. if masterPassword == "" && err == nil {
  80. agent.StartAgent()
  81. }
  82. masterPassword, err = agent.GetMasterPassword(*b)
  83. if err != nil {
  84. log.Println("Error getting from agent", err)
  85. }
  86. if masterPassword == "" && !*C && *n {
  87. log.Fatalln("Password needed in non-interactive mode")
  88. }
  89. if masterPassword == "" || (*C && (*i || *r)) {
  90. masterPassword, _ = readMasterPassword()
  91. agent.GiveMasterPassword(masterPassword)
  92. }
  93. if *C {
  94. if *i {
  95. config.Init(masterPassword)
  96. } else if *r {
  97. // todo memguard
  98. newMasterPassword, err := config.Reëncrypt(masterPassword, *fido2)
  99. if err != nil {
  100. log.Println("Error reëncrypting. ", err)
  101. return
  102. } else {
  103. agent.GiveMasterPassword(newMasterPassword)
  104. }
  105. }
  106. } else if *S {
  107. err = server.Sync(masterPassword)
  108. } else if *G {
  109. var r string
  110. r, err = operation.Get(u, l, s, *f, *p, masterPassword)
  111. // todo if error:wrongPass -> kill agent
  112. fmt.Println(r)
  113. } else if *L {
  114. var r string
  115. r, err = operation.List(masterPassword)
  116. fmt.Println(r)
  117. } else {
  118. getopt.Usage()
  119. }
  120. if err != nil {
  121. log.Println("Error. ", err)
  122. return
  123. }
  124. }