X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=blobdiff_plain;f=windows%2Fwinpgnt.c;h=828747dac62a83bdb391f616d53c934bc510f730;hb=d23c0972cd850c77871f9a314e0520d7023c8b62;hp=9d593274fbafa52909547ddab155af6ba26655ad;hpb=62cbc7dc0b33808dc8794c59f60971fbba97894b;p=PuTTY.git diff --git a/windows/winpgnt.c b/windows/winpgnt.c index 9d593274..828747da 100644 --- a/windows/winpgnt.c +++ b/windows/winpgnt.c @@ -14,6 +14,7 @@ #include "ssh.h" #include "misc.h" #include "tree234.h" +#include "winsecur.h" #include @@ -116,12 +117,6 @@ static void unmungestr(char *in, char *out, int outlen) static tree234 *rsakeys, *ssh2keys; static int has_security; -#ifndef NO_SECURITY -DECL_WINDOWS_FUNCTION(extern, DWORD, GetSecurityInfo, - (HANDLE, SE_OBJECT_TYPE, SECURITY_INFORMATION, - PSID *, PSID *, PACL *, PACL *, - PSECURITY_DESCRIPTOR *)); -#endif /* * Forward references @@ -159,10 +154,8 @@ struct blob { }; static int cmpkeys_ssh2_asymm(void *av, void *bv); -#define PASSPHRASE_MAXLEN 512 - struct PassphraseProcStruct { - char *passphrase; + char **passphrase; char *comment; }; @@ -176,7 +169,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); } @@ -247,7 +240,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) { @@ -275,8 +268,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)) { @@ -291,9 +285,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; } @@ -355,28 +348,29 @@ static void keylist_update(void) 0, (LPARAM) listentry); } for (i = 0; NULL != (skey = index234(ssh2keys, i)); i++) { - char listentry[512], *p; - int len; + char *listentry, *p; + int pos, fp_len; /* - * Replace two spaces in the fingerprint with tabs, for - * nice alignment in the box. + * Replace spaces with tabs in the fingerprint prefix, for + * nice alignment in the list box, until we encounter a : + * meaning we're into the fingerprint proper. */ p = skey->alg->fingerprint(skey->data); - strncpy(listentry, p, sizeof(listentry)); - p = strchr(listentry, ' '); - if (p) - *p = '\t'; - p = strchr(listentry, ' '); - if (p) - *p = '\t'; - len = strlen(listentry); - if (len < sizeof(listentry) - 2) { - listentry[len] = '\t'; - strncpy(listentry + len + 1, skey->comment, - sizeof(listentry) - len - 1); - } + listentry = dupprintf("%s\t%s", p, skey->comment); + fp_len = strlen(listentry); + sfree(p); + + pos = 0; + while (1) { + pos += strcspn(listentry + pos, " :"); + if (listentry[pos] == ':') + break; + listentry[pos++] = '\t'; + } + SendDlgItemMessage(keylist, 100, LB_ADDSTRING, 0, (LPARAM) listentry); + sfree(listentry); } SendDlgItemMessage(keylist, 100, LB_SETCURSEL, (WPARAM) - 1, 0); } @@ -387,7 +381,7 @@ static void keylist_update(void) */ static void add_keyfile(Filename *filename) { - char passphrase[PASSPHRASE_MAXLEN]; + char *passphrase; struct RSAKey *rkey = NULL; struct ssh2_userkey *skey = NULL; int needs_pass; @@ -395,7 +389,6 @@ static void add_keyfile(Filename *filename) int attempts; char *comment; const char *error = NULL; - struct PassphraseProcStruct pps; int type; int original_pass; @@ -453,7 +446,12 @@ static void add_keyfile(Filename *filename) 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; @@ -481,8 +479,8 @@ static void add_keyfile(Filename *filename) 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; @@ -498,8 +496,8 @@ static void add_keyfile(Filename *filename) 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; @@ -523,17 +521,24 @@ static void add_keyfile(Filename *filename) 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); @@ -545,9 +550,12 @@ 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); else { @@ -562,11 +570,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); @@ -797,8 +808,10 @@ static void *get_keylist1(int *length) 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); @@ -832,8 +845,10 @@ static void *get_keylist2(int *length) 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); @@ -928,12 +943,17 @@ static void answer_msg(void *msg) 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); @@ -958,7 +978,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 ... */ @@ -988,17 +1008,17 @@ static void answer_msg(void *msg) 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); @@ -1071,9 +1091,9 @@ static void answer_msg(void *msg) 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; @@ -1110,9 +1130,9 @@ static void answer_msg(void *msg) 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; @@ -1123,6 +1143,12 @@ static void answer_msg(void *msg) key->alg = &ssh_rsa; else if (alglen == 7 && !memcmp(alg, "ssh-dss", 7)) key->alg = &ssh_dss; + else if (alglen == 19 && memcmp(alg, "ecdsa-sha2-nistp256", 19)) + key->alg = &ssh_ecdsa_nistp256; + else if (alglen == 19 && memcmp(alg, "ecdsa-sha2-nistp384", 19)) + key->alg = &ssh_ecdsa_nistp384; + else if (alglen == 19 && memcmp(alg, "ecdsa-sha2-nistp521", 19)) + key->alg = &ssh_ecdsa_nistp521; else { sfree(key); goto failure; @@ -1146,10 +1172,10 @@ static void answer_msg(void *msg) 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; @@ -1213,10 +1239,10 @@ static void answer_msg(void *msg) 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; @@ -1423,10 +1449,12 @@ static void prompt_add_keyfile(void) 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 @@ -1436,7 +1464,9 @@ static void prompt_add_keyfile(void) 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; } @@ -1486,7 +1516,7 @@ static int CALLBACK KeyListProc(HWND hwnd, UINT msg, keylist = hwnd; { - static int tabs[] = { 35, 60, 210 }; + static int tabs[] = { 35, 75, 250 }; SendDlgItemMessage(hwnd, 100, LB_SETTABSTOPS, sizeof(tabs) / sizeof(*tabs), (LPARAM) tabs); @@ -1894,6 +1924,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, #ifdef DEBUG_IPC debug(("couldn't get user SID\n")); #endif + CloseHandle(filemap); return 0; } @@ -1901,6 +1932,8 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, #ifdef DEBUG_IPC debug(("couldn't get default SID\n")); #endif + CloseHandle(filemap); + sfree(ourself); return 0; } @@ -1912,6 +1945,9 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, debug(("couldn't get owner info for filemap: %d\n", rc)); #endif + CloseHandle(filemap); + sfree(ourself); + sfree(ourself2); return 0; } #ifdef DEBUG_IPC @@ -1928,8 +1964,13 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, } #endif if (!EqualSid(mapowner, ourself) && - !EqualSid(mapowner, ourself2)) + !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 @@ -2001,7 +2042,6 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) { WNDCLASS wndclass; MSG msg; - HMODULE advapi; char *command = NULL; int added_keys = 0; int argc, i; @@ -2028,7 +2068,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) /* * Attempt to get the security API we need. */ - if (!init_advapi()) { + if (!got_advapi()) { MessageBox(NULL, "Unable to access security APIs. Pageant will\n" "not run, in case it causes a security breach.", @@ -2042,8 +2082,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) "Pageant Fatal Error", MB_ICONERROR | MB_OK); return 1; #endif - } else - advapi = NULL; + } /* * See if we can find our Help file. @@ -2096,8 +2135,6 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) 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")) { /* @@ -2111,7 +2148,9 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) 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; } } @@ -2145,8 +2184,6 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) MessageBox(NULL, "Pageant is already running", "Pageant Error", MB_ICONERROR | MB_OK); } - if (advapi) - FreeLibrary(advapi); return 0; } @@ -2226,9 +2263,6 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) if (keypath) filereq_free(keypath); - if (advapi) - FreeLibrary(advapi); - cleanup_exit(msg.wParam); return msg.wParam; /* just in case optimiser complains */ }