Reject invalid status codes
This commit is contained in:
parent
9f1a38a0dd
commit
73e4ef0689
25
client.go
25
client.go
@ -15,11 +15,11 @@ import (
|
|||||||
|
|
||||||
// Client errors.
|
// Client errors.
|
||||||
var (
|
var (
|
||||||
ErrProtocol = errors.New("gemini: protocol error")
|
ErrInvalidURL = errors.New("gemini: invalid URL")
|
||||||
ErrInvalidURL = errors.New("gemini: requested URL is invalid")
|
ErrInvalidResponse = errors.New("gemini: invalid response")
|
||||||
ErrCertificateNotValid = errors.New("gemini: certificate is invalid")
|
ErrInvalidCertificate = errors.New("gemini: invalid certificate")
|
||||||
|
ErrUnknownCertificate = errors.New("gemini: unknown certificate")
|
||||||
ErrCertificateNotTrusted = errors.New("gemini: certificate is not trusted")
|
ErrCertificateNotTrusted = errors.New("gemini: certificate is not trusted")
|
||||||
ErrCertificateUnknown = errors.New("gemini: certificate is unknown")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Request represents a Gemini request.
|
// Request represents a Gemini request.
|
||||||
@ -133,11 +133,18 @@ func (resp *Response) read(r *bufio.Reader) error {
|
|||||||
}
|
}
|
||||||
resp.Status = status
|
resp.Status = status
|
||||||
|
|
||||||
|
// Disregard invalid status codes
|
||||||
|
const minStatus, maxStatus = 1, 6
|
||||||
|
statusClass := status / 10
|
||||||
|
if statusClass < minStatus || statusClass > maxStatus {
|
||||||
|
return ErrInvalidResponse
|
||||||
|
}
|
||||||
|
|
||||||
// Read one space
|
// Read one space
|
||||||
if b, err := r.ReadByte(); err != nil {
|
if b, err := r.ReadByte(); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if b != ' ' {
|
} else if b != ' ' {
|
||||||
return ErrProtocol
|
return ErrInvalidResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the meta
|
// Read the meta
|
||||||
@ -149,7 +156,7 @@ func (resp *Response) read(r *bufio.Reader) error {
|
|||||||
meta = meta[:len(meta)-1]
|
meta = meta[:len(meta)-1]
|
||||||
// Ensure meta is less than or equal to 1024 bytes
|
// Ensure meta is less than or equal to 1024 bytes
|
||||||
if len(meta) > 1024 {
|
if len(meta) > 1024 {
|
||||||
return ErrProtocol
|
return ErrInvalidResponse
|
||||||
}
|
}
|
||||||
resp.Meta = meta
|
resp.Meta = meta
|
||||||
|
|
||||||
@ -157,7 +164,7 @@ func (resp *Response) read(r *bufio.Reader) error {
|
|||||||
if b, err := r.ReadByte(); err != nil {
|
if b, err := r.ReadByte(); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if b != '\n' {
|
} else if b != '\n' {
|
||||||
return ErrProtocol
|
return ErrInvalidResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read response body
|
// Read response body
|
||||||
@ -244,11 +251,11 @@ func (c *Client) Send(req *Request) (*Response, error) {
|
|||||||
// Read the response
|
// Read the response
|
||||||
resp := &Response{}
|
resp := &Response{}
|
||||||
r := bufio.NewReader(conn)
|
r := bufio.NewReader(conn)
|
||||||
// Store connection information
|
|
||||||
resp.TLS = conn.ConnectionState()
|
|
||||||
if err := resp.read(r); err != nil {
|
if err := resp.read(r); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
// Store connection information
|
||||||
|
resp.TLS = conn.ConnectionState()
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,6 +38,7 @@ func main() {
|
|||||||
// To generate a TLS key pair, run:
|
// To generate a TLS key pair, run:
|
||||||
//
|
//
|
||||||
// go run -tags=example ../cert
|
// go run -tags=example ../cert
|
||||||
|
//
|
||||||
cert, err := tls.LoadX509KeyPair("examples/client/localhost.crt", "examples/client/localhost.key")
|
cert, err := tls.LoadX509KeyPair("examples/client/localhost.crt", "examples/client/localhost.key")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
@ -28,7 +28,7 @@ func init() {
|
|||||||
// Alert the user that the certificate is not trusted
|
// Alert the user that the certificate is not trusted
|
||||||
fmt.Printf("Warning: Certificate for %s is not trusted!\n", hostname)
|
fmt.Printf("Warning: Certificate for %s is not trusted!\n", hostname)
|
||||||
fmt.Println("This could indicate a Man-in-the-Middle attack.")
|
fmt.Println("This could indicate a Man-in-the-Middle attack.")
|
||||||
case gemini.ErrCertificateUnknown:
|
case gemini.ErrUnknownCertificate:
|
||||||
// Prompt the user to trust the certificate
|
// Prompt the user to trust the certificate
|
||||||
trust := trustCertificate(cert)
|
trust := trustCertificate(cert)
|
||||||
switch trust {
|
switch trust {
|
||||||
|
@ -14,6 +14,7 @@ func main() {
|
|||||||
// To generate a TLS key pair, run:
|
// To generate a TLS key pair, run:
|
||||||
//
|
//
|
||||||
// go run -tags=example ../cert
|
// go run -tags=example ../cert
|
||||||
|
//
|
||||||
cert, err := tls.LoadX509KeyPair("examples/server/localhost.crt", "examples/server/localhost.key")
|
cert, err := tls.LoadX509KeyPair("examples/server/localhost.crt", "examples/server/localhost.key")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
4
tofu.go
4
tofu.go
@ -79,7 +79,7 @@ func (k *KnownHosts) AddTemporary(hostname string, cert *x509.Certificate) {
|
|||||||
// Lookup looks for the provided certificate in the list of known hosts.
|
// Lookup looks for the provided certificate in the list of known hosts.
|
||||||
// If the hostname is in the list, but the fingerprint differs,
|
// If the hostname is in the list, but the fingerprint differs,
|
||||||
// Lookup returns ErrCertificateNotTrusted.
|
// Lookup returns ErrCertificateNotTrusted.
|
||||||
// If the hostname is not in the list, Lookup returns ErrCertificateUnknown.
|
// If the hostname is not in the list, Lookup returns ErrUnknownCertificate.
|
||||||
// If the certificate is found and the fingerprint matches, error will be nil.
|
// If the certificate is found and the fingerprint matches, error will be nil.
|
||||||
func (k *KnownHosts) Lookup(hostname string, cert *x509.Certificate) error {
|
func (k *KnownHosts) Lookup(hostname string, cert *x509.Certificate) error {
|
||||||
now := time.Now().Unix()
|
now := time.Now().Unix()
|
||||||
@ -99,7 +99,7 @@ func (k *KnownHosts) Lookup(hostname string, cert *x509.Certificate) error {
|
|||||||
// Fingerprint does not match
|
// Fingerprint does not match
|
||||||
return ErrCertificateNotTrusted
|
return ErrCertificateNotTrusted
|
||||||
}
|
}
|
||||||
return ErrCertificateUnknown
|
return ErrUnknownCertificate
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse parses the provided reader and adds the parsed known hosts to the list.
|
// Parse parses the provided reader and adds the parsed known hosts to the list.
|
||||||
|
Loading…
Reference in New Issue
Block a user