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

Contents of /trunk/Src/wptCryptdisk.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 77 - (show annotations)
Mon Nov 14 15:01:01 2005 UTC (19 years, 3 months ago) by twoaday
File size: 15822 byte(s)
2005-11-12  Timo Schulz  <ts@g10code.com>
 
        Fix more GCC warnings.
 
2005-11-10  Timo Schulz  <ts@g10code.com>
 
        * wptClipSignDlg.cpp (one_key_proc): Use
        release_gpg_passphrase_cb() to free the context.
        * wptListView.cpp (listview_deselect_all): New.
        * wptMAPI.cpp (mapi_send_pubkey): Works again.
        * wptFileManagerDlg.cpp (file_manager_dlg_proc): Support encrypt &
        zip.
        * wptPassphraseCB.cpp (passphrase_callback_proc): Fix passphrase
        caching for signing operations.
        * wptKeyManager.cpp (km_send_to_mail_recipient): Works again.
        * wptFileManager.cpp (fm_send_file): Likewise.
        (fm_encrypt_into_zip): New.
         

1 /* wptCryptdisk.cpp
2 * Copyright (C) 2004 Timo Schulz
3 *
4 * This file is part of WinPT.
5 *
6 * WinPT is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (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
14 * GNU 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 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include <windows.h>
25 #include <winioctl.h>
26 #include <stdio.h>
27 #include <ctype.h>
28
29 #include "resource.h"
30 #include "wptCryptdisk.h"
31 #include "wptTypes.h"
32 #include "wptW32API.h"
33 #include "wptNLS.h"
34 #include "wptErrors.h"
35
36 /*DWORD SHFormatDrive(HWND hwnd, UINT drive, UINT fmtID, UINT options);*/
37 typedef DWORD (WINAPI *sh_format_drive_p) (HWND, UINT, UINT, UINT);
38
39 static mount_list_t mounted=NULL;
40 static HMODULE shell32=NULL;
41 static sh_format_drive_p shfmt=NULL;
42
43
44 static int
45 is_nt4 (void)
46 {
47 static int nt_flag = -1;
48 OSVERSIONINFO osinf;
49
50 if (nt_flag != -1)
51 return nt_flag;
52
53 memset (&osinf, 0, sizeof osinf);
54 osinf.dwOSVersionInfoSize = sizeof osinf;
55 GetVersionEx (&osinf);
56 if (osinf.dwPlatformId == VER_PLATFORM_WIN32_NT) {
57 nt_flag = 1;
58 shell32 = LoadLibrary ("SHELL32.DLL");
59 shfmt = (sh_format_drive_p)GetProcAddress (shell32, "SHFormatDrive");
60 if (!shfmt)
61 BUG (0);
62 }
63 else
64 nt_flag = 0;
65 return nt_flag;
66 }
67
68 static int
69 check_filedisk (void)
70 {
71 HKEY hk;
72 int rc = -1;
73
74 rc = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
75 "SYSTEM\\CurrentControlSet\\Services\\FileDisk",
76 0, KEY_READ, &hk);
77 if (rc == ERROR_SUCCESS) {
78 RegCloseKey (hk);
79 rc = 0;
80 }
81 return rc;
82 }
83
84
85 int
86 cryptdisk_available (void)
87 {
88 return (is_nt4 () == 1 && check_filedisk () == 0)? 1 : 0;
89 }
90
91
92 void
93 cryptdisk_cleanup (void)
94 {
95 if (shell32)
96 FreeLibrary (shell32);
97 shell32 = NULL;
98 }
99
100
101 static int
102 num_of_devices (void)
103 {
104 HKEY hk;
105 BYTE buf[32];
106 DWORD n=0, type=0;
107 int rc;
108
109 rc = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
110 "SYSTEM\\CurrentControlSet\\Services\\FileDisk\\Parameters",
111 0, KEY_READ, &hk);
112 if (rc != ERROR_SUCCESS)
113 return -1;
114
115 n = sizeof buf-1;
116 memset (buf, 0, sizeof buf);
117 rc = RegQueryValueEx (hk, "NumberOfDevices", 0, &type, buf, &n);
118 if (rc != ERROR_SUCCESS || type != REG_DWORD)
119 n=0;
120 else
121 n = *buf;
122 RegCloseKey (hk);
123 return n;
124 }
125
126
127 static HWND
128 start_cryptdisk_server (HANDLE * r_proc)
129 {
130 STARTUPINFO si;
131 PROCESS_INFORMATION pi;
132
133 memset (&si, 0, sizeof si);
134 memset (&pi, 0, sizeof pi);
135 si.cb = sizeof si;
136
137 if (CreateProcess (NULL, "CryptdiskSrv", NULL, NULL, FALSE, 0,
138 NULL, NULL, &si, &pi) == FALSE) {
139 msg_box (NULL, _("Could not execute Cryptdisk Server."),
140 _("Cryptdisk Error"), MB_ERR);
141 return NULL;
142 }
143 *r_proc = pi.hProcess;
144 Sleep (300);
145 return FindWindow ("CryptdiskSrv", NULL);
146 }
147
148
149 static int
150 cryptdisk_mount (int devnum,
151 const char * imgfile,
152 u32 size,
153 const char * hdlet)
154 {
155 HWND h;
156 HANDLE proc, wait_ev;
157 COPYDATASTRUCT cds;
158 struct private_ofi_s ofi;
159
160 h = start_cryptdisk_server (&proc);
161 if (!h)
162 return WPTERR_GENERAL;
163 memset (&ofi, 0, sizeof ofi);
164 ofi.cmd = CMD_MOUNT;
165 ofi.devnum = devnum;
166 ofi.filesize.LowPart = size;
167 ofi.drvlet = *hdlet;
168 ofi.readonly = 0;
169 strcpy ((char *)ofi.fname, imgfile);
170 ofi.flen = strlen (imgfile);
171
172 wait_ev = OpenEvent (SYNCHRONIZE, FALSE, "cryptdisksrv.wait");
173 if (!wait_ev)
174 BUG (0);
175 memset (&cds, 0, sizeof cds);
176 cds.cbData = sizeof ofi;
177 cds.lpData = &ofi;
178 SendMessage (h, WM_COPYDATA, (WPARAM)GetDesktopWindow (), (LPARAM)&cds);
179 WaitForSingleObject (wait_ev, INFINITE);
180 CloseHandle (wait_ev);
181 CloseHandle (proc);
182 return 0;
183 }
184
185
186
187 int
188 cryptdisk_unmount (char drivelet, int forced)
189 {
190 HWND h;
191 HANDLE proc;
192 COPYDATASTRUCT cds;
193 struct private_ofi_s ofi;
194
195 h = start_cryptdisk_server (&proc);
196 if (!h)
197 return WPTERR_GENERAL;
198
199 memset (&ofi, 0, sizeof ofi);
200 ofi.cmd = CMD_UMOUNT;
201 ofi.drvlet = drivelet;
202 ofi.forced = forced;
203
204 memset (&cds, 0, sizeof cds);
205 cds.lpData = &ofi;
206 cds.cbData = sizeof ofi;
207 SendMessage (h, WM_COPYDATA, (WPARAM)GetDesktopWindow (), (LPARAM)&cds);
208 CloseHandle (proc);
209
210 return 0;
211 }
212
213 static void
214 print_lasterr (char * prefix)
215 {
216 LPVOID msg;
217
218 FormatMessage(
219 FORMAT_MESSAGE_ALLOCATE_BUFFER |
220 FORMAT_MESSAGE_FROM_SYSTEM |
221 FORMAT_MESSAGE_IGNORE_INSERTS,
222 NULL,
223 GetLastError(),
224 0,
225 (LPTSTR) &msg,
226 0,
227 NULL
228 );
229 MessageBox (NULL, (LPTSTR)msg, prefix, MB_ICONERROR|MB_OK);
230 LocalFree (msg);
231 }
232
233
234 static int
235 filedisk_status (char drivelet, LARGE_INTEGER * size, int * rdonly)
236 {
237 char VolumeName[] = "\\\\.\\ :";
238 HANDLE Device;
239 POPEN_FILE_INFORMATION ofi;
240 DWORD BytesReturned;
241 int n= sizeof (OPEN_FILE_INFORMATION)+ MAX_PATH;
242
243 VolumeName[4] = drivelet;
244
245 Device = CreateFile (VolumeName,
246 GENERIC_READ,
247 FILE_SHARE_READ | FILE_SHARE_WRITE,
248 NULL,
249 OPEN_EXISTING,
250 FILE_FLAG_NO_BUFFERING,
251 NULL);
252
253 if (Device == INVALID_HANDLE_VALUE) {
254 print_lasterr(&VolumeName[4]);
255 return WPTERR_CDISK_OPEN;
256 }
257
258 ofi = (POPEN_FILE_INFORMATION)malloc (n);
259
260 if (!DeviceIoControl (Device,
261 IOCTL_FILE_DISK_QUERY_FILE,
262 NULL,
263 0,
264 ofi,
265 sizeof(OPEN_FILE_INFORMATION) + MAX_PATH,
266 &BytesReturned, NULL)) {
267 print_lasterr (&VolumeName[4]);
268 return WPTERR_CDISK_QUERY;
269 }
270
271 if (BytesReturned < sizeof(OPEN_FILE_INFORMATION)) {
272 SetLastError (ERROR_INSUFFICIENT_BUFFER);
273 print_lasterr (&VolumeName[4]);
274 return WPTERR_CDISK_QUERY;
275 }
276
277 if (size)
278 *size = ofi->FileSize;
279 if (rdonly)
280 *rdonly = ofi->ReadOnly;
281
282 return 0;
283 }
284
285
286 static mount_list_t
287 new_mount_list (const char * drive, int devnum)
288 {
289 mount_list_t n;
290
291 n = (mount_list_t)calloc (1, sizeof *n);
292 if (n) {
293 strcpy (n->drive, drive);
294 n->devnum = devnum;
295 n->ttl = 1;
296 filedisk_status (*drive, &n->size, &n->rdonly);
297 }
298 return n;
299 }
300
301
302 static mount_list_t
303 find_mount_list (mount_list_t root, const char * drive)
304 {
305 mount_list_t n;
306
307 for (n=root; n; n=n->next) {
308 if (n->ttl == 0)
309 continue;
310 if (!strncmp (n->drive, drive, strlen (drive)))
311 return n;
312 }
313 return NULL;
314 }
315
316
317 static void
318 add_mount_list (mount_list_t root, mount_list_t node)
319 {
320 mount_list_t n;
321
322 if (find_mount_list (root, node->drive))
323 return;
324
325 for (n=root; n->next; n=n->next)
326 ;
327 n->next = node;
328 }
329
330
331 static void
332 remove_mount_list (mount_list_t root, mount_list_t node)
333 {
334 mount_list_t n;
335
336 n = find_mount_list (root, node->drive);
337 if (n)
338 n->ttl = 0;
339 }
340
341
342 static void
343 free_mount_list (mount_list_t root)
344 {
345 mount_list_t n;
346
347 while (root) {
348 n = root->next;
349 free (root);
350 root = n;
351 }
352 }
353
354
355 static int
356 last_devnum (mount_list_t root)
357 {
358 mount_list_t n;
359 int devnum=0;
360
361 if (!root)
362 return 0;
363
364 for (n=root; n; n=n->next) {
365 if (devnum < n->devnum)
366 devnum=n->devnum;
367 }
368 return devnum+1;
369 }
370
371
372 static char
373 init_drives (HWND dlg, int ctlid)
374 {
375 char buf[512], drv[5];
376 DWORD n=0, i=0;
377
378 n=GetLogicalDriveStrings (sizeof buf-1, buf);
379 for (i=0; i < n; i++) {
380 memcpy (drv, buf+i, 3); drv[3]=0;
381 i += 3;
382 }
383 if (!dlg && ctlid == -1)
384 return ++drv[0];
385
386 for (++drv[0]; drv[0] < 'Z'; drv[0]++)
387 SendDlgItemMessage (dlg, ctlid, CB_ADDSTRING, 0,
388 (LPARAM)(const char *)drv);
389 SendDlgItemMessage (dlg, ctlid, CB_SETCURSEL, 0, 0);
390 return 0;
391 }
392
393
394 static int
395 check_freespace (const char * imgfile, u32 size)
396 {
397 ULARGE_INTEGER tocaller, total, totfree;
398 char buf[128] = {0};
399
400 if (!strchr (imgfile, ':'))
401 GetCurrentDirectory (sizeof buf-1, buf);
402 else
403 strncpy (buf, imgfile, sizeof buf-1);
404 buf[3] = '\0';
405 GetDiskFreeSpaceEx (buf, &tocaller, &total, &totfree);
406 if (size > tocaller.LowPart)
407 return -1;
408 return 0;
409 }
410
411
412 static void
413 do_check (HWND dlg)
414 {
415 if (!cryptdisk_serv_run ()) { /* xxx */
416 msg_box (dlg, _("The Cryptdisk service seems to be available but "
417 "it is not started yet.\nPlease start the service "
418 "and try again."), _("Cryptdisk Error"), MB_ERR);
419 EndDialog (dlg, TRUE);
420 }
421 }
422
423
424 BOOL CALLBACK
425 cryptdisk_new_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
426 {
427 const char * ciphers [] = {
428 "twofish",
429 NULL
430 };
431 const char * s;
432 char imgfile[128], key[128], drv[3];
433 int i;
434 u32 size=0;
435
436 switch (msg) {
437 case WM_INITDIALOG:
438 do_check (dlg);
439 SetDlgItemInt (dlg, IDC_CDNEW_SIZE, DISK_DEFSIZE, FALSE);
440 for (i=0; (s=ciphers[i]); i++)
441 SendDlgItemMessage (dlg, IDC_CDNEW_CIPHERS, CB_ADDSTRING,
442 0, (LPARAM)(const char *) s);
443 SendDlgItemMessage (dlg, IDC_CDNEW_CIPHERS, CB_SETCURSEL, 0, 0);
444 center_window (dlg, NULL);
445 SetForegroundWindow (dlg);
446 break;
447
448 case WM_COMMAND:
449 switch (LOWORD (wparam)) {
450 case IDOK:
451 i = GetDlgItemText (dlg, IDC_CDNEW_IMGFILE, imgfile, sizeof imgfile-1);
452 if (!i) {
453 msg_box (dlg, _("Please enter a name for the image file."),
454 _("Cryptdisk"), MB_ERR);
455 return FALSE;
456 }
457 if (file_exist_check (imgfile) == 0) {
458 i = msg_box (dlg, _("This volume file already exists.\n"
459 "Do you want to overwrite it?"),
460 _("Cryptdisk Warning"), MB_YESNO|MB_WARN);
461 if (i == IDNO)
462 return FALSE;
463 }
464 for (i=0; i < (int)strlen (imgfile); i++)
465 imgfile[i] = toupper (imgfile[i]);
466 size = GetDlgItemInt (dlg, IDC_CDNEW_SIZE, NULL, FALSE);
467 if (!size) {
468 msg_box (dlg, _("Please enter the size for the volume"),
469 _("Cryptdisk"), MB_INFO);
470 return FALSE;
471 }
472 size *= 1024; /*KB*/
473 if (check_freespace (imgfile, (size*1024))) {
474 msg_box (dlg, _("There is not enough free disk space to "
475 "store the volume."), _("Cryptdisk"), MB_ERR);
476 return FALSE;
477 }
478 i = GetDlgItemText (dlg, IDC_CDNEW_PASS, key, sizeof key-1);
479 if (!i) {
480 msg_box (dlg, _("Please enter a passphrase for the volume."),
481 _("Cryptdisk"), MB_ERR);
482 return FALSE;
483 }
484 strcpy (drv, "?:\\");
485 drv[0] = init_drives (NULL, -1);
486 i = cryptdisk_mount (last_devnum (mounted), imgfile, size, drv);
487 if (!i)
488 shfmt (dlg, drv[0] - 65, 0, 0);
489 break;
490 case IDCANCEL:
491 EndDialog (dlg, FALSE);
492 break;
493 }
494 break;
495
496 }
497
498 return FALSE;
499 }
500
501
502 BOOL CALLBACK
503 cryptdisk_mount_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
504 {
505 const char * s_imgfile;
506 char buf[8], drive[8], passwd[64], imgfile[128];
507 int n, i, devnum=0;
508 int rc;
509
510 switch (msg) {
511 case WM_INITDIALOG:
512 do_check (dlg);
513 s_imgfile = (const char *)lparam;
514 if (s_imgfile)
515 SetDlgItemText (dlg, IDC_CDMOUNT_IMGFILE, s_imgfile);
516 init_drives (dlg, IDC_CDMOUNT_DRV);
517 n = num_of_devices ();
518 if (n == -1) {
519 msg_box (dlg, _("Cannot determine the number of drives."),
520 _("Cryptdisk Error"), MB_ERR);
521 EndDialog (dlg, FALSE);
522 }
523 for (i=last_devnum (mounted); i < n; i++) {
524 sprintf (buf, "%d", i);
525 SendDlgItemMessage (dlg, IDC_CDMOUNT_ID, CB_ADDSTRING, 0,
526 (LPARAM)(const char *)buf);
527 }
528 SendDlgItemMessage (dlg, IDC_CDMOUNT_ID, CB_SETCURSEL, 0, 0);
529 center_window (dlg, NULL);
530 SetForegroundWindow (dlg);
531 break;
532
533 case WM_COMMAND:
534 switch (LOWORD (wparam)) {
535 case IDC_CDMOUNT_SELFILE:
536 s_imgfile = get_fileopen_dlg (dlg, _("Select Crypdisk Volume"),
537 NULL, NULL);
538 if (s_imgfile != NULL)
539 SetDlgItemText (dlg, IDC_CDMOUNT_IMGFILE, s_imgfile);
540 break;
541
542 case IDOK:
543 n = item_get_text_length (dlg, IDC_CDMOUNT_IMGFILE);
544 if (!n) {
545 msg_box (dlg, _("Please enter the name of the image file."),
546 _("Cryptdisk Error"), MB_ERR);
547 return FALSE;
548 }
549 n = item_get_text_length (dlg, IDC_CDMOUNT_PASS);
550 if (!n) {
551 msg_box (dlg, _("Please enter a password."),
552 _("Cryptdisk Error"), MB_ERR);
553 return FALSE;
554 }
555 devnum = GetDlgItemInt (dlg, IDC_CDMOUNT_ID, NULL, FALSE);
556 GetDlgItemText (dlg, IDC_CDMOUNT_DRV, drive, sizeof drive-1);
557 GetDlgItemText (dlg, IDC_CDMOUNT_PASS, passwd, sizeof passwd-1);
558 GetDlgItemText (dlg, IDC_CDMOUNT_IMGFILE, imgfile, sizeof imgfile-1);
559 if (file_exist_check (imgfile)) {
560 msg_box (dlg, _("Image file does not exist or could not be accessed."),
561 _("Cryptdisk Error"), MB_ERR);
562 return FALSE;
563 }
564 rc = cryptdisk_mount (devnum, imgfile, 0, drive);
565 if (!rc) {
566 mount_list_t t = new_mount_list (drive, devnum);
567 if (!mounted)
568 mounted = t;
569 else
570 add_mount_list (mounted, t);
571 EndDialog (dlg, TRUE);
572 }
573 else
574 msg_box (dlg, winpt_strerror (rc), _("Cryptdisk Error"), MB_ERR);
575 break;
576
577 case IDCANCEL:
578 EndDialog (dlg, FALSE);
579 break;
580 }
581 break;
582 }
583 return FALSE;
584 }
585
586
587 static void
588 load_devs_from_mountlist (HWND dlg, int ctlid)
589 {
590 mount_list_t n;
591 char buf[128];
592
593 if (!mounted)
594 return;
595
596 for (n=mounted; n; n=n->next) {
597 if (n->ttl == 0)
598 continue;
599 _snprintf (buf, sizeof buf-1, _("Drive %s (ID %d); Size %d MB, Readonly=%s"),
600 n->drive, n->devnum, n->size.LowPart/1024/1024,
601 n->rdonly? "true" : "false");
602 SendDlgItemMessage (dlg, ctlid, LB_ADDSTRING, 0, (LPARAM)(const char *)buf);
603 }
604
605 }
606
607
608 static void
609 do_reaping (void)
610 {
611 mount_list_t n;
612 int ndevs=0, numount=0;
613
614 for (n=mounted; n; n=n->next) {
615 if (n->ttl == 0)
616 numount++;
617 ndevs++;
618 }
619 if (ndevs == numount) {
620 free_mount_list (mounted);
621 mounted = NULL;
622 }
623 }
624
625
626 BOOL CALLBACK
627 cryptdisk_umount_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
628 {
629 mount_list_t vol;
630 char buf[128];
631 int n, rc=0;
632
633 switch (msg) {
634 case WM_INITDIALOG:
635 do_check (dlg);
636 load_devs_from_mountlist (dlg, IDC_CDUMOUNT_LIST);
637 center_window (dlg, NULL);
638 SetForegroundWindow (dlg);
639 break;
640
641 case WM_DESTROY:
642 do_reaping ();
643 break;
644
645 case WM_COMMAND:
646 switch (LOWORD (wparam)) {
647 case IDOK:
648 n = SendDlgItemMessage (dlg, IDC_CDUMOUNT_LIST, LB_GETCURSEL, 0, 0);
649 if (n == LB_ERR) {
650 msg_box (dlg, _("Please select one drive to umount."), _("Cryptdisk"), MB_INFO);
651 return FALSE;
652 }
653 SendDlgItemMessage (dlg, IDC_CDUMOUNT_LIST, LB_GETTEXT, n,
654 (LPARAM)(char *)buf);
655 strcpy (buf, buf+6);
656 buf[2] = '\0';
657 vol = find_mount_list (mounted, buf);
658 if (!vol)
659 BUG (0);
660 rc = cryptdisk_unmount (buf[0], 0);
661 //if (rc == WPTERR_CDISK_LOCK)
662 // rc = cryptdisk_unmount (buf[0], 0);
663 if (!rc) {
664 SendDlgItemMessage (dlg, IDC_CDUMOUNT_LIST, LB_DELETESTRING, (WPARAM)n, 0);
665 remove_mount_list (mounted, vol);
666 }
667 else
668 msg_box (dlg, winpt_strerror (rc), _("Cryptdisk Error"), MB_ERR);
669 break;
670 case IDCANCEL:
671 EndDialog (dlg, FALSE);
672 break;
673 }
674 break;
675 }
676
677 return FALSE;
678 }
679
680
681 int
682 cryptdisk_serv_run (void)
683 {
684 SC_HANDLE hd;
685 ENUM_SERVICE_STATUS ess[4096];
686 DWORD nservs=0, dummy=0;
687 DWORD i;
688 int rc=0;
689
690 hd = OpenSCManager (NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
691 if (!hd)
692 return 0;
693
694 EnumServicesStatus (hd, SERVICE_DRIVER, SERVICE_ACTIVE,
695 (LPENUM_SERVICE_STATUS)&ess,
696 sizeof ess-1, &dummy, &nservs, &dummy);
697
698 for (i=0; i < nservs; i++) {
699 if (!strnicmp ("FileDisk", ess[i].lpDisplayName, 8)) {
700 rc = 1;
701 break;
702 }
703 }
704
705 CloseServiceHandle (hd);
706 return rc;
707 }
708

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26