Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F16569918
kpgpbase2.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
31 KB
Referenced Files
None
Subscribers
None
kpgpbase2.cpp
View Options
/*
kpgpbase2.cpp
Copyright (C) 2001,2002 the KPGP authors
See file AUTHORS.kpgp for details
This file is part of KPGP, the KDE PGP/GnuPG support library.
KPGP is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include
"kpgpbase.h"
#include
"kpgp.h"
#include
<string.h>
/* strncmp */
#include
<assert.h>
#include
<QDateTime>
#include
<klocale.h>
#include
<kshell.h>
#include
<kdebug.h>
#include
<algorithm>
#define PGP2 "pgp"
namespace
Kpgp
{
Base2
::
Base2
()
:
Base
()
{
}
Base2
::~
Base2
()
{
}
int
Base2
::
encrypt
(
Block
&
block
,
const
KeyIDList
&
recipients
)
{
return
encsign
(
block
,
recipients
,
0
);
}
int
Base2
::
clearsign
(
Block
&
block
,
const
char
*
passphrase
)
{
return
encsign
(
block
,
KeyIDList
(),
passphrase
);
}
int
Base2
::
encsign
(
Block
&
block
,
const
KeyIDList
&
recipients
,
const
char
*
passphrase
)
{
QByteArray
cmd
;
int
exitStatus
=
0
;
if
(
!
recipients
.
isEmpty
()
&&
passphrase
!=
0
)
cmd
=
PGP2
" +batchmode +language=en +verbose=1 -seat"
;
else
if
(
!
recipients
.
isEmpty
())
cmd
=
PGP2
" +batchmode +language=en +verbose=1 -eat"
;
else
if
(
passphrase
!=
0
)
cmd
=
PGP2
" +batchmode +language=en +verbose=1 -sat"
;
else
{
kDebug
(
5326
)
<<
"kpgpbase: Neither recipients nor passphrase specified."
;
return
OK
;
}
if
(
passphrase
!=
0
)
cmd
+=
addUserId
();
if
(
!
recipients
.
isEmpty
())
{
if
(
Module
::
getKpgp
()
->
encryptToSelf
())
{
cmd
+=
" 0x"
;
cmd
+=
Module
::
getKpgp
()
->
user
();
}
KeyIDList
::
ConstIterator
end
(
recipients
.
end
()
);
for
(
KeyIDList
::
ConstIterator
it
=
recipients
.
constBegin
();
it
!=
end
;
++
it
)
{
cmd
+=
" 0x"
;
cmd
+=
(
*
it
);
}
}
cmd
+=
" -f"
;
clear
();
input
=
block
.
text
();
exitStatus
=
run
(
cmd
.
data
(),
passphrase
);
if
(
!
output
.
isEmpty
()
)
block
.
setProcessedText
(
output
);
block
.
setError
(
error
);
if
(
exitStatus
!=
0
)
status
=
ERROR
;
#if 0
// #### FIXME: As we check the keys ourselves the following problems
// shouldn't occur. Therefore I don't handle them for now.
// IK 01/2002
if(!recipients.isEmpty())
{
int index = 0;
bool bad = false;
unsigned int num = 0;
QByteArray badkeys = "";
if (error.contains("Cannot find the public key") )
{
index = 0;
num = 0;
while((index = error.indexOf("Cannot find the public key",index))
!= -1)
{
bad = true;
index = error.indexOf('\'',index);
int index2 = error.indexOf('\'',index+1);
if (num++)
badkeys += ", ";
badkeys += error.mid(index, index2-index+1);
}
if(bad)
{
badkeys.trimmed();
if(num == recipients.count())
errMsg = i18n("Could not find public keys matching the userid(s)\n"
"%1;\n"
"the message is not encrypted.",
badkeys.data() );
else
errMsg = i18n("Could not find public keys matching the userid(s)\n"
"%1;\n"
"these persons will not be able to read the message.",
badkeys.data() );
status |= MISSINGKEY;
status |= ERROR;
}
}
if (error.contains("skipping userid") )
{
index = 0;
num = 0;
while((index = error.indexOf("skipping userid",index))
!= -1)
{
bad = true;
int index2 = error.indexOf('\n',index+16);
if (num++)
badkeys += ", ";
badkeys += error.mid(index+16, index2-index-16);
index = index2;
}
if(bad)
{
badkeys.trimmed();
if(num == recipients.count())
errMsg = i18n("Public keys not certified with trusted signature "
"for userid(s)\n"
"%1.\n"
"The message is not encrypted.",
badkeys.data() );
else
errMsg = i18n("Public keys not certified with trusted signature "
"for userid(s)\n"
"%1;\n"
"these persons will not be able to read the message.",
badkeys.data() );
status |= BADKEYS;
status |= ERROR;
return status;
}
}
}
#endif
if
(
passphrase
!=
0
)
{
if
(
error
.
contains
(
"Pass phrase is good"
)
)
{
//kDebug( 5326 ) <<"Base: Good Passphrase!";
status
|=
SIGNED
;
}
if
(
error
.
contains
(
"Bad pass phrase"
)
)
{
errMsg
=
i18n
(
"Bad passphrase; could not sign."
);
status
|=
BADPHRASE
;
status
|=
ERR_SIGNING
;
status
|=
ERROR
;
}
}
if
(
error
.
contains
(
"Signature error"
)
)
{
errMsg
=
i18n
(
"Signing failed: please check your PGP User Identity, "
"the PGP setup, and the key rings."
);
status
|=
NO_SEC_KEY
;
status
|=
ERR_SIGNING
;
status
|=
ERROR
;
}
if
(
error
.
contains
(
"Encryption error"
)
)
{
errMsg
=
i18n
(
"Encryption failed: please check your PGP setup "
"and the key rings."
);
status
|=
NO_SEC_KEY
;
status
|=
BADKEYS
;
status
|=
ERROR
;
}
//kDebug( 5326 ) <<"status =" << status;
block
.
setStatus
(
status
);
return
status
;
}
int
Base2
::
decrypt
(
Block
&
block
,
const
char
*
passphrase
)
{
int
index
,
index2
;
int
exitStatus
=
0
;
clear
();
input
=
block
.
text
();
exitStatus
=
run
(
PGP2
" +batchmode +language=en -f"
,
passphrase
);
if
(
!
output
.
isEmpty
()
)
block
.
setProcessedText
(
output
);
block
.
setError
(
error
);
// pgp2.6 has sometimes problems with the ascii armor pgp5.0 produces
// this hack can solve parts of the problem
if
(
error
.
contains
(
"ASCII armor corrupted."
)
)
{
kDebug
(
5326
)
<<
"removing ASCII armor header"
;
int
index1
=
input
.
indexOf
(
"-----BEGIN PGP SIGNED MESSAGE-----"
);
if
(
index1
!=
-1
)
index1
=
input
.
indexOf
(
"-----BEGIN PGP SIGNATURE-----"
,
index1
);
else
index1
=
input
.
indexOf
(
"-----BEGIN PGP MESSAGE-----"
);
index1
=
input
.
indexOf
(
'\n'
,
index1
);
index2
=
input
.
indexOf
(
"
\n\n
"
,
index1
);
input
.
remove
(
index1
,
index2
-
index1
);
exitStatus
=
run
(
PGP2
" +batchmode +language=en -f"
,
passphrase
);
if
(
!
output
.
isEmpty
()
)
block
.
setProcessedText
(
output
);
block
.
setError
(
error
);
}
if
(
exitStatus
==
-1
)
{
errMsg
=
i18n
(
"error running PGP"
);
status
=
ERROR
;
block
.
setStatus
(
status
);
return
status
;
}
/* Example No.1 (PGP 2.6.3in):
* File is encrypted. Secret key is required to read it.
* Key for user ID: Test Key (only for testing) <testkey@ingo-kloecker.de>
* 1024-bit key, key ID E2D074D3, created 2001/09/09
*
* Error: Bad pass phrase.
*
* This message can only be read by:
* Test key without secret key (for testing only) <nosectestkey@ingo-kloecker.de>
* Test Key (only for testing) <testkey@ingo-kloecker.de>
*
* You do not have the secret key needed to decrypt this file.
*/
/* Example No.2 (PGP 2.6.3in):
* File is encrypted. Secret key is required to read it.
* This message can only be read by:
* Test key without secret key (for testing only) <nosectestkey@ingo-kloecker.de>
*
* You do not have the secret key needed to decrypt this file.
*/
if
(
error
.
contains
(
"File is encrypted."
)
)
{
//kDebug( 5326 ) <<"kpgpbase: message is encrypted";
status
|=
ENCRYPTED
;
if
((
index
=
error
.
indexOf
(
"Key for user ID:"
))
!=
-1
)
{
// Find out the key for which the phrase is needed
index
+=
17
;
index2
=
error
.
indexOf
(
'\n'
,
index
);
block
.
setRequiredUserId
(
QLatin1String
(
error
.
mid
(
index
,
index2
-
index
))
);
//kDebug( 5326 ) <<"Base: key needed is \"" << block.requiredUserId() <<"\"!";
if
((
passphrase
!=
0
)
&&
(
error
.
contains
(
"Bad pass phrase"
)
))
{
errMsg
=
i18n
(
"Bad passphrase; could not decrypt."
);
kDebug
(
5326
)
<<
"Base: passphrase is bad"
;
status
|=
BADPHRASE
;
status
|=
ERROR
;
}
}
else
{
// no secret key fitting this message
status
|=
NO_SEC_KEY
;
status
|=
ERROR
;
errMsg
=
i18n
(
"You do not have the secret key needed to decrypt this message."
);
kDebug
(
5326
)
<<
"Base: no secret key for this message"
;
}
// check for persons
#if 0
// ##### FIXME: This information is anyway currently not used
// I'll change it to always determine the recipients.
index = error.indexOf("can only be read by:");
if(index != -1)
{
index = error.indexOf('\n',index);
int end = error.indexOf("\n\n",index);
mRecipients.clear();
while( (index2 = error.indexOf('\n',index+1)) <= end )
{
QByteArray item = error.mid(index+1,index2-index-1);
item.trimmed();
mRecipients.append(item);
index = index2;
}
}
#endif
}
// handle signed message
// Examples (made with PGP 2.6.3in)
/* Example No. 1 (signed with unknown key):
* File has signature. Public key is required to check signature.
*
* Key matching expected Key ID 12345678 not found in file '/home/user/.pgp/pubring.pgp'.
*
* WARNING: Can't find the right public key-- can't check signature integrity.
*/
/* Example No. 2 (bad signature):
* File has signature. Public key is required to check signature.
* ..
* WARNING: Bad signature, doesn't match file contents!
*
* Bad signature from user "Joe User <joe@foo.bar>".
* Signature made 2001/09/09 16:01 GMT using 1024-bit key, key ID 12345678
*/
/* Example No. 3.1 (good signature with untrusted key):
* File has signature. Public key is required to check signature.
* .
* Good signature from user "Joe User <joe@foo.bar>".
* Signature made 2001/09/09 16:01 GMT using 1024-bit key, key ID 12345678
*
* WARNING: Because this public key is not certified with a trusted
* signature, it is not known with high confidence that this public key
* actually belongs to: "Joe User <joe@foo.bar>".
*/
/* Example No. 3.2 (good signature with untrusted key):
* File has signature. Public key is required to check signature.
* .
* Good signature from user "Joe User <joe@foo.bar>".
* Signature made 2001/09/09 16:01 GMT using 1024-bit key, key ID 12345678
*
* WARNING: Because this public key is not certified with enough trusted
* signatures, it is not known with high confidence that this public key
* actually belongs to: "Joe User <joe@foo.bar>".
*/
/* Example No. 4 (good signature with revoked key):
* File has signature. Public key is required to check signature.
* .
* Good signature from user "Joe User <joe@foo.bar>".
* Signature made 2001/09/09 16:01 GMT using 1024-bit key, key ID 12345678
*
*
* Key for user ID: Joe User <joe@foo.bar>
* 1024-bit key, key ID 12345678, created 2001/09/09
* Key has been revoked.
*
* WARNING: This key has been revoked by its owner,
* possibly because the secret key was compromised.
* This could mean that this signature is a forgery.
*/
/* Example No. 5 (good signature with trusted key):
* File has signature. Public key is required to check signature.
* .
* Good signature from user "Joe User <joe@foo.bar>".
* Signature made 2001/09/09 16:01 GMT using 1024-bit key, key ID 12345678
*/
if
((
index
=
error
.
indexOf
(
"File has signature"
))
!=
-1
)
{
// move index to start of next line
index
=
error
.
indexOf
(
'\n'
,
index
+
18
)
+
1
;
//kDebug( 5326 ) <<"Base: message is signed";
status
|=
SIGNED
;
// get signature date and signature key ID
if
((
index2
=
error
.
indexOf
(
"Signature made"
,
index
))
!=
-1
)
{
index2
+=
15
;
int
index3
=
error
.
indexOf
(
"using"
,
index2
);
block
.
setSignatureDate
(
error
.
mid
(
index2
,
index3
-
index2
-1
)
);
kDebug
(
5326
)
<<
"Message was signed on '"
<<
block
.
signatureDate
()
<<
"'"
;
index3
=
error
.
indexOf
(
"key ID "
,
index3
)
+
7
;
block
.
setSignatureKeyId
(
error
.
mid
(
index3
,
8
)
);
kDebug
(
5326
)
<<
"Message was signed with key '"
<<
block
.
signatureKeyId
()
<<
"'"
;
}
else
{
// if pgp can't find the keyring it unfortunately doesn't print
// the signature date and key ID
block
.
setSignatureDate
(
""
);
block
.
setSignatureKeyId
(
""
);
}
if
(
(
index2
=
error
.
indexOf
(
"Key matching expected"
,
index
)
)
!=
-1
)
{
status
|=
UNKNOWN_SIG
;
status
|=
GOODSIG
;
int
index3
=
error
.
indexOf
(
"Key ID "
,
index2
)
+
7
;
block
.
setSignatureKeyId
(
error
.
mid
(
index3
,
8
)
);
block
.
setSignatureUserId
(
QString
()
);
}
else
if
(
(
index2
=
error
.
indexOf
(
"Good signature from"
,
index
))
!=
-1
)
{
status
|=
GOODSIG
;
// get signer
index
=
error
.
indexOf
(
'"'
,
index2
+
19
);
index2
=
error
.
indexOf
(
'"'
,
index
+
1
);
block
.
setSignatureUserId
(
QLatin1String
(
error
.
mid
(
index
+
1
,
index2
-
index
-1
))
);
}
else
if
(
(
index2
=
error
.
indexOf
(
"Bad signature from"
,
index
))
!=
-1
)
{
status
|=
ERROR
;
// get signer
index
=
error
.
indexOf
(
'"'
,
index2
+
19
);
index2
=
error
.
indexOf
(
'"'
,
index
+
1
);
block
.
setSignatureUserId
(
QLatin1String
(
error
.
mid
(
index
+
1
,
index2
-
index
-1
))
);
}
else
if
(
error
.
indexOf
(
"Keyring file"
,
index
)
!=
-1
)
{
// #### fix this hack
status
|=
UNKNOWN_SIG
;
status
|=
GOODSIG
;
// this is a hack...
// determine file name of missing keyring file
index
=
error
.
indexOf
(
'\''
,
index
)
+
1
;
index2
=
error
.
indexOf
(
'\''
,
index
);
block
.
setSignatureUserId
(
i18n
(
"The keyring file %1 does not exist.
\n
"
"Please check your PGP setup."
,
QString
::
fromLatin1
(
error
.
mid
(
index
,
index2
-
index
))
)
);
}
else
{
status
|=
ERROR
;
block
.
setSignatureUserId
(
i18n
(
"Unknown error"
)
);
}
}
//kDebug( 5326 ) <<"status =" << status;
block
.
setStatus
(
status
);
return
status
;
}
Key
*
Base2
::
readPublicKey
(
const
KeyID
&
keyID
,
const
bool
readTrust
/* = false */
,
Key
*
key
/* = 0 */
)
{
int
exitStatus
=
0
;
status
=
0
;
exitStatus
=
run
(
QByteArray
(
QByteArray
(
PGP2
" +batchmode +language=en +verbose=0 -kvc -f 0x"
)
+
keyID
),
0
,
true
);
if
(
exitStatus
!=
0
)
{
status
=
ERROR
;
return
0
;
}
key
=
parsePublicKeyData
(
output
,
key
);
if
(
key
==
0
)
{
return
0
;
}
if
(
readTrust
)
{
exitStatus
=
run
(
PGP2
" +batchmode +language=en +verbose=0 -kc -f"
,
0
,
true
);
if
(
exitStatus
!=
0
)
{
status
=
ERROR
;
return
0
;
}
parseTrustDataForKey
(
key
,
error
);
}
return
key
;
}
KeyList
Base2
::
publicKeys
(
const
QStringList
&
patterns
)
{
return
doGetPublicKeys
(
PGP2
" +batchmode +language=en +verbose=0 -kvc -f"
,
patterns
);
}
KeyList
Base2
::
doGetPublicKeys
(
const
QByteArray
&
cmd
,
const
QStringList
&
patterns
)
{
int
exitStatus
=
0
;
KeyList
publicKeys
;
status
=
0
;
if
(
patterns
.
isEmpty
()
)
{
exitStatus
=
run
(
cmd
,
0
,
true
);
if
(
exitStatus
!=
0
)
{
status
=
ERROR
;
return
KeyList
();
}
// now we need to parse the output for public keys
publicKeys
=
parseKeyList
(
output
,
false
);
}
else
{
typedef
QMap
<
QByteArray
,
Key
*>
KeyMap
;
KeyMap
map
;
QStringList
::
ConstIterator
end
(
patterns
.
constEnd
()
);
for
(
QStringList
::
ConstIterator
it
=
patterns
.
constBegin
();
it
!=
end
;
++
it
)
{
exitStatus
=
run
(
QByteArray
(
cmd
+
QByteArray
(
" "
)
+
KShell
::
quoteArg
(
*
it
).
toLocal8Bit
()),
0
,
true
);
if
(
exitStatus
!=
0
)
{
status
=
ERROR
;
return
KeyList
();
}
// now we need to parse the output for public keys
publicKeys
=
parseKeyList
(
output
,
false
);
// put all new keys into a map, remove duplicates
while
(
!
publicKeys
.
isEmpty
()
)
{
Key
*
key
=
publicKeys
.
takeFirst
();
if
(
!
map
.
contains
(
key
->
primaryFingerprint
()
)
)
map
.
insert
(
key
->
primaryFingerprint
(),
key
);
else
delete
key
;
}
}
// build list from the map
KeyMap
::
ConstIterator
endKeyMap
(
map
.
constEnd
()
);
for
(
KeyMap
::
ConstIterator
it
=
map
.
constBegin
();
it
!=
endKeyMap
;
++
it
)
{
publicKeys
.
append
(
it
.
value
()
);
}
}
// sort the list of public keys
std
::
sort
(
publicKeys
.
begin
(),
publicKeys
.
end
(),
KeyCompare
);
return
publicKeys
;
}
KeyList
Base2
::
secretKeys
(
const
QStringList
&
patterns
)
{
return
publicKeys
(
patterns
);
}
int
Base2
::
signKey
(
const
KeyID
&
keyID
,
const
char
*
passphrase
)
{
QByteArray
cmd
;
int
exitStatus
=
0
;
cmd
=
PGP2
" +batchmode +language=en -ks -f "
;
cmd
+=
addUserId
();
cmd
+=
" 0x"
+
keyID
;
status
=
0
;
exitStatus
=
run
(
cmd
.
data
(),
passphrase
);
if
(
exitStatus
!=
0
)
status
=
ERROR
;
return
status
;
}
QByteArray
Base2
::
getAsciiPublicKey
(
const
KeyID
&
keyID
)
{
if
(
keyID
.
isEmpty
())
return
QByteArray
();
status
=
0
;
int
exitStatus
=
run
(
QByteArray
(
QByteArray
(
PGP2
" +batchmode +force +language=en -kxaf 0x"
)
+
keyID
),
0
,
true
);
if
(
exitStatus
!=
0
)
{
status
=
ERROR
;
return
QByteArray
();
}
return
output
;
}
Key
*
Base2
::
parsePublicKeyData
(
const
QByteArray
&
output
,
Key
*
key
/* = 0 */
)
{
Subkey
*
subkey
=
0
;
int
index
;
// search start of key data
if
(
!
strncmp
(
output
.
data
(),
"pub"
,
3
)
||
!
strncmp
(
output
.
data
(),
"sec"
,
3
)
)
index
=
0
;
else
{
/*
if( secretKeys )
index = output.indexOf( "\nsec" );
else
*/
index
=
output
.
indexOf
(
"
\n
pub"
);
if
(
index
==
-1
)
return
0
;
else
index
++
;
}
while
(
true
)
{
int
index2
;
// search the end of the current line
if
(
(
index2
=
output
.
indexOf
(
'\n'
,
index
)
)
==
-1
)
break
;
if
(
!
strncmp
(
output
.
data
()
+
index
,
"pub"
,
3
)
||
!
strncmp
(
output
.
data
()
+
index
,
"sec"
,
3
)
)
{
// line contains primary key data
// Example 1 (nothing special):
// pub 1024/E2D074D3 2001/09/09 Test Key <testkey@xyz>
// Example 2 (disabled key):
// pub- 1024/8CCB2C1B 2001/11/04 Disabled Test Key <disabled@xyz>
// Example 3 (expired key):
// pub> 1024/7B94827D 2001/09/09 Expired Test Key <expired@xyz> (EXPIRE:2001-09-10)
// Example 4 (revoked key):
// pub 1024/956721F9 2001/09/09 *** KEY REVOKED ***
int
pos
,
pos2
;
if
(
key
==
0
)
key
=
new
Key
();
else
key
->
clear
();
/*key->setSecret( secretKeys );*/
// set default key capabilities
key
->
setCanEncrypt
(
true
);
key
->
setCanSign
(
true
);
key
->
setCanCertify
(
true
);
/*subkey = new Subkey( "", secretKeys );*/
subkey
=
new
Subkey
(
""
,
false
);
key
->
addSubkey
(
subkey
);
// set default key capabilities
subkey
->
setCanEncrypt
(
true
);
subkey
->
setCanSign
(
true
);
subkey
->
setCanCertify
(
true
);
// expiration date defaults to never
subkey
->
setExpirationDate
(
-1
);
// Key Flags
switch
(
output
[
index
+
3
]
)
{
case
' '
:
// nothing special
break
;
case
'-'
:
// disabled key
subkey
->
setDisabled
(
true
);
key
->
setDisabled
(
true
);
break
;
case
'>'
:
// expired key
subkey
->
setExpired
(
true
);
key
->
setExpired
(
true
);
break
;
default
:
kDebug
(
5326
)
<<
"Unknown key flag."
;
}
// Key Length
pos
=
index
+
4
;
while
(
output
[
pos
]
==
' '
)
pos
++
;
pos2
=
output
.
indexOf
(
'/'
,
pos
);
subkey
->
setKeyLength
(
output
.
mid
(
pos
,
pos2
-
pos
).
toUInt
()
);
// Key ID
pos
=
pos2
+
1
;
pos2
=
output
.
indexOf
(
' '
,
pos
);
subkey
->
setKeyID
(
output
.
mid
(
pos
,
pos2
-
pos
)
);
// Creation Date
pos
=
pos2
+
1
;
while
(
output
[
pos
]
==
' '
)
pos
++
;
pos2
=
output
.
indexOf
(
' '
,
pos
);
int
year
=
output
.
mid
(
pos
,
4
).
toInt
();
int
month
=
output
.
mid
(
pos
+
5
,
2
).
toInt
();
int
day
=
output
.
mid
(
pos
+
8
,
2
).
toInt
();
QDateTime
dt
(
QDate
(
year
,
month
,
day
),
QTime
(
00
,
00
)
);
QDateTime
epoch
(
QDate
(
1970
,
01
,
01
),
QTime
(
00
,
00
)
);
// The calculated creation date isn't exactly correct because QDateTime
// doesn't know anything about timezones and always assumes local time
// although epoch is of course UTC. But as PGP 2 anyway doesn't print
// the time this doesn't matter too much.
subkey
->
setCreationDate
(
epoch
.
secsTo
(
dt
)
);
// User ID
pos
=
pos2
+
1
;
while
(
output
[
pos
]
==
' '
)
pos
++
;
QByteArray
uid
=
output
.
mid
(
pos
,
index2
-
pos
);
if
(
uid
!=
"*** KEY REVOKED ***"
)
key
->
addUserID
(
QLatin1String
(
uid
)
);
else
{
subkey
->
setRevoked
(
true
);
key
->
setRevoked
(
true
);
}
}
else
if
(
output
[
index
]
==
' '
)
{
// line contains additional key data
if
(
key
==
0
)
break
;
assert
(
subkey
!=
0
);
int
pos
=
index
+
1
;
while
(
output
[
pos
]
==
' '
)
pos
++
;
if
(
!
strncmp
(
output
.
data
()
+
pos
,
"Key fingerprint = "
,
18
)
)
{
// line contains a fingerprint
// Example:
// Key fingerprint = 47 30 7C 76 05 BF 5E FB 72 41 00 F2 7D 0B D0 49
QByteArray
fingerprint
=
output
.
mid
(
pos
,
index2
-
pos
);
// remove white space from the fingerprint
for
(
int
idx
=
0
;
(
idx
=
fingerprint
.
indexOf
(
' '
,
idx
))
!=
-1
;
)
fingerprint
.
replace
(
idx
,
1
,
""
);
subkey
->
setFingerprint
(
fingerprint
);
}
else
if
(
!
strncmp
(
output
.
data
()
+
pos
,
"Expire: "
,
8
)
||
!
strncmp
(
output
.
data
()
+
pos
,
"no expire "
,
10
)
)
{
// line contains additional key properties
// Examples:
// Expire: 2001/09/10
// no expire ENCRyption only
// no expire SIGNature only
if
(
output
[
pos
]
==
'E'
)
{
// Expiration Date
pos
+=
8
;
int
year
=
output
.
mid
(
pos
,
4
).
toInt
();
int
month
=
output
.
mid
(
pos
+
5
,
2
).
toInt
();
int
day
=
output
.
mid
(
pos
+
8
,
2
).
toInt
();
QDateTime
dt
(
QDate
(
year
,
month
,
day
),
QTime
(
00
,
00
)
);
QDateTime
epoch
(
QDate
(
1970
,
01
,
01
),
QTime
(
00
,
00
)
);
// Here the same comments as for the creation date are valid.
subkey
->
setExpirationDate
(
epoch
.
secsTo
(
dt
)
);
pos
+=
11
;
// note that there is always a blank after the expire date
}
else
pos
+=
10
;
// optional key capabilities (sign/encrypt only)
if
(
pos
!=
index2
)
{
if
(
!
strncmp
(
output
.
data
()
+
pos
,
"SIGNature only"
,
14
)
)
{
subkey
->
setCanEncrypt
(
false
);
key
->
setCanEncrypt
(
false
);
}
else
if
(
!
strncmp
(
output
.
data
()
+
pos
,
"ENCRyption only"
,
15
)
)
{
subkey
->
setCanSign
(
false
);
key
->
setCanSign
(
false
);
subkey
->
setCanCertify
(
false
);
key
->
setCanCertify
(
false
);
}
}
}
else
{
// line contains an additional user id
// Example:
// Test key (2nd user ID) <abc@xyz>
key
->
addUserID
(
QLatin1String
(
output
.
mid
(
pos
,
index2
-
pos
))
);
}
}
index
=
index2
+
1
;
}
//kDebug( 5326 ) <<"finished parsing key data";
return
key
;
}
void
Base2
::
parseTrustDataForKey
(
Key
*
key
,
const
QByteArray
&
str
)
{
if
(
(
key
==
0
)
||
str
.
isEmpty
()
)
return
;
QByteArray
keyID
=
key
->
primaryKeyID
();
UserIDList
userIDs
=
key
->
userIDs
();
// search the trust data belonging to this key
int
index
=
str
.
indexOf
(
'\n'
)
+
1
;
while
(
(
index
>
0
)
&&
(
strncmp
(
str
.
data
()
+
index
+
2
,
keyID
.
data
(),
8
)
!=
0
)
)
index
=
str
.
indexOf
(
'\n'
,
index
)
+
1
;
if
(
index
==
0
)
return
;
bool
ultimateTrust
=
false
;
if
(
!
strncmp
(
str
.
data
()
+
index
+
11
,
"ultimate"
,
8
)
)
ultimateTrust
=
true
;
bool
firstLine
=
true
;
while
(
true
)
{
// loop over all trust information about this key
int
index2
;
// search the end of the current line
if
(
(
index2
=
str
.
indexOf
(
'\n'
,
index
)
)
==
-1
)
break
;
// check if trust info for the next key starts
if
(
!
firstLine
&&
(
str
[
index
+
2
]
!=
' '
)
)
break
;
if
(
str
[
index
+
21
]
!=
' '
)
{
// line contains a validity value for a user ID
// determine the validity
Validity
validity
=
KPGP_VALIDITY_UNKNOWN
;
if
(
!
strncmp
(
str
.
data
()
+
index
+
21
,
"complete"
,
8
)
)
if
(
ultimateTrust
)
validity
=
KPGP_VALIDITY_ULTIMATE
;
else
validity
=
KPGP_VALIDITY_FULL
;
else
if
(
!
strncmp
(
str
.
data
()
+
index
+
21
,
"marginal"
,
8
)
)
validity
=
KPGP_VALIDITY_MARGINAL
;
else
if
(
!
strncmp
(
str
.
data
()
+
index
+
21
,
"never"
,
5
)
)
validity
=
KPGP_VALIDITY_NEVER
;
else
if
(
!
strncmp
(
str
.
data
()
+
index
+
21
,
"undefined"
,
9
)
)
validity
=
KPGP_VALIDITY_UNDEFINED
;
// determine the user ID
int
pos
=
index
+
31
;
if
(
str
[
index
+
2
]
==
' '
)
pos
++
;
// additional user IDs start one column later
QString
uid
=
QLatin1String
(
str
.
mid
(
pos
,
index2
-
pos
));
// set the validity of the corresponding user ID
for
(
UserIDList
::
Iterator
it
=
userIDs
.
begin
();
it
!=
userIDs
.
end
();
++
it
)
if
(
(
*
it
)
->
text
()
==
uid
)
{
kDebug
(
5326
)
<<
"Setting the validity of"
<<
uid
<<
" to"
<<
validity
;
(
*
it
)
->
setValidity
(
validity
);
break
;
}
}
firstLine
=
false
;
index
=
index2
+
1
;
}
}
KeyList
Base2
::
parseKeyList
(
const
QByteArray
&
output
,
bool
secretKeys
)
{
kDebug
(
5326
)
<<
"Kpgp::Base2::parseKeyList()"
;
KeyList
keys
;
Key
*
key
=
0
;
Subkey
*
subkey
=
0
;
int
index
;
// search start of key data
if
(
!
strncmp
(
output
.
data
(),
"pub"
,
3
)
||
!
strncmp
(
output
.
data
(),
"sec"
,
3
)
)
index
=
0
;
else
{
if
(
secretKeys
)
index
=
output
.
indexOf
(
"
\n
sec"
);
else
index
=
output
.
indexOf
(
"
\n
pub"
);
if
(
index
==
-1
)
return
keys
;
else
index
++
;
}
while
(
true
)
{
int
index2
;
// search the end of the current line
if
(
(
index2
=
output
.
indexOf
(
'\n'
,
index
)
)
==
-1
)
break
;
if
(
!
strncmp
(
output
.
data
()
+
index
,
"pub"
,
3
)
||
!
strncmp
(
output
.
data
()
+
index
,
"sec"
,
3
)
)
{
// line contains primary key data
// Example 1:
// pub 1024/E2D074D3 2001/09/09 Test Key <testkey@xyz>
// Example 2 (disabled key):
// pub- 1024/8CCB2C1B 2001/11/04 Disabled Test Key <disabled@xyz>
// Example 3 (expired key):
// pub> 1024/7B94827D 2001/09/09 Expired Test Key <expired@xyz> (EXPIRE:2001-09-10)
// Example 4 (revoked key):
// pub 1024/956721F9 2001/09/09 *** KEY REVOKED ***
int
pos
,
pos2
;
if
(
key
!=
0
)
// store the previous key in the key list
keys
.
append
(
key
);
key
=
new
Key
();
key
->
setSecret
(
secretKeys
);
// set default key capabilities
key
->
setCanEncrypt
(
true
);
key
->
setCanSign
(
true
);
key
->
setCanCertify
(
true
);
subkey
=
new
Subkey
(
""
,
secretKeys
);
key
->
addSubkey
(
subkey
);
// set default key capabilities
subkey
->
setCanEncrypt
(
true
);
subkey
->
setCanSign
(
true
);
subkey
->
setCanCertify
(
true
);
// expiration date defaults to never
subkey
->
setExpirationDate
(
-1
);
// Key Flags
switch
(
output
[
index
+
3
]
)
{
case
' '
:
// nothing special
break
;
case
'-'
:
// disabled key
subkey
->
setDisabled
(
true
);
key
->
setDisabled
(
true
);
break
;
case
'>'
:
// expired key
subkey
->
setExpired
(
true
);
key
->
setExpired
(
true
);
break
;
default
:
kDebug
(
5326
)
<<
"Unknown key flag."
;
}
// Key Length
pos
=
index
+
4
;
while
(
output
[
pos
]
==
' '
)
pos
++
;
pos2
=
output
.
indexOf
(
'/'
,
pos
);
subkey
->
setKeyLength
(
output
.
mid
(
pos
,
pos2
-
pos
).
toUInt
()
);
// Key ID
pos
=
pos2
+
1
;
pos2
=
output
.
indexOf
(
' '
,
pos
);
subkey
->
setKeyID
(
output
.
mid
(
pos
,
pos2
-
pos
)
);
// Creation Date
pos
=
pos2
+
1
;
while
(
output
[
pos
]
==
' '
)
pos
++
;
pos2
=
output
.
indexOf
(
' '
,
pos
);
int
year
=
output
.
mid
(
pos
,
4
).
toInt
();
int
month
=
output
.
mid
(
pos
+
5
,
2
).
toInt
();
int
day
=
output
.
mid
(
pos
+
8
,
2
).
toInt
();
QDateTime
dt
(
QDate
(
year
,
month
,
day
),
QTime
(
00
,
00
)
);
QDateTime
epoch
(
QDate
(
1970
,
01
,
01
),
QTime
(
00
,
00
)
);
// The calculated creation date isn't exactly correct because QDateTime
// doesn't know anything about timezones and always assumes local time
// although epoch is of course UTC. But as PGP 2 anyway doesn't print
// the time this doesn't matter too much.
subkey
->
setCreationDate
(
epoch
.
secsTo
(
dt
)
);
// User ID
pos
=
pos2
+
1
;
while
(
output
[
pos
]
==
' '
)
pos
++
;
QByteArray
uid
=
output
.
mid
(
pos
,
index2
-
pos
);
if
(
uid
!=
"*** KEY REVOKED ***"
)
key
->
addUserID
(
QLatin1String
(
uid
)
);
else
{
subkey
->
setRevoked
(
true
);
key
->
setRevoked
(
true
);
}
}
else
if
(
output
[
index
]
==
' '
)
{
// line contains additional key data
if
(
key
==
0
)
break
;
int
pos
=
index
+
1
;
while
(
output
[
pos
]
==
' '
)
pos
++
;
if
(
!
strncmp
(
output
.
data
()
+
pos
,
"Key fingerprint = "
,
18
)
)
{
// line contains a fingerprint
// Example:
// Key fingerprint = 47 30 7C 76 05 BF 5E FB 72 41 00 F2 7D 0B D0 49
QByteArray
fingerprint
=
output
.
mid
(
pos
,
index2
-
pos
);
// remove white space from the fingerprint
for
(
int
idx
=
0
;
(
idx
=
fingerprint
.
indexOf
(
' '
,
idx
))
!=
-1
;
)
fingerprint
.
replace
(
idx
,
1
,
""
);
subkey
->
setFingerprint
(
fingerprint
);
}
else
if
(
!
strncmp
(
output
.
data
()
+
pos
,
"Expire: "
,
8
)
||
!
strncmp
(
output
.
data
()
+
pos
,
"no expire "
,
10
)
)
{
// line contains additional key properties
// Examples:
// Expire: 2001/09/10
// no expire ENCRyption only
// no expire SIGNature only
if
(
output
[
pos
]
==
'E'
)
{
// Expiration Date
pos
+=
8
;
int
year
=
output
.
mid
(
pos
,
4
).
toInt
();
int
month
=
output
.
mid
(
pos
+
5
,
2
).
toInt
();
int
day
=
output
.
mid
(
pos
+
8
,
2
).
toInt
();
QDateTime
dt
(
QDate
(
year
,
month
,
day
),
QTime
(
00
,
00
)
);
QDateTime
epoch
(
QDate
(
1970
,
01
,
01
),
QTime
(
00
,
00
)
);
// Here the same comments as for the creation date are valid.
subkey
->
setExpirationDate
(
epoch
.
secsTo
(
dt
)
);
pos
+=
11
;
// note that there is always a blank after the expire date
}
else
pos
+=
10
;
// optional key capabilities (sign/encrypt only)
if
(
pos
!=
index2
)
{
if
(
!
strncmp
(
output
.
data
()
+
pos
,
"SIGNature only"
,
14
)
)
{
subkey
->
setCanEncrypt
(
false
);
key
->
setCanEncrypt
(
false
);
}
else
if
(
!
strncmp
(
output
.
data
()
+
pos
,
"ENCRyption only"
,
15
)
)
{
subkey
->
setCanSign
(
false
);
key
->
setCanSign
(
false
);
subkey
->
setCanCertify
(
false
);
key
->
setCanCertify
(
false
);
}
}
}
else
{
// line contains an additional user id
// Example:
// Test key (2nd user ID) <abc@xyz>
key
->
addUserID
(
QLatin1String
(
output
.
mid
(
pos
,
index2
-
pos
))
);
}
}
index
=
index2
+
1
;
}
if
(
key
!=
0
)
// store the last key in the key list
keys
.
append
(
key
);
//kDebug( 5326 ) <<"finished parsing keys";
return
keys
;
}
}
// namespace Kpgp
File Metadata
Details
Attached
Mime Type
text/x-c++
Expires
Fri, Nov 1, 8:55 AM (1 d, 10 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
10075341
Default Alt Text
kpgpbase2.cpp (31 KB)
Attached To
Mode
rKP kdepim
Attached
Detach File
Event Timeline
Log In to Comment