LEFT | RIGHT |
1 package test | 1 package test |
2 | 2 |
3 import ( | 3 import ( |
| 4 "crypto/rsa" |
4 "crypto/x509" | 5 "crypto/x509" |
5 "encoding/pem" | 6 "encoding/pem" |
6 "reflect" | 7 "reflect" |
7 "strings" | 8 "strings" |
8 "testing" | 9 "testing" |
9 | 10 |
10 "code.google.com/p/go.crypto/ssh" | 11 "code.google.com/p/go.crypto/ssh" |
11 ) | 12 ) |
12 | 13 |
13 var ( | 14 var ( |
| 15 validKey = `AAAAB3NzaC1yc2EAAAADAQABAAABAQDEX/dPu4PmtvgK3La9zioCEDrJ` + |
| 16 `yUr6xEIK7Pr+rLgydcqWTU/kt7w7gKjOw4vvzgHfjKl09CWyvgb+y5dCiTk` + |
| 17 `9MxI+erGNhs3pwaoS+EavAbawB7iEqYyTep3YaJK+4RJ4OX7ZlXMAIMrTL+` + |
| 18 `UVrK89t56hCkFYaAgo3VY+z6rb/b3bDBYtE1Y2tS7C3au73aDgeb9psIrSV` + |
| 19 `86ucKBTl5X62FnYiyGd++xCnLB6uLximM5OKXfLzJQNS/QyZyk12g3D8y69` + |
| 20 `Xw1GzCSKX1u1+MQboyf0HJcG2ryUCLHdcDVppApyHx2OLq53hlkQ/yxdflD` + |
| 21 `qCqAE4j+doagSsIfC1T2T` |
| 22 |
14 authWithOptions = []string{ | 23 authWithOptions = []string{ |
15 » » `environment="HOME=/home/root",no-port-forwarding ssh-rsa AAAAB3
NzaC1yc2EAAAADAQABAAABAQDEX/dPu4PmtvgK3La9zioCEDrJyUr6xEIK7Pr+rLgydcqWTU/kt7w7gK
jOw4vvzgHfjKl09CWyvgb+y5dCiTk9MxI+erGNhs3pwaoS+EavAbawB7iEqYyTep3YaJK+4RJ4OX7ZlX
MAIMrTL+UVrK89t56hCkFYaAgo3VY+z6rb/b3bDBYtE1Y2tS7C3au73aDgeb9psIrSV86ucKBTl5X62F
nYiyGd++xCnLB6uLximM5OKXfLzJQNS/QyZyk12g3D8y69Xw1GzCSKX1u1+MQboyf0HJcG2ryUCLHdcD
VppApyHx2OLq53hlkQ/yxdflDqCqAE4j+doagSsIfC1T2T user@host`, | 24 » » `# comments to ignore before any keys...`, |
| 25 » » ``, |
| 26 » » `env="HOME=/home/root",no-port-forwarding ssh-rsa ` + validKey +
` user@host`, |
16 `# comments to ignore, along with a blank line`, | 27 `# comments to ignore, along with a blank line`, |
17 ``, | 28 ``, |
18 » » `environment="HOME=/home/root2" ssh-rsa AAAAB3NzaC1yc2EAAAADAQAB
AAABAQDEX/dPu4PmtvgK3La9zioCEDrJyUr6xEIK7Pr+rLgydcqWTU/kt7w7gKjOw4vvzgHfjKl09CWy
vgb+y5dCiTk9MxI+erGNhs3pwaoS+EavAbawB7iEqYyTep3YaJK+4RJ4OX7ZlXMAIMrTL+UVrK89t56h
CkFYaAgo3VY+z6rb/b3bDBYtE1Y2tS7C3au73aDgeb9psIrSV86ucKBTl5X62FnYiyGd++xCnLB6uLxi
mM5OKXfLzJQNS/QyZyk12g3D8y69Xw1GzCSKX1u1+MQboyf0HJcG2ryUCLHdcDVppApyHx2OLq53hlkQ
/yxdflDqCqAE4j+doagSsIfC1T2T user2@host2`, | 29 » » `env="HOME=/home/root2" ssh-rsa ` + validKey + ` user2@host2`, |
19 ``, | 30 ``, |
20 `# more comments, plus a invalid entry`, | 31 `# more comments, plus a invalid entry`, |
21 `ssh-rsa data-that-will-not-parse user@host3`, | 32 `ssh-rsa data-that-will-not-parse user@host3`, |
22 } | 33 } |
23 | 34 |
24 » authOptions = strings.Join(authWithOptions, "\n") | 35 » authOptions = strings.Join(authWithOptions, "\n") |
25 » authWithCRLF = strings.Join(authWithOptions, "\r\n") | 36 » authWithCRLF = strings.Join(authWithOptions, "\r\n") |
26 » invalidEntry = []byte(`ssh-rsa`) | 37 » invalidEntry = []byte(`ssh-rsa`) |
27 » authWithSpaceInEnv = []byte(`environment="HOME=/home/root dir",no-port
-forwarding» ssh-rsa»AAAAB3NzaC1yc2EAAAADAQABAAABAQDEX/dPu4PmtvgK3La9zioCEDrJ
yUr6xEIK7Pr+rLgydcqWTU/kt7w7gKjOw4vvzgHfjKl09CWyvgb+y5dCiTk9MxI+erGNhs3pwaoS+Eav
AbawB7iEqYyTep3YaJK+4RJ4OX7ZlXMAIMrTL+UVrK89t56hCkFYaAgo3VY+z6rb/b3bDBYtE1Y2tS7C
3au73aDgeb9psIrSV86ucKBTl5X62FnYiyGd++xCnLB6uLximM5OKXfLzJQNS/QyZyk12g3D8y69Xw1G
zCSKX1u1+MQboyf0HJcG2ryUCLHdcDVppApyHx2OLq53hlkQ/yxdflDqCqAE4j+doagSsIfC1T2T use
r@host`) | 38 » authWithQuotedCommaInEnv = []byte(`env="HOME=/home/root,dir",no-port-for
warding ssh-rsa ` + validKey + ` user@host`) |
28 » authWithInvalidSpace = []byte(`environment="HOME=/home/root dir", no-por
t-forwarding» ssh-rsa»AAAAB3NzaC1yc2EAAAADAQABAAABAQDEX/dPu4PmtvgK3La9zioCEDrJ
yUr6xEIK7Pr+rLgydcqWTU/kt7w7gKjOw4vvzgHfjKl09CWyvgb+y5dCiTk9MxI+erGNhs3pwaoS+Eav
AbawB7iEqYyTep3YaJK+4RJ4OX7ZlXMAIMrTL+UVrK89t56hCkFYaAgo3VY+z6rb/b3bDBYtE1Y2tS7C
3au73aDgeb9psIrSV86ucKBTl5X62FnYiyGd++xCnLB6uLximM5OKXfLzJQNS/QyZyk12g3D8y69Xw1G
zCSKX1u1+MQboyf0HJcG2ryUCLHdcDVppApyHx2OLq53hlkQ/yxdflDqCqAE4j+doagSsIfC1T2T use
r@host`) | 39 » authWithQuotedSpaceInEnv = []byte(`env="HOME=/home/root dir",no-port-for
warding ssh-rsa ` + validKey + ` user@host`) |
| 40 » authWithQuotedQuoteInEnv = []byte(`env="HOME=/home/\"root dir",no-port-f
orwarding` + "\t" + `ssh-rsa` + "\t" + validKey + ` user@host`) |
| 41 |
| 42 » authWithDoubleQuotedQuote = []byte(`no-port-forwarding,env="HOME=/home/
\"root dir\"" ssh-rsa ` + validKey + "\t" + `user@host`) |
| 43 » authWithInvalidSpace = []byte(`env="HOME=/home/root dir", no-port-f
orwarding ssh-rsa ` + validKey + ` user@host |
| 44 #more to follow but still no valid keys`) |
| 45 » authWithMissingQuote = []byte(`env="HOME=/home/root,no-port-forwarding s
sh-rsa ` + validKey + ` user@host |
| 46 env="HOME=/home/root",shared-control ssh-rsa ` + validKey + ` user@host`) |
29 ) | 47 ) |
30 | 48 |
31 func TestMarshalParsePublicKey(t *testing.T) { | 49 func TestMarshalParsePublicKey(t *testing.T) { |
32 block, _ := pem.Decode([]byte(testClientPrivateKey)) | 50 block, _ := pem.Decode([]byte(testClientPrivateKey)) |
33 if block == nil { | 51 if block == nil { |
34 t.Fatalf("pem.Decode: %v", testClientPrivateKey) | 52 t.Fatalf("pem.Decode: %v", testClientPrivateKey) |
35 } | 53 } |
36 priv, err := x509.ParsePKCS1PrivateKey(block.Bytes) | 54 priv, err := x509.ParsePKCS1PrivateKey(block.Bytes) |
37 if err != nil { | 55 if err != nil { |
38 t.Fatalf("x509.ParsePKCS1PrivateKey: %v", err) | 56 t.Fatalf("x509.ParsePKCS1PrivateKey: %v", err) |
(...skipping 16 matching lines...) Expand all Loading... |
55 actPub, _, _, _, ok := ssh.ParseAuthorizedKey([]byte(keys["authorized_ke
ys"])) | 73 actPub, _, _, _, ok := ssh.ParseAuthorizedKey([]byte(keys["authorized_ke
ys"])) |
56 if !ok { | 74 if !ok { |
57 t.Fatalf("cannot parse %v", keys["authorized_keys"]) | 75 t.Fatalf("cannot parse %v", keys["authorized_keys"]) |
58 } | 76 } |
59 if !reflect.DeepEqual(actPub, pub) { | 77 if !reflect.DeepEqual(actPub, pub) { |
60 t.Errorf("got %v, expected %v", actPub, pub) | 78 t.Errorf("got %v, expected %v", actPub, pub) |
61 } | 79 } |
62 } | 80 } |
63 | 81 |
64 type authResult struct { | 82 type authResult struct { |
| 83 pubkey interface{} //*rsa.PublicKey |
65 options []string | 84 options []string |
66 comments string | 85 comments string |
| 86 rest string |
67 ok bool | 87 ok bool |
68 } | 88 } |
69 | 89 |
70 func testAuthorizedKeys(t *testing.T, authKeys []byte) { | 90 func testAuthorizedKeys(t *testing.T, authKeys []byte, expValues []authResult) { |
| 91 » var actPub interface{} |
| 92 » var actComment string |
| 93 » var actOptions []string |
| 94 » var rest []byte |
| 95 » var ok bool |
| 96 |
| 97 » rest = authKeys |
| 98 » actValues := make([]authResult, 0) |
| 99 » for len(rest) > 0 { |
| 100 » » in := rest |
| 101 » » actPub, actComment, actOptions, rest, ok = ssh.ParseAuthorizedKe
y(in) |
| 102 » » r := authResult{ |
| 103 » » » pubkey: actPub, |
| 104 » » » options: actOptions, |
| 105 » » » comments: actComment, |
| 106 » » » rest: string(rest), |
| 107 » » » ok: ok, |
| 108 » » } |
| 109 » » actValues = append(actValues, r) |
| 110 » } |
| 111 |
| 112 » if !reflect.DeepEqual(actValues, expValues) { |
| 113 » » t.Errorf("got %q, expected %q", actValues, expValues) |
| 114 » } |
| 115 |
| 116 } |
| 117 |
| 118 func getTestPublicKey(t *testing.T) *rsa.PublicKey { |
71 block, _ := pem.Decode([]byte(testClientPrivateKey)) | 119 block, _ := pem.Decode([]byte(testClientPrivateKey)) |
72 if block == nil { | 120 if block == nil { |
73 t.Fatalf("pem.Decode: %v", testClientPrivateKey) | 121 t.Fatalf("pem.Decode: %v", testClientPrivateKey) |
74 } | 122 } |
75 priv, err := x509.ParsePKCS1PrivateKey(block.Bytes) | 123 priv, err := x509.ParsePKCS1PrivateKey(block.Bytes) |
76 if err != nil { | 124 if err != nil { |
77 t.Fatalf("x509.ParsePKCS1PrivateKey: %v", err) | 125 t.Fatalf("x509.ParsePKCS1PrivateKey: %v", err) |
78 } | 126 } |
79 | 127 |
80 » expPub := &priv.PublicKey | 128 » return &priv.PublicKey |
81 | |
82 » expValues := []authResult{ | |
83 » » {[]string{`environment="HOME=/home/root"`, "no-port-forwarding"}
, "user@host", true}, | |
84 » » {[]string{`environment="HOME=/home/root2"`}, "user2@host2", true
}, | |
85 » » {nil, "", false}, | |
86 » » {[]string{`environment="HOME=/home/root dir"`, "no-port-forwardi
ng"}, "user@host", true}, | |
87 » » {nil, "", false}, | |
88 » } | |
89 » actPub, actComment, actOptions, rest, ok := ssh.ParseAuthorizedKey(authK
eys) | |
90 » actPub2, actComment2, actOptions2, rest2, ok2 := ssh.ParseAuthorizedKey(
rest) | |
91 » actPub3, actComment3, actOptions3, rest3, ok3 := ssh.ParseAuthorizedKey(
rest2) | |
92 » actPub4, actComment4, actOptions4, _, ok4 := ssh.ParseAuthorizedKey(auth
WithSpaceInEnv) | |
93 » actPub5, actComment5, actOptions5, rest5, ok5 := ssh.ParseAuthorizedKey(
authWithInvalidSpace) | |
94 | |
95 » actValues := []authResult{ | |
96 » » {actOptions, actComment, ok}, | |
97 » » {actOptions2, actComment2, ok2}, | |
98 » » {actOptions3, actComment3, ok3}, | |
99 » » {actOptions4, actComment4, ok4}, | |
100 » » {actOptions5, actComment5, ok5}, | |
101 » } | |
102 | |
103 » if !reflect.DeepEqual(actPub, expPub) { | |
104 » » t.Errorf("got %v, expected %v", actPub, expPub) | |
105 » } | |
106 » if !reflect.DeepEqual(actPub2, expPub) { | |
107 » » t.Errorf("got %v, expected %v", actPub2, expPub) | |
108 » } | |
109 » if !reflect.DeepEqual(actPub3, nil) { | |
110 » » t.Errorf("got %v, expected %v", actPub3, nil) | |
111 » } | |
112 » if !reflect.DeepEqual(actPub4, expPub) { | |
113 » » t.Errorf("got %v, expected %v", actPub4, expPub) | |
114 » } | |
115 » if !reflect.DeepEqual(actPub5, nil) { | |
116 » » t.Errorf("got %v, expected %v", actPub5, nil) | |
117 » } | |
118 » t.Logf("rest5 = %q", rest5) | |
119 » if !reflect.DeepEqual(actValues, expValues) { | |
120 » » t.Errorf("got %+v, expected %+v", actValues, expValues) | |
121 » } | |
122 | |
123 » if len(rest3) != 0 { | |
124 » » t.Errorf("got %q, expected %q", "", rest3) | |
125 » } | |
126 } | 129 } |
127 | 130 |
128 func TestAuth(t *testing.T) { | 131 func TestAuth(t *testing.T) { |
129 » testAuthorizedKeys(t, []byte(authOptions)) | 132 » pub := getTestPublicKey(t) |
| 133 » rest2 := strings.Join(authWithOptions[3:], "\n") |
| 134 » rest3 := strings.Join(authWithOptions[6:], "\n") |
| 135 » testAuthorizedKeys(t, []byte(authOptions), []authResult{ |
| 136 » » {pub, []string{`env="HOME=/home/root"`, "no-port-forwarding"}, "
user@host", rest2, true}, |
| 137 » » {pub, []string{`env="HOME=/home/root2"`}, "user2@host2", rest3,
true}, |
| 138 » » {nil, nil, "", "", false}, |
| 139 » }) |
130 } | 140 } |
| 141 |
131 func TestAuthWithCRLF(t *testing.T) { | 142 func TestAuthWithCRLF(t *testing.T) { |
132 » testAuthorizedKeys(t, []byte(authWithCRLF)) | 143 » pub := getTestPublicKey(t) |
| 144 » rest2 := strings.Join(authWithOptions[3:], "\r\n") |
| 145 » rest3 := strings.Join(authWithOptions[6:], "\r\n") |
| 146 » testAuthorizedKeys(t, []byte(authWithCRLF), []authResult{ |
| 147 » » {pub, []string{`env="HOME=/home/root"`, "no-port-forwarding"}, "
user@host", rest2, true}, |
| 148 » » {pub, []string{`env="HOME=/home/root2"`}, "user2@host2", rest3,
true}, |
| 149 » » {nil, nil, "", "", false}, |
| 150 » }) |
| 151 } |
| 152 |
| 153 func TestAuthWithQuotedSpaceInEnv(t *testing.T) { |
| 154 » pub := getTestPublicKey(t) |
| 155 » testAuthorizedKeys(t, []byte(authWithQuotedSpaceInEnv), []authResult{ |
| 156 » » {pub, []string{`env="HOME=/home/root dir"`, "no-port-forwarding"
}, "user@host", "", true}, |
| 157 » }) |
| 158 } |
| 159 |
| 160 func TestAuthWithQuotedCommaInEnv(t *testing.T) { |
| 161 » pub := getTestPublicKey(t) |
| 162 » testAuthorizedKeys(t, []byte(authWithQuotedCommaInEnv), []authResult{ |
| 163 » » {pub, []string{`env="HOME=/home/root,dir"`, "no-port-forwarding"
}, "user@host", "", true}, |
| 164 » }) |
| 165 } |
| 166 |
| 167 func TestAuthWithQuotedQuoteInEnv(t *testing.T) { |
| 168 » pub := getTestPublicKey(t) |
| 169 » testAuthorizedKeys(t, []byte(authWithQuotedQuoteInEnv), []authResult{ |
| 170 » » {pub, []string{`env="HOME=/home/\"root dir"`, "no-port-forwardin
g"}, "user@host", "", true}, |
| 171 » }) |
| 172 |
| 173 » testAuthorizedKeys(t, []byte(authWithDoubleQuotedQuote), []authResult{ |
| 174 » » {pub, []string{"no-port-forwarding", `env="HOME=/home/ \"root di
r\""`}, "user@host", "", true}, |
| 175 » }) |
| 176 |
| 177 } |
| 178 |
| 179 func TestAuthWithInvalidSpace(t *testing.T) { |
| 180 » testAuthorizedKeys(t, []byte(authWithInvalidSpace), []authResult{ |
| 181 » » {nil, nil, "", "", false}, |
| 182 » }) |
| 183 } |
| 184 |
| 185 func TestAuthWithMissingQuote(t *testing.T) { |
| 186 » pub := getTestPublicKey(t) |
| 187 » testAuthorizedKeys(t, []byte(authWithMissingQuote), []authResult{ |
| 188 » » {pub, []string{`env="HOME=/home/root"`, `shared-control`}, "user
@host", "", true}, |
| 189 » }) |
133 } | 190 } |
134 | 191 |
135 func TestInvalidEntry(t *testing.T) { | 192 func TestInvalidEntry(t *testing.T) { |
136 _, _, _, _, ok := ssh.ParseAuthorizedKey(invalidEntry) | 193 _, _, _, _, ok := ssh.ParseAuthorizedKey(invalidEntry) |
137 if ok { | 194 if ok { |
138 t.Errorf("Expected invalid entry, returned valid entry") | 195 t.Errorf("Expected invalid entry, returned valid entry") |
139 } | 196 } |
140 } | 197 } |
LEFT | RIGHT |