c10cb3cc1024592b16bdca405f4abc5340ad43af
2 PubkeyListValue
: L
.cbi
.AbstractValue
.extend({
4 'A': 0, 'B': 1, 'C': 2, 'D': 3, 'E': 4, 'F': 5, 'G': 6,
5 'H': 7, 'I': 8, 'J': 9, 'K': 10, 'L': 11, 'M': 12, 'N': 13,
6 'O': 14, 'P': 15, 'Q': 16, 'R': 17, 'S': 18, 'T': 19, 'U': 20,
7 'V': 21, 'W': 22, 'X': 23, 'Y': 24, 'Z': 25, 'a': 26, 'b': 27,
8 'c': 28, 'd': 29, 'e': 30, 'f': 31, 'g': 32, 'h': 33, 'i': 34,
9 'j': 35, 'k': 36, 'l': 37, 'm': 38, 'n': 39, 'o': 40, 'p': 41,
10 'q': 42, 'r': 43, 's': 44, 't': 45, 'u': 46, 'v': 47, 'w': 48,
11 'x': 49, 'y': 50, 'z': 51, '0': 52, '1': 53, '2': 54, '3': 55,
12 '4': 56, '5': 57, '6': 58, '7': 59, '8': 60, '9': 61, '+': 62,
16 base64Decode: function(s
)
21 if (s
.match(/[^A-Za-z0-9\+\/\=]/))
26 var e1
= this.base64Table
[s
.charAt(i
++)];
27 var e2
= this.base64Table
[s
.charAt(i
++)];
28 var e3
= this.base64Table
[s
.charAt(i
++)];
29 var e4
= this.base64Table
[s
.charAt(i
++)];
31 var c1
= ( e1
<< 2) | (e2
>> 4);
32 var c2
= ((e2
& 15) << 4) | (e3
>> 2);
33 var c3
= ((e3
& 3) << 6) | e4
;
35 d
+= String
.fromCharCode(c1
);
38 d
+= String
.fromCharCode(c2
);
41 d
+= String
.fromCharCode(c3
);
47 lengthDecode: function(s
, off
)
49 var l
= (s
.charCodeAt(off
++) << 24) |
50 (s
.charCodeAt(off
++) << 16) |
51 (s
.charCodeAt(off
++) << 8) |
54 if (l
< 0 || (off
+ l
) > s
.length
)
60 pubkeyDecode: function(s
)
62 var parts
= s
.split(/\s+/);
66 var key
= this.base64Decode(parts
[1]);
73 len
= this.lengthDecode(key
, off
);
78 var type
= key
.substr(off
+ 4, len
);
84 var len1
= this.lengthDecode(key
, off
);
90 var len2
= this.lengthDecode(key
, off
);
103 return { type
: 'RSA', bits
: len2
* 8, comment
: parts
[2] };
106 return { type
: 'DSA', bits
: len1
* 8, comment
: parts
[2] };
113 _remove: function(ev
)
115 var self
= ev
.data
.self
;
117 self
._keys
.splice(ev
.data
.index
, 1);
118 self
._render(ev
.data
.div
);
123 var self
= ev
.data
.self
;
125 var form
= $('<div />')
127 .text(L
.tr('Paste the public key line into the field below and press "%s" to continue.').format(L
.tr('Ok'))))
129 .text(L
.tr('Unrecognized public key! Please add only RSA or DSA keys.'))
130 .addClass('alert alert-danger')
133 .append($('<input />')
134 .attr('type', 'text')
135 .attr('placeholder', L
.tr('Paste key here'))
136 .addClass('form-control')));
138 L
.ui
.dialog(L
.tr('Add new public key'), form
, {
140 confirm: function() {
141 var val
= form
.find('input').val();
147 var key
= self
.pubkeyDecode(val
);
150 form
.find('input').val('');
151 form
.find('.alert').show();
155 self
._keys
.push(val
);
156 self
._render(ev
.data
.div
);
165 var self
= ev
.data
.self
;
169 $('<pre />').text(self
._keys
[ev
.data
.index
]),
174 _render: function(div
)
178 for (var i
= 0; i
< this._keys
.length
; i
++)
180 var k
= this.pubkeyDecode(this._keys
[i
] || '');
186 .addClass('input-group')
187 .append($('<input />')
188 .addClass('form-control')
189 .attr('type', 'text')
190 .prop('readonly', true)
191 .click({ self
: this, index
: i
}, this._show
)
192 .val('%dBit %s - %s'.format(k
.bits
, k
.type
, k
.comment
|| '?')))
193 .append($('<span />')
194 .addClass('input-group-btn')
195 .append($('<button />')
196 .addClass('btn btn-danger')
197 .attr('title', L
.tr('Remove public key'))
199 .click({ self
: this, div
: div
, index
: i
}, this._remove
)))
203 if (this._keys
.length
> 0)
204 $('<br />').appendTo(div
);
206 L
.ui
.button(L
.tr('Add public key …'), 'success')
207 .click({ self
: this, div
: div
}, this._add
)
211 widget: function(sid
)
215 for (var i
= 0; i
< this.options
.keys
.length
; i
++)
216 this._keys
.push(this.options
.keys
[i
]);
219 .attr('id', this.id(sid
));
226 changed: function(sid
)
228 if (this.options
.keys
.length
!= this._keys
.length
)
231 for (var i
= 0; i
< this.options
.keys
.length
; i
++)
232 if (this.options
.keys
[i
] != this._keys
[i
])
240 if (this.changed(sid
))
242 this.options
.keys
= [ ];
244 for (var i
= 0; i
< this._keys
.length
; i
++)
245 this.options
.keys
.push(this._keys
[i
]);
247 return L
.system
.setSSHKeys(this._keys
);
254 execute: function() {
256 return L
.system
.getSSHKeys().then(function(keys
) {
257 var m
= new L
.cbi
.Map('dropbear', {
258 caption
: L
.tr('SSH Access'),
259 description
: L
.tr('Dropbear offers SSH network shell access and an integrated SCP server'),
263 var s1
= m
.section(L
.cbi
.DummySection
, '__password', {
264 caption
: L
.tr('Router Password'),
265 description
: L
.tr('Changes the administrator password for accessing the device'),
266 readonly
: !self
.options
.acls
.admin
269 var p1
= s1
.option(L
.cbi
.PasswordValue
, 'pass1', {
270 caption
: L
.tr('Password'),
274 var p2
= s1
.option(L
.cbi
.PasswordValue
, 'pass2', {
275 caption
: L
.tr('Confirmation'),
277 datatype: function(v
) {
278 var v1
= p1
.formvalue('__password');
279 if (v1
&& v1
.length
&& v
!= v1
)
280 return L
.tr('Passwords must match!');
285 p1
.save = function(sid
) { };
286 p2
.save = function(sid
) {
287 var v1
= p1
.formvalue(sid
);
288 var v2
= p2
.formvalue(sid
);
289 if (v2
&& v2
.length
> 0 && v1
== v2
)
290 return L
.system
.setPassword('root', v2
);
294 var s2
= m
.section(L
.cbi
.DummySection
, '__pubkeys', {
295 caption
: L
.tr('SSH-Keys'),
296 description
: L
.tr('Specifies public keys for passwordless SSH authentication'),
297 readonly
: !self
.options
.acls
.admin
300 var k
= s2
.option(self
.PubkeyListValue
, 'keys', {
301 caption
: L
.tr('Saved keys'),
306 var s3
= m
.section(L
.cbi
.TypedSection
, 'dropbear', {
307 caption
: L
.tr('SSH Server'),
308 description
: L
.tr('This sections define listening instances of the builtin Dropbear SSH server'),
310 add_caption
: L
.tr('Add instance ...'),
311 readonly
: !self
.options
.acls
.admin
,
315 s3
.option(L
.cbi
.NetworkList
, 'Interface', {
316 caption
: L
.tr('Interface'),
317 description
: L
.tr('Listen only on the given interface or, if unspecified, on all')
320 s3
.option(L
.cbi
.InputValue
, 'Port', {
321 caption
: L
.tr('Port'),
322 description
: L
.tr('Specifies the listening port of this Dropbear instance'),
328 s3
.option(L
.cbi
.CheckboxValue
, 'PasswordAuth', {
329 caption
: L
.tr('Password authentication'),
330 description
: L
.tr('Allow SSH password authentication'),
336 s3
.option(L
.cbi
.CheckboxValue
, 'RootPasswordAuth', {
337 caption
: L
.tr('Allow root logins with password'),
338 description
: L
.tr('Allow the root user to login with password'),
344 s3
.option(L
.cbi
.CheckboxValue
, 'GatewayPorts', {
345 caption
: L
.tr('Gateway ports'),
346 description
: L
.tr('Allow remote hosts to connect to local SSH forwarded ports'),
352 return m
.insertInto('#map');