Skip to content

Commit

Permalink
Merge branch 'main' into GEA-333_Remove_client_certificate_logic
Browse files Browse the repository at this point in the history
  • Loading branch information
timopollmeier authored Nov 6, 2023
2 parents 11e8b40 + c259f28 commit 8c209a7
Show file tree
Hide file tree
Showing 11 changed files with 305 additions and 173 deletions.
4 changes: 2 additions & 2 deletions src/gmp/models/__tests__/tlscertificate.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ describe('TlsCertificate Model tests', () => {
};
const tlsCertificate = TlsCertificate.fromElement(element);

expect(tlsCertificate.issuer_dn).toEqual('CN=issuer');
expect(tlsCertificate.subject_dn).toEqual('CN=subject');
expect(tlsCertificate.issuerDn).toEqual('CN=issuer');
expect(tlsCertificate.subjectDn).toEqual('CN=subject');
});

test('should parse activation_time', () => {
Expand Down
143 changes: 112 additions & 31 deletions src/gmp/models/report/__tests__/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -499,53 +499,134 @@ 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=LoremIpsumSubject3 C=Dolor',
issuer_dn: 'CN=LoremIpsumIssuer3 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(cert1.issuerDn).toEqual('CN=LoremIpsumIssuer C=Dolor');
expect(cert1.subjectDn).toEqual('CN=LoremIpsumSubject C=Dolor');

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(cert2.issuerDn).toEqual('CN=LoremIpsumIssuer C=Dolor');
expect(cert2.subjectDn).toEqual('CN=LoremIpsumSubject C=Dolor');

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(cert3.issuerDn).toEqual('CN=LoremIpsumIssuer2 C=Dolor');
expect(cert3.subjectDn).toEqual('CN=LoremIpsumSubject2 C=Dolor');

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(cert4.issuerDn).toEqual('CN=LoremIpsumIssuer2 C=Dolor');
expect(cert4.subjectDn).toEqual('CN=LoremIpsumSubject2 C=Dolor');

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);
expect(cert5.issuerDn).toEqual('CN=LoremIpsumIssuer3 C=Dolor');
expect(cert5.subjectDn).toEqual('CN=LoremIpsumSubject3 C=Dolor');
});

test('should parse empty tls certificates', () => {
Expand Down
134 changes: 52 additions & 82 deletions src/gmp/models/report/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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.subjectDn = subject_dn;
cert.issuerDn = 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
Expand Down Expand Up @@ -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);
Expand Down
6 changes: 6 additions & 0 deletions src/gmp/models/tlscertificate.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ class TlsCertificate extends Model {
// Use subject DN as name
ret.name = ret.subject_dn;

ret.subjectDn = element.subject_dn;
delete ret.subject_dn;

ret.issuerDn = element.issuer_dn;
delete ret.issuer_dn;

ret.activationTime =
element.activation_time === 'undefined' ||
element.activation_time === 'unlimited'
Expand Down
Loading

0 comments on commit 8c209a7

Please sign in to comment.