Add a setting for the used flush mode when compressing data

Fixes SMACK-593
This commit is contained in:
Florian Schmaus 2014-08-07 14:42:30 +02:00
parent 4e588f7908
commit c3f6c51d0e
3 changed files with 35 additions and 12 deletions

View File

@ -58,7 +58,9 @@ public class JzlibInputOutputStream extends XMPPInputOutputStream {
@Override
public OutputStream getOutputStream(OutputStream outputStream) throws IOException {
final DeflaterOutputStream os = new DeflaterOutputStream(outputStream);
os.setSyncFlush(true);
if (flushMethod == FlushMethod.SYNC_FLUSH) {
os.setSyncFlush(true);
}
return os;
}

View File

@ -48,6 +48,9 @@ public class Java7ZlibInputOutputStream extends XMPPInputOutputStream {
private final static boolean supported;
private final static int compressionLevel = Deflater.DEFAULT_COMPRESSION;
private static final int SYNC_FLUSH_INT = 2;
private static final int FULL_FLUSH_INT = 3;
static {
Method m = null;
try {
@ -100,25 +103,23 @@ public class Java7ZlibInputOutputStream extends XMPPInputOutputStream {
@Override
public OutputStream getOutputStream(OutputStream outputStream) {
final int flushMethodInt;
if (flushMethod == FlushMethod.SYNC_FLUSH) {
flushMethodInt = SYNC_FLUSH_INT;
} else {
flushMethodInt = FULL_FLUSH_INT;
}
return new DeflaterOutputStream(outputStream, new Deflater(compressionLevel)) {
public void flush() throws IOException {
if (!supported) {
super.flush();
return;
}
int count = 0;
if (!def.needsInput()) {
do {
count = def.deflate(buf, 0, buf.length);
out.write(buf, 0, count);
} while (count > 0);
out.flush();
}
try {
do {
count = (Integer) method.invoke(def, buf, 0, buf.length, 2);
int count;
while ((count = (Integer) method.invoke(def, buf, 0, buf.length, flushMethodInt)) != 0) {
out.write(buf, 0, count);
} while (count > 0);
}
} catch (IllegalArgumentException e) {
throw new IOException("Can't flush");
} catch (IllegalAccessException e) {

View File

@ -20,6 +20,21 @@ import java.io.InputStream;
import java.io.OutputStream;
public abstract class XMPPInputOutputStream {
protected static FlushMethod flushMethod;
/**
* Set the used flushed method when compressing data. The default is full flush which may not
* achieve the best compression ratio, but provides better security against certain attacks.
* Only use sync flush if you fully understand the implications.
*
* @see <a href="https://blog.thijsalkema.de/blog/2014/08/07/https-attacks-and-xmpp-2-crime-and-breach/">Attacks against XMPP when using compression</a>
* @param flushMethod
*/
public static void setFlushMethod(FlushMethod flushMethod) {
XMPPInputOutputStream.flushMethod = flushMethod;
}
protected String compressionMethod;
public String getCompressionMethod() {
@ -31,4 +46,9 @@ public abstract class XMPPInputOutputStream {
public abstract InputStream getInputStream(InputStream inputStream) throws Exception;
public abstract OutputStream getOutputStream(OutputStream outputStream) throws Exception;
public enum FlushMethod {
FULL_FLUSH,
SYNC_FLUSH,
}
}