diff --git a/README.md b/README.md
index 32c9f62..9b4ae6c 100644
--- a/README.md
+++ b/README.md
@@ -2,4 +2,4 @@
Convert OpenVPN config files to the ONC ChromeOS network config files.
## How to use
-Download the code and open index.html in Chrome. Follow the instructions there.
+Download the the `index.html` file and open it in Chrome. Follow the instructions there.
diff --git a/index.html b/index.html
index 0606be4..4fda698 100644
--- a/index.html
+++ b/index.html
@@ -7,23 +7,306 @@
OpenVPN to ONC
-
-
+
+
-
+
ovpn2onc
-
Name for connection:
+
Name for connection (can be chosen freely):
OpenVPN config file (*.ovpn):
-
+
-
Output
-
+
Output (copy this into a new file and load it in ChromeOS)
+
diff --git a/js/converter.js b/js/converter.js
deleted file mode 100644
index 95e27be..0000000
--- a/js/converter.js
+++ /dev/null
@@ -1,143 +0,0 @@
-/**
- * Convert the parsed OpenVPN config to ONC.
- */
-
-const oncBasics = {
- 'Type': 'UnencryptedConfiguration',
- 'Certificates': [],
- 'NetworkConfigurations': []
-}
-
-export function convert(name, ovpn, keys) {
- if (!ovpn.client) {
- console.warn('Is this a server file?')
- }
- let params = {}
-
- // Add certificates
- let certs = []
- let [cas, caGuids] = createCerts(keys, ovpn['ca'], 'Authority')
- params['ServerCARefs'] = caGuids
- certs = certs.concat(cas)
- let [clientCerts, clientCertGuids] = createCerts(keys, ovpn['cert'], 'Client')
- if (clientCerts[0]) {
- params['ClientCertType'] = 'Ref'
- params['ClientCertRef'] = clientCertGuids[0]
- certs.push(clientCerts[0])
- } else {
- params['ClientCertType'] = 'None'
- }
-
- // Add parameters
- let remote = ovpn.remote.split(' ')
- const host = remote[0]
- if (remote[1]) params['Port'] = remote[1]
- if (ovpn['auth-user-pass']) params['UserAuthenticationType'] = 'Password'
- if (ovpn['comp-lzo'] && ovpn['comp-lzo'] !== 'no') {
- params['CompLZO'] = 'true'
- } else {
- params['CompLZO'] = 'false'
- }
- if (ovpn['persist-key']) params['SaveCredentials'] = true
- if (ovpn['tls-auth']) {
- let authKey = ovpn['tls-auth'].split(' ')
- params['TLSAuthContents'] = convertKey(keys[authKey[0]])
- if (authKey[1]) params['KeyDirection'] = authKey[1]
- }
- if (ovpn['verify-x509-name']) {
- params['VerifyX509'] = {
- 'Name': ovpn['verify-x509-name']
- }
- }
- // set parameters if they exist in the ovpn config
- let conditionalSet = (ovpnName, oncName, type='str') => {
- if (ovpn[ovpnName]) {
- const raw = ovpn[ovpnName]
- let value
- switch (type) {
- case 'int':
- value = Number(raw)
- break
- default:
- value = raw
- }
- params[oncName] = value
- }
- }
- conditionalSet('port', 'Port', 'int')
- conditionalSet('proto', 'Proto')
- conditionalSet('key-direction', 'KeyDirection')
- conditionalSet('remote-cert-tls', 'RemoteCertTLS')
- conditionalSet('cipher', 'Cipher')
- conditionalSet('auth', 'Auth')
- conditionalSet('auth-retry', 'AuthRetry')
- conditionalSet('reneg-sec', 'RenegSec', 'int')
-
- // Put together network configuration
- let config = {
- 'GUID': `{${uuidv4()}}`,
- 'Name': name,
- 'Type': 'VPN',
- 'VPN': {
- 'Type': 'OpenVPN',
- 'Host': host,
- 'OpenVPN': params
- }
- }
-
- // Put everything together
- let onc = Object.assign({}, oncBasics) // create copy
- onc.NetworkConfigurations = [config]
- onc.Certificates = certs
- return onc
-}
-
-/**
- * Create UUID (from Stackoverflow).
- */
-function uuidv4() {
- return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c=>
- (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
- )
-}
-
-function convertKey(key) {
- let lines = key.split(/\n/g)
- let out = ''
- for (let line of lines) {
- // filter out empty lines and lines with comments
- if (!line || line.match(/^\s*[;#]/)) continue
- out += line + '\n'
- }
- return out
-}
-
-function extractCas(str) {
- let splits = str.replace(/\n/g, '').split('-----BEGIN CERTIFICATE-----')
- console.log(splits)
- let cas = []
- for (const s of splits) {
- if (s.includes('-----END CERTIFICATE-----')) {
- cas.push(s.split('-----END CERTIFICATE-----')[0])
- }
- }
- return cas
-}
-
-function createCerts(keys, certName, certType) {
- let certs = []
- let certGuids = []
- if (certName) {
- let rawCerts = extractCas(keys[certName])
- for (const cert of rawCerts) {
- const guid = `{${uuidv4()}}`
- certGuids.push(guid)
- certs.push({
- 'GUID': guid,
- 'Type': certType,
- 'X509': cert
- })
- }
- }
- return [certs, certGuids]
-}
diff --git a/js/main.js b/js/main.js
deleted file mode 100644
index 84deba1..0000000
--- a/js/main.js
+++ /dev/null
@@ -1,41 +0,0 @@
-import {decode} from './parser.js'
-import {convert} from './converter.js'
-
-let clickButton = document.getElementById('clickbutton')
-clickButton.addEventListener('click', handler, false)
-
-function handler() {
- let selectedFile = document.getElementById('inputopenvpn').files[0]
- let certificates = document.getElementById('inputcertificates').files
- let connName = document.getElementById('connname').value
- let output = document.getElementById('output')
- main(connName, selectedFile, certificates, output)
-}
-
-async function main(connName, selectedFile, certificateFiles, output) {
- if (connName === '') {
- alert('Please specify a name for the connection.')
- return
- }
- console.log(selectedFile.size + ' bytes')
- let content = await readFile(selectedFile)
- let [ovpn, keys] = decode(content)
- console.log(ovpn)
- for (const certificateFile of certificateFiles) {
- keys[certificateFile.name] = await readFile(certificateFile)
- }
- let onc = convert(connName, ovpn, keys)
- output.value = JSON.stringify(onc, null, 2)
-}
-
-function readFile(file) {
- return new Promise(resolve => {
- let reader = new FileReader()
- reader.onload = (e => {
- // callback and remove windows-style newlines
- resolve(e.target.result.replace(/\r/g, ''))
- })
- // start reading
- reader.readAsText(file)
- })
-}
diff --git a/js/parser.js b/js/parser.js
deleted file mode 100644
index ac1b986..0000000
--- a/js/parser.js
+++ /dev/null
@@ -1,91 +0,0 @@
-/**
- * Parse *.ovpn file.
- */
-export function decode (str) {
- let ovpn = {}
- let keys = {}
- const re = /^([^ ]+)( (.*))?$/i
- const xmlOpen = /^<([^\/].*)>$/i
- const xmlClose = /^<\/(.*)>$/i
- let xmlTag = ''
- let inXml = false
- let xmlContent = ''
- let lines = str.split(/[\r\n]+/g)
-
- for (let line of lines) {
- if (!line || line.match(/^\s*[;#]/)) continue
- if (inXml) {
- const xmlMatch = line.match(xmlClose)
- if (!xmlMatch) {
- xmlContent += line + '\n'
- continue
- }
- const tag = xmlMatch[1]
- if (tag !== xmlTag) {
- throw 'bad xml tag'
- }
- const name = unsafe(xmlTag)
- const value = unsafe(xmlContent)
- keys[name] = value
- ovpn[name] = name
- xmlContent = ''
- inXml = false
- continue
- }
- const xmlMatch = line.match(xmlOpen)
- if (xmlMatch) {
- inXml = true
- xmlTag = xmlMatch[1]
- continue
- }
- const match = line.match(re)
- if (!match) continue
- const key = unsafe(match[1])
- const value = match[2] ? unsafe((match[3] || '')) : true
- ovpn[key] = value
- }
-
- return [ovpn, keys]
-}
-
-function isQuoted (val) {
- return ((val.charAt(0) === '"' && val.slice(-1) === '"') ||
- (val.charAt(0) === "'" && val.slice(-1) === "'"))
-}
-
-function unsafe (val, doUnesc) {
- val = (val || '').trim()
- if (isQuoted(val)) {
- // remove the single quotes before calling JSON.parse
- if (val.charAt(0) === "'") {
- val = val.substr(1, val.length - 2)
- }
- try { val = JSON.parse(val) } catch (_) {}
- } else {
- // walk the val to find the first not-escaped ; character
- var esc = false
- var unesc = ''
- for (var i = 0, l = val.length; i < l; i++) {
- var c = val.charAt(i)
- if (esc) {
- if ('\\;#'.indexOf(c) !== -1) {
- unesc += c
- } else {
- unesc += '\\' + c
- }
- esc = false
- } else if (';#'.indexOf(c) !== -1) {
- break
- } else if (c === '\\') {
- esc = true
- } else {
- unesc += c
- }
- }
- if (esc) {
- unesc += '\\'
- }
- return unesc
- }
- return val
-}
diff --git a/style.css b/style.css
deleted file mode 100644
index a1d72b3..0000000
--- a/style.css
+++ /dev/null
@@ -1,3 +0,0 @@
-#output {
- background-color: lightgray;
-}