1 /* key.c - Key and keyList objects
2 * Copyright (C) 2000 Werner Koch (dd9jn)
3 * Copyright (C) 2001 g10 Code GmbH
5 * This file is part of GPGME.
7 * GPGME 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.
12 * GPGME 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.
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
31 #define ALLOC_CHUNK 1024
32 #define my_isdigit(a) ( (a) >='0' && (a) <= '9' )
36 pkalgo_to_string ( int algo )
43 case 20: return "ElG";
44 case 17: return "DSA";
45 default: return "Unknown";
53 key_new ( GpgmeKey *r_key, int secret )
58 key = xtrycalloc ( 1, sizeof *key );
60 return mk_error (Out_Of_Core);
69 _gpgme_key_new ( GpgmeKey *r_key )
71 return key_new ( r_key, 0 );
75 _gpgme_key_new_secret ( GpgmeKey *r_key )
77 return key_new ( r_key, 1 );
81 gpgme_key_ref ( GpgmeKey key )
88 static struct subkey_s *
89 add_subkey (GpgmeKey key, int secret)
91 struct subkey_s *k, *kk;
93 k = xtrycalloc (1, sizeof *k);
97 if( !(kk=key->keys.next) )
110 _gpgme_key_add_subkey (GpgmeKey key)
112 return add_subkey (key, 0);
116 _gpgme_key_add_secret_subkey (GpgmeKey key)
118 return add_subkey (key, 1);
122 gpgme_key_release ( GpgmeKey key )
124 struct user_id_s *u, *u2;
125 struct subkey_s *k, *k2;
130 assert (key->ref_count);
131 if ( --key->ref_count )
134 xfree (key->keys.fingerprint);
135 for (k = key->keys.next; k; k = k2 ) {
137 xfree (k->fingerprint);
140 for (u = key->uids; u; u = u2 ) {
148 gpgme_key_unref (GpgmeKey key)
150 gpgme_key_release (key);
155 set_user_id_part ( char *tail, const char *buf, size_t len )
157 while ( len && (buf[len-1] == ' ' || buf[len-1] == '\t') )
167 parse_user_id ( struct user_id_s *uid, char *tail )
169 const char *s, *start=NULL;
174 for (s=uid->name; *s; s++ ) {
177 in_email++; /* not legal but anyway */
180 if (!uid->email_part) {
181 uid->email_part = tail;
182 tail = set_user_id_part ( tail, start, s-start );
187 else if ( in_comment ) {
191 if ( !--in_comment ) {
192 if (!uid->comment_part) {
193 uid->comment_part = tail;
194 tail = set_user_id_part ( tail, start, s-start );
199 else if ( *s == '<' ) {
201 if ( !uid->name_part ) {
202 uid->name_part = tail;
203 tail = set_user_id_part (tail, start, s-start );
210 else if ( *s == '(' ) {
212 if ( !uid->name_part ) {
213 uid->name_part = tail;
214 tail = set_user_id_part (tail, start, s-start );
221 else if ( !in_name && *s != ' ' && *s != '\t' ) {
228 if ( !uid->name_part ) {
229 uid->name_part = tail;
230 tail = set_user_id_part (tail, start, s-start );
234 /* let unused parts point to an EOS */
237 uid->name_part = tail;
238 if (!uid->email_part)
239 uid->email_part = tail;
240 if (!uid->comment_part)
241 uid->comment_part = tail;
246 * Take a name from the --with-colon listing, remove certain escape sequences
247 * sequences and put it into the list of UIDs
250 _gpgme_key_append_name ( GpgmeKey key, const char *s )
252 struct user_id_s *uid;
256 /* we can malloc a buffer of the same length, because the
257 * converted string will never be larger. Actually we allocate it
258 * twice the size, so that we are able to store the parsed stuff
260 uid = xtrymalloc ( sizeof *uid + 2*strlen (s)+3 );
262 return mk_error (Out_Of_Core);
266 uid->name_part = NULL;
267 uid->email_part = NULL;
268 uid->comment_part = NULL;
274 else if ( s[1] == '\\' ) {
278 else if ( s[1] == 'n' ) {
282 else if ( s[1] == 'r' ) {
286 else if ( s[1] == 'v' ) {
290 else if ( s[1] == 'b' ) {
294 else if ( s[1] == '0' ) {
295 /* Hmmm: no way to express this */
300 else if ( s[1] == 'x' && my_isdigit (s[2]) && my_isdigit (s[3]) ) {
301 unsigned int val = (s[2]-'0')*16 + (s[3]-'0');
310 else { /* should not happen */
317 parse_user_id ( uid, d );
319 uid->next = key->uids;
326 add_otag ( GpgmeData d, const char *tag )
328 _gpgme_data_append_string ( d, " <" );
329 _gpgme_data_append_string ( d, tag );
330 _gpgme_data_append_string ( d, ">" );
334 add_ctag ( GpgmeData d, const char *tag )
336 _gpgme_data_append_string ( d, "</" );
337 _gpgme_data_append_string ( d, tag );
338 _gpgme_data_append_string ( d, ">\n" );
342 add_tag_and_string ( GpgmeData d, const char *tag, const char *string )
345 _gpgme_data_append_string_for_xml ( d, string );
350 add_tag_and_uint ( GpgmeData d, const char *tag, unsigned int val )
353 sprintf (buf, "%u", val );
354 add_tag_and_string ( d, tag, buf );
358 add_tag_and_time ( GpgmeData d, const char *tag, time_t val )
362 if (!val || val == (time_t)-1 )
364 sprintf (buf, "%lu", (unsigned long)val );
365 add_tag_and_string ( d, tag, buf );
369 one_uid_as_xml (GpgmeData d, struct user_id_s *u)
371 _gpgme_data_append_string (d, " <userid>\n");
373 _gpgme_data_append_string ( d, " <invalid/>\n");
375 _gpgme_data_append_string ( d, " <revoked/>\n");
376 add_tag_and_string ( d, "raw", u->name );
378 add_tag_and_string ( d, "name", u->name_part );
379 if ( *u->email_part )
380 add_tag_and_string ( d, "email", u->email_part );
381 if ( *u->comment_part )
382 add_tag_and_string ( d, "comment", u->comment_part );
383 _gpgme_data_append_string (d, " </userid>\n");
388 gpgme_key_get_as_xml ( GpgmeKey key )
397 if ( gpgme_data_new ( &d ) )
400 _gpgme_data_append_string ( d, "<GnupgKeyblock>\n"
402 if ( key->keys.secret )
403 _gpgme_data_append_string ( d, " <secret/>\n");
404 if ( key->keys.flags.invalid )
405 _gpgme_data_append_string ( d, " <invalid/>\n");
406 if ( key->keys.flags.revoked )
407 _gpgme_data_append_string ( d, " <revoked/>\n");
408 if ( key->keys.flags.expired )
409 _gpgme_data_append_string ( d, " <expired/>\n");
410 if ( key->keys.flags.disabled )
411 _gpgme_data_append_string ( d, " <disabled/>\n");
412 add_tag_and_string (d, "keyid", key->keys.keyid );
413 if (key->keys.fingerprint)
414 add_tag_and_string (d, "fpr", key->keys.fingerprint );
415 add_tag_and_uint (d, "algo", key->keys.key_algo );
416 add_tag_and_uint (d, "len", key->keys.key_len );
417 add_tag_and_time (d, "created", key->keys.timestamp );
418 /*add_tag_and_time (d, "expires", key->expires );*/
419 _gpgme_data_append_string (d, " </mainkey>\n");
421 /* Now the user IDs. We are listing the last one firs becuase this is
422 * the primary one. */
423 for (u = key->uids; u && u->next; u = u->next )
426 one_uid_as_xml (d,u);
427 for ( u = key->uids; u && u->next; u = u->next ) {
428 one_uid_as_xml (d,u);
432 /* and now the subkeys */
433 for (k=key->keys.next; k; k = k->next ) {
434 _gpgme_data_append_string (d, " <subkey>\n");
436 _gpgme_data_append_string ( d, " <secret/>\n");
437 if ( k->flags.invalid )
438 _gpgme_data_append_string ( d, " <invalid/>\n");
439 if ( k->flags.revoked )
440 _gpgme_data_append_string ( d, " <revoked/>\n");
441 if ( k->flags.expired )
442 _gpgme_data_append_string ( d, " <expired/>\n");
443 if ( k->flags.disabled )
444 _gpgme_data_append_string ( d, " <disabled/>\n");
445 add_tag_and_string (d, "keyid", k->keyid );
447 add_tag_and_string (d, "fpr", k->fingerprint );
448 add_tag_and_uint (d, "algo", k->key_algo );
449 add_tag_and_uint (d, "len", k->key_len );
450 add_tag_and_time (d, "created", k->timestamp );
451 _gpgme_data_append_string (d, " </subkey>\n");
453 _gpgme_data_append_string ( d, "</GnupgKeyblock>\n" );
455 return _gpgme_data_release_and_return_string (d);
460 capabilities_to_string (struct subkey_s *k)
462 static char *strings[8] = {
472 return strings[ (!!k->flags.can_encrypt << 2)
473 | (!!k->flags.can_sign << 1)
474 | (!!k->flags.can_certify ) ];
478 gpgme_key_get_string_attr ( GpgmeKey key, GpgmeAttr what,
479 const void *reserved, int idx )
481 const char *val = NULL;
493 case GPGME_ATTR_KEYID:
494 for (k=&key->keys; k && idx; k=k->next, idx-- )
500 for (k=&key->keys; k && idx; k=k->next, idx-- )
503 val = k->fingerprint;
505 case GPGME_ATTR_ALGO:
506 for (k=&key->keys; k && idx; k=k->next, idx-- )
509 val = pkalgo_to_string (k->key_algo);
512 case GPGME_ATTR_CREATED:
513 case GPGME_ATTR_EXPIRE:
514 break; /* use another get function */
515 case GPGME_ATTR_OTRUST:
518 case GPGME_ATTR_USERID:
519 for (u=key->uids; u && idx; u=u->next, idx-- )
521 val = u? u->name : NULL;
523 case GPGME_ATTR_NAME:
524 for (u=key->uids; u && idx; u=u->next, idx-- )
526 val = u? u->name_part : NULL;
528 case GPGME_ATTR_EMAIL:
529 for (u=key->uids; u && idx; u=u->next, idx-- )
531 val = u? u->email_part : NULL;
533 case GPGME_ATTR_COMMENT:
534 for (u=key->uids; u && idx; u=u->next, idx-- )
536 val = u? u->comment_part : NULL;
538 case GPGME_ATTR_VALIDITY:
539 for (u=key->uids; u && idx; u=u->next, idx-- )
542 switch (u->validity) {
543 case GPGME_VALIDITY_UNKNOWN: val = "?"; break;
544 case GPGME_VALIDITY_UNDEFINED: val = "q"; break;
545 case GPGME_VALIDITY_NEVER: val = "n"; break;
546 case GPGME_VALIDITY_MARGINAL: val = "m"; break;
547 case GPGME_VALIDITY_FULL: val = "f"; break;
548 case GPGME_VALIDITY_ULTIMATE: val = "u"; break;
552 case GPGME_ATTR_LEVEL: /* not used here */
553 case GPGME_ATTR_TYPE:
554 case GPGME_ATTR_KEY_REVOKED:
555 case GPGME_ATTR_KEY_INVALID:
556 case GPGME_ATTR_UID_REVOKED:
557 case GPGME_ATTR_UID_INVALID:
558 case GPGME_ATTR_CAN_ENCRYPT:
559 case GPGME_ATTR_CAN_SIGN:
560 case GPGME_ATTR_CAN_CERTIFY:
562 case GPGME_ATTR_IS_SECRET:
566 case GPGME_ATTR_KEY_CAPS:
567 for (k=&key->keys; k && idx; k=k->next, idx-- )
570 val = capabilities_to_string (k);
578 gpgme_key_get_ulong_attr ( GpgmeKey key, GpgmeAttr what,
579 const void *reserved, int idx )
581 unsigned long val = 0;
593 case GPGME_ATTR_ALGO:
594 for (k=&key->keys; k && idx; k=k->next, idx-- )
597 val = (unsigned long)k->key_algo;
600 for (k=&key->keys; k && idx; k=k->next, idx-- )
603 val = (unsigned long)k->key_len;
605 case GPGME_ATTR_CREATED:
606 for (k=&key->keys; k && idx; k=k->next, idx-- )
609 val = k->timestamp < 0? 0L:(unsigned long)k->timestamp;
611 case GPGME_ATTR_VALIDITY:
612 for (u=key->uids; u && idx; u=u->next, idx-- )
617 case GPGME_ATTR_IS_SECRET:
620 case GPGME_ATTR_KEY_REVOKED:
621 for (k=&key->keys; k && idx; k=k->next, idx-- )
624 val = k->flags.revoked;
626 case GPGME_ATTR_KEY_INVALID:
627 for (k=&key->keys; k && idx; k=k->next, idx-- )
630 val = k->flags.invalid;
632 case GPGME_ATTR_UID_REVOKED:
633 for (u=key->uids; u && idx; u=u->next, idx-- )
638 case GPGME_ATTR_UID_INVALID:
639 for (u=key->uids; u && idx; u=u->next, idx-- )
644 case GPGME_ATTR_CAN_ENCRYPT:
645 val = key->gloflags.can_encrypt;
647 case GPGME_ATTR_CAN_SIGN:
648 val = key->gloflags.can_sign;
650 case GPGME_ATTR_CAN_CERTIFY:
651 val = key->gloflags.can_encrypt;