Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: remove raw input references #423

Merged
merged 1 commit into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading