# HG changeset patch # User Da Risk # Date 1452249078 -3600 # Node ID 137d0bf0e959b6d0589191dce388f28383d99f64 # Parent af8866eba015b87755ae1b0d06d1dc08944a8ef8 Fix some checkstyle issues diff -r af8866eba015 -r 137d0bf0e959 app/src/main/java/com/beem/project/beem/BeemApplication.java --- a/app/src/main/java/com/beem/project/beem/BeemApplication.java Thu Jan 07 16:38:16 2016 +0100 +++ b/app/src/main/java/com/beem/project/beem/BeemApplication.java Fri Jan 08 11:31:18 2016 +0100 @@ -154,7 +154,7 @@ String login = mSettings.getString(BeemApplication.ACCOUNT_USERNAME_KEY, ""); String password = mSettings.getString(BeemApplication.ACCOUNT_PASSWORD_KEY, ""); boolean useSystemAccount = mSettings.getBoolean(BeemApplication.USE_SYSTEM_ACCOUNT_KEY, false); - mIsAccountConfigured = !TextUtils.isEmpty(login) && (useSystemAccount || !TextUtils.isEmpty((password))); + mIsAccountConfigured = !TextUtils.isEmpty(login) && (useSystemAccount || !TextUtils.isEmpty(password)); mSettings.registerOnSharedPreferenceChangeListener(mPreferenceListener); SmileyParser.init(this); } @@ -220,11 +220,12 @@ @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { - if (BeemApplication.ACCOUNT_USERNAME_KEY.equals(key) || BeemApplication.ACCOUNT_PASSWORD_KEY.equals(key) || BeemApplication.USE_SYSTEM_ACCOUNT_KEY.equals(key)) { + if (BeemApplication.ACCOUNT_USERNAME_KEY.equals(key) || BeemApplication.ACCOUNT_PASSWORD_KEY.equals(key) + || BeemApplication.USE_SYSTEM_ACCOUNT_KEY.equals(key)) { String login = mSettings.getString(BeemApplication.ACCOUNT_USERNAME_KEY, ""); String password = mSettings.getString(BeemApplication.ACCOUNT_PASSWORD_KEY, ""); boolean useSystemAccount = mSettings.getBoolean(BeemApplication.USE_SYSTEM_ACCOUNT_KEY, false); - mIsAccountConfigured = !TextUtils.isEmpty(login) && (useSystemAccount || !TextUtils.isEmpty((password))); + mIsAccountConfigured = !TextUtils.isEmpty(login) && (useSystemAccount || !TextUtils.isEmpty(password)); } } } diff -r af8866eba015 -r 137d0bf0e959 app/src/main/java/com/beem/project/beem/BeemService.java --- a/app/src/main/java/com/beem/project/beem/BeemService.java Thu Jan 07 16:38:16 2016 +0100 +++ b/app/src/main/java/com/beem/project/beem/BeemService.java Fri Jan 08 11:31:18 2016 +0100 @@ -152,7 +152,7 @@ */ private void initConnectionConfig() { // TODO add an option for this ? -// SmackConfiguration.setPacketReplyTimeout(30000); + // SmackConfiguration.setPacketReplyTimeout(30000); ProxyInfo proxyInfo = getProxyConfiguration(); boolean useSystemAccount = mSettings.getBoolean(BeemApplication.USE_SYSTEM_ACCOUNT_KEY, false); if (useSystemAccount) { @@ -172,8 +172,8 @@ mConnectionConfiguration = new ConnectionConfiguration(mHost, mPort, mService, proxyInfo); else mConnectionConfiguration = new ConnectionConfiguration(mService, proxyInfo); - PreferenceAuthenticator authenticator = createPreferenceAuthenticator(); - mConnectionConfiguration.setCallbackHandler(authenticator); + PreferenceAuthenticator authenticator = createPreferenceAuthenticator(); + mConnectionConfiguration.setCallbackHandler(authenticator); } if (mSettings.getBoolean("settings_key_xmpp_tls_use", false) @@ -191,13 +191,19 @@ mConnectionConfiguration.setCustomSSLContext(sslContext); } - private PreferenceAuthenticator createPreferenceAuthenticator() { - if (!mSettings.getBoolean(BeemApplication.ACCOUNT_PASSWORD_IS_ENCRYPTED_KEY, false)) { - return new PreferenceAuthenticator(this); - } - String base64Iv = mSettings.getString(BeemApplication.ACCOUNT_PASSWORD_ENCRYPTION_IV_KEY, ""); - return new EncryptedPasswordPreferenceAuthenticator(this, BeemApplication.PASSWORD_ENCRYPTION_KEY_ALIAS, base64Iv); + /** + * Create the correct preference authenticator (clear or crypted). + * + * @return the PreferenceAuthenticator + */ + private PreferenceAuthenticator createPreferenceAuthenticator() { + if (!mSettings.getBoolean(BeemApplication.ACCOUNT_PASSWORD_IS_ENCRYPTED_KEY, false)) { + return new PreferenceAuthenticator(this); } + String base64Iv = mSettings.getString(BeemApplication.ACCOUNT_PASSWORD_ENCRYPTION_IV_KEY, ""); + return new EncryptedPasswordPreferenceAuthenticator(this, + BeemApplication.PASSWORD_ENCRYPTION_KEY_ALIAS, base64Iv); + } /** * Get the save proxy configuration. diff -r af8866eba015 -r 137d0bf0e959 app/src/main/java/com/beem/project/beem/service/XmppConnectionAdapter.java --- a/app/src/main/java/com/beem/project/beem/service/XmppConnectionAdapter.java Thu Jan 07 16:38:16 2016 +0100 +++ b/app/src/main/java/com/beem/project/beem/service/XmppConnectionAdapter.java Fri Jan 08 11:31:18 2016 +0100 @@ -54,7 +54,6 @@ import android.os.RemoteCallbackList; import android.os.RemoteException; import android.support.v4.app.NotificationCompat; -import android.support.v4.app.NotificationManagerCompat; import android.util.Log; import com.beem.project.beem.BeemApplication; @@ -372,13 +371,13 @@ private void updateNotification(int status, String text) { NotificationCompat.Builder builder = new NotificationCompat.Builder(mService); Notification mStatusNotification = builder.setSmallIcon(Status.getIconBarFromStatus(status)) - .setContentText(text) - .setContentTitle("Beem Status") - .setDefaults(NotificationCompat.DEFAULT_LIGHTS) - .setWhen(System.currentTimeMillis()) - .setOngoing(true) - .setContentIntent(PendingIntent.getActivity(mService, 0, new Intent(mService, ChangeStatus.class), 0)) - .build(); + .setContentText(text) + .setContentTitle("Beem Status") + .setDefaults(NotificationCompat.DEFAULT_LIGHTS) + .setWhen(System.currentTimeMillis()) + .setOngoing(true) + .setContentIntent(PendingIntent.getActivity(mService, 0, new Intent(mService, ChangeStatus.class), 0)) + .build(); // bypass the preferences for notification mService.getNotificationManager().notify(BeemService.NOTIFICATION_STATUS_ID, mStatusNotification); diff -r af8866eba015 -r 137d0bf0e959 app/src/main/java/com/beem/project/beem/service/auth/EncryptedPasswordPreferenceAuthenticator.java --- a/app/src/main/java/com/beem/project/beem/service/auth/EncryptedPasswordPreferenceAuthenticator.java Thu Jan 07 16:38:16 2016 +0100 +++ b/app/src/main/java/com/beem/project/beem/service/auth/EncryptedPasswordPreferenceAuthenticator.java Fri Jan 08 11:31:18 2016 +0100 @@ -1,11 +1,39 @@ +/* + BEEM is a videoconference application on the Android Platform. + + Copyright (C) 2009-2012 by Frederic-Charles Barthelery, + Nikita Kozlov, + Vincent Veronis. + + This file is part of BEEM. + + BEEM 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 3 of the License, or + (at your option) any later version. + + BEEM 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with BEEM. If not, see . + + Please send bug reports with examples or suggestions to + contact@beem-project.com or http://www.beem-project.com/ + +*/ package com.beem.project.beem.service.auth; import android.content.Context; + import com.beem.project.beem.utils.EncryptionManager; + import org.jivesoftware.smack.util.Base64; /** - * Created by darisk on 07/01/16. + * An Authenticator which look for credentials stored in preferences and decrypt them. */ public class EncryptedPasswordPreferenceAuthenticator extends PreferenceAuthenticator { private final String encryptionKeyAlias; @@ -16,6 +44,8 @@ * Create a PreferenceAuthenticator. * * @param context the Android context. + * @param encryptionKeyAlias the alias of the encryption key in the Android keystore + * @param base64Iv the encryption IV encoded in base64 */ public EncryptedPasswordPreferenceAuthenticator(Context context, String encryptionKeyAlias, String base64Iv) { super(context); diff -r af8866eba015 -r 137d0bf0e959 app/src/main/java/com/beem/project/beem/service/auth/PreferenceAuthenticator.java --- a/app/src/main/java/com/beem/project/beem/service/auth/PreferenceAuthenticator.java Thu Jan 07 16:38:16 2016 +0100 +++ b/app/src/main/java/com/beem/project/beem/service/auth/PreferenceAuthenticator.java Fri Jan 08 11:31:18 2016 +0100 @@ -55,7 +55,7 @@ */ public PreferenceAuthenticator(final Context context) { settings = PreferenceManager.getDefaultSharedPreferences(context); - } + } @Override public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { @@ -89,9 +89,14 @@ } } - protected String getPassword() { - String password = settings.getString(BeemApplication.ACCOUNT_PASSWORD_KEY, ""); - return password; - } + /** + * Returns the password stored. + * + * @return the password + */ + protected String getPassword() { + String password = settings.getString(BeemApplication.ACCOUNT_PASSWORD_KEY, ""); + return password; + } } diff -r af8866eba015 -r 137d0bf0e959 app/src/main/java/com/beem/project/beem/ui/wizard/AccountConfigureFragment.java --- a/app/src/main/java/com/beem/project/beem/ui/wizard/AccountConfigureFragment.java Thu Jan 07 16:38:16 2016 +0100 +++ b/app/src/main/java/com/beem/project/beem/ui/wizard/AccountConfigureFragment.java Fri Jan 08 11:31:18 2016 +0100 @@ -85,8 +85,6 @@ import org.jivesoftware.smack.util.Base64; import org.jivesoftware.smack.util.StringUtils; -import static com.beem.project.beem.BeemApplication.PASSWORD_ENCRYPTION_KEY_ALIAS; - /** * Fragment to enter the information required in order to configure a XMPP account. * @@ -114,7 +112,7 @@ private String mSelectedAccountType; private SharedPreferences settings; private boolean useSystemAccount; - private EncryptionManager encryptionManager; + private EncryptionManager encryptionManager; private com.beem.project.beem.ui.wizard.AccountConfigureFragment.ConnectionTestTask task; @@ -133,9 +131,9 @@ Log.d(TAG, "onCreate"); setRetainInstance(true); - settings = PreferenceManager.getDefaultSharedPreferences(getActivity()); - encryptionManager = new EncryptionManager(); - } + settings = PreferenceManager.getDefaultSharedPreferences(getActivity()); + encryptionManager = new EncryptionManager(); + } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -208,17 +206,17 @@ } else if (v == mManualConfigButton) { onManualConfigurationSelected(); } else if (v == mSelectAccountButton) { - Intent i = null; - if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) { - i = AccountManager.newChooseAccountIntent(null, null, - new String[]{GOOGLE_ACCOUNT_TYPE}, - null, null, null, null); - } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { - i = AccountManager.newChooseAccountIntent(null, null, - new String[]{GOOGLE_ACCOUNT_TYPE}, - true, null, null, null, null); - } - startActivityForResult(i, SELECT_ACCOUNT_CODE); + Intent i = null; + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) { + i = AccountManager.newChooseAccountIntent(null, null, + new String[]{GOOGLE_ACCOUNT_TYPE}, + null, null, null, null); + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + i = AccountManager.newChooseAccountIntent(null, null, + new String[]{GOOGLE_ACCOUNT_TYPE}, + true, null, null, null, null); + } + startActivityForResult(i, SELECT_ACCOUNT_CODE); } } @@ -299,24 +297,24 @@ * */ private void saveCredential(String jid, String pass) { - SharedPreferences.Editor edit = settings.edit(); - String encryptedPass = pass; - boolean isEncryptedPass = false; - if (encryptionManager.isEncryptionAvailable()) { - if (!encryptionManager.hasEncryptionKey(PASSWORD_ENCRYPTION_KEY_ALIAS)) { - encryptionManager.generateEncryptionKey(PASSWORD_ENCRYPTION_KEY_ALIAS); - } - encryptedPass = encryptionManager.encryptString(encryptedPass, PASSWORD_ENCRYPTION_KEY_ALIAS); - if (encryptedPass != null) { - String encryptionIV = Base64.encodeBytes(encryptionManager.getLatestEncryptionIv()); - edit.putString(BeemApplication.ACCOUNT_PASSWORD_ENCRYPTION_IV_KEY, encryptionIV); - isEncryptedPass = true; - } - } + SharedPreferences.Editor edit = settings.edit(); + String encryptedPass = pass; + boolean isEncryptedPass = false; + if (encryptionManager.isEncryptionAvailable()) { + if (!encryptionManager.hasEncryptionKey(BeemApplication.PASSWORD_ENCRYPTION_KEY_ALIAS)) { + encryptionManager.generateEncryptionKey(BeemApplication.PASSWORD_ENCRYPTION_KEY_ALIAS); + } + encryptedPass = encryptionManager.encryptString(encryptedPass, + BeemApplication.PASSWORD_ENCRYPTION_KEY_ALIAS); + if (encryptedPass != null) { + String encryptionIV = Base64.encodeBytes(encryptionManager.getLatestEncryptionIv()); + edit.putString(BeemApplication.ACCOUNT_PASSWORD_ENCRYPTION_IV_KEY, encryptionIV); + isEncryptedPass = true; + } + } edit.putString(BeemApplication.ACCOUNT_USERNAME_KEY, jid); edit.putString(BeemApplication.ACCOUNT_PASSWORD_KEY, encryptedPass); - - edit.putBoolean(BeemApplication.ACCOUNT_PASSWORD_IS_ENCRYPTED_KEY, isEncryptedPass); + edit.putBoolean(BeemApplication.ACCOUNT_PASSWORD_IS_ENCRYPTED_KEY, isEncryptedPass); edit.putBoolean(BeemApplication.USE_SYSTEM_ACCOUNT_KEY, false); edit.commit(); } diff -r af8866eba015 -r 137d0bf0e959 app/src/main/java/com/beem/project/beem/utils/EncryptionManager.java --- a/app/src/main/java/com/beem/project/beem/utils/EncryptionManager.java Thu Jan 07 16:38:16 2016 +0100 +++ b/app/src/main/java/com/beem/project/beem/utils/EncryptionManager.java Fri Jan 08 11:31:18 2016 +0100 @@ -1,13 +1,35 @@ +/* + BEEM is a videoconference application on the Android Platform. + + Copyright (C) 2009-2012 by Frederic-Charles Barthelery, + Nikita Kozlov, + Vincent Veronis. + + This file is part of BEEM. + + BEEM 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 3 of the License, or + (at your option) any later version. + + BEEM 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with BEEM. If not, see . + + Please send bug reports with examples or suggestions to + contact@beem-project.com or http://www.beem-project.com/ + +*/ package com.beem.project.beem.utils; -import android.annotation.TargetApi; -import android.os.Build; -import android.security.keystore.KeyGenParameterSpec; -import android.security.keystore.KeyProperties; +import static com.google.android.apps.iosched.util.LogUtils.LOGD; +import static com.google.android.apps.iosched.util.LogUtils.LOGW; +import static com.google.android.apps.iosched.util.LogUtils.makeLogTag; -import com.google.android.apps.iosched.util.LogUtils; - -import org.jivesoftware.smack.util.Base64; import java.io.IOException; import java.security.GeneralSecurityException; @@ -24,12 +46,19 @@ import javax.crypto.NoSuchPaddingException; import javax.crypto.spec.IvParameterSpec; -import static com.google.android.apps.iosched.util.LogUtils.LOGD; -import static com.google.android.apps.iosched.util.LogUtils.LOGW; +import android.annotation.TargetApi; +import android.os.Build; +import android.security.keystore.KeyGenParameterSpec; +import android.security.keystore.KeyProperties; +import org.jivesoftware.smack.util.Base64; + +/** + * Allows to encrypt and decrypt some strings using the Android Keystore. + */ public class EncryptionManager { - private static final String TAG = LogUtils.makeLogTag(EncryptionManager.class); + private static final String TAG = makeLogTag(EncryptionManager.class); private static final String ANDROID_KEY_STORE = "AndroidKeyStore"; private static final String CIPHER_TRANSFORMATION = String.format("%s/%s/%s", KeyProperties.KEY_ALGORITHM_AES, KeyProperties.BLOCK_MODE_CBC, @@ -40,8 +69,10 @@ private Cipher aesCipher; private byte[] latestEncryptionIv; + /** + * Create an EncryptionManager. + */ public EncryptionManager() { - try { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { keystore = KeyStore.getInstance(ANDROID_KEY_STORE); @@ -52,16 +83,28 @@ } else { isEncryptionAvailable = false; } - } catch (NoSuchPaddingException | KeyStoreException | IOException | NoSuchProviderException | NoSuchAlgorithmException | CertificateException e) { + } catch (NoSuchPaddingException | KeyStoreException | IOException + | NoSuchProviderException | NoSuchAlgorithmException | CertificateException e) { LOGW(TAG, "Unable to load AndroidKeyStore", e); isEncryptionAvailable = false; } } + /** + * Test if the device supports encryption. + * + * @return true if encryption is available, false otherwise + */ public boolean isEncryptionAvailable() { return isEncryptionAvailable; } + /** + * Test if there is an encryption key stored with the alias. + * + * @param alias the alias to test for + * @return true if a key is available, false otherwise + */ public boolean hasEncryptionKey(String alias) { if (!isEncryptionAvailable) { return false; @@ -74,24 +117,38 @@ } } + /** + * Generate a random encryption key and store it in the keystore under alias. + * + * @param alias the alias use to retrieve the key + * @return true if the key was generate, false otherwise + */ @TargetApi(Build.VERSION_CODES.M) public boolean generateEncryptionKey(String alias) { - if (!isEncryptionAvailable) - return false; - KeyGenParameterSpec spec = new KeyGenParameterSpec.Builder(alias, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) - .setBlockModes(KeyProperties.BLOCK_MODE_CBC) - .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7) - .setUserAuthenticationRequired(false) - .build(); - try { - keyGenerator.init(spec); - return keyGenerator.generateKey() != null; - } catch (InvalidAlgorithmParameterException e) { - LOGW(TAG, "Unable to generate key", e); - return false; - } + if (!isEncryptionAvailable) + return false; + KeyGenParameterSpec spec = new KeyGenParameterSpec.Builder(alias, + KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) + .setBlockModes(KeyProperties.BLOCK_MODE_CBC) + .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7) + .setUserAuthenticationRequired(false) + .build(); + try { + keyGenerator.init(spec); + return keyGenerator.generateKey() != null; + } catch (InvalidAlgorithmParameterException e) { + LOGW(TAG, "Unable to generate key", e); + return false; + } } + /** + * Encrypt a string with the key stored with keyAlias. + * + * @param cleartext the clear text to encrypt + * @param keyAlias the alias of the key to use + * @return the encrypted string + */ public String encryptString(String cleartext, String keyAlias) { if (!isEncryptionAvailable()) return null; @@ -107,16 +164,29 @@ } } + /** + * Get the encryption IV used with the latest encryption operation. + * + * @return the encryption IV or null if no encryption operation has been done + */ public byte[] getLatestEncryptionIv() { return latestEncryptionIv; } - public String decryptString(String password, String keyAlias, byte[] encryptionIv) { + /** + * Decrypt an encrypted text using the key stored with alias keyAlias and the specified encryption IV. + * + * @param encryptedText the encrypted text to decrypt + * @param keyAlias the alias of the key to use + * @param encryptionIv the encryption IV + * @return the clear text + */ + public String decryptString(String encryptedText, String keyAlias, byte[] encryptionIv) { if (!isEncryptionAvailable()) return null; try { Key key = keystore.getKey(keyAlias, null); - byte[] passwordByte = Base64.decode(password); + byte[] passwordByte = Base64.decode(encryptedText); aesCipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(encryptionIv)); byte[] clear = aesCipher.doFinal(passwordByte); return new String(clear);