From 49c3e1f02c139182ac4ec9264dc27453b2078ac1 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Mon, 21 Jul 2014 10:26:51 +0200 Subject: [PATCH] Use ha1 instead of plain text passwords by default but still use plain text password for legacy support --- res/values/non_localizable_custom.xml | 1 + .../linphone/AccountPreferencesFragment.java | 8 ++++- src/org/linphone/LinphonePreferences.java | 19 +++++++++++- src/org/linphone/LinphoneUtils.java | 30 ++++++++++++++++++- src/org/linphone/setup/SetupActivity.java | 9 ++++-- 5 files changed, 62 insertions(+), 5 deletions(-) diff --git a/res/values/non_localizable_custom.xml b/res/values/non_localizable_custom.xml index 64a4cff87..c8ae1603a 100644 --- a/res/values/non_localizable_custom.xml +++ b/res/values/non_localizable_custom.xml @@ -70,6 +70,7 @@ false false true + true false diff --git a/src/org/linphone/AccountPreferencesFragment.java b/src/org/linphone/AccountPreferencesFragment.java index ab6ff788f..ba0116912 100644 --- a/src/org/linphone/AccountPreferencesFragment.java +++ b/src/org/linphone/AccountPreferencesFragment.java @@ -82,7 +82,13 @@ public class AccountPreferencesFragment extends PreferencesListFragment { OnPreferenceChangeListener passwordChangedListener = new OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newValue) { - mPrefs.setAccountPassword(n, newValue.toString()); + if (getResources().getBoolean(R.bool.store_ha1_passwords) + && mPrefs.getAccountPassword(n) == null) { + String ha1 = LinphoneUtils.md5Hash(mPrefs.getAccountUsername(n), newValue.toString(), mPrefs.getAccountDomain(n)); + mPrefs.setAccountHa1(n, ha1); + } else { + mPrefs.setAccountPassword(n, newValue.toString()); + } return true; } }; diff --git a/src/org/linphone/LinphonePreferences.java b/src/org/linphone/LinphonePreferences.java index dbd4444af..8de15246e 100644 --- a/src/org/linphone/LinphonePreferences.java +++ b/src/org/linphone/LinphonePreferences.java @@ -166,6 +166,7 @@ public class LinphonePreferences { private String tempDisplayName; private String tempUserId; private String tempPassword; + private String tempHa1; private String tempDomain; private String tempProxy; private boolean tempOutboundProxy; @@ -205,6 +206,11 @@ public class LinphonePreferences { return this; } + public AccountBuilder setHa1(String ha1) { + tempHa1 = ha1; + return this; + } + public AccountBuilder setDomain(String domain) { tempDomain = domain; return this; @@ -316,7 +322,7 @@ public class LinphonePreferences { prxCfg.setQualityReportingCollector(tempQualityReportingCollector); prxCfg.setQualityReportingInterval(tempQualityReportingInterval); - LinphoneAuthInfo authInfo = LinphoneCoreFactory.instance().createAuthInfo(tempUsername, tempUserId, tempPassword, null, null, tempDomain); + LinphoneAuthInfo authInfo = LinphoneCoreFactory.instance().createAuthInfo(tempUsername, tempUserId, tempPassword, tempHa1, null, tempDomain); lc.addProxyConfig(prxCfg); lc.addAuthInfo(authInfo); @@ -467,6 +473,17 @@ public class LinphonePreferences { LinphoneAuthInfo authInfo = getAuthInfo(n); return authInfo == null ? null : authInfo.getPassword(); } + + public void setAccountHa1(int n, String ha1) { + LinphoneAuthInfo info = getClonedAuthInfo(n); + info.setHa1(ha1); + saveAuthInfo(info); + } + + public String getAccountHa1(int n) { + LinphoneAuthInfo authInfo = getAuthInfo(n); + return authInfo == null ? null : authInfo.getHa1(); + } public void setAccountDomain(int n, String domain) { String identity = "sip:" + getAccountUsername(n) + "@" + domain; diff --git a/src/org/linphone/LinphoneUtils.java b/src/org/linphone/LinphoneUtils.java index 108625276..0cdf4794a 100644 --- a/src/org/linphone/LinphoneUtils.java +++ b/src/org/linphone/LinphoneUtils.java @@ -23,13 +23,14 @@ import static android.view.View.VISIBLE; import java.io.BufferedOutputStream; import java.io.BufferedReader; -import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.MalformedURLException; import java.net.URL; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -403,5 +404,32 @@ public final class LinphoneUtils { e.printStackTrace(); } } + + public static String md5Hash(String username, String password, String domain) { + String passwordToHash = username + ":" + domain + ":" + password; + + byte messageDigest[] = null; + try { + MessageDigest digest; + digest = java.security.MessageDigest.getInstance("MD5"); + digest.update(passwordToHash.getBytes()); + messageDigest = digest.digest(); + + StringBuffer hexString = new StringBuffer(); + for (int i = 0; i < messageDigest.length; i++) { + String h = Integer.toHexString(0xFF & messageDigest[i]); + while (h.length() < 2) { + h = "0" + h; + } + hexString.append(h); + } + String hash = hexString.toString(); + return hash; + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } + + return null; + } } diff --git a/src/org/linphone/setup/SetupActivity.java b/src/org/linphone/setup/SetupActivity.java index ec18e8ceb..93aa4ab8a 100644 --- a/src/org/linphone/setup/SetupActivity.java +++ b/src/org/linphone/setup/SetupActivity.java @@ -19,6 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ import org.linphone.LinphoneManager; import org.linphone.LinphonePreferences; +import org.linphone.LinphoneUtils; import org.linphone.LinphonePreferences.AccountBuilder; import org.linphone.LinphoneSimpleListener.LinphoneOnRegistrationStateChangedListener; import org.linphone.R; @@ -292,8 +293,12 @@ public class SetupActivity extends FragmentActivity implements OnClickListener { boolean useLinphoneDotOrgCustomPorts = getResources().getBoolean(R.bool.use_linphone_server_ports); AccountBuilder builder = new AccountBuilder(LinphoneManager.getLc()) .setUsername(username) - .setDomain(domain) - .setPassword(password); + .setDomain(domain); + if (getResources().getBoolean(R.bool.store_ha1_passwords)) { + builder = builder.setHa1(LinphoneUtils.md5Hash(username, password, domain)); + } else { + builder = builder.setPassword(password); + } if (isMainAccountLinphoneDotOrg && useLinphoneDotOrgCustomPorts) { if (getResources().getBoolean(R.bool.disable_all_security_features_for_markets)) {