Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added missing SCOs #18

Closed
wants to merge 17 commits into from
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
- [X] File
- [X] IPv4 Address
- [X] IPv6 Address
- [ ] MAC Address
- [ ] Mutex
- [X] Network Traffic
- [ ] Process
- [X] Software
- [X] URL
- [ ] User Account
- [ ] Windows Registry Key
- [X] X.509 Certificate

Other STIX Objects
- [x] Bundle
- [ ] Language Content
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/freetaxii/libstix2

go 1.13
go 1.18

require (
github.com/gologme/log v1.2.0
Expand Down
5 changes: 0 additions & 5 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
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=
221 changes: 117 additions & 104 deletions objects/bundle/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,18 @@ 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"
"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"
"github.com/freetaxii/libstix2/objects/sco/software"
"github.com/freetaxii/libstix2/objects/sco/urlobject"
"github.com/freetaxii/libstix2/objects/sco/x509certificate"
"io"

"github.com/freetaxii/libstix2/objects"
Expand All @@ -17,6 +29,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"
Expand All @@ -27,16 +40,107 @@ 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)
},
"malware-analysis": func(bytes []byte) (objects.STIXObject, error) {
return malwareanalysis.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)
},
"location": func(bytes []byte) (objects.STIXObject, error) {
return location.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)
},
"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)
},
"network-traffic": func(bytes []byte) (objects.STIXObject, error) {
return networktraffic.Decode(bytes)
},
"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
}

var b Bundle
var rawBundle bundleRawDecode
Expand Down Expand Up @@ -64,113 +168,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)
Expand All @@ -183,6 +188,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
Expand Down
36 changes: 35 additions & 1 deletion objects/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down Expand Up @@ -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
}
2 changes: 1 addition & 1 deletion objects/malwareanalysis/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
}

/*
Expand Down
Loading