1package scan
2
3import (
4	"encoding/json"
5	"net/http"
6	"time"
7
8	"github.com/cloudflare/cfssl/api"
9	"github.com/cloudflare/cfssl/errors"
10	"github.com/cloudflare/cfssl/log"
11	"github.com/cloudflare/cfssl/scan"
12)
13
14// scanHandler is an HTTP handler that accepts GET parameters for host (required)
15// family and scanner, and uses these to perform scans, returning a JSON blob result.
16func scanHandler(w http.ResponseWriter, r *http.Request) error {
17	if err := r.ParseForm(); err != nil {
18		log.Warningf("failed to parse body: %v", err)
19		return errors.NewBadRequest(err)
20	}
21
22	family := r.Form.Get("family")
23	scanner := r.Form.Get("scanner")
24	ip := r.Form.Get("ip")
25	timeoutStr := r.Form.Get("timeout")
26	var timeout time.Duration
27	var err error
28	if timeoutStr != "" {
29		if timeout, err = time.ParseDuration(timeoutStr); err != nil {
30			return errors.NewBadRequest(err)
31		}
32		if timeout < time.Second || timeout > 5*time.Minute {
33			return errors.NewBadRequestString("invalid timeout given")
34		}
35	} else {
36		timeout = time.Minute
37	}
38
39	host := r.Form.Get("host")
40	if host == "" {
41		log.Warningf("no host given")
42		return errors.NewBadRequestString("no host given")
43	}
44
45	results, err := scan.Default.RunScans(host, ip, family, scanner, timeout)
46	if err != nil {
47		return errors.NewBadRequest(err)
48	}
49
50	return json.NewEncoder(w).Encode(api.NewSuccessResponse(results))
51}
52
53// NewHandler returns a new http.Handler that handles a scan request.
54func NewHandler(caBundleFile string) (http.Handler, error) {
55	return api.HTTPHandler{
56		Handler: api.HandlerFunc(scanHandler),
57		Methods: []string{"GET"},
58	}, scan.LoadRootCAs(caBundleFile)
59}
60
61// scanInfoHandler is an HTTP handler that returns a JSON blob result describing
62// the possible families and scans to be run.
63func scanInfoHandler(w http.ResponseWriter, r *http.Request) error {
64	log.Info("setting up scaninfo handler")
65	response := api.NewSuccessResponse(scan.Default)
66	enc := json.NewEncoder(w)
67	return enc.Encode(response)
68}
69
70// NewInfoHandler returns a new http.Handler that handles a request for scan info.
71func NewInfoHandler() http.Handler {
72	return api.HTTPHandler{
73		Handler: api.HandlerFunc(scanInfoHandler),
74		Methods: []string{"GET"},
75	}
76}
77