fix(ipsec): исключить чужие сессии при сопоставлении CN

This commit is contained in:
Denozordec committed 2026-10-10 09:56:21 +07:00
1 parent 2aa93ad365
commit 7815e00a1c
15 files changed
+604 -13

No files matched your search

+4 -1
View File
@@ -304,7 +304,10 @@ export function mapClients(state: IpsecServerState): IpsecClientDto[] {
const subject = routerOsCertificateDn(cert)
const bySubject = subject && subjectCounts.get(subject) === 1 ? activeByRemote.get(subject) : undefined
const uniqueCn = cn && cnCounts.get(cn) === 1
const active = (uniqueCn ? findActive(cn) : undefined) ?? bySubject
// A literal CN is not a typed remote-id. It may also resemble another
// certificate's complete DN, in which case the bare-CN alias is unsafe.
const byCommonName = uniqueCn && !subjectCounts.has(cn) ? activeByRemote.get(cn) : undefined
const active = bySubject ?? byCommonName
?? (identity?.["remote-id"] ? findActive(String(identity["remote-id"]).trim()) : undefined)
out.push({
id: `${server.id}:${identity ? "identity" : "cert"}:${String(identity?.[".id"] ?? cert[".id"] ?? certName)}`,
+23
View File
@@ -129,4 +129,27 @@ state.active[0]!.id = 'C=US, S=New York, L=Albany, O=Example, Ltd, OU=QA+Operati
assert.equal(mapClients(state).find(c => c.certName === "client")?.online, true); checks++
certificate.organization = "bad\nsubject"
assert.equal(mapClients(state).find(c => c.certName === "client")?.online, false); checks++
const namespaceState = {
...state,
identities: [],
certs: [
{ ".id": "*PLAIN", name: "ipsec-user-plain", "common-name": "alice", ca: "ca", "key-usage": "tls-client" },
{ ".id": "*DNNAME", name: "ipsec-user-dn-name", "common-name": "CN=alice", ca: "ca", "key-usage": "tls-client" },
{ ".id": "*TYPEDNAME", name: "ipsec-user-typed-name", "common-name": "key-id:alice", ca: "ca", "key-usage": "tls-client" },
],
active: [{ ".id": "*NATIVE", id: "CN=alice", state: "established", "dynamic-address": "198.18.111.250" }],
} as typeof state
assert.equal(mapClients(namespaceState).find(c => c.certName === "ipsec-user-plain")?.online, true); checks++
assert.equal(mapClients(namespaceState).find(c => c.certName === "ipsec-user-dn-name")?.online, false); checks++
namespaceState.active[0]!.id = "alice"
assert.equal(mapClients(namespaceState).find(c => c.certName === "ipsec-user-plain")?.online, true); checks++
assert.equal(mapClients(namespaceState).find(c => c.certName === "ipsec-user-typed-name")?.online, false); checks++
namespaceState.active[0]!.id = "key-id:alice"
assert.equal(mapClients(namespaceState).find(c => c.certName === "ipsec-user-typed-name")?.online, true); checks++
// Type normalization belongs to an explicitly configured remote ID, not a CN.
namespaceState.identities = [{ ".id": "*EXPLICIT", peer: "ike", "auth-method": "digital-signature", "remote-certificate": "ipsec-user-plain", "remote-id": "fqdn:explicit.example", comment: "explicit certificate" }]
namespaceState.active[0]!.id = "explicit.example"
assert.equal(mapClients(namespaceState).find(c => c.certName === "ipsec-user-plain")?.online, true); checks++
namespaceState.identities[0]!["remote-id"] = "unknown:explicit.example"
assert.equal(mapClients(namespaceState).find(c => c.certName === "ipsec-user-plain")?.online, false); checks++
console.log(`ipsec-state: ${checks} checks passed`)