Skip to content

Commit

Permalink
chore: remove raw input references (#423)
Browse files Browse the repository at this point in the history
Signed-off-by: Felipe Zipitria <[email protected]>
  • Loading branch information
fzipi authored Dec 19, 2024
1 parent 49fd3f6 commit a09cd1e
Show file tree
Hide file tree
Showing 12 changed files with 100 additions and 328 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,6 @@ Tests can be altered using four lists:
- `data`: overrides data sent in the request
- `autocomplete_headers`: overrides header autocompletion (currently sets `Connection: close` and `Content-Length` for requests with body data)
- `encodedrequest`: overrides base64 encoded request
- `rawrequest`: permits to provide a raw request. `method`, `uri` and `version` values will be ignored
- `ignore` is for tests you want to ignore. You should add a comment on why you ignore the test
- `forcepass` is for tests you want to pass unconditionally. You should add a comment on why you force to pass the test
- `forcefail` is for tests you want to fail unconditionally. You should add a comment on why you force to fail the test
Expand Down
44 changes: 22 additions & 22 deletions cmd/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,31 @@
package cmd

import (
"fmt"
"os"
"fmt"
"os"

"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"

"github.com/coreruleset/go-ftw/internal/updater"
"github.com/coreruleset/go-ftw/internal/updater"
)

func NewVersionCommand(version string) *cobra.Command {
return &cobra.Command{
Use: "version",
Short: "Print the version number of go-ftw",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("go-ftw", version)
// do not run when in CI (e.g. GitHub Actions)
if os.Getenv("CI") != "true" {
latest, err := updater.LatestVersion()
if err != nil {
log.Error().Err(err).Msg("Failed to check for updates")
} else if latest != "" {
fmt.Println("Latest version is:", latest)
fmt.Println("Run 'go-ftw self-update' to update")
}
}
},
}
return &cobra.Command{
Use: "version",
Short: "Print the version number of go-ftw",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("go-ftw", version)
// do not run when in CI (e.g. GitHub Actions)
if os.Getenv("CI") != "true" {
latest, err := updater.LatestVersion()
if err != nil {
log.Error().Err(err).Msg("Failed to check for updates")
} else if latest != "" {
fmt.Println("Latest version is:", latest)
fmt.Println("Run 'go-ftw self-update' to update")
}
}
},
}
}
1 change: 0 additions & 1 deletion config/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@ type Overrides struct {
StopMagic *bool `yaml:"stop_magic" koanf:"stop_magic,omitempty"`
AutocompleteHeaders *bool `yaml:"autocomplete_headers" koanf:"autocomplete_headers,omitempty"`
EncodedRequest *string `yaml:"encoded_request,omitempty" koanf:"encoded_request,omitempty"`
RAWRequest *string `yaml:"raw_request,omitempty" koanf:"raw_request,omitempty"`
OverrideEmptyHostHeader *bool `yaml:"override_empty_host_header,omitempty" koanf:"override_empty_host_header,omitempty"`
}

Expand Down
147 changes: 51 additions & 96 deletions ftwhttp/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,11 @@ func NewRequest(reqLine *RequestLine, h Header, data []byte, autocompleteHeaders
headers: h.Clone(),
cookies: nil,
data: data,
raw: nil,
autoCompleteHeaders: autocompleteHeaders,
}
return r
}

// NewRawRequest creates a new request, an initial request line, and headers
func NewRawRequest(raw []byte, b bool) *Request {
r := &Request{
raw: raw,
autoCompleteHeaders: b,
}
return r
}

