/[winpt]/trunk/MyGPGME/key.c
ViewVC logotype

Contents of /trunk/MyGPGME/key.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 21 - (show annotations)
Wed Jul 27 11:17:44 2005 UTC (19 years, 7 months ago) by twoaday
File MIME type: text/plain
File size: 21962 byte(s)
2005-07-22  Timo Schulz  <twoaday@freakmail.de>
 
        * gpgme.c (_gpgme_add_comment): Forgot to alloc an extra
        byte for the '0'. This fixes a lot of crashes related to
        file operations.
        * keylist.c (gpgme_op_keylist_getkey): Use the param for
        'pub' or 'sec' mode.
        * keycache.c (gpgme_keycache_update_key): If the key is
        not in the cache, add it and if the cache contain secret
        key, sync it with the pub cache.
        * editkey.c (edit_key_colon_handler): Allocate 1 byte for
        the NUL-char.  This also fixes a lot of reported crashes
        related to the showpref feature.
 


1 /* key.c - Key objects
2 * Copyright (C) 2000, 2001 Werner Koch (dd9jn), g10 Code GmbH
3 * Copyright (C) 2001-2005 Timo Schulz
4 *
5 * This file is part of MyGPGME.
6 *
7 * MyGPGME 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 * MyGPGME 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 this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20 */
21
22 #include <stdio.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include <assert.h>
26 #include <time.h>
27 #include <ctype.h>
28
29 #include "util.h"
30 #include "ops.h"
31 #include "key.h"
32
33 static const char *
34 pkalgo_to_string (int algo)
35 {
36 switch (algo) {
37 case 0:
38 case 1:
39 case 2:
40 case 3: return "RSA";
41 case 16:
42 case 17: return "DSA";
43 case 20: return "ELG";
44 default: return "???";
45 }
46 } /* pkalgo_to_string */
47
48
49 static gpgme_error_t
50 key_new (gpgme_key_t *r_key, int secret)
51 {
52 gpgme_key_t key;
53
54 if (r_key)
55 *r_key = NULL;
56 key = calloc (1, sizeof *key);
57 if (!key)
58 return mk_error (Out_Of_Core);
59 key->ref_count = 1;
60 if( r_key )
61 *r_key = key;
62 if( secret )
63 key->secret = 1;
64
65 return 0;
66 } /* key_new */
67
68
69 gpgme_error_t
70 _gpgme_key_new( gpgme_key_t *r_key )
71 {
72 return key_new( r_key, 0 );
73 } /* _gpgme_key_new */
74
75
76 gpgme_error_t
77 _gpgme_key_new_secret( gpgme_key_t *r_key )
78 {
79 return key_new( r_key, 1 );
80 } /* _gpgme_key_new_secret */
81
82
83 void
84 gpgme_key_ref( gpgme_key_t key )
85 {
86 return_if_fail( key );
87 key->ref_count++;
88 } /* gpgme_key_ref */
89
90
91 static struct subkey_s *
92 add_subkey( gpgme_key_t key, int secret )
93 {
94 struct subkey_s *k, *kk;
95
96 k = calloc (1, sizeof *k);
97 if( !k )
98 return NULL;
99
100 kk = key->keys.next;
101 if( !kk )
102 key->keys.next = k;
103 else {
104 while ( kk->next )
105 kk = kk->next;
106 kk->next = k;
107 }
108 if( secret )
109 k->secret = 1;
110 return k;
111 } /* add_subkey */
112
113
114 struct subkey_s *
115 _gpgme_key_add_subkey( gpgme_key_t key )
116 {
117 return add_subkey( key, 0 );
118 } /* _gpgme_key_add_subkey */
119
120
121 struct subkey_s *
122 _gpgme_key_add_secret_subkey( gpgme_key_t key )
123 {
124 return add_subkey( key, 1 );
125 } /* _gpgme_key_add_secret_subkey */
126
127
128 struct signature_s *
129 _gpgme_key_add_signature( gpgme_key_t key )
130 {
131 struct signature_s *s;
132
133 s = calloc( 1, sizeof *s );
134 if( !s )
135 return NULL;
136 s->next = key->sigs;
137 key->sigs = s;
138 return s;
139 } /* _gpgme_key_add_signature */
140
141
142 void
143 gpgme_key_release( gpgme_key_t key )
144 {
145 struct user_id_s *u, *u2;
146 struct subkey_s *k, *k2;
147 struct revoker_key_s *r, *r2;
148 struct signature_s *s, *s2;
149
150 if( key == NULL )
151 return;
152
153 assert( key->ref_count );
154 if( --key->ref_count )
155 return;
156
157 safe_free( key->attrib.d );
158 safe_free( key->keys.fingerprint );
159 for( k = key->keys.next; k; k = k2 ) {
160 k2 = k->next;
161 safe_free( k->fingerprint );
162 safe_free( k );
163 }
164 for( u = key->uids; u; u = u2 ) {
165 u2 = u->next;
166 safe_free (u->hash);
167 safe_free (u);
168 }
169 for( r = key->rvks; r; r = r2 ) {
170 r2 = r->next;
171 safe_free( r );
172 }
173 for( s = key->sigs; s; s = s2 ) {
174 s2 = s->next;
175 safe_free( s->issuer );
176 safe_free( s->user_id );
177 safe_free( s );
178 }
179 safe_free( key );
180 } /* gpgme_key_release */
181
182 void
183 gpgme_key_unref( gpgme_key_t key )
184 {
185 gpgme_key_release( key );
186 }
187
188
189 static char *
190 set_user_id_part (char *tail, const char *buf, size_t len)
191 {
192 while (len && (buf[len-1] == ' ' || buf[len-1] == '\t'))
193 len--;
194 for (; len; len--)
195 *tail++ = *buf++;
196 *tail++ = 0;
197 return tail;
198 }
199
200
201 static void
202 parse_user_id( struct user_id_s *uid, char *tail )
203 {
204 const char *s, *start=NULL;
205 int in_name = 0;
206 int in_email = 0;
207 int in_comment = 0;
208
209 for( s=uid->name; *s; s++ ) {
210 if ( in_email ) {
211 if ( *s == '<' )
212 in_email++; /* not legal but anyway */
213 else if (*s== '>') {
214 if ( !--in_email ) {
215 if (!uid->email_part) {
216 uid->email_part = tail;
217 tail = set_user_id_part ( tail, start, s-start );
218 }
219 }
220 }
221 }
222 else if( in_comment ) {
223 if( *s == '(' )
224 in_comment++;
225 else if (*s== ')') {
226 if ( !--in_comment ) {
227 if (!uid->comment_part) {
228 uid->comment_part = tail;
229 tail = set_user_id_part ( tail, start, s-start );
230 }
231 }
232 }
233 }
234 else if( *s == '<' ) {
235 if( in_name ) {
236 if( !uid->name_part ) {
237 uid->name_part = tail;
238 tail = set_user_id_part (tail, start, s-start );
239 }
240 in_name = 0;
241 }
242 in_email = 1;
243 start = s+1;
244 }
245 else if ( *s == '(' ) {
246 if ( in_name ) {
247 if ( !uid->name_part ) {
248 uid->name_part = tail;
249 tail = set_user_id_part (tail, start, s-start );
250 }
251 in_name = 0;
252 }
253 in_comment = 1;
254 start = s+1;
255 }
256 else if ( !in_name && *s != ' ' && *s != '\t' ) {
257 in_name = 1;
258 start = s;
259 }
260 }
261
262 if( in_name ) {
263 if ( !uid->name_part ) {
264 uid->name_part = tail;
265 tail = set_user_id_part (tail, start, s-start );
266 }
267 }
268
269 /* let unused parts point to an EOS */
270 tail--;
271 if (!uid->name_part)
272 uid->name_part = tail;
273 if (!uid->email_part)
274 uid->email_part = tail;
275 if (!uid->comment_part)
276 uid->comment_part = tail;
277
278 }
279
280
281 /*
282 * Take a name from the --with-colon listing, remove certain escape sequences
283 * sequences and put it into the list of UIDs
284 */
285 gpgme_error_t
286 _gpgme_key_append_name (gpgme_key_t key, const char * s, struct user_id_s ** u)
287 {
288 struct user_id_s *uid, *u1;
289 char *dst;
290
291 assert( key );
292 /* we can malloc a buffer of the same length, because the
293 * converted string will never be larger. Actually we allocate it
294 * twice the size, so that we are able to store the parsed stuff
295 * there too */
296 uid = malloc (sizeof *uid + 2*strlen (s)+3);
297 if (!uid)
298 return mk_error (Out_Of_Core);
299 uid->flags.revoked = 0;
300 uid->flags.invalid = 0;
301 uid->validity = 0;
302 uid->name_part = NULL;
303 uid->email_part = NULL;
304 uid->comment_part = NULL;
305 uid->hash = NULL;
306 uid->next = NULL;
307 dst = uid->name;
308
309 _gpgme_decode_c_string (s, &dst, strlen (s)+1);
310 dst += strlen (s) + 1;
311 parse_user_id (uid, dst);
312
313 if (!key->uids)
314 key->uids = uid;
315 else {
316 for (u1 = key->uids; u1 && u1->next; u1 = u1->next)
317 ;
318 u1->next = uid;
319 }
320 if (u)
321 *u = uid;
322 return 0;
323 }
324
325
326 static const char *
327 capabilities_to_string (struct subkey_s *k)
328 {
329 static char *strings[8] = {
330 "",
331 "c",
332 "s",
333 "sc",
334 "e",
335 "ec",
336 "es",
337 "esc"
338 };
339 return strings[ (!!k->flags.can_encrypt << 2)
340 | (!!k->flags.can_sign << 1)
341 | (!!k->flags.can_certify )];
342 }
343
344 const char *
345 gpgme_key_get_string_attr (gpgme_key_t key, gpgme_attr_t what,
346 void **reserved, int idx)
347 {
348 const char *val = NULL;
349 struct subkey_s * k;
350 struct user_id_s * u;
351 struct revoker_key_s * r;
352 struct signature_s * s;
353 struct mpi_s * m;
354
355 if( !key )
356 return NULL;
357 if( idx < 0 )
358 return NULL;
359
360 switch( what ) {
361 case GPGME_ATTR_KEYID:
362 for (k=&key->keys; k && idx; k=k->next, idx-- )
363 ;
364 if (k)
365 val = k->keyid;
366 break;
367 case GPGME_ATTR_FPR:
368 for (k=&key->keys; k && idx; k=k->next, idx-- )
369 ;
370 if (k)
371 val = k->fingerprint;
372 break;
373 case GPGME_ATTR_ALGO:
374 for (k=&key->keys; k && idx; k=k->next, idx-- )
375 ;
376 if (k)
377 val = pkalgo_to_string (k->key_algo);
378 break;
379 case GPGME_ATTR_LEN:
380 case GPGME_ATTR_CREATED:
381 case GPGME_ATTR_EXPIRE:
382 break; /* use another get function */
383 case GPGME_ATTR_OTRUST:
384 val = "[fixme]";
385 break;
386 case GPGME_ATTR_USERID:
387 for (u=key->uids; u && idx; u=u->next, idx-- )
388 ;
389 val = u? u->name : NULL;
390 break;
391 case GPGME_ATTR_NAME:
392 for (u=key->uids; u && idx; u=u->next, idx-- )
393 ;
394 val = u? u->name_part : NULL;
395 break;
396 case GPGME_ATTR_EMAIL:
397 for (u=key->uids; u && idx; u=u->next, idx-- )
398 ;
399 val = u? u->email_part : NULL;
400 break;
401 case GPGME_ATTR_COMMENT:
402 for( u = key->uids; u && idx; u = u->next, idx-- )
403 ;
404 val = u? u->comment_part : NULL;
405 break;
406 case GPGME_ATTR_VALIDITY:
407 for( u = key->uids; u && idx; u = u->next, idx-- )
408 ;
409 if( u ) {
410 switch( u->validity ) {
411 case GPGME_VALIDITY_UNKNOWN: val = "?"; break;
412 case GPGME_VALIDITY_UNDEFINED: val = "q"; break;
413 case GPGME_VALIDITY_NEVER: val = "n"; break;
414 case GPGME_VALIDITY_MARGINAL: val = "m"; break;
415 case GPGME_VALIDITY_FULL: val = "f"; break;
416 case GPGME_VALIDITY_ULTIMATE: val = "u"; break;
417 }
418 }
419 break;
420
421 case GPGME_ATTR_LEVEL: /* not used here */
422 case GPGME_ATTR_TYPE:
423 case GPGME_ATTR_KEY_REVOKED:
424 case GPGME_ATTR_KEY_INVALID:
425 case GPGME_ATTR_UID_REVOKED:
426 case GPGME_ATTR_UID_INVALID:
427 case GPGME_ATTR_CAN_ENCRYPT:
428 case GPGME_ATTR_CAN_SIGN:
429 case GPGME_ATTR_CAN_CERTIFY:
430 break;
431
432 case GPGME_ATTR_UID_HASH:
433 for (u=key->uids; u && idx; u=u->next, idx--)
434 ;
435 if (u)
436 val = u->hash;
437 break;
438
439 case GPGME_ATTR_IS_SECRET:
440 if( key->secret )
441 val = "1";
442 break;
443
444 case GPGME_ATTR_IS_ULTIMATE:
445 if( key->gloflags.ultimate )
446 val = "1";
447 break;
448
449 case GPGME_ATTR_KEY_CAPS:
450 for( k = &key->keys; k && idx; k = k->next, idx-- )
451 ;
452 if( k )
453 val = capabilities_to_string( k );
454 break;
455
456 case GPGME_ATTR_REVKEY_FPR:
457 for( r = key->rvks; r && idx; r = r->next, idx-- )
458 ;
459 if( r )
460 val = r->fpr;
461 break;
462
463 case GPGME_ATTR_SIG_KEYID:
464 for( s = key->sigs; s && idx; s = s->next, idx-- )
465 ;
466 if( s )
467 val = s->keyid;
468 break;
469
470 case GPGME_ATTR_SIG_ISSUER:
471 for( s = key->sigs; s && idx; s = s->next, idx-- )
472 ;
473 if( s )
474 val = s->issuer;
475 break;
476
477 case GPGME_ATTR_SIG_USERID:
478 for( s = key->sigs; s && idx; s = s->next, idx-- )
479 ;
480 if( s )
481 val = s->user_id;
482
483 case GPGME_ATTR_KEYDAT_VAL:
484 for( m=key->pkey; m && idx; m=m->next, idx-- )
485 ;
486 if (m)
487 val = m->hexval;
488 break;
489
490 case GPGME_ATTR_PHOTO:
491 if( key->attrib.used )
492 val = key->attrib.d;
493 if( reserved )
494 *reserved = (size_t *)key->attrib.len;
495 break;
496
497 case GPGME_ATTR_KEY_SYMPREFS:
498 if( key->sym_prefs )
499 val = key->sym_prefs;
500 break;
501
502 case GPGME_ATTR_KEY_CARDNO:
503 for( k=&key->keys; k && idx; k=k->next, idx-- )
504 ;
505 if (k)
506 val = k->cardno;
507 break;
508 }
509 return val;
510 }
511
512
513 unsigned long
514 gpgme_key_get_ulong_attr (gpgme_key_t key, gpgme_attr_t what,
515 void ** reserved, int idx)
516 {
517 unsigned long val = 0;
518 struct subkey_s * k;
519 struct user_id_s * u;
520 struct revoker_key_s * r;
521 struct signature_s * s;
522 struct mpi_s * m;
523 int n=0;
524
525 if( !key )
526 return 0;
527 if( idx < 0 )
528 return 0;
529
530 switch( what ) {
531 case GPGME_ATTR_ALGO:
532 for (k=&key->keys; k && idx; k=k->next, idx-- )
533 ;
534 if (k)
535 val = (unsigned long)k->key_algo;
536 break;
537 case GPGME_ATTR_LEN:
538 for (k=&key->keys; k && idx; k=k->next, idx-- )
539 ;
540 if (k)
541 val = (unsigned long)k->key_len;
542 break;
543 case GPGME_ATTR_CREATED:
544 for (k=&key->keys; k && idx; k=k->next, idx-- )
545 ;
546 if (k)
547 val = k->timestamp < 0? 0L:(unsigned long)k->timestamp;
548 break;
549 case GPGME_ATTR_VALIDITY:
550 for (u = key->uids; u && idx; u=u->next, idx--)
551 ;
552 if (u)
553 val = u->validity;
554 break;
555
556 case GPGME_ATTR_IS_SECRET:
557 val = !!key->secret;
558 break;
559
560 case GPGME_ATTR_IS_PROTECTED:
561 val = key->gloflags.is_protected;
562 break;
563
564 case GPGME_ATTR_IS_ULTIMATE:
565 val = key->gloflags.ultimate;
566 break;
567
568 case GPGME_ATTR_KEY_EXPIRED:
569 for( k = &key->keys; k && idx; k=k->next, idx-- )
570 ;
571 if( k )
572 val = k->flags.expired;
573 break;
574
575 case GPGME_ATTR_EXPIRES:
576 for( k = &key->keys; k && idx; k=k->next, idx-- )
577 ;
578 if( k )
579 val = k->expires;
580 break;
581
582 case GPGME_ATTR_KEY_REVOKED:
583 for( k = &key->keys; k && idx; k=k->next, idx-- )
584 ;
585 if( k )
586 val = k->flags.revoked;
587 break;
588
589 case GPGME_ATTR_KEY_INVALID:
590 for( k = &key->keys; k && idx; k=k->next, idx-- )
591 ;
592 if( k )
593 val = k->flags.invalid;
594 break;
595
596 case GPGME_ATTR_UID_CREATED:
597 for (u=key->uids; u && idx; u=u->next, idx--)
598 ;
599 if (u)
600 val = u->created;
601 break;
602
603 case GPGME_ATTR_UID_REVOKED:
604 for( u = key->uids; u && idx; u=u->next, idx-- )
605 ;
606 if( u )
607 val = u->flags.revoked;
608 break;
609
610 case GPGME_ATTR_UID_INVALID:
611 for( u =key->uids; u && idx; u=u->next, idx-- )
612 ;
613 if( u )
614 val = u->flags.invalid;
615 break;
616 case GPGME_ATTR_CAN_ENCRYPT:
617 val = key->gloflags.can_encrypt;
618 break;
619
620 case GPGME_ATTR_CAN_SIGN:
621 val = key->gloflags.can_sign;
622 break;
623
624 case GPGME_ATTR_CAN_CERTIFY:
625 val = key->gloflags.can_certify;
626 break;
627
628 case GPGME_ATTR_CAN_AUTH:
629 val = key->gloflags.can_auth;
630 break;
631
632 case GPGME_ATTR_DIVERT_CARD:
633 val = key->gloflags.divert_to_card;
634 break;
635
636 case GPGME_ATTR_OTRUST:
637 val = key->otrust;
638 break;
639
640 case GPGME_ATTR_KEY_VALIDITY:
641 val = key->validity;
642 break;
643
644 case GPGME_ATTR_REVKEY_ALGO:
645 for( r = key->rvks; r && idx; r = r->next, idx-- )
646 ;
647 if( r )
648 val = r->algo;
649 break;
650
651 case GPGME_ATTR_SIG_ALGO:
652 for( s = key->sigs; s && idx; s = s->next, idx-- )
653 ;
654 if( s )
655 val = s->algo;
656 break;
657
658 case GPGME_ATTR_SIG_CREATED:
659 for( s = key->sigs; s && idx; s = s->next, idx-- )
660 ;
661 if( s )
662 val = s->created;
663 break;
664
665 case GPGME_ATTR_SIG_EXPIRES:
666 for( s = key->sigs; s && idx; s = s->next, idx-- )
667 ;
668 if( s )
669 val = s->expires;
670 break;
671
672 case GPGME_ATTR_SIG_CLASS:
673 for( s = key->sigs; s && idx; s = s->next, idx-- )
674 ;
675 if( s )
676 val = s->sigclass;
677 break;
678
679 case GPGME_ATTR_SIG_FLAGS:
680 for (s=key->sigs; s && idx; s=s->next, idx--)
681 ;
682 if (s) {
683 if (s->is_local)
684 val |= GPGME_SIGF_LOCAL;
685 if (s->is_nonrev)
686 val |= GPGME_SIGF_NREV;
687 }
688 break;
689
690 case GPGME_ATTR_SIG_STAT:
691 for( s = key->sigs; s && idx; s = s->next, idx-- )
692 ;
693 if( s )
694 val = s->stat;
695 break;
696
697 case GPGME_ATTR_KEYDAT_NP:
698 for( m = key->pkey; m && idx; m=m->next, idx-- )
699 n++;
700 if( m )
701 val = n;
702 break;
703
704 case GPGME_ATTR_KEYDAT_BITS:
705 for( m = key->pkey; m && idx; m=m->next, idx-- )
706 ;
707 if( m )
708 val = m->bits;
709 break;
710
711 case GPGME_ATTR_KEY_DISABLED:
712 val = key->gloflags.disabled;
713 break;
714
715 case GPGME_ATTR_VERSION: {
716 char *fpr = key->keys.fingerprint;
717 if (!fpr)
718 val = 4;
719 else if (key->keys.key_algo == GPGME_PK_RSA &&
720 strlen (fpr) == 32)
721 val = 3;
722 }
723 break;
724
725 case GPGME_ATTR_KEY_USABLE:
726 n = 4;
727 for (k=&key->keys; k && idx; k=k->next, idx--)
728 ;
729 if (k) {
730 if (!k->flags.revoked)
731 n--;
732 if (!k->flags.expired)
733 n--;
734 if (!k->flags.invalid)
735 n--;
736 if (!key->gloflags.disabled && !k->flags.disabled)
737 n--;
738 }
739 if (n == 0)
740 val = 1;
741 break;
742
743 default:
744 break;
745 }
746 return val;
747 }
748
749
750 const char*
751 gpgme_key_expand_attr (int what, unsigned long attr)
752 {
753 static char tmpbuf[16+1];
754 struct tm *iso_date;
755
756 switch( what ) {
757 case GPGME_ATTR_ALGO:
758 return pkalgo_to_string (attr);
759
760 case GPGME_ATTR_ALGO_SHORT:
761 switch( attr ) {
762 case 17: return "D";
763 case 0:
764 case 1:
765 case 2:
766 case 3: return "R";
767 case 20: return "G";
768 }
769 return "?";
770
771 case GPGME_ATTR_VALIDITY:
772 switch( attr ) {
773 case '?':
774 case GPGME_VALIDITY_UNKNOWN: return "Unknown";
775 case 'r':
776 case GPGME_VALIDITY_REVOKED: return "Revoked";
777 case 'q':
778 case '-':
779 case GPGME_VALIDITY_UNDEFINED: return "Undefined";
780 case 'n':
781 case GPGME_VALIDITY_NEVER: return "Never";
782 case 'm':
783 case GPGME_VALIDITY_MARGINAL: return "Marginal";
784 case 'f':
785 case GPGME_VALIDITY_FULL: return "Full";
786 case 'u':
787 case GPGME_VALIDITY_ULTIMATE: return "Ultimate";
788 }
789 return "???";
790
791 case GPGME_ATTR_CREATED:
792 iso_date = localtime((long*) &attr);
793 _snprintf( tmpbuf, sizeof tmpbuf -1, "%.04d-%.02d-%.02d",
794 iso_date->tm_year+1900,
795 iso_date->tm_mon+1,
796 iso_date->tm_mday );
797 return tmpbuf;
798
799 case GPGME_ATTR_LEN:
800 sprintf( tmpbuf, "%d", attr );
801 return tmpbuf;
802
803 case GPGME_ATTR_KEY_SYMPREFS:
804 switch (attr) {
805 case 0: return "PLAINTEXT";
806 case 1: return "IDEA";
807 case 2: return "3DES";
808 case 3: return "CAST5";
809 case 4: return "BLOWFISH";
810 case 5: return "RESERVED";
811 case 6: return "RESERVED";
812 case 7: return "AES";
813 case 8: return "AES-192";
814 case 9: return "AES-256";
815 }
816 break;
817 }
818 return NULL;
819 } /* gpgme_key_expand_attr */
820
821
822 int
823 gpgme_key_get_cability (gpgme_key_t key, int attr, int keyidx)
824 {
825 struct subkey_s *s;
826
827 if( !key )
828 return 0;
829
830 for ( s = &key->keys; s && keyidx; s=s->next, keyidx-- )
831 ;
832 if (!s)
833 return 0;
834 switch (attr) {
835 case GPGME_ATTR_CAN_ENCRYPT:
836 return s->flags.can_encrypt;
837
838 case GPGME_ATTR_CAN_SIGN:
839 return s->flags.can_sign;
840
841 case GPGME_ATTR_CAN_CERTIFY:
842 return s->flags.can_certify;
843
844 case GPGME_ATTR_CAN_AUTH:
845 return s->flags.can_auth;
846 }
847 return 0;
848 } /* gpgme_key_get_cability */
849
850
851 int
852 gpgme_key_count_items (gpgme_key_t key, int what)
853 {
854 union {
855 struct user_id_s *u;
856 struct subkey_s *k;
857 struct revoker_key_s *r;
858 struct signature_s *s;
859 } dat;
860 int count = 0;
861
862 if (!key)
863 return 0;
864 switch( what ) {
865 case GPGME_ATTR_USERID:
866 for( dat.u = key->uids; dat.u; dat.u = dat.u->next )
867 count++;
868 return count;
869
870 case GPGME_ATTR_KEYID:
871 for( dat.k = &key->keys; dat.k; dat.k = dat.k->next )
872 count++;
873 return count;
874
875 case GPGME_ATTR_REVKEY_FPR:
876 for( dat.r = key->rvks; dat.r; dat.r = dat.r->next )
877 count++;
878 return count;
879
880 case GPGME_ATTR_SIG_KEYID:
881 for (dat.s = key->sigs; dat.s; dat.s = dat.s->next)
882 count++;
883 return count;
884 }
885 return 0;
886 } /* gpgme_key_count_items */
887
888
889 gpgme_key_t
890 _gpgme_key_new_fromkeyid (const char * keyid)
891 {
892 gpgme_key_t key;
893
894 if (!keyid)
895 return NULL;
896 if (_gpgme_key_new (&key))
897 return NULL;
898 memset (key->keys.keyid, 0, sizeof key->keys.keyid);
899 strncpy (key->keys.keyid, keyid, DIM (key->keys.keyid)-1);
900 return key;
901 } /* _gpgme_key_new_fromkeyid */
902
903
904 int
905 gpgme_key_cability_from_algo (gpgme_pk_cipher_t algo)
906 {
907 switch (algo) {
908 case GPGME_PK_DSA:
909 case GPGME_PK_RSA_S:
910 return GPGME_KEY_CANSIGN;
911
912 case GPGME_PK_RSA:
913 case GPGME_PK_ELG_ES:
914 return GPGME_KEY_CANSIGN|GPGME_KEY_CANENCR;
915
916 case GPGME_PK_RSA_E:
917 case GPGME_PK_ELG_E:
918 return GPGME_KEY_CANENCR;
919 }
920
921 return 0;
922 } /* gpgme_key_cability_from_algo */
923
924
925 gpgme_error_t
926 gpgme_key_append (gpgme_key_t dst, gpgme_key_t src, int idx)
927 {
928 struct subkey_s *s, *key;
929
930 for (s = &src->keys; idx; idx--, s = s->next)
931 ;
932
933 key = _gpgme_key_add_subkey (dst);
934 key->expires = s->expires;
935 key->flags = s->flags;
936 key->key_algo = s->key_algo;
937 key->key_len = s->key_len;
938 key->timestamp = s->timestamp;
939 key->fingerprint = strdup (s->fingerprint);
940 strcpy (key->keyid, s->keyid);
941
942 return 0;
943 }

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26