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