2017-01-27 15:55:38 +03:00
|
|
|
import QtQuick 2.0
|
|
|
|
import io.thp.pyotherside 1.4
|
|
|
|
|
2017-01-30 16:59:58 +03:00
|
|
|
|
2017-01-27 15:55:38 +03:00
|
|
|
// @disable-check M300
|
|
|
|
Python {
|
|
|
|
id: py
|
|
|
|
|
|
|
|
property int nDevices
|
|
|
|
property bool hasDevice
|
|
|
|
property string name
|
|
|
|
property string version
|
|
|
|
property string serial
|
|
|
|
property var features: []
|
|
|
|
property var connections: []
|
2017-01-31 18:17:10 +03:00
|
|
|
property var credentials: null
|
|
|
|
property int nextRefresh: 0
|
2017-01-27 15:55:38 +03:00
|
|
|
property var enabled: []
|
|
|
|
property bool ready: false
|
|
|
|
property var queue: []
|
2017-02-07 16:17:54 +03:00
|
|
|
property bool validated
|
2017-02-08 13:55:53 +03:00
|
|
|
property var passwordKey
|
2017-02-08 18:47:28 +03:00
|
|
|
signal wrongPassword
|
2017-01-27 15:55:38 +03:00
|
|
|
|
|
|
|
Component.onCompleted: {
|
2017-01-30 16:59:58 +03:00
|
|
|
importModule('site', function () {
|
|
|
|
call('site.addsitedir', [appDir + '/pymodules'], function () {
|
2017-01-27 15:55:38 +03:00
|
|
|
addImportPath(urlPrefix + '/py')
|
|
|
|
importModule('yubikey', function () {
|
|
|
|
ready = true
|
2017-01-30 16:59:58 +03:00
|
|
|
do_call('yubikey.controller.get_features', [],
|
|
|
|
function (res) {
|
|
|
|
features = res
|
|
|
|
for (var i in queue) {
|
|
|
|
do_call(queue[i][0], queue[i][1],
|
|
|
|
queue[i][2])
|
|
|
|
}
|
|
|
|
queue = []
|
|
|
|
})
|
2017-01-27 15:55:38 +03:00
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-02-09 14:45:04 +03:00
|
|
|
onHasDeviceChanged: {
|
2017-02-16 16:14:14 +03:00
|
|
|
device.passwordKey = null
|
|
|
|
device.validated = false
|
2017-02-09 14:45:04 +03:00
|
|
|
}
|
|
|
|
|
2017-01-27 15:55:38 +03:00
|
|
|
onError: {
|
|
|
|
console.log('Python error: ' + traceback)
|
|
|
|
}
|
|
|
|
|
|
|
|
function do_call(func, args, cb) {
|
|
|
|
if (!ready) {
|
|
|
|
queue.push([func, args, cb])
|
|
|
|
} else {
|
2017-02-01 18:51:02 +03:00
|
|
|
call(func, args.map(JSON.stringify), function (json) {
|
2017-01-27 15:55:38 +03:00
|
|
|
if (cb) {
|
|
|
|
cb(json ? JSON.parse(json) : undefined)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-23 12:40:24 +03:00
|
|
|
function refresh(refreshCredentialsOnMode) {
|
2017-01-27 15:55:38 +03:00
|
|
|
do_call('yubikey.controller.count_devices', [], function (n) {
|
|
|
|
nDevices = n
|
|
|
|
if (nDevices == 1) {
|
|
|
|
do_call('yubikey.controller.refresh', [], function (dev) {
|
|
|
|
hasDevice = dev !== undefined && dev !== null
|
|
|
|
name = dev ? dev.name : ''
|
|
|
|
version = dev ? dev.version : ''
|
|
|
|
serial = dev ? dev.serial : ''
|
|
|
|
enabled = dev ? dev.enabled : []
|
|
|
|
connections = dev ? dev.connections : []
|
|
|
|
})
|
|
|
|
} else if (hasDevice) {
|
|
|
|
hasDevice = false
|
2017-01-31 18:17:10 +03:00
|
|
|
credentials = null
|
|
|
|
nextRefresh = 0
|
2017-01-27 15:55:38 +03:00
|
|
|
}
|
2017-02-23 12:40:24 +03:00
|
|
|
refreshCredentialsOnMode()
|
2017-01-27 15:55:38 +03:00
|
|
|
})
|
2017-01-30 16:59:58 +03:00
|
|
|
}
|
2017-01-27 15:55:38 +03:00
|
|
|
|
2017-02-23 14:18:20 +03:00
|
|
|
function refreshCCIDCredentials(force) {
|
2017-02-23 12:40:24 +03:00
|
|
|
var now = Math.floor(Date.now() / 1000)
|
2017-02-23 14:18:20 +03:00
|
|
|
if (force || (validated && nextRefresh < now)) {
|
|
|
|
do_call('yubikey.controller.refresh_credentials', [now, passwordKey],
|
|
|
|
handleCredentials)
|
2017-02-23 12:40:24 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-23 14:18:20 +03:00
|
|
|
function refreshSlotCredentials(slots, digits, force) {
|
2017-02-23 12:40:24 +03:00
|
|
|
var now = Math.floor(Date.now() / 1000)
|
2017-02-23 14:18:20 +03:00
|
|
|
if (force || (nextRefresh < now)) {
|
2017-02-23 12:40:24 +03:00
|
|
|
do_call('yubikey.controller.refresh_slot_credentials', [slots, digits, now], handleCredentials)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-02-07 16:17:54 +03:00
|
|
|
function validate(providedPassword) {
|
2017-02-16 16:14:14 +03:00
|
|
|
do_call('yubikey.controller.validate', [providedPassword],
|
|
|
|
function (res) {
|
|
|
|
if (res !== false) {
|
|
|
|
passwordKey = res
|
|
|
|
validated = true
|
|
|
|
}
|
|
|
|
if (res === false) {
|
|
|
|
wrongPassword()
|
|
|
|
}
|
|
|
|
})
|
2017-02-01 18:27:45 +03:00
|
|
|
}
|
|
|
|
|
2017-02-16 16:14:14 +03:00
|
|
|
function promptOrSkip(prompt) {
|
|
|
|
do_call('yubikey.controller.needs_validation', [], function (res) {
|
2017-02-09 12:57:28 +03:00
|
|
|
if (res === true) {
|
|
|
|
prompt.open()
|
|
|
|
}
|
|
|
|
if (res === false) {
|
|
|
|
validated = true
|
|
|
|
}
|
2017-02-16 16:14:14 +03:00
|
|
|
})
|
2017-02-09 12:57:28 +03:00
|
|
|
}
|
|
|
|
|
2017-02-10 16:01:49 +03:00
|
|
|
function setPassword(password) {
|
2017-02-16 16:14:14 +03:00
|
|
|
do_call('yubikey.controller.set_password', [password, passwordKey],
|
|
|
|
function () {
|
|
|
|
validate(password)
|
|
|
|
})
|
2017-02-10 16:01:49 +03:00
|
|
|
}
|
|
|
|
|
2017-01-31 18:17:10 +03:00
|
|
|
function handleCredentials(creds) {
|
2017-01-31 11:57:44 +03:00
|
|
|
var result = []
|
2017-01-31 18:17:10 +03:00
|
|
|
var minExpiration = (Date.now() / 1000) + 10000
|
2017-01-31 11:57:44 +03:00
|
|
|
for (var i = 0; i < creds.length; i++) {
|
2017-02-01 18:27:45 +03:00
|
|
|
var cred = creds[i]
|
2017-02-03 15:58:22 +03:00
|
|
|
// Update min expiration
|
2017-01-31 18:17:10 +03:00
|
|
|
if (cred.expiration && cred.expiration < minExpiration) {
|
|
|
|
minExpiration = cred.expiration
|
|
|
|
}
|
2017-02-03 15:58:22 +03:00
|
|
|
// Touch credentials should only be replaced by user
|
|
|
|
if (credentialExists(cred.name) && cred.touch) {
|
|
|
|
result.push(getCredential(cred.name))
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
// HOTP credentials should only be replaced by user
|
|
|
|
if (credentialExists(cred.name) && cred.oath_type === 'hotp') {
|
|
|
|
result.push(getCredential(cred.name))
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
// TOTP credentials should be updated
|
2017-01-31 11:57:44 +03:00
|
|
|
result.push(cred)
|
|
|
|
}
|
2017-01-31 18:17:10 +03:00
|
|
|
nextRefresh = minExpiration
|
|
|
|
credentials = result
|
2017-01-31 11:57:44 +03:00
|
|
|
}
|
|
|
|
|
2017-02-03 15:58:22 +03:00
|
|
|
function getCredential(name) {
|
|
|
|
for (var i = 0; i < credentials.length; i++) {
|
|
|
|
if (credentials[i].name === name) {
|
|
|
|
return credentials[i]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function credentialExists(name) {
|
|
|
|
if (credentials != null) {
|
|
|
|
for (var i = 0; i < credentials.length; i++) {
|
|
|
|
if (credentials[i].name === name) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2017-02-07 16:17:54 +03:00
|
|
|
function calculate(credential) {
|
|
|
|
var now = Math.floor(Date.now() / 1000)
|
2017-02-16 16:14:14 +03:00
|
|
|
do_call('yubikey.controller.calculate', [credential, now, passwordKey],
|
|
|
|
updateCredential)
|
2017-02-07 16:17:54 +03:00
|
|
|
}
|
|
|
|
|
2017-02-23 15:51:44 +03:00
|
|
|
function calculateSlotMode(slot, digits) {
|
|
|
|
var now = Math.floor(Date.now() / 1000)
|
|
|
|
do_call('yubikey.controller.calculate_slot_mode', [slot, digits, now],
|
|
|
|
updateCredential)
|
|
|
|
}
|
|
|
|
|
2017-02-07 16:17:54 +03:00
|
|
|
function updateCredential(cred) {
|
|
|
|
var result = []
|
|
|
|
for (var i = 0; i < credentials.length; i++) {
|
|
|
|
if (credentials[i].name === cred.name) {
|
|
|
|
result.push(cred)
|
|
|
|
} else {
|
|
|
|
result.push(credentials[i])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
credentials = result
|
|
|
|
}
|
|
|
|
|
2017-02-16 16:14:14 +03:00
|
|
|
function addCredential(name, key, oathType, digits, algorithm, touch, cb) {
|
2017-02-03 14:24:41 +03:00
|
|
|
do_call('yubikey.controller.add_credential',
|
2017-02-16 16:14:14 +03:00
|
|
|
[name, key, oathType, digits, algorithm, touch, passwordKey],
|
|
|
|
cb)
|
2017-02-03 14:24:41 +03:00
|
|
|
}
|
|
|
|
|
2017-02-03 18:23:28 +03:00
|
|
|
function deleteCredential(credential) {
|
2017-02-16 16:14:14 +03:00
|
|
|
do_call('yubikey.controller.delete_credential',
|
|
|
|
[credential, passwordKey])
|
2017-01-27 15:55:38 +03:00
|
|
|
}
|
2017-02-14 15:12:24 +03:00
|
|
|
|
2017-02-16 16:14:14 +03:00
|
|
|
function parseQr(screenShots, cb) {
|
2017-02-15 17:00:30 +03:00
|
|
|
do_call('yubikey.controller.parse_qr', [screenShots], cb)
|
2017-02-14 15:12:24 +03:00
|
|
|
}
|
2017-02-17 10:52:34 +03:00
|
|
|
|
|
|
|
function reset() {
|
|
|
|
do_call('yubikey.controller.reset', [])
|
|
|
|
}
|
2017-01-27 15:55:38 +03:00
|
|
|
}
|