#ifndef NO_SECURITY
#include <aclapi.h>
+#ifdef DEBUG_IPC
+#define _WIN32_WINNT 0x0500 /* for ConvertSidToStringSid */
+#include <sddl.h>
+#endif
#endif
#define IDI_MAINICON 200
static int has_security;
#ifndef NO_SECURITY
-typedef DWORD(WINAPI * gsi_fn_t)
- (HANDLE, SE_OBJECT_TYPE, SECURITY_INFORMATION,
- PSID *, PSID *, PACL *, PACL *, PSECURITY_DESCRIPTOR *);
-static gsi_fn_t getsecurityinfo;
+DECL_WINDOWS_FUNCTION(extern, DWORD, GetSecurityInfo,
+ (HANDLE, SE_OBJECT_TYPE, SECURITY_INFORMATION,
+ PSID *, PSID *, PACL *, PACL *,
+ PSECURITY_DESCRIPTOR *));
#endif
/*
};
static int cmpkeys_ssh2_asymm(void *av, void *bv);
-#define PASSPHRASE_MAXLEN 512
-
struct PassphraseProcStruct {
- char *passphrase;
+ char **passphrase;
char *comment;
};
{
while (count234(passphrases) > 0) {
char *pp = index234(passphrases, 0);
- memset(pp, 0, strlen(pp));
+ smemclr(pp, strlen(pp));
delpos234(passphrases, 0);
free(pp);
}
static int CALLBACK PassphraseProc(HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam)
{
- static char *passphrase = NULL;
+ static char **passphrase = NULL;
struct PassphraseProcStruct *p;
switch (msg) {
passphrase = p->passphrase;
if (p->comment)
SetDlgItemText(hwnd, 101, p->comment);
- *passphrase = 0;
- SetDlgItemText(hwnd, 102, passphrase);
+ burnstr(*passphrase);
+ *passphrase = dupstr("");
+ SetDlgItemText(hwnd, 102, *passphrase);
return 0;
case WM_COMMAND:
switch (LOWORD(wParam)) {
return 0;
case 102: /* edit box */
if ((HIWORD(wParam) == EN_CHANGE) && passphrase) {
- GetDlgItemText(hwnd, 102, passphrase,
- PASSPHRASE_MAXLEN - 1);
- passphrase[PASSPHRASE_MAXLEN - 1] = '\0';
+ burnstr(*passphrase);
+ *passphrase = GetDlgItemText_alloc(hwnd, 102);
}
return 0;
}
0, (LPARAM) listentry);
}
for (i = 0; NULL != (skey = index234(ssh2keys, i)); i++) {
- char listentry[512], *p;
- int len;
+ char *listentry, *p;
+ int fp_len;
/*
* Replace two spaces in the fingerprint with tabs, for
* nice alignment in the box.
*/
p = skey->alg->fingerprint(skey->data);
- strncpy(listentry, p, sizeof(listentry));
+ listentry = dupprintf("%s\t%s", p, skey->comment);
+ fp_len = strlen(listentry);
+ sfree(p);
+
p = strchr(listentry, ' ');
- if (p)
+ if (p && p < listentry + fp_len)
*p = '\t';
p = strchr(listentry, ' ');
- if (p)
+ if (p && p < listentry + fp_len)
*p = '\t';
- len = strlen(listentry);
- if (len < sizeof(listentry) - 2) {
- listentry[len] = '\t';
- strncpy(listentry + len + 1, skey->comment,
- sizeof(listentry) - len - 1);
- }
+
SendDlgItemMessage(keylist, 100, LB_ADDSTRING, 0,
(LPARAM) listentry);
+ sfree(listentry);
}
SendDlgItemMessage(keylist, 100, LB_SETCURSEL, (WPARAM) - 1, 0);
}
/*
* This function loads a key from a file and adds it.
*/
-static void add_keyfile(Filename filename)
+static void add_keyfile(Filename *filename)
{
- char passphrase[PASSPHRASE_MAXLEN];
+ char *passphrase;
struct RSAKey *rkey = NULL;
struct ssh2_userkey *skey = NULL;
int needs_pass;
int attempts;
char *comment;
const char *error = NULL;
- struct PassphraseProcStruct pps;
int type;
int original_pass;
- type = key_type(&filename);
+ type = key_type(filename);
if (type != SSH_KEYTYPE_SSH1 && type != SSH_KEYTYPE_SSH2) {
char *msg = dupprintf("Couldn't load this key (%s)",
key_type_to_str(type));
int i, nkeys, bloblen, keylistlen;
if (type == SSH_KEYTYPE_SSH1) {
- if (!rsakey_pubblob(&filename, &blob, &bloblen, &error)) {
+ if (!rsakey_pubblob(filename, &blob, &bloblen, NULL, &error)) {
char *msg = dupprintf("Couldn't load private key (%s)", error);
message_box(msg, APPNAME, MB_OK | MB_ICONERROR,
HELPCTXID(errors_cantloadkey));
keylist = get_keylist1(&keylistlen);
} else {
unsigned char *blob2;
- blob = ssh2_userkey_loadpub(&filename, NULL, &bloblen, &error);
+ blob = ssh2_userkey_loadpub(filename, NULL, &bloblen,
+ NULL, &error);
if (!blob) {
char *msg = dupprintf("Couldn't load private key (%s)", error);
message_box(msg, APPNAME, MB_OK | MB_ICONERROR,
MB_OK | MB_ICONERROR);
return;
}
- nkeys = GET_32BIT(keylist);
+ nkeys = toint(GET_32BIT(keylist));
+ if (nkeys < 0) {
+ MessageBox(NULL, "Received broken key list?!", APPNAME,
+ MB_OK | MB_ICONERROR);
+ return;
+ }
p = keylist + 4;
keylistlen -= 4;
MB_OK | MB_ICONERROR);
return;
}
- n = 4 + GET_32BIT(p);
- if (keylistlen < n) {
+ n = toint(4 + GET_32BIT(p));
+ if (n < 0 || keylistlen < n) {
MessageBox(NULL, "Received broken key list?!", APPNAME,
MB_OK | MB_ICONERROR);
return;
MB_OK | MB_ICONERROR);
return;
}
- n = 4 + GET_32BIT(p);
- if (keylistlen < n) {
+ n = toint(4 + GET_32BIT(p));
+ if (n < 0 || keylistlen < n) {
MessageBox(NULL, "Received broken key list?!", APPNAME,
MB_OK | MB_ICONERROR);
return;
error = NULL;
if (type == SSH_KEYTYPE_SSH1)
- needs_pass = rsakey_encrypted(&filename, &comment);
+ needs_pass = rsakey_encrypted(filename, &comment);
else
- needs_pass = ssh2_userkey_encrypted(&filename, &comment);
+ needs_pass = ssh2_userkey_encrypted(filename, &comment);
attempts = 0;
if (type == SSH_KEYTYPE_SSH1)
rkey = snew(struct RSAKey);
- pps.passphrase = passphrase;
- pps.comment = comment;
+ passphrase = NULL;
original_pass = 0;
do {
+ burnstr(passphrase);
+ passphrase = NULL;
+
if (needs_pass) {
/* try all the remembered passphrases first */
char *pp = index234(passphrases, attempts);
if(pp) {
- strcpy(passphrase, pp);
+ passphrase = dupstr(pp);
} else {
int dlgret;
+ struct PassphraseProcStruct pps;
+
+ pps.passphrase = &passphrase;
+ pps.comment = comment;
+
original_pass = 1;
dlgret = DialogBoxParam(hinst, MAKEINTRESOURCE(210),
NULL, PassphraseProc, (LPARAM) &pps);
sfree(rkey);
return; /* operation cancelled */
}
+
+ assert(passphrase != NULL);
}
} else
- *passphrase = '\0';
+ passphrase = dupstr("");
+
if (type == SSH_KEYTYPE_SSH1)
- ret = loadrsakey(&filename, rkey, passphrase, &error);
+ ret = loadrsakey(filename, rkey, passphrase, &error);
else {
- skey = ssh2_load_userkey(&filename, passphrase, &error);
+ skey = ssh2_load_userkey(filename, passphrase, &error);
if (skey == SSH2_WRONG_PASSPHRASE)
ret = -1;
else if (!skey)
attempts++;
} while (ret == -1);
- /* if they typed in an ok passphrase, remember it */
if(original_pass && ret) {
- char *pp = dupstr(passphrase);
- addpos234(passphrases, pp, 0);
+ /* If they typed in an ok passphrase, remember it */
+ addpos234(passphrases, passphrase, 0);
+ } else {
+ /* Otherwise, destroy it */
+ burnstr(passphrase);
}
+ passphrase = NULL;
if (comment)
sfree(comment);
retval = agent_query(request, 5, &vresponse, &resplen, NULL, NULL);
assert(retval == 1);
response = vresponse;
- if (resplen < 5 || response[4] != SSH1_AGENT_RSA_IDENTITIES_ANSWER)
+ if (resplen < 5 || response[4] != SSH1_AGENT_RSA_IDENTITIES_ANSWER) {
+ sfree(response);
return NULL;
+ }
ret = snewn(resplen-5, unsigned char);
memcpy(ret, response+5, resplen-5);
retval = agent_query(request, 5, &vresponse, &resplen, NULL, NULL);
assert(retval == 1);
response = vresponse;
- if (resplen < 5 || response[4] != SSH2_AGENT_IDENTITIES_ANSWER)
+ if (resplen < 5 || response[4] != SSH2_AGENT_IDENTITIES_ANSWER) {
+ sfree(response);
return NULL;
+ }
ret = snewn(resplen-5, unsigned char);
memcpy(ret, response+5, resplen-5);
goto failure;
p += i;
i = ssh1_read_bignum(p, msgend - p, &reqkey.modulus);
- if (i < 0)
+ if (i < 0) {
+ freebn(reqkey.exponent);
goto failure;
+ }
p += i;
i = ssh1_read_bignum(p, msgend - p, &challenge);
- if (i < 0)
+ if (i < 0) {
+ freebn(reqkey.exponent);
+ freebn(reqkey.modulus);
goto failure;
+ }
p += i;
if (msgend < p+16) {
freebn(reqkey.exponent);
MD5Init(&md5c);
MD5Update(&md5c, response_source, 48);
MD5Final(response_md5, &md5c);
- memset(response_source, 0, 48); /* burn the evidence */
+ smemclr(response_source, 48); /* burn the evidence */
freebn(response); /* and that evidence */
freebn(challenge); /* yes, and that evidence */
freebn(reqkey.exponent); /* and free some memory ... */
if (msgend < p+4)
goto failure;
- b.len = GET_32BIT(p);
+ b.len = toint(GET_32BIT(p));
+ if (b.len < 0 || b.len > msgend - (p+4))
+ goto failure;
p += 4;
- if (msgend < p+b.len)
- goto failure;
b.blob = p;
p += b.len;
if (msgend < p+4)
goto failure;
- datalen = GET_32BIT(p);
+ datalen = toint(GET_32BIT(p));
p += 4;
- if (msgend < p+datalen)
+ if (datalen < 0 || datalen > msgend - p)
goto failure;
data = p;
key = find234(ssh2keys, &b, cmpkeys_ssh2_asymm);
sfree(key);
goto failure;
}
- commentlen = GET_32BIT(p);
+ commentlen = toint(GET_32BIT(p));
- if (msgend < p+commentlen) {
+ if (commentlen < 0 || commentlen > msgend - p) {
freersakey(key);
sfree(key);
goto failure;
if (msgend < p+4)
goto failure;
- alglen = GET_32BIT(p);
+ alglen = toint(GET_32BIT(p));
p += 4;
- if (msgend < p+alglen)
+ if (alglen < 0 || alglen > msgend - p)
goto failure;
alg = p;
p += alglen;
sfree(key);
goto failure;
}
- commlen = GET_32BIT(p);
+ commlen = toint(GET_32BIT(p));
p += 4;
- if (msgend < p+commlen) {
+ if (commlen < 0 || commlen > msgend - p) {
key->alg->freekey(key->data);
sfree(key);
goto failure;
if (msgend < p+4)
goto failure;
- b.len = GET_32BIT(p);
+ b.len = toint(GET_32BIT(p));
p += 4;
- if (msgend < p+b.len)
+ if (b.len < 0 || b.len > msgend - p)
goto failure;
b.blob = p;
p += b.len;
of.lpstrTitle = "Select Private Key File";
of.Flags = OFN_ALLOWMULTISELECT | OFN_EXPLORER;
if (request_file(keypath, &of, TRUE, FALSE)) {
- if(strlen(filelist) > of.nFileOffset)
+ if(strlen(filelist) > of.nFileOffset) {
/* Only one filename returned? */
- add_keyfile(filename_from_str(filelist));
- else {
+ Filename *fn = filename_from_str(filelist);
+ add_keyfile(fn);
+ filename_free(fn);
+ } else {
/* we are returned a bunch of strings, end to
* end. first string is the directory, the
* rest the filenames. terminated with an
char *filewalker = filelist + strlen(dir) + 1;
while (*filewalker != '\0') {
char *filename = dupcat(dir, "\\", filewalker, NULL);
- add_keyfile(filename_from_str(filename));
+ Filename *fn = filename_from_str(filename);
+ add_keyfile(fn);
+ filename_free(fn);
sfree(filename);
filewalker += strlen(filewalker) + 1;
}
rd.right - rd.left, rd.bottom - rd.top, TRUE);
}
- if (help_path)
+ if (has_help())
SetWindowLongPtr(hwnd, GWL_EXSTYLE,
GetWindowLongPtr(hwnd, GWL_EXSTYLE) |
WS_EX_CONTEXTHELP);
if (item)
DestroyWindow(item);
}
- requested_help = FALSE;
keylist = hwnd;
{
case 103: /* help */
if (HIWORD(wParam) == BN_CLICKED ||
HIWORD(wParam) == BN_DOUBLECLICKED) {
- if (help_path) {
- WinHelp(hwnd, help_path, HELP_COMMAND,
- (DWORD)"JI(`',`pageant.general')");
- requested_help = TRUE;
- }
+ launch_help(hwnd, WINHELP_CTX_pageant_general);
}
return 0;
}
return 0;
case WM_HELP:
- if (help_path) {
+ {
int id = ((LPHELPINFO)lParam)->iCtrlId;
char *topic = NULL;
switch (id) {
- case 100: topic = "pageant.keylist"; break;
- case 101: topic = "pageant.addkey"; break;
- case 102: topic = "pageant.remkey"; break;
+ case 100: topic = WINHELP_CTX_pageant_keylist; break;
+ case 101: topic = WINHELP_CTX_pageant_addkey; break;
+ case 102: topic = WINHELP_CTX_pageant_remkey; break;
}
if (topic) {
- char *cmd = dupprintf("JI(`',`%s')", topic);
- WinHelp(hwnd, help_path, HELP_COMMAND, (DWORD)cmd);
- sfree(cmd);
- requested_help = TRUE;
+ launch_help(hwnd, topic);
} else {
MessageBeep(0);
}
}
}
+#ifndef NO_SECURITY
+/*
+ * Versions of Pageant prior to 0.61 expected this SID on incoming
+ * communications. For backwards compatibility, and more particularly
+ * for compatibility with derived works of PuTTY still using the old
+ * Pageant client code, we accept it as an alternative to the one
+ * returned from get_user_sid() in winpgntc.c.
+ */
+PSID get_default_sid(void)
+{
+ HANDLE proc = NULL;
+ DWORD sidlen;
+ PSECURITY_DESCRIPTOR psd = NULL;
+ PSID sid = NULL, copy = NULL, ret = NULL;
+
+ if ((proc = OpenProcess(MAXIMUM_ALLOWED, FALSE,
+ GetCurrentProcessId())) == NULL)
+ goto cleanup;
+
+ if (p_GetSecurityInfo(proc, SE_KERNEL_OBJECT, OWNER_SECURITY_INFORMATION,
+ &sid, NULL, NULL, NULL, &psd) != ERROR_SUCCESS)
+ goto cleanup;
+
+ sidlen = GetLengthSid(sid);
+
+ copy = (PSID)smalloc(sidlen);
+
+ if (!CopySid(sidlen, copy, sid))
+ goto cleanup;
+
+ /* Success. Move sid into the return value slot, and null it out
+ * to stop the cleanup code freeing it. */
+ ret = copy;
+ copy = NULL;
+
+ cleanup:
+ if (proc != NULL)
+ CloseHandle(proc);
+ if (psd != NULL)
+ LocalFree(psd);
+ if (copy != NULL)
+ sfree(copy);
+
+ return ret;
+}
+#endif
+
static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
}
break;
case IDM_HELP:
- if (help_path) {
- WinHelp(hwnd, help_path, HELP_COMMAND,
- (DWORD)"JI(`',`pageant.general')");
- requested_help = TRUE;
- }
+ launch_help(hwnd, WINHELP_CTX_pageant_general);
break;
default:
{
}
break;
case WM_DESTROY:
- if (requested_help) {
- WinHelp(hwnd, help_path, HELP_QUIT, 0);
- requested_help = FALSE;
- }
+ quit_help(hwnd);
PostQuitMessage(0);
return 0;
case WM_COPYDATA:
void *p;
HANDLE filemap;
#ifndef NO_SECURITY
- HANDLE proc;
- PSID mapowner, procowner;
- PSECURITY_DESCRIPTOR psd1 = NULL, psd2 = NULL;
+ PSID mapowner, ourself, ourself2;
#endif
+ PSECURITY_DESCRIPTOR psd = NULL;
int ret = 0;
cds = (COPYDATASTRUCT *) lParam;
#ifndef NO_SECURITY
int rc;
if (has_security) {
- if ((proc = OpenProcess(MAXIMUM_ALLOWED, FALSE,
- GetCurrentProcessId())) ==
- NULL) {
+ if ((ourself = get_user_sid()) == NULL) {
#ifdef DEBUG_IPC
- debug(("couldn't get handle for process\n"));
+ debug(("couldn't get user SID\n"));
#endif
+ CloseHandle(filemap);
return 0;
- }
- if (getsecurityinfo(proc, SE_KERNEL_OBJECT,
- OWNER_SECURITY_INFORMATION,
- &procowner, NULL, NULL, NULL,
- &psd2) != ERROR_SUCCESS) {
+ }
+
+ if ((ourself2 = get_default_sid()) == NULL) {
#ifdef DEBUG_IPC
- debug(("couldn't get owner info for process\n"));
+ debug(("couldn't get default SID\n"));
#endif
- CloseHandle(proc);
- return 0; /* unable to get security info */
- }
- CloseHandle(proc);
- if ((rc = getsecurityinfo(filemap, SE_KERNEL_OBJECT,
- OWNER_SECURITY_INFORMATION,
- &mapowner, NULL, NULL, NULL,
- &psd1) != ERROR_SUCCESS)) {
+ CloseHandle(filemap);
+ sfree(ourself);
+ return 0;
+ }
+
+ if ((rc = p_GetSecurityInfo(filemap, SE_KERNEL_OBJECT,
+ OWNER_SECURITY_INFORMATION,
+ &mapowner, NULL, NULL, NULL,
+ &psd) != ERROR_SUCCESS)) {
#ifdef DEBUG_IPC
- debug(
- ("couldn't get owner info for filemap: %d\n",
- rc));
+ debug(("couldn't get owner info for filemap: %d\n",
+ rc));
#endif
+ CloseHandle(filemap);
+ sfree(ourself);
+ sfree(ourself2);
return 0;
}
#ifdef DEBUG_IPC
- debug(("got security stuff\n"));
+ {
+ LPTSTR ours, ours2, theirs;
+ ConvertSidToStringSid(mapowner, &theirs);
+ ConvertSidToStringSid(ourself, &ours);
+ ConvertSidToStringSid(ourself2, &ours2);
+ debug(("got sids:\n oursnew=%s\n oursold=%s\n"
+ " theirs=%s\n", ours, ours2, theirs));
+ LocalFree(ours);
+ LocalFree(ours2);
+ LocalFree(theirs);
+ }
#endif
- if (!EqualSid(mapowner, procowner))
+ if (!EqualSid(mapowner, ourself) &&
+ !EqualSid(mapowner, ourself2)) {
+ CloseHandle(filemap);
+ LocalFree(psd);
+ sfree(ourself);
+ sfree(ourself2);
return 0; /* security ID mismatch! */
+ }
#ifdef DEBUG_IPC
debug(("security stuff matched\n"));
#endif
- LocalFree(psd1);
- LocalFree(psd2);
+ LocalFree(psd);
+ sfree(ourself);
+ sfree(ourself2);
} else {
#ifdef DEBUG_IPC
debug(("security APIs not present\n"));
{
int i;
for (i = 0; i < 5; i++)
- debug(
- ("p[%d]=%02x\n", i,
- ((unsigned char *) p)[i]));}
+ debug(("p[%d]=%02x\n", i,
+ ((unsigned char *) p)[i]));
+ }
#endif
answer_msg(p);
ret = 1;
assert(!"We shouldn't get here");
}
-void cleanup_exit(int code) { exit(code); }
+void cleanup_exit(int code)
+{
+ shutdown_help();
+ exit(code);
+}
int flags = FLAG_SYNCAGENT;
{
WNDCLASS wndclass;
MSG msg;
- HMODULE advapi;
char *command = NULL;
int added_keys = 0;
int argc, i;
/*
* Attempt to get the security API we need.
*/
- advapi = LoadLibrary("ADVAPI32.DLL");
- getsecurityinfo =
- (gsi_fn_t) GetProcAddress(advapi, "GetSecurityInfo");
- if (!getsecurityinfo) {
+ if (!init_advapi()) {
MessageBox(NULL,
"Unable to access security APIs. Pageant will\n"
"not run, in case it causes a security breach.",
"Pageant Fatal Error", MB_ICONERROR | MB_OK);
return 1;
#endif
- } else
- advapi = NULL;
+ }
/*
* See if we can find our Help file.
*/
- {
- char b[2048], *p, *q, *r;
- FILE *fp;
- GetModuleFileName(NULL, b, sizeof(b) - 1);
- r = b;
- p = strrchr(b, '\\');
- if (p && p >= r) r = p+1;
- q = strrchr(b, ':');
- if (q && q >= r) r = q+1;
- strcpy(r, PUTTY_HELP_FILE);
- if ( (fp = fopen(b, "r")) != NULL) {
- help_path = dupstr(b);
- fclose(fp);
- } else
- help_path = NULL;
- }
+ init_help();
/*
* Look for the PuTTY binary (we will enable the saved session
{
char b[2048], *p, *q, *r;
FILE *fp;
- GetModuleFileName(NULL, b, sizeof(b) - 1);
+ GetModuleFileName(NULL, b, sizeof(b) - 16);
r = b;
p = strrchr(b, '\\');
if (p && p >= r) r = p+1;
for (i = 0; i < argc; i++) {
if (!strcmp(argv[i], "-pgpfp")) {
pgp_fingerprints();
- if (advapi)
- FreeLibrary(advapi);
return 1;
} else if (!strcmp(argv[i], "-c")) {
/*
command = "";
break;
} else {
- add_keyfile(filename_from_str(argv[i]));
+ Filename *fn = filename_from_str(argv[i]);
+ add_keyfile(fn);
+ filename_free(fn);
added_keys = TRUE;
}
}
MessageBox(NULL, "Pageant is already running", "Pageant Error",
MB_ICONERROR | MB_OK);
}
- if (advapi)
- FreeLibrary(advapi);
return 0;
}
"&View Keys");
AppendMenu(systray_menu, MF_ENABLED, IDM_ADDKEY, "Add &Key");
AppendMenu(systray_menu, MF_SEPARATOR, 0, 0);
- if (help_path)
+ if (has_help())
AppendMenu(systray_menu, MF_ENABLED, IDM_HELP, "&Help");
AppendMenu(systray_menu, MF_ENABLED, IDM_ABOUT, "&About");
AppendMenu(systray_menu, MF_SEPARATOR, 0, 0);
if (keypath) filereq_free(keypath);
- if (advapi)
- FreeLibrary(advapi);
- return msg.wParam;
+ cleanup_exit(msg.wParam);
+ return msg.wParam; /* just in case optimiser complains */
}