BouncyCastle: allow insecure encryption

master
M66B 3 days ago
parent fa17d36a10
commit 5d4da42bcd

@ -938,7 +938,7 @@ public class ConnectionHelper {
} }
} }
static SSLSocket starttls(Socket socket, String host, int port, Context context) throws IOException { static SSLSocket starttls(SSLSocketFactory sslFactory, Socket socket, String host, int port, Context context) throws IOException {
String response; String response;
String command; String command;
boolean has = false; boolean has = false;
@ -1006,7 +1006,6 @@ public class ConnectionHelper {
} while (response != null && } while (response != null &&
!(response.startsWith("A001 OK") || response.startsWith("220 "))); !(response.startsWith("A001 OK") || response.startsWith("220 ")));
SSLSocketFactory sslFactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
return (SSLSocket) sslFactory.createSocket(socket, host, port, false); return (SSLSocket) sslFactory.createSocket(socket, host, port, false);
} else } else
throw new SocketException("No STARTTLS"); throw new SocketException("No STARTTLS");

@ -1430,9 +1430,8 @@ public class EmailProvider implements Parcelable {
for (InetAddress iaddr : DnsHelper.getAllByName(context, host)) { for (InetAddress iaddr : DnsHelper.getAllByName(context, host)) {
InetSocketAddress address = new InetSocketAddress(iaddr, Server.this.port); InetSocketAddress address = new InetSocketAddress(iaddr, Server.this.port);
SocketFactory factory = (starttls SSLSocketFactory sslFactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
? SocketFactory.getDefault() SocketFactory factory = (starttls ? SocketFactory.getDefault() : sslFactory);
: SSLSocketFactory.getDefault());
try (Socket socket = factory.createSocket()) { try (Socket socket = factory.createSocket()) {
EntityLog.log(context, "Connecting to " + address); EntityLog.log(context, "Connecting to " + address);
socket.connect(address, SCAN_TIMEOUT); socket.connect(address, SCAN_TIMEOUT);
@ -1443,7 +1442,7 @@ public class EmailProvider implements Parcelable {
SSLSocket sslSocket = null; SSLSocket sslSocket = null;
try { try {
if (starttls) if (starttls)
sslSocket = ConnectionHelper.starttls(socket, host, port, context); sslSocket = ConnectionHelper.starttls(sslFactory, socket, host, port, context);
else else
sslSocket = (SSLSocket) socket; sslSocket = (SSLSocket) socket;

@ -170,8 +170,11 @@ public class EmailService implements AutoCloseable {
// TLS_EMPTY_RENEGOTIATION_INFO_SCSV https://tools.ietf.org/html/rfc5746 // TLS_EMPTY_RENEGOTIATION_INFO_SCSV https://tools.ietf.org/html/rfc5746
static { static {
// https://downloads.bouncycastle.org/fips-java/docs/BC-FJA-%28D%29TLSUserGuide-1.0.4.pdf
Security.setProperty("jdk.tls.disabledAlgorithms", ""); Security.setProperty("jdk.tls.disabledAlgorithms", "");
Security.setProperty("jdk.tls.client.protocols", "TLSv1.3,TLSv1.2,TLSv1.1,TLSv1,SSLv3"); Security.setProperty("jdk.tls.client.protocols", "TLSv1.3,TLSv1.2,TLSv1.1,TLSv1,SSLv3");
System.setProperty("org.bouncycastle.jsse.client.dh.unrestrictedGroups", "true");
System.setProperty("org.bouncycastle.jsse.client.dh.minimumPrimeBits", "1024");
} }
private EmailService() { private EmailService() {
@ -1124,7 +1127,7 @@ public class EmailService implements AutoCloseable {
} }
} }
private static class SSLSocketFactoryService extends SSLSocketFactory { static class SSLSocketFactoryService extends SSLSocketFactory {
// openssl s_client -connect host:port < /dev/null 2>/dev/null | openssl x509 -fingerprint -noout -in /dev/stdin // openssl s_client -connect host:port < /dev/null 2>/dev/null | openssl x509 -fingerprint -noout -in /dev/stdin
// nmap --script ssl-enum-ciphers -Pn -p port host // nmap --script ssl-enum-ciphers -Pn -p port host
private String server; private String server;
@ -1195,8 +1198,7 @@ public class EmailService implements AutoCloseable {
@Override @Override
public Socket createSocket() throws IOException { public Socket createSocket() throws IOException {
Log.e("createSocket"); return configure(factory.createSocket());
throw new IOException("createSocket");
} }
@Override @Override

@ -44,6 +44,7 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.Button; import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton; import android.widget.CompoundButton;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageButton; import android.widget.ImageButton;
@ -122,6 +123,8 @@ public class FragmentOptionsConnection extends FragmentBase implements SharedPre
private EditText etHost; private EditText etHost;
private RadioGroup rgEncryption; private RadioGroup rgEncryption;
private EditText etPort; private EditText etPort;
private CheckBox cbInsecure;
private CheckBox cbDane;
private Button btnCheck; private Button btnCheck;
private TextView tvNetworkInfo; private TextView tvNetworkInfo;
@ -196,6 +199,8 @@ public class FragmentOptionsConnection extends FragmentBase implements SharedPre
etHost = view.findViewById(R.id.etHost); etHost = view.findViewById(R.id.etHost);
rgEncryption = view.findViewById(R.id.rgEncryption); rgEncryption = view.findViewById(R.id.rgEncryption);
etPort = view.findViewById(R.id.etPort); etPort = view.findViewById(R.id.etPort);
cbInsecure = view.findViewById(R.id.cbInsecure);
cbDane = view.findViewById(R.id.cbDane);
btnCheck = view.findViewById(R.id.btnCheck); btnCheck = view.findViewById(R.id.btnCheck);
tvNetworkInfo = view.findViewById(R.id.tvNetworkInfo); tvNetworkInfo = view.findViewById(R.id.tvNetworkInfo);
@ -545,12 +550,17 @@ public class FragmentOptionsConnection extends FragmentBase implements SharedPre
else else
encryption = "none"; encryption = "none";
boolean insecure = cbInsecure.isChecked();
boolean dane = cbDane.isChecked();
int timeout = prefs.getInt("timeout", EmailService.DEFAULT_CONNECT_TIMEOUT) * 1000; int timeout = prefs.getInt("timeout", EmailService.DEFAULT_CONNECT_TIMEOUT) * 1000;
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putString("host", host); args.putString("host", host);
args.putInt("port", port == null ? 0 : port); args.putInt("port", port == null ? 0 : port);
args.putString("encryption", encryption); args.putString("encryption", encryption);
args.putBoolean("insecure", insecure);
args.getBoolean("dane", dane);
args.putInt("timeout", timeout); args.putInt("timeout", timeout);
new SimpleTask<StringBuilder>() { new SimpleTask<StringBuilder>() {
@ -569,17 +579,30 @@ public class FragmentOptionsConnection extends FragmentBase implements SharedPre
String host = args.getString("host"); String host = args.getString("host");
int port = args.getInt("port"); int port = args.getInt("port");
String encryption = args.getString("encryption"); String encryption = args.getString("encryption");
boolean insecure = args.getBoolean("insecure");
boolean dane = args.getBoolean("dane");
int timeout = args.getInt("timeout"); int timeout = args.getInt("timeout");
boolean ssl_harden = prefs.getBoolean("ssl_harden", false);
boolean ssl_harden_strict = prefs.getBoolean("ssl_harden_strict", false);
boolean cert_strict = prefs.getBoolean("cert_strict", true);
boolean cert_transparency = prefs.getBoolean("cert_transparency", false);
boolean check_names = prefs.getBoolean("check_names", !BuildConfig.PLAY_STORE_RELEASE);
boolean bc = prefs.getBoolean("bouncy_castle", false);
boolean fips = prefs.getBoolean("bc_fips", false);
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("Host: ").append(host).append('\n'); sb.append("Host: ").append(host).append('\n');
sb.append("Port: ").append(port).append('\n'); sb.append("Port: ").append(port).append('\n');
sb.append("Encryption: ").append(encryption).append('\n'); sb.append("Encryption: ").append(encryption).append('\n');
InetSocketAddress address = new InetSocketAddress(host, port); InetSocketAddress address = new InetSocketAddress(host, port);
SSLSocketFactory sslFactory = new EmailService.SSLSocketFactoryService(
context, host, port, insecure, dane,
ssl_harden, ssl_harden_strict, cert_strict, cert_transparency, check_names,
bc, fips, null, null, null);
SocketFactory factory = (!"ssl".equals(encryption) SocketFactory factory = (!"ssl".equals(encryption)
? SocketFactory.getDefault() ? SocketFactory.getDefault() : sslFactory);
: SSLSocketFactory.getDefault());
try (Socket socket = factory.createSocket()) { try (Socket socket = factory.createSocket()) {
socket.connect(address, timeout); socket.connect(address, timeout);
socket.setSoTimeout(timeout); socket.setSoTimeout(timeout);
@ -588,7 +611,7 @@ public class FragmentOptionsConnection extends FragmentBase implements SharedPre
SSLSocket sslSocket = null; SSLSocket sslSocket = null;
try { try {
if ("starttls".equals(encryption)) if ("starttls".equals(encryption))
sslSocket = ConnectionHelper.starttls(socket, host, port, context); sslSocket = ConnectionHelper.starttls(sslFactory, socket, host, port, context);
else else
sslSocket = (SSLSocket) socket; sslSocket = (SSLSocket) socket;

@ -917,6 +917,26 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvPort" /> app:layout_constraintTop_toBottomOf="@id/tvPort" />
<CheckBox
android:id="@+id/cbInsecure"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="@string/title_allow_insecure"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/etPort" />
<CheckBox
android:id="@+id/cbDane"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="@string/title_dane"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/cbInsecure" />
<Button <Button
android:id="@+id/btnCheck" android:id="@+id/btnCheck"
style="?android:attr/buttonStyleSmall" style="?android:attr/buttonStyleSmall"
@ -925,7 +945,7 @@
android:layout_marginTop="12dp" android:layout_marginTop="12dp"
android:text="@string/title_check" android:text="@string/title_check"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/etPort" /> app:layout_constraintTop_toBottomOf="@id/cbDane" />
<TextView <TextView
android:id="@+id/tvNetworkInfo" android:id="@+id/tvNetworkInfo"

Loading…
Cancel
Save