Define strict TLS trust plugin API
This commit is contained in:
1 parent
f1fcef9b85
commit
1eeb8bac05
17 files changed
+834
-194
No files matched your search
@@ -1,58 +1,64 @@
|
||||
export function createFirefoxValidationPlugin() {
|
||||
return {
|
||||
manifest: {
|
||||
id: "org.browsec.firefox-validation",
|
||||
name: "Firefox validation",
|
||||
role: "advisor",
|
||||
},
|
||||
collectEvidence({ facts }) {
|
||||
if (facts.validation === "success") {
|
||||
return {
|
||||
entries: [
|
||||
{
|
||||
kind: "vote",
|
||||
code: "firefox-validation-succeeded",
|
||||
message: "Firefox constructed a valid path to a configured trust anchor.",
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
manifest: pluginManifest(
|
||||
"org.browsec.firefox-validation",
|
||||
"Firefox validation",
|
||||
["advisor"],
|
||||
),
|
||||
hooks: {
|
||||
collectEvidence({ facts }) {
|
||||
if (facts.validation === "success") {
|
||||
return {
|
||||
entries: [
|
||||
{
|
||||
kind: "vote",
|
||||
code: "firefox-validation-succeeded",
|
||||
message: "Firefox constructed a valid path to a configured trust anchor.",
|
||||
data: { trusted: true },
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
entries: facts.errors.map((error) => ({
|
||||
kind: "warning",
|
||||
code: error,
|
||||
message: explainValidationError(error),
|
||||
})),
|
||||
};
|
||||
return {
|
||||
entries: facts.errors.map((error) => ({
|
||||
kind: "warning",
|
||||
code: error,
|
||||
message: explainValidationError(error),
|
||||
})),
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function createVillageCommunityPlugin() {
|
||||
return {
|
||||
manifest: {
|
||||
id: "community.village.observer",
|
||||
name: "Village community observer",
|
||||
role: "advisor",
|
||||
},
|
||||
collectEvidence({ facts }) {
|
||||
if (facts.hostname !== "library.village") return;
|
||||
return {
|
||||
entries: [
|
||||
{
|
||||
kind: "evidence",
|
||||
code: "community-key-continuity",
|
||||
message: "This certificate has appeared in the synthetic community record for 184 days.",
|
||||
data: { observers: 7, independentOperators: 3, ageDays: 184 },
|
||||
},
|
||||
{
|
||||
kind: "vote",
|
||||
code: "community-recommends-trust",
|
||||
message: "The configured community recommends trusting this exact host certificate.",
|
||||
},
|
||||
],
|
||||
};
|
||||
manifest: pluginManifest(
|
||||
"community.village.observer",
|
||||
"Village community observer",
|
||||
["advisor"],
|
||||
),
|
||||
hooks: {
|
||||
collectEvidence({ facts }) {
|
||||
if (facts.hostname !== "library.village") return;
|
||||
return {
|
||||
entries: [
|
||||
{
|
||||
kind: "evidence",
|
||||
code: "community-key-continuity",
|
||||
message: "This certificate has appeared in the synthetic community record for 184 days.",
|
||||
data: { observers: 7, independentOperators: 3, ageDays: 184 },
|
||||
},
|
||||
{
|
||||
kind: "vote",
|
||||
code: "community-recommends-trust",
|
||||
message: "The configured community recommends trusting this exact host certificate.",
|
||||
data: { trusted: true },
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -64,42 +70,70 @@ export function createCommunityAdvicePlugin({
|
||||
message,
|
||||
}) {
|
||||
return {
|
||||
manifest: { id, name, role: "advisor" },
|
||||
collectEvidence() {
|
||||
return {
|
||||
entries: [
|
||||
{
|
||||
kind: "vote",
|
||||
code: trusted ? "community-votes-trusted" : "community-votes-not-trusted",
|
||||
message,
|
||||
data: { trusted },
|
||||
},
|
||||
],
|
||||
};
|
||||
manifest: pluginManifest(id, name, ["advisor"]),
|
||||
hooks: {
|
||||
collectEvidence() {
|
||||
return {
|
||||
entries: [
|
||||
{
|
||||
kind: "vote",
|
||||
code: trusted ? "community-votes-trusted" : "community-votes-not-trusted",
|
||||
message,
|
||||
data: { trusted },
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function createUserDecisionPlugin(decision) {
|
||||
if (decision !== true && decision !== false) return undefined;
|
||||
const decide = ({ facts, journal }) => ({
|
||||
trusted: decision,
|
||||
scope: exactCertificateScope(facts),
|
||||
lifetime: { kind: "connection" },
|
||||
reasonEntryIds: journal.entries
|
||||
.filter((entry) => entry.kind === "evidence" || entry.kind === "warning")
|
||||
.map((entry) => entry.id),
|
||||
});
|
||||
return {
|
||||
manifest: {
|
||||
id: "local.user.decision",
|
||||
name: "Local user decision",
|
||||
role: "decision-authority",
|
||||
},
|
||||
decide({ facts, journal }) {
|
||||
return {
|
||||
trusted: decision,
|
||||
scope: { hostname: facts.hostname, port: facts.port },
|
||||
reasonEntryIds: journal.entries
|
||||
.filter((entry) => entry.kind === "evidence" || entry.kind === "warning")
|
||||
.map((entry) => entry.id),
|
||||
};
|
||||
manifest: pluginManifest(
|
||||
"local.user.decision",
|
||||
"Local user decision",
|
||||
["decision-authority"],
|
||||
),
|
||||
hooks: {
|
||||
onBeforeTlsAccept: decide,
|
||||
async onTlsFailure(context) {
|
||||
return decide(context);
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function exactCertificateScope(facts) {
|
||||
return {
|
||||
kind: "certificate-for-host",
|
||||
hostname: facts.hostname,
|
||||
port: facts.port,
|
||||
certificateSha256: facts.presentedChain[0].sha256,
|
||||
};
|
||||
}
|
||||
|
||||
function pluginManifest(id, name, supportedModes) {
|
||||
return {
|
||||
manifestVersion: 1,
|
||||
trustApiVersion: "0.1",
|
||||
id,
|
||||
name,
|
||||
version: "0.0.0",
|
||||
supportedModes,
|
||||
capabilities: {},
|
||||
};
|
||||
}
|
||||
|
||||
function explainValidationError(error) {
|
||||
const explanations = {
|
||||
"unknown-issuer":
|
||||
|
||||
Reference in new issue
Block a user