]> asedeno.scripts.mit.edu Git - PuTTY.git/commitdiff
Andrew Francis's Pageant updates: you can now multi-select key files
authorSimon Tatham <anakin@pobox.com>
Mon, 10 Dec 2001 17:40:14 +0000 (17:40 +0000)
committerSimon Tatham <anakin@pobox.com>
Mon, 10 Dec 2001 17:40:14 +0000 (17:40 +0000)
to add and keys to remove (in the open-file dialog and the key list
box respectively), and passphrases are cached during the process of
adding several keys at once (in case two of the keys have the same
passphrase).

[originally from svn r1466]

pageant.c
pageant.rc

index 0114804772d800f39dc6613089f2d730b4ec090e..d249fab4719780b46240c5fe6e1944b3056d2747 100644 (file)
--- a/pageant.c
+++ b/pageant.c
@@ -115,6 +115,23 @@ struct PassphraseProcStruct {
     char *comment;
 };
 
+static tree234 *passphrases = NULL;
+
+/* 
+ * After processing a list of filenames, we want to forget the
+ * passphrases.
+ */
+static void forget_passphrases(void)
+{
+    int i;
+    while (count234(passphrases) > 0) {
+       char *pp = index234(passphrases, 0);
+       memset(pp, 0, strlen(pp));
+       delpos234(passphrases, 0);
+       free(pp);
+    }
+}
+
 /*
  * Dialog-box function for the Licence box.
  */
@@ -327,7 +344,8 @@ static void add_keyfile(char *filename)
     char *comment;
     struct PassphraseProcStruct pps;
     int ver;
