/[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 22 by twoaday, Wed Aug 10 11:33:35 2005 UTC revision 23 by twoaday, Fri Sep 30 10:10:16 2005 UTC
# Line 1  Line 1 
1  /* wptPassphraseCB.cpp - GPGME Passphrase Callback  /* wptPassphraseCB.cpp - GPGME Passphrase Callback
2   *      Copyright (C) 2001, 2002, 2003 Timo Schulz   *      Copyright (C) 2001, 2002, 2003, 2005 Timo Schulz
3   *   *
4   * This file is part of WinPT.   * This file is part of WinPT.
5   *   *
# Line 20  Line 20 
20    
21  #include <windows.h>  #include <windows.h>
22  #include <ctype.h>  #include <ctype.h>
23    #include <io.h>
24    
25  #include "../resource.h"  #include "../resource.h"
26  #include "wptNLS.h"  #include "wptNLS.h"
# Line 32  Line 33 
33  #include "wptUTF8.h"  #include "wptUTF8.h"
34  #include "wptErrors.h"  #include "wptErrors.h"
35  #include "wptTypes.h"  #include "wptTypes.h"
36    #include "wptKeyList.h"
37  #include "wptAgent.h"  #include "wptAgent.h"
38  #include "wptRegistry.h"  #include "wptRegistry.h"
39    
# Line 43  Line 45 
45      ((cmd) == GPG_CMD_DECRYPT? IDC_DECRYPT_HIDE : IDC_DECRYPT_SIGN_HIDE)      ((cmd) == GPG_CMD_DECRYPT? IDC_DECRYPT_HIDE : IDC_DECRYPT_SIGN_HIDE)
46    
47    
48  BOOL CALLBACK  /* Dialog procedure for the passphrase callback. */
49    static BOOL CALLBACK
50  passphrase_callback_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)  passphrase_callback_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
51  {      {    
52      static passphrase_cb_s * c;      static passphrase_cb_s * c;
53      gpgme_key_t key;      gpgme_key_t key;
54      const char * s, * id;      const char *id;
55      char info[768] = {0};      char *info;
56      void * ctx = NULL, * item;      void *ctx = NULL, *item;
57      unsigned int pkalgo;      int n;
58    
59      switch( msg )  {      switch( msg )  {
60      case WM_INITDIALOG:      case WM_INITDIALOG:
# Line 65  passphrase_callback_proc (HWND dlg, UINT Line 68  passphrase_callback_proc (HWND dlg, UINT
68              CheckDlgButton( dlg, IDC_DECRYPT_HIDE, BST_CHECKED );              CheckDlgButton( dlg, IDC_DECRYPT_HIDE, BST_CHECKED );
69          }          }
70          else if( c->gpg_cmd == GPG_CMD_SIGN )          else if( c->gpg_cmd == GPG_CMD_SIGN )
71              CheckDlgButton( dlg, IDC_DECRYPT_SIGN_HIDE, BST_CHECKED );              CheckDlgButton (dlg, IDC_DECRYPT_SIGN_HIDE, BST_CHECKED);
72          if( c->enc_to && c->gpg_cmd == GPG_CMD_DECRYPT ) {          if (gpgme_op_decrypt_result (c->gpg) != NULL &&
73              gpgme_recipients_enum_open( c->enc_to, &ctx );              c->gpg_cmd == GPG_CMD_DECRYPT) {
74              while ( (s = gpgme_recipients_enum_read( c->enc_to, &ctx )) ) {              gpgme_recipient_t r;
75                  pkalgo = *s; s++;              gpgme_decrypt_result_t res;
76                  get_pubkey( s, &key );  
77                  if( key ) {              res = gpgme_op_decrypt_result (c->gpg);
78                      char * uid = NULL;              for (r = res->recipients; r; r = r->next) {
79                      id = gpgme_key_get_string_attr( key, GPGME_ATTR_USERID, NULL, 0 );                  get_pubkey (r->keyid, &key);
80                      if( !id )                  if (key) {
81                        char *uid;
82                        id = key->uids->uid;
83                        if (!id)
84                          id = _("Invalid User ID");                          id = _("Invalid User ID");
85                      uid = utf8_to_wincp (id, strlen (id));                                      uid = utf8_to_wincp (id, strlen (id));
86                      _snprintf( info, sizeof info - 1, "%s (%s, 0x%s)", uid,                      info = new char [8+strlen (uid) + 4 + strlen (r->keyid) + 2];
87                                  gpgme_key_expand_attr( GPGME_ATTR_ALGO, pkalgo ), s+8 );                      if (!info)
88                      free( uid );                          BUG (NULL);
89                        sprintf (info, "%s (%s, 0x%s)", uid,
90                                 get_key_pubalgo (r->pubkey_algo), r->keyid+8);
91                        free (uid);
92                        free (info);
93                  }                  }
94                  else                  else {
95                      _snprintf( info, sizeof info - 1, _("Unknown (key ID 0x%s)"),                      info = new char [32 + strlen (r->keyid) + 2];
96                                 s? s + 8 : "DEADBEEF" );                      if (!info)
97                  listbox_add_string( GetDlgItem( dlg, IDC_DECRYPT_LIST ), info );                          BUG (NULL);
98                        sprintf (info, _("Unknown (key ID 0x%s)"),
99                                 r->keyid? r->keyid+8 : "????????");
100                        free (info);
101                    }
102                    listbox_add_string (GetDlgItem( dlg, IDC_DECRYPT_LIST ), info);
103              }              }
             gpgme_recipients_enum_close( c->enc_to, &ctx );  
104          }          }
105          SetDlgItemText( dlg, c->gpg_cmd == GPG_CMD_DECRYPT?          SetDlgItemText( dlg, c->gpg_cmd == GPG_CMD_DECRYPT?
106                          IDC_DECRYPT_PWDINFO : IDC_DECRYPT_SIGN_PWDINFO,                          IDC_DECRYPT_PWDINFO : IDC_DECRYPT_SIGN_PWDINFO,
# Line 99  passphrase_callback_proc (HWND dlg, UINT Line 113  passphrase_callback_proc (HWND dlg, UINT
113              SetFocus( GetDlgItem( dlg, IDC_DECRYPT_SIGN_PWD ) );              SetFocus( GetDlgItem( dlg, IDC_DECRYPT_SIGN_PWD ) );
114              SetDlgItemText( dlg, IDC_DECRYPT_SIGN_MSG, c->info );              SetDlgItemText( dlg, IDC_DECRYPT_SIGN_MSG, c->info );
115          }          }
116          center_window( dlg );          center_window( dlg, NULL );
117          SetForegroundWindow( dlg );          SetForegroundWindow( dlg );
118          set_active_window( dlg );          set_active_window( dlg );
119          return FALSE;          return FALSE;
# Line 130  passphrase_callback_proc (HWND dlg, UINT Line 144  passphrase_callback_proc (HWND dlg, UINT
144                  /* fixme: the item is even cached when the passphrase is not                  /* fixme: the item is even cached when the passphrase is not
145                            correct, which means that the user needs to delete all                            correct, which means that the user needs to delete all
146                            cached entries to continue. */                            cached entries to continue. */
147                  GetDlgItemText (dlg, item_ctrl_id (c->gpg_cmd), c->pwd, sizeof (c->pwd) -1);                  if (c->pwd) {
148                        delete []c->pwd;
149                        c->pwd = NULL;
150                    }
151                    n = item_get_text_length (dlg, item_ctrl_id (c->gpg_cmd));
152                    if (!n) {
153                        c->pwd = new char[2];
154                        strcpy (c->pwd, "");
155                    }
156                    else {
157                        c->pwd = new char[n+1];
158                        if (!c->pwd)
159                            BUG (NULL);
160                        GetDlgItemText (dlg, item_ctrl_id (c->gpg_cmd), c->pwd, sizeof (c->pwd) -1);
161                    }
162                  if (reg_prefs.cache_time > 0 && !c->is_card && !strstr (c->keyid, "missing")) {                  if (reg_prefs.cache_time > 0 && !c->is_card && !strstr (c->keyid, "missing")) {
163                      if (agent_get_cache (c->keyid, &item))                      if (agent_get_cache (c->keyid, &item))
164                          agent_unlock_cache_entry (&item);                          agent_unlock_cache_entry (&item);
# Line 150  passphrase_callback_proc (HWND dlg, UINT Line 178  passphrase_callback_proc (HWND dlg, UINT
178      }      }
179            
180      return FALSE;      return FALSE;
181  } /* passphrase_callback_proc */  }
182    
183    
184  static const char *  /* Extract the main keyid from @pass_info.
185  parse_gpg_keyid (const char * desc)     Return value: long main keyid or NULL for an error. */
186    static const char*
187    parse_gpg_keyid (const char *pass_info)
188  {  {
189      static char keyid[16+1];      static char keyid[16+1];
     char * p;  
190            
191      p = strrchr (desc, '\n');      if (strlen (pass_info) < 16)
     if( !p )  
192          return NULL;          return NULL;
193      /* the format of the desc buffer looks like this:      /* the format of the desc buffer looks like this:
194         request_keyid[16] main_keyid[16] keytype[1] keylength[4]         request_keyid[16] main_keyid[16] keytype[1] keylength[4]
195         we use the main keyid to use only one cache entry. */         we use the main keyid to use only one cache entry. */
196      strncpy (keyid, desc+(p-desc+1+17), 16);      strncpy (keyid, pass_info+17, 16);
197        keyid[16] = 0;
198      return keyid;      return keyid;
199  } /* parse_gpg_keyid */  }
200    
201    
202    /* Parse the information in @uid_hint and @pass_info to generate
203       a input message for the user in @desc. */
204  static void  static void
205  parse_gpg_description( char * desc, int size )  parse_gpg_description (const char *uid_hint, const char *pass_info,
206                           char *desc, int size)
207  {  {
208      char * buffer = NULL, ch, uid[128] = {0}, * uid2 = NULL;      gpgme_pubkey_algo_t algo;
209      char usedkey[16+1] = {0}, mainkey[16+1] = {0};      char usedkey[16+1], mainkey[16+1];
210      const char * buf;      char *uid, *p;
211      int i, algo, try_again = 0;      int n=0;
212    
213      if( stristr( desc, "[User ID hint missing]" )      while (p = strsep ((char**)&pass_info, " ")) {
214          || stristr( desc, "[passphrase info missing]" ) ) {          switch (n++) {
215          _snprintf( desc, size-1,          case 0: strncpy (mainkey, p, 16); mainkey[16] = 0; break;
216                     _("You need a passphrase to unlock the secret key for\n"          case 1: strncpy (usedkey, p, 16); usedkey[16] = 0; break;
217                       "user: [UserID hint missing]\n"          case 2: algo = (gpgme_pubkey_algo_t)atol (p); break;
                      "      [passphrase info missing]\n") );  
         return;  
     }  
   
     buffer = new char[size+1];  
     if( !buffer )  
         BUG( NULL );  
     strcpy( buffer, desc );  
     buf = buffer;  
     if( strstr( buf, "TRY_AGAIN" ) ) {  
         buf += strlen( "TRY_AGAIN\n" );  
         try_again = 1;  
     }  
     else if( strstr( buf, "ENTER_PASSPHRASE" ) )  
         buf += strlen( "ENTER_PASSPHRASE\n" );  
     else  
         BUG( NULL );  
     buf += 17;  
     for( i = 0; i < sizeof uid-1; i++ ) {  
         ch = *buf++;  
         if( ch == '\n' ) {  
             uid[i] = '\0';  
             break;  
218          }          }
         uid[i] = ch;  
219      }      }
220      memcpy( usedkey, buf, 16 );      uid_hint += 16; /* skip keyid */
221      usedkey[16] = '\0';      uid_hint += 1;  /* space */
     buf += 17;  
     memcpy( mainkey, buf, 16 );  
     mainkey[16] = '\0';  
     buf += 17;  
     if( !buf )  
         BUG( NULL );  
     algo = atol( buf );  
     free_if_alloc( buffer );  
222    
223      uid2 = utf8_to_wincp (uid, strlen (uid));      uid = utf8_to_wincp (uid_hint, strlen (uid_hint));
224    
225      if( strcmp( usedkey, mainkey ) )      if (strcmp (usedkey, mainkey))
226          _snprintf( desc, size-1,          _snprintf (desc, size-1,
227                     _("You need a passphrase to unlock the secret key for\n"                     _("You need a passphrase to unlock the secret key for\n"
228                       "user: \"%s\"\n"                       "user: \"%s\"\n"
229                       "%s key, ID %s (main key ID %s)\n"),                       "%s key, ID %s (main key ID %s)\n"),
230                     uid2, gpgme_key_expand_attr( GPGME_ATTR_ALGO, algo ),                     uid, get_key_pubalgo (algo), usedkey+8, mainkey+8);
231                     usedkey+8, mainkey+8 );      else if (!strcmp (usedkey, mainkey))
232      else if( !strcmp( usedkey, mainkey ) )          _snprintf (desc, size-1,
         _snprintf( desc, size-1,  
233                     _("You need a passphrase to unlock the secret key for\n"                     _("You need a passphrase to unlock the secret key for\n"
234                       "user: \"%s\"\n"                       "user: \"%s\"\n"
235                       "%s key, ID %s\n"),                       "%s key, ID %s\n"),
236                       uid2, gpgme_key_expand_attr( GPGME_ATTR_ALGO, algo ),                       uid, get_key_pubalgo (algo), usedkey+8);
237                       usedkey+8 );      free (uid);
238      free( uid2 );  }
 } /* parse_gpg_describtion */  
