/[winpt]/trunk/Src/wptKeyManager.cpp
ViewVC logotype

Diff of /trunk/Src/wptKeyManager.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 33 by twoaday, Tue Oct 25 07:46:20 2005 UTC revision 278 by twoaday, Mon Jan 15 22:02:04 2007 UTC
# Line 1  Line 1 
 /* wptKeyManager.cpp - Handy functions for the Key Manager dialog  
  *      Copyright (C) 2001-2005 Timo Schulz  
  *      Copyright (C) 2005 g10 Code GmbH  
  *  
  * This file is part of WinPT.  
  *  
  * WinPT is free software; you can redistribute it and/or  
  * modify it under the terms of the GNU General Public License  
  * as published by the Free Software Foundation; either version 2  
  * of the License, or (at your option) any later version.  
  *    
  * WinPT is distributed in the hope that it will be useful,  
  * but WITHOUT ANY WARRANTY; without even the implied warranty of  
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU  
  * General Public License for more details.  
  *  
  * You should have received a copy of the GNU General Public License  
  * along with WinPT; if not, write to the Free Software Foundation,  
  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA  
  */  
 #include <windows.h>  
 #include <commctrl.h>  
 #include <stdio.h>  
   
 #include "gpgme.h"  
 #include "../resource.h"  
 #include "wptTypes.h"  
 #include "wptW32API.h"  
 #include "wptVersion.h"  
 #include "wptCommonCtl.h"  
 #include "wptNLS.h"  
 #include "wptErrors.h"  
 #include "wptContext.h"  
 #include "wptGPG.h"  
 #include "wptKeylist.h"  
 #include "wptFileManager.h"  
 #include "wptDlgs.h"  
 #include "wptKeyserver.h"  
 #include "wptKeyManager.h"  
 #include "wptKeylist.h"  
 #include "wptHTTP.h"  
 #include "wptKeyEdit.h"  
 #include "wptImport.h"  
   
   
 /* Return a user friendly key representation in @buf of  
    the key given by @keyid. */  
 static void  
 key_get_clip_info (const char *keyid, char *buf, size_t buflen)  
 {  
     gpgme_key_t pk;  
   
     if (get_pubkey (keyid, &pk))  
         BUG (NULL);  
     _snprintf (buf, buflen-1,  
                "pub %04d%s/%s %s %s\r\n"  
                "    Primary key fingerprint: %s\r\n",  
                pk->subkeys->length,  
                get_key_pubalgo (pk->subkeys->pubkey_algo),  
                pk->subkeys->keyid+8,  
                get_key_created (pk->subkeys->timestamp),  
                pk->uids->uid,  
                get_key_fpr (pk));  
 }  
   
   
 #if 0  
 /* Quoted the user-id given by @uid. If @uid is already  
    quoted @uid is returned without any modifications.  
    Return value: quoted @uid. */  
 char*  
 km_quote_uid (const char *uid)  
 {      
     char *q;  
   
     if (*uid == '"' && uid[strlen (uid)-1] == '"')  
         return m_strdup (uid);  
     q = new char[strlen (uid) + 4];  
     if (!q)  
         BUG (NULL);  
     _snprintf (q, strlen (uid) + 3, "\"%s\"", uid);  
     return q;  
 }  
 #endif  
   
   
 /* Check if list view @lv contains a secret key at position @pos.  
    If utrust is valid, set it to 1 if the key is valid -1 otherwise.  
    Return value: 1 normal key, 2 smart card key. */  
 int  
 km_check_for_seckey (listview_ctrl_t lv, int pos, int *utrust)  
 {  
     char t[32], t2[64];  
     int type = 0;  
       
     if (utrust)  
         *utrust = 0;  
     listview_get_item_text (lv, pos, 5, t, DIM (t)-1);  
     listview_get_item_text (lv, pos, 2, t2, DIM (t2)-1);  
     if (!strcmp (t2, "pub/sec"))  
         type = 1;  
     else if (!strcmp (t2, "pub/crd"))  
         type = 2;  
     if ((strstr (t, "Expired") || strstr (t, "Revoked")) && utrust)  
         *utrust = -1;  
     else if (stristr (t, "Ultimate") && utrust)  
         *utrust = 1;  
     return type;  
 }  
   
   
 /* Check if the key at position @pos is protected with a passwd. */  
 int  
 km_check_if_protected (listview_ctrl_t lv, int pos)  
 {  
     gpgme_key_t key;  
     winpt_key_s k;  
   
     key = (gpgme_key_t)listview_get_item2 (lv, pos);  
     if (!key)  
         return 1; /* assume yes */  
     winpt_get_pubkey (key->subkeys->keyid, &k);  
     return k.is_protected;  
 }  
   
   
 int  
 km_check_key_status (listview_ctrl_t lv, int pos)  
 {  
     int flags = km_get_key_status (lv, pos);  
       
     if (flags & KM_FLAG_EXPIRED) {  
         msg_box (lv->ctrl, _("This key has expired!\n"    
                              "Key check failed."), _("Key Manager"), MB_ERR);  
         return -1;  
     }  
     else if (flags & KM_FLAG_REVOKED) {  
         msg_box (lv->ctrl, _("This key has been revoked by its owner!\n"  
                              "Key check failed."), _("Key Manager"), MB_ERR);  
         return -1;  
     }  
   
     return 0;  
 } /* km_check_key_status */  
   
   
 int  
 km_get_key_status (listview_ctrl_t lv, int pos)  
 {  
     gpgme_key_t key;  
     int flags = 0;  
   
     if (pos == -1)  
         return 0;  
     key = (gpgme_key_t)listview_get_item2 (lv, pos);  
     if (key == NULL)  
         return 0;  
   
     if (key->expired)  
         flags |= KM_FLAG_EXPIRED;  
     if (key->revoked)  
         flags |= KM_FLAG_REVOKED;  
     if (key->disabled)  
         flags |= KM_FLAG_DISABLED;  
     return flags;  
 } /* km_get_key_status */  
   
   
 /* Interface to enable or disable a key (@enable = 1 then enable).  
    The key is retrieved from a list control @lv at the pos @pos. */  
 int  
 km_enable_disable_key (listview_ctrl_t lv, HWND dlg, int pos, int enable)  
 {  
     GpgKeyEdit *ke;  
     gpgme_error_t err;  
     char keyid[32];  
   
     listview_get_item_text (lv, pos, 1, keyid, DIM (keyid)-1);  
   
     ke = new GpgKeyEdit (keyid);  
     if (!ke)  
         BUG (NULL);  
   
     err = enable? ke->enable () : ke->disable ();  
     if (!err) {  
         show_msg (dlg, 1500, _("Key status changed."));  
         keycache_set_reload (1); /* XXX: set update flag */  
     }  
     else  
         msg_box (dlg, gpgme_strerror (err), _("Key Manager"), MB_ERR);  
     delete ke;  
     return err? WPTERR_GENERAL : 0;  
 }  
   
   
   
 /* Create a string that contain all keyids from  
    the key list @rset separated by a space. */  
 char*  
 gpg_keylist_to_pattern (gpgme_key_t *rset, int n)  
 {  
     char *p;  
     int i;  
   
     if (!n)  
         return NULL;  
     p = (char *)calloc (1, n*(16+1)+n+2);  
     if (!p)  
         BUG (NULL);  
     for (i=0; i < n; i++) {  
         strcat (p, rset[i]->subkeys->keyid);  
         strcat (p, " ");  
     }  
     return p;  
 }  
   
   
 /* Export the keys given in @rset to the clipboard.  
    Return value: 0 on success. */  
 static gpgme_error_t  
 gpg_clip_export (gpgme_key_t *rset, int n)  
 {  
     gpgme_error_t err = 0;  
     gpgme_ctx_t ctx = NULL;  
     gpgme_data_t keydata = NULL;  
     char *patt=NULL;  
       
     err = gpgme_new (&ctx);  
     if (err)  
         return err;  
     gpgme_set_armor (ctx, 1);            
     err = gpgme_data_new (&keydata);  
     if (err)  
         goto leave;  
   
     patt = gpg_keylist_to_pattern (rset, n);  
     if (!patt) {  
         err = gpg_error (GPG_ERR_ENOMEM);  
         goto leave;  
     }  
   
     err = gpgme_op_export (ctx, patt, 0, keydata);  
     if (err)  
         goto leave;  
   
     gpg_data_release_and_set_clipboard (keydata, 1);  
   
 leave:  
     if (patt)  
         free (patt);  
     gpgme_release (ctx);  
     return err;  
 }  
   
   
 /* Export the selected keys in @lv to the clipboard. */  
 int  
 km_clip_export (HWND dlg, listview_ctrl_t lv)  
 {  
     gpgme_error_t err;  
     gpgme_key_t *rset;  
     char buf[256];  
     int n=0;  
     int rc=0;  
       
     rset = keylist_enum_recipients (lv, KEYLIST_LIST, &n);  
     if (!n) {  
         msg_box (dlg, _("No key was selected for export."), _("Key Manager"), MB_ERR);  
         rc = WPTERR_GENERAL;  
         goto leave;  
     }  
       
     err = gpg_clip_export (rset, n);  
     if (err) {  
         msg_box( dlg, gpgme_strerror (err), _("Key Manager"), MB_ERR);  
         rc = WPTERR_GENERAL;  
         goto leave;  
     }  
     if (n == 1) {  
         key_get_clip_info (rset[0]->subkeys->keyid, buf, sizeof (buf)-1);  
         set_clip_text2 (NULL, buf, strlen (buf), 0);  
     }  
   
     show_msg (dlg, 1500, _("GnuPG Status: Finished"));  
       
 leave:  
     free (rset);  
     return rc;  
 } /* km_clip_export */  
   
   
 /* Export the selected secret key from @lv into @fname.  
    It is only allowed to export a single secret key. */  
 int  
 km_privkey_export (HWND dlg, listview_ctrl_t lv, const char *fname)  
 {  
     gpgme_key_t *rset;  
     gpgme_error_t err;  
     int n = 0;  
   
     rset = keylist_enum_recipients (lv, KEYLIST_LIST, &n);  
     if (!n) {  
         msg_box (dlg, _("No key was selected for export."),  
                  _("Key Manager"), MB_ERR);  
         return WPTERR_GENERAL;  
     }  
     if (n > 1) {  
         msg_box (dlg, _("Only one secret key can be exported."),  
                  _("Key Manager"), MB_ERR);  
         free (rset);  
         return 0; /* we checked this before, so we just quit */  
     }  
   
     err = gpg_export_seckey (rset[0]->subkeys->keyid, fname);  
     if (err)  
         msg_box (dlg, gpgme_strerror (err), _("Key Manager"), MB_ERR);  
     else  
         log_box (_("Key Manager"), MB_OK,  
                  _("Secret key successfully saved in '%s'."), fname);  
   
     free (rset);  
     return err? WPTERR_GENERAL : 0;  
 }  
   
   
 int  
 km_file_export (HWND dlg, listview_ctrl_t lv, const char * fname)  
 {  
     gpgme_key_t *rset;  
     gpgme_data_t keydata;        
     gpgme_error_t err;  
     gpgme_ctx_t ctx;  
     char *patt;  
     int n;  
   
     rset = keylist_enum_recipients (lv, KEYLIST_LIST, &n);  
     if (!n) {  
         msg_box (dlg, _("No key was selected for export."),  
                  _("Key Manager"), MB_ERR);  
         return WPTERR_GENERAL;  
     }  
       
     err = gpgme_data_new (&keydata);  
     if (err)  
         BUG (NULL);  
     err = gpgme_new (&ctx);  
     if (err)  
         BUG (NULL);  
     gpgme_set_armor (ctx, 1);  
   
     /*gpgme_set_comment (ctx, "Generated by WinPT "PGM_VERSION);*/  
     patt = gpg_keylist_to_pattern (rset, n);  
       
     err = gpgme_op_export( ctx, patt, 0, keydata);  
     if( err ) {  
         msg_box( dlg, gpgme_strerror( err ), _("Key Manager"), MB_ERR );  
         goto leave;  
     }  
           
     log_box( _("Key Manager"), MB_OK,  
              _("Key(s) successfully saved in '%s'."), fname );  
       
 leave:  
     err = gpg_data_release_and_set_file( keydata, fname );  
     if (err)  
         log_box (_("Key Manager"), MB_OK,  
                  _("Could not save data to '%s'."), fname);  
     gpgme_release (ctx);  
     free (patt);  
     return (int)err;  
 } /* km_file_export */  
   
   
 static int  
 extract_dash_escaped_key (void)  
 {  
     gpgme_data_t inp, plain;  
     gpgme_error_t err;  
   
     err = gpg_data_new_from_clipboard (&inp, 0);  
     if (err) {  
         msg_box (NULL, gpgme_strerror( err ), _("Key Manager"), MB_ERR);  
         return -1;  
     }  
     gpg_data_extract_plaintext (inp, &plain);  
     gpg_data_release_and_set_clipboard (plain, 0);  
     gpgme_data_release (inp);  
   
     return 0;  
 } /* extract_dash_escaped_key */  
   
   
 /* Import keys from the clipboard. */  
 int  
 km_clip_import (HWND dlg)  
 {  
     gpgme_error_t err;  
     int pgptype;  
     int id;  
     int has_data = 0;  
       
     if (!gpg_clip_istext_avail (&has_data) && !has_data) {  
         msg_box( dlg, winpt_strerror (WPTERR_CLIP_ISEMPTY), _("Key Manager"), MB_ERR);  
         return WPTERR_CLIP_ISEMPTY;  
     }  
     err = gpg_clip_is_secured (&pgptype, &has_data);  
     if (err)  
         msg_box (dlg, gpgme_strerror (err), _("Key Manager"), MB_ERR);  
     if (!has_data) {  
         msg_box (dlg, _("No valid OpenPGP data found."), _("Key Manager"), MB_ERR);  
         return WPTERR_GENERAL;  
     }  
     if (!(pgptype & PGP_PUBKEY) && !(pgptype & PGP_SECKEY)) {  
         msg_box (dlg, _("No valid OpenPGP keys found."), _("Key Manager"), MB_ERR);  
         return WPTERR_GENERAL;  
     }  
     if (pgptype & PGP_DASH_ESCAPED) {  
         id = msg_box (dlg, _("The key you want to import is dash escacped.\n"  
                              "Do you want to extract the key?"),  
                       _("Key Manager"), MB_YESNO);  
         if (id == IDYES)  
             extract_dash_escaped_key ();  
         else  
             msg_box (dlg, _("Cannot import dash escaped OpenPGP keys."),  
                      _("Key Manager"), MB_INFO);  
     }  
   
     dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_IMPORT, dlg,  
                       clip_import_dlg_proc, NULL,  
                       _("Key Import"), IDS_WINPT_IMPORT);  
   
     return 0;  
 }  
   
   
 /* Import a key from the http URL @url. */  
 int  
 km_http_import (HWND dlg, const char *url)  
 {  
     http_hd_t hd;  
     FILE *fp;  
     char *p;  
     char tmpfile[500];  
     int statcode;  
     int rc = 0;  
   
     if (strncmp (url, "http://", 7)) {  
         log_box (_("Key Import HTTP"), MB_ERR, _("Invalid HTTP URL: %s"), url);  
         return WPTERR_GENERAL;  
     }  
   
     GetTempPath (sizeof (tmpfile)-128, tmpfile);  
     p = make_filename (tmpfile, "winpt_file_http", "tmp");  
     if (!p)  
         BUG (0);  
     fp = fopen (p, "wb");  
     if (!fp) {  
         free_if_alloc (p);  
         log_box (_("Key Import HTTP"), MB_ERR, "%s: %s", p, winpt_strerror (WPTERR_FILE_CREAT));  
         return WPTERR_FILE_CREAT;  
     }  
   
     /* parse URL */  
     rc = http_send_request2 (url, &hd);  
     if (!rc)  
         rc = http_parse_response (hd, &statcode);  
     if (!rc)  
         rc = http_parse_data (hd, fp);  
     http_hd_free (hd);  
     fclose (fp);  
     if (rc) {    
         msg_box (dlg, winpt_strerror (rc), _("Key Import HTTP"), MB_ERR);  
         rc = WPTERR_GENERAL;  
     }  
     km_file_import (dlg, p);  
     unlink (p);  
     free_if_alloc (p);  
     return rc;  
 }  
   
   
 /* Import a key from the given file @fname.  
    On success an import statistics dialog is shown. */  
 int  
 km_file_import (HWND dlg, const char *fname)  
 {  
     gpgme_data_t keydata = NULL;  
     gpgme_ctx_t ctx;  
     gpgme_error_t err;      
     fm_state_s fm_stat;  
     gpgme_import_result_t res;  
       
     memset (&fm_stat, 0, sizeof (fm_stat));  
     fm_stat.opaque = m_strdup (fname);  
       
     dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_IMPORT, dlg,  
                       file_import_dlg_proc, (LPARAM)&fm_stat,  
                       _("File Import"), IDS_WINPT_IMPORT);  
     if (fm_stat.cancel == 1 ) {  
         free_if_alloc (fm_stat.opaque);  
         return WPTERR_GENERAL;  
     }  
       
     err = gpgme_new (&ctx);  
     if (err)  
         BUG (NULL);  
     err = gpgme_data_new_from_file (&keydata, fname, 1);  
     if (err) {  
         msg_box (dlg, _("Could not read key-data from file."),  
                  _("Key Manager"), MB_ERR);  
         goto leave;  
     }  
       
     err = gpgme_op_import (ctx, keydata);  
     if (err) {  
         msg_box (dlg, gpgme_strerror (err), _("Key Manager"), MB_ERR);  
         goto leave;  
     }      
   
     res = gpgme_op_import_result (ctx);  
     if (res->new_revocations == 0 && fm_stat.import.revcert == 1)  
         res->new_revocations = 1;  
     if (res->secret_imported == 0 && fm_stat.import.has_seckey == 1)  
         res->secret_imported = 1;  
   
     print_import_status (res);  
     if (res->no_user_id > 0) {  
         msg_box (dlg, _("Key without a self signature was dectected!\n"  
                         "(This key is NOT usable for encryption, etc)\n"  
                         "\n"      
                         "Cannot import these key(s)!"), _("Import"), MB_INFO);  
     }  
   
 leave:  
     gpgme_data_release (keydata);  
     gpgme_release (ctx);  
     free_if_alloc (fm_stat.opaque);  
     return (int)err;  
 }  
   
   
 /* Mark the keys in @rset as deleted in the keycache. */  
 static void  
 delete_keys_from_cache (gpgme_key_t *rset, size_t n)  
 {  
     gpg_keycache_t pub = keycache_get_ctx (1);  
     int i=0;  
   
     while (n-- > 0)  
         gpg_keycache_delete_key (pub, rset[i++]->subkeys->keyid);  
 }  
   
   
 /* Delete all selected keys from the list view @lv. */  
 int  
 km_delete_keys (listview_ctrl_t lv, HWND dlg)  
 {  
     gpgme_error_t err;  
     gpgme_ctx_t ctx;  
     gpgme_key_t *rset, k;  
     char keyid[32], uid[256], date[64], keylen[64];      
     int with_seckey=0, seckey_type=0, confirm=0;  
     int i, rc, n, k_pos=0;  
       
     if (listview_get_curr_pos (lv) == -1) {  
         msg_box (dlg, _("Please select a key."), _("Key Manager"), MB_ERR);  
         return WPTERR_GENERAL;  
     }  
           
     if (listview_count_items (lv, 1) > 8) {  
         i = msg_box (NULL, _("Do you really want to confirm each key?"),  
                      _("Delete Confirmation"), MB_YESNOCANCEL|MB_ICONQUESTION);  
         if (i == IDCANCEL)  
             return 0;  
         if (i != IDNO)  
             confirm = 1;  
     }  
     else  
         confirm = 1;  
   
     n = listview_count_items (lv, 0);  
     rset = (gpgme_key_t *)calloc (n+1, sizeof (gpgme_key_t));  
     if (!rset)  
         BUG (NULL);  
     for( i = 0; i < n; i++ ) {  
         if( listview_get_item_state( lv, i ) ) {  
             listview_get_item_text( lv, i, 0, uid, sizeof uid - 1 );  
             listview_get_item_text( lv, i, 1, keyid, sizeof keyid - 1 );  
             listview_get_item_text( lv, i, 3, keylen, sizeof keylen - 1 );  
             listview_get_item_text( lv, i, 7, date, sizeof date - 1 );  
             seckey_type = km_check_for_seckey (lv, i, NULL);  
             if (confirm && !seckey_type) {  
                 rc = log_box( _("Key Manager"), MB_YESNO|MB_ICONWARNING,  
                               _("Do you really want to delete this key?\n\n"  
                                 "pub %s %s %s\n"  
                                 "  \"%s\""), keylen, keyid, date, uid );  
                 if (rc == IDYES) {  
                     get_pubkey (keyid, &k);  
                     rset[k_pos++] = k;  
                 }  
                 with_seckey = 0;  
             }  
             else if (confirm) {  
                 rc = log_box( _("Key Manager"), MB_YESNO|MB_ICONWARNING,                  
                               _("Do you really want to delete this KEY PAIR?\n\n"  
                                 "Please remember that you are not able to decrypt\n"  
                                 "messages you stored with this key any longer.\n"  
                                 "\n"  
                                 "pub/sec %s %s %s\n"  
                                 "  \"%s\""), keylen, keyid, date, uid );  
                 if( rc == IDYES ) {  
                     if (seckey_type == 2)  
                         msg_box( dlg, _("The actual secret key is stored on a smartcard.\n"  
                                         "Only the public key and the secret key \n"  
                                         "placeholder will be deleted.\n"), _("Key Manager"), MB_OK );  
                     get_pubkey (keyid, &k);  
                     rset[k_pos++] = k;  
                 }  
                 with_seckey = 1;  
             }  
             else {  
                 with_seckey = 1;  
                 get_pubkey (keyid, &k);  
                 rset[k_pos++] = k;  
             }  
         }  
     }  
       
     if (k_pos == 0) {  
         free (rset);  
         return 0;  
     }  
   
     err = gpgme_new (&ctx);  
     if (err)  
         BUG (NULL);  
     n=k_pos;  
     for (i=0; i < k_pos; i++) {  
         err = gpgme_op_delete (ctx, rset[i], with_seckey);  
         if (err)  
             msg_box (dlg, gpgme_strerror (err), _("Key Manager"), MB_ERR);  
         else  
             n--;  
     }  
     if (n == 0)  
         show_msg (dlg, 1500, _("GnuPG Status: Finished"));  
     gpgme_release (ctx);  
     listview_del_items (lv);  
     delete_keys_from_cache (rset, k_pos);  
     free (rset);  
   
     return (int)err;  
 }  
   
   
 int  
 km_send_to_keyserver (listview_ctrl_t lv, HWND dlg, const char * host, u16 port)  
 {  
     char keyid[32];  
     const char *t;  
     int id;  
       
     id = listview_get_curr_pos( lv );  
     if( id == -1 ) {  
         msg_box( dlg, _("Please select a key."), _("Key Manager"), MB_ERR );  
         return WPTERR_GENERAL;  
     }  
   
     listview_get_item_text( lv, id, 1, keyid, sizeof keyid - 1 );  
     id = log_box (_("Key Manager"), MB_YESNO,  
                   _("Do you really want to send '%s' to keyserver %s?"),  
                     keyid, host);  
     if (id == IDYES) {  
         t = keyid;  
         if (!strncmp (keyid, "0x", 2))  
             t += 2;  
         hkp_send_key (dlg, host, port, t);  
     }  
   
     return 0;  
 } /* km_send_to_keyserver */  
   
   
 int  
 km_send_to_mail_recipient( listview_ctrl_t lv, HWND dlg )  
 {  
 #if 0 /*FIXME*/  
     gpgme_key_t key;  
     gpgme_ctx_t ctx=NULL;  
     gpgme_recipients_t rset=NULL;  
     gpgme_error_t rc;  
     const char * s;  
     char keyid[32], tmp[192+256], * p =NULL;  
     int pos;  
   
     if( listview_count_items( lv, 1 ) > 1 ) {  
         msg_box( dlg, _("Please only select one key."), _("Key Manager"), MB_INFO|MB_OK );  
         return WPTERR_GENERAL;  
     }  
     pos = listview_get_curr_pos( lv );  
     if( pos == -1 ) {  
         msg_box( dlg, _("Please select a key."), _("Key Manager"), MB_ERR );  
         return WPTERR_GENERAL;  
     }  
     listview_get_item_text( lv, pos, 1, keyid, sizeof keyid-1 );  
     if( get_pubkey( keyid, &key ) )  
         BUG( NULL );  
     s = key->uids->name;  
     GetTempPath (sizeof tmp-1, tmp);  
     strncat (tmp, s, sizeof tmp-200);  
     strncat (tmp, ".asc", sizeof tmp-200);  
     p = fm_quote_file (tmp);  
   
     rc = gpgme_recipients_new( &rset );  
     if( !rc )  
         rc = gpgme_recipients_add_name( rset, keyid );  
     if( !rc )  
         rc = gpgme_new( &ctx );  
     if( !rc ) {  
         gpgme_set_armor (ctx, 1);  
         rc = gpgme_op_file_export( ctx, rset, p );  
     }  
     if( rc )  
         msg_box( dlg, gpgme_strerror( rc ), _("Key Manager"), MB_ERR );  
     else  
         mapi_send_pubkey (keyid, tmp);  
     free_if_alloc( p );  
     gpgme_recipients_release( rset );  
     gpgme_release( ctx );      
     return rc;  
 #endif  
     return 0;  
 }  
   
   
 static void  
 km_refresh_one_key (listview_ctrl_t lv, HWND dlg, int pos)  
 {  
     int idx;  
     char keyid[32];  
     const char *t;  
   
     if (pos != 0)  
         idx = pos;  
     else  
         idx = listview_get_curr_pos (lv);  
     if (idx != -1)  
     {  
         listview_get_item_text (lv, idx, 1, keyid, sizeof keyid - 1);  
         t = keyid;  
         if (!strncmp (keyid, "0x", 2))  
             t += 2;  
         hkp_recv_key (dlg, default_keyserver, default_keyserver_port, t, 0, KM_KS_REFRESH);  
     }  
 }  
   
   
 void  
 km_refresh_from_keyserver (listview_ctrl_t lv, HWND dlg)  
 {  
     int idx, id, i;  
       
     if (kserver_check_inet_connection ())  
     {  
         msg_box (dlg, _("Could not connect to keyserver, abort procedure."),  
                  _("Key Manager"), MB_ERR);  
         return;  
     }  
     idx = listview_count_items (lv, 0);  
     if (listview_count_items (lv, 1) == idx) {  
         id = msg_box (dlg, _("Do you really want to refresh all keys in the keyring?"), _("Key Manager"), MB_YESNO);  
         if (id == IDNO)  
             return;  
         for (i = 0; i < idx; i++)  
             km_refresh_one_key (lv, dlg, i);  
     }  
     else if (idx == 1)  
         km_refresh_one_key (lv, dlg, 0);  
     else {  
         for (i=0; i < listview_count_items (lv, 0); i++) {  
             if (listview_get_item_state (lv, i))  
                 km_refresh_one_key (lv, dlg, i);  
         }  
     }  
 } /* km_refresh_from_keyserver */  
   
   
 void  
 km_set_clip_info (const char *uid)  
 {      
     char buf[256];  
       
     key_get_clip_info (uid, buf, 255);      
     set_clip_text (NULL, buf, strlen (buf));  
 } /* km_set_clip_info */  
   
   
   
 /* Return TRUE if the key in the list @lv at pos @pos is an  
    old version 3 key. */  
 int  
 km_key_is_v3 (listview_ctrl_t lv, int pos)  
 {  
     gpgme_key_t pk;  
     char keyid[32];  
   
     listview_get_item_text (lv, pos, 1, keyid, sizeof keyid-1);  
     if (get_pubkey (keyid, &pk))  
         BUG (NULL);  
     if (strlen (pk->subkeys->fpr) == 32 &&  
         pk->subkeys->pubkey_algo == GPGME_PK_RSA)  
         return -1;  
     return 0;  
 }  
   
   
 /* Update the default key entry in the status bar for dialog @dlg. */  
 void  
 km_update_default_key_str (HWND dlg)  
 {  
     char *keyid, defkeyinf[512];  
     const char *fmt;  
       
     /* XXX: also show the name? */  
     keyid = get_gnupg_default_key ();  
     if (!keyid)  
         BUG (0);  
     if( (keyid[0] >= 'A' && keyid[0] <= 'Z') || (keyid[0] >= 'a' && keyid[0] <= 'z')  
         || (keyid[0] == '0' && keyid[1] == 'x') )  
         fmt = _("Default Key: %s");  
     else  
         fmt = _("Default Key: 0x%s");  
     _snprintf (defkeyinf, sizeof defkeyinf - 1, fmt, keyid);  
     SendMessage (dlg, SB_SETTEXT, 0, (LPARAM)defkeyinf);  
     free_if_alloc (keyid);  
 }  
   
   
 /* Count all keys and show from @lv results in the status bar @sb. */  
 void  
 km_complete_status_bar (HWND sb, listview_ctrl_t lv)  
 {  
     char txt_sec[128], txt_pub[128];  
     int nkeys = 0, nsec = 0, i;  
   
     nkeys = listview_count_items (lv, 0);  
     for (i = 0; i < nkeys; i++) {  
         if (km_check_for_seckey (lv, i, NULL))  
             nsec++;  
     }  
     _snprintf (txt_sec, sizeof (txt_sec)-1, _("%d secret keys"), nsec);  
     _snprintf (txt_pub, sizeof (txt_pub)-1, _("%d keys"), nkeys);  
     SendMessage (sb, SB_SETTEXT, 1, (LPARAM)txt_sec);  
     SendMessage (sb, SB_SETTEXT, 2, (LPARAM)txt_pub);  
 }  
   
   
 /* Set trust of selected key in @lv (at @pos) to ultimate. */  
 int  
 km_set_implicit_trust (HWND dlg, listview_ctrl_t lv, int pos)  
 {  
     GpgKeyEdit *ke;  
     gpgme_error_t err;      
     char keyid[32];  
   
     listview_get_item_text (lv, pos, 1, keyid, 31);  
   
     ke = new GpgKeyEdit (keyid);  
     if (!ke)  
         BUG (0);  
   
     err = ke->setTrust (GPGME_VALIDITY_ULTIMATE);  
     if (err)  
         msg_box (dlg, gpgme_strerror (err), _("Key Manager"), MB_ERR);  
     else  
         show_msg (dlg, 1500, _("GnuPG Status: Finished"));  
   
     delete ke;  
     return (int)err;  
 }  
   
   
 void  
 km_find_key (HWND dlg, listview_ctrl_t lv)  
 {  
     int oldpos = listview_get_curr_pos (lv);  
     int n;  
     char *name = get_input_dialog (dlg, _("Search"), _("Search for:"));  
     if (name == NULL)  
         return;  
     if (oldpos < 0)  
         oldpos = 0;  
     n = listview_find (lv, name);  
     if (n != -1) {  
         listview_select_one (lv, n);  
         listview_scroll (lv, oldpos, n);  
     }  
     else {  
         const char *s = _("String pattern \"%s\" not found.");  
         char *p = new char[strlen (s) + strlen (name) + 2];  
         if (!p)  
             BUG (0);  
         sprintf (p, s, name);  
         msg_box (dlg, p, _("Key Manager"), MB_INFO);  
         free_if_alloc (p);  
     }  
     free_if_alloc (name);  
 }  
   
   
   
 void  
 km_dump_key (gpgme_key_t key)  
 {  
 #if _DEBUG  
     log_box ("DEBUG", MB_OK,  
              "%d %d %s %d\n%s", key->subkeys->length,  
              key->subkeys->pubkey_algo,  
              key->subkeys->keyid,  
              key->subkeys->timestamp,  
              key->uids->uid);  
 #endif  
 }  
   
 #if 0  
 gpg_optfile_t  
 km_groupdb_open (void)  
 {        
     gpg_optfile_t opt;  
     char * optfile;  
     int err = 0;  
       
     optfile = get_gnupg_cfgfile();  
     if( !optfile )  
         BUG( NULL );  
     if( parse_gpg_options( optfile, &opt ) )  
         err = 1;  
     free_if_alloc( optfile );  
     return err? NULL : opt;  
 } /* km_groupdb_open */  
   
   
 int  
 km_groupdb_expand_recipients( const char *name, gpgme_recipients_t rset )  
 {    
     gpg_keycache_t kc;  
     gpgme_key_t pk;  
     gpg_optfile_t opt;  
     gpg_group_t grp;      
     gpg_member_t mbr;  
     int no_trust = 0, n;  
   
     kc = keycache_get_ctx( 1 );  
     if( !kc )  
         BUG( NULL );  
   
     opt = km_groupdb_open( );  
     if( !opt )  
         return WPTERR_FILE_OPEN;  
       
     grp = find_group( opt, name );  
     if( !grp )  
         return WPTERR_GENERAL;  
       
     /* we are paranoid and check that all group members exist in the  
        key cache. there is no need that it is really the real key, but  
        an entry should be available. the rest is up to GPG. */  
     for( mbr = grp->list; mbr; mbr = mbr->next ) {  
         if( gpgme_keycache_find_key( kc, mbr->name, 0, &pk ) )  
             BUG( NULL );  
         n = count_userids (pk);  
         while( n-- ) {  
             gpgme_user_id_t u = get_nth_userid (pk, n);  
             const char * s =  u->uid;  
             if( s && stristr( s, mbr->name )  
                 && u->validity < 3 )  
                 no_trust++;  
         }  
     }  
   
     gpgme_recipients_add_name( rset, name );  
     release_gpg_options( opt );  
       
     return no_trust;  
 } /* km_groupdb_expand_recipients */  
   
   
 static HTREEITEM  
 km_tv_insert_item( HWND tree, HTREEITEM parent, const char *text )  
 {  
     TVINSERTSTRUCT tvis;  
     HTREEITEM node;  
       
     memset( &tvis, 0, sizeof tvis );  
     tvis.hParent = parent;  
     tvis.hInsertAfter = TVI_LAST;  
     tvis.item.mask = TVIF_TEXT;  
     tvis.item.pszText = (char *)text;  
     node = TreeView_InsertItem( tree, &tvis );  
     return node;  
 } /* km_tv_insert_item */  
   
   
 int  
 km_groups_new( km_group_t *r_gc, HWND ctrl )  
 {  
     km_group_t gc;  
       
     gc = new km_group_s;  
     if (!gc)  
         BUG (NULL);  
     gc->tree = ctrl;  
     gc->gh = km_groupdb_open ();  
     *r_gc = gc;  
     return 0;  
 } /* km_groups_new */  
   
   
 void  
 km_groups_sync( km_group_t gc )  
 {  
     char * optfile;  
   
     optfile = get_gnupg_cfgfile ();  
     if( !optfile )  
         BUG( NULL );  
     commit_gpg_options( optfile, gc->gh );  
     free_if_alloc( optfile );  
     gc->need_sync = 0;  
 } /* km_groups_sync */  
   
   
 void  
 km_groups_release (km_group_t gc)  
 {  
     if( gc ) {  
         /* xxx: this reset the default key (sync=1) */  
         gc->need_sync=0;  
         if (gc->need_sync)  
             km_groups_sync (gc);  
         if (gc->gh)  
             release_gpg_options( gc->gh );  
         gc->gh = NULL;  
         gc->tree = NULL;  
         delete gc;  
     }      
 } /* km_groups_release */  
   
   
 int  
 km_groups_load( km_group_t gc )  
 {      
     HTREEITEM n;  
     gpg_group_t grp, g;  
     gpg_member_t mbr;  
     u32 gid = 0;  
       
     if( !gc->gh )  
         return 0;  
     grp = gc->gh->grp;  
     if( !grp )  
         return 0; /* no groups */  
           
     for( g = grp; g; g = g->next ) {  
         n = km_tv_insert_item( gc->tree, NULL, g->name );  
         for( mbr = g->list; mbr; mbr = mbr->next ) {  
             if( mbr->used && mbr->name )  
                 km_tv_insert_item( gc->tree, n, mbr->name );  
         }  
     }  
     DragAcceptFiles( gc->tree, TRUE );  
     gc->need_sync = 0;  
     return 0;  
 } /* km_groups_load */  
   
   
 int  
 km_groups_add( km_group_t gc, listview_ctrl_t lv, int km_index )  
 {  
     TVITEM tvi;  
     char uid[128], valid[64], text[128];  
     int i_valid;  
       
     memset( &tvi, 0, sizeof tvi );  
     tvi.hItem = TreeView_GetSelection( gc->tree );  
     tvi.pszText = text;  
     tvi.cchTextMax = sizeof text -1;  
     tvi.mask = TVIF_TEXT;  
     TreeView_GetItem( gc->tree, &tvi );  
       
       
     listview_get_item_text( lv, km_index, 0, uid, sizeof uid -1 );  
     listview_get_item_text( lv, km_index, 5, valid, sizeof valid -1 );  
       
     if( strstr( valid, "Ultimate" ) )  
         i_valid = 5;      
     else if( !strstr( valid, "Full" ) )  
         i_valid = 4;  
     else if( !strstr( valid, "Marginal" ) )  
         i_valid = 3;  
     else  
         i_valid = 0;  
       
     /* we can't add the full name. one way would be to use the first  
        text until a space appears.  
     group_add_entry(&gc->gh, gid, i_valid, uid);  
     treeview_add_item(gc->tree, tvi.hItem, uid);  
     */  
     gc->need_sync = 1;  
       
     return 0;  
 } /* km_groups_add */  
   
   
 static int  
 km_groups_del_main( km_group_t gc )  
 {  
     TVITEM tvi;  
     char text[128];  
     int id;  
       
     memset( &tvi, 0, sizeof tvi );  
     tvi.hItem = TreeView_GetSelection( gc->tree );  
     tvi.pszText = text;  
     tvi.cchTextMax = sizeof text -1;  
     tvi.mask = TVIF_TEXT;  
     TreeView_GetItem( gc->tree, &tvi );  
                               
     id = log_box( _("Key Manager"), MB_INFO_ASK,  
                    _("Do you really want to delete this group?\n\n%s"), text);  
     if( id == IDNO )  
         return 0;  
     delete_group( gc->gh, text );      
     TreeView_DeleteItem( gc->tree, &tvi );  
     gc->need_sync = 1;  
       
     return 0;  
 } /* km_groups_del */  
   
   
 static int  
 km_groups_del_entry( km_group_t gc )  
 {  
     TVITEM tvi;  
     HTREEITEM root;  
     int id;  
     char text[128], info[256];  
     gpg_group_t  grp = NULL;  
       
     memset( &tvi, 0, sizeof tvi );  
     tvi.hItem = TreeView_GetSelection( gc->tree );  
     tvi.pszText = text;  
     tvi.cchTextMax = sizeof text-1;  
     tvi.mask = TVIF_TEXT;  
     TreeView_GetItem( gc->tree, &tvi );  
       
     _snprintf( info, sizeof info -1,  
               _("Do you really want to delete this entry?\n\n%s"), text );  
       
     id = msg_box( gc->tree, info, _("Key Manager"), MB_INFO_ASK );  
     if( id == IDNO )  
         return 0;  
   
     root = TreeView_GetParent( gc->tree, tvi.hItem );  
     if( root ) {  
     }  
       
     delete_member( gc->gh, /*fixme*/NULL, text );  
     TreeView_DeleteItem( gc->tree, &tvi );  
     gc->need_sync = 1;  
     return 0;  
 } /* km_groups_del_entry */  
   
   
 int  
 km_groups_del( km_group_t gc )  
 {  
     if ( TreeView_GetParent( gc->tree, TreeView_GetSelection( gc->tree ) ) )  
         return km_groups_del_entry( gc );  
     else  
         return km_groups_del_main( gc );  
 } /* km_groups_del */  
 #endif  