// SetAutoCompleteHeaders sets the value to the corresponding bool
func (r *Request) SetAutoCompleteHeaders(value bool) {
r.autoCompleteHeaders = value
Expand All @@ -57,38 +47,17 @@ func (r Request) WithAutoCompleteHeaders() bool {
}

// SetData sets the data
// You can use only one of raw, encoded or data.
// You can use only one of encoded or data.
func (r *Request) SetData(data []byte) error {
if utils.IsNotEmpty(r.raw) {
return errors.New("ftw/http: raw field is already present in this request")
}
r.data = data
return nil
}

// SetRawData sets the data using raw bytes
//
// When using raw data, no other checks will be done.
// You are responsible of creating the request line, all the headers, and body.
// You can use only one of raw or data.
func (r *Request) SetRawData(raw []byte) error {
if utils.IsNotEmpty(r.data) {
return errors.New("ftw/http: data field is already present in this request")
}
r.raw = raw
return nil
}

// Data returns the data
func (r Request) Data() []byte {
return r.data
}

// RawData returns the raw data
func (r Request) RawData() []byte {
return r.raw
}

// Headers return request headers
func (r Request) Headers() Header {
return r.headers
Expand Down Expand Up @@ -121,84 +90,74 @@ func (r *Request) AddStandardHeaders() {
}
}

// isRaw is a helper that returns true if raw or encoded data
func (r Request) isRaw() bool {
return utils.IsNotEmpty(r.raw)
}

// The request should be created with anything we want. We want to actually break HTTP.
func BuildRequest(r *Request) ([]byte, error) {
var err error
var b bytes.Buffer
var data []byte

// Check if we need to create from all fields
if !r.isRaw() {
// Request line
_, err = fmt.Fprintf(&b, "%s", r.requestLine.ToString())
// Request line
_, err = fmt.Fprintf(&b, "%s", r.requestLine.ToString())
if err != nil {
return nil, err
}

// We need to add the remaining headers, unless "NoDefaults"
if utils.IsNotEmpty(r.data) && r.WithAutoCompleteHeaders() {
// If there is no Content-Type, then we add one
r.AddHeader(ContentTypeHeader, "application/x-www-form-urlencoded")
data, err = encodeDataParameters(r.headers, r.data)
if err != nil {
log.Info().Msgf("ftw/http: cannot encode data to: %q", r.data)
return nil, err
}

// We need to add the remaining headers, unless "NoDefaults"
if utils.IsNotEmpty(r.data) && r.WithAutoCompleteHeaders() {
// If there is no Content-Type, then we add one
r.AddHeader(ContentTypeHeader, "application/x-www-form-urlencoded")
data, err = encodeDataParameters(r.headers, r.data)
if err != nil {
log.Info().Msgf("ftw/http: cannot encode data to: %q", r.data)
return nil, err
}
err = r.SetData(data)
if err != nil {
log.Info().Msgf("ftw/http: cannot set data to: %q", r.data)
return nil, err
}
}

// Multipart form data needs to end in \r\n, per RFC (and modsecurity make a scene if not)
if ct := r.headers.Value(ContentTypeHeader); strings.HasPrefix(ct, "multipart/form-data;") {
crlf := []byte("\r\n")
lf := []byte("\n")
log.Debug().Msgf("ftw/http: with LF only - %d bytes:\n%x\n", len(r.data), r.data)
data = bytes.ReplaceAll(r.data, lf, crlf)
log.Debug().Msgf("ftw/http: with CRLF - %d bytes:\n%x\n", len(data), data)
r.data = data
}

if r.WithAutoCompleteHeaders() {
r.AddStandardHeaders()
}

_, err := r.Headers().WriteBytes(&b)
err = r.SetData(data)
if err != nil {
log.Debug().Msgf("ftw/http: error writing to buffer: %s", err.Error())
log.Info().Msgf("ftw/http: cannot set data to: %q", r.data)
return nil, err
}
}

// TODO: handle cookies
// if client.Jar != nil {
// for _, cookie := range client.Jar.Cookies(req.URL) {
// req.AddCookie(cookie)
// }
// }
// Multipart form data needs to end in \r\n, per RFC (and modsecurity make a scene if not)
if ct := r.headers.Value(ContentTypeHeader); strings.HasPrefix(ct, "multipart/form-data;") {
crlf := []byte("\r\n")
lf := []byte("\n")
log.Debug().Msgf("ftw/http: with LF only - %d bytes:\n%x\n", len(r.data), r.data)
data = bytes.ReplaceAll(r.data, lf, crlf)
log.Debug().Msgf("ftw/http: with CRLF - %d bytes:\n%x\n", len(data), data)
r.data = data
}

// After headers, we need one blank line
_, err = fmt.Fprintf(&b, "\r\n")
if r.WithAutoCompleteHeaders() {
r.AddStandardHeaders()
}

_, err = r.Headers().WriteBytes(&b)
if err != nil {
log.Debug().Msgf("ftw/http: error writing to buffer: %s", err.Error())
return nil, err
}

// TODO: handle cookies
// if client.Jar != nil {
// for _, cookie := range client.Jar.Cookies(req.URL) {
// req.AddCookie(cookie)
// }
// }

// After headers, we need one blank line
_, err = fmt.Fprintf(&b, "\r\n")
if err != nil {
log.Debug().Msgf("ftw/http: error writing to buffer: %s", err.Error())
return nil, err
}
// Now the body, if anything
if utils.IsNotEmpty(r.data) {
_, err = fmt.Fprintf(&b, "%s", r.data)
if err != nil {
log.Debug().Msgf("ftw/http: error writing to buffer: %s", err.Error())
return nil, err
}
// Now the body, if anything
if utils.IsNotEmpty(r.data) {
_, err = fmt.Fprintf(&b, "%s", r.data)
if err != nil {
log.Debug().Msgf("ftw/http: error writing to buffer: %s", err.Error())
return nil, err
}
}
} else {
dumpRawData(&b, r.raw)
}

return b.Bytes(), err
Expand Down Expand Up @@ -256,7 +215,3 @@ func encodeDataParameters(h Header, data []byte) ([]byte, error) {
}
return data, err
}

func dumpRawData(b *bytes.Buffer, raw []byte) {
fmt.Fprintf(b, "%s", raw)
}
Loading

0 comments on commit a09cd1e

Please sign in to comment.