Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crash (segfault, SIGILL) when using proxy with user and password #1211

Closed
smanolache opened this issue Apr 19, 2024 · 30 comments
Closed

Crash (segfault, SIGILL) when using proxy with user and password #1211

smanolache opened this issue Apr 19, 2024 · 30 comments

Comments

@smanolache
Copy link

Describe the bug
teams-for-linux --proxyServer=host:port crashes (dumps core) and restarts in an infinite loop. The proxy server requires authentication so I expected the user/pass dialog.

To Reproduce
Run teams-for-linux --proxyServer=proxy:port with a proxy requiring authentication

Expected behavior
I expect the dialog window to introduce my user and password for proxy authentication

Screenshots
Attached video.

Desktop (please complete the following information):

  • OS: Linux hostname 6.7.9-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.7.9-2 (2024-03-13) x86_64 GNU/Linux
  • Installation package: deb
  • Version: 1.4.27 amd64
  • Freshly (2024-04-19) updated debian unstable distribution

Debug
Here's the debug output in the console:

[DEBUG] configPath:,/home/user/.config/teams-for-linux
[WARN] No config file found, using default values
[DEBUG] configFile:,[object Object]
[DEBUG] Fetching custom background configuration from 'http://localhost/config.json'
[DEBUG] Custom background service url is 'http://localhost'
[DEBUG] processArgs:,/opt/teams-for-linux/teams-for-linux,--webDebug,--appLogLevels=error,info,warn,debug,--proxyServer=proxyhost:8080
[DEBUG] Testing network using net.request() for https://teams.microsoft.com/
[DEBUG] Spellchecker is disabled!
[ERROR] Failed to fetch custom background remote configuration. net::ERR_CONNECTION_REFUSED
[9080:0419/095929.079610:ERROR:command_buffer_proxy_impl.cc(131)] ContextResult::kTransientFailure: Failed to send GpuControl.CreateCommandBuffer.
[DEBUG] Network test successful with method https
[8984:0419/095929.929354:ERROR:atom_cache.cc(229)] Add _NET_WM_STATE_MODAL to kAtomsToCache
[DEBUG] GetSystemIdleState => IdleTimeout: 300s, IdleTimeoutPollInterval: 10s, ActiveCheckPollInterval: 2s, IdleTime: 0s, IdleState: 'active'
[8984:0419/095929.982126:ERROR:CONSOLE(1)] "Request Autofill.enable failed. {"code":-32601,"message":"'Autofill.enable' wasn't found"}", source: devtools://devtools/bundled/core/protocol_client/protocol_client.js (1)
[DEBUG] window closed
[DEBUG] quit

Additional context
I've attached the output of gdb.
teams-for-linux-gdb.txt

teams-for-linux.mp4
@smanolache
Copy link
Author

@IsmaelMartinez
Copy link
Owner

Hi @smanolache , what happens if you don't provide the proxy configuration? I haven't experience anything like this before but I don't use a proxy.

@smanolache
Copy link
Author

When no proxy is needed it works fine.

But I have to use a proxy when working remotely.

@smanolache
Copy link
Author

The problem is that the proxy requires authentication. If I use a proxy that does not require authentication then it works ok.

I expect a dialog window to pop up in which I would type the proxy user and password. Sometimes I do see that dialog window for a couple of milliseconds, then the program crashes and the main window and dialog window disappear.

@IsmaelMartinez
Copy link
Owner

Are you able to use a client certificate/password? If so, try using the config options clientCertPath and clientCertPassword. We have seen proxy issues in the past and sometimes are really strange but using a cert seems to bypass them.

This might be the same as older issues like #314 (it might be that you need to import your company certificates in chrome if they are self sign), #645 (that ended up adding that client cert) or maybe another one of the closed issues, but those are the ones that I can see as more relevant.

Hope helps!

@smanolache
Copy link
Author

No, I do not authenticate by certificate.

The problem is not authenticating my user on teams. The problem is authenticating with the http proxy. Only after the proxy accepts my requests I can go on to the teams server. If there is no proxy then everything goes fine. So, for example, when I'm at work, on the company's network, I need no proxy and everything goes fine. But when I am at home I must use a VPN and on this network I have to use an authenticating proxy. The proxy is very simple: just plain http (no https/SSL), with basic auth, username and password. The program crashes before being offered the dialog window in which I type my proxy username and password.

There was a previous version of teams-for-linux (unfortunately I do not remember which one) that crashed most of the times but not always. From time to time, instead of crashing it popped up an alert window in which it said that some javascript object is null. I think the error is there. There must be some race-condition. But I cannot reproduce.

Please try to reproduce. The setup is quite simple: just configure an authenticating proxy (with user and password) and run teams-for-linux with the --proxyServer argument.

@IsmaelMartinez
Copy link
Owner