239    
240    
241  static int inline  static int inline
242  is_hexstring( const char * p )  is_hexstring (const char * p)
243  {  {
244      size_t i;      size_t i;
245      for( i=0; i < strlen( p ); i++ ) {  
246          if( !isxdigit( p[i] ) )      for (i=0; i < strlen (p); i++) {
247            if (!isxdigit (p[i]))
248              return -1;              return -1;
249      }      }
250      return 0;      return 0;
251  }  }
252    
253    
254  const char *  /* Passphrase callback with the ability to support caching. */
255  passphrase_cb( void * opaque, const char * desc, void * r_hd )  gpgme_error_t
256  {    passphrase_cb (void *hook, const char *uid_hint,
257      passphrase_cb_s * c = (passphrase_cb_s *)opaque;                 const char *passphrase_info,
258      void * item;                 int prev_was_bad, int fd)
259      const char * pass, * keyid;  {
260      int rc = 0;      passphrase_cb_s *c = (passphrase_cb_s*)hook;
261        void *item;
262      if( !c )      const char *keyid, *pass;
263          return NULL;      int rc;
264    
265      if( desc ) {      if (!c)
266          keyid = parse_gpg_keyid (desc);          return gpg_error (GPG_ERR_INV_ARG);
267          pass = agent_get_cache( keyid, &item );  
268          if( pass ) {      if (passphrase_info) {
269              agent_unlock_cache_entry( &item );          keyid = parse_gpg_keyid (passphrase_info);
270            pass = agent_get_cache (keyid, &item);
271            if (pass) {
272                agent_unlock_cache_entry (&item);
273              c->pwd_init = 0;              c->pwd_init = 0;
274              return pass;              write (fd, pass, strlen (pass));
275                write (fd, "\n", 1);
276                return 0;
277          }          }
278      }      }
279    
280      if( c->pwd_init ) {      if (c->pwd_init) {
281          c->keyid = keyid;          if (keyid && strlen (keyid) == 16)
282                strcpy (c->keyid, keyid+8);
283    
284          /* if the desc has a length of 32 and only hex digits, we assume a          /* if the desc has a length of 32 and only hex digits, we assume a
285             smart card has been used. */             smart card has been used. */
286          /*log_box( "", 0, "%s %d %d", desc,strlen( desc), is_hexstring( desc ) );*/          if (uid_hint && strlen (uid_hint) == 32 && !is_hexstring (uid_hint)) {
         if( desc && strlen( desc ) == 32 && !is_hexstring( desc ) ) {  
287              char buf[16];              char buf[16];
288              memset( buf, 0, sizeof buf );              memset (buf, 0, sizeof buf);
289              strncpy( buf, desc+20, 8 );              strncpy (buf, uid_hint+20, 8);
290              _snprintf( c->info, sizeof c->info-1,              _snprintf (c->info, sizeof c->info-1,
291                      _("Please enter the PIN to unlock your secret card key\n"                         _("Please enter the PIN to unlock your secret card key\n"
292                        "Card: %s"), buf );                           "Card: %s"), buf);
293              c->is_card = 1;              c->is_card = 1;
294          }          }
295          else if(desc) {          else if (uid_hint)
296              strcpy (c->info, desc);              parse_gpg_description (uid_hint, passphrase_info,
297              parse_gpg_description (c->info, sizeof c->info - 1);                                     c->info, sizeof c->info - 1);
298            if (c->gpg_cmd == GPG_CMD_DECRYPT) {
299                rc = DialogBoxParam (glob_hinst, (LPCSTR)IDD_WINPT_DECRYPT,
300                                     (HWND)c->hwnd, passphrase_callback_proc,
301                                     (LPARAM)c);
302          }          }
303          if( c->gpg_cmd == GPG_CMD_DECRYPT ) {          else if (c->gpg_cmd == GPG_CMD_SIGN) {
304              rc = DialogBoxParam( glob_hinst, (LPCSTR)IDD_WINPT_DECRYPT,              rc = DialogBoxParam (glob_hinst, (LPCSTR)IDD_WINPT_DECRYPT_SIGN,
305                                  (HWND)c->hwnd, passphrase_callback_proc,                                   (HWND)c->hwnd, passphrase_callback_proc,
306                                  (LPARAM)c );                                   (LPARAM)c);
307          }          }
308          else if( c->gpg_cmd == GPG_CMD_SIGN ) {          if (rc == -1) {
309              rc = DialogBoxParam( glob_hinst, (LPCSTR)IDD_WINPT_DECRYPT_SIGN,              write (fd, "\n", 1);
310                                  (HWND)c->hwnd, passphrase_callback_proc,              return gpg_error (GPG_ERR_EOF);
                                 (LPARAM)c );  
311          }          }
         if( rc == -1 )  
             return NULL;  
312          c->pwd_init = 0;          c->pwd_init = 0;
313      }      }
314        if (c->cancel) {
315            write (fd, "\n", 1);
316            return gpg_error (GPG_ERR_EOF);
317        }
318    
319      if( c->cancel )      write (fd, c->pwd, strlen (c->pwd));
320          return NULL;      write (fd, "\n", 1);
321        return 0;
322      return c->pwd;  }
 } /* passphrase_cb */  
