/[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 23 by twoaday, Fri Sep 30 10:10:16 2005 UTC revision 28 by twoaday, Thu Oct 20 12:35:59 2005 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, 2003, 2005 Timo Schulz
3     *      Copyright (C) 2005 g10 Code GmbH
4   *   *
5   * This file is part of WinPT.   * This file is part of WinPT.
6   *   *
# Line 20  Line 21 
21    
22  #include <windows.h>  #include <windows.h>
23  #include <ctype.h>  #include <ctype.h>
 #include <io.h>  
24    
25  #include "../resource.h"  #include "../resource.h"
26  #include "wptNLS.h"  #include "wptNLS.h"
# Line 37  Line 37 
37  #include "wptAgent.h"  #include "wptAgent.h"
38  #include "wptRegistry.h"  #include "wptRegistry.h"
39    
40    const char* get_symkey_algo (int algo);
41    
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)
# Line 45  Line 46 
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    
49    /* Overwrite passphrase and free memory. */
50    static void
51    burn_passphrase (char **pwd)
52    {
53        char *pass = *pwd;  
54        memset (pass, 0, strlen (pass));
55        delete []pass;
56        *pwd = NULL;
57    }
58    
59    
60  /* Dialog procedure for the passphrase callback. */  /* Dialog procedure for the passphrase callback. */
61  static BOOL CALLBACK  static BOOL CALLBACK
62  passphrase_callback_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)  passphrase_callback_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
63  {      {    
64      static passphrase_cb_s * c;      static passphrase_cb_s * c;
65        gpgme_decrypt_result_t res;
66        gpgme_sign_result_t res_sig;
67      gpgme_key_t key;      gpgme_key_t key;
68        void *ctx = NULL, *item;
69      const char *id;      const char *id;
70      char *info;      char *info;
     void *ctx = NULL, *item;  
71      int n;      int n;
72    
73      switch( msg )  {      /* XXX: we need a timer to update the 'enc_to' entries. */
74        switch (msg) {
75      case WM_INITDIALOG:      case WM_INITDIALOG:
76          c = (passphrase_cb_s *)lparam;          c = (passphrase_cb_s *)lparam;
77          if (!c)          if (!c)
# Line 67  passphrase_callback_proc (HWND dlg, UINT Line 82  passphrase_callback_proc (HWND dlg, UINT
82                  _("Encrypted with the following public key(s)") );                  _("Encrypted with the following public key(s)") );
83              CheckDlgButton( dlg, IDC_DECRYPT_HIDE, BST_CHECKED );              CheckDlgButton( dlg, IDC_DECRYPT_HIDE, BST_CHECKED );
84          }          }
85          else if( c->gpg_cmd == GPG_CMD_SIGN )          else if (c->gpg_cmd == GPG_CMD_SIGN)
86              CheckDlgButton (dlg, IDC_DECRYPT_SIGN_HIDE, BST_CHECKED);              CheckDlgButton (dlg, IDC_DECRYPT_SIGN_HIDE, BST_CHECKED);
87          if (gpgme_op_decrypt_result (c->gpg) != NULL &&          res = gpgme_op_decrypt_result (c->gpg);
88              c->gpg_cmd == GPG_CMD_DECRYPT) {          if (res != NULL && c->gpg_cmd == GPG_CMD_DECRYPT) {
89              gpgme_recipient_t r;              gpgme_recipient_t r;
             gpgme_decrypt_result_t res;  
90    
91              res = gpgme_op_decrypt_result (c->gpg);              /* XXX: not all ENCRYPT_TO entries are listed here. */
92              for (r = res->recipients; r; r = r->next) {              for (r = res->recipients; r; r = r->next) {
93                  get_pubkey (r->keyid, &key);                  get_pubkey (r->keyid, &key);
94                  if (key) {                  if (key) {
95                      char *uid;                      char *uid;
96                      id = key->uids->uid;                      id = key->uids->name;
97                      if (!id)                      if (!id)
98                          id = _("Invalid User ID");                          id = _("Invalid User ID");
99                      uid = utf8_to_wincp (id, strlen (id));                      uid = utf8_to_wincp (id, strlen (id));
100                      info = new char [8+strlen (uid) + 4 + strlen (r->keyid) + 2];                      info = new char [32+strlen (uid)+1 + 4 + strlen (r->keyid)+1
101                                         + strlen (key->uids->email)+1];
102                      if (!info)                      if (!info)
103                          BUG (NULL);                          BUG (NULL);
104                      sprintf (info, "%s (%s, 0x%s)", uid,                      sprintf (info, "%s <%s> (%s, 0x%s)", uid, key->uids->email,
105                               get_key_pubalgo (r->pubkey_algo), r->keyid+8);                               get_key_pubalgo (r->pubkey_algo), r->keyid+8);
106                      free (uid);                      free (uid);
107                      free (info);                      
108                  }                  }
109                  else {                  else {
110                      info = new char [32 + strlen (r->keyid) + 2];                      info = new char [32 + strlen (r->keyid)+1 + 4];
111                      if (!info)                      if (!info)
112                          BUG (NULL);                          BUG (NULL);
113                      sprintf (info, _("Unknown (key ID 0x%s)"),                      sprintf (info, _("Unknown key ID (%s, 0x%s)"),
114                               r->keyid? r->keyid+8 : "????????");                               get_key_pubalgo (r->pubkey_algo), r->keyid+8);
                     free (info);  
115                  }                  }
116                  listbox_add_string (GetDlgItem( dlg, IDC_DECRYPT_LIST ), info);                  listbox_add_string (GetDlgItem (dlg, IDC_DECRYPT_LIST), info);
117                    free_if_alloc (info);
118              }              }
119          }          }
120          SetDlgItemText( dlg, c->gpg_cmd == GPG_CMD_DECRYPT?          else if (c->gpg_cmd == GPG_CMD_DECRYPT)
121                EnableWindow (GetDlgItem (dlg, IDC_DECRYPT_LIST), FALSE);
122            SetDlgItemText (dlg, c->gpg_cmd == GPG_CMD_DECRYPT?
123                          IDC_DECRYPT_PWDINFO : IDC_DECRYPT_SIGN_PWDINFO,                          IDC_DECRYPT_PWDINFO : IDC_DECRYPT_SIGN_PWDINFO,
124                          _("Please enter your passphrase") );                          c->bad_pwd? _("Bad passphrase; Enter passphrase again") :
125          if( c->gpg_cmd == GPG_CMD_DECRYPT ) {                          _("Please enter your passphrase"));
126              SetFocus( GetDlgItem( dlg, IDC_DECRYPT_PWD ) );          if (c->gpg_cmd == GPG_CMD_DECRYPT) {
127              SetDlgItemText( dlg, IDC_DECRYPT_MSG, c->info );              SetFocus (GetDlgItem (dlg, IDC_DECRYPT_PWD));
128                if (res && !res->recipients) {
129                    const char *s = _("Symmetric encryption.\n"
130                                      "%s encrypted data.");
131                    const char *alg = get_symkey_algo (c->sym.sym_algo);
132                    info = new char[strlen (s) + strlen (alg) + 2];
133                    if (!info)
134                        BUG (NULL);
135                    sprintf (info, s, alg);
136                    SetDlgItemText (dlg, IDC_DECRYPT_MSG, info);
137                    free_if_alloc (info);
138                }
139                else
140                    SetDlgItemText (dlg, IDC_DECRYPT_MSG, c->info);
141          }          }
142          else {          else {
143              SetFocus( GetDlgItem( dlg, IDC_DECRYPT_SIGN_PWD ) );              SetFocus( GetDlgItem (dlg, IDC_DECRYPT_SIGN_PWD));
144              SetDlgItemText( dlg, IDC_DECRYPT_SIGN_MSG, c->info );              SetDlgItemText (dlg, IDC_DECRYPT_SIGN_MSG, c->info);
145          }          }
146          center_window( dlg, NULL );          center_window (dlg, NULL);
147          SetForegroundWindow( dlg );          SetForegroundWindow (dlg);
148          set_active_window( dlg );          set_active_window (dlg);
149          return FALSE;          return FALSE;
150    
151          case WM_SYSCOMMAND:          case WM_SYSCOMMAND:
152              if( LOWORD( wparam ) == SC_CLOSE ) {              if (LOWORD (wparam) == SC_CLOSE) {
153                  SetDlgItemText( dlg, item_ctrl_id( c->gpg_cmd ), "" );                  SetDlgItemText (dlg, item_ctrl_id( c->gpg_cmd ), "");
154                  c->cancel = 1;                  c->cancel = 1;
155                  EndDialog( dlg, TRUE );                  EndDialog (dlg, TRUE);
156              }              }
157              return FALSE;              break;
158    
159          case WM_COMMAND:          case WM_COMMAND:
160              switch( HIWORD( wparam ) ) {              switch( HIWORD( wparam ) ) {
# Line 134  passphrase_callback_proc (HWND dlg, UINT Line 164  passphrase_callback_proc (HWND dlg, UINT
164                      HWND hwnd;                      HWND hwnd;
165                      int hide = IsDlgButtonChecked (dlg, item_ctrl_id2 (c->gpg_cmd));                      int hide = IsDlgButtonChecked (dlg, item_ctrl_id2 (c->gpg_cmd));
166                      hwnd = GetDlgItem (dlg, item_ctrl_id (c->gpg_cmd));                      hwnd = GetDlgItem (dlg, item_ctrl_id (c->gpg_cmd));
167                      SendMessage( hwnd, EM_SETPASSWORDCHAR, hide? '*' : 0, 0 );                      SendMessage (hwnd, EM_SETPASSWORDCHAR, hide? '*' : 0, 0);
168                      SetFocus (hwnd);                      SetFocus (hwnd);
169                  }                  }
170              }              }
# Line 144  passphrase_callback_proc (HWND dlg, UINT Line 174  passphrase_callback_proc (HWND dlg, UINT
174                  /* fixme: the item is even cached when the passphrase is not                  /* fixme: the item is even cached when the passphrase is not
175                            correct, which means that the user needs to delete all                            correct, which means that the user needs to delete all
176                            cached entries to continue. */                            cached entries to continue. */
177                  if (c->pwd) {                  if (c->pwd)
178                      delete []c->pwd;                      burn_passphrase (&c->pwd);
                     c->pwd = NULL;  
                 }  