If it is refreshing, it might be the onlineCheckMethod. If you can try changing this to none?

Unfortunately, I don't have the option/time to be checking configurations. Apologies but I don't even have a linux machine what would make any test mostly redundant.

@Wuemeli
Copy link

Wuemeli commented Apr 22, 2024

Wait what you dont own a Linux Machine?

@IsmaelMartinez
Copy link
Owner

Wait what you dont own a Linux Machine?

not anymore... my work laptop was move to MacOS and my home laptop... well... died. So supporting this is a bit of an interesting challenge :)

@Wuemeli
Copy link

Wuemeli commented Apr 22, 2024

Uffff. Why just not use a VM?

@IsmaelMartinez
Copy link
Owner

lets say I work in a highly regulated industry and the MacOS is pretty much locked down. But so far managing (already more than 3 years like this) so is fine. The community helps a lot

@pkitszel
Copy link

I'm using a proxy, additionally over VPN.
And I pass it simply via env, as for all other apps

http_proxy=http://proxy-dmz.mycorpo.com:912
https_proxy=http://proxy-dmz.mycorpo.com:912

BTW, I was forced to look for alternatives to the long retired MS app, and this started fine without anything, then asked for a new mode, this also works, so it's great, thank you Ismael!

@smanolache
Copy link
Author

@pkitszel is it an authenticating proxy? I.e. do you need to pass a username and password to it? Does teams pop a dialog window in which you type your proxy username and password?

@smanolache
Copy link
Author

As shown in the video I have posted, teams crashes, restarts, crashes again, and so on in a loop.

I let the crash-restart loop run and it stopped eventually with an error dialog window. It says:

"Uncaught Exception:
TypeError: Cannot read properties of null (reading 'WebContents') at BrowserWindow.onPageTitleUpdated (/opt/teams-for-linux/resources/app.asar/app/mainAppWindow/index.js:366:9) at BrowserWindow.emit (node:events:518:28)"

Once I click "Ok" on the dialog window, the crash-restart loop continues.

@IsmaelMartinez
Copy link
Owner

can you try removing the custom background just in case that is what is breaking your app ? having a second look at your 1st message the custom background service is trying to fetch the images from localhost, so the app might be thinking your proxy is a the custom background

image

@smanolache
Copy link
Author

It makes no difference.

@IsmaelMartinez
Copy link
Owner

IsmaelMartinez commented Apr 25, 2024 via email

@smanolache
Copy link
Author

smanolache commented Apr 25, 2024

I do not administrate the proxy server, it is managed by my employer.

I submitted a bug report. I am not looking for a work-around or wild guesses. In case of bug reports I think it is common practice to acknowledge or refute the described problem. Could you please try to reproduce? Could you please answer the following question: Does teams-for-linux crash when using an authenticating proxy? It does crash on my machine, I would like a confirmation that it is a problem encountered by others, or the opposite: a proof that it works. I repeat: an authenticating proxy. For one week only speculations and guesses but, afaik, no confirmation of the problem, no attempt to reproduce.

You seem to overlook the crash and the gdb output. When I say "crash" it is not that the window is not displayed, but I mean that a process is killed by the operating system because some violation. In this case it is a SIGILL signal.

My hypothesis is the following: When using no proxy or a non-authenticating proxy any network request succeeds and there is no error. When, however, the proxy is authenticating, then it will return HTTP 407 Proxy Authentication Required. The javascript code must react to that and pop up a dialog window in which the user types the proxy user name and password. All http requests that are issued before submitting the proxy credentials will fail. The executable is a node (javascript) interpreter. The javascript handling the proxy authentication has some nasty error and makes the interpreter crash. The entire application is made of several processes. I suppose they communicate in some way. As one of them dies, the other processes cannot initialize the application correctly. The key to the investigation is to check why one of the processes crashes.

@IsmaelMartinez
Copy link
Owner

Proxy works for other users. We are trying to help you here, so please I kindly ask you to remember that when writing messages. I think it has nothing to do with the proxy but with the background images, we don't do anything fancy with the proxy. I will see if I can have a look later

@IsmaelMartinez
Copy link
Owner

ok, if you get the latest pre-release (1.4.31) and start it with teams-for-linux --proxyServer=proxy:port --isCustomBackgroundEnabled=false and see if the loop is gone?

@smanolache
Copy link
Author

Proxy works for other users.

Authenticating proxies? Is there someone who can come forward and claim that it works for them when using an authenticating proxy?

@IsmaelMartinez
Copy link
Owner

we don't add any specific logic for proxies and just use what electron provides. Meaning, it might be an electron issue. Feel free to report in there https://github.com/electron/electron/issues

Unfortunately we can't re-produce every single scenario and/or test them and, to be honest, adding proxies in the mix only makes it even more complicated.

