Example #1
0
func fingerprintCallback(opts *options.SSHOptions, expectedFingerprint string) hostKeyCallback {
	if opts.SkipHostValidation {
		return nil
	}

	return func(hostname string, remote net.Addr, key ssh.PublicKey) error {
		switch len(expectedFingerprint) {
		case helpers.SHA1_FINGERPRINT_LENGTH:
			fingerprint := helpers.SHA1Fingerprint(key)
			if fingerprint != expectedFingerprint {
				return fmt.Errorf("Host key verification failed.\n\nThe fingerprint of the received key was %q.", fingerprint)
			}
		case helpers.MD5_FINGERPRINT_LENGTH:
			fingerprint := helpers.MD5Fingerprint(key)
			if fingerprint != expectedFingerprint {
				return fmt.Errorf("Host key verification failed.\n\nThe fingerprint of the received key was %q.", fingerprint)
			}
		case 0:
			fingerprint := helpers.MD5Fingerprint(key)
			return fmt.Errorf("Unable to verify identity of host.\n\nThe fingerprint of the received key was %q.", fingerprint)
		default:
			return errors.New("Unsupported host key fingerprint format")
		}
		return nil
	}
}
Example #2
0
func NewClientConn(logger lager.Logger, permissions *ssh.Permissions) (ssh.Conn, <-chan ssh.NewChannel, <-chan *ssh.Request, error) {
	if permissions == nil || permissions.CriticalOptions == nil {
		err := errors.New("Invalid permissions from authentication")
		logger.Error("permissions-and-critical-options-required", err)
		return nil, nil, nil, err
	}

	targetConfigJson := permissions.CriticalOptions["proxy-target-config"]
	logger = logger.Session("new-client-conn", lager.Data{
		"proxy-target-config": targetConfigJson,
	})

	var targetConfig TargetConfig
	err := json.Unmarshal([]byte(permissions.CriticalOptions["proxy-target-config"]), &targetConfig)
	if err != nil {
		logger.Error("unmarshal-failed", err)
		return nil, nil, nil, err
	}

	nConn, err := net.Dial("tcp", targetConfig.Address)
	if err != nil {
		logger.Error("dial-failed", err)
		return nil, nil, nil, err
	}

	clientConfig := &ssh.ClientConfig{}

	if targetConfig.User != "" {
		clientConfig.User = targetConfig.User
	}

	if targetConfig.PrivateKey != "" {
		key, err := ssh.ParsePrivateKey([]byte(targetConfig.PrivateKey))
		if err != nil {
			logger.Error("parsing-key-failed", err)
			return nil, nil, nil, err
		}
		clientConfig.Auth = append(clientConfig.Auth, ssh.PublicKeys(key))
	}

	if targetConfig.User != "" && targetConfig.Password != "" {
		clientConfig.Auth = append(clientConfig.Auth, ssh.Password(targetConfig.Password))
	}

	if targetConfig.HostFingerprint != "" {
		clientConfig.HostKeyCallback = func(hostname string, remote net.Addr, key ssh.PublicKey) error {
			expectedFingerprint := targetConfig.HostFingerprint

			var actualFingerprint string
			switch utf8.RuneCountInString(expectedFingerprint) {
			case helpers.MD5_FINGERPRINT_LENGTH:
				actualFingerprint = helpers.MD5Fingerprint(key)
			case helpers.SHA1_FINGERPRINT_LENGTH:
				actualFingerprint = helpers.SHA1Fingerprint(key)
			}

			if expectedFingerprint != actualFingerprint {
				err := errors.New("Host fingerprint mismatch")
				logger.Error("host-key-fingerprint-mismatch", err)
				return err
			}

			return nil
		}
	}

	conn, ch, req, err := ssh.NewClientConn(nConn, targetConfig.Address, clientConfig)
	if err != nil {
		logger.Error("handshake-failed", err)
		return nil, nil, nil, err
	}

	return conn, ch, req, nil
}
Example #3
0
									"proxy-target-config": string(targetConfigJson),
								},
							}
							proxyAuthenticator.AuthenticateReturns(permissions, nil)
						})

						It("handshakes with the target using the provided configuration", func() {
							Eventually(daemonAuthenticator.AuthenticateCallCount).Should(Equal(1))
						})
					})

					Context("when the host fingerprint is a sha1 hash", func() {
						BeforeEach(func() {
							targetConfigJson, err := json.Marshal(proxy.TargetConfig{
								Address:         sshdListener.Addr().String(),
								HostFingerprint: helpers.SHA1Fingerprint(TestHostKey.PublicKey()),
								User:            "******",
								Password:        "******",
							})
							Expect(err).NotTo(HaveOccurred())

							permissions := &ssh.Permissions{
								CriticalOptions: map[string]string{
									"proxy-target-config": string(targetConfigJson),
								},
							}
							proxyAuthenticator.AuthenticateReturns(permissions, nil)
						})

						It("handshakes with the target using the provided configuration", func() {
							Eventually(daemonAuthenticator.AuthenticateCallCount).Should(Equal(1))
	})

	Describe("MD5 Fingerprint", func() {
		BeforeEach(func() {
			fingerprint = helpers.MD5Fingerprint(publicKey)
		})

		It("should have the correct length", func() {
			Expect(utf8.RuneCountInString(fingerprint)).To(Equal(helpers.MD5_FINGERPRINT_LENGTH))
		})

		It("should match the expected fingerprint", func() {
			Expect(fingerprint).To(Equal(ExpectedMD5Fingerprint))
		})
	})

	Describe("SHA1 Fingerprint", func() {
		BeforeEach(func() {
			fingerprint = helpers.SHA1Fingerprint(publicKey)
		})

		It("should have the correct length", func() {
			Expect(utf8.RuneCountInString(fingerprint)).To(Equal(helpers.SHA1_FINGERPRINT_LENGTH))
		})

		It("should match the expected fingerprint", func() {
			Expect(fingerprint).To(Equal(ExpectedSHA1Fingerprint))
		})
	})
})