Skip to content

Commit

Permalink
Merge pull request #28 from ninedraft/fix-path-dots
Browse files Browse the repository at this point in the history
  • Loading branch information
ninedraft committed Feb 11, 2022
2 parents 5b9c2b8 + 9fc561a commit 21a13ab
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 2 deletions.
9 changes: 9 additions & 0 deletions gemax/request.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package gemax

import (
"errors"
"fmt"
"io"
"net/url"
"strings"
)

// MaxRequestSize is the maximum incoming request size in bytes.
Expand All @@ -15,6 +17,10 @@ type IncomingRequest interface {
RemoteAddr() string
}

var (
errDotPath = errors.New("dots in path are not permitted")
)

// ParseIncomingRequest constructs an IncomingRequest from bytestream
// and additional parameters (remote address for now).
func ParseIncomingRequest(re io.Reader, remoteAddr string) (IncomingRequest, error) {
Expand All @@ -28,6 +34,9 @@ func ParseIncomingRequest(re io.Reader, remoteAddr string) (IncomingRequest, err
if errParse != nil {
return nil, fmt.Errorf("bad request: %w", errParse)
}
if strings.Contains(parsed.Path, "/..") {
return nil, errDotPath
}
return &incomingRequest{
url: parsed,
remoteAddr: remoteAddr,
Expand Down
11 changes: 9 additions & 2 deletions gemax/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package gemax
import (
"context"
"crypto/tls"
"errors"
"fmt"
"net"
"net/url"
Expand Down Expand Up @@ -109,9 +110,15 @@ func (server *Server) handle(ctx context.Context, conn net.Conn) {
}
}()
var req, errParseReq = ParseIncomingRequest(conn, conn.RemoteAddr().String())
var code = status.Success
switch {
case errors.Is(errParseReq, errDotPath):
code = status.PermanentFailure
case errParseReq != nil:
code = status.BadRequest
}
if errParseReq != nil {
server.logf("WARN: bad request: remote_ip=%s", conn.RemoteAddr())
const code = status.BadRequest
server.logf("WARN: bad request: remote_ip=%s, code=%s", conn.RemoteAddr(), code)
rw.WriteStatus(code, status.Text(code))
return
}
Expand Down
19 changes: 19 additions & 0 deletions gemax/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,25 @@ func TestListenAndServe(test *testing.T) {
test.Logf("%s / %v", data, errRead)
}

// emulates michael-lazar/gemini-diagnostics localhost $PORT --checks='URLDotEscape'
func TestURLDotEscape(test *testing.T) {
var listener, server = setupEchoServer(test)
server.Hosts = []string{"example.com"}
defer func() { _ = listener.Close() }()
var ctx, cancel = context.WithCancel(context.Background())
test.Cleanup(cancel)
runTask(test, func() {
var err = server.Serve(ctx, listener)
if err != nil {
test.Logf("test server: Serve: %v", err)
}
})

var resp = listener.next(test.Name(), strings.NewReader("gemini://example.com/../../\r\n"))

expectResponse(test, resp, "50 50 PERMANENT FAILURE\r\n")
}

func setupEchoServer(t *testing.T) (*fakeListener, *gemax.Server) {
t.Helper()
var server = &gemax.Server{
Expand Down

0 comments on commit 21a13ab

Please sign in to comment.