1password 1pif: import password history (#33)

* 1password 1pif import password history

* 1password 1pif importer: process windows password history

* linter fix
This commit is contained in:
Robert Wachs 2019-03-24 15:50:49 +01:00 committed by Kyle Spearrin
parent df429fe178
commit 8ed27eeeec
3 changed files with 120 additions and 1 deletions

View File

@ -49,6 +49,12 @@ const TestData: string = '***aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee***\n' +
name: 'admin_console',
},
],
passwordHistory: [
{
value: 'old-password',
time: 1447791421,
},
],
},
URLs: [
{
@ -61,6 +67,76 @@ const TestData: string = '***aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee***\n' +
typeName: 'webforms.WebForm',
});
const WindowsTestData = JSON.stringify({
category: '001',
created: 1544823719,
hmac: 'NtyBmTTPOb88HV3JUKPx1xl/vcMhac9kvCfe/NtszY0=',
k: 'XC/z20QveYCoV8xQ4tCJZZp/uum77xLkMSMEhlUULndryXgSmkG+VBtkW7AfuerfKc8Rtu43a4Sd078j7XfZTcwUCEKtBECUTDNbEgv4+4hoFVk1EzZgEUy/0bW1Ap+jNLmmdSU9h74+REu6pdxsvQ==',
tx: 1553395669,
updated: 1553395669,
uuid: '528AB076FB5F4FBF960884B8E01619AC',
overview: {
title: 'Google',
URLs: [
{
u: 'google.com',
},
],
url: 'google.com',
ps: 26,
ainfo: 'googluser',
},
details: {
passwordHistory: [
{
value: 'oldpass2',
time: 1553394449,
},
{
value: 'oldpass1',
time: 1553394457,
},
],
fields: [
{
type: 'T',
id: 'username',
name: 'username',
value: 'googluser',
designation: 'username',
},
{
type: 'P',
id: 'password',
name: 'password',
value: '12345678901',
designation: 'password',
},
],
notesPlain: 'This is a note\r\n\r\nline1\r\nline2',
sections: [
{
title: 'test',
name: '1214FD88CD30405D9EED14BEB4D61B60',
fields: [
{
k: 'string',
n: '6CC3BD77482D4559A4B8BB2D360F821B',
v: 'fgfg',
t: 'fgggf',
},
{
k: 'concealed',
n: '5CFE7BCAA1DF4578BBF7EB508959BFF3',
v: 'dfgdfgfdg',
t: 'pwfield',
},
],
},
],
},
});
const IdentityTestData = JSON.stringify({
uuid: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
updatedAt: 1553365894,
@ -393,4 +469,30 @@ describe('1Password 1Pif Importer', () => {
// remaining fields as custom fields
expect(cipher.fields.length).toEqual(6);
});
it('should create password history', async () => {
const importer = new Importer();
const result = importer.parse(TestData);
const cipher = result.ciphers.shift();
expect(cipher.passwordHistory.length).toEqual(1);
const ph = cipher.passwordHistory.shift();
expect(ph.password).toEqual('old-password');
expect(ph.lastUsedDate.toISOString()).toEqual('2015-11-17T20:17:01.000Z');
});
it('should create password history from windows 1pif format', async () => {
const importer = new Importer();
const result = importer.parse(WindowsTestData);
const cipher = result.ciphers.shift();
expect(cipher.passwordHistory.length).toEqual(2);
let ph = cipher.passwordHistory.shift();
expect(ph.password).toEqual('oldpass2');
expect(ph.lastUsedDate.toISOString()).toEqual('2019-03-24T02:27:29.000Z');
ph = cipher.passwordHistory.shift();
expect(ph.password).toEqual('oldpass1');
expect(ph.lastUsedDate.toISOString()).toEqual('2019-03-24T02:27:37.000Z');
});
});

View File

@ -1,5 +1,5 @@
import { throttle } from '../../../src/misc/throttle';
import { sequentialize } from '../../../src/misc/sequentialize';
import { throttle } from '../../../src/misc/throttle';
describe('throttle decorator', () => {
it('should call the function once at a time', async () => {

View File

@ -6,6 +6,7 @@ import { ImportResult } from '../models/domain/importResult';
import { CardView } from '../models/view/cardView';
import { CipherView } from '../models/view/cipherView';
import { IdentityView } from '../models/view/identityView';
import { PasswordHistoryView } from '../models/view/passwordHistoryView';
import { SecureNoteView } from '../models/view/secureNoteView';
import { CipherType } from '../enums/cipherType';
@ -77,9 +78,22 @@ export class OnePassword1PifImporter extends BaseImporter implements Importer {
}
});
}
if (item.details.passwordHistory != null) {
this.processPasswordHistory(item.details.passwordHistory, cipher);
}
}
}
private processPasswordHistory(items: any[], cipher: CipherView) {
cipher.passwordHistory = cipher.passwordHistory || [];
items.forEach((entry: any) => {
const phv = new PasswordHistoryView();
phv.password = entry.value;
phv.lastUsedDate = new Date(entry.time * 1000);
cipher.passwordHistory.push(phv);
});
}
private processStandardItem(item: any, cipher: CipherView) {
cipher.favorite = item.openContents && item.openContents.faveIndex ? true : false;
cipher.name = this.getValueOrDefault(item.title);
@ -128,6 +142,9 @@ export class OnePassword1PifImporter extends BaseImporter implements Importer {
}
});
}
if (item.secureContents.passwordHistory != null) {
this.processPasswordHistory(item.secureContents.passwordHistory, cipher);
}
}
}