From 36bac67dd5f19b72a58584f2fab104e6e26df66a Mon Sep 17 00:00:00 2001 From: Tim Bray Date: Tue, 11 Nov 2014 18:45:36 -0800 Subject: All keybase proofs now in place --- .../keychain/service/KeychainIntentService.java | 38 +++++++-- .../service/KeychainIntentServiceHandler.java | 5 ++ .../keychain/ui/ViewKeyTrustFragment.java | 90 ++++++++++++---------- 3 files changed, 89 insertions(+), 44 deletions(-) (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain') diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java index 42e0c7cc9..8a670df25 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java @@ -84,6 +84,12 @@ import java.util.Iterator; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; +import de.measite.minidns.Client; +import de.measite.minidns.Question; +import de.measite.minidns.Record; +import de.measite.minidns.record.Data; +import de.measite.minidns.record.TXT; + /** * This Service contains all important long lasting operations for APG. It receives Intents with * data from the activities or other apps, queues these intents, executes them, and stops itself @@ -124,6 +130,7 @@ public class KeychainIntentService extends IntentService implements Progressable // encrypt, decrypt, import export public static final String TARGET = "target"; public static final String SOURCE = "source"; + // possible targets: public static final int IO_BYTES = 1; public static final int IO_URI = 2; @@ -321,12 +328,27 @@ public class KeychainIntentService extends IntentService implements Progressable return; } + String domain = prover.dnsTxtCheckRequired(); + if (domain != null) { + Record[] records = new Client().query(new Question(domain, Record.TYPE.TXT)).getAnswers(); + List> extents = new ArrayList>(); + for (Record r : records) { + Data d = r.getPayload(); + if (d instanceof TXT) { + extents.add(((TXT) d).getExtents()); + } + } + if (!prover.checkDnsTxt(extents)) { + sendProofError(prover.getLog(), null); + return; + } + } + byte[] messageBytes = prover.getPgpMessage().getBytes(); if (prover.rawMessageCheckRequired()) { InputStream messageByteStream = PGPUtil.getDecoderStream(new ByteArrayInputStream(messageBytes)); - String problem = prover.checkRawMessageBytes(messageByteStream); - if (problem != null) { - sendProofError(prover.getLog(), problem); + if (!prover.checkRawMessageBytes(messageByteStream)) { + sendProofError(prover.getLog(), null); return; } } @@ -365,6 +387,11 @@ public class KeychainIntentService extends IntentService implements Progressable Bundle resultData = new Bundle(); resultData.putString(KeychainIntentServiceHandler.DATA_MESSAGE, "OK"); + + // these help the handler construct a useful human-readable message + resultData.putString(KeychainIntentServiceHandler.KEYBASE_PROOF_URL, prover.getProofUrl()); + resultData.putString(KeychainIntentServiceHandler.KEYBASE_PRESENCE_URL, prover.getPresenceUrl()); + resultData.putString(KeychainIntentServiceHandler.KEYBASE_PRESENCE_LABEL, prover.getPresenceLabel()); sendMessageToHandler(KeychainIntentServiceHandler.MESSAGE_OKAY, resultData); } catch (Exception e) { sendErrorToHandler(e); @@ -678,11 +705,12 @@ public class KeychainIntentService extends IntentService implements Progressable private void sendProofError(List log, String label) { String msg = null; + label = (label == null) ? "" : label + ": "; for (String m : log) { - Log.e(Constants.TAG, label + ": " + m); + Log.e(Constants.TAG, label + m); msg = m; } - sendProofError(label + ": " + msg); + sendProofError(label + msg); } private void sendProofError(String msg) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentServiceHandler.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentServiceHandler.java index 180020d0b..fc65757f5 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentServiceHandler.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentServiceHandler.java @@ -45,6 +45,11 @@ public class KeychainIntentServiceHandler extends Handler { public static final String DATA_MESSAGE = "message"; public static final String DATA_MESSAGE_ID = "message_id"; + // keybase proof specific + public static final String KEYBASE_PROOF_URL = "keybase_proof_url"; + public static final String KEYBASE_PRESENCE_URL = "keybase_presence_url"; + public static final String KEYBASE_PRESENCE_LABEL = "keybase_presence_label"; + Activity mActivity; ProgressDialogFragment mProgressDialogFragment; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyTrustFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyTrustFragment.java index 540dcc0b1..4965b2525 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyTrustFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyTrustFragment.java @@ -324,9 +324,6 @@ public class ViewKeyTrustFragment extends LoaderFragment implements } private void appendIfOK(Hashtable> table, Integer proofType, Proof proof) throws KeybaseException { - if (!proofIsOK(proof)) { - return; - } ArrayList list = table.get(proofType); if (list == null) { list = new ArrayList(); @@ -335,23 +332,16 @@ public class ViewKeyTrustFragment extends LoaderFragment implements list.add(proof); } - // We only accept http & https proofs. Maybe whitelist later? - private boolean proofIsOK(Proof proof) throws KeybaseException { - Uri uri = Uri.parse(proof.getServiceUrl()); - String scheme = uri.getScheme(); - return ("https".equalsIgnoreCase(scheme) || "http".equalsIgnoreCase(scheme)); - } - // which proofs do we have working verifiers for? private boolean haveProofFor(int proofType) { switch (proofType) { case Proof.PROOF_TYPE_TWITTER: return true; case Proof.PROOF_TYPE_GITHUB: return true; - case Proof.PROOF_TYPE_DNS: return false; + case Proof.PROOF_TYPE_DNS: return true; case Proof.PROOF_TYPE_WEB_SITE: return true; case Proof.PROOF_TYPE_HACKERNEWS: return true; - case Proof.PROOF_TYPE_COINBASE: return false; - case Proof.PROOF_TYPE_REDDIT: return false; + case Proof.PROOF_TYPE_COINBASE: return true; + case Proof.PROOF_TYPE_REDDIT: return true; default: return false; } } @@ -381,47 +371,69 @@ public class ViewKeyTrustFragment extends LoaderFragment implements SpannableStringBuilder ssb = new SpannableStringBuilder(); if ((msg != null) && msg.equals("OK")) { + //yay - String serviceUrl, urlLabel, postUrl; - try { - serviceUrl = proof.getServiceUrl(); - if (serviceUrl.startsWith("https://")) { - urlLabel = serviceUrl.substring("https://".length()); - } else if (serviceUrl.startsWith("http://")) { - urlLabel = serviceUrl.substring("http://".length()); - } else { - urlLabel = serviceUrl; - } - postUrl = proof.getHumanUrl(); - - } catch (KeybaseException e) { - throw new RuntimeException(e); + String proofUrl = returnData.getString(KeychainIntentServiceHandler.KEYBASE_PROOF_URL); + String presenceUrl = returnData.getString(KeychainIntentServiceHandler.KEYBASE_PRESENCE_URL); + String presenceLabel = returnData.getString(KeychainIntentServiceHandler.KEYBASE_PRESENCE_LABEL); + + String proofLabel; + switch (proof.getType()) { + case Proof.PROOF_TYPE_TWITTER: + proofLabel = getString(R.string.keybase_twitter_proof); + break; + case Proof.PROOF_TYPE_DNS: + proofLabel = getString(R.string.keybase_dns_proof); + break; + case Proof.PROOF_TYPE_WEB_SITE: + proofLabel = getString(R.string.keybase_web_site_proof); + break; + case Proof.PROOF_TYPE_GITHUB: + proofLabel = getString(R.string.keybase_github_proof); + break; + case Proof.PROOF_TYPE_REDDIT: + proofLabel = getString(R.string.keybase_reddit_proof); + break; + default: + proofLabel = getString(R.string.keybase_a_post); + break; } + ssb.append(getString(R.string.keybase_proof_succeeded)); StyleSpan bold = new StyleSpan(Typeface.BOLD); ssb.setSpan(bold, 0, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); ssb.append("\n\n"); int length = ssb.length(); - String segment = getString(R.string.keybase_a_post); - ssb.append(segment); - URLSpan postLink = new URLSpan(postUrl); - ssb.setSpan(postLink, length, length + segment.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - ssb.append(" ").append(getString(R.string.keybase_fetched_from)).append(" "); - URLSpan serviceLink = new URLSpan(serviceUrl); + ssb.append(proofLabel); + if (proofUrl != null) { + URLSpan postLink = new URLSpan(proofUrl); + ssb.setSpan(postLink, length, length + proofLabel.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + if (Proof.PROOF_TYPE_DNS == proof.getType()) { + ssb.append(" ").append(getString(R.string.keybase_for_the_domain)).append(" "); + } else { + ssb.append(" ").append(getString(R.string.keybase_fetched_from)).append(" "); + } length = ssb.length(); - ssb.append(urlLabel); - ssb.setSpan(serviceLink, length, length + urlLabel.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + URLSpan presenceLink = new URLSpan(presenceUrl); + ssb.append(presenceLabel); + ssb.setSpan(presenceLink, length, length + presenceLabel.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + if (Proof.PROOF_TYPE_REDDIT == proof.getType()) { + ssb.append(", "). + append(getString(R.string.keybase_reddit_attribution)). + append(" “").append(proof.getHandle()).append("”, "); + } ssb.append(" ").append(getString(R.string.keybase_contained_signature)); - } else { + // verification failed! msg = returnData.getString(KeychainIntentServiceHandler.DATA_ERROR); ssb.append(getString(R.string.keybase_proof_failure)); if (msg == null) { msg = getString(R.string.keybase_unknown_proof_failure); - StyleSpan bold = new StyleSpan(Typeface.BOLD); - ssb.setSpan(bold, 0, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); - ssb.append("\n\n").append(msg); } + StyleSpan bold = new StyleSpan(Typeface.BOLD); + ssb.setSpan(bold, 0, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + ssb.append("\n\n").append(msg); } mProofVerifyHeader.setVisibility(View.VISIBLE); mProofVerifyDetail.setVisibility(View.VISIBLE); -- cgit v1.2.3