Author: Adam <git@apiote.xyz>
add option to block when keyring is not open
agent/client.go | 43 ++++++++++++++++++++++++++++++++++++++----- eeze.go | 33 ++++++++++++++++++++++++--------- go.mod | 9 ++++++--- go.sum | 23 +++++++++++++++++++++++ server/sync.go | 8 +++-----
diff --git a/agent/client.go b/agent/client.go index c315523de3ddbc91ee3020a94340a3b3d04115fa..fb320bb7ba670a7552c3faf3149abe40cb27b5e9 100644 --- a/agent/client.go +++ b/agent/client.go @@ -4,14 +4,21 @@ import ( "log" "net" "os" + "os/exec" "os/user" "git.sr.ht/~sircmpwn/go-bare" ) -func GetMasterPassword() (string, error) { +func GetMasterPassword(block bool) (string, error) { // todo memguard var masterPassword = "" + var command byte + if block { + command = 2 + } else { + command = 1 + } user, err := user.Current() if err != nil { log.Println("Error getting user ", err) @@ -26,7 +33,7 @@ return "", err } defer conn.Close() - _, err = conn.Write([]byte{1}) + _, err = conn.Write([]byte{command}) if err != nil { log.Println("Warning, cannot write to agent", err) return "", err @@ -42,10 +49,36 @@ return masterPassword, nil } // todo memguard -func GiveMasterPassword(masterPassword string) { - // todo implement GiveMasterPassword +func GiveMasterPassword(masterPassword string) error { + user, err := user.Current() + if err != nil { + log.Println("Error getting user ", err) + return err + } + fileInfo, err := os.Stat("/tmp/eeze-agent-" + user.Username) + if err == nil && fileInfo.Mode()&os.ModeSocket != 0 { + conn, err := net.Dial("unix", "/tmp/eeze-agent-"+user.Username) + if err != nil { + log.Println("Warning, cannot connect to agent", err) + return err + } + defer conn.Close() + + w := bare.NewWriter(conn) + err = w.WriteU8(0) + if err != nil { + log.Println("Warning, cannot write cmd to agent", err) + return err + } + err = w.WriteString(masterPassword) + if err != nil { + log.Println("Warning, cannot write password to agent", err) + return err + } + } + return nil } func StartAgent() { - // todo implement StartAgent + exec.Command("eeze-agent").Run() } diff --git a/eeze.go b/eeze.go index 1f01072f741290b8344fc1ef75fc59c1715f77e6..78e278753bed0d1874414fbaa65e83945241aad0 100644 --- a/eeze.go +++ b/eeze.go @@ -15,11 +15,23 @@ "git.sr.ht/~sircmpwn/getopt" ) +func rememberMasterPassword() string { + fmt.Print("Master password: ") + // todo memguard + masterPass_b, _ := terminal.ReadPassword(int(os.Stdin.Fd())) + // todo memguard + masterPassword := string(masterPass_b) + fmt.Print("\n") + agent.GiveMasterPassword(masterPassword) + return masterPassword +} + func main() { C := getopt.Bool("C", false, "Config") S := getopt.Bool("S", false, "Sync") L := getopt.Bool("L", false, "List") G := getopt.Bool("G", false, "Get") + P := getopt.Bool("P", false, "Put") var u string getopt.StringVar(&u, "u", "", "filter Get by username") @@ -32,6 +44,7 @@ p := getopt.Bool("p", false, "show just password in Get") i := getopt.Bool("i", false, "in Config: set server, username, password (initialise)") r := getopt.Bool("r", false, "in Config: reëncrypt (change master password)") n := getopt.Bool("n", false, "do not ask for anything, fail if password cannot be obtained from agent") + b := getopt.Bool("b", false, "block until password can be received from agent") err := getopt.Parse() if err != nil { @@ -39,10 +52,18 @@ log.Println("Error parsing opts. ", err) return } - masterPassword, err := agent.GetMasterPassword() + if *P { + _ = rememberMasterPassword() + return + } + + masterPassword, err := agent.GetMasterPassword(*b) + if masterPassword == "" && err == nil { + agent.StartAgent() + } + masterPassword, err = agent.GetMasterPassword(*b) if err != nil { log.Println("Error getting from agent", err) - agent.StartAgent() } if masterPassword == "" && !*C && *n { @@ -50,13 +71,7 @@ log.Fatalln("Password needed in non-interactive mode") } if masterPassword == "" || (*C && (*i || *r)) { - fmt.Print("Master password: ") - // todo memguard - masterPass_b, _ := terminal.ReadPassword(int(os.Stdin.Fd())) - // todo memguard - masterPassword = string(masterPass_b) - fmt.Print("\n") - agent.GiveMasterPassword(masterPassword) + masterPassword = rememberMasterPassword() } if *C { diff --git a/go.mod b/go.mod index e9cdc6c6e3d531e59a7c52e8c71baecefc5ca105..58a3ef030559e3272405877ca1a2d9b604283ce3 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,10 @@ go 1.15 require ( - git.sr.ht/~sircmpwn/getopt v0.0.0-20191230200459-23622cc906b3 - git.sr.ht/~sircmpwn/go-bare v0.0.0-20200812160916-d2c72e1a5018 - golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de + git.sr.ht/~sircmpwn/getopt v1.0.0 + git.sr.ht/~sircmpwn/go-bare v0.0.0-20210406120253-ab86bc2846d9 + github.com/keys-pub/go-libfido2 v1.5.2 // indirect + golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 + golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac // indirect + golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect ) diff --git a/go.sum b/go.sum index 52571e1349b657cc9f400629247b4910abb434f7..b8e8cc21a481a3982c6142cf7cd5e40f8321b72d 100644 --- a/go.sum +++ b/go.sum @@ -1,19 +1,42 @@ git.sr.ht/~sircmpwn/getopt v0.0.0-20191230200459-23622cc906b3 h1:4wDp4BKF7NQqoh73VXpZsB/t1OEhDpz/zEpmdQfbjDk= git.sr.ht/~sircmpwn/getopt v0.0.0-20191230200459-23622cc906b3/go.mod h1:wMEGFFFNuPos7vHmWXfszqImLppbc0wEhh6JBfJIUgw= +git.sr.ht/~sircmpwn/getopt v1.0.0 h1:/pRHjO6/OCbBF4puqD98n6xtPEgE//oq5U8NXjP7ROc= +git.sr.ht/~sircmpwn/getopt v1.0.0/go.mod h1:wMEGFFFNuPos7vHmWXfszqImLppbc0wEhh6JBfJIUgw= git.sr.ht/~sircmpwn/go-bare v0.0.0-20200812160916-d2c72e1a5018 h1:89QMorzx6ML69PKPoayL3HuSfb7WqAlxD1dZ7DyzD0k= git.sr.ht/~sircmpwn/go-bare v0.0.0-20200812160916-d2c72e1a5018/go.mod h1:BVJwbDfVjCjoFiKrhkei6NdGcZYpkDkdyCdg1ukytRA= +git.sr.ht/~sircmpwn/go-bare v0.0.0-20210406120253-ab86bc2846d9 h1:Ahny8Ud1LjVMMAlt8utUFKhhxJtwBAualvsbc/Sk7cE= +git.sr.ht/~sircmpwn/go-bare v0.0.0-20210406120253-ab86bc2846d9/go.mod h1:BVJwbDfVjCjoFiKrhkei6NdGcZYpkDkdyCdg1ukytRA= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/keys-pub/go-libfido2 v1.5.2 h1:YJVK9iMOMlfRZrEzZtnJBRNO+jYB+/sfNtO4ruV7BXI= +github.com/keys-pub/go-libfido2 v1.5.2/go.mod h1:P0V19qHwJNY0htZwZDe9Ilvs/nokGhdFX7faKFyZ6+U= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de h1:ikNHVSjEfnvz6sxdSPCaPt572qowuyMDMJLLm3Db3ig= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac h1:oN6lz7iLW/YC7un8pq+9bOLyXrprv2+DKfkJY+2LJJw= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/server/sync.go b/server/sync.go index e16920c19d57361a784d96e5db517874bf0495e0..87264cfd89f20f7f7db19157ffdf154cc3814d4d 100644 --- a/server/sync.go +++ b/server/sync.go @@ -22,8 +22,6 @@ // todo memguard credentials func open(credentials fs.Credentials) (string, error) { // todo memguard - authorization := base64.StdEncoding.EncodeToString([]byte(credentials.Username + ":" + credentials.Password)) - req, err := http.NewRequest("POST", credentials.Server+"/index.php/apps/passwords/api/1.0/session/open", bytes.NewBuffer([]byte("{}"))) @@ -34,9 +32,9 @@ return "", err } req.Header.Set("Accept", "application/json") - req.Header.Set("authorization", "Basic "+authorization) - - client := &http.Client{Timeout: time.Second * 10} + req.SetBasicAuth(credentials.Username, credentials.Password) + + client := &http.Client{Timeout: time.Second * 30} resp, err := client.Do(req) if err != nil {