aboutsummaryrefslogtreecommitdiffstats
path: root/dmvpn-pfx-decode
blob: ac30ea976300d6e00d63c3abb8d87383a2e0c091 (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
#!/usr/bin/lua5.2

--[[
Copyright (c) 2017-2018 Kaarle Ritvanen
See LICENSE file for license details
]]--

dmvpn = require('dmvpn')
pkcs12 = require('openssl.pkcs12')
rfc5280 = require('asn1.rfc5280')

name = arg[1]
file = io.open(name)
data = file:read('*a')
file:close()

name = name:match('/([^/]+)$') or name
password = name:match('^[-%w]*_%d+%.(%w+)%.pfx$')
if password then
	success, key, cert, chain = pcall(pkcs12.parse, data, password)
end
if not success then
	key, cert, chain = pkcs12.parse(data, dmvpn.get_password())
end

function write_pem_file(data, dir, suffix)
	local file = io.open(
		'/etc/swanctl/'..dir..'/dmvpn'..(suffix or '')..'.pem', 'w'
	)
	file:write(data)
	file:close()
end

write_pem_file(key:toPEM('private'), 'private')
write_pem_file(tostring(cert), 'x509')
for _, ca_cert in pairs(chain) do
	local suffix
	local usage = rfc5280.KeyUsage.decode(
		ca_cert:getExtension('keyUsage'):getData()
	)
	if usage.keyCertSign then suffix = ''
	elseif usage.cRLSign then suffix = '-crl' end
	if suffix then write_pem_file(tostring(ca_cert), 'x509ca', suffix) end
end

function print_var(name, value)
	print(name.."='"..value:gsub("'", "'\\''").."'")
end

for tpe, value in pairs(cert:getSubjectAlt()) do
	if tpe == 'IP' then
		if value:match('^[%d%.]+$') then
			print_var('GRE_IPV4_ADDRESS', value)
		elseif value:match('^[%x:]+$') then
			print_var('GRE_IPV6_ADDRESS', value)
		else assert(false) end
	end
end

EXTENSIONS = {
	basicConstraints=true,
	['sbgp-ipAddrBlock']={
		IPV4_PREFIXES=function(v) return v[1] end,
		IPV6_PREFIXES=function(v) return v[2] end
	},
	['sbgp-autonomousSysNum']='AS_NUMBER',
	[dmvpn.OID_IS_HUB]={
		VPNC_TYPE=function(v) return v and 'hub' or 'spoke' end
	},
	[dmvpn.OID_HUB_HOSTS]='HUBS'
}


for i=1,cert:getExtensionCount() do
	ext = cert:getExtension(i)
	k = ext:getName()
	v = EXTENSIONS[k]
	if v then
		if type(v) == 'string' then
			v = {[v]=function(v) return v end}
		end
		if type(v) == 'table' then
			local data = dmvpn.decode_ext(k, ext)
			for var, func in pairs(v) do
				local d = func(data)
				print_var(
					var,
					type(d) == 'table' and
						table.concat(d, ' ') or
						tostring(d)
				)
			end
		end
	elseif ext:getCritical() then
		error('Unrecognized critical extension: '..k)
	end
end