github.com/devops-filetransfer/sshego@v7.0.4+incompatible/knownhosts_test.go (about) 1 package sshego 2 3 import ( 4 "context" 5 "fmt" 6 "testing" 7 8 "github.com/glycerine/sshego/xendor/github.com/glycerine/xcryptossh" 9 10 cv "github.com/glycerine/goconvey/convey" 11 ) 12 13 func Test301ReadKnownHosts(t *testing.T) { 14 15 cv.Convey("LoadSshKnownHosts() should read a known hosts file.", t, func() { 16 h, err := LoadSshKnownHosts("./testdata/fake_known_hosts") 17 panicOn(err) 18 cv.So(len(h.Hosts), cv.ShouldEqual, 4) 19 // spot check 20 a, ok := h.Hosts["ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDV9+u9lgOMCrRcRa3CR76eQkoJVFauaCUu7P9XasMCpWaWYK/yGqo/WuMEiA3kysAjPyfBSZ9vkOsJIVlnsgKfQqXXmE1yIQeS0qFz+bHx5QaM4zNTLnh5HcXvs5V//831VvHnwqWCapiUj/akyFc8TQaGmUJ0IzQNF5Z1U6brTFv6w5IVO59dJUCUWwr2x08ol+NKTjMIsTtkaqLE2wDZJNUCjKDHzKDGtz1uM+do1we59PrQ3fLK1wVquiNWG9eG9qsylusJaw8IRQu7VtYLq7Y0hv/SXjzv5rULODdnoQhuKkSz/pG3BwyTkZS/Id2aI4gbRLb40pbNDFZx2iY7jyDFyqlaf2mQRFw7lTrjahTfTtpJpTl5VqJMq6+fVV1sx5YkTaCP/uELd8aTk/KdagDOnSv8s+7utz6TW43L1fJl2Ucwmvb8SvByoLZdbphnUhHxhkJ++UaDBRUpqptT2V+tyjP0mCo6GddJbFPiK6nE2DhWqrVhzo3BkkyPeA0L+VTQnF7dTmgInAjat+eU9IooYUFofkrTq+15iJxW7mNY2wp2sUCi94zCzHi9KvkMHv9tVqOU24dJCfUzXEqdYDmTt04DUtDqYB9w3THQFz6a3bdKcB1zbWXH36/6yhdocfu+lPmb9nMbpLChXMRuaSjBSRbpzcVnKxXoTFrCjw==\n"] 21 cv.So(ok, cv.ShouldBeTrue) 22 23 cv.So(a.Hostname, cv.ShouldEqual, "10.0.0.200:22") 24 25 b, ok := h.Hosts["ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC9hxNTsXHBIuWdc0SZAwN6Bytwr5vCB2K7rf5yVoC5YX5Hb08c25Xd5sGhehAj8RXooNxCa62mDnk/ACcByDa35gv3HyDqm1kmFLNvM/OcNNmK2FCuIdwKG7QWjmZwIwS3eCudJjDGR3qUTUzZbLpV80eZ0WxYE/CbZdb9gx6lNSAWx+ZaeGTt9M0sD5AfEHSxg2lJFaA5pa0Zaaq4QoultLtfisEnTHKCprjRc9RHuZ0l4kwi2eLtBdMmvR3Guk+wrd/qy6+S2zqn4WMDgE50VE6B6ODXN5nsFGrKfqx4mRD3dic28j1rJ7JVkc8sz8/tI+Mr4onomLZftbAFa5dwdiXtqDbOJlxe4sd4oVDImpocAtk+aIqupqN+Sc0JxCGlNvo5eKdNBZP7u/9UC7eee7Y7lHYRmhzoC7FSzFL1/mGgVxrEljcp8UZ1OD47Aq0XYvJA+5MAElbgWrK+M+EMwOGA85qQES5xtvfyVlnNvked6GQlfEuckM6H5bQCIdGkeuJ/+eWWW0rXNVkYHwA4EdiIaAXya4pO439kZfip/gWFF4mazHKCYOQAKndusFSOvxyWOTY/EbSrI7BYoYwm1WR75q7OozJTYP0V3UO+lQ+0/RgSh2uEqyfqB+EMZlATWBl3QnjxKHm7R0dVPnk9qpsjlVXGgGCCWn1UVHKq8w==\n"] 26 cv.So(ok, cv.ShouldBeTrue) 27 28 cv.So(b.Hostname, cv.ShouldEqual, "10.0.0.201:22") 29 30 }) 31 } 32 33 func Test302ReadKnownHosts(t *testing.T) { 34 35 cv.Convey("LoadSshKnownHosts() should read a known hosts file.", t, func() { 36 37 fmt.Printf("\n when a client connects to a new unknown host with -new or TofuAddIfNotKnown=true, we should record the new host in the known hosts file\n") 38 39 // start a simple TCP server that is the target of the forward through the sshd, 40 // so we can confirm the client has made the connection. 41 42 // generate a random payload for the client to send to the server. 43 payloadByteCount := 50 44 confirmationPayload := RandomString(payloadByteCount) 45 confirmationReply := RandomString(payloadByteCount) 46 47 serverDone := ssh.NewHalter() 48 49 tcpSrvLsn, tcpSrvPort := GetAvailPort() 50 51 StartBackgroundTestTcpServer( 52 serverDone, 53 payloadByteCount, 54 confirmationPayload, 55 confirmationReply, 56 tcpSrvLsn, nil) 57 58 s := MakeTestSshClientAndServer(true) 59 defer TempDirCleanup(s.SrvCfg.Origdir, s.SrvCfg.Tempdir) 60 61 fmt.Printf("\n tell the server to represent itself as B so we can add its key\n") 62 bPubKey, err := s.SrvCfg.HostDb.adoptNewHostKeyFromPath(s.SrvCfg.Tempdir + "/testdata/id_rsa_b") 63 panicOn(err) 64 sbPubKey := string(ssh.MarshalAuthorizedKey(bPubKey)) 65 fmt.Printf("\n we had the server adopt public key '%s'\n", sbPubKey) 66 67 // also have to update the Esshd auth state on the update channel: 68 s.SrvCfg.Esshd.updateHostKey <- s.SrvCfg.HostDb.HostSshSigner 69 70 dest := fmt.Sprintf("127.0.0.1:%v", tcpSrvPort) 71 72 pp("just prior to manual NewKnownHosts call") 73 cliKnownHosts, err := NewKnownHosts(s.CliCfg.ClientKnownHostsPath, KHSsh) 74 panicOn(err) 75 76 cv.So(len(cliKnownHosts.Hosts), cv.ShouldEqual, 3) 77 78 // verify that read of known hosts lacks B 79 _, ok := cliKnownHosts.Hosts["ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC9hxNTsXHBIuWdc0SZAwN6Bytwr5vCB2K7rf5yVoC5YX5Hb08c25Xd5sGhehAj8RXooNxCa62mDnk/ACcByDa35gv3HyDqm1kmFLNvM/OcNNmK2FCuIdwKG7QWjmZwIwS3eCudJjDGR3qUTUzZbLpV80eZ0WxYE/CbZdb9gx6lNSAWx+ZaeGTt9M0sD5AfEHSxg2lJFaA5pa0Zaaq4QoultLtfisEnTHKCprjRc9RHuZ0l4kwi2eLtBdMmvR3Guk+wrd/qy6+S2zqn4WMDgE50VE6B6ODXN5nsFGrKfqx4mRD3dic28j1rJ7JVkc8sz8/tI+Mr4onomLZftbAFa5dwdiXtqDbOJlxe4sd4oVDImpocAtk+aIqupqN+Sc0JxCGlNvo5eKdNBZP7u/9UC7eee7Y7lHYRmhzoC7FSzFL1/mGgVxrEljcp8UZ1OD47Aq0XYvJA+5MAElbgWrK+M+EMwOGA85qQES5xtvfyVlnNvked6GQlfEuckM6H5bQCIdGkeuJ/+eWWW0rXNVkYHwA4EdiIaAXya4pO439kZfip/gWFF4mazHKCYOQAKndusFSOvxyWOTY/EbSrI7BYoYwm1WR75q7OozJTYP0V3UO+lQ+0/RgSh2uEqyfqB+EMZlATWBl3QnjxKHm7R0dVPnk9qpsjlVXGgGCCWn1UVHKq8w==\n"] 80 cv.So(ok, cv.ShouldBeFalse) 81 82 // but A should have loaded just fine 83 _, ok = cliKnownHosts.Hosts["ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDV9+u9lgOMCrRcRa3CR76eQkoJVFauaCUu7P9XasMCpWaWYK/yGqo/WuMEiA3kysAjPyfBSZ9vkOsJIVlnsgKfQqXXmE1yIQeS0qFz+bHx5QaM4zNTLnh5HcXvs5V//831VvHnwqWCapiUj/akyFc8TQaGmUJ0IzQNF5Z1U6brTFv6w5IVO59dJUCUWwr2x08ol+NKTjMIsTtkaqLE2wDZJNUCjKDHzKDGtz1uM+do1we59PrQ3fLK1wVquiNWG9eG9qsylusJaw8IRQu7VtYLq7Y0hv/SXjzv5rULODdnoQhuKkSz/pG3BwyTkZS/Id2aI4gbRLb40pbNDFZx2iY7jyDFyqlaf2mQRFw7lTrjahTfTtpJpTl5VqJMq6+fVV1sx5YkTaCP/uELd8aTk/KdagDOnSv8s+7utz6TW43L1fJl2Ucwmvb8SvByoLZdbphnUhHxhkJ++UaDBRUpqptT2V+tyjP0mCo6GddJbFPiK6nE2DhWqrVhzo3BkkyPeA0L+VTQnF7dTmgInAjat+eU9IooYUFofkrTq+15iJxW7mNY2wp2sUCi94zCzHi9KvkMHv9tVqOU24dJCfUzXEqdYDmTt04DUtDqYB9w3THQFz6a3bdKcB1zbWXH36/6yhdocfu+lPmb9nMbpLChXMRuaSjBSRbpzcVnKxXoTFrCjw==\n"] 84 cv.So(ok, cv.ShouldBeTrue) 85 86 // below over SSH should be equivalent of the following 87 // non-encrypted ping/pong. 88 89 dc := DialConfig{ 90 ClientKnownHostsPath: s.CliCfg.ClientKnownHostsPath, 91 KnownHosts: cliKnownHosts, 92 Mylogin: s.Mylogin, 93 RsaPath: s.RsaPath, 94 TotpUrl: s.Totp, 95 Pw: s.Pw, 96 Sshdhost: s.SrvCfg.EmbeddedSSHd.Host, 97 Sshdport: s.SrvCfg.EmbeddedSSHd.Port, 98 DownstreamHostPort: dest, 99 TofuAddIfNotKnown: true, 100 } 101 ctx := context.Background() 102 103 // first time we add the server key 104 channelToTcpServer, _, _, err := dc.Dial(ctx, nil, false) 105 cv.So(err.Error(), cv.ShouldContainSubstring, "Re-run without -new") 106 107 fmt.Printf("\n now host key B should be known.\n") 108 cv.So(len(cliKnownHosts.Hosts), cv.ShouldEqual, 4) 109 110 // show the hosts: 111 i := 0 112 for k := range cliKnownHosts.Hosts { 113 fmt.Printf("%v: we known about host k = '%v'\n", i, k) 114 i++ 115 } 116 117 // verify that hostkey for B is now present 118 _, ok = cliKnownHosts.Hosts["ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC9hxNTsXHBIuWdc0SZAwN6Bytwr5vCB2K7rf5yVoC5YX5Hb08c25Xd5sGhehAj8RXooNxCa62mDnk/ACcByDa35gv3HyDqm1kmFLNvM/OcNNmK2FCuIdwKG7QWjmZwIwS3eCudJjDGR3qUTUzZbLpV80eZ0WxYE/CbZdb9gx6lNSAWx+ZaeGTt9M0sD5AfEHSxg2lJFaA5pa0Zaaq4QoultLtfisEnTHKCprjRc9RHuZ0l4kwi2eLtBdMmvR3Guk+wrd/qy6+S2zqn4WMDgE50VE6B6ODXN5nsFGrKfqx4mRD3dic28j1rJ7JVkc8sz8/tI+Mr4onomLZftbAFa5dwdiXtqDbOJlxe4sd4oVDImpocAtk+aIqupqN+Sc0JxCGlNvo5eKdNBZP7u/9UC7eee7Y7lHYRmhzoC7FSzFL1/mGgVxrEljcp8UZ1OD47Aq0XYvJA+5MAElbgWrK+M+EMwOGA85qQES5xtvfyVlnNvked6GQlfEuckM6H5bQCIdGkeuJ/+eWWW0rXNVkYHwA4EdiIaAXya4pO439kZfip/gWFF4mazHKCYOQAKndusFSOvxyWOTY/EbSrI7BYoYwm1WR75q7OozJTYP0V3UO+lQ+0/RgSh2uEqyfqB+EMZlATWBl3QnjxKHm7R0dVPnk9qpsjlVXGgGCCWn1UVHKq8w==\n"] 119 cv.So(ok, cv.ShouldBeTrue) 120 121 // second time we connect based on that server key 122 dc.TofuAddIfNotKnown = false 123 channelToTcpServer, _, _, err = dc.Dial(ctx, nil, false) 124 cv.So(err, cv.ShouldBeNil) 125 126 VerifyClientServerExchangeAcrossSshd(channelToTcpServer, confirmationPayload, confirmationReply, payloadByteCount) 127 channelToTcpServer.Close() 128 129 // tcp-server should have exited because it got the expected 130 // message and replied with the agreed upon reply and then exited. 131 serverDone.RequestStop() 132 <-serverDone.DoneChan() 133 134 // done with testing, cleanup 135 s.SrvCfg.Esshd.Stop() 136 <-s.SrvCfg.Esshd.Halt.DoneChan() 137 cv.So(true, cv.ShouldEqual, true) // we should get here. 138 139 }) 140 } 141 142 func (s *TestSetup) forTestingUpdateServerHostKey(path string) (sbPubKey string) { 143 144 bPubKey, err := s.SrvCfg.HostDb.adoptNewHostKeyFromPath(path) 145 panicOn(err) 146 sbPubKey = string(ssh.MarshalAuthorizedKey(bPubKey)) 147 fmt.Printf("\n we had the server adopt public key '%s'\n", sbPubKey) 148 149 // also have to update the Esshd auth state on the update channel: 150 s.SrvCfg.Esshd.updateHostKey <- s.SrvCfg.HostDb.HostSshSigner 151 return 152 } 153 154 func Test303DedupKnownHosts(t *testing.T) { 155 156 cv.Convey("known hosts should be deduplicated and not add to the known hosts file every time the same server as before is contacted", t, func() { 157 158 payloadByteCount := 50 159 confirmationPayload := RandomString(payloadByteCount) 160 confirmationReply := RandomString(payloadByteCount) 161 162 serverDone := ssh.NewHalter() 163 164 tcpSrvLsn, tcpSrvPort := GetAvailPort() 165 166 StartBackgroundTestTcpServer( 167 serverDone, 168 payloadByteCount, 169 confirmationPayload, 170 confirmationReply, 171 tcpSrvLsn, nil) 172 173 s := MakeTestSshClientAndServer(true) 174 defer TempDirCleanup(s.SrvCfg.Origdir, s.SrvCfg.Tempdir) 175 176 fmt.Printf("\n tell the server to represent itself as B so we can add its key\n") 177 s.forTestingUpdateServerHostKey(s.SrvCfg.Tempdir + "/testdata/id_rsa_b") 178 179 dest := fmt.Sprintf("127.0.0.1:%v", tcpSrvPort) 180 181 pp("just prior to manual NewKnownHosts call") 182 cliKnownHosts, err := NewKnownHosts(s.CliCfg.ClientKnownHostsPath, KHSsh) 183 panicOn(err) 184 185 p("cliKnownHosts.Hosts=(len %v) '%#v'", len(cliKnownHosts.Hosts), cliKnownHosts.Hosts) 186 cv.So(len(cliKnownHosts.Hosts), cv.ShouldEqual, 3) 187 188 // verify that read of known hosts lacks B 189 _, ok := cliKnownHosts.Hosts["ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC9hxNTsXHBIuWdc0SZAwN6Bytwr5vCB2K7rf5yVoC5YX5Hb08c25Xd5sGhehAj8RXooNxCa62mDnk/ACcByDa35gv3HyDqm1kmFLNvM/OcNNmK2FCuIdwKG7QWjmZwIwS3eCudJjDGR3qUTUzZbLpV80eZ0WxYE/CbZdb9gx6lNSAWx+ZaeGTt9M0sD5AfEHSxg2lJFaA5pa0Zaaq4QoultLtfisEnTHKCprjRc9RHuZ0l4kwi2eLtBdMmvR3Guk+wrd/qy6+S2zqn4WMDgE50VE6B6ODXN5nsFGrKfqx4mRD3dic28j1rJ7JVkc8sz8/tI+Mr4onomLZftbAFa5dwdiXtqDbOJlxe4sd4oVDImpocAtk+aIqupqN+Sc0JxCGlNvo5eKdNBZP7u/9UC7eee7Y7lHYRmhzoC7FSzFL1/mGgVxrEljcp8UZ1OD47Aq0XYvJA+5MAElbgWrK+M+EMwOGA85qQES5xtvfyVlnNvked6GQlfEuckM6H5bQCIdGkeuJ/+eWWW0rXNVkYHwA4EdiIaAXya4pO439kZfip/gWFF4mazHKCYOQAKndusFSOvxyWOTY/EbSrI7BYoYwm1WR75q7OozJTYP0V3UO+lQ+0/RgSh2uEqyfqB+EMZlATWBl3QnjxKHm7R0dVPnk9qpsjlVXGgGCCWn1UVHKq8w==\n"] 190 cv.So(ok, cv.ShouldBeFalse) 191 192 // but A should have loaded just fine 193 _, ok = cliKnownHosts.Hosts["ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDV9+u9lgOMCrRcRa3CR76eQkoJVFauaCUu7P9XasMCpWaWYK/yGqo/WuMEiA3kysAjPyfBSZ9vkOsJIVlnsgKfQqXXmE1yIQeS0qFz+bHx5QaM4zNTLnh5HcXvs5V//831VvHnwqWCapiUj/akyFc8TQaGmUJ0IzQNF5Z1U6brTFv6w5IVO59dJUCUWwr2x08ol+NKTjMIsTtkaqLE2wDZJNUCjKDHzKDGtz1uM+do1we59PrQ3fLK1wVquiNWG9eG9qsylusJaw8IRQu7VtYLq7Y0hv/SXjzv5rULODdnoQhuKkSz/pG3BwyTkZS/Id2aI4gbRLb40pbNDFZx2iY7jyDFyqlaf2mQRFw7lTrjahTfTtpJpTl5VqJMq6+fVV1sx5YkTaCP/uELd8aTk/KdagDOnSv8s+7utz6TW43L1fJl2Ucwmvb8SvByoLZdbphnUhHxhkJ++UaDBRUpqptT2V+tyjP0mCo6GddJbFPiK6nE2DhWqrVhzo3BkkyPeA0L+VTQnF7dTmgInAjat+eU9IooYUFofkrTq+15iJxW7mNY2wp2sUCi94zCzHi9KvkMHv9tVqOU24dJCfUzXEqdYDmTt04DUtDqYB9w3THQFz6a3bdKcB1zbWXH36/6yhdocfu+lPmb9nMbpLChXMRuaSjBSRbpzcVnKxXoTFrCjw==\n"] 194 cv.So(ok, cv.ShouldBeTrue) 195 196 // below over SSH should be equivalent of the following 197 // non-encrypted ping/pong. 198 199 dc := DialConfig{ 200 ClientKnownHostsPath: s.CliCfg.ClientKnownHostsPath, 201 KnownHosts: cliKnownHosts, 202 Mylogin: s.Mylogin, 203 RsaPath: s.RsaPath, 204 TotpUrl: s.Totp, 205 Pw: s.Pw, 206 Sshdhost: s.SrvCfg.EmbeddedSSHd.Host, 207 Sshdport: s.SrvCfg.EmbeddedSSHd.Port, 208 DownstreamHostPort: dest, 209 TofuAddIfNotKnown: true, 210 } 211 ctx := context.Background() 212 213 // first time we add the server key 214 channelToTcpServer, _, _, err := dc.Dial(ctx, nil, false) 215 cv.So(err.Error(), cv.ShouldContainSubstring, "Re-run without -new") 216 217 fmt.Printf("\n now host key B should be known.\n") 218 cv.So(len(cliKnownHosts.Hosts), cv.ShouldEqual, 4) 219 220 // verify that hostkey for B is now present 221 _, ok = cliKnownHosts.Hosts["ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC9hxNTsXHBIuWdc0SZAwN6Bytwr5vCB2K7rf5yVoC5YX5Hb08c25Xd5sGhehAj8RXooNxCa62mDnk/ACcByDa35gv3HyDqm1kmFLNvM/OcNNmK2FCuIdwKG7QWjmZwIwS3eCudJjDGR3qUTUzZbLpV80eZ0WxYE/CbZdb9gx6lNSAWx+ZaeGTt9M0sD5AfEHSxg2lJFaA5pa0Zaaq4QoultLtfisEnTHKCprjRc9RHuZ0l4kwi2eLtBdMmvR3Guk+wrd/qy6+S2zqn4WMDgE50VE6B6ODXN5nsFGrKfqx4mRD3dic28j1rJ7JVkc8sz8/tI+Mr4onomLZftbAFa5dwdiXtqDbOJlxe4sd4oVDImpocAtk+aIqupqN+Sc0JxCGlNvo5eKdNBZP7u/9UC7eee7Y7lHYRmhzoC7FSzFL1/mGgVxrEljcp8UZ1OD47Aq0XYvJA+5MAElbgWrK+M+EMwOGA85qQES5xtvfyVlnNvked6GQlfEuckM6H5bQCIdGkeuJ/+eWWW0rXNVkYHwA4EdiIaAXya4pO439kZfip/gWFF4mazHKCYOQAKndusFSOvxyWOTY/EbSrI7BYoYwm1WR75q7OozJTYP0V3UO+lQ+0/RgSh2uEqyfqB+EMZlATWBl3QnjxKHm7R0dVPnk9qpsjlVXGgGCCWn1UVHKq8w==\n"] 222 cv.So(ok, cv.ShouldBeTrue) 223 224 // second time we connect based on that server key 225 dc.TofuAddIfNotKnown = false 226 channelToTcpServer, _, _, err = dc.Dial(ctx, nil, false) 227 cv.So(err, cv.ShouldBeNil) 228 229 VerifyClientServerExchangeAcrossSshd(channelToTcpServer, confirmationPayload, confirmationReply, payloadByteCount) 230 channelToTcpServer.Close() 231 232 // tcp-server should have exited because it got the expected 233 // message and replied with the agreed upon reply and then exited. 234 serverDone.RequestStop() 235 <-serverDone.DoneChan() 236 237 // now, the point of 303: connecting to a *2nd* sshd server with 238 // a different IP address but the same server key should 239 // result in de-duplication. 240 241 serverDone = ssh.NewHalter() 242 243 tcpSrvLsn, tcpSrvPort = GetAvailPort() 244 245 StartBackgroundTestTcpServer( 246 serverDone, 247 payloadByteCount, 248 confirmationPayload, 249 confirmationReply, 250 tcpSrvLsn, nil) 251 252 // prior to contacting the 2nd B server, we should have 253 // only one SplitHostname 254 entry, ok := cliKnownHosts.Hosts["ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC9hxNTsXHBIuWdc0SZAwN6Bytwr5vCB2K7rf5yVoC5YX5Hb08c25Xd5sGhehAj8RXooNxCa62mDnk/ACcByDa35gv3HyDqm1kmFLNvM/OcNNmK2FCuIdwKG7QWjmZwIwS3eCudJjDGR3qUTUzZbLpV80eZ0WxYE/CbZdb9gx6lNSAWx+ZaeGTt9M0sD5AfEHSxg2lJFaA5pa0Zaaq4QoultLtfisEnTHKCprjRc9RHuZ0l4kwi2eLtBdMmvR3Guk+wrd/qy6+S2zqn4WMDgE50VE6B6ODXN5nsFGrKfqx4mRD3dic28j1rJ7JVkc8sz8/tI+Mr4onomLZftbAFa5dwdiXtqDbOJlxe4sd4oVDImpocAtk+aIqupqN+Sc0JxCGlNvo5eKdNBZP7u/9UC7eee7Y7lHYRmhzoC7FSzFL1/mGgVxrEljcp8UZ1OD47Aq0XYvJA+5MAElbgWrK+M+EMwOGA85qQES5xtvfyVlnNvked6GQlfEuckM6H5bQCIdGkeuJ/+eWWW0rXNVkYHwA4EdiIaAXya4pO439kZfip/gWFF4mazHKCYOQAKndusFSOvxyWOTY/EbSrI7BYoYwm1WR75q7OozJTYP0V3UO+lQ+0/RgSh2uEqyfqB+EMZlATWBl3QnjxKHm7R0dVPnk9qpsjlVXGgGCCWn1UVHKq8w==\n"] 255 cv.So(ok, cv.ShouldBeTrue) 256 cv.So(len(entry.SplitHostnames), cv.ShouldEqual, 1) 257 258 // s2 server will be on a new port, so that is enough to 259 // check that dedup happened. 260 s2 := MakeTestSshClientAndServer(true) 261 defer TempDirCleanup(s2.SrvCfg.Origdir, s2.SrvCfg.Tempdir) 262 263 fmt.Printf("\n tell the server to represent itself as B so we can add its key\n") 264 s2.forTestingUpdateServerHostKey(s2.SrvCfg.Tempdir + "/testdata/id_rsa_b") 265 266 cv.So(len(cliKnownHosts.Hosts), cv.ShouldEqual, 4) 267 268 dc2 := DialConfig{ 269 ClientKnownHostsPath: s2.CliCfg.ClientKnownHostsPath, 270 KnownHosts: cliKnownHosts, 271 Mylogin: s2.Mylogin, 272 RsaPath: s2.RsaPath, 273 TotpUrl: s2.Totp, 274 Pw: s2.Pw, 275 Sshdhost: s2.SrvCfg.EmbeddedSSHd.Host, 276 Sshdport: s2.SrvCfg.EmbeddedSSHd.Port, 277 DownstreamHostPort: dest, 278 TofuAddIfNotKnown: true, 279 } 280 281 // first time we add the server key 282 channelToTcpServer, _, _, err = dc2.Dial(ctx, nil, false) 283 pp("dc2.Dial() -> err = %#v", err) 284 cv.So(err.Error(), cv.ShouldContainSubstring, "Re-run without -new") 285 286 fmt.Printf("\n now host key B under a different port should be known and dedupped \n") 287 cv.So(len(cliKnownHosts.Hosts), cv.ShouldEqual, 4) 288 289 // verify that hostkey for B now has two SplitHostnames 290 entry, ok = cliKnownHosts.Hosts["ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC9hxNTsXHBIuWdc0SZAwN6Bytwr5vCB2K7rf5yVoC5YX5Hb08c25Xd5sGhehAj8RXooNxCa62mDnk/ACcByDa35gv3HyDqm1kmFLNvM/OcNNmK2FCuIdwKG7QWjmZwIwS3eCudJjDGR3qUTUzZbLpV80eZ0WxYE/CbZdb9gx6lNSAWx+ZaeGTt9M0sD5AfEHSxg2lJFaA5pa0Zaaq4QoultLtfisEnTHKCprjRc9RHuZ0l4kwi2eLtBdMmvR3Guk+wrd/qy6+S2zqn4WMDgE50VE6B6ODXN5nsFGrKfqx4mRD3dic28j1rJ7JVkc8sz8/tI+Mr4onomLZftbAFa5dwdiXtqDbOJlxe4sd4oVDImpocAtk+aIqupqN+Sc0JxCGlNvo5eKdNBZP7u/9UC7eee7Y7lHYRmhzoC7FSzFL1/mGgVxrEljcp8UZ1OD47Aq0XYvJA+5MAElbgWrK+M+EMwOGA85qQES5xtvfyVlnNvked6GQlfEuckM6H5bQCIdGkeuJ/+eWWW0rXNVkYHwA4EdiIaAXya4pO439kZfip/gWFF4mazHKCYOQAKndusFSOvxyWOTY/EbSrI7BYoYwm1WR75q7OozJTYP0V3UO+lQ+0/RgSh2uEqyfqB+EMZlATWBl3QnjxKHm7R0dVPnk9qpsjlVXGgGCCWn1UVHKq8w==\n"] 291 cv.So(ok, cv.ShouldBeTrue) 292 cv.So(len(entry.SplitHostnames), cv.ShouldEqual, 2) 293 294 for k := range entry.SplitHostnames { 295 fmt.Printf("entry.SplitHostnames['%v'] is present\n", k) 296 } 297 298 // done with testing, cleanup 299 s.SrvCfg.Esshd.Stop() 300 <-s.SrvCfg.Esshd.Halt.DoneChan() 301 cv.So(true, cv.ShouldEqual, true) // we should get here. 302 303 }) 304 }