Some cleanup
This commit is contained in:
parent
1cc706da63
commit
5b93b733fa
132
js/connection.js
132
js/connection.js
@ -35,12 +35,10 @@ weechat.factory('connection',
|
|||||||
$log.debug('Connecting to URL: ', url);
|
$log.debug('Connecting to URL: ', url);
|
||||||
|
|
||||||
|
|
||||||
var weechatIsPre2_9 = false;
|
var weechatAssumedPre2_9 = false;
|
||||||
var onopen = function () {
|
var onopen = function () {
|
||||||
|
|
||||||
var _performHandshake = function() {
|
var _performHandshake = function() {
|
||||||
return new Promise(function(resolve) {
|
return new Promise(function(resolve) {
|
||||||
|
|
||||||
// First a handshake is sent to determine authentication method
|
// First a handshake is sent to determine authentication method
|
||||||
// This is only supported for weechat >= 2.9
|
// This is only supported for weechat >= 2.9
|
||||||
// If after 'a while' weechat does not respond
|
// If after 'a while' weechat does not respond
|
||||||
@ -54,7 +52,7 @@ weechat.factory('connection',
|
|||||||
|
|
||||||
// Wait long enough to assume we are on a version < 2.9
|
// Wait long enough to assume we are on a version < 2.9
|
||||||
var handShakeTimeout = setTimeout(function () {
|
var handShakeTimeout = setTimeout(function () {
|
||||||
weechatIsPre2_9 = true;
|
weechatAssumedPre2_9 = true;
|
||||||
console.log('Weechat\'s version is assumed to be < 2.9');
|
console.log('Weechat\'s version is assumed to be < 2.9');
|
||||||
resolve();
|
resolve();
|
||||||
}, WAIT_TIME_OLD_WEECHAT);
|
}, WAIT_TIME_OLD_WEECHAT);
|
||||||
@ -68,43 +66,35 @@ weechat.factory('connection',
|
|||||||
clearTimeout(handShakeTimeout);
|
clearTimeout(handShakeTimeout);
|
||||||
resolve(message);
|
resolve(message);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
};
|
||||||
}
|
|
||||||
|
|
||||||
var _askTotp = function (useTotp) {
|
var _askTotp = function (useTotp) {
|
||||||
return new Promise(function(resolve) {
|
return new Promise(function(resolve) {
|
||||||
|
|
||||||
// If weechat is < 2.9 the totp will be a setting (checkbox)
|
// If weechat is < 2.9 the totp will be a setting (checkbox)
|
||||||
// Otherwise the handshake will specify it
|
// Otherwise the handshake will specify it
|
||||||
if ( useTotp ) {
|
if (useTotp) {
|
||||||
// Ask the user to input his TOTP
|
// Ask the user to input his TOTP
|
||||||
var totp = prompt("Please enter your TOTP Token");
|
var totp = prompt("Please enter your TOTP Token");
|
||||||
resolve (totp);
|
resolve(totp);
|
||||||
} else {
|
} else {
|
||||||
// User does not use TOTP, don't ask
|
// User does not use TOTP, don't ask
|
||||||
resolve(null);
|
resolve(null);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
})
|
};
|
||||||
}
|
|
||||||
|
|
||||||
// Helper methods for initialization commands
|
// Helper methods for initialization commands
|
||||||
// This method is used to initialize weechat < 2.9
|
// This method is used to initialize weechat < 2.9
|
||||||
var _initializeConnectionPre29 = function(passwd, totp) {
|
var _initializeConnectionPre29 = function(passwd, totp) {
|
||||||
|
|
||||||
// This is not secure, this has to be specifically allowed with a setting
|
// This is not secure, this has to be specifically allowed with a setting
|
||||||
// Otherwise an attacker could persuade the client to send it's password
|
// Otherwise an attacker could persuade the client to send it's password
|
||||||
// Or due to latency the client could think weechat was an older version
|
// Or due to latency the client could think weechat was an older version
|
||||||
if (!settings.compatibilityWeechat28)
|
if (!settings.compatibilityWeechat28) {
|
||||||
{
|
|
||||||
$rootScope.oldWeechatError = true;
|
$rootScope.oldWeechatError = true;
|
||||||
$rootScope.$emit('relayDisconnect');
|
$rootScope.$emit('relayDisconnect');
|
||||||
$rootScope.$digest() // Have to do this otherwise change detection doesn't see the error.
|
$rootScope.$digest(); // Have to do this otherwise change detection doesn't see the error.
|
||||||
throw new Error('Plainttext authentication not allowed.');
|
throw new Error('Plaintext authentication not allowed.');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Escape comma in password (#937)
|
// Escape comma in password (#937)
|
||||||
@ -120,8 +110,8 @@ weechat.factory('connection',
|
|||||||
|
|
||||||
// Wait a little bit until the init is sent
|
// Wait a little bit until the init is sent
|
||||||
return new Promise(function(resolve) {
|
return new Promise(function(resolve) {
|
||||||
setTimeout(() => resolve(), 5);
|
setTimeout(function() { resolve(); }, 5);
|
||||||
})
|
});
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -129,48 +119,39 @@ weechat.factory('connection',
|
|||||||
// This method is used to initialize weechat >= 2.9
|
// This method is used to initialize weechat >= 2.9
|
||||||
var salt;
|
var salt;
|
||||||
var _initializeConnection29 = function(passwd, nonce, iterations, totp) {
|
var _initializeConnection29 = function(passwd, nonce, iterations, totp) {
|
||||||
|
|
||||||
return window.crypto.subtle.importKey(
|
return window.crypto.subtle.importKey(
|
||||||
|
|
||||||
'raw',
|
'raw',
|
||||||
utils.stringToUTF8Array(passwd),
|
utils.stringToUTF8Array(passwd),
|
||||||
{name: 'PBKDF2'},//{name: 'HMAC', hash: 'SHA-512'},
|
{name: 'PBKDF2'},//{name: 'HMAC', hash: 'SHA-512'},
|
||||||
false,
|
false,
|
||||||
['deriveBits']
|
['deriveBits']
|
||||||
|
).then(function (key) {
|
||||||
).then( function (key) {
|
var clientnonce = window.crypto.getRandomValues(new Uint8Array(16));
|
||||||
|
//nonce:clientnonce, 3A is a ':' in ASCII
|
||||||
salt = utils.concatenateTypedArray(utils.concatenateTypedArray(nonce, new Uint8Array([0x3A])), window.crypto.getRandomValues(new Uint8Array(16))); //nonce:cnonce, 3A is a ':' in ASCII
|
salt = utils.concatenateTypedArrays(
|
||||||
|
nonce, new Uint8Array([0x3A]), clientnonce);
|
||||||
return window.crypto.subtle.deriveBits(
|
return window.crypto.subtle.deriveBits(
|
||||||
{
|
{
|
||||||
name: 'PBKDF2',
|
name: 'PBKDF2',
|
||||||
hash: 'SHA-512',
|
hash: 'SHA-512',
|
||||||
salt: salt,
|
salt: salt,
|
||||||
iterations: iterations,
|
iterations: iterations,
|
||||||
},
|
}, key, 512
|
||||||
key, //your key from generateKey or importKey
|
|
||||||
512
|
|
||||||
);
|
);
|
||||||
|
}).then(function (hash) {
|
||||||
}).then( function (hash) {
|
|
||||||
|
|
||||||
|
|
||||||
ngWebsockets.send(
|
ngWebsockets.send(
|
||||||
weeChat.Protocol.formatInit29(
|
weeChat.Protocol.formatInit29(
|
||||||
'pbkdf2+sha512:' + utils.bytetoHexString(salt) + ':' + iterations + ':' + utils.bytetoHexString(hash),
|
'pbkdf2+sha512:' + utils.bytetoHexString(salt) + ':' +
|
||||||
|
iterations + ':' + utils.bytetoHexString(hash),
|
||||||
totp
|
totp
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Wait a little bit until the init is sent
|
// Wait a little bit until the init is sent
|
||||||
return new Promise(function(resolve) {
|
return new Promise(function(resolve) {
|
||||||
|
setTimeout(function() { resolve(); }, 5);
|
||||||
setTimeout(() => resolve(), 5);
|
});
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var _requestHotlist = function() {
|
var _requestHotlist = function() {
|
||||||
@ -295,61 +276,49 @@ weechat.factory('connection',
|
|||||||
$rootScope.angularTimeFormat = angularFormat;
|
$rootScope.angularTimeFormat = angularFormat;
|
||||||
};
|
};
|
||||||
|
|
||||||
var passwordMethod
|
var passwordMethod;
|
||||||
var totpRequested;
|
var totpRequested;
|
||||||
var nonce;
|
var nonce;
|
||||||
var iterations;
|
var iterations;
|
||||||
|
|
||||||
_performHandshake().then(
|
_performHandshake().then(
|
||||||
|
// Wait for weechat to respond or handshake times out
|
||||||
//Wait for weechat to respond or handshake times out
|
function (message) {
|
||||||
function (message)
|
|
||||||
{
|
|
||||||
// Do nothing if the handshake was received
|
// Do nothing if the handshake was received
|
||||||
// after concluding weechat was an old version
|
// after concluding weechat was an old version
|
||||||
// TODO maybe warn the user here
|
// TODO maybe warn the user here
|
||||||
if(weechatIsPre2_9) {
|
if (weechatAssumedPre2_9) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
passwordMethod = message.objects[0].content.password_hash_algo;
|
var content = message.objects[0].content;
|
||||||
totpRequested = message.objects[0].content.totp === 'on' ? true : false;
|
passwordMethod = content.password_hash_algo;
|
||||||
nonce = utils.hexStringToByte(message.objects[0].content.nonce);
|
totpRequested = (content.totp === 'on');
|
||||||
iterations = message.objects[0].content.password_hash_iterations;
|
nonce = utils.hexStringToByte(content.nonce);
|
||||||
|
iterations = content.password_hash_iterations;
|
||||||
|
|
||||||
if(passwordMethod != "pbkdf2+sha512")
|
if (passwordMethod != "pbkdf2+sha512") {
|
||||||
{
|
|
||||||
$rootScope.hashAlgorithmDisagree = true;
|
$rootScope.hashAlgorithmDisagree = true;
|
||||||
$rootScope.$emit('relayDisconnect');
|
$rootScope.$emit('relayDisconnect');
|
||||||
$rootScope.$digest() // Have to do this otherwise change detection doesn't see the error.
|
$rootScope.$digest(); // Have to do this otherwise change detection doesn't see the error.
|
||||||
throw new Error('No password hash algorithm returned.');
|
throw new Error('No supported password hash algorithm returned.');
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
).then(function() {
|
||||||
).then( function() {
|
if (weechatAssumedPre2_9) {
|
||||||
|
|
||||||
if(weechatIsPre2_9)
|
|
||||||
{
|
|
||||||
// Ask the user for the TOTP token if this is enabled
|
// Ask the user for the TOTP token if this is enabled
|
||||||
return _askTotp(useTotp)
|
return _askTotp(useTotp)
|
||||||
.then( function (totp) {
|
.then(function (totp) {
|
||||||
return _initializeConnectionPre29(passwd, totp)
|
return _initializeConnectionPre29(passwd, totp);
|
||||||
})
|
});
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// Weechat version >= 2.9
|
// Weechat version >= 2.9
|
||||||
return _askTotp(totpRequested)
|
return _askTotp(totpRequested)
|
||||||
.then( function(totp) {
|
.then(function(totp) {
|
||||||
return _initializeConnection29(passwd, nonce, iterations, totp)
|
return _initializeConnection29(passwd, nonce, iterations, totp);
|
||||||
})
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}).then(function(){
|
||||||
}).then( function(){
|
|
||||||
|
|
||||||
// The Init was sent, weechat will not respond
|
// The Init was sent, weechat will not respond
|
||||||
// Wait until either the connection closes
|
// Wait until either the connection closes
|
||||||
// Or try to send version and see if weechat responds
|
// Or try to send version and see if weechat responds
|
||||||
@ -358,9 +327,7 @@ weechat.factory('connection',
|
|||||||
name: 'version'
|
name: 'version'
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
}).then(function(version) {
|
||||||
}).then( function(version) {
|
|
||||||
|
|
||||||
// From now on we are assumed initialized
|
// From now on we are assumed initialized
|
||||||
// We don't know for sure because weechat does not respond
|
// We don't know for sure because weechat does not respond
|
||||||
// All we know is the socket wasn't closed afer waiting a little bit
|
// All we know is the socket wasn't closed afer waiting a little bit
|
||||||
@ -417,10 +384,6 @@ weechat.factory('connection',
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
var onmessage = function() {
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
var onclose = function (evt) {
|
var onclose = function (evt) {
|
||||||
/*
|
/*
|
||||||
* Handles websocket disconnection
|
* Handles websocket disconnection
|
||||||
@ -450,7 +413,9 @@ weechat.factory('connection',
|
|||||||
|
|
||||||
var handleWrongPassword = function() {
|
var handleWrongPassword = function() {
|
||||||
// Connection got closed, lets check if we ever was connected successfully
|
// Connection got closed, lets check if we ever was connected successfully
|
||||||
if (!$rootScope.waseverconnected && !$rootScope.errorMessage && !$rootScope.oldWeechatError && !$rootScope.hashAlgorithmDisagree) {
|
if (!$rootScope.waseverconnected && !$rootScope.errorMessage &&
|
||||||
|
!$rootScope.oldWeechatError && !$rootScope.hashAlgorithmDisagree)
|
||||||
|
{
|
||||||
$rootScope.passwordError = true;
|
$rootScope.passwordError = true;
|
||||||
$rootScope.$apply();
|
$rootScope.$apply();
|
||||||
}
|
}
|
||||||
@ -485,7 +450,6 @@ weechat.factory('connection',
|
|||||||
'binaryType': "arraybuffer",
|
'binaryType': "arraybuffer",
|
||||||
'onopen': onopen,
|
'onopen': onopen,
|
||||||
'onclose': onclose,
|
'onclose': onclose,
|
||||||
'onmessage': onmessage,
|
|
||||||
'onerror': onerror
|
'onerror': onerror
|
||||||
});
|
});
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
|
@ -778,13 +778,11 @@ weechat.controller('WeechatCtrl', ['$rootScope', '$scope', '$store', '$timeout',
|
|||||||
};
|
};
|
||||||
|
|
||||||
$scope.toggleAccordionByName = function(name) {
|
$scope.toggleAccordionByName = function(name) {
|
||||||
|
var target = document.getElementById(name);
|
||||||
var target = document.getElementById(name);;
|
|
||||||
toggleAccordionByTarget(target);
|
toggleAccordionByTarget(target);
|
||||||
};
|
};
|
||||||
|
|
||||||
var toggleAccordionByTarget = function(target) {
|
var toggleAccordionByTarget = function(target) {
|
||||||
|
|
||||||
target.setAttribute('data-state', target.getAttribute('data-state') === 'active' ? 'collapsed' : 'active');
|
target.setAttribute('data-state', target.getAttribute('data-state') === 'active' ? 'collapsed' : 'active');
|
||||||
|
|
||||||
// Hide all other siblings
|
// Hide all other siblings
|
||||||
|
27
js/utils.js
27
js/utils.js
@ -53,7 +53,7 @@ weechat.factory('utils', function() {
|
|||||||
|
|
||||||
var a = [];
|
var a = [];
|
||||||
for (var i = 0, len = str.length; i < len; i+=2) {
|
for (var i = 0, len = str.length; i < len; i+=2) {
|
||||||
a.push(parseInt(str.substr(i,2),16));
|
a.push(parseInt(str.substr(i, 2), 16));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Uint8Array(a);
|
return new Uint8Array(a);
|
||||||
@ -61,25 +61,24 @@ weechat.factory('utils', function() {
|
|||||||
|
|
||||||
function bytetoHexString(buffer) {
|
function bytetoHexString(buffer) {
|
||||||
return Array
|
return Array
|
||||||
.from (new Uint8Array (buffer))
|
.from(new Uint8Array (buffer))
|
||||||
.map (b => b.toString (16).padStart (2, "0"))
|
.map(function(b) { return b.toString(16).padStart(2, "0"); })
|
||||||
.join ("");
|
.join("");
|
||||||
}
|
}
|
||||||
|
|
||||||
function stringToUTF8Array(string) {
|
function stringToUTF8Array(string) {
|
||||||
const encoder = new TextEncoder()
|
return new TextEncoder().encode(string);
|
||||||
const view = encoder.encode(string)
|
|
||||||
return view;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function concatenateTypedArray(a, b) { // a, b TypedArray of same type
|
// Concatenate three TypedArrays of the same type
|
||||||
var c = new (a.constructor)(a.length + b.length);
|
function concatenateTypedArrays(a, b, c) {
|
||||||
c.set(a, 0);
|
var res = new (a.constructor)(a.length + b.length + c.length);
|
||||||
c.set(b, a.length);
|
res.set(a, 0);
|
||||||
return c;
|
res.set(b, a.length);
|
||||||
|
res.set(c, a.length + b.length);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
changeClassStyle: changeClassStyle,
|
changeClassStyle: changeClassStyle,
|
||||||
getClassStyle: getClassStyle,
|
getClassStyle: getClassStyle,
|
||||||
@ -90,6 +89,6 @@ weechat.factory('utils', function() {
|
|||||||
hexStringToByte: hexStringToByte,
|
hexStringToByte: hexStringToByte,
|
||||||
bytetoHexString: bytetoHexString,
|
bytetoHexString: bytetoHexString,
|
||||||
stringToUTF8Array: stringToUTF8Array,
|
stringToUTF8Array: stringToUTF8Array,
|
||||||
concatenateTypedArray: concatenateTypedArray
|
concatenateTypedArrays: concatenateTypedArrays
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@ -699,7 +699,6 @@
|
|||||||
* @return Formatted init command string
|
* @return Formatted init command string
|
||||||
*/
|
*/
|
||||||
WeeChatProtocol.formatInit29 = function(password_hash, totp) {
|
WeeChatProtocol.formatInit29 = function(password_hash, totp) {
|
||||||
|
|
||||||
var keys = [];
|
var keys = [];
|
||||||
var parts = [];
|
var parts = [];
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user