diff --git a/cmd/csaf_checker/checks.go b/cmd/csaf_checker/checks.go index 1b98225..0eba457 100644 --- a/cmd/csaf_checker/checks.go +++ b/cmd/csaf_checker/checks.go @@ -8,13 +8,18 @@ package main -type processor struct { - opts *options - domain string -} +import ( + "crypto/tls" + "errors" + "fmt" + "net/http" + "sort" + "strings" +) -func newProcessor(opts *options) *processor { - return &processor{opts: opts} +type processor struct { + opts *options + redirects map[string]string } type check interface { @@ -22,6 +27,19 @@ type check interface { report(*processor, *Domain) } +func newProcessor(opts *options) *processor { + return &processor{ + opts: opts, + redirects: map[string]string{}, + } +} + +func (p *processor) clean() { + for k := range p.redirects { + delete(p.redirects, k) + } +} + func (p *processor) run(checks []check, domains []string) (*Report, error) { var report Report @@ -37,14 +55,49 @@ func (p *processor) run(checks []check, domains []string) (*Report, error) { ch.report(p, domain) } report.Domains = append(report.Domains, domain) + p.clean() } return &report, nil } +func (p *processor) checkRedirect(r *http.Request, via []*http.Request) error { + + var path strings.Builder + for i, v := range via { + if i > 0 { + path.WriteString(", ") + } + path.WriteString(v.URL.String()) + } + p.redirects[r.URL.String()] = path.String() + + if len(via) > 10 { + return errors.New("Too many redirections") + } + return nil +} + +func (p *processor) httpClient() *http.Client { + client := http.Client{ + CheckRedirect: p.checkRedirect, + } + + if p.opts.Insecure { + client.Transport = &http.Transport{ + TLSClientConfig: &tls.Config{ + InsecureSkipVerify: true, + }, + } + } + + return &client +} + type baseCheck struct { num int description string + messages []string } type tlsCheck struct { @@ -100,7 +153,11 @@ type publicPGPKeyCheck struct { } func (bc *baseCheck) report(_ *processor, domain *Domain) { - req := &Requirement{Num: bc.num, Description: bc.description} + req := &Requirement{ + Num: bc.num, + Description: bc.description, + Messages: bc.messages, + } domain.Requirements = append(domain.Requirements, req) } @@ -115,13 +172,22 @@ func (tc *tlsCheck) report(p *processor, domain *Domain) { } func (rc *redirectsCheck) run(*processor, string) error { - // TODO: Implement me! return nil } func (rc *redirectsCheck) report(p *processor, domain *Domain) { + keys := make([]string, len(p.redirects)) + var i int + for k := range p.redirects { + keys[i] = k + i++ + } + sort.Strings(keys) + for i, k := range keys { + keys[i] = fmt.Sprintf("Redirect %s: %s", k, p.redirects[k]) + } + rc.baseCheck.messages = keys rc.baseCheck.report(p, domain) - // TODO: Implement me! } func (pmdc *providerMetadataCheck) run(*processor, string) error { diff --git a/cmd/csaf_checker/main.go b/cmd/csaf_checker/main.go index 22ddda9..46c059c 100644 --- a/cmd/csaf_checker/main.go +++ b/cmd/csaf_checker/main.go @@ -100,19 +100,19 @@ func writeReport(report *Report, opts *options) error { func buildChecks() []check { return []check{ - &tlsCheck{baseCheck{3, "TLS"}}, - &redirectsCheck{baseCheck{6, "Redirects"}}, - &providerMetadataCheck{baseCheck{7, "provider-metadata.json"}}, - &securityCheck{baseCheck{8, "security.txt"}}, - &wellknownMetadataCheck{baseCheck{9, "/.well-known/csaf/provider-metadata.json"}}, - &dnsPathCheck{baseCheck{10, "DNS path"}}, - &oneFolderPerYearCheck{baseCheck{11, "One folder per year"}}, - &indexCheck{baseCheck{12, "index.txt"}}, - &changesCheck{baseCheck{13, "changes.csv"}}, - &directoryListingsCheck{baseCheck{14, "Directory listings"}}, - &integrityCheck{baseCheck{18, "Integrity"}}, - &signaturesCheck{baseCheck{19, "Signatures"}}, - &publicPGPKeyCheck{baseCheck{20, "Public PGP Key"}}, + &tlsCheck{baseCheck{num: 3, description: "TLS"}}, + &redirectsCheck{baseCheck{num: 6, description: "Redirects"}}, + &providerMetadataCheck{baseCheck{num: 7, description: "provider-metadata.json"}}, + &securityCheck{baseCheck{num: 8, description: "security.txt"}}, + &wellknownMetadataCheck{baseCheck{num: 9, description: "/.well-known/csaf/provider-metadata.json"}}, + &dnsPathCheck{baseCheck{num: 10, description: "DNS path"}}, + &oneFolderPerYearCheck{baseCheck{num: 11, description: "One folder per year"}}, + &indexCheck{baseCheck{num: 12, description: "index.txt"}}, + &changesCheck{baseCheck{num: 13, description: "changes.csv"}}, + &directoryListingsCheck{baseCheck{num: 14, description: "Directory listings"}}, + &integrityCheck{baseCheck{num: 18, description: "Integrity"}}, + &signaturesCheck{baseCheck{num: 19, description: "Signatures"}}, + &publicPGPKeyCheck{baseCheck{num: 20, description: "Public PGP Key"}}, } }