179                  n = item_get_text_length (dlg, item_ctrl_id (c->gpg_cmd));                  n = item_get_text_length (dlg, item_ctrl_id (c->gpg_cmd));
180                  if (!n) {                  if (!n) {
181                      c->pwd = new char[2];                      c->pwd = new char[2];
182                        if (!c->pwd)
183                            BUG (NULL);
184                      strcpy (c->pwd, "");                      strcpy (c->pwd, "");
185                  }                  }
186                  else {                  else {
187                      c->pwd = new char[n+1];                      c->pwd = new char[n+2];
188                      if (!c->pwd)                      if (!c->pwd)
189                          BUG (NULL);                          BUG (NULL);
190                      GetDlgItemText (dlg, item_ctrl_id (c->gpg_cmd), c->pwd, sizeof (c->pwd) -1);                      GetDlgItemText (dlg, item_ctrl_id (c->gpg_cmd), c->pwd, n+1);
191                  }                  }
192                  if (reg_prefs.cache_time > 0 && !c->is_card && !strstr (c->keyid, "missing")) {                  res = gpgme_op_decrypt_result (c->gpg);
193                    if (!res)
194                        res_sig = gpgme_op_sign_result (c->gpg);
195                    if (reg_prefs.cache_time > 0 && !c->is_card &&
196                        ((res && res->recipients) || (res_sig && res_sig->signatures))) {
197                      if (agent_get_cache (c->keyid, &item))                      if (agent_get_cache (c->keyid, &item))
198                          agent_unlock_cache_entry (&item);                          agent_unlock_cache_entry (&item);
199                      else                      else
# Line 188  parse_gpg_keyid (const char *pass_info) Line 222  parse_gpg_keyid (const char *pass_info)
222  {  {
223      static char keyid[16+1];      static char keyid[16+1];
224            
225        /* XXX: check for leading alpha-chars? */
226      if (strlen (pass_info) < 16)      if (strlen (pass_info) < 16)
227          return NULL;          return NULL;
228      /* the format of the desc buffer looks like this:      /* the format of the desc buffer looks like this:
# Line 201  parse_gpg_keyid (const char *pass_info) Line 236  parse_gpg_keyid (const char *pass_info)
236    
237  /* Parse the information in @uid_hint and @pass_info to generate  /* Parse the information in @uid_hint and @pass_info to generate
238     a input message for the user in @desc. */     a input message for the user in @desc. */
239  static void  static int
240  parse_gpg_description (const char *uid_hint, const char *pass_info,  parse_gpg_description (const char *uid_hint, const char *pass_info,
241                         char *desc, int size)                         char *desc, int size)
242  {  {
# Line 210  parse_gpg_description (const char *uid_h Line 245  parse_gpg_description (const char *uid_h
245      char *uid, *p;      char *uid, *p;
246      int n=0;      int n=0;
247    
248        if (strlen (uid_hint) < 17) {
249            *desc = 0;
250            return -1;
251        }
252    
253      while (p = strsep ((char**)&pass_info, " ")) {      while (p = strsep ((char**)&pass_info, " ")) {
254          switch (n++) {          switch (n++) {
255          case 0: strncpy (mainkey, p, 16); mainkey[16] = 0; break;          case 0: strncpy (mainkey, p, 16); mainkey[16] = 0; break;
# Line 235  parse_gpg_description (const char *uid_h Line 275  parse_gpg_description (const char *uid_h
275                       "%s key, ID %s\n"),                       "%s key, ID %s\n"),
276                       uid, get_key_pubalgo (algo), usedkey+8);                       uid, get_key_pubalgo (algo), usedkey+8);
277      free (uid);      free (uid);
278        return 0;
279  }  }
280    
281    
282    /*
283  static int inline  static int inline
284  is_hexstring (const char * p)  is_hexstring (const char * p)
285  {  {
# Line 249  is_hexstring (const char * p) Line 291  is_hexstring (const char * p)
291      }      }
292      return 0;      return 0;
293  }  }
294    */
295    
296    
297    /* Extract the serial number from the card ID @id and return it. */
298    const char*
299    extract_serial_no (const char *id)
300    {
301        static char buf[8];
302        char *p;
303    
304        p = strchr (id, '/');
305        if (!p)
306            return NULL;
307        strncpy (buf, id+(p-id)-6, 6);
308        return buf;
309    }
310    
311    
312  /* Passphrase callback with the ability to support caching. */  /* Passphrase callback with the ability to support caching. */
# Line 258  passphrase_cb (void *hook, const char *u Line 316  passphrase_cb (void *hook, const char *u
316                 int prev_was_bad, int fd)                 int prev_was_bad, int fd)
317  {  {
318      passphrase_cb_s *c = (passphrase_cb_s*)hook;      passphrase_cb_s *c = (passphrase_cb_s*)hook;
319        HANDLE hd = (HANDLE)fd;
320      void *item;      void *item;
321      const char *keyid, *pass;      const char *keyid, *pass;
322        DWORD n;
323      int rc;      int rc;
324    
325      if (!c)      if (!c)
326          return gpg_error (GPG_ERR_INV_ARG);          return gpg_error (GPG_ERR_INV_ARG);
327        c->bad_pwd = prev_was_bad? 1 : 0;
328        if (prev_was_bad && !c->cancel) {
329            if (c->pwd)
330                burn_passphrase (&c->pwd);
331            agent_del_cache (c->keyid);
332            c->pwd_init = 1;
333        }
334    
335      if (passphrase_info) {      if (passphrase_info) {
336            if (strlen (passphrase_info) < 16 &&
337                !strstr (passphrase_info, "OPENPGP")) {/* assume symetric encryption. */
338                int n=2;
339                c->sym.sym_algo = atoi (passphrase_info);
340                if (c->sym.sym_algo > 9)
341                    n++;
342                /* XXX: be more strict. */
343                c->sym.s2k_mode = atoi (passphrase_info+n);
344                c->sym.s2k_hash = atoi (passphrase_info+n+2);
345            }
346    
347          keyid = parse_gpg_keyid (passphrase_info);          keyid = parse_gpg_keyid (passphrase_info);
348          pass = agent_get_cache (keyid, &item);          pass = agent_get_cache (keyid+8, &item);
349          if (pass) {          if (pass) {
350              agent_unlock_cache_entry (&item);              agent_unlock_cache_entry (&item);
351              c->pwd_init = 0;              c->pwd_init = 0;
352              write (fd, pass, strlen (pass));              if (!WriteFile (hd, pass, strlen (pass), &n, NULL))
353              write (fd, "\n", 1);                  log_debug ("passphrase_cb: WriteFile() failed ec=%d\n", w32_errno);
354                if (!WriteFile (hd, "\n", 1, &n, NULL))
355                    log_debug ("passphrase_cb: WriteFile() failed ec=%d\n", w32_errno);
356              return 0;              return 0;
357          }          }
358      }      }
# Line 281  passphrase_cb (void *hook, const char *u Line 361  passphrase_cb (void *hook, const char *u
361          if (keyid && strlen (keyid) == 16)          if (keyid && strlen (keyid) == 16)
362              strcpy (c->keyid, keyid+8);              strcpy (c->keyid, keyid+8);
363    
364          /* if the desc has a length of 32 and only hex digits, we assume a          /* if @passphrase_info contains 'OPENPGP' we assume a smart card
365             smart card has been used. */              has been used. */
366          if (uid_hint && strlen (uid_hint) == 32 && !is_hexstring (uid_hint)) {          if (strstr (passphrase_info, "OPENPGP")) {
367              char buf[16];              const char *s=passphrase_info;
368              memset (buf, 0, sizeof buf);              while (s && *s && *s != 'D')
369              strncpy (buf, uid_hint+20, 8);                  s++;
370              _snprintf (c->info, sizeof c->info-1,              _snprintf (c->info, sizeof c->info-1,
371                         _("Please enter the PIN to unlock your secret card key\n"                         _("Please enter the PIN to unlock your secret card key\n"
372                           "Card: %s"), buf);                           "Card: %s"), extract_serial_no (s));
373              c->is_card = 1;              c->is_card = 1;
374          }          }
375          else if (uid_hint)          else if (uid_hint)
# Line 306  passphrase_cb (void *hook, const char *u Line 386  passphrase_cb (void *hook, const char *u
386                                   (LPARAM)c);                                   (LPARAM)c);
387          }          }
388          if (rc == -1) {          if (rc == -1) {
389              write (fd, "\n", 1);              WriteFile (hd, "\n", 1, &n, NULL);
390              return gpg_error (GPG_ERR_EOF);              return 0;
391          }          }
392          c->pwd_init = 0;          c->pwd_init = 0;
393      }      }
394      if (c->cancel) {      if (c->cancel) {
395          write (fd, "\n", 1);          WriteFile (hd, "\n", 1, &n, NULL);
396          return gpg_error (GPG_ERR_EOF);          return 0;
397      }      }
398    
399      write (fd, c->pwd, strlen (c->pwd));      WriteFile (hd, c->pwd, strlen (c->pwd), &n, NULL);
400      write (fd, "\n", 1);      WriteFile (hd, "\n", 1, &n, NULL);
401      return 0;      return 0;
402  }  }
403    
# Line 331  set_gpg_passphrase_cb (passphrase_cb_s * Line 411  set_gpg_passphrase_cb (passphrase_cb_s *
411  {  {
412      memset (cb, 0, sizeof *cb);      memset (cb, 0, sizeof *cb);
413      cb->gpg_cmd = cmd;      cb->gpg_cmd = cmd;
414        cb->bad_pwd = 0;
415      cb->is_card = 0;      cb->is_card = 0;
416      cb->cancel = 0;      cb->cancel = 0;
417      cb->hwnd = hwnd;      cb->hwnd = hwnd;
# Line 354  release_gpg_passphrase_cb (passphrase_cb Line 435  release_gpg_passphrase_cb (passphrase_cb
435      free_if_alloc (ctx->title);      free_if_alloc (ctx->title);
436  }  }
437    
438    
439  /* Simple check to measure passphrase (@pass) quality.  /* Simple check to measure passphrase (@pass) quality.
440     Return value: 0 on success. */     Return value: 0 on success. */
441  int  int

Legend:
Removed from v.23  
changed lines
  Added in v.28

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26