--- trunk/Src/wptKeylist.cpp 2005/07/27 11:17:22 20 +++ trunk/Src/wptKeylist.cpp 2005/10/12 10:04:26 25 @@ -1,5 +1,5 @@ /* wptKeylist.cpp - Keylist element - * Copyright (C) 2001-2004 Timo Schulz + * Copyright (C) 2001-2005 Timo Schulz * Copyright (C) 2004 Andreas Jobs * * This file is part of WinPT. @@ -18,7 +18,6 @@ * along with WinPT; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - #include #include #include @@ -33,6 +32,10 @@ #include "wptErrors.h" #include "wptUTF8.h" #include "wptRegistry.h" +#include "wptContext.h" + + +#define key_is_useable(key) (!(key)->revoked && !(key)->expired && !(key)->disabled) static struct listview_column_s klist_enc[] = { {0, 242, (char *)_("User ID")}, @@ -104,28 +107,110 @@ } /* key_array_search */ +gpgme_user_id_t +get_nth_userid (gpgme_key_t key, int idx) +{ + gpgme_user_id_t t; + + if (!key->uids) + return NULL; + t = key->uids; + while (idx-- && t->next) + t = t->next; + return t; +} + + +int +count_userids (gpgme_key_t key) +{ + gpgme_user_id_t u; + int n = 1; + + u = key->uids; + if (!u) + return 0; + while (u->next) { + u = u->next; + n++; + } + return n; +} + + +gpgme_subkey_t +get_nth_key (gpgme_key_t key, int idx) +{ + gpgme_subkey_t t; + + if (!key->subkeys) + return NULL; + t = key->subkeys; + while (idx-- && t->next) + t = t->next; + return t; +} + +int +count_subkeys (gpgme_key_t key) +{ + gpgme_subkey_t k; + int n = 1; + + k = key->subkeys; + if (!k) + return 0; + while (k->next) { + k = k->next; + n++; + } + return n; +} + + +gpgme_key_sig_t +get_selfsig (gpgme_user_id_t uid, const char *keyid, int first) +{ + gpgme_key_sig_t s, self_sig=NULL; + long timestamp=0; + + for (s = uid->signatures; s; s = s->next) { + if (!strcmp (s->keyid+8, keyid) && s->timestamp > timestamp) { + self_sig = s; + timestamp = s->timestamp; + if (first) + break; + } + } + return self_sig; +} + + + const char* -get_key_algo( gpgme_key_t key, int keyidx ) +get_key_algo (gpgme_key_t key, int keyidx) { static char algo_id[128]; - int n, algo_main, algo_sub; + gpgme_subkey_t k; + char alg[32]; + const char *subalg; + int n=0; - if( keyidx > 0 ) { - algo_main = gpgme_key_get_ulong_attr( key, GPGME_ATTR_ALGO, NULL, keyidx-1 ); - _snprintf( algo_id, sizeof algo_id-1, "%s", - gpgme_key_expand_attr( GPGME_ATTR_ALGO, algo_main ) ); + if (keyidx > 0) { + k = get_nth_key (key, keyidx-1); + subalg = get_key_pubalgo (k->pubkey_algo); + _snprintf( algo_id, DIM (algo_id)-1, "%s", subalg); return algo_id; } - algo_main = gpgme_key_get_ulong_attr( key, GPGME_ATTR_ALGO, NULL, 0 ); - n = gpgme_key_count_items( key, GPGME_ATTR_KEYID ); - if( n > 1 ) { - algo_sub = gpgme_key_get_ulong_attr( key, GPGME_ATTR_ALGO, NULL, n-1 ); - _snprintf( algo_id, sizeof algo_id - 1, "%s/%s", - gpgme_key_expand_attr( GPGME_ATTR_ALGO, algo_main ), - gpgme_key_expand_attr( GPGME_ATTR_ALGO, algo_sub ) ); + strcpy (alg, get_key_pubalgo (key->subkeys->pubkey_algo)); + n = count_subkeys (key); + if (n > 1) { + k = get_nth_key (key, n-1); + subalg = get_key_pubalgo (k->pubkey_algo); + _snprintf (algo_id, DIM (algo_id)-1, "%s/%s", alg, subalg); return algo_id; } - return gpgme_key_expand_attr( GPGME_ATTR_ALGO, algo_main ); + return get_key_pubalgo (key->subkeys->pubkey_algo); } /* get_key_algo */ @@ -135,7 +220,7 @@ static char timebuf[128]; struct tm *warp; - if( timestamp == 0 || timestamp == -1 ) + if (timestamp == 0 || timestamp == -1) return "????-??-??"; warp = localtime( ×tamp ); _snprintf( timebuf, sizeof timebuf - 1, "%04d-%02d-%02d", @@ -145,7 +230,7 @@ const char* -get_key_expire_date( long timestamp ) +get_key_expire_date (long timestamp) { static char timebuf[64]; struct tm *warp; @@ -159,31 +244,33 @@ } /* get_key_expire_date */ -const char * -get_key_type( gpgme_key_t key ) +const char* +get_key_type (gpgme_key_t key) { - int valid = gpgme_key_get_ulong_attr( key, GPGME_ATTR_VALIDITY, NULL, 0 ); - if( find_secret_key( key ) || valid == GPGME_VALIDITY_ULTIMATE ) + if (find_secret_key (key)) return _("Key Pair"); return _("Public Key"); } /* get_key_type */ -const char * -get_key_size( gpgme_key_t key, int keyidx ) +const char* +get_key_size (gpgme_key_t key, int keyidx) { static char size_id[64]; + gpgme_subkey_t k; int n, size_main, size_sub; - if( keyidx > 0 ) { - size_main = gpgme_key_get_ulong_attr( key, GPGME_ATTR_LEN, NULL, keyidx-1 ); - _snprintf( size_id, sizeof size_id-1, "%d", size_main ); + if (keyidx > 0) { + k = get_nth_key (key, keyidx-1); + size_main = k->length; + _snprintf (size_id, DIM (size_id)-1, "%d", size_main); return size_id; } - size_main = gpgme_key_get_ulong_attr( key, GPGME_ATTR_LEN, NULL, 0 ); - n = gpgme_key_count_items( key, GPGME_ATTR_KEYID ); - if( n > 1 ) { - size_sub = gpgme_key_get_ulong_attr( key, GPGME_ATTR_LEN, NULL, n-1 ); + size_main = key->subkeys->length; + n = count_subkeys (key); + if (n > 1) { + k = get_nth_key (key, n-1); + size_sub = k->length; _snprintf( size_id, sizeof (size_id) - 1, "%d/%d", size_main, size_sub ); return size_id; } @@ -192,44 +279,65 @@ } /* get_key_size */ +const char* +get_key_pubalgo (gpgme_pubkey_algo_t alg) +{ + switch (alg) { + case GPGME_PK_DSA: return "DSA"; + case GPGME_PK_ELG: + case GPGME_PK_ELG_E: return "ELG"; + case GPGME_PK_RSA: return "RSA"; + } + return "???"; +} + const char * -get_key_fpr( gpgme_key_t key ) +get_key_fpr (gpgme_key_t key) { static char fpr_md[64]; - const char * fpr; + const char *fpr; char t[16], tmp[40]; - size_t i; + size_t i=0; memset (fpr_md, 0, sizeof (fpr_md)); - fpr = gpgme_key_get_string_attr (key, GPGME_ATTR_FPR, NULL, 0); + fpr = key->subkeys->fpr; if (!fpr || !*fpr) { memset (tmp, '0', 40); fpr = tmp; } - for (i = 0; i < strlen (fpr) / 4; i++) { - sprintf (t, "%c%c%c%c ", fpr[4*i], fpr[4*i+1], fpr[4*i+2], fpr[4*i+3]); - strcat (fpr_md, t); + if (strlen (fpr) == 32) { + strcat (fpr_md, " "); + for (i=0; i < strlen (fpr)/2; i++) { + sprintf (t, "%c%c ", fpr[2*i], fpr[2*i+1]); + strcat (fpr_md, t); + } + } + else { + strcat (fpr_md, " "); + for (i = 0; i < strlen (fpr) / 4; i++) { + sprintf (t, "%c%c%c%c ", fpr[4*i], fpr[4*i+1], fpr[4*i+2], fpr[4*i+3]); + strcat (fpr_md, t); + } } return fpr_md; } /* get_key_fpr */ - -static const char * +const char * get_key_trust2 (gpgme_key_t key, int val, int uididx, int listmode) { if (key) - val = gpgme_key_get_ulong_attr (key, GPGME_ATTR_OTRUST, NULL, uididx); + val = key->owner_trust; /* uididx?? */ switch (val) { - case GPGME_TRUST_UNKNOWN: - case GPGME_TRUST_DONTKNOW: + case GPGME_VALIDITY_UNKNOWN: + case GPGME_VALIDITY_UNDEFINED: return "None"; - case GPGME_TRUST_NEVER: + case GPGME_VALIDITY_NEVER: return "Never"; - case GPGME_TRUST_MARGINAL: + case GPGME_VALIDITY_MARGINAL: return "Marginal"; - case GPGME_TRUST_FULLY: - case GPGME_TRUST_ULTIMATE: + case GPGME_VALIDITY_FULL: + case GPGME_VALIDITY_ULTIMATE: return "Full"; } return ""; @@ -251,130 +359,116 @@ char* -get_key_status( gpgme_key_t key, int uididx, int listmode ) +get_key_status (gpgme_key_t key, int uididx, int listmode) { - char fmt[128], * p; + gpgme_user_id_t u; + char fmt[64], * p; const char * attr; int i = 0; u32 key_attr =0; - if( uididx < 0 || gpgme_key_count_items( key, GPGME_ATTR_USERID ) > uididx ) + if (uididx < 0 || count_userids (key) > uididx) uididx = 0; - memset( fmt, 0, sizeof fmt ); - if( listmode ) { - fmt[i++] = '['; - if( gpgme_key_get_ulong_attr( key, GPGME_ATTR_KEY_REVOKED, NULL, 0 ) ) - fmt[i++] = 'R'; - if( gpgme_key_get_ulong_attr( key, GPGME_ATTR_KEY_EXPIRED, NULL, 0 ) ) - fmt[i++] = 'E'; - if( gpgme_key_get_ulong_attr( key, GPGME_ATTR_KEY_DISABLED, NULL, 0 ) ) - fmt[i++] = 'D'; - fmt[i++] = ']'; - fmt[i++] = ' '; - } - key_attr = gpgme_key_get_ulong_attr( key, GPGME_ATTR_VALIDITY, NULL, uididx ); - attr = gpgme_key_expand_attr( GPGME_ATTR_VALIDITY, key_attr ); - p = new char[strlen( fmt ) + 1 + strlen( attr ) + 2]; - sprintf( p, "%s%s", fmt, attr ); + memset (fmt, 0, sizeof (fmt)); + if (listmode) { + if (key->revoked) + sprintf (fmt, "Revoked"); + else if (key->expired) + sprintf (fmt, "Expired"); + else if (key->disabled) + sprintf (fmt, "Disabled"); + /* if the key has a special status, we don't continue to figure out + what any user-id validities. */ + if (strlen (fmt) > 0) + return m_strdup (fmt); + } + u = get_nth_userid (key, uididx); + key_attr = u->validity; + attr = get_key_trust2 (NULL, key_attr, 0, 0); + p = new char[strlen( attr ) + 2]; + if (!p) + BUG (NULL); + sprintf (p, "%s", attr); return p; } /* get_key_status */ +/* Integer comparsion of @a and @b. + Return values: same as in strcmp. */ static inline int -int_cmp( int a, int b ) +int_cmp (int a, int b) { - if( a == b ) return 0; - else if( a > b ) return 1; + if (a == b) return 0; + else if (a > b) return 1; else return -1; return 0; } +/* List view sorting callback. */ static int CALLBACK keylist_cmp_cb (LPARAM first, LPARAM second, LPARAM sortby) { - static char tmpa[128], tmpb[128]; gpgme_key_t a, b; - const char *aa = NULL, *bb = NULL; - long ta, tb; - int na = 0, nb = 0; int cmpresult = 0; a = (gpgme_key_t)first; - b = (gpgme_key_t)second; + b = (gpgme_key_t)second; + if (!a || !b) + BUG (NULL); - switch( sortby & ~KEYLIST_SORT_DESC ) { - case GPGME_ATTR_USERID: - aa = gpgme_key_get_string_attr( a, GPGME_ATTR_USERID, NULL, 0 ); - bb = gpgme_key_get_string_attr( b, GPGME_ATTR_USERID, NULL, 0 ); - cmpresult = strcmpi( aa? aa : "", bb? bb : "" ); + switch (sortby & ~KEYLIST_SORT_DESC) { + case KEY_SORT_USERID: + cmpresult = strcmpi (a->uids->uid, b->uids->uid); break; - case GPGME_ATTR_KEYID: - aa = gpgme_key_get_string_attr( a, GPGME_ATTR_KEYID, NULL, 0) + 8; - bb = gpgme_key_get_string_attr( b, GPGME_ATTR_KEYID, NULL, 0) + 8; - cmpresult = strcmpi( aa? aa : "", bb? bb : "" ); + case KEY_SORT_KEYID: + cmpresult = strcmpi (a->subkeys->keyid+8, + b->subkeys->keyid+8); break; - case GPGME_ATTR_VALIDITY: - na = gpgme_key_get_ulong_attr( a, GPGME_ATTR_VALIDITY, NULL, 0 ); - nb = gpgme_key_get_ulong_attr( b, GPGME_ATTR_VALIDITY, NULL, 0 ); - cmpresult = int_cmp( na, nb ); + case KEY_SORT_VALIDITY: /* XXX: handle expire, revoked */ + cmpresult = int_cmp (a->uids->validity, b->uids->validity); break; - case GPGME_ATTR_OTRUST: - na = gpgme_key_get_ulong_attr (a, GPGME_ATTR_OTRUST, NULL, 0); - nb = gpgme_key_get_ulong_attr (b, GPGME_ATTR_OTRUST, NULL, 0); - cmpresult = int_cmp (na, nb); + case KEY_SORT_OTRUST: /* XXX: handle expire, revoked */ + cmpresult = int_cmp (a->owner_trust, b->owner_trust); break; - case GPGME_ATTR_IS_SECRET: - aa = gpgme_key_get_string_attr( a, GPGME_ATTR_KEYID, NULL, 0 ); - bb = gpgme_key_get_string_attr( b, GPGME_ATTR_KEYID, NULL, 0 ); - get_seckey( aa, &a ); - get_seckey( bb, &b ); - if( a ) - na = gpgme_key_get_ulong_attr( a, GPGME_ATTR_IS_SECRET, NULL, 0 ); - if( b ) - nb = gpgme_key_get_ulong_attr( b, GPGME_ATTR_IS_SECRET, NULL, 0 ); - cmpresult = int_cmp( na, nb ); + case KEY_SORT_IS_SECRET: + get_seckey (a->subkeys->keyid, &a); + get_seckey (b->subkeys->keyid, &b); + cmpresult = int_cmp (a? a->secret : 0, b? b->secret : 0); break; - case GPGME_ATTR_LEN: - na = gpgme_key_get_ulong_attr( a, GPGME_ATTR_LEN, NULL, 0 ); - nb = gpgme_key_get_ulong_attr( b, GPGME_ATTR_LEN, NULL, 0 ); - cmpresult = int_cmp( na, nb ); + case KEY_SORT_LEN: + cmpresult = int_cmp (a->subkeys->length, + b->subkeys->length); break; - case GPGME_ATTR_CREATED: - ta = gpgme_key_get_ulong_attr( a, GPGME_ATTR_CREATED, NULL, 0 ); - tb = gpgme_key_get_ulong_attr( b, GPGME_ATTR_CREATED, NULL, 0 ); - strcpy( tmpa, get_key_created( ta ) ); aa = tmpa; - strcpy( tmpb, get_key_created( tb ) ); bb = tmpb; - cmpresult = strcmpi( aa? aa : "", bb? bb : "" ); + case KEY_SORT_CREATED: + cmpresult = int_cmp (a->subkeys->timestamp, + b->subkeys->timestamp); break; - case GPGME_ATTR_ALGO: - aa = gpgme_key_get_string_attr (a, GPGME_ATTR_ALGO, NULL, 0); - bb = gpgme_key_get_string_attr (b, GPGME_ATTR_ALGO, NULL, 0); - cmpresult = strcmpi (aa? aa : "", bb? bb : ""); + case KEY_SORT_ALGO: + cmpresult = int_cmp (a->subkeys->pubkey_algo, + b->subkeys->pubkey_algo); break; default: - aa = gpgme_key_get_string_attr( a, GPGME_ATTR_USERID, NULL, 0 ); - bb = gpgme_key_get_string_attr( b, GPGME_ATTR_USERID, NULL, 0 ); - cmpresult = strcmpi( aa? aa : "", bb? bb : "" ); + cmpresult = strcmpi (a->uids->uid, b->uids->uid); break; } if (sortby & KEYLIST_SORT_DESC) return (~cmpresult + 1); else return cmpresult; -} /* keylist_cmp_cb */ +} static const char* -calc_validity( gpg_group_t grp ) +calc_validity (gpg_group_t grp) { int level = 0, valid; gpg_member_t mbr; @@ -383,21 +477,22 @@ for( mbr = grp->list; mbr; mbr = mbr->next ) { if( get_pubkey( mbr->name, &key ) ) continue; - valid = gpgme_key_get_ulong_attr( key, GPGME_ATTR_KEY_VALIDITY, NULL, 0 ); + valid = key->uids->validity; switch( valid ) { case GPGME_VALIDITY_MARGINAL: case GPGME_VALIDITY_NEVER: case GPGME_VALIDITY_UNDEFINED: - return gpgme_key_expand_attr( GPGME_ATTR_VALIDITY, valid ); + return get_key_trust2 (NULL, valid, 0, 0); } } - return gpgme_key_expand_attr( GPGME_ATTR_VALIDITY, GPGME_VALIDITY_FULL ); + return _("Full"); } /* calc_validity */ int keylist_add_groups( listview_ctrl_t lv ) { +#if 0 gpg_optfile_t gh; gpg_group_t grp; const char *valid; @@ -415,6 +510,7 @@ listview_add_sub_item( lv, 0, 3, "Unknown" ); listview_add_sub_item( lv, 0, 4, valid?valid : "Unknown" ); } +#endif return 0; } /* keylist_add_groups */ @@ -456,24 +552,24 @@ static void keylist_load_keycache (listview_ctrl_t lv, int mode, - gpgme_keycache_t pubkc, gpgme_keycache_t seckc) + gpg_keycache_t pubkc, gpg_keycache_t seckc) { - gpgme_error_t err = GPGME_No_Error; + gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR); gpgme_key_t key, skey; const char * keyid; - if( pubkc && seckc ) { - gpgme_keycache_rewind( pubkc ); - while( !gpgme_keycache_next_key( pubkc, 0, &key ) ) { - keyid = gpgme_key_get_string_attr( key, GPGME_ATTR_KEYID, NULL, 0 ); - if( keyid && !gpgme_keycache_find_key( seckc, keyid, 0, &skey ) ) + if (pubkc && seckc) { + gpg_keycache_rewind (pubkc); + while (!gpg_keycache_next_key (pubkc, 0, &key)) { + keyid = key->subkeys->keyid; + if (keyid && !gpg_keycache_find_key (seckc, keyid, 0, &skey)) keylist_add_key (lv, mode, key); } } else if (pubkc) { - gpgme_keycache_rewind (pubkc); + gpg_keycache_rewind (pubkc); while (!err) { - err = gpgme_keycache_next_key (pubkc, 0, &key); + err = gpg_keycache_next_key (pubkc, 0, &key); if (!err) keylist_add_key (lv, mode, key); } @@ -482,25 +578,25 @@ listview_ctrl_t -keylist_load( HWND ctrl, gpgme_keycache_t pubkc, gpgme_keycache_t seckc, - int mode, int sortby ) +keylist_load (HWND ctrl, gpg_keycache_t pubkc, gpg_keycache_t seckc, + int mode, int sortby) { listview_ctrl_t lv; - int rc = 0; + int rc = 0; - rc = keylist_build( &lv, ctrl, mode ); - if( rc ) + rc = keylist_build (&lv, ctrl, mode); + if (rc) return NULL; - keylist_load_keycache( lv, mode, pubkc, seckc ); - keylist_sort( lv, sortby ); - if( (mode & KEYLIST_ENCRYPT) || (mode & KEYLIST_ENCRYPT_MIN) ) - keylist_add_groups( lv ); + keylist_load_keycache (lv, mode, pubkc, seckc); + keylist_sort (lv, sortby); + if ((mode & KEYLIST_ENCRYPT) || (mode & KEYLIST_ENCRYPT_MIN)) + keylist_add_groups (lv); return lv; } /* keylist_load */ int -keylist_reload( listview_ctrl_t lv, gpgme_keycache_t pubkc, int mode, int sortby ) +keylist_reload( listview_ctrl_t lv, gpg_keycache_t pubkc, int mode, int sortby ) { listview_del_all( lv ); keylist_load_keycache( lv, mode, pubkc, NULL ); @@ -524,34 +620,38 @@ const char * keyid; gpgme_key_t skey; - keyid = gpgme_key_get_string_attr( key, GPGME_ATTR_KEYID, NULL, 0 ); - if( !keyid ) + keyid = key->subkeys->keyid; + if (!keyid) return 0; - get_seckey( keyid, &skey ); + get_seckey (keyid, &skey); return skey? 1 : 0; } /* find_secret_key */ static int -do_addkey( listview_ctrl_t lv, gpgme_key_t key, int uididx, int keyidx, int list ) +do_addkey (listview_ctrl_t lv, gpgme_key_t key, int uididx, int keyidx, int list) { LV_ITEM lvi; - gpgme_key_t seckey; + gpgme_user_id_t u; + gpgme_subkey_t k; char fmt[128]; const char *attr; u32 key_attr; - int idx = 0; + int idx = 0; /* we check the pubkey algorithm here to make sure that no ElGamal sign+encrypt key is used in _any_ mode */ - if( list != 1 && gpgme_key_get_ulong_attr( key, GPGME_ATTR_ALGO, NULL, 0 ) - == GPGME_PK_ELG_ES ) + if (list != 1 && key->subkeys->pubkey_algo == GPGME_PK_ELG) { + log_debug ("ElGamal (E+S) key found: %s (%s)\n", + key->uids->name, key->subkeys->keyid); return 0; + } + - if( listview_add_item( lv, " " ) ) + if (listview_add_item2 (lv, " ", (void *)key)) return WPTERR_GENERAL; - attr = gpgme_key_get_string_attr( key, GPGME_ATTR_USERID, NULL, 0 ); + attr = key->uids->uid; memset( &lvi, 0, sizeof lvi ); lvi.mask = LVIF_TEXT | LVIF_PARAM; lvi.pszText = (char *)attr; @@ -559,15 +659,16 @@ if( ListView_SetItem( lv->ctrl, &lvi ) == FALSE ) return WPTERR_GENERAL; - if( uididx == -1 ) { - /* request the primary user-id of the key. */ - attr = gpgme_key_get_string_attr( key, GPGME_ATTR_USERID, NULL, 0 ); + if( uididx == -1 ) { /* request the primary user-id of the key. */ + attr = key->uids->uid; uididx = 0; } else { - if( gpgme_key_get_ulong_attr( key, GPGME_ATTR_UID_REVOKED, NULL, uididx ) || uididx < 0 ) + u = get_nth_userid (key, uididx); + if (!u || u->revoked || uididx < 0) uididx = 0; /* fixme: this happen sometimes but it's illegal! (<0) */ - attr = gpgme_key_get_string_attr( key, GPGME_ATTR_USERID, NULL, uididx ); + u = get_nth_userid (key, uididx); + attr = key->uids->uid; } if( attr == NULL || strlen( attr ) < 5 ) { /* normal userids are >= 5 chars */ attr = _("Invalid User ID"); @@ -575,53 +676,52 @@ } else { char * uid = utf8_to_wincp (attr, strlen (attr)); - if( uid ) { + if (uid) { listview_add_sub_item( lv, 0, idx++, uid ); - free( uid ); + free (uid); } } - attr = gpgme_key_get_string_attr( key, GPGME_ATTR_KEYID, NULL, keyidx ); - if( attr ) { - _snprintf( fmt, sizeof fmt -1, "0x%s", attr + 8 ); + k = get_nth_key (key, keyidx); + if( k && k->keyid ) { + _snprintf( fmt, sizeof fmt -1, "0x%s", k->keyid + 8 ); listview_add_sub_item( lv, 0, idx++, fmt ); } - - if( list > 0 ) { - attr = find_secret_key( key )? "pub/sec" : "pub"; - if( strchr( attr, '/' ) ) { - const char * kid; - kid = gpgme_key_get_string_attr( key, GPGME_ATTR_KEYID, NULL, 0 ); - get_seckey( kid, &seckey ); - if( gpgme_key_get_ulong_attr( seckey, GPGME_ATTR_DIVERT_CARD, NULL, 0 ) ) + if (list > 0) { + attr = find_secret_key (key)? "pub/sec" : "pub"; + if (strchr( attr, '/')) { + struct winpt_key_s k; + winpt_get_seckey (key->subkeys->keyid, &k); + if (k.ext->gloflags.divert_to_card) attr = "pub/crd"; } listview_add_sub_item( lv, 0, idx++, attr ); } - if( lv->cols >= 2 ) { - attr = get_key_size( key, list==-1? keyidx+1 : 0 ); - if( attr ) - listview_add_sub_item( lv, 0, idx++, attr ); - } - if( lv->cols >= 3 ) { - attr = get_key_algo( key, list==-1? keyidx+1 : 0 ); - if( attr ) - listview_add_sub_item( lv, 0, idx++, attr ); + if (lv->cols >= 2) { + attr = get_key_size (key, list == -1? keyidx+1 : 0); + if (attr) + listview_add_sub_item (lv, 0, idx++, attr); + } + if (lv->cols >= 3) { + attr = get_key_algo (key, list == -1? keyidx+1 : 0); + if (attr) + listview_add_sub_item( lv, 0, idx++, attr); } if( lv->cols >= 4 ) { - char * status = get_key_status( key, uididx, list>0? 1 : 0 ); - if( !status ) + char * status = get_key_status( key, uididx, list > 0? 1 : 0 ); + if (!status) return WPTERR_GENERAL; listview_add_sub_item( lv, 0, idx++, status ); free_if_alloc( status ); } if (lv->cols >= 5) { - const char * s = get_key_trust (key, uididx, list>0? 1 : 0); + const char * s = get_key_trust (key, uididx, list > 0? 1 : 0); listview_add_sub_item (lv, 0, idx++, s); } if( lv->cols >= 6 ) { - key_attr = gpgme_key_get_ulong_attr( key, GPGME_ATTR_CREATED, NULL, keyidx ); + k = get_nth_key (key, keyidx); + key_attr = k->timestamp; if( key_attr ) { - attr = gpgme_key_expand_attr( GPGME_ATTR_CREATED, key_attr ); + attr = get_key_created (key_attr); listview_add_sub_item( lv, 0, idx++, attr ); } } @@ -630,17 +730,65 @@ } /* do_addkey */ +void +keylist_upd_key (listview_ctrl_t lv, int pos, gpgme_key_t key) +{ + const char *s; + char tmp[32]; + + listview_set_item2 (lv, pos, (void *)key); + /* the only mode we support is KYLIST_LIST in the Key Manager */ + + s = key->uids->uid; + if (s) + listview_add_sub_item (lv, pos, 0, s); + + s = key->subkeys->keyid; + if (s) { + sprintf (tmp, "0x%s", s+8); + listview_add_sub_item (lv, pos, 1, tmp); + } + + s = find_secret_key (key)? "pub/sec" : "pub"; + listview_add_sub_item (lv, pos, 2, s); + + s = get_key_size (key, 0); + if (s) + listview_add_sub_item (lv, pos, 3, s); + + s = get_key_algo (key, 0); + if (s) + listview_add_sub_item (lv, pos, 4, s); + + s = get_key_status (key, 0, 1); + if (s) + listview_add_sub_item (lv, pos, 5, s); + + s = get_key_trust (key, 0, 1); + if (s) + listview_add_sub_item (lv, pos, 6, s); + + long t = key->subkeys->timestamp; + s = get_key_created (t); + if (s) + listview_add_sub_item (lv, pos, 7, s); +} + + int keylist_add_key (listview_ctrl_t lv, int mode, gpgme_key_t key) { int uids, rc = 0, i, n = 0; - - for (i = 0; i < gpgme_key_count_items (key, GPGME_ATTR_KEYID); i++) { - if (gpgme_key_get_ulong_attr( key, GPGME_ATTR_KEY_INVALID, NULL, i)) + gpgme_subkey_t k; + + for (k=key->subkeys, i = 0; i < count_subkeys (key); i++, k=k->next) { + if (k->invalid) { + log_debug ("keylist_add_key: invalid key \"%s\"\n", key->uids->name); continue; /* Don't use invalid keys */ - + } + if (mode & KEYLIST_ALL) { - uids = gpgme_key_count_items (key, GPGME_ATTR_USERID); + uids = count_userids (key); rc = do_addkey (lv, key, uids, i, 0); if( rc ) return rc; @@ -648,16 +796,14 @@ else if (mode & KEYLIST_LIST) return do_addkey (lv, key, -1, i, 1); else if (mode & KEYLIST_ENCRYPT) { - if (gpgme_key_get_cability (key, GPGME_ATTR_CAN_ENCRYPT, i) - && gpgme_key_get_ulong_attr (key, GPGME_ATTR_KEY_USABLE, NULL, i)) - { - if (mode & KEYLIST_FLAG_FILE ) { - rc = do_addkey( lv, key, -1, i, -1 ); - if( rc ) + if (k->can_encrypt && key_is_useable (k)) { + if (mode & KEYLIST_FLAG_FILE) { + rc = do_addkey (lv, key, -1, i, -1); + if (rc) return rc; } else { - for( uids = 0; uids < gpgme_key_count_items( key, GPGME_ATTR_USERID ); uids++ ) { + for( uids = 0; uids < count_userids (key); uids++ ) { rc = do_addkey( lv, key, uids, i, -1 ); if( rc ) return rc; @@ -666,17 +812,16 @@ } } else if (mode & KEYLIST_ENCRYPT_MIN) { - if( gpgme_key_get_cability (key, GPGME_ATTR_CAN_ENCRYPT, i) - && gpgme_key_get_ulong_attr (key, GPGME_ATTR_KEY_USABLE, NULL, i)) + if( k->can_encrypt && key_is_useable (k)) { rc = do_addkey (lv, key, -1, i, -1); return rc; } } else if (mode & KEYLIST_SIGN) { - if ( gpgme_key_get_cability( key, GPGME_ATTR_CAN_SIGN, i ) + if ( k->can_sign && find_secret_key( key ) - && gpgme_key_get_ulong_attr (key, GPGME_ATTR_KEY_USABLE, NULL, i)) + && key_is_useable (k)) { rc = do_addkey (lv, key, -1, i, -1); if( rc ) @@ -692,53 +837,54 @@ int keylist_sort (listview_ctrl_t lv, int sortby) { - return listview_sort_items( lv, sortby, keylist_cmp_cb ); -} /* keylist_sort */ + return listview_sort_items (lv, sortby, keylist_cmp_cb); +} +/* Check that the validity @validity is at least >= marginal. */ static int key_check_validity (const char *validity) { - if (strstr (validity, "Unknown") - || strstr (validity, "Undefined") - || strstr (validity, "Never")) + if (strstr (validity, "Unknown") || + strstr (validity, "Undefined") || + strstr (validity, "Never") || + strstr (validity, "None")) return 0; return 1; -} /* key_check_validity */ +} -gpgme_recipients_t +/* Extract all selected recipients from the list @lv and return them + as a vector. @r_force_trust is >= 1 if one of the recipients is not + fully trusted. @r_count returns the number of selected keys. + Return value: the key list on success, NULL otherwise. */ +gpgme_key_t* keylist_get_recipients (listview_ctrl_t lv, int *r_force_trust, int *r_count) { int count = 0, force_trust = 0; int n, j, ka_pos = 0, rc = 0; + int k_pos=0; char keyid[32], valid[32], id[100]; key_array_s *ka = NULL; - gpgme_error_t err; - gpgme_recipients_t rset; + gpgme_key_t *keybuf; - err = gpgme_recipients_new( &rset ); - if( err ) - BUG( NULL ); - n = listview_count_items( lv, 0 ); + ka = key_array_new( n ); - if ( !ka ) - BUG( NULL ); + if (!ka) + BUG (NULL); + + keybuf = (gpgme_key_t*)calloc (n, sizeof (gpgme_key_t)); + if (!keybuf) + BUG (NULL); for( j = 0; j < n; j++ ) { - if( listview_get_item_state( lv, j ) || n == 1 ) { - listview_get_item_text( lv, j, 1, keyid, sizeof keyid - 1 ); - listview_get_item_text( lv, j, 4, valid, sizeof valid -1 ); - listview_get_item_text( lv, j, 0, id, sizeof id-1 ); - if( !strncmp( keyid, "gpg_group_t", 5 ) ) { - listview_get_item_text( lv, j, 0, id, sizeof id -1 ); - rc = km_groupdb_expand_recipients( id, rset ); - if( rc ) - force_trust++; - } - else if( !key_check_validity( valid ) - && !key_array_search( ka, ka_pos, keyid ) ) { + if( listview_get_item_state (lv, j) || n == 1) { + listview_get_item_text (lv, j, 0, id, sizeof id-1); + listview_get_item_text (lv, j, 1, keyid, sizeof keyid - 1); + listview_get_item_text (lv, j, 4, valid, sizeof valid -1); + if( !key_check_validity (valid) + && !key_array_search( ka, ka_pos, keyid )) { char *warn = new char[512+strlen (id) + 1]; if (!warn) BUG (0); @@ -753,16 +899,21 @@ else rc = msg_box (NULL, warn, _("Recipients"), MB_ERR_ASK); if (rc == IDYES) { - gpgme_recipients_add_name_with_validity (rset, keyid, GPGME_VALIDITY_FULL); + gpgme_key_t k; + get_pubkey (keyid, &k); + keybuf[k_pos++] = k; force_trust++; ka[ka_pos].checked = 1; strcpy (ka[ka_pos++].keyid, keyid); + count++; } free_if_alloc (warn); } else { + gpgme_key_t k; listview_get_item_text( lv, j, 1, keyid, sizeof keyid -1 ); - gpgme_recipients_add_name( rset, keyid ); + get_pubkey (keyid, &k); + keybuf[k_pos++] = k; count++; } } @@ -772,8 +923,8 @@ *r_force_trust = force_trust; if (r_count) *r_count = count; - return rset; -} /* keylist_get_recipients */ + return keybuf; +} static int @@ -798,17 +949,20 @@ } /* keylist_get_keyflags */ -gpgme_recipients_t -keylist_enum_recipients (listview_ctrl_t lv, int listype) +gpgme_key_t* +keylist_enum_recipients (listview_ctrl_t lv, int listype, int *r_count) { - gpgme_recipients_t rset; - int i, n, id; + gpgme_key_t* rset; + gpgme_key_t k; + int i, n, id, k_pos=0; char keyid[32], t[128], t2[128]; - if( gpgme_recipients_new( &rset ) ) - BUG( NULL ); - - n = listview_count_items( lv, 0 ); + n = listview_count_items (lv, 0); + if (!n) + return 0; + rset = (gpgme_key_t*)calloc (n, sizeof (gpgme_key_t)); + if (!rset) + BUG (NULL); for( i = 0; i < n; i++ ) { if( !listview_get_item_state( lv, i ) ) continue; @@ -825,8 +979,11 @@ } break; } - gpgme_recipients_add_name( rset, keyid ); + get_pubkey (keyid, &k); + rset[k_pos++] = k; } + if (r_count) + *r_count = k_pos; return rset; } /* keylist_enum_recipients */ @@ -847,11 +1004,10 @@ void seclist_init (HWND dlg, int ctlid, int flags, keylist_t * ret_list) { - gpgme_keycache_t kc = NULL; + gpg_keycache_t kc = NULL; gpgme_key_t key = NULL; HWND kb; - keylist_t list=NULL, l, l2; - gpgme_attr_t name_attr = GPGME_ATTR_USERID; + keylist_t list=NULL, l, l2; long pos = 0; SendDlgItemMessage (dlg, ctlid, CB_RESETCONTENT, 0, 0); @@ -859,23 +1015,24 @@ kc = keycache_get_ctx (0); if (!kc) BUG (0); - gpgme_keycache_rewind (kc); - - if (flags & KEYLIST_FLAG_SHORT) - name_attr = GPGME_ATTR_NAME; - while (!gpgme_keycache_next_key (kc, 1, &key)) { + gpg_keycache_rewind (kc); + + while (!gpg_keycache_next_key (kc, 1, &key)) { char * inf = NULL, * uid = NULL; const char * id; const char * keyid; int algo; size_t size = 0; - - id = gpgme_key_get_string_attr (key, name_attr, NULL, 0); - keyid = gpgme_key_get_string_attr (key, GPGME_ATTR_KEYID, NULL, 0); - algo = gpgme_key_get_ulong_attr (key, GPGME_ATTR_ALGO, NULL, 0); + + if (flags & KEYLIST_FLAG_SHORT) + id = key->uids->name; + else + id = key->uids->uid; + keyid = key->subkeys->keyid; + algo = key->subkeys->pubkey_algo; if (!id || !keyid) continue; /* fixme: error? */ - if (!gpgme_key_get_ulong_attr (key, GPGME_ATTR_KEY_USABLE, NULL, 0)) + if (!key_is_useable (key->subkeys)) continue; uid = utf8_to_wincp (id, strlen (id)); @@ -883,9 +1040,8 @@ inf = new char[size+1]; if( !inf ) BUG( NULL ); - _snprintf(inf, size, _("%s (%s/0x%s)"), uid, - gpgme_key_expand_attr (GPGME_ATTR_ALGO, algo), keyid + 8); - + _snprintf (inf, size, _("%s (%s/0x%s)"), uid, + get_key_pubalgo (key->subkeys->pubkey_algo), keyid + 8); combox_add_string (kb, inf); free_if_alloc (inf); free (uid); @@ -895,8 +1051,7 @@ l->key = key; if (!list) list = l; - else - { + else { for( l2 = list; l2->next; l2 = l2->next ) ; l2->next = l; @@ -906,23 +1061,25 @@ SendMessage( kb, CB_SETITEMDATA, pos, (LPARAM)(DWORD)l2->key ); SendMessage( kb, CB_SETCURSEL, 0, 0 ); *ret_list = list; -} /* seclist_init */ +} +/* Select a secret key from the combo box with the ID @ctlid. + Return the code on success in @ret_key. */ int -seclist_select_key (HWND dlg, int ctlid, gpgme_key_t * ret_key) +seclist_select_key (HWND dlg, int ctlid, gpgme_key_t *ret_key) { int pos; DWORD k = 0; - pos = SendDlgItemMessage( dlg, ctlid, CB_GETCURSEL, 0, 0 ); - if( pos == CB_ERR ) { - msg_box( dlg, _("No key was selected."), _("Secret Key List"), MB_ERR ); + pos = SendDlgItemMessage (dlg, ctlid, CB_GETCURSEL, 0, 0); + if (pos == CB_ERR) { + msg_box (dlg, _("No key was selected."), _("Secret Key List"), MB_ERR); *ret_key = NULL; } else { - k = SendDlgItemMessage( dlg, ctlid, CB_GETITEMDATA, pos, 0 ); + k = SendDlgItemMessage (dlg, ctlid, CB_GETITEMDATA, pos, 0); *ret_key = (gpgme_key_t)k; } return k? 0 : -1; -} /* seclist_dlg_proc */ +}