From d98f6c6ba51ae8810bd2d035fa89f6ca24eba8fd Mon Sep 17 00:00:00 2001 From: Arne Schwabe Date: Mon, 16 Mar 2015 12:55:41 +0100 Subject: Update/cleanup of external API, allow adding of non user editable profiles --HG-- rename : remoteExample/src/main/assets/hd.conf => remoteExample/src/main/assets/test.conf --- .../de/blinkt/openvpn/api/IOpenVPNAPIService.aidl | 13 +++- .../main/java/de/blinkt/openvpn/VpnProfile.java | 2 +- .../blinkt/openvpn/activities/VPNPreferences.java | 19 ++--- .../java/de/blinkt/openvpn/api/APIVpnProfile.java | 84 +++++++++++----------- .../blinkt/openvpn/api/ExternalOpenVPNService.java | 50 +++++++------ .../de/blinkt/openvpn/core/ProfileManager.java | 8 +-- .../de/blinkt/openvpn/fragments/FaqFragment.java | 13 ++-- .../blinkt/openvpn/fragments/Settings_Basic.java | 20 ++---- .../openvpn/fragments/Settings_Connections.java | 12 +--- .../openvpn/fragments/Settings_Fragment.java | 35 +++++++++ .../openvpn/fragments/Settings_UserEditable.java | 49 +++++++++++++ main/src/main/res/layout/settings_usereditable.xml | 21 ++++++ main/src/main/res/values/strings.xml | 1 + 13 files changed, 218 insertions(+), 109 deletions(-) create mode 100644 main/src/main/java/de/blinkt/openvpn/fragments/Settings_Fragment.java create mode 100644 main/src/main/java/de/blinkt/openvpn/fragments/Settings_UserEditable.java create mode 100644 main/src/main/res/layout/settings_usereditable.xml (limited to 'main') diff --git a/main/src/main/aidl/de/blinkt/openvpn/api/IOpenVPNAPIService.aidl b/main/src/main/aidl/de/blinkt/openvpn/api/IOpenVPNAPIService.aidl index d0791a4a..273a0046 100644 --- a/main/src/main/aidl/de/blinkt/openvpn/api/IOpenVPNAPIService.aidl +++ b/main/src/main/aidl/de/blinkt/openvpn/api/IOpenVPNAPIService.aidl @@ -12,10 +12,14 @@ interface IOpenVPNAPIService { void startProfile (String profileUUID); - /** Use a profile with all certificates etc. embedded */ + /** Use a profile with all certificates etc. embedded, + * old version which does not return the UUID of the addded profile, see + * below for a version that return the UUID on add */ boolean addVPNProfile (String name, String config); - /** start a profile using an config */ + /** start a profile using a config as inline string. Make sure that all needed data is inlined, + * e.g., using ... or ... + * See the OpenVPN manual page for more on inlining files */ void startVPN (String inlineconfig); /** This permission framework is used to avoid confused deputy style attack to the VPN @@ -55,5 +59,8 @@ interface IOpenVPNAPIService { * Before calling this function you should make sure OpenVPN for Android may actually * this function by checking if prepareVPNService returns null; */ boolean protectSocket(in ParcelFileDescriptor fd); - + + + /** Use a profile with all certificates etc. embedded */ + APIVpnProfile addNewVPNProfile (String name, boolean userEditable, String config); } \ No newline at end of file diff --git a/main/src/main/java/de/blinkt/openvpn/VpnProfile.java b/main/src/main/java/de/blinkt/openvpn/VpnProfile.java index 73e095ad..058e8097 100644 --- a/main/src/main/java/de/blinkt/openvpn/VpnProfile.java +++ b/main/src/main/java/de/blinkt/openvpn/VpnProfile.java @@ -152,7 +152,7 @@ public class VpnProfile implements Serializable, Cloneable { public boolean mRemoteRandom=false; public HashSet mAllowedAppsVpn = new HashSet(); public boolean mAllowedAppsVpnAreDisallowed = true; - + public String mProfileCreator; /* Options no long used in new profiles */ public String mServerName = "openvpn.blinkt.de"; diff --git a/main/src/main/java/de/blinkt/openvpn/activities/VPNPreferences.java b/main/src/main/java/de/blinkt/openvpn/activities/VPNPreferences.java index f56a2d48..d81968a2 100644 --- a/main/src/main/java/de/blinkt/openvpn/activities/VPNPreferences.java +++ b/main/src/main/java/de/blinkt/openvpn/activities/VPNPreferences.java @@ -28,6 +28,7 @@ import de.blinkt.openvpn.fragments.Settings_Connections; import de.blinkt.openvpn.fragments.Settings_IP; import de.blinkt.openvpn.fragments.Settings_Obscure; import de.blinkt.openvpn.fragments.Settings_Routing; +import de.blinkt.openvpn.fragments.Settings_UserEditable; import de.blinkt.openvpn.fragments.ShowConfigFragment; import de.blinkt.openvpn.fragments.VPNProfileList; import de.blinkt.openvpn.views.ScreenSlidePagerAdapter; @@ -134,21 +135,23 @@ public class VPNPreferences extends Activity { fragmentArguments.putString(getPackageName() + ".profileUUID",mProfileUUID); mPagerAdapter.setFragmentArgs(fragmentArguments); - mPagerAdapter.addTab(R.string.basic, Settings_Basic.class); - mPagerAdapter.addTab(R.string.server_list, Settings_Connections.class); - mPagerAdapter.addTab(R.string.ipdns, Settings_IP.class); - mPagerAdapter.addTab(R.string.routing, Settings_Routing.class); - mPagerAdapter.addTab(R.string.settings_auth, Settings_Authentication.class); + if (mProfile.mUserEditable) { + mPagerAdapter.addTab(R.string.basic, Settings_Basic.class); + mPagerAdapter.addTab(R.string.server_list, Settings_Connections.class); + mPagerAdapter.addTab(R.string.ipdns, Settings_IP.class); + mPagerAdapter.addTab(R.string.routing, Settings_Routing.class); + mPagerAdapter.addTab(R.string.settings_auth, Settings_Authentication.class); - mPagerAdapter.addTab(R.string.advanced, Settings_Obscure.class); + mPagerAdapter.addTab(R.string.advanced, Settings_Obscure.class); + } else { + mPagerAdapter.addTab(R.string.basic, Settings_UserEditable.class); + } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) mPagerAdapter.addTab(R.string.vpn_allowed_apps, Settings_Allowed_Apps.class); mPagerAdapter.addTab(R.string.generated_config, ShowConfigFragment.class); - - mPager.setAdapter(mPagerAdapter); TabBarView tabs = (TabBarView) findViewById(R.id.sliding_tabs); diff --git a/main/src/main/java/de/blinkt/openvpn/api/APIVpnProfile.java b/main/src/main/java/de/blinkt/openvpn/api/APIVpnProfile.java index 7637f57f..fe96c668 100644 --- a/main/src/main/java/de/blinkt/openvpn/api/APIVpnProfile.java +++ b/main/src/main/java/de/blinkt/openvpn/api/APIVpnProfile.java @@ -10,47 +10,51 @@ import android.os.Parcelable; public class APIVpnProfile implements Parcelable { - public final String mUUID; - public final String mName; - public final boolean mUserEditable; - - public APIVpnProfile(Parcel in) { - mUUID = in.readString(); - mName = in.readString(); + public final String mUUID; + public final String mName; + public final boolean mUserEditable; + public final String mProfileCreator; + + public APIVpnProfile(Parcel in) { + mUUID = in.readString(); + mName = in.readString(); mUserEditable = in.readInt() != 0; - } - - public APIVpnProfile(String uuidString, String name, boolean userEditable) { - mUUID=uuidString; - mName = name; - mUserEditable=userEditable; - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeString(mUUID); - dest.writeString(mName); - if(mUserEditable) - dest.writeInt(0); - else - dest.writeInt(1); - } - - public static final Parcelable.Creator CREATOR - = new Parcelable.Creator() { - public APIVpnProfile createFromParcel(Parcel in) { - return new APIVpnProfile(in); - } - - public APIVpnProfile[] newArray(int size) { - return new APIVpnProfile[size]; - } - }; + mProfileCreator = in.readString(); + } + + public APIVpnProfile(String uuidString, String name, boolean userEditable, String profileCreator) { + mUUID = uuidString; + mName = name; + mUserEditable = userEditable; + mProfileCreator = profileCreator; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(mUUID); + dest.writeString(mName); + if (mUserEditable) + dest.writeInt(0); + else + dest.writeInt(1); + dest.writeString(mProfileCreator); + } + + public static final Parcelable.Creator CREATOR + = new Parcelable.Creator() { + public APIVpnProfile createFromParcel(Parcel in) { + return new APIVpnProfile(in); + } + + public APIVpnProfile[] newArray(int size) { + return new APIVpnProfile[size]; + } + }; } diff --git a/main/src/main/java/de/blinkt/openvpn/api/ExternalOpenVPNService.java b/main/src/main/java/de/blinkt/openvpn/api/ExternalOpenVPNService.java index 27143781..eae31b17 100644 --- a/main/src/main/java/de/blinkt/openvpn/api/ExternalOpenVPNService.java +++ b/main/src/main/java/de/blinkt/openvpn/api/ExternalOpenVPNService.java @@ -48,7 +48,7 @@ public class ExternalOpenVPNService extends Service implements StateListener { private static final int SEND_TOALL = 0; final RemoteCallbackList mCallbacks = - new RemoteCallbackList(); + new RemoteCallbackList<>(); private OpenVPNService mService; private ExternalAppDatabase mExtAppDb; @@ -87,19 +87,19 @@ public class ExternalOpenVPNService extends Service implements StateListener { private final IOpenVPNAPIService.Stub mBinder = new IOpenVPNAPIService.Stub() { - private void checkOpenVPNPermission() throws SecurityRemoteException { + private String checkOpenVPNPermission() throws SecurityRemoteException { PackageManager pm = getPackageManager(); - for (String apppackage : mExtAppDb.getExtAppList()) { + for (String appPackage : mExtAppDb.getExtAppList()) { ApplicationInfo app; try { - app = pm.getApplicationInfo(apppackage, 0); + app = pm.getApplicationInfo(appPackage, 0); if (Binder.getCallingUid() == app.uid) { - return; + return appPackage; } } catch (NameNotFoundException e) { // App not found. Remove it from the list - mExtAppDb.removeApp(apppackage); + mExtAppDb.removeApp(appPackage); } } @@ -112,11 +112,11 @@ public class ExternalOpenVPNService extends Service implements StateListener { ProfileManager pm = ProfileManager.getInstance(getBaseContext()); - List profiles = new LinkedList(); + List profiles = new LinkedList<>(); for (VpnProfile vp : pm.getProfiles()) { if (!vp.profileDeleted) - profiles.add(new APIVpnProfile(vp.getUUIDString(), vp.mName, vp.mUserEditable)); + profiles.add(new APIVpnProfile(vp.getUUIDString(), vp.mName, vp.mUserEditable, vp.mProfileCreator)); } return profiles; @@ -155,12 +155,12 @@ public class ExternalOpenVPNService extends Service implements StateListener { startProfile(vp); } - public void startVPN(String inlineconfig) throws RemoteException { + public void startVPN(String inlineConfig) throws RemoteException { checkOpenVPNPermission(); ConfigParser cp = new ConfigParser(); try { - cp.parseConfig(new StringReader(inlineconfig)); + cp.parseConfig(new StringReader(inlineConfig)); VpnProfile vp = cp.convertProfile(); if (vp.checkProfile(getApplicationContext()) != R.string.no_error_found) throw new RemoteException(getString(vp.checkProfile(getApplicationContext()))); @@ -173,35 +173,41 @@ public class ExternalOpenVPNService extends Service implements StateListener { ProfileManager.setTemporaryProfile(vp); startProfile(vp); - } catch (IOException e) { - throw new RemoteException(e.getMessage()); - } catch (ConfigParseError e) { + } catch (IOException | ConfigParseError e) { throw new RemoteException(e.getMessage()); } } - @Override public boolean addVPNProfile(String name, String config) throws RemoteException { - checkOpenVPNPermission(); + return addNewVPNProfile(name, true, config) != null; + } + + + @Override + public APIVpnProfile addNewVPNProfile(String name, boolean userEditable, String config) throws RemoteException { + String callingPackage = checkOpenVPNPermission(); ConfigParser cp = new ConfigParser(); try { cp.parseConfig(new StringReader(config)); VpnProfile vp = cp.convertProfile(); vp.mName = name; + vp.mProfileCreator = callingPackage; + vp.mUserEditable = userEditable; ProfileManager pm = ProfileManager.getInstance(getBaseContext()); pm.addProfile(vp); + pm.saveProfile(ExternalOpenVPNService.this, vp); + pm.saveProfileList(ExternalOpenVPNService.this); + return new APIVpnProfile(vp.getUUIDString(), vp.mName, vp.mUserEditable, vp.mProfileCreator); } catch (IOException e) { VpnStatus.logException(e); - return false; + return null; } catch (ConfigParseError e) { VpnStatus.logException(e); - return false; + return null; } - - return true; } @Override @@ -226,8 +232,8 @@ public class ExternalOpenVPNService extends Service implements StateListener { @Override - public Intent prepare(String packagename) { - if (new ExternalAppDatabase(ExternalOpenVPNService.this).isAllowed(packagename)) + public Intent prepare(String packageName) { + if (new ExternalAppDatabase(ExternalOpenVPNService.this).isAllowed(packageName)) return null; Intent intent = new Intent(); @@ -339,7 +345,7 @@ public class ExternalOpenVPNService extends Service implements StateListener { WeakReference service = null; private void setService(ExternalOpenVPNService eos) { - service = new WeakReference(eos); + service = new WeakReference<>(eos); } @Override diff --git a/main/src/main/java/de/blinkt/openvpn/core/ProfileManager.java b/main/src/main/java/de/blinkt/openvpn/core/ProfileManager.java index 1ebc0a57..e4687c3c 100644 --- a/main/src/main/java/de/blinkt/openvpn/core/ProfileManager.java +++ b/main/src/main/java/de/blinkt/openvpn/core/ProfileManager.java @@ -140,9 +140,7 @@ public class ProfileManager { } - public void saveProfile(Context context,VpnProfile profile) { - // First let basic settings save its state - + public void saveProfile(Context context, VpnProfile profile) { ObjectOutputStream vpnfile; try { vpnfile = new ObjectOutputStream(context.openFileOutput((profile.getUUID().toString() + ".vp"),Activity.MODE_PRIVATE)); @@ -150,10 +148,6 @@ public class ProfileManager { vpnfile.writeObject(profile); vpnfile.flush(); vpnfile.close(); - } catch (FileNotFoundException e) { - - VpnStatus.logException("saving VPN profile", e); - throw new RuntimeException(e); } catch (IOException e) { VpnStatus.logException("saving VPN profile", e); throw new RuntimeException(e); diff --git a/main/src/main/java/de/blinkt/openvpn/fragments/FaqFragment.java b/main/src/main/java/de/blinkt/openvpn/fragments/FaqFragment.java index 4bc93cef..91a683b8 100644 --- a/main/src/main/java/de/blinkt/openvpn/fragments/FaqFragment.java +++ b/main/src/main/java/de/blinkt/openvpn/fragments/FaqFragment.java @@ -8,16 +8,21 @@ package de.blinkt.openvpn.fragments; import android.app.Fragment; import android.content.Context; import android.os.Build; +import android.os.Bundle; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.StaggeredGridLayoutManager; +import android.util.DisplayMetrics; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import java.util.Vector; import de.blinkt.openvpn.R; public class FaqFragment extends Fragment { static class FAQEntry { - public FAQEntry(int startVersion, int endVersion, int description) { - this(startVersion, endVersion, -1, description); - } - public FAQEntry(int startVersion, int endVersion, int title, int description) { this.startVersion = startVersion; this.endVersion = endVersion; diff --git a/main/src/main/java/de/blinkt/openvpn/fragments/Settings_Basic.java b/main/src/main/java/de/blinkt/openvpn/fragments/Settings_Basic.java index 1fda0a9c..5f25b38b 100644 --- a/main/src/main/java/de/blinkt/openvpn/fragments/Settings_Basic.java +++ b/main/src/main/java/de/blinkt/openvpn/fragments/Settings_Basic.java @@ -9,7 +9,6 @@ import android.annotation.TargetApi; import android.app.Activity; import android.app.AlertDialog; import android.app.AlertDialog.Builder; -import android.app.Fragment; import android.content.ActivityNotFoundException; import android.content.Intent; import android.os.Build; @@ -40,7 +39,7 @@ import de.blinkt.openvpn.core.ProfileManager; import de.blinkt.openvpn.core.X509Utils; import de.blinkt.openvpn.views.FileSelectLayout; -public class Settings_Basic extends Fragment implements View.OnClickListener, OnItemSelectedListener, Callback, FileSelectLayout.FileSelectCallback { +public class Settings_Basic extends Settings_Fragment implements View.OnClickListener, OnItemSelectedListener, Callback, FileSelectLayout.FileSelectCallback { private static final int CHOOSE_FILE_OFFSET = 1000; private static final int UPDATE_ALIAS = 20; @@ -57,11 +56,10 @@ public class Settings_Basic extends Fragment implements View.OnClickListener, On private EditText mUserName; private EditText mPassword; private View mView; - private VpnProfile mProfile; private EditText mProfileName; private EditText mKeyPassword; - private SparseArray fileselects = new SparseArray(); + private SparseArray fileselects = new SparseArray<>(); @@ -73,9 +71,7 @@ public class Settings_Basic extends Fragment implements View.OnClickListener, On public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - String profileUuid = getArguments().getString(getActivity().getPackageName() + ".profileUUID"); - mProfile=ProfileManager.get(getActivity(),profileUuid); - getActivity().setTitle(getString(R.string.edit_profile_title, mProfile.getName())); + } @@ -191,15 +187,9 @@ public class Settings_Basic extends Fragment implements View.OnClickListener, On changeType(position); } } - @Override - public void onPause() { - super.onPause(); - savePreferences(); - } - - private void changeType(int type){ + private void changeType(int type){ // hide everything mView.findViewById(R.id.pkcs12).setVisibility(View.GONE); mView.findViewById(R.id.certs).setVisibility(View.GONE); @@ -266,7 +256,7 @@ public class Settings_Basic extends Fragment implements View.OnClickListener, On } - void savePreferences() { + protected void savePreferences() { mProfile.mName = mProfileName.getText().toString(); mProfile.mCaFilename = mCaCert.getData(); diff --git a/main/src/main/java/de/blinkt/openvpn/fragments/Settings_Connections.java b/main/src/main/java/de/blinkt/openvpn/fragments/Settings_Connections.java index 55cce60b..530d1df8 100644 --- a/main/src/main/java/de/blinkt/openvpn/fragments/Settings_Connections.java +++ b/main/src/main/java/de/blinkt/openvpn/fragments/Settings_Connections.java @@ -25,8 +25,7 @@ import de.blinkt.openvpn.R; import de.blinkt.openvpn.VpnProfile; import de.blinkt.openvpn.core.ProfileManager; -public class Settings_Connections extends Fragment implements View.OnClickListener { - private VpnProfile mProfile; +public class Settings_Connections extends Settings_Fragment implements View.OnClickListener { private ConnectionsAdapter mConnectionsAdapter; private TextView mWarning; private Checkable mUseRandomRemote; @@ -35,9 +34,7 @@ public class Settings_Connections extends Fragment implements View.OnClickListen @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - String profileUuid = getArguments().getString(getActivity().getPackageName() + ".profileUUID"); - mProfile= ProfileManager.get(getActivity(), profileUuid); - getActivity().setTitle(getString(R.string.edit_profile_title, mProfile.getName())); + setHasOptionsMenu(true); } @@ -82,8 +79,6 @@ public class Settings_Connections extends Fragment implements View.OnClickListen return v; } - - @Override public void onClick(View v) { if (v.getId() == R.id.add_new_remote) { @@ -99,8 +94,7 @@ public class Settings_Connections extends Fragment implements View.OnClickListen } @Override - public void onPause() { - super.onPause(); + protected void savePreferences() { mConnectionsAdapter.saveProfile(); mProfile.mRemoteRandom = mUseRandomRemote.isChecked(); } diff --git a/main/src/main/java/de/blinkt/openvpn/fragments/Settings_Fragment.java b/main/src/main/java/de/blinkt/openvpn/fragments/Settings_Fragment.java new file mode 100644 index 00000000..738bd0e9 --- /dev/null +++ b/main/src/main/java/de/blinkt/openvpn/fragments/Settings_Fragment.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2012-2015 Arne Schwabe + * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt + */ + +package de.blinkt.openvpn.fragments; + +import android.app.Fragment; +import android.os.Bundle; + +import de.blinkt.openvpn.R; +import de.blinkt.openvpn.VpnProfile; +import de.blinkt.openvpn.core.ProfileManager; + +public abstract class Settings_Fragment extends Fragment { + + protected VpnProfile mProfile; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + String profileUuid = getArguments().getString(getActivity().getPackageName() + ".profileUUID"); + mProfile= ProfileManager.get(getActivity(), profileUuid); + getActivity().setTitle(getString(R.string.edit_profile_title, mProfile.getName())); + } + + + @Override + public void onPause() { + super.onPause(); + savePreferences(); + } + + protected abstract void savePreferences(); +} diff --git a/main/src/main/java/de/blinkt/openvpn/fragments/Settings_UserEditable.java b/main/src/main/java/de/blinkt/openvpn/fragments/Settings_UserEditable.java new file mode 100644 index 00000000..f9477a85 --- /dev/null +++ b/main/src/main/java/de/blinkt/openvpn/fragments/Settings_UserEditable.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2012-2015 Arne Schwabe + * Distributed under the GNU GPL v2 with additional terms. For full terms see the file doc/LICENSE.txt + */ + +package de.blinkt.openvpn.fragments; + +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import de.blinkt.openvpn.R; + +public class Settings_UserEditable extends OpenVpnPreferencesFragment { + @Override + protected void loadSettings() { + + } + + @Override + protected void saveSettings() { + + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View v = inflater.inflate(R.layout.settings_usereditable, container, false); + TextView messageView = (TextView) v.findViewById(R.id.messageUserEdit); + messageView.setText(getString(R.string.message_no_user_edit, getPackageString(mProfile.mProfileCreator))); + return v; + } + + + private String getPackageString(String packageName) { + final PackageManager pm = getActivity().getPackageManager(); + ApplicationInfo ai; + try { + ai = pm.getApplicationInfo( packageName, 0); + } catch (final PackageManager.NameNotFoundException e) { + ai = null; + } + final String applicationName = (String) (ai != null ? pm.getApplicationLabel(ai) : "(unknown)"); + return String.format("%s (%s)", applicationName, packageName); + } +} diff --git a/main/src/main/res/layout/settings_usereditable.xml b/main/src/main/res/layout/settings_usereditable.xml new file mode 100644 index 00000000..5a330df2 --- /dev/null +++ b/main/src/main/res/layout/settings_usereditable.xml @@ -0,0 +1,21 @@ + + + + + + + \ No newline at end of file diff --git a/main/src/main/res/values/strings.xml b/main/src/main/res/values/strings.xml index 61cf4700..f552cb3d 100755 --- a/main/src/main/res/values/strings.xml +++ b/main/src/main/res/values/strings.xml @@ -378,5 +378,6 @@ %s and later Connections fails with SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure Newer OpenVPN for Android versions (0.6.29/March 2015) use a more secure default for the allowed cipher suites (tls-cipher \"DEFAULT:!EXP:!PSK:!SRP:!kRSA\"). Unfortunately, omitting the less secure cipher suites and export cipher suites, especially the omission of cipher suites that do not support Perfect Forward Secrecy (Diffie-Hellman) causes some problems. This usually caused by an well-intentioned but poorly executed attempts to strengthen TLS security by setting tls-cipher on the server.\nTo solve this problem the problem, set the tls-cipher settings on the server to reasonable default like tls-cipher \"DEFAULT:!EXP:!PSK:!SRP:!kRSA\". To work around the problem on the client add the custom option tls-cipher DEFAULT on the Android client. + This profile has been added from an external app (%s) and has been marked as not user editable. -- cgit v1.2.3