323    
324    
325    /* Initialize the given passphrase callback @cb with the
326       used gpgme context @ctx, the command @cmd and a title
327       @title for the dialog. */
328  void  void
329  set_gpg_passphrase_cb (gpgme_ctx_t c, passphrase_cb_s *ctx, int cmd,  set_gpg_passphrase_cb (passphrase_cb_s *cb, gpgme_ctx_t ctx,
330                         HWND hwnd, const char *title)                         int cmd, HWND hwnd, const char *title)
331  {  {
332      ctx->gpg_cmd = cmd;      memset (cb, 0, sizeof *cb);
333      ctx->is_card = 0;      cb->gpg_cmd = cmd;
334      ctx->cancel = 0;      cb->is_card = 0;
335      ctx->hwnd = hwnd;      cb->cancel = 0;
336      ctx->pwd_init = 1;      cb->hwnd = hwnd;
337      if (strlen (title) > 256)      cb->pwd_init = 1;
338          BUG (NULL); /* check bounds */      free_if_alloc (cb->title);
339      strcpy (ctx->title, title);      cb->title = m_strdup (title);
340      gpgme_set_passphrase_cb (c, passphrase_cb, ctx);      if (!cb->title)
341  } /* set_gpg_passphrase_cb */          BUG (NULL);
342        gpgme_set_passphrase_cb (ctx, passphrase_cb, cb);
343        cb->gpg = ctx;
344    }
345    
346    
347    /* Release a passphrase callback @ctx. */
348    void
349    release_gpg_passphrase_cb (passphrase_cb_s *ctx)
350    {
351        if (!ctx)
352            return;
353        sfree_if_alloc (ctx->pwd);
354        free_if_alloc (ctx->title);
355    }
356    
357    /* Simple check to measure passphrase (@pass) quality.
358       Return value: 0 on success. */
359  int  int
360  check_passwd_quality (const char *pass, int strict)  check_passwd_quality (const char *pass, int strict)
361  {  {

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26