Example #1
0
func checkHeartbeat(host string, timeout time.Duration, dial Dialer) (int, error) {
	var err error
	var c *tls.Conn

	if dial != nil {
		c, err = dial(host)
	} else {
		c, err = tls.Dial("tcp", host, &defaultTLSConfig)
	}

	if err != nil {
		log.Printf("Error connecting to %s: %s\n", host, err)
		return ResultConnectionRefused, err
	}
	defer c.Close()

	err = c.WriteHeartbeat(1, nil)
	if err == tls.ErrNoHeartbeat {
		log.Printf("SECURE(%s) - does not have the heartbeat extension enabled", host)
		return ResultSecure, err
	}

	if err != nil {
		log.Printf("UNKNOWN(%s) - Heartbeat enabled, but there was an error writing the payload:", host, err)
		return ResultError, err
	}

	readErr := make(chan error)
	go func() {
		_, _, err := c.ReadHeartbeat()
		readErr <- err
	}()

	select {
	case err := <-readErr:
		if err == nil {
			log.Printf("VULNERABLE(%s) - has the heartbeat extension enabled and is vulnerable to CVE-2014-0160", host)
			return ResultVunerable, err
		}
		log.Printf("SECURE(%s) has heartbeat extension enabled but is not vulnerable: %q", host, err)
		return ResultSecure, err
	case <-time.After(timeout):
	}

	log.Printf("SECURE(%s) - has the heartbeat extension enabled, but timed out after a malformed heartbeat (this likely means that it is not vulnerable)", host)
	return ResultSecure, err
}