Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions extension/js/common/api/attester.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ export class Attester extends Api {
}

public lookupEmail = async (email: string): Promise<PubkeySearchResult> => {
if (!this.rules.canLookupThisRecipientOnAttester(email)) {
console.info(`Skipping attester lookup of ${email} because attester search on this domain is disabled.`);
return { pubkey: null, pgpClient: null }; // tslint:disable-line:no-null-keyword
}
try {
const r = await this.pubCall(`pub/${email}`);
// when requested from the content script, `getResponseHeader` will be missing because it's not a real XMLHttpRequest we are getting back
Expand Down
5 changes: 5 additions & 0 deletions extension/js/common/rules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ type DomainRules$flag = 'NO_PRV_CREATE' | 'NO_PRV_BACKUP' |
export type DomainRules = {
flags: DomainRules$flag[],
custom_keyserver_url?: string,
disallow_attester_search_for_domains?: string[],
};

export class Rules {
Expand Down Expand Up @@ -56,4 +57,8 @@ export class Rules {
return !this.domainRules.flags.includes('NO_ATTESTER_SUBMIT');
}

public canLookupThisRecipientOnAttester = (emailAddr: string) => {
return !(this.domainRules.disallow_attester_search_for_domains || []).includes(emailAddr.split('@')[1] || 'NONE');
}

}
15 changes: 8 additions & 7 deletions test/source/mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@ import { Config } from './util';
import { opgp } from './core/pgp';
import { startAllApisMock } from './mock/all-apis-mock';

export const acctsWithoutMockData = [
'flowcrypt.test.key.multibackup@gmail.com',
'has.pub@org-rules-test.flowcrypt.com',
'no.pub@org-rules-test.flowcrypt.com',
'user@no-submit-org-rule.flowcrypt.com',
'user@no-search-domains-org-rule.flowcrypt.com',
];

export const mock = async (logger: (line: string) => void) => {
const acctsWithoutMockData = [
'flowcrypt.test.key.multibackup@gmail.com',
'has.pub@org-rules-test.flowcrypt.com',
'no.pub@org-rules-test.flowcrypt.com',
'user@no-submit-org-rule.flowcrypt.com',
'user@no-search-domains-org-rule.flowcrypt.com',
];
const start = Date.now();
await Promise.all(Config.secrets.auth.google.map(a => a.email).map(async email => { // load and decrypt mock data if missing
if (acctsWithoutMockData.includes(email)) {
Expand Down
3 changes: 3 additions & 0 deletions test/source/mock/backend/backend-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ export class BackendData {
if (domain === 'no-submit-org-rule.flowcrypt.com') {
return { "flags": ["NO_ATTESTER_SUBMIT"] };
}
if (domain === 'no-search-domains-org-rule.flowcrypt.com') {
return { "flags": [], "disallow_attester_search_for_domains": ["flowcrypt.com"] };
}
return { 'flags': [] };
}

Expand Down
7 changes: 6 additions & 1 deletion test/source/mock/google/google-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { AddressObject, ParsedMail, StructuredHeader } from 'mailparser';
import UserMessages from '../../../samples/mock-data';
import { Util } from '../../util/index';
import { readFileSync } from 'fs';
import { acctsWithoutMockData } from '../../mock';

type GmailMsg$header = { name: string, value: string };
type GmailMsg$payload$body = { attachmentId?: string, size: number, data?: string };
Expand Down Expand Up @@ -106,7 +107,11 @@ export class GoogleData {

constructor(private acct: string) {
if (!DATA[acct]) {
DATA[acct] = JSON.parse(readFileSync(`./test/samples/${acct.replace(/[^a-z0-9]+/g, '')}.json`, { encoding: 'UTF-8' })) as AcctDataFile;
if (acctsWithoutMockData.includes(acct)) {
DATA[acct] = { drafts: [], messages: [], attachments: {}, labels: [] };
} else {
DATA[acct] = JSON.parse(readFileSync(`./test/samples/${acct.replace(/[^a-z0-9]+/g, '')}.json`, { encoding: 'UTF-8' })) as AcctDataFile;
}
if (UserMessages[acct]) {
DATA[acct].drafts = UserMessages[acct].drafts;
DATA[acct].messages.push(...UserMessages[acct].messages);
Expand Down
13 changes: 13 additions & 0 deletions test/source/tests/tests/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { SetupPageRecipe } from '../page-recipe/setup-page-recipe';
import { TestWithBrowser } from '../../test';
import { expect } from 'chai';
import { SettingsPageRecipe } from '../page-recipe/settings-page-recipe';
import { ComposePageRecipe } from '../page-recipe/compose-page-recipe';

// tslint:disable:no-blank-lines-func

Expand Down Expand Up @@ -158,6 +159,18 @@ export const defineSetupTests = (testVariant: TestVariant, testWithBrowser: Test
await attesterFrame.waitAndRespondToModal('error', 'confirm', 'Disallowed by your organisation rules');
}));

ava.default('user@no-search-domains-org-rule.flowcrypt.com - do not search attester for recipients on particular domains', testWithBrowser(undefined, async (t, browser) => {
// disallowed searching attester for pubkeys on "flowcrypt.com" domain
// below we search for human@flowcrypt.com which normally has pubkey on attester, but none should be found due to the rule
const acct = 'user@no-search-domains-org-rule.flowcrypt.com';
const settingsPage = await BrowserRecipe.openSettingsLoginApprove(t, browser, acct);
await SetupPageRecipe.manualEnter(settingsPage, 'flowcrypt.test.key.used.pgp');
const composePage = await ComposePageRecipe.openStandalone(t, browser, acct);
await ComposePageRecipe.fillMsg(composePage, { to: 'human@flowcrypt.com' }, 'normally has pubkey but should show none');
await composePage.waitForContent('.email_address.no_pgp', 'human@flowcrypt.com');
await composePage.waitAll('@input-password');
}));

}

};