-
+    int original_pass;
+       
     ver = keyfile_version(filename);
     if (ver == 0) {
        MessageBox(NULL, "Couldn't load private key.", APPNAME,
@@ -344,18 +362,26 @@ static void add_keyfile(char *filename)
        rkey = smalloc(sizeof(*rkey));
     pps.passphrase = passphrase;
     pps.comment = comment;
+    original_pass = 0;
     do {
        if (needs_pass) {
-           int dlgret;
-           dlgret = DialogBoxParam(instance, MAKEINTRESOURCE(210),
-                                   NULL, PassphraseProc, (LPARAM) & pps);
-           passphrase_box = NULL;
-           if (!dlgret) {
-               if (comment)
-                   sfree(comment);
-               if (ver == 1)
-                   sfree(rkey);
-               return;                /* operation cancelled */
+           /* try all the remembered passphrases first */
+           char *pp = index234(passphrases, attempts);
+           if(pp) {
+               strcpy(passphrase, pp);
+           } else {
+               int dlgret;
+               original_pass = 1;
+               dlgret = DialogBoxParam(instance, MAKEINTRESOURCE(210),
+                                       NULL, PassphraseProc, (LPARAM) & pps);
+               passphrase_box = NULL;
+               if (!dlgret) {
+                   if (comment)
+                       sfree(comment);
+                   if (ver == 1)
+                       sfree(rkey);
+                   return;                    /* operation cancelled */
+               }
            }
        } else
            *passphrase = '\0';
@@ -372,6 +398,13 @@ static void add_keyfile(char *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 (comment)
        sfree(comment);
     if (ret == 0) {
@@ -980,6 +1013,10 @@ static void prompt_add_keyfile(void)
 {
     OPENFILENAME of;
     char filename[FILENAME_MAX];
+    char *filelist = smalloc(8192);
+    char *filewalker;
+    int n, dirlen;
+       
     memset(&of, 0, sizeof(of));
 #ifdef OPENFILENAME_SIZE_VERSION_400
     of.lStructSize = OPENFILENAME_SIZE_VERSION_400;
@@ -990,17 +1027,52 @@ static void prompt_add_keyfile(void)
     of.lpstrFilter = "All Files\0*\0\0\0";
     of.lpstrCustomFilter = NULL;
     of.nFilterIndex = 1;
-    of.lpstrFile = filename;
-    *filename = '\0';
-    of.nMaxFile = sizeof(filename);
+    of.lpstrFile = filelist;
+    *filelist = '\0';
+    of.nMaxFile = FILENAME_MAX;
     of.lpstrFileTitle = NULL;
     of.lpstrInitialDir = NULL;
     of.lpstrTitle = "Select Private Key File";
-    of.Flags = 0;
+    of.Flags = OFN_ALLOWMULTISELECT | OFN_EXPLORER;
     if (GetOpenFileName(&of)) {
-       add_keyfile(filename);
+       if(strlen(filelist) > of.nFileOffset)
+           /* Only one filename returned? */
+           add_keyfile(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);
+           }
+       }
+
        keylist_update();
+       forget_passphrases();
     }
+    sfree(filelist);
 }
 
 /*
@@ -1059,29 +1131,61 @@ static int CALLBACK KeyListProc(HWND hwnd, UINT msg,
          case 102:                    /* remove key */
            if (HIWORD(wParam) == BN_CLICKED ||
                HIWORD(wParam) == BN_DOUBLECLICKED) {
-               int n = SendDlgItemMessage(hwnd, 100, LB_GETCURSEL, 0, 0);
                int i;
-               if (n == LB_ERR) {
+               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;
                }
-               for (i = 0; NULL != (rkey = index234(rsakeys, i)); i++)
-                   if (n-- == 0)
-                       break;
-               if (rkey) {
-                   del234(rsakeys, rkey);
-                   freersakey(rkey);
-                   sfree(rkey);
-               } else {
-                   for (i = 0; NULL != (skey = index234(ssh2keys, i));
-                        i++) if (n-- == 0)
-                           break;
-                   if (skey) {
-                       del234(ssh2keys, skey);
-                       skey->alg->freekey(skey->data);
-                       sfree(skey);
-                   }
+
+               /* get item indices in an array */
+               selectedArray = smalloc(numSelected * sizeof(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;
@@ -1423,6 +1527,11 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
 
     }
 
+    /*
+     * Initialise storage for short-term passphrase cache.
+     */
+    passphrases = newtree234(NULL);
+
     /*
      * Process the command line and add keys as listed on it.
      * If we already determined that we need to spawn a program from above we
@@ -1435,10 +1544,10 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
        while (*p) {
            while (*p && isspace(*p))
                p++;
-           if (*p && !isspace(*p)) {
+               if (*p && !isspace(*p)) {
                char *q = p, *pp = p;
                while (*p && (inquotes || !isspace(*p))) {
-                   if (*p == '"') {
+                       if (*p == '"') {
                        inquotes = !inquotes;
                        p++;
                        continue;
@@ -1468,6 +1577,12 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
        }
     }
 
+    /*
+     * Forget any passphrase that we retained while going over
+     * command line keyfiles.
+     */
+    forget_passphrases();
+
     if (command)
        spawn_cmd(command, show);
 
index 70aeec31ea7da7333a10b4abf1491ca16d356851..1224a59e3eb72f35ae93d2a63e9a21ec699bf8ff 100644 (file)
@@ -24,7 +24,7 @@ CAPTION "Pageant Key List"
 FONT 8, "MS Sans Serif"
 BEGIN
     LISTBOX 100, 10, 10, 310, 155,
-        LBS_HASSTRINGS | LBS_USETABSTOPS | WS_VSCROLL | WS_TABSTOP
+        LBS_EXTENDEDSEL | LBS_HASSTRINGS | LBS_USETABSTOPS | WS_VSCROLL | WS_TABSTOP
     PUSHBUTTON "&Add Key", 101, 75, 162, 60, 14
     PUSHBUTTON "&Remove Key", 102, 195, 162, 60, 14
     DEFPUSHBUTTON "&Close", IDOK, 270, 182, 50, 14