summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pgweb/security/migrations/0003_add_security_patch_details.py20
-rw-r--r--pgweb/security/models.py5
-rw-r--r--pgweb/security/struct.py9
-rw-r--r--pgweb/security/views.py33
-rw-r--r--pgweb/urls.py1
-rw-r--r--templates/security/details.html95
-rw-r--r--templates/security/security.html4
7 files changed, 162 insertions, 5 deletions
diff --git a/pgweb/security/migrations/0003_add_security_patch_details.py b/pgweb/security/migrations/0003_add_security_patch_details.py
new file mode 100644
index 00000000..23acb72b
--- /dev/null
+++ b/pgweb/security/migrations/0003_add_security_patch_details.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.13 on 2018-11-12 16:37
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('security', '0002_cve_visible'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='securitypatch',
+ name='details',
+ field=models.TextField(blank=True, help_text='Additional details about the security patch', null=True),
+ ),
+ ]
diff --git a/pgweb/security/models.py b/pgweb/security/models.py
index e82c7d4f..208a9de7 100644
--- a/pgweb/security/models.py
+++ b/pgweb/security/models.py
@@ -70,6 +70,7 @@ class SecurityPatch(models.Model):
cvenumber = models.IntegerField(null=False, blank=False, db_index=True)
detailslink = models.URLField(null=False, blank=True)
description = models.TextField(null=False, blank=False)
+ details = models.TextField(blank=True, null=True, help_text="Additional details about the security patch")
component = models.CharField(max_length=32, null=False, blank=False, help_text="If multiple components, choose the most critical one", choices=component_choices)
versions = models.ManyToManyField(Version, through='SecurityPatchVersion')
@@ -84,7 +85,9 @@ class SecurityPatch(models.Model):
vector_a = models.CharField(max_length=1, null=False, blank=True, verbose_name="Availability Impact", choices=vector_choices['A'])
legacyscore = models.CharField(max_length=1, null=False, blank=True, verbose_name='Legacy score', choices=(('A', 'A'), ('B', 'B'), ('C', 'C'), ('D', 'D')))
- purge_urls = ('/support/security/', )
+ def purge_urls(self):
+ yield '/support/security/CVE-%s/' % self.cve
+ yield '/support/security/'
def save(self, force_insert=False, force_update=False):
# Calculate a number from the CVE, that we can use to sort by. We need to
diff --git a/pgweb/security/struct.py b/pgweb/security/struct.py
new file mode 100644
index 00000000..fd5a713b
--- /dev/null
+++ b/pgweb/security/struct.py
@@ -0,0 +1,9 @@
+from datetime import date, timedelta
+from .models import SecurityPatch
+
+
+def get_struct():
+ """create sitemap entries for each CVE entry and the top level CVE URL"""
+ yield ('support/security/', None)
+ for s in SecurityPatch.objects.filter(public=True).order_by('-cvenumber'):
+ yield ('support/security/CVE-{}'.format(s.cve), None)
diff --git a/pgweb/security/views.py b/pgweb/security/views.py
index 0a7f2041..b36fcc04 100644
--- a/pgweb/security/views.py
+++ b/pgweb/security/views.py
@@ -1,9 +1,11 @@
-from django.shortcuts import get_object_or_404
+from django.core.validators import ValidationError
+from django.http import Http404
+from django.shortcuts import get_object_or_404, redirect
from pgweb.util.contexts import render_pgweb
from pgweb.core.models import Version
-from .models import SecurityPatch
+from .models import SecurityPatch, make_cvenumber
def GetPatchesList(filt):
@@ -22,6 +24,33 @@ def _list_patches(request, filt):
})
+def details(request, cve_prefix, cve):
+ """Provides additional details about a specific CVE"""
+ # First determine if the entrypoint of the URL is a lowercase "cve". If it
+ # is, redirect to the uppercase
+ if cve_prefix != "CVE":
+ return redirect('/support/security/CVE-{}/'.format(cve), permanent=True)
+ # Get the CVE number from the CVE ID string so we can look it up
+ # against the database. This shouldn't fail due to an ill-formatted CVE,
+ # as both use the same validation check, but we will wrap it just in case.
+ #
+ # However, we do need to ensure that the CVE does both exist and
+ # is published.
+ try:
+ security_patch = get_object_or_404(
+ SecurityPatch,
+ cvenumber=make_cvenumber(cve),
+ public=True,
+ )
+ except ValidationError:
+ raise Http404()
+
+ return render_pgweb(request, 'support', 'security/details.html', {
+ 'security_patch': security_patch,
+ 'versions': security_patch.securitypatchversion_set.select_related('version').order_by('-version__tree').all(),
+ })
+
+
def index(request):
# Show all supported versions
return _list_patches(request, "v.supported")
diff --git a/pgweb/urls.py b/pgweb/urls.py
index 64fb616b..cc29aaba 100644
--- a/pgweb/urls.py
+++ b/pgweb/urls.py
@@ -81,6 +81,7 @@ urlpatterns = [
url(r'^support/security/$', pgweb.security.views.index),
url(r'^support/security/(\d\.\d|\d{2})/$', pgweb.security.views.version),
+ url(r'^support/security/(?P<cve_prefix>CVE|cve)-(?P<cve>\d{4}-\d{4,7})/$', pgweb.security.views.details),
url(r'^support/security_archive/$', RedirectView.as_view(url='/support/security/', permanent=True)),
url(r'^support/professional_(support|hosting)/$', pgweb.profserv.views.root),
diff --git a/templates/security/details.html b/templates/security/details.html
new file mode 100644
index 00000000..0e894c5a
--- /dev/null
+++ b/templates/security/details.html
@@ -0,0 +1,95 @@
+{%extends "base/page.html"%}
+{%block title%}CVE-{{ security_patch.cve }}: {{ security_patch.description }}{%endblock%}
+{%block contents%}
+
+<h1>CVE-{{ security_patch.cve }} <i class="fas fa-lock"></i></h1>
+<h3>{{ security_patch.description }}</h3>
+
+{% if security_patch.details %}
+<p>{{ security_patch.details }}</p>
+{% endif %}
+
+<h2>Version Information</h2>
+
+<table class="table">
+ <thead>
+ <tr>
+ <th>Affected Version</th>
+ <th>Fixed In</th>
+ {% if security_patch.newspost %}
+ <th>Fix Published</th>
+ {% endif %}
+ </thead>
+ <tbody>
+ {% for version in versions %}
+ <tr>
+ <td>
+ {% if version.version.tree >= 10 %}
+ {{ version.version.tree|floatformat:"0" }}
+ {% else %}
+ {{ version.version.tree }}
+ {% endif %}
+ </td>
+ <td>
+ <a href="/docs/release/{% if version.version.tree >= 10 %}{{ version.version.tree|floatformat:"0" }}.{{ version.fixed_minor }}{% else %}{{ version.version.tree }}.{{ version.fixed_minor }}{% endif %}">
+ {% if version.version.tree >= 10 %}
+ {{ version.version.tree|floatformat:"0" }}.{{ version.fixed_minor }}
+ {% else %}
+ {{ version.version.tree }}.{{ version.fixed_minor }}
+ {% endif %}
+ </a>
+ </td>
+ {% if security_patch.newspost %}
+ <td>
+ <a href="/about/news/{{ security_patch.newspost.title|slugify }}-{{ security_patch.newspost.id }}/">
+ {{ security_patch.newspost.date }}
+ </a>
+ </td>
+ {% endif %}
+ </tr>
+ {% endfor %}
+ </tbody>
+</table>
+
+<p>
+ For more information about <a href="/support/versioning/">PostgreSQL versioning</a>,
+ please visit the <a href="/support/versioning/">versioning page</a>.
+</p>
+
+{% if security_patch.cvssscore >= 0 %}
+<h2>CVSS 3.0</h2>
+
+<table class="table">
+ <tbody>
+ <tr>
+ <th>Overall Score</th>
+ <td><strong>{{ security_patch.cvssscore }}</strong></td>
+ </tr>
+ <tr>
+ <th>Component</th>
+ <td>{{ security_patch.component }}</td>
+ </tr>
+ <tr>
+ <th>Vector</th>
+ <td>
+ <a href="https://nvd.nist.gov/vuln-metrics/cvss/v3-calculator?vector={{ security_patch.cvssvector }}&version=3.0" target="_blank" rel="noopener noreferer">
+ {{ security_patch.cvssvector }}
+ </a>
+ </td>
+ </tr>
+ </tbody>
+</table>
+{% endif %}
+
+<h2>Reporting Security Vulnerabilities</h2>
+
+<p>
+ If you wish to report a new security vulnerability in PostgreSQL, please
+ send an email to
+ <a href="mailto:security@postgresql.org">security@postgresql.org</a>.
+</p>
+
+<p>
+ For reporting non-security bugs, please see the <a href="/account/submitbug/">Report a Bug</a> page.
+</p>
+{%endblock%}
diff --git a/templates/security/security.html b/templates/security/security.html
index a6e0a6fc..13fcc169 100644
--- a/templates/security/security.html
+++ b/templates/security/security.html
@@ -75,7 +75,7 @@ You can filter the view of patches to show just patches for version:<br/>
{%for p in patches%}
<tr>
<td>
- {%if p.cve%}<nobr>{%if p.cve_visible%}<a href="{{p.cvelink}}">CVE-{{p.cve}}</a>{%else%}CVE-{{p.cve}}{%endif%}</nobr><br/>{%endif%}
+ {%if p.cve%}<nobr><a href="/support/security/CVE-{{ p.cve }}/">CVE-{{p.cve}}</a></nobr><br/>{%endif%}
{%if p.newspost%}<a href="/about/news/{{p.newspost.title|slugify}}-{{p.newspost.id}}/">Announcement</a><br/>{%endif%}
</td>
<td>{{p.affected|join:", "}}</td>
@@ -83,7 +83,7 @@ You can filter the view of patches to show just patches for version:<br/>
<td>{{p.component}}<br/>
{%if p.cvssscore >= 0%}<a href="https://nvd.nist.gov/vuln-metrics/cvss/v3-calculator?vector={{p.cvssvector}}">{{p.cvssscore}}</a><br/><span class="cvssvector">{{p.cvssvector}}</span>
{%else%}Legacy: {{p.legacyscore}}{%endif%}</td>
- <td>{{p.description}}{%if p.detailslink%}<br/><br/><a href="{{p.detailslink}}">more details</a>{%endif%}</td>
+ <td>{{p.description}}<br/><br/><a href="/support/security/CVE-{{ p.cve }}/">more details</a></td>
</tr>
{% endfor %}
</tbody>