diff options
author | Vincent Breitmoser <valodim@mugenguild.com> | 2014-06-06 16:15:27 +0200 |
---|---|---|
committer | Vincent Breitmoser <valodim@mugenguild.com> | 2014-06-06 16:15:27 +0200 |
commit | 787f6edf3260056030025388b921e9d6ce996d92 (patch) | |
tree | 53b3e86e0fac8363c683fcb567d3f89f343c9ec9 /OpenKeychain/src | |
parent | b995b836a38ef8a87aa189f408f8542bf5a2c94c (diff) | |
download | open-keychain-787f6edf3260056030025388b921e9d6ce996d92.tar.gz open-keychain-787f6edf3260056030025388b921e9d6ce996d92.tar.bz2 open-keychain-787f6edf3260056030025388b921e9d6ce996d92.zip |
import-log: add log statements in import routine
Diffstat (limited to 'OpenKeychain/src')
2 files changed, 225 insertions, 97 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/OperationResultParcel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/OperationResultParcel.java index f2da4389d..8110590b1 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/OperationResultParcel.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/OperationResultParcel.java @@ -88,9 +88,43 @@ public class OperationResultParcel implements Parcelable { } public static enum LogType { - // TODO add actual log entry types here - MSG_IMPORT_OK (R.string.copy), - MSG_IMPORT_FAILED (R.string.cancel); + MSG_IP_APPLY_BATCH (R.string.msg_ip_apply_batch), + MSG_IP_BAD_TYPE_SECRET (R.string.msg_ip_bad_type_secret), + MSG_IP_DELETE_OLD_FAIL (R.string.msg_ip_delete_old_fail), + MSG_IP_DELETE_OLD_OK (R.string.msg_ip_delete_old_ok), + MSG_IP_ENCODE_FAIL (R.string.msg_ip_encode_fail), + MSG_IP_FAIL_IO_EXC (R.string.msg_ip_fail_io_exc), + MSG_IP_FAIL_OP_EX (R.string.msg_ip_fail_op_ex), + MSG_IP_FAIL_REMOTE_EX (R.string.msg_ip_fail_remote_ex), + MSG_IP_IMPORTING (R.string.msg_ip_importing), + MSG_IP_INSERT_KEYRING (R.string.msg_ip_insert_keyring), + MSG_IP_INSERT_SUBKEY (R.string.msg_ip_insert_subkey), + MSG_IP_INSERT_SUBKEYS (R.string.msg_ip_insert_subkeys), + MSG_IP_PRESERVING_SECRET (R.string.msg_ip_preserving_secret), + MSG_IP_REINSERT_SECRET (R.string.msg_ip_reinsert_secret), + MSG_IP_SUCCESS (R.string.msg_ip_success), + MSG_IP_TRUST_RETRIEVE (R.string.msg_ip_trust_retrieve), + MSG_IP_TRUST_USING (R.string.msg_ip_trust_using), + MSG_IP_TRUST_USING_SEC (R.string.msg_ip_trust_using_sec), + MSG_IP_UID_CERT_BAD (R.string.msg_ip_uid_cert_bad), + MSG_IP_UID_CERT_ERROR (R.string.msg_ip_uid_cert_error), + MSG_IP_UID_CERT_GOOD (R.string.msg_ip_uid_cert_good), + MSG_IP_UID_CERTS_UNKNOWN (R.string.msg_ip_uid_certs_unknown), + MSG_IP_UID_CLASSIFYING (R.string.msg_ip_uid_classifying), + MSG_IP_UID_INSERT (R.string.msg_ip_uid_insert), + MSG_IP_UID_PROCESSING (R.string.msg_ip_uid_processing), + MSG_IP_UID_SELF_BAD (R.string.msg_ip_uid_self_bad), + MSG_IP_UID_SELF_GOOD (R.string.msg_ip_uid_self_good), + MSG_IP_UID_SELF_IGNORING_OLD (R.string.msg_ip_uid_self_ignoring_old), + MSG_IP_UID_SELF_NEWER (R.string.msg_ip_uid_self_newer), + MSG_IS_BAD_TYPE_PUBLIC (R.string.msg_is_bad_type_public), + MSG_IS_IMPORTING (R.string.msg_is_importing), + MSG_IS_IMPORTING_SUBKEYS (R.string.msg_is_importing_subkeys), + MSG_IS_IO_EXCPTION (R.string.msg_is_io_excption), + MSG_IS_SUBKEY_NONEXISTENT (R.string.msg_is_subkey_nonexistent), + MSG_IS_SUBKEY_OK (R.string.msg_is_subkey_ok), + MSG_IS_SUCCESS (R.string.msg_is_success), + ; private int mMsgId; LogType(int msgId) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java index 83b55cc14..170fc4df2 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/ProviderHelper.java @@ -241,136 +241,208 @@ public class ProviderHelper { * Saves PGPPublicKeyRing with its keys and userIds in DB */ @SuppressWarnings("unchecked") - public void savePublicKeyRing(UncachedKeyRing keyRing) throws IOException { + public OperationResultParcel savePublicKeyRing(UncachedKeyRing keyRing) { if (keyRing.isSecret()) { - throw new RuntimeException("Tried to save secret keyring as public! " + - "This is a bug, please file a bug report."); + log(LogLevel.ERROR, LogType.MSG_IP_BAD_TYPE_SECRET); + return new OperationResultParcel(1, mLog); } UncachedPublicKey masterKey = keyRing.getPublicKey(); long masterKeyId = masterKey.getKeyId(); + log(LogLevel.INFO, LogType.MSG_IP_IMPORTING, + new String[]{Long.toString(masterKeyId)}); // IF there is a secret key, preserve it! - UncachedKeyRing secretRing = null; + UncachedKeyRing secretRing; try { secretRing = getWrappedSecretKeyRing(masterKeyId).getUncached(); + log(LogLevel.DEBUG, LogType.MSG_IP_PRESERVING_SECRET); } catch (NotFoundException e) { - Log.e(Constants.TAG, "key not found!"); + secretRing = null; } // delete old version of this keyRing, which also deletes all keys and userIds on cascade try { mContentResolver.delete(KeyRingData.buildPublicKeyRingUri(Long.toString(masterKeyId)), null, null); + log(LogLevel.DEBUG, LogType.MSG_IP_DELETE_OLD_OK); } catch (UnsupportedOperationException e) { Log.e(Constants.TAG, "Key could not be deleted! Maybe we are creating a new one!", e); + log(LogLevel.DEBUG, LogType.MSG_IP_DELETE_OLD_FAIL); } // insert new version of this keyRing ContentValues values = new ContentValues(); values.put(KeyRingData.MASTER_KEY_ID, masterKeyId); - values.put(KeyRingData.KEY_RING_DATA, keyRing.getEncoded()); - Uri uri = KeyRingData.buildPublicKeyRingUri(Long.toString(masterKeyId)); - mContentResolver.insert(uri, values); + try { + values.put(KeyRingData.KEY_RING_DATA, keyRing.getEncoded()); + } catch (IOException e) { + log(LogLevel.ERROR, LogType.MSG_IP_ENCODE_FAIL); + return new OperationResultParcel(1, mLog); + } // save all keys and userIds included in keyRing object in database ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(); - int rank = 0; - for (UncachedPublicKey key : new IterableIterator<UncachedPublicKey>(keyRing.getPublicKeys())) { - operations.add(buildPublicKeyOperations(masterKeyId, key, rank)); - ++rank; - } + try { - // get a list of owned secret keys, for verification filtering - LongSparseArray<UncachedPublicKey> allKeyRings = - getUncachedMasterKeys(KeyRingData.buildSecretKeyRingUri()); - // special case: available secret keys verify themselves! - if (secretRing != null) { - allKeyRings.put(secretRing.getMasterKeyId(), secretRing.getPublicKey()); - } + log(LogLevel.INFO, LogType.MSG_IP_INSERT_KEYRING); + Uri uri = KeyRingData.buildPublicKeyRingUri(Long.toString(masterKeyId)); + operations.add(ContentProviderOperation.newInsert(uri).withValues(values).build()); - // classify and order user ids. primary are moved to the front, revoked to the back, - // otherwise the order in the keyfile is preserved. - List<UserIdItem> uids = new ArrayList<UserIdItem>(); - - for (String userId : new IterableIterator<String>( - masterKey.getUnorderedUserIds().iterator())) { - UserIdItem item = new UserIdItem(); - uids.add(item); - item.userId = userId; - - // look through signatures for this specific key - for (WrappedSignature cert : new IterableIterator<WrappedSignature>( - masterKey.getSignaturesForId(userId))) { - long certId = cert.getKeyId(); - try { - // self signature - if (certId == masterKeyId) { - cert.init(masterKey); - if (!cert.verifySignature(masterKey, userId)) { - // not verified?! dang! TODO notify user? this is kinda serious... - Log.e(Constants.TAG, "Could not verify self signature for " + userId + "!"); - continue; - } - // is this the first, or a more recent certificate? - if (item.selfCert == null || - item.selfCert.getCreationTime().before(cert.getCreationTime())) { + log(LogLevel.INFO, LogType.MSG_IP_INSERT_SUBKEYS); + mIndent += 1; + int rank = 0; + for (UncachedPublicKey key : new IterableIterator<UncachedPublicKey>(keyRing.getPublicKeys())) { + log(LogLevel.DEBUG, LogType.MSG_IP_INSERT_SUBKEY, new String[] { + PgpKeyHelper.convertKeyIdToHex(masterKeyId) + }); + operations.add(buildPublicKeyOperations(masterKeyId, key, rank)); + ++rank; + } + mIndent -= 1; + + log(LogLevel.DEBUG, LogType.MSG_IP_TRUST_RETRIEVE); + // get a list of owned secret keys, for verification filtering + LongSparseArray<UncachedPublicKey> trustedKeys = + getUncachedMasterKeys(KeyRingData.buildSecretKeyRingUri()); + // special case: available secret keys verify themselves! + if (secretRing != null) { + trustedKeys.put(secretRing.getMasterKeyId(), secretRing.getPublicKey()); + log(LogLevel.INFO, LogType.MSG_IP_TRUST_USING_SEC, new String[]{ + Integer.toString(trustedKeys.size()) + }); + } else { + log(LogLevel.INFO, LogType.MSG_IP_TRUST_USING, new String[] { + Integer.toString(trustedKeys.size()) + }); + } + + // classify and order user ids. primary are moved to the front, revoked to the back, + // otherwise the order in the keyfile is preserved. + log(LogLevel.DEBUG, LogType.MSG_IP_UID_CLASSIFYING); + mIndent += 1; + List<UserIdItem> uids = new ArrayList<UserIdItem>(); + for (String userId : new IterableIterator<String>( + masterKey.getUnorderedUserIds().iterator())) { + UserIdItem item = new UserIdItem(); + uids.add(item); + item.userId = userId; + + int unknownCerts = 0; + + log(LogLevel.INFO, LogType.MSG_IP_UID_PROCESSING, new String[] { userId }); + mIndent += 1; + // look through signatures for this specific key + for (WrappedSignature cert : new IterableIterator<WrappedSignature>( + masterKey.getSignaturesForId(userId))) { + long certId = cert.getKeyId(); + try { + // self signature + if (certId == masterKeyId) { + cert.init(masterKey); + if (!cert.verifySignature(masterKey, userId)) { + // Bad self certification? That's kinda bad... + log(LogLevel.ERROR, LogType.MSG_IP_UID_SELF_BAD); + return new OperationResultParcel(1, mLog); + } + + // if we already have a cert.. + if (item.selfCert != null) { + // ..is this perchance a more recent one? + if (item.selfCert.getCreationTime().before(cert.getCreationTime())) { + log(LogLevel.DEBUG, LogType.MSG_IP_UID_SELF_NEWER); + } else { + log(LogLevel.DEBUG, LogType.MSG_IP_UID_SELF_IGNORING_OLD); + continue; + } + } else { + log(LogLevel.DEBUG, LogType.MSG_IP_UID_SELF_GOOD); + } + + // save certificate as primary self-cert item.selfCert = cert; item.isPrimary = cert.isPrimaryUserId(); item.isRevoked = cert.isRevocation(); + } - } - // verify signatures from known private keys - if (allKeyRings.indexOfKey(certId) >= 0) { - cert.init(allKeyRings.get(certId)); - if (cert.verifySignature(masterKey, userId)) { - item.trustedCerts.add(cert); + + // verify signatures from known private keys + if (trustedKeys.indexOfKey(certId) >= 0) { + UncachedPublicKey trustedKey = trustedKeys.get(certId); + cert.init(trustedKey); + if (cert.verifySignature(masterKey, userId)) { + item.trustedCerts.add(cert); + log(LogLevel.INFO, LogType.MSG_IP_UID_CERT_GOOD, new String[] { + PgpKeyHelper.convertKeyIdToHex(trustedKey.getKeyId()) + }); + } else { + log(LogLevel.WARN, LogType.MSG_IP_UID_CERT_BAD); + } } + + unknownCerts += 1; + + } catch (PgpGeneralException e) { + log(LogLevel.WARN, LogType.MSG_IP_UID_CERT_ERROR, new String[]{ + PgpKeyHelper.convertKeyIdToHex(cert.getKeyId()) + }); } - } catch (PgpGeneralException e) { - Log.e(Constants.TAG, "Signature verification failed! " - + PgpKeyHelper.convertKeyIdToHex(masterKey.getKeyId()) - + " from " - + PgpKeyHelper.convertKeyIdToHex(cert.getKeyId()), e); } - } - } + mIndent -= 1; + + if (unknownCerts > 0) { + log(LogLevel.DEBUG, LogType.MSG_IP_UID_CERTS_UNKNOWN, new String[] { + Integer.toString(unknownCerts) + }); + } - // primary before regular before revoked (see UserIdItem.compareTo) - // this is a stable sort, so the order of keys is otherwise preserved. - Collections.sort(uids); - // iterate and put into db - for (int userIdRank = 0; userIdRank < uids.size(); userIdRank++) { - UserIdItem item = uids.get(userIdRank); - operations.add(buildUserIdOperations(masterKeyId, item, userIdRank)); - // no self cert is bad, but allowed by the rfc... - if (item.selfCert != null) { - operations.add(buildCertOperations( - masterKeyId, userIdRank, item.selfCert, Certs.VERIFIED_SELF)); - } - // don't bother with trusted certs if the uid is revoked, anyways - if (item.isRevoked) { - continue; } - for (int i = 0; i < item.trustedCerts.size(); i++) { - operations.add(buildCertOperations( - masterKeyId, userIdRank, item.trustedCerts.get(i), Certs.VERIFIED_SECRET)); + mIndent -= 1; + + log(LogLevel.INFO, LogType.MSG_IP_UID_INSERT); + // primary before regular before revoked (see UserIdItem.compareTo) + // this is a stable sort, so the order of keys is otherwise preserved. + Collections.sort(uids); + // iterate and put into db + for (int userIdRank = 0; userIdRank < uids.size(); userIdRank++) { + UserIdItem item = uids.get(userIdRank); + operations.add(buildUserIdOperations(masterKeyId, item, userIdRank)); + // no self cert is bad, but allowed by the rfc... + if (item.selfCert != null) { + operations.add(buildCertOperations( + masterKeyId, userIdRank, item.selfCert, Certs.VERIFIED_SELF)); + } + // don't bother with trusted certs if the uid is revoked, anyways + if (item.isRevoked) { + continue; + } + for (int i = 0; i < item.trustedCerts.size(); i++) { + operations.add(buildCertOperations( + masterKeyId, userIdRank, item.trustedCerts.get(i), Certs.VERIFIED_SECRET)); + } } - } - try { + log(LogLevel.DEBUG, LogType.MSG_IP_APPLY_BATCH); mContentResolver.applyBatch(KeychainContract.CONTENT_AUTHORITY, operations); + } catch (IOException e) { + log(LogLevel.ERROR, LogType.MSG_IP_FAIL_IO_EXC); } catch (RemoteException e) { - Log.e(Constants.TAG, "applyBatch failed!", e); + log(LogLevel.ERROR, LogType.MSG_IP_FAIL_REMOTE_EX); } catch (OperationApplicationException e) { - Log.e(Constants.TAG, "applyBatch failed!", e); + log(LogLevel.ERROR, LogType.MSG_IP_FAIL_OP_EX); } // Save the saved keyring (if any) if (secretRing != null) { + log(LogLevel.DEBUG, LogType.MSG_IP_REINSERT_SECRET); + mIndent += 1; saveSecretKeyRing(secretRing); + mIndent -= 1; } + log(LogLevel.INFO, LogType.MSG_IP_SUCCESS); + return new OperationResultParcel(0, mLog); + } private static class UserIdItem implements Comparable<UserIdItem> { @@ -398,13 +470,29 @@ public class ProviderHelper { * Saves a PGPSecretKeyRing in the DB. This will only work if a corresponding public keyring * is already in the database! */ - public void saveSecretKeyRing(UncachedKeyRing keyRing) throws IOException { + public OperationResultParcel saveSecretKeyRing(UncachedKeyRing keyRing) { if (!keyRing.isSecret()) { - throw new RuntimeException("Tried to save publkc keyring as secret! " + - "This is a bug, please file a bug report."); + log(LogLevel.ERROR, LogType.MSG_IS_BAD_TYPE_PUBLIC); + return new OperationResultParcel(1, mLog); } long masterKeyId = keyRing.getMasterKeyId(); + log(LogLevel.INFO, LogType.MSG_IS_IMPORTING, + new String[]{ Long.toString(masterKeyId) }); + + // save secret keyring + try { + ContentValues values = new ContentValues(); + values.put(KeyRingData.MASTER_KEY_ID, masterKeyId); + values.put(KeyRingData.KEY_RING_DATA, keyRing.getEncoded()); + // insert new version of this keyRing + Uri uri = KeyRingData.buildSecretKeyRingUri(Long.toString(masterKeyId)); + mContentResolver.insert(uri, values); + } catch (IOException e) { + Log.e(Constants.TAG, "Failed to encode key!", e); + log(LogLevel.ERROR, LogType.MSG_IS_IO_EXCPTION); + return new OperationResultParcel(1, mLog); + } { Uri uri = Keys.buildKeysUri(Long.toString(masterKeyId)); @@ -416,24 +504,30 @@ public class ProviderHelper { values.put(Keys.HAS_SECRET, 1); // then, mark exactly the keys we have available + log(LogLevel.INFO, LogType.MSG_IS_IMPORTING_SUBKEYS); + mIndent += 1; for (Long sub : new IterableIterator<Long>(keyRing.getAvailableSubkeys().iterator())) { - mContentResolver.update(uri, values, Keys.KEY_ID + " = ?", new String[] { + int upd = mContentResolver.update(uri, values, Keys.KEY_ID + " = ?", new String[] { Long.toString(sub) }); + if(upd == 0) { + log(LogLevel.DEBUG, LogType.MSG_IS_SUBKEY_OK, new String[] { + PgpKeyHelper.convertKeyIdToHex(sub) + }); + } else { + log(LogLevel.WARN, LogType.MSG_IS_SUBKEY_NONEXISTENT, new String[] { + PgpKeyHelper.convertKeyIdToHex(sub) + }); + } } + mIndent -= 1; + // this implicitly leaves all keys which were not in the secret key ring // with has_secret = 0 } - // save secret keyring - { - ContentValues values = new ContentValues(); - values.put(KeyRingData.MASTER_KEY_ID, masterKeyId); - values.put(KeyRingData.KEY_RING_DATA, keyRing.getEncoded()); - // insert new version of this keyRing - Uri uri = KeyRingData.buildSecretKeyRingUri(Long.toString(masterKeyId)); - mContentResolver.insert(uri, values); - } + log(LogLevel.INFO, LogType.MSG_IS_SUCCESS); + return new OperationResultParcel(0, mLog); } |