25 |
#include <windows.h> |
#include <windows.h> |
26 |
#include <stdio.h> |
#include <stdio.h> |
27 |
#include <string.h> |
#include <string.h> |
|
#include <malloc.h> |
|
28 |
#include <ctype.h> |
#include <ctype.h> |
29 |
#include <assert.h> |
#include <assert.h> |
30 |
#include <gpgme.h> |
#include <gpgme.h> |
42 |
#include "wptUTF8.h" |
#include "wptUTF8.h" |
43 |
|
|
44 |
|
|
45 |
|
gpgme_error_t parse_keyserver_url (char **r_keyserver, unsigned short *r_port); |
46 |
|
|
47 |
/* Attribute list which holds the image data. */ |
/* Attribute list which holds the image data. */ |
48 |
struct attr_list_s { |
struct attr_list_s { |
49 |
struct attr_list_s *next; |
struct attr_list_s *next; |
55 |
typedef struct attr_list_s *attr_list_t; |
typedef struct attr_list_s *attr_list_t; |
56 |
|
|
57 |
|
|
58 |
|
/* XXX: convert it to an inline function and place it in a header file. */ |
59 |
|
static unsigned char* |
60 |
|
safe_uchar_alloc (size_t n) |
61 |
|
{ |
62 |
|
unsigned char *p = new unsigned char[n]; |
63 |
|
if (!p) |
64 |
|
BUG (0); |
65 |
|
return p; |
66 |
|
} |
67 |
|
|
68 |
|
|
69 |
/* Free attribute list @ctx. */ |
/* Free attribute list @ctx. */ |
70 |
void |
void |
71 |
free_attr_list (attr_list_t ctx) |
free_attr_list (attr_list_t ctx) |
72 |
{ |
{ |
73 |
attr_list_t n; |
attr_list_t n; |
74 |
|
|
75 |
while (ctx) { |
while (ctx) { |
76 |
n = ctx->next; |
n = ctx->next; |
77 |
safe_free (ctx->fpr); |
free_if_alloc (ctx->fpr); |
78 |
safe_free (ctx->d); |
free_if_alloc (ctx->d); |
79 |
|
free_if_alloc (ctx); |
80 |
ctx = n; |
ctx = n; |
81 |
} |
} |
82 |
} |
} |
100 |
continue; |
continue; |
101 |
buffer = buf+9+10; |
buffer = buf+9+10; |
102 |
pos = 0; |
pos = 0; |
103 |
c = (attr_list_t)calloc (1, sizeof *c); |
c = new attr_list_s; |
104 |
if (!c) |
if (!c) |
105 |
BUG (0); |
BUG (0); |
106 |
|
memset (c, 0, sizeof *c); |
107 |
|
|
108 |
p = strtok (buffer, " "); |
p = strtok (buffer, " "); |
109 |
while (p != NULL) { |
while (p != NULL) { |
110 |
switch (pos) { |
switch (pos) { |
111 |
case 0: |
case 0: |
112 |
c->fpr = strdup (p); |
c->fpr = m_strdup (p); |
113 |
break; |
break; |
114 |
|
|
115 |
case 1: |
case 1: |
133 |
; |
; |
134 |
t->next = c; |
t->next = c; |
135 |
} |
} |
136 |
c->d = (unsigned char*)malloc (c->octets); |
c->d = safe_uchar_alloc (c->octets); |
|
if (!c->d) |
|
|
BUG (0); |
|
137 |
memcpy (c->d, data, c->octets); |
memcpy (c->d, data, c->octets); |
138 |
data += c->octets; |
data += c->octets; |
139 |
datlen -= c->octets; |
datlen -= c->octets; |
212 |
goto next; |
goto next; |
213 |
c->gloflags.is_protected = sk->is_protected; |
c->gloflags.is_protected = sk->is_protected; |
214 |
c->gloflags.divert_to_card = sk->protect.s2k.mode==1002? 1 : 0; |
c->gloflags.divert_to_card = sk->protect.s2k.mode==1002? 1 : 0; |
215 |
if (c->pubpart != NULL) { |
if (c->pubpart != NULL) { |
216 |
c->pubpart->gloflags.is_protected = sk->is_protected; |
c->pubpart->gloflags.is_protected = sk->is_protected; |
217 |
c->pubpart->gloflags.divert_to_card = sk->protect.s2k.mode==1002? 1 : 0; |
c->pubpart->gloflags.divert_to_card = sk->protect.s2k.mode==1002? 1 : 0; |
218 |
} |
} |
219 |
} |
} |
237 |
gpg_keycache_find_key2 (ctx, fpr, 0, &key, &fnd); |
gpg_keycache_find_key2 (ctx, fpr, 0, &key, &fnd); |
238 |
if (!fnd) |
if (!fnd) |
239 |
return gpg_error (GPG_ERR_NOT_FOUND); |
return gpg_error (GPG_ERR_NOT_FOUND); |
240 |
safe_free (fnd->attrib.d); |
free_if_alloc (fnd->attrib.d); |
241 |
fnd->attrib.flags = dat->flags; |
fnd->attrib.flags = dat->flags; |
242 |
fnd->attrib.len = dat->octets; |
fnd->attrib.len = dat->octets; |
243 |
fnd->attrib.d = (unsigned char*)malloc (dat->octets); |
fnd->attrib.d = safe_uchar_alloc (dat->octets); |
|
if (!fnd->attrib.d) |
|
|
BUG (0); |
|
244 |
memcpy (fnd->attrib.d, dat->d, dat->octets); |
memcpy (fnd->attrib.d, dat->d, dat->octets); |
245 |
return 0; |
return 0; |
246 |
} |
} |
266 |
} |
} |
267 |
|
|
268 |
|
|
269 |
static void |
void |
270 |
keycache_decode_uid (struct keycache_s *ctx) |
keycache_decode_uid (struct keycache_s *ctx) |
271 |
{ |
{ |
272 |
gpgme_user_id_t u; |
gpgme_user_id_t u; |
273 |
struct native_uid_s *n, *t; |
struct native_uid_s *n, *t; |
274 |
|
|
275 |
for (u = ctx->key->uids; u; u = u->next) { |
for (u = ctx->key->uids; u; u = u->next) { |
276 |
n = (struct native_uid_s*)calloc (1, sizeof *n); |
n = new native_uid_s; |
277 |
if (!n) |
if (!n) |
278 |
BUG (0); |
BUG (0); |
279 |
|
memset (n, 0, sizeof *n); |
280 |
if (is_8bit_string (u->uid)) { |
if (is_8bit_string (u->uid)) { |
281 |
n->malloced = 1; |
n->malloced = 1; |
282 |
n->uid = utf8_to_native (u->uid); |
n->uid = utf8_to_native (u->uid); |
283 |
if (u->name != NULL) |
if (u->name != NULL) |
284 |
n->name = utf8_to_native (u->name); |
n->name = utf8_to_native (u->name); |
285 |
if (u->email != NULL) |
if (u->email != NULL) |
286 |
n->email = strdup (u->email); |
n->email = m_strdup (u->email); |
287 |
if (u->comment != NULL) |
if (u->comment != NULL) |
288 |
n->comment = utf8_to_native (u->comment); |
n->comment = utf8_to_native (u->comment); |
289 |
} |
} |
328 |
while (n != NULL) { |
while (n != NULL) { |
329 |
t = n->next; |
t = n->next; |
330 |
if (n->malloced) { |
if (n->malloced) { |
331 |
safe_free (n->uid); |
free_if_alloc (n->uid); |
332 |
safe_free (n->name); |
free_if_alloc (n->name); |
333 |
safe_free (n->comment); |
free_if_alloc (n->comment); |
334 |
safe_free (n->email); |
free_if_alloc (n->email); |
|
safe_free (n->uid); |
|
335 |
} |
} |
336 |
safe_free (n); |
free_if_alloc (n); |
337 |
n = t; |
n = t; |
338 |
} |
} |
339 |
*r_n = NULL; |
*r_n = NULL; |
351 |
gpg_iobuf_t inp; |
gpg_iobuf_t inp; |
352 |
PACKET *pkt; |
PACKET *pkt; |
353 |
struct keycache_s *c; |
struct keycache_s *c; |
354 |
const byte *sym_prefs; |
const BYTE *sym_prefs; |
355 |
char keyid[16+1]; |
char keyid[16+1]; |
356 |
int key_seen = 0; |
int key_seen = 0; |
357 |
size_t nsym =0; |
size_t nsym =0; |
389 |
c->gloflags.has_desig_rev = 1; |
c->gloflags.has_desig_rev = 1; |
390 |
} |
} |
391 |
if (pkt->pkttype == PKT_SIGNATURE && key_seen == 1 && c != NULL) { |
if (pkt->pkttype == PKT_SIGNATURE && key_seen == 1 && c != NULL) { |
|
if (c->sym_prefs) /* only use the prefs from the primary uid. */ |
|
|
goto next; |
|
392 |
sym_prefs = gpg_parse_sig_subpkt (pkt->pkt.signature->hashed, |
sym_prefs = gpg_parse_sig_subpkt (pkt->pkt.signature->hashed, |
393 |
SIGSUBPKT_PREF_SYM, &nsym); |
SIGSUBPKT_PREF_SYM, &nsym); |
394 |
if (!sym_prefs) |
if (!sym_prefs) |
398 |
if (kid && strcmp (kid, keyid) != 0) |
if (kid && strcmp (kid, keyid) != 0) |
399 |
goto next; |
goto next; |
400 |
err = gpg_keycache_find_key2 (ctx, keyid, 0, &key, &c); |
err = gpg_keycache_find_key2 (ctx, keyid, 0, &key, &c); |
401 |
if (err) |
if (err || !c) |
402 |
|
goto next; |
403 |
|
if (c->sym_prefs) // only use the prefs from the primary uid. |
404 |
goto next; |
goto next; |
405 |
else if (nsym > 0) { |
else if (nsym > 0) { |
406 |
c->sym_prefs = (unsigned char*)calloc (1, nsym+1); |
c->sym_prefs = safe_uchar_alloc (nsym+1); |
407 |
if (!c->sym_prefs) |
memset (c->sym_prefs, 0, nsym+1); |
|
BUG (0); |
|
408 |
memcpy (c->sym_prefs, sym_prefs, nsym); |
memcpy (c->sym_prefs, sym_prefs, nsym); |
409 |
} |
} |
410 |
} |
} |
444 |
|
|
445 |
if (!r_ctx) |
if (!r_ctx) |
446 |
return gpg_error (GPG_ERR_INV_ARG); |
return gpg_error (GPG_ERR_INV_ARG); |
447 |
ctx = (gpg_keycache_t)calloc (1, sizeof *ctx); |
ctx = new gpg_keycache_s; |
448 |
if (!ctx) |
if (!ctx) |
449 |
BUG (0); |
BUG (0); |
450 |
|
memset (ctx, 0, sizeof *ctx); |
451 |
ctx->secret = 0; |
ctx->secret = 0; |
452 |
ctx->pos = 0; |
ctx->pos = 0; |
453 |
*r_ctx = ctx; |
*r_ctx = ctx; |
455 |
} |
} |
456 |
|
|
457 |
|
|
458 |
|
void |
459 |
|
gpg_keycache_item_release (struct keycache_s *c) |
460 |
|
{ |
461 |
|
if (c->key) |
462 |
|
gpgme_key_release (c->key); |
463 |
|
c->key = NULL; |
464 |
|
if (c->rev != NULL) |
465 |
|
gpg_desig_rev_release (c->rev); |
466 |
|
c->rev = NULL; |
467 |
|
free_if_alloc (c->pref_keyserver); |
468 |
|
free_if_alloc (c->sym_prefs); |
469 |
|
free_if_alloc (c->attrib.d); |
470 |
|
free_if_alloc (c->card_type); |
471 |
|
free_native_uids (&c->uids); |
472 |
|
free_if_alloc (c); |
473 |
|
} |
474 |
|
|
475 |
|
|
476 |
/* Release keycache object @ctx. */ |
/* Release keycache object @ctx. */ |
477 |
void |
void |
478 |
gpg_keycache_release (gpg_keycache_t ctx) |
gpg_keycache_release (gpg_keycache_t ctx) |
484 |
|
|
485 |
for (c = ctx->item; c; c = c2) { |
for (c = ctx->item; c; c = c2) { |
486 |
c2 = c->next; |
c2 = c->next; |
487 |
gpgme_key_release (c->key); |
gpg_keycache_item_release (c); |
|
c->key = NULL; |
|
|
if (c->rev != NULL) |
|
|
gpg_desig_rev_release (c->rev); |
|
|
c->rev = NULL; |
|
|
safe_free (c->pref_keyserver); |
|
|
safe_free (c->sym_prefs); |
|
|
safe_free (c->attrib.d); |
|
|
safe_free (c->card_type); |
|
|
free_native_uids (&c->uids); |
|
|
safe_free (c); |
|
488 |
} |
} |
489 |
safe_free (ctx); |
free_if_alloc (ctx); |
490 |
} |
} |
491 |
|
|
492 |
|
|
518 |
if (!ctx) |
if (!ctx) |
519 |
return gpg_error (GPG_ERR_INV_ARG); |
return gpg_error (GPG_ERR_INV_ARG); |
520 |
|
|
521 |
c = (struct keycache_s*)calloc (1, sizeof *c); |
c = new keycache_s; |
522 |
if (!c) |
if (!c) |
523 |
BUG (0); |
BUG (0); |
524 |
|
memset (c, 0, sizeof *c); |
525 |
c->gloflags.is_protected = 1; /*default: assume protection. */ |
c->gloflags.is_protected = 1; /*default: assume protection. */ |
526 |
c->key = key; |
c->key = key; |
527 |
if (!ctx->item) |
if (!ctx->item) |
635 |
if (c->flags != 0) { |
if (c->flags != 0) { |
636 |
*r_status = c->flags; |
*r_status = c->flags; |
637 |
*r_obj = c; |
*r_obj = c; |
638 |
c->flags = 0; |
c->flags = 0; /* reset update flag. */ |
639 |
return 0; |
return 0; |
640 |
} |
} |
641 |
} |
} |
643 |
} |
} |
644 |
|
|
645 |
|
|
646 |
|
/* Helper to retrieve a GPG key. */ |
647 |
|
static gpgme_error_t |
648 |
|
get_gpg_key (const char *keyid, int is_sec, gpgme_key_t *r_key) |
649 |
|
{ |
650 |
|
gpgme_ctx_t ctx; |
651 |
|
gpgme_error_t err; |
652 |
|
|
653 |
|
err = gpgme_new (&ctx); |
654 |
|
if (err) |
655 |
|
return err; |
656 |
|
gpgme_set_keylist_mode (ctx, GPGME_KEYLIST_MODE_SIGS); |
657 |
|
err = gpgme_get_key (ctx, keyid, r_key, is_sec); |
658 |
|
gpgme_release (ctx); |
659 |
|
return err; |
660 |
|
} |
661 |
|
|
662 |
|
|
663 |
|
/* Fetch a key directly from gpg but without adding |
664 |
|
it to the key cache. Caller must free @r_ctx. */ |
665 |
|
gpgme_error_t |
666 |
|
gpg_keycache_fetch_key (const char *keyid, int is_sec, |
667 |
|
gpgme_key_t *r_key, struct keycache_s **r_c) |
668 |
|
{ |
669 |
|
gpgme_error_t err; |
670 |
|
gpgme_key_t key; |
671 |
|
struct keycache_s *c; |
672 |
|
|
673 |
|
*r_key = NULL; |
674 |
|
*r_c = NULL; |
675 |
|
err = get_gpg_key (keyid, is_sec, &key); |
676 |
|
if (err) |
677 |
|
return err; |
678 |
|
|
679 |
|
c = new keycache_s; |
680 |
|
if (!c) |
681 |
|
BUG (0); |
682 |
|
memset (c, 0, sizeof *c); |
683 |
|
c->gloflags.is_protected = 1; /*default: assume protection. */ |
684 |
|
c->key = key; |
685 |
|
keycache_decode_uid (c); |
686 |
|
*r_key = key; |
687 |
|
*r_c = c; |
688 |
|
return 0; |
689 |
|
} |
690 |
|
|
691 |
|
|
692 |
|
/* Update the key with the keyid @key in the key cache. |
693 |
|
If the key does not exist, it is added otherwise all |
694 |
|
parts are first freed and then replaced with the updated data. */ |
695 |
gpgme_error_t |
gpgme_error_t |
696 |
gpg_keycache_update_key (gpg_keycache_t ctx, int is_sec, |
gpg_keycache_update_key (gpg_keycache_t ctx, int is_sec, |
697 |
void *opaque, const char *keyid) |
void *opaque, const char *keyid) |
698 |
{ |
{ |
|
struct keycache_s *c = NULL, *c_new=NULL; |
|
699 |
gpgme_key_t key=NULL, fndkey=NULL; |
gpgme_key_t key=NULL, fndkey=NULL; |
700 |
gpgme_error_t err; |
gpgme_error_t err; |
701 |
gpgme_ctx_t gctx; |
struct keycache_s *c = NULL, *c_new=NULL; |
702 |
gpg_keycache_t pub = (gpg_keycache_t)opaque; |
gpg_keycache_t pub = (gpg_keycache_t)opaque; |
703 |
|
|
704 |
err = gpgme_new (&gctx); |
err = get_gpg_key (keyid, is_sec, &key); |
|
if (err) |
|
|
return err; |
|
|
gpgme_set_keylist_mode (gctx, GPGME_KEYLIST_MODE_SIGS/*|GPGME_KEYLIST_MODE_SIG_NOTATIONS*/); |
|
|
err = gpgme_get_key (gctx, keyid, &key, is_sec); |
|
|
gpgme_release (gctx); |
|
705 |
if (err) |
if (err) |
706 |
return err; |
return err; |
707 |
err = gpg_keycache_find_key2 (ctx, keyid, 0, &fndkey, &c); |
err = gpg_keycache_find_key2 (ctx, keyid, 0, &fndkey, &c); |
732 |
c->gloflags.divert_to_card = c_new->gloflags.divert_to_card; |
c->gloflags.divert_to_card = c_new->gloflags.divert_to_card; |
733 |
} |
} |
734 |
} |
} |
735 |
if (c) |
if (c != NULL) |
736 |
c->flags = KC_FLAG_ADD; |
c->flags = KC_FLAG_ADD; |
|
|
|
737 |
} |
} |
738 |
|
|
739 |
/* refresh utf8 user ID list. */ |
/* refresh utf8 user ID list. */ |
740 |
if (c != NULL) { |
if (c != NULL && c->key) { |
741 |
free_native_uids (&c->uids); |
free_native_uids (&c->uids); |
742 |
keycache_decode_uid (c); |
keycache_decode_uid (c); |
743 |
} |
} |
763 |
|
|
764 |
c = ctx->item; |
c = ctx->item; |
765 |
if (c->next == NULL) { |
if (c->next == NULL) { |
766 |
gpgme_key_release (itm->key); |
if (itm->key) |
767 |
safe_free (itm); |
gpgme_key_release (itm->key); |
768 |
ctx->item = NULL; |
itm->key = NULL; |
769 |
|
free_if_alloc (itm); |
770 |
} |
} |
771 |
else { |
else { |
772 |
for (; c != NULL; c = c->next) { |
for (; c != NULL; c = c->next) { |
775 |
} |
} |
776 |
assert (c != NULL); /* XXX: sometimes access violation. */ |
assert (c != NULL); /* XXX: sometimes access violation. */ |
777 |
c->next = c->next->next; |
c->next = c->next->next; |
778 |
gpgme_key_release (itm->key); |
if (itm->key) |
779 |
safe_free (itm); |
gpgme_key_release (itm->key); |
780 |
|
itm->key = NULL; |
781 |
|
free_if_alloc (itm); |
782 |
} |
} |
783 |
return 0; |
return 0; |
784 |
} |
} |
803 |
return err; |
return err; |
804 |
|
|
805 |
/* XXX: GPGME_KEYLIST_MODE_SIG_NOTATIONS causes an internal error! */ |
/* XXX: GPGME_KEYLIST_MODE_SIG_NOTATIONS causes an internal error! */ |
806 |
gpgme_set_keylist_mode (c, GPGME_KEYLIST_MODE_SIGS/*|GPGME_KEYLIST_MODE_SIG_NOTATIONS*/); |
gpgme_set_keylist_mode (c, GPGME_KEYLIST_MODE_SIGS); |
807 |
err = gpgme_op_keylist_start (c, pattern, secret); |
err = gpgme_op_keylist_start (c, pattern, secret); |
808 |
while(!err) { |
while(!err) { |
809 |
err = gpgme_op_keylist_next (c, &key); |
err = gpgme_op_keylist_next (c, &key); |
817 |
err = gpg_error (GPG_ERR_NO_ERROR); |
err = gpg_error (GPG_ERR_NO_ERROR); |
818 |
keycache_update_photos (ctx); |
keycache_update_photos (ctx); |
819 |
keycache_decode_uids (ctx); |
keycache_decode_uids (ctx); |
|
/* XXX: make sure the progress dialog is closed. */ |
|
820 |
gpgme_op_keylist_end (c); |
gpgme_op_keylist_end (c); |
821 |
gpgme_release (c); |
gpgme_release (c); |
822 |
return err; |
return err; |
823 |
} |
} |
824 |
|
|
825 |
|
|
826 |
/* XXX: kludge to see if the key is stored on a card. */ |
/* Return 1 if we can assume that the actual private key is |
827 |
|
stored on a smart card. This is not bullet proof, but the |
828 |
|
card provides 3 keys (RSA) and each key for a different purpose. */ |
829 |
static int |
static int |
830 |
key_divert_to_card (gpgme_key_t key) |
key_divert_to_card (gpgme_key_t key) |
831 |
{ |
{ |
832 |
gpgme_subkey_t k; |
gpgme_subkey_t k; |
833 |
int n=0, n_alg=0, can_auth = 0; |
int n=0, n_alg=0; |
834 |
|
int can_auth = 0, can_encr = 0; |
835 |
|
|
836 |
for (k = key->subkeys; k; k = k->next) { |
for (k = key->subkeys; k; k = k->next) { |
837 |
n++; |
n++; |
839 |
n_alg++; |
n_alg++; |
840 |
if (k->can_authenticate) |
if (k->can_authenticate) |
841 |
can_auth++; |
can_auth++; |
842 |
|
if (k->can_encrypt) |
843 |
|
can_encr++; |
844 |
} |
} |
845 |
if (n == 3 && n_alg == 3 && can_auth == 1) |
if (n == 3 && n_alg == 3 && can_auth == 1 && can_encr == 1) |
846 |
return 1; |
return 1; |
847 |
return 0; |
return 0; |
848 |
} |
} |
856 |
|
|
857 |
while (prefs[pos] != 0) |
while (prefs[pos] != 0) |
858 |
pos++; |
pos++; |
859 |
p = (unsigned char*)calloc (1, pos+1); |
p = safe_uchar_alloc (pos+1); |
860 |
if (!p) |
memset (p, 0, pos+1); |
|
BUG (0); |
|
861 |
memcpy (p, prefs, pos); |
memcpy (p, prefs, pos); |
862 |
return p; |
return p; |
863 |
} |
} |
864 |
|
|
865 |
|
|
866 |
|
/* Sync the secret and the public key cache information. */ |
867 |
gpgme_error_t |
gpgme_error_t |
868 |
gpg_keycache_sync (gpg_keycache_t pub, gpg_keycache_t sec) |
gpg_keycache_sync (gpg_keycache_t pub, gpg_keycache_t sec) |
869 |
{ |
{ |
873 |
if (!pub || !sec) |
if (!pub || !sec) |
874 |
return gpg_error (GPG_ERR_INV_ARG); |
return gpg_error (GPG_ERR_INV_ARG); |
875 |
|
|
876 |
for (c=sec->item; c; c=c->next) { |
for (c=sec->item; c; c=c->next) { |
877 |
if (!gpg_keycache_find_key2 (pub, c->key->subkeys->keyid, 0, &key, &c_sec)) { |
if (!gpg_keycache_find_key2 (pub, c->key->subkeys->keyid, 0, |
878 |
|
&key, &c_sec)) { |
879 |
c_sec->gloflags.is_protected = c->gloflags.is_protected; |
c_sec->gloflags.is_protected = c->gloflags.is_protected; |
880 |
c_sec->gloflags.divert_to_card = c->gloflags.divert_to_card; |
c_sec->gloflags.divert_to_card = c->gloflags.divert_to_card; |
881 |
if (!c->gloflags.divert_to_card) |
if (!c->gloflags.divert_to_card) |
932 |
} |
} |
933 |
if (ctx->tmp->flags != 0) |
if (ctx->tmp->flags != 0) |
934 |
ctx->tmp->flags = 0; /* reset the 'updated' status. */ |
ctx->tmp->flags = 0; /* reset the 'updated' status. */ |
935 |
|
|
936 |
/* it might be possible there is no public key. */ |
/* it might be possible there is no public key. */ |
937 |
if (flags && ctx->tmp->pubpart == NULL) |
if (flags && ctx->tmp->pubpart == NULL) |
938 |
flags = 0; |
flags = 0; |
939 |
*r_key = flags? ctx->tmp->pubpart->key : ctx->tmp->key; |
*r_key = flags? ctx->tmp->pubpart->key : ctx->tmp->key; |
940 |
*c = ctx->tmp; |
*c = ctx->tmp; |
941 |
ctx->tmp = ctx->tmp->next; |
ctx->tmp = ctx->tmp->next; |
942 |
ctx->pos++; |
ctx->pos++; |
943 |
|
|
944 |
return 0; |
return 0; |
958 |
return err; |
return err; |
959 |
} |
} |
960 |
|
|
961 |
|
|
962 |
gpgme_error_t |
gpgme_error_t |
963 |
gpg_keycache_next_key2 (gpg_keycache_t ctx, int flags, |
gpg_keycache_next_key2 (gpg_keycache_t ctx, int flags, |
964 |
struct keycache_s **c, gpgme_key_t *r_key) |
struct keycache_s **c, gpgme_key_t *r_key) |
1014 |
char **out, WORD *outlen) |
char **out, WORD *outlen) |
1015 |
{ |
{ |
1016 |
char tmp[128], *val; |
char tmp[128], *val; |
1017 |
char *enc = NULL; |
char *enc = NULL; |
1018 |
size_t pos = 0, i=0; |
size_t pos = 0; |
1019 |
|
|
1020 |
/* example: spk:24:1:21:http%3A//subkeys.pgp.de */ |
/* example: spk:24:1:21:http%3A//subkeys.pgp.de */ |
1021 |
*outlen = 0; |
*outlen = 0; |
1024 |
if (strncmp (subpkt_data, "spk:", 4)) |
if (strncmp (subpkt_data, "spk:", 4)) |
1025 |
return gpg_error (GPG_ERR_NO_DATA); |
return gpg_error (GPG_ERR_NO_DATA); |
1026 |
|
|
1027 |
strncpy (tmp, subpkt_data, 62); |
/* XXX: do not use static buffer sizes. */ |
1028 |
|
strncpy (tmp, subpkt_data, DIM (tmp)-4); |
1029 |
val = strtok (tmp, ":"); |
val = strtok (tmp, ":"); |
1030 |
while (val != NULL) { |
while (val != NULL) { |
1031 |
switch (pos++) { |
switch (pos++) { |
1045 |
break; |
break; |
1046 |
|
|
1047 |
case 4: |
case 4: |
1048 |
enc = strdup (val); |
enc = m_strdup (val); |
1049 |
break; |
break; |
1050 |
} |
} |
1051 |
val = strtok (NULL, ":"); |
val = strtok (NULL, ":"); |
1052 |
} |
} |
1053 |
if (!enc) |
if (!enc) |
1054 |
return gpg_error (GPG_ERR_NO_DATA);; |
return gpg_error (GPG_ERR_NO_DATA); |
1055 |
*out = (char*)calloc (1, strlen (enc)+1); |
unhexify_buffer (enc, out); |
1056 |
if (!*out) |
free_if_alloc (enc); |
|
BUG (0); |
|
|
for (pos = 0; pos < strlen (enc); pos++) { |
|
|
if (enc[pos] == '%' && enc[pos+1] == '%') |
|
|
(*out)[i++] = '%'; |
|
|
else if (enc[pos] == '%') { |
|
|
char temp[3]; |
|
|
temp[0] = enc[++pos]; |
|
|
temp[1] = enc[++pos]; |
|
|
temp[2] = 0; |
|
|
(*out)[i++] = (char)strtoul (temp, NULL, 16); |
|
|
} |
|
|
else |
|
|
(*out)[i++] = enc[pos]; |
|
|
} |
|
|
(*out)[i] = 0; |
|
|
safe_free (enc); |
|
1057 |
return 0; |
return 0; |
1058 |
} |
} |
1059 |
|
|
1072 |
case KC_ATTR_PREFSYM: |
case KC_ATTR_PREFSYM: |
1073 |
if (!force && item->sym_prefs) |
if (!force && item->sym_prefs) |
1074 |
break; |
break; |
1075 |
safe_free (item->sym_prefs); |
free_if_alloc (item->sym_prefs); |
1076 |
err = gpg_find_key_subpacket (item->key->subkeys->keyid+8, attr, &val); |
err = gpg_find_key_subpacket (item->key->subkeys->keyid+8, attr, &val); |
1077 |
if (!err && val != NULL) |
if (!err && val != NULL) |
1078 |
err = decode_subpacket (val, NULL, (char**)&item->sym_prefs, &n); |
err = decode_subpacket (val, NULL, (char**)&item->sym_prefs, &n); |
1081 |
case KC_ATTR_PREFKSERV: |
case KC_ATTR_PREFKSERV: |
1082 |
if (!force && item->pref_keyserver) |
if (!force && item->pref_keyserver) |
1083 |
break; |
break; |
1084 |
safe_free (item->pref_keyserver); |
free_if_alloc (item->pref_keyserver); |
1085 |
err = gpg_find_key_subpacket (item->key->subkeys->keyid+8, attr, &val); |
err = gpg_find_key_subpacket (item->key->subkeys->keyid+8, attr, &val); |
1086 |
if (!err && val != NULL) |
if (!err && val != NULL) |
1087 |
err = decode_subpacket (val, NULL, &item->pref_keyserver, &n); |
err = decode_subpacket (val, NULL, &item->pref_keyserver, &n); |
1088 |
|
if (!err && item->pref_keyserver) |
1089 |
|
err = parse_keyserver_url (&item->pref_keyserver, |
1090 |
|
&item->pref_keyserver_port); |
1091 |
break; |
break; |
1092 |
} |
} |
1093 |
safe_free (val); |
safe_free (val); |