1    /* wptKeyManager.cpp - Handy functions for the Key Manager dialog
2     *      Copyright (C) 2001-2006 Timo Schulz
3     *      Copyright (C) 2005 g10 Code GmbH
4     *
5     * This file is part of WinPT.
6     *
7     * WinPT is free software; you can redistribute it and/or
8     * modify it under the terms of the GNU General Public License
9     * as published by the Free Software Foundation; either version 2
10     * of the License, or (at your option) any later version.
11     *  
12     * WinPT 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 GNU
15     * General Public License for more details.
16     */
17    #ifdef HAVE_CONFIG_H
18    #include <config.h>
19    #endif
20    
21    #include <windows.h>
22    #include <commctrl.h>
23    #include <assert.h>
24    #include <stdio.h>
25    
26    #include "gpgme.h"
27    #include "resource.h"
28    #include "wptTypes.h"
29    #include "wptW32API.h"
30    #include "wptVersion.h"
31    #include "wptCommonCtl.h"
32    #include "wptNLS.h"
33    #include "wptErrors.h"
34    #include "wptContext.h"
35    #include "wptGPG.h"
36    #include "wptKeylist.h"
37    #include "wptFileManager.h"
38    #include "wptDlgs.h"
39    #include "wptKeyserver.h"
40    #include "wptKeyManager.h"
41    #include "wptKeylist.h"
42    #include "wptHTTP.h"
43    #include "wptKeyEdit.h"
44    #include "wptImport.h"
45    #include "wptCrypto.h"
46    #include "wptUTF8.h"
47    #include "wptGPGME.h"
48    #include "StringBuffer.h"
49    
50    
51    /* Remove all kind of invalid characters which would
52       result in an illegal file name. */
53    void
54    secure_filename (char *file, size_t len)
55    {
56        char *p = file;
57        size_t i;
58    
59        /* XXX: it is possible that the recipient has a different
60                charset and thus maybe 8-bit chars should be stripped also. */
61        for (i=0; i < len; i++) {
62            if (p[i] == ' ' || p[i] == ':' || p[i] == '?' || p[i] == '|' ||
63                p[i] == '\\' || p[i] == '/')
64                p[i] = '_';
65        }
66    }
67    
68    
69    /* Return a user friendly key representation in @buf of
70       the key given by @keyid. */
71    void
72    key_get_clip_info (const char *keyid, char *buf, size_t buflen)
73    {
74        winpt_key_s key;
75        gpgme_key_t pk;
76    
77        memset (&key, 0, sizeof (key));
78        if (winpt_get_pubkey (keyid, &key))
79            BUG (NULL);
80        pk = key.ctx;
81        _snprintf (buf, buflen-1,
82                   "pub %04d%s/%s %s %s\r\n"
83                   "    Primary key fingerprint: %s\r\n",
84                   pk->subkeys->length,
85                   get_key_pubalgo2 (pk->subkeys->pubkey_algo),
86                   pk->subkeys->keyid+8,
87                   get_key_created (pk->subkeys->timestamp),
88                   key.ext->uids->uid,
89                   get_key_fpr (pk));
90    }
91    
92    
93    /* Return a general description of the key @key. */
94    char*
95    km_key_get_info (winpt_key_t key, int is_sec)
96    {
97        gpgme_key_t pk;
98        StringBuffer p;
99        char *inf;
100    
101        pk = key->ctx;
102        p = (is_sec? "sec": "pub");
103        p = p + (int)pk->subkeys->length + get_key_pubalgo2 (pk->subkeys->pubkey_algo);
104        p = p + "/0x" + (pk->subkeys->keyid+8);
105        p = p + " " + get_key_created (pk->subkeys->timestamp) + "\n";
106        p = p + "  \"" + key->ext->uids->uid + "\"";  
107        inf = p.getBufferCopy ();
108        return inf;
109    }
110    
111    
112    /* Retrieve the opaque 32-bit param stored within the list view item
113       at position @idx and return the gpgme key context. */
114    gpgme_key_t
115    km_get_key_ptr (listview_ctrl_t lv, int idx, struct keycache_s **r_ctx)
116    {
117        struct keycache_s *ctx;
118    
119        ctx = (struct keycache_s *)listview_get_item2 (lv, idx);
120        if (!ctx)
121            BUG (0);
122        if (r_ctx)
123            *r_ctx = ctx;
124        return ctx->key;
125    }
126    
127    
128    /* Check if list view @lv contains a secret key at position @pos.
129       If utrust is valid, set it to 1 if the key is valid -1 otherwise.
130       Return value: 1 normal key, 2 smart card key. */
131    int
132    km_check_for_seckey (listview_ctrl_t lv, int pos, int *utrust)
133    {
134        gpgme_key_t key;
135        winpt_key_s sk;
136        int type = 0;
137        
138        key = km_get_key_ptr (lv, pos, NULL);
139        if (utrust)
140            *utrust = 0;
141        memset (&sk, 0, sizeof (sk));
142        if (!winpt_get_seckey (key->subkeys->keyid+8, &sk))
143            type = 1;
144        if (sk.ext && sk.ext->gloflags.divert_to_card)
145            type = 2;
146        if (utrust && (key->expired || key->revoked))
147            *utrust = -1;
148        else if (utrust && key->owner_trust == GPGME_VALIDITY_ULTIMATE)
149            *utrust = 1;
150        return type;
151    }
152    
153    
154    /* Check if the key at position @pos is protected with a passwd. */
155    int
156    km_check_if_protected (listview_ctrl_t lv, int pos)
157    {
158        gpgme_key_t key;
159        winpt_key_s k;
160    
161        key = km_get_key_ptr (lv, pos, NULL);
162        if (!key)
163            return 1; /* assume yes */
164        winpt_get_pubkey (key->subkeys->keyid, &k);
165        return k.is_protected;
166    }
167    
168    
169    /* Check if the key has a good status.
170       Return value: 0 on success. */
171    int
172    km_check_key_status (listview_ctrl_t lv, int pos)
173    {
174        int flags = km_get_key_status (lv, pos);
175        
176        if (flags & KM_FLAG_EXPIRED) {
177            msg_box (lv->ctrl, _("This key has expired!\n"  
178                                 "Key check failed."), _("Key Manager"), MB_ERR);
179            return -1;
180        }
181        else if (flags & KM_FLAG_REVOKED) {
182            msg_box (lv->ctrl, _("This key has been revoked by its owner!\n"
183                                 "Key check failed."), _("Key Manager"), MB_ERR);
184            return -1;
185        }
186    
187        return 0;
188    }
189    
190    
191    /* Return all key flags ORed. */
192    int
193    km_get_key_status (listview_ctrl_t lv, int pos)
194    {
195        gpgme_key_t key;
196        int flags = 0;
197    
198        if (pos == -1)
199            return 0;
200        key = km_get_key_ptr (lv, pos, NULL);
201        if (!key)
202            return 0;
203    
204        if (key->expired)
205            flags |= KM_FLAG_EXPIRED;
206        if (key->revoked)
207            flags |= KM_FLAG_REVOKED;
208        if (key->disabled)
209            flags |= KM_FLAG_DISABLED;
210        return flags;
211    }
212    
213    
214    /* Interface to enable or disable a key (@enable = 1 then enable).
215       The key is retrieved from a list control @lv at the pos @pos. */
216    int
217    km_enable_disable_key (listview_ctrl_t lv, HWND dlg, int pos, int enable)
218    {
219        gpgme_error_t err;
220        gpgme_key_t key;
221        GpgKeyEdit *ke;
222    
223        key = km_get_key_ptr (lv, pos, NULL);
224        ke = new GpgKeyEdit (key->subkeys->keyid);
225        if (!ke)
226            BUG (NULL);
227    
228        err = enable? ke->enable () : ke->disable ();
229        if (!err)
230            show_msg (dlg, 1500, _("Key status changed."));
231        else
232            msg_box (dlg, gpgme_strerror (err), _("Key Manager"), MB_ERR);
233        delete ke;
234        return err? WPTERR_GENERAL : 0;
235    }
236    
237    
238    
239    /* Create a string that contain all keyids from
240       the key list @rset separated by a space. */
241    char*
242    gpg_keylist_to_pattern (gpgme_key_t *rset, size_t n)
243    {
244        char *p;
245        size_t i;
246    
247        if (!n)
248            return NULL;
249        p = (char *)calloc (1, n*(16+1)+n+2);
250        if (!p)
251            BUG (NULL);
252        for (i=0; i < n; i++) {
253            strcat (p, rset[i]->subkeys->keyid);
254            strcat (p, " ");
255        }
256        return p;
257    }
258    
259    
260    /* Export the selected keys in @lv to the clipboard. */
261    int
262    km_clip_export (HWND dlg, listview_ctrl_t lv)
263    {
264        gpgme_error_t err;
265        gpgme_key_t *rset;
266        GPGME *ctx;
267        char *patt=NULL;
268        char buf[256];
269        size_t n=0;
270        int rc=0;
271        
272        rset = keylist_enum_recipients (lv, KEYLIST_LIST, &n);
273        if (!n) {
274            msg_box (dlg, _("No key was selected for export."),
275                     _("Key Manager"), MB_ERR);
276            return WPTERR_GENERAL;
277        }
278        
279        patt = gpg_keylist_to_pattern (rset, n);
280    
281        ctx = new GPGME ();
282        if (!ctx)
283            BUG (0);
284        ctx->setArmor (true);
285        err = ctx->exportToClipboard (patt);
286        if (err) {
287            msg_box (dlg, gpgme_strerror (err), _("Key Manager"), MB_ERR);
288            rc = WPTERR_GENERAL;
289            goto leave;
290        }
291        if (n == 1) {
292            key_get_clip_info (rset[0]->subkeys->keyid, buf, DIM (buf)-1);
293            set_clip_text2 (NULL, buf, strlen (buf), 0);
294        }
295    
296        show_msg (dlg, 1500, _("GnuPG Status: Finished"));
297        
298    leave:
299        safe_free (rset);
300        safe_free (patt);
301        delete ctx;
302        return rc;
303    }
304    
305    
306    /* Export the selected secret key from @lv into @fname.
307       It is only allowed to export a single secret key. */
308    int
309    km_privkey_export (HWND dlg, listview_ctrl_t lv, const char *fname)
310    {
311        gpgme_key_t *rset;
312        gpgme_error_t err;
313        size_t n = 0;
314    
315        rset = keylist_enum_recipients (lv, KEYLIST_LIST, &n);
316        if (!n) {
317            msg_box (dlg, _("No key was selected for export."),
318                     _("Key Manager"), MB_ERR);
319            return WPTERR_GENERAL;
320        }
321        if (n > 1) {
322            msg_box (dlg, _("Only one secret key can be exported."),
323                     _("Key Manager"), MB_ERR);
324            free (rset);
325            return 0; /* we checked this before, so we just quit */
326        }
327    
328        err = gpg_export_seckey (rset[0]->subkeys->keyid, fname);
329        if (err)
330            msg_box (dlg, gpgme_strerror (err), _("Key Manager"), MB_ERR);
331        else
332            log_box (_("Key Manager"), MB_OK,
333                     _("Secret key successfully saved in '%s'."), fname);
334    
335        safe_free (rset);
336        return err? WPTERR_GENERAL : 0;
337    }
338    
339    
340    /* Export the selected recipients from @lv into the file @fname. */
341    int
342    km_file_export (HWND dlg, listview_ctrl_t lv, const char *fname)
343    {
344        GPGME *ctx;
345        gpgme_key_t *rset;
346        gpgme_error_t err;
347        char *patt;
348        size_t n;
349    
350        rset = keylist_enum_recipients (lv, KEYLIST_LIST, &n);
351        if (!n) {
352            msg_box (dlg, _("No key was selected for export."),
353                     _("Key Manager"), MB_ERR);
354            return WPTERR_GENERAL;
355        }
356        patt = gpg_keylist_to_pattern (rset, n);
357    
358        ctx = new GPGME ();
359        ctx->setArmor (true);
360        err = ctx->exportToFile (patt, fname);
361        if (err) {
362            msg_box (dlg, gpgme_strerror (err), _("Key Manager"), MB_ERR);
363            goto leave;
364        }
365        else
366            log_box (_("Key Manager"), MB_OK,
367                     _("Key(s) successfully saved in '%s'."), fname);
368        
369    leave:
370        delete ctx;
371        safe_free (patt);
372        return (int)err;
373    }
374    
375    
376    /* Read a dash escaped key from the clipboard
377       unescape it and write it back. */
378    static int
379    extract_dash_escaped_key (void)
380    {
381        gpgme_data_t inp, plain;
382        gpgme_error_t err;
383    
384        err = gpg_data_new_from_clipboard (&inp, 0);
385        if (err) {
386            msg_box (NULL, gpgme_strerror (err), _("Key Manager"), MB_ERR);
387            return -1;
388        }
389        gpg_data_extract_plaintext (inp, &plain);
390        gpg_data_release_and_set_clipboard (plain, 0);
391        gpgme_data_release (inp);
392    
393        return 0;
394    }
395    
396    
397    /* Import keys from the clipboard. */
398    int
399    km_clip_import (HWND dlg, int *r_newkeys, int *r_newsks)
400    {
401        gpgme_error_t err;  
402        gpgme_import_result_t res;
403        GPGME *gpg = NULL;
404        fm_state_s fm_stat;
405        int pgptype;
406        int id, has_data = 0;
407        int new_keys = 0, new_sks = 0;
408    
409        if (!gpg_clip_istext_avail (&has_data) && !has_data) {
410            msg_box (dlg, winpt_strerror (WPTERR_CLIP_ISEMPTY),
411                     _("Key Manager"), MB_ERR);
412            return WPTERR_CLIP_ISEMPTY;
413        }
414        err = gpg_clip_is_secured (&pgptype, &has_data);
415        if (err)
416            msg_box (dlg, gpgme_strerror (err), _("Key Manager"), MB_ERR);
417        if (!has_data) {
418            msg_box (dlg, _("No valid OpenPGP data found."),
419                     _("Key Manager"), MB_ERR);
420            return WPTERR_NODATA;
421        }
422        if (!(pgptype & PGP_PUBKEY) && !(pgptype & PGP_SECKEY)) {
423            msg_box (dlg, _("No valid OpenPGP keys found."),
424                     _("Key Manager"), MB_ERR);
425            return WPTERR_NODATA;
426        }
427        if (pgptype & PGP_DASH_ESCAPED) {
428            id = msg_box (dlg, _("The key you want to import is dash escaped.\n"
429                                 "Do you want to extract the key?"),
430                          _("Key Manager"), MB_YESNO);
431            if (id == IDYES)
432                extract_dash_escaped_key ();
433            else
434                msg_box (dlg, _("Cannot import dash escaped OpenPGP keys."),
435                         _("Key Manager"), MB_INFO);
436        }
437    
438        memset (&fm_stat, 0, sizeof (fm_stat));
439        fm_stat.opaque = m_strdup ("Clipboard");
440        fm_stat.import.is_clip = 1;
441        has_data = dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_IMPORT, dlg,
442                                     file_import_dlg_proc, (LPARAM)&fm_stat,
443                                     _("Key Import"), IDS_WINPT_IMPORT);
444        if (!has_data)
445            goto leave;
446    
447        gpg = new GPGME ();
448        err = gpg->importFromClipboard ();
449        if (err) {
450            msg_box (dlg, gpgme_strerror (err), _("Import"), MB_ERR);
451            goto leave;
452        }
453    
454        res = gpg->importGetResult ();
455        print_import_status (res);
456        new_keys = res->considered - res->unchanged;
457        new_sks = res->secret_imported - res->secret_unchanged;
458        if (res->no_user_id > 0) {
459            msg_box (dlg, _("Key without a self signature was dectected!\n"
460                            "(This key is NOT usable for encryption, etc)\n"),
461                            _("Import"), MB_WARN);
462        }
463    
464    leave:
465        if (gpg)
466            delete gpg;
467        free_if_alloc (fm_stat.opaque);
468        if (r_newkeys)
469            *r_newkeys = new_keys;
470        if (r_newsks)
471            *r_newsks = new_sks;
472        if (!new_keys || !has_data)
473            return WPTERR_NODATA;
474        return (int)err;
475    }
476    
477    
478    /* Import a key from the http URL @url. */
479    int
480    km_http_import (HWND dlg, const char *url)
481    {
482        FILE *fp;
483        wHTTP *hd;
484        char tmpfile[MAX_PATH+64];
485        int rc = 0, err = 0;
486    
487        if (strncmp (url, "http://", 7)) {
488            log_box (_("Key Import HTTP"), MB_ERR, _("Invalid HTTP URL: %s"), url);
489            return WPTERR_GENERAL;
490        }
491    
492        get_temp_name (tmpfile, DIM (tmpfile)-1, "tmp_winpt_http");
493        fp = fopen (tmpfile, "wb");
494        if (!fp) {
495            log_box (_("Key Import HTTP"), MB_ERR, "%s: %s", tmpfile,
496                     winpt_strerror (WPTERR_FILE_CREAT));
497            return WPTERR_FILE_CREAT;
498        }
499    
500        op_begin ();
501        hd = new wHTTP (url);
502        if (hd->getStatusCode () == HTTP_STAT_200)
503            err = hd->readData (fp);
504        else
505            err = WPTERR_KEYSERVER_NOTFOUND;
506        op_end ();
507        if (err) {
508            log_box (_("HTTP Key Import"), MB_ERR,
509                     _("Could not fetch key from URL: %s"), url);
510            rc = WPTERR_GENERAL;
511        }
512    
513        delete hd;
514        fclose (fp);
515        if (!rc)
516            km_file_import (dlg, tmpfile, NULL, NULL);
517        DeleteFile (tmpfile);
518        return rc;
519    }
520    
521    
522    /* Import a key from the given file @fname, if @fname is
523       NULL use the common 'file open' dialog.
524       On success an import statistics dialog is shown. */
525    int
526    km_file_import (HWND dlg, const char *fname, int *r_newkeys, int *r_newsks)
527    {    
528        gpgme_error_t err;
529        gpgme_import_result_t res;
530        GPGME *gpg;
531        fm_state_s fm_stat;    
532        const char *name;
533        int no_data = 0;
534        int new_keys = 0, new_sks = 0;
535    
536        if (!fname) {
537            name = get_fileopen_dlg (dlg, _("Choose Name of the Key File"),
538                                     NULL, NULL);
539            if (!name)
540                return WPTERR_GENERAL;
541        }
542        else
543            name = fname;
544    
545        memset (&fm_stat, 0, sizeof (fm_stat));
546        fm_stat.opaque = m_strdup (name);
547        
548        dialog_box_param (glob_hinst, (LPCSTR)IDD_WINPT_IMPORT, dlg,
549                          file_import_dlg_proc, (LPARAM)&fm_stat,
550                          _("File Import"), IDS_WINPT_IMPORT);
551        if (fm_stat.cancel == 1) {
552            free_if_alloc (fm_stat.opaque);
553            return WPTERR_GENERAL;
554        }
555        
556        gpg = new GPGME ();
557        err = gpg->importFromFile (name);
558        if (err) {
559            msg_box (dlg, gpgme_strerror (err), _("Import"), MB_ERR);
560            goto leave;
561        }
562    
563        res = gpg->importGetResult ();
564        if (res->unchanged == res->considered &&
565            res->secret_unchanged == res->secret_imported)
566            no_data = 1;
567        new_keys = res->considered - res->unchanged;
568        new_sks = res->secret_imported - res->secret_unchanged;
569        if (res->new_revocations == 0 && fm_stat.import.revcert == 1)
570            res->new_revocations = 1;
571        if (res->secret_imported == 0 && fm_stat.import.has_seckey == 1)
572            res->secret_imported = 1;
573    
574        print_import_status (res);
575        if (res->no_user_id > 0) {
576            msg_box (dlg, _("Key without a self signature was dectected!\n"
577                            "(This key is NOT usable for encryption, etc)\n"),
578                            _("Import"), MB_WARN);
579        }
580    
581    leave:
582        delete gpg;
583        free_if_alloc (fm_stat.opaque);
584        if (r_newkeys)
585            *r_newkeys = new_keys;
586        if (r_newsks)
587            *r_newsks = new_sks;
588        if (no_data)
589            return WPTERR_NODATA;
590        return (int)err;
591    }
592    
593    
594    /* Import all dropped files. */
595    int
596    km_dropped_file_import (HWND dlg, HDROP hdrop,
597                            int *r_newkeys, int *r_newsks)
598    {
599        char name[MAX_PATH+1];
600        UINT n = DragQueryFile (hdrop, 0xFFFFFFFF, NULL, 0);
601        UINT i;
602        int newk=0, newsk=0, err=0;
603    
604        for (i=0; i < n; i++) {
605            DragQueryFile (hdrop, i, name, MAX_PATH);
606            err = km_file_import (dlg, name, &newk, &newsk);
607            *r_newkeys = (*r_newkeys) + newk;
608            *r_newsks = (*r_newsks) + newsk;
609        }
610        DragFinish (hdrop);
611        return err;
612    }
613    
614    
615    /* Mark the keys in @rset as deleted in the keycache. */
616    static void
617    delete_keys_from_cache (gpgme_key_t *rset, size_t n)
618    {
619        gpg_keycache_t pub = keycache_get_ctx (1);
620        gpg_keycache_t sec = keycache_get_ctx (0);
621        gpgme_key_t sk;
622        int i=0;
623    
624        while (n-- > 0) {
625            if (!get_seckey (rset[i]->subkeys->keyid, &sk))
626                gpg_keycache_delete_key (sec, sk->subkeys->keyid);
627            gpg_keycache_delete_key (pub, rset[i]->subkeys->keyid);
628            i++;
629        }
630    }
631    
632    
633    /* Check that the selected default secret key is still
634       available. If not, delete the entry in gpg.conf. */
635    static void
636    check_exist_default_key (void)
637    {
638        gpgme_key_t sk;
639        char *defkey;
640    
641        defkey = get_gnupg_default_key ();
642        if (defkey && get_seckey (defkey, &sk))
643            set_gnupg_default_key (NULL);
644        free_if_alloc (defkey);
645    }
646    
647    
648    /* Delete the list view items which match a key ptr
649       inside the @rset array. */
650    static void
651    lv_del_confirmed_keys (listview_ctrl_t lv, gpgme_key_t *rset, int n_rset)
652    {
653        winpt_key_s key2;
654        int j, i, n = listview_count_items (lv, 0);
655        
656        for (i = n; i > -1; i--) {
657            if (listview_get_item_state (lv, i)) {
658                km_get_key (lv, i, &key2);
659                for (j=0; j < n_rset; j++) {
660                    if (rset[j] == key2.ctx) {
661                        listview_del_item (lv, i);
662                    }
663                }
664            }
665        }
666    }
667    
668    
669    /* Delete all selected keys from the list view @lv. */
670    int
671    km_delete_keys (listview_ctrl_t lv, HWND dlg)
672    {
673        gpgme_error_t err;
674        gpgme_ctx_t ctx;
675        gpgme_key_t *rset;
676        winpt_key_s key2;
677        char *p;
678        int with_seckey=0, seckey_type=0, confirm=0;
679        int i, rc, n, k_pos=0;
680        
681        if (listview_get_curr_pos (lv) == -1) {
682            msg_box (dlg, _("Please select a key."), _("Key Manager"), MB_ERR);
683            return -1;
684        }
685            
686        if (listview_count_items (lv, 1) > 8) {
687            i = msg_box (NULL, _("Do you really want to confirm each key?"),
688                         _("Delete Confirmation"), MB_YESNOCANCEL|MB_ICONQUESTION);
689            if (i == IDCANCEL)
690                return 0;
691            if (i != IDNO)
692                confirm = 1;
693        }
694        else
695            confirm = 1;
696    
697        /* n = total amount of keys, i is the selected amount. */
698        n = listview_count_items (lv, 0);
699        i = listview_count_items (lv, 1);
700        rset = (gpgme_key_t *)calloc (i+1, sizeof (gpgme_key_t));
701        if (!rset)
702            BUG (NULL);
703        for (i = 0; i < n; i++) {
704            if (listview_get_item_state(lv, i)) {
705                km_get_key (lv, i, &key2);
706    
707                seckey_type = km_check_for_seckey (lv, i, NULL);
708                if (confirm && !seckey_type) {
709                    p = km_key_get_info (&key2, 0);
710                    rc = log_box (_("Key Manager"), MB_YESNO|MB_ICONWARNING,
711                                  _("Do you really want to delete this key?\n\n"
712                                    "%s"), p);
713                    if (rc == IDYES)
714                        rset[k_pos++] = key2.ctx;
715                    free_if_alloc (p);
716                }
717                else if (confirm) {
718                    p = km_key_get_info (&key2, 1);
719                    rc = log_box (_("Key Manager"), MB_YESNO|MB_ICONWARNING,                
720                                  _("Do you really want to delete this KEY PAIR?\n\n"
721                                    "Please remember that you are not able to decrypt\n"
722                                    "messages you stored with this key any longer.\n"
723                                    "\n"
724                                    "%s"), p);
725                    if (rc == IDYES) {
726                        if (seckey_type == 2)
727                            msg_box (dlg, _("The actual secret key is stored on a smartcard.\n"
728                                            "Only the public key and the secret key \n"
729                                            "placeholder will be deleted.\n"),
730                                            _("Key Manager"), MB_OK);
731                        rset[k_pos++] = key2.ctx;
732                    }
733                    with_seckey = 1;
734                    free_if_alloc (p);
735                }
736                else {
737                    with_seckey = 1;
738                    rset[k_pos++] = key2.ctx;
739                }
740            }
741        }
742        
743        if (k_pos == 0) {
744            free (rset);
745            return 0;
746        }
747    
748        err = gpgme_new (&ctx);
749        if (err)
750            BUG (NULL);
751        n = k_pos;
752        op_begin ();
753        for (i=0; i < k_pos; i++) {
754            err = gpgme_op_delete (ctx, rset[i], with_seckey);
755            if (err)
756                msg_box (dlg, gpgme_strerror (err), _("Key Manager"), MB_ERR);
757            else
758                n--;
759        }
760        op_end ();
761        if (n == 0)
762            show_msg (dlg, 1500, _("GnuPG Status: Finished"));
763        gpgme_release (ctx);
764        lv_del_confirmed_keys (lv, rset, k_pos);
765        delete_keys_from_cache (rset, k_pos);
766        safe_free (rset);
767        if (with_seckey)
768            check_exist_default_key ();
769        return (int)err;
770    }
771    
772    
773    /* Send the select key in @lv to the keyserver @host:@port. */
774    int
775    km_send_to_keyserver (listview_ctrl_t lv, HWND dlg,
776                          const char *host, WORD port)
777    {
778        winpt_key_s key;
779        int id;
780        
781        id = listview_get_curr_pos (lv);
782        if (id == -1) {
783            msg_box( dlg, _("Please select a key."), _("Key Manager"), MB_ERR );
784            return WPTERR_GENERAL;
785        }
786    
787        km_get_key (lv, id, &key);
788        id = log_box (_("Key Manager"), MB_YESNO,
789                      _("Do you really want to send '0x%s' to keyserver %s?"),
790                      key.keyid, host);
791        if (id == IDYES)
792            hkp_send_key (dlg, host, port, key.keyid);
793    
794        return 0;
795    }
796    
797    
798    /* Send the selected key in @lv via MAPI to a mail recipient. */
799    int
800    km_send_to_mail_recipient (listview_ctrl_t lv, HWND dlg)
801    {
802        gpgme_key_t key;
803        gpgme_error_t rc;
804        GPGME *ctx;
805        struct keycache_s *c;
806        char *fname, *uid;
807        int pos, n;
808    
809        if (listview_count_items (lv, 1) > 1) {
810            msg_box (dlg, _("Please only select one key."),
811                     _("Key Manager"), MB_INFO|MB_OK);
812            return WPTERR_GENERAL;
813        }
814        pos = listview_get_curr_pos (lv);
815        if (pos == -1) {
816            msg_box (dlg, _("Please select a key."), _("Key Manager"), MB_ERR);
817            return WPTERR_GENERAL;
818        }
819        key = km_get_key_ptr (lv, pos, &c);
820        uid = m_strdup (c->uids->name);
821        secure_filename (uid, strlen (uid));
822        n = strlen (uid) + 1 + MAX_PATH + 5;
823        fname = new char[n+1];
824        get_temp_name (fname, n-5-strlen (uid)-1, uid);
825        strcat (fname, ".asc");
826        ctx = new GPGME ();
827        ctx->setArmor (true);
828        rc = ctx->exportToFile (key->subkeys->keyid, fname);
829        if (rc)
830            msg_box (dlg, gpgme_strerror (rc), _("Key Manager"), MB_ERR);
831        else
832            mapi_send_pubkey (key->subkeys->keyid+8, fname);
833    
834        delete ctx;
835        free_if_alloc (fname);
836        free_if_alloc (uid);
837        return rc;
838    }
839    
840    
841    /* Refresh the selected key in the listview @lv at position @pos.
842       Legal flags are 0 = single key. */
843    static int
844    km_refresh_one_key (listview_ctrl_t lv, HWND dlg, int pos, int flags)
845    {
846        winpt_key_s pk;
847        gpgme_key_t key;
848        const char *pref_kserv = default_keyserver;
849        unsigned short pref_kserv_port = default_keyserver_port;
850        char keyid[16+1];
851        int idx, err = 0;
852        
853        if (pos != 0)
854            idx = pos;
855        else
856            idx = listview_get_curr_pos (lv);
857        if (idx != -1) {
858            key = km_get_key_ptr (lv, idx, NULL);
859            
860            /* In single refresh mode, try to use the users preferred keyserver. */
861            if (flags == 0 &&
862                !winpt_get_pubkey (key->subkeys->keyid+8, &pk) &&
863                !gpg_keycache_update_attr (pk.ext, KC_ATTR_PREFKSERV, 0) &&
864                pk.ext->pref_keyserver &&
865                !strstr (pk.ext->pref_keyserver, "ldap://")) {
866                pref_kserv = pk.ext->pref_keyserver;
867                pref_kserv_port = pk.ext->pref_keyserver_port;
868            }
869            _snprintf (keyid, DIM (keyid)-1, "%s", key->subkeys->keyid+8);
870            err = hkp_recv_key (dlg, pref_kserv, pref_kserv_port,
871                                keyid, 0, flags);
872            /* if we receive just a single key (no refresh mode), update it. */
873            if (!flags && !err)
874                keycache_update (0, keyid);
875        }
876        return err;
877    }
878    
879    
880    /* Refresh the selected keys from the default keyserver. */
881    int
882    km_refresh_from_keyserver (listview_ctrl_t lv, HWND dlg)
883    {
884        int cnt, id, i;
885        int err = 0;
886    
887        cnt = listview_count_items (lv, 0);
888        if (listview_count_items (lv, 1) == cnt) {
889            id = msg_box (dlg, _("Do you really want to refresh all keys in the keyring?"),
890                          _("Key Manager"), MB_YESNO);
891            if (id == IDNO)
892                return -1;
893            if (kserver_check_inet_connection ()) {
894                msg_box (dlg, _("Could not connect to keyserver, abort procedure."),
895                         _("Key Manager"), MB_ERR);
896                return -1;
897            }
898        }
899        if (listview_count_items (lv, 1) == 1)
900            err = km_refresh_one_key (lv, dlg, listview_get_curr_pos (lv), 0);
901        else {
902            for (i=0; i < cnt; i++) {
903                if (listview_get_item_state (lv, i))
904                    km_refresh_one_key (lv, dlg, i, KM_KS_REFRESH);
905            }
906        }
907        return err;
908    }
909    
910    
911    void
912    km_set_clip_info (const char *uid)
913    {    
914        char buf[256];
915        
916        key_get_clip_info (uid, buf, DIM (buf)-1);
917        set_clip_text (NULL, buf, strlen (buf));
918    }
919    
920    
921    
922    /* Return TRUE if the key in the list @lv at pos @pos is an
923       old version 3 key. */
924    int
925    km_key_is_v3 (listview_ctrl_t lv, int pos)
926    {
927        gpgme_key_t pk;
928    
929        pk = km_get_key_ptr (lv, pos, NULL);
930        if (strlen (pk->subkeys->fpr) == 32 &&
931            pk->subkeys->pubkey_algo == GPGME_PK_RSA)
932            return -1;
933        return 0;
934    }
935    
936    
937    /* Set trust of selected key in @lv (at @pos) to ultimate. */
938    int
939    km_set_implicit_trust (HWND dlg, listview_ctrl_t lv, int pos)
940    {
941        gpgme_error_t err;
942        gpgme_key_t key;
943        GpgKeyEdit *ke;
944    
945        key = km_get_key_ptr (lv, pos, NULL);
946        ke = new GpgKeyEdit (key->subkeys->keyid);
947        if (!ke)
948            BUG (0);
949    
950        err = ke->setTrust (GPGME_VALIDITY_ULTIMATE);
951        if (err)
952            msg_box (dlg, gpgme_strerror (err), _("Key Manager"), MB_ERR);
953        else
954            show_msg (dlg, 1500, _("GnuPG Status: Finished"));
955    
956        delete ke;
957        return (int)err;
958    }
959    
960    
961    /* Provide a search dialog and try to find and select
962       the key which matches the entered pattern. */
963    void
964    km_find_key (HWND dlg, listview_ctrl_t lv)
965    {
966        int oldpos = listview_get_curr_pos (lv);
967        int n;
968        char *name = get_input_dialog (dlg, _("Search"), _("Search for:"));
969    
970        if (!name)
971            return;
972        if (oldpos < 0)
973            oldpos = 0;
974        n = listview_find (lv, name, 1);
975        if (n != -1) {
976            listview_select_one (lv, n);
977            listview_scroll (lv, oldpos, n);
978        }
979        else {
980            StringBuffer s;
981    
982            s = _("String pattern not found:");
983            s = s + " \"" + name + "\"";
984            msg_box (dlg, s.getBuffer (), _("Key Manager"), MB_INFO);
985        }
986        free_if_alloc (name);
987    }
988    
989    
990    /* Return a user-friendly name for a key derrived from
991       name. If @is_secret is 1, a secret key name will be generated. */
992    char*
993    km_gen_export_filename (const char *keyid, int is_secret)
994    {
995        winpt_key_s key;
996        StringBuffer p;
997        char *name;
998    
999        memset (&key, 0, sizeof (key));
1000        if (winpt_get_pubkey (keyid, &key))
1001            return m_strdup (keyid);
1002        
1003        p = key.ext->uids->name;
1004        p = p + (is_secret? "_sec" : "") + ".asc";
1005    
1006        name = p.getBufferCopy ();
1007        secure_filename (name, strlen (name));
1008        return name;
1009    }
1010    
1011    
1012    /* Retrieve the GPGME pointer from the selected list view
1013       item and return the WinPT specific key context. */
1014    int
1015    km_get_key (listview_ctrl_t lv, int pos, winpt_key_t k)
1016    {
1017        struct keycache_s *c;
1018        gpgme_key_t key;
1019    
1020        if (pos == -1)
1021            return -1;
1022        key = km_get_key_ptr (lv, pos, &c);
1023        memset (k, 0, sizeof (*k));
1024        strncpy (k->tmp_keyid, key->subkeys->keyid+8, 8);
1025        k->keyid = k->tmp_keyid;
1026        k->is_protected = km_check_if_protected (lv, pos);
1027        k->key_pair = km_check_for_seckey (lv, pos, NULL);
1028        k->is_v3 = km_key_is_v3 (lv, pos);
1029        k->flags = km_get_key_status (lv, pos);
1030        k->ctx = key;
1031        k->ext = c;
1032        k->uid = c->uids->uid;
1033        return 0;
1034    }
1035    
1036    
1037    /* Show details of the revocation of the key @k. */
1038    void
1039    km_key_show_revoc_info (winpt_key_t k)
1040    {
1041        const char *desc;
1042        char *val=NULL, *p;
1043        int len, reason;
1044        const char *reasons[] = {
1045            _("0. No reason specified"),
1046            _("1. Key has been compromised"),
1047            _("2. Key is superseded"),
1048            _("3. Key is no longer used"),
1049            NULL
1050        };
1051    
1052        /* spk:29:1:19:%00This key is kaputt */
1053        gpg_find_key_subpacket (k->keyid, 29, &val);    
1054        if (!val || strlen (val) < 3) {
1055            safe_free (val);
1056            return;
1057        }
1058    
1059        len = atoi (val+9);
1060        p = strchr (val+9, ':');
1061        assert (p);
1062        p++;
1063        reason = atoi (p+1);
1064        if (strlen (p+1) > 0)
1065            desc = p+3;
1066        else
1067            desc = "none";
1068        log_box (_("Key Manager"), MB_OK,
1069                 "Key revocation info for '%s':\n"
1070                 "Reason for revocation: %s\n"
1071                 "Description: %s\n",
1072                 k->ctx->uids->name, reasons[reason % 4]+3,
1073                 desc);
1074        safe_free (val);
1075    }

Legend:
Removed from v.33  
changed lines
  Added in v.278

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26