EionRobb / pidgin-opensteamworks

Steam plugin for Pidgin/libpurple
153 stars 5 forks source link

BitlBee: only the first login with a steam guard code succeeds #198

Open Mzyxptlk opened 4 years ago

Mzyxptlk commented 4 years ago

I'm trying to use v1.7 of this plugin with the BitlBee v3.6, based on libpurple, on Debian testing.

When I add my Steam account account to BitlBee and perform my first connection, I get sent a Steam guard code. After I pass it to BitlBee, I can log in and chat with friends. Huzzah!

However, every log in attempt after the first one fails with 'Could not authenticate steam-guard code'. This persists until I clear the steam guard code and try to log in again, after which Steam sends me another guard code, allowing another one-off session.

When I look in the configuration file or list the configuration parameters for the plugin from within BitlBee, the steam guard code is set to the expected value.

I tried reconnecting manually, and restarting BitlBee after the first login attempt, thinking maybe the guard code isn't saved or loaded somehow, but that resulted in the same behaviour.

I looked at the differences between the Pidgin and BitlBee configuration files, but the only thing that sprang out at me is that the settings 'emailsteamid' and 'access_token' are listed in my Pidgin configuration file, but not in the BitlBee one. I tried adding them as user options in plugin_init(), but while they're now listed within BitlBee, their values always stay at their defaults (ie. empty).

I'm happy to do some more debugging, but at this point I'm out of ideas.

EionRobb commented 4 years ago

So as a bit of a background as to why this happens, bitlbee and Pidgin set settings in the plugin in different ways - Pidgin treats the libpurple file accounts.xml as authoritative, but bitlbee has it's own settings/pref store so will just drip feed information to the plugin that it needs, overwriting all previous settings. Whenever a plugin updates its own settings, they don't get saved back into bitlbee as the settings are only one-way. (Except for setting the account password, which is a workaround that some protocol plugins eg Hangouts and Slack use)

As you've found, to work out what it needs, it uses the equivalent of the 'Advanced' tab in Pidgin which doesn't show behind-the-scenes/hidden settings, which is why adding them to the plugin_init() is a good first step :) You'll also need to manually set those values in bitlbee (to pass to the plugin), which you can copy from your Pidgin settings account steam set access_token abc123

The other workaround could be to edit the code for https://github.com/EionRobb/pidgin-opensteamworks/blob/master/steam-mobile/libsteam.c#L1919 so that bitlbee counts as a "telepathy-haze" client, which will store settings in the libsecret (aka gnome-keyring), which gets around the one-way setting of... uh, settings.

Mzyxptlk commented 4 years ago

OK, I made some progress. Your first suggestion worked flawlessly. After creating the configuration variables and setting the values manually, I can login and re-login and everything looks fine. I could add some output to make the plugin tell the user to set those configuration values manually after the first login, but I'd rather it all happen automagically.

I'm having some trouble implementing the second workaround you suggest. I removed the access_token setting again (but not the emailsteamid one, which seems to be used when logging in?), added a global bool to keep track of whether we're in BitlBee, and use that bool in steamaccount(get|set)_access_token. Debug output confirms that I'm now using libsecret, but the behaviour is still the same: first login succeeds, subsequent ones fail.

To figure out what goes wrong, I passed a callback to my_secret_store_password and call secret_password_store_finish() from it to determine if the store succeeded. Turns out, I receive the following error when storing the access_token on my first login with a new steam guard code:

No such interface “org.freedesktop.Secret.Collection” on object at path /org/freedesktop/secrets/collection/login

I dug around on the web for a bit and found this StackOverflow answer, which linked this Arch wiki page. I followed the instructions under 'without a display manager', but that hasn't helped.

The bitlbee user doesn't have a real login session, but it also happens when I manually start dbus-daemon and gnome-keyring-daemon..

Here's my changes so far. It's just the global boolean, some debug output, and a small change in keyring_got_password() to make Emacs indentation play nice: bitlbee-pidgin.patch

I'm not really very familiar in this section of *nix space, so I'm not really sure how to proceed. Got any more pointers?

EionRobb commented 4 years ago

Wow, that's definitely more dedication to resolving this than I was expecting! :)

So after reading the links, it looks to me like libsecret isn't really the right answer for bitlbee after all. Asking a bitlbee server admin to jump through all those hoops to have something that maybe might possibly work, doesn't really feel right to me.

I suddenly had a thought, that maybe automating the "tell the user to set those config values manually" was something that I'd toyed with before, and it was! https://github.com/EionRobb/purple-hangouts/blob/master/hangouts_auth.c#L64-L92

So in the Hangouts prpl (before bitlbee added the method for prpls to set passwords in the parent app, using a signal) it'll try to load in the bitlbee .so and call functions on it in order to set settings in the bitlbee config. Using that in combo with making the options available in the plugin_load (like you have commented out in the patch, but maybe only displaying if the current UI is 'bitlbee'?) should save it persistently for bitlbee servers.

@dequis really really hates this code btw, but it's worked 'acceptably' in the past so..... 🤷 (just don't tell @dequis)

Mzyxptlk commented 4 years ago

What can I say, hacking on random code is my idea of fun, I guess. :)

Third attempt!

I copied over that function, made it a bit more generic to be able to use it with both emailsteamid and access_token, and removed the password-specific code from it. I call it from steam_account_set_access_token() and added a new function steam_account_set_steam_id(). In both functions, we check if we're using BitlBee, and if so, call the new setter function. Otherwise, call the normal purple_account_set_string(). I also re-enabled both options in plugin_init().

It still doesn't work, though. On my first connection attempt with a new steam guard code, steam_login() is called, the request succeeds and then steam_login_cb() calls steam_account_set_access_token() with a valid-looking access token. So far so good.

Next, steam_login_with_access_code() is called, but when it calls steam_account_get_access_code(), it gets back an empty string, causing the login to fail with the 401 mentioned in the TODO. It then resets the access_token and tries a bunch more times in rapid succession.

I looked around in purple-hangouts, but I can't find the place where the password is actually read back again. I currently just call purple_account_get_string(), is that right? The write succeeds, at least, the debug output proves that much.

New patch: bitlbee-pidgin-2.patch

Mzyxptlk commented 4 years ago

I've given up on the more elegant solution. Attached is a patch that adds the access_token and emailsteamid configuration parameters for BitlBee only, and then prompts the user to manually save the access token and Steam ID after the first login. It ain't pretty, but at least it works. :)

bitlbee-pidgin-3.patch