luci-app-udpxy: disambiguate strings
[project/luci.git] / protocols / luci-proto-openconnect / htdocs / luci-static / resources / protocol / openconnect.js
1 'use strict';
2 'require rpc';
3 'require form';
4 'require network';
5 'require validation';
6
7 var callGetCertificateFiles = rpc.declare({
8 object: 'luci.openconnect',
9 method: 'getCertificates',
10 params: [ 'interface' ],
11 expect: { '': {} }
12 });
13
14 var callSetCertificateFiles = rpc.declare({
15 object: 'luci.openconnect',
16 method: 'setCertificates',
17 params: [ 'interface', 'user_certificate', 'user_privatekey', 'ca_certificate' ],
18 expect: { '': {} }
19 });
20
21 network.registerPatternVirtual(/^vpn-.+$/);
22
23 function sanitizeCert(s) {
24 if (typeof(s) != 'string')
25 return null;
26
27 s = s.trim();
28
29 if (s == '')
30 return null;
31
32 s = s.replace(/\r\n?/g, '\n');
33
34 if (!s.match(/\n$/))
35 s += '\n';
36
37 return s;
38 }
39
40 function validateCert(priv, section_id, value) {
41 var beg = priv ? /^-----BEGIN (RSA )?PRIVATE KEY-----$/ : /^-----BEGIN CERTIFICATE-----$/,
42 end = priv ? /^-----END (RSA )?PRIVATE KEY-----$/ : /^-----END CERTIFICATE-----$/,
43 lines = value.trim().split(/[\r\n]/),
44 start = false,
45 i;
46
47 if (value === null || value === '')
48 return true;
49
50 for (i = 0; i < lines.length; i++) {
51 if (lines[i].match(beg))
52 start = true;
53 else if (start && !lines[i].match(/^(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=)?$/))
54 break;
55 }
56
57 if (!start || i < lines.length - 1 || !lines[i].match(end))
58 return _('This does not look like a valid PEM file');
59
60 return true;
61 }
62
63 return network.registerProtocol('openconnect', {
64 getI18n: function() {
65 return _('OpenConnect');
66 },
67
68 getIfname: function() {
69 return this._ubus('l3_device') || 'vpn-%s'.format(this.sid);
70 },
71
72 getOpkgPackage: function() {
73 return 'openconnect';
74 },
75
76 isFloating: function() {
77 return true;
78 },
79
80 isVirtual: function() {
81 return true;
82 },
83
84 getDevices: function() {
85 return null;
86 },
87
88 containsDevice: function(ifname) {
89 return (network.getIfnameOf(ifname) == this.getIfname());
90 },
91
92 renderFormOptions: function(s) {
93 var dev = this.getDevice().getName(),
94 certLoadPromise = null,
95 o;
96
97 o = s.taboption('general', form.ListValue, 'vpn_protocol', _('VPN Protocol'));
98 o.value('anyconnect', 'OpenConnect or Cisco AnyConnect SSL VPN');
99 o.value('nc', 'Juniper Network Connect');
100 o.value('gp', 'Palo Alto Networks GlobalProtect');
101 o.value('pulse', 'Pulse Connect Secure SSL VPN');
102 o.value('f5', 'F5 BIG-IP SSL VPN');
103 o.value('fortinet', 'Fortinet SSL VPN');
104 o.value('array', 'Array Networks SSL VPN');
105
106 o = s.taboption('general', form.Value, 'uri', _('VPN Server'));
107 o.placeholder = 'https://example.com:443/usergroup';
108 o.validate = function(section_id, value) {
109 var m = String(value).match(/^(?:(\w+):\/\/|)(?:\[([0-9a-f:.]{2,45})\]|([^\/:]+))(?::([0-9]{1,5}))?(?:\/.*)?$/i);
110
111 if (!m)
112 return _('Invalid server URL');
113
114 if (m[1] != null) {
115 if (!m[1].match(/^(?:https|socks|socks4|socks5)$/i))
116 return _('Unsupported protocol');
117 }
118
119 if (m[2] != null) {
120 if (!validation.parseIPv6(m[2]))
121 return _('Invalid IPv6 address');
122 }
123
124 if (m[3] != null) {
125 if (!validation.parseIPv4(m[3])) {
126 if (!(m[3].length <= 253 &&
127 (m[3].match(/^[a-zA-Z0-9_]+$/) != null ||
128 (m[3].match(/^[a-zA-Z0-9_][a-zA-Z0-9_\-.]*[a-zA-Z0-9]$/) &&
129 m[3].match(/[^0-9.]/)))))
130 return _('Invalid hostname or IPv4 address');
131 }
132 }
133
134 if (m[4] != null) {
135 var p = +m[4];
136
137 if (p < 0 || p > 65535)
138 return _('Invalid port');
139 }
140
141 return true;
142 };
143
144 s.taboption('general', form.Value, 'serverhash', _("VPN Server's certificate SHA1 hash"));
145 s.taboption('general', form.Value, 'authgroup', _('Auth Group'));
146 s.taboption("general", form.Value, "username", _("Username"));
147
148 o = s.taboption('general', form.Value, 'password', _('Password'));
149 o.password = true;
150
151 o = s.taboption('general', form.Value, 'password2', _('Password2'));
152 o.password = true;
153
154 o = s.taboption('general', form.Value, 'proxy', _('Proxy Server'));
155 o.optional = true;
156
157 o = s.taboption('general', form.TextValue, 'usercert', _('User certificate (PEM encoded)'));
158 o.rows = 10;
159 o.monospace = true;
160 o.validate = L.bind(validateCert, o, false);
161 o.load = function(section_id) {
162 certLoadPromise = certLoadPromise || callGetCertificateFiles(section_id);
163 return certLoadPromise.then(function(certs) { return certs.user_certificate });
164 };
165 o.write = function(section_id, value) {
166 return callSetCertificateFiles(section_id, sanitizeCert(value), null, null);
167 };
168
169 o = s.taboption('general', form.TextValue, 'userkey', _('User key (PEM encoded)'));
170 o.rows = 10;
171 o.monospace = true;
172 o.validate = L.bind(validateCert, o, true);
173 o.load = function(section_id) {
174 certLoadPromise = certLoadPromise || callGetCertificateFiles(section_id);
175 return certLoadPromise.then(function(certs) { return certs.user_privatekey });
176 };
177 o.write = function(section_id, value) {
178 return callSetCertificateFiles(section_id, null, sanitizeCert(value), null);
179 };
180
181 o = s.taboption('general', form.TextValue, 'ca', _('CA certificate; if empty it will be saved after the first connection.'));
182 o.rows = 10;
183 o.monospace = true;
184 o.validate = L.bind(validateCert, o, false);
185 o.load = function(section_id) {
186 certLoadPromise = certLoadPromise || callGetCertificateFiles(section_id);
187 return certLoadPromise.then(function(certs) { return certs.ca_certificate });
188 };
189 o.write = function(section_id, value) {
190 return callSetCertificateFiles(section_id, null, null, sanitizeCert(value));
191 };
192
193 o = s.taboption('advanced', form.Value, 'mtu', _('Override MTU'));
194 o.optional = true;
195 o.placeholder = 1406;
196 o.datatype = 'range(68, 9200)';
197
198 o = s.taboption('advanced', form.Value, 'reconnect_timeout', _('Reconnect Timeout'));
199 o.optional = true;
200 o.placeholder = 300;
201 o.datatype = 'min(10)';
202 }
203 });