📄 pageant.c
字号:
alg = p;
p += alglen;
key = snew(struct ssh2_userkey);
/* Add further algorithm names here. */
if (alglen == 7 && !memcmp(alg, "ssh-rsa", 7))
key->alg = &ssh_rsa;
else if (alglen == 7 && !memcmp(alg, "ssh-dss", 7))
key->alg = &ssh_dss;
else {
sfree(key);
goto failure;
}
bloblen = msgend - p;
key->data = key->alg->openssh_createkey(&p, &bloblen);
if (!key->data) {
sfree(key);
goto failure;
}
/*
* p has been advanced by openssh_createkey, but
* certainly not _beyond_ the end of the buffer.
*/
assert(p <= msgend);
if (msgend < p+4) {
key->alg->freekey(key->data);
sfree(key);
goto failure;
}
commlen = GET_32BIT(p);
p += 4;
if (msgend < p+commlen) {
key->alg->freekey(key->data);
sfree(key);
goto failure;
}
comment = snewn(commlen + 1, char);
if (comment) {
memcpy(comment, p, commlen);
comment[commlen] = '\0';
}
key->comment = comment;
PUT_32BIT(ret, 1);
ret[4] = SSH_AGENT_FAILURE;
if (add234(ssh2keys, key) == key) {
keylist_update();
ret[4] = SSH_AGENT_SUCCESS;
} else {
key->alg->freekey(key->data);
sfree(key->comment);
sfree(key);
}
}
break;
case SSH1_AGENTC_REMOVE_RSA_IDENTITY:
/*
* Remove from the list and return SSH_AGENT_SUCCESS, or
* perhaps SSH_AGENT_FAILURE if it wasn't in the list to
* start with.
*/
{
struct RSAKey reqkey, *key;
int n;
n = makekey(p, msgend - p, &reqkey, NULL, 0);
if (n < 0)
goto failure;
key = find234(rsakeys, &reqkey, NULL);
freebn(reqkey.exponent);
freebn(reqkey.modulus);
PUT_32BIT(ret, 1);
ret[4] = SSH_AGENT_FAILURE;
if (key) {
del234(rsakeys, key);
keylist_update();
freersakey(key);
sfree(key);
ret[4] = SSH_AGENT_SUCCESS;
}
}
break;
case SSH2_AGENTC_REMOVE_IDENTITY:
/*
* Remove from the list and return SSH_AGENT_SUCCESS, or
* perhaps SSH_AGENT_FAILURE if it wasn't in the list to
* start with.
*/
{
struct ssh2_userkey *key;
struct blob b;
if (msgend < p+4)
goto failure;
b.len = GET_32BIT(p);
p += 4;
if (msgend < p+b.len)
goto failure;
b.blob = p;
p += b.len;
key = find234(ssh2keys, &b, cmpkeys_ssh2_asymm);
if (!key)
goto failure;
PUT_32BIT(ret, 1);
ret[4] = SSH_AGENT_FAILURE;
if (key) {
del234(ssh2keys, key);
keylist_update();
key->alg->freekey(key->data);
sfree(key);
ret[4] = SSH_AGENT_SUCCESS;
}
}
break;
case SSH1_AGENTC_REMOVE_ALL_RSA_IDENTITIES:
/*
* Remove all SSH1 keys. Always returns success.
*/
{
struct RSAKey *rkey;
while ((rkey = index234(rsakeys, 0)) != NULL) {
del234(rsakeys, rkey);
freersakey(rkey);
sfree(rkey);
}
keylist_update();
PUT_32BIT(ret, 1);
ret[4] = SSH_AGENT_SUCCESS;
}
break;
case SSH2_AGENTC_REMOVE_ALL_IDENTITIES:
/*
* Remove all SSH2 keys. Always returns success.
*/
{
struct ssh2_userkey *skey;
while ((skey = index234(ssh2keys, 0)) != NULL) {
del234(ssh2keys, skey);
skey->alg->freekey(skey->data);
sfree(skey);
}
keylist_update();
PUT_32BIT(ret, 1);
ret[4] = SSH_AGENT_SUCCESS;
}
break;
default:
failure:
/*
* Unrecognised message. Return SSH_AGENT_FAILURE.
*/
PUT_32BIT(ret, 1);
ret[4] = SSH_AGENT_FAILURE;
break;
}
}
/*
* Key comparison function for the 2-3-4 tree of RSA keys.
*/
static int cmpkeys_rsa(void *av, void *bv)
{
struct RSAKey *a = (struct RSAKey *) av;
struct RSAKey *b = (struct RSAKey *) bv;
Bignum am, bm;
int alen, blen;
am = a->modulus;
bm = b->modulus;
/*
* Compare by length of moduli.
*/
alen = bignum_bitcount(am);
blen = bignum_bitcount(bm);
if (alen > blen)
return +1;
else if (alen < blen)
return -1;
/*
* Now compare by moduli themselves.
*/
alen = (alen + 7) / 8; /* byte count */
while (alen-- > 0) {
int abyte, bbyte;
abyte = bignum_byte(am, alen);
bbyte = bignum_byte(bm, alen);
if (abyte > bbyte)
return +1;
else if (abyte < bbyte)
return -1;
}
/*
* Give up.
*/
return 0;
}
/*
* Key comparison function for the 2-3-4 tree of SSH2 keys.
*/
static int cmpkeys_ssh2(void *av, void *bv)
{
struct ssh2_userkey *a = (struct ssh2_userkey *) av;
struct ssh2_userkey *b = (struct ssh2_userkey *) bv;
int i;
int alen, blen;
unsigned char *ablob, *bblob;
int c;
/*
* Compare purely by public blob.
*/
ablob = a->alg->public_blob(a->data, &alen);
bblob = b->alg->public_blob(b->data, &blen);
c = 0;
for (i = 0; i < alen && i < blen; i++) {
if (ablob[i] < bblob[i]) {
c = -1;
break;
} else if (ablob[i] > bblob[i]) {
c = +1;
break;
}
}
if (c == 0 && i < alen)
c = +1; /* a is longer */
if (c == 0 && i < blen)
c = -1; /* a is longer */
sfree(ablob);
sfree(bblob);
return c;
}
/*
* Key comparison function for looking up a blob in the 2-3-4 tree
* of SSH2 keys.
*/
static int cmpkeys_ssh2_asymm(void *av, void *bv)
{
struct blob *a = (struct blob *) av;
struct ssh2_userkey *b = (struct ssh2_userkey *) bv;
int i;
int alen, blen;
unsigned char *ablob, *bblob;
int c;
/*
* Compare purely by public blob.
*/
ablob = a->blob;
alen = a->len;
bblob = b->alg->public_blob(b->data, &blen);
c = 0;
for (i = 0; i < alen && i < blen; i++) {
if (ablob[i] < bblob[i]) {
c = -1;
break;
} else if (ablob[i] > bblob[i]) {
c = +1;
break;
}
}
if (c == 0 && i < alen)
c = +1; /* a is longer */
if (c == 0 && i < blen)
c = -1; /* a is longer */
sfree(bblob);
return c;
}
/*
* Prompt for a key file to add, and add it.
*/
static void prompt_add_keyfile(void)
{
OPENFILENAME of;
char filename[FILENAME_MAX];
char *filelist = snewn(8192, char);
char *filewalker;
int n, dirlen;
memset(&of, 0, sizeof(of));
#ifdef OPENFILENAME_SIZE_VERSION_400
of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
#else
of.lStructSize = sizeof(of);
#endif
of.hwndOwner = main_hwnd;
of.lpstrFilter = "PuTTY Private Key Files (*.ppk)\0*.ppk\0"
"All Files (*.*)\0*\0\0\0";
of.lpstrCustomFilter = NULL;
of.nFilterIndex = 1;
of.lpstrFile = filelist;
*filelist = '\0';
of.nMaxFile = FILENAME_MAX;
of.lpstrFileTitle = NULL;
of.lpstrInitialDir = NULL;
of.lpstrTitle = "Select Private Key File";
of.Flags = OFN_ALLOWMULTISELECT | OFN_EXPLORER;
if (GetOpenFileName(&of)) {
if(strlen(filelist) > of.nFileOffset)
/* Only one filename returned? */
add_keyfile(filename_from_str(filelist));
else {
/* we are returned a bunch of strings, end to
* end. first string is the directory, the
* rest the filenames. terminated with an
* empty string.
*/
filewalker = filelist;
dirlen = strlen(filewalker);
if(dirlen > FILENAME_MAX - 8) return;
memcpy(filename, filewalker, dirlen);
filewalker += dirlen + 1;
filename[dirlen++] = '\\';
/* then go over names one by one */
for(;;) {
n = strlen(filewalker) + 1;
/* end of the list */
if(n == 1)
break;
/* too big, shouldn't happen */
if(n + dirlen > FILENAME_MAX)
break;
memcpy(filename + dirlen, filewalker, n);
filewalker += n;
add_keyfile(filename_from_str(filename));
}
}
keylist_update();
forget_passphrases();
}
sfree(filelist);
}
/*
* Dialog-box function for the key list box.
*/
static int CALLBACK KeyListProc(HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam)
{
struct RSAKey *rkey;
struct ssh2_userkey *skey;
switch (msg) {
case WM_INITDIALOG:
/*
* Centre the window.
*/
{ /* centre the window */
RECT rs, rd;
HWND hw;
hw = GetDesktopWindow();
if (GetWindowRect(hw, &rs) && GetWindowRect(hwnd, &rd))
MoveWindow(hwnd,
(rs.right + rs.left + rd.left - rd.right) / 2,
(rs.bottom + rs.top + rd.top - rd.bottom) / 2,
rd.right - rd.left, rd.bottom - rd.top, TRUE);
}
if (help_path)
SetWindowLong(hwnd, GWL_EXSTYLE,
GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_CONTEXTHELP);
else {
HWND item = GetDlgItem(hwnd, 103); /* the Help button */
if (item)
DestroyWindow(item);
}
requested_help = FALSE;
keylist = hwnd;
{
static int tabs[] = { 35, 60, 210 };
SendDlgItemMessage(hwnd, 100, LB_SETTABSTOPS,
sizeof(tabs) / sizeof(*tabs),
(LPARAM) tabs);
}
keylist_update();
return 0;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDOK:
case IDCANCEL:
keylist = NULL;
DestroyWindow(hwnd);
return 0;
case 101: /* add key */
if (HIWORD(wParam) == BN_CLICKED ||
HIWORD(wParam) == BN_DOUBLECLICKED) {
if (passphrase_box) {
MessageBeep(MB_ICONERROR);
SetForegroundWindow(passphrase_box);
break;
}
prompt_add_keyfile();
}
return 0;
case 102: /* remove key */
if (HIWORD(wParam) == BN_CLICKED ||
HIWORD(wParam) == BN_DOUBLECLICKED) {
int i;
int rCount, sCount;
int *selectedArray;
/* our counter within the array of selected items */
int itemNum;
/* get the number of items selected in the list */
int numSelected =
SendDlgItemMessage(hwnd, 100, LB_GETSELCOUNT, 0, 0);
/* none selected? that was silly */
if (numSelected == 0) {
MessageBeep(0);
break;
}
/* get item indices in an array */
selectedArray = snewn(numSelected, int);
SendDlgItemMessage(hwnd, 100, LB_GETSELITEMS,
numSelected, (WPARAM)selectedArray);
itemNum = numSelected - 1;
rCount = count234(rsakeys);
sCount = count234(ssh2keys);
/* go through the non-rsakeys until we've covered them all,
* and/or we're out of selected items to check. note that
* we go *backwards*, to avoid complications from deleting
* things hence altering the offset of subsequent items
*/
for (i = sCount - 1; (itemNum >= 0) && (i >= 0); i--) {
skey = index234(ssh2keys, i);
if (selectedArray[itemNum] == rCount + i) {
del234(ssh2keys, skey);
skey->alg->freekey(skey->data);
sfree(skey);
itemNum--;
}
}
/* do the same for the rsa keys */
for (i = rCount - 1; (itemNum >= 0) && (i >= 0); i--) {
rkey = index234(rsakeys, i);
if(selectedArray[itemNum] == i) {
del234(rsakeys, rkey);
freersakey(rkey);
sfree(rkey);
itemNum--;
}
}
sfree(selectedArray);
keylist_update();
}
return 0;
case 103: /* help */
if (HIWORD(wParam) == BN_CLICKED ||
HIWORD(wParam) == BN_DOUBLECLICKED) {
if (help_path) {
WinHelp(main_hwnd, help_path, HELP_COMMAND,
(DWORD)"JI(`',`pageant.general')");
requested_help = TRUE;
}
}
return 0;
}
return 0;
case WM_HELP:
if (help_path) {
int id = ((LPHELPINFO)lParam)->iCtrlId;
char *cmd = NULL;
switch (id) {
case 100: cmd = "JI(`',`pageant.keylist')"; break;
case 101: cmd = "JI(`',`pageant.addkey')"; break;
case 102: cmd = "JI(`',`pageant.remkey')"; break;
}
if (cmd) {
WinHelp(main_hwnd, help_path, HELP_COMMAND, (DWORD)cmd);
requested_help = TRUE;
} else {
MessageBeep(0);
}
}
break;
case WM_CLOSE:
keylist = NULL;
DestroyWindow(hwnd);
return 0;
}
return 0;
}
/* Set up a system tray icon */
static BOOL AddTrayIcon(HWND hwnd)
{
BOOL res;
NOTIFYICONDATA tnid;
HICON hicon;
#ifdef NIM_SETVERSION
tnid.uVersion = 0;
res = Shell_NotifyIcon(NIM_SETVERSION, &tnid);
#endif
tnid.cbSize = sizeof(NOTIFYICONDATA);
tnid.hWnd = hwnd;
tnid.uID = 1; /* unique within this systray use */
tnid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
tnid.uCallbackMessage = WM_SYSTRAY;
tnid.hIcon = hicon = LoadIcon(instance, MAKEINTRESOURCE(201));
strcpy(tnid.szTip, "Pageant (PuTTY authentication agent)");
res = Shell_NotifyIcon(NIM_ADD, &tnid);
if (hicon) DestroyIcon(hicon);
return res;
}
/* Update the saved-sessions menu. */
static void update_sessions(void)
{
int num_entries;
HKEY hkey;
TCHAR buf[MAX_PATH + 1];
MENUITEMINFO mii;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -