summaryrefslogtreecommitdiffstats
path: root/lint_cached.fnc
blob: 00f8965c1037de27e3145754ce55ab751ff815d8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/* certwatch_db - Database schema
 * Written by Rob Stradling
 * Copyright (C) 2015-2016 COMODO CA Limited
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

CREATE OR REPLACE FUNCTION lint_cached(
	cert_id					certificate.ID%TYPE,
	v_linter				linter_type
) RETURNS SETOF lint_issue.ID%TYPE
AS $$
DECLARE
	t_certificate		certificate.CERTIFICATE%TYPE;
	t_linterDeployedAt	linter_version.DEPLOYED_AT%TYPE;
	t_lintCachedAt		timestamp;
	t_lintIssueID		lint_issue.ID%TYPE;
	t_issuerCAID		certificate.ISSUER_CA_ID%TYPE;
	t_query				text;
	t_certType			integer;
	t_count				integer;
	l_record			RECORD;
BEGIN
	SELECT c.CERTIFICATE, c.ISSUER_CA_ID,
			CASE v_linter
				WHEN 'cablint' THEN c.CABLINT_CACHED_AT AT TIME ZONE 'UTC'
				WHEN 'x509lint' THEN c.X509LINT_CACHED_AT AT TIME ZONE 'UTC'
				WHEN 'zlint' THEN c.ZLINT_CACHED_AT AT TIME ZONE 'UTC'
			END
		INTO t_certificate, t_issuerCAID,
			t_lintCachedAt
		FROM certificate c
		WHERE c.ID = cert_id;
	IF NOT FOUND THEN
		RETURN;
	END IF;

	SELECT max(lv.DEPLOYED_AT AT TIME ZONE 'UTC')
		INTO t_linterDeployedAt
		FROM linter_version lv
		WHERE lv.LINTER = v_linter;

	IF coalesce(t_lintCachedAt, t_linterDeployedAt) > t_linterDeployedAt THEN
		RETURN QUERY
			SELECT lci.LINT_ISSUE_ID
				FROM lint_cert_issue lci, lint_issue li
				WHERE lci.CERTIFICATE_ID = cert_id
					AND lci.LINT_ISSUE_ID = li.ID
					AND li.LINTER = v_linter;
	ELSE
		DELETE FROM lint_cert_issue lci
			USING lint_issue li
			WHERE lci.CERTIFICATE_ID = cert_id
				AND lci.LINT_ISSUE_ID = li.ID
				AND li.LINTER = v_linter;

		IF v_linter = 'cablint' THEN
			t_query := 'SELECT cablint_embedded($1) LINT';
		ELSIF v_linter = 'x509lint' THEN
			t_query := 'SELECT x509lint_embedded($1,$2) LINT';
			IF NOT x509_canIssueCerts(t_certificate) THEN
				t_certType := 0;
			ELSE
				SELECT count(*)
					INTO t_count
					FROM ca_certificate cac
					WHERE cac.CERTIFICATE_ID = cert_id
						AND cac.CA_ID = t_issuerCAID;
				IF t_count = 0 THEN
					t_certType := 1;
				ELSE
					t_certType := 2;
				END IF;
			END IF;
		ELSIF v_linter = 'zlint' THEN
			t_query := 'SELECT zlint_embedded($1) LINT';
		END IF;

		FOR l_record IN EXECUTE t_query USING t_certificate, t_certType LOOP
			IF substr(l_record.LINT, 1, 1) IN ('W', 'E', 'F') THEN
				SELECT li.ID
					INTO t_lintIssueID
					FROM lint_issue li
					WHERE li.LINTER = v_linter
						AND li.SEVERITY = substr(l_record.LINT, 1, 1)
						AND li.ISSUE_TEXT = substr(l_record.LINT, 4);
				IF NOT FOUND THEN
					BEGIN
						INSERT INTO lint_issue (
								LINTER, SEVERITY, ISSUE_TEXT
							)
							VALUES (
								v_linter, substr(l_record.LINT, 1, 1), substr(l_record.LINT, 4)
							)
							RETURNING ID
								INTO t_lintIssueID;
					EXCEPTION
						WHEN unique_violation THEN
							SELECT li.ID
								INTO t_lintIssueID
								FROM lint_issue li
								WHERE li.LINTER = v_linter
									AND li.SEVERITY = substr(l_record.LINT, 1, 1)
									AND li.ISSUE_TEXT = substr(l_record.LINT, 4);
					END;
				END IF;
				INSERT INTO lint_cert_issue (
						CERTIFICATE_ID, lint_issue_ID, ISSUER_CA_ID, NOT_BEFORE_DATE
					)
					VALUES (
						cert_id, t_lintIssueID, t_issuerCAID, x509_notBefore(t_certificate)::date
					);
				RETURN NEXT t_lintIssueID;
			END IF;
		END LOOP;

		IF v_linter = 'cablint' THEN
			UPDATE certificate
				SET CABLINT_CACHED_AT = statement_timestamp() AT TIME ZONE 'UTC'
				WHERE ID = cert_id;
		ELSIF v_linter = 'x509lint' THEN
			UPDATE certificate
				SET X509LINT_CACHED_AT = statement_timestamp() AT TIME ZONE 'UTC'
				WHERE ID = cert_id;
		ELSIF v_linter = 'zlint' THEN
			UPDATE certificate
				SET ZLINT_CACHED_AT = statement_timestamp() AT TIME ZONE 'UTC'
				WHERE ID = cert_id;
		END IF;
	END IF;
END;
$$ LANGUAGE plpgsql STRICT;