diff options
author | kali kaneko (leap communications) <kali@leap.se> | 2020-08-18 18:05:45 +0200 |
---|---|---|
committer | kali kaneko (leap communications) <kali@leap.se> | 2020-08-20 20:27:46 +0200 |
commit | b9cae0b715ce34cfb0b7f85f023c31ef8ddd54d3 (patch) | |
tree | ce8ff309c26150604e96eb9c5cd41cd61ff48470 | |
parent | a10c5ecd2b4bba6814fd66f0ec1997938d95bf92 (diff) |
[feat] cache authentication token
-rw-r--r-- | pkg/config/unix.go | 3 | ||||
-rw-r--r-- | pkg/vpn/bonafide/auth_sip.go | 59 | ||||
-rw-r--r-- | pkg/vpn/bonafide/bonafide.go | 22 | ||||
-rw-r--r-- | pkg/vpn/openvpn.go | 9 |
4 files changed, 75 insertions, 18 deletions
diff --git a/pkg/config/unix.go b/pkg/config/unix.go index 7425f5b..f96f6a6 100644 --- a/pkg/config/unix.go +++ b/pkg/config/unix.go @@ -18,7 +18,8 @@ package config import ( "os" + "path" ) // Path for the config files -var Path = os.Getenv("HOME") + "/.config/leap" +var Path = path.Join(os.Getenv("HOME"), ".config", "leap") diff --git a/pkg/vpn/bonafide/auth_sip.go b/pkg/vpn/bonafide/auth_sip.go index 1f200bb..e00252f 100644 --- a/pkg/vpn/bonafide/auth_sip.go +++ b/pkg/vpn/bonafide/auth_sip.go @@ -19,7 +19,13 @@ import ( "encoding/json" "fmt" "io/ioutil" + "log" + "os" + "path" "strings" + "time" + + "0xacab.org/leap/bitmask-vpn/pkg/config" ) type sipAuthentication struct { @@ -32,10 +38,11 @@ func (a *sipAuthentication) needsCredentials() bool { } func (a *sipAuthentication) getToken(user, password string) ([]byte, error) { - /* TODO - [ ] get token from disk? - [ ] check if expired? set a goroutine to refresh it periodically? - */ + /* TODO refresh session token periodically */ + if hasRecentToken() { + log.Println("Got cached token") + return readToken() + } credJSON, err := formatCredentials(user, password) if err != nil { return nil, fmt.Errorf("Cannot encode credentials: %s", err) @@ -48,7 +55,49 @@ func (a *sipAuthentication) getToken(user, password string) ([]byte, error) { if resp.StatusCode != 200 { return nil, fmt.Errorf("Cannot get token: Error %d", resp.StatusCode) } - return ioutil.ReadAll(resp.Body) + token, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, err + } + writeToken(token) + return token, nil +} + +func getTokenPath() string { + return path.Join(config.Path, config.ApplicationName+".token") +} + +func writeToken(token []byte) { + tp := getTokenPath() + err := ioutil.WriteFile(tp, token, 0600) + if err != nil { + log.Println("BUG: cannot write token to", tp) + } +} + +func readToken() ([]byte, error) { + f, err := os.Open(getTokenPath()) + if err != nil { + log.Println("Error: cannot open token file") + return nil, err + } + token, err := ioutil.ReadAll(f) + if err != nil { + log.Println("Error: cannot read token") + return nil, err + } + return token, nil +} + +func hasRecentToken() bool { + statinfo, err := os.Stat(getTokenPath()) + if err != nil { + return false + } + lastWrote := statinfo.ModTime().Unix() + /* in vpnweb we set the duration of the token to 24 hours */ + old := time.Now().Add(-time.Hour * 20).Unix() + return lastWrote >= old } func formatCredentials(user, pass string) (string, error) { diff --git a/pkg/vpn/bonafide/bonafide.go b/pkg/vpn/bonafide/bonafide.go index dd8c597..b81fd84 100644 --- a/pkg/vpn/bonafide/bonafide.go +++ b/pkg/vpn/bonafide/bonafide.go @@ -114,8 +114,18 @@ func New() *Bonafide { return b } +/* NeedsCredentials signals if we have to ask user for credentials. If false, it can be that we have a cached token */ func (b *Bonafide) NeedsCredentials() bool { - return b.auth.needsCredentials() + if !b.auth.needsCredentials() { + return false + } + /* try cached */ + /* TODO cleanup this call - maybe expose getCachedToken instead of relying on empty creds? */ + _, err := b.auth.getToken("", "") + if err != nil { + return true + } + return false } func (b *Bonafide) DoLogin(username, password string) (bool, error) { @@ -136,9 +146,13 @@ func (b *Bonafide) GetPemCertificate() ([]byte, error) { if b.auth == nil { log.Fatal("ERROR: bonafide did not initialize auth") } - if b.auth.needsCredentials() && b.token == nil { - log.Println("Needs token, but token is empty") - return nil, errors.New("Needs to login, but it was not logged in. Please, restart the application and report it if it continues happening") + if b.auth.needsCredentials() { + /* try cached token */ + token, err := b.auth.getToken("", "") + if err != nil { + return nil, errors.New("BUG: This service needs login, but we were not logged in.") + } + b.token = token } req, err := http.NewRequest("POST", b.getURL("certv3"), strings.NewReader("")) diff --git a/pkg/vpn/openvpn.go b/pkg/vpn/openvpn.go index 11bba69..6055e6a 100644 --- a/pkg/vpn/openvpn.go +++ b/pkg/vpn/openvpn.go @@ -51,14 +51,7 @@ func (b *Bitmask) StartVPN(provider string) error { } func (b *Bitmask) CanStartVPN() bool { - if !b.bonafide.NeedsCredentials() { - return true - } - _, err := b.getCert() - if err != nil { - return false - } - return true + return !b.bonafide.NeedsCredentials() } func (b *Bitmask) startTransport() (proxy string, err error) { |