diff options
Diffstat (limited to 'src/main/java/eu')
8 files changed, 109 insertions, 95 deletions
diff --git a/src/main/java/eu/siacs/conversations/crypto/OtrService.java b/src/main/java/eu/siacs/conversations/crypto/OtrService.java index af11756f..3663cd3b 100644 --- a/src/main/java/eu/siacs/conversations/crypto/OtrService.java +++ b/src/main/java/eu/siacs/conversations/crypto/OtrService.java @@ -53,28 +53,30 @@ public class OtrService extends OtrCryptoEngineImpl implements OtrEngineHost { this.mXmppConnectionService = service; } - private KeyPair loadKey(JSONObject keys) { + private KeyPair loadKey(final JSONObject keys) { if (keys == null) { return null; } - try { - BigInteger x = new BigInteger(keys.getString("otr_x"), 16); - BigInteger y = new BigInteger(keys.getString("otr_y"), 16); - BigInteger p = new BigInteger(keys.getString("otr_p"), 16); - BigInteger q = new BigInteger(keys.getString("otr_q"), 16); - BigInteger g = new BigInteger(keys.getString("otr_g"), 16); - KeyFactory keyFactory = KeyFactory.getInstance("DSA"); - DSAPublicKeySpec pubKeySpec = new DSAPublicKeySpec(y, p, q, g); - DSAPrivateKeySpec privateKeySpec = new DSAPrivateKeySpec(x, p, q, g); - PublicKey publicKey = keyFactory.generatePublic(pubKeySpec); - PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec); - return new KeyPair(publicKey, privateKey); - } catch (JSONException e) { - return null; - } catch (NoSuchAlgorithmException e) { - return null; - } catch (InvalidKeySpecException e) { - return null; + synchronized (keys) { + try { + BigInteger x = new BigInteger(keys.getString("otr_x"), 16); + BigInteger y = new BigInteger(keys.getString("otr_y"), 16); + BigInteger p = new BigInteger(keys.getString("otr_p"), 16); + BigInteger q = new BigInteger(keys.getString("otr_q"), 16); + BigInteger g = new BigInteger(keys.getString("otr_g"), 16); + KeyFactory keyFactory = KeyFactory.getInstance("DSA"); + DSAPublicKeySpec pubKeySpec = new DSAPublicKeySpec(y, p, q, g); + DSAPrivateKeySpec privateKeySpec = new DSAPrivateKeySpec(x, p, q, g); + PublicKey publicKey = keyFactory.generatePublic(pubKeySpec); + PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec); + return new KeyPair(publicKey, privateKey); + } catch (JSONException e) { + return null; + } catch (NoSuchAlgorithmException e) { + return null; + } catch (InvalidKeySpecException e) { + return null; + } } } diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java index 9218e524..7d60dcf7 100644 --- a/src/main/java/eu/siacs/conversations/entities/Account.java +++ b/src/main/java/eu/siacs/conversations/entities/Account.java @@ -203,7 +203,7 @@ public class Account extends AbstractEntity { protected int options = 0; protected String rosterVersion; protected State status = State.OFFLINE; - protected JSONObject keys = new JSONObject(); + protected final JSONObject keys; protected String avatar; protected String displayName = null; protected String hostname = null; @@ -238,11 +238,13 @@ public class Account extends AbstractEntity { this.password = password; this.options = options; this.rosterVersion = rosterVersion; + JSONObject tmp; try { - this.keys = new JSONObject(keys); - } catch (final JSONException ignored) { - this.keys = new JSONObject(); + tmp = new JSONObject(keys); + } catch(JSONException e) { + tmp = new JSONObject(); } + this.keys = tmp; this.avatar = avatar; this.displayName = displayName; this.hostname = hostname; @@ -391,15 +393,28 @@ public class Account extends AbstractEntity { } public String getKey(final String name) { - return this.keys.optString(name, null); + synchronized (this.keys) { + return this.keys.optString(name, null); + } } - public boolean setKey(final String keyName, final String keyValue) { + public int getKeyAsInt(final String name, int defaultValue) { + String key = getKey(name); try { - this.keys.put(keyName, keyValue); - return true; - } catch (final JSONException e) { - return false; + return key == null ? defaultValue : Integer.parseInt(key); + } catch (NumberFormatException e) { + return defaultValue; + } + } + + public boolean setKey(final String keyName, final String keyValue) { + synchronized (this.keys) { + try { + this.keys.put(keyName, keyValue); + return true; + } catch (final JSONException e) { + return false; + } } } @@ -419,7 +434,9 @@ public class Account extends AbstractEntity { values.put(SERVER, jid.getDomainpart()); values.put(PASSWORD, password); values.put(OPTIONS, options); - values.put(KEYS, this.keys.toString()); + synchronized (this.keys) { + values.put(KEYS, this.keys.toString()); + } values.put(ROSTERVERSION, rosterVersion); values.put(AVATAR, avatar); values.put(DISPLAY_NAME, displayName); @@ -496,54 +513,42 @@ public class Account extends AbstractEntity { } public String getPgpSignature() { - try { - if (keys.has(KEY_PGP_SIGNATURE) && !"null".equals(keys.getString(KEY_PGP_SIGNATURE))) { - return keys.getString(KEY_PGP_SIGNATURE); - } else { - return null; - } - } catch (final JSONException e) { - return null; - } + return getKey(KEY_PGP_SIGNATURE); } public boolean setPgpSignature(String signature) { - try { - keys.put(KEY_PGP_SIGNATURE, signature); - } catch (JSONException e) { - return false; - } - return true; + return setKey(KEY_PGP_SIGNATURE, signature); } public boolean unsetPgpSignature() { - try { - keys.put(KEY_PGP_SIGNATURE, JSONObject.NULL); - } catch (JSONException e) { - return false; + synchronized (this.keys) { + return keys.remove(KEY_PGP_SIGNATURE) != null; } - return true; } public long getPgpId() { - if (keys.has(KEY_PGP_ID)) { - try { - return keys.getLong(KEY_PGP_ID); - } catch (JSONException e) { + synchronized (this.keys) { + if (keys.has(KEY_PGP_ID)) { + try { + return keys.getLong(KEY_PGP_ID); + } catch (JSONException e) { + return 0; + } + } else { return 0; } - } else { - return 0; } } public boolean setPgpSignId(long pgpID) { - try { - keys.put(KEY_PGP_ID, pgpID); - } catch (JSONException e) { - return false; + synchronized (this.keys) { + try { + keys.put(KEY_PGP_ID, pgpID); + } catch (JSONException e) { + return false; + } + return true; } - return true; } public Roster getRoster() { diff --git a/src/main/java/eu/siacs/conversations/entities/MucOptions.java b/src/main/java/eu/siacs/conversations/entities/MucOptions.java index 9d54a86d..fa6afcfa 100644 --- a/src/main/java/eu/siacs/conversations/entities/MucOptions.java +++ b/src/main/java/eu/siacs/conversations/entities/MucOptions.java @@ -127,7 +127,6 @@ public class MucOptions { UNKNOWN } - public static final String STATUS_CODE_ROOM_CONFIG_CHANGED = "104"; public static final String STATUS_CODE_SELF_PRESENCE = "110"; public static final String STATUS_CODE_ROOM_CREATED = "201"; public static final String STATUS_CODE_BANNED = "301"; diff --git a/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java b/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java index 5ef47a33..f5c701cc 100644 --- a/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java +++ b/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java @@ -183,6 +183,10 @@ public class MessageGenerator extends AbstractGenerator { packet.setFrom(conversation.getAccount().getJid()); Element x = packet.addChild("x", "jabber:x:conference"); x.setAttribute("jid", conversation.getJid().toBareJid().toString()); + String password = conversation.getMucOptions().getPassword(); + if (password != null) { + x.setAttribute("password",password); + } return packet; } diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java index b4553012..81b68ed9 100644 --- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java +++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java @@ -587,26 +587,27 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece } } if (conversation != null && mucUserElement != null && from.isBareJid()) { - if (mucUserElement.hasChild("status")) { - for (Element child : mucUserElement.getChildren()) { - if (child.getName().equals("status") - && MucOptions.STATUS_CODE_ROOM_CONFIG_CHANGED.equals(child.getAttribute("code"))) { - mXmppConnectionService.fetchConferenceConfiguration(conversation); - } - } - } else if (mucUserElement.hasChild("item")) { - for(Element child : mucUserElement.getChildren()) { - if ("item".equals(child.getName())) { - MucOptions.User user = AbstractParser.parseItem(conversation,child); - Log.d(Config.LOGTAG,account.getJid()+": changing affiliation for " - +user.getRealJid()+" to "+user.getAffiliation()+" in " - +conversation.getJid().toBareJid()); - if (!user.realJidMatchesAccount()) { - conversation.getMucOptions().addUser(user); - mXmppConnectionService.getAvatarService().clear(conversation); - mXmppConnectionService.updateMucRosterUi(); - mXmppConnectionService.updateConversationUi(); + for (Element child : mucUserElement.getChildren()) { + if ("status".equals(child.getName())) { + try { + int code = Integer.parseInt(child.getAttribute("code")); + if ((code >= 170 && code <= 174) || (code >= 102 && code <= 104)) { + mXmppConnectionService.fetchConferenceConfiguration(conversation); + break; } + } catch (Exception e) { + //ignored + } + } else if ("item".equals(child.getName())) { + MucOptions.User user = AbstractParser.parseItem(conversation,child); + Log.d(Config.LOGTAG,account.getJid()+": changing affiliation for " + +user.getRealJid()+" to "+user.getAffiliation()+" in " + +conversation.getJid().toBareJid()); + if (!user.realJidMatchesAccount()) { + conversation.getMucOptions().addUser(user); + mXmppConnectionService.getAvatarService().clear(conversation); + mXmppConnectionService.updateMucRosterUi(); + mXmppConnectionService.updateConversationUi(); } } } diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index f6298ea2..5650b894 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -1135,7 +1135,8 @@ public class XmppConnectionService extends Service { } if (packet != null) { - if (account.getXmppConnection().getFeatures().sm() || conversation.getMode() == Conversation.MODE_MULTI) { + if (account.getXmppConnection().getFeatures().sm() + || (conversation.getMode() == Conversation.MODE_MULTI && message.getCounterpart().isBareJid())) { message.setStatus(Message.STATUS_UNSEND); } else { message.setStatus(Message.STATUS_SEND); @@ -1177,7 +1178,8 @@ public class XmppConnectionService extends Service { if (resend) { if (packet != null && addToConversation) { - if (account.getXmppConnection().getFeatures().sm() || conversation.getMode() == Conversation.MODE_MULTI) { + if (account.getXmppConnection().getFeatures().sm() + || (conversation.getMode() == Conversation.MODE_MULTI && message.getCounterpart().isBareJid())) { markMessage(message, Message.STATUS_UNSEND); } else { markMessage(message, Message.STATUS_SEND); diff --git a/src/main/java/eu/siacs/conversations/ui/WelcomeActivity.java b/src/main/java/eu/siacs/conversations/ui/WelcomeActivity.java index 3c837b94..59d58db5 100644 --- a/src/main/java/eu/siacs/conversations/ui/WelcomeActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/WelcomeActivity.java @@ -1,5 +1,6 @@ package eu.siacs.conversations.ui; +import android.app.ActionBar; import android.app.Activity; import android.content.Intent; import android.content.pm.ActivityInfo; @@ -16,6 +17,11 @@ public class WelcomeActivity extends Activity { if (getResources().getBoolean(R.bool.portrait_only)) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } + final ActionBar ab = getActionBar(); + if (ab != null) { + ab.setDisplayShowHomeEnabled(false); + ab.setDisplayHomeAsUpEnabled(false); + } super.onCreate(savedInstanceState); setContentView(R.layout.welcome); final Button createAccount = (Button) findViewById(R.id.create_account); diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java index ab92535a..383e990d 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -852,18 +852,13 @@ public class XmppConnection implements Runnable { saslMechanism = new Anonymous(tagWriter, account, mXmppConnectionService.getRNG()); } if (saslMechanism != null) { - final JSONObject keys = account.getKeys(); - try { - if (keys.has(Account.PINNED_MECHANISM_KEY) && - keys.getInt(Account.PINNED_MECHANISM_KEY) > saslMechanism.getPriority()) { - Log.e(Config.LOGTAG, "Auth failed. Authentication mechanism " + saslMechanism.getMechanism() + - " has lower priority (" + String.valueOf(saslMechanism.getPriority()) + - ") than pinned priority (" + keys.getInt(Account.PINNED_MECHANISM_KEY) + - "). Possible downgrade attack?"); - throw new SecurityException(); - } - } catch (final JSONException e) { - Log.d(Config.LOGTAG, "Parse error while checking pinned auth mechanism"); + final int pinnedMechanism = account.getKeyAsInt(Account.PINNED_MECHANISM_KEY, -1); + if (pinnedMechanism > saslMechanism.getPriority()) { + Log.e(Config.LOGTAG, "Auth failed. Authentication mechanism " + saslMechanism.getMechanism() + + " has lower priority (" + String.valueOf(saslMechanism.getPriority()) + + ") than pinned priority (" + pinnedMechanism + + "). Possible downgrade attack?"); + throw new SecurityException(); } Log.d(Config.LOGTAG, account.getJid().toString() + ": Authenticating with " + saslMechanism.getMechanism()); auth.setAttribute("mechanism", saslMechanism.getMechanism()); |