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

Annotation of /trunk/Src/wptGPGUtil.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 181 - (hide annotations)
Tue Mar 14 11:01:22 2006 UTC (18 years, 11 months ago) by twoaday
File size: 21131 byte(s)
2006-03-12  Timo Schulz  <ts@g10code.de>
 
        * wptGPG.cpp (gnupg_load_config): Search for 'ask-cert-expire'.
        * wptKeyPropsDlg.cpp (display_key_info): Automatically update
        sym algorithm preferences if needed.
        * wptKeysignDlg.cpp (date_is_today): New.
        (keysign_dlg_proc): Only allow to set cert expire date if
        the option was found.
        * wptGPGPrefsDlg.cpp (gpgprefs_dlg_proc): Allow to set
        'ask-cert-expire'.
         


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26