|
| 1 | +/* eslint standard/no-callback-literal: 0 */ |
| 2 | + |
| 3 | +const ElectronProxyAgent = require('electron-proxy-agent') |
| 4 | +const url = require('url') |
| 5 | +const http = require('http') |
| 6 | +const https = require('https') |
| 7 | + |
| 8 | +const log = require('cozy-desktop').default.logger({ |
| 9 | + component: 'GUI:proxy' |
| 10 | +}) |
| 11 | + |
| 12 | +const config = require('yargs') |
| 13 | + .env('COZY_DRIVE') |
| 14 | + .conflicts('proxy-script', 'proxy-rules') |
| 15 | + .describe('proxy-script', 'The URL associated with the PAC file.') |
| 16 | + .describe('proxy-rules', 'Rules indicating which proxies to use.') |
| 17 | + .describe('proxy-bypassrules', 'Rules indicating which URLs should bypass the proxy settings. ' + |
| 18 | + 'See https://github.com/electron/electron/blob/master/docs/api/session.md#sessetproxyconfig-callback') |
| 19 | + .default('proxy-ntlm-domains', '*') |
| 20 | + .describe('proxy-ntlm-domains', 'A comma-separated list of servers for which integrated authentication is enabled. ' + |
| 21 | + 'Dynamically sets whether to always send credentials for HTTP NTLM or Negotiate authentication.') |
| 22 | + .describe('login-by-realm', 'comma-separated list of realm:user:password') |
| 23 | + .help('help') |
| 24 | + .parse() |
| 25 | + |
| 26 | +log.debug({config}, 'argv') |
| 27 | + |
| 28 | +const formatCertificate = (certif) => `Certificate(${certif.issuerName} ${certif.subjectName})` |
| 29 | + |
| 30 | +module.exports = (app, session, doneSetup) => { |
| 31 | + const loginByRealm = {} |
| 32 | + if (config['login-by-realm']) { |
| 33 | + config['login-by-realm'].split(',').forEach((lbr) => { |
| 34 | + const [realm, username, ...password] = lbr.split(':') |
| 35 | + loginByRealm[realm] = [username, password.join(':')] |
| 36 | + }) |
| 37 | + } |
| 38 | + |
| 39 | + if (config['proxy-ntlm-domains']) { |
| 40 | + session.defaultSession.allowNTLMCredentialsForDomains(config['proxy-ntlm-domains']) |
| 41 | + } |
| 42 | + |
| 43 | + session.defaultSession.setCertificateVerifyProc((request, callback) => { |
| 44 | + const {hostname, certificate, verificationResult, errorCode} = request |
| 45 | + if (verificationResult < 0) { |
| 46 | + log.warn({hostname, certificate: formatCertificate(certificate), verificationResult, errorCode}, 'Certificate Verification Error') |
| 47 | + } else { |
| 48 | + log.debug({hostname, certificate: formatCertificate(certificate), verificationResult, errorCode}, 'Certificate Validated') |
| 49 | + } |
| 50 | + callback(-3) // use chrome validation |
| 51 | + }) |
| 52 | + |
| 53 | + app.on('select-client-certificate', (event, webContents, url, list, callback) => { |
| 54 | + log.debug({url}, 'select-client-certificate') |
| 55 | + callback() |
| 56 | + }) |
| 57 | + |
| 58 | + app.on('certificate-error', (event, webContents, url, error, certificate, callback) => { |
| 59 | + log.warn({url, error, certificate: formatCertificate(certificate)}, 'App Certificate Error') |
| 60 | + callback(false) |
| 61 | + }) |
| 62 | + |
| 63 | + app.on('login', (event, webContents, request, authInfo, callback) => { |
| 64 | + log.debug({request: request.method + ' ' + request.url, authInfo}, 'Login event') |
| 65 | + const auth = loginByRealm[authInfo.realm] |
| 66 | + if (auth) { |
| 67 | + event.preventDefault() |
| 68 | + callback(...auth) |
| 69 | + } else { |
| 70 | + callback() |
| 71 | + } |
| 72 | + }) |
| 73 | + |
| 74 | + const electronFetch = require('electron-fetch') |
| 75 | + global.fetch = (url, opts = {}) => { |
| 76 | + opts.session = session.defaultSession |
| 77 | + return electronFetch(url, opts) |
| 78 | + } |
| 79 | + http.Agent.globalAgent = http.globalAgent = https.globalAgent = new ElectronProxyAgent(session.defaultSession) |
| 80 | + const _httpRequest = http.request |
| 81 | + http.request = function (options, cb) { |
| 82 | + log.warn(options, 'USING RAW HTTP REQUEST') |
| 83 | + options.agent = options.agent || http.globalAgent |
| 84 | + options.headers = options.headers || {} |
| 85 | + options.headers.host = options.hostname |
| 86 | + return _httpRequest.call(http, options, cb) |
| 87 | + } |
| 88 | + const _httpsRequest = https.request |
| 89 | + https.request = function (options, cb) { |
| 90 | + log.warn(options, 'USING RAW HTTPS REQUEST') |
| 91 | + if (typeof options === 'string') { |
| 92 | + options = url.parse(options) |
| 93 | + } else { |
| 94 | + options = Object.assign({}, options) |
| 95 | + } |
| 96 | + options.agent = options.agent || https.globalAgent |
| 97 | + return _httpsRequest.call(https, options, cb) |
| 98 | + } |
| 99 | + |
| 100 | + if (config['proxy-script'] || config['proxy-rules']) { |
| 101 | + session.defaultSession.setProxy({ |
| 102 | + pacScript: config['proxy-script'], |
| 103 | + proxyRules: config['proxy-rules'], |
| 104 | + proxyBypassRules: config['proxy-bypassrules'] |
| 105 | + }, doneSetup) |
| 106 | + } else doneSetup() |
| 107 | +} |
0 commit comments