Skip to content

Commit

Permalink
Merge pull request #1553 from Bilb/master
Browse files Browse the repository at this point in the history
Bump to v1.5.2
  • Loading branch information
Bilb authored Mar 24, 2021
2 parents 35321c2 + 77ce9ce commit 7bb5243
Show file tree
Hide file tree
Showing 19 changed files with 193 additions and 187 deletions.
1 change: 0 additions & 1 deletion app/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ if (environment === 'production') {
process.env.HOSTNAME = '';
process.env.ALLOW_CONFIG_MUTATIONS = '';
process.env.SUPPRESS_NO_CONFIG_WARNING = '';
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '';

// We could be running againt production but still be in dev mode, we need to handle that
if (!isDevelopment) {
Expand Down
7 changes: 4 additions & 3 deletions js/modules/debuglogs.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@
/* global window */

const FormData = require('form-data');
const fetch = require('node-fetch');
const insecureNodeFetch = require('node-fetch');

const BASE_URL = 'https://debuglogs.org';
const VERSION = window.getVersion();
const USER_AGENT = `Session ${VERSION}`;

// upload :: String -> Promise URL
exports.upload = async content => {
const signedForm = await fetch(BASE_URL, {
window.log.warn('insecureNodeFetch => upload debugLogs');
const signedForm = await insecureNodeFetch(BASE_URL, {
headers: {
'user-agent': USER_AGENT,
},
Expand Down Expand Up @@ -38,7 +39,7 @@ exports.upload = async content => {
filename: `session-desktop-debug-log-${VERSION}.txt`,
});

const result = await fetch(url, {
const result = await insecureNodeFetch(url, {
method: 'POST',
body: form,
});
Expand Down
39 changes: 15 additions & 24 deletions js/modules/loki_app_dot_net_api.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* global log, textsecure, libloki, Signal, Whisper,
clearTimeout, getMessageController, libsignal, StringView, window, _,
dcodeIO, Buffer, process */
const nodeFetch = require('node-fetch');
const insecureNodeFetch = require('node-fetch');
const { URL, URLSearchParams } = require('url');
const FormData = require('form-data');
const https = require('https');
Expand Down Expand Up @@ -253,7 +253,7 @@ const serverRequest = async (endpoint, options = {}) => {
let response;
let result;
let txtResponse;
let mode = 'nodeFetch';
let mode = 'insecureNodeFetch';
try {
const host = url.host.toLowerCase();
// log.info('host', host, FILESERVER_HOSTS);
Expand All @@ -268,7 +268,12 @@ const serverRequest = async (endpoint, options = {}) => {
fetchOptions,
options
));
} else if (window.lokiFeatureFlags.useFileOnionRequests && srvPubKey) {
} else if (window.lokiFeatureFlags.useFileOnionRequests) {
if (!srvPubKey) {
throw new Error(
'useFileOnionRequests=true but we do not have a server pubkey set.'
);
}
mode = 'sendViaOnionOG';
({ response, txtResponse, result } = await sendViaOnion(
srvPubKey,
Expand All @@ -277,13 +282,9 @@ const serverRequest = async (endpoint, options = {}) => {
options
));
} else {
// disable check for .loki
process.env.NODE_TLS_REJECT_UNAUTHORIZED = host.match(/\.loki$/i)
? '0'
: '1';
result = await nodeFetch(url, fetchOptions);
// always make sure this check is enabled
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '1';
// we end up here only if window.lokiFeatureFlags.useFileOnionRequests is false
log.info(`insecureNodeFetch => plaintext for ${url}`);
result = await insecureNodeFetch(url, fetchOptions);

txtResponse = await result.text();
// cloudflare timeouts (504s) will be html...
Expand Down Expand Up @@ -1395,23 +1396,13 @@ class LokiPublicChannelAPI {
// do we already have this image? no, then

// download a copy and save it
const imageData = await nodeFetch(avatarAbsUrl);
// eslint-disable-next-line no-inner-declarations
function toArrayBuffer(buf) {
const ab = new ArrayBuffer(buf.length);
const view = new Uint8Array(ab);
// eslint-disable-next-line no-plusplus
for (let i = 0; i < buf.length; i++) {
view[i] = buf[i];
}
return ab;
}
// eslint-enable-next-line no-inner-declarations
const imageData = await this.serverAPI.downloadAttachment(
avatarAbsUrl
);

const buffer = await imageData.buffer();
const newAttributes = await window.Signal.Types.Conversation.maybeUpdateAvatar(
this.conversation.attributes,
toArrayBuffer(buffer),
imageData,
{
writeNewAttachmentData,
deleteAttachmentData,
Expand Down
11 changes: 8 additions & 3 deletions js/modules/loki_primitives.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,14 @@ async function allowOnlyOneAtATime(name, process, timeout) {
try {
innerRetVal = await process();
} catch (e) {
log.error(
`loki_primitives:::allowOnlyOneAtATime - error ${e.code} ${e.message}`
);
if (typeof e === 'string') {
log.error(`loki_primitives:::allowOnlyOneAtATime - error ${e}`);
} else {
log.error(
`loki_primitives:::allowOnlyOneAtATime - error ${e.code} ${e.message}`
);
}

// clear timeout timer
if (timeout) {
if (timeoutTimer !== null) {
Expand Down
123 changes: 69 additions & 54 deletions js/modules/loki_public_chat_api.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,78 +2,93 @@
const EventEmitter = require('events');
const LokiAppDotNetAPI = require('./loki_app_dot_net_api');

const nodeFetch = require('node-fetch');

const insecureNodeFetch = require('node-fetch');

/**
* 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
*
*/
const validOpenGroupServer = async serverUrl => {
// test to make sure it's online (and maybe has a valid SSL cert)
try {
const url = new URL(serverUrl);

if (window.lokiFeatureFlags.useFileOnionRequests) {
// check for LSRPC
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)
log.info(`insecureNodeFetch => plaintext for ${url.toString()}`);

// this is safe (as long as node's in your trust model)
// because
const result = await window.tokenlessFileServerAdnAPI.serverRequest(
`loki/v1/getOpenGroupKey/${url.hostname}`
);
// 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) {
// supports it
const obj = JSON.parse(result.response.data);
const pubKey = dcodeIO.ByteBuffer.wrap(
obj.data,
'base64'
).toArrayBuffer();
// verify it works...
// get around the FILESERVER_HOSTS filter by not using serverRequest
const res = await LokiAppDotNetAPI.sendViaOnion(
pubKey,
url,
{ method: 'GET' },
{ noJson: true }
);
if (res.result && res.result.status === 200) {
log.info(
`loki_public_chat::validOpenGroupServer - onion routing enabled on ${url.toString()}`
);
// save pubkey for use...
window.lokiPublicChatAPI.openGroupPubKeys[serverUrl] = pubKey;
return true;
}
// otherwise fall back
} else if (result.response.meta.code !== 404) {
// unknown error code
log.warn(
'loki_public_chat::validOpenGroupServer - unknown error code',
result.response.meta
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 = 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 LokiAppDotNetAPI.sendViaOnion(
pubKey,
url,
{ method: 'GET' },
{ noJson: true }
);
if (res.result && res.result.status === 200) {
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
log.warn(
'loki_public_chat::validOpenGroupServer - unknown error code',
result.response.meta
);
}
// doesn't support it, fallback
log.info(
`loki_public_chat::validOpenGroupServer - directly contacting ${url.toString()}`
);

// allow .loki (may only need an agent but not sure
// until we have a .loki to test with)
process.env.NODE_TLS_REJECT_UNAUTHORIZED = url.host.match(/\.loki$/i)
? '0'
: '1';
await nodeFetch(serverUrl);
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '1';
// const txt = await res.text();
return false;
} catch (e) {
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '1';
log.warn(
`loki_public_chat::validOpenGroupServer - failing to create ${serverUrl}`,
e.code,
e.message
);
// bail out if not valid enough
return false;
}
return true;
return false;
};

class LokiPublicChatFactoryAPI extends EventEmitter {
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "session-desktop",
"productName": "Session",
"description": "Private messaging from your desktop",
"version": "1.5.1",
"version": "1.5.2",
"license": "GPL-3.0",
"author": {
"name": "Loki Project",
Expand Down Expand Up @@ -344,4 +344,4 @@
"*/**/*.{css,js,json,scss,ts,tsx}": "prettier --write",
"*.js": "eslint --cache --fix"
}
}
}
3 changes: 1 addition & 2 deletions ts/components/session/LeftPaneContactSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,7 @@ export class LeftPaneContactSection extends React.Component<Props, State> {
if (error) {
ToastUtils.pushToastError('addContact', error);
} else {
// tslint:disable-next-line: no-floating-promises
ConversationController.getInstance()
void ConversationController.getInstance()
.getOrCreateAndWait(sessionID, 'private')
.then(() => {
this.props.openConversationExternal(sessionID);
Expand Down
10 changes: 7 additions & 3 deletions ts/components/session/conversation/SessionStagedLinkPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react';
import { arrayBufferFromFile } from '../../../types/Attachment';
import { AttachmentUtil, LinkPreviewUtil } from '../../../util';
import { StagedLinkPreviewData } from './SessionCompositionBox';
import fetch from 'node-fetch';
import { default as insecureNodeFetch } from 'node-fetch';
import { fetchLinkPreviewImage } from '../../../util/linkPreviewFetch';
import { AbortSignal } from 'abort-controller';
import { StagedLinkPreview } from '../../conversation/StagedLinkPreview';
Expand Down Expand Up @@ -37,8 +37,10 @@ export const getPreview = async (
throw new Error('Link not safe for preview');
}

window.log.info('insecureNodeFetch => plaintext for getPreview()');

const linkPreviewMetadata = await LinkPreviewUtil.fetchLinkPreviewMetadata(
fetch,
insecureNodeFetch,
url,
abortSignal
);
Expand All @@ -51,8 +53,10 @@ export const getPreview = async (
if (imageHref && window.Signal.LinkPreviews.isLinkSafeToPreview(imageHref)) {
let objectUrl: void | string;
try {
window.log.info('insecureNodeFetch => plaintext for getPreview()');

const fullSizeImage = await fetchLinkPreviewImage(
fetch,
insecureNodeFetch,
imageHref,
abortSignal
);
Expand Down
6 changes: 3 additions & 3 deletions ts/models/conversation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -472,9 +472,9 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
const newAdmins = _.sortBy(groupAdmins);

if (_.isEqual(existingAdmins, newAdmins)) {
window.log.info(
'Skipping updates of groupAdmins/moderators. No change detected.'
);
// window.log.info(
// 'Skipping updates of groupAdmins/moderators. No change detected.'
// );
return;
}
this.set({ groupAdmins });
Expand Down
12 changes: 6 additions & 6 deletions ts/session/onions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import { allowOnlyOneAtATime } from '../../../js/modules/loki_primitives';
import { getGuardNodes } from '../../../ts/data/data';
import * as SnodePool from '../snode_api/snodePool';
import _ from 'lodash';
import fetch from 'node-fetch';
import { default as insecureNodeFetch } from 'node-fetch';
import { UserUtils } from '../utils';
import { snodeHttpsAgent } from '../snode_api/onions';

type Snode = SnodePool.Snode;

Expand Down Expand Up @@ -155,23 +156,22 @@ export class OnionPaths {
body: JSON.stringify(body),
headers: { 'Content-Type': 'application/json' },
timeout: 10000, // 10s, we want a smaller timeout for testing
agent: snodeHttpsAgent,
};

process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';

let response;

try {
// Log this line for testing
// curl -k -X POST -H 'Content-Type: application/json' -d '"+fetchOptions.body.replace(/"/g, "\\'")+"'", url
response = await fetch(url, fetchOptions);
window.log.info('insecureNodeFetch => plaintext for testGuardNode');

response = await insecureNodeFetch(url, fetchOptions);
} catch (e) {
if (e.type === 'request-timeout') {
log.warn('test timeout for node,', snode);
}
return false;
} finally {
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '1';
}

if (!response.ok) {
Expand Down
Loading

0 comments on commit 7bb5243

Please sign in to comment.