If you can confirm if the flag changes anything for you, that helps us narrow down the possible options. Sometimes we can work around issue by adding specific code, but we will need your collaboration, otherwise we are blind.

Please understand we aren't providing a paid service here. I sense frustration in your writing and if you need to vent your frustration do it with Microsoft that should be providing a client for you instead of you needing to use this community driven product.

If you try the options we are giving you and provide as much information as you can on the back of them (console logs etc), then we might be able to work together to find a solution to your problem.

@pkitszel
Copy link

@pkitszel is it an authenticating proxy? I.e. do you need to pass a username and password to it? Does teams pop a dialog window in which you type your proxy username and password?

ugh, sorry, NO

apologies for confusion

@smanolache
Copy link
Author

I've tried with --isCustomBackgroundEnabled=false and it makes no difference.

Google found these issues:
electron/electron#14589
electron/electron#21269

Both are closed though. It seems there was (is?) a problem with authenticating proxies in electron.

@IsmaelMartinez
Copy link
Owner

yep, it does look that proxy would require adding some code to handle it.

Easier said than done but it might just be a matter of adding something like this:

if (config.localProxy) {
  mainWin.webContents.session.setProxy(config.localProxy, () => {
          mainWin.loadURL(config.url);
      });
}

around

window.webContents.session.webRequest.onBeforeSendHeaders(getWebRequestFilterFromURL(), onBeforeSendHeadersHandler);

And to add that 'localProxy' as an option that can be configured in https://github.com/IsmaelMartinez/teams-for-linux/blob/0330cc0e863dcad4cc6380d62aeaba0e3a1502f6/app/config/index.js

But there is a lot of magic/crazy logic happening in that area, so it might just break altogether. I will see if I can get some time this week to create a wee PoC so you can validate if it works.

@lealnetosena
Copy link

I go through this every day. And an alternative to escape this looping was the configuration below that I go through parameters:

Add args in app/config/index.js

			userProxy: {
				default: "meusuario",
				describe: 'Sets the user for login proxy',
				type: 'string'
			},
			passwordProxy: {
				default: "minhasenha",
				describe: 'Sets the pasword for login proxy',
				type: 'string'
			},

Add args in call function in app/mainAppWindow/index.js

login.handleLoginDialogTry(window,config.userProxy,config.passwordProxy);

function addEventHandlers() {
	  initializeCustomBGServiceURL();
	  window.on('page-title-updated', onPageTitleUpdated);
	  window.webContents.setWindowOpenHandler(onNewWindow);
	  window.webContents.session.webRequest.onBeforeRequest({ urls: ['https://*/*'] }, onBeforeRequestHandler);
	  window.webContents.session.webRequest.onHeadersReceived({ urls: ['https://*/*'] }, onHeadersReceivedHandler);
	  window.webContents.session.webRequest.onBeforeSendHeaders(getWebRequestFilterFromURL(), onBeforeSendHeadersHandler);
	  login.handleLoginDialogTry(window,config.userProxy,config.passwordProxy);
	  window.webContents.on('did-finish-load', onDidFinishLoad);
	  window.webContents.on('did-frame-finish-load', onDidFrameFinishLoad);
	  window.on('closed', onWindowClosed);
	  window.webContents.addListener('before-input-event', onBeforeInput);
  }

Add arguments in proxy authentication calls in app/login/index.js

const { app, ipcMain, BrowserWindow } = require('electron');
let isFirstLoginTry = true;

exports.loginService = function loginService(parentWindow, callback,userProxy, passwordProxy) {
	let win = new BrowserWindow({
		width: 363,
		height: 124,
		modal: true,
		frame: false,
		parent: parentWindow,

		show: false,
		autoHideMenuBar: true,
		webPreferences: {
			contextIsolation: false,
			nodeIntegration: true
		}
	});
	require('@electron/remote/main').enable(win.webContents);

	win.once('ready-to-show', () => {
		win.show();
	});

	ipcMain.on('submitForm', submitFormHandler(callback, win,userProxy,passwordProxy));

	win.on('closed', () => {
		win = null;
	});

	win.loadURL(`file://${__dirname}/login.html`);
};


exports.handleLoginDialogTry = function handleLoginDialogTry(window, userProxy, passwordProxy) {
	window.webContents.on('login', (event, request, authInfo, callback) => {
		event.preventDefault();
		if (isFirstLoginTry) {
			isFirstLoginTry = false;
			this.loginService(window, callback, userProxy, passwordProxy);
		} else {
			// if fails to authenticate we need to relanch the app as we have close the login browser window.
			isFirstLoginTry = true;
			app.relaunch();
			app.exit(0);
		}
	});
};

function submitFormHandler(callback, win, userProxy, passwordProxy) {
	return (event, data) => {
		callback(userProxy || data.username, passwordProxy || data.password);
		win.close();
	};
}

