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

Annotation of /trunk/Src/wptGPGUtil.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 273 - (hide annotations)
Fri Dec 8 10:22:17 2006 UTC (18 years, 2 months ago) by twoaday
File size: 20505 byte(s)


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26