Add U2F support

This commit is contained in:
Jonas Lochmann
2022-09-22 08:47:06 +02:00
parent 04aa2ce517
commit 613776cbf9
64 changed files with 2501 additions and 134 deletions
@@ -1,6 +1,6 @@
/*
* server component for the TimeLimit App
* Copyright (C) 2019 - 2020 Jonas Lochmann
* Copyright (C) 2019 - 2022 Jonas Lochmann
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
@@ -25,6 +25,7 @@ export interface FamilyEntry {
userListVersion: string
hasFullVersion: boolean
fullVersionUntil: string
u2fKeysVersion: string
}
export async function getFamilyEntry ({ database, familyId, transaction }: {
@@ -40,7 +41,8 @@ export async function getFamilyEntry ({ database, familyId, transaction }: {
'deviceListVersion',
'userListVersion',
'hasFullVersion',
'fullVersionUntil'
'fullVersionUntil',
'u2fKeysVersion'
],
transaction
})
@@ -54,6 +56,7 @@ export async function getFamilyEntry ({ database, familyId, transaction }: {
deviceListVersion: familyEntryUnsafe.deviceListVersion,
userListVersion: familyEntryUnsafe.userListVersion,
hasFullVersion: familyEntryUnsafe.hasFullVersion,
fullVersionUntil: familyEntryUnsafe.fullVersionUntil
fullVersionUntil: familyEntryUnsafe.fullVersionUntil,
u2fKeysVersion: familyEntryUnsafe.u2fKeysVersion
}
}
@@ -34,6 +34,7 @@ import { getFamilyEntry } from './family-entry'
import { getUserList } from './user-list'
import { getKeyRequests } from './key-requests'
import { getKeyResponses } from './key-responses'
import { getU2f } from './u2f'
export const generateServerDataStatus = async ({
database, clientStatus, familyId, deviceId, transaction, eventHandler
@@ -51,13 +52,14 @@ export const generateServerDataStatus = async ({
const doesClientSupportTasks = clientLevel >= 3
const doesClientSupportCryptoApps = clientLevel >= 4
const doesClientSupportDh = clientLevel >= 5
const doesClientSupportU2f = clientLevel >= 6
const result: ServerDataStatus = {
fullVersion: config.alwaysPro ? 1 : (
familyEntry.hasFullVersion ? parseInt(familyEntry.fullVersionUntil, 10) : 0
),
message: await getStatusMessage({ database, transaction }) || undefined,
apiLevel: 5
apiLevel: 6
}
if (familyEntry.deviceListVersion !== clientStatus.devices) {
@@ -152,5 +154,14 @@ export const generateServerDataStatus = async ({
}) || undefined
}
if (doesClientSupportU2f) {
result.u2f = await getU2f({
database,
transaction,
familyEntry,
lastVersionId: clientStatus.u2f || null
}) || undefined
}
return result
}
@@ -0,0 +1,49 @@
/*
* server component for the TimeLimit App
* Copyright (C) 2019 - 2022 Jonas Lochmann
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import * as Sequelize from 'sequelize'
import { Database } from '../../../database'
import { U2fData } from '../../../object/serverdatastatus'
import { FamilyEntry } from './family-entry'
export async function getU2f ({
database, transaction, familyEntry, lastVersionId
}: {
database: Database
transaction: Sequelize.Transaction
familyEntry: FamilyEntry
lastVersionId: string | null
}): Promise<U2fData | null> {
if (lastVersionId === familyEntry.u2fKeysVersion) return null
const savedData = await database.u2fKey.findAll({
where: {
familyId: familyEntry.familyId
},
transaction
})
return {
v: familyEntry.u2fKeysVersion,
d: savedData.map((item) => ({
u: item.userId,
a: parseInt(item.addedAt, 10),
h: item.keyHandle.toString('base64'),
p: item.publicKey.toString('base64')
}))
}
}