1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-25 01:02:24 +00:00

Fix `win-randseed-location': use SHGetFolderPath() to find the

Application Data directory in preference to the old-fashioned
attempt to find the user's home directory, and use the _local-
machine_ Application Data directory in preference even to that.

SHGetFolderPath() is called via GetProcAddress, so this degrades
gracefully on old Windowses. (Tested myself on Win95.)

As part of this change, we now search for a location for the seed
file separately for reading and writing, so that installing the new
PuTTY should cause a seamless migration as the old seed file is read
from the old location and then a new one written to the new location.

`putty -cleanup' attempts to delete the seed file from _all_
affected locations.

Naturally, a user-specified seed file path in the Registry still
takes priority over all other means of finding the location.

[originally from svn r7082]
This commit is contained in:
Simon Tatham 2007-01-09 18:05:17 +00:00
parent 6c3f4b3baa
commit dbbd6eb5ec

View File

@ -9,12 +9,24 @@
#include "putty.h"
#include "storage.h"
#include <shlobj.h>
#ifndef CSIDL_APPDATA
#define CSIDL_APPDATA 0x001a
#endif
#ifndef CSIDL_LOCAL_APPDATA
#define CSIDL_LOCAL_APPDATA 0x001c
#endif
static const char *const puttystr = PUTTY_REG_POS "\\Sessions";
static char seedpath[2 * MAX_PATH + 10] = "\0";
static const char hex[16] = "0123456789ABCDEF";
static int tried_shgetfolderpath = FALSE;
static HMODULE shell32_module = NULL;
typedef HRESULT (WINAPI *p_SHGetFolderPath_t)
(HWND, int, HANDLE, DWORD, LPTSTR);
static p_SHGetFolderPath_t p_SHGetFolderPath = NULL;
static void mungestr(const char *in, char *out)
{
int candot = 0;
@ -415,15 +427,52 @@ void store_host_key(const char *hostname, int port,
}
/*
* Find the random seed file path and store it in `seedpath'.
* Open (or delete) the random seed file.
*/
static void get_seedpath(void)
enum { DEL, OPEN_R, OPEN_W };
static int try_random_seed(char const *path, int action, HANDLE *ret)
{
if (action == DEL) {
remove(path);
*ret = INVALID_HANDLE_VALUE;
return FALSE; /* so we'll do the next ones too */
}
*ret = CreateFile(path,
action == OPEN_W ? GENERIC_WRITE : GENERIC_READ,
action == OPEN_W ? 0 : (FILE_SHARE_READ |
FILE_SHARE_WRITE),
NULL,
action == OPEN_W ? CREATE_ALWAYS : OPEN_EXISTING,
action == OPEN_W ? FILE_ATTRIBUTE_NORMAL : 0,
NULL);
return (*ret != INVALID_HANDLE_VALUE);
}
static HANDLE access_random_seed(int action)
{
HKEY rkey;
DWORD type, size;
HANDLE rethandle;
char seedpath[2 * MAX_PATH + 10] = "\0";
/*
* Iterate over a selection of possible random seed paths until
* we find one that works.
*
* We do this iteration separately for reading and writing,
* meaning that we will automatically migrate random seed files
* if a better location becomes available (by reading from the
* best location in which we actually find one, and then
* writing to the best location in which we can _create_ one).
*/
/*
* First, try the location specified by the user in the
* Registry, if any.
*/
size = sizeof(seedpath);
if (RegOpenKey(HKEY_CURRENT_USER, PUTTY_REG_POS, &rkey) ==
ERROR_SUCCESS) {
int ret = RegQueryValueEx(rkey, "RandSeedFile",
@ -431,10 +480,45 @@ static void get_seedpath(void)
if (ret != ERROR_SUCCESS || type != REG_SZ)
seedpath[0] = '\0';
RegCloseKey(rkey);
} else
seedpath[0] = '\0';
if (!seedpath[0]) {
if (*seedpath && try_random_seed(seedpath, action, &rethandle))
return rethandle;
}
/*
* Next, try the user's local Application Data directory,
* followed by their non-local one. This is found using the
* SHGetFolderPath function, which won't be present on all
* versions of Windows.
*/
if (!tried_shgetfolderpath) {
shell32_module = LoadLibrary("SHELL32.DLL");
if (shell32_module) {
p_SHGetFolderPath = (p_SHGetFolderPath_t)
GetProcAddress(shell32_module, "SHGetFolderPathA");
}
}
if (p_SHGetFolderPath) {
if (SUCCEEDED(p_SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA,
NULL, SHGFP_TYPE_CURRENT, seedpath))) {
strcat(seedpath, "\\PUTTY.RND");
if (try_random_seed(seedpath, action, &rethandle))
return rethandle;
}
if (SUCCEEDED(p_SHGetFolderPath(NULL, CSIDL_APPDATA,
NULL, SHGFP_TYPE_CURRENT, seedpath))) {
strcat(seedpath, "\\PUTTY.RND");
if (try_random_seed(seedpath, action, &rethandle))
return rethandle;
}
}
/*
* Failing that, try %HOMEDRIVE%%HOMEPATH% as a guess at the
* user's home directory.
*/
{
int len, ret;
len =
@ -443,25 +527,30 @@ static void get_seedpath(void)
ret =
GetEnvironmentVariable("HOMEPATH", seedpath + len,
sizeof(seedpath) - len);
if (ret == 0) { /* probably win95; store in \WINDOWS */
GetWindowsDirectory(seedpath, sizeof(seedpath));
len = strlen(seedpath);
} else
len += ret;
strcpy(seedpath + len, "\\PUTTY.RND");
if (ret != 0) {
strcat(seedpath, "\\PUTTY.RND");
if (try_random_seed(seedpath, action, &rethandle))
return rethandle;
}
}
/*
* And finally, fall back to C:\WINDOWS.
*/
GetWindowsDirectory(seedpath, sizeof(seedpath));
strcat(seedpath, "\\PUTTY.RND");
if (try_random_seed(seedpath, action, &rethandle))
return rethandle;
/*
* If even that failed, give up.
*/
return INVALID_HANDLE_VALUE;
}
void read_random_seed(noise_consumer_t consumer)
{
HANDLE seedf;
if (!seedpath[0])
get_seedpath();
seedf = CreateFile(seedpath, GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, NULL);
HANDLE seedf = access_random_seed(OPEN_R);
if (seedf != INVALID_HANDLE_VALUE) {
while (1) {
@ -479,13 +568,7 @@ void read_random_seed(noise_consumer_t consumer)
void write_random_seed(void *data, int len)
{
HANDLE seedf;
if (!seedpath[0])
get_seedpath();
seedf = CreateFile(seedpath, GENERIC_WRITE, 0,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
HANDLE seedf = access_random_seed(OPEN_W);
if (seedf != INVALID_HANDLE_VALUE) {
DWORD lenwritten;
@ -521,11 +604,10 @@ void cleanup_all(void)
char name[MAX_PATH + 1];
/* ------------------------------------------------------------
* Wipe out the random seed file.
* Wipe out the random seed file, in all of its possible
* locations.
*/
if (!seedpath[0])
get_seedpath();
remove(seedpath);
access_random_seed(DEL);
/* ------------------------------------------------------------
* Destroy all registry information associated with PuTTY.