From ed9331c161c3d5dbf5b418fb92450c11d931cd88 Mon Sep 17 00:00:00 2001 From: Konstantin Papesh Date: Tue, 17 May 2022 15:55:50 +0200 Subject: [PATCH 01/16] fixed custom object unmarshal error Added missing '&', without it decoding will fail with _InvalidUnmarshalError_. --- objects/json.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/objects/json.go b/objects/json.go index 0611753..a216ebd 100644 --- a/objects/json.go +++ b/objects/json.go @@ -41,7 +41,7 @@ func DecodeType(data []byte) (string, error) { func Decode(data []byte) (*CommonObjectProperties, error) { var o CommonObjectProperties - err := json.Unmarshal(data, o) + err := json.Unmarshal(data, &o) if err != nil { return nil, err } From 70797c98ed1684c234b751d1a3f6ef572d586d4c Mon Sep 17 00:00:00 2001 From: Konstantin Papesh Date: Wed, 18 May 2022 15:29:22 +0200 Subject: [PATCH 02/16] Added custom object support to bundle.Decode --- objects/bundle/json.go | 169 ++++++++++++++++------------------------- objects/json.go | 36 ++++++++- 2 files changed, 100 insertions(+), 105 deletions(-) diff --git a/objects/bundle/json.go b/objects/bundle/json.go index 7656444..d0e8569 100644 --- a/objects/bundle/json.go +++ b/objects/bundle/json.go @@ -27,16 +27,68 @@ import ( "github.com/freetaxii/libstix2/objects/vulnerability" ) +type DecodeFunc func([]byte) (objects.STIXObject, error) + // ---------------------------------------------------------------------- // Public Functions - JSON Decoder // ---------------------------------------------------------------------- /* -Decode - This function will decode a bundle and return the object as a pointer +DecodeWithCustomObjects - This function will decode a bundle and return the object as a pointer along with any errors found. */ -func Decode(r io.Reader) (*Bundle, []error) { +func DecodeWithCustomObjects(r io.Reader, customDecoders map[string]DecodeFunc) (*Bundle, []error) { allErrors := make([]error, 0) + decoders := map[string]DecodeFunc{ + "attack-pattern": func(bytes []byte) (objects.STIXObject, error) { + return attackpattern.Decode(bytes) + }, + "campaign": func(bytes []byte) (objects.STIXObject, error) { + return campaign.Decode(bytes) + }, + "course-of-action": func(bytes []byte) (objects.STIXObject, error) { + return courseofaction.Decode(bytes) + }, + "identity": func(bytes []byte) (objects.STIXObject, error) { + return identity.Decode(bytes) + }, + "indicator": func(bytes []byte) (objects.STIXObject, error) { + return indicator.Decode(bytes) + }, + "infrastructure": func(bytes []byte) (objects.STIXObject, error) { + return infrastructure.Decode(bytes) + }, + "intrusion-set": func(bytes []byte) (objects.STIXObject, error) { + return intrusionset.Decode(bytes) + }, + "malware": func(bytes []byte) (objects.STIXObject, error) { + return malware.Decode(bytes) + }, + "observed-data": func(bytes []byte) (objects.STIXObject, error) { + return observeddata.Decode(bytes) + }, + "relationship": func(bytes []byte) (objects.STIXObject, error) { + return relationship.Decode(bytes) + }, + "sighting": func(bytes []byte) (objects.STIXObject, error) { + return sighting.Decode(bytes) + }, + "threat-actor": func(bytes []byte) (objects.STIXObject, error) { + return threatactor.Decode(bytes) + }, + "tool": func(bytes []byte) (objects.STIXObject, error) { + return tool.Decode(bytes) + }, + "vulnerability": func(bytes []byte) (objects.STIXObject, error) { + return vulnerability.Decode(bytes) + }, + "report": func(bytes []byte) (objects.STIXObject, error) { + return report.Decode(bytes) + }, + } + for k, v := range customDecoders { + decoders[k] = v + } var b Bundle var rawBundle bundleRawDecode @@ -64,113 +116,14 @@ func Decode(r io.Reader) (*Bundle, []error) { return nil, allErrors } - switch stixtype { - case "attack-pattern": - obj, err := attackpattern.Decode(v) - if err != nil { - allErrors = append(allErrors, err) - continue - } - b.AddObject(obj) - case "campaign": - obj, err := campaign.Decode(v) - if err != nil { - allErrors = append(allErrors, err) - continue - } - b.AddObject(obj) - case "course-of-action": - obj, err := courseofaction.Decode(v) - if err != nil { - allErrors = append(allErrors, err) - continue - } - b.AddObject(obj) - case "identity": - obj, err := identity.Decode(v) - if err != nil { - allErrors = append(allErrors, err) - continue - } - b.AddObject(obj) - case "indicator": - obj, err := indicator.Decode(v) - if err != nil { - allErrors = append(allErrors, err) - continue - } - b.AddObject(obj) - case "infrastructure": - obj, err := infrastructure.Decode(v) - if err != nil { - allErrors = append(allErrors, err) - continue - } - b.AddObject(obj) - case "intrusion-set": - obj, err := intrusionset.Decode(v) - if err != nil { - allErrors = append(allErrors, err) - continue - } - b.AddObject(obj) - case "malware": - obj, err := malware.Decode(v) - if err != nil { - allErrors = append(allErrors, err) - continue - } - b.AddObject(obj) - case "observed-data": - obj, err := observeddata.Decode(v) + if function, ok := decoders[stixtype]; ok { + obj, err := function(v) if err != nil { allErrors = append(allErrors, err) continue } b.AddObject(obj) - case "relationship": - obj, err := relationship.Decode(v) - if err != nil { - allErrors = append(allErrors, err) - continue - } - b.AddObject(obj) - case "report": - obj, err := report.Decode(v) - if err != nil { - allErrors = append(allErrors, err) - continue - } - b.AddObject(obj) - case "sighting": - obj, err := sighting.Decode(v) - if err != nil { - allErrors = append(allErrors, err) - continue - } - b.AddObject(obj) - case "threat-actor": - obj, err := threatactor.Decode(v) - if err != nil { - allErrors = append(allErrors, err) - continue - } - b.AddObject(obj) - case "tool": - obj, err := tool.Decode(v) - if err != nil { - allErrors = append(allErrors, err) - continue - } - b.AddObject(obj) - case "vulnerability": - obj, err := vulnerability.Decode(v) - if err != nil { - allErrors = append(allErrors, err) - continue - } - b.AddObject(obj) - default: + } else { obj, err := objects.Decode(v) if err != nil { allErrors = append(allErrors, err) @@ -183,6 +136,14 @@ func Decode(r io.Reader) (*Bundle, []error) { return &b, allErrors } +/* +Decode - This function will decode a bundle and return the object as a pointer +along with any errors found. +*/ +func Decode(r io.Reader) (*Bundle, []error) { + return DecodeWithCustomObjects(r, map[string]DecodeFunc{}) +} + // ---------------------------------------------------------------------- // Public Methods JSON Encoders // The encoding is done here at the individual object level instead of at diff --git a/objects/json.go b/objects/json.go index 0611753..24a2bcb 100644 --- a/objects/json.go +++ b/objects/json.go @@ -41,7 +41,7 @@ func DecodeType(data []byte) (string, error) { func Decode(data []byte) (*CommonObjectProperties, error) { var o CommonObjectProperties - err := json.Unmarshal(data, o) + err := json.Unmarshal(data, &o) if err != nil { return nil, err } @@ -78,3 +78,37 @@ func (o *CommonObjectProperties) FindCustomProperties(b []byte, p []string) erro } return nil } + +// ---------------------------------------------------------------------- +// Public Methods JSON Encoders +// The encoding is done here at the individual object level instead of at +// the STIX Object level so that individual pre/post processing rules can +// be applied. Since some of the STIX Objects do not follow a universal +// model, we need to cleanup some things that were inherited but not valid +// for the object. +// ---------------------------------------------------------------------- + +/* +Encode - This method is a simple wrapper for encoding an object into JSON +*/ +func (o *CommonObjectProperties) Encode() ([]byte, error) { + data, err := json.MarshalIndent(o, "", " ") + if err != nil { + return nil, err + } + + // Any needed preprocessing would be done here + return data, nil +} + +/* +EncodeToString - This method is a simple wrapper for encoding an object into +JSON +*/ +func (o *CommonObjectProperties) EncodeToString() (string, error) { + data, err := o.Encode() + if err != nil { + return "", err + } + return string(data), nil +} From 9a0cda3bde1e5a9f9a228c4700ab4a5c610b025c Mon Sep 17 00:00:00 2001 From: Konstantin Papesh Date: Mon, 18 Jul 2022 16:15:59 +0200 Subject: [PATCH 03/16] Added GetPropertyList() to CommonObjectProperties --- objects/objects.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/objects/objects.go b/objects/objects.go index b9730aa..3e27750 100644 --- a/objects/objects.go +++ b/objects/objects.go @@ -58,6 +58,15 @@ func (o *CommonObjectProperties) GetCommonProperties() *CommonObjectProperties { return o } +/* +GetPropertyList - This method will return a list of all of the properties that +are unique to this object. This is used by the custom UnmarshalJSON for this +object. As this is the base object, an empty list is returned +*/ +func (o *CommonObjectProperties) GetPropertyList() []string { + return []string{} +} + // ---------------------------------------------------------------------- // Helper Functions // ---------------------------------------------------------------------- From b8321dd75bc589af3e122fd68874cd970ebf15e7 Mon Sep 17 00:00:00 2001 From: Konstantin Papesh Date: Tue, 26 Jul 2022 15:43:02 +0200 Subject: [PATCH 04/16] Added some SCOs --- go.sum | 10 --- objects/bundle/json.go | 32 ++++++++ objects/objects.go | 18 +++++ objects/properties.go | 15 ++++ objects/sco/autonomoussystem/doc.go | 13 +++ objects/sco/autonomoussystem/json.go | 100 ++++++++++++++++++++++++ objects/sco/autonomoussystem/model.go | 51 ++++++++++++ objects/sco/autonomoussystem/setters.go | 6 ++ objects/sco/autonomoussystem/valid.go | 32 ++++++++ objects/sco/domainname/valid_test.go | 62 --------------- objects/sco/emailaddr/doc.go | 12 +++ objects/sco/emailaddr/json.go | 100 ++++++++++++++++++++++++ objects/sco/emailaddr/model.go | 51 ++++++++++++ objects/sco/emailaddr/setters.go | 6 ++ objects/sco/emailaddr/valid.go | 32 ++++++++ objects/sco/emailmessage/doc.go | 12 +++ objects/sco/emailmessage/json.go | 100 ++++++++++++++++++++++++ objects/sco/emailmessage/model.go | 79 +++++++++++++++++++ objects/sco/emailmessage/setters.go | 6 ++ objects/sco/emailmessage/valid.go | 48 ++++++++++++ objects/sco/ipv4addr/setters.go | 2 +- objects/sco/ipv4addr/valid.go | 7 +- objects/sco/ipv4addr/valid_test.go | 64 --------------- objects/sco/ipv6addr/doc.go | 14 ++++ objects/sco/ipv6addr/json.go | 100 ++++++++++++++++++++++++ objects/sco/ipv6addr/model.go | 51 ++++++++++++ objects/sco/ipv6addr/setters.go | 6 ++ objects/sco/ipv6addr/valid.go | 32 ++++++++ objects/sco/urlobject/valid_test.go | 47 ----------- objects/sco/x509certificate/doc.go | 13 +++ objects/sco/x509certificate/json.go | 100 ++++++++++++++++++++++++ objects/sco/x509certificate/model.go | 76 ++++++++++++++++++ objects/sco/x509certificate/setters.go | 6 ++ objects/sco/x509certificate/valid.go | 32 ++++++++ 34 files changed, 1145 insertions(+), 190 deletions(-) delete mode 100644 go.sum create mode 100644 objects/sco/autonomoussystem/doc.go create mode 100644 objects/sco/autonomoussystem/json.go create mode 100644 objects/sco/autonomoussystem/model.go create mode 100644 objects/sco/autonomoussystem/setters.go create mode 100644 objects/sco/autonomoussystem/valid.go delete mode 100644 objects/sco/domainname/valid_test.go create mode 100644 objects/sco/emailaddr/doc.go create mode 100644 objects/sco/emailaddr/json.go create mode 100644 objects/sco/emailaddr/model.go create mode 100644 objects/sco/emailaddr/setters.go create mode 100644 objects/sco/emailaddr/valid.go create mode 100644 objects/sco/emailmessage/doc.go create mode 100644 objects/sco/emailmessage/json.go create mode 100644 objects/sco/emailmessage/model.go create mode 100644 objects/sco/emailmessage/setters.go create mode 100644 objects/sco/emailmessage/valid.go delete mode 100644 objects/sco/ipv4addr/valid_test.go create mode 100644 objects/sco/ipv6addr/doc.go create mode 100644 objects/sco/ipv6addr/json.go create mode 100644 objects/sco/ipv6addr/model.go create mode 100644 objects/sco/ipv6addr/setters.go create mode 100644 objects/sco/ipv6addr/valid.go delete mode 100644 objects/sco/urlobject/valid_test.go create mode 100644 objects/sco/x509certificate/doc.go create mode 100644 objects/sco/x509certificate/json.go create mode 100644 objects/sco/x509certificate/model.go create mode 100644 objects/sco/x509certificate/setters.go create mode 100644 objects/sco/x509certificate/valid.go diff --git a/go.sum b/go.sum deleted file mode 100644 index 4905fb9..0000000 --- a/go.sum +++ /dev/null @@ -1,10 +0,0 @@ -github.com/gologme/log v1.2.0 h1:Ya5Ip/KD6FX7uH0S31QO87nCCSucKtF44TLbTtO7V4c= -github.com/gologme/log v1.2.0/go.mod h1:gq31gQ8wEHkR+WekdWsqDuf8pXTUZA9BnnzTuPz1Y9U= -github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA= -github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/mattn/go-sqlite3 v1.13.0 h1:LnJI81JidiW9r7pS/hXe6cFeO5EXNq7KbfvoJLRI69c= -github.com/mattn/go-sqlite3 v1.13.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= -github.com/pborman/getopt v0.0.0-20190409184431-ee0cd42419d3 h1:YtFkrqsMEj7YqpIhRteVxJxCeC3jJBieuLr0d4C4rSA= -github.com/pborman/getopt v0.0.0-20190409184431-ee0cd42419d3/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= -github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g= -github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= diff --git a/objects/bundle/json.go b/objects/bundle/json.go index d0e8569..c4597bb 100644 --- a/objects/bundle/json.go +++ b/objects/bundle/json.go @@ -7,6 +7,14 @@ package bundle import ( "encoding/json" + "github.com/freetaxii/libstix2/objects/sco/autonomoussystem" + "github.com/freetaxii/libstix2/objects/sco/domainname" + "github.com/freetaxii/libstix2/objects/sco/emailaddr" + "github.com/freetaxii/libstix2/objects/sco/emailmessage" + "github.com/freetaxii/libstix2/objects/sco/ipv4addr" + "github.com/freetaxii/libstix2/objects/sco/ipv6addr" + "github.com/freetaxii/libstix2/objects/sco/urlobject" + "github.com/freetaxii/libstix2/objects/sco/x509certificate" "io" "github.com/freetaxii/libstix2/objects" @@ -85,6 +93,30 @@ func DecodeWithCustomObjects(r io.Reader, customDecoders map[string]DecodeFunc) "report": func(bytes []byte) (objects.STIXObject, error) { return report.Decode(bytes) }, + "ipv4-addr": func(bytes []byte) (objects.STIXObject, error) { + return ipv4addr.Decode(bytes) + }, + "ipv6-addr": func(bytes []byte) (objects.STIXObject, error) { + return ipv6addr.Decode(bytes) + }, + "domain-name": func(bytes []byte) (objects.STIXObject, error) { + return domainname.Decode(bytes) + }, + "email-addr": func(bytes []byte) (objects.STIXObject, error) { + return emailaddr.Decode(bytes) + }, + "email-message": func(bytes []byte) (objects.STIXObject, error) { + return emailmessage.Decode(bytes) + }, + "url": func(bytes []byte) (objects.STIXObject, error) { + return urlobject.Decode(bytes) + }, + "x509-certificate": func(bytes []byte) (objects.STIXObject, error) { + return x509certificate.Decode(bytes) + }, + "autonomous-system": func(bytes []byte) (objects.STIXObject, error) { + return autonomoussystem.Decode(bytes) + }, } for k, v := range customDecoders { decoders[k] = v diff --git a/objects/objects.go b/objects/objects.go index 3e27750..64feb30 100644 --- a/objects/objects.go +++ b/objects/objects.go @@ -44,6 +44,24 @@ func ValidObjectType(t string) bool { "threat-actor": 1, "tool": 1, "vulnerability": 1, + // SCOs + "artifact": 1, + "autonomous-system": 1, + "directory": 1, + "domain-name": 1, + "email-addr": 1, + "email-message": 1, + "file": 1, + "ipv4-addr": 1, + "ipv6-addr": 1, + "mac-addr": 1, + "mutex": 1, + "network-traffic": 1, + "process": 1, + "software": 1, + "url": 1, + "user-account": 1, + "x509-certificate": 1, } if _, ok := m[t]; ok { diff --git a/objects/properties.go b/objects/properties.go index 136c13f..1b5c621 100644 --- a/objects/properties.go +++ b/objects/properties.go @@ -556,3 +556,18 @@ func (o *ValueProperty) SetValue(val string) error { o.Value = val return nil } + +// ---------------------------------------------------------------------- +// Display Name Property +// ---------------------------------------------------------------------- + +// DisplayNameProperty - +type DisplayNameProperty struct { + DisplayName string `json:"display_name,omitempty" bson:"display_name,omitempty"` +} + +// SetDisplayName - +func (o *DisplayNameProperty) SetDisplayName(val string) error { + o.DisplayName = val + return nil +} diff --git a/objects/sco/autonomoussystem/doc.go b/objects/sco/autonomoussystem/doc.go new file mode 100644 index 0000000..85fce4a --- /dev/null +++ b/objects/sco/autonomoussystem/doc.go @@ -0,0 +1,13 @@ +// Copyright 2015-2022 Bret Jordan, All rights reserved. +// +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file in the root of the source tree. + +/* +Package domainname implements the STIX 2.1 Domain Name SCO object. + +The following information comes directly from the STIX 2.1 specification. + +The Domain Name object represents the properties of a network domain name. +*/ +package autonomoussystem diff --git a/objects/sco/autonomoussystem/json.go b/objects/sco/autonomoussystem/json.go new file mode 100644 index 0000000..d683776 --- /dev/null +++ b/objects/sco/autonomoussystem/json.go @@ -0,0 +1,100 @@ +// Copyright 2015-2022 Bret Jordan, All rights reserved. +// +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file in the root of the source tree. + +package autonomoussystem + +import ( + "encoding/json" + + "github.com/freetaxii/libstix2/defs" +) + +// ---------------------------------------------------------------------- +// Public Functions - JSON Decoder +// ---------------------------------------------------------------------- + +/* +Decode - This function is a simple wrapper for decoding JSON data. It will +decode a slice of bytes into an actual struct and return a pointer to that +object along with any errors. +*/ +func Decode(data []byte) (*AutonomousSystem, error) { + var o AutonomousSystem + + if err := json.Unmarshal(data, &o); err != nil { + return nil, err + } + + return &o, nil +} + +/* +UnmarshalJSON - This method will over write the default UnmarshalJSON method +to enable custom properties that this library does not know about. It will store +them as map where the value of each key is a byte arrays. This way a tool that +does know how to deal with them can then further process them after this is +done. This will also allow the storage of the raw JSON data. +*/ +func (o *AutonomousSystem) UnmarshalJSON(b []byte) error { + + type alias AutonomousSystem + temp := &struct { + *alias + }{ + alias: (*alias)(o), + } + if err := json.Unmarshal(b, &temp); err != nil { + return err + } + + // This will create a map of all of the custom properties and store them in a + // property called o.Custom + if err := o.FindCustomProperties(b, o.GetPropertyList()); err != nil { + return err + } + + // This will store a complete copy of the original JSON in a byte array called + // o.Raw. This could be useful if you need to digitally sign the JSON or do + // verification on what was actually received. + if defs.KEEP_RAW_DATA == true { + o.SetRawData(b) + } + + return nil +} + +// ---------------------------------------------------------------------- +// Public Methods JSON Encoders +// The encoding is done here at the individual object level instead of at +// the STIX Object level so that individual pre/post processing rules can +// be applied. Since some of the STIX Objects do not follow a universal +// model, we need to cleanup some things that were inherited but not valid +// for the object. +// ---------------------------------------------------------------------- + +/* +Encode - This method is a simple wrapper for encoding an object into JSON +*/ +func (o *AutonomousSystem) Encode() ([]byte, error) { + data, err := json.MarshalIndent(o, "", " ") + if err != nil { + return nil, err + } + + // Any needed preprocessing would be done here + return data, nil +} + +/* +EncodeToString - This method is a simple wrapper for encoding an object into +JSON +*/ +func (o *AutonomousSystem) EncodeToString() (string, error) { + data, err := o.Encode() + if err != nil { + return "", err + } + return string(data), nil +} diff --git a/objects/sco/autonomoussystem/model.go b/objects/sco/autonomoussystem/model.go new file mode 100644 index 0000000..832d472 --- /dev/null +++ b/objects/sco/autonomoussystem/model.go @@ -0,0 +1,51 @@ +// Copyright 2015-2022 Bret Jordan, All rights reserved. +// +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file in the root of the source tree. + +package autonomoussystem + +import ( + "github.com/freetaxii/libstix2/objects" +) + +// ---------------------------------------------------------------------- +// Define Object Model +// ---------------------------------------------------------------------- + +/* +DomainName - This type implements the STIX 2 Domain Name SCO and defines +all of the properties and methods needed to create and work with this object. +All of the methods not defined local to this type are inherited from the +individual properties. +*/ +type AutonomousSystem struct { + objects.CommonObjectProperties + Number int `json:"number,omitempty" bson:"number,omitempty"` + objects.NameProperty + Rir string `json:"rir,omitempty" bson:"rir,omitempty"` +} + +/* +GetPropertyList - This method will return a list of all of the properties that +are unique to this object. This is used by the custom UnmarshalJSON for this +object. It is defined here in this file to make it easy to keep in sync. +*/ +func (o *AutonomousSystem) GetPropertyList() []string { + return []string{"number", "name", "rir"} +} + +// ---------------------------------------------------------------------- +// Initialization Functions +// ---------------------------------------------------------------------- + +/* +New - This function will create a new STIX Domain Name SCO and return it as a +pointer. It will also initialize the object by setting all of the basic +properties. +*/ +func New() *AutonomousSystem { + var obj AutonomousSystem + obj.InitSCO("autonomous-system") + return &obj +} diff --git a/objects/sco/autonomoussystem/setters.go b/objects/sco/autonomoussystem/setters.go new file mode 100644 index 0000000..fd54855 --- /dev/null +++ b/objects/sco/autonomoussystem/setters.go @@ -0,0 +1,6 @@ +// Copyright 2015-2022 Bret Jordan, All rights reserved. +// +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file in the root of the source tree. + +package autonomoussystem diff --git a/objects/sco/autonomoussystem/valid.go b/objects/sco/autonomoussystem/valid.go new file mode 100644 index 0000000..78bf7c0 --- /dev/null +++ b/objects/sco/autonomoussystem/valid.go @@ -0,0 +1,32 @@ +// Copyright 2015-2022 Bret Jordan, All rights reserved. +// +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file in the root of the source tree. + +package autonomoussystem + +// ---------------------------------------------------------------------- +// Public Methods +// ---------------------------------------------------------------------- + +/* +Valid - This method will verify and test all of the properties on an object +to make sure they are valid per the specification. It will return a boolean, an +integer that tracks the number of problems found, and a slice of strings that +contain the detailed results, whether good or bad. +*/ +func (o *AutonomousSystem) Valid(debug bool) (bool, int, []string) { + problemsFound := 0 + resultDetails := make([]string, 0) + + // Check common base properties first + _, pBase, dBase := o.CommonObjectProperties.ValidSDO(debug) + problemsFound += pBase + resultDetails = append(resultDetails, dBase...) + + if problemsFound > 0 { + return false, problemsFound, resultDetails + } + + return true, 0, resultDetails +} diff --git a/objects/sco/domainname/valid_test.go b/objects/sco/domainname/valid_test.go deleted file mode 100644 index c4e111c..0000000 --- a/objects/sco/domainname/valid_test.go +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2015-2022 Bret Jordan, All rights reserved. -// -// Use of this source code is governed by an Apache 2.0 license that can be -// found in the LICENSE file in the root of the source tree. - -package domainname - -import ( - "testing" -) - -// ---------------------------------------------------------------------- -// Tests -// These tests will not use the setters as some setters will have their -// own logic and verification steps in them. -// ---------------------------------------------------------------------- - -// ---------------------------------------------------------------------- -// Test the public Valid method - Make sure we hit each level and make sure -// required property checks are working when they are left blank. -// ---------------------------------------------------------------------- - -/* -TestValid1 - Make sure we get a value of false when DomainNameObject obj is blank. -*/ -func TestValid1(t *testing.T) { - m := New() - want := false - - if got, err := m.Valid(false); got != want { - t.Error("Fail DomainNameObject Object should be invalid when empty") - t.Log(err) - } -} - -//TestValid2 - -func TestValid2(t *testing.T) { - m := New() - want := true - - m.SetValue("test.domain.name") - - if got, err := m.Valid(false); got != want { - t.Error("Fail DomainNameObject Object should be valid when required fields are not empty") - t.Log(err) - } -} - -//TestValid9 - should be valid -func TestValid9(t *testing.T) { - m := New() - want := true - - m.SetValue("test.domein.name") - m.AddResolvesToRefs([]string{"ipv4-addr--efcd5e80-570d-4131-b213-62cb18eaa6a8", "ipv4-addr--efcd5e80-570d-4131-b213-62cb18eaa6a9"}) - m.AddResolvesToRef("ipv4-addr--efcd5e80-570d-4131-b213-62cb18eaa6a7") - - if got, err := m.Valid(false); got != want { - t.Error("Fail DomainNameObject Object should be valid") - t.Log(err) - } -} diff --git a/objects/sco/emailaddr/doc.go b/objects/sco/emailaddr/doc.go new file mode 100644 index 0000000..2a8cc7a --- /dev/null +++ b/objects/sco/emailaddr/doc.go @@ -0,0 +1,12 @@ +// Copyright 2015-2022 Bret Jordan, All rights reserved. +// +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file in the root of the source tree. + +/* +Package emailaddr implements the STIX 2.1 Email Address SCO object. + +The following information comes directly from the STIX 2.1 specification. + +*/ +package emailaddr diff --git a/objects/sco/emailaddr/json.go b/objects/sco/emailaddr/json.go new file mode 100644 index 0000000..ec438aa --- /dev/null +++ b/objects/sco/emailaddr/json.go @@ -0,0 +1,100 @@ +// Copyright 2015-2022 Bret Jordan, All rights reserved. +// +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file in the root of the source tree. + +package emailaddr + +import ( + "encoding/json" + + "github.com/freetaxii/libstix2/defs" +) + +// ---------------------------------------------------------------------- +// Public Functions - JSON Decoder +// ---------------------------------------------------------------------- + +/* +Decode - This function is a simple wrapper for decoding JSON data. It will +decode a slice of bytes into an actual struct and return a pointer to that +object along with any errors. +*/ +func Decode(data []byte) (*EmailAddr, error) { + var o EmailAddr + + if err := json.Unmarshal(data, &o); err != nil { + return nil, err + } + + return &o, nil +} + +/* +UnmarshalJSON - This method will over write the default UnmarshalJSON method +to enable custom properties that this library does not know about. It will store +them as map where the value of each key is a byte arrays. This way a tool that +does know how to deal with them can then further process them after this is +done. This will also allow the storage of the raw JSON data. +*/ +func (o *EmailAddr) UnmarshalJSON(b []byte) error { + + type alias EmailAddr + temp := &struct { + *alias + }{ + alias: (*alias)(o), + } + if err := json.Unmarshal(b, &temp); err != nil { + return err + } + + // This will create a map of all of the custom properties and store them in a + // property called o.Custom + if err := o.FindCustomProperties(b, o.GetPropertyList()); err != nil { + return err + } + + // This will store a complete copy of the original JSON in a byte array called + // o.Raw. This could be useful if you need to digitally sign the JSON or do + // verification on what was actually received. + if defs.KEEP_RAW_DATA == true { + o.SetRawData(b) + } + + return nil +} + +// ---------------------------------------------------------------------- +// Public Methods JSON Encoders +// The encoding is done here at the individual object level instead of at +// the STIX Object level so that individual pre/post processing rules can +// be applied. Since some of the STIX Objects do not follow a universal +// model, we need to cleanup some things that were inherited but not valid +// for the object. +// ---------------------------------------------------------------------- + +/* +Encode - This method is a simple wrapper for encoding an object into JSON +*/ +func (o *EmailAddr) Encode() ([]byte, error) { + data, err := json.MarshalIndent(o, "", " ") + if err != nil { + return nil, err + } + + // Any needed preprocessing would be done here + return data, nil +} + +/* +EncodeToString - This method is a simple wrapper for encoding an object into +JSON +*/ +func (o *EmailAddr) EncodeToString() (string, error) { + data, err := o.Encode() + if err != nil { + return "", err + } + return string(data), nil +} diff --git a/objects/sco/emailaddr/model.go b/objects/sco/emailaddr/model.go new file mode 100644 index 0000000..d85fd45 --- /dev/null +++ b/objects/sco/emailaddr/model.go @@ -0,0 +1,51 @@ +// Copyright 2015-2022 Bret Jordan, All rights reserved. +// +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file in the root of the source tree. + +package emailaddr + +import ( + "github.com/freetaxii/libstix2/objects" +) + +// ---------------------------------------------------------------------- +// Define Object Model +// ---------------------------------------------------------------------- + +/* +IPv4Addr - This type implements the STIX 2 IPv4 Address SCO and defines +all of the properties and methods needed to create and work with this object. +All of the methods not defined local to this type are inherited from the +individual properties. +*/ +type EmailAddr struct { + objects.CommonObjectProperties + objects.ValueProperty + objects.DisplayNameProperty + objects.BelongsToRefsProperty +} + +/* +GetPropertyList - This method will return a list of all of the properties that +are unique to this object. This is used by the custom UnmarshalJSON for this +object. It is defined here in this file to make it easy to keep in sync. +*/ +func (o *EmailAddr) GetPropertyList() []string { + return []string{"value", "resolves_to_refs", "display_name", "belongs_to_refs"} +} + +// ---------------------------------------------------------------------- +// Initialization Functions +// ---------------------------------------------------------------------- + +/* +New - This function will create a new STIX IPv4 Address SCO and return it as +a pointer. It will also initialize the object by setting all of the basic +properties. +*/ +func New() *EmailAddr { + var obj EmailAddr + obj.InitSCO("email-addr") + return &obj +} diff --git a/objects/sco/emailaddr/setters.go b/objects/sco/emailaddr/setters.go new file mode 100644 index 0000000..b94ffe7 --- /dev/null +++ b/objects/sco/emailaddr/setters.go @@ -0,0 +1,6 @@ +// Copyright 2015-2022 Bret Jordan, All rights reserved. +// +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file in the root of the source tree. + +package emailaddr diff --git a/objects/sco/emailaddr/valid.go b/objects/sco/emailaddr/valid.go new file mode 100644 index 0000000..7e0ddcd --- /dev/null +++ b/objects/sco/emailaddr/valid.go @@ -0,0 +1,32 @@ +// Copyright 2015-2022 Bret Jordan, All rights reserved. +// +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file in the root of the source tree. + +package emailaddr + +// ---------------------------------------------------------------------- +// Public Methods +// ---------------------------------------------------------------------- + +/* +Valid - This method will verify and test all of the properties on an object +to make sure they are valid per the specification. It will return a boolean, an +integer that tracks the number of problems found, and a slice of strings that +contain the detailed results, whether good or bad. +*/ +func (o *EmailAddr) Valid(debug bool) (bool, int, []string) { + problemsFound := 0 + resultDetails := make([]string, 0) + + // Check common base properties first + _, pBase, dBase := o.CommonObjectProperties.ValidSDO(debug) + problemsFound += pBase + resultDetails = append(resultDetails, dBase...) + + if problemsFound > 0 { + return false, problemsFound, resultDetails + } + + return true, 0, resultDetails +} diff --git a/objects/sco/emailmessage/doc.go b/objects/sco/emailmessage/doc.go new file mode 100644 index 0000000..9c28c60 --- /dev/null +++ b/objects/sco/emailmessage/doc.go @@ -0,0 +1,12 @@ +// Copyright 2015-2022 Bret Jordan, All rights reserved. +// +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file in the root of the source tree. + +/* +Package emailaddr implements the STIX 2.1 Email Address SCO object. + +The following information comes directly from the STIX 2.1 specification. + +*/ +package emailmessage diff --git a/objects/sco/emailmessage/json.go b/objects/sco/emailmessage/json.go new file mode 100644 index 0000000..601eba0 --- /dev/null +++ b/objects/sco/emailmessage/json.go @@ -0,0 +1,100 @@ +// Copyright 2015-2022 Bret Jordan, All rights reserved. +// +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file in the root of the source tree. + +package emailmessage + +import ( + "encoding/json" + + "github.com/freetaxii/libstix2/defs" +) + +// ---------------------------------------------------------------------- +// Public Functions - JSON Decoder +// ---------------------------------------------------------------------- + +/* +Decode - This function is a simple wrapper for decoding JSON data. It will +decode a slice of bytes into an actual struct and return a pointer to that +object along with any errors. +*/ +func Decode(data []byte) (*EmailMessage, error) { + var o EmailMessage + + if err := json.Unmarshal(data, &o); err != nil { + return nil, err + } + + return &o, nil +} + +/* +UnmarshalJSON - This method will over write the default UnmarshalJSON method +to enable custom properties that this library does not know about. It will store +them as map where the value of each key is a byte arrays. This way a tool that +does know how to deal with them can then further process them after this is +done. This will also allow the storage of the raw JSON data. +*/ +func (o *EmailMessage) UnmarshalJSON(b []byte) error { + + type alias EmailMessage + temp := &struct { + *alias + }{ + alias: (*alias)(o), + } + if err := json.Unmarshal(b, &temp); err != nil { + return err + } + + // This will create a map of all of the custom properties and store them in a + // property called o.Custom + if err := o.FindCustomProperties(b, o.GetPropertyList()); err != nil { + return err + } + + // This will store a complete copy of the original JSON in a byte array called + // o.Raw. This could be useful if you need to digitally sign the JSON or do + // verification on what was actually received. + if defs.KEEP_RAW_DATA == true { + o.SetRawData(b) + } + + return nil +} + +// ---------------------------------------------------------------------- +// Public Methods JSON Encoders +// The encoding is done here at the individual object level instead of at +// the STIX Object level so that individual pre/post processing rules can +// be applied. Since some of the STIX Objects do not follow a universal +// model, we need to cleanup some things that were inherited but not valid +// for the object. +// ---------------------------------------------------------------------- + +/* +Encode - This method is a simple wrapper for encoding an object into JSON +*/ +func (o *EmailMessage) Encode() ([]byte, error) { + data, err := json.MarshalIndent(o, "", " ") + if err != nil { + return nil, err + } + + // Any needed preprocessing would be done here + return data, nil +} + +/* +EncodeToString - This method is a simple wrapper for encoding an object into +JSON +*/ +func (o *EmailMessage) EncodeToString() (string, error) { + data, err := o.Encode() + if err != nil { + return "", err + } + return string(data), nil +} diff --git a/objects/sco/emailmessage/model.go b/objects/sco/emailmessage/model.go new file mode 100644 index 0000000..e9a4593 --- /dev/null +++ b/objects/sco/emailmessage/model.go @@ -0,0 +1,79 @@ +// Copyright 2015-2022 Bret Jordan, All rights reserved. +// +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file in the root of the source tree. + +package emailmessage + +import ( + "github.com/freetaxii/libstix2/objects" +) + +// ---------------------------------------------------------------------- +// Define Object Model +// ---------------------------------------------------------------------- + +/* +IPv4Addr - This type implements the STIX 2 IPv4 Address SCO and defines +all of the properties and methods needed to create and work with this object. +All of the methods not defined local to this type are inherited from the +individual properties. +*/ +type EmailMessage struct { + objects.CommonObjectProperties + IsMultipart bool `json:"is_multipart,omitempty" bson:"is_multipart,omitempty"` + Date string `json:"date,omitempty" bson:"date,omitempty"` + ContentType string `json:"content_type,omitempty" bson:"content_type,omitempty"` + FromRef string `json:"from_ref,omitempty" bson:"from_ref,omitempty"` + SenderRef string `json:"sender_ref,omitempty" bson:"sender_ref,omitempty"` + ToRefs []string `json:"to_refs,omitempty" bson:"to_refs,omitempty"` + CcRefs []string `json:"cc_refs,omitempty" bson:"cc_refs,omitempty"` + BccRefs []string `json:"bcc_refs,omitempty" bson:"bcc_refs,omitempty"` + MessageId string `json:"message_id,omitempty" bson:"message_id,omitempty"` + Subject string `json:"subject,omitempty" bson:"subject,omitempty"` + ReceivedLines []string `json:"received_lines,omitempty" bson:"received_lines,omitempty"` + AdditionalHeaderFields map[string]string `json:"additional_header_fields,omitempty" bson:"additional_header_fields,omitempty"` + Body string `json:"body,omitempty" bson:"body,omitempty"` + BodyMultipart []string `json:"body_multipart,omitempty" bson:"body_multipart,omitempty"` + RawEmailRef string `json:"raw_email_ref,omitempty" bson:"raw_email_ref,omitempty"` +} + +/* +GetPropertyList - This method will return a list of all of the properties that +are unique to this object. This is used by the custom UnmarshalJSON for this +object. It is defined here in this file to make it easy to keep in sync. +*/ +func (o *EmailMessage) GetPropertyList() []string { + return []string{ + "is_multipart", + "date", + "content_type", + "from_ref", + "sender_ref", + "to_refs", + "cc_refs", + "bcc_refs", + "message_id", + "subject", + "received_lines", + "additional_header_fields", + "body", + "body_multipart", + "raw_email_ref", + } +} + +// ---------------------------------------------------------------------- +// Initialization Functions +// ---------------------------------------------------------------------- + +/* +New - This function will create a new STIX IPv4 Address SCO and return it as +a pointer. It will also initialize the object by setting all of the basic +properties. +*/ +func New() *EmailMessage { + var obj EmailMessage + obj.InitSCO("email-message") + return &obj +} diff --git a/objects/sco/emailmessage/setters.go b/objects/sco/emailmessage/setters.go new file mode 100644 index 0000000..905fc2b --- /dev/null +++ b/objects/sco/emailmessage/setters.go @@ -0,0 +1,6 @@ +// Copyright 2015-2022 Bret Jordan, All rights reserved. +// +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file in the root of the source tree. + +package emailmessage diff --git a/objects/sco/emailmessage/valid.go b/objects/sco/emailmessage/valid.go new file mode 100644 index 0000000..2ac9c89 --- /dev/null +++ b/objects/sco/emailmessage/valid.go @@ -0,0 +1,48 @@ +// Copyright 2015-2022 Bret Jordan, All rights reserved. +// +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file in the root of the source tree. + +package emailmessage + +import "fmt" + +// ---------------------------------------------------------------------- +// Public Methods +// ---------------------------------------------------------------------- + +/* +Valid - This method will verify and test all of the properties on an object +to make sure they are valid per the specification. It will return a boolean, an +integer that tracks the number of problems found, and a slice of strings that +contain the detailed results, whether good or bad. +*/ +func (o *EmailMessage) Valid(debug bool) (bool, int, []string) { + problemsFound := 0 + resultDetails := make([]string, 0) + + // Check common base properties first + _, pBase, dBase := o.CommonObjectProperties.ValidSDO(debug) + problemsFound += pBase + resultDetails = append(resultDetails, dBase...) + + if !o.IsMultipart { + problemsFound++ + str := fmt.Sprintf("-- The is_multipart property is required but missing") + resultDetails = append(resultDetails, str) + } else { + str := fmt.Sprintf("++ The is_multipart property is required and is present") + resultDetails = append(resultDetails, str) + } + + // Verify object refs property is present + // _, pObjectRefs, dObjectRefs := o.ObjectRefsProperty.VerifyExists() + // problemsFound += pObjectRefs + // resultDetails = append(resultDetails, dObjectRefs...) + + if problemsFound > 0 { + return false, problemsFound, resultDetails + } + + return true, 0, resultDetails +} diff --git a/objects/sco/ipv4addr/setters.go b/objects/sco/ipv4addr/setters.go index 4f3d6de..ec24afb 100644 --- a/objects/sco/ipv4addr/setters.go +++ b/objects/sco/ipv4addr/setters.go @@ -3,4 +3,4 @@ // Use of this source code is governed by an Apache 2.0 license that can be // found in the LICENSE file in the root of the source tree. -package ipv4add +package ipv4addr diff --git a/objects/sco/ipv4addr/valid.go b/objects/sco/ipv4addr/valid.go index 885780b..b9cbace 100644 --- a/objects/sco/ipv4addr/valid.go +++ b/objects/sco/ipv4addr/valid.go @@ -15,7 +15,7 @@ to make sure they are valid per the specification. It will return a boolean, an integer that tracks the number of problems found, and a slice of strings that contain the detailed results, whether good or bad. */ -func (o *DomainName) Valid(debug bool) (bool, int, []string) { +func (o *IPv4Addr) Valid(debug bool) (bool, int, []string) { problemsFound := 0 resultDetails := make([]string, 0) @@ -24,11 +24,6 @@ func (o *DomainName) Valid(debug bool) (bool, int, []string) { problemsFound += pBase resultDetails = append(resultDetails, dBase...) - // Verify object value property present - _, pValue, dValue := o.ValueProperty.VerifyExists() - problemsFound += pValue - resultDetails = append(resultDetails, dValue...) - if problemsFound > 0 { return false, problemsFound, resultDetails } diff --git a/objects/sco/ipv4addr/valid_test.go b/objects/sco/ipv4addr/valid_test.go deleted file mode 100644 index c9d0e03..0000000 --- a/objects/sco/ipv4addr/valid_test.go +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2015-2022 Bret Jordan, All rights reserved. -// -// Use of this source code is governed by an Apache 2.0 license that can be -// found in the LICENSE file in the root of the source tree. - -package ipv4addrobject - -import ( - "testing" -) - -// ---------------------------------------------------------------------- -// Tests -// These tests will not use the setters as some setters will have their -// own logic and verification steps in them. -// ---------------------------------------------------------------------- - -// ---------------------------------------------------------------------- -// Test the public Valid method - Make sure we hit each level and make sure -// required property checks are working when they are left blank. -// ---------------------------------------------------------------------- - -/* -TestValid1 - Make sure we get a value of false when IPv4AddrObject obj is blank. -*/ -func TestValid1(t *testing.T) { - m := New() - want := false - - if got, err := m.Valid(false); got != want { - t.Error("Fail IPv4AddrObject Object should be invalid when empty") - t.Log(err) - } -} - -//TestValid2 - -func TestValid2(t *testing.T) { - m := New() - want := true - - m.SetValue("127.0.0.1") - - if got, err := m.Valid(false); got != want { - t.Error("Fail IPv4AddrObject Object should be valid when required fields are not empty") - t.Log(err) - } -} - -//TestValid9 - should be valid -func TestValid9(t *testing.T) { - m := New() - want := true - - m.SetValue("127.0.0.1") - m.AddResolvesToRefs([]string{"mac-addr--efcd5e80-570d-4131-b213-62cb18eaa6a8", "mac-addr--efcd5e80-570d-4131-b213-62cb18eaa6a9"}) - m.AddResolvesToRef("mac-addr--efcd5e80-570d-4131-b213-62cb18eaa6a7") - m.AddBelongsToRefs([]string{"3", "4"}) - m.AddBelongsToRef("5") - - if got, err := m.Valid(); got != want { - t.Error("Fail IPv4AddrObject Object shoulf be valid") - t.Log(err) - } -} diff --git a/objects/sco/ipv6addr/doc.go b/objects/sco/ipv6addr/doc.go new file mode 100644 index 0000000..9c80e60 --- /dev/null +++ b/objects/sco/ipv6addr/doc.go @@ -0,0 +1,14 @@ +// Copyright 2015-2022 Bret Jordan, All rights reserved. +// +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file in the root of the source tree. + +/* +Package ipv6addr implements the STIX 2.1 IPv6 Address SCO object. + +The following information comes directly from the STIX 2.1 specification. + +The IPv4 Address object represents one or more IPv4 addresses expressed using +CIDR notation. +*/ +package ipv6addr diff --git a/objects/sco/ipv6addr/json.go b/objects/sco/ipv6addr/json.go new file mode 100644 index 0000000..4a1893f --- /dev/null +++ b/objects/sco/ipv6addr/json.go @@ -0,0 +1,100 @@ +// Copyright 2015-2022 Bret Jordan, All rights reserved. +// +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file in the root of the source tree. + +package ipv6addr + +import ( + "encoding/json" + + "github.com/freetaxii/libstix2/defs" +) + +// ---------------------------------------------------------------------- +// Public Functions - JSON Decoder +// ---------------------------------------------------------------------- + +/* +Decode - This function is a simple wrapper for decoding JSON data. It will +decode a slice of bytes into an actual struct and return a pointer to that +object along with any errors. +*/ +func Decode(data []byte) (*IPv6Addr, error) { + var o IPv6Addr + + if err := json.Unmarshal(data, &o); err != nil { + return nil, err + } + + return &o, nil +} + +/* +UnmarshalJSON - This method will over write the default UnmarshalJSON method +to enable custom properties that this library does not know about. It will store +them as map where the value of each key is a byte arrays. This way a tool that +does know how to deal with them can then further process them after this is +done. This will also allow the storage of the raw JSON data. +*/ +func (o *IPv6Addr) UnmarshalJSON(b []byte) error { + + type alias IPv6Addr + temp := &struct { + *alias + }{ + alias: (*alias)(o), + } + if err := json.Unmarshal(b, &temp); err != nil { + return err + } + + // This will create a map of all of the custom properties and store them in a + // property called o.Custom + if err := o.FindCustomProperties(b, o.GetPropertyList()); err != nil { + return err + } + + // This will store a complete copy of the original JSON in a byte array called + // o.Raw. This could be useful if you need to digitally sign the JSON or do + // verification on what was actually received. + if defs.KEEP_RAW_DATA == true { + o.SetRawData(b) + } + + return nil +} + +// ---------------------------------------------------------------------- +// Public Methods JSON Encoders +// The encoding is done here at the individual object level instead of at +// the STIX Object level so that individual pre/post processing rules can +// be applied. Since some of the STIX Objects do not follow a universal +// model, we need to cleanup some things that were inherited but not valid +// for the object. +// ---------------------------------------------------------------------- + +/* +Encode - This method is a simple wrapper for encoding an object into JSON +*/ +func (o *IPv6Addr) Encode() ([]byte, error) { + data, err := json.MarshalIndent(o, "", " ") + if err != nil { + return nil, err + } + + // Any needed preprocessing would be done here + return data, nil +} + +/* +EncodeToString - This method is a simple wrapper for encoding an object into +JSON +*/ +func (o *IPv6Addr) EncodeToString() (string, error) { + data, err := o.Encode() + if err != nil { + return "", err + } + return string(data), nil +} diff --git a/objects/sco/ipv6addr/model.go b/objects/sco/ipv6addr/model.go new file mode 100644 index 0000000..f610616 --- /dev/null +++ b/objects/sco/ipv6addr/model.go @@ -0,0 +1,51 @@ +// Copyright 2015-2022 Bret Jordan, All rights reserved. +// +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file in the root of the source tree. + +package ipv6addr + +import ( + "github.com/freetaxii/libstix2/objects" +) + +// ---------------------------------------------------------------------- +// Define Object Model +// ---------------------------------------------------------------------- + +/* +IPv6Addr - This type implements the STIX 2 IPv6 Address SCO and defines +all of the properties and methods needed to create and work with this object. +All of the methods not defined local to this type are inherited from the +individual properties. +*/ +type IPv6Addr struct { + objects.CommonObjectProperties + objects.ValueProperty + objects.ResolvesToRefsProperty + objects.BelongsToRefsProperty +} + +/* +GetPropertyList - This method will return a list of all of the properties that +are unique to this object. This is used by the custom UnmarshalJSON for this +object. It is defined here in this file to make it easy to keep in sync. +*/ +func (o *IPv6Addr) GetPropertyList() []string { + return []string{"value", "resolves_to_refs", "belongs_to_refs"} +} + +// ---------------------------------------------------------------------- +// Initialization Functions +// ---------------------------------------------------------------------- + +/* +New - This function will create a new STIX IPv4 Address SCO and return it as +a pointer. It will also initialize the object by setting all of the basic +properties. +*/ +func New() *IPv6Addr { + var obj IPv6Addr + obj.InitSCO("ipv6-addr") + return &obj +} diff --git a/objects/sco/ipv6addr/setters.go b/objects/sco/ipv6addr/setters.go new file mode 100644 index 0000000..9003cf7 --- /dev/null +++ b/objects/sco/ipv6addr/setters.go @@ -0,0 +1,6 @@ +// Copyright 2015-2022 Bret Jordan, All rights reserved. +// +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file in the root of the source tree. + +package ipv6addr diff --git a/objects/sco/ipv6addr/valid.go b/objects/sco/ipv6addr/valid.go new file mode 100644 index 0000000..033a6db --- /dev/null +++ b/objects/sco/ipv6addr/valid.go @@ -0,0 +1,32 @@ +// Copyright 2015-2022 Bret Jordan, All rights reserved. +// +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file in the root of the source tree. + +package ipv6addr + +// ---------------------------------------------------------------------- +// Public Methods +// ---------------------------------------------------------------------- + +/* +Valid - This method will verify and test all of the properties on an object +to make sure they are valid per the specification. It will return a boolean, an +integer that tracks the number of problems found, and a slice of strings that +contain the detailed results, whether good or bad. +*/ +func (o *IPv6Addr) Valid(debug bool) (bool, int, []string) { + problemsFound := 0 + resultDetails := make([]string, 0) + + // Check common base properties first + _, pBase, dBase := o.CommonObjectProperties.ValidSDO(debug) + problemsFound += pBase + resultDetails = append(resultDetails, dBase...) + + if problemsFound > 0 { + return false, problemsFound, resultDetails + } + + return true, 0, resultDetails +} diff --git a/objects/sco/urlobject/valid_test.go b/objects/sco/urlobject/valid_test.go deleted file mode 100644 index 51fb20e..0000000 --- a/objects/sco/urlobject/valid_test.go +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2015-2022 Bret Jordan, All rights reserved. -// -// Use of this source code is governed by an Apache 2.0 license that can be -// found in the LICENSE file in the root of the source tree. - -package urlobject - -import ( - "testing" -) - -// ---------------------------------------------------------------------- -// Tests -// These tests will not use the setters as some setters will have their -// own logic and verification steps in them. -// ---------------------------------------------------------------------- - -// ---------------------------------------------------------------------- -// Test the public Valid method - Make sure we hit each level and make sure -// required property checks are working when they are left blank. -// ---------------------------------------------------------------------- - -/* -TestValid1 - Make sure we get a value of false when UrlObject obj is blank. -*/ -func TestValid1(t *testing.T) { - m := New() - want := false - - if got, err := m.Valid(false); got != want { - t.Error("Fail UrlObject Object should be invalid when empty") - t.Log(err) - } -} - -//TestValid2 - -func TestValid2(t *testing.T) { - m := New() - want := true - - m.SetValue("https://example.com/research/index.html") - - if got, err := m.Valid(false); got != want { - t.Error("Fail UrlObject Object should be valid when required fields are not empty") - t.Log(err) - } -} diff --git a/objects/sco/x509certificate/doc.go b/objects/sco/x509certificate/doc.go new file mode 100644 index 0000000..35149c2 --- /dev/null +++ b/objects/sco/x509certificate/doc.go @@ -0,0 +1,13 @@ +// Copyright 2015-2022 Bret Jordan, All rights reserved. +// +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file in the root of the source tree. + +/* +Package x509certificate implements the STIX 2.1 X509 Certificate SCO object. + +The following information comes directly from the STIX 2.1 specification. + +The Domain Name object represents the properties of a network domain name. +*/ +package x509certificate diff --git a/objects/sco/x509certificate/json.go b/objects/sco/x509certificate/json.go new file mode 100644 index 0000000..c8dcd62 --- /dev/null +++ b/objects/sco/x509certificate/json.go @@ -0,0 +1,100 @@ +// Copyright 2015-2022 Bret Jordan, All rights reserved. +// +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file in the root of the source tree. + +package x509certificate + +import ( + "encoding/json" + + "github.com/freetaxii/libstix2/defs" +) + +// ---------------------------------------------------------------------- +// Public Functions - JSON Decoder +// ---------------------------------------------------------------------- + +/* +Decode - This function is a simple wrapper for decoding JSON data. It will +decode a slice of bytes into an actual struct and return a pointer to that +object along with any errors. +*/ +func Decode(data []byte) (*X509Certificate, error) { + var o X509Certificate + + if err := json.Unmarshal(data, &o); err != nil { + return nil, err + } + + return &o, nil +} + +/* +UnmarshalJSON - This method will over write the default UnmarshalJSON method +to enable custom properties that this library does not know about. It will store +them as map where the value of each key is a byte arrays. This way a tool that +does know how to deal with them can then further process them after this is +done. This will also allow the storage of the raw JSON data. +*/ +func (o *X509Certificate) UnmarshalJSON(b []byte) error { + + type alias X509Certificate + temp := &struct { + *alias + }{ + alias: (*alias)(o), + } + if err := json.Unmarshal(b, &temp); err != nil { + return err + } + + // This will create a map of all of the custom properties and store them in a + // property called o.Custom + if err := o.FindCustomProperties(b, o.GetPropertyList()); err != nil { + return err + } + + // This will store a complete copy of the original JSON in a byte array called + // o.Raw. This could be useful if you need to digitally sign the JSON or do + // verification on what was actually received. + if defs.KEEP_RAW_DATA == true { + o.SetRawData(b) + } + + return nil +} + +// ---------------------------------------------------------------------- +// Public Methods JSON Encoders +// The encoding is done here at the individual object level instead of at +// the STIX Object level so that individual pre/post processing rules can +// be applied. Since some of the STIX Objects do not follow a universal +// model, we need to cleanup some things that were inherited but not valid +// for the object. +// ---------------------------------------------------------------------- + +/* +Encode - This method is a simple wrapper for encoding an object into JSON +*/ +func (o *X509Certificate) Encode() ([]byte, error) { + data, err := json.MarshalIndent(o, "", " ") + if err != nil { + return nil, err + } + + // Any needed preprocessing would be done here + return data, nil +} + +/* +EncodeToString - This method is a simple wrapper for encoding an object into +JSON +*/ +func (o *X509Certificate) EncodeToString() (string, error) { + data, err := o.Encode() + if err != nil { + return "", err + } + return string(data), nil +} diff --git a/objects/sco/x509certificate/model.go b/objects/sco/x509certificate/model.go new file mode 100644 index 0000000..79b1343 --- /dev/null +++ b/objects/sco/x509certificate/model.go @@ -0,0 +1,76 @@ +// Copyright 2015-2022 Bret Jordan, All rights reserved. +// +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file in the root of the source tree. + +package x509certificate + +import ( + "github.com/freetaxii/libstix2/objects" +) + +// ---------------------------------------------------------------------- +// Define Object Model +// ---------------------------------------------------------------------- + +/* +X509Certificate - This type implements the STIX 2 Domain Name SCO and defines +all of the properties and methods needed to create and work with this object. +All of the methods not defined local to this type are inherited from the +individual properties. +*/ +type X509Certificate struct { + objects.CommonObjectProperties + objects.ValueProperty + IsSelfSigned bool `json:"is_self_signed,omitempty" bson:"is_self_signed,omitempty"` + Hashes map[string]string `json:"hashes,omitempty" bson:"hashes,omitempty"` + Version string `json:"version,omitempty" bson:"version,omitempty"` + SerialNumber string `json:"serial_number,omitempty" bson:"serial_number,omitempty"` + SignatureAlgorithm string `json:"signature_algorithm,omitempty" bson:"signature_algorithm,omitempty"` + Issuer string `json:"issuer,omitempty" bson:"issuer,omitempty"` + ValidityNotBefore string `json:"validity_not_before,omitempty" bson:"validity_not_before,omitempty"` + ValidityNotAfter string `json:"validity_not_after,omitempty" bson:"validity_not_after,omitempty"` + Subject string `json:"subject,omitempty" bson:"subject,omitempty"` + SubjectPublicKeyAlgorithm string `json:"subject_public_key_algorithm,omitempty" bson:"subject_public_key_algorithm,omitempty"` + SubjectPublicKeyModulus string `json:"subject_public_key_modulus,omitempty" bson:"subject_public_key_modulus,omitempty"` + SubjectPublicKeyExponent int `json:"subject_public_key_exponent,omitempty" bson:"subject_public_key_exponent,omitempty"` + //TODO add X.509 V3 extension +} + +/* +GetPropertyList - This method will return a list of all of the properties that +are unique to this object. This is used by the custom UnmarshalJSON for this +object. It is defined here in this file to make it easy to keep in sync. +*/ +func (o *X509Certificate) GetPropertyList() []string { + return []string{ + "value", + "is_self_signed", + "hashes", + "version", + "serial_number", + "signature_algorithm", + "issuer", + "validity_not_before", + "validity_not_after", + "subject", + "subject_public_key_algorithm", + "subject_public_key_modulus", + "subject_public_key_exponent", + } +} + +// ---------------------------------------------------------------------- +// Initialization Functions +// ---------------------------------------------------------------------- + +/* +New - This function will create a new STIX Domain Name SCO and return it as a +pointer. It will also initialize the object by setting all of the basic +properties. +*/ +func New() *X509Certificate { + var obj X509Certificate + obj.InitSCO("x509-certificate") + return &obj +} diff --git a/objects/sco/x509certificate/setters.go b/objects/sco/x509certificate/setters.go new file mode 100644 index 0000000..fdeb33b --- /dev/null +++ b/objects/sco/x509certificate/setters.go @@ -0,0 +1,6 @@ +// Copyright 2015-2022 Bret Jordan, All rights reserved. +// +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file in the root of the source tree. + +package x509certificate diff --git a/objects/sco/x509certificate/valid.go b/objects/sco/x509certificate/valid.go new file mode 100644 index 0000000..1d24897 --- /dev/null +++ b/objects/sco/x509certificate/valid.go @@ -0,0 +1,32 @@ +// Copyright 2015-2022 Bret Jordan, All rights reserved. +// +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file in the root of the source tree. + +package x509certificate + +// ---------------------------------------------------------------------- +// Public Methods +// ---------------------------------------------------------------------- + +/* +Valid - This method will verify and test all of the properties on an object +to make sure they are valid per the specification. It will return a boolean, an +integer that tracks the number of problems found, and a slice of strings that +contain the detailed results, whether good or bad. +*/ +func (o *X509Certificate) Valid(debug bool) (bool, int, []string) { + problemsFound := 0 + resultDetails := make([]string, 0) + + // Check common base properties first + _, pBase, dBase := o.CommonObjectProperties.ValidSDO(debug) + problemsFound += pBase + resultDetails = append(resultDetails, dBase...) + + if problemsFound > 0 { + return false, problemsFound, resultDetails + } + + return true, 0, resultDetails +} From 9b38ed13058b4addbda37353005b043816fbac6a Mon Sep 17 00:00:00 2001 From: Konstantin Papesh Date: Tue, 26 Jul 2022 16:19:38 +0200 Subject: [PATCH 05/16] Fixed validation --- objects/sco/domainname/valid.go | 5 ----- objects/sco/urlobject/valid.go | 5 ----- 2 files changed, 10 deletions(-) diff --git a/objects/sco/domainname/valid.go b/objects/sco/domainname/valid.go index f481a73..c4d6d87 100644 --- a/objects/sco/domainname/valid.go +++ b/objects/sco/domainname/valid.go @@ -24,11 +24,6 @@ func (o *DomainName) Valid(debug bool) (bool, int, []string) { problemsFound += pBase resultDetails = append(resultDetails, dBase...) - // Verify object value property present - _, pValue, dValue := o.ValueProperty.VerifyExists() - problemsFound += pValue - resultDetails = append(resultDetails, dValue...) - if problemsFound > 0 { return false, problemsFound, resultDetails } diff --git a/objects/sco/urlobject/valid.go b/objects/sco/urlobject/valid.go index ead4aec..425b6e1 100644 --- a/objects/sco/urlobject/valid.go +++ b/objects/sco/urlobject/valid.go @@ -24,11 +24,6 @@ func (o *URLObject) Valid(debug bool) (bool, int, []string) { problemsFound += pBase resultDetails = append(resultDetails, dBase...) - // Verify object value property present - _, pValue, dValue := o.ValueProperty.VerifyExists() - problemsFound += pValue - resultDetails = append(resultDetails, dValue...) - if problemsFound > 0 { return false, problemsFound, resultDetails } From 9193caf7b1b1d98633e0069f24d4c88a5f4e2704 Mon Sep 17 00:00:00 2001 From: Konstantin Papesh Date: Tue, 26 Jul 2022 16:19:56 +0200 Subject: [PATCH 06/16] Added location to bundle --- objects/bundle/json.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/objects/bundle/json.go b/objects/bundle/json.go index c4597bb..f8e8fde 100644 --- a/objects/bundle/json.go +++ b/objects/bundle/json.go @@ -25,6 +25,7 @@ import ( "github.com/freetaxii/libstix2/objects/indicator" "github.com/freetaxii/libstix2/objects/infrastructure" "github.com/freetaxii/libstix2/objects/intrusionset" + "github.com/freetaxii/libstix2/objects/location" "github.com/freetaxii/libstix2/objects/malware" "github.com/freetaxii/libstix2/objects/observeddata" "github.com/freetaxii/libstix2/objects/relationship" @@ -81,6 +82,9 @@ func DecodeWithCustomObjects(r io.Reader, customDecoders map[string]DecodeFunc) "sighting": func(bytes []byte) (objects.STIXObject, error) { return sighting.Decode(bytes) }, + "location": func(bytes []byte) (objects.STIXObject, error) { + return location.Decode(bytes) + }, "threat-actor": func(bytes []byte) (objects.STIXObject, error) { return threatactor.Decode(bytes) }, From 077f284a0a5c3af4ebe125365af30509870e8f98 Mon Sep 17 00:00:00 2001 From: Konstantin Papesh Date: Tue, 26 Jul 2022 16:20:12 +0200 Subject: [PATCH 07/16] Fixed AdditionalHeaderFields mapping --- objects/sco/emailmessage/model.go | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/objects/sco/emailmessage/model.go b/objects/sco/emailmessage/model.go index e9a4593..e213022 100644 --- a/objects/sco/emailmessage/model.go +++ b/objects/sco/emailmessage/model.go @@ -21,21 +21,21 @@ individual properties. */ type EmailMessage struct { objects.CommonObjectProperties - IsMultipart bool `json:"is_multipart,omitempty" bson:"is_multipart,omitempty"` - Date string `json:"date,omitempty" bson:"date,omitempty"` - ContentType string `json:"content_type,omitempty" bson:"content_type,omitempty"` - FromRef string `json:"from_ref,omitempty" bson:"from_ref,omitempty"` - SenderRef string `json:"sender_ref,omitempty" bson:"sender_ref,omitempty"` - ToRefs []string `json:"to_refs,omitempty" bson:"to_refs,omitempty"` - CcRefs []string `json:"cc_refs,omitempty" bson:"cc_refs,omitempty"` - BccRefs []string `json:"bcc_refs,omitempty" bson:"bcc_refs,omitempty"` - MessageId string `json:"message_id,omitempty" bson:"message_id,omitempty"` - Subject string `json:"subject,omitempty" bson:"subject,omitempty"` - ReceivedLines []string `json:"received_lines,omitempty" bson:"received_lines,omitempty"` - AdditionalHeaderFields map[string]string `json:"additional_header_fields,omitempty" bson:"additional_header_fields,omitempty"` - Body string `json:"body,omitempty" bson:"body,omitempty"` - BodyMultipart []string `json:"body_multipart,omitempty" bson:"body_multipart,omitempty"` - RawEmailRef string `json:"raw_email_ref,omitempty" bson:"raw_email_ref,omitempty"` + IsMultipart bool `json:"is_multipart,omitempty" bson:"is_multipart,omitempty"` + Date string `json:"date,omitempty" bson:"date,omitempty"` + ContentType string `json:"content_type,omitempty" bson:"content_type,omitempty"` + FromRef string `json:"from_ref,omitempty" bson:"from_ref,omitempty"` + SenderRef string `json:"sender_ref,omitempty" bson:"sender_ref,omitempty"` + ToRefs []string `json:"to_refs,omitempty" bson:"to_refs,omitempty"` + CcRefs []string `json:"cc_refs,omitempty" bson:"cc_refs,omitempty"` + BccRefs []string `json:"bcc_refs,omitempty" bson:"bcc_refs,omitempty"` + MessageId string `json:"message_id,omitempty" bson:"message_id,omitempty"` + Subject string `json:"subject,omitempty" bson:"subject,omitempty"` + ReceivedLines []string `json:"received_lines,omitempty" bson:"received_lines,omitempty"` + AdditionalHeaderFields map[string]any `json:"additional_header_fields,omitempty" bson:"additional_header_fields,omitempty"` + Body string `json:"body,omitempty" bson:"body,omitempty"` + BodyMultipart []string `json:"body_multipart,omitempty" bson:"body_multipart,omitempty"` + RawEmailRef string `json:"raw_email_ref,omitempty" bson:"raw_email_ref,omitempty"` } /* From a6b6483bae8cdbe01ea98b0cba7b5dc73adfaec6 Mon Sep 17 00:00:00 2001 From: Konstantin Papesh Date: Tue, 26 Jul 2022 16:20:24 +0200 Subject: [PATCH 08/16] Bumped go version to 1.18 --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 1f2eb15..e4a2ea2 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/freetaxii/libstix2 -go 1.13 +go 1.18 require ( github.com/gologme/log v1.2.0 From c8e94a36fc24e1693bb890b4f37d066696cefe52 Mon Sep 17 00:00:00 2001 From: Konstantin Papesh Date: Mon, 1 Aug 2022 12:34:19 +0200 Subject: [PATCH 09/16] Added BodyMultipart --- objects/sco/emailmessage/model.go | 11 +++++++++-- objects/sco/emailmessage/valid.go | 10 +++++++--- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/objects/sco/emailmessage/model.go b/objects/sco/emailmessage/model.go index e213022..11d869f 100644 --- a/objects/sco/emailmessage/model.go +++ b/objects/sco/emailmessage/model.go @@ -14,7 +14,7 @@ import ( // ---------------------------------------------------------------------- /* -IPv4Addr - This type implements the STIX 2 IPv4 Address SCO and defines +EmailMessage - This type implements the STIX 2 Email Message SCO and defines all of the properties and methods needed to create and work with this object. All of the methods not defined local to this type are inherited from the individual properties. @@ -34,10 +34,17 @@ type EmailMessage struct { ReceivedLines []string `json:"received_lines,omitempty" bson:"received_lines,omitempty"` AdditionalHeaderFields map[string]any `json:"additional_header_fields,omitempty" bson:"additional_header_fields,omitempty"` Body string `json:"body,omitempty" bson:"body,omitempty"` - BodyMultipart []string `json:"body_multipart,omitempty" bson:"body_multipart,omitempty"` + BodyMultipart []MimePartType `json:"body_multipart,omitempty" bson:"body_multipart,omitempty"` RawEmailRef string `json:"raw_email_ref,omitempty" bson:"raw_email_ref,omitempty"` } +type MimePartType struct { + Body string `json:"body,omitempty" bson:"body,omitempty"` + BodyRawRef string `json:"body_raw_ref,omitempty" bson:"body_raw_ref,omitempty"` + ContentType string `json:"content_type,omitempty" bson:"content_type,omitempty"` + ContentDisposition string `json:"content_disposition,omitempty" bson:"content_disposition,omitempty"` +} + /* GetPropertyList - This method will return a list of all of the properties that are unique to this object. This is used by the custom UnmarshalJSON for this diff --git a/objects/sco/emailmessage/valid.go b/objects/sco/emailmessage/valid.go index 2ac9c89..565bf19 100644 --- a/objects/sco/emailmessage/valid.go +++ b/objects/sco/emailmessage/valid.go @@ -26,12 +26,16 @@ func (o *EmailMessage) Valid(debug bool) (bool, int, []string) { problemsFound += pBase resultDetails = append(resultDetails, dBase...) - if !o.IsMultipart { + if o.IsMultipart && len(o.BodyMultipart) == 0 { problemsFound++ - str := fmt.Sprintf("-- The is_multipart property is required but missing") + str := fmt.Sprintf("-- is_multipart is set but body_multipart is empty") + resultDetails = append(resultDetails, str) + } else if !o.IsMultipart && len(o.BodyMultipart) > 0 { + problemsFound++ + str := fmt.Sprintf("-- is_multipart is not set but body_multipart is not empty") resultDetails = append(resultDetails, str) } else { - str := fmt.Sprintf("++ The is_multipart property is required and is present") + str := fmt.Sprintf("-- is_multipart is ok") resultDetails = append(resultDetails, str) } From fb094553555e92982fa02ec2bf4bd9cf24ccb3d4 Mon Sep 17 00:00:00 2001 From: Konstantin Papesh Date: Tue, 2 Aug 2022 10:21:39 +0200 Subject: [PATCH 10/16] Fixed analysis_sco_refs not being a list --- objects/malwareanalysis/model.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/objects/malwareanalysis/model.go b/objects/malwareanalysis/model.go index d4fa919..d30650e 100644 --- a/objects/malwareanalysis/model.go +++ b/objects/malwareanalysis/model.go @@ -32,7 +32,7 @@ type MalwareAnalysis struct { AnalysisStarted string `json:"analysis_started,omitempty" bson:"analysis_started,omitempty"` AnalysisEnded string `json:"analysis_ended,omitempty" bson:"analysis_ended,omitempty"` AVResults string `json:"av_results,omitempty" bson:"av_results,omitempty"` - AnalysisSCORefs string `json:"analysis_sco_refs,omitempty" bson:"analysis_sco_refs,omitempty"` + AnalysisSCORefs []string `json:"analysis_sco_refs,omitempty" bson:"analysis_sco_refs,omitempty"` } /* From 9c54f0e1b42a59cd03510cdec7f6cadc7918760d Mon Sep 17 00:00:00 2001 From: Konstantin Papesh Date: Wed, 3 Aug 2022 12:44:23 +0200 Subject: [PATCH 11/16] Fixed missing malware-analysis --- objects/bundle/json.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/objects/bundle/json.go b/objects/bundle/json.go index f8e8fde..ecff6d4 100644 --- a/objects/bundle/json.go +++ b/objects/bundle/json.go @@ -7,6 +7,7 @@ package bundle import ( "encoding/json" + "github.com/freetaxii/libstix2/objects/malwareanalysis" "github.com/freetaxii/libstix2/objects/sco/autonomoussystem" "github.com/freetaxii/libstix2/objects/sco/domainname" "github.com/freetaxii/libstix2/objects/sco/emailaddr" @@ -73,6 +74,9 @@ func DecodeWithCustomObjects(r io.Reader, customDecoders map[string]DecodeFunc) "malware": func(bytes []byte) (objects.STIXObject, error) { return malware.Decode(bytes) }, + "malware-analysis": func(bytes []byte) (objects.STIXObject, error) { + return malwareanalysis.Decode(bytes) + }, "observed-data": func(bytes []byte) (objects.STIXObject, error) { return observeddata.Decode(bytes) }, From 5fafd6b760c4b1bacbf5423206f488ead524fff8 Mon Sep 17 00:00:00 2001 From: Konstantin Papesh Date: Sun, 7 Aug 2022 14:00:11 +0200 Subject: [PATCH 12/16] Added go.sum --- go.sum | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 go.sum diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..9a2c4e2 --- /dev/null +++ b/go.sum @@ -0,0 +1,5 @@ +github.com/gologme/log v1.2.0/go.mod h1:gq31gQ8wEHkR+WekdWsqDuf8pXTUZA9BnnzTuPz1Y9U= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/mattn/go-sqlite3 v1.13.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/pborman/getopt v0.0.0-20190409184431-ee0cd42419d3/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= From 576c297aef5b818ffd2105999fc721073b322fbd Mon Sep 17 00:00:00 2001 From: Konstantin Papesh Date: Wed, 10 Aug 2022 12:40:03 +0200 Subject: [PATCH 13/16] Added network-traffic --- objects/bundle/json.go | 4 ++ objects/sco/networktraffic/doc.go | 13 ++++ objects/sco/networktraffic/json.go | 100 ++++++++++++++++++++++++++ objects/sco/networktraffic/model.go | 85 ++++++++++++++++++++++ objects/sco/networktraffic/setters.go | 6 ++ objects/sco/networktraffic/valid.go | 32 +++++++++ 6 files changed, 240 insertions(+) create mode 100644 objects/sco/networktraffic/doc.go create mode 100644 objects/sco/networktraffic/json.go create mode 100644 objects/sco/networktraffic/model.go create mode 100644 objects/sco/networktraffic/setters.go create mode 100644 objects/sco/networktraffic/valid.go diff --git a/objects/bundle/json.go b/objects/bundle/json.go index ecff6d4..c7fe39d 100644 --- a/objects/bundle/json.go +++ b/objects/bundle/json.go @@ -14,6 +14,7 @@ import ( "github.com/freetaxii/libstix2/objects/sco/emailmessage" "github.com/freetaxii/libstix2/objects/sco/ipv4addr" "github.com/freetaxii/libstix2/objects/sco/ipv6addr" + "github.com/freetaxii/libstix2/objects/sco/networktraffic" "github.com/freetaxii/libstix2/objects/sco/urlobject" "github.com/freetaxii/libstix2/objects/sco/x509certificate" "io" @@ -125,6 +126,9 @@ func DecodeWithCustomObjects(r io.Reader, customDecoders map[string]DecodeFunc) "autonomous-system": func(bytes []byte) (objects.STIXObject, error) { return autonomoussystem.Decode(bytes) }, + "network-traffic": func(bytes []byte) (objects.STIXObject, error) { + return networktraffic.Decode(bytes) + }, } for k, v := range customDecoders { decoders[k] = v diff --git a/objects/sco/networktraffic/doc.go b/objects/sco/networktraffic/doc.go new file mode 100644 index 0000000..e0aeaa4 --- /dev/null +++ b/objects/sco/networktraffic/doc.go @@ -0,0 +1,13 @@ +// Copyright 2015-2022 Bret Jordan, All rights reserved. +// +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file in the root of the source tree. + +/* +Package networktraffic implements the STIX 2.1 Network Traffic SCO object. + +The following information comes directly from the STIX 2.1 specification. + +The Domain Name object represents the properties of a network domain name. +*/ +package networktraffic diff --git a/objects/sco/networktraffic/json.go b/objects/sco/networktraffic/json.go new file mode 100644 index 0000000..1d3cb8c --- /dev/null +++ b/objects/sco/networktraffic/json.go @@ -0,0 +1,100 @@ +// Copyright 2015-2022 Bret Jordan, All rights reserved. +// +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file in the root of the source tree. + +package networktraffic + +import ( + "encoding/json" + + "github.com/freetaxii/libstix2/defs" +) + +// ---------------------------------------------------------------------- +// Public Functions - JSON Decoder +// ---------------------------------------------------------------------- + +/* +Decode - This function is a simple wrapper for decoding JSON data. It will +decode a slice of bytes into an actual struct and return a pointer to that +object along with any errors. +*/ +func Decode(data []byte) (*NetworkTraffic, error) { + var o NetworkTraffic + + if err := json.Unmarshal(data, &o); err != nil { + return nil, err + } + + return &o, nil +} + +/* +UnmarshalJSON - This method will over write the default UnmarshalJSON method +to enable custom properties that this library does not know about. It will store +them as map where the value of each key is a byte arrays. This way a tool that +does know how to deal with them can then further process them after this is +done. This will also allow the storage of the raw JSON data. +*/ +func (o *NetworkTraffic) UnmarshalJSON(b []byte) error { + + type alias NetworkTraffic + temp := &struct { + *alias + }{ + alias: (*alias)(o), + } + if err := json.Unmarshal(b, &temp); err != nil { + return err + } + + // This will create a map of all of the custom properties and store them in a + // property called o.Custom + if err := o.FindCustomProperties(b, o.GetPropertyList()); err != nil { + return err + } + + // This will store a complete copy of the original JSON in a byte array called + // o.Raw. This could be useful if you need to digitally sign the JSON or do + // verification on what was actually received. + if defs.KEEP_RAW_DATA == true { + o.SetRawData(b) + } + + return nil +} + +// ---------------------------------------------------------------------- +// Public Methods JSON Encoders +// The encoding is done here at the individual object level instead of at +// the STIX Object level so that individual pre/post processing rules can +// be applied. Since some of the STIX Objects do not follow a universal +// model, we need to cleanup some things that were inherited but not valid +// for the object. +// ---------------------------------------------------------------------- + +/* +Encode - This method is a simple wrapper for encoding an object into JSON +*/ +func (o *NetworkTraffic) Encode() ([]byte, error) { + data, err := json.MarshalIndent(o, "", " ") + if err != nil { + return nil, err + } + + // Any needed preprocessing would be done here + return data, nil +} + +/* +EncodeToString - This method is a simple wrapper for encoding an object into +JSON +*/ +func (o *NetworkTraffic) EncodeToString() (string, error) { + data, err := o.Encode() + if err != nil { + return "", err + } + return string(data), nil +} diff --git a/objects/sco/networktraffic/model.go b/objects/sco/networktraffic/model.go new file mode 100644 index 0000000..94974fe --- /dev/null +++ b/objects/sco/networktraffic/model.go @@ -0,0 +1,85 @@ +// Copyright 2015-2022 Bret Jordan, All rights reserved. +// +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file in the root of the source tree. + +package networktraffic + +import ( + "github.com/freetaxii/libstix2/objects" +) + +// ---------------------------------------------------------------------- +// Define Object Model +// ---------------------------------------------------------------------- + +/* +NetworkTraffic - This type implements the STIX 2 Network Traffic SCO and defines +all of the properties and methods needed to create and work with this object. +All of the methods not defined local to this type are inherited from the +individual properties. +*/ +type NetworkTraffic struct { + objects.CommonObjectProperties + Extensions map[string]string `json:"extensions,omitempty" bson:"extensions,omitempty"` + Start string `json:"start,omitempty" bson:"start,omitempty"` + End string `json:"end,omitempty" bson:"end,omitempty"` + IsActive bool `json:"is_active,omitempty" bson:"is_active,omitempty"` + SrcRef string `json:"src_ref,omitempty" bson:"src_ref,omitempty"` + DstRef string `json:"dst_ref,omitempty" bson:"dst_ref,omitempty"` + SrcPort int `json:"src_port,omitempty" bson:"src_port,omitempty"` + DstPort int `json:"dst_port,omitempty" bson:"dst_port,omitempty"` + Protocols []string `json:"protocols,omitempty" bson:"protocols,omitempty"` + SrcByteCount int `json:"src_byte_count,omitempty" bson:"src_byte_count,omitempty"` + DstByteCount int `json:"dst_byte_count,omitempty" bson:"dst_byte_count,omitempty"` + SrcPackets int `json:"src_packets,omitempty" bson:"src_packets,omitempty"` + DstPackets int `json:"dst_packets,omitempty" bson:"dst_packets,omitempty"` + Ipfix map[string]string `json:"ipfix,omitempty" bson:"ipfix,omitempty"` + SrcPayloadRef string `json:"src_payload_ref,omitempty" bson:"src_payload_ref,omitempty"` + DstPayloadRef string `json:"dst_payload_ref,omitempty" bson:"dst_payload_ref,omitempty"` + EncapsulatesRefs []string `json:"encapsulates_refs,omitempty" bson:"encapsulates_refs,omitempty"` + EncapsulatedByRef string `json:"encapsulated_by_ref,omitempty" bson:"encapsulated_by_ref,omitempty"` +} + +/* +GetPropertyList - This method will return a list of all of the properties that +are unique to this object. This is used by the custom UnmarshalJSON for this +object. It is defined here in this file to make it easy to keep in sync. +*/ +func (o *NetworkTraffic) GetPropertyList() []string { + return []string{ + "extensions", + "start", + "end", + "is_active", + "src_ref", + "dst_ref", + "src_port", + "dst_port", + "protocols", + "src_byte_count", + "dst_byte_count", + "src_packets", + "dst_packets", + "ipfix", + "src_payload_ref", + "dst_payload_ref", + "encapsulates_ref", + "encapsulated_by_ref", + } +} + +// ---------------------------------------------------------------------- +// Initialization Functions +// ---------------------------------------------------------------------- + +/* +New - This function will create a new STIX Domain Name SCO and return it as a +pointer. It will also initialize the object by setting all of the basic +properties. +*/ +func New() *NetworkTraffic { + var obj NetworkTraffic + obj.InitSCO("network-traffic") + return &obj +} diff --git a/objects/sco/networktraffic/setters.go b/objects/sco/networktraffic/setters.go new file mode 100644 index 0000000..f1de22a --- /dev/null +++ b/objects/sco/networktraffic/setters.go @@ -0,0 +1,6 @@ +// Copyright 2015-2022 Bret Jordan, All rights reserved. +// +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file in the root of the source tree. + +package networktraffic diff --git a/objects/sco/networktraffic/valid.go b/objects/sco/networktraffic/valid.go new file mode 100644 index 0000000..e1c737e --- /dev/null +++ b/objects/sco/networktraffic/valid.go @@ -0,0 +1,32 @@ +// Copyright 2015-2022 Bret Jordan, All rights reserved. +// +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file in the root of the source tree. + +package networktraffic + +// ---------------------------------------------------------------------- +// Public Methods +// ---------------------------------------------------------------------- + +/* +Valid - This method will verify and test all of the properties on an object +to make sure they are valid per the specification. It will return a boolean, an +integer that tracks the number of problems found, and a slice of strings that +contain the detailed results, whether good or bad. +*/ +func (o *NetworkTraffic) Valid(debug bool) (bool, int, []string) { + problemsFound := 0 + resultDetails := make([]string, 0) + + // Check common base properties first + _, pBase, dBase := o.CommonObjectProperties.ValidSDO(debug) + problemsFound += pBase + resultDetails = append(resultDetails, dBase...) + + if problemsFound > 0 { + return false, problemsFound, resultDetails + } + + return true, 0, resultDetails +} From 002f9f2bb5fa6d7119a4c87d3f2220a99ed449d4 Mon Sep 17 00:00:00 2001 From: Konstantin Papesh Date: Wed, 10 Aug 2022 12:43:53 +0200 Subject: [PATCH 14/16] Added sofware SCO --- README.md | 20 +++++++ objects/bundle/json.go | 4 ++ objects/sco/software/doc.go | 13 +++++ objects/sco/software/json.go | 100 ++++++++++++++++++++++++++++++++ objects/sco/software/model.go | 59 +++++++++++++++++++ objects/sco/software/setters.go | 6 ++ objects/sco/software/valid.go | 32 ++++++++++ 7 files changed, 234 insertions(+) create mode 100644 objects/sco/software/doc.go create mode 100644 objects/sco/software/json.go create mode 100644 objects/sco/software/model.go create mode 100644 objects/sco/software/setters.go create mode 100644 objects/sco/software/valid.go diff --git a/README.md b/README.md index 0b8a5ba..c11b51c 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,26 @@ STIX Relationship Objects - [x] Relationship - [x] Sighting +STIX Cyber-observable Objects +- [ ] Artifact +- [X] Autonomous System +- [ ] Directory +- [X] Domain Name +- [X] Email Address +- [X] Email Message +- [ ] File +- [X] IPv4 Address +- [X] IPv6 Address +- [ ] MAC Address +- [ ] Mutex +- [X] Network Traffic +- [ ] Process +- [ ] Software +- [X] URL +- [ ] User Account +- [ ] Windows Registry Key +- [X] X.509 Certificate + Other STIX Objects - [x] Bundle - [ ] Language Content diff --git a/objects/bundle/json.go b/objects/bundle/json.go index c7fe39d..000e73c 100644 --- a/objects/bundle/json.go +++ b/objects/bundle/json.go @@ -15,6 +15,7 @@ import ( "github.com/freetaxii/libstix2/objects/sco/ipv4addr" "github.com/freetaxii/libstix2/objects/sco/ipv6addr" "github.com/freetaxii/libstix2/objects/sco/networktraffic" + "github.com/freetaxii/libstix2/objects/sco/software" "github.com/freetaxii/libstix2/objects/sco/urlobject" "github.com/freetaxii/libstix2/objects/sco/x509certificate" "io" @@ -129,6 +130,9 @@ func DecodeWithCustomObjects(r io.Reader, customDecoders map[string]DecodeFunc) "network-traffic": func(bytes []byte) (objects.STIXObject, error) { return networktraffic.Decode(bytes) }, + "software": func(bytes []byte) (objects.STIXObject, error) { + return software.Decode(bytes) + }, } for k, v := range customDecoders { decoders[k] = v diff --git a/objects/sco/software/doc.go b/objects/sco/software/doc.go new file mode 100644 index 0000000..ce0b9e4 --- /dev/null +++ b/objects/sco/software/doc.go @@ -0,0 +1,13 @@ +// Copyright 2015-2022 Bret Jordan, All rights reserved. +// +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file in the root of the source tree. + +/* +Package software implements the STIX 2.1 Software SCO object. + +The following information comes directly from the STIX 2.1 specification. + +The Domain Name object represents the properties of a network domain name. +*/ +package software diff --git a/objects/sco/software/json.go b/objects/sco/software/json.go new file mode 100644 index 0000000..8d134a1 --- /dev/null +++ b/objects/sco/software/json.go @@ -0,0 +1,100 @@ +// Copyright 2015-2022 Bret Jordan, All rights reserved. +// +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file in the root of the source tree. + +package software + +import ( + "encoding/json" + + "github.com/freetaxii/libstix2/defs" +) + +// ---------------------------------------------------------------------- +// Public Functions - JSON Decoder +// ---------------------------------------------------------------------- + +/* +Decode - This function is a simple wrapper for decoding JSON data. It will +decode a slice of bytes into an actual struct and return a pointer to that +object along with any errors. +*/ +func Decode(data []byte) (*Software, error) { + var o Software + + if err := json.Unmarshal(data, &o); err != nil { + return nil, err + } + + return &o, nil +} + +/* +UnmarshalJSON - This method will over write the default UnmarshalJSON method +to enable custom properties that this library does not know about. It will store +them as map where the value of each key is a byte arrays. This way a tool that +does know how to deal with them can then further process them after this is +done. This will also allow the storage of the raw JSON data. +*/ +func (o *Software) UnmarshalJSON(b []byte) error { + + type alias Software + temp := &struct { + *alias + }{ + alias: (*alias)(o), + } + if err := json.Unmarshal(b, &temp); err != nil { + return err + } + + // This will create a map of all of the custom properties and store them in a + // property called o.Custom + if err := o.FindCustomProperties(b, o.GetPropertyList()); err != nil { + return err + } + + // This will store a complete copy of the original JSON in a byte array called + // o.Raw. This could be useful if you need to digitally sign the JSON or do + // verification on what was actually received. + if defs.KEEP_RAW_DATA == true { + o.SetRawData(b) + } + + return nil +} + +// ---------------------------------------------------------------------- +// Public Methods JSON Encoders +// The encoding is done here at the individual object level instead of at +// the STIX Object level so that individual pre/post processing rules can +// be applied. Since some of the STIX Objects do not follow a universal +// model, we need to cleanup some things that were inherited but not valid +// for the object. +// ---------------------------------------------------------------------- + +/* +Encode - This method is a simple wrapper for encoding an object into JSON +*/ +func (o *Software) Encode() ([]byte, error) { + data, err := json.MarshalIndent(o, "", " ") + if err != nil { + return nil, err + } + + // Any needed preprocessing would be done here + return data, nil +} + +/* +EncodeToString - This method is a simple wrapper for encoding an object into +JSON +*/ +func (o *Software) EncodeToString() (string, error) { + data, err := o.Encode() + if err != nil { + return "", err + } + return string(data), nil +} diff --git a/objects/sco/software/model.go b/objects/sco/software/model.go new file mode 100644 index 0000000..7fd5483 --- /dev/null +++ b/objects/sco/software/model.go @@ -0,0 +1,59 @@ +// Copyright 2015-2022 Bret Jordan, All rights reserved. +// +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file in the root of the source tree. + +package software + +import ( + "github.com/freetaxii/libstix2/objects" +) + +// ---------------------------------------------------------------------- +// Define Object Model +// ---------------------------------------------------------------------- + +/* +Software - This type implements the STIX 2 Software SCO and defines +all of the properties and methods needed to create and work with this object. +All of the methods not defined local to this type are inherited from the +individual properties. +*/ +type Software struct { + objects.CommonObjectProperties + objects.NameProperty + Cpe string `json:"cpe,omitempty" bson:"cpe,omitempty"` + Languages []string `json:"languages,omitempty" bson:"languages,omitempty"` + Vendor string `json:"vendor,omitempty" vendor,omitempty"` + Version string `json:"version,omitempty" bson:"version,omitempty"` +} + +/* +GetPropertyList - This method will return a list of all of the properties that +are unique to this object. This is used by the custom UnmarshalJSON for this +object. It is defined here in this file to make it easy to keep in sync. +*/ +func (o *Software) GetPropertyList() []string { + return []string{ + "name", + "cpe", + "languages", + "vendor", + "version", + } +} + +// ---------------------------------------------------------------------- +// Initialization Functions +// ---------------------------------------------------------------------- + +/* +New - This function will create a new STIX Domain Name SCO and return it as a +pointer. It will also initialize the object by setting all of the basic +properties. +*/ +func New() *Software { + var obj Software + obj.InitSCO("software") + return &obj +} diff --git a/objects/sco/software/setters.go b/objects/sco/software/setters.go new file mode 100644 index 0000000..cf2e893 --- /dev/null +++ b/objects/sco/software/setters.go @@ -0,0 +1,6 @@ +// Copyright 2015-2022 Bret Jordan, All rights reserved. +// +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file in the root of the source tree. + +package software diff --git a/objects/sco/software/valid.go b/objects/sco/software/valid.go new file mode 100644 index 0000000..71bb0e0 --- /dev/null +++ b/objects/sco/software/valid.go @@ -0,0 +1,32 @@ +// Copyright 2015-2022 Bret Jordan, All rights reserved. +// +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file in the root of the source tree. + +package software + +// ---------------------------------------------------------------------- +// Public Methods +// ---------------------------------------------------------------------- + +/* +Valid - This method will verify and test all of the properties on an object +to make sure they are valid per the specification. It will return a boolean, an +integer that tracks the number of problems found, and a slice of strings that +contain the detailed results, whether good or bad. +*/ +func (o *Software) Valid(debug bool) (bool, int, []string) { + problemsFound := 0 + resultDetails := make([]string, 0) + + // Check common base properties first + _, pBase, dBase := o.CommonObjectProperties.ValidSDO(debug) + problemsFound += pBase + resultDetails = append(resultDetails, dBase...) + + if problemsFound > 0 { + return false, problemsFound, resultDetails + } + + return true, 0, resultDetails +} From fee9fc5384305e0ef0a0d69e91bcd58478c180d4 Mon Sep 17 00:00:00 2001 From: Konstantin Papesh Date: Wed, 10 Aug 2022 12:45:28 +0200 Subject: [PATCH 15/16] Fixed software SCO --- README.md | 2 +- objects/sco/software/model.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c11b51c..13c6efa 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,7 @@ STIX Cyber-observable Objects - [ ] Mutex - [X] Network Traffic - [ ] Process -- [ ] Software +- [X] Software - [X] URL - [ ] User Account - [ ] Windows Registry Key diff --git a/objects/sco/software/model.go b/objects/sco/software/model.go index 7fd5483..3ae9e6e 100644 --- a/objects/sco/software/model.go +++ b/objects/sco/software/model.go @@ -24,7 +24,7 @@ type Software struct { objects.NameProperty Cpe string `json:"cpe,omitempty" bson:"cpe,omitempty"` Languages []string `json:"languages,omitempty" bson:"languages,omitempty"` - Vendor string `json:"vendor,omitempty" vendor,omitempty"` + Vendor string `json:"vendor,omitempty" bson:"vendor,omitempty"` Version string `json:"version,omitempty" bson:"version,omitempty"` } From 6151e8a01afaefff39f7ff0281cc930f8a76404d Mon Sep 17 00:00:00 2001 From: Konstantin Papesh Date: Wed, 10 Aug 2022 12:52:15 +0200 Subject: [PATCH 16/16] Added File SCO --- README.md | 2 +- objects/bundle/json.go | 4 ++ objects/sco/file/doc.go | 13 +++++ objects/sco/file/json.go | 100 ++++++++++++++++++++++++++++++++++ objects/sco/file/model.go | 75 +++++++++++++++++++++++++ objects/sco/file/setters.go | 6 ++ objects/sco/file/valid.go | 32 +++++++++++ objects/sco/software/model.go | 2 +- 8 files changed, 232 insertions(+), 2 deletions(-) create mode 100644 objects/sco/file/doc.go create mode 100644 objects/sco/file/json.go create mode 100644 objects/sco/file/model.go create mode 100644 objects/sco/file/setters.go create mode 100644 objects/sco/file/valid.go diff --git a/README.md b/README.md index 13c6efa..381d530 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,7 @@ STIX Cyber-observable Objects - [X] Domain Name - [X] Email Address - [X] Email Message -- [ ] File +- [X] File - [X] IPv4 Address - [X] IPv6 Address - [ ] MAC Address diff --git a/objects/bundle/json.go b/objects/bundle/json.go index 000e73c..ec98eec 100644 --- a/objects/bundle/json.go +++ b/objects/bundle/json.go @@ -12,6 +12,7 @@ import ( "github.com/freetaxii/libstix2/objects/sco/domainname" "github.com/freetaxii/libstix2/objects/sco/emailaddr" "github.com/freetaxii/libstix2/objects/sco/emailmessage" + "github.com/freetaxii/libstix2/objects/sco/file" "github.com/freetaxii/libstix2/objects/sco/ipv4addr" "github.com/freetaxii/libstix2/objects/sco/ipv6addr" "github.com/freetaxii/libstix2/objects/sco/networktraffic" @@ -133,6 +134,9 @@ func DecodeWithCustomObjects(r io.Reader, customDecoders map[string]DecodeFunc) "software": func(bytes []byte) (objects.STIXObject, error) { return software.Decode(bytes) }, + "file": func(bytes []byte) (objects.STIXObject, error) { + return file.Decode(bytes) + }, } for k, v := range customDecoders { decoders[k] = v diff --git a/objects/sco/file/doc.go b/objects/sco/file/doc.go new file mode 100644 index 0000000..7fef7e5 --- /dev/null +++ b/objects/sco/file/doc.go @@ -0,0 +1,13 @@ +// Copyright 2015-2022 Bret Jordan, All rights reserved. +// +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file in the root of the source tree. + +/* +Package software implements the STIX 2.1 Software SCO object. + +The following information comes directly from the STIX 2.1 specification. + +The Domain Name object represents the properties of a network domain name. +*/ +package file diff --git a/objects/sco/file/json.go b/objects/sco/file/json.go new file mode 100644 index 0000000..aa0f296 --- /dev/null +++ b/objects/sco/file/json.go @@ -0,0 +1,100 @@ +// Copyright 2015-2022 Bret Jordan, All rights reserved. +// +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file in the root of the source tree. + +package file + +import ( + "encoding/json" + + "github.com/freetaxii/libstix2/defs" +) + +// ---------------------------------------------------------------------- +// Public Functions - JSON Decoder +// ---------------------------------------------------------------------- + +/* +Decode - This function is a simple wrapper for decoding JSON data. It will +decode a slice of bytes into an actual struct and return a pointer to that +object along with any errors. +*/ +func Decode(data []byte) (*File, error) { + var o File + + if err := json.Unmarshal(data, &o); err != nil { + return nil, err + } + + return &o, nil +} + +/* +UnmarshalJSON - This method will over write the default UnmarshalJSON method +to enable custom properties that this library does not know about. It will store +them as map where the value of each key is a byte arrays. This way a tool that +does know how to deal with them can then further process them after this is +done. This will also allow the storage of the raw JSON data. +*/ +func (o *File) UnmarshalJSON(b []byte) error { + + type alias File + temp := &struct { + *alias + }{ + alias: (*alias)(o), + } + if err := json.Unmarshal(b, &temp); err != nil { + return err + } + + // This will create a map of all of the custom properties and store them in a + // property called o.Custom + if err := o.FindCustomProperties(b, o.GetPropertyList()); err != nil { + return err + } + + // This will store a complete copy of the original JSON in a byte array called + // o.Raw. This could be useful if you need to digitally sign the JSON or do + // verification on what was actually received. + if defs.KEEP_RAW_DATA == true { + o.SetRawData(b) + } + + return nil +} + +// ---------------------------------------------------------------------- +// Public Methods JSON Encoders +// The encoding is done here at the individual object level instead of at +// the STIX Object level so that individual pre/post processing rules can +// be applied. Since some of the STIX Objects do not follow a universal +// model, we need to cleanup some things that were inherited but not valid +// for the object. +// ---------------------------------------------------------------------- + +/* +Encode - This method is a simple wrapper for encoding an object into JSON +*/ +func (o *File) Encode() ([]byte, error) { + data, err := json.MarshalIndent(o, "", " ") + if err != nil { + return nil, err + } + + // Any needed preprocessing would be done here + return data, nil +} + +/* +EncodeToString - This method is a simple wrapper for encoding an object into +JSON +*/ +func (o *File) EncodeToString() (string, error) { + data, err := o.Encode() + if err != nil { + return "", err + } + return string(data), nil +} diff --git a/objects/sco/file/model.go b/objects/sco/file/model.go new file mode 100644 index 0000000..fb30a4d --- /dev/null +++ b/objects/sco/file/model.go @@ -0,0 +1,75 @@ +// Copyright 2015-2022 Bret Jordan, All rights reserved. +// +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file in the root of the source tree. + +package file + +import ( + "github.com/freetaxii/libstix2/objects" +) + +// ---------------------------------------------------------------------- +// Define Object Model +// ---------------------------------------------------------------------- + +/* +File - This type implements the STIX 2 File SCO and defines +all of the properties and methods needed to create and work with this object. +All of the methods not defined local to this type are inherited from the +individual properties. +*/ +type File struct { + objects.CommonObjectProperties + Extensions map[string]string `json:"extensions,omitempty" bson:"extensions,omitempty"` + Hashes map[string]string `json:"hashes,omitempty" bson:"hashes,omitempty"` + Size int `json:"size,omitempty" bson:"size,omitempty"` + objects.NameProperty + NameEnc string `json:"name_enc,omitempty" bson:"name_enc,omitempty"` + MagicNumberHex string `json:"magic_number_hex,omitempty" bson:"magic_number_hex,omitempty"` + MimeType string `json:"mime_type,omitempty" bson:"mime_type,omitempty"` + Ctime string `json:"ctime,omitempty" bson:"ctime,omitempty"` + Mtime string `json:"mtime,omitempty" bson:"mtime,omitempty"` + Atime string `json:"atime,omitempty" bson:"atime,omitempty"` + ParentDirectoryRef string `json:"parent_directory_ref,omitempty" bson:"parent_directory_ref,omitempty"` + ContainsRef []string `json:"contains_ref,omitempty" bson:"contains_ref,omitempty"` + ContentRef string `json:"content_ref,omitempty" bson:"content_ref,omitempty"` +} + +/* +GetPropertyList - This method will return a list of all of the properties that +are unique to this object. This is used by the custom UnmarshalJSON for this +object. It is defined here in this file to make it easy to keep in sync. +*/ +func (o *File) GetPropertyList() []string { + return []string{ + "extensions", + "hashes", + "size", + "name", + "name_enc", + "magic_number_hex", + "mime_type", + "ctime", + "mtime", + "atime", + "parent_directory_ref", + "contains_ref", + "content_ref", + } +} + +// ---------------------------------------------------------------------- +// Initialization Functions +// ---------------------------------------------------------------------- + +/* +New - This function will create a new STIX File SCO and return it as a +pointer. It will also initialize the object by setting all of the basic +properties. +*/ +func New() *File { + var obj File + obj.InitSCO("file") + return &obj +} diff --git a/objects/sco/file/setters.go b/objects/sco/file/setters.go new file mode 100644 index 0000000..a34b621 --- /dev/null +++ b/objects/sco/file/setters.go @@ -0,0 +1,6 @@ +// Copyright 2015-2022 Bret Jordan, All rights reserved. +// +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file in the root of the source tree. + +package file diff --git a/objects/sco/file/valid.go b/objects/sco/file/valid.go new file mode 100644 index 0000000..5afe9d9 --- /dev/null +++ b/objects/sco/file/valid.go @@ -0,0 +1,32 @@ +// Copyright 2015-2022 Bret Jordan, All rights reserved. +// +// Use of this source code is governed by an Apache 2.0 license that can be +// found in the LICENSE file in the root of the source tree. + +package file + +// ---------------------------------------------------------------------- +// Public Methods +// ---------------------------------------------------------------------- + +/* +Valid - This method will verify and test all of the properties on an object +to make sure they are valid per the specification. It will return a boolean, an +integer that tracks the number of problems found, and a slice of strings that +contain the detailed results, whether good or bad. +*/ +func (o *File) Valid(debug bool) (bool, int, []string) { + problemsFound := 0 + resultDetails := make([]string, 0) + + // Check common base properties first + _, pBase, dBase := o.CommonObjectProperties.ValidSDO(debug) + problemsFound += pBase + resultDetails = append(resultDetails, dBase...) + + if problemsFound > 0 { + return false, problemsFound, resultDetails + } + + return true, 0, resultDetails +} diff --git a/objects/sco/software/model.go b/objects/sco/software/model.go index 3ae9e6e..5dd7ecc 100644 --- a/objects/sco/software/model.go +++ b/objects/sco/software/model.go @@ -48,7 +48,7 @@ func (o *Software) GetPropertyList() []string { // ---------------------------------------------------------------------- /* -New - This function will create a new STIX Domain Name SCO and return it as a +New - This function will create a new STIX Software SCO and return it as a pointer. It will also initialize the object by setting all of the basic properties. */