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

Annotation of /trunk/Src/wptGPGUtil.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 193 - (hide annotations)
Sat Apr 1 12:36:35 2006 UTC (18 years, 11 months ago) by twoaday
File size: 20950 byte(s)
2006-03-31  Timo Schulz  <ts@g10code.de>
 
        * wptCommonDlg.cpp (nls_load_langlist): New.
        (nsl_set_language): New.
        (nls_dlg_proc): New.
        (select_language): New. Allow user to select the language.
        * wptNLS.c (get_gettext_langid): Updated available languages.
        * WinPT.cpp (WinMain): Allow to select the languag on first
        start in non-installer environments.
        * wptVerifyList.cpp (verlist_build): Simplified.
        (verlist_add_sig_log): Likewise.
        * wptListview.cpp (listview_set_column_width,
        listview_get_selected_item): New.
        * wptKeyManager.cpp (gpg_clip_export): Merged into..
        (km_clip_export): ..this function.


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     free (p);
176     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     if (RegOpenKeyEx (root_key, dir, 0, KEY_READ, &key_handle))
193     return NULL; /* no need for a RegClose, so return direct */
194    
195     nbytes = 1;
196     if (RegQueryValueEx (key_handle, name, 0, NULL, NULL, &nbytes))
197     goto leave;
198 twoaday 193 result = (char*)xcalloc (1, (n1=nbytes+1));
199 werner 36 if (RegQueryValueEx (key_handle, name, 0, &type, (BYTE*)result, &n1)) {
200     free (result);
201     result = NULL;
202     goto leave;
203     }
204     if (type == REG_EXPAND_SZ && strchr (result, '%')) {
205     char *p = expand_path (result);
206     free (result);
207     result = p;
208     }
209    
210     leave:
211     RegCloseKey (key_handle);
212     return result;
213     }
214    
215 twoaday 193
216 twoaday 133 static char*
217     read_gpg_program (void)
218     {
219     return read_w32_registry (HKEY_CURRENT_USER,
220     "Software\\GNU\\GnuPG", "gpgProgram");
221     }
222 werner 36
223 twoaday 133
224 werner 36 /* Create a temp file based on the name of @name.
225     Return value: handle to the file in case of success. */
226     static HANDLE
227     create_tmpfile (const char *name)
228     {
229     HANDLE out;
230 twoaday 121 SECURITY_ATTRIBUTES sec_attr;
231 werner 36 char tmp[300];
232    
233 twoaday 121 memset (&sec_attr, 0, sizeof sec_attr);
234     sec_attr.bInheritHandle = TRUE;
235     sec_attr.lpSecurityDescriptor = NULL;
236     sec_attr.nLength = sizeof sec_attr;
237 werner 36
238 twoaday 175 get_temp_name (tmp, DIM (tmp)-1, name);
239 werner 36 out = CreateFile (tmp, GENERIC_READ|GENERIC_WRITE,
240 twoaday 121 FILE_SHARE_WRITE, &sec_attr,
241 werner 36 OPEN_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL);
242 twoaday 121 if (out == INVALID_HANDLE_VALUE)
243     log_debug ("create_tmpfile: CreateFile failed ec=%d\r\n",
244     (int)GetLastError ());
245 werner 36 return out;
246     }
247    
248    
249     /* Create a pipe with a readable remote end and
250     write the data from @dat to the local end.
251     Return value: read handle on success. */
252     static HANDLE
253     create_in_pipe (const char *dat)
254     {
255     HANDLE r, w;
256     SECURITY_ATTRIBUTES sec_attr;
257     DWORD n;
258    
259     memset (&sec_attr, 0, sizeof sec_attr);
260     sec_attr.bInheritHandle = TRUE;
261     sec_attr.nLength = sizeof sec_attr;
262    
263 twoaday 121 if (!CreatePipe (&r, &w, &sec_attr, 4096)) {
264     log_debug ("create_in_pipe: CreatePipeFailed ec=%d\r\n",
265     (int)GetLastError ());
266 werner 36 return NULL;
267 twoaday 121 }
268 werner 36
269     WriteFile (w, dat, strlen (dat), &n, NULL);
270     CloseHandle (w);
271    
272     return r;
273     }
274    
275    
276     /* Map the contents of the file handle @out to
277     a buffer and return it. */
278     static char*
279 twoaday 133 map_tmpfile (HANDLE out, DWORD *nread)
280 werner 36 {
281     DWORD n;
282     char *p;
283    
284     FlushFileBuffers (out);
285     SetFilePointer (out, 0, NULL, FILE_BEGIN);
286     n = GetFileSize (out, NULL);
287 twoaday 193 p = (char*)xcalloc (1, n+1);
288 werner 36 ReadFile (out, p, n, &n, NULL);
289     p[n] = 0;
290 twoaday 133 if (nread)
291     *nread = n;
292 werner 36 return p;
293     }
294    
295    
296     /* Create a process from the command line in @cmd.
297     If @out is != NULL, the output of the process will
298     be redirected to @out. If @in is != NULL the input
299     will be read from @in.
300     Return value: 0 on success. */
301     static int
302 twoaday 133 create_process (const char *cmd, HANDLE in, HANDLE out, HANDLE err)
303 werner 36 {
304     STARTUPINFO si;
305     PROCESS_INFORMATION pi;
306    
307     memset (&si, 0, sizeof (si));
308     si.cb = sizeof si;
309 twoaday 133 if (in || out || err)
310 twoaday 121 si.dwFlags = STARTF_USESTDHANDLES;
311 werner 36 if (out)
312     si.hStdOutput = out;
313     if (in)
314     si.hStdInput = in;
315 twoaday 133 if (err)
316     si.hStdError = err;
317 twoaday 121 si.dwFlags |= STARTF_USESHOWWINDOW;
318 werner 36 si.wShowWindow = SW_HIDE;
319     if (!CreateProcess (NULL, (char*)cmd, NULL, NULL, TRUE, 0,
320 twoaday 121 NULL, NULL, &si, &pi)) {
321     log_debug ("create_process: CreateProcess failed ec=%d\r\n",
322 twoaday 73 (int)GetLastError ());
323 werner 36 return -1;
324 twoaday 73 }
325 werner 36 WaitForSingleObject (pi.hProcess, INFINITE);
326     CloseHandle (pi.hProcess);
327     return 0;
328     }
329    
330    
331     /* Export a GPG secret key given by @keyid into the file @outfile.
332     Return value: 0 on success. */
333     gpgme_error_t
334     gpg_export_seckey (const char *keyid, const char *outfile)
335     {
336     gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
337     struct stat st;
338     char *p;
339     char *cmd;
340    
341 twoaday 133 p = read_gpg_program ();
342 werner 36 if (!p)
343     return gpg_error (GPG_ERR_INV_ARG);
344 twoaday 193 cmd = (char*)xcalloc (1, strlen (p) + strlen (keyid)
345 werner 36 + strlen (outfile) + 64 + 2);
346     sprintf (cmd, "%s --yes --output \"%s\" --export-secret-key %s",
347     p, outfile, keyid);
348 twoaday 133 if (create_process (cmd, NULL, NULL, NULL))
349 werner 36 err = gpg_error (GPG_ERR_INTERNAL);
350    
351     if (stat (outfile, &st) == -1 || st.st_size == 0)
352     err = gpg_error (GPG_ERR_NO_DATA);
353    
354     free (p);
355     free (cmd);
356     return err;
357     }
358    
359    
360 twoaday 121 /* If @export is 1, export the ownertrust data to the
361     buffer @data. Otherwise import the ownertrust data from @data.
362 werner 36 Return value: 0 on success. */
363     gpgme_error_t
364 twoaday 121 gpg_manage_ownertrust (char **data, int do_export)
365 werner 36 {
366     gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
367     HANDLE out = NULL, in = NULL;
368     char *p;
369     char *cmd;
370    
371 twoaday 133 p = read_gpg_program ();
372 werner 36 if (!p)
373     return gpg_error (GPG_ERR_INV_ARG);
374    
375 twoaday 193 cmd = (char*)xcalloc (1, strlen (p) + 64 + 1);
376 werner 36 sprintf (cmd, "%s %s", p,
377 twoaday 121 do_export? "--export-ownertrust" : "--import-ownertrust");
378 werner 36
379 twoaday 121 if (do_export)
380 werner 36 out = create_tmpfile ("gpg_ot_out");
381     else {
382     DWORD nw;
383     in = create_tmpfile ("gpg_ot_in");
384     WriteFile (in, *data, strlen (*data), &nw, NULL);
385     FlushFileBuffers (in);
386     /* XXX: need a rewind? */
387     }
388 twoaday 133 if (create_process (cmd, in, out, NULL))
389 werner 36 err = gpg_error (GPG_ERR_INTERNAL);
390    
391     free (p);
392     free (cmd);
393    
394     if (in)
395     CloseHandle (in);
396     if (out) {
397 twoaday 133 *data = map_tmpfile (out, NULL);
398 werner 36 CloseHandle (out);
399     }
400 twoaday 129
401 werner 36 return err;
402     }
403    
404    
405     /* Call gpg --rebuild-keydb-caches to speed up signature listings. */
406     gpgme_error_t
407     gpg_rebuild_cache (char **r_inf)
408     {
409     gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
410     HANDLE out = NULL;
411 twoaday 193 const char *fmt;
412 werner 36 char *p;
413     char *cmd;
414    
415 twoaday 133 p = read_gpg_program ();
416 werner 36 if (!p)
417     return gpg_error (GPG_ERR_INV_ARG);
418 twoaday 193 fmt = "%s --logger-fd=1 --batch --rebuild-keydb-caches";
419     cmd = (char*)xcalloc (1, strlen (p) + strlen (fmt) + 32);
420     sprintf (cmd, fmt, p);
421 werner 36
422     if (r_inf)
423     out = create_tmpfile ("gpg_rebuild_cache");
424    
425 twoaday 133 if (create_process (cmd, NULL, out, NULL))
426 werner 36 err = gpg_error (GPG_ERR_INTERNAL);
427    
428     if (r_inf)
429 twoaday 133 *r_inf = map_tmpfile (out, NULL);
430 werner 36 if (out)
431     CloseHandle (out);
432     free (p);
433     free (cmd);
434     return 0;
435     }
436    
437    
438     /* Call gpg --version to retrieve the 'about' information. */
439     gpgme_error_t
440     gpg_get_version (char **r_inf)
441     {
442     gpgme_error_t err= gpg_error (GPG_ERR_NO_ERROR);
443     HANDLE out;
444     char *p, *cmd;
445    
446 twoaday 133 p = read_gpg_program ();
447 werner 36 if (!p)
448     return gpg_error (GPG_ERR_INV_ARG);
449 twoaday 193 cmd = (char*)xcalloc (1, strlen (p) + 32);
450 werner 36 sprintf (cmd, "%s --version", p);
451    
452     out = create_tmpfile ("gpg_out");
453 twoaday 133 if (create_process (cmd, NULL, out, NULL))
454 werner 36 err = gpg_error (GPG_ERR_INTERNAL);
455    
456     free (p);
457     free (cmd);
458    
459 twoaday 133 *r_inf = map_tmpfile (out, NULL);
460 werner 36 CloseHandle (out);
461     return err;
462     }
463    
464    
465     /* Return the colon file output of the given file @fname in @r_out.
466     Return value: 0 on success. */
467     gpgme_error_t
468     gpg_import_key_list (const char *fname, char **r_out)
469     {
470     gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
471     char *cmd, *p;
472     HANDLE out;
473    
474 twoaday 133 p = read_gpg_program ();
475 werner 36 if (!p)
476     return gpg_error (GPG_ERR_INV_ARG);
477    
478 twoaday 193 cmd = (char*)xcalloc (1, strlen (p) + strlen (fname) + 2+2 + 64);
479 werner 36 sprintf (cmd, "%s --fixed-list-mode --with-colons \"%s\"", p, fname);
480    
481     out = create_tmpfile ("gpg_keys");
482 twoaday 133 if (create_process (cmd, NULL, out, NULL))
483 werner 36 err = gpg_error (GPG_ERR_INTERNAL);
484    
485     free (p);
486     free (cmd);
487    
488 twoaday 133 *r_out = map_tmpfile (out, NULL);
489 werner 36 CloseHandle (out);
490     return err;
491     }
492    
493 twoaday 129
494 werner 36 char*
495 twoaday 129 generate_revoke_input (int code, const char *cmt, const char *pass)
496 werner 36 {
497     const char *fmt;
498     char *p;
499     size_t n;
500    
501     fmt = "Y\n" /* gen_revoke.okay */
502     "%d\n" /* ask_revocation_reason.code */
503     "%s\n" /* ask_revocation_reason.text */
504     "%s" /* text != NULL '\n' otherwise '' */
505     "Y\n" /* ask_revocation_reason.okay */
506     "%s\n"; /* passphrase.enter. */
507     n = strlen (fmt) + 32;
508     if (pass)
509     n += strlen (pass) + 1;
510     if (cmt)
511     n += strlen (cmt) + 1;
512 twoaday 193 p = (char*)xcalloc (1, n+1);
513 werner 36 sprintf (p, fmt, code, cmt? cmt : "", cmt? "\n" : "", pass? pass : "");
514     return p;
515     }
516    
517    
518     /* Generate a revocation certificate for the key with the keyid @keyid.
519     @inp_data contains all needed data to answer the questions of the
520     command handler. Each separate with a '\n'.
521     @r_revcert contains the revocation cert on success.
522     Return value: 0 on success. */
523     gpgme_error_t
524 twoaday 129 gpg_revoke_cert (const char *inp_data, const char *keyid, char **r_revcert)
525 werner 36 {
526     gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
527     char *rcrt;
528     char *cmd, *p;
529     HANDLE in, out;
530    
531 twoaday 133 p = read_gpg_program ();
532 werner 36 if (!p)
533     return gpg_error (GPG_ERR_INV_ARG);
534    
535 twoaday 193 cmd = (char*)xcalloc (1, strlen (p) + strlen (keyid)+1 + 128);
536 werner 36 sprintf (cmd, "%s --pgp7 --command-fd=0 --status-fd=2 --gen-revoke %s",
537     p, keyid);
538    
539     in = create_in_pipe (inp_data);
540     out = create_tmpfile ("gpg_revcert");
541 twoaday 133 if (create_process (cmd, in, out, NULL)) {
542 werner 36 *r_revcert = NULL;
543     err = gpg_error (GPG_ERR_INTERNAL);
544     }
545     else {
546 twoaday 133 rcrt = map_tmpfile (out, NULL);
547 werner 36 *r_revcert = rcrt;
548 twoaday 129 if (rcrt && strlen (rcrt) == 0)
549     err = gpg_error (GPG_ERR_BAD_PASSPHRASE);
550 werner 36 }
551    
552     free (p);
553     free (cmd);
554    
555     CloseHandle (in);
556     CloseHandle (out);
557     return err;
558     }
559    
560    
561 twoaday 133 /* Return the raw photo-id data combined with the status-fd
562     entry in @r_data. If @keyid is set, only the data for this
563     key will be returned.
564     Return value: 0 on success. */
565     gpgme_error_t
566     gpg_get_photoid_data (const char *keyid, char **r_status_data,
567     unsigned char **r_data, unsigned long *ndata)
568     {
569     gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
570     HANDLE herr, hdat;
571     char *p, *cmd;
572     DWORD n;
573    
574 twoaday 164 if (ndata)
575     *ndata = 0;
576 twoaday 133 p = read_gpg_program ();
577     if (!p)
578     return gpg_error (GPG_ERR_INV_ARG);
579     n = strlen (p) + 128;
580     if (keyid)
581     n += strlen (keyid) + 1;
582 twoaday 193 cmd = (char*)xcalloc (1, n+1);
583 twoaday 133 hdat = create_tmpfile ("gpg_uat_data");
584     herr = create_tmpfile ("gpg_uat_status");
585     /* XXX: add --list-options show-unsuable-uid to display
586     revoked attribute IDs */
587     sprintf (cmd, "%s --attribute-fd=%d --status-fd=2 --list-keys %s",
588     p, (int)hdat, keyid? keyid : "");
589     if (create_process (cmd, NULL, NULL, herr))
590     err = gpg_error (GPG_ERR_INTERNAL);
591    
592     free (p);
593     free (cmd);
594    
595     *r_data = (BYTE*)map_tmpfile (hdat, ndata);
596     *r_status_data = map_tmpfile (herr, NULL);
597     CloseHandle (hdat);
598     CloseHandle (herr);
599    
600     return err;
601     }
602    
603    
604 twoaday 175 /* Extract one or more keys from the key file @keyfile.
605     The keys to extract are give in @keys and the size of it is @nkeys.
606     @new_keyfile is a file with the extract keys.
607     Return value: 0 on success. */
608     gpgme_error_t
609     gpg_extract_keys (const char *keyfile, const char **keys, DWORD nkeys,
610     char **new_keyfile)
611     {
612     gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
613     const char *fmt;
614     char *p, *cmd;
615     char tmpnam[MAX_PATH], tmpdir[MAX_PATH];
616     int i, n;
617    
618     /* copy key file to temp dir. */
619     GetTempPath (MAX_PATH-1, tmpdir);
620     get_temp_name (tmpnam, MAX_PATH-1, NULL);
621     CopyFile (keyfile, tmpnam, FALSE);
622    
623     /* create temp file for output. */
624     *new_keyfile = new char[MAX_PATH];
625     if (!*new_keyfile)
626     BUG (NULL);
627     get_temp_name (*new_keyfile, MAX_PATH-1, "sel_keys");
628    
629     p = read_gpg_program ();
630     if (!p)
631     return gpg_error (GPG_ERR_INV_ARG);
632    
633     /* Use the temp key file as a keyring and export the selected
634     keys from it. */
635     fmt = "%s --yes --output %s --no-options --homedir %s --keyring %s --export ";
636     n = strlen (fmt) + strlen (p)+1 + strlen (tmpdir)+1 + strlen (tmpnam) + 1;
637     n += strlen (*new_keyfile)+1;
638     for (i=0; i < (int)nkeys; i++)
639     n += strlen (keys[i])+1+2;
640 twoaday 193 cmd = (char*)xcalloc (1, n+1);
641 twoaday 175 sprintf (cmd, fmt, p, *new_keyfile, tmpdir, tmpnam);
642     for (i=0; i < (int)nkeys; i++) {
643     strcat (cmd, keys[i]);
644     strcat (cmd, " " );
645     }
646    
647     if (create_process (cmd, NULL, NULL, NULL))
648     err = gpgme_error (GPG_ERR_INTERNAL);
649    
650     DeleteFile (tmpnam);
651     safe_free (cmd);
652     safe_free (p);
653     return err;
654     }
655    
656    
657 werner 36 /* Return the validity of the user attribute, informerly known
658     as photo-ID. If no uat was found, return 0 for unknown. */
659     gpgme_error_t
660     get_uat_validity (const char *keyid, gpgme_validity_t *r_valid)
661     {
662     gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
663     HANDLE out;
664     char *p, *cmd;
665     char *uat;
666    
667     *r_valid = GPGME_VALIDITY_UNKNOWN;
668 twoaday 133 p = read_gpg_program ();
669 werner 36 if (!p)
670     return gpg_error (GPG_ERR_INV_ARG);
671    
672 twoaday 193 cmd = (char*)xcalloc (1, strlen (p) + strlen (keyid)+1 + 128);
673 werner 36 sprintf (cmd, "%s --with-colons --fixed-list-mode --list-keys \"%s\"",
674     p, keyid);
675    
676     out = create_tmpfile ("gpg_keys");
677 twoaday 133 if (create_process (cmd, NULL, out, NULL))
678 werner 36 err = gpg_error (GPG_ERR_INTERNAL);
679    
680 twoaday 175 safe_free (p);
681     safe_free (cmd);
682 werner 36
683 twoaday 133 p = map_tmpfile (out, NULL);
684 werner 36 if ((uat = strstr (p, "uat:"))) {
685     switch (*(uat+4)) {
686     case 'm': *r_valid = GPGME_VALIDITY_MARGINAL; break;
687     case 'f':
688     case 'u': *r_valid = GPGME_VALIDITY_FULL; break;
689     default: *r_valid = GPGME_VALIDITY_UNDEFINED; break;
690     }
691     }
692    
693     free (p);
694     CloseHandle (out);
695     return err;
696     }
697    
698    
699 twoaday 179 static gpgme_error_t
700     clip_store_data (char *tmp_outname, DWORD outlen)
701     {
702     gpgme_data_t in;
703     gpgme_error_t err;
704    
705     get_temp_name (tmp_outname, outlen-1, NULL);
706     err = gpg_data_new_from_clipboard (&in, 0);
707     if (err)
708     return err;
709     err = gpg_data_release_and_set_file (in, tmp_outname);
710     return err;
711     }
712    
713    
714 werner 36 /* Extract all recipients from the file @file.
715     Return value: 0 on success. */
716 twoaday 179 static gpgme_error_t
717     file_extract_recipient (const char *file, gpgme_recipient_t *r_list)
718     {
719 werner 36 PACKET *pkt;
720 twoaday 179 PKT_pubkey_enc *enc;
721 werner 36 gpg_iobuf_t inp = NULL;
722     armor_filter_context_t afx;
723 twoaday 179 gpgme_recipient_t l;
724 werner 36 int rc = 0, quit=0;
725    
726     if (!file || !r_list) {
727     log_debug ("do_list_packets: !r_list || !file");
728 twoaday 179 return gpgme_error (GPG_ERR_INV_ARG);
729 werner 36 }
730    
731     *r_list=NULL;
732     inp = gpg_iobuf_open (file);
733     if (!inp)
734 twoaday 179 return gpgme_err_code_from_errno (errno);
735 werner 36 gpg_iobuf_ioctl (inp, 3, 1, NULL); /* disable cache */
736     if (gpg_use_armor_filter (inp)) {
737     memset (&afx, 0, sizeof (afx));
738     gpg_iobuf_push_filter (inp, gpg_armor_filter, &afx);
739     }
740 twoaday 193 pkt = (PACKET *)xcalloc(1, sizeof *pkt);
741 werner 36 gpg_init_packet (pkt);
742     while (!quit && (rc = gpg_parse_packet (inp, pkt)) != -1) {
743     switch (pkt->pkttype) {
744     case PKT_PUBKEY_ENC:
745 twoaday 179 enc = pkt->pkt.pubkey_enc;
746 werner 36 if (!enc)
747     break;
748 twoaday 193 l = (gpgme_recipient_t)xcalloc (1, sizeof *l);
749     l->keyid = (char*)xcalloc (1, 16+1);
750 werner 36 _snprintf (l->keyid, 16, "%08lX%08lX", enc->keyid[0], enc->keyid[1]);
751 twoaday 179 l->pubkey_algo = (gpgme_pubkey_algo_t)enc->pubkey_algo;
752 werner 36 l->status = 0;
753     l->next = (*r_list);
754     *r_list = l;
755 twoaday 179 break;
756 werner 36
757     case PKT_ENCRYPTED:
758     case PKT_ENCRYPTED_MDC:
759     case PKT_COMPRESSED:
760     case PKT_PUBLIC_KEY:
761     case PKT_SECRET_KEY:
762     quit = 1;
763     break;
764 twoaday 181
765 twoaday 180 default:
766     break;
767 werner 36 }
768     gpg_free_packet (pkt);
769     gpg_init_packet (pkt);
770     }
771     gpg_iobuf_close (inp);
772     safe_free (pkt);
773     return 0;
774     }
775 twoaday 179
776    
777     /* Either extract the list of recipients from the file @file or
778     if the string is NULL, try to extract them from the clipboard.
779     Return value: 0 on success. */
780     gpgme_error_t
781     gpg_get_recipients (const char *file, gpgme_recipient_t *r_list)
782     {
783     gpgme_error_t err;
784     char tmp[MAX_PATH+1];
785    
786     if (!file) {
787     clip_store_data (tmp, DIM (tmp)-2);
788     err = file_extract_recipient (tmp, r_list);
789     DeleteFile (tmp);
790     }
791     else
792     err = file_extract_recipient (file, r_list);
793     return err;
794     }
795 twoaday 181
796    
797     /* Try to find a subpacket with the given id @subpktid
798     inside the key @key.
799     Return value: 0 on success. */
800     gpgme_error_t
801     gpg_find_key_subpacket (const char *key, int subpktid,
802     char **value)
803     {
804     gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
805     const char *fmt;
806     const char *spk;
807     char *p, *cmd;
808     HANDLE out;
809    
810     *value = NULL;
811     p = read_gpg_program ();
812     fmt = "%s --with-colons --list-options show-sig-subpackets=%d --list-sigs %s";
813 twoaday 193 cmd = (char*)xcalloc (1, strlen (fmt) + strlen (p) + strlen (key) + 32 + 1);
814 twoaday 181 sprintf (cmd, fmt, p, subpktid, key);
815    
816     out = create_tmpfile ("gpg_subpackets");
817     if (create_process (cmd, NULL, out, NULL))
818     err = gpg_error (GPG_ERR_INTERNAL);
819    
820     free (p);
821     free (cmd);
822    
823     p = map_tmpfile (out, NULL);
824     if (p && (spk=strstr (p, "spk"))) {
825     char *end = strstr (spk, "\n");
826     if (end) {
827 twoaday 193 *value = (char*)xcalloc (1, (end-spk)+1);
828 twoaday 181 memcpy (*value, spk, (end-spk)-1);
829     }
830     }
831    
832     free (p);
833     CloseHandle (out);
834     return err;
835     }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26