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