2019-03-23 17:27:50 +01:00
|
|
|
import { FieldType } from '../../../src/enums/fieldType';
|
|
|
|
import { OnePassword1PifImporter as Importer } from '../../../src/importers/onepassword1PifImporter';
|
|
|
|
|
|
|
|
import { Utils } from '../../../src/misc/utils';
|
|
|
|
|
|
|
|
if (Utils.isNode) {
|
|
|
|
// Polyfills
|
|
|
|
// tslint:disable-next-line
|
|
|
|
const jsdom: any = require('jsdom');
|
|
|
|
(global as any).DOMParser = new jsdom.JSDOM().window.DOMParser;
|
|
|
|
}
|
|
|
|
|
2019-03-23 17:31:52 +01:00
|
|
|
const TestData: string = '***aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee***\n' +
|
2019-03-23 17:27:50 +01:00
|
|
|
JSON.stringify({
|
2019-03-25 14:10:33 +01:00
|
|
|
uuid: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
|
|
|
|
updatedAt: 1486071244,
|
|
|
|
securityLevel: 'SL5',
|
|
|
|
contentsHash: 'aaaaaaaa',
|
|
|
|
title: 'Imported Entry',
|
|
|
|
location: 'https://www.google.com',
|
|
|
|
secureContents: {
|
|
|
|
fields: [
|
|
|
|
{
|
|
|
|
value: 'user@test.net',
|
|
|
|
id: 'email-input',
|
|
|
|
name: 'email',
|
|
|
|
type: 'T',
|
|
|
|
designation: 'username',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
value: 'myservicepassword',
|
|
|
|
id: 'password-input',
|
|
|
|
name: 'password',
|
|
|
|
type: 'P',
|
|
|
|
designation: 'password',
|
|
|
|
},
|
|
|
|
],
|
|
|
|
sections: [
|
|
|
|
{
|
|
|
|
fields: [
|
|
|
|
{
|
|
|
|
k: 'concealed',
|
|
|
|
n: 'AAAAAAAAAAAABBBBBBBBBBBCCCCCCCCC',
|
|
|
|
v: 'console-password-123',
|
|
|
|
t: 'console password',
|
|
|
|
},
|
|
|
|
],
|
|
|
|
title: 'Admin Console',
|
|
|
|
name: 'admin_console',
|
|
|
|
},
|
|
|
|
],
|
|
|
|
passwordHistory: [
|
|
|
|
{
|
|
|
|
value: 'old-password',
|
|
|
|
time: 1447791421,
|
|
|
|
},
|
|
|
|
],
|
|
|
|
},
|
|
|
|
URLs: [
|
2019-03-23 17:27:50 +01:00
|
|
|
{
|
2019-03-25 14:10:33 +01:00
|
|
|
label: 'website',
|
|
|
|
url: 'https://www.google.com',
|
2019-03-23 17:27:50 +01:00
|
|
|
},
|
|
|
|
],
|
2019-03-25 14:10:33 +01:00
|
|
|
txTimestamp: 1508941334,
|
|
|
|
createdAt: 1390426636,
|
|
|
|
typeName: 'webforms.WebForm',
|
|
|
|
});
|
2019-03-23 17:27:50 +01:00
|
|
|
|
2019-03-25 14:10:33 +01:00
|
|
|
const WindowsOpVaultTestData = JSON.stringify({
|
2019-03-24 15:50:49 +01:00
|
|
|
category: '001',
|
|
|
|
created: 1544823719,
|
|
|
|
hmac: 'NtyBmTTPOb88HV3JUKPx1xl/vcMhac9kvCfe/NtszY0=',
|
2019-03-27 19:46:34 +01:00
|
|
|
k: '**REMOVED LONG LINE FOR LINTER** -Kyle',
|
2019-03-24 15:50:49 +01:00
|
|
|
tx: 1553395669,
|
|
|
|
updated: 1553395669,
|
|
|
|
uuid: '528AB076FB5F4FBF960884B8E01619AC',
|
|
|
|
overview: {
|
|
|
|
title: 'Google',
|
|
|
|
URLs: [
|
|
|
|
{
|
|
|
|
u: 'google.com',
|
|
|
|
},
|
|
|
|
],
|
|
|
|
url: 'google.com',
|
|
|
|
ps: 26,
|
|
|
|
ainfo: 'googluser',
|
|
|
|
},
|
|
|
|
details: {
|
|
|
|
passwordHistory: [
|
|
|
|
{
|
2019-03-25 14:10:33 +01:00
|
|
|
value: 'oldpass1',
|
2019-03-24 15:50:49 +01:00
|
|
|
time: 1553394449,
|
|
|
|
},
|
|
|
|
{
|
2019-03-25 14:10:33 +01:00
|
|
|
value: 'oldpass2',
|
2019-03-24 15:50:49 +01:00
|
|
|
time: 1553394457,
|
|
|
|
},
|
2019-03-25 14:10:33 +01:00
|
|
|
{
|
|
|
|
value: 'oldpass3',
|
|
|
|
time: 1553394458,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
value: 'oldpass4',
|
|
|
|
time: 1553394459,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
value: 'oldpass5',
|
|
|
|
time: 1553394460,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
value: 'oldpass6',
|
|
|
|
time: 1553394461,
|
|
|
|
},
|
2019-03-24 15:50:49 +01:00
|
|
|
],
|
|
|
|
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',
|
|
|
|
},
|
|
|
|
],
|
|
|
|
},
|
|
|
|
],
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
2019-03-24 03:21:43 +01:00
|
|
|
const IdentityTestData = JSON.stringify({
|
|
|
|
uuid: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
|
|
|
|
updatedAt: 1553365894,
|
|
|
|
securityLevel: 'SL5',
|
|
|
|
contentsHash: 'eeeeeeee',
|
|
|
|
title: 'Test Identity',
|
|
|
|
secureContents: {
|
|
|
|
lastname: 'Fritzenberger',
|
|
|
|
zip: '223344',
|
|
|
|
birthdate_dd: '11',
|
|
|
|
homephone: '+49 333 222 111',
|
|
|
|
company: 'Web Inc.',
|
|
|
|
firstname: 'Frank',
|
|
|
|
birthdate_mm: '3',
|
|
|
|
country: 'de',
|
|
|
|
sex: 'male',
|
|
|
|
sections: [
|
|
|
|
{
|
|
|
|
fields: [
|
|
|
|
{
|
|
|
|
k: 'string',
|
|
|
|
inputTraits: {
|
|
|
|
autocapitalization: 'Words',
|
|
|
|
},
|
|
|
|
n: 'firstname',
|
|
|
|
v: 'Frank',
|
|
|
|
a: {
|
|
|
|
guarded: 'yes',
|
|
|
|
},
|
|
|
|
t: 'first name',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
k: 'string',
|
|
|
|
inputTraits: {
|
|
|
|
autocapitalization: 'Words',
|
|
|
|
},
|
|
|
|
n: 'initial',
|
|
|
|
v: 'MD',
|
|
|
|
a: {
|
|
|
|
guarded: 'yes',
|
|
|
|
},
|
|
|
|
t: 'initial',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
k: 'string',
|
|
|
|
inputTraits: {
|
|
|
|
autocapitalization: 'Words',
|
|
|
|
},
|
|
|
|
n: 'lastname',
|
|
|
|
v: 'Fritzenberger',
|
|
|
|
a: {
|
|
|
|
guarded: 'yes',
|
|
|
|
},
|
|
|
|
t: 'last name',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
k: 'menu',
|
|
|
|
v: 'male',
|
|
|
|
n: 'sex',
|
|
|
|
a: {
|
|
|
|
guarded: 'yes',
|
|
|
|
},
|
|
|
|
t: 'sex',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
k: 'date',
|
|
|
|
v: 1552305660,
|
|
|
|
n: 'birthdate',
|
|
|
|
a: {
|
|
|
|
guarded: 'yes',
|
|
|
|
},
|
|
|
|
t: 'birth date',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
k: 'string',
|
|
|
|
inputTraits: {
|
|
|
|
autocapitalization: 'Words',
|
|
|
|
},
|
|
|
|
n: 'occupation',
|
|
|
|
v: 'Engineer',
|
|
|
|
a: {
|
|
|
|
guarded: 'yes',
|
|
|
|
},
|
|
|
|
t: 'occupation',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
k: 'string',
|
|
|
|
inputTraits: {
|
|
|
|
autocapitalization: 'Words',
|
|
|
|
},
|
|
|
|
n: 'company',
|
|
|
|
v: 'Web Inc.',
|
|
|
|
a: {
|
|
|
|
guarded: 'yes',
|
|
|
|
},
|
|
|
|
t: 'company',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
k: 'string',
|
|
|
|
inputTraits: {
|
|
|
|
autocapitalization: 'Words',
|
|
|
|
},
|
|
|
|
n: 'department',
|
|
|
|
v: 'IT',
|
|
|
|
a: {
|
|
|
|
guarded: 'yes',
|
|
|
|
},
|
|
|
|
t: 'department',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
k: 'string',
|
|
|
|
inputTraits: {
|
|
|
|
autocapitalization: 'Words',
|
|
|
|
},
|
|
|
|
n: 'jobtitle',
|
|
|
|
v: 'Developer',
|
|
|
|
a: {
|
|
|
|
guarded: 'yes',
|
|
|
|
},
|
|
|
|
t: 'job title',
|
|
|
|
},
|
|
|
|
],
|
|
|
|
title: 'Identification',
|
|
|
|
name: 'name',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
fields: [
|
|
|
|
{
|
|
|
|
k: 'address',
|
|
|
|
inputTraits: {
|
|
|
|
autocapitalization: 'Sentences',
|
|
|
|
},
|
|
|
|
n: 'address',
|
|
|
|
v: {
|
|
|
|
street: 'Mainstreet 1',
|
|
|
|
city: 'Berlin',
|
|
|
|
country: 'de',
|
|
|
|
zip: '223344',
|
|
|
|
},
|
|
|
|
a: {
|
|
|
|
guarded: 'yes',
|
|
|
|
},
|
|
|
|
t: 'address',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
k: 'phone',
|
|
|
|
v: '+49 001 222 333 44',
|
|
|
|
n: 'defphone',
|
|
|
|
a: {
|
|
|
|
guarded: 'yes',
|
|
|
|
},
|
|
|
|
t: 'default phone',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
k: 'phone',
|
|
|
|
v: '+49 333 222 111',
|
|
|
|
n: 'homephone',
|
|
|
|
a: {
|
|
|
|
guarded: 'yes',
|
|
|
|
},
|
|
|
|
t: 'home',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
k: 'phone',
|
|
|
|
n: 'cellphone',
|
|
|
|
a: {
|
|
|
|
guarded: 'yes',
|
|
|
|
},
|
|
|
|
t: 'mobile',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
k: 'phone',
|
|
|
|
n: 'busphone',
|
|
|
|
a: {
|
|
|
|
guarded: 'yes',
|
|
|
|
},
|
|
|
|
t: 'business',
|
|
|
|
},
|
|
|
|
],
|
|
|
|
title: 'Address',
|
|
|
|
name: 'address',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
fields: [
|
|
|
|
{
|
|
|
|
k: 'string',
|
|
|
|
n: 'username',
|
|
|
|
a: {
|
|
|
|
guarded: 'yes',
|
|
|
|
},
|
|
|
|
t: 'username',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
k: 'string',
|
|
|
|
n: 'reminderq',
|
|
|
|
t: 'reminder question',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
k: 'string',
|
|
|
|
n: 'remindera',
|
|
|
|
t: 'reminder answer',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
k: 'string',
|
|
|
|
inputTraits: {
|
|
|
|
keyboard: 'EmailAddress',
|
|
|
|
},
|
|
|
|
n: 'email',
|
|
|
|
v: 'test@web.de',
|
|
|
|
a: {
|
|
|
|
guarded: 'yes',
|
|
|
|
},
|
|
|
|
t: 'email',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
k: 'string',
|
|
|
|
n: 'website',
|
|
|
|
inputTraits: {
|
|
|
|
keyboard: 'URL',
|
|
|
|
},
|
|
|
|
t: 'website',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
k: 'string',
|
|
|
|
n: 'icq',
|
|
|
|
t: 'ICQ',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
k: 'string',
|
|
|
|
n: 'skype',
|
|
|
|
t: 'skype',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
k: 'string',
|
|
|
|
n: 'aim',
|
|
|
|
t: 'AOL/AIM',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
k: 'string',
|
|
|
|
n: 'yahoo',
|
|
|
|
t: 'Yahoo',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
k: 'string',
|
|
|
|
n: 'msn',
|
|
|
|
t: 'MSN',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
k: 'string',
|
|
|
|
n: 'forumsig',
|
|
|
|
t: 'forum signature',
|
|
|
|
},
|
|
|
|
],
|
|
|
|
title: 'Internet Details',
|
|
|
|
name: 'internet',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
title: 'Related Items',
|
|
|
|
name: 'linked items',
|
|
|
|
},
|
|
|
|
],
|
|
|
|
initial: 'MD',
|
|
|
|
address1: 'Mainstreet 1',
|
|
|
|
city: 'Berlin',
|
|
|
|
jobtitle: 'Developer',
|
|
|
|
occupation: 'Engineer',
|
|
|
|
department: 'IT',
|
|
|
|
email: 'test@web.de',
|
|
|
|
birthdate_yy: '2019',
|
|
|
|
homephone_local: '+49 333 222 111',
|
|
|
|
defphone_local: '+49 001 222 333 44',
|
|
|
|
defphone: '+49 001 222 333 44',
|
|
|
|
},
|
|
|
|
txTimestamp: 1553365894,
|
|
|
|
createdAt: 1553364679,
|
|
|
|
typeName: 'identities.Identity',
|
|
|
|
});
|
|
|
|
|
2019-03-23 17:27:50 +01:00
|
|
|
describe('1Password 1Pif Importer', () => {
|
|
|
|
it('should parse data', async () => {
|
|
|
|
const importer = new Importer();
|
|
|
|
const result = importer.parse(TestData);
|
|
|
|
expect(result != null).toBe(true);
|
|
|
|
|
|
|
|
const cipher = result.ciphers.shift();
|
|
|
|
expect(cipher.login.username).toEqual('user@test.net');
|
|
|
|
expect(cipher.login.password).toEqual('myservicepassword');
|
|
|
|
expect(cipher.login.uris.length).toEqual(1);
|
|
|
|
const uriView = cipher.login.uris.shift();
|
|
|
|
expect(uriView.uri).toEqual('https://www.google.com');
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should create concealed field as "hidden" type', async () => {
|
|
|
|
const importer = new Importer();
|
|
|
|
const result = importer.parse(TestData);
|
|
|
|
expect(result != null).toBe(true);
|
|
|
|
|
|
|
|
const ciphers = result.ciphers;
|
|
|
|
expect(ciphers.length).toEqual(1);
|
|
|
|
|
|
|
|
const cipher = ciphers.shift();
|
|
|
|
const fields = cipher.fields;
|
|
|
|
expect(fields.length).toEqual(1);
|
|
|
|
|
|
|
|
const field = fields.shift();
|
|
|
|
expect(field.name).toEqual('console password');
|
|
|
|
expect(field.value).toEqual('console-password-123');
|
|
|
|
expect(field.type).toEqual(FieldType.Hidden);
|
|
|
|
});
|
2019-03-24 03:21:43 +01:00
|
|
|
|
|
|
|
it('should create identity records', async () => {
|
|
|
|
const importer = new Importer();
|
|
|
|
const result = importer.parse(IdentityTestData);
|
|
|
|
expect(result != null).toBe(true);
|
|
|
|
const cipher = result.ciphers.shift();
|
|
|
|
expect(cipher.name).toEqual('Test Identity');
|
|
|
|
|
|
|
|
const identity = cipher.identity;
|
|
|
|
expect(identity.firstName).toEqual('Frank');
|
|
|
|
expect(identity.middleName).toEqual('MD');
|
|
|
|
expect(identity.lastName).toEqual('Fritzenberger');
|
|
|
|
expect(identity.company).toEqual('Web Inc.');
|
|
|
|
expect(identity.address1).toEqual('Mainstreet 1');
|
2019-03-24 03:49:22 +01:00
|
|
|
expect(identity.country).toEqual('DE');
|
2019-03-24 03:21:43 +01:00
|
|
|
expect(identity.city).toEqual('Berlin');
|
|
|
|
expect(identity.postalCode).toEqual('223344');
|
|
|
|
expect(identity.phone).toEqual('+49 001 222 333 44');
|
|
|
|
expect(identity.email).toEqual('test@web.de');
|
|
|
|
|
|
|
|
// remaining fields as custom fields
|
|
|
|
expect(cipher.fields.length).toEqual(6);
|
|
|
|
});
|
2019-03-24 15:50:49 +01:00
|
|
|
|
|
|
|
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');
|
|
|
|
});
|
|
|
|
|
2019-03-25 14:10:33 +01:00
|
|
|
it('should create password history from windows opvault 1pif format', async () => {
|
2019-03-24 15:50:49 +01:00
|
|
|
const importer = new Importer();
|
2019-03-25 14:10:33 +01:00
|
|
|
const result = importer.parse(WindowsOpVaultTestData);
|
2019-03-24 15:50:49 +01:00
|
|
|
const cipher = result.ciphers.shift();
|
|
|
|
|
2019-03-25 14:10:33 +01:00
|
|
|
expect(cipher.passwordHistory.length).toEqual(5);
|
2019-03-24 15:50:49 +01:00
|
|
|
let ph = cipher.passwordHistory.shift();
|
2019-03-25 14:10:33 +01:00
|
|
|
expect(ph.password).toEqual('oldpass6');
|
|
|
|
expect(ph.lastUsedDate.toISOString()).toEqual('2019-03-24T02:27:41.000Z');
|
|
|
|
ph = cipher.passwordHistory.shift();
|
|
|
|
expect(ph.password).toEqual('oldpass5');
|
|
|
|
expect(ph.lastUsedDate.toISOString()).toEqual('2019-03-24T02:27:40.000Z');
|
|
|
|
ph = cipher.passwordHistory.shift();
|
|
|
|
expect(ph.password).toEqual('oldpass4');
|
|
|
|
expect(ph.lastUsedDate.toISOString()).toEqual('2019-03-24T02:27:39.000Z');
|
2019-03-24 15:50:49 +01:00
|
|
|
ph = cipher.passwordHistory.shift();
|
2019-03-25 14:10:33 +01:00
|
|
|
expect(ph.password).toEqual('oldpass3');
|
|
|
|
expect(ph.lastUsedDate.toISOString()).toEqual('2019-03-24T02:27:38.000Z');
|
|
|
|
ph = cipher.passwordHistory.shift();
|
|
|
|
expect(ph.password).toEqual('oldpass2');
|
2019-03-24 15:50:49 +01:00
|
|
|
expect(ph.lastUsedDate.toISOString()).toEqual('2019-03-24T02:27:37.000Z');
|
|
|
|
});
|
2019-03-23 17:27:50 +01:00
|
|
|
});
|