2005-06-24 23:38:04 +00:00
/*
2007-03-29 03:26:27 +00:00
* Copyright ( C ) 2005 - 2007 Justin Karneges < justin @ affinix . com >
2005-06-24 23:38:04 +00:00
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2.1 of the License , or ( at your option ) any later version .
*
* This library 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
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library ; if not , write to the Free Software
2007-01-02 04:52:05 +00:00
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA
2005-06-24 23:38:04 +00:00
*
*/
2005-03-14 11:40:03 +00:00
# include <QtCrypto>
2007-04-17 12:07:11 +00:00
# include <QCoreApplication>
# include <QDebug>
# include <QFile>
# include <QFileInfo>
# include <QTextStream>
# include <QTimer>
2014-09-24 18:03:37 +06:00
# include <QDir>
2014-01-02 03:50:18 +06:00
# ifdef QT_STATICPLUGIN
# include "import_plugins.h"
# endif
2007-05-30 19:15:29 +00:00
const char * const APPNAME = " qcatool " ;
2013-10-02 22:22:37 +06:00
const char * const EXENAME = " qcatool " ;
2014-01-03 04:14:31 +06:00
const char * const VERSION = QCA_VERSION_STR ;
2007-03-30 01:00:19 +00:00
2006-02-25 02:43:31 +00:00
static QStringList wrapstring ( const QString & str , int width )
{
QStringList out ;
QString simp = str . simplified ( ) ;
QString rest = simp ;
2020-01-30 17:24:31 +01:00
while ( true )
2006-02-25 02:43:31 +00:00
{
int lastSpace = - 1 ;
int n ;
for ( n = 0 ; n < rest . length ( ) ; + + n )
{
if ( rest [ n ] . isSpace ( ) )
lastSpace = n ;
if ( n = = width )
break ;
}
if ( n = = rest . length ( ) )
{
out + = rest ;
break ;
}
QString line ;
if ( lastSpace ! = - 1 )
{
line = rest . mid ( 0 , lastSpace ) ;
rest = rest . mid ( lastSpace + 1 ) ;
}
else
{
line = rest . mid ( 0 , n ) ;
rest = rest . mid ( n ) ;
}
out + = line ;
}
return out ;
}
2007-04-14 12:02:03 +00:00
class StreamLogger : public QCA : : AbstractLogDevice
{
2020-01-29 14:23:48 +01:00
Q_OBJECT
2007-04-14 12:02:03 +00:00
public :
2020-02-10 00:29:23 +01:00
StreamLogger ( QTextStream & stream ) : QCA : : AbstractLogDevice ( QStringLiteral ( " Stream logger " ) ) , _stream ( stream )
2007-04-14 12:02:03 +00:00
{
QCA : : logger ( ) - > registerLogDevice ( this ) ;
}
2020-01-30 17:14:07 +01:00
~ StreamLogger ( ) override
2007-04-14 12:02:03 +00:00
{
QCA : : logger ( ) - > unregisterLogDevice ( name ( ) ) ;
}
2020-01-19 16:28:44 +01:00
void logTextMessage ( const QString & message , enum QCA : : Logger : : Severity severity ) override
2007-04-14 12:02:03 +00:00
{
_stream < < now ( ) < < " " < < severityName ( severity ) < < " " < < message < < endl ;
}
2020-01-19 16:28:44 +01:00
void logBinaryMessage ( const QByteArray & blob , enum QCA : : Logger : : Severity severity ) override
2007-04-14 12:02:03 +00:00
{
Q_UNUSED ( blob ) ;
_stream < < now ( ) < < " " < < severityName ( severity ) < < " " < < " Binary blob not implemented yet " < < endl ;
}
private :
2007-10-23 13:11:38 +00:00
inline const char * severityName ( enum QCA : : Logger : : Severity severity )
2007-04-14 12:02:03 +00:00
{
if ( severity < = QCA : : Logger : : Debug ) {
return s_severityNames [ severity ] ;
}
else {
return s_severityNames [ QCA : : Logger : : Debug + 1 ] ;
}
}
inline QString now ( ) {
2020-02-10 00:29:23 +01:00
static QString format = QStringLiteral ( " yyyy-MM-dd hh:mm:ss " ) ;
2007-04-14 12:02:03 +00:00
return QDateTime : : currentDateTime ( ) . toString ( format ) ;
}
private :
2007-10-23 13:11:38 +00:00
static const char * s_severityNames [ ] ;
2007-04-14 12:02:03 +00:00
QTextStream & _stream ;
} ;
2007-10-23 13:11:38 +00:00
const char * StreamLogger : : s_severityNames [ ] = {
2007-04-14 12:25:06 +00:00
" Q " ,
2007-04-14 12:02:03 +00:00
" M " ,
" A " ,
" C " ,
" E " ,
" W " ,
" N " ,
" I " ,
" D " ,
" U "
} ;
2007-05-14 21:31:53 +00:00
static void output_plugin_diagnostic_text ( )
{
QString str = QCA : : pluginDiagnosticText ( ) ;
QCA : : clearPluginDiagnosticText ( ) ;
2020-02-13 00:59:09 +01:00
if ( str [ str . length ( ) - 1 ] = = QLatin1Char ( ' \n ' ) )
2008-05-20 22:24:18 +00:00
str . truncate ( str . length ( ) - 1 ) ;
2020-02-16 12:11:57 +01:00
const QStringList lines = str . split ( QLatin1Char ( ' \n ' ) , QString : : KeepEmptyParts ) ;
2007-05-14 21:31:53 +00:00
for ( int n = 0 ; n < lines . count ( ) ; + + n )
fprintf ( stderr , " plugin: %s \n " , qPrintable ( lines [ n ] ) ) ;
}
static void output_keystore_diagnostic_text ( )
{
QString str = QCA : : KeyStoreManager : : diagnosticText ( ) ;
QCA : : KeyStoreManager : : clearDiagnosticText ( ) ;
2020-02-13 00:59:09 +01:00
if ( str [ str . length ( ) - 1 ] = = QLatin1Char ( ' \n ' ) )
2008-05-20 22:24:18 +00:00
str . truncate ( str . length ( ) - 1 ) ;
2020-02-16 12:11:57 +01:00
const QStringList lines = str . split ( QLatin1Char ( ' \n ' ) , QString : : KeepEmptyParts ) ;
2007-05-14 21:31:53 +00:00
for ( int n = 0 ; n < lines . count ( ) ; + + n )
fprintf ( stderr , " keystore: %s \n " , qPrintable ( lines [ n ] ) ) ;
}
static void output_message_diagnostic_text ( QCA : : SecureMessage * msg )
{
QString str = msg - > diagnosticText ( ) ;
2020-02-13 00:59:09 +01:00
if ( str [ str . length ( ) - 1 ] = = QLatin1Char ( ' \n ' ) )
2008-05-20 22:24:18 +00:00
str . truncate ( str . length ( ) - 1 ) ;
2020-02-16 12:11:57 +01:00
const QStringList lines = str . split ( QLatin1Char ( ' \n ' ) , QString : : KeepEmptyParts ) ;
2007-05-14 21:31:53 +00:00
for ( int n = 0 ; n < lines . count ( ) ; + + n )
fprintf ( stderr , " message: %s \n " , qPrintable ( lines [ n ] ) ) ;
}
2005-03-14 11:40:03 +00:00
class AnimatedKeyGen : public QObject
{
Q_OBJECT
public :
static QCA : : PrivateKey makeKey ( QCA : : PKey : : Type type , int bits , QCA : : DLGroupSet set )
{
AnimatedKeyGen kg ;
kg . type = type ;
kg . bits = bits ;
kg . set = set ;
QEventLoop eventLoop ;
kg . eventLoop = & eventLoop ;
2020-01-29 17:23:29 +01:00
QTimer : : singleShot ( 0 , & kg , & AnimatedKeyGen : : start ) ;
2005-03-14 11:40:03 +00:00
eventLoop . exec ( ) ;
QCA : : PrivateKey key = kg . key ;
return key ;
}
private :
QCA : : PKey : : Type type ;
int bits ;
QCA : : DLGroupSet set ;
QEventLoop * eventLoop ;
QCA : : KeyGenerator gen ;
QCA : : DLGroup group ;
QCA : : PrivateKey key ;
QTimer t ;
int x ;
AnimatedKeyGen ( )
{
2007-06-08 20:40:22 +00:00
gen . setBlockingEnabled ( false ) ;
2020-01-27 16:22:21 +01:00
connect ( & gen , & QCA : : KeyGenerator : : finished , this , & AnimatedKeyGen : : gen_finished ) ;
connect ( & t , & QTimer : : timeout , this , & AnimatedKeyGen : : t_timeout ) ;
2005-03-14 11:40:03 +00:00
}
2020-01-22 19:31:28 +01:00
private Q_SLOTS :
2005-03-14 11:40:03 +00:00
void start ( )
{
printf ( " Generating Key ... " ) ;
fflush ( stdout ) ;
x = 0 ;
t . start ( 125 ) ;
if ( type = = QCA : : PKey : : RSA )
gen . createRSA ( bits ) ;
else
gen . createDLGroup ( set ) ;
}
void gen_finished ( )
{
if ( type = = QCA : : PKey : : DSA | | type = = QCA : : PKey : : DH )
{
if ( group . isNull ( ) )
{
group = gen . dlGroup ( ) ;
if ( type = = QCA : : PKey : : DSA )
gen . createDSA ( group ) ;
else
gen . createDH ( group ) ;
return ;
}
}
key = gen . key ( ) ;
printf ( " \b " ) ;
if ( ! key . isNull ( ) )
printf ( " Done \n " ) ;
else
printf ( " Error \n " ) ;
eventLoop - > exit ( ) ;
}
void t_timeout ( )
{
if ( x = = 0 )
printf ( " \b / " ) ;
else if ( x = = 1 )
printf ( " \b - " ) ;
else if ( x = = 2 )
printf ( " \b \\ " ) ;
else if ( x = = 3 )
printf ( " \b | " ) ;
fflush ( stdout ) ;
+ + x ;
x % = 4 ;
}
} ;
2007-05-13 22:36:52 +00:00
class KeyStoreMonitor : public QObject
{
Q_OBJECT
public :
static void monitor ( )
{
KeyStoreMonitor monitor ;
QEventLoop eventLoop ;
monitor . eventLoop = & eventLoop ;
2020-01-29 17:23:29 +01:00
QTimer : : singleShot ( 0 , & monitor , & KeyStoreMonitor : : start ) ;
2007-05-13 22:36:52 +00:00
eventLoop . exec ( ) ;
}
private :
QEventLoop * eventLoop ;
QCA : : KeyStoreManager * ksm ;
QList < QCA : : KeyStore * > keyStores ;
QCA : : ConsolePrompt * prompt ;
2020-01-22 19:31:28 +01:00
private Q_SLOTS :
2007-05-13 22:36:52 +00:00
void start ( )
{
// user can quit the monitoring by pressing enter
2007-06-21 22:38:43 +00:00
printf ( " Monitoring keystores, press 'q' to quit. \n " ) ;
2007-05-13 22:36:52 +00:00
prompt = new QCA : : ConsolePrompt ( this ) ;
2020-01-27 16:22:21 +01:00
connect ( prompt , & QCA : : ConsolePrompt : : finished , this , & KeyStoreMonitor : : prompt_finished ) ;
2007-06-21 22:38:43 +00:00
prompt - > getChar ( ) ;
2007-05-13 22:36:52 +00:00
// kick off the subsystem
QCA : : KeyStoreManager : : start ( ) ;
// setup keystore manager for monitoring
ksm = new QCA : : KeyStoreManager ( this ) ;
2020-01-27 16:22:21 +01:00
connect ( ksm , & QCA : : KeyStoreManager : : keyStoreAvailable , this , & KeyStoreMonitor : : ks_available ) ;
2007-05-13 22:36:52 +00:00
foreach ( const QString & keyStoreId , ksm - > keyStores ( ) )
ks_available ( keyStoreId ) ;
}
void ks_available ( const QString & keyStoreId )
{
QCA : : KeyStore * ks = new QCA : : KeyStore ( keyStoreId , ksm ) ;
2020-01-27 16:22:21 +01:00
connect ( ks , & QCA : : KeyStore : : updated , this , & KeyStoreMonitor : : ks_updated ) ;
connect ( ks , & QCA : : KeyStore : : unavailable , this , & KeyStoreMonitor : : ks_unavailable ) ;
2007-05-13 22:36:52 +00:00
keyStores + = ks ;
printf ( " available: %s \n " , qPrintable ( ks - > name ( ) ) ) ;
}
void ks_updated ( )
{
QCA : : KeyStore * ks = ( QCA : : KeyStore * ) sender ( ) ;
printf ( " updated: %s \n " , qPrintable ( ks - > name ( ) ) ) ;
}
void ks_unavailable ( )
{
QCA : : KeyStore * ks = ( QCA : : KeyStore * ) sender ( ) ;
printf ( " unavailable: %s \n " , qPrintable ( ks - > name ( ) ) ) ;
keyStores . removeAll ( ks ) ;
delete ks ;
}
void prompt_finished ( )
{
2007-06-21 22:38:43 +00:00
QChar c = prompt - > resultChar ( ) ;
2020-02-13 00:59:09 +01:00
if ( c = = QLatin1Char ( ' q ' ) | | c = = QLatin1Char ( ' Q ' ) )
2007-06-21 22:38:43 +00:00
{
eventLoop - > exit ( ) ;
return ;
}
prompt - > getChar ( ) ;
2007-05-13 22:36:52 +00:00
}
} ;
2007-04-05 23:27:59 +00:00
2005-06-05 08:51:03 +00:00
class PassphrasePrompt : public QObject
{
Q_OBJECT
public :
2007-04-21 00:01:13 +00:00
class Item
{
public :
QString promptStr ;
int id ;
QCA : : Event event ;
} ;
2006-04-06 21:57:19 +00:00
QCA : : EventHandler handler ;
2007-03-29 03:26:27 +00:00
bool allowPrompt ;
bool warned ;
bool have_pass ;
bool used_pass ;
2007-04-13 19:04:16 +00:00
QCA : : SecureArray pass ;
2007-04-21 00:01:13 +00:00
QCA : : ConsolePrompt * prompt ;
int prompt_id ;
QCA : : Event prompt_event ;
QList < Item > pending ;
2007-06-21 22:38:43 +00:00
bool auto_accept ;
2005-07-28 12:17:09 +00:00
2007-05-13 22:36:52 +00:00
QCA : : KeyStoreManager ksm ;
QList < QCA : : KeyStore * > keyStores ;
PassphrasePrompt ( ) : handler ( this ) , ksm ( this )
2005-06-05 08:51:03 +00:00
{
2007-03-29 03:26:27 +00:00
allowPrompt = true ;
warned = false ;
have_pass = false ;
2007-06-21 22:38:43 +00:00
auto_accept = false ;
2007-03-29 03:26:27 +00:00
2020-02-12 17:14:33 +01:00
prompt = nullptr ;
2007-04-21 00:01:13 +00:00
2020-01-27 16:22:21 +01:00
connect ( & handler , & QCA : : EventHandler : : eventReady , this , & PassphrasePrompt : : ph_eventReady ) ;
2006-04-06 21:57:19 +00:00
handler . start ( ) ;
2007-05-13 22:36:52 +00:00
2020-01-27 16:22:21 +01:00
connect ( & ksm , & QCA : : KeyStoreManager : : keyStoreAvailable , this , & PassphrasePrompt : : ks_available ) ;
2007-05-13 22:36:52 +00:00
foreach ( const QString & keyStoreId , ksm . keyStores ( ) )
ks_available ( keyStoreId ) ;
2005-06-05 08:51:03 +00:00
}
2020-01-30 17:14:07 +01:00
~ PassphrasePrompt ( ) override
2007-04-21 00:01:13 +00:00
{
2007-05-13 22:36:52 +00:00
qDeleteAll ( keyStores ) ;
2007-04-21 00:01:13 +00:00
if ( prompt )
{
handler . reject ( prompt_id ) ;
delete prompt ;
}
while ( ! pending . isEmpty ( ) )
handler . reject ( pending . takeFirst ( ) . id ) ;
}
2007-04-13 19:04:16 +00:00
void setExplicitPassword ( const QCA : : SecureArray & _pass )
2007-03-29 03:26:27 +00:00
{
have_pass = true ;
used_pass = false ;
pass = _pass ;
}
2020-01-22 19:31:28 +01:00
private Q_SLOTS :
2006-04-06 21:57:19 +00:00
void ph_eventReady ( int id , const QCA : : Event & e )
2005-06-05 08:51:03 +00:00
{
2007-03-29 03:26:27 +00:00
if ( have_pass )
{
// only allow using an explicit passphrase once
if ( used_pass )
{
handler . reject ( id ) ;
return ;
}
used_pass = true ;
handler . submitPassword ( id , pass ) ;
return ;
}
if ( ! allowPrompt )
{
if ( ! have_pass & & ! warned )
{
warned = true ;
fprintf ( stderr , " Error: no passphrase specified (use '--pass=' for none). \n " ) ;
}
handler . reject ( id ) ;
return ;
}
2006-04-06 21:57:19 +00:00
if ( e . type ( ) = = QCA : : Event : : Password )
2005-07-31 05:12:42 +00:00
{
2020-02-10 00:29:23 +01:00
QString type = QStringLiteral ( " password " ) ;
2006-04-06 21:57:19 +00:00
if ( e . passwordStyle ( ) = = QCA : : Event : : StylePassphrase )
2020-02-10 00:29:23 +01:00
type = QStringLiteral ( " passphrase " ) ;
2006-04-06 21:57:19 +00:00
else if ( e . passwordStyle ( ) = = QCA : : Event : : StylePIN )
2020-02-10 00:29:23 +01:00
type = QStringLiteral ( " PIN " ) ;
2006-04-06 21:57:19 +00:00
QString str ;
if ( e . source ( ) = = QCA : : Event : : KeyStore )
2005-07-31 05:12:42 +00:00
{
2007-04-05 23:27:59 +00:00
QString name ;
2007-04-13 06:32:02 +00:00
QCA : : KeyStoreEntry entry = e . keyStoreEntry ( ) ;
2006-04-06 21:57:19 +00:00
if ( ! entry . isNull ( ) )
{
2007-04-05 00:01:12 +00:00
name = entry . name ( ) ;
}
else
{
2007-04-26 01:55:37 +00:00
if ( e . keyStoreInfo ( ) . type ( ) = = QCA : : KeyStore : : SmartCard )
2020-02-13 00:59:09 +01:00
name = QStringLiteral ( " the ' " ) + e . keyStoreInfo ( ) . name ( ) + QStringLiteral ( " ' token " ) ;
2007-04-07 21:48:59 +00:00
else
2007-04-26 01:55:37 +00:00
name = e . keyStoreInfo ( ) . name ( ) ;
2006-04-06 21:57:19 +00:00
}
2020-02-10 00:29:23 +01:00
str = QStringLiteral ( " Enter %1 for %2 " ) . arg ( type , name ) ;
2005-07-31 05:12:42 +00:00
}
2007-04-07 21:48:59 +00:00
else if ( ! e . fileName ( ) . isEmpty ( ) )
2020-02-10 00:29:23 +01:00
str = QStringLiteral ( " Enter %1 for %2 " ) . arg ( type , e . fileName ( ) ) ;
2006-04-06 21:57:19 +00:00
else
2020-02-10 00:29:23 +01:00
str = QStringLiteral ( " Enter %1 " ) . arg ( type ) ;
2006-04-06 21:57:19 +00:00
2007-04-21 00:01:13 +00:00
if ( ! prompt )
{
prompt = new QCA : : ConsolePrompt ( this ) ;
2020-01-27 16:22:21 +01:00
connect ( prompt , & QCA : : ConsolePrompt : : finished , this , & PassphrasePrompt : : prompt_finished ) ;
2007-04-21 00:01:13 +00:00
prompt_id = id ;
prompt_event = e ;
prompt - > getHidden ( str ) ;
}
else
{
Item i ;
i . promptStr = str ;
i . id = id ;
i . event = e ;
pending + = i ;
}
2006-04-06 21:57:19 +00:00
}
else if ( e . type ( ) = = QCA : : Event : : Token )
{
2007-05-13 22:36:52 +00:00
// even though we're being prompted for a missing token,
// we should still check if the token is present, due to
// a possible race between insert and token request.
bool found = false ;
2007-07-06 01:47:35 +00:00
// token-only
if ( e . keyStoreEntry ( ) . isNull ( ) )
2007-05-13 22:36:52 +00:00
{
2007-07-06 01:47:35 +00:00
foreach ( QCA : : KeyStore * ks , keyStores )
2007-05-13 22:36:52 +00:00
{
2007-07-06 01:47:35 +00:00
if ( ks - > id ( ) = = e . keyStoreInfo ( ) . id ( ) )
{
found = true ;
break ;
}
}
}
// token-entry
else
{
QCA : : KeyStoreEntry kse = e . keyStoreEntry ( ) ;
2020-02-12 17:14:33 +01:00
QCA : : KeyStore * ks = nullptr ;
2007-07-06 01:47:35 +00:00
foreach ( QCA : : KeyStore * i , keyStores )
{
if ( i - > id ( ) = = e . keyStoreInfo ( ) . id ( ) )
{
ks = i ;
break ;
}
}
if ( ks )
{
QList < QCA : : KeyStoreEntry > list = ks - > entryList ( ) ;
foreach ( const QCA : : KeyStoreEntry & e , list )
{
if ( e . id ( ) = = kse . id ( ) & & kse . isAvailable ( ) )
{
found = true ;
break ;
}
}
2007-05-13 22:36:52 +00:00
}
}
if ( found )
{
// auto-accept
handler . tokenOkay ( id ) ;
return ;
}
2007-04-13 06:32:02 +00:00
QCA : : KeyStoreEntry entry = e . keyStoreEntry ( ) ;
2007-04-05 00:01:12 +00:00
QString name ;
if ( ! entry . isNull ( ) )
{
2020-02-13 00:59:09 +01:00
name = QStringLiteral ( " Please make " ) + entry . name ( ) + QStringLiteral ( " (of " ) + entry . storeName ( ) + QStringLiteral ( " ) available " ) ;
2007-04-05 00:01:12 +00:00
}
else
{
2020-02-13 00:59:09 +01:00
name = QStringLiteral ( " Please insert the ' " ) + e . keyStoreInfo ( ) . name ( ) + QStringLiteral ( " ' token " ) ;
2007-04-05 00:01:12 +00:00
}
2007-04-21 00:01:13 +00:00
2020-02-10 00:29:23 +01:00
QString str = QStringLiteral ( " %1 and press Enter (or 'q' to cancel) ... " ) . arg ( name ) ;
2007-04-21 00:01:13 +00:00
if ( ! prompt )
{
2007-05-13 22:36:52 +00:00
fprintf ( stderr , " %s \n " , qPrintable ( str ) ) ;
2007-04-21 00:01:13 +00:00
prompt = new QCA : : ConsolePrompt ( this ) ;
2020-01-27 16:22:21 +01:00
connect ( prompt , & QCA : : ConsolePrompt : : finished , this , & PassphrasePrompt : : prompt_finished ) ;
2007-04-21 00:01:13 +00:00
prompt_id = id ;
prompt_event = e ;
2007-06-21 22:38:43 +00:00
prompt - > getChar ( ) ;
2007-04-21 00:01:13 +00:00
}
else
{
Item i ;
i . promptStr = str ;
i . id = id ;
i . event = e ;
pending + = i ;
}
}
else
handler . reject ( id ) ;
}
void prompt_finished ( )
{
if ( prompt_event . type ( ) = = QCA : : Event : : Password )
2007-06-21 22:38:43 +00:00
{
2007-04-21 00:01:13 +00:00
handler . submitPassword ( prompt_id , prompt - > result ( ) ) ;
2007-06-21 22:38:43 +00:00
}
2007-04-21 00:01:13 +00:00
else
2007-06-21 22:38:43 +00:00
{
if ( auto_accept )
{
auto_accept = false ;
handler . tokenOkay ( prompt_id ) ;
}
else
{
QChar c = prompt - > resultChar ( ) ;
2020-02-13 00:59:09 +01:00
if ( c = = QLatin1Char ( ' \r ' ) | | c = = QLatin1Char ( ' \n ' ) )
2007-06-21 22:38:43 +00:00
handler . tokenOkay ( prompt_id ) ;
2020-02-13 00:59:09 +01:00
else if ( c = = QLatin1Char ( ' q ' ) | | c = = QLatin1Char ( ' Q ' ) )
2007-06-21 22:38:43 +00:00
handler . reject ( prompt_id ) ;
else
{
// retry
prompt - > getChar ( ) ;
return ;
}
}
}
2007-04-21 00:01:13 +00:00
if ( ! pending . isEmpty ( ) )
{
Item i = pending . takeFirst ( ) ;
prompt_id = i . id ;
prompt_event = i . event ;
if ( i . event . type ( ) = = QCA : : Event : : Password )
{
prompt - > getHidden ( i . promptStr ) ;
}
else // Token
{
2007-05-13 22:36:52 +00:00
fprintf ( stderr , " %s \n " , qPrintable ( i . promptStr ) ) ;
2007-06-21 22:38:43 +00:00
prompt - > getChar ( ) ;
2007-04-21 00:01:13 +00:00
}
}
else
{
delete prompt ;
2020-02-12 17:14:33 +01:00
prompt = nullptr ;
2006-04-06 21:57:19 +00:00
}
2005-06-05 08:51:03 +00:00
}
2007-05-13 22:36:52 +00:00
void ks_available ( const QString & keyStoreId )
{
QCA : : KeyStore * ks = new QCA : : KeyStore ( keyStoreId , & ksm ) ;
2020-01-27 16:22:21 +01:00
connect ( ks , & QCA : : KeyStore : : updated , this , & PassphrasePrompt : : ks_updated ) ;
connect ( ks , & QCA : : KeyStore : : unavailable , this , & PassphrasePrompt : : ks_unavailable ) ;
2007-05-13 22:36:52 +00:00
keyStores + = ks ;
2007-07-06 01:47:35 +00:00
ks - > startAsynchronousMode ( ) ;
2007-05-13 22:36:52 +00:00
2007-07-06 01:47:35 +00:00
// are we currently in a token-only prompt?
if ( prompt & & prompt_event . type ( ) = = QCA : : Event : : Token & & prompt_event . keyStoreEntry ( ) . isNull ( ) )
2007-05-13 22:36:52 +00:00
{
// was the token we're looking for just inserted?
if ( prompt_event . keyStoreInfo ( ) . id ( ) = = keyStoreId )
{
fprintf ( stderr , " Token inserted! Continuing... \n " ) ;
// auto-accept
2007-06-21 22:38:43 +00:00
auto_accept = true ;
2007-05-13 22:36:52 +00:00
prompt_finished ( ) ;
}
}
}
void ks_unavailable ( )
{
QCA : : KeyStore * ks = ( QCA : : KeyStore * ) sender ( ) ;
keyStores . removeAll ( ks ) ;
delete ks ;
}
2007-07-06 01:47:35 +00:00
void ks_updated ( )
{
QCA : : KeyStore * ks = ( QCA : : KeyStore * ) sender ( ) ;
// are we currently in a token-entry prompt?
if ( prompt & & prompt_event . type ( ) = = QCA : : Event : : Token & & ! prompt_event . keyStoreEntry ( ) . isNull ( ) )
{
QCA : : KeyStoreEntry kse = prompt_event . keyStoreEntry ( ) ;
// was the token of the entry we're looking for updated?
if ( prompt_event . keyStoreInfo ( ) . id ( ) = = ks - > id ( ) )
{
// is the entry available?
bool avail = false ;
QList < QCA : : KeyStoreEntry > list = ks - > entryList ( ) ;
foreach ( const QCA : : KeyStoreEntry & e , list )
{
if ( e . id ( ) = = kse . id ( ) )
{
avail = kse . isAvailable ( ) ;
break ;
}
}
if ( avail )
{
fprintf ( stderr , " Entry available! Continuing... \n " ) ;
// auto-accept
auto_accept = true ;
prompt_finished ( ) ;
}
}
}
}
2005-06-05 08:51:03 +00:00
} ;
2007-04-07 18:34:52 +00:00
class PassphrasePromptThread : public QCA : : SyncThread
{
2020-01-29 14:23:48 +01:00
Q_OBJECT
2007-04-07 18:34:52 +00:00
public :
PassphrasePrompt * pp ;
PassphrasePromptThread ( )
{
start ( ) ;
}
2020-01-30 17:14:07 +01:00
~ PassphrasePromptThread ( ) override
2007-04-07 18:34:52 +00:00
{
stop ( ) ;
}
protected :
2020-01-19 16:28:44 +01:00
void atStart ( ) override
2007-04-07 18:34:52 +00:00
{
pp = new PassphrasePrompt ;
}
2020-01-19 16:28:44 +01:00
void atEnd ( ) override
2007-04-07 18:34:52 +00:00
{
delete pp ;
}
} ;
2007-04-13 19:04:16 +00:00
static bool promptForNewPassphrase ( QCA : : SecureArray * result )
2005-03-14 11:40:03 +00:00
{
2007-04-21 00:01:13 +00:00
QCA : : ConsolePrompt prompt ;
2020-02-10 00:29:23 +01:00
prompt . getHidden ( QStringLiteral ( " Enter new passphrase " ) ) ;
2007-04-21 00:01:13 +00:00
prompt . waitForFinished ( ) ;
QCA : : SecureArray out = prompt . result ( ) ;
2020-02-10 00:29:23 +01:00
prompt . getHidden ( QStringLiteral ( " Confirm new passphrase " ) ) ;
2007-04-21 00:01:13 +00:00
prompt . waitForFinished ( ) ;
if ( prompt . result ( ) ! = out )
2007-03-29 03:26:27 +00:00
{
fprintf ( stderr , " Error: confirmation does not match original entry. \n " ) ;
2005-03-14 11:40:03 +00:00
return false ;
2007-03-29 03:26:27 +00:00
}
* result = out ;
2005-03-14 11:40:03 +00:00
return true ;
}
2007-05-13 22:36:52 +00:00
static void ksm_start_and_wait ( )
{
// activate the KeyStoreManager and block until ready
QCA : : KeyStoreManager : : start ( ) ;
{
QCA : : KeyStoreManager ksm ;
ksm . waitForBusyFinished ( ) ;
}
}
2007-03-29 03:26:27 +00:00
static QString line_encode ( const QString & in )
{
QString out ;
2020-01-30 17:24:31 +01:00
for ( const QChar & c : in )
2007-03-29 03:26:27 +00:00
{
2020-02-13 00:59:09 +01:00
if ( c = = QLatin1Char ( ' \\ ' ) )
2020-02-10 00:29:23 +01:00
out + = QStringLiteral ( " \\ \\ " ) ;
2020-02-13 00:59:09 +01:00
else if ( c = = QLatin1Char ( ' \n ' ) )
2020-02-10 00:29:23 +01:00
out + = QStringLiteral ( " \\ n " ) ;
2007-03-29 03:26:27 +00:00
else
2020-01-30 17:24:31 +01:00
out + = c ;
2007-03-29 03:26:27 +00:00
}
return out ;
}
static QString line_decode ( const QString & in )
{
QString out ;
for ( int n = 0 ; n < in . length ( ) ; + + n )
{
2020-02-13 00:59:09 +01:00
if ( in [ n ] = = QLatin1Char ( ' \\ ' ) )
2007-03-29 03:26:27 +00:00
{
if ( n + 1 < in . length ( ) )
{
2020-02-13 00:59:09 +01:00
if ( in [ n + 1 ] = = QLatin1Char ( ' \\ ' ) )
out + = QLatin1Char ( ' \\ ' ) ;
else if ( in [ n + 1 ] = = QLatin1Char ( ' n ' ) )
out + = QLatin1Char ( ' \n ' ) ;
2007-03-29 03:26:27 +00:00
+ + n ;
}
}
else
out + = in [ n ] ;
}
return out ;
}
static QString make_ksentry_string ( const QString & id )
{
QString out ;
2020-02-10 00:29:23 +01:00
out + = QStringLiteral ( " QCATOOL_KEYSTOREENTRY_1 \n " ) ;
2020-02-13 00:59:09 +01:00
out + = line_encode ( id ) + QLatin1Char ( ' \n ' ) ;
2007-03-29 03:26:27 +00:00
return out ;
}
/*static bool write_ksentry_file(const QString &id, const QString &fileName)
2005-03-14 11:40:03 +00:00
{
QFile f ( fileName ) ;
if ( ! f . open ( QFile : : WriteOnly | QFile : : Truncate ) )
return false ;
2007-03-29 03:26:27 +00:00
f . write ( make_ksentry_string ( id ) . toUtf8 ( ) ) ;
2005-03-14 11:40:03 +00:00
return true ;
2007-03-29 03:26:27 +00:00
} */
2005-03-14 11:40:03 +00:00
2007-03-29 03:26:27 +00:00
static QString read_ksentry_file ( const QString & fileName )
2005-03-14 11:40:03 +00:00
{
2007-03-29 03:26:27 +00:00
QString out ;
2005-03-14 11:40:03 +00:00
QFile f ( fileName ) ;
if ( ! f . open ( QFile : : ReadOnly ) )
2007-03-29 03:26:27 +00:00
return out ;
2005-03-14 11:40:03 +00:00
QTextStream ts ( & f ) ;
2007-03-29 03:26:27 +00:00
int linenum = 0 ;
2005-03-14 11:40:03 +00:00
while ( ! ts . atEnd ( ) )
{
QString line = ts . readLine ( ) ;
2007-03-29 03:26:27 +00:00
if ( linenum = = 0 )
{
2020-02-10 00:29:23 +01:00
if ( line ! = QLatin1String ( " QCATOOL_KEYSTOREENTRY_1 " ) )
2007-03-29 03:26:27 +00:00
return out ;
}
else
{
out = line_decode ( line ) ;
break ;
}
+ + linenum ;
2005-03-14 11:40:03 +00:00
}
2007-03-29 03:26:27 +00:00
return out ;
2005-03-14 11:40:03 +00:00
}
2007-08-20 15:16:08 +00:00
static bool is_pem_file ( const QString & fileName )
{
QFile f ( fileName ) ;
if ( ! f . open ( QFile : : ReadOnly ) )
return false ;
QTextStream ts ( & f ) ;
if ( ! ts . atEnd ( ) )
{
QString line = ts . readLine ( ) ;
2020-02-10 00:29:23 +01:00
if ( line . startsWith ( QLatin1String ( " -----BEGIN " ) ) )
2007-08-20 15:16:08 +00:00
return true ;
}
return false ;
}
2007-03-29 03:26:27 +00:00
static QByteArray read_der_file ( const QString & fileName )
2005-03-14 11:40:03 +00:00
{
2007-03-29 03:26:27 +00:00
QFile f ( fileName ) ;
if ( ! f . open ( QFile : : ReadOnly ) )
return QByteArray ( ) ;
return f . readAll ( ) ;
2005-03-14 11:40:03 +00:00
}
2007-03-29 03:26:27 +00:00
class InfoType
2005-03-14 11:40:03 +00:00
{
2007-03-29 03:26:27 +00:00
public :
QCA : : CertificateInfoType type ;
QString varname ;
QString shortname ;
QString name ;
QString desc ;
2005-03-14 11:40:03 +00:00
2007-03-29 03:26:27 +00:00
InfoType ( )
{
}
2020-01-29 17:23:29 +01:00
InfoType ( const QCA : : CertificateInfoType & _type , const QString & _varname , const QString & _shortname , const QString & _name , const QString & _desc )
2007-03-29 03:26:27 +00:00
: type ( _type ) , varname ( _varname ) , shortname ( _shortname ) , name ( _name ) , desc ( _desc )
{
}
} ;
2007-04-10 01:25:39 +00:00
static QList < InfoType > makeInfoTypeList ( bool legacyEmail = false )
2005-03-14 11:40:03 +00:00
{
2007-03-29 03:26:27 +00:00
QList < InfoType > out ;
2020-02-10 00:29:23 +01:00
out + = InfoType ( QCA : : CommonName , QStringLiteral ( " CommonName " ) , QStringLiteral ( " CN " ) , QStringLiteral ( " Common Name (CN) " ) , QStringLiteral ( " Full name, domain, anything " ) ) ;
out + = InfoType ( QCA : : Email , QStringLiteral ( " Email " ) , QLatin1String ( " " ) , QStringLiteral ( " Email Address " ) , QLatin1String ( " " ) ) ;
2007-04-10 01:25:39 +00:00
if ( legacyEmail )
2020-02-10 00:29:23 +01:00
out + = InfoType ( QCA : : EmailLegacy , QStringLiteral ( " EmailLegacy " ) , QLatin1String ( " " ) , QStringLiteral ( " PKCS#9 Email Address " ) , QLatin1String ( " " ) ) ;
out + = InfoType ( QCA : : Organization , QStringLiteral ( " Organization " ) , QStringLiteral ( " O " ) , QStringLiteral ( " Organization (O) " ) , QStringLiteral ( " Company, group, etc " ) ) ;
out + = InfoType ( QCA : : OrganizationalUnit , QStringLiteral ( " OrganizationalUnit " ) , QStringLiteral ( " OU " ) , QStringLiteral ( " Organizational Unit (OU) " ) , QStringLiteral ( " Division/branch of organization " ) ) ;
out + = InfoType ( QCA : : Locality , QStringLiteral ( " Locality " ) , QLatin1String ( " " ) , QStringLiteral ( " Locality (L) " ) , QStringLiteral ( " City, shire, part of a state " ) ) ;
out + = InfoType ( QCA : : State , QStringLiteral ( " State " ) , QLatin1String ( " " ) , QStringLiteral ( " State (ST) " ) , QStringLiteral ( " State within the country " ) ) ;
out + = InfoType ( QCA : : Country , QStringLiteral ( " Country " ) , QStringLiteral ( " C " ) , QStringLiteral ( " Country Code (C) " ) , QStringLiteral ( " 2-letter code " ) ) ;
out + = InfoType ( QCA : : IncorporationLocality , QStringLiteral ( " IncorporationLocality " ) , QLatin1String ( " " ) , QStringLiteral ( " Incorporation Locality " ) , QStringLiteral ( " For EV certificates " ) ) ;
out + = InfoType ( QCA : : IncorporationState , QStringLiteral ( " IncorporationState " ) , QLatin1String ( " " ) , QStringLiteral ( " Incorporation State " ) , QStringLiteral ( " For EV certificates " ) ) ;
out + = InfoType ( QCA : : IncorporationCountry , QStringLiteral ( " IncorporationCountry " ) , QLatin1String ( " " ) , QStringLiteral ( " Incorporation Country " ) , QStringLiteral ( " For EV certificates " ) ) ;
out + = InfoType ( QCA : : URI , QStringLiteral ( " URI " ) , QLatin1String ( " " ) , QStringLiteral ( " URI " ) , QLatin1String ( " " ) ) ;
out + = InfoType ( QCA : : DNS , QStringLiteral ( " DNS " ) , QLatin1String ( " " ) , QStringLiteral ( " Domain Name " ) , QStringLiteral ( " Domain (dnsName) " ) ) ;
out + = InfoType ( QCA : : IPAddress , QStringLiteral ( " IPAddress " ) , QLatin1String ( " " ) , QStringLiteral ( " IP Adddress " ) , QLatin1String ( " " ) ) ;
out + = InfoType ( QCA : : XMPP , QStringLiteral ( " XMPP " ) , QLatin1String ( " " ) , QStringLiteral ( " XMPP Address (JID) " ) , QStringLiteral ( " From RFC 3920 (id-on-xmppAddr) " ) ) ;
2007-03-29 03:26:27 +00:00
return out ;
2005-03-14 11:40:03 +00:00
}
2007-03-29 03:26:27 +00:00
class MyConstraintType
2005-03-14 11:40:03 +00:00
{
2007-03-29 03:26:27 +00:00
public :
QCA : : ConstraintType type ;
QString varname ;
QString name ;
QString desc ;
MyConstraintType ( )
2006-05-13 11:29:24 +00:00
{
}
2005-03-14 11:40:03 +00:00
2007-06-14 21:32:04 +00:00
MyConstraintType ( const QCA : : ConstraintType & _type , const QString & _varname , const QString & _name , const QString & _desc )
2007-03-29 03:26:27 +00:00
: type ( _type ) , varname ( _varname ) , name ( _name ) , desc ( _desc )
{
}
} ;
static QList < MyConstraintType > makeConstraintTypeList ( )
2005-03-14 11:40:03 +00:00
{
2007-03-29 03:26:27 +00:00
QList < MyConstraintType > out ;
2020-02-10 00:29:23 +01:00
out + = MyConstraintType ( QCA : : DigitalSignature , QStringLiteral ( " DigitalSignature " ) , QStringLiteral ( " Digital Signature " ) , QStringLiteral ( " Can be used for signing " ) ) ;
out + = MyConstraintType ( QCA : : NonRepudiation , QStringLiteral ( " NonRepudiation " ) , QStringLiteral ( " Non-Repudiation " ) , QStringLiteral ( " Usage is legally binding " ) ) ;
out + = MyConstraintType ( QCA : : KeyEncipherment , QStringLiteral ( " KeyEncipherment " ) , QStringLiteral ( " Key Encipherment " ) , QStringLiteral ( " Can encrypt other keys " ) ) ;
out + = MyConstraintType ( QCA : : DataEncipherment , QStringLiteral ( " DataEncipherment " ) , QStringLiteral ( " Data Encipherment " ) , QStringLiteral ( " Can encrypt arbitrary data " ) ) ;
out + = MyConstraintType ( QCA : : KeyAgreement , QStringLiteral ( " KeyAgreement " ) , QStringLiteral ( " Key Agreement " ) , QStringLiteral ( " Can perform key agreement (DH) " ) ) ;
out + = MyConstraintType ( QCA : : KeyCertificateSign , QStringLiteral ( " KeyCertificateSign " ) , QStringLiteral ( " Certificate Sign " ) , QStringLiteral ( " Can sign other certificates " ) ) ;
out + = MyConstraintType ( QCA : : CRLSign , QStringLiteral ( " CRLSign " ) , QStringLiteral ( " CRL Sign " ) , QStringLiteral ( " Can sign CRLs " ) ) ;
out + = MyConstraintType ( QCA : : EncipherOnly , QStringLiteral ( " EncipherOnly " ) , QStringLiteral ( " Encipher Only " ) , QStringLiteral ( " Can be used for encrypting " ) ) ;
out + = MyConstraintType ( QCA : : DecipherOnly , QStringLiteral ( " DecipherOnly " ) , QStringLiteral ( " Decipher Only " ) , QStringLiteral ( " Can be used for decrypting " ) ) ;
out + = MyConstraintType ( QCA : : ServerAuth , QStringLiteral ( " ServerAuth " ) , QStringLiteral ( " Server Authentication " ) , QStringLiteral ( " TLS Server " ) ) ;
out + = MyConstraintType ( QCA : : ClientAuth , QStringLiteral ( " ClientAuth " ) , QStringLiteral ( " Client Authentication " ) , QStringLiteral ( " TLS Client " ) ) ;
out + = MyConstraintType ( QCA : : CodeSigning , QStringLiteral ( " CodeSigning " ) , QStringLiteral ( " Code Signing " ) , QLatin1String ( " " ) ) ;
out + = MyConstraintType ( QCA : : EmailProtection , QStringLiteral ( " EmailProtection " ) , QStringLiteral ( " Email Protection " ) , QStringLiteral ( " S/MIME " ) ) ;
out + = MyConstraintType ( QCA : : IPSecEndSystem , QStringLiteral ( " IPSecEndSystem " ) , QStringLiteral ( " IPSec End-System " ) , QLatin1String ( " " ) ) ;
out + = MyConstraintType ( QCA : : IPSecTunnel , QStringLiteral ( " IPSecTunnel " ) , QStringLiteral ( " IPSec Tunnel " ) , QLatin1String ( " " ) ) ;
out + = MyConstraintType ( QCA : : IPSecUser , QStringLiteral ( " IPSecUser " ) , QStringLiteral ( " IPSec User " ) , QLatin1String ( " " ) ) ;
out + = MyConstraintType ( QCA : : TimeStamping , QStringLiteral ( " TimeStamping " ) , QStringLiteral ( " Time Stamping " ) , QLatin1String ( " " ) ) ;
out + = MyConstraintType ( QCA : : OCSPSigning , QStringLiteral ( " OCSPSigning " ) , QStringLiteral ( " OCSP Signing " ) , QLatin1String ( " " ) ) ;
2007-03-29 03:26:27 +00:00
return out ;
2005-03-14 11:40:03 +00:00
}
2007-05-14 06:15:56 +00:00
const char * crlEntryReasonToString ( QCA : : CRLEntry : : Reason r )
{
switch ( r )
{
case QCA : : CRLEntry : : Unspecified : return " Unspecified " ;
case QCA : : CRLEntry : : KeyCompromise : return " KeyCompromise " ;
case QCA : : CRLEntry : : CACompromise : return " CACompromise " ;
case QCA : : CRLEntry : : AffiliationChanged : return " AffiliationChanged " ;
case QCA : : CRLEntry : : Superseded : return " Superseded " ;
case QCA : : CRLEntry : : CessationOfOperation : return " CessationOfOperation " ;
case QCA : : CRLEntry : : CertificateHold : return " CertificateHold " ;
case QCA : : CRLEntry : : RemoveFromCRL : return " RemoveFromCRL " ;
case QCA : : CRLEntry : : PrivilegeWithdrawn : return " PrivilegeWithdrawn " ;
case QCA : : CRLEntry : : AACompromise : return " AACompromise " ;
default : return " Unknown " ;
}
}
2007-03-29 03:26:27 +00:00
static bool validOid ( const QString & in )
2005-03-14 11:40:03 +00:00
{
2020-01-30 17:24:31 +01:00
for ( const QChar & c : in )
2007-03-29 03:26:27 +00:00
{
2020-02-13 00:59:09 +01:00
if ( ! c . isDigit ( ) & & c ! = QLatin1Char ( ' . ' ) )
2007-03-29 03:26:27 +00:00
return false ;
2005-03-14 11:40:03 +00:00
}
2007-03-29 03:26:27 +00:00
return true ;
2005-03-14 11:40:03 +00:00
}
2007-03-29 03:26:27 +00:00
class ValidityLength
2005-03-14 11:40:03 +00:00
{
2007-03-29 03:26:27 +00:00
public :
int years , months , days ;
} ;
static int vl_getnext ( const QString & in , int offset = 0 )
{
if ( offset > = in . length ( ) )
return in . length ( ) ;
int n = offset ;
bool lookForNonDigit ;
if ( in [ n ] . isDigit ( ) )
lookForNonDigit = true ;
else
lookForNonDigit = false ;
for ( + + n ; n < in . length ( ) ; + + n )
2005-03-14 11:40:03 +00:00
{
2007-03-29 03:26:27 +00:00
if ( in [ n ] . isDigit ( ) ! = lookForNonDigit )
2005-03-14 11:40:03 +00:00
break ;
}
2007-03-29 03:26:27 +00:00
return n ;
2005-03-14 11:40:03 +00:00
}
2007-03-29 03:26:27 +00:00
static QStringList vl_getparts ( const QString & in )
2006-04-06 21:57:19 +00:00
{
2007-03-29 03:26:27 +00:00
QStringList out ;
int offset = 0 ;
2020-01-30 17:24:31 +01:00
while ( true )
2007-03-29 03:26:27 +00:00
{
int n = vl_getnext ( in , offset ) ;
if ( n = = offset )
break ;
out + = in . mid ( offset , n - offset ) ;
offset = n ;
}
return out ;
2006-04-06 21:57:19 +00:00
}
2007-03-29 03:26:27 +00:00
static bool parseValidityLength ( const QString & in , ValidityLength * vl )
2005-05-10 21:10:35 +00:00
{
2007-03-29 03:26:27 +00:00
vl - > years = - 1 ;
vl - > months = - 1 ;
vl - > days = - 1 ;
QStringList parts = vl_getparts ( in ) ;
2020-01-30 17:24:31 +01:00
while ( true )
2005-05-10 21:10:35 +00:00
{
2007-03-29 03:26:27 +00:00
// first part should be a number
if ( parts . count ( ) < 1 )
2005-05-10 21:10:35 +00:00
break ;
2007-03-29 03:26:27 +00:00
QString str = parts . takeFirst ( ) ;
bool ok ;
int x = str . toInt ( & ok ) ;
if ( ! ok )
return false ;
// next part should be 1 letter plus any amount of space
if ( parts . count ( ) < 1 )
return false ;
str = parts . takeFirst ( ) ;
if ( ! str [ 0 ] . isLetter ( ) )
return false ;
str = str . trimmed ( ) ; // remove space
2020-02-10 00:29:23 +01:00
if ( str = = QLatin1String ( " y " ) )
2005-05-10 21:10:35 +00:00
{
2007-03-29 03:26:27 +00:00
if ( vl - > years ! = - 1 )
return false ;
vl - > years = x ;
}
2020-02-10 00:29:23 +01:00
if ( str = = QLatin1String ( " m " ) )
2007-03-29 03:26:27 +00:00
{
if ( vl - > months ! = - 1 )
return false ;
vl - > months = x ;
}
2020-02-10 00:29:23 +01:00
if ( str = = QLatin1String ( " d " ) )
2007-03-29 03:26:27 +00:00
{
if ( vl - > days ! = - 1 )
return false ;
vl - > days = x ;
2005-05-10 21:10:35 +00:00
}
}
2007-03-29 03:26:27 +00:00
if ( vl - > years = = - 1 )
vl - > years = 0 ;
if ( vl - > months = = - 1 )
vl - > months = 0 ;
if ( vl - > days = = - 1 )
vl - > days = 0 ;
return true ;
2005-06-25 20:27:10 +00:00
}
2007-03-29 03:26:27 +00:00
static QString prompt_for ( const QString & prompt )
2005-06-25 20:27:10 +00:00
{
2007-03-29 03:26:27 +00:00
printf ( " %s: " , prompt . toLatin1 ( ) . data ( ) ) ;
fflush ( stdout ) ;
QByteArray result ( 256 , 0 ) ;
2010-11-27 20:38:00 +00:00
if ( fgets ( ( char * ) result . data ( ) , result . size ( ) , stdin ) )
return QString : : fromLocal8Bit ( result ) . trimmed ( ) ;
else
return QString ( ) ;
2005-06-25 20:27:10 +00:00
}
2007-03-29 03:26:27 +00:00
static QCA : : CertificateOptions promptForCertAttributes ( bool advanced , bool req )
2005-06-25 20:27:10 +00:00
{
2007-03-29 03:26:27 +00:00
QCA : : CertificateOptions opts ;
if ( advanced )
{
if ( ! req )
{
2020-01-30 17:24:31 +01:00
while ( true )
2007-03-29 03:26:27 +00:00
{
2020-02-10 00:29:23 +01:00
QString str = prompt_for ( QStringLiteral ( " Create an end user ('user') certificate or a CA ('ca') certificate? [user] " ) ) ;
2007-03-29 03:26:27 +00:00
if ( str . isEmpty ( ) )
2020-02-10 00:29:23 +01:00
str = QStringLiteral ( " user " ) ;
if ( str ! = QLatin1String ( " user " ) & & str ! = QLatin1String ( " ca " ) )
2007-03-29 03:26:27 +00:00
{
printf ( " '%s' is not a valid entry. \n " , qPrintable ( str ) ) ;
continue ;
}
2020-02-10 00:29:23 +01:00
if ( str = = QLatin1String ( " ca " ) )
2007-03-29 03:26:27 +00:00
opts . setAsCA ( ) ;
break ;
}
printf ( " \n " ) ;
2020-01-30 17:24:31 +01:00
while ( true )
2007-03-29 03:26:27 +00:00
{
2020-02-10 00:29:23 +01:00
QString str = prompt_for ( QStringLiteral ( " Serial Number " ) ) ;
2007-04-13 19:04:16 +00:00
QCA : : BigInteger num ;
2007-03-29 03:26:27 +00:00
if ( str . isEmpty ( ) | | ! num . fromString ( str ) )
{
printf ( " '%s' is not a valid entry. \n " , qPrintable ( str ) ) ;
continue ;
}
opts . setSerialNumber ( num ) ;
break ;
}
printf ( " \n " ) ;
}
{
QCA : : CertificateInfoOrdered info ;
printf ( " Choose the information attributes to add to the certificate. They will be \n "
" added in the order they are entered. \n \n " ) ;
printf ( " Available information attributes: \n " ) ;
QList < InfoType > list = makeInfoTypeList ( ) ;
for ( int n = 0 ; n < list . count ( ) ; + + n )
{
const InfoType & i = list [ n ] ;
char c = ' a ' + n ;
printf ( " %c) %-32s %s \n " , c , qPrintable ( i . name ) , qPrintable ( i . desc ) ) ;
}
printf ( " \n " ) ;
2020-01-30 17:24:31 +01:00
while ( true )
2007-03-29 03:26:27 +00:00
{
int index ;
2020-01-30 17:24:31 +01:00
while ( true )
2007-03-29 03:26:27 +00:00
{
2020-02-10 00:29:23 +01:00
QString str = prompt_for ( QStringLiteral ( " Select an attribute to add, or enter to move on " ) ) ;
2007-03-29 03:26:27 +00:00
if ( str . isEmpty ( ) )
{
index = - 1 ;
break ;
}
if ( str . length ( ) = = 1 )
{
index = str [ 0 ] . toLatin1 ( ) - ' a ' ;
if ( index > = 0 & & index < list . count ( ) )
break ;
}
printf ( " '%s' is not a valid entry. \n " , qPrintable ( str ) ) ;
}
if ( index = = - 1 )
break ;
QString val = prompt_for ( list [ index ] . name ) ;
info + = QCA : : CertificateInfoPair ( list [ index ] . type , val ) ;
printf ( " Added attribute. \n \n " ) ;
}
opts . setInfoOrdered ( info ) ;
}
{
QCA : : Constraints constraints ;
printf ( " \n " ) ;
printf ( " Choose the constraint attributes to add to the certificate. \n \n " ) ;
printf ( " Available attributes: \n " ) ;
QList < MyConstraintType > list = makeConstraintTypeList ( ) ;
for ( int n = 0 ; n < list . count ( ) ; + + n )
{
const MyConstraintType & i = list [ n ] ;
char c = ' a ' + n ;
printf ( " %c) %-32s %s \n " , c , qPrintable ( i . name ) , qPrintable ( i . desc ) ) ;
}
printf ( " \n " ) ;
printf ( " If no constraints are added, then the certificate may be used for any purpose. \n \n " ) ;
2020-01-30 17:24:31 +01:00
while ( true )
2007-03-29 03:26:27 +00:00
{
int index ;
2020-01-30 17:24:31 +01:00
while ( true )
2007-03-29 03:26:27 +00:00
{
2020-02-10 00:29:23 +01:00
QString str = prompt_for ( QStringLiteral ( " Select an attribute to add, or enter to move on " ) ) ;
2007-03-29 03:26:27 +00:00
if ( str . isEmpty ( ) )
{
index = - 1 ;
break ;
}
if ( str . length ( ) = = 1 )
{
index = str [ 0 ] . toLatin1 ( ) - ' a ' ;
if ( index > = 0 & & index < list . count ( ) )
break ;
}
printf ( " '%s' is not a valid entry. \n \n " , qPrintable ( str ) ) ;
}
if ( index = = - 1 )
break ;
if ( constraints . contains ( list [ index ] . type ) )
{
printf ( " You have already added '%s'. \n \n " , qPrintable ( list [ index ] . name ) ) ;
continue ;
}
constraints + = list [ index ] . type ;
printf ( " Added attribute. \n \n " ) ;
}
opts . setConstraints ( constraints ) ;
}
{
QStringList policies ;
printf ( " \n " ) ;
printf ( " Are there any policy OID attributes that you wish to add? Use the dotted \n "
" string format. \n \n " ) ;
2020-01-30 17:24:31 +01:00
while ( true )
2007-03-29 03:26:27 +00:00
{
2020-02-10 00:29:23 +01:00
QString str = prompt_for ( QStringLiteral ( " Enter a policy OID to add, or enter to move on " ) ) ;
2007-03-29 03:26:27 +00:00
if ( str . isEmpty ( ) )
break ;
if ( ! validOid ( str ) )
{
printf ( " '%s' is not a valid entry. \n \n " , qPrintable ( str ) ) ;
continue ;
}
if ( policies . contains ( str ) )
{
printf ( " You have already added '%s'. \n \n " , qPrintable ( str ) ) ;
continue ;
}
policies + = str ;
printf ( " Added attribute. \n \n " ) ;
}
opts . setPolicies ( policies ) ;
}
printf ( " \n " ) ;
}
else
{
QCA : : CertificateInfo info ;
2020-02-10 00:29:23 +01:00
info . insert ( QCA : : CommonName , prompt_for ( QStringLiteral ( " Common Name " ) ) ) ;
info . insert ( QCA : : Country , prompt_for ( QStringLiteral ( " Country Code (2 letters) " ) ) ) ;
info . insert ( QCA : : Organization , prompt_for ( QStringLiteral ( " Organization " ) ) ) ;
info . insert ( QCA : : Email , prompt_for ( QStringLiteral ( " Email " ) ) ) ;
2007-03-29 03:26:27 +00:00
opts . setInfo ( info ) ;
printf ( " \n " ) ;
}
if ( ! req )
{
2020-01-30 17:24:31 +01:00
while ( true )
2007-03-29 03:26:27 +00:00
{
2020-02-10 00:29:23 +01:00
QString str = prompt_for ( QStringLiteral ( " How long should the certificate be valid? (e.g. '1y2m3d') " ) ) ;
2007-03-29 03:26:27 +00:00
ValidityLength vl ;
if ( ! parseValidityLength ( str , & vl ) )
{
printf ( " '%s' is not a valid entry. \n \n " , qPrintable ( str ) ) ;
continue ;
}
if ( vl . years = = 0 & & vl . months = = 0 & & vl . days = = 0 )
{
printf ( " The certificate must be valid for at least one day. \n \n " ) ;
continue ;
}
2020-01-29 15:15:27 +01:00
QDateTime start = QDateTime : : currentDateTimeUtc ( ) ;
2007-03-29 03:26:27 +00:00
QDateTime end = start ;
if ( vl . years > 0 )
end = end . addYears ( vl . years ) ;
if ( vl . months > 0 )
end = end . addMonths ( vl . months ) ;
if ( vl . days > 0 )
end = end . addDays ( vl . days ) ;
opts . setValidityPeriod ( start , end ) ;
QStringList parts ;
if ( vl . years > 0 )
2020-02-10 00:29:23 +01:00
parts + = QStringLiteral ( " %1 year(s) " ) . arg ( vl . years ) ;
2007-03-29 03:26:27 +00:00
if ( vl . months > 0 )
2020-02-10 00:29:23 +01:00
parts + = QStringLiteral ( " %1 month(s) " ) . arg ( vl . months ) ;
2007-03-29 03:26:27 +00:00
if ( vl . days > 0 )
2020-02-10 00:29:23 +01:00
parts + = QStringLiteral ( " %1 day(s) " ) . arg ( vl . days ) ;
2007-03-29 03:26:27 +00:00
QString out ;
if ( parts . count ( ) = = 1 )
out = parts [ 0 ] ;
else if ( parts . count ( ) = = 2 )
2020-02-13 00:59:09 +01:00
out = parts [ 0 ] + QStringLiteral ( " and " ) + parts [ 1 ] ;
2007-03-29 03:26:27 +00:00
else if ( parts . count ( ) = = 3 )
2020-02-13 00:59:09 +01:00
out = parts [ 0 ] + QStringLiteral ( " , " ) + parts [ 1 ] + QStringLiteral ( " , and " ) + parts [ 2 ] ;
2007-03-29 03:26:27 +00:00
printf ( " Certificate will be valid for %s. \n " , qPrintable ( out ) ) ;
break ;
}
printf ( " \n " ) ;
}
return opts ;
}
2007-05-16 01:04:15 +00:00
// qsettings seems to give us a string type for both bool and int (and
// possibly others, but those are the only two we care about here).
// in order to figure out what is actually a bool or an int, we need
// to examine the string. so for the functions below, we convert
// the variant to a string, and then inspect it to see if it looks
// like a bool or an int.
static bool string_is_bool ( const QString & in )
{
QString lc = in . toLower ( ) ;
2020-02-10 00:29:23 +01:00
if ( lc = = QLatin1String ( " true " ) | | lc = = QLatin1String ( " false " ) )
2007-05-16 01:04:15 +00:00
return true ;
return false ;
}
static bool string_is_int ( const QString & in )
{
bool ok ;
in . toInt ( & ok ) ;
return ok ;
}
static bool variant_is_bool ( const QVariant & in )
{
2013-04-02 11:00:43 +00:00
if ( in . canConvert < QString > ( ) & & string_is_bool ( in . toString ( ) ) )
2007-05-16 01:04:15 +00:00
return true ;
return false ;
}
static bool variant_is_int ( const QVariant & in )
{
2013-04-02 11:00:43 +00:00
if ( in . canConvert < QString > ( ) & & string_is_int ( in . toString ( ) ) )
2007-05-16 01:04:15 +00:00
return true ;
return false ;
}
static QString prompt_for_string ( const QString & prompt , const QString & def = QString ( ) )
{
printf ( " %s " , prompt . toLatin1 ( ) . data ( ) ) ;
fflush ( stdout ) ;
QByteArray result ( 256 , 0 ) ;
2010-11-27 20:38:00 +00:00
if ( ! fgets ( ( char * ) result . data ( ) , result . size ( ) , stdin ) )
return QString ( ) ;
2008-05-25 17:11:37 +00:00
if ( result [ result . length ( ) - 1 ] = = ' \n ' )
result . truncate ( result . length ( ) - 1 ) ;
// empty input -> use default
if ( result . isEmpty ( ) )
2007-05-16 01:04:15 +00:00
return def ;
2008-05-25 17:11:37 +00:00
// trimmed input could result in an empty value, but in that case
// it is treated as if the user wishes to submit an empty value.
return QString : : fromLocal8Bit ( result ) . trimmed ( ) ;
2007-05-16 01:04:15 +00:00
}
static int prompt_for_int ( const QString & prompt , int def = 0 )
{
2020-01-30 17:24:31 +01:00
while ( true )
2007-05-16 01:04:15 +00:00
{
QString str = prompt_for_string ( prompt ) ;
if ( str . isEmpty ( ) )
return def ;
bool ok ;
int x = str . toInt ( & ok ) ;
if ( ok )
return x ;
printf ( " '%s' is not a valid entry. \n \n " , qPrintable ( str ) ) ;
}
}
static bool partial_compare_nocase ( const QString & in , const QString & target , int min = 1 )
{
if ( in . length ( ) > = min & & in . length ( ) < = target . length ( ) & & target . mid ( 0 , in . length ( ) ) . toLower ( ) = = in . toLower ( ) )
return true ;
return false ;
}
static bool prompt_for_bool ( const QString & prompt , bool def = false )
{
2020-01-30 17:24:31 +01:00
while ( true )
2007-05-16 01:04:15 +00:00
{
QString str = prompt_for_string ( prompt ) ;
if ( str . isEmpty ( ) )
return def ;
2020-02-10 00:29:23 +01:00
if ( partial_compare_nocase ( str , QStringLiteral ( " true " ) ) )
2007-05-16 01:04:15 +00:00
return true ;
2020-02-10 00:29:23 +01:00
else if ( partial_compare_nocase ( str , QStringLiteral ( " false " ) ) )
2007-05-16 01:04:15 +00:00
return false ;
printf ( " '%s' is not a valid entry. \n \n " , qPrintable ( str ) ) ;
}
}
static bool prompt_for_yesno ( const QString & prompt , bool def = false )
{
2020-01-30 17:24:31 +01:00
while ( true )
2007-05-16 01:04:15 +00:00
{
QString str = prompt_for_string ( prompt ) ;
if ( str . isEmpty ( ) )
return def ;
2020-02-10 00:29:23 +01:00
if ( partial_compare_nocase ( str , QStringLiteral ( " yes " ) ) )
2007-05-16 01:04:15 +00:00
return true ;
2020-02-10 00:29:23 +01:00
else if ( partial_compare_nocase ( str , QStringLiteral ( " no " ) ) )
2007-05-16 01:04:15 +00:00
return false ;
printf ( " '%s' is not a valid entry. \n \n " , qPrintable ( str ) ) ;
}
}
2007-05-16 21:46:00 +00:00
static QString prompt_for_slotevent_method ( const QString & prompt , const QString & def = QString ( ) )
{
2020-01-30 17:24:31 +01:00
while ( true )
2007-05-16 21:46:00 +00:00
{
QString str = prompt_for_string ( prompt ) ;
if ( str . isEmpty ( ) )
return def ;
2020-02-10 00:29:23 +01:00
if ( partial_compare_nocase ( str , QStringLiteral ( " auto " ) ) )
return QStringLiteral ( " auto " ) ;
else if ( partial_compare_nocase ( str , QStringLiteral ( " trigger " ) ) )
return QStringLiteral ( " trigger " ) ;
else if ( partial_compare_nocase ( str , QStringLiteral ( " poll " ) ) )
return QStringLiteral ( " poll " ) ;
2007-05-16 21:46:00 +00:00
printf ( " '%s' is not a valid entry. \n \n " , qPrintable ( str ) ) ;
}
}
2007-05-16 01:04:15 +00:00
static QVariantMap provider_config_edit_generic ( const QVariantMap & in )
{
QVariantMap config = in ;
QMutableMapIterator < QString , QVariant > it ( config ) ;
while ( it . hasNext ( ) )
{
it . next ( ) ;
QString var = it . key ( ) ;
2020-02-10 00:29:23 +01:00
if ( var = = QLatin1String ( " formtype " ) )
2007-05-16 01:04:15 +00:00
continue ;
QVariant val = it . value ( ) ;
// fields must be bool, int, or string
QVariant newval ;
2020-02-10 00:29:23 +01:00
QString prompt = QStringLiteral ( " %1: [%2] " ) . arg ( var , val . toString ( ) ) ;
2007-05-16 01:04:15 +00:00
if ( variant_is_bool ( val ) )
2020-02-10 00:29:23 +01:00
newval = prompt_for_bool ( QStringLiteral ( " bool " ) + prompt , val . toBool ( ) ) ;
2007-05-16 01:04:15 +00:00
else if ( variant_is_int ( val ) )
2020-02-10 00:29:23 +01:00
newval = prompt_for_int ( QStringLiteral ( " int " ) + prompt , val . toInt ( ) ) ;
2013-04-02 11:00:43 +00:00
else if ( val . canConvert < QString > ( ) )
2020-02-10 00:29:23 +01:00
newval = prompt_for_string ( QStringLiteral ( " string " ) + prompt , val . toString ( ) ) ;
2007-05-16 01:04:15 +00:00
else
continue ; // skip bogus fields
it . setValue ( newval ) ;
}
return config ;
}
class Pkcs11ProviderConfig
{
public :
bool allow_protected_authentication ;
bool cert_private ;
bool enabled ;
QString library ;
QString name ;
int private_mask ;
QString slotevent_method ;
int slotevent_timeout ;
Pkcs11ProviderConfig ( ) :
allow_protected_authentication ( true ) ,
cert_private ( false ) ,
enabled ( false ) ,
private_mask ( 0 ) ,
2020-02-10 00:29:23 +01:00
slotevent_method ( QStringLiteral ( " auto " ) ) ,
2007-05-16 01:04:15 +00:00
slotevent_timeout ( 0 )
{
}
QVariantMap toVariantMap ( ) const
{
QVariantMap out ;
2020-02-10 00:29:23 +01:00
out [ QStringLiteral ( " allow_protected_authentication " ) ] = allow_protected_authentication ;
out [ QStringLiteral ( " cert_private " ) ] = cert_private ;
out [ QStringLiteral ( " enabled " ) ] = enabled ;
out [ QStringLiteral ( " library " ) ] = library ;
out [ QStringLiteral ( " name " ) ] = name ;
out [ QStringLiteral ( " private_mask " ) ] = private_mask ;
out [ QStringLiteral ( " slotevent_method " ) ] = slotevent_method ;
out [ QStringLiteral ( " slotevent_timeout " ) ] = slotevent_timeout ;
2007-05-16 01:04:15 +00:00
return out ;
}
bool fromVariantMap ( const QVariantMap & in )
{
2020-02-10 00:29:23 +01:00
allow_protected_authentication = in [ QStringLiteral ( " allow_protected_authentication " ) ] . toBool ( ) ;
cert_private = in [ QStringLiteral ( " cert_private " ) ] . toBool ( ) ;
enabled = in [ QStringLiteral ( " enabled " ) ] . toBool ( ) ;
library = in [ QStringLiteral ( " library " ) ] . toString ( ) ;
name = in [ QStringLiteral ( " name " ) ] . toString ( ) ;
private_mask = in [ QStringLiteral ( " private_mask " ) ] . toInt ( ) ;
slotevent_method = in [ QStringLiteral ( " slotevent_method " ) ] . toString ( ) ;
slotevent_timeout = in [ QStringLiteral ( " slotevent_timeout " ) ] . toInt ( ) ;
2007-05-16 01:04:15 +00:00
return true ;
}
} ;
class Pkcs11Config
{
public :
bool allow_load_rootca ;
bool allow_protected_authentication ;
int log_level ;
int pin_cache ;
QList < Pkcs11ProviderConfig > providers ;
QVariantMap orig_config ;
Pkcs11Config ( ) :
allow_load_rootca ( false ) ,
allow_protected_authentication ( true ) ,
log_level ( 0 ) ,
pin_cache ( - 1 )
{
}
QVariantMap toVariantMap ( ) const
{
QVariantMap out = orig_config ;
// form type
2020-02-13 00:59:09 +01:00
out [ QStringLiteral ( " formtype " ) ] = QLatin1String ( " http://affinix.com/qca/forms/qca-pkcs11#1.0 " ) ;
2007-05-16 01:04:15 +00:00
// base settings
2020-02-10 00:29:23 +01:00
out [ QStringLiteral ( " allow_load_rootca " ) ] = allow_load_rootca ;
out [ QStringLiteral ( " allow_protected_authentication " ) ] = allow_protected_authentication ;
out [ QStringLiteral ( " log_level " ) ] = log_level ;
out [ QStringLiteral ( " pin_cache " ) ] = pin_cache ;
2007-05-16 01:04:15 +00:00
// provider settings (always write at least 10 providers)
for ( int n = 0 ; n < 10 | | n < providers . count ( ) ; + + n )
{
2020-01-19 17:42:58 +01:00
QString prefix = QString : : asprintf ( " provider_%02d_ " , n ) ;
2007-05-16 01:04:15 +00:00
Pkcs11ProviderConfig provider ;
if ( n < providers . count ( ) )
provider = providers [ n ] ;
QVariantMap subconfig = provider . toVariantMap ( ) ;
QMapIterator < QString , QVariant > it ( subconfig ) ;
while ( it . hasNext ( ) )
{
it . next ( ) ;
out . insert ( prefix + it . key ( ) , it . value ( ) ) ;
}
}
return out ;
}
bool fromVariantMap ( const QVariantMap & in )
{
2020-02-13 00:59:09 +01:00
if ( in [ QStringLiteral ( " formtype " ) ] ! = QLatin1String ( " http://affinix.com/qca/forms/qca-pkcs11#1.0 " ) )
2007-05-16 01:04:15 +00:00
return false ;
2020-02-10 00:29:23 +01:00
allow_load_rootca = in [ QStringLiteral ( " allow_load_rootca " ) ] . toBool ( ) ;
allow_protected_authentication = in [ QStringLiteral ( " allow_protected_authentication " ) ] . toBool ( ) ;
log_level = in [ QStringLiteral ( " log_level " ) ] . toInt ( ) ;
pin_cache = in [ QStringLiteral ( " pin_cache " ) ] . toInt ( ) ;
2007-05-16 01:04:15 +00:00
for ( int n = 0 ; ; + + n )
{
2020-01-19 17:42:58 +01:00
QString prefix = QString : : asprintf ( " provider_%02d_ " , n ) ;
2007-05-16 01:04:15 +00:00
// collect all key/values with this prefix into a
// a separate container, leaving out the prefix
// from the keys.
QVariantMap subconfig ;
QMapIterator < QString , QVariant > it ( in ) ;
while ( it . hasNext ( ) )
{
it . next ( ) ;
if ( it . key ( ) . startsWith ( prefix ) )
subconfig . insert ( it . key ( ) . mid ( prefix . length ( ) ) , it . value ( ) ) ;
}
// if there are no config items with this prefix, we're done
if ( subconfig . isEmpty ( ) )
break ;
Pkcs11ProviderConfig provider ;
if ( ! provider . fromVariantMap ( subconfig ) )
return false ;
// skip unnamed entries
if ( provider . name . isEmpty ( ) )
continue ;
// skip duplicate entries
bool have_name_already = false ;
foreach ( const Pkcs11ProviderConfig & i , providers )
{
if ( i . name = = provider . name )
{
have_name_already = true ;
break ;
}
}
if ( have_name_already )
continue ;
providers + = provider ;
}
orig_config = in ;
return true ;
}
} ;
static QVariantMap provider_config_edit_pkcs11 ( const QVariantMap & in )
{
Pkcs11Config config ;
if ( ! config . fromVariantMap ( in ) )
{
fprintf ( stderr , " Error: unable to parse PKCS#11 provider configuration. \n " ) ;
return QVariantMap ( ) ;
}
2020-01-30 17:24:31 +01:00
while ( true )
2007-05-16 01:04:15 +00:00
{
printf ( " \n " ) ;
printf ( " Global settings: \n " ) ;
printf ( " Allow loading of root CAs: %s \n " , config . allow_load_rootca ? " Yes " : " No " ) ;
printf ( " Allow protected authentication: %s \n " , config . allow_protected_authentication ? " Yes " : " No " ) ;
QString str ;
if ( config . pin_cache = = - 1 )
2020-02-10 00:29:23 +01:00
str = QStringLiteral ( " No limit " ) ;
2007-05-16 01:04:15 +00:00
else
2020-02-10 00:29:23 +01:00
str = QStringLiteral ( " %1 seconds " ) . arg ( config . pin_cache ) ;
2007-05-16 01:04:15 +00:00
printf ( " Maximum PIN cache time: %s \n " , qPrintable ( str ) ) ;
printf ( " Log level: %d \n " , config . log_level ) ;
2007-05-16 21:46:00 +00:00
printf ( " \n " ) ;
2007-05-16 01:04:15 +00:00
printf ( " PKCS#11 modules: \n " ) ;
if ( ! config . providers . isEmpty ( ) )
{
foreach ( const Pkcs11ProviderConfig & provider , config . providers )
printf ( " %s \n " , qPrintable ( provider . name ) ) ;
}
else
printf ( " (None) \n " ) ;
printf ( " \n " ) ;
printf ( " Actions: \n " ) ;
printf ( " a) Edit global settings \n " ) ;
printf ( " b) Add PKCS#11 module \n " ) ;
printf ( " c) Edit PKCS#11 module \n " ) ;
printf ( " d) Remove PKCS#11 module \n " ) ;
printf ( " \n " ) ;
int index ;
2020-01-30 17:24:31 +01:00
while ( true )
2007-05-16 01:04:15 +00:00
{
2020-02-10 00:29:23 +01:00
QString str = prompt_for ( QStringLiteral ( " Select an action, or enter to quit " ) ) ;
2007-05-16 01:04:15 +00:00
if ( str . isEmpty ( ) )
{
index = - 1 ;
break ;
}
if ( str . length ( ) = = 1 )
{
index = str [ 0 ] . toLatin1 ( ) - ' a ' ;
if ( index > = 0 & & index < 4 )
break ;
}
printf ( " '%s' is not a valid entry. \n \n " , qPrintable ( str ) ) ;
}
if ( index = = - 1 )
break ;
if ( index = = 0 )
{
printf ( " \n " ) ;
QString prompt ;
2020-02-10 00:29:23 +01:00
prompt = QStringLiteral ( " Allow loading of root CAs: [%1] " ) . arg ( config . allow_load_rootca ? QStringLiteral ( " Yes " ) : QStringLiteral ( " No " ) ) ;
2007-05-16 01:04:15 +00:00
config . allow_load_rootca = prompt_for_yesno ( prompt , config . allow_load_rootca ) ;
2020-02-10 00:29:23 +01:00
prompt = QStringLiteral ( " Allow protected authentication: [%1] " ) . arg ( config . allow_protected_authentication ? QStringLiteral ( " Yes " ) : QStringLiteral ( " No " ) ) ;
2007-05-16 01:04:15 +00:00
config . allow_protected_authentication = prompt_for_yesno ( prompt , config . allow_protected_authentication ) ;
2020-02-10 00:29:23 +01:00
prompt = QStringLiteral ( " Maximum PIN cache time in seconds (-1 for no limit): [%1] " ) . arg ( config . pin_cache ) ;
2007-05-16 01:04:15 +00:00
config . pin_cache = prompt_for_int ( prompt , config . pin_cache ) ;
2020-02-10 00:29:23 +01:00
prompt = QStringLiteral ( " Log level: [%1] " ) . arg ( config . log_level ) ;
2007-05-16 01:04:15 +00:00
config . log_level = prompt_for_int ( prompt , config . log_level ) ;
}
2007-05-16 21:46:00 +00:00
else // 1, 2, 3
{
int at = - 1 ;
// for edit/remove, need to select provider
if ( index = = 2 | | index = = 3 )
{
printf ( " \n Which PKCS#11 module? \n " ) ;
for ( int n = 0 ; n < config . providers . count ( ) ; + + n )
{
const Pkcs11ProviderConfig & provider = config . providers [ n ] ;
char c = ' a ' + n ;
printf ( " %c) %s \n " , c , qPrintable ( provider . name ) ) ;
}
printf ( " \n " ) ;
int index ;
2020-01-30 17:24:31 +01:00
while ( true )
2007-05-16 21:46:00 +00:00
{
2020-02-10 00:29:23 +01:00
QString str = prompt_for ( QStringLiteral ( " Select a module, or enter to go back " ) ) ;
2007-05-16 21:46:00 +00:00
if ( str . isEmpty ( ) )
{
index = - 1 ;
break ;
}
if ( str . length ( ) = = 1 )
{
index = str [ 0 ] . toLatin1 ( ) - ' a ' ;
if ( index > = 0 & & index < config . providers . count ( ) )
break ;
}
printf ( " '%s' is not a valid entry. \n " , qPrintable ( str ) ) ;
}
// exit?
if ( index = = - 1 )
continue ;
at = index ;
}
// edit the entry
if ( index = = 1 | | index = = 2 )
{
Pkcs11ProviderConfig provider ;
if ( index = = 2 ) // edit
provider = config . providers [ at ] ;
provider . enabled = true ;
printf ( " \n " ) ;
QString prompt ;
// prompt for unique name
2020-01-30 17:24:31 +01:00
while ( true )
2007-05-16 21:46:00 +00:00
{
if ( index = = 1 )
2020-02-10 00:29:23 +01:00
prompt = QStringLiteral ( " Unique friendly name: " ) ;
2007-05-16 21:46:00 +00:00
else
2020-02-10 00:29:23 +01:00
prompt = QStringLiteral ( " Unique friendly name: [%1] " ) . arg ( provider . name ) ;
2007-05-16 21:46:00 +00:00
provider . name = prompt_for_string ( prompt , provider . name ) ;
if ( provider . name . isEmpty ( ) )
{
printf ( " The friendly name cannot be blank. \n \n " ) ;
continue ;
}
bool have_name_already = false ;
for ( int n = 0 ; n < config . providers . count ( ) ; + + n )
{
const Pkcs11ProviderConfig & i = config . providers [ n ] ;
// skip checking against the entry we are editing
if ( at ! = - 1 & & n = = at )
continue ;
if ( i . name = = provider . name )
{
have_name_already = true ;
break ;
}
}
if ( have_name_already )
{
printf ( " This name is already used by another module. \n \n " ) ;
continue ;
}
break ;
}
// prompt for library file
QString last ;
2020-01-30 17:24:31 +01:00
while ( true )
2007-05-16 21:46:00 +00:00
{
if ( index = = 1 )
2020-02-10 00:29:23 +01:00
prompt = QStringLiteral ( " Library filename: " ) ;
2007-05-16 21:46:00 +00:00
else
2020-02-10 00:29:23 +01:00
prompt = QStringLiteral ( " Library filename: [%1] " ) . arg ( provider . library ) ;
2007-05-16 21:46:00 +00:00
provider . library = prompt_for_string ( prompt , provider . library ) ;
if ( provider . library . isEmpty ( ) )
{
printf ( " The library filename cannot be blank. \n \n " ) ;
continue ;
}
if ( last ! = provider . library & & ! QFile : : exists ( provider . library ) )
{
last = provider . library ;
printf ( " '%s' does not exist. \n Press enter again if you really want this. \n \n " , qPrintable ( provider . library ) ) ;
continue ;
}
break ;
}
2020-02-10 00:29:23 +01:00
prompt = QStringLiteral ( " Allow protected authentication: [%1] " ) . arg ( provider . allow_protected_authentication ? QStringLiteral ( " Yes " ) : QStringLiteral ( " No " ) ) ;
2007-05-16 21:46:00 +00:00
provider . allow_protected_authentication = prompt_for_yesno ( prompt , provider . allow_protected_authentication ) ;
2020-02-10 00:29:23 +01:00
prompt = QStringLiteral ( " Provider stores certificates as private objects: [%1] " ) . arg ( provider . cert_private ? QStringLiteral ( " Yes " ) : QStringLiteral ( " No " ) ) ;
2007-05-16 21:46:00 +00:00
provider . cert_private = prompt_for_yesno ( prompt , provider . cert_private ) ;
printf ( " \n " ) ;
printf ( " Provider private key mask: \n " ) ;
printf ( " 0 Determine automatically. \n " ) ;
printf ( " 1 Use sign. \n " ) ;
printf ( " 2 Use sign recover. \n " ) ;
printf ( " 4 Use decrypt. \n " ) ;
printf ( " 8 Use unwrap. \n " ) ;
2020-02-10 00:29:23 +01:00
prompt = QStringLiteral ( " Mask value: [%1] " ) . arg ( provider . private_mask ) ;
2007-05-16 21:46:00 +00:00
provider . private_mask = prompt_for_int ( prompt , provider . private_mask ) ;
printf ( " \n " ) ;
printf ( " Slot event method: \n " ) ;
printf ( " auto Determine automatically. \n " ) ;
printf ( " trigger Use trigger. \n " ) ;
printf ( " poll Use poll. \n " ) ;
2020-02-10 00:29:23 +01:00
prompt = QStringLiteral ( " Method value: [%1] " ) . arg ( provider . slotevent_method ) ;
2007-05-16 21:46:00 +00:00
provider . slotevent_method = prompt_for_slotevent_method ( prompt , provider . slotevent_method ) ;
2020-02-10 00:29:23 +01:00
if ( provider . slotevent_method = = QLatin1String ( " poll " ) )
2007-05-16 21:46:00 +00:00
{
2020-02-10 00:29:23 +01:00
prompt = QStringLiteral ( " Poll timeout (0 for no preference): [%1] " ) . arg ( provider . slotevent_timeout ) ;
2007-05-16 21:46:00 +00:00
provider . slotevent_timeout = prompt_for_int ( prompt , provider . slotevent_timeout ) ;
}
else
provider . slotevent_timeout = 0 ;
if ( index = = 1 )
config . providers + = provider ;
else // 2
config . providers [ at ] = provider ;
}
// remove the entry
else // 3
{
config . providers . removeAt ( at ) ;
}
}
2007-05-16 01:04:15 +00:00
}
return config . toVariantMap ( ) ;
}
static QVariantMap provider_config_edit ( const QVariantMap & in )
{
// see if we have a configurator for a known form type
2020-02-13 00:59:09 +01:00
if ( in [ QStringLiteral ( " formtype " ) ] = = QLatin1String ( " http://affinix.com/qca/forms/qca-pkcs11#1.0 " ) )
2007-05-16 01:04:15 +00:00
return provider_config_edit_pkcs11 ( in ) ;
// otherwise, use the generic configurator
return provider_config_edit_generic ( in ) ;
}
2007-08-20 15:58:28 +00:00
static QString get_fingerprint ( const QCA : : Certificate & cert , const QString & hashType )
{
QString hex = QCA : : Hash ( hashType ) . hashToString ( cert . toDER ( ) ) ;
QString out ;
for ( int n = 0 ; n < hex . count ( ) ; + + n )
{
if ( n ! = 0 & & n % 2 = = 0 )
2020-02-13 00:59:09 +01:00
out + = QLatin1Char ( ' : ' ) ;
2007-08-20 15:58:28 +00:00
out + = hex [ n ] ;
}
return out ;
}
2007-03-29 03:26:27 +00:00
static QString kstype_to_string ( QCA : : KeyStore : : Type _type )
{
QString type ;
switch ( _type )
{
2020-02-10 00:29:23 +01:00
case QCA : : KeyStore : : System : type = QStringLiteral ( " Sys " ) ; break ;
case QCA : : KeyStore : : User : type = QStringLiteral ( " User " ) ; break ;
case QCA : : KeyStore : : Application : type = QStringLiteral ( " App " ) ; break ;
case QCA : : KeyStore : : SmartCard : type = QStringLiteral ( " Card " ) ; break ;
case QCA : : KeyStore : : PGPKeyring : type = QStringLiteral ( " PGP " ) ; break ;
default : type = QStringLiteral ( " XXXX " ) ; break ;
2007-03-29 03:26:27 +00:00
}
return type ;
}
static QString ksentrytype_to_string ( QCA : : KeyStoreEntry : : Type _type )
{
QString type ;
switch ( _type )
{
2020-02-10 00:29:23 +01:00
case QCA : : KeyStoreEntry : : TypeKeyBundle : type = QStringLiteral ( " Key " ) ; break ;
case QCA : : KeyStoreEntry : : TypeCertificate : type = QStringLiteral ( " Cert " ) ; break ;
case QCA : : KeyStoreEntry : : TypeCRL : type = QStringLiteral ( " CRL " ) ; break ;
case QCA : : KeyStoreEntry : : TypePGPSecretKey : type = QStringLiteral ( " PSec " ) ; break ;
case QCA : : KeyStoreEntry : : TypePGPPublicKey : type = QStringLiteral ( " PPub " ) ; break ;
default : type = QStringLiteral ( " XXXX " ) ; break ;
2007-03-29 03:26:27 +00:00
}
return type ;
}
2020-02-10 00:29:23 +01:00
static void try_print_info ( const char * name , const QStringList & values )
2007-03-29 03:26:27 +00:00
{
if ( ! values . isEmpty ( ) )
{
2020-02-10 00:29:23 +01:00
QString value = values . join ( QStringLiteral ( " , " ) ) ;
printf ( " %s: %s \n " , name , value . toUtf8 ( ) . data ( ) ) ;
2007-03-29 03:26:27 +00:00
}
}
2020-02-10 00:29:23 +01:00
static void print_info ( const char * title , const QCA : : CertificateInfo & info )
2007-03-29 03:26:27 +00:00
{
QList < InfoType > list = makeInfoTypeList ( ) ;
2020-02-10 00:29:23 +01:00
printf ( " %s \n " , title ) ;
2007-03-29 03:26:27 +00:00
foreach ( const InfoType & t , list )
2020-02-10 00:29:23 +01:00
try_print_info ( qPrintable ( t . name ) , info . values ( t . type ) ) ;
2007-03-29 03:26:27 +00:00
}
2020-02-10 00:29:23 +01:00
static void print_info_ordered ( const char * title , const QCA : : CertificateInfoOrdered & info )
2007-03-29 03:26:27 +00:00
{
2007-04-10 01:25:39 +00:00
QList < InfoType > list = makeInfoTypeList ( true ) ;
2020-02-10 00:29:23 +01:00
printf ( " %s \n " , title ) ;
2007-03-29 03:26:27 +00:00
foreach ( const QCA : : CertificateInfoPair & pair , info )
{
QCA : : CertificateInfoType type = pair . type ( ) ;
2007-04-10 01:08:04 +00:00
QString name ;
int at = - 1 ;
2007-03-29 03:26:27 +00:00
for ( int n = 0 ; n < list . count ( ) ; + + n )
{
if ( list [ n ] . type = = type )
{
2007-04-10 01:08:04 +00:00
at = n ;
2007-03-29 03:26:27 +00:00
break ;
}
}
2007-04-10 01:08:04 +00:00
// known type?
if ( at ! = - 1 )
{
name = list [ at ] . name ;
}
else
{
2007-06-07 21:31:12 +00:00
if ( pair . type ( ) . section ( ) = = QCA : : CertificateInfoType : : DN )
2020-02-10 00:29:23 +01:00
name = QStringLiteral ( " DN: " ) + pair . type ( ) . id ( ) ;
2007-04-10 01:08:04 +00:00
else
2020-02-10 00:29:23 +01:00
name = QStringLiteral ( " AN: " ) + pair . type ( ) . id ( ) ;
2007-04-10 01:08:04 +00:00
}
printf ( " %s: %s \n " , qPrintable ( name ) , pair . value ( ) . toUtf8 ( ) . data ( ) ) ;
2007-03-29 03:26:27 +00:00
}
}
2007-06-14 21:32:04 +00:00
static QString constraint_to_string ( const QCA : : ConstraintType & t )
2007-03-29 03:26:27 +00:00
{
QList < MyConstraintType > list = makeConstraintTypeList ( ) ;
for ( int n = 0 ; n < list . count ( ) ; + + n )
{
if ( list [ n ] . type = = t )
return list [ n ] . name ;
}
2007-06-14 21:32:04 +00:00
return t . id ( ) ;
2007-03-29 03:26:27 +00:00
}
static QString sigalgo_to_string ( QCA : : SignatureAlgorithm algo )
{
QString str ;
switch ( algo )
{
2020-02-10 00:29:23 +01:00
case QCA : : EMSA1_SHA1 : str = QStringLiteral ( " EMSA1(SHA1) " ) ; break ;
case QCA : : EMSA3_SHA1 : str = QStringLiteral ( " EMSA3(SHA1) " ) ; break ;
case QCA : : EMSA3_MD5 : str = QStringLiteral ( " EMSA3(MD5) " ) ; break ;
case QCA : : EMSA3_MD2 : str = QStringLiteral ( " EMSA3(MD2) " ) ; break ;
case QCA : : EMSA3_RIPEMD160 : str = QStringLiteral ( " EMSA3(RIPEMD160) " ) ; break ;
case QCA : : EMSA3_Raw : str = QStringLiteral ( " EMSA3(raw) " ) ; break ;
default : str = QStringLiteral ( " Unknown " ) ; break ;
2007-03-29 03:26:27 +00:00
}
return str ;
}
static void print_cert ( const QCA : : Certificate & cert , bool ordered = false )
{
printf ( " Serial Number: %s \n " , qPrintable ( cert . serialNumber ( ) . toString ( ) ) ) ;
if ( ordered )
{
print_info_ordered ( " Subject " , cert . subjectInfoOrdered ( ) ) ;
print_info_ordered ( " Issuer " , cert . issuerInfoOrdered ( ) ) ;
}
else
{
print_info ( " Subject " , cert . subjectInfo ( ) ) ;
print_info ( " Issuer " , cert . issuerInfo ( ) ) ;
}
printf ( " Validity \n " ) ;
printf ( " Not before: %s \n " , qPrintable ( cert . notValidBefore ( ) . toString ( ) ) ) ;
printf ( " Not after: %s \n " , qPrintable ( cert . notValidAfter ( ) . toString ( ) ) ) ;
printf ( " Constraints \n " ) ;
QCA : : Constraints constraints = cert . constraints ( ) ;
int n ;
if ( ! constraints . isEmpty ( ) )
{
for ( n = 0 ; n < constraints . count ( ) ; + + n )
printf ( " %s \n " , qPrintable ( constraint_to_string ( constraints [ n ] ) ) ) ;
}
else
printf ( " No constraints \n " ) ;
printf ( " Policies \n " ) ;
QStringList policies = cert . policies ( ) ;
if ( ! policies . isEmpty ( ) )
{
for ( n = 0 ; n < policies . count ( ) ; + + n )
printf ( " %s \n " , qPrintable ( policies [ n ] ) ) ;
}
else
printf ( " No policies \n " ) ;
QByteArray id ;
printf ( " Issuer Key ID: " ) ;
id = cert . issuerKeyId ( ) ;
if ( ! id . isEmpty ( ) )
printf ( " %s \n " , qPrintable ( QCA : : arrayToHex ( id ) ) ) ;
else
printf ( " None \n " ) ;
printf ( " Subject Key ID: " ) ;
id = cert . subjectKeyId ( ) ;
if ( ! id . isEmpty ( ) )
printf ( " %s \n " , qPrintable ( QCA : : arrayToHex ( id ) ) ) ;
else
printf ( " None \n " ) ;
printf ( " CA: %s \n " , cert . isCA ( ) ? " Yes " : " No " ) ;
printf ( " Signature Algorithm: %s \n " , qPrintable ( sigalgo_to_string ( cert . signatureAlgorithm ( ) ) ) ) ;
QCA : : PublicKey key = cert . subjectPublicKey ( ) ;
printf ( " Public Key: \n %s " , key . toPEM ( ) . toLatin1 ( ) . data ( ) ) ;
2007-08-20 15:58:28 +00:00
2020-02-10 00:29:23 +01:00
printf ( " SHA1 Fingerprint: %s \n " , qPrintable ( get_fingerprint ( cert , QStringLiteral ( " sha1 " ) ) ) ) ;
printf ( " MD5 Fingerprint: %s \n " , qPrintable ( get_fingerprint ( cert , QStringLiteral ( " md5 " ) ) ) ) ;
2007-03-29 03:26:27 +00:00
}
static void print_certreq ( const QCA : : CertificateRequest & cert , bool ordered = false )
{
if ( ordered )
print_info_ordered ( " Subject " , cert . subjectInfoOrdered ( ) ) ;
else
print_info ( " Subject " , cert . subjectInfo ( ) ) ;
printf ( " Constraints \n " ) ;
QCA : : Constraints constraints = cert . constraints ( ) ;
int n ;
if ( ! constraints . isEmpty ( ) )
{
for ( n = 0 ; n < constraints . count ( ) ; + + n )
printf ( " %s \n " , qPrintable ( constraint_to_string ( constraints [ n ] ) ) ) ;
}
else
printf ( " No constraints \n " ) ;
printf ( " Policies \n " ) ;
QStringList policies = cert . policies ( ) ;
if ( ! policies . isEmpty ( ) )
{
for ( n = 0 ; n < policies . count ( ) ; + + n )
printf ( " %s \n " , qPrintable ( policies [ n ] ) ) ;
}
else
printf ( " No policies \n " ) ;
printf ( " CA: %s \n " , cert . isCA ( ) ? " Yes " : " No " ) ;
printf ( " Signature Algorithm: %s \n " , qPrintable ( sigalgo_to_string ( cert . signatureAlgorithm ( ) ) ) ) ;
QCA : : PublicKey key = cert . subjectPublicKey ( ) ;
printf ( " Public Key: \n %s " , key . toPEM ( ) . toLatin1 ( ) . data ( ) ) ;
}
2007-05-14 06:15:56 +00:00
static void print_crl ( const QCA : : CRL & crl , bool ordered = false )
{
if ( ordered )
print_info_ordered ( " Issuer " , crl . issuerInfoOrdered ( ) ) ;
else
print_info ( " Issuer " , crl . issuerInfo ( ) ) ;
int num = crl . number ( ) ;
if ( num ! = - 1 )
printf ( " Number: %d \n " , num ) ;
printf ( " Validity \n " ) ;
printf ( " This update: %s \n " , qPrintable ( crl . thisUpdate ( ) . toString ( ) ) ) ;
printf ( " Next update: %s \n " , qPrintable ( crl . nextUpdate ( ) . toString ( ) ) ) ;
QByteArray id ;
printf ( " Issuer Key ID: " ) ;
id = crl . issuerKeyId ( ) ;
if ( ! id . isEmpty ( ) )
printf ( " %s \n " , qPrintable ( QCA : : arrayToHex ( id ) ) ) ;
else
printf ( " None \n " ) ;
printf ( " Signature Algorithm: %s \n " , qPrintable ( sigalgo_to_string ( crl . signatureAlgorithm ( ) ) ) ) ;
QList < QCA : : CRLEntry > revokedList = crl . revoked ( ) ;
foreach ( const QCA : : CRLEntry & entry , revokedList )
{
printf ( " %s: %s, %s \n " ,
qPrintable ( entry . serialNumber ( ) . toString ( ) ) ,
crlEntryReasonToString ( entry . reason ( ) ) ,
qPrintable ( entry . time ( ) . toString ( ) ) ) ;
}
}
2008-04-23 23:59:05 +00:00
static QString format_pgp_fingerprint ( const QString & in )
{
QString out ;
bool first = true ;
for ( int n = 0 ; n + 3 < in . length ( ) ; n + = 4 )
{
if ( ! first )
2020-02-13 00:59:09 +01:00
out + = QLatin1Char ( ' ' ) ;
2008-04-23 23:59:05 +00:00
else
first = false ;
out + = in . mid ( n , 4 ) . toUpper ( ) ;
}
return out ;
}
2007-03-29 03:26:27 +00:00
static void print_pgp ( const QCA : : PGPKey & key )
{
printf ( " Key ID: %s \n " , qPrintable ( key . keyId ( ) ) ) ;
printf ( " User IDs: \n " ) ;
foreach ( const QString & s , key . userIds ( ) )
printf ( " %s \n " , qPrintable ( s ) ) ;
printf ( " Validity \n " ) ;
printf ( " Not before: %s \n " , qPrintable ( key . creationDate ( ) . toString ( ) ) ) ;
2008-04-23 23:59:05 +00:00
if ( ! key . expirationDate ( ) . isNull ( ) )
printf ( " Not after: %s \n " , qPrintable ( key . expirationDate ( ) . toString ( ) ) ) ;
else
printf ( " Not after: (no expiration) \n " ) ;
2007-03-29 03:26:27 +00:00
printf ( " In Keyring: %s \n " , key . inKeyring ( ) ? " Yes " : " No " ) ;
printf ( " Secret Key: %s \n " , key . isSecret ( ) ? " Yes " : " No " ) ;
printf ( " Trusted: %s \n " , key . isTrusted ( ) ? " Yes " : " No " ) ;
2008-04-23 23:59:05 +00:00
printf ( " Fingerprint: %s \n " , qPrintable ( format_pgp_fingerprint ( key . fingerprint ( ) ) ) ) ;
2007-03-29 03:26:27 +00:00
}
static QString validityToString ( QCA : : Validity v )
{
QString s ;
switch ( v )
{
case QCA : : ValidityGood :
2020-02-10 00:29:23 +01:00
s = QStringLiteral ( " Validated " ) ;
2007-03-29 03:26:27 +00:00
break ;
case QCA : : ErrorRejected :
2020-02-10 00:29:23 +01:00
s = QStringLiteral ( " Root CA is marked to reject the specified purpose " ) ;
2007-03-29 03:26:27 +00:00
break ;
case QCA : : ErrorUntrusted :
2020-02-10 00:29:23 +01:00
s = QStringLiteral ( " Certificate not trusted for the required purpose " ) ;
2007-03-29 03:26:27 +00:00
break ;
case QCA : : ErrorSignatureFailed :
2020-02-10 00:29:23 +01:00
s = QStringLiteral ( " Invalid signature " ) ;
2007-03-29 03:26:27 +00:00
break ;
case QCA : : ErrorInvalidCA :
2020-02-10 00:29:23 +01:00
s = QStringLiteral ( " Invalid CA certificate " ) ;
2007-03-29 03:26:27 +00:00
break ;
case QCA : : ErrorInvalidPurpose :
2020-02-10 00:29:23 +01:00
s = QStringLiteral ( " Invalid certificate purpose " ) ;
2007-03-29 03:26:27 +00:00
break ;
case QCA : : ErrorSelfSigned :
2020-02-10 00:29:23 +01:00
s = QStringLiteral ( " Certificate is self-signed " ) ;
2007-03-29 03:26:27 +00:00
break ;
case QCA : : ErrorRevoked :
2020-02-10 00:29:23 +01:00
s = QStringLiteral ( " Certificate has been revoked " ) ;
2007-03-29 03:26:27 +00:00
break ;
case QCA : : ErrorPathLengthExceeded :
2020-02-10 00:29:23 +01:00
s = QStringLiteral ( " Maximum certificate chain length exceeded " ) ;
2007-03-29 03:26:27 +00:00
break ;
case QCA : : ErrorExpired :
2020-02-10 00:29:23 +01:00
s = QStringLiteral ( " Certificate has expired " ) ;
2007-03-29 03:26:27 +00:00
break ;
case QCA : : ErrorExpiredCA :
2020-02-10 00:29:23 +01:00
s = QStringLiteral ( " CA has expired " ) ;
2007-03-29 03:26:27 +00:00
break ;
case QCA : : ErrorValidityUnknown :
default :
2020-02-10 00:29:23 +01:00
s = QStringLiteral ( " General certificate validation error " ) ;
2007-03-29 03:26:27 +00:00
break ;
}
return s ;
}
2007-05-15 02:50:43 +00:00
static QString smIdentityResultToString ( QCA : : SecureMessageSignature : : IdentityResult r )
{
QString str ;
switch ( r )
{
2020-02-10 00:29:23 +01:00
case QCA : : SecureMessageSignature : : Valid : str = QStringLiteral ( " Valid " ) ; break ;
case QCA : : SecureMessageSignature : : InvalidSignature : str = QStringLiteral ( " InvalidSignature " ) ; break ;
case QCA : : SecureMessageSignature : : InvalidKey : str = QStringLiteral ( " InvalidKey " ) ; break ;
case QCA : : SecureMessageSignature : : NoKey : str = QStringLiteral ( " NoKey " ) ; break ;
default : str = QStringLiteral ( " Unknown " ) ;
2007-05-15 02:50:43 +00:00
}
return str ;
}
2007-03-29 03:26:27 +00:00
static QString smErrorToString ( QCA : : SecureMessage : : Error e )
{
QMap < QCA : : SecureMessage : : Error , QString > map ;
2020-02-10 00:29:23 +01:00
map [ QCA : : SecureMessage : : ErrorPassphrase ] = QStringLiteral ( " ErrorPassphrase " ) ;
map [ QCA : : SecureMessage : : ErrorFormat ] = QStringLiteral ( " ErrorFormat " ) ;
map [ QCA : : SecureMessage : : ErrorSignerExpired ] = QStringLiteral ( " ErrorSignerExpired " ) ;
map [ QCA : : SecureMessage : : ErrorSignerInvalid ] = QStringLiteral ( " ErrorSignerInvalid " ) ;
map [ QCA : : SecureMessage : : ErrorEncryptExpired ] = QStringLiteral ( " ErrorEncryptExpired " ) ;
map [ QCA : : SecureMessage : : ErrorEncryptUntrusted ] = QStringLiteral ( " ErrorEncryptUntrusted " ) ;
map [ QCA : : SecureMessage : : ErrorEncryptInvalid ] = QStringLiteral ( " ErrorEncryptInvalid " ) ;
map [ QCA : : SecureMessage : : ErrorNeedCard ] = QStringLiteral ( " ErrorNeedCard " ) ;
map [ QCA : : SecureMessage : : ErrorCertKeyMismatch ] = QStringLiteral ( " ErrorCertKeyMismatch " ) ;
map [ QCA : : SecureMessage : : ErrorUnknown ] = QStringLiteral ( " ErrorUnknown " ) ;
2007-03-29 03:26:27 +00:00
return map [ e ] ;
}
2007-05-15 02:50:43 +00:00
static void smDisplaySignatures ( const QList < QCA : : SecureMessageSignature > & signers )
{
foreach ( const QCA : : SecureMessageSignature & signer , signers )
{
QCA : : SecureMessageSignature : : IdentityResult r = signer . identityResult ( ) ;
fprintf ( stderr , " IdentityResult: %s \n " , qPrintable ( smIdentityResultToString ( r ) ) ) ;
QCA : : SecureMessageKey key = signer . key ( ) ;
if ( ! key . isNull ( ) )
{
if ( key . type ( ) = = QCA : : SecureMessageKey : : PGP )
{
QCA : : PGPKey pub = key . pgpPublicKey ( ) ;
fprintf ( stderr , " From: %s (%s) \n " , qPrintable ( pub . primaryUserId ( ) ) , qPrintable ( pub . keyId ( ) ) ) ;
}
else
{
QCA : : Certificate cert = key . x509CertificateChain ( ) . primary ( ) ;
QString emailStr ;
QCA : : CertificateInfo info = cert . subjectInfo ( ) ;
if ( info . contains ( QCA : : Email ) )
2020-02-10 00:29:23 +01:00
emailStr = QStringLiteral ( " (%1) " ) . arg ( info . value ( QCA : : Email ) ) ;
2007-05-15 02:50:43 +00:00
fprintf ( stderr , " From: %s%s \n " , qPrintable ( cert . commonName ( ) ) , qPrintable ( emailStr ) ) ;
}
}
}
}
2020-01-29 17:23:29 +01:00
static const char * mime_signpart =
2007-03-29 03:26:27 +00:00
" Content-Type: text/plain; charset=UTF-8 \r \n "
" Content-Transfer-Encoding: 8bit \r \n "
" \r \n "
" %1 " ;
2020-01-29 17:23:29 +01:00
static const char * mime_signed =
2007-03-29 03:26:27 +00:00
" Content-Type: multipart/signed; \r \n "
" micalg=%1; \r \n "
" boundary=QCATOOL-0001; \r \n "
" protocol= \" application/pkcs7-signature \" \r \n "
" \r \n "
" \r \n "
" --QCATOOL-0001 \r \n "
" %2 \r \n "
" --QCATOOL-0001 \r \n "
" Content-Transfer-Encoding: base64 \r \n "
" Content-Type: application/pkcs7-signature; \r \n "
" name=smime.p7s \r \n "
" Content-Disposition: attachment; \r \n "
" filename=smime.p7s \r \n "
" \r \n "
" %3 \r \n "
" \r \n "
" --QCATOOL-0001-- \r \n " ;
2020-01-29 17:23:29 +01:00
static const char * mime_enveloped =
2007-03-29 03:26:27 +00:00
" Mime-Version: 1.0 \r \n "
" Content-Transfer-Encoding: base64 \r \n "
" Content-Type: application/pkcs7-mime; \r \n "
" name=smime.p7m; \r \n "
" smime-type=enveloped-data \r \n "
" Content-Disposition: attachment; \r \n "
" filename=smime.p7m \r \n "
" \r \n "
" %1 \r \n " ;
static QString add_cr ( const QString & in )
{
QString out = in ;
int at = 0 ;
2020-01-30 17:24:31 +01:00
while ( true )
2007-03-29 03:26:27 +00:00
{
2020-02-13 00:59:09 +01:00
at = out . indexOf ( QLatin1Char ( ' \n ' ) , at ) ;
2007-03-29 03:26:27 +00:00
if ( at = = - 1 )
break ;
2020-02-13 00:59:09 +01:00
if ( at - 1 > = 0 & & out [ at - 1 ] ! = QLatin1Char ( ' \r ' ) )
2007-03-29 03:26:27 +00:00
{
2020-02-13 00:59:09 +01:00
out . insert ( at , QLatin1Char ( ' \r ' ) ) ;
2007-03-29 03:26:27 +00:00
+ + at ;
}
+ + at ;
}
return out ;
}
static QString rem_cr ( const QString & in )
{
QString out = in ;
2020-02-10 00:29:23 +01:00
out . replace ( QLatin1String ( " \r \n " ) , QLatin1String ( " \n " ) ) ;
2007-03-29 03:26:27 +00:00
return out ;
}
static int indexOf_newline ( const QString & in , int offset = 0 )
{
for ( int n = offset ; n < in . length ( ) ; + + n )
{
2020-02-13 00:59:09 +01:00
if ( n + 1 < in . length ( ) & & in [ n ] = = QLatin1Char ( ' \r ' ) & & in [ n + 1 ] = = QLatin1Char ( ' \n ' ) )
2007-03-29 03:26:27 +00:00
return n ;
2020-02-13 00:59:09 +01:00
if ( in [ n ] = = QLatin1Char ( ' \n ' ) )
2007-03-29 03:26:27 +00:00
return n ;
}
return - 1 ;
}
static int indexOf_doublenewline ( const QString & in , int offset = 0 )
{
int at = - 1 ;
2020-01-30 17:24:31 +01:00
while ( true )
2007-03-29 03:26:27 +00:00
{
int n = indexOf_newline ( in , offset ) ;
if ( n = = - 1 )
return - 1 ;
if ( at ! = - 1 )
{
if ( n = = offset )
break ;
}
at = n ;
2020-02-13 00:59:09 +01:00
if ( in [ n ] = = QLatin1Char ( ' \n ' ) )
2007-03-29 03:26:27 +00:00
offset = n + 1 ;
else
offset = n + 2 ;
}
return at ;
}
// this is so gross
static int newline_len ( const QString & in , int offset = 0 )
{
2020-02-13 00:59:09 +01:00
if ( in [ offset ] = = QLatin1Char ( ' \r ' ) )
2007-03-29 03:26:27 +00:00
return 2 ;
else
return 1 ;
}
2007-05-13 22:36:52 +00:00
// all of this mime stuff is a total hack
2007-03-29 03:26:27 +00:00
static QString open_mime_envelope ( const QString & in )
{
int n = indexOf_doublenewline ( in ) ;
if ( n = = - 1 )
return QString ( ) ;
return in . mid ( n + ( newline_len ( in , n ) * 2 ) ) ; // good lord
}
static bool open_mime_data_sig ( const QString & in , QString * data , QString * sig )
{
2020-02-10 00:29:23 +01:00
int n = in . indexOf ( QLatin1String ( " boundary= " ) ) ;
2007-03-29 03:26:27 +00:00
if ( n = = - 1 )
return false ;
n + = 9 ;
int i = indexOf_newline ( in , n ) ;
if ( i = = - 1 )
return false ;
QString boundary ;
QString bregion = in . mid ( n , i - n ) ;
2020-02-13 00:59:09 +01:00
n = bregion . indexOf ( QLatin1Char ( ' ; ' ) ) ;
2007-03-29 03:26:27 +00:00
if ( n ! = - 1 )
boundary = bregion . mid ( 0 , n ) ;
else
boundary = bregion ;
2020-02-13 00:59:09 +01:00
if ( boundary [ 0 ] = = QLatin1Char ( ' \" ' ) )
2007-03-29 03:26:27 +00:00
boundary . remove ( 0 , 1 ) ;
2020-02-13 00:59:09 +01:00
if ( boundary [ boundary . length ( ) - 1 ] = = QLatin1Char ( ' \" ' ) )
2007-03-29 03:26:27 +00:00
boundary . remove ( boundary . length ( ) - 1 , 1 ) ;
//printf("boundary: [%s]\n", qPrintable(boundary));
2020-02-10 00:29:23 +01:00
QString boundary_end = QStringLiteral ( " -- " ) + boundary ;
boundary = QStringLiteral ( " -- " ) + boundary ;
2007-03-29 03:26:27 +00:00
QString work = open_mime_envelope ( in ) ;
//printf("work: [%s]\n", qPrintable(work));
2005-06-25 20:27:10 +00:00
n = work . indexOf ( boundary ) ;
if ( n = = - 1 )
return false ;
n + = boundary . length ( ) ;
2007-03-29 03:26:27 +00:00
i = indexOf_newline ( work , n ) ;
if ( i = = - 1 )
return false ;
n + = newline_len ( work , i ) ;
int data_start = n ;
n = work . indexOf ( boundary , data_start ) ;
2005-06-25 20:27:10 +00:00
if ( n = = - 1 )
return false ;
2007-03-29 03:26:27 +00:00
int data_end = n ;
n = data_end + boundary . length ( ) ;
i = indexOf_newline ( work , n ) ;
2005-06-25 20:27:10 +00:00
if ( i = = - 1 )
return false ;
2007-03-29 03:26:27 +00:00
n + = newline_len ( work , i ) ;
int next = n ;
QString tmp_data = work . mid ( data_start , data_end - data_start ) ;
n = work . indexOf ( boundary_end , next ) ;
if ( n = = - 1 )
return false ;
QString tmp_sig = work . mid ( next , n - next ) ;
2005-06-25 20:27:10 +00:00
// nuke some newlines
2020-02-10 00:29:23 +01:00
if ( tmp_data . right ( 2 ) = = QLatin1String ( " \r \n " ) )
2005-06-25 20:27:10 +00:00
tmp_data . truncate ( tmp_data . length ( ) - 2 ) ;
2020-02-10 00:29:23 +01:00
else if ( tmp_data . right ( 1 ) = = QLatin1String ( " \n " ) )
2007-03-29 03:26:27 +00:00
tmp_data . truncate ( tmp_data . length ( ) - 1 ) ;
2020-02-10 00:29:23 +01:00
if ( tmp_sig . right ( 2 ) = = QLatin1String ( " \r \n " ) )
2005-06-25 20:27:10 +00:00
tmp_sig . truncate ( tmp_sig . length ( ) - 2 ) ;
2020-02-10 00:29:23 +01:00
else if ( tmp_sig . right ( 1 ) = = QLatin1String ( " \n " ) )
2007-03-29 03:26:27 +00:00
tmp_sig . truncate ( tmp_sig . length ( ) - 1 ) ;
2005-06-25 20:27:10 +00:00
tmp_sig = open_mime_envelope ( tmp_sig ) ;
* data = tmp_data ;
* sig = tmp_sig ;
return true ;
}
2007-03-29 03:26:27 +00:00
static QString idHash ( const QString & id )
{
// hash the id and take the rightmost 4 hex characters
2020-02-10 00:29:23 +01:00
return QCA : : Hash ( QStringLiteral ( " md5 " ) ) . hashToString ( id . toUtf8 ( ) ) . right ( 4 ) ;
2007-03-29 03:26:27 +00:00
}
2005-05-13 04:34:09 +00:00
// first = ids, second = names
2007-03-25 19:36:00 +00:00
static QPair < QStringList , QStringList > getKeyStoreStrings ( const QStringList & list , QCA : : KeyStoreManager * ksm )
2005-05-13 04:34:09 +00:00
{
QPair < QStringList , QStringList > out ;
for ( int n = 0 ; n < list . count ( ) ; + + n )
{
2007-03-25 19:36:00 +00:00
QCA : : KeyStore ks ( list [ n ] , ksm ) ;
2007-05-08 05:15:25 +00:00
out . first . append ( idHash ( ks . id ( ) ) ) ;
2005-07-28 12:17:09 +00:00
out . second . append ( ks . name ( ) ) ;
2005-05-13 04:34:09 +00:00
}
return out ;
}
static QPair < QStringList , QStringList > getKeyStoreEntryStrings ( const QList < QCA : : KeyStoreEntry > & list )
{
QPair < QStringList , QStringList > out ;
for ( int n = 0 ; n < list . count ( ) ; + + n )
{
2007-03-29 03:26:27 +00:00
out . first . append ( idHash ( list [ n ] . id ( ) ) ) ;
2005-05-13 04:34:09 +00:00
out . second . append ( list [ n ] . name ( ) ) ;
}
return out ;
}
static QList < int > getPartialMatches ( const QStringList & list , const QString & str )
{
QList < int > out ;
for ( int n = 0 ; n < list . count ( ) ; + + n )
{
if ( list [ n ] . contains ( str , Qt : : CaseInsensitive ) )
out + = n ;
}
return out ;
}
static int findByString ( const QPair < QStringList , QStringList > & in , const QString & str )
{
// exact id match
int n = in . first . indexOf ( str ) ;
if ( n ! = - 1 )
return n ;
// partial id match
QList < int > ret = getPartialMatches ( in . first , str ) ;
if ( ! ret . isEmpty ( ) )
return ret . first ( ) ;
// partial name match
ret = getPartialMatches ( in . second , str ) ;
if ( ! ret . isEmpty ( ) )
return ret . first ( ) ;
return - 1 ;
}
2005-07-28 12:17:09 +00:00
static QString getKeyStore ( const QString & name )
2005-05-13 04:34:09 +00:00
{
2007-03-29 03:26:27 +00:00
QCA : : KeyStoreManager ksm ;
2007-03-25 19:36:00 +00:00
QStringList storeList = ksm . keyStores ( ) ;
int n = findByString ( getKeyStoreStrings ( storeList , & ksm ) , name ) ;
2005-05-13 04:34:09 +00:00
if ( n ! = - 1 )
return storeList [ n ] ;
2006-02-24 08:08:43 +00:00
return QString ( ) ;
2005-05-13 04:34:09 +00:00
}
static QCA : : KeyStoreEntry getKeyStoreEntry ( QCA : : KeyStore * store , const QString & name )
{
QList < QCA : : KeyStoreEntry > list = store - > entryList ( ) ;
int n = findByString ( getKeyStoreEntryStrings ( list ) , name ) ;
if ( n ! = - 1 )
return list [ n ] ;
return QCA : : KeyStoreEntry ( ) ;
}
2007-03-29 03:26:27 +00:00
// here are a bunch of get_Foo functions for the various types
2005-05-13 04:34:09 +00:00
2007-03-29 03:26:27 +00:00
// E - generic entry
// K - private key
// C - cert
// X - keybundle
// P - pgp public key
// S - pgp secret key
2005-05-13 04:34:09 +00:00
2007-03-29 03:26:27 +00:00
// in all cases but K, the store:obj notation can be used. if there
// is no colon present, then we treat the input as a filename. we
// try the file as an exported passive entry id, and if the type
// is C or X, we'll fall back to regular files if necessary.
2005-05-13 04:34:09 +00:00
2007-03-29 03:26:27 +00:00
static QCA : : KeyStoreEntry get_E ( const QString & name , bool nopassiveerror = false )
2006-04-03 22:54:32 +00:00
{
2007-03-29 03:26:27 +00:00
QCA : : KeyStoreEntry entry ;
2007-06-19 21:39:27 +00:00
QCA : : KeyStoreManager : : start ( ) ;
2007-05-13 22:36:52 +00:00
2020-02-13 00:59:09 +01:00
int n = name . indexOf ( QLatin1Char ( ' : ' ) ) ;
2007-03-29 03:26:27 +00:00
if ( n ! = - 1 )
2006-04-03 22:54:32 +00:00
{
2007-06-19 21:39:27 +00:00
ksm_start_and_wait ( ) ;
2007-03-29 03:26:27 +00:00
// store:obj lookup
QString storeName = name . mid ( 0 , n ) ;
QString objectName = name . mid ( n + 1 ) ;
2006-04-03 22:54:32 +00:00
2007-03-29 03:26:27 +00:00
QCA : : KeyStoreManager ksm ;
QCA : : KeyStore store ( getKeyStore ( storeName ) , & ksm ) ;
if ( ! store . isValid ( ) )
{
fprintf ( stderr , " Error: no such store [%s]. \n " , qPrintable ( storeName ) ) ;
return entry ;
}
2006-04-03 22:54:32 +00:00
2007-03-29 03:26:27 +00:00
entry = getKeyStoreEntry ( & store , objectName ) ;
if ( entry . isNull ( ) )
{
fprintf ( stderr , " Error: no such object [%s]. \n " , qPrintable ( objectName ) ) ;
return entry ;
}
2006-04-03 22:54:32 +00:00
}
2007-03-29 03:26:27 +00:00
else
2006-04-03 22:54:32 +00:00
{
2007-03-29 03:26:27 +00:00
// exported id
2007-04-13 07:08:17 +00:00
QString serialized = read_ksentry_file ( name ) ;
entry = QCA : : KeyStoreEntry ( serialized ) ;
2007-03-29 03:26:27 +00:00
if ( entry . isNull ( ) )
{
if ( ! nopassiveerror )
fprintf ( stderr , " Error: invalid/unknown entry [%s]. \n " , qPrintable ( name ) ) ;
return entry ;
}
2006-04-03 22:54:32 +00:00
}
2007-03-29 03:26:27 +00:00
return entry ;
2006-04-03 22:54:32 +00:00
}
2007-05-14 05:37:05 +00:00
static QCA : : PrivateKey get_K ( const QString & name )
2005-05-13 04:34:09 +00:00
{
2007-03-29 03:26:27 +00:00
QCA : : PrivateKey key ;
2005-05-13 04:34:09 +00:00
2020-02-13 00:59:09 +01:00
int n = name . indexOf ( QLatin1Char ( ' : ' ) ) ;
2007-03-29 03:26:27 +00:00
if ( n ! = - 1 )
2005-05-13 04:34:09 +00:00
{
2007-03-29 03:26:27 +00:00
fprintf ( stderr , " Error: cannot use store:obj notation for raw private keys. \n " ) ;
return key ;
2005-05-13 04:34:09 +00:00
}
2007-08-20 15:16:08 +00:00
if ( is_pem_file ( name ) )
key = QCA : : PrivateKey : : fromPEMFile ( name ) ;
else
2007-05-14 05:37:05 +00:00
key = QCA : : PrivateKey : : fromDER ( read_der_file ( name ) ) ;
2007-08-20 15:16:08 +00:00
if ( key . isNull ( ) )
{
fprintf ( stderr , " Error: unable to read/process private key file. \n " ) ;
return key ;
2005-05-13 04:34:09 +00:00
}
2007-03-29 03:26:27 +00:00
return key ;
}
static QCA : : Certificate get_C ( const QString & name )
{
QCA : : KeyStoreEntry entry = get_E ( name , true ) ;
if ( ! entry . isNull ( ) )
2005-05-13 04:34:09 +00:00
{
2007-03-29 03:26:27 +00:00
if ( entry . type ( ) ! = QCA : : KeyStoreEntry : : TypeCertificate )
{
2007-05-15 06:47:19 +00:00
fprintf ( stderr , " Error: entry is not a certificate. \n " ) ;
2007-03-29 03:26:27 +00:00
return QCA : : Certificate ( ) ;
}
return entry . certificate ( ) ;
2005-05-13 04:34:09 +00:00
}
2007-05-15 06:47:19 +00:00
if ( ! QCA : : isSupported ( " cert " ) )
{
fprintf ( stderr , " Error: need 'cert' feature. \n " ) ;
return QCA : : Certificate ( ) ;
}
2007-03-29 03:26:27 +00:00
// try file
2007-08-20 15:16:08 +00:00
QCA : : Certificate cert ;
if ( is_pem_file ( name ) )
cert = QCA : : Certificate : : fromPEMFile ( name ) ;
else
cert = QCA : : Certificate : : fromDER ( read_der_file ( name ) ) ;
2007-03-29 03:26:27 +00:00
if ( cert . isNull ( ) )
2005-05-13 04:34:09 +00:00
{
2007-08-20 15:16:08 +00:00
fprintf ( stderr , " Error: unable to read/process certificate file. \n " ) ;
return cert ;
2005-05-13 04:34:09 +00:00
}
return cert ;
}
2007-03-29 03:26:27 +00:00
static QCA : : KeyBundle get_X ( const QString & name )
2005-07-28 12:17:09 +00:00
{
2007-03-29 03:26:27 +00:00
QCA : : KeyStoreEntry entry = get_E ( name , true ) ;
if ( ! entry . isNull ( ) )
2005-07-28 12:17:09 +00:00
{
2007-03-29 03:26:27 +00:00
if ( entry . type ( ) ! = QCA : : KeyStoreEntry : : TypeKeyBundle )
{
2007-05-15 06:47:19 +00:00
fprintf ( stderr , " Error: entry is not a keybundle. \n " ) ;
2007-03-29 03:26:27 +00:00
return QCA : : KeyBundle ( ) ;
}
return entry . keyBundle ( ) ;
2005-07-28 12:17:09 +00:00
}
2007-05-15 06:47:19 +00:00
if ( ! QCA : : isSupported ( " pkcs12 " ) )
{
fprintf ( stderr , " Error: need 'pkcs12' feature. \n " ) ;
return QCA : : KeyBundle ( ) ;
}
2007-03-29 03:26:27 +00:00
// try file
2007-05-13 22:36:52 +00:00
QCA : : KeyBundle key = QCA : : KeyBundle : : fromFile ( name ) ;
2007-03-29 03:26:27 +00:00
if ( key . isNull ( ) )
2005-07-28 12:17:09 +00:00
{
2007-05-15 06:47:19 +00:00
fprintf ( stderr , " Error: unable to read/process keybundle file. \n " ) ;
2005-07-28 12:17:09 +00:00
return key ;
}
2007-03-29 03:26:27 +00:00
return key ;
}
static QCA : : PGPKey get_P ( const QString & name )
{
2008-04-23 23:59:05 +00:00
QCA : : KeyStoreEntry entry = get_E ( name , true ) ;
2007-03-29 03:26:27 +00:00
if ( ! entry . isNull ( ) )
2005-07-28 12:17:09 +00:00
{
2007-03-29 03:26:27 +00:00
if ( entry . type ( ) ! = QCA : : KeyStoreEntry : : TypePGPPublicKey & & entry . type ( ) ! = QCA : : KeyStoreEntry : : TypePGPSecretKey )
{
2007-05-15 06:47:19 +00:00
fprintf ( stderr , " Error: entry is not a pgp public key. \n " ) ;
2008-04-23 23:59:05 +00:00
return QCA : : PGPKey ( ) ;
2007-03-29 03:26:27 +00:00
}
return entry . pgpPublicKey ( ) ;
2005-07-28 12:17:09 +00:00
}
2008-04-23 23:59:05 +00:00
// try file
QCA : : PGPKey key = QCA : : PGPKey : : fromFile ( name ) ;
if ( key . isNull ( ) )
{
fprintf ( stderr , " Error: unable to read/process pgp key file. \n " ) ;
return key ;
}
2007-03-29 03:26:27 +00:00
return key ;
}
2005-07-28 12:17:09 +00:00
2008-04-23 23:59:05 +00:00
static QPair < QCA : : PGPKey , QCA : : PGPKey > get_S ( const QString & name , bool noerror = false )
2007-03-29 03:26:27 +00:00
{
QPair < QCA : : PGPKey , QCA : : PGPKey > key ;
2008-04-23 23:59:05 +00:00
QCA : : KeyStoreEntry entry = get_E ( name , true ) ;
2007-03-29 03:26:27 +00:00
if ( ! entry . isNull ( ) )
2005-07-28 12:17:09 +00:00
{
2007-03-29 03:26:27 +00:00
if ( entry . type ( ) ! = QCA : : KeyStoreEntry : : TypePGPSecretKey )
{
2008-04-23 23:59:05 +00:00
if ( ! noerror )
fprintf ( stderr , " Error: entry is not a pgp secret key. \n " ) ;
2007-03-29 03:26:27 +00:00
return key ;
}
key . first = entry . pgpSecretKey ( ) ;
key . second = entry . pgpPublicKey ( ) ;
2005-07-28 12:17:09 +00:00
return key ;
}
2007-03-29 03:26:27 +00:00
return key ;
2005-07-28 12:17:09 +00:00
}
2005-03-14 11:40:03 +00:00
static void usage ( )
{
2007-05-30 19:15:29 +00:00
printf ( " %s: simple qca utility \n " , APPNAME ) ;
printf ( " usage: %s (options) [command] \n " , EXENAME ) ;
2007-03-29 03:26:27 +00:00
printf ( " options: --pass=x, --newpass=x, --nonroots=x, --roots=x, --nosys, \n " ) ;
2007-05-14 23:18:48 +00:00
printf ( " --noprompt, --ordered, --debug, --log-file=x, --log-level=n, \n " ) ;
printf ( " --nobundle \n " ) ;
2005-05-13 04:34:09 +00:00
printf ( " \n " ) ;
2007-03-29 03:26:27 +00:00
printf ( " help|--help|-h This help text \n " ) ;
2007-03-30 01:00:19 +00:00
printf ( " version|--version|-v Print version information \n " ) ;
2007-03-29 03:26:27 +00:00
printf ( " plugins List available plugins \n " ) ;
2007-03-30 01:00:19 +00:00
printf ( " config [command] \n " ) ;
printf ( " save [provider] Save default provider config \n " ) ;
2007-05-16 01:04:15 +00:00
printf ( " edit [provider] Edit provider config \n " ) ;
2005-05-13 04:34:09 +00:00
printf ( " key [command] \n " ) ;
2007-03-29 03:26:27 +00:00
printf ( " make rsa|dsa [bits] Create a key pair \n " ) ;
printf ( " changepass [K] Add/change/remove passphrase of a key \n " ) ;
2005-05-13 04:34:09 +00:00
printf ( " cert [command] \n " ) ;
2007-03-29 03:26:27 +00:00
printf ( " makereq [K] Create certificate request (CSR) \n " ) ;
printf ( " makeself [K] Create self-signed certificate \n " ) ;
printf ( " makereqadv [K] Advanced version of 'makereq' \n " ) ;
printf ( " makeselfadv [K] Advanced version of 'makeself' \n " ) ;
printf ( " validate [C] Validate certificate \n " ) ;
2005-05-13 04:34:09 +00:00
printf ( " keybundle [command] \n " ) ;
2007-03-29 03:26:27 +00:00
printf ( " make [K] [C] Create a keybundle \n " ) ;
printf ( " extract [X] Extract certificate(s) and key \n " ) ;
printf ( " changepass [X] Change passphrase of a keybundle \n " ) ;
2005-05-13 04:34:09 +00:00
printf ( " keystore [command] \n " ) ;
2007-03-29 03:26:27 +00:00
printf ( " list-stores List all available keystores \n " ) ;
printf ( " list [storeName] List content of a keystore \n " ) ;
2007-05-13 22:36:52 +00:00
printf ( " monitor Monitor for keystore availability \n " ) ;
2007-03-29 03:26:27 +00:00
printf ( " export [E] Export a keystore entry's content \n " ) ;
printf ( " exportref [E] Export a keystore entry reference \n " ) ;
printf ( " addkb [storeName] [cert.p12] Add a keybundle into a keystore \n " ) ;
printf ( " addpgp [storeName] [key.asc] Add a PGP key into a keystore \n " ) ;
printf ( " remove [E] Remove an object from a keystore \n " ) ;
2005-05-13 04:34:09 +00:00
printf ( " show [command] \n " ) ;
2007-03-29 03:26:27 +00:00
printf ( " cert [C] Examine a certificate \n " ) ;
printf ( " req [req.pem] Examine a certificate request (CSR) \n " ) ;
2007-05-14 06:15:56 +00:00
printf ( " crl [crl.pem] Examine a certificate revocation list \n " ) ;
printf ( " kb [X] Examine a keybundle \n " ) ;
2007-03-29 03:26:27 +00:00
printf ( " pgp [P|S] Examine a PGP key \n " ) ;
2005-05-13 04:34:09 +00:00
printf ( " message [command] \n " ) ;
2007-03-29 03:26:27 +00:00
printf ( " sign pgp|pgpdetach|smime [X|S] Sign a message \n " ) ;
printf ( " encrypt pgp|smime [C|P] Encrypt a message \n " ) ;
printf ( " signencrypt [S] [P] PGP sign & encrypt a message \n " ) ;
printf ( " verify pgp|smime Verify a message \n " ) ;
2007-05-15 03:07:50 +00:00
printf ( " decrypt pgp|smime ((X) ...) Decrypt a message (S/MIME needs X) \n " ) ;
2007-03-29 03:26:27 +00:00
printf ( " exportcerts Export certs from S/MIME message \n " ) ;
2005-05-13 04:34:09 +00:00
printf ( " \n " ) ;
printf ( " Object types: K = private key, C = certificate, X = key bundle, \n " ) ;
2007-03-29 03:26:27 +00:00
printf ( " P = PGP public key, S = PGP secret key, E = generic entry \n " ) ;
2005-05-13 04:34:09 +00:00
printf ( " \n " ) ;
printf ( " An object must be either a filename or a keystore reference ( \" store:obj \" ). \n " ) ;
2007-03-29 03:26:27 +00:00
printf ( " \n " ) ;
2007-04-14 12:25:06 +00:00
printf ( " Log level is from 0 (quiet) to 8 (debug) \n " ) ;
printf ( " \n " ) ;
2005-03-14 11:40:03 +00:00
}
int main ( int argc , char * * argv )
{
QCA : : Initializer qcaInit ;
QCoreApplication app ( argc , argv ) ;
2007-04-14 12:02:03 +00:00
QFile logFile ;
QTextStream logStream ( stderr ) ;
StreamLogger streamLogger ( logStream ) ;
2005-03-14 11:40:03 +00:00
2007-03-29 03:26:27 +00:00
QStringList args ;
for ( int n = 1 ; n < argc ; + + n )
args . append ( QString : : fromLocal8Bit ( argv [ n ] ) ) ;
2005-03-14 11:40:03 +00:00
2007-03-29 03:26:27 +00:00
if ( args . count ( ) < 1 )
2005-03-14 11:40:03 +00:00
{
2007-03-29 03:26:27 +00:00
usage ( ) ;
2005-03-14 11:40:03 +00:00
return 1 ;
}
2007-03-29 03:26:27 +00:00
bool have_pass = false ;
bool have_newpass = false ;
2007-04-13 19:04:16 +00:00
QCA : : SecureArray pass , newpass ;
2007-03-29 03:26:27 +00:00
bool allowprompt = true ;
bool ordered = false ;
bool debug = false ;
bool nosys = false ;
2007-05-14 23:18:48 +00:00
bool nobundle = false ;
2007-03-29 03:26:27 +00:00
QString rootsFile , nonRootsFile ;
2005-03-14 11:40:03 +00:00
2007-03-29 03:26:27 +00:00
for ( int n = 0 ; n < args . count ( ) ; + + n )
2005-05-05 18:48:36 +00:00
{
2007-03-29 03:26:27 +00:00
QString s = args [ n ] ;
2020-02-10 00:29:23 +01:00
if ( ! s . startsWith ( QLatin1String ( " -- " ) ) )
2007-03-29 03:26:27 +00:00
continue ;
QString var ;
QString val ;
2020-02-13 00:59:09 +01:00
int x = s . indexOf ( QLatin1Char ( ' = ' ) ) ;
2007-03-29 03:26:27 +00:00
if ( x ! = - 1 )
{
var = s . mid ( 2 , x - 2 ) ;
val = s . mid ( x + 1 ) ;
}
else
{
var = s . mid ( 2 ) ;
}
2005-05-05 18:48:36 +00:00
2007-03-29 03:26:27 +00:00
bool known = true ;
2005-03-14 11:40:03 +00:00
2020-02-10 00:29:23 +01:00
if ( var = = QLatin1String ( " pass " ) )
2007-03-29 03:26:27 +00:00
{
have_pass = true ;
pass = val . toUtf8 ( ) ;
}
2020-02-10 00:29:23 +01:00
else if ( var = = QLatin1String ( " newpass " ) )
2007-03-29 03:26:27 +00:00
{
have_newpass = true ;
newpass = val . toUtf8 ( ) ;
}
2020-02-10 00:29:23 +01:00
else if ( var = = QLatin1String ( " log-file " ) )
2007-04-14 12:02:03 +00:00
{
logFile . setFileName ( val ) ;
logFile . open ( QIODevice : : Append | QIODevice : : Text | QIODevice : : Unbuffered ) ;
logStream . setDevice ( & logFile ) ;
}
2020-02-10 00:29:23 +01:00
else if ( var = = QLatin1String ( " log-level " ) )
2007-04-14 12:02:03 +00:00
{
QCA : : logger ( ) - > setLevel ( ( QCA : : Logger : : Severity ) val . toInt ( ) ) ;
}
2020-02-10 00:29:23 +01:00
else if ( var = = QLatin1String ( " noprompt " ) )
2007-03-29 03:26:27 +00:00
allowprompt = false ;
2020-02-10 00:29:23 +01:00
else if ( var = = QLatin1String ( " ordered " ) )
2007-03-29 03:26:27 +00:00
ordered = true ;
2020-02-10 00:29:23 +01:00
else if ( var = = QLatin1String ( " debug " ) )
2007-03-29 03:26:27 +00:00
debug = true ;
2020-02-10 00:29:23 +01:00
else if ( var = = QLatin1String ( " roots " ) )
2007-03-29 03:26:27 +00:00
rootsFile = val ;
2020-02-10 00:29:23 +01:00
else if ( var = = QLatin1String ( " nonroots " ) )
2007-03-29 03:26:27 +00:00
nonRootsFile = val ;
2020-02-10 00:29:23 +01:00
else if ( var = = QLatin1String ( " nosys " ) )
2007-03-29 03:26:27 +00:00
nosys = true ;
2020-02-10 00:29:23 +01:00
else if ( var = = QLatin1String ( " nobundle " ) )
2007-05-14 23:18:48 +00:00
nobundle = true ;
2007-03-29 03:26:27 +00:00
else
known = false ;
if ( known )
{
args . removeAt ( n ) ;
- - n ; // adjust position
}
2005-03-14 11:40:03 +00:00
}
2007-03-29 03:26:27 +00:00
// help
2020-02-10 00:29:23 +01:00
if ( args . isEmpty ( ) | | args [ 0 ] = = QLatin1String ( " help " ) | | args [ 0 ] = = QLatin1String ( " --help " ) | | args [ 0 ] = = QLatin1String ( " -h " ) )
2005-03-14 11:40:03 +00:00
{
usage ( ) ;
2007-03-30 01:00:19 +00:00
return 0 ;
}
// version
2020-02-10 00:29:23 +01:00
if ( args [ 0 ] = = QLatin1String ( " version " ) | | args [ 0 ] = = QLatin1String ( " --version " ) | | args [ 0 ] = = QLatin1String ( " -v " ) )
2007-03-30 01:00:19 +00:00
{
int ver = qcaVersion ( ) ;
int maj = ( ver > > 16 ) & 0xff ;
int min = ( ver > > 8 ) & 0xff ;
int bug = ver & 0xff ;
2007-05-30 19:15:29 +00:00
printf ( " %s version %s by Justin Karneges \n " , APPNAME , VERSION ) ;
2007-03-30 01:00:19 +00:00
printf ( " Using QCA version %d.%d.%d \n " , maj , min , bug ) ;
return 0 ;
2005-03-14 11:40:03 +00:00
}
2007-03-29 03:26:27 +00:00
// show plugins
2020-02-10 00:29:23 +01:00
if ( args [ 0 ] = = QLatin1String ( " plugins " ) )
2006-02-24 08:08:43 +00:00
{
2014-09-24 17:31:37 +06:00
QStringList paths = QCA : : pluginPaths ( ) ;
2006-02-24 08:08:43 +00:00
if ( ! paths . isEmpty ( ) )
{
for ( int n = 0 ; n < paths . count ( ) ; + + n )
{
2014-09-24 18:03:37 +06:00
printf ( " %s \n " , qPrintable ( QDir : : toNativeSeparators ( paths [ n ] ) ) ) ;
2006-02-24 08:08:43 +00:00
}
}
else
printf ( " (none) \n " ) ;
QCA : : ProviderList list = QCA : : providers ( ) ;
if ( debug )
2007-05-14 21:31:53 +00:00
output_plugin_diagnostic_text ( ) ;
2006-02-24 08:08:43 +00:00
printf ( " Available Providers: \n " ) ;
if ( ! list . isEmpty ( ) )
{
for ( int n = 0 ; n < list . count ( ) ; + + n )
{
printf ( " %s \n " , qPrintable ( list [ n ] - > name ( ) ) ) ;
2006-02-25 02:43:31 +00:00
QString credit = list [ n ] - > credit ( ) ;
if ( ! credit . isEmpty ( ) )
{
QStringList lines = wrapstring ( credit , 74 ) ;
2008-06-02 20:20:37 +00:00
foreach ( const QString & s , lines )
2006-02-25 02:43:31 +00:00
printf ( " %s \n " , qPrintable ( s ) ) ;
}
2009-09-16 02:51:43 +00:00
if ( debug )
{
QStringList capabilities = list [ n ] - > features ( ) ;
foreach ( const QString & capability , capabilities )
{
printf ( " *%s " , qPrintable ( capability ) ) ;
if ( ! QCA : : isSupported ( qPrintable ( capability ) , list [ n ] - > name ( ) ) )
{
printf ( " (NOT supported) - bug " ) ;
}
printf ( " \n " ) ;
}
}
2006-02-24 08:08:43 +00:00
}
}
else
printf ( " (none) \n " ) ;
QCA : : unloadAllPlugins ( ) ;
2007-05-14 21:31:53 +00:00
2006-02-24 08:08:43 +00:00
if ( debug )
2007-05-14 21:31:53 +00:00
output_plugin_diagnostic_text ( ) ;
2007-03-29 03:26:27 +00:00
2006-02-24 08:08:43 +00:00
return 0 ;
}
2007-03-30 01:00:19 +00:00
// config stuff
2020-02-10 00:29:23 +01:00
if ( args [ 0 ] = = QLatin1String ( " config " ) )
2007-03-30 01:00:19 +00:00
{
if ( args . count ( ) < 2 )
{
usage ( ) ;
return 1 ;
}
2020-02-10 00:29:23 +01:00
if ( args [ 1 ] = = QLatin1String ( " save " ) )
2007-03-30 01:00:19 +00:00
{
if ( args . count ( ) < 3 )
{
usage ( ) ;
return 1 ;
}
2007-05-16 01:04:15 +00:00
QString name = args [ 2 ] ;
QCA : : Provider * p = QCA : : findProvider ( name ) ;
if ( ! p )
{
fprintf ( stderr , " Error: no such provider '%s'. \n " , qPrintable ( name ) ) ;
return 1 ;
}
QVariantMap map1 = p - > defaultConfig ( ) ;
if ( map1 . isEmpty ( ) )
{
fprintf ( stderr , " Error: provider does not support configuration. \n " ) ;
return 1 ;
}
// set and save
QCA : : setProviderConfig ( name , map1 ) ;
QCA : : saveProviderConfig ( name ) ;
printf ( " Done. \n " ) ;
return 0 ;
}
2020-02-10 00:29:23 +01:00
else if ( args [ 1 ] = = QLatin1String ( " edit " ) )
2007-05-16 01:04:15 +00:00
{
if ( args . count ( ) < 3 )
{
usage ( ) ;
return 1 ;
}
2007-03-30 01:00:19 +00:00
QString name = args [ 2 ] ;
if ( ! QCA : : findProvider ( name ) )
{
fprintf ( stderr , " Error: no such provider '%s'. \n " , qPrintable ( name ) ) ;
return 1 ;
}
QVariantMap map1 = QCA : : getProviderConfig ( name ) ;
if ( map1 . isEmpty ( ) )
{
fprintf ( stderr , " Error: provider does not support configuration. \n " ) ;
return 1 ;
}
2007-05-16 01:04:15 +00:00
printf ( " Editing configuration for %s ... \n " , qPrintable ( name ) ) ;
2008-05-25 17:11:37 +00:00
printf ( " Note: to clear a string entry, type whitespace and press enter. \n " ) ;
2007-05-16 01:04:15 +00:00
map1 = provider_config_edit ( map1 ) ;
if ( map1 . isEmpty ( ) )
return 1 ;
2007-03-30 01:00:19 +00:00
// set and save
QCA : : setProviderConfig ( name , map1 ) ;
QCA : : saveProviderConfig ( name ) ;
printf ( " Done. \n " ) ;
return 0 ;
}
else
{
usage ( ) ;
return 1 ;
}
}
2007-04-07 18:34:52 +00:00
// enable console passphrase prompt
PassphrasePromptThread passphrasePrompt ;
if ( ! allowprompt )
passphrasePrompt . pp - > allowPrompt = false ;
if ( have_pass )
passphrasePrompt . pp - > setExplicitPassword ( pass ) ;
2020-02-10 00:29:23 +01:00
if ( args [ 0 ] = = QLatin1String ( " key " ) )
2005-03-14 11:40:03 +00:00
{
if ( args . count ( ) < 2 )
{
usage ( ) ;
return 1 ;
}
2020-02-10 00:29:23 +01:00
if ( args [ 1 ] = = QLatin1String ( " make " ) )
2006-12-09 12:41:04 +00:00
{
2007-03-29 03:26:27 +00:00
if ( args . count ( ) < 4 )
{
usage ( ) ;
return 1 ;
}
2005-03-14 11:40:03 +00:00
2007-03-29 03:26:27 +00:00
bool genrsa ;
int bits ;
2005-03-14 11:40:03 +00:00
2020-02-10 00:29:23 +01:00
if ( args [ 2 ] = = QLatin1String ( " rsa " ) )
2007-03-29 03:26:27 +00:00
{
2007-05-15 06:47:19 +00:00
if ( ! QCA : : isSupported ( " rsa " ) )
{
fprintf ( stderr , " Error: need 'rsa' feature. \n " ) ;
return 1 ;
}
2007-03-29 03:26:27 +00:00
genrsa = true ;
bits = args [ 3 ] . toInt ( ) ;
if ( bits < 512 )
{
fprintf ( stderr , " Error: RSA bits must be at least 512. \n " ) ;
return 1 ;
}
}
2020-02-10 00:29:23 +01:00
else if ( args [ 2 ] = = QLatin1String ( " dsa " ) )
2007-03-29 03:26:27 +00:00
{
2007-05-15 06:47:19 +00:00
if ( ! QCA : : isSupported ( " dsa " ) )
{
fprintf ( stderr , " Error: need 'dsa' feature. \n " ) ;
return 1 ;
}
if ( ! QCA : : isSupported ( " dlgroup " ) )
{
fprintf ( stderr , " Error: need 'dlgroup' feature. \n " ) ;
return 1 ;
}
2007-03-29 03:26:27 +00:00
genrsa = false ;
bits = args [ 3 ] . toInt ( ) ;
if ( bits ! = 512 & & bits ! = 768 & & bits ! = 1024 )
{
fprintf ( stderr , " Error: DSA bits must be 512, 768, or 1024. \n " ) ;
return 1 ;
}
}
2005-03-14 11:40:03 +00:00
else
{
usage ( ) ;
return 1 ;
}
2007-03-29 03:26:27 +00:00
if ( ! allowprompt & & ! have_newpass )
2005-03-14 11:40:03 +00:00
{
2007-03-29 03:26:27 +00:00
fprintf ( stderr , " Error: no passphrase specified (use '--newpass=' for none). \n " ) ;
2005-03-14 11:40:03 +00:00
return 1 ;
}
2007-03-29 03:26:27 +00:00
QCA : : PrivateKey priv ;
QString pubFileName , privFileName ;
2005-03-14 11:40:03 +00:00
2007-03-29 03:26:27 +00:00
if ( genrsa )
{
// note: third arg is bogus, doesn't apply to RSA
priv = AnimatedKeyGen : : makeKey ( QCA : : PKey : : RSA , bits , QCA : : DSA_512 ) ;
2020-02-10 00:29:23 +01:00
pubFileName = QStringLiteral ( " rsapub.pem " ) ;
privFileName = QStringLiteral ( " rsapriv.pem " ) ;
2007-03-29 03:26:27 +00:00
}
else // dsa
{
QCA : : DLGroupSet set ;
if ( bits = = 512 )
set = QCA : : DSA_512 ;
else if ( bits = = 768 )
set = QCA : : DSA_768 ;
else // 1024
set = QCA : : DSA_1024 ;
// note: second arg is bogus, doesn't apply to DSA
priv = AnimatedKeyGen : : makeKey ( QCA : : PKey : : DSA , 0 , set ) ;
2020-02-10 00:29:23 +01:00
pubFileName = QStringLiteral ( " dsapub.pem " ) ;
privFileName = QStringLiteral ( " dsapriv.pem " ) ;
2007-03-29 03:26:27 +00:00
}
if ( priv . isNull ( ) )
{
fprintf ( stderr , " Error: unable to generate key. \n " ) ;
return 1 ;
}
2005-03-14 11:40:03 +00:00
2007-03-29 03:26:27 +00:00
QCA : : PublicKey pub = priv . toPublicKey ( ) ;
2005-03-14 11:40:03 +00:00
2007-03-29 03:26:27 +00:00
// prompt for new passphrase if necessary
if ( ! have_newpass )
{
while ( ! promptForNewPassphrase ( & newpass ) )
{
}
have_newpass = true ;
}
2005-03-14 11:40:03 +00:00
2007-03-29 03:26:27 +00:00
if ( pub . toPEMFile ( pubFileName ) )
printf ( " Public key saved to %s \n " , qPrintable ( pubFileName ) ) ;
2005-03-14 11:40:03 +00:00
else
{
2007-03-29 03:26:27 +00:00
fprintf ( stderr , " Error: can't encode/write %s \n " , qPrintable ( pubFileName ) ) ;
2005-03-14 11:40:03 +00:00
return 1 ;
}
bool ok ;
2007-03-29 03:26:27 +00:00
if ( ! newpass . isEmpty ( ) )
ok = priv . toPEMFile ( privFileName , newpass ) ;
2005-03-14 11:40:03 +00:00
else
2007-03-29 03:26:27 +00:00
ok = priv . toPEMFile ( privFileName ) ;
2005-03-14 11:40:03 +00:00
if ( ok )
2007-03-29 03:26:27 +00:00
printf ( " Private key saved to %s \n " , qPrintable ( privFileName ) ) ;
2005-03-14 11:40:03 +00:00
else
{
2007-03-29 03:26:27 +00:00
fprintf ( stderr , " Error: can't encode/write %s \n " , qPrintable ( privFileName ) ) ;
2005-03-14 11:40:03 +00:00
return 1 ;
}
}
2020-02-10 00:29:23 +01:00
else if ( args [ 1 ] = = QLatin1String ( " changepass " ) )
2005-03-14 11:40:03 +00:00
{
2007-03-29 03:26:27 +00:00
if ( args . count ( ) < 3 )
{
usage ( ) ;
return 1 ;
}
2007-05-14 05:37:05 +00:00
QCA : : PrivateKey priv = get_K ( args [ 2 ] ) ;
2007-03-29 03:26:27 +00:00
if ( priv . isNull ( ) )
return 1 ;
if ( ! allowprompt & & ! have_newpass )
2005-03-14 11:40:03 +00:00
{
2007-03-29 03:26:27 +00:00
fprintf ( stderr , " Error: no passphrase specified (use '--newpass=' for none). \n " ) ;
2005-03-14 11:40:03 +00:00
return 1 ;
}
2007-03-29 03:26:27 +00:00
// prompt for new passphrase if necessary
if ( ! have_newpass )
{
while ( ! promptForNewPassphrase ( & newpass ) )
{
}
have_newpass = true ;
}
QString out ;
if ( ! newpass . isEmpty ( ) )
out = priv . toPEM ( newpass ) ;
else
out = priv . toPEM ( ) ;
if ( ! out . isEmpty ( ) )
printf ( " %s " , qPrintable ( out ) ) ;
2005-03-14 11:40:03 +00:00
else
{
2007-03-29 03:26:27 +00:00
fprintf ( stderr , " Error: can't encode key. \n " ) ;
2005-03-14 11:40:03 +00:00
return 1 ;
}
}
2007-03-29 03:26:27 +00:00
else
2005-03-14 11:40:03 +00:00
{
usage ( ) ;
return 1 ;
}
2007-03-29 03:26:27 +00:00
}
2020-02-10 00:29:23 +01:00
else if ( args [ 0 ] = = QLatin1String ( " cert " ) )
2007-03-29 03:26:27 +00:00
{
if ( args . count ( ) < 2 )
2005-03-14 11:40:03 +00:00
{
2007-03-29 03:26:27 +00:00
usage ( ) ;
2005-03-14 11:40:03 +00:00
return 1 ;
}
2020-02-10 00:29:23 +01:00
if ( args [ 1 ] = = QLatin1String ( " makereq " ) | | args [ 1 ] = = QLatin1String ( " makereqadv " ) )
2005-03-14 11:40:03 +00:00
{
2007-03-29 03:26:27 +00:00
if ( args . count ( ) < 3 )
2005-03-14 11:40:03 +00:00
{
2007-03-29 03:26:27 +00:00
usage ( ) ;
2005-03-14 11:40:03 +00:00
return 1 ;
}
2007-05-15 06:47:19 +00:00
if ( ! QCA : : isSupported ( " csr " ) )
{
fprintf ( stderr , " Error: need 'csr' feature. \n " ) ;
return 1 ;
}
2007-05-14 05:37:05 +00:00
QCA : : PrivateKey priv = get_K ( args [ 2 ] ) ;
2007-03-29 03:26:27 +00:00
if ( priv . isNull ( ) )
return 1 ;
printf ( " \n " ) ;
2005-03-14 11:40:03 +00:00
2020-02-10 00:29:23 +01:00
bool advanced = ( args [ 1 ] = = QLatin1String ( " makereqadv " ) ) ? true : false ;
2005-03-14 11:40:03 +00:00
2007-03-29 03:26:27 +00:00
QCA : : CertificateOptions opts = promptForCertAttributes ( advanced , true ) ;
QCA : : CertificateRequest req ( opts , priv ) ;
2020-02-10 00:29:23 +01:00
QString reqname = QStringLiteral ( " certreq.pem " ) ;
2007-03-29 03:26:27 +00:00
if ( req . toPEMFile ( reqname ) )
printf ( " Certificate request saved to %s \n " , qPrintable ( reqname ) ) ;
else
{
fprintf ( stderr , " Error: can't encode/write %s \n " , qPrintable ( reqname ) ) ;
return 1 ;
}
2005-03-14 11:40:03 +00:00
}
2020-02-10 00:29:23 +01:00
else if ( args [ 1 ] = = QLatin1String ( " makeself " ) | | args [ 1 ] = = QLatin1String ( " makeselfadv " ) )
2007-03-29 03:26:27 +00:00
{
if ( args . count ( ) < 3 )
{
usage ( ) ;
return 1 ;
}
2005-03-14 11:40:03 +00:00
2007-05-15 06:47:19 +00:00
if ( ! QCA : : isSupported ( " cert " ) )
{
fprintf ( stderr , " Error: need 'cert' feature. \n " ) ;
return 1 ;
}
2007-05-14 05:37:05 +00:00
QCA : : PrivateKey priv = get_K ( args [ 2 ] ) ;
2007-03-29 03:26:27 +00:00
if ( priv . isNull ( ) )
return 1 ;
2005-03-14 11:40:03 +00:00
2007-03-29 03:26:27 +00:00
printf ( " \n " ) ;
2005-03-14 11:40:03 +00:00
2020-02-10 00:29:23 +01:00
bool advanced = ( args [ 1 ] = = QLatin1String ( " makeselfadv " ) ) ? true : false ;
2005-03-14 11:40:03 +00:00
2007-03-29 03:26:27 +00:00
QCA : : CertificateOptions opts = promptForCertAttributes ( advanced , false ) ;
QCA : : Certificate cert ( opts , priv ) ;
2005-03-14 11:40:03 +00:00
2020-02-10 00:29:23 +01:00
QString certname = QStringLiteral ( " cert.pem " ) ;
2007-03-29 03:26:27 +00:00
if ( cert . toPEMFile ( certname ) )
printf ( " Certificate saved to %s \n " , qPrintable ( certname ) ) ;
else
{
fprintf ( stderr , " Error: can't encode/write %s \n " , qPrintable ( certname ) ) ;
return 1 ;
}
2005-03-14 11:40:03 +00:00
}
2020-02-10 00:29:23 +01:00
else if ( args [ 1 ] = = QLatin1String ( " validate " ) )
2005-03-14 11:40:03 +00:00
{
2007-03-29 03:26:27 +00:00
if ( args . count ( ) < 3 )
{
usage ( ) ;
return 1 ;
}
2005-03-14 11:40:03 +00:00
2007-03-29 03:26:27 +00:00
QCA : : Certificate target = get_C ( args [ 2 ] ) ;
if ( target . isNull ( ) )
return 1 ;
2005-03-14 11:40:03 +00:00
2007-03-29 03:26:27 +00:00
// get roots
QCA : : CertificateCollection roots ;
if ( ! nosys )
roots + = QCA : : systemStore ( ) ;
if ( ! rootsFile . isEmpty ( ) )
roots + = QCA : : CertificateCollection : : fromFlatTextFile ( rootsFile ) ;
// get nonroots
QCA : : CertificateCollection nonroots ;
if ( ! nonRootsFile . isEmpty ( ) )
nonroots = QCA : : CertificateCollection : : fromFlatTextFile ( nonRootsFile ) ;
QCA : : Validity v = target . validate ( roots , nonroots ) ;
if ( v = = QCA : : ValidityGood )
printf ( " Certificate is valid \n " ) ;
else
2005-03-14 11:40:03 +00:00
{
2007-03-29 03:26:27 +00:00
printf ( " Certificate is NOT valid: %s \n " , qPrintable ( validityToString ( v ) ) ) ;
2005-03-14 11:40:03 +00:00
return 1 ;
}
}
2007-03-29 03:26:27 +00:00
else
2005-03-14 11:40:03 +00:00
{
2007-03-29 03:26:27 +00:00
usage ( ) ;
2005-03-14 11:40:03 +00:00
return 1 ;
}
}
2020-02-10 00:29:23 +01:00
else if ( args [ 0 ] = = QLatin1String ( " keybundle " ) )
2005-03-14 11:40:03 +00:00
{
2007-02-19 03:58:54 +00:00
if ( args . count ( ) < 2 )
2005-03-14 11:40:03 +00:00
{
usage ( ) ;
return 1 ;
}
2020-02-10 00:29:23 +01:00
if ( args [ 1 ] = = QLatin1String ( " make " ) )
2005-03-14 11:40:03 +00:00
{
2007-03-29 03:26:27 +00:00
if ( args . count ( ) < 4 )
{
usage ( ) ;
return 1 ;
}
2005-03-14 11:40:03 +00:00
2007-05-15 06:47:19 +00:00
if ( ! QCA : : isSupported ( " pkcs12 " ) )
{
fprintf ( stderr , " Error: need 'pkcs12' feature. \n " ) ;
return 1 ;
}
2007-05-14 05:37:05 +00:00
QCA : : PrivateKey priv = get_K ( args [ 2 ] ) ;
2007-03-29 03:26:27 +00:00
if ( priv . isNull ( ) )
return 1 ;
2007-02-19 03:58:54 +00:00
2007-03-29 03:26:27 +00:00
QCA : : Certificate cert = get_C ( args [ 3 ] ) ;
if ( cert . isNull ( ) )
return 1 ;
2007-02-19 03:58:54 +00:00
2007-03-29 03:26:27 +00:00
// get roots
QCA : : CertificateCollection roots ;
if ( ! nosys )
roots + = QCA : : systemStore ( ) ;
if ( ! rootsFile . isEmpty ( ) )
roots + = QCA : : CertificateCollection : : fromFlatTextFile ( rootsFile ) ;
2005-03-14 11:40:03 +00:00
2007-03-29 03:26:27 +00:00
// get nonroots
QCA : : CertificateCollection nonroots ;
if ( ! nonRootsFile . isEmpty ( ) )
nonroots = QCA : : CertificateCollection : : fromFlatTextFile ( nonRootsFile ) ;
2005-03-14 11:40:03 +00:00
2007-03-29 03:26:27 +00:00
QList < QCA : : Certificate > issuer_pool = roots . certificates ( ) + nonroots . certificates ( ) ;
2005-03-14 11:40:03 +00:00
2007-03-29 03:26:27 +00:00
QCA : : CertificateChain chain ;
chain + = cert ;
chain = chain . complete ( issuer_pool ) ;
2005-03-14 11:40:03 +00:00
2007-03-29 03:26:27 +00:00
QCA : : KeyBundle key ;
key . setName ( chain . primary ( ) . commonName ( ) ) ;
key . setCertificateChainAndKey ( chain , priv ) ;
2007-02-19 03:58:54 +00:00
2007-03-29 03:26:27 +00:00
if ( ! allowprompt & & ! have_newpass )
2005-03-14 11:40:03 +00:00
{
2007-03-29 03:26:27 +00:00
fprintf ( stderr , " Error: no passphrase specified (use '--newpass=' for none). \n " ) ;
return 1 ;
2005-03-14 11:40:03 +00:00
}
2007-02-19 03:58:54 +00:00
2007-03-29 03:26:27 +00:00
// prompt for new passphrase if necessary
if ( ! have_newpass )
{
while ( ! promptForNewPassphrase ( & newpass ) )
{
}
have_newpass = true ;
}
2007-02-19 03:58:54 +00:00
2007-03-29 03:26:27 +00:00
if ( newpass . isEmpty ( ) )
{
fprintf ( stderr , " Error: keybundles cannot have empty passphrases. \n " ) ;
return 1 ;
}
2007-02-19 03:58:54 +00:00
2020-02-10 00:29:23 +01:00
QString newFileName = QStringLiteral ( " cert.p12 " ) ;
2007-02-19 03:58:54 +00:00
2007-03-29 03:26:27 +00:00
if ( key . toFile ( newFileName , newpass ) )
printf ( " Keybundle saved to %s \n " , qPrintable ( newFileName ) ) ;
else
{
fprintf ( stderr , " Error: can't encode keybundle. \n " ) ;
return 1 ;
}
2005-03-14 11:40:03 +00:00
}
2020-02-10 00:29:23 +01:00
else if ( args [ 1 ] = = QLatin1String ( " extract " ) )
2005-03-14 11:40:03 +00:00
{
2007-03-29 03:26:27 +00:00
if ( args . count ( ) < 3 )
{
usage ( ) ;
return 1 ;
}
2005-03-14 11:40:03 +00:00
2007-03-29 03:26:27 +00:00
QCA : : KeyBundle key = get_X ( args [ 2 ] ) ;
if ( key . isNull ( ) )
return 1 ;
2005-03-14 11:40:03 +00:00
2007-03-29 03:26:27 +00:00
QCA : : PrivateKey priv = key . privateKey ( ) ;
bool export_priv = priv . canExport ( ) ;
2005-03-14 11:40:03 +00:00
2007-03-29 03:26:27 +00:00
if ( export_priv )
{
fprintf ( stderr , " You will need to create a passphrase for the extracted private key. \n " ) ;
2005-03-14 11:40:03 +00:00
2007-03-29 03:26:27 +00:00
if ( ! allowprompt & & ! have_newpass )
{
fprintf ( stderr , " Error: no passphrase specified (use '--newpass=' for none). \n " ) ;
return 1 ;
}
2005-03-14 11:40:03 +00:00
2007-03-29 03:26:27 +00:00
// prompt for new passphrase if necessary
if ( ! have_newpass )
{
while ( ! promptForNewPassphrase ( & newpass ) )
{
}
have_newpass = true ;
}
}
2005-03-14 11:40:03 +00:00
2007-03-29 03:26:27 +00:00
printf ( " Certs: (first is primary) \n " ) ;
QCA : : CertificateChain chain = key . certificateChain ( ) ;
for ( int n = 0 ; n < chain . count ( ) ; + + n )
printf ( " %s " , qPrintable ( chain [ n ] . toPEM ( ) ) ) ;
printf ( " Private Key: \n " ) ;
if ( export_priv )
{
QString out ;
if ( ! newpass . isEmpty ( ) )
out = priv . toPEM ( newpass ) ;
else
out = priv . toPEM ( ) ;
printf ( " %s " , qPrintable ( out ) ) ;
}
else
{
printf ( " (Key is not exportable) \n " ) ;
}
2005-03-14 11:40:03 +00:00
}
2020-02-10 00:29:23 +01:00
else if ( args [ 1 ] = = QLatin1String ( " changepass " ) )
2005-03-14 11:40:03 +00:00
{
2007-03-29 03:26:27 +00:00
if ( args . count ( ) < 3 )
{
usage ( ) ;
return 1 ;
}
2005-03-14 11:40:03 +00:00
2007-03-29 03:26:27 +00:00
QCA : : KeyBundle key = get_X ( args [ 2 ] ) ;
if ( key . isNull ( ) )
return 1 ;
2005-03-14 11:40:03 +00:00
2007-03-29 03:26:27 +00:00
if ( ! key . privateKey ( ) . canExport ( ) )
{
fprintf ( stderr , " Error: private key not exportable. \n " ) ;
return 1 ;
}
2005-03-14 11:40:03 +00:00
2007-03-29 03:26:27 +00:00
if ( ! allowprompt & & ! have_newpass )
{
fprintf ( stderr , " Error: no passphrase specified (use '--newpass=' for none). \n " ) ;
return 1 ;
}
2005-03-14 11:40:03 +00:00
2007-03-29 03:26:27 +00:00
// prompt for new passphrase if necessary
if ( ! have_newpass )
{
while ( ! promptForNewPassphrase ( & newpass ) )
{
}
have_newpass = true ;
}
2005-03-14 11:40:03 +00:00
2007-03-29 03:26:27 +00:00
if ( newpass . isEmpty ( ) )
{
fprintf ( stderr , " Error: keybundles cannot have empty passphrases. \n " ) ;
return 1 ;
}
2005-03-14 11:40:03 +00:00
2007-03-29 03:26:27 +00:00
QFileInfo fi ( args [ 2 ] ) ;
2020-02-13 00:59:09 +01:00
QString newFileName = fi . baseName ( ) + QStringLiteral ( " _new.p12 " ) ;
2005-03-14 11:40:03 +00:00
2007-03-29 03:26:27 +00:00
if ( key . toFile ( newFileName , newpass ) )
printf ( " Keybundle saved to %s \n " , qPrintable ( newFileName ) ) ;
else
{
fprintf ( stderr , " Error: can't encode keybundle. \n " ) ;
return 1 ;
}
}
2005-03-14 11:40:03 +00:00
else
{
2007-03-29 03:26:27 +00:00
usage ( ) ;
2005-03-14 11:40:03 +00:00
return 1 ;
}
}
2020-02-10 00:29:23 +01:00
else if ( args [ 0 ] = = QLatin1String ( " keystore " ) )
2005-03-14 11:40:03 +00:00
{
if ( args . count ( ) < 2 )
{
usage ( ) ;
return 1 ;
}
2020-02-10 00:29:23 +01:00
if ( args [ 1 ] = = QLatin1String ( " list-stores " ) )
2005-03-14 11:40:03 +00:00
{
2007-05-13 22:36:52 +00:00
ksm_start_and_wait ( ) ;
2007-03-29 03:26:27 +00:00
QCA : : KeyStoreManager ksm ;
QStringList storeList = ksm . keyStores ( ) ;
2005-03-14 11:40:03 +00:00
2007-03-29 03:26:27 +00:00
for ( int n = 0 ; n < storeList . count ( ) ; + + n )
{
QCA : : KeyStore ks ( storeList [ n ] , & ksm ) ;
QString type = kstype_to_string ( ks . type ( ) ) ;
2007-05-08 05:15:25 +00:00
printf ( " %s %s [%s] \n " , qPrintable ( type ) , qPrintable ( idHash ( ks . id ( ) ) ) , qPrintable ( ks . name ( ) ) ) ;
2007-03-29 03:26:27 +00:00
}
2007-05-14 21:31:53 +00:00
if ( debug )
output_keystore_diagnostic_text ( ) ;
2007-03-29 03:26:27 +00:00
}
2020-02-10 00:29:23 +01:00
else if ( args [ 1 ] = = QLatin1String ( " list " ) )
2007-03-29 03:26:27 +00:00
{
if ( args . count ( ) < 3 )
{
usage ( ) ;
return 1 ;
}
2005-03-14 11:40:03 +00:00
2007-05-13 22:36:52 +00:00
ksm_start_and_wait ( ) ;
2007-03-29 03:26:27 +00:00
QCA : : KeyStoreManager ksm ;
QCA : : KeyStore store ( getKeyStore ( args [ 2 ] ) , & ksm ) ;
if ( ! store . isValid ( ) )
{
2007-05-14 21:31:53 +00:00
if ( debug )
output_keystore_diagnostic_text ( ) ;
2007-03-29 03:26:27 +00:00
fprintf ( stderr , " Error: no such store \n " ) ;
return 1 ;
}
2005-03-14 11:40:03 +00:00
2007-03-29 03:26:27 +00:00
QList < QCA : : KeyStoreEntry > list = store . entryList ( ) ;
for ( int n = 0 ; n < list . count ( ) ; + + n )
{
QCA : : KeyStoreEntry i = list [ n ] ;
QString type = ksentrytype_to_string ( i . type ( ) ) ;
printf ( " %s %s [%s] \n " , qPrintable ( type ) , qPrintable ( idHash ( i . id ( ) ) ) , qPrintable ( i . name ( ) ) ) ;
}
2007-05-14 21:31:53 +00:00
if ( debug )
output_keystore_diagnostic_text ( ) ;
2007-03-29 03:26:27 +00:00
}
2020-02-10 00:29:23 +01:00
else if ( args [ 1 ] = = QLatin1String ( " monitor " ) )
2007-05-13 22:36:52 +00:00
{
KeyStoreMonitor : : monitor ( ) ;
2007-05-14 21:31:53 +00:00
if ( debug )
output_keystore_diagnostic_text ( ) ;
2007-05-13 22:36:52 +00:00
}
2020-02-10 00:29:23 +01:00
else if ( args [ 1 ] = = QLatin1String ( " export " ) )
2007-03-29 03:26:27 +00:00
{
if ( args . count ( ) < 3 )
{
usage ( ) ;
return 1 ;
}
2005-03-14 11:40:03 +00:00
2007-03-29 03:26:27 +00:00
QCA : : KeyStoreEntry entry = get_E ( args [ 2 ] ) ;
if ( entry . isNull ( ) )
return 1 ;
2005-03-14 11:40:03 +00:00
2007-03-29 03:26:27 +00:00
if ( entry . type ( ) = = QCA : : KeyStoreEntry : : TypeCertificate )
printf ( " %s " , qPrintable ( entry . certificate ( ) . toPEM ( ) ) ) ;
else if ( entry . type ( ) = = QCA : : KeyStoreEntry : : TypeCRL )
printf ( " %s " , qPrintable ( entry . crl ( ) . toPEM ( ) ) ) ;
else if ( entry . type ( ) = = QCA : : KeyStoreEntry : : TypePGPPublicKey | | entry . type ( ) = = QCA : : KeyStoreEntry : : TypePGPSecretKey )
printf ( " %s " , qPrintable ( entry . pgpPublicKey ( ) . toString ( ) ) ) ;
else if ( entry . type ( ) = = QCA : : KeyStoreEntry : : TypeKeyBundle )
2007-05-14 21:31:53 +00:00
{
2007-03-29 03:26:27 +00:00
fprintf ( stderr , " Error: use 'keybundle extract' command instead. \n " ) ;
2007-05-14 21:31:53 +00:00
return 1 ;
}
2007-03-29 03:26:27 +00:00
else
2007-05-14 21:31:53 +00:00
{
2007-03-29 03:26:27 +00:00
fprintf ( stderr , " Error: cannot export type '%d'. \n " , entry . type ( ) ) ;
2007-05-14 21:31:53 +00:00
return 1 ;
}
2005-03-14 11:40:03 +00:00
}
2020-02-10 00:29:23 +01:00
else if ( args [ 1 ] = = QLatin1String ( " exportref " ) )
2005-03-14 11:40:03 +00:00
{
2007-03-29 03:26:27 +00:00
if ( args . count ( ) < 3 )
{
usage ( ) ;
return 1 ;
}
QCA : : KeyStoreEntry entry = get_E ( args [ 2 ] ) ;
if ( entry . isNull ( ) )
return 1 ;
2007-04-13 07:08:17 +00:00
printf ( " %s " , make_ksentry_string ( entry . toString ( ) ) . toUtf8 ( ) . data ( ) ) ;
2005-03-14 11:40:03 +00:00
}
2020-02-10 00:29:23 +01:00
else if ( args [ 1 ] = = QLatin1String ( " addkb " ) )
2007-03-29 03:26:27 +00:00
{
if ( args . count ( ) < 4 )
{
usage ( ) ;
return 1 ;
}
2005-03-14 11:40:03 +00:00
2007-05-13 22:36:52 +00:00
ksm_start_and_wait ( ) ;
2007-03-29 03:26:27 +00:00
QCA : : KeyStoreManager ksm ;
QCA : : KeyStore store ( getKeyStore ( args [ 2 ] ) , & ksm ) ;
if ( ! store . isValid ( ) )
{
fprintf ( stderr , " Error: no such store \n " ) ;
return 1 ;
}
2005-03-14 11:40:03 +00:00
2007-05-15 06:47:19 +00:00
QCA : : KeyBundle key = get_X ( args [ 3 ] ) ;
if ( key . isNull ( ) )
2007-03-29 03:26:27 +00:00
return 1 ;
2005-03-14 11:40:03 +00:00
2007-05-15 06:47:19 +00:00
if ( ! store . writeEntry ( key ) . isEmpty ( ) )
2007-03-29 03:26:27 +00:00
printf ( " Entry written. \n " ) ;
else
{
fprintf ( stderr , " Error: unable to write entry. \n " ) ;
return 1 ;
}
}
2020-02-10 00:29:23 +01:00
else if ( args [ 1 ] = = QLatin1String ( " addpgp " ) )
2007-03-29 03:26:27 +00:00
{
if ( args . count ( ) < 4 )
{
usage ( ) ;
return 1 ;
}
2005-03-14 11:40:03 +00:00
2007-05-15 06:47:19 +00:00
if ( ! QCA : : isSupported ( " openpgp " ) )
{
fprintf ( stderr , " Error: need 'openpgp' feature. \n " ) ;
return 1 ;
}
2007-05-13 22:36:52 +00:00
ksm_start_and_wait ( ) ;
2007-03-29 03:26:27 +00:00
QCA : : KeyStoreManager ksm ;
QCA : : KeyStore store ( getKeyStore ( args [ 2 ] ) , & ksm ) ;
if ( ! store . isValid ( ) )
{
fprintf ( stderr , " Error: no such store \n " ) ;
return 1 ;
}
2005-03-14 11:40:03 +00:00
2007-03-29 03:26:27 +00:00
QCA : : PGPKey pub = QCA : : PGPKey : : fromFile ( args [ 3 ] ) ;
if ( pub . isNull ( ) )
return 1 ;
2005-03-14 11:40:03 +00:00
2007-04-13 06:32:02 +00:00
if ( ! store . writeEntry ( pub ) . isEmpty ( ) )
2007-03-29 03:26:27 +00:00
printf ( " Entry written. \n " ) ;
else
{
fprintf ( stderr , " Error: unable to write entry. \n " ) ;
return 1 ;
}
2005-03-14 11:40:03 +00:00
}
2020-02-10 00:29:23 +01:00
else if ( args [ 1 ] = = QLatin1String ( " remove " ) )
2007-03-29 03:26:27 +00:00
{
if ( args . count ( ) < 3 )
{
usage ( ) ;
return 1 ;
}
2005-03-14 11:40:03 +00:00
2007-03-29 03:26:27 +00:00
QCA : : KeyStoreEntry entry = get_E ( args [ 2 ] ) ;
if ( entry . isNull ( ) )
return 1 ;
2005-04-05 07:57:40 +00:00
2007-03-29 03:26:27 +00:00
QCA : : KeyStoreManager ksm ;
QCA : : KeyStore store ( entry . storeId ( ) , & ksm ) ;
if ( ! store . isValid ( ) )
{
fprintf ( stderr , " Error: no such store \n " ) ;
return 1 ;
}
2005-04-05 07:57:40 +00:00
2007-03-29 03:26:27 +00:00
if ( store . removeEntry ( entry . id ( ) ) )
printf ( " Entry removed. \n " ) ;
else
{
fprintf ( stderr , " Error: unable to remove entry. \n " ) ;
return 1 ;
}
}
2005-04-05 07:57:40 +00:00
else
2005-03-14 11:40:03 +00:00
{
usage ( ) ;
return 1 ;
}
}
2020-02-10 00:29:23 +01:00
else if ( args [ 0 ] = = QLatin1String ( " show " ) )
2005-03-14 11:40:03 +00:00
{
if ( args . count ( ) < 2 )
{
usage ( ) ;
return 1 ;
}
2020-02-10 00:29:23 +01:00
if ( args [ 1 ] = = QLatin1String ( " cert " ) )
2005-03-14 11:40:03 +00:00
{
2007-03-29 03:26:27 +00:00
if ( args . count ( ) < 3 )
{
usage ( ) ;
return 1 ;
}
2005-03-14 11:40:03 +00:00
2007-03-29 03:26:27 +00:00
QCA : : Certificate cert = get_C ( args [ 2 ] ) ;
if ( cert . isNull ( ) )
return 1 ;
print_cert ( cert , ordered ) ;
2005-03-14 11:40:03 +00:00
}
2020-02-10 00:29:23 +01:00
else if ( args [ 1 ] = = QLatin1String ( " req " ) )
2007-03-29 03:26:27 +00:00
{
if ( args . count ( ) < 3 )
{
usage ( ) ;
return 1 ;
}
2007-05-15 06:47:19 +00:00
if ( ! QCA : : isSupported ( " csr " ) )
{
fprintf ( stderr , " Error: need 'csr' feature. \n " ) ;
return 1 ;
}
2007-03-29 03:26:27 +00:00
QCA : : CertificateRequest req ( args [ 2 ] ) ;
if ( req . isNull ( ) )
{
2007-05-14 06:15:56 +00:00
fprintf ( stderr , " Error: can't read/process certificate request file. \n " ) ;
2007-03-29 03:26:27 +00:00
return 1 ;
}
2005-03-14 11:40:03 +00:00
2007-03-29 03:26:27 +00:00
print_certreq ( req , ordered ) ;
}
2020-02-10 00:29:23 +01:00
else if ( args [ 1 ] = = QLatin1String ( " crl " ) )
2007-05-14 06:15:56 +00:00
{
if ( args . count ( ) < 3 )
{
usage ( ) ;
return 1 ;
}
2007-05-15 06:47:19 +00:00
if ( ! QCA : : isSupported ( " crl " ) )
{
fprintf ( stderr , " Error: need 'crl' feature. \n " ) ;
return 1 ;
}
2007-08-20 15:16:08 +00:00
QCA : : CRL crl ;
if ( is_pem_file ( args [ 2 ] ) )
crl = QCA : : CRL : : fromPEMFile ( args [ 2 ] ) ;
else
crl = QCA : : CRL : : fromDER ( read_der_file ( args [ 2 ] ) ) ;
2007-05-14 06:15:56 +00:00
if ( crl . isNull ( ) )
{
2007-08-20 15:16:08 +00:00
fprintf ( stderr , " Error: unable to read/process CRL file. \n " ) ;
return 1 ;
2007-05-14 06:15:56 +00:00
}
print_crl ( crl , ordered ) ;
}
2020-02-10 00:29:23 +01:00
else if ( args [ 1 ] = = QLatin1String ( " kb " ) )
2007-05-14 06:15:56 +00:00
{
if ( args . count ( ) < 3 )
{
usage ( ) ;
return 1 ;
}
QCA : : KeyBundle key = get_X ( args [ 2 ] ) ;
if ( key . isNull ( ) )
return 1 ;
printf ( " Keybundle contains %d certificates. Displaying primary: \n " , key . certificateChain ( ) . count ( ) ) ;
print_cert ( key . certificateChain ( ) . primary ( ) , ordered ) ;
}
2020-02-10 00:29:23 +01:00
else if ( args [ 1 ] = = QLatin1String ( " pgp " ) )
2007-03-29 03:26:27 +00:00
{
if ( args . count ( ) < 3 )
{
usage ( ) ;
return 1 ;
}
2005-03-14 11:40:03 +00:00
2007-05-13 22:36:52 +00:00
// try for secret key, then try public key
2008-04-23 23:59:05 +00:00
QCA : : PGPKey key = get_S ( args [ 2 ] , true ) . first ;
2007-05-13 22:36:52 +00:00
if ( key . isNull ( ) )
{
key = get_P ( args [ 2 ] ) ;
if ( key . isNull ( ) )
return 1 ;
}
2005-03-14 11:40:03 +00:00
2007-05-13 22:36:52 +00:00
print_pgp ( key ) ;
2007-03-29 03:26:27 +00:00
}
2005-03-14 11:40:03 +00:00
else
{
2007-03-29 03:26:27 +00:00
usage ( ) ;
2005-03-14 11:40:03 +00:00
return 1 ;
}
}
2020-02-10 00:29:23 +01:00
else if ( args [ 0 ] = = QLatin1String ( " message " ) )
2005-05-10 21:10:35 +00:00
{
if ( args . count ( ) < 2 )
{
usage ( ) ;
return 1 ;
}
2020-02-10 00:29:23 +01:00
if ( args [ 1 ] = = QLatin1String ( " sign " ) )
2005-05-10 21:10:35 +00:00
{
2007-03-29 03:26:27 +00:00
if ( args . count ( ) < 4 )
2005-05-10 21:10:35 +00:00
{
usage ( ) ;
return 1 ;
}
2007-03-29 03:26:27 +00:00
QCA : : SecureMessageSystem * sms ;
QCA : : SecureMessageKey skey ;
QCA : : SecureMessage : : SignMode mode ;
bool pgp = false ;
2005-05-10 21:10:35 +00:00
2020-02-10 00:29:23 +01:00
if ( args [ 2 ] = = QLatin1String ( " pgp " ) )
2005-05-10 21:10:35 +00:00
{
2007-05-15 06:47:19 +00:00
if ( ! QCA : : isSupported ( " openpgp " ) )
{
fprintf ( stderr , " Error: need 'openpgp' feature. \n " ) ;
return 1 ;
}
2007-03-29 03:26:27 +00:00
QPair < QCA : : PGPKey , QCA : : PGPKey > key = get_S ( args [ 3 ] ) ;
if ( key . first . isNull ( ) )
return 1 ;
sms = new QCA : : OpenPGP ;
skey . setPGPSecretKey ( key . first ) ;
mode = QCA : : SecureMessage : : Clearsign ;
pgp = true ;
}
2020-02-10 00:29:23 +01:00
else if ( args [ 2 ] = = QLatin1String ( " pgpdetach " ) )
2007-03-29 03:26:27 +00:00
{
2007-05-15 06:47:19 +00:00
if ( ! QCA : : isSupported ( " openpgp " ) )
{
fprintf ( stderr , " Error: need 'openpgp' feature. \n " ) ;
return 1 ;
}
2007-03-29 03:26:27 +00:00
QPair < QCA : : PGPKey , QCA : : PGPKey > key = get_S ( args [ 3 ] ) ;
if ( key . first . isNull ( ) )
return 1 ;
sms = new QCA : : OpenPGP ;
skey . setPGPSecretKey ( key . first ) ;
mode = QCA : : SecureMessage : : Detached ;
pgp = true ;
2005-05-10 21:10:35 +00:00
}
2020-02-10 00:29:23 +01:00
else if ( args [ 2 ] = = QLatin1String ( " smime " ) )
2007-03-29 03:26:27 +00:00
{
2007-05-15 06:47:19 +00:00
if ( ! QCA : : isSupported ( " cms " ) )
{
fprintf ( stderr , " Error: need 'cms' feature. \n " ) ;
return 1 ;
}
2007-03-29 03:26:27 +00:00
QCA : : KeyBundle key = get_X ( args [ 3 ] ) ;
if ( key . isNull ( ) )
return 1 ;
2005-05-10 21:10:35 +00:00
2007-03-29 03:26:27 +00:00
// get nonroots
QCA : : CertificateCollection nonroots ;
if ( ! nonRootsFile . isEmpty ( ) )
nonroots = QCA : : CertificateCollection : : fromFlatTextFile ( nonRootsFile ) ;
QList < QCA : : Certificate > issuer_pool = nonroots . certificates ( ) ;
QCA : : CertificateChain chain = key . certificateChain ( ) ;
chain = chain . complete ( issuer_pool ) ;
sms = new QCA : : CMS ;
skey . setX509CertificateChain ( chain ) ;
skey . setX509PrivateKey ( key . privateKey ( ) ) ;
mode = QCA : : SecureMessage : : Detached ;
}
else
2005-05-10 21:10:35 +00:00
{
2007-03-29 03:26:27 +00:00
usage ( ) ;
2005-05-10 21:10:35 +00:00
return 1 ;
}
2007-03-29 03:26:27 +00:00
// read input data from stdin all at once
QByteArray plain ;
while ( ! feof ( stdin ) )
2005-05-10 21:10:35 +00:00
{
2007-03-29 03:26:27 +00:00
QByteArray block ( 1024 , 0 ) ;
int n = fread ( block . data ( ) , 1 , 1024 , stdin ) ;
if ( n < 0 )
break ;
block . resize ( n ) ;
plain + = block ;
2005-05-10 21:10:35 +00:00
}
2007-03-29 03:26:27 +00:00
// smime envelope
if ( ! pgp )
2005-05-10 21:10:35 +00:00
{
2007-03-29 03:26:27 +00:00
QString text = add_cr ( QString : : fromUtf8 ( plain ) ) ;
2020-02-13 00:59:09 +01:00
plain = QString : : fromLatin1 ( mime_signpart ) . arg ( text ) . toUtf8 ( ) ;
2005-05-10 21:10:35 +00:00
}
2007-03-29 03:26:27 +00:00
QCA : : SecureMessage * msg = new QCA : : SecureMessage ( sms ) ;
msg - > setSigner ( skey ) ;
// pgp should always be ascii
if ( pgp )
msg - > setFormat ( QCA : : SecureMessage : : Ascii ) ;
2007-06-08 03:47:24 +00:00
msg - > setBundleSignerEnabled ( ! nobundle ) ;
2007-03-29 03:26:27 +00:00
msg - > startSign ( mode ) ;
msg - > update ( plain ) ;
msg - > end ( ) ;
msg - > waitForFinished ( - 1 ) ;
2007-05-14 21:31:53 +00:00
if ( debug )
{
output_keystore_diagnostic_text ( ) ;
output_message_diagnostic_text ( msg ) ;
}
2007-03-29 03:26:27 +00:00
if ( ! msg - > success ( ) )
2005-05-10 21:10:35 +00:00
{
2007-03-29 03:26:27 +00:00
QString errstr = smErrorToString ( msg - > errorCode ( ) ) ;
delete msg ;
delete sms ;
2007-05-14 21:31:53 +00:00
2007-03-29 03:26:27 +00:00
fprintf ( stderr , " Error: unable to sign: %s \n " , qPrintable ( errstr ) ) ;
2005-05-10 21:10:35 +00:00
return 1 ;
}
2007-03-29 03:26:27 +00:00
QString hashName = msg - > hashName ( ) ;
2005-05-10 21:10:35 +00:00
2007-03-29 03:26:27 +00:00
QByteArray output ;
if ( mode = = QCA : : SecureMessage : : Detached )
output = msg - > signature ( ) ;
else
output = msg - > read ( ) ;
2005-05-10 21:10:35 +00:00
2007-03-29 03:26:27 +00:00
delete msg ;
delete sms ;
2005-05-10 21:10:35 +00:00
2007-03-29 03:26:27 +00:00
// smime envelope
if ( ! pgp )
{
QCA : : Base64 enc ;
enc . setLineBreaksEnabled ( true ) ;
enc . setLineBreaksColumn ( 76 ) ;
QString sigtext = add_cr ( enc . arrayToString ( output ) ) ;
2020-02-13 00:59:09 +01:00
QString str = QString : : fromLatin1 ( mime_signed ) . arg ( hashName , QString : : fromUtf8 ( plain ) , sigtext ) ;
2007-03-29 03:26:27 +00:00
output = str . toUtf8 ( ) ;
}
2005-05-10 21:10:35 +00:00
2007-03-29 03:26:27 +00:00
printf ( " %s " , output . data ( ) ) ;
2005-05-10 21:10:35 +00:00
}
2020-02-10 00:29:23 +01:00
else if ( args [ 1 ] = = QLatin1String ( " encrypt " ) )
2005-05-10 21:10:35 +00:00
{
if ( args . count ( ) < 4 )
{
usage ( ) ;
return 1 ;
}
2007-03-29 03:26:27 +00:00
QCA : : SecureMessageSystem * sms ;
QCA : : SecureMessageKey skey ;
bool pgp = false ;
2020-02-10 00:29:23 +01:00
if ( args [ 2 ] = = QLatin1String ( " pgp " ) )
2005-05-10 21:10:35 +00:00
{
2007-05-15 06:47:19 +00:00
if ( ! QCA : : isSupported ( " openpgp " ) )
{
fprintf ( stderr , " Error: need 'openpgp' feature. \n " ) ;
return 1 ;
}
2007-03-29 03:26:27 +00:00
QCA : : PGPKey key = get_P ( args [ 3 ] ) ;
if ( key . isNull ( ) )
return 1 ;
sms = new QCA : : OpenPGP ;
skey . setPGPPublicKey ( key ) ;
pgp = true ;
2005-05-10 21:10:35 +00:00
}
2020-02-10 00:29:23 +01:00
else if ( args [ 2 ] = = QLatin1String ( " smime " ) )
2007-03-29 03:26:27 +00:00
{
2007-05-15 06:47:19 +00:00
if ( ! QCA : : isSupported ( " cms " ) )
{
fprintf ( stderr , " Error: need 'cms' feature. \n " ) ;
return 1 ;
}
2007-03-29 03:26:27 +00:00
QCA : : Certificate cert = get_C ( args [ 3 ] ) ;
if ( cert . isNull ( ) )
return 1 ;
2005-05-10 21:10:35 +00:00
2007-03-29 03:26:27 +00:00
sms = new QCA : : CMS ;
skey . setX509CertificateChain ( cert ) ;
}
else
2005-05-10 21:10:35 +00:00
{
2007-03-29 03:26:27 +00:00
usage ( ) ;
2005-05-10 21:10:35 +00:00
return 1 ;
}
2007-03-29 03:26:27 +00:00
// read input data from stdin all at once
QByteArray plain ;
while ( ! feof ( stdin ) )
2005-05-10 21:10:35 +00:00
{
2007-03-29 03:26:27 +00:00
QByteArray block ( 1024 , 0 ) ;
int n = fread ( block . data ( ) , 1 , 1024 , stdin ) ;
if ( n < 0 )
break ;
block . resize ( n ) ;
plain + = block ;
2005-05-10 21:10:35 +00:00
}
2007-03-29 03:26:27 +00:00
QCA : : SecureMessage * msg = new QCA : : SecureMessage ( sms ) ;
msg - > setRecipient ( skey ) ;
// pgp should always be ascii
if ( pgp )
msg - > setFormat ( QCA : : SecureMessage : : Ascii ) ;
msg - > startEncrypt ( ) ;
msg - > update ( plain ) ;
msg - > end ( ) ;
msg - > waitForFinished ( - 1 ) ;
2007-05-14 21:31:53 +00:00
if ( debug )
{
output_keystore_diagnostic_text ( ) ;
output_message_diagnostic_text ( msg ) ;
}
2007-03-29 03:26:27 +00:00
if ( ! msg - > success ( ) )
2005-05-10 21:10:35 +00:00
{
2007-03-29 03:26:27 +00:00
QString errstr = smErrorToString ( msg - > errorCode ( ) ) ;
delete msg ;
delete sms ;
fprintf ( stderr , " Error: unable to encrypt: %s \n " , qPrintable ( errstr ) ) ;
2005-05-10 21:10:35 +00:00
return 1 ;
}
2007-03-29 03:26:27 +00:00
QByteArray output = msg - > read ( ) ;
delete msg ;
delete sms ;
2005-05-10 21:10:35 +00:00
2007-03-29 03:26:27 +00:00
// smime envelope
if ( ! pgp )
2005-05-10 21:10:35 +00:00
{
2007-03-29 03:26:27 +00:00
QCA : : Base64 enc ;
enc . setLineBreaksEnabled ( true ) ;
enc . setLineBreaksColumn ( 76 ) ;
QString enctext = add_cr ( enc . arrayToString ( output ) ) ;
2020-02-13 00:59:09 +01:00
QString str = QString : : fromLatin1 ( mime_enveloped ) . arg ( enctext ) ;
2007-03-29 03:26:27 +00:00
output = str . toUtf8 ( ) ;
2005-05-10 21:10:35 +00:00
}
2007-03-29 03:26:27 +00:00
printf ( " %s " , output . data ( ) ) ;
2005-05-10 21:10:35 +00:00
}
2020-02-10 00:29:23 +01:00
else if ( args [ 1 ] = = QLatin1String ( " signencrypt " ) )
2005-06-25 20:27:10 +00:00
{
2007-03-29 03:26:27 +00:00
if ( args . count ( ) < 4 )
2005-06-25 20:27:10 +00:00
{
usage ( ) ;
return 1 ;
}
2007-05-15 06:47:19 +00:00
if ( ! QCA : : isSupported ( " openpgp " ) )
{
fprintf ( stderr , " Error: need 'openpgp' feature. \n " ) ;
return 1 ;
}
2007-03-29 03:26:27 +00:00
QCA : : SecureMessageSystem * sms ;
QCA : : SecureMessageKey skey ;
QCA : : SecureMessageKey rkey ;
2005-06-25 20:27:10 +00:00
{
2007-03-29 03:26:27 +00:00
QPair < QCA : : PGPKey , QCA : : PGPKey > sec = get_S ( args [ 2 ] ) ;
if ( sec . first . isNull ( ) )
return 1 ;
2005-06-25 20:27:10 +00:00
2007-03-29 03:26:27 +00:00
QCA : : PGPKey pub = get_P ( args [ 3 ] ) ;
if ( pub . isNull ( ) )
return 1 ;
2005-06-25 20:27:10 +00:00
2007-03-29 03:26:27 +00:00
sms = new QCA : : OpenPGP ;
skey . setPGPSecretKey ( sec . first ) ;
rkey . setPGPPublicKey ( pub ) ;
2005-06-25 20:27:10 +00:00
}
2007-03-29 03:26:27 +00:00
// read input data from stdin all at once
QByteArray plain ;
while ( ! feof ( stdin ) )
2005-06-25 20:27:10 +00:00
{
2007-03-29 03:26:27 +00:00
QByteArray block ( 1024 , 0 ) ;
int n = fread ( block . data ( ) , 1 , 1024 , stdin ) ;
if ( n < 0 )
break ;
block . resize ( n ) ;
plain + = block ;
2005-06-25 20:27:10 +00:00
}
2007-03-29 03:26:27 +00:00
QCA : : SecureMessage * msg = new QCA : : SecureMessage ( sms ) ;
if ( ! msg - > canSignAndEncrypt ( ) )
2005-06-25 20:27:10 +00:00
{
2007-03-29 03:26:27 +00:00
delete msg ;
delete sms ;
fprintf ( stderr , " Error: cannot perform integrated sign and encrypt. \n " ) ;
2005-06-25 20:27:10 +00:00
return 1 ;
}
2007-03-29 03:26:27 +00:00
msg - > setSigner ( skey ) ;
msg - > setRecipient ( rkey ) ;
msg - > setFormat ( QCA : : SecureMessage : : Ascii ) ;
msg - > startSignAndEncrypt ( ) ;
msg - > update ( plain ) ;
msg - > end ( ) ;
msg - > waitForFinished ( - 1 ) ;
2005-06-25 20:27:10 +00:00
2007-05-14 21:31:53 +00:00
if ( debug )
{
output_keystore_diagnostic_text ( ) ;
output_message_diagnostic_text ( msg ) ;
}
2007-03-29 03:26:27 +00:00
if ( ! msg - > success ( ) )
2005-06-25 20:27:10 +00:00
{
2007-03-29 03:26:27 +00:00
QString errstr = smErrorToString ( msg - > errorCode ( ) ) ;
delete msg ;
delete sms ;
fprintf ( stderr , " Error: unable to sign and encrypt: %s \n " , qPrintable ( errstr ) ) ;
2005-06-25 20:27:10 +00:00
return 1 ;
}
2007-03-29 03:26:27 +00:00
QByteArray output = msg - > read ( ) ;
delete msg ;
delete sms ;
2005-06-25 20:27:10 +00:00
2007-03-29 03:26:27 +00:00
printf ( " %s " , output . data ( ) ) ;
2005-06-25 20:27:10 +00:00
}
2020-02-10 00:29:23 +01:00
else if ( args [ 1 ] = = QLatin1String ( " verify " ) )
2005-06-25 20:27:10 +00:00
{
if ( args . count ( ) < 3 )
{
usage ( ) ;
return 1 ;
}
2007-03-29 03:26:27 +00:00
QCA : : SecureMessageSystem * sms ;
bool pgp = false ;
2020-02-10 00:29:23 +01:00
if ( args [ 2 ] = = QLatin1String ( " pgp " ) )
2005-06-25 20:27:10 +00:00
{
2007-05-15 06:47:19 +00:00
if ( ! QCA : : isSupported ( " openpgp " ) )
{
fprintf ( stderr , " Error: need 'openpgp' feature. \n " ) ;
return 1 ;
}
2007-03-29 03:26:27 +00:00
sms = new QCA : : OpenPGP ;
pgp = true ;
2005-06-25 20:27:10 +00:00
}
2020-02-10 00:29:23 +01:00
else if ( args [ 2 ] = = QLatin1String ( " smime " ) )
2007-03-29 03:26:27 +00:00
{
2007-05-15 06:47:19 +00:00
if ( ! QCA : : isSupported ( " cms " ) )
{
fprintf ( stderr , " Error: need 'cms' feature. \n " ) ;
return 1 ;
}
2007-03-29 03:26:27 +00:00
// get roots
QCA : : CertificateCollection roots ;
if ( ! nosys )
roots + = QCA : : systemStore ( ) ;
if ( ! rootsFile . isEmpty ( ) )
roots + = QCA : : CertificateCollection : : fromFlatTextFile ( rootsFile ) ;
2007-05-14 23:18:48 +00:00
// get intermediates and possible signers, in case
// the message does not have them.
QCA : : CertificateCollection nonroots ;
if ( ! nonRootsFile . isEmpty ( ) )
nonroots + = QCA : : CertificateCollection : : fromFlatTextFile ( nonRootsFile ) ;
2007-03-29 03:26:27 +00:00
sms = new QCA : : CMS ;
( ( QCA : : CMS * ) sms ) - > setTrustedCertificates ( roots ) ;
2007-05-14 23:18:48 +00:00
( ( QCA : : CMS * ) sms ) - > setUntrustedCertificates ( nonroots ) ;
2007-03-29 03:26:27 +00:00
}
else
2005-06-25 20:27:10 +00:00
{
2007-03-29 03:26:27 +00:00
usage ( ) ;
2005-06-25 20:27:10 +00:00
return 1 ;
}
2007-03-29 03:26:27 +00:00
QByteArray data , sig ;
QString smime_text ;
{
// read input data from stdin all at once
QByteArray plain ;
while ( ! feof ( stdin ) )
{
QByteArray block ( 1024 , 0 ) ;
int n = fread ( block . data ( ) , 1 , 1024 , stdin ) ;
if ( n < 0 )
break ;
block . resize ( n ) ;
plain + = block ;
}
if ( pgp )
{
// pgp can be either a detached signature followed
// by data, or an integrated message.
// detached signature?
if ( plain . startsWith ( " -----BEGIN PGP SIGNATURE----- " ) )
{
2018-07-26 21:43:48 +02:00
QByteArray footer = " -----END PGP SIGNATURE----- \n " ;
2007-03-29 03:26:27 +00:00
int n = plain . indexOf ( footer ) ;
if ( n = = - 1 )
{
delete sms ;
fprintf ( stderr , " Error: pgp signature header, but no footer. \n " ) ;
return 1 ;
}
n + = footer . length ( ) ;
sig = plain . mid ( 0 , n ) ;
data = plain . mid ( n ) ;
}
else
{
data = plain ;
}
}
else
{
// smime envelope
QString in = QString : : fromUtf8 ( plain ) ;
in = add_cr ( in ) ; // change the line endings?!
QString str , sigtext ;
if ( ! open_mime_data_sig ( in , & str , & sigtext ) )
{
fprintf ( stderr , " Error: can't parse message file. \n " ) ;
return 1 ;
}
2005-06-25 20:27:10 +00:00
2007-03-29 03:26:27 +00:00
data = str . toUtf8 ( ) ;
smime_text = str ;
2005-06-25 20:27:10 +00:00
2007-03-29 03:26:27 +00:00
QCA : : Base64 dec ;
dec . setLineBreaksEnabled ( true ) ;
sig = dec . stringToArray ( rem_cr ( sigtext ) ) . toByteArray ( ) ;
}
}
2005-06-25 20:27:10 +00:00
2007-03-29 03:26:27 +00:00
QCA : : SecureMessage * msg = new QCA : : SecureMessage ( sms ) ;
if ( pgp )
msg - > setFormat ( QCA : : SecureMessage : : Ascii ) ;
msg - > startVerify ( sig ) ;
msg - > update ( data ) ;
msg - > end ( ) ;
msg - > waitForFinished ( - 1 ) ;
2005-06-25 20:27:10 +00:00
2007-05-14 21:31:53 +00:00
if ( debug )
{
output_keystore_diagnostic_text ( ) ;
output_message_diagnostic_text ( msg ) ;
}
2007-03-29 03:26:27 +00:00
if ( ! msg - > success ( ) )
2005-06-25 20:27:10 +00:00
{
2007-03-29 03:26:27 +00:00
QString errstr = smErrorToString ( msg - > errorCode ( ) ) ;
delete msg ;
delete sms ;
fprintf ( stderr , " Error: verify failed: %s \n " , qPrintable ( errstr ) ) ;
2005-06-25 20:27:10 +00:00
return 1 ;
}
2007-03-29 03:26:27 +00:00
QByteArray output ;
if ( pgp & & sig . isEmpty ( ) )
output = msg - > read ( ) ;
2007-05-15 02:50:43 +00:00
QList < QCA : : SecureMessageSignature > signers = msg - > signers ( ) ;
2007-03-29 03:26:27 +00:00
delete msg ;
delete sms ;
// for pgp clearsign, pgp signed (non-detached), and smime,
// the signed content was inside of the message. we need
// to print that content now
if ( pgp )
{
printf ( " %s " , output . data ( ) ) ;
}
else
{
QString str = open_mime_envelope ( smime_text ) ;
printf ( " %s " , str . toUtf8 ( ) . data ( ) ) ;
}
2005-06-25 20:27:10 +00:00
2007-05-15 02:50:43 +00:00
smDisplaySignatures ( signers ) ;
2007-03-29 03:26:27 +00:00
2007-05-15 02:50:43 +00:00
bool allgood = true ;
foreach ( const QCA : : SecureMessageSignature & signer , signers )
2005-06-25 20:27:10 +00:00
{
2007-05-15 02:50:43 +00:00
if ( signer . identityResult ( ) ! = QCA : : SecureMessageSignature : : Valid )
2007-03-29 03:26:27 +00:00
{
2007-05-15 02:50:43 +00:00
allgood = false ;
break ;
2007-03-29 03:26:27 +00:00
}
2005-05-13 04:34:09 +00:00
}
2007-05-15 02:50:43 +00:00
if ( ! allgood )
return 1 ;
2005-05-13 04:34:09 +00:00
}
2020-02-10 00:29:23 +01:00
else if ( args [ 1 ] = = QLatin1String ( " decrypt " ) )
2005-05-13 04:34:09 +00:00
{
2007-03-29 03:26:27 +00:00
if ( args . count ( ) < 3 )
2005-05-13 04:34:09 +00:00
{
usage ( ) ;
return 1 ;
}
2007-03-29 03:26:27 +00:00
QCA : : SecureMessageSystem * sms ;
bool pgp = false ;
2005-05-13 04:34:09 +00:00
2020-02-10 00:29:23 +01:00
if ( args [ 2 ] = = QLatin1String ( " pgp " ) )
2006-04-03 22:54:32 +00:00
{
2007-05-15 06:47:19 +00:00
if ( ! QCA : : isSupported ( " openpgp " ) )
{
fprintf ( stderr , " Error: need 'openpgp' feature. \n " ) ;
return 1 ;
}
2007-03-29 03:26:27 +00:00
sms = new QCA : : OpenPGP ;
pgp = true ;
2006-04-03 22:54:32 +00:00
}
2020-02-10 00:29:23 +01:00
else if ( args [ 2 ] = = QLatin1String ( " smime " ) )
2006-04-03 22:54:32 +00:00
{
2007-03-29 03:26:27 +00:00
if ( args . count ( ) < 4 )
{
usage ( ) ;
return 1 ;
}
2006-04-03 22:54:32 +00:00
2007-05-15 06:47:19 +00:00
if ( ! QCA : : isSupported ( " cms " ) )
{
fprintf ( stderr , " Error: need 'cms' feature. \n " ) ;
return 1 ;
}
2007-05-15 03:07:50 +00:00
// user can provide many possible decrypt keys
QList < QCA : : KeyBundle > keys ;
for ( int n = 3 ; n < args . count ( ) ; + + n )
{
QCA : : KeyBundle key = get_X ( args [ n ] ) ;
if ( key . isNull ( ) )
return 1 ;
keys + = key ;
}
2006-04-03 22:54:32 +00:00
2007-03-29 03:26:27 +00:00
sms = new QCA : : CMS ;
2006-04-03 22:54:32 +00:00
2007-05-15 03:07:50 +00:00
QList < QCA : : SecureMessageKey > skeys ;
foreach ( const QCA : : KeyBundle & key , keys )
{
QCA : : SecureMessageKey skey ;
skey . setX509CertificateChain ( key . certificateChain ( ) ) ;
skey . setX509PrivateKey ( key . privateKey ( ) ) ;
skeys + = skey ;
}
( ( QCA : : CMS * ) sms ) - > setPrivateKeys ( skeys ) ;
2006-04-03 22:54:32 +00:00
}
2007-05-03 22:19:30 +00:00
else
{
usage ( ) ;
return 1 ;
}
2006-04-03 22:54:32 +00:00
2007-03-29 03:26:27 +00:00
// read input data from stdin all at once
QByteArray plain ;
while ( ! feof ( stdin ) )
2006-04-03 22:54:32 +00:00
{
2007-03-29 03:26:27 +00:00
QByteArray block ( 1024 , 0 ) ;
int n = fread ( block . data ( ) , 1 , 1024 , stdin ) ;
if ( n < 0 )
break ;
block . resize ( n ) ;
plain + = block ;
2006-04-03 22:54:32 +00:00
}
2007-03-29 03:26:27 +00:00
// smime envelope
if ( ! pgp )
2006-04-03 22:54:32 +00:00
{
2007-03-29 03:26:27 +00:00
QString in = QString : : fromUtf8 ( plain ) ;
QString str = open_mime_envelope ( in ) ;
if ( str . isEmpty ( ) )
{
delete sms ;
fprintf ( stderr , " Error: can't parse message file. \n " ) ;
return 1 ;
}
QCA : : Base64 dec ;
dec . setLineBreaksEnabled ( true ) ;
plain = dec . stringToArray ( rem_cr ( str ) ) . toByteArray ( ) ;
2006-04-03 22:54:32 +00:00
}
2007-03-29 03:26:27 +00:00
QCA : : SecureMessage * msg = new QCA : : SecureMessage ( sms ) ;
if ( pgp )
msg - > setFormat ( QCA : : SecureMessage : : Ascii ) ;
msg - > startDecrypt ( ) ;
msg - > update ( plain ) ;
msg - > end ( ) ;
msg - > waitForFinished ( - 1 ) ;
2007-05-14 21:31:53 +00:00
if ( debug )
{
output_keystore_diagnostic_text ( ) ;
output_message_diagnostic_text ( msg ) ;
}
2007-03-29 03:26:27 +00:00
if ( ! msg - > success ( ) )
2006-04-03 22:54:32 +00:00
{
2007-03-29 03:26:27 +00:00
QString errstr = smErrorToString ( msg - > errorCode ( ) ) ;
delete msg ;
delete sms ;
fprintf ( stderr , " Error: decrypt failed: %s \n " , qPrintable ( errstr ) ) ;
2006-04-03 22:54:32 +00:00
return 1 ;
}
2007-03-29 03:26:27 +00:00
QByteArray output = msg - > read ( ) ;
2006-04-03 22:54:32 +00:00
2007-05-15 02:50:43 +00:00
QList < QCA : : SecureMessageSignature > signers ;
2007-03-29 03:26:27 +00:00
bool wasSigned = false ;
if ( msg - > wasSigned ( ) )
2006-04-03 22:54:32 +00:00
{
2007-05-15 02:50:43 +00:00
signers = msg - > signers ( ) ;
2007-03-29 03:26:27 +00:00
wasSigned = true ;
2006-04-03 22:54:32 +00:00
}
2007-03-29 03:26:27 +00:00
delete msg ;
delete sms ;
2006-04-03 22:54:32 +00:00
2007-03-29 03:26:27 +00:00
printf ( " %s " , output . data ( ) ) ;
2006-04-03 22:54:32 +00:00
2007-03-29 03:26:27 +00:00
if ( wasSigned )
2006-04-03 22:54:32 +00:00
{
2007-03-29 03:26:27 +00:00
fprintf ( stderr , " Message was also signed: \n " ) ;
2007-05-15 02:50:43 +00:00
smDisplaySignatures ( signers ) ;
bool allgood = true ;
foreach ( const QCA : : SecureMessageSignature & signer , signers )
2007-03-29 03:26:27 +00:00
{
2007-05-15 02:50:43 +00:00
if ( signer . identityResult ( ) ! = QCA : : SecureMessageSignature : : Valid )
{
allgood = false ;
break ;
}
2007-03-29 03:26:27 +00:00
}
2007-05-15 02:50:43 +00:00
if ( ! allgood )
return 1 ;
2006-04-03 22:54:32 +00:00
}
}
2020-02-10 00:29:23 +01:00
else if ( args [ 1 ] = = QLatin1String ( " exportcerts " ) )
2006-04-03 22:54:32 +00:00
{
2007-05-15 06:47:19 +00:00
if ( ! QCA : : isSupported ( " cms " ) )
{
fprintf ( stderr , " Error: need 'cms' feature. \n " ) ;
return 1 ;
}
2007-05-15 05:55:19 +00:00
QCA : : SecureMessageSystem * sms = new QCA : : CMS ;
2006-04-03 22:54:32 +00:00
2007-03-29 03:26:27 +00:00
QByteArray data , sig ;
QString smime_text ;
{
// read input data from stdin all at once
QByteArray plain ;
while ( ! feof ( stdin ) )
{
QByteArray block ( 1024 , 0 ) ;
int n = fread ( block . data ( ) , 1 , 1024 , stdin ) ;
if ( n < 0 )
break ;
block . resize ( n ) ;
plain + = block ;
}
2006-04-03 22:54:32 +00:00
2007-03-29 03:26:27 +00:00
// smime envelope
QString in = QString : : fromUtf8 ( plain ) ;
QString str , sigtext ;
if ( ! open_mime_data_sig ( in , & str , & sigtext ) )
{
delete sms ;
fprintf ( stderr , " Error: can't parse message file. \n " ) ;
return 1 ;
}
2006-04-03 22:54:32 +00:00
2007-03-29 03:26:27 +00:00
data = str . toUtf8 ( ) ;
smime_text = str ;
2006-04-03 22:54:32 +00:00
2007-03-29 03:26:27 +00:00
QCA : : Base64 dec ;
dec . setLineBreaksEnabled ( true ) ;
sig = dec . stringToArray ( rem_cr ( sigtext ) ) . toByteArray ( ) ;
2006-04-03 22:54:32 +00:00
}
2007-03-29 03:26:27 +00:00
QCA : : SecureMessage * msg = new QCA : : SecureMessage ( sms ) ;
msg - > startVerify ( sig ) ;
msg - > update ( data ) ;
msg - > end ( ) ;
msg - > waitForFinished ( - 1 ) ;
2006-04-03 22:54:32 +00:00
2007-05-15 05:55:19 +00:00
if ( debug )
output_message_diagnostic_text ( msg ) ;
2007-05-14 21:31:53 +00:00
2007-03-29 03:26:27 +00:00
if ( ! msg - > success ( ) )
2006-04-03 22:54:32 +00:00
{
2007-03-29 03:26:27 +00:00
QString errstr = smErrorToString ( msg - > errorCode ( ) ) ;
delete msg ;
delete sms ;
2007-05-15 05:55:19 +00:00
fprintf ( stderr , " Error: export failed: %s \n " , qPrintable ( errstr ) ) ;
2006-04-03 22:54:32 +00:00
return 1 ;
}
2007-05-15 05:55:19 +00:00
QList < QCA : : SecureMessageSignature > signers = msg - > signers ( ) ;
2007-03-29 03:26:27 +00:00
delete msg ;
delete sms ;
2006-04-03 22:54:32 +00:00
2007-05-15 05:55:19 +00:00
// print out all certs of all signers
foreach ( const QCA : : SecureMessageSignature & signer , signers )
2006-04-03 22:54:32 +00:00
{
2007-05-15 05:55:19 +00:00
QCA : : SecureMessageKey key = signer . key ( ) ;
if ( ! key . isNull ( ) )
{
foreach ( const QCA : : Certificate & c , key . x509CertificateChain ( ) )
printf ( " %s " , qPrintable ( c . toPEM ( ) ) ) ;
}
2006-04-03 22:54:32 +00:00
}
2005-05-13 04:34:09 +00:00
}
else
{
usage ( ) ;
return 1 ;
}
}
2005-03-14 11:40:03 +00:00
else
{
usage ( ) ;
return 1 ;
}
return 0 ;
}
2007-03-29 03:26:27 +00:00
# include "main.moc"