1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-10 01:48:00 +00:00

Fix dodgy strcats in access_random_seed().

Looking over this function today, I spotted several questionable uses
of strcat to concatenate "\PUTTY.RND" to the end of a pathname,
without having checked whether the pathname had filled up the static
fixed-size buffer already.

I don't think this is exploitable (because you'd have to be in control
of the local account already to control any of the data sources used
to fill those buffers). But it's horrible anyway, of course. Now all
of those are replaced with sensible dupcats.

(This patch re-indents a lot of the function, to give variables
tighter scopes. So the diff is best viewed with whitespace ignored.)
This commit is contained in:
Simon Tatham 2019-06-30 15:21:08 +01:00
parent 453cf99357
commit 721650bcb1

View File

@ -488,12 +488,17 @@ static bool try_random_seed(char const *path, int action, HANDLE *ret)
return (*ret != INVALID_HANDLE_VALUE);
}
static bool try_random_seed_and_free(char *path, int action, HANDLE *hout)
{
bool retd = try_random_seed(path, action, hout);
sfree(path);
return retd;
}
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
@ -510,17 +515,18 @@ static HANDLE access_random_seed(int action)
* 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",
0, &type, (BYTE *)seedpath, &size);
if (ret != ERROR_SUCCESS || type != REG_SZ)
seedpath[0] = '\0';
RegCloseKey(rkey);
if (*seedpath && try_random_seed(seedpath, action, &rethandle))
return rethandle;
{
char regpath[MAX_PATH + 1];
DWORD type, size = sizeof(regpath);
if (RegOpenKey(HKEY_CURRENT_USER, PUTTY_REG_POS, &rkey) ==
ERROR_SUCCESS) {
int ret = RegQueryValueEx(rkey, "RandSeedFile",
0, &type, (BYTE *)regpath, &size);
RegCloseKey(rkey);
if (ret == ERROR_SUCCESS && type == REG_SZ &&
try_random_seed(regpath, action, &rethandle))
return rethandle;
}
}
/*
@ -541,19 +547,20 @@ static HANDLE access_random_seed(int action)
tried_shgetfolderpath = true;
}
if (p_SHGetFolderPathA) {
char profile[MAX_PATH + 1];
if (SUCCEEDED(p_SHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA,
NULL, SHGFP_TYPE_CURRENT, seedpath))) {
strcat(seedpath, "\\PUTTY.RND");
if (try_random_seed(seedpath, action, &rethandle))
return rethandle;
}
NULL, SHGFP_TYPE_CURRENT, profile)) &&
try_random_seed_and_free(dupcat(profile, "\\PUTTY.RND",
(const char *)NULL),
action, &rethandle))
return rethandle;
if (SUCCEEDED(p_SHGetFolderPathA(NULL, CSIDL_APPDATA,
NULL, SHGFP_TYPE_CURRENT, seedpath))) {
strcat(seedpath, "\\PUTTY.RND");
if (try_random_seed(seedpath, action, &rethandle))
return rethandle;
}
NULL, SHGFP_TYPE_CURRENT, profile)) &&
try_random_seed_and_free(dupcat(profile, "\\PUTTY.RND",
(const char *)NULL),
action, &rethandle))
return rethandle;
}
/*
@ -561,28 +568,36 @@ static HANDLE access_random_seed(int action)
* user's home directory.
*/
{
int len, ret;
char drv[MAX_PATH], path[MAX_PATH];
len =
GetEnvironmentVariable("HOMEDRIVE", seedpath,
sizeof(seedpath));
ret =
GetEnvironmentVariable("HOMEPATH", seedpath + len,
sizeof(seedpath) - len);
if (ret != 0) {
strcat(seedpath, "\\PUTTY.RND");
if (try_random_seed(seedpath, action, &rethandle))
return rethandle;
}
DWORD drvlen = GetEnvironmentVariable("HOMEDRIVE", drv, sizeof(drv));
DWORD pathlen = GetEnvironmentVariable("HOMEPATH", path, sizeof(path));
/* We permit %HOMEDRIVE% to expand to an empty string, but if
* %HOMEPATH% does that, we abort the attempt. Same if either
* variable overflows its buffer. */
if (drvlen == 0)
drv[0] = '\0';
if (drvlen < lenof(drv) && pathlen < lenof(path) && pathlen > 0 &&
try_random_seed_and_free(
dupcat(drv, path, "\\PUTTY.RND", (const char *)NULL),
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;
{
char windir[MAX_PATH];
DWORD len = GetWindowsDirectory(windir, sizeof(windir));
if (len < lenof(windir) &&
try_random_seed_and_free(
dupcat(windir, "\\PUTTY.RND", (const char *)NULL),
action, &rethandle))
return rethandle;
}
/*
* If even that failed, give up.