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

Annotation of /trunk/Src/wptGPGUtil.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 219 - (hide annotations)
Sat May 27 08:56:00 2006 UTC (18 years, 9 months ago) by twoaday
File size: 20921 byte(s)
2006-05-25  Timo Schulz  <ts@g10code.de>
                                                                                
        * wptGPGUtil.cpp (gpg_rebuild_cache): Return error code.
        * wptGPGME.cpp (winpt_get_seckey): Fix off-by-one bug.
        * wptVerifyList.cpp (verlist_build): New argument type.
        Change all callers.
        (verlist_set_info_control): New.
        (verlist_set_additional_info): New.
        * wptFileVerifyDlg.cpp (file_verify_dlg_proc): Adjust code.
        * wptClipVerifyDlg.cpp (clip_verify_dlg_proc): Likewise.
        * wptFileCBS.cpp (read_cb, write_cb): Add logging.
                                                                                


1 twoaday 121 /* wptGPGUtil.cpp - GPG util functions
2 twoaday 133 * Copyright (C) 2005, 2006 Timo Schulz
3 werner 36 * 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 twoaday 121
22 werner 36 #ifdef HAVE_CONFIG_H
23     #include <config.h>
24     #endif
25    
26     #include <windows.h>
27     #include <sys/stat.h>
28 twoaday 179 #include <string.h>
29     #include <errno.h>
30 werner 36
31 twoaday 121 #include "gpgme.h"
32     #include "wptTypes.h"
33 twoaday 73 #include "wptErrors.h"
34 twoaday 175 #include "wptW32API.h"
35 twoaday 179 #include "wptGPG.h"
36     #include "openpgp.h"
37 werner 36
38 twoaday 175
39 twoaday 193 /* safe wrapper around calloc. */
40     static void*
41     xcalloc (size_t n, size_t m)
42     {
43     void *p = calloc (n, m);
44     if (!p)
45     BUG (0);
46     return p;
47     }
48    
49    
50 werner 36 #define NROFHEXDIGITS 2
51     /* Convert two hexadecimal digits from STR to the value they
52     represent. Returns -1 if one of the characters is not a
53     hexadecimal digit. */
54     static int
55     hextobyte (const unsigned char *str)
56     {
57     int val = 0;
58     int i;
59    
60     for (i = 0; i < NROFHEXDIGITS; i++) {
61     if (*str >= '0' && *str <= '9')
62     val += *str - '0';
63     else if (*str >= 'A' && *str <= 'F')
64     val += 10 + *str - 'A';
65     else if (*str >= 'a' && *str <= 'f')
66     val += 10 + *str - 'a';
67     else
68     return -1;
69     if (i < NROFHEXDIGITS - 1)
70     val *= 16;
71     str++;
72     }
73     return val;
74     }
75    
76     /* Decode the C formatted string @src and store the result in the
77     buffer @destp which is @len bytes long. If @len is zero, then a
78     large enough buffer is allocated with malloc and @destp is set to
79     the result. Currently, @len is only used to specify if allocation
80     is desired or not, the caller is expected to make sure that @destp
81     is large enough if @len is not zero. */
82     gpgme_error_t
83     gpg_decode_c_string (const char *src, char **destp, size_t len)
84     {
85     char *dest;
86    
87     /* Set up the destination buffer. */
88     if (len) {
89     if (len < strlen (src) + 1)
90     return gpg_error (GPG_ERR_TOO_SHORT);
91     dest = *destp;
92     }
93     else {
94     /* The converted string will never be larger than the original string. */
95 twoaday 193 dest = (char*)xcalloc (1,strlen (src) + 1);
96 werner 36 *destp = dest;
97     }
98    
99     /* Convert the string. */
100     while (*src) {
101     if (*src != '\\') {
102     *(dest++) = *(src++);
103     continue;
104     }
105    
106     switch (src[1]) {
107     #define DECODE_ONE(match,result) \
108     case match: \
109     src += 2; \
110     *(dest++) = result; \
111     break;
112    
113     DECODE_ONE ('\'', '\'');
114     DECODE_ONE ('\"', '\"');
115     DECODE_ONE ('\?', '\?');
116     DECODE_ONE ('\\', '\\');
117     DECODE_ONE ('a', '\a');
118     DECODE_ONE ('b', '\b');
119     DECODE_ONE ('f', '\f');
120     DECODE_ONE ('n', '\n');
121     DECODE_ONE ('r', '\r');
122     DECODE_ONE ('t', '\t');
123     DECODE_ONE ('v', '\v');
124    
125     case 'x': {
126     int val = hextobyte ((unsigned char*)&src[2]);
127     if (val == -1) { /* Should not happen. */
128     *(dest++) = *(src++);
129     *(dest++) = *(src++);
130     if (*src)
131     *(dest++) = *(src++);
132     if (*src)
133     *(dest++) = *(src++);
134     }
135     else {
136     if (!val) {
137     /* A binary zero is not representable in a C string. */
138     *(dest++) = '\\';
139     *(dest++) = '0';
140     }
141     else
142     *((unsigned char *) dest++) = val;
143     src += 4;
144     }
145     }
146    
147     default: /* Should not happen. */
148     {
149     *(dest++) = *(src++);
150     *(dest++) = *(src++);
151     }
152     }
153     }
154     *(dest++) = 0;
155     return 0;
156     }
157    
158 twoaday 193
159    
160 werner 36 /* Replace %foo% entries with its real values.
161     Return value: expanded path or NULL on error. */
162     static char *
163     expand_path (const char *path)
164     {
165     DWORD len;
166     char *p;
167    
168     len = ExpandEnvironmentStrings (path, NULL, 0);
169     if (!len)
170     return NULL;
171     len += 1;
172 twoaday 193 p = (char*)xcalloc (1, len+1);
173 werner 36 len = ExpandEnvironmentStrings (path, p, len);
174     if (!len) {
175 twoaday 200 safe_free (p);
176 werner 36 return NULL;
177     }
178     return p;
179     }
180    
181    
182     /* Read a string from the W32 registry. The directory is given
183     in @dir and the name of the value in @name, */
184     static char *
185     read_w32_registry (HKEY root_key, const char *dir, const char *name)
186     {
187     HKEY key_handle;
188     DWORD n1, nbytes;
189     DWORD type;
190     char *result = NULL;
191    
192 twoaday 219 if (RegOpenKeyEx (root_key, dir, 0, KEY_READ, &key_handle)) {
193     log_debug ("read_w32_registry (%s, %s) failed.\r\n", dir, name);
194 werner 36 return NULL; /* no need for a RegClose, so return direct */
195 twoaday 219 }
196 werner 36
197     nbytes = 1;
198     if (RegQueryValueEx (key_handle, name, 0, NULL, NULL, &nbytes))
199     goto leave;
200 twoaday 193 result = (char*)xcalloc (1, (n1=nbytes+1));
201 werner 36 if (RegQueryValueEx (key_handle, name, 0, &type, (BYTE*)result, &n1)) {
202 twoaday 200 safe_free (result);
203 werner 36 result = NULL;
204     goto leave;
205     }
206     if (type == REG_EXPAND_SZ && strchr (result, '%')) {
207     char *p = expand_path (result);
208 twoaday 200 safe_free (result);
209 werner 36 result = p;
210     }
211    
212     leave:
213     RegCloseKey (key_handle);
214     return result;
215     }
216    
217 twoaday 193
218 twoaday 133 static char*
219     read_gpg_program (void)
220     {
221     return read_w32_registry (HKEY_CURRENT_USER,
222     "Software\\GNU\\GnuPG", "gpgProgram");
223     }
224 werner 36
225 twoaday 133
226 werner 36 /* Create a temp file based on the name of @name.
227     Return value: handle to the file in case of success. */
228     static HANDLE
229     create_tmpfile (const char *name)
230     {
231     HANDLE out;
232 twoaday 121 SECURITY_ATTRIBUTES sec_attr;
233 twoaday 219 char tmp[MAX_PATH+64];
234 werner 36
235 twoaday 121 memset (&sec_attr, 0, sizeof sec_attr);
236     sec_attr.bInheritHandle = TRUE;
237     sec_attr.lpSecurityDescriptor = NULL;
238     sec_attr.nLength = sizeof sec_attr;
239 werner 36
240 twoaday 175 get_temp_name (tmp, DIM (tmp)-1, name);
241 werner 36 out = CreateFile (tmp, GENERIC_READ|GENERIC_WRITE,
242 twoaday 121 FILE_SHARE_WRITE, &sec_attr,
243 werner 36 OPEN_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL);
244 twoaday 121 if (out == INVALID_HANDLE_VALUE)
245     log_debug ("create_tmpfile: CreateFile failed ec=%d\r\n",
246     (int)GetLastError ());
247 werner 36 return out;
248     }
249    
250    
251     /* Create a pipe with a readable remote end and
252     write the data from @dat to the local end.
253     Return value: read handle on success. */
254     static HANDLE
255     create_in_pipe (const char *dat)
256     {
257     HANDLE r, w;
258     SECURITY_ATTRIBUTES sec_attr;
259     DWORD n;
260    
261     memset (&sec_attr, 0, sizeof sec_attr);
262     sec_attr.bInheritHandle = TRUE;
263     sec_attr.nLength = sizeof sec_attr;
264    
265 twoaday 121 if (!CreatePipe (&r, &w, &sec_attr, 4096)) {
266     log_debug ("create_in_pipe: CreatePipeFailed ec=%d\r\n",
267     (int)GetLastError ());
268 werner 36 return NULL;
269 twoaday 121 }
270 werner 36
271     WriteFile (w, dat, strlen (dat), &n, NULL);
272     CloseHandle (w);
273    
274     return r;
275     }
276    
277    
278     /* Map the contents of the file handle @out to
279     a buffer and return it. */
280     static char*
281 twoaday 133 map_tmpfile (HANDLE out, DWORD *nread)
282 werner 36 {
283     DWORD n;
284     char *p;
285    
286     FlushFileBuffers (out);
287     SetFilePointer (out, 0, NULL, FILE_BEGIN);
288     n = GetFileSize (out, NULL);
289 twoaday 193 p = (char*)xcalloc (1, n+1);
290 werner 36 ReadFile (out, p, n, &n, NULL);
291     p[n] = 0;
292 twoaday 133 if (nread)
293     *nread = n;
294 werner 36 return p;
295     }
296    
297    
298     /* Create a process from the command line in @cmd.
299     If @out is != NULL, the output of the process will
300     be redirected to @out. If @in is != NULL the input
301     will be read from @in.
302     Return value: 0 on success. */
303     static int
304 twoaday 133 create_process (const char *cmd, HANDLE in, HANDLE out, HANDLE err)
305 werner 36 {
306     STARTUPINFO si;
307     PROCESS_INFORMATION pi;
308    
309     memset (&si, 0, sizeof (si));
310     si.cb = sizeof si;
311 twoaday 133 if (in || out || err)
312 twoaday 121 si.dwFlags = STARTF_USESTDHANDLES;
313 werner 36 if (out)
314     si.hStdOutput = out;
315     if (in)
316     si.hStdInput = in;
317 twoaday 133 if (err)
318     si.hStdError = err;
319 twoaday 121 si.dwFlags |= STARTF_USESHOWWINDOW;
320 werner 36 si.wShowWindow = SW_HIDE;
321     if (!CreateProcess (NULL, (char*)cmd, NULL, NULL, TRUE, 0,
322 twoaday 121 NULL, NULL, &si, &pi)) {
323     log_debug ("create_process: CreateProcess failed ec=%d\r\n",
324 twoaday 73 (int)GetLastError ());
325 werner 36 return -1;
326 twoaday 73 }
327 werner 36 WaitForSingleObject (pi.hProcess, INFINITE);
328     CloseHandle (pi.hProcess);
329     return 0;
330     }
331    
332    
333     /* Export a GPG secret key given by @keyid into the file @outfile.
334     Return value: 0 on success. */
335     gpgme_error_t
336     gpg_export_seckey (const char *keyid, const char *outfile)
337     {
338     gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
339     struct stat st;
340 twoaday 200 const char *fmt;
341 werner 36 char *p;
342     char *cmd;
343    
344 twoaday 133 p = read_gpg_program ();
345 werner 36 if (!p)
346     return gpg_error (GPG_ERR_INV_ARG);
347 twoaday 200 fmt = "%s --armor --yes --output \"%s\" --export-secret-key %s";
348 twoaday 193 cmd = (char*)xcalloc (1, strlen (p) + strlen (keyid)
349 twoaday 200 + strlen (outfile) + strlen (fmt) + 2);
350     sprintf (cmd, fmt, p, outfile, keyid);
351 twoaday 133 if (create_process (cmd, NULL, NULL, NULL))
352 werner 36 err = gpg_error (GPG_ERR_INTERNAL);
353    
354     if (stat (outfile, &st) == -1 || st.st_size == 0)
355     err = gpg_error (GPG_ERR_NO_DATA);
356    
357 twoaday 200 safe_free (p);
358     safe_free (cmd);
359 werner 36 return err;
360     }
361    
362    
363 twoaday 121 /* If @export is 1, export the ownertrust data to the
364     buffer @data. Otherwise import the ownertrust data from @data.
365 werner 36 Return value: 0 on success. */
366     gpgme_error_t
367 twoaday 121 gpg_manage_ownertrust (char **data, int do_export)
368 werner 36 {
369     gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
370     HANDLE out = NULL, in = NULL;
371     char *p;
372     char *cmd;
373    
374 twoaday 133 p = read_gpg_program ();
375 werner 36 if (!p)
376     return gpg_error (GPG_ERR_INV_ARG);
377    
378 twoaday 193 cmd = (char*)xcalloc (1, strlen (p) + 64 + 1);
379 twoaday 219 sprintf (cmd, "%s %s", p,
380 twoaday 121 do_export? "--export-ownertrust" : "--import-ownertrust");
381 werner 36
382 twoaday 121 if (do_export)
383 werner 36 out = create_tmpfile ("gpg_ot_out");
384     else {
385     DWORD nw;
386     in = create_tmpfile ("gpg_ot_in");
387     WriteFile (in, *data, strlen (*data), &nw, NULL);
388     FlushFileBuffers (in);
389     }
390 twoaday 133 if (create_process (cmd, in, out, NULL))
391 werner 36 err = gpg_error (GPG_ERR_INTERNAL);
392    
393 twoaday 200 safe_free (p);
394     safe_free (cmd);
395 werner 36
396     if (in)
397     CloseHandle (in);
398     if (out) {
399 twoaday 133 *data = map_tmpfile (out, NULL);
400 werner 36 CloseHandle (out);
401     }
402 twoaday 129
403 werner 36 return err;
404     }
405    
406    
407     /* Call gpg --rebuild-keydb-caches to speed up signature listings. */
408     gpgme_error_t
409     gpg_rebuild_cache (char **r_inf)
410     {
411     gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
412     HANDLE out = NULL;
413 twoaday 193 const char *fmt;
414 werner 36 char *p;
415     char *cmd;
416    
417 twoaday 133 p = read_gpg_program ();
418 werner 36 if (!p)
419     return gpg_error (GPG_ERR_INV_ARG);
420 twoaday 193 fmt = "%s --logger-fd=1 --batch --rebuild-keydb-caches";
421     cmd = (char*)xcalloc (1, strlen (p) + strlen (fmt) + 32);
422     sprintf (cmd, fmt, p);
423 werner 36
424     if (r_inf)
425     out = create_tmpfile ("gpg_rebuild_cache");
426    
427 twoaday 133 if (create_process (cmd, NULL, out, NULL))
428 werner 36 err = gpg_error (GPG_ERR_INTERNAL);
429    
430     if (r_inf)
431 twoaday 133 *r_inf = map_tmpfile (out, NULL);
432 werner 36 if (out)
433     CloseHandle (out);
434 twoaday 200 safe_free (p);
435     safe_free (cmd);
436 twoaday 219 return err;
437 werner 36 }
438    
439    
440     /* Call gpg --version to retrieve the 'about' information. */
441     gpgme_error_t
442     gpg_get_version (char **r_inf)
443     {
444     gpgme_error_t err= gpg_error (GPG_ERR_NO_ERROR);
445     HANDLE out;
446     char *p, *cmd;
447    
448 twoaday 133 p = read_gpg_program ();
449 werner 36 if (!p)
450     return gpg_error (GPG_ERR_INV_ARG);
451 twoaday 193 cmd = (char*)xcalloc (1, strlen (p) + 32);
452 werner 36 sprintf (cmd, "%s --version", p);
453    
454     out = create_tmpfile ("gpg_out");
455 twoaday 133 if (create_process (cmd, NULL, out, NULL))
456 werner 36 err = gpg_error (GPG_ERR_INTERNAL);
457    
458 twoaday 200 safe_free (p);
459     safe_free (cmd);
460 werner 36
461 twoaday 133 *r_inf = map_tmpfile (out, NULL);
462 werner 36 CloseHandle (out);
463     return err;
464     }
465    
466    
467     /* Return the colon file output of the given file @fname in @r_out.
468     Return value: 0 on success. */
469     gpgme_error_t
470     gpg_import_key_list (const char *fname, char **r_out)
471     {
472     gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
473 twoaday 200 const char *fmt;
474 werner 36 char *cmd, *p;
475     HANDLE out;
476    
477 twoaday 133 p = read_gpg_program ();
478 werner 36 if (!p)
479     return gpg_error (GPG_ERR_INV_ARG);
480    
481 twoaday 200 fmt = "%s --fixed-list-mode --with-colons \"%s\"";
482     cmd = (char*)xcalloc (1, strlen (p) + strlen (fname) + strlen (fmt) + 2);
483     sprintf (cmd, fmt, p, fname);
484 werner 36
485     out = create_tmpfile ("gpg_keys");
486 twoaday 133 if (create_process (cmd, NULL, out, NULL))
487 werner 36 err = gpg_error (GPG_ERR_INTERNAL);
488    
489 twoaday 200 safe_free (p);
490     safe_free (cmd);
491 werner 36
492 twoaday 133 *r_out = map_tmpfile (out, NULL);
493 werner 36 CloseHandle (out);
494     return err;
495     }
496    
497 twoaday 129
498 werner 36 /* Generate a revocation certificate for the key with the keyid @keyid.
499     @inp_data contains all needed data to answer the questions of the
500     command handler. Each separate with a '\n'.
501     @r_revcert contains the revocation cert on success.
502 twoaday 208 if @desig_revoke is 1, the designated revoker mode is used.
503 werner 36 Return value: 0 on success. */
504     gpgme_error_t
505 twoaday 208 gpg_revoke_cert (int desig_revoke, const char *inp_data,
506     const char *keyid, char **r_revcert)
507 werner 36 {
508     gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
509 twoaday 208 const char *fmt, *revcmd;
510 werner 36 char *rcrt;
511     char *cmd, *p;
512     HANDLE in, out;
513    
514 twoaday 133 p = read_gpg_program ();
515 werner 36 if (!p)
516     return gpg_error (GPG_ERR_INV_ARG);
517    
518 twoaday 208 revcmd = desig_revoke? "--desig-revoke" : "--gen-revoke";
519     fmt = "%s --pgp7 --command-fd=0 --status-fd=2 %s %s";
520     cmd = (char*)xcalloc (1, strlen (p) + strlen (revcmd) +
521     strlen (keyid) + strlen (fmt) + 2);
522     sprintf (cmd, fmt, p, revcmd, keyid);
523 werner 36
524     in = create_in_pipe (inp_data);
525     out = create_tmpfile ("gpg_revcert");
526 twoaday 133 if (create_process (cmd, in, out, NULL)) {
527 werner 36 *r_revcert = NULL;
528     err = gpg_error (GPG_ERR_INTERNAL);
529     }
530     else {
531 twoaday 133 rcrt = map_tmpfile (out, NULL);
532 werner 36 *r_revcert = rcrt;
533 twoaday 129 if (rcrt && strlen (rcrt) == 0)
534     err = gpg_error (GPG_ERR_BAD_PASSPHRASE);
535 werner 36 }
536    
537 twoaday 200 safe_free (p);
538     safe_free (cmd);
539 werner 36
540     CloseHandle (in);
541     CloseHandle (out);
542     return err;
543     }
544    
545    
546 twoaday 133 /* Return the raw photo-id data combined with the status-fd
547     entry in @r_data. If @keyid is set, only the data for this
548     key will be returned.
549     Return value: 0 on success. */
550     gpgme_error_t
551     gpg_get_photoid_data (const char *keyid, char **r_status_data,
552     unsigned char **r_data, unsigned long *ndata)
553     {
554     gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
555     HANDLE herr, hdat;
556 twoaday 200 const char *fmt;
557 twoaday 133 char *p, *cmd;
558     DWORD n;
559    
560 twoaday 164 if (ndata)
561     *ndata = 0;
562 twoaday 133 p = read_gpg_program ();
563     if (!p)
564     return gpg_error (GPG_ERR_INV_ARG);
565 twoaday 200 fmt = "%s --attribute-fd=%d --status-fd=2 --list-keys %s";
566     n = strlen (p) + strlen (fmt) + 1;
567 twoaday 133 if (keyid)
568     n += strlen (keyid) + 1;
569 twoaday 193 cmd = (char*)xcalloc (1, n+1);
570 twoaday 200 /* XXX: add --list-options show-unsuable-uid to display
571     revoked attribute IDs */
572 twoaday 133 hdat = create_tmpfile ("gpg_uat_data");
573     herr = create_tmpfile ("gpg_uat_status");
574 twoaday 200 sprintf (cmd, fmt, p, (int)hdat, keyid? keyid : "");
575 twoaday 133 if (create_process (cmd, NULL, NULL, herr))
576     err = gpg_error (GPG_ERR_INTERNAL);
577    
578 twoaday 200 safe_free (p);
579     safe_free (cmd);
580 twoaday 133
581     *r_data = (BYTE*)map_tmpfile (hdat, ndata);
582     *r_status_data = map_tmpfile (herr, NULL);
583     CloseHandle (hdat);
584     CloseHandle (herr);
585    
586     return err;
587     }
588    
589    
590 twoaday 175 /* Extract one or more keys from the key file @keyfile.
591     The keys to extract are give in @keys and the size of it is @nkeys.
592     @new_keyfile is a file with the extract keys.
593     Return value: 0 on success. */
594     gpgme_error_t
595     gpg_extract_keys (const char *keyfile, const char **keys, DWORD nkeys,
596     char **new_keyfile)
597     {
598     gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
599     const char *fmt;
600     char *p, *cmd;
601     char tmpnam[MAX_PATH], tmpdir[MAX_PATH];
602     int i, n;
603    
604     /* copy key file to temp dir. */
605     GetTempPath (MAX_PATH-1, tmpdir);
606     get_temp_name (tmpnam, MAX_PATH-1, NULL);
607     CopyFile (keyfile, tmpnam, FALSE);
608    
609     /* create temp file for output. */
610     *new_keyfile = new char[MAX_PATH];
611     if (!*new_keyfile)
612     BUG (NULL);
613     get_temp_name (*new_keyfile, MAX_PATH-1, "sel_keys");
614    
615     p = read_gpg_program ();
616     if (!p)
617     return gpg_error (GPG_ERR_INV_ARG);
618    
619     /* Use the temp key file as a keyring and export the selected
620     keys from it. */
621     fmt = "%s --yes --output %s --no-options --homedir %s --keyring %s --export ";
622     n = strlen (fmt) + strlen (p)+1 + strlen (tmpdir)+1 + strlen (tmpnam) + 1;
623     n += strlen (*new_keyfile)+1;
624     for (i=0; i < (int)nkeys; i++)
625     n += strlen (keys[i])+1+2;
626 twoaday 193 cmd = (char*)xcalloc (1, n+1);
627 twoaday 175 sprintf (cmd, fmt, p, *new_keyfile, tmpdir, tmpnam);
628     for (i=0; i < (int)nkeys; i++) {
629     strcat (cmd, keys[i]);
630     strcat (cmd, " " );
631     }
632    
633     if (create_process (cmd, NULL, NULL, NULL))
634     err = gpgme_error (GPG_ERR_INTERNAL);
635    
636     DeleteFile (tmpnam);
637     safe_free (cmd);
638     safe_free (p);
639     return err;
640     }
641    
642    
643 werner 36 /* Return the validity of the user attribute, informerly known
644     as photo-ID. If no uat was found, return 0 for unknown. */
645     gpgme_error_t
646     get_uat_validity (const char *keyid, gpgme_validity_t *r_valid)
647     {
648     gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
649     HANDLE out;
650 twoaday 200 const char *fmt;
651 werner 36 char *p, *cmd;
652     char *uat;
653    
654     *r_valid = GPGME_VALIDITY_UNKNOWN;
655 twoaday 133 p = read_gpg_program ();
656 werner 36 if (!p)
657     return gpg_error (GPG_ERR_INV_ARG);
658    
659 twoaday 200 fmt = "%s --with-colons --fixed-list-mode --list-keys \"%s\"";
660     cmd = (char*)xcalloc (1, strlen (p) + strlen (keyid) + strlen (fmt) + 2);
661     sprintf (cmd, fmt, p, keyid);
662 werner 36
663     out = create_tmpfile ("gpg_keys");
664 twoaday 133 if (create_process (cmd, NULL, out, NULL))
665 werner 36 err = gpg_error (GPG_ERR_INTERNAL);
666    
667 twoaday 175 safe_free (p);
668     safe_free (cmd);
669 werner 36
670 twoaday 133 p = map_tmpfile (out, NULL);
671 werner 36 if ((uat = strstr (p, "uat:"))) {
672     switch (*(uat+4)) {
673     case 'm': *r_valid = GPGME_VALIDITY_MARGINAL; break;
674     case 'f':
675     case 'u': *r_valid = GPGME_VALIDITY_FULL; break;
676 twoaday 219 default : *r_valid = GPGME_VALIDITY_UNDEFINED; break;
677 werner 36 }
678     }
679    
680 twoaday 200 safe_free (p);
681 werner 36 CloseHandle (out);
682     return err;
683     }
684    
685    
686 twoaday 179 static gpgme_error_t
687     clip_store_data (char *tmp_outname, DWORD outlen)
688     {
689     gpgme_data_t in;
690     gpgme_error_t err;
691    
692     get_temp_name (tmp_outname, outlen-1, NULL);
693     err = gpg_data_new_from_clipboard (&in, 0);
694     if (err)
695     return err;
696     err = gpg_data_release_and_set_file (in, tmp_outname);
697     return err;
698     }
699    
700    
701 werner 36 /* Extract all recipients from the file @file.
702     Return value: 0 on success. */
703 twoaday 179 static gpgme_error_t
704     file_extract_recipient (const char *file, gpgme_recipient_t *r_list)
705     {
706 werner 36 PACKET *pkt;
707 twoaday 179 PKT_pubkey_enc *enc;
708 werner 36 gpg_iobuf_t inp = NULL;
709     armor_filter_context_t afx;
710 twoaday 179 gpgme_recipient_t l;
711 werner 36 int rc = 0, quit=0;
712    
713     if (!file || !r_list) {
714     log_debug ("do_list_packets: !r_list || !file");
715 twoaday 179 return gpgme_error (GPG_ERR_INV_ARG);
716 werner 36 }
717    
718 twoaday 200 *r_list = NULL;
719 werner 36 inp = gpg_iobuf_open (file);
720     if (!inp)
721 twoaday 179 return gpgme_err_code_from_errno (errno);
722 werner 36 gpg_iobuf_ioctl (inp, 3, 1, NULL); /* disable cache */
723     if (gpg_use_armor_filter (inp)) {
724     memset (&afx, 0, sizeof (afx));
725     gpg_iobuf_push_filter (inp, gpg_armor_filter, &afx);
726     }
727 twoaday 193 pkt = (PACKET *)xcalloc(1, sizeof *pkt);
728 werner 36 gpg_init_packet (pkt);
729     while (!quit && (rc = gpg_parse_packet (inp, pkt)) != -1) {
730     switch (pkt->pkttype) {
731     case PKT_PUBKEY_ENC:
732 twoaday 179 enc = pkt->pkt.pubkey_enc;
733 werner 36 if (!enc)
734     break;
735 twoaday 193 l = (gpgme_recipient_t)xcalloc (1, sizeof *l);
736     l->keyid = (char*)xcalloc (1, 16+1);
737 twoaday 219 _snprintf (l->keyid, 16, "%08lX%08lX",
738     enc->keyid[0], enc->keyid[1]);
739 twoaday 179 l->pubkey_algo = (gpgme_pubkey_algo_t)enc->pubkey_algo;
740 werner 36 l->status = 0;
741     l->next = (*r_list);
742     *r_list = l;
743 twoaday 179 break;
744 werner 36
745     case PKT_ENCRYPTED:
746     case PKT_ENCRYPTED_MDC:
747 twoaday 200 case PKT_PLAINTEXT:
748 werner 36 case PKT_COMPRESSED:
749     case PKT_PUBLIC_KEY:
750     case PKT_SECRET_KEY:
751     quit = 1;
752     break;
753 twoaday 181
754 twoaday 180 default:
755     break;
756 werner 36 }
757     gpg_free_packet (pkt);
758     gpg_init_packet (pkt);
759     }
760     gpg_iobuf_close (inp);
761     safe_free (pkt);
762     return 0;
763     }
764 twoaday 179
765    
766     /* Either extract the list of recipients from the file @file or
767     if the string is NULL, try to extract them from the clipboard.
768     Return value: 0 on success. */
769     gpgme_error_t
770     gpg_get_recipients (const char *file, gpgme_recipient_t *r_list)
771     {
772     gpgme_error_t err;
773     char tmp[MAX_PATH+1];
774    
775     if (!file) {
776     clip_store_data (tmp, DIM (tmp)-2);
777     err = file_extract_recipient (tmp, r_list);
778     DeleteFile (tmp);
779     }
780     else
781     err = file_extract_recipient (file, r_list);
782     return err;
783     }
784 twoaday 181
785    
786     /* Try to find a subpacket with the given id @subpktid
787     inside the key @key.
788     Return value: 0 on success. */
789     gpgme_error_t
790 twoaday 219 gpg_find_key_subpacket (const char *key, int subpktid, char **value)
791 twoaday 181 {
792     gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
793     const char *fmt;
794     const char *spk;
795     char *p, *cmd;
796     HANDLE out;
797    
798     *value = NULL;
799     p = read_gpg_program ();
800 twoaday 214 fmt = "%s --with-colons --no-options --list-options show-sig-subpackets=%d --list-sigs %s";
801 twoaday 193 cmd = (char*)xcalloc (1, strlen (fmt) + strlen (p) + strlen (key) + 32 + 1);
802 twoaday 181 sprintf (cmd, fmt, p, subpktid, key);
803    
804     out = create_tmpfile ("gpg_subpackets");
805     if (create_process (cmd, NULL, out, NULL))
806     err = gpg_error (GPG_ERR_INTERNAL);
807    
808 twoaday 200 safe_free (p);
809     safe_free (cmd);
810 twoaday 181
811 twoaday 219 p = map_tmpfile (out, NULL);
812 twoaday 181 if (p && (spk=strstr (p, "spk"))) {
813     char *end = strstr (spk, "\n");
814 twoaday 200
815 twoaday 181 if (end) {
816 twoaday 193 *value = (char*)xcalloc (1, (end-spk)+1);
817 twoaday 181 memcpy (*value, spk, (end-spk)-1);
818     }
819     }
820    
821 twoaday 200 safe_free (p);
822 twoaday 181 CloseHandle (out);
823     return err;
824     }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26