X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/2e85c969d67eb14a07314802d4ac5dd63eef660b..dfb88efd1c9503370bee8e677bbefad6ef41df85:/windows/winpgnt.c diff --git a/windows/winpgnt.c b/windows/winpgnt.c index 6962ed89..21a69cc0 100644 --- a/windows/winpgnt.c +++ b/windows/winpgnt.c @@ -19,14 +19,17 @@ #ifndef NO_SECURITY #include +#ifdef DEBUG_IPC +#define _WIN32_WINNT 0x0500 /* for ConvertSidToStringSid */ +#include +#endif #endif #define IDI_MAINICON 200 #define IDI_TRAYICON 201 -#define WM_XUSER (WM_USER + 0x2000) -#define WM_SYSTRAY (WM_XUSER + 6) -#define WM_SYSTRAY2 (WM_XUSER + 7) +#define WM_SYSTRAY (WM_APP + 6) +#define WM_SYSTRAY2 (WM_APP + 7) #define AGENT_COPYDATA_ID 0x804e50ba /* random goop */ @@ -114,10 +117,10 @@ static tree234 *rsakeys, *ssh2keys; 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 /* @@ -156,22 +159,8 @@ struct blob { }; static int cmpkeys_ssh2_asymm(void *av, void *bv); -#define GET_32BIT(cp) \ - (((unsigned long)(unsigned char)(cp)[0] << 24) | \ - ((unsigned long)(unsigned char)(cp)[1] << 16) | \ - ((unsigned long)(unsigned char)(cp)[2] << 8) | \ - ((unsigned long)(unsigned char)(cp)[3])) - -#define PUT_32BIT(cp, value) { \ - (cp)[0] = (unsigned char)((value) >> 24); \ - (cp)[1] = (unsigned char)((value) >> 16); \ - (cp)[2] = (unsigned char)((value) >> 8); \ - (cp)[3] = (unsigned char)(value); } - -#define PASSPHRASE_MAXLEN 512 - struct PassphraseProcStruct { - char *passphrase; + char **passphrase; char *comment; }; @@ -185,7 +174,7 @@ static void forget_passphrases(void) { while (count234(passphrases) > 0) { char *pp = index234(passphrases, 0); - memset(pp, 0, strlen(pp)); + smemclr(pp, strlen(pp)); delpos234(passphrases, 0); free(pp); } @@ -256,7 +245,7 @@ static HWND passphrase_box; 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) { @@ -284,8 +273,9 @@ static int CALLBACK PassphraseProc(HWND hwnd, UINT 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)) { @@ -300,9 +290,8 @@ static int CALLBACK PassphraseProc(HWND hwnd, UINT msg, 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; } @@ -394,9 +383,9 @@ static void keylist_update(void) /* * 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; @@ -404,11 +393,10 @@ static void add_keyfile(Filename filename) 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)); @@ -428,7 +416,7 @@ static void add_keyfile(Filename filename) 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)); @@ -438,7 +426,8 @@ static void add_keyfile(Filename filename) 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, @@ -525,23 +514,30 @@ static void add_keyfile(Filename filename) 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); @@ -553,13 +549,16 @@ static void add_keyfile(Filename filename) 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) @@ -570,11 +569,14 @@ static void add_keyfile(Filename filename) 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); @@ -966,7 +968,7 @@ static void answer_msg(void *msg) 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 ... */ @@ -1482,15 +1484,15 @@ static int CALLBACK KeyListProc(HWND hwnd, UINT msg, rd.right - rd.left, rd.bottom - rd.top, TRUE); } - if (help_path) - SetWindowLong(hwnd, GWL_EXSTYLE, - GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_CONTEXTHELP); + if (has_help()) + SetWindowLongPtr(hwnd, GWL_EXSTYLE, + GetWindowLongPtr(hwnd, GWL_EXSTYLE) | + WS_EX_CONTEXTHELP); else { HWND item = GetDlgItem(hwnd, 103); /* the Help button */ if (item) DestroyWindow(item); } - requested_help = FALSE; keylist = hwnd; { @@ -1583,29 +1585,22 @@ static int CALLBACK KeyListProc(HWND hwnd, UINT msg, 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); } @@ -1699,6 +1694,53 @@ static void update_sessions(void) } } +#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) { @@ -1799,11 +1841,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, } 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: { @@ -1830,10 +1868,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, } 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: @@ -1843,10 +1878,9 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, 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; @@ -1866,46 +1900,54 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, #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 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)) { + 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 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); 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")); @@ -1918,9 +1960,9 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, { 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; @@ -1959,7 +2001,11 @@ void agent_schedule_callback(void (*callback)(void *, void *, int), 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; @@ -1994,10 +2040,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) /* * 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.", @@ -2017,22 +2060,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) /* * 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 @@ -2041,7 +2069,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) { 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; @@ -2058,67 +2086,14 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) /* * Find out if Pageant is already running. */ - already_running = FALSE; - if (agent_exists()) - already_running = TRUE; - else { - - if (!prev) { - wndclass.style = 0; - wndclass.lpfnWndProc = WndProc; - wndclass.cbClsExtra = 0; - wndclass.cbWndExtra = 0; - wndclass.hInstance = inst; - wndclass.hIcon = LoadIcon(inst, MAKEINTRESOURCE(IDI_MAINICON)); - wndclass.hCursor = LoadCursor(NULL, IDC_IBEAM); - wndclass.hbrBackground = GetStockObject(BLACK_BRUSH); - wndclass.lpszMenuName = NULL; - wndclass.lpszClassName = APPNAME; - - RegisterClass(&wndclass); - } - - keylist = NULL; - - hwnd = CreateWindow(APPNAME, APPNAME, - WS_OVERLAPPEDWINDOW | WS_VSCROLL, - CW_USEDEFAULT, CW_USEDEFAULT, - 100, 100, NULL, NULL, inst, NULL); - - /* Set up a system tray icon */ - AddTrayIcon(hwnd); - - /* Accelerators used: nsvkxa */ - systray_menu = CreatePopupMenu(); - if (putty_path) { - session_menu = CreateMenu(); - AppendMenu(systray_menu, MF_ENABLED, IDM_PUTTY, "&New Session"); - AppendMenu(systray_menu, MF_POPUP | MF_ENABLED, - (UINT) session_menu, "&Saved Sessions"); - AppendMenu(systray_menu, MF_SEPARATOR, 0, 0); - } - AppendMenu(systray_menu, MF_ENABLED, IDM_VIEWKEYS, - "&View Keys"); - AppendMenu(systray_menu, MF_ENABLED, IDM_ADDKEY, "Add &Key"); - AppendMenu(systray_menu, MF_SEPARATOR, 0, 0); - if (help_path) - AppendMenu(systray_menu, MF_ENABLED, IDM_HELP, "&Help"); - AppendMenu(systray_menu, MF_ENABLED, IDM_ABOUT, "&About"); - AppendMenu(systray_menu, MF_SEPARATOR, 0, 0); - AppendMenu(systray_menu, MF_ENABLED, IDM_CLOSE, "E&xit"); - initial_menuitems_count = GetMenuItemCount(session_menu); - - /* Set the default menu item. */ - SetMenuDefaultItem(systray_menu, IDM_VIEWKEYS, FALSE); + already_running = agent_exists(); - ShowWindow(hwnd, SW_HIDE); - - /* - * Initialise storage for RSA keys. - */ + /* + * Initialise storage for RSA keys. + */ + if (!already_running) { rsakeys = newtree234(cmpkeys_rsa); ssh2keys = newtree234(cmpkeys_ssh2); - } /* @@ -2131,7 +2106,12 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) */ split_into_argv(cmdline, &argc, &argv, &argstart); for (i = 0; i < argc; i++) { - if (!strcmp(argv[i], "-c")) { + if (!strcmp(argv[i], "-pgpfp")) { + pgp_fingerprints(); + if (advapi) + FreeLibrary(advapi); + return 1; + } else if (!strcmp(argv[i], "-c")) { /* * If we see `-c', then the rest of the * command line should be treated as a @@ -2182,6 +2162,56 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) return 0; } + if (!prev) { + wndclass.style = 0; + wndclass.lpfnWndProc = WndProc; + wndclass.cbClsExtra = 0; + wndclass.cbWndExtra = 0; + wndclass.hInstance = inst; + wndclass.hIcon = LoadIcon(inst, MAKEINTRESOURCE(IDI_MAINICON)); + wndclass.hCursor = LoadCursor(NULL, IDC_IBEAM); + wndclass.hbrBackground = GetStockObject(BLACK_BRUSH); + wndclass.lpszMenuName = NULL; + wndclass.lpszClassName = APPNAME; + + RegisterClass(&wndclass); + } + + keylist = NULL; + + hwnd = CreateWindow(APPNAME, APPNAME, + WS_OVERLAPPEDWINDOW | WS_VSCROLL, + CW_USEDEFAULT, CW_USEDEFAULT, + 100, 100, NULL, NULL, inst, NULL); + + /* Set up a system tray icon */ + AddTrayIcon(hwnd); + + /* Accelerators used: nsvkxa */ + systray_menu = CreatePopupMenu(); + if (putty_path) { + session_menu = CreateMenu(); + AppendMenu(systray_menu, MF_ENABLED, IDM_PUTTY, "&New Session"); + AppendMenu(systray_menu, MF_POPUP | MF_ENABLED, + (UINT) session_menu, "&Saved Sessions"); + AppendMenu(systray_menu, MF_SEPARATOR, 0, 0); + } + AppendMenu(systray_menu, MF_ENABLED, IDM_VIEWKEYS, + "&View Keys"); + AppendMenu(systray_menu, MF_ENABLED, IDM_ADDKEY, "Add &Key"); + AppendMenu(systray_menu, MF_SEPARATOR, 0, 0); + 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); + AppendMenu(systray_menu, MF_ENABLED, IDM_CLOSE, "E&xit"); + initial_menuitems_count = GetMenuItemCount(session_menu); + + /* Set the default menu item. */ + SetMenuDefaultItem(systray_menu, IDM_VIEWKEYS, FALSE); + + ShowWindow(hwnd, SW_HIDE); + /* * Main message loop. */ @@ -2210,5 +2240,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) if (advapi) FreeLibrary(advapi); - return msg.wParam; + + cleanup_exit(msg.wParam); + return msg.wParam; /* just in case optimiser complains */ }