/[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 4 by twoaday, Sun Feb 6 11:11:40 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 39  Line 41 
41  #define item_ctrl_id( cmd ) \  #define item_ctrl_id( cmd ) \
42      ((cmd) == GPG_CMD_DECRYPT? IDC_DECRYPT_PWD : IDC_DECRYPT_SIGN_PWD)      ((cmd) == GPG_CMD_DECRYPT? IDC_DECRYPT_PWD : IDC_DECRYPT_SIGN_PWD)
43    
44    #define item_ctrl_id2(cmd) \
45        ((cmd) == GPG_CMD_DECRYPT? IDC_DECRYPT_HIDE : IDC_DECRYPT_SIGN_HIDE)
46    
47  BOOL CALLBACK  
48    /* 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;
     static int hide = 1;  
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:
         hide = 1;  
61          c = (passphrase_cb_s *)lparam;          c = (passphrase_cb_s *)lparam;
62          if (!c)          if (!c)
63              BUG (0);              BUG (0);
# Line 64  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 {
95                        info = new char [32 + strlen (r->keyid) + 2];
96                        if (!info)
97                            BUG (NULL);
98                        sprintf (info, _("Unknown (key ID 0x%s)"),
99                                 r->keyid? r->keyid+8 : "????????");
100                        free (info);
101                  }                  }
102                  else                  listbox_add_string (GetDlgItem( dlg, IDC_DECRYPT_LIST ), info);
                     _snprintf( info, sizeof info - 1, _("Unknown (key ID 0x%s)"),  
                                s? s + 8 : "DEADBEEF" );  
                 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 98  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 117  passphrase_callback_proc (HWND dlg, UINT Line 132  passphrase_callback_proc (HWND dlg, UINT
132                  if ( LOWORD( wparam ) == IDC_DECRYPT_HIDE                  if ( LOWORD( wparam ) == IDC_DECRYPT_HIDE
133                      || LOWORD( wparam ) == IDC_DECRYPT_SIGN_HIDE ) {                      || LOWORD( wparam ) == IDC_DECRYPT_SIGN_HIDE ) {
134                      HWND hwnd;                      HWND hwnd;
135                      hide ^= 1;                      int hide = IsDlgButtonChecked (dlg, item_ctrl_id2 (c->gpg_cmd));
136                      hwnd = GetDlgItem( dlg, item_ctrl_id( c->gpg_cmd ) );                      hwnd = GetDlgItem (dlg, item_ctrl_id (c->gpg_cmd));
137                      SendMessage( hwnd, EM_SETPASSWORDCHAR, hide? '*' : 0, 0 );                      SendMessage( hwnd, EM_SETPASSWORDCHAR, hide? '*' : 0, 0 );
138                      SetFocus( hwnd );                      SetFocus (hwnd);
139                  }                  }
140              }              }
141    
# Line 129  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 149  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        write (fd, c->pwd, strlen (c->pwd));
320        write (fd, "\n", 1);
321        return 0;
322    }
323    
     if( c->cancel )  
         return NULL;  
324    
325      return c->pwd;  /* Initialize the given passphrase callback @cb with the
326  } /* passphrase_cb */     used gpgme context @ctx, the command @cmd and a title
327       @title for the dialog. */
328    void
329    set_gpg_passphrase_cb (passphrase_cb_s *cb, gpgme_ctx_t ctx,
330                           int cmd, HWND hwnd, const char *title)
331    {
332        memset (cb, 0, sizeof *cb);
333        cb->gpg_cmd = cmd;
334        cb->is_card = 0;
335        cb->cancel = 0;
336        cb->hwnd = hwnd;
337        cb->pwd_init = 1;
338        free_if_alloc (cb->title);
339        cb->title = m_strdup (title);
340        if (!cb->title)
341            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  void
349  set_gpg_passphrase_cb( gpgme_ctx_t c, passphrase_cb_s * ctx, int cmd,  release_gpg_passphrase_cb (passphrase_cb_s *ctx)
                        HWND hwnd, const char * title )  
350  {  {
351      ctx->gpg_cmd = cmd;      if (!ctx)
352      ctx->is_card = 0;          return;
353      ctx->cancel = 0;      sfree_if_alloc (ctx->pwd);
354      ctx->hwnd = hwnd;      free_if_alloc (ctx->title);
355      ctx->pwd_init = 1;  }
356      if( strlen( title ) > 256 )  
357          BUG( NULL ); /* check bounds */  /* Simple check to measure passphrase (@pass) quality.
358      strcpy( ctx->title, title );     Return value: 0 on success. */
359      gpgme_set_passphrase_cb( c, passphrase_cb, ctx );  int
360  } /* set_gpg_passphrase_cb */  check_passwd_quality (const char *pass, int strict)
361    {
362        int i, nd=0, nc=0, n;
363    
364        n = strlen (pass);
365        if (n < 8)
366            return -1;
367    
368        for (i=0; i < n; i++) {
369            if (isdigit (pass[i])) nd++;
370            if (isalpha (pass[i])) nc++;
371        }
372    
373        if (nd == n || nc == n)
374            return -1;
375    
376        return 0;
377    }

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26