Implement several missing UnsupportedOperationException

master
Lonami Exo 2018-07-25 21:03:59 +02:00
parent 757f684c6b
commit bc0414a436
8 changed files with 102 additions and 47 deletions

View File

@ -1,6 +1,7 @@
package io.github.lonamiwebs.overgram.crypto;
import io.github.lonamiwebs.overgram.network.MTProtoPlainSender;
import io.github.lonamiwebs.overgram.network.MTProtoState;
import io.github.lonamiwebs.overgram.tl.Abstract;
import io.github.lonamiwebs.overgram.tl.Functions;
import io.github.lonamiwebs.overgram.tl.Types;
@ -14,7 +15,8 @@ import java.nio.ByteBuffer;
public class Authenticator {
public static AuthKey doAuthentication(final MTProtoPlainSender sender) throws IOException, ClassNotFoundException {
public static void doAuthentication(final MTProtoPlainSender sender, final MTProtoState state)
throws IOException, ClassNotFoundException {
final BigInteger nonce = new BigInteger(Utils.randomBytes(16));
final Types.ResPQ resPq = sender.send(
new Functions.ReqPqMulti().nonce(nonce));
@ -55,6 +57,7 @@ public class Authenticator {
throw new SecurityException("Step 2 could not find a known RSA key");
}
// TODO This step fails half the time, why?
final Abstract.ServerDHParams abstractDhParams = sender.send(
new Functions.ReqDHParams()
.nonce(resPq.nonce())
@ -149,6 +152,7 @@ public class Authenticator {
throw new SecurityException("Step 3 DH gen data have invalid nonce hash");
}
return authKey; // TODO And time offset
state.authKey = authKey;
state.setTimeOffset(timeOffset);
}
}

View File

@ -67,7 +67,7 @@ public class MTProtoSender {
success = false;
for (int i = 0; i < retries; ++i) {
try {
state.authKey = Authenticator.doAuthentication(plain);
Authenticator.doAuthentication(plain, state);
success = true;
break;
} catch (SecurityException | IOException | ClassNotFoundException ignored) {
@ -222,6 +222,7 @@ public class MTProtoSender {
}
try {
processMessage(message);
} catch (ClassNotFoundException ignored) {
} catch (InterruptedException ignored) {
doDisconnect();
return;
@ -229,7 +230,7 @@ public class MTProtoSender {
}
}
private void processMessage(final TLMessage message) throws InterruptedException {
private void processMessage(final TLMessage message) throws InterruptedException, ClassNotFoundException {
pendingAck.add(message.id);
if (message.object instanceof RPCResult) {
handleRpcResult(message);
@ -264,33 +265,37 @@ public class MTProtoSender {
}
}
private void handleRpcResult(final TLMessage message) {
private void handleRpcResult(final TLMessage message) throws ClassNotFoundException {
final RPCResult result = (RPCResult) message.object;
final TLMessage replyMessage = pendingMessages.remove(result.reqMsgId);
if (result.error != null) {
replyMessage.future.completeExceptionally(new RPCError(result.error));
return;
}
final BinaryReader reader = new BinaryReader(ByteBuffer.wrap(result.result));
boolean ok = false;
try {
replyMessage.future.complete(((TLRequest) replyMessage.object).readResult(reader));
} catch (ClassNotFoundException e) {
replyMessage.future.completeExceptionally(e);
if (result.error != null) {
replyMessage.future.completeExceptionally(new RPCError(result.error));
} else {
final BinaryReader reader = new BinaryReader(ByteBuffer.wrap(result.result));
replyMessage.future.complete(((TLRequest) replyMessage.object).readResult(reader));
}
ok = true;
} finally {
if (!ok) {
replyMessage.future.completeExceptionally(new Exception());
}
}
}
public void handleContainer(final TLMessage message) throws InterruptedException {
public void handleContainer(final TLMessage message) throws InterruptedException, ClassNotFoundException {
final MessageContainer result = (MessageContainer) message.object;
for (final TLMessage innerMessage : result.messages) {
processMessage(innerMessage);
}
}
public void handleGzipPacked(final TLMessage message) throws InterruptedException {
public void handleGzipPacked(final TLMessage message) throws InterruptedException, ClassNotFoundException {
final GzipPacked result = (GzipPacked) message.object;
message.object = result.packedObject();
final BinaryReader reader = new BinaryReader(ByteBuffer.wrap(result.unpackedData));
message.object = reader.readTl();
processMessage(message);
}
@ -323,9 +328,11 @@ public class MTProtoSender {
final TLMessage badMessage = pendingMessages.get(result.badMsgId());
if (result.errorCode() == 16 || result.errorCode() == 17) {
state.updateTimeOffset(message.id);
if (badMessage != null) {
// resend and update time offset
throw new UnsupportedOperationException();
pendingMessages.remove(badMessage.id);
badMessage.id = state.getNewMsgId();
pendingMessages.put(badMessage.id, badMessage);
}
return;
}

View File

@ -114,12 +114,9 @@ public class MTProtoState {
throw new SecurityException("Server replied with a wrong session ID");
}
final long remoteMsgId = tlReader.readLong();
final int remoteSeq = tlReader.readInt();
tlReader.readInt(); // inner message length
final TLObject object = tlReader.readTl();
return new TLMessage(remoteMsgId, remoteSeq, object);
final TLMessage message = new TLMessage();
message.deserialize(tlReader);
return message;
}
public long getNewMsgId() {
@ -140,6 +137,10 @@ public class MTProtoState {
lastMsgId = 0;
}
public void setTimeOffset(final long timeOffset) {
this.timeOffset = timeOffset;
}
public int getSeqNo(final boolean contentRelated) {
if (contentRelated) {
return 1 + 2 * sequence++;

View File

@ -51,8 +51,16 @@ public class TcpFull extends Connection {
final int length = buffer.getInt();
final int seq = buffer.getInt();
final byte[] body = client.read(length - 12);
final int crc = ByteBuffer.wrap(client.read(4)).getInt();
// TODO Check crc
final int crc = ByteBuffer.wrap(client.read(4)).order(ByteOrder.LITTLE_ENDIAN).getInt();
final CRC32 validCrc = new CRC32();
buffer.rewind();
validCrc.update(buffer.array());
validCrc.update(body);
if ((int) validCrc.getValue() != crc) {
throw new SecurityException("Invalid CRC");
}
return body;
}
}

View File

@ -3,24 +3,53 @@ package io.github.lonamiwebs.overgram.tl;
import io.github.lonamiwebs.overgram.utils.BinaryReader;
import io.github.lonamiwebs.overgram.utils.BinaryWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
public class GzipPacked extends TLObject {
public static final int CONSTRUCTOR_ID = 812830625;
public byte[] unpackedData;
@Override
public void serialize(final BinaryWriter writer) {
throw new UnsupportedOperationException();
try {
final ByteArrayOutputStream out = new ByteArrayOutputStream();
final GZIPOutputStream gzip = new GZIPOutputStream(out);
gzip.write(unpackedData);
gzip.finish();
writer.write(out.toByteArray());
} catch (IOException ignored) {
throw new RuntimeException();
}
}
@Override
public void deserialize(final BinaryReader reader) throws ClassNotFoundException {
throw new UnsupportedOperationException();
}
public TLObject packedObject() {
throw new UnsupportedOperationException();
try {
final GZIPInputStream gzip = new GZIPInputStream(new ByteArrayInputStream(reader.read()));
final ByteArrayOutputStream out = new ByteArrayOutputStream(4096);
final byte[] buffer = new byte[4096];
int read;
while ((read = gzip.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
unpackedData = out.toByteArray();
} catch (IOException ignored) {
throw new RuntimeException();
}
}
public static byte[] unzip(final BinaryReader reader) {
throw new UnsupportedOperationException();
final GzipPacked gzipPacked = new GzipPacked();
try {
gzipPacked.deserialize(reader);
} catch (ClassNotFoundException ignored) {
throw new RuntimeException();
}
return gzipPacked.unpackedData;
}
}

View File

@ -13,7 +13,11 @@ public class MessageContainer extends TLObject {
@Override
public void serialize(final BinaryWriter writer) {
throw new UnsupportedOperationException();
writer.write(CONSTRUCTOR_ID);
writer.write(messages.size());
for (final TLMessage message : messages) {
writer.write(message);
}
}
@Override
@ -21,13 +25,9 @@ public class MessageContainer extends TLObject {
messages.clear();
final int count = reader.readInt();
for (int i = 0; i < count; ++i) {
final long msgId = reader.readLong();
final int seqNo = reader.readInt();
final int length = reader.readInt();
final int before = reader.tell();
final TLObject object = reader.readTl();
reader.set(before + length);
messages.add(new TLMessage(msgId, seqNo, object));
final TLMessage message = new TLMessage();
message.deserialize(reader);
messages.add(message);
}
}
}

View File

@ -3,8 +3,6 @@ package io.github.lonamiwebs.overgram.tl;
import io.github.lonamiwebs.overgram.utils.BinaryReader;
import io.github.lonamiwebs.overgram.utils.BinaryWriter;
import java.util.Arrays;
public class RPCResult extends TLObject {
public static final int CONSTRUCTOR_ID = -212046591;

View File

@ -12,6 +12,9 @@ public class TLMessage extends TLObject {
public int seqNo;
public TLObject object;
public TLMessage() {
}
public TLMessage(final long id, final int seqNo, final TLObject object) {
this.id = id;
this.seqNo = seqNo;
@ -20,7 +23,7 @@ public class TLMessage extends TLObject {
}
@Override
public void serialize(BinaryWriter writer) {
public void serialize(final BinaryWriter writer) {
final BinaryWriter tmp = new BinaryWriter();
tmp.write(object);
writer.write(id);
@ -30,7 +33,12 @@ public class TLMessage extends TLObject {
}
@Override
public void deserialize(BinaryReader reader) throws ClassNotFoundException {
throw new UnsupportedOperationException();
public void deserialize(final BinaryReader reader) throws ClassNotFoundException {
id = reader.readLong();
seqNo = reader.readInt();
final int length = reader.readInt();
final int before = reader.tell();
object = reader.readTl();
reader.set(before + length);
}
}