cpedict/cpedict.go (81 lines of code) (raw):

// Package cpedict defines the types and methods necessary to parse and lookup CPE dictionary conforming to // CPE Dictionary specification 2.3 as per https://nvlpubs.nist.gov/nistpubs/Legacy/IR/nistir7697.pdf. // The implementation is not full, only parts required to parse NVD vulnerability feed are implemented // // Copyright (c) Facebook, Inc. and its affiliates. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cpedict import ( "encoding/xml" "io" "time" "github.com/facebookincubator/nvdtools/wfn" ) // TextType represents multi-language text type TextType map[string]string // UnmarshalXML -- load TextType from XML func (t *TextType) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { var text string lang := "en" if *t == nil { *t = TextType{} } for _, attr := range start.Attr { if attr.Name.Local == "lang" { lang = attr.Value } } if err := d.DecodeElement(&text, &start); err != nil { return err } (*t)[lang] = text return nil } // PlatformType -- NVD doesn't use it // TODO: implement // type PlatformType struct{} // CheckFactRefType is a reference to a check that always evaluates to // TRUE, FALSE, or ERROR. Examples of types of checks are OVAL and OCIL checks. // NVD doesn't use it // TODO: implement // type CheckFactRefType struct{} // NamePattern represents CPE name type NamePattern wfn.Attributes // UnmarshalXMLAttr implements xml.UnmarshalerAttr interface func (np *NamePattern) UnmarshalXMLAttr(attr xml.Attr) error { wfn, err := wfn.Parse(attr.Value) if err != nil { return err } *np = (NamePattern)(*wfn) return nil } func (np NamePattern) String() string { return wfn.Attributes(np).String() } // Reference holds additional information about CPE. type Reference struct { URL string `xml:"href,attr"` Desc string `xml:",chardata"` } // DeprecatedInfo contains the name that is deprecating the identifier name and the type of Deprecation type DeprecatedInfo struct { Name NamePattern `xml:"name,attr"` Type string `xml:"type,attr"` } // Deprecation contains the deprecation information for a specific deprecation of a given identifier name. type Deprecation struct { Date time.Time `xml:"date,attr"` DeprecatedBy []DeprecatedInfo `xml:"deprecated-by"` } // CPE23Item contains all CPE 2.3 specific data related to a given identifier name. type CPE23Item struct { Name NamePattern `xml:"name,attr"` Deprecation *Deprecation `xml:"deprecation"` // TODO: implement ProvenanceRecord } // CPEItem contains all of the information for a single dictionary entry (identifier name), including metadata. type CPEItem struct { Name NamePattern `xml:"name,attr"` Deprecated bool `xml:"deprecated,attr"` DeprecatedBy *NamePattern `xml:"deprecated_by,attr"` DeprecationDate time.Time `xml:"deprecation_date,attr"` CPE23 CPE23Item `xml:"cpe23-item"` Title TextType `xml:"title"` Notes TextType `xml:"notes"` References []Reference `xml:"references>reference"` // Calls out a check, such as an OVAL definition, that can confirm or reject // an IT system as an instance of the named platform. 0-n occurrences. // TODO: not implemented Check struct{} `xml:"check"` } // Generator contains information about the generation of the dictionary file. type Generator struct { ProductName string `xml:"product_name"` ProductVersion string `xml:"product_version"` SchemaVersion string `xml:"schema_version"` TimeStamp time.Time `xml:"timestamp"` } // CPEList contains all of the dictionary entries and dictionary metadata. type CPEList struct { Generator Generator `xml:"generator"` Items []CPEItem `xml:"cpe-item"` } // Decode decodes dictionary XML func Decode(r io.Reader) (*CPEList, error) { var list CPEList if err := xml.NewDecoder(r).Decode(&list); err != nil { return nil, err } return &list, nil }