@@ -15,6 +15,16 @@ import (
15
15
. "github.com/djthorpe/go-errors"
16
16
)
17
17
18
+ ///////////////////////////////////////////////////////////////////////////////
19
+ // TYPES
20
+
21
+ type bwCipher struct {
22
+ Name string
23
+ Username string
24
+ URI string
25
+ Folder string
26
+ }
27
+
18
28
///////////////////////////////////////////////////////////////////////////////
19
29
// GLOBALS
20
30
@@ -47,9 +57,10 @@ func bwRegister(flags *Flags) {
47
57
Description : "Interact with the Bitwarden API" ,
48
58
Parse : bwParse ,
49
59
Fn : []Fn {
50
- {Name : "login " , Description : "Login to Bitwarden" , Call : bwLogin },
60
+ {Name : "auth " , Description : "Authenticate with Bitwarden" , Call : bwAuth },
51
61
{Name : "sync" , Description : "Sync items from Bitwarden" , Call : bwSync },
52
62
{Name : "folders" , Description : "Retrieve folders" , Call : bwFolders },
63
+ {Name : "logins" , Description : "Retrieve login items" , Call : bwLogins },
53
64
},
54
65
})
55
66
}
@@ -87,7 +98,7 @@ func bwParse(flags *Flags, opts ...client.ClientOpt) error {
87
98
///////////////////////////////////////////////////////////////////////////////
88
99
// API METHODS
89
100
90
- func bwLogin (w * tablewriter.TableWriter ) error {
101
+ func bwAuth (w * tablewriter.TableWriter ) error {
91
102
// Load session or create a new one
92
103
session , err := bwReadSession ()
93
104
if err != nil {
@@ -168,24 +179,15 @@ func bwFolders(w *tablewriter.TableWriter) error {
168
179
return err
169
180
}
170
181
171
- // If no password is set, then read it
172
- password := bwPassword
173
- if password == "" {
174
- stdin := int (os .Stdin .Fd ())
175
- if ! term .IsTerminal (stdin ) {
176
- return ErrBadParameter .With ("No password set and not running in terminal" )
177
- }
178
- fmt .Fprintf (os .Stdout , "Enter password: " )
179
- if value , err := term .ReadPassword (stdin ); err != nil {
182
+ // Make an encryption key
183
+ if bwPassword == "" {
184
+ if v , err := bwReadPasswordFromTerminal (); err != nil {
180
185
return err
181
186
} else {
182
- password = string ( value )
187
+ bwPassword = v
183
188
}
184
- fmt .Fprintf (os .Stdout , "\n " )
185
189
}
186
-
187
- // Make the decryption key
188
- if err := session .CacheKey (profile .Key , profile .Email , password ); err != nil {
190
+ if err := session .CacheKey (profile .Key , profile .Email , bwPassword ); err != nil {
189
191
return err
190
192
}
191
193
@@ -211,9 +213,80 @@ func bwFolders(w *tablewriter.TableWriter) error {
211
213
return nil
212
214
}
213
215
216
+ func bwLogins (w * tablewriter.TableWriter ) error {
217
+ // Load the profile
218
+ profile , err := bwReadProfile ()
219
+ if err != nil {
220
+ return err
221
+ }
222
+
223
+ // Load session or create a new one
224
+ session , err := bwReadSession ()
225
+ if err != nil {
226
+ return err
227
+ }
228
+
229
+ // Make an encryption key
230
+ if bwPassword == "" {
231
+ if v , err := bwReadPasswordFromTerminal (); err != nil {
232
+ return err
233
+ } else {
234
+ bwPassword = v
235
+ }
236
+ }
237
+ if err := session .CacheKey (profile .Key , profile .Email , bwPassword ); err != nil {
238
+ return err
239
+ }
240
+
241
+ // Read the ciphers
242
+ ciphers := schema.Ciphers {}
243
+ result := []bwCipher {}
244
+ if err := bwRead ("ciphers.json" , & ciphers ); err != nil {
245
+ return err
246
+ }
247
+ // Decrypt the ciphers from the session
248
+ for _ , cipher := range ciphers {
249
+ if cipher .Type != schema .CipherTypeLogin {
250
+ continue
251
+ }
252
+ if decrypted , err := cipher .Decrypt (session ); err != nil {
253
+ return err
254
+ } else {
255
+ result = append (result , bwCipher {
256
+ Name : decrypted .(* schema.Cipher ).Name ,
257
+ Username : decrypted .(* schema.Cipher ).Login .Username ,
258
+ URI : decrypted .(* schema.Cipher ).Login .URI ,
259
+ Folder : decrypted .(* schema.Cipher ).FolderId ,
260
+ })
261
+ }
262
+ }
263
+
264
+ // Output the ciphers
265
+ w .Write (result )
266
+
267
+ // Return success
268
+ return nil
269
+ }
270
+
214
271
///////////////////////////////////////////////////////////////////////////////
215
272
// OTHER
216
273
274
+ func bwReadPasswordFromTerminal () (string , error ) {
275
+ stdin := int (os .Stdin .Fd ())
276
+ if ! term .IsTerminal (stdin ) {
277
+ return "" , ErrBadParameter .With ("No password set and not running in terminal" )
278
+ }
279
+ fmt .Fprintf (os .Stdout , "Enter password: " )
280
+ defer func () {
281
+ fmt .Fprintf (os .Stdout , "\n " )
282
+ }()
283
+ if value , err := term .ReadPassword (stdin ); err != nil {
284
+ return "" , err
285
+ } else {
286
+ return string (value ), nil
287
+ }
288
+ }
289
+
217
290
func bwReadProfile () (* schema.Profile , error ) {
218
291
result := schema .NewProfile ()
219
292
filename := filepath .Join (bwConfigDir , "profile.json" )
0 commit comments