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

Annotation of /trunk/Src/wptGPGUtil.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 278 - (hide annotations)
Mon Jan 15 22:02:04 2007 UTC (18 years, 1 month ago) by twoaday
File size: 19373 byte(s)
See ChangeLog.


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

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26