]> git.wincent.com - passage.git/blob - passage.go
Write results back over socket
[passage.git] / passage.go
1 package main
2
3 import (
4         "encoding/json"
5         "github.com/keybase/go-keychain"
6         "log"
7         "net"
8         "os"
9         "os/signal"
10         "os/user"
11         "syscall"
12 )
13
14 type Request struct {
15         Account string
16         Service string
17 }
18
19 func main() {
20         path := getSockPath()
21         syscall.Umask(0077)
22         listener, err := net.Listen("unix", path)
23         if err != nil {
24                 log.Fatal(err)
25         }
26         defer listener.Close()
27
28         go func() {
29                 for {
30                         conn, err := listener.Accept()
31                         if err != nil {
32                                 log.Print(err)
33                                 return
34                         }
35                         go handleConnection(conn)
36                 }
37         }()
38         log.Print("Open and ready for business on UNIX socket at ", path)
39
40         // Need to catch signals in order for `defer`-ed clean-up items to run.
41         c := make(chan os.Signal, 1)
42         signal.Notify(c, os.Interrupt, os.Kill, syscall.SIGTERM)
43         sig := <-c
44         log.Print("Got signal ", sig)
45 }
46
47 func getSockPath() string {
48         user, err := user.Current()
49         if err != nil {
50                 log.Fatal(err)
51         }
52         return user.HomeDir + "/.passage.sock"
53 }
54
55 func handleConnection(conn net.Conn) {
56         defer conn.Close()
57         decoder := json.NewDecoder(conn)
58         var request Request
59         err := decoder.Decode(&request)
60         if err != nil {
61                 log.Print(err)
62                 return
63         }
64
65         query := keychain.NewItem()
66         query.SetSecClass(keychain.SecClassGenericPassword)
67         query.SetService(request.Service)
68         query.SetAccount(request.Account)
69         query.SetMatchLimit(keychain.MatchLimitOne)
70         query.SetReturnData(true)
71         results, err := keychain.QueryItem(query)
72         if err != nil {
73                 log.Print(err)
74         } else if len(results) != 1 {
75                 log.Print("Item not found")
76         } else {
77                 conn.Write(results[0].Data)
78                 log.Print("Wrote")
79         }
80 }