Merge branch 'master' into ah/trigger

This commit is contained in:
Zakir Durumeric 2018-06-28 15:05:12 -04:00 committed by GitHub
commit 681d6e0a56
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 299 additions and 251 deletions

@ -17,57 +17,76 @@ import (
var raceEnabled = false // set by race.go
var knownHeaders = map[string]bool{
"access_control_allow_origin": true,
"accept": true,
"accept_charset": true,
"accept_encoding": true,
"accept_language": true,
"accept_patch": true,
"accept_ranges": true,
"age": true,
"allow": true,
"alt_svc": true,
"alternate_protocol": true,
"cache_control": true,
"connection": true,
"content_disposition": true,
"content_encoding": true,
"content_language": true,
"content_length": true,
"content_location": true,
"content_md5": true,
"content_range": true,
"content_type": true,
"expires": true,
"last_modified": true,
"link": true,
"location": true,
"p3p": true,
"pragma": true,
"proxy_agent": true,
"proxy_authenticate": true,
"public_key_pins": true,
"referer": true,
"refresh": true,
"retry_after": true,
"server": true,
"set_cookie": true,
"status": true,
"strict_transport_security": true,
"trailer": true,
"transfer_encoding": true,
"upgrade": true,
"vary": true,
"via": true,
"warning": true,
"www_authenticate": true,
"x_frame_options": true,
"x_xss_protection": true,
"content_security_policy": true,
"x_content_security_policy": true,
"x_webkit_csp": true,
"x_content_type_options": true,
"x_powered_by": true,
"x_ua_compatible": true,
"x_content_duration": true,
"x_real_ip": true,
"x_forwarded_for": true,
"access_control_allow_origin": true,
"age": true,
"allow": true,
"alt_svc": true,
"alternate_protocol": true,
"authorization": true,
"cache_control": true,
"connection": true,
"content_disposition": true,
"content_encoding": true,
"content_language": true,
"content_length": true,
"content_location": true,
"content_md5": true,
"content_range": true,
"content_security_policy": true,
"content_type": true,
"cookie": true,
"date": true,
"etag": true,
"expect": true,
"expires": true,
"from": true,
"host": true,
"if_match": true,
"if_modified_since": true,
"if_none_match": true,
"if_unmodified_since": true,
"last_modified": true,
"link": true,
"location": true,
"max_forwards": true,
"p3p": true,
"pragma": true,
"proxy_agent": true,
"proxy_authenticate": true,
"proxy_authorization": true,
"public_key_pins": true,
"range": true,
"referer": true,
"refresh": true,
"retry_after": true,
"server": true,
"set_cookie": true,
"status": true,
"strict_transport_security": true,
"trailer": true,
"transfer_encoding": true,
"upgrade": true,
"user_agent": true,
"vary": true,
"via": true,
"warning": true,
"www_authenticate": true,
"x_content_duration": true,
"x_content_security_policy": true,
"x_content_type_options": true,
"x_forwarded_for": true,
"x_frame_options": true,
"x_powered_by": true,
"x_real_ip": true,
"x_ua_compatible": true,
"x_webkit_csp": true,
"x_xss_protection": true,
}
// A Header represents the key-value pairs in an HTTP header.

@ -42,7 +42,7 @@ var (
// TODO: Explain this error
ErrVersionNotSupported = errors.New("IPP version not supported")
Versions = [...]version {{Major: 2, Minor: 1}, {Major: 2, Minor: 0}, {Major: 1, Minor: 1}, {Major: 1, Minor: 0},}
Versions = []version{{Major: 2, Minor: 1}, {Major: 2, Minor: 0}, {Major: 1, Minor: 1}, {Major: 1, Minor: 0}}
)
type scan struct {
@ -68,10 +68,11 @@ type ScanResults struct {
MinorVersion *int8 `json:"version_minor,omitempty"`
VersionString string `json:"version_string,omitempty"`
CUPSVersion string `json:"cups_version,omitempty"`
AttributeCUPSVersion string `json:"attr_cups_version,omitempty"`
AttributeCUPSVersion string `json:"attr_cups_version,omitempty"`
AttributeIPPVersions []string `json:"attr_ipp_versions,omitempty"`
AttributePrinterURI string `json:"attr_printer_uri,omitempty"`
TLSLog *zgrab2.TLSLog `json:"tls,omitempty"`
AttributePrinterURI string `json:"attr_printer_uri,omitempty"`
TLSLog *zgrab2.TLSLog `json:"tls,omitempty"`
}
// TODO: Annotate every flag thoroughly
@ -181,12 +182,12 @@ func (scanner *Scanner) GetPort() uint {
return scanner.config.Port
}
func ippInContentType(resp http.Response) (bool, error) {
func hasContentType(resp *http.Response, contentType string) (bool, error) {
// TODO: Capture parameters and report them in ScanResults?
// Parameters can be ignored, since there are no required or optional parameters
// IPP parameters specified at https://www.iana.org/assignments/media-types/application/ipp
mediatype, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type"))
// FIXME: See if empty media type is sufficient as failure indicator,
// TODO: See if empty media type is sufficient as failure indicator,
// there could be other states where reading mediatype screwed up, but isn't empty (ie: corrupted/malformed)
if mediatype == "" && err != nil {
//TODO: Handle errors in a weird way, since media type is still returned
@ -194,7 +195,7 @@ func ippInContentType(resp http.Response) (bool, error) {
return false, err
}
// FIXME: Maybe pass the error along, maybe not. We got what we wanted.
return mediatype == ContentType, nil
return mediatype == contentType, nil
}
// FIXME: Cleaner to write this code, possibly slower than copy-pasted version
@ -263,19 +264,58 @@ func readAttributeFromBody(attrString string, body *[]byte) ([][]byte, error) {
return nil, errors.New("Attribute \"" + attrString + "\" not present.")
}
func (scan *scan) tryReadAttributes(body string) {
bodyBytes := []byte(body)
// Write reported CUPS version to results object
if scan.results.AttributeCUPSVersion == "" {
if cupsVersions, err := readAttributeFromBody(CupsVersion, &bodyBytes); err != nil {
log.WithFields(log.Fields{
"error": err,
"attribute": CupsVersion,
}).Debug("Failed to read attribute.")
} else if len(cupsVersions) > 0 {
scan.results.AttributeCUPSVersion = string(cupsVersions[0])
}
}
// Write reported IPP versions to results object
if len(scan.results.AttributeIPPVersions) == 0 {
if ippVersions, err := readAttributeFromBody(VersionsSupported, &bodyBytes); err != nil {
log.WithFields(log.Fields{
"error": err,
"attribute": VersionsSupported,
}).Debug("Failed to read attribute.")
} else {
for _, v := range ippVersions {
scan.results.AttributeIPPVersions = append(scan.results.AttributeIPPVersions, string(v))
}
}
}
// Write reported printer URI to results object
if scan.results.AttributePrinterURI == "" {
if uris, err := readAttributeFromBody(PrinterURISupported, &bodyBytes); err != nil {
log.WithFields(log.Fields{
"error": err,
"attribute": PrinterURISupported,
}).Debug("Failed to read attribute.")
} else if len(uris) > 0 {
scan.results.AttributePrinterURI = string(uris[0])
}
}
}
func versionNotSupported(body string) bool {
if body != "" {
buf := bytes.NewBuffer([]byte(body))
// Ignore first two bytes, read second two for status code
var reader struct {
_ uint16
_ uint16
StatusCode uint16
}
err := binary.Read(buf, binary.BigEndian, &reader)
if err != nil {
log.WithFields(log.Fields{
"error": err,
"body": body,
"body": body,
}).Debug("Failed to read statusCode from body.")
return false
}
@ -286,50 +326,14 @@ func versionNotSupported(body string) bool {
return false
}
// TODO: Genericize this with passed-in getIPPRequest function and *http.Response for some result field to store into
func (scanner *Scanner) augmentWithCUPSData(scan *scan, target *zgrab2.ScanTarget, version *version) *zgrab2.ScanError {
cupsBody := getPrintersRequest(version.Major, version.Minor)
cupsReq, err := http.NewRequest("POST", scan.url, cupsBody)
if err != nil {
return zgrab2.DetectScanError(err)
}
cupsReq.Header.Set("Accept", "*/*")
cupsReq.Header.Set("Content-Type", ContentType)
cupsResp, err := scan.client.Do(cupsReq)
cupsResp, err := sendIPPRequest(scan, cupsBody)
//Store response regardless of error in request, because we may have gotten something back
scan.results.CUPSResponse = cupsResp
// FIXME: This block is copy-pasted directly from Grab()
if err != nil {
//If error is a url.Error (a struct), unwrap it
if urlError, ok := err.(*url.Error); ok {
err = urlError.Err
}
}
if err != nil {
switch err {
case ErrRedirLocalhost:
break
case ErrTooManyRedirects:
return zgrab2.NewScanError(zgrab2.SCAN_APPLICATION_ERROR, err)
default:
return zgrab2.DetectScanError(err)
}
}
if cupsResp != nil && cupsResp.Body != nil {
defer cupsResp.Body.Close()
} else {
if cupsResp == nil {
return zgrab2.NewScanError(zgrab2.SCAN_CONNECTION_TIMEOUT, errors.New("No HTTP response"))
}
if cupsResp.Body == nil {
return zgrab2.NewScanError(zgrab2.SCAN_PROTOCOL_ERROR, errors.New("Empty body."))
}
// resp == nil or resp.Body == nil
// Empty response/body is not allowed in IPP because a response has required parameter
// Source: RFC 8011 Section 4.1.1 https://tools.ietf.org/html/rfc8011#section-4.1.1
// Still returns the response, if any, because assignment occurs before this else block
// TODO: Examine whether an empty response overall is a protocol error, I'd think of it as another kind of error entirely,
// and later conditions might handle that case; see RFC 8011 Section 4.2.5.2?
return err
}
// Store data into BodyText and BodySHA256 of cupsResp
storeBody(cupsResp, scanner)
@ -337,53 +341,21 @@ func (scanner *Scanner) augmentWithCUPSData(scan *scan, target *zgrab2.ScanTarge
return zgrab2.NewScanError(zgrab2.SCAN_APPLICATION_ERROR, ErrVersionNotSupported)
}
bodyBytes := []byte(cupsResp.BodyText)
// Write reported CUPS version to results object
if cupsVersions, err := readAttributeFromBody(CupsVersion, &bodyBytes); err != nil {
log.WithFields(log.Fields{
"error": err,
"attribute": CupsVersion,
}).Debug("Failed to read attribute.")
} else if len(cupsVersions) > 0 {
scan.results.AttributeCUPSVersion = string(cupsVersions[0])
}
// Write reported IPP versions to results object
if ippVersions, err := readAttributeFromBody(VersionsSupported, &bodyBytes); err != nil {
log.WithFields(log.Fields{
"error": err,
"attribute": VersionsSupported,
}).Debug("Failed to read attribute.")
} else {
for _, v := range ippVersions {
scan.results.AttributeIPPVersions = append(scan.results.AttributeIPPVersions, string(v))
}
}
// Write reported printer URI to results object
if uris, err := readAttributeFromBody(PrinterURISupported, &bodyBytes); err != nil {
log.WithFields(log.Fields{
"error": err,
"attribute": PrinterURISupported,
}).Debug("Failed to read attribute.")
} else if len(uris) > 0 {
scan.results.AttributePrinterURI = string(uris[0])
}
scan.tryReadAttributes(scan.results.CUPSResponse.BodyText)
return nil
}
func (scanner *Scanner) Grab(scan *scan, target *zgrab2.ScanTarget, version *version) *zgrab2.ScanError {
// Send get-printer-attributes request to the host, preferably a print server
body := getPrinterAttributesRequest(version.Major, version.Minor, scan.url, scanner.config.IPPSecure)
// TODO: Let this receive generic *io.Reader rather than *bytes.Buffer in particular
func sendIPPRequest(scan *scan, body *bytes.Buffer) (*http.Response, *zgrab2.ScanError) {
request, err := http.NewRequest("POST", scan.url, body)
if err != nil {
return zgrab2.DetectScanError(err)
// TODO: Log the error to see what exactly went wrong
return nil, zgrab2.DetectScanError(err)
}
request.Header.Set("Accept", "*/*")
request.Header.Set("Content-Type", ContentType)
resp, err := scan.client.Do(request)
//Store response regardless of error in request, because we may have gotten something back
scan.results.Response = resp
if err != nil {
//If error is a url.Error (a struct), unwrap it
if urlError, ok := err.(*url.Error); ok {
err = urlError.Err
}
@ -393,38 +365,38 @@ func (scanner *Scanner) Grab(scan *scan, target *zgrab2.ScanTarget, version *ver
case ErrRedirLocalhost:
break
case ErrTooManyRedirects:
return zgrab2.NewScanError(zgrab2.SCAN_APPLICATION_ERROR, err)
return resp, zgrab2.NewScanError(zgrab2.SCAN_APPLICATION_ERROR, err)
default:
return zgrab2.DetectScanError(err)
return resp, zgrab2.DetectScanError(err)
}
}
// TODO: Examine whether an empty response overall is a connection error; see RFC 8011 Section 4.2.5.2
if resp == nil {
return resp, zgrab2.NewScanError(zgrab2.SCAN_CONNECTION_TIMEOUT, errors.New("No HTTP response"))
}
// Empty body is not allowed in IPP because a response has required parameter
// Source: RFC 8011 Section 4.1.1 (https://tools.ietf.org/html/rfc8011#section-4.1.1)
if resp.Body == nil {
return resp, zgrab2.NewScanError(zgrab2.SCAN_PROTOCOL_ERROR, errors.New("Empty body."))
}
return resp, nil
}
if resp != nil && resp.Body != nil {
defer resp.Body.Close()
} else {
if resp == nil {
return zgrab2.NewScanError(zgrab2.SCAN_CONNECTION_TIMEOUT, errors.New("No HTTP response"))
}
if resp.Body == nil {
return zgrab2.NewScanError(zgrab2.SCAN_PROTOCOL_ERROR, errors.New("Empty body."))
}
// resp == nil or resp.Body == nil
// Empty response/body is not allowed in IPP because a response has required parameter
// Source: RFC 8011 Section 4.1.1 https://tools.ietf.org/html/rfc8011#section-4.1.1
// Still returns the response, if any, because assignment occurs before this else block
// TODO: Examine whether an empty response overall is a protocol error, I'd think of it as another kind of error entirely,
// and later conditions might handle that case; see RFC 8011 Section 4.2.5.2?
func (scanner *Scanner) Grab(scan *scan, target *zgrab2.ScanTarget, version *version) *zgrab2.ScanError {
// Send get-printer-attributes request to the host, preferably a print server
body := getPrinterAttributesRequest(version.Major, version.Minor, scan.url, scanner.config.IPPSecure)
// TODO: Log any weird errors coming out of this
resp, err := sendIPPRequest(scan, body)
//Store response regardless of error in request, because we may have gotten something back
scan.results.Response = resp
if err != nil {
return err
}
storeBody(resp, scanner)
if versionNotSupported(scan.results.Response.BodyText) {
return zgrab2.NewScanError(zgrab2.SCAN_APPLICATION_ERROR, ErrVersionNotSupported)
}
// TODO: Check to make sure that the repsonse received is actually IPP
//Content-Type header matches is sufficient
//HTTP on port 631 is sufficient
//Still record data in the case of protocol error to see what that data looks like
protocols := strings.Split(resp.Header.Get("Server"), " ")
for _, p := range protocols {
if strings.HasPrefix(strings.ToUpper(p), "IPP/") {
@ -437,7 +409,7 @@ func (scanner *Scanner) Grab(scan *scan, target *zgrab2.ScanTarget, version *ver
if len(components) >= 1 {
if val, err := strconv.Atoi(components[0]); err != nil {
log.WithFields(log.Fields{
"error": err,
"error": err,
"string": components[0],
}).Debug("Failed to read major version from string.")
} else {
@ -448,7 +420,7 @@ func (scanner *Scanner) Grab(scan *scan, target *zgrab2.ScanTarget, version *ver
if len(components) >= 2 {
if val, err := strconv.Atoi(components[1]); err != nil {
log.WithFields(log.Fields{
"error": err,
"error": err,
"string": components[1],
}).Debug("Failed to read minor version from string.")
} else {
@ -468,6 +440,20 @@ func (scanner *Scanner) Grab(scan *scan, target *zgrab2.ScanTarget, version *ver
}
}
// TODO: Cite RFC justification for this
// Reject successful responses which specify non-IPP MIME mediatype (ie: text/html)
if isIPP, _ := hasContentType(resp, ContentType);
resp.StatusCode == 200 && resp.Header.Get("Content-Type") != "" && !isIPP {
// TODO: Log error if any
return zgrab2.NewScanError(zgrab2.SCAN_PROTOCOL_ERROR, errors.New("application/ipp not present in Content-Type header."))
}
if resp.StatusCode != 200 {
return zgrab2.NewScanError(zgrab2.SCAN_APPLICATION_ERROR, errors.New("Response returned with status " + resp.Status))
}
scan.tryReadAttributes(scan.results.Response.BodyText)
return nil
}
@ -569,49 +555,60 @@ func (scanner *Scanner) newIPPScan(target *zgrab2.ScanTarget) *scan {
return &newScan
}
// TODO: Do you want to retry with TLS for all versions? Just one's you've already tried? Haven't tried? Just the same version?
func (scanner *Scanner) tryGrabForVersions(target *zgrab2.ScanTarget, versions *[]version) (*scan, *zgrab2.ScanError) {
scan := scanner.newIPPScan(target)
// TODO: Implement scan.Cleanup()
var err *zgrab2.ScanError
for i := 0; i < len(*versions); i++ {
err = scanner.Grab(scan, target, &(*versions)[i])
if err != nil && err.Err == ErrVersionNotSupported && i < len(*versions)-1 {
continue
}
break
}
return scan, err
}
// TODO: Incorporate status into this? I don't think so, b/c with certain statuses, we should return
// early, so special casing seems to make sense
func (scan *scan) shouldReportResult(scanner *Scanner) bool {
if scan.results.Response != nil {
return true
} else if scanner.config.IPPSecure {
l := scan.results.TLSLog
return l != nil && l.HandshakeLog != nil && l.HandshakeLog.ServerHello != nil
}
return false
}
// Scan TODO: describe how scan operates in appropriate detail
//1. Send a request (currently get-printer-attributes)
//2. Take in that response & read out version numbers
func (scanner *Scanner) Scan(target zgrab2.ScanTarget) (zgrab2.ScanStatus, interface{}, error) {
scan := scanner.newIPPScan(&target)
//defer scan.Cleanup()
var err *zgrab2.ScanError
// Try all known IPP versions from newest to oldest until version is supported
for i := 0; i < len(Versions); i++ {
err = scanner.Grab(scan, &target, &Versions[i])
if err == nil || (err != nil && err.Err != ErrVersionNotSupported) {
break
}
if i == len(Versions) - 1 && err.Err == ErrVersionNotSupported {
return zgrab2.SCAN_APPLICATION_ERROR, &scan.results, err.Err
}
}
// Try all known IPP versions from newest to oldest until we reach a supported version
scan, err := scanner.tryGrabForVersions(&target, &Versions)
if err != nil {
// Adapted from http module's RetryHTTPS logic
if scanner.config.RetryTLS && !scanner.config.IPPSecure {
//scan.Cleanup()
scanner.config.IPPSecure = true
// TODO: ?Refactor this to just call Scan again??
retry := scanner.newIPPScan(&target)
//defer retry.Cleanup()
var retryErr *zgrab2.ScanError
// Try all known IPP versions from newest to oldest until version is supported
// TODO: Figure out why retry-TLS is working worse than w/ or w/o TLS in the first place
for i := 0; i < len(Versions); i++ {
retryErr = scanner.Grab(retry, &target, &Versions[i])
if err == nil || (err != nil && err.Err != ErrVersionNotSupported) {
break
}
if i == len(Versions) - 1 && err.Err == ErrVersionNotSupported {
return zgrab2.SCAN_APPLICATION_ERROR, &scan.results, err.Err
}
}
if retryErr != nil {
return retryErr.Unpack(retry.results)
}
return zgrab2.SCAN_SUCCESS, retry.results, nil
// If versionNotSupported error was confirmed, the scanner was connecting w/o TLS, so don't retry
// Same goes for a protocol error of any kind. It means we got something back but it didn't conform.
if err.Status == zgrab2.SCAN_APPLICATION_ERROR || err.Status == zgrab2.SCAN_PROTOCOL_ERROR {
return err.Unpack(&scan.results)
}
return zgrab2.TryGetScanStatus(err), &scan.results, err
if scanner.config.RetryTLS && !scanner.config.IPPSecure {
scanner.config.IPPSecure = true
retry, retryErr := scanner.tryGrabForVersions(&target, &Versions)
if retryErr != nil {
if retry.shouldReportResult(scanner) {
return err.Unpack(&retry.results)
}
return zgrab2.TryGetScanStatus(err), nil, err
}
return zgrab2.SCAN_SUCCESS, &retry.results, nil
}
if scan.shouldReportResult(scanner) {
return err.Unpack(&scan.results)
}
return zgrab2.TryGetScanStatus(err), nil, err
}
return zgrab2.SCAN_SUCCESS, &scan.results, nil
}

@ -0,0 +1,2 @@
package ipp

@ -44,10 +44,22 @@ func (target ScanTarget) String() string {
return res
}
// Host gets the host identifier as a string: the IP address if it is available,
// or the domain if not.
func (target *ScanTarget) Host() string {
if target.IP != nil {
return target.IP.String()
} else if target.Domain != "" {
return target.Domain
}
log.Fatalf("Bad target %s: no IP/Domain", target.String())
panic("unreachable")
}
// Open connects to the ScanTarget using the configured flags, and returns a net.Conn that uses the configured timeouts for Read/Write operations.
func (target *ScanTarget) Open(flags *BaseFlags) (net.Conn, error) {
timeout := time.Second * time.Duration(flags.Timeout)
address := net.JoinHostPort(target.IP.String(), fmt.Sprintf("%d", flags.Port))
address := net.JoinHostPort(target.Host(), fmt.Sprintf("%d", flags.Port))
return DialTimeoutConnection("tcp", address, timeout)
}
@ -55,7 +67,7 @@ func (target *ScanTarget) Open(flags *BaseFlags) (net.Conn, error) {
// Note that the UDP "connection" does not have an associated timeout.
func (target *ScanTarget) OpenUDP(flags *BaseFlags, udp *UDPFlags) (net.Conn, error) {
timeout := time.Second * time.Duration(flags.Timeout)
address := net.JoinHostPort(target.IP.String(), fmt.Sprintf("%d", flags.Port))
address := net.JoinHostPort(target.Host(), fmt.Sprintf("%d", flags.Port))
var local *net.UDPAddr
var err error

@ -9,57 +9,76 @@ import zgrab2
# lib/http/header.go: knownHeaders
http_known_headers = [
"access_control_allow_origin",
"accept_patch",
"accept_ranges",
"age",
"allow",
"alt_svc",
"alternate_protocol",
"cache_control",
"connection",
"content_disposition",
"content_encoding",
"content_language",
"content_length",
"content_location",
"content_md5",
"content_range",
"content_type",
"expires",
"last_modified",
"link",
"location",
"p3p",
"pragma",
"proxy_agent",
"proxy_authenticate",
"public_key_pins",
"referer",
"refresh",
"retry_after",
"server",
"set_cookie",
"status",
"strict_transport_security",
"trailer",
"transfer_encoding",
"upgrade",
"vary",
"via",
"warning",
"www_authenticate",
"x_frame_options",
"x_xss_protection",
"content_security_policy",
"x_content_security_policy",
"x_webkit_csp",
"x_content_type_options",
"x_powered_by",
"x_ua_compatible",
"x_content_duration",
"x_real_ip",
"x_forwarded_for",
"accept",
"accept_charset",
"accept_encoding",
"accept_language",
"accept_patch",
"accept_ranges",
"access_control_allow_origin",
"age",
"allow",
"alt_svc",
"alternate_protocol",
"authorization",
"cache_control",
"connection",
"content_disposition",
"content_encoding",
"content_language",
"content_length",
"content_location",
"content_md5",
"content_range",
"content_security_policy",
"content_type",
"cookie",
"date",
"etag",
"expect",
"expires",
"from",
"host",
"if_match",
"if_modified_since",
"if_none_match",
"if_unmodified_since",
"last_modified",
"link",
"location",
"max_forwards",
"p3p",
"pragma",
"proxy_agent",
"proxy_authenticate",
"proxy_authorization",
"public_key_pins",
"range",
"referer",
"refresh",
"retry_after",
"server",
"set_cookie",
"status",
"strict_transport_security",
"trailer",
"transfer_encoding",
"upgrade",
"user_agent",
"vary",
"via",
"warning",
"www_authenticate",
"x_content_duration",
"x_content_security_policy",
"x_content_type_options",
"x_forwarded_for",
"x_frame_options",
"x_powered_by",
"x_real_ip",
"x_ua_compatible",
"x_webkit_csp",
"x_xss_protection",
]
http_unknown_headers = ListOf(SubRecord({

@ -7,7 +7,7 @@ import zschema.registry
import zcrypto_schemas.zcrypto as zcrypto
import zgrab2
# FIXME: Copy-pasted from http schema except for ipp_scan_response
# TODO: Eventually re-introduce (non-cicular) dependency on HTTP zgrab2 schema
# lib/http/header.go: knownHeaders
http_known_headers = [
"access_control_allow_origin",
@ -147,7 +147,6 @@ http_response_full = SubRecord({
"request": http_request_full
})
# TODO: Re-work to use most of schema from http module, rather than copy-pasting
ipp_scan_response = SubRecord({
"result": SubRecord({
"version_major": Signed8BitInteger(),