You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
session-desktop/ts/opengroup/utils/OpenGroupUtils.ts

116 lines
3.9 KiB
TypeScript

import { default as insecureNodeFetch } from 'node-fetch';
import { sendViaOnion } from '../../session/onions/onionSend';
/**
* Tries to establish a connection with the specified open group url.
*
* This will try to do an onion routing call if the `useFileOnionRequests` feature flag is set,
* or call directly insecureNodeFetch if it's not.
*
* Returns
* * true if useFileOnionRequests is false and no exception where thrown by insecureNodeFetch
* * true if useFileOnionRequests is true and we established a connection to the server with onion routing
* * false otherwise
*
*/
export const validOpenGroupServer = async (serverUrl: string) => {
// test to make sure it's online (and maybe has a valid SSL cert)
try {
const url = new URL(serverUrl);
if (!window.lokiFeatureFlags.useFileOnionRequests) {
// we are not running with onion request
// this is an insecure insecureNodeFetch. It will expose the user ip to the serverUrl (not onion routed)
window.log.info(`insecureNodeFetch => plaintext for ${url.toString()}`);
// we probably have to check the response here
await insecureNodeFetch(serverUrl);
return true;
}
// This MUST be an onion routing call, no nodeFetch calls below here.
/**
* this is safe (as long as node's in your trust model)
*
* First, we need to fetch the open group public key of this open group.
* The fileserver have all the open groups public keys.
* We need the open group public key because for onion routing we will need to encode
* our request with it.
* We can just ask the file-server to get the one for the open group we are trying to add.
*/
const result = await window.tokenlessFileServerAdnAPI.serverRequest(
`loki/v1/getOpenGroupKey/${url.hostname}`
);
if (result.response.meta.code === 200) {
// we got the public key of the server we are trying to add.
// decode it.
const obj = JSON.parse(result.response.data);
const pubKey = window.dcodeIO.ByteBuffer.wrap(
obj.data,
'base64'
).toArrayBuffer();
// verify we can make an onion routed call to that open group with the decoded public key
// get around the FILESERVER_HOSTS filter by not using serverRequest
const res = await sendViaOnion(
pubKey,
url,
{ method: 'GET' },
{ noJson: true }
);
if (res.result && res.result.status === 200) {
window.log.info(
`loki_public_chat::validOpenGroupServer - onion routing enabled on ${url.toString()}`
);
// save pubkey for use...
window.lokiPublicChatAPI.openGroupPubKeys[serverUrl] = pubKey;
return true;
}
// return here, just so we are sure adding some code below won't do a nodeFetch fallback
return false;
} else if (result.response.meta.code !== 404) {
// unknown error code
window.log.warn(
'loki_public_chat::validOpenGroupServer - unknown error code',
result.response.meta
);
}
return false;
} catch (e) {
window.log.warn(
`loki_public_chat::validOpenGroupServer - failing to create ${serverUrl}`,
e.code,
e.message
);
// bail out if not valid enough
}
return false;
};
/**
* Prefix server with https:// if it's not already prefixed with http or https.
*/
export function prefixify(server: string, hasSSL: boolean = true): string {
const hasPrefix = server.match('^https?://');
if (hasPrefix) {
return server;
}
return `http${hasSSL ? 's' : ''}://${server}`;
}
/**
* No sql access. Just how our open groupv2 url looks like
* @returns `publicChat:${roomId}@${serverUrl}`
*/
export function getOpenGroupV2ConversationId(
serverUrl: string,
roomId: string
) {
if (roomId.length < 2) {
throw new Error('Invalid roomId: too short');
}
return `publicChat:${roomId}@${serverUrl}`;
}