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

Contents of /trunk/Src/wptPassphraseCB.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (show annotations)
Mon Jan 31 11:02:21 2005 UTC (20 years, 1 month ago) by twoaday
File size: 9407 byte(s)
WinPT initial checkin.


1 /* wptPassphraseCB.cpp - GPGME Passphrase Callback
2 * Copyright (C) 2001, 2002, 2003 Timo Schulz
3 *
4 * This file is part of WinPT.
5 *
6 * WinPT is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * WinPT is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with WinPT; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include <windows.h>
22 #include <ctype.h>
23
24 #include "../resource.h"
25 #include "wptNLS.h"
26 #include "wptW32API.h"
27 #include "wptVersion.h"
28 #include "wptGPG.h"
29 #include "wptCommonCtl.h"
30 #include "wptContext.h"
31 #include "wptDlgs.h"
32 #include "wptUTF8.h"
33 #include "wptErrors.h"
34 #include "wptTypes.h"
35 #include "wptAgent.h"
36 #include "wptRegistry.h"
37
38
39 #define item_ctrl_id( cmd ) \
40 ((cmd) == GPG_CMD_DECRYPT? IDC_DECRYPT_PWD : IDC_DECRYPT_SIGN_PWD)
41
42
43 BOOL CALLBACK
44 passphrase_callback_proc( HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam )
45 {
46 static passphrase_cb_s * c;
47 static int yes = 1;
48 gpgme_key_t key;
49 const char * s, * id;
50 char info[768] = {0};
51 void * ctx = NULL, * item;
52 unsigned int pkalgo;
53
54 switch( msg ) {
55 case WM_INITDIALOG:
56 c = (passphrase_cb_s *)lparam;
57 if( !c )
58 BUG( NULL );
59 SetWindowText( dlg, c->title );
60 if( c->gpg_cmd == GPG_CMD_DECRYPT ) {
61 SetDlgItemText( dlg, IDC_DECRYPT_LISTINF,
62 _("Encrypted with the following public key(s)") );
63 CheckDlgButton( dlg, IDC_DECRYPT_HIDE, BST_CHECKED );
64 }
65 else if( c->gpg_cmd == GPG_CMD_SIGN )
66 CheckDlgButton( dlg, IDC_DECRYPT_SIGN_HIDE, BST_CHECKED );
67 if( c->enc_to && c->gpg_cmd == GPG_CMD_DECRYPT ) {
68 gpgme_recipients_enum_open( c->enc_to, &ctx );
69 while ( (s = gpgme_recipients_enum_read( c->enc_to, &ctx )) ) {
70 pkalgo = *s; s++;
71 get_pubkey( s, &key );
72 if( key ) {
73 char * uid = NULL;
74 id = gpgme_key_get_string_attr( key, GPGME_ATTR_USERID, NULL, 0 );
75 if( !id )
76 id = _("Invalid User ID");
77 uid = utf8_to_wincp (id, strlen (id));
78 _snprintf( info, sizeof info - 1, "%s (%s, 0x%s)", uid,
79 gpgme_key_expand_attr( GPGME_ATTR_ALGO, pkalgo ), s+8 );
80 free( uid );
81 }
82 else
83 _snprintf( info, sizeof info - 1, _("Unknown (key ID 0x%s)"),
84 s? s + 8 : "DEADBEEF" );
85 listbox_add_string( GetDlgItem( dlg, IDC_DECRYPT_LIST ), info );
86 }
87 gpgme_recipients_enum_close( c->enc_to, &ctx );
88 }
89 SetDlgItemText( dlg, c->gpg_cmd == GPG_CMD_DECRYPT?
90 IDC_DECRYPT_PWDINFO : IDC_DECRYPT_SIGN_PWDINFO,
91 _("Please enter your passphrase") );
92 if( c->gpg_cmd == GPG_CMD_DECRYPT ) {
93 SetFocus( GetDlgItem( dlg, IDC_DECRYPT_PWD ) );
94 SetDlgItemText( dlg, IDC_DECRYPT_MSG, c->info );
95 }
96 else {
97 SetFocus( GetDlgItem( dlg, IDC_DECRYPT_SIGN_PWD ) );
98 SetDlgItemText( dlg, IDC_DECRYPT_SIGN_MSG, c->info );
99 }
100 center_window( dlg );
101 SetForegroundWindow( dlg );
102 set_active_window( dlg );
103 return FALSE;
104
105 case WM_SYSCOMMAND:
106 if( LOWORD( wparam ) == SC_CLOSE ) {
107 SetDlgItemText( dlg, item_ctrl_id( c->gpg_cmd ), "" );
108 c->cancel = 1;
109 EndDialog( dlg, TRUE );
110 }
111 return FALSE;
112
113 case WM_COMMAND:
114 switch( HIWORD( wparam ) ) {
115 case BN_CLICKED:
116 if ( LOWORD( wparam ) == IDC_DECRYPT_HIDE
117 || LOWORD( wparam ) == IDC_DECRYPT_SIGN_HIDE ) {
118 HWND hwnd;
119 yes ^= 1;
120 hwnd = GetDlgItem( dlg, item_ctrl_id( c->gpg_cmd ) );
121 SendMessage( hwnd, EM_SETPASSWORDCHAR, yes? '*' : 0, 0 );
122 SetFocus( hwnd );
123 }
124 }
125
126 switch( LOWORD( wparam ) ) {
127 case IDOK:
128 /* fixme: the item is even cached when the passphrase is not
129 correct, which means that the user needs to delete all
130 cached entries to continue. */
131 GetDlgItemText( dlg, item_ctrl_id( c->gpg_cmd ), c->pwd, sizeof c->pwd -1 );
132 if( reg_prefs.cache_time > 0 && !c->is_card ) {
133 if( agent_get_cache( c->keyid, &item ) )
134 agent_unlock_cache_entry( &item );
135 else
136 agent_put_cache( c->keyid, c->pwd, reg_prefs.cache_time );
137 }
138 EndDialog( dlg, TRUE );
139 return TRUE;
140
141 case IDCANCEL:
142 SetDlgItemText( dlg, item_ctrl_id( c->gpg_cmd ), "" );
143 c->cancel = 1;
144 EndDialog( dlg, FALSE );
145 return FALSE;
146 }
147 break;
148 }
149
150 return FALSE;
151 } /* passphrase_callback_proc */
152
153
154 static const char *
155 parse_gpg_keyid( const char * desc )
156 {
157 static char keyid[16+1];
158 char * p;
159
160 p = strrchr( desc, '\n' );
161 if( !p )
162 return NULL;
163 /* the format of the desc buffer looks like this:
164 request_keyid[16] main_keyid[16] keytype[1] keylength[4]
165 we use the main keyid to use only one cache entry. */
166 strncpy( keyid, desc+(p-desc+1+17), 16 );
167 return keyid;
168 } /* parse_gpg_keyid */
169
170
171 static void
172 parse_gpg_description( char * desc, int size )
173 {
174 char * buffer = NULL, ch, uid[128] = {0}, * uid2 = NULL;
175 char usedkey[16+1] = {0}, mainkey[16+1] = {0};
176 const char * buf;
177 int i, algo, try_again = 0;
178
179 if( stristr( desc, "[User ID hint missing]" )
180 || stristr( desc, "[passphrase info missing]" ) ) {
181 _snprintf( desc, size-1,
182 _("You need a passphrase to unlock the secret key for\n"
183 "user: [UserID hint missing]\n"
184 " [passphrase info missing]\n") );
185 return;
186 }
187
188 buffer = new char[size+1];
189 if( !buffer )
190 BUG( NULL );
191 strcpy( buffer, desc );
192 buf = buffer;
193 if( strstr( buf, "TRY_AGAIN" ) ) {
194 buf += strlen( "TRY_AGAIN\n" );
195 try_again = 1;
196 }
197 else if( strstr( buf, "ENTER_PASSPHRASE" ) )
198 buf += strlen( "ENTER_PASSPHRASE\n" );
199 else
200 BUG( NULL );
201 buf += 17;
202 for( i = 0; i < sizeof uid-1; i++ ) {
203 ch = *buf++;
204 if( ch == '\n' ) {
205 uid[i] = '\0';
206 break;
207 }
208 uid[i] = ch;
209 }
210 memcpy( usedkey, buf, 16 );
211 usedkey[16] = '\0';
212 buf += 17;
213 memcpy( mainkey, buf, 16 );
214 mainkey[16] = '\0';
215 buf += 17;
216 if( !buf )
217 BUG( NULL );
218 algo = atol( buf );
219 free_if_alloc( buffer );
220
221 uid2 = utf8_to_wincp (uid, strlen (uid));
222
223 if( strcmp( usedkey, mainkey ) )
224 _snprintf( desc, size-1,
225 _("You need a passphrase to unlock the secret key for\n"
226 "user: \"%s\"\n"
227 "%s key, ID %s (main key ID %s)\n"),
228 uid2, gpgme_key_expand_attr( GPGME_ATTR_ALGO, algo ),
229 usedkey+8, mainkey+8 );
230 else if( !strcmp( usedkey, mainkey ) )
231 _snprintf( desc, size-1,
232 _("You need a passphrase to unlock the secret key for\n"
233 "user: \"%s\"\n"
234 "%s key, ID %s\n"),
235 uid2, gpgme_key_expand_attr( GPGME_ATTR_ALGO, algo ),
236 usedkey+8 );
237 free( uid2 );
238 } /* parse_gpg_describtion */
239
240
241 static int inline
242 is_hexstring( const char * p )
243 {
244 size_t i;
245 for( i=0; i < strlen( p ); i++ ) {
246 if( !isxdigit( p[i] ) )
247 return -1;
248 }
249 return 0;
250 }
251
252
253 const char *
254 passphrase_cb( void * opaque, const char * desc, void * r_hd )
255 {
256 passphrase_cb_s * c = (passphrase_cb_s *)opaque;
257 void * item;
258 const char * pass, * keyid;
259 int rc = 0;
260
261 if( !c )
262 return NULL;
263
264 if( desc ) {
265 keyid = parse_gpg_keyid( desc );
266 pass = agent_get_cache( keyid, &item );
267 if( pass ) {
268 agent_unlock_cache_entry( &item );
269 c->pwd_init = 0;
270 return pass;
271 }
272 }
273
274 if( c->pwd_init ) {
275 c->keyid = keyid;
276 /* if the desc has a length of 32 and only hex digits, we assume a
277 smart card has been used. */
278 /*log_box( "", 0, "%s %d %d", desc,strlen( desc), is_hexstring( desc ) );*/
279 if( desc && strlen( desc ) == 32 && !is_hexstring( desc ) ) {
280 char buf[16];
281 memset( buf, 0, sizeof buf );
282 strncpy( buf, desc+20, 8 );
283 _snprintf( c->info, sizeof c->info-1,
284 _("Please enter the PIN to unlock your secret card key\n"
285 "Card: %s"), buf );
286 c->is_card = 1;
287 }
288 else if( desc ) {
289 strcpy( c->info, desc );
290 parse_gpg_description( c->info, sizeof c->info - 1 );
291 }
292 if( c->gpg_cmd == GPG_CMD_DECRYPT ) {
293 rc = DialogBoxParam( glob_hinst, (LPCSTR)IDD_WINPT_DECRYPT,
294 (HWND)c->hwnd, passphrase_callback_proc,
295 (LPARAM)c );
296 }
297 else if( c->gpg_cmd == GPG_CMD_SIGN ) {
298 rc = DialogBoxParam( glob_hinst, (LPCSTR)IDD_WINPT_DECRYPT_SIGN,
299 (HWND)c->hwnd, passphrase_callback_proc,
300 (LPARAM)c );
301 }
302 if( rc == -1 )
303 return NULL;
304 c->pwd_init = 0;
305 }
306
307 if( c->cancel )
308 return NULL;
309
310 return c->pwd;
311 } /* passphrase_cb */
312
313
314 void
315 set_gpg_passphrase_cb( gpgme_ctx_t c, passphrase_cb_s * ctx, int cmd,
316 HWND hwnd, const char * title )
317 {
318 ctx->gpg_cmd = cmd;
319 ctx->is_card = 0;
320 ctx->cancel = 0;
321 ctx->hwnd = hwnd;
322 ctx->pwd_init = 1;
323 if( strlen( title ) > 256 )
324 BUG( NULL ); /* check bounds */
325 strcpy( ctx->title, title );
326 gpgme_set_passphrase_cb( c, passphrase_cb, ctx );
327 } /* set_gpg_passphrase_cb */

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26