Support decryption of shared journals

pull/935/head
Alex Baker 6 years ago
parent a31cdb777b
commit 29d1b54ca7

@ -17,8 +17,10 @@ public class AddEteSyncAccountViewModel extends CompletableViewModel<Pair<UserIn
String password) { String password) {
run( run(
() -> { () -> {
client.setForeground();
playServices.updateSecurityProvider(context); playServices.updateSecurityProvider(context);
return client.setForeground().forUrl(url, username, null, null).getInfoAndToken(password); String token = client.forUrl(url, username, null, null).getToken(password);
return Pair.create(client.forUrl(url, username, null, token).getUserInfo(), token);
}); });
} }
} }

@ -9,6 +9,7 @@ import androidx.core.util.Pair;
import at.bitfire.cert4android.CustomCertManager; import at.bitfire.cert4android.CustomCertManager;
import at.bitfire.cert4android.CustomCertManager.CustomHostnameVerifier; import at.bitfire.cert4android.CustomCertManager.CustomHostnameVerifier;
import com.etesync.journalmanager.Constants; import com.etesync.journalmanager.Constants;
import com.etesync.journalmanager.Crypto;
import com.etesync.journalmanager.Crypto.CryptoManager; import com.etesync.journalmanager.Crypto.CryptoManager;
import com.etesync.journalmanager.Exceptions; import com.etesync.journalmanager.Exceptions;
import com.etesync.journalmanager.Exceptions.HttpException; import com.etesync.journalmanager.Exceptions.HttpException;
@ -152,25 +153,8 @@ public class EteSyncClient {
foreground); foreground);
} }
private EteSyncClient withToken(String token) String getToken(String password) throws IOException, HttpException {
throws KeyManagementException, NoSuchAlgorithmException { return new JournalAuthenticator(httpClient, httpUrl).getAuthToken(username, password);
return new EteSyncClient(
context,
encryption,
preferences,
interceptor,
httpUrl.toString(),
username,
encryptionPassword,
token,
foreground);
}
Pair<UserInfo, String> getInfoAndToken(String password)
throws IOException, HttpException, NoSuchAlgorithmException, KeyManagementException {
JournalAuthenticator journalAuthenticator = new JournalAuthenticator(httpClient, httpUrl);
String token = journalAuthenticator.getAuthToken(username, password);
return Pair.create(withToken(token).getUserInfo(), token);
} }
UserInfo getUserInfo() throws HttpException { UserInfo getUserInfo() throws HttpException {
@ -178,13 +162,23 @@ public class EteSyncClient {
return userInfoManager.fetch(username); return userInfoManager.fetch(username);
} }
CryptoManager getCrypto(Journal journal) throws VersionTooNewException, IntegrityException { CryptoManager getCrypto(UserInfo userInfo, Journal journal)
throws VersionTooNewException, IntegrityException {
if (journal.getKey() == null) {
return new CryptoManager(journal.getVersion(), encryptionPassword, journal.getUid()); return new CryptoManager(journal.getVersion(), encryptionPassword, journal.getUid());
} }
if (userInfo == null) {
throw new RuntimeException("Missing userInfo");
}
CryptoManager cryptoManager = new CryptoManager(userInfo.getVersion(), encryptionPassword, "userInfo");
Crypto.AsymmetricKeyPair keyPair =
new Crypto.AsymmetricKeyPair(userInfo.getContent(cryptoManager), userInfo.getPubkey());
return new CryptoManager(journal.getVersion(), keyPair, journal.getKey());
}
private @Nullable CollectionInfo convertJournalToCollection(Journal journal) { private @Nullable CollectionInfo convertJournalToCollection(UserInfo userInfo, Journal journal) {
try { try {
CryptoManager cryptoManager = getCrypto(journal); CryptoManager cryptoManager = getCrypto(userInfo, journal);
journal.verify(cryptoManager); journal.verify(cryptoManager);
CollectionInfo collection = CollectionInfo collection =
CollectionInfo.Companion.fromJson(journal.getContent(cryptoManager)); CollectionInfo.Companion.fromJson(journal.getContent(cryptoManager));
@ -196,10 +190,11 @@ public class EteSyncClient {
} }
} }
public Map<Journal, CollectionInfo> getCalendars() throws Exceptions.HttpException { public Map<Journal, CollectionInfo> getCalendars(UserInfo userInfo)
throws Exceptions.HttpException {
Map<Journal, CollectionInfo> result = new HashMap<>(); Map<Journal, CollectionInfo> result = new HashMap<>();
for (Journal journal : journalManager.list()) { for (Journal journal : journalManager.list()) {
CollectionInfo collection = convertJournalToCollection(journal); CollectionInfo collection = convertJournalToCollection(userInfo, journal);
if (collection != null) { if (collection != null) {
if (TYPE_TASKS.equals(collection.getType())) { if (TYPE_TASKS.equals(collection.getType())) {
Timber.v("Found %s", collection); Timber.v("Found %s", collection);
@ -213,11 +208,14 @@ public class EteSyncClient {
} }
void getSyncEntries( void getSyncEntries(
Journal journal, CaldavCalendar calendar, Callback<List<Pair<Entry, SyncEntry>>> callback) UserInfo userInfo,
Journal journal,
CaldavCalendar calendar,
Callback<List<Pair<Entry, SyncEntry>>> callback)
throws IntegrityException, Exceptions.HttpException, VersionTooNewException { throws IntegrityException, Exceptions.HttpException, VersionTooNewException {
JournalEntryManager journalEntryManager = JournalEntryManager journalEntryManager =
new JournalEntryManager(httpClient, httpUrl, journal.getUid()); new JournalEntryManager(httpClient, httpUrl, journal.getUid());
CryptoManager crypto = getCrypto(journal); CryptoManager crypto = getCrypto(userInfo, journal);
List<Entry> journalEntries; List<Entry> journalEntries;
do { do {
journalEntries = journalEntryManager.list(crypto, calendar.getCtag(), MAX_FETCH); journalEntries = journalEntryManager.list(crypto, calendar.getCtag(), MAX_FETCH);
@ -235,9 +233,8 @@ public class EteSyncClient {
} }
} }
EteSyncClient setForeground() { void setForeground() {
foreground = true; foreground = true;
return this;
} }
void invalidateToken() { void invalidateToken() {
@ -266,10 +263,11 @@ public class EteSyncClient {
throws VersionTooNewException, IntegrityException, HttpException { throws VersionTooNewException, IntegrityException, HttpException {
String uid = calendar.getUrl(); String uid = calendar.getUrl();
Journal journal = journalManager.fetch(uid); Journal journal = journalManager.fetch(uid);
CollectionInfo collectionInfo = convertJournalToCollection(journal); UserInfo userInfo = getUserInfo();
CryptoManager crypto = getCrypto(userInfo, journal);
CollectionInfo collectionInfo = convertJournalToCollection(userInfo, journal);
collectionInfo.setDisplayName(name); collectionInfo.setDisplayName(name);
collectionInfo.setColor(color == 0 ? null : color); collectionInfo.setColor(color == 0 ? null : color);
CryptoManager crypto = new CryptoManager(collectionInfo.getVersion(), encryptionPassword, uid);
journalManager.update(new Journal(crypto, collectionInfo.toJson(), uid)); journalManager.update(new Journal(crypto, collectionInfo.toJson(), uid));
return uid; return uid;
} }

@ -20,6 +20,7 @@ import com.etesync.journalmanager.Exceptions.VersionTooNewException;
import com.etesync.journalmanager.JournalEntryManager; import com.etesync.journalmanager.JournalEntryManager;
import com.etesync.journalmanager.JournalEntryManager.Entry; import com.etesync.journalmanager.JournalEntryManager.Entry;
import com.etesync.journalmanager.JournalManager.Journal; import com.etesync.journalmanager.JournalManager.Journal;
import com.etesync.journalmanager.UserInfoManager.UserInfo;
import com.etesync.journalmanager.model.CollectionInfo; import com.etesync.journalmanager.model.CollectionInfo;
import com.etesync.journalmanager.model.SyncEntry; import com.etesync.journalmanager.model.SyncEntry;
import com.etesync.journalmanager.model.SyncEntry.Actions; import com.etesync.journalmanager.model.SyncEntry.Actions;
@ -129,7 +130,8 @@ public class EteSynchronizer {
throws KeyManagementException, NoSuchAlgorithmException, Exceptions.HttpException, throws KeyManagementException, NoSuchAlgorithmException, Exceptions.HttpException,
IntegrityException, VersionTooNewException { IntegrityException, VersionTooNewException {
EteSyncClient client = this.client.forAccount(account); EteSyncClient client = this.client.forAccount(account);
Map<Journal, CollectionInfo> resources = client.getCalendars(); UserInfo userInfo = client.getUserInfo();
Map<Journal, CollectionInfo> resources = client.getCalendars(userInfo);
Set<String> uids = newHashSet(Iterables.transform(resources.values(), CollectionInfo::getUid)); Set<String> uids = newHashSet(Iterables.transform(resources.values(), CollectionInfo::getUid));
Timber.d("Found uids: %s", uids); Timber.d("Found uids: %s", uids);
@ -162,7 +164,7 @@ public class EteSynchronizer {
localBroadcastManager.broadcastRefreshList(); localBroadcastManager.broadcastRefreshList();
} }
} }
sync(client, calendar, entry.getKey()); sync(client, userInfo, calendar, entry.getKey());
} }
setError(account, ""); setError(account, "");
} }
@ -176,7 +178,8 @@ public class EteSynchronizer {
} }
} }
private void sync(EteSyncClient client, CaldavCalendar caldavCalendar, Journal journal) private void sync(
EteSyncClient client, UserInfo userInfo, CaldavCalendar caldavCalendar, Journal journal)
throws IntegrityException, Exceptions.HttpException, VersionTooNewException { throws IntegrityException, Exceptions.HttpException, VersionTooNewException {
Timber.d("sync(%s)", caldavCalendar); Timber.d("sync(%s)", caldavCalendar);
@ -189,6 +192,7 @@ public class EteSynchronizer {
if (Strings.isNullOrEmpty(remoteCtag) || !remoteCtag.equals(caldavCalendar.getCtag())) { if (Strings.isNullOrEmpty(remoteCtag) || !remoteCtag.equals(caldavCalendar.getCtag())) {
Timber.v("Applying remote changes"); Timber.v("Applying remote changes");
client.getSyncEntries( client.getSyncEntries(
userInfo,
journal, journal,
caldavCalendar, caldavCalendar,
syncEntries -> applyEntries(caldavCalendar, syncEntries, localChanges.keySet())); syncEntries -> applyEntries(caldavCalendar, syncEntries, localChanges.keySet()));
@ -218,7 +222,7 @@ public class EteSynchronizer {
} }
remoteCtag = caldavCalendar.getCtag(); remoteCtag = caldavCalendar.getCtag();
CryptoManager crypto = client.getCrypto(journal); CryptoManager crypto = client.getCrypto(userInfo, journal);
List<Pair<Entry, SyncEntry>> updates = new ArrayList<>(); List<Pair<Entry, SyncEntry>> updates = new ArrayList<>();
JournalEntryManager.Entry previous = JournalEntryManager.Entry previous =
Strings.isNullOrEmpty(remoteCtag) ? null : Entry.getFakeWithUid(remoteCtag); Strings.isNullOrEmpty(remoteCtag) ? null : Entry.getFakeWithUid(remoteCtag);

@ -16,10 +16,14 @@ public class UpdateEteSyncAccountViewModel extends CompletableViewModel<Pair<Use
@Nullable String token) { @Nullable String token) {
run( run(
() -> { () -> {
EteSyncClient newClient = client.setForeground().forUrl(url, username, null, token); client.setForeground();
return Strings.isNullOrEmpty(password) if (Strings.isNullOrEmpty(password)) {
? Pair.create(newClient.getUserInfo(), token) return Pair.create(client.forUrl(url, username, null, token).getUserInfo(), token);
: newClient.getInfoAndToken(password); } else {
String newToken = client.forUrl(url, username, null, null).getToken(password);
return Pair.create(
client.forUrl(url, username, null, newToken).getUserInfo(), newToken);
}
}); });
} }
} }

Loading…
Cancel
Save