1101 lines
41 KiB
Go
1101 lines
41 KiB
Go
package test
|
|
|
|
// FIXME: This is in its own package to work around import loops.
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"testing"
|
|
|
|
"crypto/rsa"
|
|
"encoding/asn1"
|
|
"encoding/base64"
|
|
"encoding/hex"
|
|
"math/big"
|
|
"sync"
|
|
"time"
|
|
|
|
"strings"
|
|
|
|
"io/ioutil"
|
|
"os/exec"
|
|
|
|
"github.com/sirupsen/logrus"
|
|
jsonKeys "github.com/zmap/zcrypto/json"
|
|
"github.com/zmap/zcrypto/tls"
|
|
"github.com/zmap/zcrypto/x509"
|
|
"github.com/zmap/zcrypto/x509/pkix"
|
|
"github.com/zmap/zgrab2"
|
|
"github.com/zmap/zgrab2/lib/output"
|
|
)
|
|
|
|
const doFailDiffs = false
|
|
|
|
// The tests operate by manually constructing the stripped versions of the output.
|
|
type Strippable interface {
|
|
Stripped() string
|
|
}
|
|
|
|
// JSON encode the value, then decode it as a map[string]interface{}.
|
|
func toMap(v interface{}) map[string]interface{} {
|
|
ret, err := json.MarshalIndent(v, "", " ")
|
|
if err != nil {
|
|
logrus.Fatalf("Error marshaling: %v", err)
|
|
}
|
|
theMap := new(map[string]interface{})
|
|
err = json.Unmarshal(ret, theMap)
|
|
if err != nil {
|
|
logrus.Fatalf("Error unmarshaling: %v", err)
|
|
}
|
|
return *theMap
|
|
}
|
|
|
|
// Get v[key0][key1]...[keyN], or return nil, error if any values along the way
|
|
// are nil / not present / not maps.
|
|
func mapPath(theMap interface{}, keys ...string) (interface{}, error) {
|
|
for i, key := range keys {
|
|
cast, ok := theMap.(map[string]interface{})
|
|
if !ok {
|
|
return nil, fmt.Errorf("%s in map is not a map", strings.Join(keys[0:i], "."))
|
|
}
|
|
theMap = cast
|
|
next, ok := cast[key]
|
|
if !ok {
|
|
return nil, fmt.Errorf("map does not contain %s", strings.Join(keys[0:i+1], "."))
|
|
}
|
|
theMap = next
|
|
}
|
|
return theMap, nil
|
|
}
|
|
|
|
// Set theMap[key0][key1]...[keyN] = value, or return error if any values along
|
|
// the way are nil / not present / not maps.
|
|
func setMapValue(theMap map[string]interface{}, value interface{}, keys ...string) error {
|
|
lastIndex := len(keys) - 1
|
|
out, err := mapPath(theMap, keys[0:lastIndex]...)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
cast, ok := out.(map[string]interface{})
|
|
if !ok {
|
|
return fmt.Errorf("%s in map is not a map", strings.Join(keys[0:lastIndex], "."))
|
|
}
|
|
cast[keys[lastIndex]] = value
|
|
return nil
|
|
}
|
|
|
|
// delete the value at theMap[key0][key1]...[keyN], or return an error if any
|
|
// values along the way are nil / not present / not maps.
|
|
func delOut(theMap map[string]interface{}, keys ...string) error {
|
|
lastIndex := len(keys) - 1
|
|
out, err := mapPath(theMap, keys[0:lastIndex]...)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
cast, ok := out.(map[string]interface{})
|
|
if !ok {
|
|
return fmt.Errorf("%s in map is not a map", strings.Join(keys[0:lastIndex], "."))
|
|
}
|
|
delete(cast, keys[lastIndex])
|
|
return nil
|
|
}
|
|
|
|
// Get a marshalled version of the struct suitable for comparison.
|
|
// structs' keys are sorted by order in the definition, which can vary between
|
|
// the original and "stripped" versions, the marshalled text is unmarshaled into
|
|
// a map (whose keys are sorted alphabetically) and then re-marshaled.
|
|
func marshal(v interface{}) string {
|
|
theMap := toMap(v)
|
|
realRet, err := json.MarshalIndent(theMap, "", " ")
|
|
if err != nil {
|
|
logrus.Fatalf("Error re-marshaling: %v", err)
|
|
}
|
|
return string(realRet)
|
|
}
|
|
|
|
// Get the processed copy of v using the given verbosity value.
|
|
func process(verbose bool, v interface{}) interface{} {
|
|
proc := output.NewProcessor()
|
|
proc.Verbose = verbose
|
|
ret, err := proc.Process(v)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return ret
|
|
}
|
|
|
|
// Return the marshalled processed copy of v using the given verbosity value.
|
|
func strip(verbose bool, v interface{}) string {
|
|
theCopy := process(verbose, v)
|
|
return marshal(theCopy)
|
|
}
|
|
|
|
// Flat value with a wide variety of types, both debug and non-debug.
|
|
type Flat struct {
|
|
StringValue string `json:"string_value"`
|
|
TrueValue bool `json:"true_value"`
|
|
FalseValue bool `json:"false_value"`
|
|
IntValue int `json:"int_value"`
|
|
BytesValue []byte `json:"bytes_value"`
|
|
ArrayValue [5]string `json:"array_value"`
|
|
InterfaceValue interface{} `json:"interface_value"`
|
|
|
|
PtrStringValue *string `json:"ptr_string_value"`
|
|
PtrTrueValue *bool `json:"ptr_true_value"`
|
|
PtrFalseValue *bool `json:"ptr_false_value"`
|
|
PtrIntValue *int `json:"ptr_int_value"`
|
|
PtrBytesValue *[]byte `json:"ptr_bytes_value"`
|
|
PtrArrayValue *[5]string `json:"ptr_array_value"`
|
|
|
|
DebugStringValue string `json:"debug_string_value,omitempty" zgrab:"debug"`
|
|
DebugTrueValue bool `json:"debug_true_value,omitempty" zgrab:"debug"`
|
|
DebugFalseValue bool `json:"debug_false_value,omitempty" zgrab:"debug"`
|
|
DebugIntValue int `json:"debug_int_value,omitempty" zgrab:"debug"`
|
|
DebugBytesValue []byte `json:"debug_bytes_value,omitempty" zgrab:"debug"`
|
|
DebugArrayValue [5]string `json:"debug_array_value,omitempty" zgrab:"debug"`
|
|
DebugInterfaceValue interface{} `json:"debug_interface_value,omitempty" zgrab:"debug"`
|
|
|
|
DebugPtrStringValue *string `json:"debug_ptr_string_value,omitempty" zgrab:"debug"`
|
|
DebugPtrTrueValue *bool `json:"debug_ptr_true_value,omitempty" zgrab:"debug"`
|
|
DebugPtrFalseValue *bool `json:"debug_ptr_false_value,omitempty" zgrab:"debug"`
|
|
DebugPtrIntValue *int `json:"debug_ptr_int_value,omitempty" zgrab:"debug"`
|
|
DebugPtrBytesValue *[]byte `json:"debug_ptr_bytes_value,omitempty" zgrab:"debug"`
|
|
DebugPtrArrayValue *[5]string `json:"debug_ptr_array_value,omitempty" zgrab:"debug"`
|
|
}
|
|
|
|
type StrippedFlat struct {
|
|
*Flat
|
|
OmitDebugStringValue string `json:"debug_string_value,omitempty" zgrab:"debug"`
|
|
OmitDebugTrueValue bool `json:"debug_true_value,omitempty" zgrab:"debug"`
|
|
OmitDebugFalseValue bool `json:"debug_false_value,omitempty" zgrab:"debug"`
|
|
OmitDebugIntValue int `json:"debug_int_value,omitempty" zgrab:"debug"`
|
|
OmitDebugBytesValue []byte `json:"debug_bytes_value,omitempty" zgrab:"debug"`
|
|
OmitDebugArrayValue [5]string `json:"debug_array_value,omitempty" zgrab:"debug"`
|
|
OmitDebugInterfaceValue interface{} `json:"debug_interface_value,omitempty" zgrab:"debug"`
|
|
|
|
OmitDebugPtrStringValue *string `json:"debug_ptr_string_value,omitempty" zgrab:"debug"`
|
|
OmitDebugPtrTrueValue *bool `json:"debug_ptr_true_value,omitempty" zgrab:"debug"`
|
|
OmitDebugPtrFalseValue *bool `json:"debug_ptr_false_value,omitempty" zgrab:"debug"`
|
|
OmitDebugPtrIntValue *int `json:"debug_ptr_int_value,omitempty" zgrab:"debug"`
|
|
OmitDebugPtrBytesValue *[]byte `json:"debug_ptr_bytes_value,omitempty" zgrab:"debug"`
|
|
OmitDebugPtrArrayValue *[5]string `json:"debug_ptr_array_value,omitempty" zgrab:"debug"`
|
|
}
|
|
|
|
func (flat *Flat) GetStripped() *StrippedFlat {
|
|
return &StrippedFlat{Flat: flat}
|
|
}
|
|
|
|
func (flat *Flat) Stripped() string {
|
|
return marshal(flat.GetStripped())
|
|
}
|
|
|
|
func getStringArray(id string) *[5]string {
|
|
ret := [5]string{}
|
|
for i := 0; i < 5; i++ {
|
|
ret[i] = fmt.Sprintf("%s[%d]", id, i)
|
|
}
|
|
return &ret
|
|
}
|
|
|
|
func pString(s string) *string {
|
|
return &s
|
|
}
|
|
|
|
func pInt(i int) *int {
|
|
return &i
|
|
}
|
|
|
|
func pBool(v bool) *bool {
|
|
return &v
|
|
}
|
|
|
|
func getFlat(id string) *Flat {
|
|
return &Flat{
|
|
StringValue: id,
|
|
TrueValue: true,
|
|
FalseValue: false,
|
|
IntValue: len(id),
|
|
BytesValue: []byte{0x64, 0x64, 0x40, 0x05, 0x35, 0x8e},
|
|
ArrayValue: *getStringArray(id),
|
|
InterfaceValue: &[]byte{0x64, 0x64, 0x40, 0x05, 0x35, 0x8e},
|
|
|
|
PtrStringValue: pString(id),
|
|
PtrTrueValue: pBool(true),
|
|
PtrFalseValue: pBool(false),
|
|
PtrIntValue: pInt(len(id)),
|
|
PtrBytesValue: &[]byte{0x64, 0x64, 0x40, 0x05, 0x35, 0x8e},
|
|
PtrArrayValue: getStringArray(id),
|
|
|
|
DebugStringValue: "debug_" + id,
|
|
DebugTrueValue: true,
|
|
DebugFalseValue: false,
|
|
DebugIntValue: -len(id),
|
|
DebugBytesValue: []byte{0x64, 0x64, 0x40, 0x05, 0x35, 0x8e},
|
|
DebugArrayValue: *getStringArray("debug_" + id),
|
|
DebugInterfaceValue: &[]byte{0x64, 0x64, 0x40, 0x05, 0x35, 0x8e},
|
|
|
|
DebugPtrStringValue: pString("debug_" + id),
|
|
DebugPtrTrueValue: pBool(true),
|
|
DebugPtrFalseValue: pBool(false),
|
|
DebugPtrIntValue: pInt(-len(id)),
|
|
DebugPtrBytesValue: &[]byte{0x64, 0x64, 0x40, 0x05, 0x35, 0x8e},
|
|
DebugPtrArrayValue: getStringArray("debug_" + id),
|
|
}
|
|
}
|
|
|
|
// An arbitrarily deep struct with debug and non-debug fields
|
|
type Deep struct {
|
|
ID string `json:"id,omitempty"`
|
|
DebugID string `json:"debug_id,omitempty" zgrab:"debug"`
|
|
|
|
Child *Deep `json:"child"`
|
|
DebugChild *Deep `json:"debug_child,omitempty" zgrab:"debug"`
|
|
|
|
Flat Flat `json:"flat,omitempty"`
|
|
PtrFlat *Flat `json:"ptr_flat,omitempty"`
|
|
|
|
DebugFlat Flat `json:"debug_flat,omitempty" zgrab:"debug"`
|
|
DebugPtrFlat *Flat `json:"debug_ptr_flat,omitempty" zgrab:"debug"`
|
|
}
|
|
|
|
type StrippedDeep struct {
|
|
*Deep
|
|
|
|
OmitDebugID string `json:"debug_id,omitempty" zgrab:"debug"`
|
|
|
|
OverrideChild *StrippedDeep `json:"child"`
|
|
OmitDebugChild *StrippedDeep `json:"debug_child,omitempty" zgrab:"debug"`
|
|
|
|
OverrideFlat StrippedFlat `json:"flat,omitempty"`
|
|
OverridePtrFlat *StrippedFlat `json:"ptr_flat,omitempty"`
|
|
|
|
OverrideDebugFlat Flat `json:"debug_flat" zgrab:"debug"`
|
|
OmitDebugPtrFlat *StrippedFlat `json:"debug_ptr_flat,omitempty" zgrab:"debug"`
|
|
}
|
|
|
|
func (deep *Deep) GetStripped() *StrippedDeep {
|
|
temp := StrippedDeep{Deep: deep}
|
|
if deep.Child != nil {
|
|
temp.OverrideChild = deep.Child.GetStripped()
|
|
}
|
|
temp.OverrideFlat = *deep.Flat.GetStripped()
|
|
if deep.PtrFlat != nil {
|
|
temp.OverridePtrFlat = deep.PtrFlat.GetStripped()
|
|
}
|
|
temp.OverrideDebugFlat = Flat{}
|
|
// deep.DebugFlat should be "nilled" automatically; if not, tmep.OverrideDebugFlat = StrippedFlat{}
|
|
return &temp
|
|
}
|
|
|
|
func (deep *Deep) Stripped() string {
|
|
return marshal(deep.GetStripped())
|
|
}
|
|
|
|
// getDeep (and all similar functions) takes an identifier string, which is used
|
|
// as a prefix for all children, and a depth, which determines how many levels
|
|
// of children the return value will have.
|
|
func getDeep(id string, depth int) *Deep {
|
|
ret := &Deep{
|
|
ID: id,
|
|
DebugID: "debug_" + id,
|
|
Flat: *getFlat(id + ".flat"),
|
|
PtrFlat: getFlat(id + ".ptr_flat"),
|
|
DebugFlat: *getFlat(id + ".debug_flat"),
|
|
DebugPtrFlat: getFlat(id + ".debug_ptr_flat"),
|
|
}
|
|
if depth > 0 {
|
|
ret.Child = getDeep(ret.ID+".child", depth-1)
|
|
ret.DebugChild = getDeep(ret.ID+".debug_child", depth-1)
|
|
}
|
|
return ret
|
|
}
|
|
|
|
// An arbitrarily deep struct, with its children stored as interface{} fields.
|
|
type DeepIface struct {
|
|
ID string `json:"id"`
|
|
DebugID string `json:"debug_id,omitempty" zgrab:"debug"`
|
|
Child interface{} `json:"child"`
|
|
DebugChild interface{} `json:"debug_child,omitempty" zgrab:"debug"`
|
|
|
|
Flat Flat `json:"flat,omitempty"`
|
|
PtrFlat *Flat `json:"ptr_flat,omitempty"`
|
|
|
|
DebugFlat Flat `json:"debug_flat,omitempty" zgrab:"debug"`
|
|
DebugPtrFlat *Flat `json:"debug_ptr_flat,omitempty" zgrab:"debug"`
|
|
}
|
|
|
|
type StrippedDeepIface struct {
|
|
*DeepIface
|
|
OmitDebugID string `json:"debug_id,omitempty" zgrab:"debug"`
|
|
OverrideChild interface{} `json:"child"`
|
|
OmitDebugChild interface{} `json:"debug_child,omitempty" zgrab:"debug"`
|
|
|
|
OverrideFlat StrippedFlat `json:"flat,omitempty"`
|
|
OverridePtrFlat *StrippedFlat `json:"ptr_flat,omitempty"`
|
|
|
|
OverrideDebugFlat Flat `json:"debug_flat,omitempty" zgrab:"debug"`
|
|
OmitDebugPtrFlat *StrippedFlat `json:"debug_ptr_flat,omitempty" zgrab:"debug"`
|
|
}
|
|
|
|
func (deep *DeepIface) GetStripped() *StrippedDeepIface {
|
|
temp := StrippedDeepIface{DeepIface: deep}
|
|
// child and debugChild are both pointers to DeepIface
|
|
if deep.Child != nil {
|
|
temp.OverrideChild = deep.Child.(*DeepIface).GetStripped()
|
|
}
|
|
temp.OverrideFlat = *deep.Flat.GetStripped()
|
|
if deep.PtrFlat != nil {
|
|
temp.OverridePtrFlat = deep.PtrFlat.GetStripped()
|
|
}
|
|
temp.OverrideDebugFlat = Flat{}
|
|
return &temp
|
|
}
|
|
|
|
func (deep *DeepIface) Stripped() string {
|
|
return marshal(deep.GetStripped())
|
|
}
|
|
|
|
func getDeepIface(id string, depth int) *DeepIface {
|
|
ret := &DeepIface{
|
|
ID: id,
|
|
DebugID: "debug_" + id,
|
|
Flat: *getFlat(id + ".flat"),
|
|
PtrFlat: getFlat(id + ".ptr_flat"),
|
|
DebugFlat: *getFlat(id + ".debug_flat"),
|
|
DebugPtrFlat: getFlat(id + ".debug_ptr_flat"),
|
|
}
|
|
if depth > 0 {
|
|
ret.Child = getDeepIface(ret.ID+".child", depth-1)
|
|
ret.DebugChild = getDeepIface(ret.ID+".debug_child", depth-1)
|
|
}
|
|
return ret
|
|
}
|
|
|
|
// An arbitrarily deep struct, with its children stored in a slice.
|
|
type DeepSlice struct {
|
|
ID string `json:"id"`
|
|
DebugID string `json:"debug_id,omitempty" zgrab:"debug"`
|
|
|
|
Children []DeepSlice `json:"children"`
|
|
DebugChildren []DeepSlice `json:"debug_children,omitempty" zgrab:"debug"`
|
|
|
|
Flat Flat `json:"flat,omitempty"`
|
|
PtrFlat *Flat `json:"ptr_flat,omitempty"`
|
|
|
|
DebugFlat Flat `json:"debug_flat,omitempty" zgrab:"debug"`
|
|
DebugPtrFlat *Flat `json:"debug_ptr_flat,omitempty" zgrab:"debug"`
|
|
}
|
|
|
|
type StrippedDeepSlice struct {
|
|
*DeepSlice
|
|
OmitDebugID string `json:"debug_id,omitempty" zgrab:"debug"`
|
|
|
|
OverrideChildren []StrippedDeepSlice `json:"children"`
|
|
OmitDebugChildren []StrippedDeepSlice `json:"debug_children,omitempty" zgrab:"debug"`
|
|
|
|
OverrideFlat StrippedFlat `json:"flat,omitempty"`
|
|
OverridePtrFlat *StrippedFlat `json:"ptr_flat,omitempty"`
|
|
|
|
OverrideDebugFlat Flat `json:"debug_flat,omitempty" zgrab:"debug"`
|
|
OmitDebugPtrFlat *Flat `json:"debug_ptr_flat,omitempty" zgrab:"debug"`
|
|
}
|
|
|
|
func (deep *DeepSlice) GetStripped() *StrippedDeepSlice {
|
|
temp := StrippedDeepSlice{DeepSlice: deep}
|
|
// child and debugChild are both pointers to DeepIface
|
|
if len(deep.Children) > 0 {
|
|
temp.OverrideChildren = make([]StrippedDeepSlice, len(deep.Children))
|
|
for i, v := range deep.Children {
|
|
temp.OverrideChildren[i] = *v.GetStripped()
|
|
}
|
|
}
|
|
temp.OverrideFlat = *deep.Flat.GetStripped()
|
|
if deep.PtrFlat != nil {
|
|
temp.OverridePtrFlat = deep.PtrFlat.GetStripped()
|
|
}
|
|
temp.OverrideDebugFlat = Flat{}
|
|
return &temp
|
|
}
|
|
|
|
func (deep *DeepSlice) Stripped() string {
|
|
return marshal(deep.GetStripped())
|
|
}
|
|
|
|
func getDeepSlice(id string, depth int) *DeepSlice {
|
|
ret := &DeepSlice{
|
|
ID: id,
|
|
DebugID: "debug_" + id,
|
|
Flat: *getFlat(id + ".flat"),
|
|
PtrFlat: getFlat(id + ".ptr_flat"),
|
|
DebugFlat: *getFlat(id + ".debug_flat"),
|
|
DebugPtrFlat: getFlat(id + ".debug_ptr_flat"),
|
|
}
|
|
if depth > 0 {
|
|
ret.Children = []DeepSlice{*getDeepSlice(ret.ID+".child", depth-1)}
|
|
ret.DebugChildren = []DeepSlice{*getDeepSlice(ret.ID+".debug_child", depth-1)}
|
|
}
|
|
return ret
|
|
}
|
|
|
|
// An arbitrarily deep struct, with its children stored in an array of pointers.
|
|
type DeepArray struct {
|
|
ID string `json:"id"`
|
|
DebugID string `json:"debug_id,omitempty" zgrab:"debug"`
|
|
|
|
Children [1]*DeepArray `json:"children"`
|
|
DebugChildren [1]*DeepArray `json:"debug_children,omitempty" zgrab:"debug"`
|
|
|
|
Flat Flat `json:"flat,omitempty"`
|
|
PtrFlat *Flat `json:"ptr_flat,omitempty"`
|
|
|
|
DebugFlat Flat `json:"debug_flat,omitempty" zgrab:"debug"`
|
|
DebugPtrFlat *Flat `json:"debug_ptr_flat,omitempty" zgrab:"debug"`
|
|
}
|
|
|
|
type StrippedDeepArray struct {
|
|
*DeepArray
|
|
OmitDebugID string `json:"debug_id,omitempty" zgrab:"debug"`
|
|
|
|
OverrideChildren [1]*StrippedDeepArray `json:"children"`
|
|
OmitDebugChildren [1]*StrippedDeepArray `json:"debug_children,omitempty" zgrab:"debug"`
|
|
|
|
OverrideFlat StrippedFlat `json:"flat,omitempty"`
|
|
OverridePtrFlat *StrippedFlat `json:"ptr_flat,omitempty"`
|
|
|
|
OverrideDebugFlat Flat `json:"debug_flat,omitempty" zgrab:"debug"`
|
|
OmitDebugPtrFlat *StrippedFlat `json:"debug_ptr_flat,omitempty" zgrab:"debug"`
|
|
}
|
|
|
|
func (deep *DeepArray) GetStripped() *StrippedDeepArray {
|
|
temp := StrippedDeepArray{DeepArray: deep}
|
|
// child and debugChild are both pointers to DeepIface
|
|
if deep.Children[0] != nil {
|
|
temp.OverrideChildren[0] = deep.Children[0].GetStripped()
|
|
}
|
|
temp.OverrideFlat = *deep.Flat.GetStripped()
|
|
if deep.PtrFlat != nil {
|
|
temp.OverridePtrFlat = deep.PtrFlat.GetStripped()
|
|
}
|
|
temp.OverrideDebugFlat = Flat{}
|
|
return &temp
|
|
}
|
|
|
|
func (deep *DeepArray) Stripped() string {
|
|
return marshal(deep.GetStripped())
|
|
}
|
|
|
|
func getDeepArray(id string, depth int) *DeepArray {
|
|
ret := &DeepArray{
|
|
ID: id,
|
|
DebugID: "debug_" + id,
|
|
Flat: *getFlat(id + ".flat"),
|
|
PtrFlat: getFlat(id + ".ptr_flat"),
|
|
DebugFlat: *getFlat(id + ".debug_flat"),
|
|
DebugPtrFlat: getFlat(id + ".debug_ptr_flat"),
|
|
}
|
|
if depth > 0 {
|
|
ret.Children[0] = getDeepArray(ret.ID+".child", depth-1)
|
|
ret.DebugChildren[0] = getDeepArray(ret.ID+".child", depth-1)
|
|
}
|
|
return ret
|
|
}
|
|
|
|
// An arbitrarily deep struct, with its children stored in a slice of interface{}s.
|
|
type DeepIfaceSlice struct {
|
|
ID string `json:"id"`
|
|
DebugID string `json:"debug_id,omitempty" zgrab:"debug"`
|
|
|
|
Children []interface{} `json:"children"`
|
|
DebugChildren []interface{} `json:"debug_children,omitempty" zgrab:"debug"`
|
|
|
|
Flat Flat `json:"flat,omitempty"`
|
|
PtrFlat *Flat `json:"ptr_flat,omitempty"`
|
|
|
|
DebugFlat Flat `json:"debug_flat,omitempty" zgrab:"debug"`
|
|
DebugPtrFlat *Flat `json:"debug_ptr_flat,omitempty" zgrab:"debug"`
|
|
}
|
|
|
|
type StrippedDeepIfaceSlice struct {
|
|
*DeepIfaceSlice
|
|
OmitDebugID string `json:"debug_id,omitempty" zgrab:"debug"`
|
|
|
|
OverrideChildren []interface{} `json:"children"`
|
|
OmitDebugChildren []interface{} `json:"debug_children,omitempty" zgrab:"debug"`
|
|
|
|
OverrideFlat StrippedFlat `json:"flat,omitempty"`
|
|
OverridePtrFlat *StrippedFlat `json:"ptr_flat,omitempty"`
|
|
|
|
OverrideDebugFlat Flat `json:"debug_flat,omitempty" zgrab:"debug"`
|
|
OmitDebugPtrFlat *StrippedFlat `json:"debug_ptr_flat,omitempty" zgrab:"debug"`
|
|
}
|
|
|
|
func (deep *DeepIfaceSlice) GetStripped() *StrippedDeepIfaceSlice {
|
|
temp := StrippedDeepIfaceSlice{DeepIfaceSlice: deep}
|
|
// child and debugChild are both pointers to DeepIface
|
|
if len(deep.Children) > 0 {
|
|
child0 := deep.Children[0].(DeepIfaceSlice)
|
|
child1 := deep.Children[1].(Flat)
|
|
temp.OverrideChildren = []interface{}{
|
|
*(&child0).GetStripped(),
|
|
*(&child1).GetStripped(),
|
|
}
|
|
}
|
|
temp.OverrideFlat = *deep.Flat.GetStripped()
|
|
if deep.PtrFlat != nil {
|
|
temp.OverridePtrFlat = deep.PtrFlat.GetStripped()
|
|
}
|
|
temp.OverrideDebugFlat = Flat{}
|
|
return &temp
|
|
}
|
|
|
|
func (deep *DeepIfaceSlice) Stripped() string {
|
|
return marshal(deep.GetStripped())
|
|
}
|
|
|
|
func getDeepIfaceSlice(id string, depth int) *DeepIfaceSlice {
|
|
ret := &DeepIfaceSlice{
|
|
ID: id,
|
|
DebugID: "debug_" + id,
|
|
Flat: *getFlat(id + ".flat"),
|
|
PtrFlat: getFlat(id + ".ptr_flat"),
|
|
DebugFlat: *getFlat(id + ".debug_flat"),
|
|
DebugPtrFlat: getFlat(id + ".debug_ptr_flat"),
|
|
}
|
|
if depth > 0 {
|
|
ret.Children = []interface{}{
|
|
*getDeepIfaceSlice(ret.ID+".children[0]", depth-1),
|
|
*getFlat(id + ".children[1]"),
|
|
}
|
|
ret.DebugChildren = []interface{}{
|
|
*getDeepIfaceSlice(ret.ID+".debug_children[0]", depth-1),
|
|
*getFlat(ret.ID + ".debug_children[1]"),
|
|
}
|
|
}
|
|
return ret
|
|
}
|
|
|
|
// An arbitrarily deep struct, with its children stored in an array of interface{}s
|
|
type DeepIfaceArray struct {
|
|
ID string `json:"id"`
|
|
DebugID string `json:"debug_id,omitempty" zgrab:"debug"`
|
|
|
|
Children [2]interface{} `json:"children"`
|
|
DebugChildren [2]interface{} `json:"debug_children,omitempty" zgrab:"debug"`
|
|
|
|
Flat Flat `json:"flat,omitempty"`
|
|
PtrFlat *Flat `json:"ptr_flat,omitempty"`
|
|
|
|
DebugFlat Flat `json:"debug_flat,omitempty" zgrab:"debug"`
|
|
DebugPtrFlat *Flat `json:"debug_ptr_flat,omitempty" zgrab:"debug"`
|
|
}
|
|
|
|
type StrippedDeepIfaceArray struct {
|
|
*DeepIfaceArray
|
|
OmitDebugID string `json:"debug_id,omitempty" zgrab:"debug"`
|
|
|
|
OverrideChildren [2]interface{} `json:"children"`
|
|
OmitDebugChildren [2]interface{} `json:"debug_children,omitempty" zgrab:"debug"`
|
|
|
|
OverrideFlat StrippedFlat `json:"flat,omitempty"`
|
|
OverridePtrFlat *StrippedFlat `json:"ptr_flat,omitempty"`
|
|
|
|
OverrideDebugFlat Flat `json:"debug_flat,omitempty" zgrab:"debug"`
|
|
OmitDebugPtrFlat *StrippedFlat `json:"debug_ptr_flat,omitempty" zgrab:"debug"`
|
|
}
|
|
|
|
func (deep *DeepIfaceArray) GetStripped() *StrippedDeepIfaceArray {
|
|
temp := StrippedDeepIfaceArray{DeepIfaceArray: deep}
|
|
// child and debugChild are both pointers to DeepIface
|
|
if deep.Children[0] != nil {
|
|
temp.OverrideChildren[0] = deep.Children[0].(*DeepIfaceArray).GetStripped()
|
|
}
|
|
if deep.Children[1] != nil {
|
|
temp.OverrideChildren[1] = deep.Children[1].(*Flat).GetStripped()
|
|
}
|
|
temp.OverrideFlat = *deep.Flat.GetStripped()
|
|
if deep.PtrFlat != nil {
|
|
temp.OverridePtrFlat = deep.PtrFlat.GetStripped()
|
|
}
|
|
temp.OverrideDebugFlat = Flat{}
|
|
return &temp
|
|
}
|
|
|
|
func (deep *DeepIfaceArray) Stripped() string {
|
|
return marshal(deep.GetStripped())
|
|
}
|
|
|
|
func getDeepIfaceArray(id string, depth int) *DeepIfaceArray {
|
|
ret := &DeepIfaceArray{
|
|
ID: id,
|
|
DebugID: "debug_" + id,
|
|
Flat: *getFlat(id + ".flat"),
|
|
PtrFlat: getFlat(id + ".ptr_flat"),
|
|
DebugFlat: *getFlat(id + ".debug_flat"),
|
|
DebugPtrFlat: getFlat(id + ".debug_ptr_flat"),
|
|
}
|
|
if depth > 0 {
|
|
ret.Children[0] = getDeepIfaceArray(ret.ID+".children[0]", depth-1)
|
|
ret.Children[1] = getFlat(ret.ID + ".children[1]")
|
|
ret.DebugChildren[0] = getDeepIfaceArray(ret.ID+".debug_children[0]", depth-1)
|
|
ret.DebugChildren[1] = getFlat(ret.ID + ".debug_children[1]")
|
|
}
|
|
return ret
|
|
}
|
|
|
|
// A wrapper around a Deep, with field names prefixed with anon0 so that it can
|
|
// be used as an anonymous member struct.
|
|
type DeepAnon0 struct {
|
|
Anon0ID string `json:"anon0_id,omitempty"`
|
|
DebugAnon0ID string `json:"debug_anon0_id,omitempty" zgrab:"debug"`
|
|
|
|
Anon0 Deep `json:"anon0,omitempty"`
|
|
DebugAnon0 Deep `json:"debug_anon0,omitempty" zgrab:"debug"`
|
|
|
|
Anon0Flat Flat `json:"anon0_flat,omitempty"`
|
|
PtrAnon0Flat *Flat `json:"ptr_anon0_flat,omitempty"`
|
|
|
|
DebugAnon0Flat Flat `json:"debug_anon0_flat,omitempty" zgrab:"debug"`
|
|
DebugPtrAnon0Flat *Flat `json:"debug_ptr_anon0_flat,omitempty" zgrab:"debug"`
|
|
}
|
|
|
|
type StrippedDeepAnon0 struct {
|
|
*DeepAnon0
|
|
OmitDebugAnon0ID string `json:"debug_anon0_id,omitempty" zgrab:"debug"`
|
|
|
|
OverrideAnon0 StrippedDeep `json:"anon0,omitempty"`
|
|
OverrideDebugAnon0 Deep `json:"debug_anon0,omitempty" zgrab:"debug"`
|
|
|
|
OverrideAnon0Flat StrippedFlat `json:"anon0_flat,omitempty"`
|
|
OverridePtrAnon0Flat *StrippedFlat `json:"ptr_anon0_flat,omitempty"`
|
|
|
|
OverrideDebugAnon0Flat Flat `json:"debug_anon0_flat" zgrab:"debug"`
|
|
OmitDebugPtrAnon0Flat *Flat `json:"debug_ptr_anon0_flat,omitempty" zgrab:"debug"`
|
|
}
|
|
|
|
func (deep *DeepAnon0) GetStripped() *StrippedDeepAnon0 {
|
|
temp := StrippedDeepAnon0{DeepAnon0: deep}
|
|
// child and debugChild are both pointers to DeepIface
|
|
temp.OverrideAnon0 = *deep.Anon0.GetStripped()
|
|
temp.OverrideDebugAnon0 = Deep{}
|
|
temp.OverrideAnon0Flat = *deep.Anon0Flat.GetStripped()
|
|
temp.OverridePtrAnon0Flat = deep.PtrAnon0Flat.GetStripped()
|
|
|
|
temp.OverrideDebugAnon0Flat = Flat{}
|
|
return &temp
|
|
}
|
|
|
|
func (deep *DeepAnon0) Stripped() string {
|
|
return marshal(deep.GetStripped())
|
|
}
|
|
|
|
// A wrapper around a Deep, with field names prefixed with anon1 so that it can
|
|
// be used as an anonymous member struct.
|
|
type DeepAnon1 struct {
|
|
Anon1ID string `json:"anon1_id"`
|
|
DebugAnon1ID string `json:"debug_anon1_id,omitempty" zgrab:"debug"`
|
|
|
|
Anon1 Deep `json:"anon1"`
|
|
DebugAnon1 Deep `json:"debug_anon1,omitempty" zgrab:"debug"`
|
|
|
|
Anon1Flat Flat `json:"anon1_flat,omitempty"`
|
|
PtrAnon1Flat *Flat `json:"ptr_anon1_flat,omitempty"`
|
|
|
|
DebugAnon1Flat Flat `json:"debug_anon1_flat,omitempty" zgrab:"debug"`
|
|
DebugPtrAnon1Flat *Flat `json:"debug_ptr_anon1_flat,omitempty" zgrab:"debug"`
|
|
}
|
|
|
|
type StrippedDeepAnon1 struct {
|
|
*DeepAnon1
|
|
OmitDebugAnon1ID string `json:"debug_anon1_id,omitempty" zgrab:"debug"`
|
|
|
|
OverrideAnon1 StrippedDeep `json:"anon1,omitempty"`
|
|
OverrideDebugAnon1 Deep `json:"debug_anon1,omitempty" zgrab:"debug"`
|
|
|
|
OverrideAnon1Flat StrippedFlat `json:"anon1_flat,omitempty"`
|
|
OverridePtrAnon1Flat *StrippedFlat `json:"ptr_anon1_flat,omitempty"`
|
|
|
|
OverrideDebugAnon1Flat Flat `json:"debug_anon1_flat" zgrab:"debug"`
|
|
OmitDebugPtrAnon1Flat *Flat `json:"debug_ptr_anon1_flat,omitempty" zgrab:"debug"`
|
|
}
|
|
|
|
func (deep *DeepAnon1) GetStripped() *StrippedDeepAnon1 {
|
|
temp := StrippedDeepAnon1{DeepAnon1: deep}
|
|
// child and debugChild are both pointers to DeepIface
|
|
temp.OverrideAnon1 = *deep.Anon1.GetStripped()
|
|
temp.OverrideDebugAnon1 = Deep{}
|
|
temp.OverrideAnon1Flat = *deep.Anon1Flat.GetStripped()
|
|
temp.OverridePtrAnon1Flat = deep.PtrAnon1Flat.GetStripped()
|
|
|
|
temp.OverrideDebugAnon1Flat = Flat{}
|
|
return &temp
|
|
}
|
|
|
|
func (deep *DeepAnon1) Stripped() string {
|
|
return marshal(deep.GetStripped())
|
|
}
|
|
|
|
// An arbitrarily deep struct, with a pair of anonymous member structs (one a pointer).
|
|
type DeepAnon struct {
|
|
DeepAnon0
|
|
*DeepAnon1
|
|
|
|
ID string `json:"id"`
|
|
DebugID string `json:"debug_id,omitempty" zgrab:"debug"`
|
|
Child *DeepAnon `json:"child,omitempty"`
|
|
DebugChild *DeepAnon `json:"debug_child,omitempty" zgrab:"debug"`
|
|
|
|
Flat Flat `json:"flat,omitempty"`
|
|
PtrFlat *Flat `json:"ptr_flat,omitempty"`
|
|
|
|
DebugFlat Flat `json:"debug_flat,omitempty" zgrab:"debug"`
|
|
DebugPtrFlat *Flat `json:"debug_ptr_flat,omitempty" zgrab:"debug"`
|
|
}
|
|
|
|
type StrippedDeepAnon struct {
|
|
*DeepAnon
|
|
*StrippedDeepAnon0
|
|
*StrippedDeepAnon1
|
|
|
|
OverrideAnon0ID string `json:"anon0_id,omitempty"`
|
|
OverrideAnon1ID string `json:"anon1_id,omitempty"`
|
|
|
|
OmitDebugID string `json:"debug_id,omitempty" zgrab:"debug"`
|
|
OverrideChild *StrippedDeepAnon `json:"child,omitempty"`
|
|
OmitDebugChild *StrippedDeepAnon `json:"debug_child,omitempty" zgrab:"debug"`
|
|
|
|
OverrideFlat StrippedFlat `json:"flat,omitempty"`
|
|
OverridePtrFlat *StrippedFlat `json:"ptr_flat,omitempty"`
|
|
|
|
OverrideDebugFlat Flat `json:"debug_flat,omitempty" zgrab:"debug"`
|
|
OmitDebugPtrFlat *Flat `json:"debug_ptr_flat,omitempty" zgrab:"debug"`
|
|
}
|
|
|
|
func (deep *DeepAnon) GetStripped() *StrippedDeepAnon {
|
|
temp := StrippedDeepAnon{
|
|
DeepAnon: deep,
|
|
StrippedDeepAnon0: deep.DeepAnon0.GetStripped(),
|
|
StrippedDeepAnon1: deep.DeepAnon1.GetStripped(),
|
|
OverrideAnon0ID: deep.DeepAnon0.Anon0ID,
|
|
OverrideAnon1ID: deep.DeepAnon1.Anon1ID,
|
|
}
|
|
if deep.Child != nil {
|
|
temp.OverrideChild = deep.Child.GetStripped()
|
|
}
|
|
temp.OverrideFlat = *deep.Flat.GetStripped()
|
|
if deep.PtrFlat != nil {
|
|
temp.OverridePtrFlat = deep.PtrFlat.GetStripped()
|
|
}
|
|
temp.OverrideDebugFlat = Flat{}
|
|
|
|
return &temp
|
|
}
|
|
|
|
func (deep *DeepAnon) Stripped() string {
|
|
return marshal(deep.GetStripped())
|
|
}
|
|
|
|
func getDeepAnon(id string, depth int) *DeepAnon {
|
|
ret := &DeepAnon{
|
|
DeepAnon0: DeepAnon0{
|
|
Anon0ID: id + ".anon0",
|
|
DebugAnon0ID: id + ".debug_anon0",
|
|
Anon0: *getDeep(id+".anon0", depth-1),
|
|
DebugAnon0: *getDeep(id+".anon0", depth-1),
|
|
Anon0Flat: *getFlat(id + ".anon0_flat"),
|
|
PtrAnon0Flat: getFlat(id + ".ptr_anon0_flat"),
|
|
DebugAnon0Flat: *getFlat(id + ".debug_anon0_flat"),
|
|
DebugPtrAnon0Flat: getFlat(id + ".debug_ptr_anon0_flat"),
|
|
},
|
|
DeepAnon1: &DeepAnon1{
|
|
Anon1ID: id + ".anon1",
|
|
DebugAnon1ID: id + ".debug_anon1",
|
|
Anon1: *getDeep(id+".anon1", depth-1),
|
|
DebugAnon1: *getDeep(id+".anon1", depth-1),
|
|
Anon1Flat: *getFlat(id + ".anon1_flat"),
|
|
PtrAnon1Flat: getFlat(id + ".ptr_anon1_flat"),
|
|
DebugAnon1Flat: *getFlat(id + ".debug_anon1_flat"),
|
|
DebugPtrAnon1Flat: getFlat(id + ".debug_ptr_anon1_flat"),
|
|
},
|
|
ID: id,
|
|
DebugID: "debug_" + id,
|
|
Flat: *getFlat(id + ".flat"),
|
|
DebugFlat: *getFlat(id + ".debug_flat"),
|
|
}
|
|
if depth > 0 {
|
|
ret.Child = getDeepAnon(id+".child", depth-1)
|
|
ret.DebugChild = getDeepAnon(id+".debug_child", depth-1)
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func fail(t *testing.T, id string, expected string, actual string) {
|
|
t.Logf("%s: mismatch: expected %s, got %s", id, expected, actual)
|
|
if doFailDiffs {
|
|
ioutil.WriteFile(id+"-expected.json", []byte(expected), 0)
|
|
ioutil.WriteFile(id+"-actual.json", []byte(actual), 0)
|
|
cmd := exec.Command("diff", "-u", id+"-expected.json", id+"-actual.json")
|
|
ret, _ := cmd.Output()
|
|
ioutil.WriteFile(id+".diff", ret, 0)
|
|
}
|
|
t.Errorf("%s mismatch", id)
|
|
}
|
|
|
|
// Test processing all of the different types, in verbose and default mode, in parallel.
|
|
func TestProcess(t *testing.T) {
|
|
tests := map[string]Strippable{
|
|
"flat": getFlat("flat"),
|
|
"deep": getDeep("deep", 3),
|
|
"deepAnon": getDeepAnon("deepAnon", 3),
|
|
"deepArray": getDeepArray("deepArray", 3),
|
|
"deepIface": getDeepIface("deepIface", 3),
|
|
"deepIfaceArray": getDeepIfaceArray("deepIfaceArray", 3),
|
|
"deepIfaceSlice": getDeepIfaceSlice("deepIfaceSlice", 3),
|
|
"deepSlice": getDeepSlice("deepSlice", 3),
|
|
}
|
|
|
|
doTest := func(verbose bool, id string, input Strippable) {
|
|
var testID string
|
|
if verbose {
|
|
testID = id + "-verbose"
|
|
} else {
|
|
testID = id + "-default"
|
|
}
|
|
var expected string
|
|
if verbose {
|
|
expected = marshal(input)
|
|
} else {
|
|
expected = input.Stripped()
|
|
}
|
|
actual := strip(verbose, input)
|
|
if expected != actual {
|
|
fail(t, testID, expected, actual)
|
|
}
|
|
}
|
|
doTests := func(verbose bool) {
|
|
var done sync.WaitGroup
|
|
done.Add(len(tests))
|
|
for k, v := range tests {
|
|
//done.Add(1)
|
|
go func(id string, input Strippable) {
|
|
defer done.Done()
|
|
doTest(verbose, id, input)
|
|
}(k, v)
|
|
//done.Wait()
|
|
}
|
|
done.Wait()
|
|
}
|
|
doTests(true)
|
|
doTests(false)
|
|
}
|
|
|
|
func _b64(s string) []byte {
|
|
raw, err := base64.StdEncoding.DecodeString(s)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return raw
|
|
}
|
|
|
|
func _hex(s string) []byte {
|
|
if len(s)%2 != 0 {
|
|
s = "0" + s
|
|
}
|
|
raw, err := hex.DecodeString(s)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return raw
|
|
}
|
|
|
|
type fakeMySQLScanResults struct {
|
|
// ProtocolVersion is the 8-bit unsigned integer representing the
|
|
// server's protocol version sent in the initial HandshakePacket from
|
|
// the server.
|
|
// This has been 10 for all MySQL versionssince 3.2.2 (from 1998).
|
|
ProtocolVersion byte `json:"protocol_version"`
|
|
|
|
// ServerVersion is a null-terminated string giving the specific
|
|
// server version in the initial HandshakePacket. Often of the format
|
|
// x.y.z, but not always.
|
|
ServerVersion string `json:"server_version"`
|
|
|
|
// ConnectionID is the server's internal identifier for this client's
|
|
// connection, sent in the initial HandshakePacket.
|
|
ConnectionID uint32 `json:"connection_id" zgrab:"debug"`
|
|
|
|
// AuthPluginData is optional plugin-specific data, whose meaning
|
|
// depends on the value of AuthPluginName. Returned in the initial
|
|
// HandshakePacket.
|
|
AuthPluginData []byte `json:"auth_plugin_data" zgrab:"debug"`
|
|
|
|
// CharacterSet is the identifier for the character set the server is
|
|
// using. Returned in the initial HandshakePacket.
|
|
CharacterSet byte `json:"character_set,omitempty" zgrab:"debug"`
|
|
|
|
// StatusFlags is the set of status flags the server returned in the
|
|
// initial HandshakePacket. Each true entry in the map corresponds to
|
|
// a bit set to 1 in the flags, where the keys correspond to the
|
|
// #defines in the MySQL docs.
|
|
StatusFlags map[string]bool `json:"status_flags"`
|
|
|
|
// CapabilityFlags is the set of capability flags the server returned
|
|
// initial HandshakePacket. Each true entry in the map corresponds to
|
|
// a bit set to 1 in the flags, where the keys correspond to the
|
|
// #defines in the MySQL docs.
|
|
CapabilityFlags map[string]bool `json:"capability_flags"`
|
|
|
|
// AuthPluginName is the name of the authentication plugin, returned
|
|
// in the initial HandshakePacket.
|
|
AuthPluginName string `json:"auth_plugin_name,omitempty" zgrab:"debug"`
|
|
|
|
// ErrorCode is only set if there is an error returned by the server,
|
|
// for example if the scanner is not on the allowed hosts list.
|
|
ErrorCode *int `json:"error_code,omitempty"`
|
|
|
|
// ErrorMessage is an optional string describing the error. Only set
|
|
// if there is an error.
|
|
ErrorMessage string `json:"error_message,omitempty"`
|
|
|
|
// RawPackets contains the base64 encoding of all packets sent and
|
|
// received during the scan.
|
|
RawPackets []string `json:"raw_packets,omitempty"`
|
|
|
|
// TLSLog contains the usual shared TLS logs.
|
|
TLSLog *zgrab2.TLSLog `json:"tls,omitempty"`
|
|
}
|
|
|
|
// TestMySQL builds a bogus MySQL result, and then manually checks that the
|
|
// debug fields (and only the debug fields) are omitted.
|
|
func TestMySQL(t *testing.T) {
|
|
results := fakeMySQLScanResults{}
|
|
results.AuthPluginData = []byte("auth plugin data")
|
|
results.CapabilityFlags = map[string]bool{
|
|
"CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS": true,
|
|
"CLIENT_COMPRESS": true,
|
|
"CLIENT_SSL": true,
|
|
"CLIENT_SECURE_CONNECTION": true,
|
|
"CLIENT_INTERACTIVE": true,
|
|
"CLIENT_PLUGIN_AUTH": true,
|
|
"CLIENT_PLUGIN_AUTH_LEN_ENC_CLIENT_DATA": true,
|
|
"CLIENT_PROTOCOL_41": true,
|
|
}
|
|
results.ProtocolVersion = 10
|
|
results.RawPackets = []string{
|
|
"dGhpcyBpcyBub3QgYSByZWFsIHBhY2tldA==",
|
|
"bm9yIGlzIHRoaXM=",
|
|
}
|
|
results.ConnectionID = 1234
|
|
results.ServerVersion = "8.0.3-rc-log"
|
|
results.StatusFlags = map[string]bool{
|
|
"SERVER_STATUS_AUTOCOMMIT": true,
|
|
}
|
|
results.TLSLog = new(zgrab2.TLSLog)
|
|
results.TLSLog.HandshakeLog = &tls.ServerHandshake{
|
|
ClientFinished: &tls.Finished{
|
|
VerifyData: []byte("not real data"),
|
|
},
|
|
ClientHello: &tls.ClientHello{
|
|
CipherSuites: []tls.CipherSuite{
|
|
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
|
tls.TLS_RSA_WITH_AES_256_CBC_SHA,
|
|
},
|
|
CompressionMethods: []tls.CompressionMethod{0x00},
|
|
OcspStapling: true,
|
|
Random: []byte("some random data"),
|
|
SecureRenegotiation: true,
|
|
// leaving out SignatureAndHashes, since these aren't exported (yet?)
|
|
SupportedCurves: []tls.CurveID{
|
|
tls.CurveP256,
|
|
tls.CurveP384,
|
|
tls.CurveP521,
|
|
},
|
|
SupportedPoints: []tls.PointFormat{0},
|
|
Version: 0x303,
|
|
},
|
|
ClientKeyExchange: &tls.ClientKeyExchange{
|
|
RSAParams: &jsonKeys.RSAClientParams{
|
|
EncryptedPMS: []byte("fake"),
|
|
Length: 4,
|
|
},
|
|
},
|
|
KeyMaterial: &tls.KeyMaterial{
|
|
MasterSecret: &tls.MasterSecret{
|
|
Value: []byte("fake"),
|
|
Length: 4,
|
|
},
|
|
PreMasterSecret: &tls.PreMasterSecret{
|
|
Value: []byte("fake"),
|
|
Length: 4,
|
|
},
|
|
},
|
|
ServerCertificates: &tls.Certificates{
|
|
Certificate: tls.SimpleCertificate{
|
|
Raw: _b64("MIIC9DCCAdwCAQIwDQYJKoZIhvcNAQELBQAwPjE8MDoGA1UEAwwzTXlTUUxfU2VydmVyXzguMC4zLXJjX0F1dG9fR2VuZXJhdGVkX0NBX0NlcnRpZmljYXRlMB4XDTE4MDMyMzE5MDMyOFoXDTI4MDMyMDE5MDMyOFowQjFAMD4GA1UEAww3TXlTUUxfU2VydmVyXzguMC4zLXJjX0F1dG9fR2VuZXJhdGVkX1NlcnZlcl9DZXJ0aWZpY2F0ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALspPX60RdH8fgSsBjvXRhJ3egQBQWRoga8iGqAjdYrapvNwsdNqzsIe1v+q0FzIKwTkrrGQ3At1ikBjxOhobJOeNeB84jJp+72lPQM2ngYUx3ua/zwZKQw+vZIIqeGPnLzAc180anZl9AL5olyMR+sWm23+YCqEWK0+o9UW5tj27HOX5dL/xZSX+Y8Hsp/1cMK0AmReUsejNobfJ9jBomfKJRiyrEm4Zp3nCA8SuHByboQcKONHMWHeuvvSH5k/ndNf53yw7B/fYua8DHfZ9JUOIZfiGTPJFy1a7zLpIE0fjKRIVaGgggZA9lJzlnNVKna5KT92q+Vi4qgg5pPVqVUCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAiOYzSZapOpbSqJHAwpjQRhF02xu8f2sqeckpvROzDMRaq7lP/b5No51Sc7mqe2FrDB2O80G8qwZiM06INRd4HaoKDvolXD+xpyBZ5daNY09/ucpg8f1gDr83sS++AT+LHeoQ9ZmbpRn/x2ZfwA3L8fAoOJg/9m1Z07JOX/9h2uKgZVZBvIQNdm7QSjM7hqgHAcBQVVgk6p2BVd17RYuM9SXJIaCrCKJlg2EcBDyqSD4bdXm941o3+if7eeaTXkBlPzj7MzmrQnaI1Q11LfUrrrNrYDqv1DgIAwMIQ3BzqsJ4GQipq1z5DqU3I8jz0LtsI6J8hFqQf5zQDTuxP3b+tw=="),
|
|
Parsed: &x509.Certificate{
|
|
Raw: _b64("MIIC9DCCAdwCAQIwDQYJKoZIhvcNAQELBQAwPjE8MDoGA1UEAwwzTXlTUUxfU2VydmVyXzguMC4zLXJjX0F1dG9fR2VuZXJhdGVkX0NBX0NlcnRpZmljYXRlMB4XDTE4MDMyMzE5MDMyOFoXDTI4MDMyMDE5MDMyOFowQjFAMD4GA1UEAww3TXlTUUxfU2VydmVyXzguMC4zLXJjX0F1dG9fR2VuZXJhdGVkX1NlcnZlcl9DZXJ0aWZpY2F0ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALspPX60RdH8fgSsBjvXRhJ3egQBQWRoga8iGqAjdYrapvNwsdNqzsIe1v+q0FzIKwTkrrGQ3At1ikBjxOhobJOeNeB84jJp+72lPQM2ngYUx3ua/zwZKQw+vZIIqeGPnLzAc180anZl9AL5olyMR+sWm23+YCqEWK0+o9UW5tj27HOX5dL/xZSX+Y8Hsp/1cMK0AmReUsejNobfJ9jBomfKJRiyrEm4Zp3nCA8SuHByboQcKONHMWHeuvvSH5k/ndNf53yw7B/fYua8DHfZ9JUOIZfiGTPJFy1a7zLpIE0fjKRIVaGgggZA9lJzlnNVKna5KT92q+Vi4qgg5pPVqVUCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAiOYzSZapOpbSqJHAwpjQRhF02xu8f2sqeckpvROzDMRaq7lP/b5No51Sc7mqe2FrDB2O80G8qwZiM06INRd4HaoKDvolXD+xpyBZ5daNY09/ucpg8f1gDr83sS++AT+LHeoQ9ZmbpRn/x2ZfwA3L8fAoOJg/9m1Z07JOX/9h2uKgZVZBvIQNdm7QSjM7hqgHAcBQVVgk6p2BVd17RYuM9SXJIaCrCKJlg2EcBDyqSD4bdXm941o3+if7eeaTXkBlPzj7MzmrQnaI1Q11LfUrrrNrYDqv1DgIAwMIQ3BzqsJ4GQipq1z5DqU3I8jz0LtsI6J8hFqQf5zQDTuxP3b+tw=="),
|
|
RawTBSCertificate: _b64("MIIB3AIBAjANBgkqhkiG9w0BAQsFADA+MTwwOgYDVQQDDDNNeVNRTF9TZXJ2ZXJfOC4wLjMtcmNfQXV0b19HZW5lcmF0ZWRfQ0FfQ2VydGlmaWNhdGUwHhcNMTgwMzIzMTkwMzI4WhcNMjgwMzIwMTkwMzI4WjBCMUAwPgYDVQQDDDdNeVNRTF9TZXJ2ZXJfOC4wLjMtcmNfQXV0b19HZW5lcmF0ZWRfU2VydmVyX0NlcnRpZmljYXRlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuyk9frRF0fx+BKwGO9dGEnd6BAFBZGiBryIaoCN1itqm83Cx02rOwh7W/6rQXMgrBOSusZDcC3WKQGPE6Ghsk5414HziMmn7vaU9AzaeBhTHe5r/PBkpDD69kgip4Y+cvMBzXzRqdmX0AvmiXIxH6xabbf5gKoRYrT6j1Rbm2Pbsc5fl0v/FlJf5jweyn/VwwrQCZF5Sx6M2ht8n2MGiZ8olGLKsSbhmnecIDxK4cHJuhBwo40cxYd66+9IfmT+d01/nfLDsH99i5rwMd9n0lQ4hl+IZM8kXLVrvMukgTR+MpEhVoaCCBkD2UnOWc1UqdrkpP3ar5WLiqCDmk9WpVQIDAQAB"),
|
|
RawSubjectPublicKeyInfo: _b64("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuyk9frRF0fx+BKwGO9dGEnd6BAFBZGiBryIaoCN1itqm83Cx02rOwh7W/6rQXMgrBOSusZDcC3WKQGPE6Ghsk5414HziMmn7vaU9AzaeBhTHe5r/PBkpDD69kgip4Y+cvMBzXzRqdmX0AvmiXIxH6xabbf5gKoRYrT6j1Rbm2Pbsc5fl0v/FlJf5jweyn/VwwrQCZF5Sx6M2ht8n2MGiZ8olGLKsSbhmnecIDxK4cHJuhBwo40cxYd66+9IfmT+d01/nfLDsH99i5rwMd9n0lQ4hl+IZM8kXLVrvMukgTR+MpEhVoaCCBkD2UnOWc1UqdrkpP3ar5WLiqCDmk9WpVQIDAQAB"),
|
|
RawSubject: _b64("MEIxQDA+BgNVBAMMN015U1FMX1NlcnZlcl84LjAuMy1yY19BdXRvX0dlbmVyYXRlZF9TZXJ2ZXJfQ2VydGlmaWNhdGU="),
|
|
RawIssuer: _b64("MD4xPDA6BgNVBAMMM015U1FMX1NlcnZlcl84LjAuMy1yY19BdXRvX0dlbmVyYXRlZF9DQV9DZXJ0aWZpY2F0ZQ=="),
|
|
Signature: _b64("iOYzSZapOpbSqJHAwpjQRhF02xu8f2sqeckpvROzDMRaq7lP/b5No51Sc7mqe2FrDB2O80G8qwZiM06INRd4HaoKDvolXD+xpyBZ5daNY09/ucpg8f1gDr83sS++AT+LHeoQ9ZmbpRn/x2ZfwA3L8fAoOJg/9m1Z07JOX/9h2uKgZVZBvIQNdm7QSjM7hqgHAcBQVVgk6p2BVd17RYuM9SXJIaCrCKJlg2EcBDyqSD4bdXm941o3+if7eeaTXkBlPzj7MzmrQnaI1Q11LfUrrrNrYDqv1DgIAwMIQ3BzqsJ4GQipq1z5DqU3I8jz0LtsI6J8hFqQf5zQDTuxP3b+tw=="),
|
|
SignatureAlgorithm: 4,
|
|
SignatureAlgorithmOID: asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11},
|
|
PublicKeyAlgorithm: x509.PublicKeyAlgorithm(1),
|
|
PublicKey: &rsa.PublicKey{
|
|
N: (&big.Int{}).SetBytes(_hex("23626899336418032268426511006251456008957710946561236060077488477243930404389062857052756514213142729464147136250009726616710651748049570319952455766122793111751860932493085339042549427591735641622561350827399950711160330519889423606741185340361830307539991923398265174995648216248341512414059342081655136496339884654761519474219238937533274055680590823298754387287727134545334674412201273293183886639463834612608672984702302550038373374767049834134869307465746789634588312053503628028754854224411402349197656713279667931626157560702246437041136455602220365024967237813532823227555845248339489268414093584421359036757")),
|
|
E: 65537,
|
|
},
|
|
PublicKeyAlgorithmOID: asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1},
|
|
Version: 2,
|
|
SerialNumber: big.NewInt(2),
|
|
Issuer: pkix.Name{
|
|
CommonName: "MySQL_Server_8.0.3-rc_Auto_Generated_CA_Certificate",
|
|
Names: []pkix.AttributeTypeAndValue{pkix.AttributeTypeAndValue{Type: asn1.ObjectIdentifier{2, 5, 4, 3},
|
|
Value: "MySQL_Server_8.0.3-rc_Auto_Generated_CA_Certificate"}},
|
|
ExtraNames: []pkix.AttributeTypeAndValue(nil),
|
|
OriginalRDNS: pkix.RDNSequence{pkix.RelativeDistinguishedNameSET{pkix.AttributeTypeAndValue{Type: asn1.ObjectIdentifier{2, 5, 4, 3},
|
|
Value: "MySQL_Server_8.0.3-rc_Auto_Generated_CA_Certificate"}}}},
|
|
Subject: pkix.Name{
|
|
CommonName: "MySQL_Server_8.0.3-rc_Auto_Generated_Server_Certificate",
|
|
Names: []pkix.AttributeTypeAndValue{pkix.AttributeTypeAndValue{Type: asn1.ObjectIdentifier{2, 5, 4, 3},
|
|
Value: "MySQL_Server_8.0.3-rc_Auto_Generated_Server_Certificate"}},
|
|
ExtraNames: []pkix.AttributeTypeAndValue(nil),
|
|
OriginalRDNS: pkix.RDNSequence{pkix.RelativeDistinguishedNameSET{pkix.AttributeTypeAndValue{Type: asn1.ObjectIdentifier{2, 5, 4, 3},
|
|
Value: "MySQL_Server_8.0.3-rc_Auto_Generated_Server_Certificate"}}}},
|
|
NotBefore: time.Unix(63657428608/1000, 0),
|
|
NotAfter: time.Unix(63972788608/1000, 0),
|
|
ValidityPeriod: 315360000,
|
|
KeyUsage: 0,
|
|
SPKISubjectFingerprint: x509.CertificateFingerprint(_hex("14ffb1395597876cf13957c7de6994f7361efa951ceb49e222897ec964566c98")),
|
|
SPKIFingerprint: x509.CertificateFingerprint(_hex("66bedbc8b8f7df04f2dea4eb7d351f4f7f2b88b51eb52b988f8579201f9e5f3c")),
|
|
TBSCertificateFingerprint: x509.CertificateFingerprint(_hex("2cfc9ad82b7871734febcc892f61c81c4d8cf051ac071d357c8b9d08a13a2707")),
|
|
FingerprintNoCT: x509.CertificateFingerprint(_hex("a678d89928d1b7d398c1bc194bf393aac70239876b3f17da15c0fe5d1cde34f7")),
|
|
FingerprintSHA256: x509.CertificateFingerprint(_hex("202dc36b950a33f12237dd6197a60c06ddaba945b8c281d811c7b1a6d45b0640")),
|
|
FingerprintSHA1: x509.CertificateFingerprint(_hex("48e5d105675ea12ef95f7ef31eb8af3639ee57b2")),
|
|
FingerprintMD5: x509.CertificateFingerprint(_hex("da94c3e3592de3da093c5da51f46d4ce")),
|
|
},
|
|
},
|
|
},
|
|
ServerFinished: &tls.Finished{
|
|
VerifyData: []byte("fake"),
|
|
},
|
|
ServerHello: &tls.ServerHello{
|
|
CipherSuite: tls.TLS_RSA_WITH_AES_256_CBC_SHA,
|
|
CompressionMethod: 0,
|
|
Random: []byte("some other random data"),
|
|
SessionID: []byte("some session ID"),
|
|
Version: 0x302,
|
|
},
|
|
}
|
|
results.TLSLog.HeartbleedLog = &tls.Heartbleed{}
|
|
mapVal := toMap(results)
|
|
mapVal["auth_plugin_data"] = nil
|
|
mapVal["connection_id"] = 0
|
|
delOut(mapVal, "tls", "handshake_log", "client_hello")
|
|
expected := marshal(mapVal)
|
|
actual := strip(false, results)
|
|
if actual != expected {
|
|
fail(t, "fake-mysql", expected, actual)
|
|
}
|
|
}
|