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

Diff of /trunk/Src/wptKeygenDlg.cpp

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

revision 2 by twoaday, Mon Jan 31 11:02:21 2005 UTC revision 130 by twoaday, Fri Dec 30 14:06:39 2005 UTC
# Line 1  Line 1 
 /* wptKeygenDlg.cpp - Key Generation dialog  
  *      Copyright (C) 2000-2004 Timo Schulz  
  *  
  * 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 "../resource.h"  
 #include "wptTypes.h"  
 #include "wptNLS.h"  
 #include "wptGPG.h"  
 #include "wptCommonCtl.h"  
 #include "wptContext.h" /* for passphrase_s */  
 #include "wptDlgs.h"  
 #include "wptW32API.h"  
 #include "wptVersion.h"  
 #include "wptErrors.h"  
 #include "wptUTF8.h"  
   
   
 static void  
 clear_dlg_fields( HWND dlg )  
 {  
     SetDlgItemText( dlg, IDC_KEYGEN_SUBKEYBITS, "" );  
     SetDlgItemText( dlg, IDC_KEYGEN_NAME, "" );  
     SetDlgItemText( dlg, IDC_KEYGEN_EMAIL, "" );  
     SetDlgItemText( dlg, IDC_KEYGEN_COMMENT, "" );  
     SetDlgItemText( dlg, IDC_KEYGEN_EXPDATE, "" );  
     SetDlgItemText( dlg, IDC_KEYGEN_PASSPHRASE, "" );  
     SetDlgItemText( dlg, IDC_KEYGEN_PWDCHECK, "" );  
 } /* clear_dlg_fields */  
   
   
 static void  
 ask_for_backup( HWND dlg )  
 {  
     int id;  
     char * path = NULL, * keyring = NULL;  
     const char * name;  
       
     path = get_gnupg_path( );  
     if( !path )  
         BUG( dlg );  
     id = msg_box( dlg,  
                  _("It is STRONGLY recommend that you backup your keyrings because they both "  
                    "contain VERY important data.\nRemember that your hard disk can crash or the "  
                    "files can be deleted by accident; so it is a good\nidea to store them on "  
                    "a different mass stoarge like a floppy or CDR!\n\n"  
                    "Backup your keyrings now?"),  
                  _("WARNING - Important hint" ), MB_YESNO );  
     if( id == IDYES ) {  
         name = get_filename_dlg( dlg, 1, _("Destination for Public Keyring"), NULL, "pubring.gpg" );  
         if( name ) {  
             keyring = make_filename( path, "pubring", "gpg" );  
             if( !CopyFile( keyring, name, FALSE ) )  
                 log_box( _("Key Generation"), MB_ERR,  
                          _("Could not copy %s -> %s"), keyring, name );      
             free_if_alloc( keyring );  
         }  
         name = get_filename_dlg( dlg, 1, _("Destination for Secret Keyring"), NULL, "secring.gpg" );  
         if( name ) {  
             keyring = make_filename( path, "secring", "gpg" );  
             if( !CopyFile( keyring, name, FALSE ) )  
                 log_box( _("Key Generation"), MB_ERR,  
                          _("Could not copy %s -> %s"), keyring, name );  
             free_if_alloc( keyring );  
         }  
     }  
     free_if_alloc( path );  
 } /* ask_for_backup */  
   
   
 static void  
 fill_keytype_box( HWND dlg )  
 {  
     HWND cb = GetDlgItem( dlg, IDC_KEYGEN_KEYTYPE );  
   
 #define addstr( cb, str ) \  
     SendMessage( (cb), CB_ADDSTRING, 0, (LPARAM)(LPCTSTR)(str) )  
     addstr( cb, _("DSA and ELG (default)") );  
     addstr( cb, _("DSA and RSA") );  
     addstr( cb, _("DSA sign only") );  
     addstr( cb, _("RSA sign only") );  
     addstr( cb, _("RSA sign and encrypt") );  
     addstr( cb, _("RSA and RSA (PGP)") );  
     SendMessage( cb, CB_SETCURSEL, 0, 0 );  
 #undef addstr  
 } /* fill_keytype_box */  
   
   
 static inline int  
 get_keytype( HWND dlg )  
 {  
     HWND cb = GetDlgItem( dlg, IDC_KEYGEN_KEYTYPE );  
     return SendMessage( cb, CB_GETCURSEL, 0, 0 ) + 1;  
 } /* get_keytype */  
   
   
 int  
 keygen_check_date( SYSTEMTIME *st )  
 {        
     SYSTEMTIME t;  
           
     GetSystemTime( &t );  
     if( st->wYear > t.wYear || st->wMonth > t.wMonth )  
         return 1;  
     else if( st->wYear < t.wYear || st->wMonth < t.wMonth || st->wDay < t.wDay)  
         return 0;        
     return 1;  
 } /* keygen_check_date */  
   
   
 BOOL CALLBACK  
 keygen_dlg_proc( HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam )  
 {  
     static int hide = 1;  
     static int act_expdate = 0;  
     SYSTEMTIME st;  
     gpgme_error_t err;  
     char name[128] = {0}, email[128] = {0}, comment[128] = {0};  
     char pwd[128], pwd2[128];  
     char t[64], *expire = NULL;  
     int bits, use_comment, keytype = 0;      
     char * p;    
       
     switch ( msg ) {  
     case WM_INITDIALOG:  
         hide = 1;  
 #ifndef LANG_DE  
         SetWindowText( dlg, _("Key Generation") );  
         SetDlgItemText( dlg, IDC_KEYGEN_INFO,  
                         _("NOTE: Key generation can be a lengthy process! Please wait until "  
                           "you get the message that key generation was finished.") );  
         SetDlgItemText( dlg, IDC_KEYGEN_SUBKEYINF, _("Subkey size in &bits"));  
         SetDlgItemText( dlg, IDC_KEYGEN_NAMEINF, _("&Real name") );  
         SetDlgItemText( dlg, IDC_KEYGEN_COMMINF, _("&Comment (optional)") );  
         SetDlgItemText( dlg, IDC_KEYGEN_EMAILINF, _("Email &address") );  
         SetDlgItemText( dlg, IDC_KEYGEN_EXPINF, _("Key &expiration") );  
         SetDlgItemText( dlg, IDC_KEYGEN_PWDINF, _("&Passphrase") );  
         SetDlgItemText( dlg, IDC_KEYGEN_REPWDINF, _("&Repeat passphrase") );  
         SetDlgItemText( dlg, IDC_KEYGEN_KEYTYPEINF, _("Key &type") );  
         SetDlgItemText (dlg, IDC_KEYGEN_CLEAR, _("&Never"));  
         SetDlgItemText (dlg, IDC_KEYGEN_HIDEPWD, _("&Hide Typing"));  
 #endif  
         SetDlgItemInt( dlg, IDC_KEYGEN_SUBKEYBITS, 2048, FALSE );  
         CheckDlgButton (dlg, IDC_KEYGEN_HIDEPWD, BST_CHECKED);  
         CheckDlgButton (dlg, IDC_KEYGEN_EXPNEVER, BST_CHECKED);  
         EnableWindow (GetDlgItem (dlg, IDC_KEYGEN_EXPDATE), FALSE);  
         fill_keytype_box( dlg );  
         center_window( dlg );  
         SetForegroundWindow( dlg );  
         return TRUE;  
           
     case WM_SYSCOMMAND:  
         if( LOWORD( wparam ) == SC_CLOSE ) {  
             SetDlgItemText( dlg, IDC_KEYGEN_PASSPHRASE, "" );  
             SetDlgItemText( dlg, IDC_KEYGEN_PWDCHECK, "" );  
             EndDialog( dlg, TRUE );  
         }  
         return FALSE;  
           
     case WM_COMMAND:  
         if (HIWORD (wparam) == BN_CLICKED &&  
             LOWORD (wparam) == IDC_KEYGEN_EXPNEVER) {  
             act_expdate ^= 1;  
             EnableWindow (GetDlgItem (dlg, IDC_KEYGEN_EXPDATE), act_expdate);  
         }  
         if( HIWORD( wparam ) == BN_CLICKED  
             && LOWORD( wparam ) == IDC_KEYGEN_HIDEPWD ) {  
             HWND hwnd_a = GetDlgItem( dlg, IDC_KEYGEN_PASSPHRASE );  
             HWND hwnd_b = GetDlgItem( dlg, IDC_KEYGEN_PWDCHECK );  
             hide ^= 1;  
             SendMessage( hwnd_a, EM_SETPASSWORDCHAR, hide? '*' : 0, 0 );  
             SetFocus( hwnd_a );  
             SendMessage( hwnd_b, EM_SETPASSWORDCHAR, hide? '*' : 0, 0 );  
             SetFocus( hwnd_b );  
   
         }  
   
         switch( LOWORD( wparam ) ) {  
         case IDOK:  
             bits = GetDlgItemInt (dlg, IDC_KEYGEN_SUBKEYBITS, NULL, FALSE);  
             if (bits < 1024 || bits > 4096) {  
                 msg_box (dlg, _("Invalid value. Allowed values 1024-4096 bits."),  
                          _("Key Generation"), MB_ERR);  
                 return FALSE;  
             }  
             if (bits > 2048) {  
                 int id = msg_box (dlg, _("Do you really need such a large key?"),  
                                   _("Key Generation"), MB_YESNO);  
                 if (id == IDNO)  
                     bits = 2048;  
             }  
             if( !GetDlgItemText( dlg, IDC_KEYGEN_NAME, name, sizeof name - 1 ) ) {  
                 msg_box( dlg, _("Please enter the name."), _("Key Generation"), MB_ERR );  
                 return FALSE;  
             }  
             if (strchr (name, '@')) {  
                 msg_box (dlg, _("Please do not enter the email address in the name field."),  
                          _("Key Generation"), MB_INFO);  
                 return FALSE;  
             }  
             if( !GetDlgItemText(dlg, IDC_KEYGEN_EMAIL, email, sizeof email -1 )  
                 || !strchr( email, '@') ) {  
                 msg_box( dlg, _("Please enter a valid email address."),  
                          _("Key Generation"), MB_ERR );  
                 return FALSE;  
             }  
             use_comment = GetDlgItemText( dlg, IDC_KEYGEN_COMMENT, comment, sizeof comment -1 );  
             if( use_comment > 0 && strchr( comment, '@' ) ) {  
                 msg_box( dlg, _("Please do NOT enter the email address in the comment field."),  
                          _("Key Generation"), MB_INFO );  
                 return FALSE;  
             }  
             keytype = get_keytype( dlg );  
             if (IsDlgButtonChecked (dlg, IDC_KEYGEN_EXPNEVER))  
                 expire = NULL;  
             else {  
                 DateTime_GetSystemtime (GetDlgItem (dlg, IDC_KEYGEN_EXPDATE), &st);  
                 _snprintf (t, DIM (t)-1, "%04d-%02d-%02d", st.wYear, st.wMonth, st.wDay);  
                 expire = t;  
             }  
               
             if( !GetDlgItemText( dlg, IDC_KEYGEN_PASSPHRASE, pwd, sizeof pwd -1 ) ) {  
                 msg_box( dlg, _("Please enter the passphrase."),  
                          _("Key Generation"), MB_ERR );  
                 return FALSE;  
             }  
             else if( strlen( pwd ) < 8 ) {  
                 int id = msg_box( dlg, _("Your passphrase should be at least 8 characters"  
                                          " long\nand should contain non-alphabetic characters."  
                                          "\n\nStill proceed?"),  
                                     _("Key Generation"), MB_ICONWARNING|MB_YESNO );  
                 if( id == IDNO ) {  
                     SetDlgItemText( dlg, IDC_KEYGEN_PASSPHRASE, "" );  
                     SetDlgItemText( dlg, IDC_KEYGEN_PWDCHECK, "" );  
                     return FALSE;  
                 }  
             }  
             if( !GetDlgItemText( dlg, IDC_KEYGEN_PWDCHECK, pwd2, sizeof pwd2 -1 ) ) {  
                 msg_box( dlg, _("Please repeat the passphrase."),  
                          _("Key Generation"), MB_ERR );  
                 return FALSE;  
             }  
             if( strcmp( pwd, pwd2 ) ) {  
                 msg_box( dlg,  _("Passphrases are NOT identical!" ),  
                          _("Key Generation"), MB_ERR );  
                 memset( pwd, 0, sizeof pwd );  
                 memset( pwd2, 0, sizeof pwd2 );  
                 return FALSE;  
             }  
             if( is_8bit_string( pwd ) ) {  
                 msg_box( dlg, _("The passphrase contains 8-bit characters.\n"  
                                 "It is not suggested to use charset specific characters."),  
                          _("Key Generation"), MB_ERR );  
                 memset( pwd, 0, sizeof pwd );  
                 memset( pwd2, 0, sizeof pwd2 );  
                 SetDlgItemText( dlg, IDC_KEYGEN_PASSPHRASE, "" );  
                 SetDlgItemText( dlg, IDC_KEYGEN_PWDCHECK, "" );  
                 return FALSE;  
             }  
                                   
             if( !use_comment && !strlen( comment ) ) {  
                 char *utf8_name;  
                 utf8_name = wincp_to_utf8 (name, strlen (name));  
                 if( !utf8_name )  
                     BUG( dlg );  
                 p = gpgme_genkey_params( keytype, bits, utf8_name, NULL, email, expire, pwd );  
                 free( utf8_name );  
             }  
             else {  
                 char *utf8_name, *utf8_comment;  
                 utf8_name = wincp_to_utf8 (name, strlen (name));  
                 utf8_comment = wincp_to_utf8 (comment, strlen (comment));                
                 if( !utf8_name || !utf8_comment )  
                     BUG( dlg );  
                 p = gpgme_genkey_params( keytype, bits, utf8_name, utf8_comment, email, expire, pwd );  
                 free( utf8_name );  
                 free( utf8_comment );  
             }  
             keygen_cb_dlg_create( );  
             err = gpgme_op_genkey_auto( p, keygen_cb, NULL );  
             memset( pwd, 0, sizeof pwd );  
             memset( pwd2, 0, sizeof pwd2 );  
             if( p ) {  
                 memset( p, 0, strlen( p ) ); /* burn the passphrase! */  
                 free( p );  
             }  
             keygen_cb_dlg_destroy( );  
             keygen_cb( NULL, NULL, 0, 0, 0 ); /* flush */  
             if( err ) {  
                 msg_box( dlg, gpgme_strerror( err ), _("Key Generation"), MB_ERR );  
                 return FALSE;  
             }  
             status_box( dlg, _("Key Generation completed"), _("GnuPG Status") );  
             keycache_set_reload( 1 );  
             clear_dlg_fields( dlg );  
             ask_for_backup( dlg );  
             EndDialog( dlg, TRUE );  
             return TRUE;  
               
         case IDCANCEL:  
             SetDlgItemText (dlg, IDC_KEYGEN_PASSPHRASE, "");  
             SetDlgItemText (dlg, IDC_KEYGEN_PWDCHECK, "");  
             EndDialog (dlg, FALSE);  
             return FALSE;  
         }  
         break;  
     }  
       
     return FALSE;  
 } /* keygen_dlg_proc */  
   
   
 BOOL CALLBACK  
 keygen_wizard_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)  
 {  
     static key_wizard_s * ctx;  
     static int pubkey_algo = GPGME_KEYGEN_DSA_ELG;  
     gpgme_error_t err;  
     char name[128], email[128];  
     char * utf8_name, * p;  
     char * pass = NULL;  
     int cancel = 0;  
       
   
     switch( msg ) {  
     case WM_INITDIALOG:  
         ctx = (key_wizard_s *)lparam;  
         if (!ctx || (ctx && ctx->interactive == 0))  
             EnableWindow (GetDlgItem (dlg, IDC_KEYWIZARD_EXPERT), FALSE);  
         SetDlgItemText (dlg, IDC_KEYWIZARD_USERSA, _("&Prefer RSA keys"));  
         SetDlgItemText (dlg, IDC_KEYWIZARD_NAMEINF, _("Real name:"));  
         SetDlgItemText (dlg, IDC_KEYWIZARD_EMAILINF, _("Email address:"));  
         SetDlgItemText (dlg, IDC_KEYWIZARD_TITLEINF, _("Name and E-Mail Assignment"));  
         SetDlgItemText (dlg, IDC_KEYWIZARD_TEXT1INF, _("Every key pair must have a name associated with it. The name and\nemail address let your correspondents that your public key they are\nusing belongs to us."));  
         SetDlgItemText (dlg, IDC_KEYWIZARD_TEXT2INF, _("By accosiating an email address with your key pair, you will enable WinPT to assist your correspondents in selecting the correct public\nkey when communicating with you."));  
         SetForegroundWindow (dlg);  
         center_window (dlg);  
         break;  
   
     case WM_SYSCOMMAND:  
         if( LOWORD( wparam ) == SC_CLOSE )  
             EndDialog( dlg, FALSE );  
   
     case WM_COMMAND:  
         switch( LOWORD( wparam ) ) {  
         case IDC_KEYWIZARD_EXPERT:  
             DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_KEYGEN, dlg,  
                             keygen_dlg_proc, NULL);  
             EndDialog (dlg, TRUE);  
             break;  
   
         case IDOK:  
             if( !GetDlgItemText( dlg, IDC_KEYWIZARD_NAME, name, sizeof name-1 ) ) {  
                 msg_box( dlg, _("Please enter the name."),  
                          _("Key Generation Wizard"), MB_ERR );  
                 return FALSE;  
             }  
             if (strchr (name, '@')) {  
                 msg_box (dlg, _("Please do not enter the email address in the name field."),  
                          _("Key Generation Wizard"), MB_ERR);  
                 return FALSE;  
             }  
             if( !GetDlgItemText( dlg, IDC_KEYWIZARD_EMAIL, email, sizeof email-1 )  
                 || !strchr( email, '@' ) ) {  
                 msg_box( dlg, _("Please enter a valid email address."),  
                          _("Key Generation Wizard"), MB_ERR );  
                 return FALSE;  
             }  
             pass = request_passphrase2 (_("Key Generation"), &cancel);  
             if (cancel)  
                 return FALSE;  
             utf8_name = wincp_to_utf8 (name, strlen (name));  
             if( !utf8_name )  
                 BUG( NULL );  
             if (IsDlgButtonChecked (dlg, IDC_KEYWIZARD_USERSA))  
                 pubkey_algo = GPGME_KEYGEN_DSA_RSA;  
             p = gpgme_genkey_params (pubkey_algo, 2048, utf8_name,  
                                      NULL, email, NULL, pass);  
             free( utf8_name );  
             keygen_cb_dlg_create();  
             err = gpgme_op_genkey_auto( p, keygen_cb, NULL );  
             keygen_cb_dlg_destroy();  
             keygen_cb( NULL, NULL, 0, 0, 0 );  
             if( p ) {  
                 memset( p, 0, strlen( p ) );  
                 free( p );  
             }  
             sfree_if_alloc (pass);  
             if( err ) {  
                 msg_box( dlg, gpgme_strerror( err ), _("Key Generation Wizard"), MB_ERR );  
                 return FALSE;  
             }  
             status_box( dlg, _("Key Generation completed"), _("GnuPG Status") );  
             keycache_set_reload( 1 );  
             EndDialog( dlg, TRUE );  
             break;  
   
         case IDCANCEL:  
             EndDialog( dlg, FALSE );  
             break;  
         }  
         break;  
     }  
     return FALSE;  
 }  
