Completed
Pull Request — master (#729)
by kota
05:25
created

report.NewDBClient   B

Complexity

Conditions 8

Size

Total Lines 39
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 31
dl 0
loc 39
rs 7.2693
c 0
b 0
f 0
nop 1
1
package report
2
3
import (
4
	"fmt"
5
	"os"
6
7
	"github.com/future-architect/vuls/config"
8
	"github.com/future-architect/vuls/util"
9
	gostdb "github.com/knqyf263/gost/db"
10
	cvedb "github.com/kotakanbe/go-cve-dictionary/db"
11
	ovaldb "github.com/kotakanbe/goval-dictionary/db"
12
	exploitdb "github.com/mozqnet/go-exploitdb/db"
13
)
14
15
// DBClient is a dictionarie's db client for reporting
16
type DBClient struct {
17
	CveDB     cvedb.DB
18
	OvalDB    ovaldb.DB
19
	GostDB    gostdb.DB
20
	ExploitDB exploitdb.DB
21
}
22
23
// DBClientConf has a configuration of Vulnerability DBs
24
type DBClientConf struct {
25
	CveDictCnf  config.GoCveDictConf
26
	OvalDictCnf config.GovalDictConf
27
	GostCnf     config.GostConf
28
	ExploitCnf  config.ExploitConf
29
	DebugSQL    bool
30
}
31
32
func (c DBClientConf) isCveDBViaHTTP() bool {
33
	return c.CveDictCnf.URL != "" && c.CveDictCnf.Type == "sqlite3"
34
}
35
36
func (c DBClientConf) isOvalViaHTTP() bool {
37
	return c.OvalDictCnf.URL != "" && c.OvalDictCnf.Type == "sqlite3"
38
}
39
40
func (c DBClientConf) isGostViaHTTP() bool {
41
	return c.GostCnf.URL != "" && c.GostCnf.Type == "sqlite3"
42
}
43
44
func (c DBClientConf) isExploitViaHTTP() bool {
45
	return c.ExploitCnf.URL != "" && c.ExploitCnf.Type == "sqlite3"
46
}
47
48
// NewDBClient returns db clients
49
func NewDBClient(cnf DBClientConf) (dbclient *DBClient, locked bool, err error) {
50
	cveDriver, locked, err := NewCveDB(cnf)
51
	if err != nil {
52
		return nil, locked, err
53
	}
54
55
	ovaldb, locked, err := NewOvalDB(cnf)
56
	if locked {
57
		return nil, true, fmt.Errorf("OvalDB is locked: %s",
58
			cnf.OvalDictCnf.SQLite3Path)
59
	} else if err != nil {
60
		util.Log.Warnf("Unable to use OvalDB: %s, err: %s",
61
			cnf.OvalDictCnf.SQLite3Path, err)
62
	}
63
64
	gostdb, locked, err := NewGostDB(cnf)
65
	if locked {
66
		return nil, true, fmt.Errorf("gostDB is locked: %s",
67
			cnf.GostCnf.SQLite3Path)
68
	} else if err != nil {
69
		util.Log.Warnf("Unable to use gostDB: %s, err: %s",
70
			cnf.GostCnf.SQLite3Path, err)
71
	}
72
73
	exploitdb, locked, err := NewExploitDB(cnf)
74
	if locked {
75
		return nil, true, fmt.Errorf("exploitDB is locked: %s",
76
			cnf.ExploitCnf.SQLite3Path)
77
	} else if err != nil {
78
		util.Log.Warnf("Unable to use exploitDB: %s, err: %s",
79
			cnf.ExploitCnf.SQLite3Path, err)
80
	}
81
82
	return &DBClient{
83
		CveDB:     cveDriver,
84
		OvalDB:    ovaldb,
85
		GostDB:    gostdb,
86
		ExploitDB: exploitdb,
87
	}, false, nil
88
}
89
90
// NewCveDB returns cve db client
91
func NewCveDB(cnf DBClientConf) (driver cvedb.DB, locked bool, err error) {
92
	if cnf.isCveDBViaHTTP() {
93
		return nil, false, nil
94
	}
95
	util.Log.Debugf("open cve-dictionary db (%s)", cnf.CveDictCnf.Type)
96
	path := cnf.CveDictCnf.URL
97
	if cnf.CveDictCnf.Type == "sqlite3" {
98
		path = cnf.CveDictCnf.SQLite3Path
99
	}
100
101
	util.Log.Debugf("Open cve-dictionary db (%s): %s", cnf.CveDictCnf.Type, path)
102
	driver, locked, err = cvedb.NewDB(cnf.CveDictCnf.Type, path, cnf.DebugSQL)
103
	if err != nil {
104
		err = fmt.Errorf("Failed to init CVE DB. err: %s, path: %s", err, path)
105
		return nil, locked, err
106
	}
107
	return driver, false, nil
108
}
109
110
// NewOvalDB returns oval db client
111
func NewOvalDB(cnf DBClientConf) (driver ovaldb.DB, locked bool, err error) {
112
	if cnf.isOvalViaHTTP() {
113
		return nil, false, nil
114
	}
115
	path := cnf.OvalDictCnf.URL
116
	if cnf.OvalDictCnf.Type == "sqlite3" {
117
		path = cnf.OvalDictCnf.SQLite3Path
118
119
		if _, err := os.Stat(path); os.IsNotExist(err) {
120
			util.Log.Warnf("--ovaldb-path=%s is not found. It's recommended to use OVAL to improve scanning accuracy. For details, see https://github.com/kotakanbe/goval-dictionary#usage", path)
121
			return nil, false, nil
122
		}
123
	}
124
125
	util.Log.Debugf("Open oval-dictionary db (%s): %s", cnf.OvalDictCnf.Type, path)
126
	driver, locked, err = ovaldb.NewDB("", cnf.OvalDictCnf.Type, path, cnf.DebugSQL)
127
	if err != nil {
128
		err = fmt.Errorf("Failed to new OVAL DB. err: %s", err)
129
		if locked {
130
			return nil, true, err
131
		}
132
		return nil, false, err
133
	}
134
	return driver, false, nil
135
}
136
137
// NewGostDB returns db client for Gost
138
func NewGostDB(cnf DBClientConf) (driver gostdb.DB, locked bool, err error) {
139
	if cnf.isGostViaHTTP() {
140
		return nil, false, nil
141
	}
142
	path := cnf.GostCnf.URL
143
	if cnf.GostCnf.Type == "sqlite3" {
144
		path = cnf.GostCnf.SQLite3Path
145
146
		if _, err := os.Stat(path); os.IsNotExist(err) {
147
			util.Log.Warnf("--gostdb-path=%s is not found. If the scan target server is Debian, RHEL or CentOS, it's recommended to use gost to improve scanning accuracy. To use gost database, see https://github.com/knqyf263/gost#fetch-redhat", path)
148
			return nil, false, nil
149
		}
150
	}
151
152
	util.Log.Debugf("Open gost db (%s): %s", cnf.GostCnf.Type, path)
153
	if driver, locked, err = gostdb.NewDB(cnf.GostCnf.Type, path, cnf.DebugSQL); err != nil {
154
		if locked {
155
			util.Log.Errorf("gostDB is locked: %s", err)
156
			return nil, true, err
157
		}
158
		return nil, false, err
159
	}
160
	return driver, false, nil
161
}
162
163
// NewExploitDB returns db client for Exploit
164
func NewExploitDB(cnf DBClientConf) (driver exploitdb.DB, locked bool, err error) {
165
	if cnf.isExploitViaHTTP() {
166
		return nil, false, nil
167
	}
168
	path := cnf.ExploitCnf.URL
169
	if cnf.ExploitCnf.Type == "sqlite3" {
170
		path = cnf.ExploitCnf.SQLite3Path
171
172
		if _, err := os.Stat(path); os.IsNotExist(err) {
173
			util.Log.Warnf("--exploitdb-path=%s is not found. It's recommended to use exploit to improve scanning accuracy. To use exploit db database, see https://github.com/mozqnet/go-exploitdb", path)
174
			return nil, false, nil
175
		}
176
	}
177
178
	util.Log.Debugf("Open exploit db (%s): %s", cnf.ExploitCnf.Type, path)
179
	if driver, locked, err = exploitdb.NewDB(cnf.ExploitCnf.Type, path, cnf.DebugSQL); err != nil {
180
		if locked {
181
			util.Log.Errorf("exploitDB is locked: %s", err)
182
			return nil, true, err
183
		}
184
		return nil, false, err
185
	}
186
	return driver, false, nil
187
}
188
189
// CloseDB close dbs
190
func (d DBClient) CloseDB() {
191
	if d.CveDB != nil {
192
		if err := d.CveDB.CloseDB(); err != nil {
193
			util.Log.Errorf("Failed to close DB: %s", err)
194
		}
195
	}
196
	if d.OvalDB != nil {
197
		if err := d.OvalDB.CloseDB(); err != nil {
198
			util.Log.Errorf("Failed to close DB: %s", err)
199
		}
200
	}
201
}
202