38 |
#define GPG_CONF "gpg.conf" |
#define GPG_CONF "gpg.conf" |
39 |
|
|
40 |
struct gpg_watcher_s { |
struct gpg_watcher_s { |
41 |
FILETIME last_access; |
FILETIME last_access; |
42 |
FILETIME access; |
FILETIME access; |
43 |
char * object; |
char *object; |
44 |
int modified; |
int modified; |
45 |
}; |
}; |
46 |
|
|
47 |
|
|
48 |
/* XXX need to watch for gpg.conf due to the fact keyring entries could be changed */ |
/* XXX need to watch for gpg.conf due to the fact keyring entries could be changed */ |
49 |
static const char * gpg_objs[] = {"pubring.gpg", "secring.gpg", "trustdb.gpg"}; |
static const char * gpg_objs[] = {"pubring.gpg", "secring.gpg", "trustdb.gpg"}; |
50 |
static gpg_watcher_s gpg_table[3]; |
static gpg_watcher_s gpg_table[3]; |
55 |
static int check_keyring (char ** r_path); |
static int check_keyring (char ** r_path); |
56 |
|
|
57 |
|
|
58 |
|
/* Return the application data folder of the current user. */ |
59 |
static char* |
static char* |
60 |
multi_gnupg_path (void) |
multi_gnupg_path (void) |
61 |
{ |
{ |
64 |
|
|
65 |
/* MSDN: buf must be at least MAX_PATH=256 bytes */ |
/* MSDN: buf must be at least MAX_PATH=256 bytes */ |
66 |
memset (buf, 0, sizeof (buf)); |
memset (buf, 0, sizeof (buf)); |
67 |
|
/* XXX: ec should be NOERROR (MSDN) but NOERROR is defined as '0' !? */ |
68 |
ec = SHGetSpecialFolderPath (HWND_DESKTOP, buf, CSIDL_APPDATA, TRUE); |
ec = SHGetSpecialFolderPath (HWND_DESKTOP, buf, CSIDL_APPDATA, TRUE); |
69 |
if (ec != 1) |
if (ec != 1) |
70 |
return NULL; |
return NULL; |
74 |
return m_strdup (buf); |
return m_strdup (buf); |
75 |
} |
} |
76 |
|
|
77 |
|
|
78 |
/* Return the full path of the GnuPG application. First the registry is scanned |
/* Return the full path of the GnuPG application. First the registry is scanned |
79 |
for the entry 'HomeDir'. If it wasn't set, the default dir C:\GNUPG is used. |
for the entry 'HomeDir'. If it wasn't set, the default dir C:\GNUPG is used. |
80 |
*/ |
*/ |
81 |
char* |
char* |
82 |
get_gnupg_path (void) |
get_gnupg_path (void) |
83 |
{ |
{ |
95 |
} |
} |
96 |
|
|
97 |
|
|
98 |
|
/* Return the full path of the gpg config file. |
99 |
|
A value of NULL indicates an error. */ |
100 |
char* |
char* |
101 |
get_gnupg_cfgfile (void) |
get_gnupg_cfgfile (void) |
102 |
{ |
{ |
104 |
size_t nlen = 0; |
size_t nlen = 0; |
105 |
|
|
106 |
path = get_gnupg_path (); |
path = get_gnupg_path (); |
107 |
if (path == NULL) |
if (!path) |
108 |
return NULL; |
return NULL; |
109 |
p = get_reg_entry_gpg ("OptFile"); |
p = get_reg_entry_gpg ("OptFile"); |
110 |
if (p && !strcmp (p, "")) |
if (p && !strcmp (p, "")) { |
|
{ |
|
111 |
nlen = strlen (path) + 64; |
nlen = strlen (path) + 64; |
112 |
optfile = new char[nlen + 1]; |
optfile = new char[nlen + 1]; |
113 |
if (optfile == NULL) |
if (!optfile) |
114 |
BUG (0); |
BUG (0); |
115 |
_snprintf (optfile, nlen, "%s\\"GPG_CONF, path); |
_snprintf (optfile, nlen, "%s\\"GPG_CONF, path); |
116 |
} |
} |
117 |
else if( p ) { |
else if (p) { |
118 |
nlen = strlen( p ) + 4; |
nlen = strlen( p ) + 4; |
119 |
optfile = new char[nlen + 1]; |
optfile = new char[nlen + 1]; |
120 |
if( optfile == NULL ) |
if (!optfile) |
121 |
BUG( NULL ); |
BUG (NULL); |
122 |
_snprintf( optfile, nlen, "%s", p ); |
_snprintf (optfile, nlen, "%s", p); |
123 |
} |
} |
124 |
else { |
else { |
125 |
nlen = strlen( path ) + 64; |
nlen = strlen (path) + 64; |
126 |
optfile = new char[nlen + 1]; |
optfile = new char[nlen + 1]; |
127 |
if( optfile == NULL ) |
if( !optfile) |
128 |
BUG( NULL ); |
BUG (NULL); |
129 |
_snprintf( optfile, nlen, "%s\\"GPG_CONF, path ); |
_snprintf (optfile, nlen, "%s\\"GPG_CONF, path); |
130 |
} |
} |
131 |
free_if_alloc (path); |
free_if_alloc (path); |
132 |
free_if_alloc (p); |
free_if_alloc (p); |
|
|
|
133 |
return optfile; |
return optfile; |
134 |
} /* get_gnupg_cfgfile */ |
} |
135 |
|
|
136 |
|
|
137 |
char * |
/* Return the full path of the keyring. If @pub is 1, the public |
138 |
|
keyring is return, otherwise the secret keyring. */ |
139 |
|
char* |
140 |
get_gnupg_keyring (int pub, int strict) |
get_gnupg_keyring (int pub, int strict) |
141 |
{ |
{ |
142 |
char * optfile = NULL, * path = NULL; |
char *optfile = NULL; |
143 |
char * keyring = NULL; |
char *path = NULL; |
144 |
|
char *keyring = NULL; |
145 |
|
|
146 |
path = get_gnupg_path (); |
path = get_gnupg_path (); |
147 |
if (!path) |
if (!path) |
159 |
free_if_alloc (path); |
free_if_alloc (path); |
160 |
free_if_alloc (optfile); |
free_if_alloc (optfile); |
161 |
return keyring; |
return keyring; |
162 |
} /* get_gnupg_keyring */ |
} |
163 |
|
|
164 |
|
|
165 |
/* |
/* Return the full path (with the gpg exe name). First the registry is scanned |
166 |
* Return the full path (with the gpg exe name). First the registry is scanned |
for the entry 'gpgProgram'. If it wasn't set, the default path is the |
167 |
* for the entry 'gpgProgram'. If it wasn't set, the default path is the |
appended string 'gpg.exe' is used. */ |
|
* appended string 'gpg.exe' is used. |
|
|
*/ |
|
168 |
char* |
char* |
169 |
get_gnupg_prog (void) |
get_gnupg_prog (void) |
170 |
{ |
{ |
171 |
char *p, *path, *pgm = NULL; |
char *p; |
172 |
|
char *pgm = NULL; |
173 |
size_t nlen = 0; |
size_t nlen = 0; |
|
|
|
|
path = get_gnupg_path (); |
|
|
if (path == NULL) |
|
|
return NULL; |
|
174 |
|
|
175 |
p = get_reg_entry_gpg ("gpgProgram"); |
p = get_reg_entry_gpg ("gpgProgram"); |
176 |
if (p == NULL) |
if (!p) { |
177 |
|
char *path = get_gnupg_path (); |
178 |
|
if (!path) |
179 |
|
return NULL; |
180 |
pgm = make_filename (path, "gpg", "exe"); |
pgm = make_filename (path, "gpg", "exe"); |
181 |
|
free_if_alloc (path); |
182 |
|
} |
183 |
else { |
else { |
184 |
pgm = m_strdup (p); |
pgm = m_strdup (p); |
185 |
free_if_alloc (p); |
free_if_alloc (p); |
186 |
} |
} |
|
free_if_alloc (path); |
|
187 |
return pgm; |
return pgm; |
188 |
} /* get_gnupg_prog */ |
} |
189 |
|
|
190 |
|
|
191 |
|
/* Retrieve the first usable secret key from cache. |
192 |
|
If no usable was found, @ret_no_useable is 1. |
193 |
|
Return value: the keyid of the secret key. */ |
194 |
static char * |
static char * |
195 |
default_key_from_cache (int *ret_no_useable) |
default_key_from_cache (int *ret_no_useable) |
196 |
{ |
{ |
212 |
} |
} |
213 |
if (!keyid) { |
if (!keyid) { |
214 |
*ret_no_useable = 1; |
*ret_no_useable = 1; |
215 |
msg_box( NULL, _("No useable secret key found."), _("GPG Error"), MB_ERR); |
msg_box (NULL, _("No useable secret key found."), _("GPG Error"), MB_ERR); |
216 |
} |
} |
217 |
return keyid; |
return keyid; |
218 |
} /* default_key_from_cache */ |
} |
219 |
|
|
220 |
|
|
221 |
char * |
char* |
222 |
get_gnupg_default_key (void) |
get_gnupg_default_key (void) |
223 |
{ |
{ |
224 |
gpg_optfile_t opt = NULL; |
gpg_optfile_t opt = NULL; |
228 |
|
|
229 |
optfile = get_gnupg_cfgfile (); |
optfile = get_gnupg_cfgfile (); |
230 |
if (!optfile) |
if (!optfile) |
231 |
return default_key_from_cache( &no_usable ); |
return default_key_from_cache (&no_usable); |
232 |
rc = parse_gpg_options( optfile, &opt ); |
rc = parse_gpg_options (optfile, &opt); |
233 |
if( rc ) { |
if (rc) { |
234 |
free_if_alloc( optfile ); |
free_if_alloc( optfile ); |
235 |
return default_key_from_cache( &no_usable ); |
return default_key_from_cache( &no_usable ); |
236 |
} |
} |
280 |
int i; |
int i; |
281 |
|
|
282 |
i=0; |
i=0; |
283 |
while( buf && *buf != '.' && i < 8 ) |
while (buf && *buf != '.' && i < 8) |
284 |
tmp[i++] = *buf++; |
tmp[i++] = *buf++; |
285 |
tmp[i] = 0; buf++; |
tmp[i] = 0; buf++; |
286 |
*major = atol( tmp ); |
*major = atol( tmp ); |
287 |
i=0; |
i=0; |
288 |
while( buf && *buf != '.' && i < 8 ) |
while (buf && *buf != '.' && i < 8) |
289 |
tmp[i++] = *buf++; |
tmp[i++] = *buf++; |
290 |
tmp[i] = 0; buf++; |
tmp[i] = 0; buf++; |
291 |
*minor = atol( tmp ); |
*minor = atol (tmp); |
292 |
i=0; |
i=0; |
293 |
while( buf && isdigit( *buf ) && i < 8 ) |
while (buf && isdigit( *buf ) && i < 8) |
294 |
tmp[i++] = *buf++; |
tmp[i++] = *buf++; |
295 |
tmp[i] = 0; |
tmp[i] = 0; |
296 |
*patch = atol( tmp ); |
*patch = atol (tmp); |
297 |
return 0; |
return 0; |
298 |
} |
} |
299 |
|
|
348 |
gpg_option_t e; |
gpg_option_t e; |
349 |
int rc = 0; |
int rc = 0; |
350 |
|
|
351 |
if( r_secrings ) |
*r_secrings = 0; |
352 |
*r_secrings = 0; |
*r_pubrings = 0; |
|
if( r_pubrings ) |
|
|
*r_pubrings = 0; |
|
353 |
rc = parse_gpg_options( fname, &opt ); |
rc = parse_gpg_options( fname, &opt ); |
354 |
if( rc ) |
if( rc ) |
355 |
return WPTERR_FILE_OPEN; |
return WPTERR_FILE_OPEN; |
368 |
return 0; |
return 0; |
369 |
} /* check_gnupg_cfgfile */ |
} /* check_gnupg_cfgfile */ |
370 |
|
|
371 |
|
|
372 |
/* |
/* |
373 |
* Check if both keyrings are located in the gnupg home directory. |
* Check if both keyrings are located in the gnupg home directory. |
374 |
*/ |
*/ |
416 |
|
|
417 |
|
|
418 |
static int |
static int |
419 |
create_gpg_options( void ) |
create_gpg_options (void) |
420 |
{ |
{ |
421 |
FILE *fp; |
FILE *fp; |
422 |
char *s, *optfile; |
char *s, *optfile; |
582 |
} /* check_gnupg_options */ |
} /* check_gnupg_options */ |
583 |
|
|
584 |
|
|
585 |
|
/* Store the last access of the file inside the watcher @ctx. */ |
586 |
static int |
static int |
587 |
get_last_gnupg_access (gpg_watcher_s * ctx) |
get_last_gnupg_access (gpg_watcher_s *ctx) |
588 |
{ |
{ |
589 |
HANDLE fd; |
HANDLE fd; |
590 |
char *path = NULL, *file = NULL; |
char *path; |
591 |
|
char *file; |
592 |
|
|
593 |
path = get_gnupg_path (); |
path = get_gnupg_path (); |
594 |
file = make_filename (path, ctx->object, NULL); |
file = make_filename (path, ctx->object, NULL); |
595 |
fd = CreateFile (file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL); |
fd = CreateFile (file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL); |
596 |
if( fd == INVALID_HANDLE_VALUE ) { |
if (fd == INVALID_HANDLE_VALUE) { |
597 |
free_if_alloc (path); |
free_if_alloc (path); |
598 |
free_if_alloc (file); |
free_if_alloc (file); |
599 |
return WPTERR_FILE_OPEN; |
return WPTERR_FILE_OPEN; |
600 |
} |
} |
601 |
GetFileTime (fd, NULL, NULL, &ctx->access); |
GetFileTime (fd, NULL, NULL, &ctx->access); |
602 |
CloseHandle (fd); |
CloseHandle (fd); |
603 |
free_if_alloc (path); |
free_if_alloc (path); |
604 |
free_if_alloc (file); |
free_if_alloc (file); |
605 |
return 0; |
return 0; |
606 |
} /* get_last_gnupg_access */ |
} |
607 |
|
|
608 |
|
|
609 |
|
/* Check if the file inside watcher @ctx was modified. */ |
610 |
static void |
static void |
611 |
check_last_gnupg_access( gpg_watcher_s *ctx ) |
check_last_gnupg_access (gpg_watcher_s *ctx) |
612 |
{ |
{ |
613 |
ctx->modified = 0; |
ctx->modified = 0; |
614 |
|
|
615 |
if( ctx->last_access.dwHighDateTime != ctx->access.dwHighDateTime && |
if (ctx->last_access.dwHighDateTime != ctx->access.dwHighDateTime && |
616 |
ctx->last_access.dwLowDateTime != ctx->access.dwLowDateTime ) |
ctx->last_access.dwLowDateTime != ctx->access.dwLowDateTime) |
617 |
ctx->modified = 1; |
ctx->modified = 1; |
618 |
|
|
619 |
ctx->last_access.dwLowDateTime = ctx->access.dwLowDateTime; |
ctx->last_access.dwLowDateTime = ctx->access.dwLowDateTime; |
620 |
ctx->last_access.dwHighDateTime = ctx->access.dwHighDateTime; |
ctx->last_access.dwHighDateTime = ctx->access.dwHighDateTime; |
621 |
} /* check_last_gnupg_access */ |
} |
622 |
|
|
623 |
|
|
624 |
|
/* Init GPG watcher table for all monitored files. */ |
625 |
void |
void |
626 |
init_gnupg_table (void) |
init_gnupg_table (void) |
627 |
{ |
{ |
628 |
|
char *p; |
629 |
int j; |
int j; |
630 |
|
|
631 |
for (j = 0; j < gpg_table_count; j++) { |
for (j = 0; j < gpg_table_count; j++) { |
632 |
gpg_table[j].object = m_strdup (gpg_objs[j]); |
p = gpg_table[j].object = m_strdup (gpg_objs[j]); |
633 |
|
if (!p) |
634 |
|
BUG (NULL); |
635 |
memset (&gpg_table[j].access, 0, sizeof (FILETIME)); |
memset (&gpg_table[j].access, 0, sizeof (FILETIME)); |
636 |
memset (&gpg_table[j].last_access, 0, sizeof (FILETIME)); |
memset (&gpg_table[j].last_access, 0, sizeof (FILETIME)); |
637 |
gpg_table[j].modified = 0; |
gpg_table[j].modified = 0; |
638 |
} |
} |
639 |
} /* init_gnupg_table */ |
} |
640 |
|
|
641 |
|
|
642 |
void |
void |
646 |
|
|
647 |
for (j=0; j < gpg_table_count; j++) |
for (j=0; j < gpg_table_count; j++) |
648 |
free_if_alloc (gpg_table[j].object); |
free_if_alloc (gpg_table[j].object); |
649 |
} /* free_gnupg_table */ |
} |
650 |
|
|
651 |
|
|
652 |
|
/* Return the amount of files modified since the last call. */ |
653 |
int |
int |
654 |
keyring_check_last_access (void) |
keyring_check_last_access (void) |
655 |
{ |
{ |
657 |
|
|
658 |
rc = 0; |
rc = 0; |
659 |
for (j = 0; j < gpg_table_count; j++) { |
for (j = 0; j < gpg_table_count; j++) { |
660 |
get_last_gnupg_access( &gpg_table[j] ); |
get_last_gnupg_access (&gpg_table[j]); |
661 |
check_last_gnupg_access( &gpg_table[j] ); |
check_last_gnupg_access (&gpg_table[j]); |
662 |
if ( gpg_table[j].modified ) |
if (gpg_table[j].modified) |
663 |
rc++; |
rc++; |
664 |
} |
} |
665 |
|
|
666 |
return rc; |
return rc; |
667 |
} /* keyring_check_last_access */ |
} |
668 |
|
|
669 |
|
|
670 |
const char* |
const char* |
672 |
{ |
{ |
673 |
char file_ext[5]; |
char file_ext[5]; |
674 |
|
|
675 |
if (r_type) *r_type = PGP_NONE; |
if (r_type) |
676 |
|
*r_type = PGP_NONE; |
677 |
if (!strchr (fname, '.' )) |
if (!strchr (fname, '.' )) |
678 |
return "UNKNOWN"; |
return "UNKNOWN"; |
679 |
|
|
695 |
} |
} |
696 |
|
|
697 |
|
|
698 |
char * |
char* |
699 |
get_gnupg_keyring_from_options (const char * fname, int pub) |
get_gnupg_keyring_from_options (const char * fname, int pub) |
700 |
{ |
{ |
701 |
gpg_optfile_t opt; |
gpg_optfile_t opt; |
715 |
release_gpg_options (opt); |
release_gpg_options (opt); |
716 |
|
|
717 |
return kring; |
return kring; |
718 |
} /* get_gnupg_keyring_from_options */ |
} |
719 |
|
|
720 |
|
|
721 |
|
|
724 |
my_access (const char * fname) |
my_access (const char * fname) |
725 |
{ |
{ |
726 |
HANDLE hd; |
HANDLE hd; |
727 |
hd = CreateFile (fname, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); |
hd = CreateFile (fname, GENERIC_WRITE, FILE_SHARE_WRITE, |
728 |
|
NULL, OPEN_EXISTING, 0, NULL); |
729 |
if (hd == INVALID_HANDLE_VALUE) |
if (hd == INVALID_HANDLE_VALUE) |
730 |
return -1; |
return -1; |
731 |
CloseHandle (hd); |
CloseHandle (hd); |
732 |
return 0; |
return 0; |
733 |
} /* my_access */ |
} |
734 |
|
|
735 |
|
|
736 |
int |
int |
783 |
} /* gpg_check_permissions */ |
} /* gpg_check_permissions */ |
784 |
|
|
785 |
|
|
786 |
|
/* Check the GPG home dir. If all methods failed, try to |
787 |
|
create the default folder. */ |
788 |
static int |
static int |
789 |
check_homedir (void) |
check_homedir (void) |
790 |
{ |
{ |
791 |
char * homedir = NULL; |
char *homedir = NULL; |
792 |
int yes = 0; |
int yes = 0; |
793 |
|
|
794 |
homedir = get_reg_entry_gpg ("HomeDir"); |
homedir = get_reg_entry_gpg ("HomeDir"); |
802 |
_("%s does not exit.\n" |
_("%s does not exit.\n" |
803 |
"Do you want to create this directory?"), homedir); |
"Do you want to create this directory?"), homedir); |
804 |
if (yes == IDYES) { |
if (yes == IDYES) { |
805 |
if (CreateDirectory (homedir, NULL) == FALSE) { |
BOOL ec = CreateDirectory (homedir, NULL); |
806 |
free_if_alloc (homedir); |
free_if_alloc (homedir); |
807 |
|
if (ec == FALSE) |
808 |
return WPTERR_DIR_CREAT; |
return WPTERR_DIR_CREAT; |
809 |
} |
return 0; |
810 |
} |
} |
811 |
return WPTERR_DIR_OPEN; |
return WPTERR_DIR_OPEN; |
812 |
} |
} |
813 |
free_if_alloc (homedir); |
free_if_alloc (homedir); |
814 |
} |
} |
815 |
return 0; |
return 0; |
816 |
} /* check_homedir */ |
} |
817 |
|
|
818 |
|
|
819 |
int |
int |
820 |
gnupg_check_homedir (void) |
gnupg_check_homedir (void) |
821 |
{ |
{ |
822 |
char *homedir = NULL, *prog = NULL; |
char *homedir = NULL; |
823 |
|
char *prog = NULL; |
824 |
int rc = 0, ec = 0; |
int rc = 0, ec = 0; |
825 |
|
|
826 |
rc = check_homedir (); |
rc = check_homedir (); |
942 |
|
|
943 |
|
|
944 |
static int |
static int |
945 |
backup_one_file (const char * srcpath, const char * srcn, |
backup_one_file (const char *srcpath, const char *srcn, |
946 |
const char * dstpath, const char * dstn) |
const char *dstpath, const char *dstn) |
947 |
{ |
{ |
948 |
char * src, * dst; |
char * src, * dst; |
949 |
BOOL rc; |
BOOL rc; |
1043 |
tmpfile = make_filename (reg_prefs.backup.path, "test", "tmp"); |
tmpfile = make_filename (reg_prefs.backup.path, "test", "tmp"); |
1044 |
fp = fopen (tmpfile, "wb"); |
fp = fopen (tmpfile, "wb"); |
1045 |
if (!fp) |
if (!fp) |
1046 |
rc = log_box (_("Backup"), MB_WARN|MB_RETRYCANCEL, _("The backup drive '%s' does not seems to accessable.\n" |
rc = log_box (_("Backup"), MB_WARN|MB_RETRYCANCEL, |
1047 |
"Please insert/check the drive to continue."), dstpath); |
_("The backup drive '%s' does not seems to accessable.\n" |
1048 |
|
"Please insert/check the drive to continue."), dstpath); |
1049 |
else { |
else { |
1050 |
rc = 0; |
rc = 0; |
1051 |
fclose (fp); |
fclose (fp); |
1069 |
} /* gnupg_backup_keyrings */ |
} /* gnupg_backup_keyrings */ |
1070 |
|
|
1071 |
|
|
1072 |
|
/* Display GPG error from file if possible. */ |
1073 |
void |
void |
1074 |
gnupg_display_error (void) |
gnupg_display_error (void) |
1075 |
{ |
{ |
1095 |
fclose (fp); |
fclose (fp); |
1096 |
msg_box (NULL, errstr, _("GPG Error"), MB_INFO); |
msg_box (NULL, errstr, _("GPG Error"), MB_INFO); |
1097 |
free_if_alloc (errstr); |
free_if_alloc (errstr); |
1098 |
} /* gnupg_display_error */ |
} |
1099 |
|
|
1100 |
|
|
1101 |
|
|
1102 |
|
/* check that the requested GPG keyring exist and. |
1103 |
|
Return value: 0 for success. */ |
1104 |
int |
int |
1105 |
gnupg_access_keyring (int _pub) |
gnupg_access_keyring (int _pub) |
1106 |
{ |
{ |
1107 |
int rc = 0; |
int rc = 0; |
1108 |
char * name = get_gnupg_keyring (_pub, 1); |
char *name = get_gnupg_keyring (_pub, 1); |
1109 |
if (file_exist_check (name)) |
if (!name || file_exist_check (name)) |
1110 |
rc = -1; |
rc = -1; |
1111 |
free_if_alloc (name); |
free_if_alloc (name); |
1112 |
return rc; |
return rc; |
1113 |
} |
} |
|
|
|