aboutsummaryrefslogtreecommitdiffstats
path: root/lib/orm/models.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/orm/models.py')
-rw-r--r--lib/orm/models.py363
1 files changed, 235 insertions, 128 deletions
diff --git a/lib/orm/models.py b/lib/orm/models.py
index 3a4a39a7..0d287bb4 100644
--- a/lib/orm/models.py
+++ b/lib/orm/models.py
@@ -42,10 +42,8 @@ from signal import SIGUSR1
import logging
logger = logging.getLogger("srt")
-def _log(msg):
- f1=open('/tmp/srt.log', 'a')
- f1.write("|" + msg + "|\n" )
- f1.close()
+# quick development/debugging support
+from srtgui.api import _log
# Sqlite support
@@ -127,7 +125,6 @@ class SrtSetting(models.Model):
def __unicode__(self):
return "Setting %s = %s" % (self.name, self.value)
-
class HelpText(models.Model):
VARIABLE = 0
HELPTEXT_AREA = ((VARIABLE, 'variable'), )
@@ -136,7 +133,25 @@ class HelpText(models.Model):
key = models.CharField(max_length=100)
text = models.TextField()
+
+#UPDATE_FREQUENCY: 0 = every minute, 1 = every hour, 2 = every day, 3 = every week, 4 = every month, 5 = every year
class DataSource(models.Model):
+ #UPDATE FREQUENCT
+ MINUTELY = 0
+ HOURLY = 1
+ DAILY = 2
+ WEEKLY = 3
+ MONTHLY = 4
+ ONDEMAND = 5
+ FREQUENCY = (
+ (MINUTELY, 'New'),
+ (HOURLY, 'Hourly'),
+ (DAILY, 'Daily'),
+ (WEEKLY, 'Weekly'),
+ (MONTHLY, 'Monthly'),
+ (ONDEMAND, 'OnDemand'),
+ )
+
data = models.CharField(max_length=20)
source = models.CharField(max_length=20)
type = models.CharField(max_length=20)
@@ -144,6 +159,15 @@ class DataSource(models.Model):
file_path = models.FilePathField()
url = models.TextField(blank=True)
loaded = models.BooleanField(default=False)
+ meta_url = models.TextField(blank=True)
+ lastModifiedDate = models.CharField(max_length=50, blank=True)
+ update_frequency = models.IntegerField(choices=FREQUENCY, default=DAILY)
+ update_time = models.CharField(max_length=50, blank=True)
+ command = models.TextField(blank=True)
+
+
+ def get_frequency_text(self):
+ return DataSource.FREQUENCY[int(self.update_frequency)][1]
class CweTable(models.Model):
search_allowed_fields = ['name', 'href', 'description', 'summary']
@@ -155,9 +179,25 @@ class CweTable(models.Model):
vulnerable_count = models.IntegerField(default=0)
found = models.BooleanField(default=False)
+
class Cve(models.Model):
search_allowed_fields = ['name', 'description', 'publishedDate',
'lastModifiedDate', 'comments', 'comments_private']
+
+ # SRTool Priority
+ UNDEFINED = 0
+ MINOR = 1
+ LOW = 2
+ MEDIUM = 3
+ HIGH = 4
+ PRIORITY = (
+ (UNDEFINED, ''),
+ (MINOR, 'Minor'),
+ (LOW, 'Low'),
+ (MEDIUM, 'Medium'),
+ (HIGH, 'High'),
+ )
+
# WR Status
NEW = 0
INVESTIGATE = 1
@@ -170,18 +210,20 @@ class Cve(models.Model):
(NOT_VULNERABLE, 'Not Vulnerable'),
)
- # Publish options
- PUBLISH_UNDEF = 0
- PUBLISH_AUTO = 1
- PUBLISH_REQUEST = 2
- PUBLISH_PUBLISHED = 3
- PUBLISH_NOPUBLISH = 4
- PUBLISH = (
- (PUBLISH_UNDEF, 'Undetermined'),
- (PUBLISH_AUTO, 'Automatic Publish Date'),
- (PUBLISH_REQUEST, 'Request Publish Date'),
+ # Publish state
+ PUBLISH_UNPUBLISHED = 0
+ PUBLISH_NOPUBLISH = 1
+ PUBLISH_PUBLISHED = 2
+ PUBLISH_REQUEST = 3
+ PUBLISH_UPDATE = 4
+ PUBLISH_SUBMITTED = 5
+ PUBLISH_STATE = (
+ (PUBLISH_UNPUBLISHED, 'Unpublished'),
+ (PUBLISH_NOPUBLISH, 'Not to be Published'),
(PUBLISH_PUBLISHED, 'Published'),
- (PUBLISH_NOPUBLISH, 'Do Not Published'),
+ (PUBLISH_REQUEST, 'Publish Request (New)'),
+ (PUBLISH_UPDATE, 'Publish Request (Update)'),
+ (PUBLISH_SUBMITTED, 'Publish Submitted'),
)
# CPE item list
@@ -193,69 +235,44 @@ class Cve(models.Model):
name = models.CharField(max_length=50)
source = models.CharField(max_length=50)
+ datasource = models.ForeignKey(DataSource,related_name="cve_datasource")
+ priority = models.IntegerField(default=0)
status = models.IntegerField(choices=STATUS, default=NEW)
comments = models.TextField(blank=True)
comments_private = models.TextField(blank=True)
-
+
cve_data_type = models.CharField(max_length=100, blank=True)
cve_data_format = models.CharField(max_length=50, blank=True)
cve_data_version = models.CharField(max_length=50, blank=True)
public = models.BooleanField(default=True)
- publish = models.IntegerField(choices=PUBLISH, default=PUBLISH_UNDEF)
+ publish_state = models.IntegerField(choices=PUBLISH_STATE, default=PUBLISH_UNPUBLISHED)
publish_date = models.CharField(max_length=50, blank=True)
description = models.TextField(blank=True)
publishedDate = models.CharField(max_length=50, blank=True)
lastModifiedDate = models.CharField(max_length=50, blank=True)
-# problemtype = models.CharField(max_length=40, blank=True)
-# problemtype = models.ForeignKey(CweTable, related_name='cwe')
recommend = models.IntegerField(default=0)
-
- cpe_list= models.TextField(blank=True)
+ recommend_list = models.TextField(blank=True)
cvssV3_baseScore = models.CharField(max_length=50, blank=True)
cvssV3_baseSeverity = models.CharField(max_length=50, blank=True)
- cvssV3_vectorString = models.TextField(blank=True)
- cvssV3_exploitabilityScore = models.CharField(max_length=50, blank=True)
- cvssV3_impactScore = models.CharField(max_length=50, blank=True)
- cvssV3_attackVector = models.CharField(max_length=50, blank=True)
- cvssV3_attackComplexity = models.CharField(max_length=50, blank=True)
- cvssV3_privilegesRequired = models.CharField(max_length=50, blank=True)
- cvssV3_userInteraction = models.CharField(max_length=50, blank=True)
- cvssV3_scope = models.CharField(max_length=50, blank=True)
- cvssV3_confidentialityImpact = models.CharField(max_length=50, blank=True)
- cvssV3_integrityImpact = models.CharField(max_length=50, blank=True)
- cvssV3_availabilityImpact = models.CharField(max_length=50, blank=True)
cvssV2_baseScore = models.CharField(max_length=50, blank=True)
cvssV2_severity = models.CharField(max_length=50, blank=True)
- cvssV2_vectorString = models.TextField(blank=True)
- cvssV2_exploitabilityScore = models.CharField(max_length=50, blank=True)
- cvssV2_impactScore = models.CharField(max_length=50, blank=True)
- cvssV2_accessVector = models.CharField(max_length=50, blank=True)
- cvssV2_accessComplexity = models.CharField(max_length=50, blank=True)
- cvssV2_authentication = models.CharField(max_length=50, blank=True)
- cvssV2_confidentialityImpact = models.CharField(max_length=50, blank=True)
- cvssV2_integrityImpact = models.CharField(max_length=50, blank=True)
class Meta:
unique_together = ('name', 'source' )
@property
- def problemtype_summary(self):
- """ Return the summary of the CWE """
- summary = '?'
- try:
- r = CweTable.objects.get(name=self.problemtype)
- summary = r.summary
- except Exception as e:
- logger.warning("ERROR: could not find CWE %s" % self.problemtype)
- return summary
+ def get_priority_text(self):
+ return Cve.PRIORITY[int(self.priority)][1]
+ @property
def get_publish_text(self):
- return Cve.PUBLISH[int(self.publish)][1]
+ return Cve.PUBLISH_STATE[int(self.publish_state)][1]
+ @property
def get_status_text(self):
return Cve.STATUS[int(self.status)][1]
def get_cpe_list(self):
@@ -264,31 +281,54 @@ class Cve(models.Model):
cpe_array.append(cpe.split(','))
return cpe_array
- FOR_LIST = ['linux','openjpeg','libtiff','libav','tcp','binutil ','ssl','ssh','glibc']
- AGAINST_LIST = ['cisco','microsoft','windows','ibm','oracle','sun','java','peoplesoft','hancom','zyxel','wordpress','sugarcrm','cobham',
- 'juniper']
-
- def recommendation(self):
- recommendation = 0
- for s in Cve.FOR_LIST:
- if 0 <= self.description.lower().find(s):
- recommendation += 1
- for s in Cve.AGAINST_LIST:
- if 0 <= self.description.lower().find(s):
- recommendation -= 1
- return recommendation
- def reasons_for(self):
- reason = ''
- for s in Cve.FOR_LIST:
- if 0 <= self.description.lower().find(s):
- reason += '%s ' % s
- return reason
- def reasons_against(self):
- reason = ''
- for s in Cve.AGAINST_LIST:
- if 0 <= self.description.lower().find(s):
- reason += '%s ' % s
- return reason
+
+class CveDetail():
+ # CPE item list
+ CPE_LIST_KEY = 0 # entry is <[/]component|and|or> tag or '|' delimited list
+ CPE_LIST_VULNERABLE = 0
+ CPE_LIST_CPE23 = 1
+ CPE_LIST_CPE22 = 2
+ CPE_LIST_VERSIONEND = 3
+
+ name = ''
+# problemtype = ''
+
+ recommend = ''
+ recommend_list = ''
+
+ cpe_list= ''
+
+ cvssV3_baseScore = ''
+ cvssV3_baseSeverity = ''
+ cvssV3_vectorString = ''
+ cvssV3_exploitabilityScore = ''
+ cvssV3_impactScore = ''
+ cvssV3_attackVector = ''
+ cvssV3_attackComplexity = ''
+ cvssV3_privilegesRequired = ''
+ cvssV3_userInteraction = ''
+ cvssV3_scope = ''
+ cvssV3_confidentialityImpact = ''
+ cvssV3_integrityImpact = ''
+ cvssV3_availabilityImpact = ''
+
+ cvssV2_baseScore = ''
+ cvssV2_severity = ''
+ cvssV2_vectorString = ''
+ cvssV2_exploitabilityScore = ''
+ cvssV2_impactScore = ''
+ cvssV2_accessVector = ''
+ cvssV2_accessComplexity = ''
+ cvssV2_authentication = ''
+ cvssV2_confidentialityImpact = ''
+ cvssV2_integrityImpact = ''
+
+ def get_cpe_list(self):
+ cpe_array = []
+ for cpe in self.cpe_list.split('|'):
+ cpe_array.append(cpe.split(','))
+ return cpe_array
+
# Same CVE from multiple sources and/or revisions
class CveSet(models.Model):
@@ -319,7 +359,7 @@ class CpeTable(models.Model):
cpeMatchString = models.TextField(blank=True)
cpe23Uri = models.TextField(blank=True)
versionEndIncluding = models.TextField(blank=True)
-
+
class CpeToCve(models.Model):
cpe = models.ForeignKey(CpeTable,related_name="cpe2cve")
cve = models.ForeignKey(Cve,related_name="cve2cpe")
@@ -353,7 +393,7 @@ class CpeFilter(models.Model):
@property
def get_status_text(self):
return CpeFilter.STATUS[int(self.status)][1]
-
+
# CVE/CWE Mapping
@@ -373,6 +413,8 @@ class CveReference(models.Model):
# PRODUCT
class Product(models.Model):
+ search_allowed_fields = ['name', 'version', 'profile']
+
name = models.CharField(max_length=40)
version = models.CharField(max_length=40)
profile = models.CharField(max_length=40)
@@ -382,13 +424,14 @@ class Product(models.Model):
class Meta:
unique_together = ('name', 'version', 'profile', )
+ @property
def long_name(self):
return '%s %s %s' % (self.name,self.version,self.profile)
# VULNERABILITY
-# Company-level Vulnerablility Record
+# Company-level Vulnerablility Record
class Vulnerability(models.Model):
search_allowed_fields = ['name', 'comments', 'comments_private']
@@ -410,22 +453,27 @@ class Vulnerability(models.Model):
(FIXED, 'Closed (Fixed)'),
(NOT_FIX, "Closed (Won't Fix)"),
)
- LOW = 0
- MEDIUM = 1
- HIGH = 2
+ # SRTool Severity, matched with Cve/Defect Priority with placeholder for 'minor'
+ UNDEFINED = 0
+ MINOR = 1
+ LOW = 2
+ MEDIUM = 3
+ HIGH = 4
SEVERITY = (
+ (UNDEFINED, ''),
+ (MINOR, 'Minor'),
(LOW, 'Low'),
(MEDIUM, 'Medium'),
(HIGH, 'High'),
)
name = models.CharField(max_length=50)
- cve_primary_name = models.CharField(max_length=50)
- description = models.TextField(blank=True)
+ cve_primary_name = models.CharField(max_length=50, default='')
+ description = models.TextField(blank=True, default='')
- public = models.BooleanField(default=False)
- comments = models.TextField(blank=True)
- comments_private = models.TextField(blank=True)
+ public = models.BooleanField(default=True)
+ comments = models.TextField(blank=True, default='')
+ comments_private = models.TextField(blank=True, default='')
status = models.IntegerField(choices=STATUS, default=INVESTIGATE)
outcome = models.IntegerField(choices=OUTCOME, default=OPEN)
@@ -485,7 +533,7 @@ class Vulnerability(models.Model):
except IntegrityError:
print("Error in new_vulnerability_name")
raise
- return "V%04d" % index
+ return "V%05d" % index
class VulnerabilityComments(models.Model):
vulnerability = models.ForeignKey(Vulnerability,related_name="vulnerability_comments")
@@ -513,7 +561,7 @@ class CveToVulnerablility(models.Model):
# Defects
-# Defect Record
+# Defect Record
class Defect(models.Model):
search_allowed_fields = ['name', 'summary', 'release_version'] #, 'product']
@@ -521,11 +569,13 @@ class Defect(models.Model):
#Issue Type,Key,Summary,Priority,Status,Resolution,Publish To OLS,Fix Version
#Bug,LIN10-2031,Security Advisory - libvorbis - CVE-2017-14633,P3,Closed,Fixed,Reviewed - Publish,10.17.41.3
- MINOR = 0
- LOW = 1
- MEDIUM = 2
- HIGH = 3
+ NONE = 0
+ MINOR = 1
+ LOW = 2
+ MEDIUM = 3
+ HIGH = 4
Priority = (
+ (NONE, 'None'),
(MINOR, 'P4'),
(LOW, 'P3'),
(MEDIUM, 'P2'),
@@ -546,35 +596,49 @@ class Defect(models.Model):
(CLOSED, 'Closed'),
)
UNRESOLVED = 0
- FIXED = 1
- WILL_NOT_FIX = 2
- WITHDRAWN = 3
- REJECTED = 4
- DUPLICATE = 5
+ RESOLVED = 1
+ FIXED = 2
+ WILL_NOT_FIX = 3
+ WITHDRAWN = 4
+ REJECTED = 5
+ DUPLICATE = 6
+ NOT_APPLICABLE = 7
+ REPLACED_BY_REQUIREMENT = 8
+ CANNOT_REPRODUCE = 9
+ DONE = 10
Resolution = (
(UNRESOLVED, 'Unresolved'),
+ (RESOLVED, 'Resolved'),
(FIXED, 'Fixed'),
(WILL_NOT_FIX, 'Won\'t Fix'),
(WITHDRAWN, 'Withdrawn'),
(REJECTED, 'Rejected'),
(DUPLICATE, 'Duplicate'),
+ (NOT_APPLICABLE, 'Not Applicable'),
+ (REPLACED_BY_REQUIREMENT, 'Replaced By Requirement'),
+ (CANNOT_REPRODUCE, 'Cannot Reproduce'),
+ (DONE, 'Done'),
)
name = models.CharField(max_length=50)
summary = models.TextField(blank=True)
+ url = models.TextField(blank=True)
priority = models.IntegerField(choices=Priority, default=MINOR)
status = models.IntegerField(choices=Status, default=OPEN)
resolution = models.IntegerField(choices=Resolution, default=UNRESOLVED)
- publishOLS = models.TextField(blank=True)
+ publish = models.TextField(blank=True)
release_version = models.CharField(max_length=50)
product = models.ForeignKey(Product,related_name="product_defect")
date_created = models.CharField(max_length=50)
date_updated = models.CharField(max_length=50)
# Methods
+ @property
def get_priority_text(self):
return Defect.Priority[int(self.priority)][1]
+ @property
def get_status_text(self):
return Defect.Status[int(self.status)][1]
+ @property
def get_resolution_text(self):
return Defect.Resolution[int(self.resolution)][1]
def get_long_name(self):
@@ -585,7 +649,7 @@ class Defect(models.Model):
# INVESTIGATION
-# Product-level Vulnerablility Investigation Record
+# Product-level Vulnerablility Investigation Record
class Investigation(models.Model):
search_allowed_fields = ['name', 'comments', 'comments_private']
@@ -607,10 +671,15 @@ class Investigation(models.Model):
(FIXED, 'Fixed'),
(NOT_FIX, "Won't Fix"),
)
- LOW = 0
- MEDIUM = 1
- HIGH = 2
+ # SRTool Severity, matched with Cve/Defect Priority with placeholder for 'minor'
+ UNDEFINED = 0
+ MINOR = 1
+ LOW = 2
+ MEDIUM = 3
+ HIGH = 4
SEVERITY = (
+ (UNDEFINED, ''),
+ (MINOR, 'Minor'),
(LOW, 'Low'),
(MEDIUM, 'Medium'),
(HIGH, 'High'),
@@ -650,7 +719,7 @@ class Investigation(models.Model):
index = int(current_investigation_index.value) + 1
current_investigation_index.value = str(index)
current_investigation_index.save()
- return "I%04d" % index
+ return "I%05d" % index
class InvestigationToDefect(models.Model):
investigation = models.ForeignKey(Investigation,related_name="investigation_to_defect")
@@ -700,7 +769,7 @@ class User(models.Model):
# the default guest user account is ID=1
USER_GUEST = 1
- # Access model
+ # Access model
READER = 0
CONTRIBUTOR = 1
CREATOR = 2
@@ -720,6 +789,32 @@ class User(models.Model):
def get_access_text(self):
return User.ACCESS[int(self.access)][1]
+ @property
+ def builtin(self):
+ return( ('Guest' == self.name) or ('SRTool' == self.name))
+
+# Minimal and safe User object to pass to web pages (no passwords)
+class UserSafe():
+ def __init__(self, pk, name, email):
+ self.pk = pk
+ self.name = name
+ self.email = email
+
+ def __str__(self):
+ return "UserSafeStr=%d,%s,%s" % (self.pk, self.name, self.email)
+
+ @staticmethod
+ def get_safe_userlist(allow_assignment=True):
+ user_list = []
+ for user in User.objects.all():
+ if 'SRTool' == user.name:
+ continue
+ if allow_assignment and ('Guest' == user.name):
+ continue
+ u = UserSafe(user.id,user.name,user.email)
+ user_list.append(u)
+ return user_list
+
class VulnerabilityAccess(models.Model):
vulnerability = models.ForeignKey(Vulnerability,related_name="vulnerability_users")
user = models.ForeignKey(User,related_name="vulnerability_user")
@@ -759,47 +854,59 @@ class Keywords(models.Model):
def get_keytype_text(self):
return Keywords.KeyType[int(self.key_type)][1]
-
-
-# ====
+# Items waiting for SRTool external publishing
+class PublishPending(models.Model):
+ cve = models.ForeignKey(Cve,related_name="publish_pending_cves",blank=True,null=True)
+ vulnerability = models.ForeignKey(Vulnerability,related_name="publish_pending_vulnerabilities",blank=True,null=True)
+ investigation = models.ForeignKey(Investigation,related_name="publish_pending_investigations",blank=True,null=True)
+ date = models.DateField(null=True, blank=True)
+ note = models.TextField(blank=True)
+
+# ==== Support clases, meta classes ====
+
+def _log_args(msg, *args, **kwargs):
+ s = '%s:(' % msg
+ if args:
+ for a in args:
+ s += '%s,' % a
+ s += '),('
+ if kwargs:
+ for key, value in kwargs.iteritems():
+ s += '(%s=%s),' % (key,value)
+ s += ')'
+ _log(s)
class Access():
# default user is "Guest"
-
- def read_values(self):
- v, created = SrtSetting.objects.get_or_create(name='current_user')
- if created:
- v.value = User.USER_GUEST
- v.save()
- self.current_user = int(v.value)
+
+ def __init__(self, *args, **kwargs):
+ _log_args("ACCESS:", *args, **kwargs)
+ srt_user_id = args[0]
+
+ # default to "Guest"
+ if 0 == srt_user_id:
+ srt_user_id = 1
+
+ self.current_user = srt_user_id
try:
- self.current_user_name = User.objects.get(pk=self.current_user).name
+ user = User.objects.get(pk=self.current_user)
+ self.current_user_name = user.name
+ self.current_user_access = user.access
except:
self.current_user_name = '<not_found>'
-
- v, created = SrtSetting.objects.get_or_create(name='current_user_access')
- if created:
- v.value = User.READER
- v.save()
- self.current_user_access = int(v.value)
+ self.current_user_access = User.READER
def is_guest(self):
- self.read_values()
return self.current_user == User.USER_GUEST
def is_reader(self):
- self.read_values()
return self.current_user_access >= User.READER
def is_contributor(self):
- self.read_values()
return self.current_user_access >= User.CONTRIBUTOR
def is_creator(self):
- self.read_values()
return self.current_user_access >= User.CREATOR
def is_admin(self):
- self.read_values()
return self.current_user_access >= User.ADMIN
def user_name(self):
- self.read_values()
return self.current_user_name
# Database Cache Support