diff --git a/src/gmp/models/report/__tests__/parser.js b/src/gmp/models/report/__tests__/parser.js
index 693e3c5571..ab4754cc43 100644
--- a/src/gmp/models/report/__tests__/parser.js
+++ b/src/gmp/models/report/__tests__/parser.js
@@ -499,53 +499,124 @@ describe('report parser tests', () => {
},
],
ssl_certs: {count: '123'},
+ tls_certificates: {
+ tls_certificate: [
+ {
+ name: '57610B6A3C73866870678E638C7825743145B24',
+ certificate: {
+ __text: '66870678E638C7825743145B247554E0D92C94',
+ _format: 'DER',
+ },
+ sha256_fingerprint: '57610B6A3C73866870678E638C78',
+ md5_fingerprint: 'fa:a9:9d:f2:28:cc:2c:c0:80:16',
+ activation_time: '2019-08-10T12:51:27Z',
+ expiration_time: '2019-09-10T12:51:27Z',
+ valid: true,
+ subject_dn: 'CN=LoremIpsumSubject C=Dolor',
+ issuer_dn: 'CN=LoremIpsumIssuer C=Dolor',
+ serial: '00B49C541FF5A8E1D9',
+ host: {ip: '192.168.9.90', hostname: 'foo.bar'},
+ ports: {port: ['4021', '4023']},
+ },
+ {
+ name: 'C137E9D559CC95ED130011FE4012DE56CAE2F8',
+ certificate: {
+ __text: 'MIICGTCCAYICCQDDh8Msu4YfXDANBgkqhkiG9w0B',
+ _format: 'DER',
+ },
+ sha256_fingerprint: 'C137E9D559CC95ED130011FE4012',
+ md5_fingerprint: '63:70:d6:65:17:32:01:66:9e:7d:c4',
+ activation_time: 'unlimited',
+ expiration_time: 'undefined',
+ valid: false,
+ subject_dn: 'CN=LoremIpsumSubject2 C=Dolor',
+ issuer_dn: 'CN=LoremIpsumIssuer2 C=Dolor',
+ serial: '00C387C32CBB861F5C',
+ host: {ip: '191.164.9.93', hostname: ''},
+ ports: {port: ['8445', '5061']},
+ },
+ {
+ name: 'C137E9D559CC95ED130011FE4012DE56CAE2F8',
+ certificate: {},
+ sha256_fingerprint: 'C137E9D559CC95ED130011FE4012',
+ md5_fingerprint: '63:70:d6:65:17:32:01:66:9e:7d:c4',
+ activation_time: 'unlimited',
+ expiration_time: 'undefined',
+ valid: false,
+ subject_dn: 'CN=LoremIpsumSubject2 C=Dolor',
+ issuer_dn: 'CN=LoremIpsumIssuer2 C=Dolor',
+ serial: '00C387C32CBB861F5C',
+ host: {},
+ ports: {port: ['8441']},
+ },
+ ],
+ },
};
const counts = {
first: 1,
all: 123,
- filtered: 4,
- length: 4,
- rows: 4,
- last: 4,
+ filtered: 5,
+ length: 5,
+ rows: 5,
+ last: 5,
};
const tlsCerts = parseTlsCertificates(report, filterString);
- expect(tlsCerts.entities.length).toEqual(4);
+ expect(tlsCerts.entities.length).toEqual(5);
expect(tlsCerts.counts).toEqual(counts);
expect(tlsCerts.filter).toEqual('foo=bar rows=5');
- const [cert1, cert2, cert3, cert4] = tlsCerts.entities;
+ const [cert1, cert2, cert3, cert4, cert5] = tlsCerts.entities;
- expect(cert1.fingerprint).toEqual('fingerprint1');
+ expect(cert1.fingerprint).toEqual(
+ '57610B6A3C73866870678E638C7825743145B24',
+ );
expect(cert1.hostname).toEqual('foo.bar');
- expect(cert1.ip).toEqual('1.1.1.1');
- expect(cert1.data).toEqual('foobar');
- expect(cert1._data).toEqual('x509:foobar');
+ expect(cert1.ip).toEqual('192.168.9.90');
+ expect(cert1.data).toEqual('66870678E638C7825743145B247554E0D92C94');
+ expect(cert1.valid).toEqual(true);
expect(cert1.ports).toBeUndefined();
- expect(cert1.port).toEqual(123);
-
- expect(cert2.fingerprint).toEqual('fingerprint2');
- expect(cert2.hostname).toBeUndefined();
- expect(cert2.ip).toEqual('2.2.2.2');
- expect(cert2.data).toBeUndefined();
- expect(cert2._data).toBeUndefined();
+ expect(cert1.port).toEqual(4021);
+
+ expect(cert2.fingerprint).toEqual(
+ '57610B6A3C73866870678E638C7825743145B24',
+ );
+ expect(cert2.hostname).toEqual('foo.bar');
+ expect(cert2.ip).toEqual('192.168.9.90');
+ expect(cert2.data).toEqual('66870678E638C7825743145B247554E0D92C94');
+ expect(cert2.valid).toEqual(true);
expect(cert2.ports).toBeUndefined();
- expect(cert2.port).toEqual(123);
-
- expect(cert3.fingerprint).toEqual('fingerprint2');
- expect(cert3.hostname).toBeUndefined();
- expect(cert3.ip).toEqual('2.2.2.2');
- expect(cert3.data).toBeUndefined();
- expect(cert3._data).toBeUndefined();
+ expect(cert2.port).toEqual(4023);
+
+ expect(cert3.fingerprint).toEqual('C137E9D559CC95ED130011FE4012DE56CAE2F8');
+ expect(cert3.hostname).toEqual('');
+ expect(cert3.ip).toEqual('191.164.9.93');
+ expect(cert3.data).toEqual('MIICGTCCAYICCQDDh8Msu4YfXDANBgkqhkiG9w0B');
+ expect(cert3.valid).toEqual(false);
+ expect(cert3.activationTime).toBeUndefined();
+ expect(cert3.expirationTime).toBeUndefined();
expect(cert3.ports).toBeUndefined();
- expect(cert3.port).toEqual(234);
-
- expect(cert4.fingerprint).toEqual('fingerprint1');
- expect(cert4.ip).toEqual('2.2.2.2');
- expect(cert4.data).toBeUndefined();
- expect(cert4._data).toBeUndefined();
+ expect(cert3.port).toEqual(8445);
+
+ expect(cert4.fingerprint).toEqual('C137E9D559CC95ED130011FE4012DE56CAE2F8');
+ expect(cert4.hostname).toEqual('');
+ expect(cert4.ip).toEqual('191.164.9.93');
+ expect(cert4.data).toEqual('MIICGTCCAYICCQDDh8Msu4YfXDANBgkqhkiG9w0B');
+ expect(cert4.valid).toEqual(false);
+ expect(cert4.activationTime).toBeUndefined();
+ expect(cert4.expirationTime).toBeUndefined();
expect(cert4.ports).toBeUndefined();
- expect(cert4.port).toEqual(234);
+ expect(cert4.port).toEqual(5061);
+
+ expect(cert5.fingerprint).toEqual('C137E9D559CC95ED130011FE4012DE56CAE2F8');
+ expect(cert5.hostname).toBeUndefined();
+ expect(cert5.ip).toBeUndefined();
+ expect(cert5.data).toBeUndefined();
+ expect(cert5.valid).toEqual(false);
+ expect(cert5.activationTime).toBeUndefined();
+ expect(cert5.expirationTime).toBeUndefined();
+ expect(cert5.ports).toBeUndefined();
+ expect(cert5.port).toEqual(8441);
});
test('should parse empty tls certificates', () => {
diff --git a/src/gmp/models/report/parser.js b/src/gmp/models/report/parser.js
index 6b5fc472a2..0be541734a 100644
--- a/src/gmp/models/report/parser.js
+++ b/src/gmp/models/report/parser.js
@@ -20,7 +20,7 @@ import {isDefined} from 'gmp/utils/identity';
import {isEmpty} from 'gmp/utils/string';
import {filter as filter_func, forEach, map} from 'gmp/utils/array';
-import {parseSeverity, parseDate} from 'gmp/parser';
+import {parseBoolean, parseSeverity, parseDate} from 'gmp/parser';
import {
parseCollectionList,
@@ -52,89 +52,60 @@ const emptyCollectionList = filter => {
};
};
-const getTlsCertificate = (certs, fingerprint) => {
- let cert = certs[fingerprint];
-
- if (!isDefined(cert)) {
- cert = ReportTLSCertificate.fromElement({fingerprint});
- certs[fingerprint] = cert;
- }
- return cert;
-};
-
export const parseTlsCertificates = (report, filter) => {
- const {host: hosts, ssl_certs, results} = report;
+ const {ssl_certs, tls_certificates, results} = report;
- if (!isDefined(ssl_certs) || !isReportWithDetails(results)) {
+ if (
+ !isDefined(ssl_certs) ||
+ !isDefined(tls_certificates) ||
+ !isReportWithDetails(results)
+ ) {
return emptyCollectionList(filter);
}
const {count: full_count} = ssl_certs;
- let certs_array = [];
-
- forEach(hosts, host => {
- const host_certs = {};
- let hostname;
-
- forEach(host.detail, detail => {
- const {name = '', value = ''} = detail;
-
- if (name.startsWith('SSLInfo')) {
- const [port, fingerprint] = value.split('::');
-
- const cert = getTlsCertificate(host_certs, fingerprint);
-
- cert.ip = host.ip;
-
- cert.addPort(port);
- } else if (name.startsWith('SSLDetails')) {
- const [, fingerprint] = name.split(':');
-
- const cert = getTlsCertificate(host_certs, fingerprint);
-
- value.split('|').reduce((c, v) => {
- let [key, val] = v.split(':');
- if (key === 'notAfter' || key === 'notBefore') {
- val = parseDate(val);
- }
- c[key.toLowerCase()] = val;
- return c;
- }, cert);
-
- cert.details = value;
- } else if (name.startsWith('Cert')) {
- const [, fingerprint] = name.split(':');
-
- const cert = getTlsCertificate(host_certs, fingerprint);
-
- // currently cert data starts with x509:
- // not sure if there are other types of certs
- // therefore keep original data
-
- cert._data = value;
-
- if (value.includes(':')) {
- const [, data] = value.split(':');
- cert.data = data;
- } else {
- cert.data = value;
- }
- } else if (name === 'hostname') {
- // collect hostnames
- hostname = value;
- }
+ const certs_array = [];
+
+ forEach(tls_certificates.tls_certificate, tls_cert => {
+ const {
+ name,
+ certificate,
+ sha256_fingerprint,
+ md5_fingerprint,
+ valid,
+ activation_time,
+ expiration_time,
+ subject_dn,
+ issuer_dn,
+ serial,
+ host,
+ ports,
+ } = tls_cert;
+
+ const cert = ReportTLSCertificate.fromElement({fingerprint: name});
+ cert.data = isDefined(certificate) ? certificate.__text : undefined;
+ cert.sha256Fingerprint = sha256_fingerprint;
+ cert.md5Fingerprint = md5_fingerprint;
+ cert.activationTime =
+ activation_time === 'undefined' || activation_time === 'unlimited'
+ ? undefined
+ : parseDate(activation_time);
+ cert.expirationTime =
+ expiration_time === 'undefined' || expiration_time === 'unlimited'
+ ? undefined
+ : parseDate(expiration_time);
+ cert.valid = parseBoolean(valid);
+ cert.subject_dn = subject_dn;
+ cert.issuer_dn = issuer_dn;
+ cert.serial = serial;
+ cert.hostname = isDefined(host) ? host.hostname : '';
+ cert.ip = isDefined(host) ? host.ip : undefined;
+
+ forEach(ports.port, port => {
+ cert.addPort(port);
});
-
- const certs = Object.values(host_certs);
-
- if (isDefined(hostname)) {
- for (const cert of certs) {
- cert.hostname = hostname;
- }
- }
-
- certs_array = certs_array.concat(certs);
+ certs_array.push(cert);
});
// create a cert per port
@@ -367,12 +338,11 @@ export const parseOperatingSystems = (report, filter) => {
const severity = severities[ip];
if (!isDefined(os)) {
- os = operating_systems[
- best_os_cpe
- ] = ReportOperatingSystem.fromElement({
- best_os_cpe,
- best_os_txt,
- });
+ os = operating_systems[best_os_cpe] =
+ ReportOperatingSystem.fromElement({
+ best_os_cpe,
+ best_os_txt,
+ });
}
os.addHost(host);
diff --git a/src/web/entities/withRowDetails.js b/src/web/entities/withRowDetails.js
index b0271abed2..fae9e992f1 100644
--- a/src/web/entities/withRowDetails.js
+++ b/src/web/entities/withRowDetails.js
@@ -57,34 +57,38 @@ const StyledTableRow = styled(TableRow)`
}
`;
-const withRowDetails = (type, colSpan = '10') => Component => {
- const RowDetailsWrapper = ({entity, links = true, ...props}) => (
-
-
- {links && (
-
-
-
-
+const withRowDetails =
+ (type, colSpan = '10', details = true) =>
+ Component => {
+ const RowDetailsWrapper = ({entity, links = true, ...props}) => (
+
+
+ {links && (
+
+ {details && (
+
+
+
+ )}
+
+ )}
+
+
+
- )}
-
-
-
-
-
-
- );
-
- RowDetailsWrapper.propTypes = {
- entity: PropTypes.model.isRequired,
- links: PropTypes.bool,
+
+
+ );
+
+ RowDetailsWrapper.propTypes = {
+ entity: PropTypes.model.isRequired,
+ links: PropTypes.bool,
+ };
+ return RowDetailsWrapper;
};
- return RowDetailsWrapper;
-};
export default withRowDetails;
diff --git a/src/web/pages/reports/__mocks__/mockreport.js b/src/web/pages/reports/__mocks__/mockreport.js
index 247353a68d..05df5ba85a 100644
--- a/src/web/pages/reports/__mocks__/mockreport.js
+++ b/src/web/pages/reports/__mocks__/mockreport.js
@@ -236,6 +236,44 @@ const error2 = {
},
};
+// TLS certificates
+const tlsCertificate1 = {
+ name: '57610B6A3C73866870678E638C7825743145B24',
+ certificate: {
+ __text: '66870678E638C7825743145B247554E0D92C94',
+ _format: 'DER',
+ },
+ data: 'MIIDSzCCAjOgAwIBAgIJALScVB/zqOLZMA0GCSqGSIb3DQ',
+ sha256_fingerprint: '57610B6A3C73866870678E638C78',
+ md5_fingerprint: 'fa:a9:9d:f2:28:cc:2c:c0:80:16',
+ activation_time: '2019-08-10T12:51:27Z',
+ expiration_time: '2019-09-10T12:51:27Z',
+ valid: true,
+ subject_dn: 'CN=LoremIpsumSubject1 C=Dolor',
+ issuer_dn: 'CN=LoremIpsumIssuer1 C=Dolor',
+ serial: '00B49C541FF5A8E1D9',
+ host: {ip: '192.168.9.90', hostname: 'foo.bar'},
+ ports: {port: ['4021', '4023']},
+};
+
+const tlsCertificate2 = {
+ name: 'C137E9D559CC95ED130011FE4012DE56CAE2F8',
+ certificate: {
+ __text: 'MIICGTCCAYICCQDDh8Msu4YfXDANBgkqhkiG9w0B',
+ _format: 'DER',
+ },
+ sha256_fingerprint: 'C137E9D559CC95ED130011FE4012',
+ md5_fingerprint: '63:70:d6:65:17:32:01:66:9e:7d:c4',
+ activation_time: 'unlimited',
+ expiration_time: 'undefined',
+ valid: false,
+ subject_dn: 'CN=LoremIpsumSubject2 C=Dolor',
+ issuer_dn: 'CN=LoremIpsumIssuer2 C=Dolor',
+ serial: '00C387C32CBB861F5C',
+ host: {ip: '191.164.9.93', hostname: ''},
+ ports: {port: ['8445', '5061']},
+};
+
export const getMockReport = () => {
const report = {
_id: '1234',
@@ -255,6 +293,9 @@ export const getMockReport = () => {
results: {result: [result1, result2, result3]},
hosts: {count: 2},
host: [host1, host2],
+ tls_certificates: {
+ tls_certificate: [tlsCertificate1, tlsCertificate2],
+ },
ports: {
count: 2,
port: [port1, port2],
diff --git a/src/web/pages/reports/details/__tests__/tlscertificatestab.js b/src/web/pages/reports/details/__tests__/tlscertificatestab.js
index 705ac88be0..03c3de3a58 100644
--- a/src/web/pages/reports/details/__tests__/tlscertificatestab.js
+++ b/src/web/pages/reports/details/__tests__/tlscertificatestab.js
@@ -32,7 +32,7 @@ import TLSCertificatesTab from '../tlscertificatestab';
setLocale('en');
const filter = Filter.fromString(
- 'apply_overrides=0 levels=hml rows=2 min_qod=70 first=1 sort-reverse=severity',
+ 'apply_overrides=0 levels=hml rows=3 min_qod=70 first=1 sort-reverse=severity',
);
describe('Report TLS Certificates Tab tests', () => {
@@ -81,44 +81,59 @@ describe('Report TLS Certificates Tab tests', () => {
expect(header[7]).toHaveTextContent('Actions');
// Row 1
- expect(rows[1]).toHaveTextContent('CN=foo');
- expect(rows[1]).toHaveTextContent('abcd');
- expect(rows[1]).toHaveTextContent('Wed, Jan 30, 2019');
- expect(rows[1]).toHaveTextContent('Thu, Aug 1, 2019');
+ expect(rows[1]).toHaveTextContent('CN=LoremIpsumSubject1 C=Dolor');
+ expect(rows[1]).toHaveTextContent('00B49C541FF5A8E1D9');
+ expect(rows[1]).toHaveTextContent('Sat, Aug 10, 2019');
+ expect(rows[1]).toHaveTextContent('Tue, Sep 10, 2019');
expect(links[7]).toHaveAttribute(
'href',
- '/hosts?filter=name%3D123.456.78.910',
+ '/hosts?filter=name%3D192.168.9.90',
);
expect(links[7]).toHaveAttribute(
'title',
- 'Show all Hosts with IP 123.456.78.910',
+ 'Show all Hosts with IP 192.168.9.90',
);
- expect(links[7]).toHaveTextContent('123.456.78.910');
+ expect(links[7]).toHaveTextContent('192.168.9.90');
expect(rows[1]).toHaveTextContent('foo.bar');
- expect(rows[1]).toHaveTextContent('1234');
+ expect(rows[1]).toHaveTextContent('4021');
expect(icons[4]).toHaveTextContent('download.svg');
// Row 2
- expect(rows[2]).toHaveTextContent('CN=bar');
- expect(rows[2]).toHaveTextContent('dcba');
- expect(rows[2]).toHaveTextContent('Sat, Mar 30, 2019');
- expect(rows[2]).toHaveTextContent('Tue, Oct 1, 2019');
+ expect(rows[2]).toHaveTextContent('CN=LoremIpsumSubject1 C=Dolor');
+ expect(rows[2]).toHaveTextContent('00B49C541FF5A8E1D9');
+ expect(rows[2]).toHaveTextContent('Sat, Aug 10, 2019');
+ expect(rows[2]).toHaveTextContent('Tue, Sep 10, 2019');
expect(links[8]).toHaveAttribute(
'href',
- '/hosts?filter=name%3D109.876.54.321',
+ '/hosts?filter=name%3D192.168.9.90',
);
expect(links[8]).toHaveAttribute(
'title',
- 'Show all Hosts with IP 109.876.54.321',
+ 'Show all Hosts with IP 192.168.9.90',
);
- expect(links[8]).toHaveTextContent('109.876.54.321');
- expect(rows[2]).toHaveTextContent('lorem.ipsum');
- expect(rows[2]).toHaveTextContent('5678');
+ expect(links[8]).toHaveTextContent('192.168.9.90');
+ expect(rows[2]).toHaveTextContent('foo.bar');
+ expect(rows[2]).toHaveTextContent('4023');
expect(icons[5]).toHaveTextContent('download.svg');
+ // Row 3
+ expect(rows[3]).toHaveTextContent('CN=LoremIpsumSubject2 C=Dolor');
+ expect(rows[3]).toHaveTextContent('00C387C32CBB861F5C');
+ expect(links[9]).toHaveAttribute(
+ 'href',
+ '/hosts?filter=name%3D191.164.9.93',
+ );
+ expect(links[9]).toHaveAttribute(
+ 'title',
+ 'Show all Hosts with IP 191.164.9.93',
+ );
+ expect(links[9]).toHaveTextContent('191.164.9.93');
+ expect(rows[3]).toHaveTextContent('8445');
+ expect(icons[6]).toHaveTextContent('download.svg');
+
// Filter
expect(baseElement).toHaveTextContent(
- '(Applied filter: apply_overrides=0 levels=hml rows=2 min_qod=70 first=1 sort-reverse=severity)',
+ '(Applied filter: apply_overrides=0 levels=hml rows=3 min_qod=70 first=1 sort-reverse=severity)',
);
});
diff --git a/src/web/pages/reports/details/tlscertificatestab.js b/src/web/pages/reports/details/tlscertificatestab.js
index 59c2b1fd7f..1df017d6db 100644
--- a/src/web/pages/reports/details/tlscertificatestab.js
+++ b/src/web/pages/reports/details/tlscertificatestab.js
@@ -31,10 +31,10 @@ import {
} from 'web/utils/sort';
const tlsCertificatesSortFunctions = {
- dn: makeCompareString('issuer'),
+ dn: makeCompareString('subject_dn'),
serial: makeCompareString('serial'),
- notvalidbefore: makeCompareDate('notbefore'),
- notvalidafter: makeCompareDate('notafter'),
+ notvalidbefore: makeCompareDate('activationTime'),
+ notvalidafter: makeCompareDate('expirationTime'),
ip: makeCompareIp('ip'),
hostname: makeCompareString('hostname'),
port: makeComparePort('port'),
diff --git a/src/web/pages/reports/details/tlscertificatestable.js b/src/web/pages/reports/details/tlscertificatestable.js
index b575f4674f..e38b79ec7b 100644
--- a/src/web/pages/reports/details/tlscertificatestable.js
+++ b/src/web/pages/reports/details/tlscertificatestable.js
@@ -36,6 +36,10 @@ import TableHead from 'web/components/table/head';
import TableHeader from 'web/components/table/header';
import TableRow from 'web/components/table/row';
+import TlsCertificateDetails from '../../tlscertificates/details';
+import withRowDetails from 'web/entities/withRowDetails';
+import {RowDetailsToggle} from 'web/entities/row';
+
import {createEntitiesTable} from 'web/entities/table';
const Header = ({
@@ -58,7 +62,7 @@ const Header = ({
{...sortProps}
sortBy="dn"
width={actions ? '35%' : '40%'}
- title={_('Issuer DN')}
+ title={_('Subject DN')}
/>
{
- const {issuer, serial, notafter, notbefore, hostname, ip, port} = entity;
+ const {serial, activationTime, expirationTime, hostname, ip, port} = entity;
return (
- {issuer}
+
+
+ {entity.subject_dn}
+
+
{serial}
-
+
-
+