blob: aa4b248976ce3b3d1490213bf30eabb95b96091b [file] [log] [blame]
Bogdan Caprita2b219362014-12-09 17:03:33 -08001// Package keymgr provides a client for the Device Manager to manage keys in
Ryan Brown81789442014-10-30 13:23:53 -07002// the "Agent" process.
3package keymgr
4
5import (
6 "net"
7 "os"
8 "strconv"
9 "sync"
10
Jiri Simsa6ac95222015-02-23 16:11:49 -080011 "v.io/v23/context"
12 "v.io/v23/verror"
Jiri Simsaffceefa2015-02-28 11:03:34 -080013 "v.io/x/ref/lib/unixfd"
14 "v.io/x/ref/security/agent/server"
Mike Burrows4b9b5d52014-12-05 18:08:07 -080015)
16
Jiri Simsaffceefa2015-02-28 11:03:34 -080017const pkgPath = "v.io/x/ref/security/agent/keymgr"
Mike Burrows4b9b5d52014-12-05 18:08:07 -080018
19// Errors
20var (
21 errInvalidResponse = verror.Register(pkgPath+".errInvalidResponse",
22 verror.NoRetry, "{1:}{2:} invalid response from agent. (expected {3} bytes, got {4})")
23 errInvalidKeyHandle = verror.Register(pkgPath+".errInvalidKeyHandle",
24 verror.NoRetry, "{1:}{2:} Invalid key handle")
Ryan Brown81789442014-10-30 13:23:53 -070025)
26
27const defaultManagerSocket = 4
28
29type Agent struct {
30 conn *net.UnixConn // Guarded by mu
31 mu sync.Mutex
32}
33
34// NewAgent returns a client connected to the agent on the default file descriptors.
35func NewAgent() (*Agent, error) {
36 return newAgent(defaultManagerSocket)
37}
38
Ryan Browna08a2212015-01-15 15:40:10 -080039func NewLocalAgent(ctx *context.T, path string, passphrase []byte) (*Agent, error) {
40 file, err := server.RunKeyManager(ctx, path, passphrase)
41 if err != nil {
42 return nil, err
43 }
Ryan Browna08a2212015-01-15 15:40:10 -080044 conn, err := net.FileConn(file)
45 if err != nil {
46 return nil, err
47 }
48 return &Agent{conn: conn.(*net.UnixConn)}, nil
49}
50
Ryan Brown81789442014-10-30 13:23:53 -070051func newAgent(fd int) (a *Agent, err error) {
52 file := os.NewFile(uintptr(fd), "fd")
53 defer file.Close()
54 conn, err := net.FileConn(file)
55 if err != nil {
56 return nil, err
57 }
58
59 return &Agent{conn: conn.(*net.UnixConn)}, nil
60}
61
Matt Rosencrantz4f8ac602014-12-29 14:42:48 -080062// TODO(caprita): Get rid of *context.T arg. Doesn't seem to be used.
Bogdan Caprita7f491672014-11-13 14:51:08 -080063
Ryan Brown81789442014-10-30 13:23:53 -070064// NewPrincipal creates a new principal and returns the handle and a socket serving
65// the principal.
66// Typically the socket will be passed to a child process using cmd.ExtraFiles.
Matt Rosencrantz4f8ac602014-12-29 14:42:48 -080067func (a *Agent) NewPrincipal(ctx *context.T, inMemory bool) (handle []byte, conn *os.File, err error) {
Ryan Brown81789442014-10-30 13:23:53 -070068 req := make([]byte, 1)
Bogdan Caprita7f491672014-11-13 14:51:08 -080069 if inMemory {
Ryan Brown81789442014-10-30 13:23:53 -070070 req[0] = 1
71 }
72 a.mu.Lock()
73 defer a.mu.Unlock()
74 conn, err = a.connect(req)
75 if err != nil {
76 return nil, nil, err
77 }
78 buf := make([]byte, server.PrincipalHandleByteSize)
79 n, err := a.conn.Read(buf)
80 if err != nil {
81 conn.Close()
82 return nil, nil, err
83 }
84 if n != server.PrincipalHandleByteSize {
85 conn.Close()
Todd Wangff73e1f2015-02-10 21:45:52 -080086 return nil, nil, verror.New(errInvalidResponse, ctx, server.PrincipalHandleByteSize, n)
Ryan Brown81789442014-10-30 13:23:53 -070087 }
88 return buf, conn, nil
89}
90
91func (a *Agent) connect(req []byte) (*os.File, error) {
Bogdan Capritabb37c542015-01-22 10:21:57 -080092 addr, err := unixfd.SendConnection(a.conn, req)
Ryan Brown81789442014-10-30 13:23:53 -070093 if err != nil {
94 return nil, err
95 }
96 fd, err := strconv.ParseInt(addr.String(), 10, 32)
97 if err != nil {
98 return nil, err
99 }
100 return os.NewFile(uintptr(fd), "client"), nil
101}
102
103// NewConnection creates a connection to an agent which exports a principal
104// previously created with NewPrincipal.
105// Typically this will be passed to a child process using cmd.ExtraFiles.
106func (a *Agent) NewConnection(handle []byte) (*os.File, error) {
107 if len(handle) != server.PrincipalHandleByteSize {
Todd Wangff73e1f2015-02-10 21:45:52 -0800108 return nil, verror.New(errInvalidKeyHandle, nil)
Ryan Brown81789442014-10-30 13:23:53 -0700109 }
110 a.mu.Lock()
111 defer a.mu.Unlock()
112 return a.connect(handle)
113}