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

Contents of /trunk/Src/wptGPGUtil.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 179 - (show annotations)
Fri Feb 24 13:12:26 2006 UTC (19 years ago) by twoaday
File size: 20089 byte(s)
Prepare 0.11.8


1 /* wptGPGUtil.cpp - GPG util functions
2 * Copyright (C) 2005, 2006 Timo Schulz
3 * 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
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <windows.h>
27 #include <sys/stat.h>
28 #include <string.h>
29 #include <errno.h>
30
31 #include "gpgme.h"
32 #include "wptTypes.h"
33 #include "wptErrors.h"
34 #include "wptW32API.h"
35 #include "wptGPG.h"
36 #include "openpgp.h"
37
38
39 #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 BUG (NULL);
164 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 BUG (NULL);
192 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 static char*
209 read_gpg_program (void)
210 {
211 return read_w32_registry (HKEY_CURRENT_USER,
212 "Software\\GNU\\GnuPG", "gpgProgram");
213 }
214
215
216 /* 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 SECURITY_ATTRIBUTES sec_attr;
223 char tmp[300];
224
225 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
230 get_temp_name (tmp, DIM (tmp)-1, name);
231 out = CreateFile (tmp, GENERIC_READ|GENERIC_WRITE,
232 FILE_SHARE_WRITE, &sec_attr,
233 OPEN_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL);
234 if (out == INVALID_HANDLE_VALUE)
235 log_debug ("create_tmpfile: CreateFile failed ec=%d\r\n",
236 (int)GetLastError ());
237 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 if (!CreatePipe (&r, &w, &sec_attr, 4096)) {
256 log_debug ("create_in_pipe: CreatePipeFailed ec=%d\r\n",
257 (int)GetLastError ());
258 return NULL;
259 }
260
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 map_tmpfile (HANDLE out, DWORD *nread)
272 {
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 BUG (NULL);
282 ReadFile (out, p, n, &n, NULL);
283 p[n] = 0;
284 if (nread)
285 *nread = n;
286 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 create_process (const char *cmd, HANDLE in, HANDLE out, HANDLE err)
297 {
298 STARTUPINFO si;
299 PROCESS_INFORMATION pi;
300
301 memset (&si, 0, sizeof (si));
302 si.cb = sizeof si;
303 if (in || out || err)
304 si.dwFlags = STARTF_USESTDHANDLES;
305 if (out)
306 si.hStdOutput = out;
307 if (in)
308 si.hStdInput = in;
309 if (err)
310 si.hStdError = err;
311 si.dwFlags |= STARTF_USESHOWWINDOW;
312 si.wShowWindow = SW_HIDE;
313 if (!CreateProcess (NULL, (char*)cmd, NULL, NULL, TRUE, 0,
314 NULL, NULL, &si, &pi)) {
315 log_debug ("create_process: CreateProcess failed ec=%d\r\n",
316 (int)GetLastError ());
317 return -1;
318 }
319 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 p = read_gpg_program ();
336 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 BUG (NULL);
342 sprintf (cmd, "%s --yes --output \"%s\" --export-secret-key %s",
343 p, outfile, keyid);
344 if (create_process (cmd, NULL, NULL, NULL))
345 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 /* If @export is 1, export the ownertrust data to the
357 buffer @data. Otherwise import the ownertrust data from @data.
358 Return value: 0 on success. */
359 gpgme_error_t
360 gpg_manage_ownertrust (char **data, int do_export)
361 {
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 p = read_gpg_program ();
368 if (!p)
369 return gpg_error (GPG_ERR_INV_ARG);
370
371 cmd = (char*)calloc (1, strlen (p) + 64 + 1);
372 if (!cmd)
373 BUG (NULL);
374 sprintf (cmd, "%s %s", p,
375 do_export? "--export-ownertrust" : "--import-ownertrust");
376
377 if (do_export)
378 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 if (create_process (cmd, in, out, NULL))
387 err = gpg_error (GPG_ERR_INTERNAL);
388
389 free (p);
390 free (cmd);
391
392 if (in)
393 CloseHandle (in);
394 if (out) {
395 *data = map_tmpfile (out, NULL);
396 CloseHandle (out);
397 }
398
399 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 p = read_gpg_program ();
413 if (!p)
414 return gpg_error (GPG_ERR_INV_ARG);
415 cmd = (char*)calloc (1, strlen (p) + 64);
416 if (!cmd)
417 BUG (NULL);
418 sprintf (cmd, "%s --logger-fd=1 --rebuild-keydb-caches", p);
419
420 if (r_inf)
421 out = create_tmpfile ("gpg_rebuild_cache");
422
423 if (create_process (cmd, NULL, out, NULL))
424 err = gpg_error (GPG_ERR_INTERNAL);
425
426 if (r_inf)
427 *r_inf = map_tmpfile (out, NULL);
428 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 p = read_gpg_program ();
445 if (!p)
446 return gpg_error (GPG_ERR_INV_ARG);
447 cmd = (char*)calloc (1, strlen (p) + 32);
448 if (!cmd)
449 BUG (NULL);
450 sprintf (cmd, "%s --version", p);
451
452 out = create_tmpfile ("gpg_out");
453 if (create_process (cmd, NULL, out, NULL))
454 err = gpg_error (GPG_ERR_INTERNAL);
455
456 free (p);
457 free (cmd);
458
459 *r_inf = map_tmpfile (out, NULL);
460 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 p = read_gpg_program ();
475 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 BUG (NULL);
481 sprintf (cmd, "%s --fixed-list-mode --with-colons \"%s\"", p, fname);
482
483 out = create_tmpfile ("gpg_keys");
484 if (create_process (cmd, NULL, out, NULL))
485 err = gpg_error (GPG_ERR_INTERNAL);
486
487 free (p);
488 free (cmd);
489
490 *r_out = map_tmpfile (out, NULL);
491 CloseHandle (out);
492 return err;
493 }
494
495
496 char*
497 generate_revoke_input (int code, const char *cmt, const char *pass)
498 {
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 BUG (NULL);
517 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 gpg_revoke_cert (const char *inp_data, const char *keyid, char **r_revcert)
529 {
530 gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
531 char *rcrt;
532 char *cmd, *p;
533 HANDLE in, out;
534
535 p = read_gpg_program ();
536 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 BUG (NULL);
542 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 if (create_process (cmd, in, out, NULL)) {
548 *r_revcert = NULL;
549 err = gpg_error (GPG_ERR_INTERNAL);
550 }
551 else {
552 rcrt = map_tmpfile (out, NULL);
553 *r_revcert = rcrt;
554 if (rcrt && strlen (rcrt) == 0)
555 err = gpg_error (GPG_ERR_BAD_PASSPHRASE);
556 }
557
558 free (p);
559 free (cmd);
560
561 CloseHandle (in);
562 CloseHandle (out);
563 return err;
564 }
565
566
567 /* 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 if (ndata)
581 *ndata = 0;
582 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 /* 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 /* 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 p = read_gpg_program ();
677 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 BUG (NULL);
683 sprintf (cmd, "%s --with-colons --fixed-list-mode --list-keys \"%s\"",
684 p, keyid);
685
686 out = create_tmpfile ("gpg_keys");
687 if (create_process (cmd, NULL, out, NULL))
688 err = gpg_error (GPG_ERR_INTERNAL);
689
690 safe_free (p);
691 safe_free (cmd);
692
693 p = map_tmpfile (out, NULL);
694 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 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 /* Extract all recipients from the file @file.
725 Return value: 0 on success. */
726 static gpgme_error_t
727 file_extract_recipient (const char *file, gpgme_recipient_t *r_list)
728 {
729 PACKET *pkt;
730 PKT_pubkey_enc *enc;
731 gpg_iobuf_t inp = NULL;
732 armor_filter_context_t afx;
733 gpgme_recipient_t l;
734 int rc = 0, quit=0;
735
736 if (!file || !r_list) {
737 log_debug ("do_list_packets: !r_list || !file");
738 return gpgme_error (GPG_ERR_INV_ARG);
739 }
740
741 *r_list=NULL;
742 inp = gpg_iobuf_open (file);
743 if (!inp)
744 return gpgme_err_code_from_errno (errno);
745 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 enc = pkt->pkt.pubkey_enc;
756 if (!enc)
757 break;
758 l = (gpgme_recipient_t)calloc (1, sizeof *l);
759 if (!l)
760 BUG (NULL);
761 l->keyid = (char*)calloc (1, 16+1);
762 _snprintf (l->keyid, 16, "%08lX%08lX", enc->keyid[0], enc->keyid[1]);
763 l->pubkey_algo = (gpgme_pubkey_algo_t)enc->pubkey_algo;
764 l->status = 0;
765 l->next = (*r_list);
766 *r_list = l;
767 break;
768
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 }
777 gpg_free_packet (pkt);
778 gpg_init_packet (pkt);
779 }
780 gpg_iobuf_close (inp);
781 safe_free (pkt);
782 return 0;
783 }
784
785
786 /* Either extract the list of recipients from the file @file or
787 if the string is NULL, try to extract them from the clipboard.
788 Return value: 0 on success. */
789 gpgme_error_t
790 gpg_get_recipients (const char *file, gpgme_recipient_t *r_list)
791 {
792 gpgme_error_t err;
793 char tmp[MAX_PATH+1];
794
795 if (!file) {
796 clip_store_data (tmp, DIM (tmp)-2);
797 err = file_extract_recipient (tmp, r_list);
798 DeleteFile (tmp);
799 }
800 else
801 err = file_extract_recipient (file, r_list);
802 return err;
803 }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26