Skip to content

Commit

Permalink
fix: wrap tor path in double quotes to handle spaces in path; spawn t…
Browse files Browse the repository at this point in the history
…or in shell; kill group of processes (shell: true spawns 2 processes)
  • Loading branch information
EmiM committed Dec 5, 2023
1 parent 2d293da commit 8589e68
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 19 deletions.
4 changes: 1 addition & 3 deletions packages/backend/src/nest/common/test.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,9 @@ import { createTmpDir, getCors, torBinForPlatform, torDirForPlatform } from './u

const torPath = torBinForPlatform()
const libPath = torDirForPlatform()
// torBinaryPath: '../../../../../3rd-party/tor/linux/tor',
// torResourcesPath: '../../../../../3rd-party/tor/linux',
export const defaultConfigForTest = {
socketIOPort: TEST_DATA_PORT,
torBinaryPath: torBinForPlatform(),
torBinaryPath: torPath,
torResourcesPath: torPath,
torControlPort: await getPort(),
options: {
Expand Down
21 changes: 20 additions & 1 deletion packages/backend/src/nest/common/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ import { UserData } from '@quiet/types'
import createHttpsProxyAgent from 'https-proxy-agent'
import PeerId from 'peer-id'
import tmp from 'tmp'
import crypto from 'crypto'
import crypto, { sign } from 'crypto'
import { type PermsData } from '@quiet/types'
import { TestConfig } from '../const'
import logger from './logger'
import { Libp2pNodeParams } from '../libp2p/libp2p.types'
import { createLibp2pAddress, createLibp2pListenAddress, isDefined } from '@quiet/common'
import { Libp2pService } from '../libp2p/libp2p.service'
import { CertFieldsTypes, getReqFieldValue, loadCSR } from '@quiet/identity'
import { exec } from 'child_process'

const log = logger('test')

Expand Down Expand Up @@ -249,3 +250,21 @@ export async function createPeerId(): Promise<PeerId> {
const peerId = await PeerId.create()
return peerIdFromKeys(peerId.marshalPubKey(), peerId.marshalPrivKey())
}

export function killAll(pid: number, signal: string | number = 'SIGTERM') {
// Kills group of processes
console.log(`Killing processes group with pid ${pid}. Signal: ${signal}`)
if (process.platform == 'win32') {
exec(`taskkill /PID ${pid} /T /F`, (error, stdout, stderr) => {

Check warning

Code scanning / CodeQL

Unsafe shell command constructed from library input Medium

This string concatenation which depends on
library input
is later used in a
shell command
.
console.log('taskkill stdout: ' + stdout)
console.log('taskkill stderr: ' + stderr)
if (error) {
console.log('error: ' + error.message)
}
})
} else {
// see https://nodejs.org/api/child_process.html#child_process_options_detached
// If pid is less than -1, then sig is sent to every process in the process group whose ID is -pid.
process.kill(-pid, signal)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,10 @@ beforeEach(async () => {
],
})
.overrideProvider(TOR_PASSWORD_PROVIDER)
.useValue({ torPassword: 'b5e447c10b0d99e7871636ee5e0839b5', torHashedPassword: '16:FCFFE21F3D9138906021FAADD9E49703CC41848A95F829E0F6E1BDBE63' })
.useValue({
torPassword: 'b5e447c10b0d99e7871636ee5e0839b5',
torHashedPassword: '16:FCFFE21F3D9138906021FAADD9E49703CC41848A95F829E0F6E1BDBE63',
})
.compile()

connectionsManagerService = await module.resolve(ConnectionsManagerService)
Expand Down
37 changes: 26 additions & 11 deletions packages/backend/src/nest/tor/tor.service.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import * as child_process from 'child_process'
import crypto from 'crypto'
import * as fs from 'fs'
import path from 'path'
import getPort from 'get-port'
import { removeFilesFromDir } from '../common/utils'
import { killAll, removeFilesFromDir } from '../common/utils'
import { EventEmitter } from 'events'
import { ConnectionProcessInfo, SocketActionTypes, SupportedPlatform } from '@quiet/types'
import { SocketActionTypes, SupportedPlatform } from '@quiet/types'
import { Inject, OnModuleInit } from '@nestjs/common'
import { ConfigOptions, ServerIoProviderTypes } from '../types'
import { CONFIG_OPTIONS, QUIET_DIR, SERVER_IO_PROVIDER, TOR_PARAMS_PROVIDER, TOR_PASSWORD_PROVIDER } from '../const'
Expand All @@ -16,7 +15,7 @@ import Logger from '../common/logger'

export class Tor extends EventEmitter implements OnModuleInit {
socksPort: number
process: child_process.ChildProcessWithoutNullStreams | any = null
process: child_process.ChildProcessWithoutNullStreams | null = null
torDataDirectory: string
torPidPath: string
extraTorProcessParams: TorParams
Expand Down Expand Up @@ -93,7 +92,7 @@ export class Tor extends EventEmitter implements OnModuleInit {
try {
this.clearHangingTorProcess()
} catch (e) {
this.logger('Error occured while trying to clear hanging tor processes')
this.logger('Error occured while trying to clear hanging tor processes', e)
}

try {
Expand All @@ -113,7 +112,7 @@ export class Tor extends EventEmitter implements OnModuleInit {
resolve()
} catch {
this.logger('Killing tor')
await this.process.kill()
this.process?.pid && killAll(this.process?.pid)
removeFilesFromDir(this.torDataDirectory)

// eslint-disable-next-line
Expand Down Expand Up @@ -161,7 +160,7 @@ export class Tor extends EventEmitter implements OnModuleInit {
if (!torProcessId) return
this.logger(`Found tor process with pid ${torProcessId}. Killing...`)
try {
process.kill(Number(torProcessId), 'SIGTERM')
killAll(Number(torProcessId))
} catch (e) {
this.logger.error(`Tried killing hanging tor process. Failed. Reason: ${e.message}`)
}
Expand Down Expand Up @@ -204,8 +203,12 @@ export class Tor extends EventEmitter implements OnModuleInit {
reject(new Error("Can't spawn tor - no controlPort"))
return
}
const options: child_process.SpawnOptionsWithoutStdio = {
...this.torParamsProvider.options,
shell: true,
}
this.process = child_process.spawn(
`${this.torParamsProvider.torPath}`,
this.torParamsProvider.torPath,
[
'--SocksPort',
this.socksPort.toString(),
Expand All @@ -221,8 +224,19 @@ export class Tor extends EventEmitter implements OnModuleInit {
this.torPasswordProvider.torHashedPassword,
// ...this.torProcessParams
],
Object.assign(this.torParamsProvider.options, { shell: true })
options
)
this.process.stderr.on('data', e => {
this.logger.error('Tor process. Stderr:', e)
})

this.process.on('exit', (code, signal) => {
this.logger(`Tor exited with code ${code} and signal ${signal}`)
})

this.process.on('error', err => {
this.logger.error(`Tor process. Error occurred: ${err.message}`)
})

this.process.stdout.on('data', (data: any) => {
this.logger(data.toString())
Expand Down Expand Up @@ -321,7 +335,7 @@ export class Tor extends EventEmitter implements OnModuleInit {

public async kill(): Promise<void> {
return await new Promise((resolve, reject) => {
this.logger('Killing tor...')
this.logger('Killing tor... with pid', this.process?.pid)
if (this.process === null) {
this.logger('TOR: Process is not initalized.')
resolve()
Expand All @@ -337,7 +351,8 @@ export class Tor extends EventEmitter implements OnModuleInit {
this.process?.on('error', () => {
reject(new Error('TOR: Something went wrong with killing tor process'))
})
this.process?.kill()
if (!this.process?.pid) return
killAll(this.process?.pid)
})
}
}
3 changes: 0 additions & 3 deletions packages/e2e-tests/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,6 @@ export class BuildSetup {
DEBUG: 'backend*,desktop*,utils*',
DATA_DIR: this.dataDir,
}
// if (this.dataDir) {
// env = Object.assign(env, { DATA_DIR: this.dataDir })
// }
if (process.platform === 'win32') {
console.log('!WINDOWS!')
this.child = spawn(`cd node_modules/.bin & chromedriver.cmd --port=${this.port} --verbose`, [], {
Expand Down

0 comments on commit 8589e68

Please sign in to comment.