SSL-Zertifikatsprüfung bei jeder Interaktion mit dem Server.

Bugs im Gruppenchat nachdem man ihn durch eine Benachrichtigung geöffnet hat beseitigt.
This commit is contained in:
Lyndon
2018-06-12 18:46:45 +02:00
parent 668a4a03ea
commit 73801269cf
18 changed files with 71 additions and 65 deletions

View File

@@ -9,7 +9,7 @@ buildscript {
}
dependencies {
classpath 'io.fabric.tools:gradle:1.25.0'
classpath 'io.fabric.tools:gradle:1.+'
}
}
@@ -33,8 +33,8 @@ android {
applicationId "de.beyondsoft.ownchat"
minSdkVersion 19
targetSdkVersion 27
versionCode 13
versionName "1.13"
versionCode 14
versionName "1.14"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
multiDexEnabled true
}
@@ -123,8 +123,11 @@ dependencies {
compileOnly 'javax.annotation:jsr250-api:1.0'
implementation files('libs/sanselan-0_97-android-1.0.0.jar')
implementation 'com.firebase:firebase-jobdispatcher:0.5.2'
implementation 'com.google.android.gms:play-services-base:15.0.1'
implementation files('libs/core-1.58.0.0.jar')
implementation files('libs/prov-1.58.0.0.jar')
implementation files('libs/bcpkix-jdk15on-1.58.0.0.jar')
implementation files('libs/bcpg-jdk15on-1.58.0.0.jar')
}
task adp2upload(type: Exec, dependsOn: "build") {

View File

@@ -5,6 +5,8 @@ import android.util.Log;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.spongycastle.openssl.PEMWriter;
import de.beyondsoft.ownchat.BewoplanerApplication;
import de.beyondsoft.ownchat.BuildConfig;
import de.beyondsoft.ownchat.data.AppPrefsConstants;
@@ -14,7 +16,6 @@ import de.beyondsoft.ownchat.di.scopes.ApplicationScope;
import de.beyondsoft.ownchat.utils.Constants;
import java.io.File;
import java.math.BigInteger;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.List;
@@ -38,10 +39,12 @@ import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import rx.schedulers.Schedulers;
import static de.beyondsoft.ownchat.utils.Constants.DICTIONARY_PUB_KEY;
import static de.beyondsoft.ownchat.utils.Constants.INTERMEDIATE_PUB_KEY;
import java.io.StringWriter;
import static de.beyondsoft.ownchat.utils.Constants.LOG_TAG_NETWORK_INTERCEPTOR;
@Module
public class ApiModule {
@@ -103,7 +106,7 @@ public class ApiModule {
Request request = chain.request();
HttpUrl url = request.url();
//Log.d(LOG_TAG_NETWORK_INTERCEPTOR, "Pinning certificate for URL: " + url);
Log.d(LOG_TAG_NETWORK_INTERCEPTOR, "Pinning certificate for URL: " + url);
List<Certificate> certificates = chain.connection().handshake().peerCertificates();
@@ -111,15 +114,21 @@ public class ApiModule {
if(url.toString().contains(".ownchat.de")) {
for(Certificate cert : certificates) {
X509Certificate x509Certificate = (X509Certificate) cert;
X509Certificate x509 = (X509Certificate) cert;
BigInteger serialNumber = x509Certificate.getSerialNumber();
String name = x509.getIssuerX500Principal().getName();
String name = x509Certificate.getIssuerX500Principal().getName();
StringWriter writer = new StringWriter();
//Log.d(LOG_TAG_NETWORK_INTERCEPTOR, "Certificate name: " + name + "; serial number: " + serialNumber);
PEMWriter pemWriter = new PEMWriter(writer);
pemWriter.writeObject(x509.getPublicKey());
pemWriter.flush();
pemWriter.close();
if((serialNumber.equals(INTERMEDIATE_PUB_KEY) || serialNumber.equals(DICTIONARY_PUB_KEY)) && name.contains("O=Let's Encrypt")) {
String writerAsString = writer.toString();
String base64EncodedKey = writerAsString.split("-----BEGIN PUBLIC KEY-----")[1].split("-----END PUBLIC KEY-----")[0].replaceAll(System.getProperty("line.separator"), "");
if(name.contains("O=Let's Encrypt") && base64EncodedKey.equals(Constants.PUBLIC_KEY)) {
isVerified = true;
break;
}
@@ -127,7 +136,7 @@ public class ApiModule {
}
if(!isVerified) {
//Log.e(LOG_TAG_NETWORK_INTERCEPTOR, "SSL certificates are invalid!");
Log.e(LOG_TAG_NETWORK_INTERCEPTOR, "SSL certificates are invalid!");
throw new SSLHandshakeException("Invalid SSL certificates");
}

View File

@@ -24,6 +24,7 @@ public interface LoginService {
);
@GET("https://dict.ownchat.de/api/server/resolve/{type}/{customerid}")
//@GET("https://bewoplaner.de/{type}/{customerid}")
Observable<JsonObject> getServiceType(@Path("type") String type, @Path("customerid") String customerId);
@GET("api/ownchat/uploadmaxsize")

View File

@@ -60,9 +60,6 @@ import rx.schedulers.Schedulers;
import static de.beyondsoft.ownchat.data.AppPrefsConstants.USER_ID;
/**
* Created by Rares Teodorescu on 21/02/2017.
*/
@ActivityScope
public class ChatPresenter extends MVPAbstractPresenter<ChatView> implements ChatView.Callback {
@@ -162,7 +159,7 @@ public class ChatPresenter extends MVPAbstractPresenter<ChatView> implements Cha
.compose(RxUtils.provideDefaultTransformer())
.flatMap(new ErrorHandlingResponseConverter<>())
.flatMap(messageResponse -> {
if (messageResponse.response.messages == null || messageResponse.response.messages.isEmpty()) {
if(messageResponse.response.messages == null || messageResponse.response.messages.isEmpty()) {
return Observable.just(null);
}
@@ -170,7 +167,7 @@ public class ChatPresenter extends MVPAbstractPresenter<ChatView> implements Cha
lastMessage.status = Message.Status.DELIVERED;
lastMessage.isRead = true;
if (!mMessages.contains(lastMessage)) {
if(!mMessages.contains(lastMessage)) {
long groupId1 = mGroupId;
resetMessages();
loadMessagesFromServerByGroupId(groupId1);
@@ -178,7 +175,7 @@ public class ChatPresenter extends MVPAbstractPresenter<ChatView> implements Cha
return Observable.just(null);
}
for (int i = 0; i < mMessageToUpdate.size(); i++) {
for(int i = 0; i < mMessageToUpdate.size(); i++) {
Pair<Message, String> messageToUpdate = mMessageToUpdate.get(i);
if (isAttached()) {
@@ -189,13 +186,13 @@ public class ChatPresenter extends MVPAbstractPresenter<ChatView> implements Cha
mMessageToUpdate.clear();
ArrayList<Message> messages = new ArrayList<>();
for (int i = messageResponse.response.messages.size() - 1; i >= 0; i--) {
for(int i = messageResponse.response.messages.size() - 1; i >= 0; i--) {
Message message = messageResponse.response.messages.get(i);
message.status = Message.Status.DELIVERED;
message.isRead = true;
message.userId = mUserIdPreference.get();
if (mMessages.contains(message)) {
if(mMessages.contains(message)) {
continue;
}

View File

@@ -13,21 +13,19 @@ import android.content.IntentFilter;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.view.View;
/**
* Created by Rares Teodorescu on 21/02/2017.
*/
public class GroupChatActivity extends BaseChatActivity {
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getBundleExtra(Constants.MESSAGE);
if(mCallback == null) {
mChatPresenter.attachView(GroupChatActivity.this);
}
if(mCallback.getGroupId() == bundle.getLong(Constants.GROUP_ID)) {
Message message = new Message(bundle.getString(Constants.MESSAGE_ID),
bundle.getLong(Constants.GROUP_ID),
@@ -44,6 +42,7 @@ public class GroupChatActivity extends BaseChatActivity {
true,
mUserIdPreference.get(),
false);
mCallback.saveMessage(message);
Bundle results = getResultExtras(true);
results.putBoolean(Constants.CHAT_IS_ALREADY_OPEN, true);
@@ -101,7 +100,6 @@ public class GroupChatActivity extends BaseChatActivity {
if(getIntent().hasExtra(MESSAGE_ARG)) {
long groupId = getIntent().getBundleExtra(MESSAGE_ARG).getLong(Constants.GROUP_ID);
mCallback.fetchNewMessages(groupId);
return;
}
setGroupFromArguments();

View File

@@ -18,9 +18,6 @@ import android.support.v4.content.ContextCompat;
import android.text.TextUtils;
import android.view.View;
/**
* Created by Rares Teodorescu on 21/02/2017.
*/
public class SingleChatActivity extends BaseChatActivity {
public static Intent createIntent(Context context, Group contact) {

View File

@@ -31,9 +31,6 @@ import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
/**
* Created by imarneanu on 2/20/17.
*/
class ContactsPresenter extends MVPAbstractPresenter<ContactsView> implements ContactsView.Callback {
@Inject
@@ -69,10 +66,6 @@ class ContactsPresenter extends MVPAbstractPresenter<ContactsView> implements Co
super.beforeDetachView(view);
}
/**
* Get all user groups from server.
*/
@Override
public void loadGroups() {
Subscription subscription = mChatService.getGroups()
@@ -98,9 +91,6 @@ class ContactsPresenter extends MVPAbstractPresenter<ContactsView> implements Co
addSubscription(subscription);
}
/**
* Send error messages to view.
*/
private void groupsError(Throwable throwable) {
Log.e("REALM_TRANSACTION", "An error occurred. This message was brought to you by ContactsPresenter");
if (mSystemUtils.isNetworkUnavailable()) {
@@ -133,10 +123,6 @@ class ContactsPresenter extends MVPAbstractPresenter<ContactsView> implements Co
});
}
/**
* Load groups from local database.
*/
@Override
public void loadGroupsFromDB() {
GroupSpecification groupSpecification = new GroupSpecification(mUserIdReference.get());
@@ -146,9 +132,6 @@ class ContactsPresenter extends MVPAbstractPresenter<ContactsView> implements Co
.subscribe(this::loadGroupsFromDBSuccessful, this::loadGroupsError);
}
/**
* Load groups by name.
*/
@Override
public void loadGroupsContainingName(String name) {
GroupByNameSpecification groupByNameSpecification = new GroupByNameSpecification(name, mUserIdReference.get());
@@ -162,7 +145,7 @@ class ContactsPresenter extends MVPAbstractPresenter<ContactsView> implements Co
if (!isAttached()) {
return;
}
/**/
getView().hideProgress();
getView().setGroups(groups);
}

View File

@@ -43,6 +43,9 @@ import android.support.v7.widget.Toolbar;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
import java.util.Date;
import javax.inject.Inject;
import javax.inject.Named;
@@ -84,10 +87,15 @@ public class MainActivity extends AppCompatActivity implements MainNavigation, L
@Named(AppPrefsConstants.CHAT_OPENED)
BooleanPreference mChatOpenedPref;
@Inject
@Named(AppPrefsConstants.SAVE_PASSWORD)
BooleanPreference mSavePassword;
@Inject
SystemUtils mSystemUtils;
private boolean mLogoutClicked;
private Date mBackButtonLastPressed;
public static Intent createIntent(Context context, Bundle bundle, int numberOfUsers, int groupId) {
Intent intent = new Intent(context, MainActivity.class);
@@ -192,6 +200,18 @@ public class MainActivity extends AppCompatActivity implements MainNavigation, L
@Override
public void onBackPressed() {
if(!mSavePassword.get()) {
Toast.makeText(this, getString(R.string.logout_by_back_button_confirmation), Toast.LENGTH_SHORT).show();
Date kek = new Date();
if(mBackButtonLastPressed != null && (kek.getTime() - mBackButtonLastPressed.getTime() < 2000L)) {
return;
}
}
mBackButtonLastPressed = new Date();
if(mDrawer.isDrawerOpen(GravityCompat.START)) {
mDrawer.closeDrawer(GravityCompat.START);
}

View File

@@ -35,21 +35,14 @@ class SplashPresenter extends MVPAbstractPresenter<SplashView> implements Splash
SplashPresenter() {
}
/**
* Start timer for splash screen.
*/
@Override
public void startTimer() {
Subscription subscription = rx.Observable.timer(SPLASH_DELAY_MILLIS, TimeUnit.MILLISECONDS)
Subscription subscription = rx.Observable.timer(0, TimeUnit.MILLISECONDS)
.compose(RxUtils.provideDefaultTransformer())
.subscribe(aLong -> checkUserLoggedIn());
addSubscription(subscription);
}
/**
* Check if the user is already logged in and saved the passwords.
*/
private void checkUserLoggedIn() {
getView().userLoggedIn(mLoginTokenPreference.isSet() && mSavePasswordPreference.get());
}

View File

@@ -1,10 +1,5 @@
package de.beyondsoft.ownchat.utils;
import java.math.BigInteger;
/**
* Created by laszloffiferenc on 2/21/17.
*/
public interface Constants {
String BEWOPLANER_ENDPOINT = "https://www.p3ds.net/bewoplaner/public/";
int DISK_CACHE_SIZE = 10 * 1024;
@@ -43,6 +38,11 @@ public interface Constants {
String LOG_TAG_NETWORK_INTERCEPTOR = "NETWORK_INTERCEPTOR";
BigInteger INTERMEDIATE_PUB_KEY = new BigInteger("281431956120940106936008670181301568443719");
BigInteger DICTIONARY_PUB_KEY = new BigInteger("306629510923814782023122164817648258606804");
String PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq2g5mGlWyikJyrHeiB/j" +
"u9oNJCkJgqWTu03g47wgTqbIkwrgTZsbh5QmBztEs/UPHwawRC768gHRBmQLf+nC" +
"jMwCWHTE/xzYgr1xD+4Hd3Owkd1Ko3dnIK2ihUjWSEaepYUMDMNF5FHlTFoKWmHe" +
"7akO0EmUqL63kKoQad78MCg6cORu01dr1CWbIxN9fc8c06X8K+hWvIrgA/1U7C22" +
"y0UYUQnwiQpD8WQSztyal58eyqkFSzWA3SZfyOaxSpnnGpge5VEfNhkG5Ufkzqk1" +
"NoP+R0w3rFsPhw6/cH+++6LOPFQyZ/VkbmkFtUkjOrF0lmoHZUywksKO3ag8/2Tx" +
"NQIDAQAB";
}

View File

@@ -24,6 +24,7 @@
android:layout_width="match_parent"
android:background="@drawable/shape_round_top_corners"
android:hint="@string/login_account_number_hint"
android:textCursorDrawable="@null"
android:inputType="number" />
<View
@@ -38,6 +39,7 @@
android:layout_width="match_parent"
android:background="@color/colorWhite"
android:hint="@string/login_chat_code_hint"
android:textCursorDrawable="@null"
android:inputType="text" />
<View
@@ -52,6 +54,7 @@
android:layout_width="match_parent"
android:background="@color/colorWhite"
android:hint="@string/login_username_hint"
android:textCursorDrawable="@null"
android:inputType="text" />
<View
@@ -66,6 +69,7 @@
android:layout_width="match_parent"
android:background="@drawable/shape_round_bottom_corners"
android:hint="@string/login_password_hint"
android:textCursorDrawable="@null"
android:inputType="textPassword" />
<CheckBox

View File

@@ -6,6 +6,7 @@
<string name="search">Suche</string>
<string name="login_again">Bitte melden Sie sich erneut an.</string>
<string name="logout_confirmation">Wollen Sie sich wirklich abmelden?</string>
<string name="logout_by_back_button_confirmation">Tippen Sie erneut, um die Anwendung zu beenden und sich von ownChat abzumelden</string>
<!-- Login -->
<string name="login_chat_code_hint">Chat-Code</string>

View File

@@ -6,7 +6,7 @@ buildscript {
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.2'
classpath 'com.android.tools.build:gradle:3.1.3'
classpath 'io.realm:realm-gradle-plugin:2.2.2'
// NOTE: Do not place your application dependencies here; they belong

View File

@@ -10,7 +10,7 @@
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# org.gradle.jvmargs=-Xmx1536m
org.gradle.jvmargs=-Xmx8192m -XX:MaxPermSize=2048m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
org.gradle.jvmargs=-Xmx8192m -XX:MaxPermSize=8192m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit