blob: 99e512f0b0600f7dfb7d8230201d9ebfcaece7c1 [file] [log] [blame]
Asim Shankarae8d4c52014-10-08 13:03:31 -07001package security
2
3import (
Suharsh Sivakumaraca1c322014-10-21 11:27:32 -07004 "crypto/ecdsa"
5 "crypto/elliptic"
6 "crypto/rand"
Asim Shankarae8d4c52014-10-08 13:03:31 -07007 "io/ioutil"
8 "os"
Suharsh Sivakumaraca1c322014-10-21 11:27:32 -07009 "path"
gauthamtf8263932014-12-16 10:59:09 -080010 "reflect"
Asim Shankarae8d4c52014-10-08 13:03:31 -070011 "testing"
gauthamtf8263932014-12-16 10:59:09 -080012
Jiri Simsa764efb72014-12-25 20:57:03 -080013 "v.io/core/veyron2/security"
Asim Shankarae8d4c52014-10-08 13:03:31 -070014)
15
Suharsh Sivakumaraca1c322014-10-21 11:27:32 -070016func TestLoadPersistentPrincipal(t *testing.T) {
17 // If the directory does not exist want os.IsNotExists.
18 _, err := LoadPersistentPrincipal("/tmp/fake/path/", nil)
19 if !os.IsNotExist(err) {
20 t.Errorf("invalid path should return does not exist error, instead got %v", err)
21 }
22 // If the key file exists and is unencrypted we should succeed.
23 dir := generatePEMFile(nil)
24 if _, err = LoadPersistentPrincipal(dir, nil); err != nil {
25 t.Errorf("unencrypted LoadPersistentPrincipal should have succeeded: %v", err)
26 }
27 os.RemoveAll(dir)
28
29 // If the private key file exists and is encrypted we should succeed with correct passphrase.
30 passphrase := []byte("passphrase")
31 incorrect_passphrase := []byte("incorrect_passphrase")
32 dir = generatePEMFile(passphrase)
33 if _, err = LoadPersistentPrincipal(dir, passphrase); err != nil {
34 t.Errorf("encrypted LoadPersistentPrincipal should have succeeded: %v", err)
35 }
36 // and fail with an incorrect passphrase.
37 if _, err = LoadPersistentPrincipal(dir, incorrect_passphrase); err == nil {
38 t.Errorf("encrypted LoadPersistentPrincipal with incorrect passphrase should fail")
39 }
Suharsh Sivakumar4684f4e2014-10-24 13:42:06 -070040 // and return PassphraseError if the passphrase is nil.
41 if _, err = LoadPersistentPrincipal(dir, nil); err != PassphraseErr {
42 t.Errorf("encrypted LoadPersistentPrincipal with nil passphrase should return PassphraseErr: %v", err)
Suharsh Sivakumaraca1c322014-10-21 11:27:32 -070043 }
44 os.RemoveAll(dir)
45}
46
47func TestCreatePersistentPrincipal(t *testing.T) {
48 tests := []struct {
49 Message, Passphrase []byte
50 }{
51 {[]byte("unencrypted"), nil},
52 {[]byte("encrypted"), []byte("passphrase")},
53 }
54 for _, test := range tests {
55 testCreatePersistentPrincipal(t, test.Message, test.Passphrase)
56 }
57}
58
59func testCreatePersistentPrincipal(t *testing.T, message, passphrase []byte) {
Asim Shankarae8d4c52014-10-08 13:03:31 -070060 // Persistence of the BlessingRoots and BlessingStore objects is
61 // tested in other files. Here just test the persistence of the key.
Suharsh Sivakumaraca1c322014-10-21 11:27:32 -070062 dir, err := ioutil.TempDir("", "TestCreatePersistentPrincipal")
Asim Shankarae8d4c52014-10-08 13:03:31 -070063 if err != nil {
64 t.Fatal(err)
65 }
66 defer os.RemoveAll(dir)
67
Suharsh Sivakumaraca1c322014-10-21 11:27:32 -070068 p, err := CreatePersistentPrincipal(dir, passphrase)
Asim Shankarae8d4c52014-10-08 13:03:31 -070069 if err != nil {
70 t.Fatal(err)
71 }
gauthamtb7bb39b2014-11-10 11:40:41 -080072 _, err = CreatePersistentPrincipal(dir, passphrase)
Ankur4704f5f2014-10-23 12:40:54 -070073 if err == nil {
74 t.Error("CreatePersistentPrincipal passed unexpectedly")
75 }
Ankur4704f5f2014-10-23 12:40:54 -070076
Asim Shankarae8d4c52014-10-08 13:03:31 -070077 sig, err := p.Sign(message)
78 if err != nil {
79 t.Fatal(err)
80 }
81
Ankur4704f5f2014-10-23 12:40:54 -070082 p2, err := LoadPersistentPrincipal(dir, passphrase)
Asim Shankarae8d4c52014-10-08 13:03:31 -070083 if err != nil {
Suharsh Sivakumar8a7fba42014-10-27 12:40:48 -070084 t.Fatalf("%s failed: %v", message, err)
Asim Shankarae8d4c52014-10-08 13:03:31 -070085 }
Ankur4704f5f2014-10-23 12:40:54 -070086 if !sig.Verify(p2.PublicKey(), message) {
Suharsh Sivakumaraca1c322014-10-21 11:27:32 -070087 t.Errorf("%s failed: p.PublicKey=%v, p2.PublicKey=%v", message, p.PublicKey(), p2.PublicKey())
Asim Shankarae8d4c52014-10-08 13:03:31 -070088 }
89}
Suharsh Sivakumaraca1c322014-10-21 11:27:32 -070090
91func generatePEMFile(passphrase []byte) (dir string) {
92 dir, err := ioutil.TempDir("", "TestLoadPersistentPrincipal")
93 if err != nil {
94 panic(err)
95 }
96 key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
97 if err != nil {
98 panic(err)
99 }
100 f, err := os.Create(path.Join(dir, privateKeyFile))
101 if err != nil {
102 panic(err)
103 }
104 defer f.Close()
Ankur73e7a932014-10-24 15:57:03 -0700105 if err = SavePEMKey(f, key, passphrase); err != nil {
Suharsh Sivakumaraca1c322014-10-21 11:27:32 -0700106 panic(err)
107 }
108 return dir
109}
gauthamtf8263932014-12-16 10:59:09 -0800110
111func TestPrincipalBlessingsByName(t *testing.T) {
112 var p1, p2, p3 security.Principal
113 var err error
114
115 if p1, err = NewPrincipal(); err != nil {
116 t.Fatal(err)
117 }
118 if p2, err = NewPrincipal(); err != nil {
119 t.Fatal(err)
120 }
121 alice, err := p1.BlessSelf("alice")
122 if err != nil {
123 t.Fatal(err)
124 }
125 p2.AddToRoots(alice)
126 var aliceworkfriend, alicegymfriend, aliceworkboss security.Blessings
127
128 if aliceworkfriend, err = p1.Bless(p2.PublicKey(), alice, "work/friend", security.UnconstrainedUse()); err != nil {
129 t.Errorf("Bless(work/friend) failed: %v", err)
130 }
131 p2.BlessingStore().Set(aliceworkfriend, "alice/work/friend")
132 if alicegymfriend, err = p1.Bless(p2.PublicKey(), alice, "gym/friend", security.UnconstrainedUse()); err != nil {
133 t.Errorf("Bless(gym/friend) failed: %v", err)
134 }
135 p2.BlessingStore().Set(alicegymfriend, "alice/gym/friend")
136 if aliceworkboss, err = p1.Bless(p2.PublicKey(), alice, "work/boss", security.UnconstrainedUse()); err != nil {
137 t.Errorf("Bless(work/friend) failed: %v", err)
138 }
139 p2.BlessingStore().Set(aliceworkboss, "alice/work/boss")
140
141 // Blessing from an untrusted principal that should never be returned
142 if p3, err = NewPrincipal(); err != nil {
143 t.Fatal(err)
144 }
145 fake, err := p3.BlessSelf("alice")
146 if err != nil {
147 t.Fatal(err)
148 }
149 fakefriend, err := p3.Bless(p2.PublicKey(), fake, "work/friend", security.UnconstrainedUse())
150 if err != nil {
151 t.Errorf("Bless(work/friend) failed: %v", err)
152 }
153 _, err = p2.BlessingStore().Set(fakefriend, "fake/work/friend")
154
155 tests := []struct {
156 matched []security.Blessings
157 pattern security.BlessingPattern
158 }{
159 {
160 matched: []security.Blessings{aliceworkfriend, aliceworkboss},
Ankur78b8b2a2015-02-04 20:16:28 -0800161 pattern: "alice/work",
gauthamtf8263932014-12-16 10:59:09 -0800162 },
163 {
164 matched: []security.Blessings{aliceworkfriend},
165 pattern: "alice/work/friend",
166 },
167 {
168 matched: []security.Blessings{alicegymfriend},
169 pattern: "alice/gym/friend",
170 },
171 {
172 matched: []security.Blessings{aliceworkfriend, alicegymfriend, aliceworkboss},
Ankur78b8b2a2015-02-04 20:16:28 -0800173 pattern: "alice",
gauthamtf8263932014-12-16 10:59:09 -0800174 },
175 {
176 matched: []security.Blessings{aliceworkfriend, alicegymfriend, aliceworkboss},
Ankur78b8b2a2015-02-04 20:16:28 -0800177 pattern: security.AllPrincipals,
gauthamtf8263932014-12-16 10:59:09 -0800178 },
179 {
180 matched: nil,
Ankur78b8b2a2015-02-04 20:16:28 -0800181 pattern: "alice/school",
gauthamtf8263932014-12-16 10:59:09 -0800182 },
183 }
184
185 for _, test := range tests {
186 matched := p2.BlessingsByName(test.pattern)
187 if len(matched) != len(test.matched) {
188 t.Errorf("BlessingsByName(%s) did not return expected number of matches wanted:%d got:%d", test.pattern, len(test.matched), len(matched))
189 }
190 for _, m := range matched {
191 found := false
192 for _, tm := range test.matched {
193 if reflect.DeepEqual(m, tm) {
194 found = true
195 break
196 }
197 }
198 if !found {
199 t.Errorf("Invalid blessing was returned as a match:%v for pattern:%s", m, test.pattern)
200 }
201 }
202 }
203}