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

Contents of /trunk/Src/wptCardDlg.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 47 - (show annotations)
Mon Oct 31 14:04:59 2005 UTC (19 years, 4 months ago) by werner
File size: 23439 byte(s)
Minor changes; compiles now but gettext is still missing.

1 /* wptCardDlg.cpp - Smart Card support
2 * Copyright (C) 2003, 2004, 2005 Timo Schulz
3 * Copyright (C) 2005 g10 Code GmbH
4 *
5 * This file is part of WinPT.
6 *
7 * WinPT is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * WinPT is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with WinPT; if not, write to the Free Software Foundation,
19 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20 */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <windows.h>
27 #include <windows.h>
28 #include <commctrl.h>
29 #include <ctype.h>
30
31 #include "resource.h"
32 #include "gpgme.h"
33 #include "wptTypes.h"
34 #include "wptW32API.h"
35 #include "wptErrors.h"
36 #include "wptRegistry.h"
37 #include "wptVersion.h"
38 #include "wptCommonCtl.h"
39 #include "wptDlgs.h"
40 #include "wptGPG.h"
41 #include "wptUTF8.h"
42 #include "wptCardEdit.h"
43 #include "wptCard.h"
44 #include "wptContext.h"
45
46 int keygen_check_date (SYSTEMTIME * st);
47
48 static const char * sex[] = {"Male", "Female", "Undefined", NULL};
49 static const char * lang[] = {"Undefined", "cs", "de", "en", "es", "fr", "hu",
50 "it", "nl", "pt", "ro", "ru", "zh", "at",
51 NULL};
52
53 static pin_cb_ctx_s pincb;
54
55 struct {
56 int ctlid;
57 const char * err;
58 } attr_tab[] = {
59 {IDC_CEDIT_AID, ""},
60 {IDC_CEDIT_VENDOR, "No Vendor"},
61 {IDC_CEDIT_VERSION,"No Version"},
62 {IDC_CEDIT_SERIAL, "No Serial-No"},
63 {IDC_CEDIT_NAME, "No Name"},
64 {IDC_CEDIT_NAME2, "No Surname"},
65 {IDC_CEDIT_KEYURL, "No Key-URL"},
66 {IDC_CEDIT_LOGIN, "No Login name"},
67 {0},
68 };
69
70
71
72 /* XXX: simplify code. */
73 char*
74 get_printable_version (const char *version)
75 {
76 static char buf[16];
77 char tmp_maj[3]={0}, tmp_min[3]={0};
78
79 strncpy (tmp_maj, version, 2);
80 strncpy (tmp_min, version+2, 2);
81 sprintf (buf, "%d.%d", atoi (tmp_maj), atoi (tmp_min));
82 return buf;
83 }
84
85 /* Return all card attributes from @card. @n contains
86 the number of items which were returned. */
87 char**
88 card_get_items (gpg_card_t card, int *n)
89 {
90 char **p;
91
92 *n= 8;
93 p = (char **)calloc (*n+1, sizeof (char*));
94 if (!p)
95 BUG (0);
96 p[0] = card->aid;
97 p[1] = card->vendor;
98 p[2] = get_printable_version (card->version);
99 p[3] = card->serial;
100 p[4] = card->givenname;
101 p[5] = card->surname;
102 p[6] = card->url;
103 p[7] = card->login;
104 return p;
105 }
106
107
108 static int
109 idx_from_lang (const char * _lang)
110 {
111 const char * s;
112 int i;
113
114 if (!_lang)
115 return 0;
116 for (i=0; (s = lang[i]); i++) {
117 if (!strcmp (_lang, s ))
118 return i;
119 }
120 return 0;
121 }
122
123
124 #if 0 /* @unused@ */
125 int
126 show_card_status (void)
127 {
128 int rc = 0;
129 int cardstat;
130
131 cardstat = pcsc_get_card_status ();
132 if ((cardstat & CARD_STATE_UNAWARE) || (cardstat & CARD_STATE_UNAVAIL))
133 rc = WPTERR_NOREADER;
134 else if (cardstat & CARD_STATE_EMPTY)
135 rc = WPTERR_NOCARD;
136 if (rc) {
137 msg_box (NULL, winpt_strerror (rc), _("Card Manager"), MB_ERR);
138 return -1;
139 }
140 return 0;
141 } /* show_card_status */
142 #endif
143
144 /* Check if there is a card in the reader and analyze the
145 returned information.
146 Return value: card context or NULL on error. */
147 gpg_card_t
148 gpg_card_load (void)
149 {
150 gpgme_error_t err;
151 GpgCardEdit *ce;
152 gpg_card_t card = NULL;
153 struct card_cb_s cb = {0};
154
155 ce = new GpgCardEdit ();
156 if (!ce)
157 BUG (0);
158 memset (&cb, 0, sizeof (cb));
159 ce->setCallback (card_callback, &cb);
160 err = ce->getCardStatus (&card);
161 if (err) {
162 msg_box (NULL, gpgme_strerror (err), _("Card Manager"), MB_ERR);
163 goto leave;
164 }
165
166 if (!card->aid || strncmp (card->aid, "D276000124", 10)) {
167 msg_box (NULL, winpt_strerror (WPTERR_NOPGPCARD), "WinPT", MB_ERR);
168 gpg_card_release (card);
169 card = NULL;
170 }
171 else {
172 struct winpt_key_s key;
173 memset (&key, 0, sizeof (key));
174 winpt_get_pubkey (card->fpr[1]+32, &key);
175 if (key.ext) {
176 key.ext->card_type = strdup (card->card_type);
177 if (!key.ext->card_type)
178 BUG (NULL);
179 /* memory will be released in gpg_keycache_release (). */
180 }
181 }
182
183 leave:
184 delete ce;
185 return card;
186 }
187
188
189 /* Print human friendly fingerprint to control @id in the
190 dialog @dlg. @fpr contains the raw fingerprint. */
191 static void
192 print_fpr (HWND dlg, int id, const char * fpr)
193 {
194 char buf[128], dig[2];
195 size_t i, c;
196
197 if (!fpr)
198 strcpy (buf, _("No Fingerprint"));
199 else {
200 memset (buf, 0, sizeof (buf));
201 for( i=0, c=0; i < strlen (fpr); i++) {
202 dig[0] = fpr[i]; dig[1] = 0;
203 strcat (buf, dig);
204 if (++c == 4) {
205 strcat (buf, " ");
206 c=0;
207 }
208 }
209 }
210 SetDlgItemText (dlg, id, buf);
211 }
212
213
214 /* Fill in all card information from @card. into the corresponding
215 dialog item fields in the dialog @dlg.
216 Return value: 0 on success. */
217 static int
218 card_status (HWND dlg, gpg_card_t card)
219 {
220 static int fprbuf[] = {IDC_CEDIT_FPR1, IDC_CEDIT_FPR2, IDC_CEDIT_FPR3, 0};
221 static int fprtime[] = {IDC_CEDIT_SIG_FPRTIME, IDC_CEDIT_DEC_FPRTIME, IDC_CEDIT_AUTH_FPRTIME, 0};
222 const char *s;
223 char **attrs;
224 char cardinf[128];
225 int idx=0, n=0;
226
227 if (!card->aid) {
228 msg_box( dlg, _("No OpenPGP smart card detected."), "WinPT", MB_ERR );
229 return -1;
230 }
231 SetDlgItemText (dlg, IDC_CEDIT_AID, card->aid);
232 SetDlgItemInt (dlg, IDC_CEDIT_SIGCOUNT, card->sig_count, TRUE);
233
234 for (idx=0; fprbuf[idx]; idx++) {
235 print_fpr (dlg, fprbuf[idx], card->fpr[idx]);
236 SetDlgItemText (dlg, fprtime[idx], card->fpr_created_str[idx]);
237 }
238
239 attrs = card_get_items (card, &n);
240 for (idx=1; attr_tab[idx].ctlid; idx++) {
241 s = attrs[idx];
242 SetDlgItemText (dlg, attr_tab[idx].ctlid, s && *s? s : attr_tab[idx].err);
243 }
244 free (attrs);
245
246 idx = idx_from_lang (card->lang);
247 SendDlgItemMessage (dlg, IDC_CEDIT_LANG, CB_SETCURSEL, (WPARAM)idx, 0);
248
249 switch (card->sex) {
250 case 'm': idx=0; break;
251 case 'f': idx=1; break;
252 default :
253 case 'u': idx=2; break;
254 }
255 SendDlgItemMessage (dlg, IDC_CEDIT_SEX, CB_SETCURSEL, (WPARAM)idx, 0);
256
257 s = card->serial;
258 while (s && *s == '0') s++;
259 _snprintf (cardinf, sizeof (cardinf)-1,
260 "Card Edit - %s serial no. %s version %s",
261 card->card_type, s, get_printable_version (card->version));
262 SetWindowText (dlg, cardinf);
263
264 return 0;
265 }
266
267
268 /* Initialize the enum combox boxes in dialog @dlg. */
269 static void
270 prepare_dialog (HWND dlg)
271 {
272 const char * s;
273 int i;
274
275 for (i=0; (s = sex[i]); i++)
276 SendDlgItemMessage (dlg, IDC_CEDIT_SEX, CB_ADDSTRING, 0, (LPARAM) s);
277 SendDlgItemMessage (dlg, IDC_CEDIT_SEX, CB_SETCURSEL, 0, 0);
278 for (i=0; (s = lang[i]); i++)
279 SendDlgItemMessage (dlg, IDC_CEDIT_LANG, CB_ADDSTRING, 0, (LPARAM)s);
280 SendDlgItemMessage (dlg, IDC_CEDIT_LANG, CB_SETCURSEL, 0, 0);
281 }
282
283
284 /* Return 0 if the given string @str has the proper format. */
285 static int
286 check_string (const char *str, int flags)
287 {
288 size_t i;
289 for (i=0; i < strlen (str); i++) {
290 if (flags & 0x02 && !isalpha (str[i]))
291 return -1;
292 }
293 return 0;
294 }
295
296
297 static int
298 do_proc_card_cmds (HWND dlg, struct pin_cb_ctx_s *pincb, gpg_card_t card)
299 {
300 static struct {
301 int id;
302 int cmd;
303 int us_ascii;
304 int changed;
305 } idctl[] = {
306 {IDC_CEDIT_NAME, GPG_EDITCARD_NAME, 1, 0},
307 {IDC_CEDIT_LANG2, GPG_EDITCARD_LANG, 1, 0},
308 {IDC_CEDIT_SEX2, GPG_EDITCARD_SEX, 1|1,0},
309 {IDC_CEDIT_KEYURL,GPG_EDITCARD_KEYURL,1|4,0},
310 {IDC_CEDIT_LOGIN, GPG_EDITCARD_LOGIN, 1, 0},
311 {0}
312 };
313 gpgme_error_t err;
314 GpgCardEdit *ce;
315 char buf[256], tmp[128];
316 int errc=0, use_arg2 = 0;
317 int i, id, n=0;
318
319 /* XXX rewrite the entire function */
320 for( i=0; idctl[i].id; i++ ) /* reset */
321 idctl[i].changed = 0;
322
323 if( SendMessage( GetDlgItem( dlg, IDC_CEDIT_LANG2 ), WM_GETTEXTLENGTH, 0, 0 ) ) {
324 idctl[1].changed = 1;
325 n++;
326 }
327 if( SendMessage( GetDlgItem( dlg, IDC_CEDIT_SEX2 ), WM_GETTEXTLENGTH, 0, 0 ) ) {
328 idctl[2].changed = 1;
329 n++;
330 }
331
332 if( SendDlgItemMessage( dlg, IDC_CEDIT_NAME2, EM_GETMODIFY, 0, 0 ) ) {
333 idctl[0].changed = 1;
334 n++;
335 }
336 for( i=0; (id = idctl[i].id); i++ ) {
337 if( SendDlgItemMessage( dlg, id, EM_GETMODIFY, 0, 0 ) ) {
338 idctl[i].changed = 1;
339 n++;
340 }
341 }
342 if (!pincb || !card) /* just return the changed elements */
343 return n;
344 if (!n)
345 return 0;
346 if (!pincb->apin) {
347 msg_box (dlg, _("No PINs found."), _("Card Edit"), MB_ERR);
348 return 0;
349 }
350
351 ce = new GpgCardEdit ();
352 if (!ce)
353 BUG (NULL);
354 ce->setAdminPIN (pincb->apin);
355 /*ce->setPIN (pincb->upin);*/
356 for( i=0; idctl[i].id; i++ ) {
357 if( idctl[i].changed ) {
358 GetDlgItemText( dlg, idctl[i].id, buf, sizeof (buf)-1 );
359 if (idctl[i].us_ascii && is_8bit_string (buf)) {
360 msg_box (dlg, _("Only plain ASCII is currently allowed."),
361 _("Card Edit"), MB_ERR);
362 errc--; continue;
363 }
364 if( (idctl[i].us_ascii & 2) && check_string( buf, 2 ) ) {
365 msg_box( dlg, _("Only alphabetic characters are allowed."),
366 _("Card Edit"), MB_ERR );
367 errc--; continue;
368 }
369 if ((idctl[i].us_ascii & 4) &&
370 (!strchr (buf, ':') || !strstr (buf, "//"))) {
371 /* XXX: better URL check. */
372 msg_box (dlg, _("Invalid URL."), _("Card Edit"), MB_ERR);
373 errc--; continue;
374 }
375 if( idctl[i].cmd == GPG_EDITCARD_NAME ) {
376 /* The "name" command actually needs two fields */
377 GetDlgItemText( dlg, IDC_CEDIT_NAME2, tmp, sizeof tmp-1 );
378 use_arg2 = 1;
379 }
380 else
381 use_arg2 = 0;
382 err = ce->doCmd (idctl[i].cmd, buf, use_arg2? tmp : NULL);
383 if (err) {
384 log_box (_("Card Edit"), MB_ERR,
385 _("Could not modify card attribute: %s"),
386 gpgme_strerror (err));
387 errc--;
388 /* If no card is inserted, we leave the loop. */
389 if (gpgme_err_code (err) == GPG_ERR_CARD_NOT_PRESENT)
390 break;
391 }
392 }
393 }
394 if (!errc) {
395 /* if the operation(s) succeeded, reset the modify flag for each control */
396 for( i = 0; idctl[i].id; i++ )
397 SendDlgItemMessage( dlg, idctl[i].id, EM_SETMODIFY, (WPARAM)(UINT)FALSE, 0 );
398 msg_box( dlg, _("Card attribute changed."), _("Card Edit"), MB_OK );
399 SetDlgItemText( dlg, IDC_CEDIT_LANG2, "" );
400 SetDlgItemText( dlg, IDC_CEDIT_SEX2, "" );
401 }
402 delete ce;
403 return errc;
404 } /* do_proc_card_cmds */
405
406
407 /* Cleanup pin callback @ctx. */
408 void
409 free_pincb (struct pin_cb_ctx_s *ctx)
410 {
411 if (!ctx)
412 return;
413 free_if_alloc (ctx->info_text);
414 sfree_if_alloc (ctx->upin);
415 sfree_if_alloc (ctx->apin);
416 }
417
418
419 /* Request a PIN from the user. @which decided if the
420 normal PIN or the admin PIN will be requested.
421 @card is used to show some information to the user.
422 @pincb is the actuall callback context.
423 Return value: 0 on success. */
424 static int
425 do_askpin (HWND dlg, int which, gpg_card_t card,
426 struct pin_cb_ctx_s *pincb)
427 {
428 const char * s, * fmt;
429 const char * n1, * n2, * serial;
430 char * p;
431 size_t n;
432
433 if( (which == CARD_ADMIN_PIN && pincb->apin) ||
434 (which == CARD_USER_PIN && pincb->upin) )
435 return 0;
436
437 if (which == CARD_ADMIN_PIN)
438 s = _("Please enter the 'Admin PIN'");
439 else if (which == CARD_USER_PIN)
440 s = _("Please enter the 'User PIN'");
441 else
442 s = _("Please enter the PIN");
443 pincb->which = which;
444 free_if_alloc( pincb->info_text );
445 if( card ) {
446 fmt = _("%s\nName: %s %s\nSerial-No: %s\n");
447 n1 = card->givenname;
448 n2 = card->surname;
449 if( !n1 || !n2 ) {
450 n1 = "No"; n2 = "Name";
451 }
452 serial = card->serial;
453 if (!serial)
454 serial = "No Serial ID";
455 n = strlen( n1 ) + strlen( n2 ) + strlen( fmt ) + strlen( serial ) + 3;
456 p = pincb->info_text = new char[strlen( s )+n+1 ];
457 if( !p )
458 BUG (0);
459 sprintf( p, fmt, s, n1, n2, serial );
460 }
461 else {
462 p = pincb->info_text = m_strdup (s);
463 if (!p)
464 BUG (0);
465 }
466 DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_PIN, dlg,
467 pin_cb_dlg_proc, (LPARAM)pincb);
468 if (!pincb->apin && !pincb->upin) {
469 safe_free (pincb->info_text);
470 return -1;
471 }
472 return 0;
473 }
474
475
476 /* Dialog box procedure for card edit. */
477 BOOL CALLBACK
478 card_edit_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
479 {
480 static gpg_card_t card;
481 char tmp[128];
482 size_t n=0;
483
484 switch (msg) {
485 case WM_INITDIALOG:
486 card = (gpg_card_t)lparam;
487 if (!card)
488 BUG (0);
489 prepare_dialog (dlg);
490 if (card_status (dlg, card ))
491 EndDialog (dlg, TRUE);
492 center_window (dlg, NULL);
493 SetForegroundWindow (dlg);
494 return TRUE;
495
496 case WM_DESTROY:
497 free_pincb (&pincb);
498 memset (&pincb, 0, sizeof pincb);
499 break;
500
501 case WM_COMMAND:
502 switch( HIWORD( wparam ) ) {
503 case CBN_KILLFOCUS:
504 case CBN_EDITCHANGE:
505 case CBN_EDITUPDATE:
506 int ctlid = GetDlgCtrlID( (HWND)lparam );
507 int dstid = 0;
508
509 switch (ctlid) {
510 case IDC_CEDIT_LANG: dstid = IDC_CEDIT_LANG2; break;
511 case IDC_CEDIT_SEX: dstid = IDC_CEDIT_SEX2; break;
512 }
513 GetDlgItemText (dlg, ctlid, tmp, sizeof (tmp)-1);
514 SetDlgItemText (dlg, dstid, tmp);
515 break;
516 }
517 switch (LOWORD (wparam)) {
518 case IDC_CEDIT_CHPIN:
519 DialogBoxParam( glob_hinst, (LPCTSTR)IDD_WINPT_CARD_CHPIN, dlg,
520 card_changepin_dlg_proc, NULL );
521 break;
522
523 case IDC_CEDIT_NEWKEYS:
524 if (item_get_text_length (dlg, IDC_CEDIT_FPR1) > 0) {
525 int id = msg_box (dlg,
526 _("This operation will override the keys on the card.\n"
527 "Still proceed?"), _("Card Edit"), MB_WARN|MB_YESNO);
528 if (id == IDNO)
529 return TRUE;
530 }
531 DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_CARD_KEYGEN,
532 glob_hwnd, card_keygen_dlg_proc, NULL);
533 break;
534
535 case IDOK:
536 n = do_proc_card_cmds (dlg, NULL, NULL);
537 if (n) {
538 if (do_askpin (dlg, CARD_ADMIN_PIN, card, &pincb))
539 EndDialog (dlg, FALSE);
540 }
541 do_proc_card_cmds (dlg, &pincb, card);
542 free_pincb (&pincb);
543 if (!n)
544 EndDialog (dlg, TRUE);
545 break;
546
547 case IDCANCEL:
548 EndDialog( dlg, FALSE );
549 break;
550 }
551 break;
552 }
553
554 return FALSE;
555 }
556
557
558 static int /* fixme: works only roughly */
559 calc_days (int y2, int m2, int d2,
560 int y1, int m1, int d1)
561
562 {
563 int n=0;
564
565 if ((y2-y1) > 0)
566 n += (y2-y1)*365;
567 if ((m2-m1) > 0)
568 n += (m2-m1)*30;
569 if ((d2-d1) > 0)
570 n += (d2-d1);
571 else if ((d2-d1) < 0)
572 n -= (d1-d2);
573 return n;
574 }
575
576
577 /* Dialog box procedure for the key generation on cards. */
578 BOOL CALLBACK
579 card_keygen_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
580 {
581 gpgme_error_t err;
582 GpgCardEdit *ce;
583 char name[128], email[128], comment[128];
584 char pass[128];
585 int card_flags = GPG_CARDFLAG_NONE;
586 int expires=0, valid;
587 size_t n;
588
589 switch (msg) {
590 case WM_INITDIALOG:
591 center_window (dlg, NULL);
592 CheckDlgButton (dlg, IDC_CKEYGEN_REPLACE, BST_CHECKED);
593 CheckDlgButton (dlg, IDC_CKEYGEN_NEVER, BST_CHECKED);
594 CheckDlgButton (dlg, IDC_CKEYGEN_BACKUP, BST_CHECKED);
595 EnableWindow (GetDlgItem (dlg, IDC_CKEYGEN_VALID), FALSE);
596 SendDlgItemMessage (dlg, IDC_CKEYGEN_ALG, CB_ADDSTRING, 0,
597 (LPARAM)(const char*)"RSA");
598 SendDlgItemMessage (dlg, IDC_CKEYGEN_ALG, CB_SETCURSEL, 0, 0);
599 SetFocus (GetDlgItem (dlg, IDC_CKEYGEN_NAME));
600 SetForegroundWindow (dlg);
601 SetDlgItemText (dlg, IDC_CKEYGEN_NAMEINF, _("&Name"));
602 SetDlgItemText (dlg, IDC_CKEYGEN_CMTINF, _("&Comment (optional)"));
603 SetDlgItemText (dlg, IDC_CKEYGEN_EXPDATEINF, _("&Expire date"));
604 SetDlgItemText (dlg, IDC_CKEYGEN_PWDINF, _("Off-card passphrase"));
605 SetDlgItemText (dlg, IDC_CKEYGEN_NEVER, _("&Never"));
606 SetDlgItemText (dlg, IDC_CKEYGEN_MAILINF, _("Email &address"));
607 SetWindowText (dlg, _("Card Key Generation"));
608 return FALSE;
609
610 case WM_SYSCOMMAND:
611 if (LOWORD (wparam) == SC_CLOSE)
612 EndDialog (dlg, TRUE);
613 return FALSE;
614
615 case WM_COMMAND:
616 if (HIWORD (wparam) == BN_CLICKED &&
617 (LOWORD (wparam) == IDC_CKEYGEN_BACKUP) ||
618 LOWORD (wparam) == IDC_CKEYGEN_NEVER) {
619 EnableWindow (GetDlgItem (dlg, IDC_CKEYGEN_VALID),
620 IsDlgButtonChecked (dlg, IDC_CKEYGEN_NEVER)? 0: 1);
621 EnableWindow (GetDlgItem (dlg, IDC_CKEYGEN_PASS),
622 IsDlgButtonChecked (dlg, IDC_CKEYGEN_BACKUP)? 1 : 0);
623 return TRUE;
624 }
625
626 switch (LOWORD (wparam)) {
627 case IDOK:
628 n = item_get_text_length (dlg, IDC_CKEYGEN_NAME);
629 if (!n) {
630 msg_box (dlg, _("Please enter your name."), _("Card Edit"), MB_ERR);
631 return TRUE;
632 }
633 if (n < 5) {
634 msg_box (dlg, _("Name must be at least 5 characters long."),
635 _("Card Edit"), MB_INFO);
636 return TRUE;
637 }
638 n = item_get_text_length (dlg, IDC_CKEYGEN_EMAIL);
639 if (!n) {
640 msg_box (dlg, _("Please enter your e-mail address."),
641 _("Card Edit"), MB_ERR);
642 return TRUE;
643 }
644 GetDlgItemText (dlg, IDC_CKEYGEN_NAME, name, sizeof (name)-1);
645 GetDlgItemText (dlg, IDC_CKEYGEN_EMAIL, email, sizeof (email)-1);
646 if (!strchr (email, '@') || n < 3) {
647 msg_box (dlg, _("Please enter a valid e-mail address."),
648 _("Card Edit"), MB_ERR);
649 return TRUE;
650 }
651 n = GetDlgItemText (dlg, IDC_CKEYGEN_PASS, pass, sizeof (pass)-1);
652 if (!n && IsDlgButtonChecked (dlg, IDC_CKEYGEN_BACKUP)) {
653 msg_box (dlg, _("Please enter an off-card passphrase."), _("Card Edit"), MB_ERR);
654 return TRUE;
655 }
656 n = item_get_text_length (dlg, IDC_CKEYGEN_COMMENT);
657 if (n > 0)
658 GetDlgItemText (dlg, IDC_CKEYGEN_COMMENT, comment, sizeof (comment)-1);
659 if (is_8bit_string (name) || n > 0 && is_8bit_string (comment)) {
660 msg_box (dlg, _("Please use plain ASCII charset for the fields."),
661 _("Card Edit"), MB_INFO);
662 return TRUE;
663 }
664 memset (&pincb, 0, sizeof (pincb));
665 if (do_askpin (dlg, CARD_ADMIN_PIN, NULL, &pincb)) {
666 free_pincb (&pincb);
667 return TRUE;
668 }
669 if (do_askpin (dlg, CARD_USER_PIN, NULL, &pincb)) {
670 free_pincb (&pincb);
671 return TRUE;
672 }
673 ce = new GpgCardEdit ();
674 if (!ce)
675 BUG (0);
676
677 expires = !IsDlgButtonChecked (dlg, IDC_CKEYGEN_NEVER);
678 if (expires) {
679 SYSTEMTIME st, ct;
680 DateTime_GetSystemtime (GetDlgItem (dlg, IDC_CKEYGEN_VALID), &st);
681 if (!keygen_check_date (&st)) {
682 msg_box (dlg, _("The date you have chosen lies in the past."),
683 _("Card Edit"), MB_ERR);
684 free_pincb (&pincb);
685 delete ce;
686 return TRUE;
687 }
688 GetSystemTime (&ct);
689 /* XXX this is not very precise */
690 valid = calc_days (st.wYear, st.wMonth, st.wDay,
691 ct.wYear, ct.wMonth, ct.wDay);
692 }
693 if (IsDlgButtonChecked (dlg, IDC_CKEYGEN_REPLACE))
694 card_flags |= GPG_CARDFLAG_REPLACE;
695 if (IsDlgButtonChecked (dlg, IDC_CKEYGEN_BACKUP))
696 card_flags |= GPG_CARDFLAG_BAKENC;
697 ce->setKeygenPassphrase (pass);
698 ce->setPIN (pincb.upin);
699 ce->setAdminPIN (pincb.apin);
700
701 SetCursor (LoadCursor (NULL, IDC_WAIT));
702 err = ce->genKey (card_flags, name, email, n? comment: NULL,
703 expires? valid : 0, NULL);
704
705 SetCursor (LoadCursor (NULL, IDC_ARROW));
706
707 if (gpgme_err_code (err) == GPG_ERR_CANCELED)
708 msg_box (dlg, _("Operation was canceled. It seems that there are "
709 "existing\nkeys on the cards. You need to mark the "
710 "'Overwrite' flag."), _("Card Edit"), MB_INFO);
711 else
712 if (err)
713 msg_box (dlg, "The operation does not succeed.\n"
714 "Please make sure you entered the right PIN's."
715 , _("Card Edit"), MB_ERR);
716 else
717 msg_box (dlg, _("Keys successfully created."),
718 _("Card Edit"), MB_OK);
719 wipememory (pass, sizeof (pass));
720 free_pincb (&pincb);
721 delete ce;
722 return TRUE;
723
724 case IDCANCEL:
725 EndDialog (dlg, FALSE);
726 return FALSE;
727 }
728 break;
729 }
730 return FALSE;
731 }
732
733
734 /* Check if the given pinlen is valid.
735 @which decided what PIN will be used.
736 @pinlen is the pin length entered by the user.
737 Return value: 0 on success. */
738 static int
739 check_pin_len (int which, int flag, int pinlen)
740 {
741 if (!pinlen) {
742 if (flag)
743 msg_box (NULL, _("Please enter the old card PIN."), _("Card Edit"), MB_ERR);
744 else
745 msg_box (NULL, _("Please enter the new card PIN."), _("Card Edit"), MB_ERR);
746 return -1;
747 }
748 if (which == CARD_ADMIN_PIN
749 && pinlen < 8) {
750 msg_box (NULL, _("Admin PIN must be minimal 8 characters."), _("Card Edit"), MB_ERR);
751 return -1;
752 }
753 if (which == CARD_USER_PIN
754 && pinlen < 6) {
755 msg_box (NULL, _("PIN must be minimal 6 characters."), _("Card Edit"), MB_ERR);
756 return -1;
757 }
758 return 0;
759 }
760
761 /* Dialog box procedure to change the PIN. */
762 BOOL CALLBACK
763 card_changepin_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
764 {
765 static int hide = 1;
766 gpgme_error_t err;
767 GpgCardEdit *ce;
768 char pold[128], pnew[128], pnew2[128];
769 int which;
770 size_t n;
771
772 switch( msg ) {
773 case WM_INITDIALOG:
774 hide = 1;
775 CheckDlgButton (dlg, IDC_CHPIN_HIDE, BST_CHECKED);
776 center_window (dlg, NULL);
777 CheckDlgButton (dlg, IDC_CHPIN_ISWORK, BST_CHECKED);
778 SetWindowText (dlg, _("Change Card PIN"));
779 SetForegroundWindow (dlg);
780 break;
781
782 case WM_COMMAND:
783 if (HIWORD (wparam) == BN_CLICKED && LOWORD (wparam) == IDC_CHPIN_HIDE) {
784 HWND hwnd;
785 hide ^= 1;
786 hwnd = GetDlgItem (dlg, IDC_CHPIN_OLDPIN);
787 SendMessage (hwnd, EM_SETPASSWORDCHAR, hide? '*' : 0, 0);
788 SetFocus (hwnd);
789 hwnd = GetDlgItem (dlg, IDC_CHPIN_NEWPIN);
790 SendMessage (hwnd, EM_SETPASSWORDCHAR, hide? '*' : 0, 0);
791 SetFocus (hwnd);
792 hwnd = GetDlgItem (dlg, IDC_CHPIN_NEWPIN2);
793 SendMessage (hwnd, EM_SETPASSWORDCHAR, hide? '*' : 0, 0);
794 SetFocus (hwnd);
795 }
796 switch( LOWORD( wparam ) ) {
797 case IDOK:
798 if (IsDlgButtonChecked (dlg, IDC_CHPIN_ISADMIN))
799 which = CARD_ADMIN_PIN;
800 else if (IsDlgButtonChecked (dlg, IDC_CHPIN_ISWORK))
801 which = CARD_USER_PIN;
802
803 n = item_get_text_length (dlg, IDC_CHPIN_OLDPIN);
804 if (check_pin_len (which, 1, n))
805 return TRUE;
806 n = item_get_text_length (dlg, IDC_CHPIN_NEWPIN);
807 if (check_pin_len (which, 0, n))
808 return TRUE;
809 n = item_get_text_length (dlg, IDC_CHPIN_NEWPIN2);
810 if (check_pin_len (which, 0, n))
811 return TRUE;
812 GetDlgItemText (dlg, IDC_CHPIN_OLDPIN, pold, sizeof (pold)-1);
813 GetDlgItemText (dlg, IDC_CHPIN_NEWPIN, pnew, sizeof (pnew)-1);
814 GetDlgItemText (dlg, IDC_CHPIN_NEWPIN2, pnew2, sizeof (pnew2)-1);
815 if (strcmp (pnew, pnew2)) {
816 msg_box (dlg, _("Passphrases do not match. Please try again."),
817 _("Card Edit"), MB_ERR);
818 return TRUE;
819 }
820
821 ce = new GpgCardEdit ();
822 if (!ce)
823 BUG (0);
824 if (which == CARD_ADMIN_PIN)
825 ce->setAdminPIN (pold);
826 else
827 ce->setPIN (pold);
828 ce->setNewPIN (pnew);
829 err = ce->changePIN (which == CARD_ADMIN_PIN? GPG_EDITCARD_CHAPIN :
830 GPG_EDITCARD_CHUPIN);
831 if (err)
832 msg_box (dlg, gpgme_strerror (err), _("Card Edit"), MB_ERR);
833 else {
834 msg_box (dlg, _("PIN successfully changed."),
835 _("Card Edit"), MB_OK);
836 SetDlgItemText (dlg, IDC_CHPIN_NEWPIN, "");
837 SetDlgItemText (dlg, IDC_CHPIN_OLDPIN, "");
838 SetDlgItemText (dlg, IDC_CHPIN_NEWPIN2, "");
839 }
840 wipememory (pold, sizeof (pold));
841 wipememory (pnew, sizeof (pnew));
842 wipememory (pnew2, sizeof (pnew2));
843 delete ce;
844 break;
845
846 case IDCANCEL:
847 SetDlgItemText (dlg, IDC_CHPIN_NEWPIN, "");
848 SetDlgItemText (dlg, IDC_CHPIN_OLDPIN, "");
849 SetDlgItemText (dlg, IDC_CHPIN_NEWPIN2, "");
850 EndDialog (dlg, FALSE);
851 break;
852 }
853 break;
854 }
855
856 return FALSE;
857 }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26