/[winpt]/trunk/Src/wptPassphraseCB.cpp
ViewVC logotype

Diff of /trunk/Src/wptPassphraseCB.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 34 by twoaday, Wed Oct 26 11:20:09 2005 UTC revision 278 by twoaday, Mon Jan 15 22:02:04 2007 UTC
# Line 1  Line 1 
1  /* wptPassphraseCB.cpp - GPGME Passphrase Callback  /* wptPassphraseCB.cpp - GPGME Passphrase Callback
2   *      Copyright (C) 2001, 2002, 2003, 2005 Timo Schulz   *      Copyright (C) 2001, 2002-2006 Timo Schulz
3   *      Copyright (C) 2005 g10 Code GmbH   *      Copyright (C) 2005 g10 Code GmbH
4   *   *
5   * This file is part of WinPT.   * This file is part of WinPT.
6   *   *
7   * WinPT is free software; you can redistribute it and/or   * WinPT is free software; you can redistribute it and/or
8   * modify it under the terms of the GNU General Public License   * modify it under the terms of the GNU General Public License
9   * as published by the Free Software Foundation; either version 2   * as published by the Free Software Foundation; either version 2
10   * of the License, or (at your option) any later version.   * of the License, or (at your option) any later version.
11   *     *  
12   * WinPT is distributed in the hope that it will be useful,   * WinPT is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   * General Public License for more details.   * General Public License for more details.
16   *   */
17   * You should have received a copy of the GNU General Public License  #ifdef HAVE_CONFIG_H
18   * along with WinPT; if not, write to the Free Software Foundation,  #include <config.h>
19   * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA  #endif
20   */  
21    #include <windows.h>
22  #include <windows.h>  #include <ctype.h>
23  #include <ctype.h>  
24    #include "resource.h"
25  #include "../resource.h"  #include "wptNLS.h"
26  #include "wptNLS.h"  #include "wptW32API.h"
27  #include "wptW32API.h"  #include "wptVersion.h"
28  #include "wptVersion.h"  #include "wptGPG.h"
29  #include "wptGPG.h"  #include "wptCommonCtl.h"
30  #include "wptCommonCtl.h"  #include "wptContext.h"
31  #include "wptContext.h"  #include "wptDlgs.h"
32  #include "wptDlgs.h"  #include "wptErrors.h"
33  #include "wptUTF8.h"  #include "wptTypes.h"
34  #include "wptErrors.h"  #include "wptKeylist.h"
35  #include "wptTypes.h"  #include "wptAgent.h"
36  #include "wptKeyList.h"  #include "wptRegistry.h"
37  #include "wptAgent.h"  #include "wptUTF8.h"
38  #include "wptRegistry.h"  #include "StringBuffer.h"
39    
40  const char* get_symkey_algo (int algo);  
41    /* Return the control ID dependent on the mode (sign or decrypt). */
42  #define item_ctrl_id( cmd ) \  #define item_ctrl_id(cmd) \
43      ((cmd) == GPG_CMD_DECRYPT? IDC_DECRYPT_PWD : IDC_DECRYPT_SIGN_PWD)      ((cmd) == GPG_CMD_DECRYPT? IDC_DECRYPT_PWD : IDC_DECRYPT_SIGN_PWD)
44    
45  #define item_ctrl_id2(cmd) \  #define item_ctrl_id2(cmd) \
46      ((cmd) == GPG_CMD_DECRYPT? IDC_DECRYPT_HIDE : IDC_DECRYPT_SIGN_HIDE)      ((cmd) == GPG_CMD_DECRYPT? IDC_DECRYPT_HIDE : IDC_DECRYPT_SIGN_HIDE)
47    
48    const char* get_symkey_algo (int algo);
49  /* Overwrite passphrase and free memory. */  void ListBox_AddString_utf8 (HWND lb, const char *txt);
50  static void  
51  burn_passphrase (char **pwd)  
52  {  /* Overwrite passphrase and free memory. */
53      char *pass = *pwd;  static void
54      wipememory (pass, strlen (pass));  burn_passphrase (char **pwd)
55      delete []pass;  {
56      *pwd = NULL;      char *pass = *pwd;
57  }  
58        wipememory (pass, strlen (pass));
59        delete []pass;
60  /* Dialog procedure for the passphrase callback. */      *pwd = NULL;
61  static BOOL CALLBACK  }
62  passphrase_callback_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)  
63  {      
64      static passphrase_cb_s * c;  /* Dialog procedure for the passphrase callback. */
65      gpgme_decrypt_result_t res;  static BOOL CALLBACK
66      gpgme_sign_result_t res_sig;  passphrase_callback_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
67      gpgme_key_t key;  {    
68      gpgme_recipient_t recip, r;      static passphrase_cb_s *c;
69      void *ctx = NULL, *item;      gpgme_decrypt_result_t res=NULL;
70      const char *id;      gpgme_sign_result_t res_sig=NULL;
71      char *info;      gpgme_recipient_t recip=NULL, r;
72      int n;      winpt_key_s key;
73        void *item;
74      switch (msg) {      int n;
75      case WM_INITDIALOG:  
76          c = (passphrase_cb_s *)lparam;      switch (msg) {
77          if (!c)      case WM_ACTIVATE:
78              BUG (0);          safe_edit_control_init (dlg, item_ctrl_id (c->gpg_cmd));
79          SetWindowText (dlg, c->title);          break;
80          if (c->gpg_cmd == GPG_CMD_DECRYPT) {  
81              SetDlgItemText (dlg, IDC_DECRYPT_LISTINF,      case WM_DESTROY:
82                              _("Encrypted with the following public key(s)"));          safe_edit_control_free (dlg, item_ctrl_id (c->gpg_cmd));
83              CheckDlgButton (dlg, IDC_DECRYPT_HIDE, BST_CHECKED);          break;
84          }  
85          else if (c->gpg_cmd == GPG_CMD_SIGN)      case WM_INITDIALOG:
86              CheckDlgButton (dlg, IDC_DECRYPT_SIGN_HIDE, BST_CHECKED);          c = (passphrase_cb_s *)lparam;
87          if (c->recipients)          if (!c)
88              recip = c->recipients; /* recipients were already extracted. */              BUG (0);
89          else {          SetDlgItemText (dlg, IDCANCEL, _("&Cancel"));
90              /* XXX: not all ENCRYPT_TO entries are listed here. */          SetWindowText (dlg, c->title);
91              res = gpgme_op_decrypt_result (c->gpg);          if (c->gpg_cmd == GPG_CMD_DECRYPT) {
92              if (res && res->recipients)              SetDlgItemText (dlg, IDC_DECRYPT_HIDE, _("&Hide Typing"));
93                  recip = res->recipients;              SetDlgItemText (dlg, IDC_DECRYPT_LISTINF,
94          }                              _("Encrypted with the following public key(s)"));
95          if (recip != NULL && c->gpg_cmd == GPG_CMD_DECRYPT) {              CheckDlgButton (dlg, IDC_DECRYPT_HIDE, BST_CHECKED);
96              for (r = res->recipients; r; r = r->next) {          }
97                  get_pubkey (r->keyid, &key);          else if (c->gpg_cmd == GPG_CMD_SIGN) {
98                  if (key) {              SetDlgItemText (dlg, IDC_DECRYPT_SIGN_HIDE, _("&Hide Typing"));
99                      char *uid;              CheckDlgButton (dlg, IDC_DECRYPT_SIGN_HIDE, BST_CHECKED);
100                      id = key->uids->name;          }
101                      if (!id)          /* Because it depends on the order the keys are stored in the
102                          id = _("Invalid User ID");             keyring whether res->recipients is complete or not, we also
103                      uid = utf8_to_wincp (id, strlen (id));             support that the recipients were externally extracted and then
104                      info = new char [32+strlen (uid)+1 + 4 + strlen (r->keyid)+1             we use this list. */
105                                       + strlen (key->uids->email)+1];          if (c->recipients)
106                      if (!info)              recip = c->recipients; /* recipients were already extracted. */
107                          BUG (NULL);          else {
108                      sprintf (info, "%s <%s> (%s, 0x%s)", uid, key->uids->email,              res = gpgme_op_decrypt_result (c->gpg);
109                               get_key_pubalgo (r->pubkey_algo), r->keyid+8);              if (res && res->recipients)
110                      free (uid);                  recip = res->recipients;
111                                }
112                  }          if (recip != NULL && c->gpg_cmd == GPG_CMD_DECRYPT) {
113                  else {              StringBuffer inf;
114                      info = new char [32 + strlen (r->keyid)+1 + 4];  
115                      if (!info)              for (r = recip; r; r = r->next) {
116                          BUG (NULL);                  memset (&key, 0, sizeof (key));
117                      sprintf (info, _("Unknown key ID (%s, 0x%s)"),                  if (!winpt_get_pubkey (r->keyid, &key)) {
118                               get_key_pubalgo (r->pubkey_algo), r->keyid+8);                      gpgme_user_id_t u = key.ctx->uids;
119                  }                      
120                  listbox_add_string (GetDlgItem (dlg, IDC_DECRYPT_LIST), info);                      inf = (u->name? u->name : _("Invalid User ID"));
121                  free_if_alloc (info);                      if (u->email != NULL && strlen (u->email) > 1)
122              }                          inf = inf + " <" + u->email + ">";
123          }                      inf = inf + " (" + get_key_pubalgo (r->pubkey_algo);
124          else if (c->gpg_cmd == GPG_CMD_DECRYPT)                      inf = inf + ", 0x" + (r->keyid+8) + ")";
125              EnableWindow (GetDlgItem (dlg, IDC_DECRYPT_LIST), FALSE);                  }
126          SetDlgItemText (dlg, c->gpg_cmd == GPG_CMD_DECRYPT?                  else {
127                          IDC_DECRYPT_PWDINFO : IDC_DECRYPT_SIGN_PWDINFO,                      inf = _("Unknown key ID");
128                          c->bad_pwd? _("Bad passphrase; Enter passphrase again") :                      inf = inf + " (" + get_key_pubalgo (r->pubkey_algo);
129                          _("Please enter your passphrase"));                      inf = inf + ", 0x" + (r->keyid+8) + ")";
130          if (c->gpg_cmd == GPG_CMD_DECRYPT) {                  }
131              SetFocus (GetDlgItem (dlg, IDC_DECRYPT_PWD));                  ListBox_AddString_utf8 (GetDlgItem (dlg, IDC_DECRYPT_LIST),
132              if (res && !res->recipients) {                                          inf.getBuffer ());
133                  const char *s = _("Symmetric encryption.\n"                  winpt_release_pubkey (&key);
134                                    "%s encrypted data.");              }
135                  const char *alg = get_symkey_algo (c->sym.sym_algo);          }
136                  info = new char[strlen (s) + strlen (alg) + 2];          else if (c->gpg_cmd == GPG_CMD_DECRYPT)
137                  if (!info)              EnableWindow (GetDlgItem (dlg, IDC_DECRYPT_LIST), FALSE);
138                      BUG (NULL);          SetDlgItemText (dlg, c->gpg_cmd == GPG_CMD_DECRYPT?
139                  sprintf (info, s, alg);                          IDC_DECRYPT_PWDINFO : IDC_DECRYPT_SIGN_PWDINFO,
140                  SetDlgItemText (dlg, IDC_DECRYPT_MSG, info);                          c->bad_pwd? _("Bad passphrase; Enter passphrase again") :
141                  free_if_alloc (info);                          _("Please enter your passphrase"));
142              }          if (c->gpg_cmd == GPG_CMD_DECRYPT) {
143              else              SetFocus (GetDlgItem (dlg, IDC_DECRYPT_PWD));
144                  SetDlgItemText (dlg, IDC_DECRYPT_MSG, c->info);              if (res && !res->recipients) {
145          }                  StringBuffer sinf;
146          else {  
147              SetFocus( GetDlgItem (dlg, IDC_DECRYPT_SIGN_PWD));                  sinf = _("Symmetric encryption.");
148              SetDlgItemText (dlg, IDC_DECRYPT_SIGN_MSG, c->info);                  sinf = sinf + "\n" + get_symkey_algo (c->sym.sym_algo);
149          }                  sinf = sinf + " " + _("encrypted data.");
150          center_window (dlg, NULL);                  SetDlgItemText (dlg, IDC_DECRYPT_MSG, sinf.getBuffer ());
151          SetForegroundWindow (dlg);              }
152          set_active_window (dlg);              else
153          return FALSE;                  SetDlgItemText (dlg, IDC_DECRYPT_MSG, c->info);
154            }
155          case WM_SYSCOMMAND:          else {
156              if (LOWORD (wparam) == SC_CLOSE) {              SetFocus (GetDlgItem (dlg, IDC_DECRYPT_SIGN_PWD));
157                  SetDlgItemText (dlg, item_ctrl_id (c->gpg_cmd), "");              SetDlgItemText (dlg, IDC_DECRYPT_SIGN_MSG, c->info);
158                  c->cancel = 1;          }
159                  EndDialog (dlg, TRUE);          center_window (dlg, NULL);
160              }          SetForegroundWindow (dlg);
161              break;          return FALSE;
162    
163          case WM_COMMAND:          case WM_COMMAND:
164              switch (HIWORD (wparam)) {              switch (HIWORD (wparam)) {
165              case BN_CLICKED:              case BN_CLICKED:
166                  if  (LOWORD (wparam) == IDC_DECRYPT_HIDE                  if  (LOWORD (wparam) == IDC_DECRYPT_HIDE
167                      || LOWORD (wparam) == IDC_DECRYPT_SIGN_HIDE) {                      || LOWORD (wparam) == IDC_DECRYPT_SIGN_HIDE) {
168                      HWND hwnd;                      HWND hwnd;
169                      int hide = IsDlgButtonChecked (dlg, item_ctrl_id2 (c->gpg_cmd));                      int hide = IsDlgButtonChecked (dlg, item_ctrl_id2 (c->gpg_cmd));
170                      hwnd = GetDlgItem (dlg, item_ctrl_id (c->gpg_cmd));                      hwnd = GetDlgItem (dlg, item_ctrl_id (c->gpg_cmd));
171                      SendMessage (hwnd, EM_SETPASSWORDCHAR, hide? '*' : 0, 0);                      SendMessage (hwnd, EM_SETPASSWORDCHAR, hide? '*' : 0, 0);
172                      SetFocus (hwnd);                      SetFocus (hwnd);
173                  }                  }
174              }              }
175    
176              switch (LOWORD (wparam)) {              switch (LOWORD (wparam)) {
177              case IDOK:                case IDOK:  
178                  /* XXX: the item is even cached when the passphrase is not                  /* XXX: the item is even cached when the passphrase is not
179                          correct, which means that the user needs to delete all                          correct, which means that the user needs to delete all
180                          cached entries to continue. */                          cached entries to continue. */
181                  if (c->pwd)                  if (c->pwd)
182                      burn_passphrase (&c->pwd);                      burn_passphrase (&c->pwd);
183                  n = item_get_text_length (dlg, item_ctrl_id (c->gpg_cmd));                  n = item_get_text_length (dlg, item_ctrl_id (c->gpg_cmd));
184                  if (!n) {                  if (!n) {
185                      c->pwd = new char[2];                      c->pwd = new char[2];
186                      if (!c->pwd)                      if (!c->pwd)
187                          BUG (NULL);                          BUG (NULL);
188                      strcpy (c->pwd, "");                      strcpy (c->pwd, "");
189                  }                  }
190                  else {                  else {
191                      c->pwd = new char[n+2];                      char *p = new char[n+2];
192                      if (!c->pwd)                      if (!p)
193                          BUG (NULL);                          BUG (NULL);
194                      GetDlgItemText (dlg, item_ctrl_id (c->gpg_cmd), c->pwd, n+1);                      /* Get the passphrase and convert it utf8.
195                  }                         This does not just the us-ascii charset. */
196                  res = gpgme_op_decrypt_result (c->gpg);                      SafeGetDlgItemText (dlg, item_ctrl_id (c->gpg_cmd), p, n+1);
197                  if (!res)                      c->pwd = native_to_utf8 (p);
198                      res_sig = gpgme_op_sign_result (c->gpg);                      sfree_if_alloc (p);
199                  if (reg_prefs.cache_time > 0 && !c->is_card &&                  }
200                      ((res && res->recipients) || (res_sig && res_sig->signatures))) {                  res = gpgme_op_decrypt_result (c->gpg);
201                      if (agent_get_cache (c->keyid, &item))                  if (!res)
202                          agent_unlock_cache_entry (&item);                      res_sig = gpgme_op_sign_result (c->gpg);
203                      else                  if (!c->is_card && reg_prefs.cache_time > 0 &&
204                          agent_put_cache (c->keyid, c->pwd, reg_prefs.cache_time);                      (res || res_sig)) {
205                  }                      if (agent_get_cache (c->keyid, &item))
206                  c->cancel = 0;                          agent_unlock_cache_entry (&item);
207                  EndDialog (dlg, TRUE);                      else
208                  return TRUE;                          agent_put_cache (c->keyid, c->pwd, reg_prefs.cache_time);
209                                    }
210              case IDCANCEL:                  c->cancel = 0;
211                  SetDlgItemText (dlg, item_ctrl_id (c->gpg_cmd), "");                  EndDialog (dlg, TRUE);
212                  c->cancel = 1;                  return TRUE;
213                  EndDialog (dlg, FALSE);                  
214                  return FALSE;              case IDCANCEL:
215              }                  SetDlgItemText (dlg, item_ctrl_id (c->gpg_cmd), "");
216              break;                  c->cancel = 1;
217      }                  EndDialog (dlg, FALSE);
218                        return TRUE;
219      return FALSE;              }
220  }              break;
221        }
222        
223  /* Extract the main keyid from @pass_info.      return FALSE;
224     Return value: long main keyid or NULL for an error. */  }
225  static const char*  
226  parse_gpg_keyid (const char *pass_info)  
227  {  /* Extract the main keyid from @pass_info.
228      static char keyid[16+1];     Return value: long main keyid or NULL for an error. */
229        static const char*
230      /* XXX: check for leading alpha-chars? */  parse_gpg_keyid (const char *pass_info)
231      if (strlen (pass_info) < 16)  {
232          return NULL;      static char keyid[16+1];
233      /* the format of the desc buffer looks like this:      
234         request_keyid[16] main_keyid[16] keytype[1] keylength[4]      /* XXX: check for leading alpha-chars? */
235         we use the main keyid to use only one cache entry. */      if (strlen (pass_info) < 16) {
236      strncpy (keyid, pass_info+17, 16);          log_debug ("parse_gpg_keyid: error '%s'\r\n", pass_info);
237      keyid[16] = 0;          return NULL;
238      return keyid;      }
239  }      /* the format of the desc buffer looks like this:
240           request_keyid[16] main_keyid[16] keytype[1] keylength[4]
241           we use the main keyid to use only one cache entry. */
242  /* Parse the information in @uid_hint and @pass_info to generate      strncpy (keyid, pass_info+17, 16);
243     a input message for the user in @desc. */      keyid[16] = 0;
244  static int      return keyid;
245  parse_gpg_description (const char *uid_hint, const char *pass_info,  }
246                         char *desc, int size)  
247  {  
248      gpgme_pubkey_algo_t algo;  /* Parse the information in @uid_hint and @pass_info to generate
249      char usedkey[16+1];     a input message for the user in @desc. */
250      char mainkey[16+1];  static int
251      char *uid, *p;  parse_gpg_description (const char *uid_hint, const char *pass_info,
252      int n=0;                         char *desc, int size)
253    {
254      /* Each uid_hint contains a long key-ID so it is at least 16 bytes. */      gpgme_pubkey_algo_t algo;
255      if (strlen (uid_hint) < 17) {      char usedkey[16+1];
256          *desc = 0;      char mainkey[16+1];
257          return -1;      char *p, *uid;
258      }      int n=0;
259    
260      while (p = strsep ((char**)&pass_info, " ")) {      algo = (gpgme_pubkey_algo_t)0;
261          switch (n++) {      /* Each uid_hint contains a long key-ID so it is at least 16 bytes. */
262          case 0: strncpy (mainkey, p, 16); mainkey[16] = 0; break;      if (strlen (uid_hint) < 17) {
263          case 1: strncpy (usedkey, p, 16); usedkey[16] = 0; break;          *desc = 0;
264          case 2: algo = (gpgme_pubkey_algo_t)atol (p); break;          log_debug ("parse_gpg_description: error '%s'\r\n", uid_hint);
265          }          return -1;
266      }      }
267      uid_hint += 16; /* skip keyid */  
268      uid_hint += 1;  /* space */      while (p = strsep ((char**)&pass_info, " ")) {
269            switch (n++) {
270      uid = utf8_to_wincp (uid_hint, strlen (uid_hint));          case 0: strncpy (mainkey, p, 16); mainkey[16] = 0; break;
271            case 1: strncpy (usedkey, p, 16); usedkey[16] = 0; break;
272      if (strcmp (usedkey, mainkey))          case 2: algo = (gpgme_pubkey_algo_t)atol (p); break;
273          _snprintf (desc, size-1,          }
274                     _("You need a passphrase to unlock the secret key for\n"      }
275                       "user: \"%s\"\n"      uid_hint += 16; /* skip keyid */
276                       "%s key, ID %s (main key ID %s)\n"),      uid_hint += 1;  /* space */
277                     uid, get_key_pubalgo (algo), usedkey+8, mainkey+8);  
278      else if (!strcmp (usedkey, mainkey))      uid = utf8_to_native (uid_hint);
279          _snprintf (desc, size-1,      if (strcmp (usedkey, mainkey))
280                     _("You need a passphrase to unlock the secret key for\n"          _snprintf (desc, size-1,
281                       "user: \"%s\"\n"                     _("You need a passphrase to unlock the secret key for user:\n"
282                       "%s key, ID %s\n"),                       "\"%s\"\n"
283                       uid, get_key_pubalgo (algo), usedkey+8);                       "%s key, ID 0x%s (main key ID 0x%s)\n"),
284      free (uid);                     uid, get_key_pubalgo (algo), usedkey+8, mainkey+8);
285      return 0;      else if (!strcmp (usedkey, mainkey))
286  }          _snprintf (desc, size-1,
287                       _("You need a passphrase to unlock the secret key for user:\n"
288                         "\"%s\"\n"
289  /* Extract the serial number from the card ID @id and return it. */                       "%s key, ID 0x%s\n"),
290  const char*                       uid, get_key_pubalgo (algo), usedkey+8);
291  extract_serial_no (const char *id)      safe_free (uid);
292  {      return 0;
293      static char buf[8];  }
294      char *p;  
295    
296      p = strchr (id, '/');  /* Extract the serial number from the card ID @id and return it. */
297      if (!p)  const char*
298          return NULL;  extract_serial_no (const char *id)
299      strncpy (buf, id+(p-id)-6, 6);  {
300      return buf;      static char buf[8];
301  }      char *p;
302    
303        p = strchr (id, '/');
304  /* Passphrase callback with the ability to support caching. */      if (!p) {
305  gpgme_error_t          log_debug ("extract_serial_no: error '%s'\r\n", id);
306  passphrase_cb (void *hook, const char *uid_hint,          return "";
307                 const char *passphrase_info,      }
308                 int prev_was_bad, int fd)      memset (buf, 0, sizeof (buf));
309  {      strncpy (buf, id+(p-id)-6, 6);
310      passphrase_cb_s *c = (passphrase_cb_s*)hook;      return buf;
311      HANDLE hd = (HANDLE)fd;  }
312      void *item;  
313      const char *keyid, *pass;  
314      DWORD n;  /* Passphrase callback with the ability to support caching. */
315      int rc;  gpgme_error_t
316    passphrase_cb (void *hook, const char *uid_hint,
317      if (!c)                 const char *passphrase_info,
318          return gpg_error (GPG_ERR_INV_ARG);                 int prev_was_bad, int fd)
319      c->bad_pwd = prev_was_bad? 1 : 0;  {
320      if (prev_was_bad && !c->cancel) {      passphrase_cb_s *c = (passphrase_cb_s*)hook;
321          if (c->pwd)      HANDLE hd = (HANDLE)fd;
322              burn_passphrase (&c->pwd);      void *item;
323          agent_del_cache (c->keyid);      const char *keyid=NULL, *pass;
324          c->pwd_init = 1;      DWORD n;
325      }      int rc = 0;
326    
327      if (passphrase_info) {      if (!c) {
328          if (strlen (passphrase_info) < 16 &&          log_debug ("passphrase_cb: error no valid callback\r\n");
329              !strstr (passphrase_info, "OPENPGP")) {          return gpg_error (GPG_ERR_INV_ARG);
330              /* assume symetric encryption. */      }
331              int n=2;      c->bad_pwd = prev_was_bad? 1 : 0;
332              c->sym.sym_algo = atoi (passphrase_info);      if (prev_was_bad && !c->cancel) {
333              if (c->sym.sym_algo > 9)          if (c->pwd)
334                  n++;              burn_passphrase (&c->pwd);
335              /* XXX: be more strict. */          agent_del_cache (c->keyid);
336              c->sym.s2k_mode = atoi (passphrase_info+n);          c->pwd_init = 1;
337              c->sym.s2k_hash = atoi (passphrase_info+n+2);      }
338          }  
339        if (passphrase_info) {
340          keyid = parse_gpg_keyid (passphrase_info);          if (strlen (passphrase_info) < 16 &&
341          pass = agent_get_cache (keyid+8, &item);              !strstr (passphrase_info, "OPENPGP")) {
342          if (pass) {              /* assume symetric encryption. */
343              agent_unlock_cache_entry (&item);              int pos=2;
344              c->pwd_init = 0;              c->sym.sym_algo = atoi (passphrase_info);
345              if (!WriteFile (hd, pass, strlen (pass), &n, NULL))              if (c->sym.sym_algo > 9)
346                  log_debug ("passphrase_cb: WriteFile() failed ec=%d\n", w32_errno);                  pos++;
347              if (!WriteFile (hd, "\n", 1, &n, NULL))              /* XXX: be more strict. */
348                  log_debug ("passphrase_cb: WriteFile() failed ec=%d\n", w32_errno);              c->sym.s2k_mode = atoi (passphrase_info+pos);
349              return 0;              c->sym.s2k_hash = atoi (passphrase_info+pos+2);
350          }          }
351      }  
352            keyid = parse_gpg_keyid (passphrase_info);
353      if (c->pwd_init) {          pass = agent_get_cache (keyid+8, &item);        
354          if (keyid && strlen (keyid) == 16)          if (pass) {
355              strcpy (c->keyid, keyid+8);              agent_unlock_cache_entry (&item);
356                c->pwd_init = 0;
357          /* if @passphrase_info contains 'OPENPGP' we assume a smart card              if (!WriteFile (hd, pass, strlen (pass), &n, NULL))
358              has been used. */                  log_debug ("passphrase_cb: WriteFile() failed ec=%d\n", w32_errno);
359          if (strstr (passphrase_info, "OPENPGP")) {              if (!WriteFile (hd, "\n", 1, &n, NULL))
360              const char *s=passphrase_info;                  log_debug ("passphrase_cb: WriteFile() failed ec=%d\n", w32_errno);
361              while (s && *s && *s != 'D')              return 0;
362                  s++;          }
363              _snprintf (c->info, sizeof c->info-1,      }
364                         _("Please enter the PIN to unlock your secret card key\n"  
365                           "Card: %s"), extract_serial_no (s));      if (c->pwd_init) {
366              c->is_card = 1;          if (keyid && strlen (keyid) == 16)
367          }              strcpy (c->keyid, keyid+8);
368          else if (uid_hint)  
369              parse_gpg_description (uid_hint, passphrase_info,          /* if @passphrase_info contains 'OPENPGP' we assume a smart card
370                                     c->info, sizeof c->info - 1);              has been used. */
371          if (c->gpg_cmd == GPG_CMD_DECRYPT) {          if (strstr (passphrase_info, "OPENPGP")) {
372              rc = DialogBoxParam (glob_hinst, (LPCSTR)IDD_WINPT_DECRYPT,              const char *s=passphrase_info;
373                                   (HWND)c->hwnd, passphrase_callback_proc,              while (s && *s && *s != 'D')
374                                   (LPARAM)c);                  s++;
375          }              _snprintf (c->info, sizeof (c->info)-1,
376          else if (c->gpg_cmd == GPG_CMD_SIGN) {                         _("Please enter the PIN to unlock your secret card key\n"
377              rc = DialogBoxParam (glob_hinst, (LPCSTR)IDD_WINPT_DECRYPT_SIGN,                           "Card: %s"), extract_serial_no (s));
378                                   (HWND)c->hwnd, passphrase_callback_proc,              c->is_card = 1;
379                                   (LPARAM)c);          }
380          }          else if (uid_hint)
381          if (rc == -1) {              parse_gpg_description (uid_hint, passphrase_info,
382              if (!WriteFile (hd, "\n", 1, &n, NULL))                                     c->info, sizeof (c->info) - 1);
383                  log_debug ("passphrase_cb: WriteFile() failed ec=%d\n", w32_errno);          if (c->gpg_cmd == GPG_CMD_DECRYPT) {
384              return 0;              rc = DialogBoxParam (glob_hinst, (LPCSTR)IDD_WINPT_DECRYPT,
385          }                                   (HWND)c->hwnd, passphrase_callback_proc,
386          c->pwd_init = 0;                                   (LPARAM)c);
387      }          }
388      if (c->cancel) {          else if (c->gpg_cmd == GPG_CMD_SIGN) {
389          if (!WriteFile (hd, "\n", 1, &n, NULL))              rc = DialogBoxParam (glob_hinst, (LPCSTR)IDD_WINPT_DECRYPT_SIGN,
390              log_debug ("passphrase_cb: WriteFile() failed ec=%d\n", w32_errno);                                   (HWND)c->hwnd, passphrase_callback_proc,
391          return 0;                                   (LPARAM)c);
392      }          }
393            if (rc == -1) {
394      WriteFile (hd, c->pwd, strlen (c->pwd), &n, NULL);              if (!WriteFile (hd, "\n", 1, &n, NULL))
395      WriteFile (hd, "\n", 1, &n, NULL);                  log_debug ("passphrase_cb: WriteFile() failed ec=%d\n", w32_errno);
396      return 0;              log_debug ("passphrase_cb: could not create dialog box\n");
397  }              return 0;
398            }
399            c->pwd_init = 0;
400  /* Initialize the given passphrase callback @cb with the      }
401     used gpgme context @ctx, the command @cmd and a title      if (c->cancel || !c->pwd) {
402     @title for the dialog. */          if (!WriteFile (hd, "\n", 1, &n, NULL))
403  void              log_debug ("passphrase_cb: WriteFile() failed ec=%d\n", w32_errno);
404  set_gpg_passphrase_cb (passphrase_cb_s *cb, gpgme_ctx_t ctx,          return 0;
405                         int cmd, HWND hwnd, const char *title)      }
406  {  
407      memset (cb, 0, sizeof *cb);      if (!WriteFile (hd, c->pwd, strlen (c->pwd), &n, NULL))
408      cb->gpg_cmd = cmd;          log_debug ("passphrase_cb: WriteFile() failed ec=%d\n", w32_errno);
409      cb->bad_pwd = 0;      if (!WriteFile (hd, "\n", 1, &n, NULL))
410      cb->is_card = 0;          log_debug ("passphrase_cb: WriteFile() failed ec=%d\n", w32_errno);
411      cb->cancel = 0;      return 0;
412      cb->hwnd = hwnd;  }
413      cb->pwd_init = 1;  
414      free_if_alloc (cb->title);  
415      cb->title = m_strdup (title);  /* Initialize the given passphrase callback @cb with the
416      if (!cb->title)     used gpgme context @ctx, the command @cmd and a title
417          BUG (NULL);     @title for the dialog. */
418      gpgme_set_passphrase_cb (ctx, passphrase_cb, cb);  void
419      cb->gpg = ctx;  set_gpg_passphrase_cb (passphrase_cb_s *cb, gpgme_ctx_t ctx,
420  }                         int cmd, HWND hwnd, const char *title)
421    {
422        memset (cb, 0, sizeof *cb);
423  /* Release a passphrase callback @ctx. */      cb->gpg_cmd = cmd;
424  void      cb->bad_pwd = 0;
425  release_gpg_passphrase_cb (passphrase_cb_s *ctx)      cb->is_card = 0;
426  {      cb->cancel = 0;
427      gpgme_recipient_t r, n;      cb->hwnd = hwnd;
428        cb->pwd_init = 1;
429      if (!ctx)      free_if_alloc (cb->title);
430          return;      cb->title = m_strdup (title);
431      sfree_if_alloc (ctx->pwd);      gpgme_set_passphrase_cb (ctx, passphrase_cb, cb);
432      free_if_alloc (ctx->title);      cb->gpg = ctx;
433      r = ctx->recipients;  }
434      while (r) {  
435          n = r->next;  
436          safe_free (r->keyid);  /* Release the gpg recipient list. */
437          safe_free (r);  void
438          r = n;  release_gpg_recipients (gpgme_recipient_t *recipients)
439      }  {
440  }      gpgme_recipient_t r, n;
441    
442        r = *recipients;
443  /* Simple check to measure passphrase (@pass) quality.      while (r != NULL) {
444     Return value: 0 on success. */          n = r->next;
445  int          safe_free (r->keyid);
446  check_passwd_quality (const char *pass, int strict)          safe_free (r);
447  {          r = n;
448      int i, nd=0, nc=0, n;      }
449        *recipients = NULL;
450      n = strlen (pass);  }
451      if (n < 8)  
452          return -1;  
453    
454      for (i=0; i < n; i++) {  /* Release a passphrase callback @ctx. */
455          if (isdigit (pass[i]))  void
456              nd++;  release_gpg_passphrase_cb (passphrase_cb_s *ctx)
457          if (isalpha (pass[i]))  {
458              nc++;      if (!ctx)
459      }          return;
460        sfree_if_alloc (ctx->pwd);
461      /* check that the passphrase contains letters and numbers. */      free_if_alloc (ctx->title);
462      if (nd == n || nc == n)      release_gpg_recipients (&ctx->recipients);
463          return -1;  }
464    
465      return 0;  
466  }  /* _Simple_ check to measure passphrase (@pass) quality.
467       Return value: 0 on success. */
468    int
469    check_passwd_quality (const char *pass, int strict)
470    {
471        int i, nd=0, nc=0, n;
472    
473        /* A good passphrase should be at least 8 characters. */
474        n = strlen (pass);
475        if (n < 8)
476            return -1;
477    
478        for (i=0; i < n; i++) {
479            if (isdigit (pass[i]))
480                nd++;
481            if (isalpha (pass[i]))
482                nc++;
483        }
484    
485        /* Check that the passphrase contains letters and numbers. */
486        if (nd == n || nc == n)
487            return -1;
488    
489        return 0;
490    }

Legend:
Removed from v.34  
changed lines
  Added in v.278

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26