mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-09 17:38:00 +00:00
0ad344ca32
In the previous state of the code, we first tested agent_exists() to decide whether to be the long-running Pageant server or a short-lived client; then, during the command-line parsing loop, we prompted for passphrases to add keys presented on the command line (to ourself or the server, respectively); *then* we set up the named pipe and WM_COPYDATA receiver window to actually start functioning as a server, if we decided that was our role. A consequence is that if a user started up two Pageants each with an encrypted key on the command line, there would be a race condition: each one would decide that it was _going_ to be the server, then prompt for a passphrase, and then try to set itself up as the server once the passphrase is entered. So whichever one's passphrase prompt was answered second would add its key to its own internal data structures, then fail to set up the server's named pipe, terminate with an error, and end up not having added its key to the _surviving_ server. This change reorders the setup steps so that the command-line parsing loop does not add the keys immediately; instead it merely caches the key filenames provided. Then we make the decision about whether we're the server, and set up both the named pipe and WM_COPYDATA window if we are; and finally, we go back to our list of key filenames and actually add them, either to ourself (if we're the server) or to some other Pageant (if we're a client). Moreover, the decision about whether to be the server is now wrapped in an interprocess mutex similar to the one used in connection sharing, which means that even if two or more Pageants are started up as close to simultaneously as possible, they should avoid a race condition and successfully manage to agree on exactly one of themselves to be the server. For example, a user reported that this could occur if you put shortcuts to multiple private key files in your Windows Startup folder, so that they were all launched simultaneously at startup. One slightly odd behaviour that remains: if the server Pageant has to prompt for private key passphrases at startup, then it won't actually start _servicing_ requests from other Pageants until it's finished dealing with its own prompts. As a result, if you do start up two Pageants at once each with an encrypted key file on its command line, the second one won't even manage to present its passphrase prompt until the first one's prompt is dismissed, because it will block waiting for the initial check of the key list. But it will get there in the end, so that's only a cosmetic oddity. It would be nice to arrange that Pageant GUI operations don't block unrelated agent requests (e.g. by having the GUI and the agent code run in separate threads). But that's a bigger problem, not specific to startup time - the same thing happens if you interactively load a key via Pageant's file dialog. And it would require a major reorganisation to fix that fully, because currently the GUI code depends on being able to call _internal_ Pageant query functions like pageant_count_ssh2_keys() that don't work by constructing an agent request at all.
15 lines
348 B
C
15 lines
348 B
C
/*
|
|
* Return the full pathname of the global mutex that Pageant uses at
|
|
* startup to atomically decide whether to be a server or a client.
|
|
*/
|
|
|
|
#include "putty.h"
|
|
|
|
char *agent_mutex_name(void)
|
|
{
|
|
char *username = get_username();
|
|
char *mutexname = dupprintf("Local\\pageant-mutex.%s", username);
|
|
sfree(username);
|
|
return mutexname;
|
|
}
|