1    /* wptKeygenDlg.cpp - Key Generation dialog
2     *      Copyright (C) 2000-2005 Timo Schulz
3     *
4     * This file is part of WinPT.
5     *
6     * WinPT is free software; you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * WinPT is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with WinPT; if not, write to the Free Software Foundation,
18     * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19     */
20    #ifdef HAVE_CONFIG_H
21    #include <config.h>
22    #endif
23    
24    #include <windows.h>
25    
26    #include "resource.h"
27    #include "wptTypes.h"
28    #include "wptNLS.h"
29    #include "wptGPG.h"
30    #include "wptCommonCtl.h"
31    #include "wptContext.h" /* for passphrase_s */
32    #include "wptDlgs.h"
33    #include "wptW32API.h"
34    #include "wptVersion.h"
35    #include "wptErrors.h"
36    #include "wptUTF8.h"
37    
38    /* All valid key generation combination. */
39    enum gpg_keytype_t {
40        GPG_KEYGEN_NONE    = 0,
41        GPG_KEYGEN_DSA_ELG = 1,
42        GPG_KEYGEN_DSA_RSA = 2,
43        GPG_KEYGEN_DSA_SIG = 3,
44        GPG_KEYGEN_RSA_SIG = 4,    
45        GPG_KEYGEN_RSA     = 5,
46        GPG_KEYGEN_RSA_RSA = 6 /*PGP*/
47    };
48    
49    
50    static const char key_params[] =
51            "<GnupgKeyParms format=\"internal\">\n"
52            "Key-Type: %s\n"
53            "Key-Usage: sign\n"
54            "Key-Length: %d\n"
55            "Subkey-Type: %s\n"
56            "Subkey-Length: %d\n"
57            "Name-Real: %s\n"      
58            "Name-Email: %s\n"
59            "Expire-Date: %s\n"
60            "Passphrase: %s\n"
61            "</GnupgKeyParms>\n";
62    
63    static const char key_params_with_comment[] =
64            "<GnupgKeyParms format=\"internal\">\n"
65            "Key-Type: %s\n"
66            "Key-Usage: sign\n"
67            "Key-Length: %d\n"
68            "Subkey-Type: %s\n"
69            "Subkey-Length: %d\n"
70            "Name-Real: %s\n"
71            "Name-Comment: %s\n"
72            "Name-Email: %s\n"
73            "Expire-Date: %s\n"
74            "Passphrase: %s\n"
75            "</GnupgKeyParms>\n";
76    
77    static const char key_params_one[] =
78            "<GnupgKeyParms format=\"internal\">\n"
79            "Key-Type: %s\n"
80            "Key-Length: %d\n"
81            "Key-Usage: %s\n"      
82            "Name-Real: %s\n"      
83            "Name-Email: %s\n"
84            "Expire-Date: %s\n"
85            "Passphrase: %s\n"
86            "</GnupgKeyParms>\n";
87    
88    static const char key_params_one_with_comment[] =
89            "<GnupgKeyParms format=\"internal\">\n"
90            "Key-Type: %s\n"
91            "Key-Length: %d\n"
92            "Key-Usage: %s\n"      
93            "Name-Real: %s\n"      
94            "Name-Email: %s\n"
95            "Name-Comment: %s\n"
96            "Expire-Date: %s\n"
97            "Passphrase: %s\n"
98            "</GnupgKeyParms>\n";
99    
100    
101    /* Generate the GPG specific genkey params with the given information.
102       @keytype: See valid combinations.
103       @bits: Length in bits.
104       @user: user-ID name
105       @comment: comment for the user-ID.
106       @email: email address.
107       @expdata: date of expiration or NULL.
108       @passphrase: the actual passphrase.
109       Return value: the gen. params. */
110    static char*
111    gpg_genkey_params (int keytype, int bits,
112                       const char *user, const char *comment, const char *email,
113                       const char *expdate, const char *passphrase)
114    {
115        char *p = NULL;
116        int addsize = strlen ("sign encrypt");
117        int size = 0;
118        
119        if (keytype == GPG_KEYGEN_NONE)
120            return NULL;
121        
122        size = strlen (user) + strlen (email) + strlen (passphrase) + addsize + 48;
123        if (comment && *comment)
124            size += strlen (key_params_with_comment) + strlen (comment);
125        else
126            size += strlen (key_params);
127        if (expdate)
128            size += strlen (expdate) + 1;
129        p = (char *)malloc (size+1);
130        if (!p)
131            BUG (0);
132        /* XXX: simply the whole switch-case code. */
133        if (comment && *comment) {
134            switch( keytype ) {
135            case GPG_KEYGEN_DSA_ELG:
136                sprintf (p, key_params_with_comment,
137                         "DSA", 1024, "ELG-E", bits, user, comment, email,
138                         expdate ? expdate : "0", passphrase);
139                break;
140                
141            case GPG_KEYGEN_DSA_RSA:
142                sprintf( p, key_params_with_comment,
143                         "DSA", 1024, "RSA", bits, user, comment, email,
144                         expdate ? expdate : "0", passphrase );
145                break;
146                
147            case GPG_KEYGEN_DSA_SIG:
148                sprintf( p, key_params_one_with_comment,
149                         "DSA", 1024, "sign",
150                         user, comment, email,
151                         expdate ? expdate : "0", passphrase );
152                break;
153                
154            case GPG_KEYGEN_RSA_SIG:
155                sprintf( p, key_params_one_with_comment,
156                         "RSA", bits, "sign",
157                         user, comment, email,
158                         expdate ? expdate : "0", passphrase );
159                break;
160                
161            case GPG_KEYGEN_RSA:
162                sprintf( p, key_params_one_with_comment,
163                        "RSA", bits, "sign encrypt",
164                        user, comment, email,
165                        expdate ? expdate : "0", passphrase );
166                break;
167    
168            case GPG_KEYGEN_RSA_RSA:
169                sprintf( p, key_params_with_comment,
170                         "RSA", bits, "RSA", bits, user, comment, email,
171                         expdate? expdate : "0", passphrase );
172                break;
173                
174            default:
175                if (p)
176                    free (p);
177                p = NULL;
178                break;
179            }
180        }
181        else {
182            switch ( keytype ) {
183            case GPG_KEYGEN_DSA_ELG:
184                sprintf( p, key_params,
185                        "DSA", 1024, "ELG-E", bits, user, email,
186                        expdate ? expdate : "0", passphrase );
187                break;
188                
189            case GPG_KEYGEN_DSA_RSA:
190                sprintf( p, key_params,
191                        "DSA", 1024, "RSA", bits, user, email,
192                        expdate ? expdate : "0", passphrase );
193                break;
194                
195            case GPG_KEYGEN_DSA_SIG:
196                sprintf( p, key_params_one,
197                        "DSA", 1024, "sign",
198                        user, email,
199                        expdate ? expdate : "0", passphrase );
200                break;
201                
202            case GPG_KEYGEN_RSA_SIG:
203                sprintf( p, key_params_one,
204                        "RSA", bits, "sign",
205                        user, email,
206                        expdate ? expdate : "0", passphrase );
207                break;
208                
209            case GPG_KEYGEN_RSA:
210                sprintf( p, key_params_one,
211                        "RSA", bits, "sign encrypt",
212                        user, email,
213                        expdate ? expdate : "0", passphrase );
214                break;
215    
216            case GPG_KEYGEN_RSA_RSA:
217                sprintf( p, key_params,
218                         "RSA", bits, "RSA", bits, user, email,
219                         expdate? expdate : "0", passphrase );
220                break;
221                
222            default:
223                if (p)
224                    free (p);
225                p = NULL;
226                break;
227            }
228        }
229        return p;
230    }
231    
232    
233    /* Generate a key with the given params @params. @prog_cb is a user defined
234       progress callback which is called during the generation.
235       @fpr will store the fingerprint of the generated key.
236       Return value: 0 on success. */
237    gpgme_error_t
238    gpg_genkey (const char *params, gpgme_progress_cb_t prog_cb, char **fpr)
239    {
240        gpgme_error_t err = 0;
241        gpgme_ctx_t ctx;
242        gpgme_genkey_result_t res;
243        
244        err = gpgme_new(&ctx);
245        if (err)
246            return err;
247        if (prog_cb)
248            gpgme_set_progress_cb (ctx, prog_cb, NULL);
249        err = gpgme_op_genkey (ctx, params, NULL, NULL);
250        if (!err) {
251            res = gpgme_op_genkey_result (ctx);
252            *fpr = res->fpr? strdup (res->fpr) : NULL;
253        }
254        gpgme_release (ctx);
255        return err;
256    }
257    
258    
259    
260    /* Clear all dialog fields. */
261    static void
262    clear_dlg_fields (HWND dlg)
263    {
264        SetDlgItemText (dlg, IDC_KEYGEN_SUBKEYBITS, "");
265        SetDlgItemText (dlg, IDC_KEYGEN_NAME, "");
266        SetDlgItemText (dlg, IDC_KEYGEN_EMAIL, "");
267        SetDlgItemText (dlg, IDC_KEYGEN_COMMENT, "");
268        SetDlgItemText (dlg, IDC_KEYGEN_EXPDATE, "");
269        SetDlgItemText (dlg, IDC_KEYGEN_PASSPHRASE, "");
270        SetDlgItemText (dlg, IDC_KEYGEN_PWDCHECK, "");
271    }
272    
273    
274    /* Ask the user if a keyring backup is wanted and if so,
275       backup both keyrings to the selected folder. @dlg is
276       the handle of the parent window.*/
277    static void
278    backup_keyrings (HWND dlg)
279    {
280        const char *name;
281        char *path = NULL;
282        char *keyring = NULL;
283        int id;
284        
285        path = get_gnupg_path ();
286        if (!path)
287            BUG (dlg);
288        id = msg_box (dlg,
289                     _("It is STRONGLY recommend that you backup your keyrings because they both "
290                       "contain VERY important data.\nRemember that your hard disk can crash or the "
291                       "files can be deleted by accident; so it is a good\nidea to store them on "
292                       "a different mass stoarge like a floppy or CDR!\n\n"
293                       "Backup your keyrings now?"),
294                     _("WARNING - Important hint" ), MB_YESNO);
295        if (id == IDYES) {
296            name = get_filesave_dlg (dlg, _("Destination for Public Keyring"),
297                                     NULL, "pubring.gpg");
298            if( name ) {
299                keyring = make_filename (path, "pubring", "gpg");
300                if( !CopyFile (keyring, name, FALSE))
301                    log_box (_("Key Generation"), MB_ERR,
302                             _("Could not copy %s -> %s"), keyring, name);
303                free_if_alloc (keyring);
304            }
305            name = get_filesave_dlg (dlg, _("Destination for Secret Keyring"),
306                                     NULL, "secring.gpg");
307            if( name ) {
308                keyring = make_filename (path, "secring", "gpg");
309                if (!CopyFile (keyring, name, FALSE))
310                    log_box (_("Key Generation"), MB_ERR,
311                             _("Could not copy %s -> %s"), keyring, name);
312                free_if_alloc (keyring);
313            }
314        }
315        free_if_alloc (path);
316    }
317    
318    
319    /* Fill in all valid GPG algorithms. */
320    static void
321    fill_keytype_box (HWND dlg)
322    {
323        HWND cb = GetDlgItem (dlg, IDC_KEYGEN_KEYTYPE);
324    
325    #define addstr(cb, str) \
326        SendMessage ((cb), CB_ADDSTRING, 0, (LPARAM)(LPCTSTR)(str))
327        addstr (cb, _("DSA and ELG (default)"));
328        addstr (cb, _("DSA and RSA"));
329        addstr (cb, _("DSA sign only"));
330        addstr (cb, _("RSA sign only"));
331        addstr (cb, _("RSA sign and encrypt"));
332        addstr (cb, _("RSA and RSA (PGP)") );
333        SendMessage (cb, CB_SETCURSEL, 0, 0);
334    #undef addstr
335    }
336    
337    
338    /* Check that the given date lies not in the past.
339       Return value: 1 on success. */
340    int
341    keygen_check_date (SYSTEMTIME *st)
342    {      
343        SYSTEMTIME t;
344            
345        GetSystemTime (&t);
346        if (st->wYear > t.wYear || st->wMonth > t.wMonth)
347            return 1;
348        else if (st->wYear < t.wYear || st->wMonth < t.wMonth || st->wDay < t.wDay)
349            return 0;
350        return 1;
351    }
352    
353    
354    /* Dialog box procedure for key generation. */
355    BOOL CALLBACK
356    keygen_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
357    {
358        static genkey_s *ctx;
359        SYSTEMTIME st;
360        gpgme_error_t err;
361        char name[128] = {0}, email[128] = {0}, comment[128] = {0};
362        char *pwd;
363        char t[64], *expire = NULL, *fpr=NULL;
364        int bits, use_comment, keytype = 0;
365        int cancel = 0;
366        char *p;
367        
368        switch ( msg ) {
369        case WM_INITDIALOG:
370            if (lparam != 0)
371                ctx = (genkey_s *)lparam;
372            SetWindowText (dlg, _("Key Generation"));
373            SetDlgItemText(dlg, IDC_KEYGEN_INFO,
374                            _("NOTE: Key generation can be a lengthy process! Please wait until "
375                              "you get the message that key generation was finished."));
376            SetDlgItemText (dlg, IDC_KEYGEN_SUBKEYINF, _("Subkey size in &bits"));
377            SetDlgItemText (dlg, IDC_KEYGEN_NAMEINF, _("&Real name"));
378            SetDlgItemText (dlg, IDC_KEYGEN_COMMINF, _("&Comment (optional)"));
379            SetDlgItemText (dlg, IDC_KEYGEN_EMAILINF, _("Email &address"));
380            SetDlgItemText (dlg, IDC_KEYGEN_EXPINF, _("&Expire date"));
381            SetDlgItemText (dlg, IDC_KEYGEN_KEYTYPEINF, _("Key &type"));
382            SetDlgItemText (dlg, IDC_KEYGEN_EXPNEVER, _("&Never"));
383            SetDlgItemText (dlg, IDCANCEL, _("&Cancel"));
384    
385            SetDlgItemInt (dlg, IDC_KEYGEN_SUBKEYBITS, DFAULT_KEYSIZE, FALSE);
386            CheckDlgButton (dlg, IDC_KEYGEN_HIDEPWD, BST_CHECKED);
387            CheckDlgButton (dlg, IDC_KEYGEN_EXPNEVER, BST_CHECKED);
388            EnableWindow (GetDlgItem (dlg, IDC_KEYGEN_EXPDATE), FALSE);
389            fill_keytype_box (dlg);
390            center_window (dlg, NULL);
391            SetForegroundWindow (dlg);
392            return TRUE;
393            
394        case WM_SYSCOMMAND:
395            if (LOWORD (wparam) == SC_CLOSE)
396                EndDialog (dlg, TRUE);
397            return FALSE;
398            
399        case WM_COMMAND:
400            if (HIWORD (wparam) == BN_CLICKED &&
401                LOWORD (wparam) == IDC_KEYGEN_EXPNEVER) {
402                int never = IsDlgButtonChecked (dlg, IDC_KEYGEN_EXPNEVER);
403                EnableWindow (GetDlgItem (dlg, IDC_KEYGEN_EXPDATE), !never);
404            }
405    
406            switch (LOWORD (wparam)) {
407            case IDOK:
408                bits = GetDlgItemInt (dlg, IDC_KEYGEN_SUBKEYBITS, NULL, FALSE);
409                if (bits < 1024 || bits > 4096) {
410                    msg_box (dlg, _("Invalid value. Allowed values 1024-4096 bits."),
411                             _("Key Generation"), MB_ERR);
412                    return FALSE;
413                }
414                if (bits > DFAULT_KEYSIZE) {
415                    int id = msg_box (dlg, _("Do you really need such a large key?"),
416                                      _("Key Generation"), MB_YESNO);
417                    if (id == IDNO)
418                        bits = DFAULT_KEYSIZE;
419                }
420                if (!GetDlgItemText (dlg, IDC_KEYGEN_NAME, name, sizeof (name) - 1)) {
421                    msg_box( dlg, _("Please enter the name."), _("Key Generation"), MB_ERR);
422                    return FALSE;
423                }
424                if (strchr (name, '@')) {
425                    msg_box (dlg, _("Please do not enter the email address in the name field."),
426                             _("Key Generation"), MB_INFO);
427                    return FALSE;
428                }
429                if (!GetDlgItemText (dlg, IDC_KEYGEN_EMAIL, email, sizeof (email) -1)
430                    || !strchr (email, '@')) {
431                    msg_box (dlg, _("Please enter a valid email address."),
432                             _("Key Generation"), MB_ERR);
433                    return FALSE;
434                }
435                use_comment = GetDlgItemText(dlg, IDC_KEYGEN_COMMENT,
436                                             comment, sizeof (comment) -1);
437                if (use_comment > 0 && strchr (comment, '@')) {
438                    msg_box (dlg, _("Please do NOT enter the email address in the comment field."),
439                             _("Key Generation"), MB_INFO);
440                    return FALSE;
441                }
442                keytype = SendDlgItemMessage (dlg, IDC_KEYGEN_KEYTYPE, CB_GETCURSEL, 0, 0) + 1;
443                if (IsDlgButtonChecked (dlg, IDC_KEYGEN_EXPNEVER))
444                    expire = NULL;
445                else {
446                    DateTime_GetSystemtime (GetDlgItem (dlg, IDC_KEYGEN_EXPDATE), &st);
447                    _snprintf (t, DIM (t)-1, "%04d-%02d-%02d", st.wYear, st.wMonth, st.wDay);
448                    expire = t;
449                }
450    
451                pwd = request_passphrase2 (_("Key Generation"), PASSDLG_STRICT, &cancel);
452                if (cancel) {
453                    sfree_if_alloc (pwd);
454                    return FALSE;
455                }
456                if (!pwd) {
457                    msg_box (dlg, _("Please enter the passphrase."),
458                             _("Key Generation"), MB_ERR);
459                    return FALSE;
460                }
461    
462                if (!use_comment && !strlen (comment)) {
463                    char *utf8_name;
464                    utf8_name = wincp_to_utf8 (name, strlen (name));
465                    if (!utf8_name)
466                        BUG (0);
467                    p = gpg_genkey_params (keytype, bits, utf8_name, NULL,
468                                           email, expire, pwd);
469                    safe_free (utf8_name);
470                }
471                else {
472                    char *utf8_name, *utf8_comment;
473                    utf8_name = wincp_to_utf8 (name, strlen (name));
474                    utf8_comment = wincp_to_utf8 (comment, strlen (comment));              
475                    if( !utf8_name || !utf8_comment )
476                        BUG (0);
477                    p = gpg_genkey_params (keytype, bits, utf8_name, utf8_comment,
478                                           email, expire, pwd);
479                    safe_free (utf8_name);
480                    safe_free (utf8_comment);
481                }
482                keygen_cb_dlg_create ();
483                err = gpg_genkey (p, keygen_cb, &fpr);
484                sfree_if_alloc (pwd);
485                if (p) {
486                    wipememory (p, strlen (p));  /* burn the passphrase! */
487                    free (p);
488                }
489                keygen_cb_dlg_destroy ();
490                keygen_cb (NULL, NULL, 0, 0, 0); /* flush */
491                if (err) {
492                    safe_free (fpr);
493                    msg_box (dlg, gpgme_strerror (err), _("Key Generation"), MB_ERR);
494                    return FALSE;
495                }
496                status_box (dlg, _("Key Generation completed"), _("GnuPG Status"));
497                
498                keycache_update (0, fpr);
499                keycache_update (1, fpr);
500                if (ctx != NULL && ctx->first_start == 0)
501                    get_pubkey (fpr, &ctx->newkey);
502                safe_free (fpr);
503    
504                clear_dlg_fields (dlg);
505                backup_keyrings (dlg);
506                EndDialog (dlg, TRUE);
507                return TRUE;
508                
509            case IDCANCEL:
510                EndDialog (dlg, FALSE);
511                return FALSE;
512            }
513            break;
514        }
515        
516        return FALSE;
517    }
518    
519    
520    BOOL CALLBACK
521    keygen_wizard_dlg_proc (HWND dlg, UINT msg, WPARAM wparam, LPARAM lparam)
522    {
523        static genkey_s *ctx;
524        static int pubkey_algo = GPG_KEYGEN_DSA_ELG;
525        gpgme_error_t err;
526        char name[128], email[128];
527        char * utf8_name, * p, *fpr=NULL;
528        char * pass = NULL;
529        int cancel = 0;
530        
531    
532        switch( msg ) {
533        case WM_INITDIALOG:
534            ctx = (genkey_s *)lparam;
535            if (!ctx || (ctx && ctx->interactive == 0))
536                EnableWindow (GetDlgItem (dlg, IDC_KEYWIZARD_EXPERT), FALSE);
537            SetDlgItemText (dlg, IDC_KEYWIZARD_USERSA, _("&Prefer RSA keys"));
538            SetDlgItemText (dlg, IDC_KEYWIZARD_NAMEINF, _("Real name:"));
539            SetDlgItemText (dlg, IDC_KEYWIZARD_EMAILINF, _("Email address:"));
540            SetDlgItemText (dlg, IDC_KEYWIZARD_TITLEINF, _("Name and E-Mail Assignment"));
541            SetDlgItemText (dlg, IDC_KEYWIZARD_TEXT1INF, _("Every key pair must have a name associated with it. The name and\nemail address let your correspondents that your public key they are\nusing belongs to us."));
542            SetDlgItemText (dlg, IDC_KEYWIZARD_TEXT2INF, _("By accosiating an email address with your key pair, you will enable WinPT to assist your correspondents in selecting the correct public\nkey when communicating with you."));
543            SetWindowText (dlg, _("Key Generation Wizard"));
544            SetDlgItemText (dlg, IDCANCEL, _("&Cancel"));
545            SetDlgItemText (dlg, IDC_KEYWIZARD_EXPERT, _("E&xpert"));
546            SetForegroundWindow (dlg);
547            center_window (dlg, NULL);
548            break;
549    
550        case WM_SYSCOMMAND:
551            if( LOWORD( wparam ) == SC_CLOSE )
552                EndDialog( dlg, FALSE );
553    
554        case WM_COMMAND:
555            switch( LOWORD( wparam ) ) {
556            case IDC_KEYWIZARD_EXPERT:
557                DialogBoxParam (glob_hinst, (LPCTSTR)IDD_WINPT_KEYGEN, dlg,
558                                keygen_dlg_proc, 0);
559                EndDialog (dlg, TRUE);
560                break;
561    
562            case IDOK:
563                if( !GetDlgItemText( dlg, IDC_KEYWIZARD_NAME, name, sizeof name-1 ) ) {
564                    msg_box( dlg, _("Please enter the name."),
565                             _("Key Generation Wizard"), MB_ERR );
566                    return FALSE;
567                }
568                if (strchr (name, '@')) {
569                    msg_box (dlg, _("Please do not enter the email address in the name field."),
570                             _("Key Generation Wizard"), MB_WARN);
571                    return FALSE;
572                }
573                if( !GetDlgItemText( dlg, IDC_KEYWIZARD_EMAIL, email, sizeof email-1 )
574                    || !strchr( email, '@' ) ) {
575                    msg_box( dlg, _("Please enter a valid email address."),
576                             _("Key Generation Wizard"), MB_ERR );
577                    return FALSE;
578                }
579                if (strchr (email, '<') || strchr (email, '>')) {
580                    msg_box (dlg, _("Please do not add '<' or '>' to the email address."),
581                             _("Key Generation Wizard"), MB_WARN);
582                    return FALSE;
583                }
584                pass = request_passphrase2 (_("Key Generation"), PASSDLG_STRICT, &cancel);
585                if (cancel)
586                    return FALSE;
587                utf8_name = wincp_to_utf8 (name, strlen (name));
588                if( !utf8_name )
589                    BUG( NULL );
590                if (IsDlgButtonChecked (dlg, IDC_KEYWIZARD_USERSA))
591                    pubkey_algo = GPG_KEYGEN_DSA_RSA;
592                p = gpg_genkey_params (pubkey_algo, DFAULT_KEYSIZE, utf8_name,
593                                         NULL, email, NULL, pass);
594                free( utf8_name );
595                keygen_cb_dlg_create();
596                err = gpg_genkey (p, keygen_cb, &fpr);
597                keygen_cb_dlg_destroy();
598                keygen_cb( NULL, NULL, 0, 0, 0 );
599                if( p ) {
600                    memset( p, 0, strlen( p ) );
601                    free( p );
602                }
603                sfree_if_alloc (pass);
604                if( err ) {
605                    msg_box( dlg, gpgme_strerror( err ), _("Key Generation Wizard"), MB_ERR );
606                    if (fpr)
607                        free (fpr);
608                    return FALSE;
609                }
610                status_box( dlg, _("Key Generation completed"), _("GnuPG Status") );
611                
612                keycache_update (0, fpr);
613                keycache_update (1, fpr);
614                if (ctx->first_start == 0 && ctx != NULL)
615                    get_pubkey (fpr, &ctx->newkey);
616                if (fpr)
617                    free (fpr);
618                backup_keyrings (dlg);
619                EndDialog (dlg, TRUE);
620                break;
621    
622            case IDCANCEL:
623                EndDialog( dlg, FALSE );
624                break;
625            }
626            break;
627        }
628        return FALSE;
629    }

Legend:
Removed from v.2  
changed lines
  Added in v.130

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26