And for me it works like this:

  1. I added the username and password on the command line
    image
  • I did it this way because the company often forces you to change your password and it becomes easier to change.
  1. I open Teams outside the VPN
  2. Connect to the VPN
  3. When the username and password window opens, I send an empty username and password.
  • If you miss this screen it enters the loop so you have to be quick to give the OK. Before, I had to enter the username and password and while I was typing, the screen and Teams closed.

I know it's something that could be done better as an automatic login without having to click OK. I believe that automatic login would even solve this problem.

PS: The logic of that window that asks for username and password occurs in this app/login folder

@lealnetosena
Copy link

lealnetosena commented May 13, 2024

I believe that the way to make it automatic is to submit the username and password as soon as there is a login event. When the "login" event occurs, the authentication window is called.

window.webContents.on('login', (event, request, authInfo, callback) => {
Exactly here it calls this.loginService which creates a BrowserWindow which in this case could, instead of creating the BrowserWindows, already call the submitFormHandler function passing the username and password coming from the command line arguments.

app/login/index.js:

exports.handleLoginDialogTry = function handleLoginDialogTry(window, userProxy, passwordProxy) {
	window.webContents.on('login', (event, request, authInfo, callback) => {
		event.preventDefault();
		if (isFirstLoginTry) {
			isFirstLoginTry = false;
			this.loginService(window, callback, userProxy, passwordProxy);
		} else {
			// if fails to authenticate we need to relanch the app as we have close the login browser window.
			isFirstLoginTry = true;
			app.relaunch();
			app.exit(0);
		}
	});
};

function submitFormHandler(callback, win, userProxy, passwordProxy) {
	return (event, data) => {
		callback(userProxy || data.username, passwordProxy || data.password);
		win.close();
	};
}

@lealnetosena
Copy link

lealnetosena commented May 13, 2024

I was able to auto login!
Steps:

Add args in app/config/index.js
File: app/config/index.js

			userProxy: {
				default: "meusuario",
				describe: 'Sets the user for login proxy',
				type: 'string'
			},
			passwordProxy: {
				default: "minhasenha",
				describe: 'Sets the pasword for login proxy',
				type: 'string'
			},

Add the config.userProxy,config.passwordProxy parameters to the function and its call.

File: app/mainAppWindow/index.js

login.handleLoginDialogTry(window,config.userProxy,config.passwordProxy);

function addEventHandlers() {
	initializeCustomBGServiceURL();
	window.on('page-title-updated', onPageTitleUpdated);
	window.webContents.setWindowOpenHandler(onNewWindow);
	window.webContents.session.webRequest.onBeforeRequest({ urls: ['https://*/*'] }, onBeforeRequestHandler);
	window.webContents.session.webRequest.onHeadersReceived({ urls: ['https://*/*'] }, onHeadersReceivedHandler);
	window.webContents.session.webRequest.onBeforeSendHeaders(getWebRequestFilterFromURL(), onBeforeSendHeadersHandler);
	login.handleLoginDialogTry(window,config.userProxy,config.passwordProxy);
	window.webContents.on('did-finish-load', onDidFinishLoad);
	window.webContents.on('did-frame-finish-load', onDidFrameFinishLoad);
	window.on('closed', onWindowClosed);
	window.webContents.addListener('before-input-event', onBeforeInput);
}

File: app/login/index.js:


exports.handleLoginDialogTry = function handleLoginDialogTry(window, userProxy, passwordProxy) {
	window.webContents.on('login', (event, request, authInfo, callback) => {
		event.preventDefault();
		if (isFirstLoginTry) {
			isFirstLoginTry = false;
			// this.loginService(window, callback, userProxy, passwordProxy);
			console.log("Vou fazer a autenticação")
			console.log(userProxy, passwordProxy)
			callback(userProxy, passwordProxy)
			console.log("Fiz a autenticação")
		} else {
			// if fails to authenticate we need to relanch the app as we have close the login browser window.
			isFirstLoginTry = true;
			app.relaunch();
			app.exit(0);
		}
	});
};

And for me it works like this:

  1. I added the username and password on the command line
    image
  • I did it this way because the company often forces you to change your password and it becomes easier to change.

Result: Log showing authentication occurring with Teams remaining open:
image

@IsmaelMartinez
Copy link
Owner

Ok, I think we can use the ssoUser and ssoPasswordCommand config options to bypass this now. See https://github.com/IsmaelMartinez/teams-for-linux/releases/tag/v1.4.40 . The solution is similar to the one you provided @lealnetosena , but using a command. So people can hook into their password manager or similar, or just do an echo of their password if they are happy for it to be stored in plain text in their computer (something I would not recommend at all)

@IsmaelMartinez
Copy link
Owner

I am renaming those properties to ssoBasicAuthUser and ssoBasicAuthPasswordCommand in v1.5.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants