diff --git a/src/main/java/com/rapid7/client/dcerpc/objects/SIDNameUse.java b/src/main/java/com/rapid7/client/dcerpc/dto/SIDUse.java similarity index 89% rename from src/main/java/com/rapid7/client/dcerpc/objects/SIDNameUse.java rename to src/main/java/com/rapid7/client/dcerpc/dto/SIDUse.java index 56d0629a..043ccba7 100644 --- a/src/main/java/com/rapid7/client/dcerpc/objects/SIDNameUse.java +++ b/src/main/java/com/rapid7/client/dcerpc/dto/SIDUse.java @@ -19,7 +19,7 @@ * */ -package com.rapid7.client.dcerpc.objects; +package com.rapid7.client.dcerpc.dto; import java.util.HashMap; import java.util.Map; @@ -51,7 +51,7 @@ * SidTypeComputer: This member is not used. * SidTypeLabel: This member is not used. */ -public enum SIDNameUse { +public enum SIDUse { SID_TYPE_USER((short) 1), SID_TYPE_GROUP((short) 2), SID_TYPE_DOMAIN((short) 3), @@ -65,7 +65,7 @@ public enum SIDNameUse { private final short value; - SIDNameUse(final short value) { + SIDUse(final short value) { this.value = value; } @@ -73,14 +73,14 @@ public short getValue() { return value; } - private static final Map VALUE_MAP = new HashMap<>(); + private static final Map VALUE_MAP = new HashMap<>(); static { - for (SIDNameUse sidNameUse : SIDNameUse.values()) { + for (SIDUse sidNameUse : SIDUse.values()) { VALUE_MAP.put(sidNameUse.getValue(), sidNameUse); } } - public static SIDNameUse fromValue(final short value) { + public static SIDUse fromValue(final short value) { return VALUE_MAP.get(value); } } diff --git a/src/main/java/com/rapid7/client/dcerpc/io/PacketInput.java b/src/main/java/com/rapid7/client/dcerpc/io/PacketInput.java index 8ee05a1b..a1200b14 100644 --- a/src/main/java/com/rapid7/client/dcerpc/io/PacketInput.java +++ b/src/main/java/com/rapid7/client/dcerpc/io/PacketInput.java @@ -18,8 +18,10 @@ */ package com.rapid7.client.dcerpc.io; +import java.io.EOFException; import java.io.IOException; import java.io.InputStream; +import java.rmi.UnmarshalException; import com.rapid7.client.dcerpc.io.ndr.Unmarshallable; public class PacketInput extends PrimitiveInput { @@ -27,6 +29,16 @@ public PacketInput(final InputStream inputStream) { super(inputStream); } + /** + * Read a non-null object which implements {@link Unmarshallable}. + * This object *must* be considered a top level object; if it is not, consider calling + * {@link Unmarshallable#unmarshalPreamble(PacketInput)}, {@link Unmarshallable#unmarshalEntity(PacketInput)}, + * and {@link Unmarshallable#unmarshalDeferrals(PacketInput)} separately at the appropriate locations. + * @param unmarshallable A non-null {@link Unmarshallable} object. + * @param The class of the provided unmarshallable object. + * @return The same input parameter. Useful for chaining. + * @throws IOException On read failure. + */ public T readUnmarshallable(T unmarshallable) throws IOException { unmarshallable.unmarshalPreamble(this); unmarshallable.unmarshalEntity(this); @@ -34,112 +46,58 @@ public T readUnmarshallable(T unmarshallable) throws return unmarshallable; } - public Integer readIntRef() throws IOException { - return 0 != readReferentID() ? readInt() : null; - } - - public Long readLongRef() throws IOException { - return 0 != readReferentID() ? readLong() : null; - } - + /** + * Read a referent ID unique to this instance of {@link PacketInput}. + * @return A referent ID unique to this instance of {@link PacketInput}. + * @throws IOException On read failure. + */ public int readReferentID() throws IOException { // Currently only supports NDR20 return readInt(); } - public byte[] readByteArray() throws IOException { - readInt(); - final int initialOffset = readInt(); - final int actualCount = readInt(); - final byte[] result = new byte[initialOffset + actualCount]; - - for (int index = initialOffset; index < result.length; index++) { - result[index] = readByte(); - } - - return result; - } - - public byte[] readByteArrayRef() throws IOException { - final byte[] result; - if (0 != readReferentID()) { - result = readByteArray(); - align(); - } else { - result = null; - } - - return result; - } - - public byte[] readRawBytes(int length) throws IOException { + /** + * Read and return length number of bytes. + * @param length The number of bytes to read. + * @return A byte[] populated with length bytes. + * @throws EOFException If not enough bytes are available. + * @throws IOException On read failure. + */ + public byte[] readRawBytes(final int length) throws IOException { byte[] bytes = new byte[length]; readRawBytes(bytes); return bytes; } - public void readRawBytes(byte[] buf) throws IOException { + /** + * Read all bytes into the given buffer. + * @param buf The buffer to read into. + * @throws EOFException If not enough bytes are available to fill the buffer. + * @throws IOException On read failure. + */ + public void readRawBytes(final byte[] buf) throws IOException { readFully(buf, 0, buf.length); } - public String readString(final boolean nullTerminated) throws IOException { - final StringBuffer result; - - readInt(); - final int initialOffset = readInt(); - final int currentChars = readInt(); - - result = new StringBuffer(currentChars); - result.setLength(initialOffset); - - int currentOffset = 0; - while (currentOffset++ < currentChars) { - final char currentChar = (char) readShort(); - if (nullTerminated && currentChar == 0) { - break; - } - result.append(currentChar); - } - - while (currentOffset++ < currentChars) { - readShort(); - } - - align(); - - return result.toString(); - } - - public String readStringRef(final boolean nullTerminated) throws IOException { - final String result; - - if (0 != readReferentID()) { - result = readString(nullTerminated); - align(); - } else { - result = null; - } - - return result != null ? result.toString() : null; - } - - public String readStringBuf(final boolean nullTerminated) throws IOException { - readShort(); // Current byte length - readShort(); // Maximum byte length - - return readStringRef(nullTerminated); - } - - public String readStringBufRef(final boolean nullTerminated) throws IOException { - final String result; - if (0 != readReferentID()) { - result = readStringBuf(nullTerminated); - align(); - } else { - result = null; + /** + * Read an unsigned integer which is to be used as an array size or offset. + * + * Due to the limitations of Java, we must used a signed integer, and array lengths can not + * exceed the maximum value of an unsigned integer. Therefore, if the read unsigned integer + * is greater than {@link Integer#MAX_VALUE}, this will throw an {@link UnmarshalException}. + * + * @param name The name of the entity being read. Used in the potential {@link UnmarshalException}. + * @return The unsigned integer which is guaranteed to be valid as an array size or offset. + * @throws UnmarshalException When the value exceeds {@link Integer#MAX_VALUE}. + * @throws IOException On read failure. + */ + public int readIndex(final String name) throws IOException { + final long ret = readUnsignedInt(); + // Don't allow array length or index values bigger than signed int + if (ret > Integer.MAX_VALUE) { + throw new UnmarshalException(String.format("%s %d > %d", name, ret, Integer.MAX_VALUE)); } - - return result; + return (int) ret; } } diff --git a/src/main/java/com/rapid7/client/dcerpc/io/PacketOutput.java b/src/main/java/com/rapid7/client/dcerpc/io/PacketOutput.java index f8441bda..16a7d6ad 100644 --- a/src/main/java/com/rapid7/client/dcerpc/io/PacketOutput.java +++ b/src/main/java/com/rapid7/client/dcerpc/io/PacketOutput.java @@ -29,126 +29,120 @@ public PacketOutput(final OutputStream outputStream) { super(outputStream); } - public T writeMarshallable(T marshallable) throws IOException { + /** + * Write a non-null object which implements {@link Marshallable}. + * This object *must* be considered a top level object; if it is not, consider calling + * {@link Marshallable#marshalPreamble(PacketOutput)}, {@link Marshallable#marshalEntity(PacketOutput)}, + * and {@link Marshallable#marshalDeferrals(PacketOutput)} separately at the appropriate locations. + * @param marshallable A non-null {@link Marshallable} object. + * @param The class of the provided marshallable object. + * @return The same input parameter. Useful for chaining. + * @throws IOException On write failure. + */ + public T writeMarshallable(final T marshallable) throws IOException { marshallable.marshalPreamble(this); marshallable.marshalEntity(this); marshallable.marshalDeferrals(this); return marshallable; } - public void writeIntRef(final Integer value) throws IOException { - if (value != null) { - writeReferentID(); - writeInt(value); - align(); - } else { - writeNull(); - } - } - - public void writeLongRef(final Long value) throws IOException { - if (value != null) { - writeReferentID(); - writeLong(value); - align(); - } else { - writeNull(); - } - } - + /** + * Write a referent ID unique to this instance of {@link PacketOutput}. + * @throws IOException On write failure. + */ public void writeReferentID() throws IOException { final int referentID = this.referentID; this.referentID += 4; writeInt(referentID); } + /** + * If the object is not null, write a referent ID unique to this instance of {@link PacketOutput}. + * If the object is null, a null reference (0) will be written. + * @param obj The object, which may be null. + * @return True iff the object was not null. + * @throws IOException On write failure. + */ + public boolean writeReferentID(final Object obj) throws IOException { + if (obj == null) { + writeNull(); + return false; + } + writeReferentID(); + return true; + } + + /** + * Write a null referent ID + * @throws IOException On write failure. + */ public void writeNull() throws IOException { writeInt(0); } - public void writeEmptyArray(final int maximumCount) throws IOException { + /** + * Writes an empty conformant varying array with the given MaximumCount + * MaximumCount=maximumCount + * Offset=0 + * ActualCount=0 + * + * Required Alignment: 4 + * Resulting Alignment: N+12 + * + * NOTE: This is written as a top level object, and must not be used within an embedding structure. + * NOTE: Like all actions in this class, existing stream alignment is assumed. + * + * @param maximumCount The MaximumCount + * @throws IOException On write failure. + */ + public void writeEmptyCVArray(final int maximumCount) throws IOException { + // MaximumCount writeInt(maximumCount); + // Offset + // Alignment: 4 - Already aligned writeInt(0); + // ActualCount + // Alignment: 4 - Already aligned writeInt(0); } - public void writeEmptyArrayRef(final int maximumCount) throws IOException { - writeReferentID(); - writeEmptyArray(maximumCount); - align(); - } - - public void writeStringBufferRef(final String string, final boolean nullTerminate) throws IOException { - if (string != null) { - writeReferentID(); - writeStringBuffer(string, nullTerminate); - } else { - writeNull(); - } - } - - public void writeStringBuffer(final String string, final boolean nullTerminate) throws IOException { - final int maximumBytes; - final int currentBytes; - - if (string == null) { - maximumBytes = 0; - currentBytes = 0; - } else { - maximumBytes = 2 * string.length() + (nullTerminate ? 2 : 0); - currentBytes = 2 * string.length() + (nullTerminate ? 2 : 0); - } - - writeShort((short) currentBytes); - writeShort((short) maximumBytes); - - if (string != null) { - writeReferentID(); - writeString(string, nullTerminate); - } else { - writeNull(); - } - } - - public void writeStringRef(final String string, final boolean nullTerminate) throws IOException { - writeReferentID(); - writeString(string, nullTerminate); - } - - public void writeString(final String string, final boolean nullTerminate) throws IOException { - final int maximumChars; - final int currentChars; - - maximumChars = string.length() + (nullTerminate ? 1 : 0); - currentChars = string.length() + (nullTerminate ? 1 : 0); - - writeInt(maximumChars); //max_is (max size) - writeInt(0); //min_is (offset) - writeInt(currentChars); //size_is (actual size) - - writeChars(string); - if (nullTerminate) { - writeShort((short) 0); - } - align(); - } - - public void writeStringBuffer(final int maximumChars) throws IOException { - final int maximumBytes = maximumChars << 1; - final int currentBytes = 0; - final int currentChars = 0; - - writeShort((short) currentBytes); - writeShort((short) maximumBytes); + /** + * Writes an empty {@link com.rapid7.client.dcerpc.objects.RPCUnicodeString} with the + * given number of UTF-16 characters (maximumChars). + * This serves to allocate a buffer for the request call, without actually writing the buffer to the stream. + * Length=0 + * MaximumLength=(maximumChars/2) + * MaximumCount=maximumChars + * Offset=0 + * ActualCount=0 + * + * Required Alignment: 4 + * Resulting Alignment: N+20 + * + * NOTE: This is written as a top level object, and must not be used within an embedding structure. + * NOTE: Like all actions in this class, existing stream alignment is assumed. + * + * @param maximumChars The number of UTF-16 characters to allocate. + * @throws IOException On write failure. + */ + public void writeEmptyRPCUnicodeString(final int maximumChars) throws IOException { + // unsigned short Length; + writeShort((short) 0); // Length + // unsigned short MaximumLength; + // Alignment: 2 - Already aligned + writeShort((short) maximumChars << 1); // MaximumLength + // [size_is(MaximumLength/2), length_is(Length/2)] WCHAR* Buffer; + // Alignment: 4 - Already aligned writeReferentID(); + // MaximumCount: [size_is(MaximumLength/2), length_is(Length/2)] WCHAR* Buffer; + // Alignment: 4 - Already aligned writeInt(maximumChars); + // Offset: [size_is(MaximumLength/2), length_is(Length/2)] WCHAR* Buffer; + // Alignment: 4 - Already aligned writeInt(0); - writeInt(currentChars); - } - - public void writeStringBufferRef(final int maximumChars) throws IOException { - writeReferentID(); - writeStringBuffer(maximumChars); - align(); + // ActualCount: [size_is(MaximumLength/2), length_is(Length/2)] WCHAR* Buffer; + // Alignment: 4 - Already aligned + writeInt(0); + // No entries } } diff --git a/src/main/java/com/rapid7/client/dcerpc/io/PrimitiveInput.java b/src/main/java/com/rapid7/client/dcerpc/io/PrimitiveInput.java index 46fe4cb6..84874dcc 100644 --- a/src/main/java/com/rapid7/client/dcerpc/io/PrimitiveInput.java +++ b/src/main/java/com/rapid7/client/dcerpc/io/PrimitiveInput.java @@ -38,16 +38,12 @@ public PrimitiveInput(final InputStream inputStream) { dataIn = new LittleEndianDataInputStream(dataInStream); } - public void align() throws IOException { - align(Alignment.FOUR); - } - public void align(Alignment alignment) throws IOException { - if (alignment == Alignment.ONE) return; - final long alignmentOffset = alignment.getOffByOneAlignment() + dataInStream.getCount() & ~alignment.getOffByOneAlignment(); - while (alignmentOffset > dataInStream.getCount()) { + if (alignment == Alignment.ONE) + return; + long readBytes = ((alignment.getOffByOneAlignment() + dataInStream.getCount()) & ~alignment.getOffByOneAlignment()) - dataInStream.getCount(); + while (readBytes-- > 0) readByte(); - } } public long getCount() { diff --git a/src/main/java/com/rapid7/client/dcerpc/io/PrimitiveOutput.java b/src/main/java/com/rapid7/client/dcerpc/io/PrimitiveOutput.java index b454883e..ec5bd26f 100644 --- a/src/main/java/com/rapid7/client/dcerpc/io/PrimitiveOutput.java +++ b/src/main/java/com/rapid7/client/dcerpc/io/PrimitiveOutput.java @@ -37,13 +37,10 @@ public PrimitiveOutput(final OutputStream outputStream) { dataOut = new LittleEndianDataOutputStream(dataOutStream); } - public void align() throws IOException { - align(Alignment.FOUR); - } - public void align(Alignment alignment) throws IOException { - if (alignment == Alignment.ONE) return; - final long alignmentOffset = alignment.getOffByOneAlignment() + dataOutStream.getCount() & ~alignment.getOffByOneAlignment(); + if (alignment == Alignment.ONE) + return; + final long alignmentOffset = (alignment.getOffByOneAlignment() + dataOutStream.getCount()) & ~alignment.getOffByOneAlignment(); pad(alignmentOffset - dataOutStream.getCount()); } diff --git a/src/main/java/com/rapid7/client/dcerpc/io/ndr/arrays/RPCConformantArray.java b/src/main/java/com/rapid7/client/dcerpc/io/ndr/arrays/RPCConformantArray.java new file mode 100644 index 00000000..682998d3 --- /dev/null +++ b/src/main/java/com/rapid7/client/dcerpc/io/ndr/arrays/RPCConformantArray.java @@ -0,0 +1,86 @@ +/* + * Copyright 2017, Rapid7, Inc. + * + * License: BSD-3-clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + */ +package com.rapid7.client.dcerpc.io.ndr.arrays; + +import java.io.IOException; +import com.rapid7.client.dcerpc.io.PacketInput; +import com.rapid7.client.dcerpc.io.PacketOutput; +import com.rapid7.client.dcerpc.io.ndr.Alignment; +import com.rapid7.client.dcerpc.io.ndr.Marshallable; +import com.rapid7.client.dcerpc.io.ndr.Unmarshallable; + +public abstract class RPCConformantArray extends RPCConformantBuffer { + private T[] array; + + public RPCConformantArray(final T[] array) { + super(array.length); + this.array = array; + } + + protected abstract void unmarshalEntryPreamble(final PacketInput in, final int index) throws IOException; + protected abstract void unmarshalEntryEntity(final PacketInput in, final int index) throws IOException; + protected abstract void unmarshalEntryDeferrals(final PacketInput in, final int index) throws IOException; + protected abstract void marshalEntryPreamble(final PacketOutput out, final int index) throws IOException; + protected abstract void marshalEntryEntity(final PacketOutput out, final int index) throws IOException; + protected abstract void marshalEntryDeferrals(final PacketOutput out, final int index) throws IOException; + + public T[] getArray() { + return this.array; + } + + @Override + public void unmarshalEntity(final PacketInput in) throws IOException { + // No entity + } + + @Override + public void unmarshalDeferrals(final PacketInput in) throws IOException { + for (int i = 0; i < this.array.length; i++) + unmarshalEntryPreamble(in, i); + for (int i = 0; i < this.array.length; i++) + unmarshalEntryEntity(in, i); + for (int i = 0; i < this.array.length; i++) + unmarshalEntryDeferrals(in, i); + } + + @Override + public void marshalPreamble(final PacketOutput out) throws IOException { + out.align(Alignment.FOUR); + out.writeInt(getMaximumCount()); + } + + @Override + public void marshalEntity(final PacketOutput out) throws IOException { + // No entity + } + + @Override + public void marshalDeferrals(final PacketOutput out) throws IOException { + if (this.array == null) + return; + for (int i = 0; i < this.array.length; i++) + marshalEntryPreamble(out, i); + for (int i = 0; i < this.array.length; i++) + marshalEntryEntity(out, i); + for (int i = 0; i < this.array.length; i++) + marshalEntryDeferrals(out, i); + } +} diff --git a/src/main/java/com/rapid7/client/dcerpc/io/ndr/arrays/RPCConformantBuffer.java b/src/main/java/com/rapid7/client/dcerpc/io/ndr/arrays/RPCConformantBuffer.java new file mode 100644 index 00000000..b69145d5 --- /dev/null +++ b/src/main/java/com/rapid7/client/dcerpc/io/ndr/arrays/RPCConformantBuffer.java @@ -0,0 +1,72 @@ +/* + * Copyright 2017, Rapid7, Inc. + * + * License: BSD-3-clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + */ +package com.rapid7.client.dcerpc.io.ndr.arrays; + +import java.io.IOException; +import com.rapid7.client.dcerpc.io.PacketInput; +import com.rapid7.client.dcerpc.io.PacketOutput; +import com.rapid7.client.dcerpc.io.ndr.Alignment; +import com.rapid7.client.dcerpc.io.ndr.Marshallable; +import com.rapid7.client.dcerpc.io.ndr.Unmarshallable; + +public class RPCConformantBuffer implements Unmarshallable, Marshallable { + + private int maximumCount; + + public RPCConformantBuffer(final int maximumCount) { + this.maximumCount = maximumCount; + } + + public int getMaximumCount() { + return this.maximumCount; + } + + @Override + public void unmarshalPreamble(final PacketInput in) throws IOException { + this.maximumCount = in.readIndex("MaximumCount"); + } + + @Override + public void unmarshalEntity(final PacketInput in) throws IOException { + // No entity + } + + @Override + public void unmarshalDeferrals(final PacketInput in) throws IOException { + // No deferrals + } + + @Override + public void marshalPreamble(final PacketOutput out) throws IOException { + out.align(Alignment.FOUR); + out.writeInt(getMaximumCount()); + } + + @Override + public void marshalEntity(final PacketOutput out) throws IOException { + // No entity + } + + @Override + public void marshalDeferrals(final PacketOutput out) throws IOException { + // No deferrals + } +} diff --git a/src/main/java/com/rapid7/client/dcerpc/io/ndr/arrays/RPCConformantIntegerArray.java b/src/main/java/com/rapid7/client/dcerpc/io/ndr/arrays/RPCConformantIntegerArray.java new file mode 100644 index 00000000..9786df0f --- /dev/null +++ b/src/main/java/com/rapid7/client/dcerpc/io/ndr/arrays/RPCConformantIntegerArray.java @@ -0,0 +1,42 @@ +/* + * Copyright 2017, Rapid7, Inc. + * + * License: BSD-3-clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + */ +package com.rapid7.client.dcerpc.io.ndr.arrays; + +import java.io.IOException; +import com.rapid7.client.dcerpc.io.PacketInput; +import com.rapid7.client.dcerpc.io.PacketOutput; + +public class RPCConformantIntegerArray extends RPCConformantPrimitiveArray { + + public RPCConformantIntegerArray(Integer[] array) { + super(array); + } + + @Override + protected Integer unmarshalPrimitive(final PacketInput in) throws IOException { + return in.readInt(); + } + + @Override + protected void marshalPrimitive(final PacketOutput out, final Integer entry) throws IOException { + out.writeInt(entry); + } +} diff --git a/src/main/java/com/rapid7/client/dcerpc/io/ndr/arrays/RPCConformantPrimitiveArray.java b/src/main/java/com/rapid7/client/dcerpc/io/ndr/arrays/RPCConformantPrimitiveArray.java new file mode 100644 index 00000000..209fa7c9 --- /dev/null +++ b/src/main/java/com/rapid7/client/dcerpc/io/ndr/arrays/RPCConformantPrimitiveArray.java @@ -0,0 +1,65 @@ +/* + * Copyright 2017, Rapid7, Inc. + * + * License: BSD-3-clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + */ +package com.rapid7.client.dcerpc.io.ndr.arrays; + +import java.io.IOException; +import com.rapid7.client.dcerpc.io.PacketInput; +import com.rapid7.client.dcerpc.io.PacketOutput; + +public abstract class RPCConformantPrimitiveArray extends RPCConformantArray { + + public RPCConformantPrimitiveArray(final T[] array) { + super(array); + } + + protected abstract T unmarshalPrimitive(final PacketInput in) throws IOException; + protected abstract void marshalPrimitive(final PacketOutput out, final T entry) throws IOException; + + @Override + protected void unmarshalEntryPreamble(final PacketInput in, final int index) { + // Primitives have no preamble + } + + @Override + protected void unmarshalEntryEntity(final PacketInput in, final int index) throws IOException { + getArray()[index] = unmarshalPrimitive(in); + } + + @Override + protected void unmarshalEntryDeferrals(final PacketInput in, final int index) { + // Primitives have no deferrals + } + + @Override + protected void marshalEntryPreamble(final PacketOutput out, final int index) { + // Primitives have no preamble + } + + @Override + protected void marshalEntryEntity(final PacketOutput out, final int index) throws IOException { + marshalPrimitive(out, getArray()[index]); + } + + @Override + protected void marshalEntryDeferrals(final PacketOutput out, final int index) { + // Primitives have no deferrals + } +} diff --git a/src/main/java/com/rapid7/client/dcerpc/io/ndr/arrays/RPCConformantReferentArray.java b/src/main/java/com/rapid7/client/dcerpc/io/ndr/arrays/RPCConformantReferentArray.java new file mode 100644 index 00000000..43840538 --- /dev/null +++ b/src/main/java/com/rapid7/client/dcerpc/io/ndr/arrays/RPCConformantReferentArray.java @@ -0,0 +1,74 @@ +/* + * Copyright 2017, Rapid7, Inc. + * + * License: BSD-3-clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + */ +package com.rapid7.client.dcerpc.io.ndr.arrays; + +import java.io.IOException; +import com.rapid7.client.dcerpc.io.PacketInput; +import com.rapid7.client.dcerpc.io.PacketOutput; +import com.rapid7.client.dcerpc.io.ndr.Marshallable; +import com.rapid7.client.dcerpc.io.ndr.Unmarshallable; + +public abstract class RPCConformantReferentArray + extends RPCConformantArray { + + public RPCConformantReferentArray(T[] array) { + super(array); + } + + protected abstract T createEntry(); + + @Override + protected void unmarshalEntryPreamble(PacketInput in, int index) { + // No preamble + } + + @Override + protected void unmarshalEntryEntity(PacketInput in, int index) throws IOException { + if (in.readReferentID() == 0) + getArray()[index] = null; + else + getArray()[index] = createEntry(); + } + + @Override + protected void unmarshalEntryDeferrals(PacketInput in, int index) throws IOException { + final T entry = getArray()[index]; + if (entry != null) + in.readUnmarshallable(entry); + } + + @Override + protected void marshalEntryPreamble(PacketOutput out, int index) { + // No preamble + } + + @Override + protected void marshalEntryEntity(PacketOutput out, int index) throws IOException { + out.writeReferentID(getArray()[index]); + } + + @Override + protected void marshalEntryDeferrals(PacketOutput out, int index) throws IOException { + final T entry = getArray()[index]; + if (entry != null) + out.writeMarshallable(entry); + } +} diff --git a/src/main/java/com/rapid7/client/dcerpc/io/ndr/arrays/RPCConformantVaryingBuffer.java b/src/main/java/com/rapid7/client/dcerpc/io/ndr/arrays/RPCConformantVaryingBuffer.java new file mode 100644 index 00000000..b29ca3ed --- /dev/null +++ b/src/main/java/com/rapid7/client/dcerpc/io/ndr/arrays/RPCConformantVaryingBuffer.java @@ -0,0 +1,65 @@ +/* + * Copyright 2017, Rapid7, Inc. + * + * License: BSD-3-clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + */ +package com.rapid7.client.dcerpc.io.ndr.arrays; + +import java.io.IOException; +import com.rapid7.client.dcerpc.io.PacketInput; +import com.rapid7.client.dcerpc.io.PacketOutput; +import com.rapid7.client.dcerpc.io.ndr.Alignment; + +public class RPCConformantVaryingBuffer extends RPCConformantBuffer { + private int offset; + private int actualCount; + + public RPCConformantVaryingBuffer(final int maximumCount) { + this(maximumCount, 0, 0); + } + + public RPCConformantVaryingBuffer(final int maximumCount, final int offset, final int actualCount) { + super(maximumCount); + this.offset = offset; + this.actualCount = actualCount; + } + + public int getOffset() { + return offset; + } + + public int getActualCount() { + return this.actualCount; + } + + @Override + public void marshalEntity(PacketOutput out) throws IOException { + super.marshalEntity(out); + out.align(Alignment.FOUR); + out.writeInt(getOffset()); + out.writeInt(getActualCount()); + } + + @Override + public void unmarshalEntity(PacketInput in) throws IOException { + super.unmarshalEntity(in); + in.align(Alignment.FOUR); + this.offset = in.readIndex("Offset"); + this.actualCount = in.readIndex("ActualCount"); + } +} diff --git a/src/main/java/com/rapid7/client/dcerpc/io/ndr/arrays/RPCConformantVaryingByteArray.java b/src/main/java/com/rapid7/client/dcerpc/io/ndr/arrays/RPCConformantVaryingByteArray.java new file mode 100644 index 00000000..05c37b46 --- /dev/null +++ b/src/main/java/com/rapid7/client/dcerpc/io/ndr/arrays/RPCConformantVaryingByteArray.java @@ -0,0 +1,98 @@ +/* + * Copyright 2017, Rapid7, Inc. + * + * License: BSD-3-clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + */ + +package com.rapid7.client.dcerpc.io.ndr.arrays; + +import java.io.IOException; +import com.rapid7.client.dcerpc.io.PacketInput; +import com.rapid7.client.dcerpc.io.PacketOutput; +import com.rapid7.client.dcerpc.io.ndr.Alignment; +import com.rapid7.client.dcerpc.io.ndr.Marshallable; +import com.rapid7.client.dcerpc.io.ndr.Unmarshallable; + +public class RPCConformantVaryingByteArray implements Unmarshallable, Marshallable { + private static final byte[] EMPTY = new byte[0]; + + private int offset; + private byte[] array = EMPTY; + + public byte[] getArray() { + return this.array; + } + + public void setArray(byte[] array) { + if (array == null) + throw new IllegalArgumentException("Array must not be null"); + this.array = array; + } + + @Override + public void unmarshalPreamble(PacketInput in) throws IOException { + // MaximumCount + in.align(Alignment.FOUR); + in.fullySkipBytes(4); + } + + @Override + public void unmarshalEntity(PacketInput in) throws IOException { + // Structure alignment: 4 + in.align(Alignment.FOUR); + // Offset + // Alignment: 4 - Already aligned + this.offset = in.readIndex("Offset"); + // Alignment: 4 - Already aligned + this.array = new byte[in.readIndex("ActualCount")]; + } + + @Override + public void unmarshalDeferrals(PacketInput in) throws IOException { + // Alignment: 1 - Already aligned + in.fullySkipBytes(this.offset); + // Entries + // Alignment: 1 - Already aligned + in.readRawBytes(this.array); + } + + @Override + public void marshalPreamble(PacketOutput out) throws IOException { + // MaximumCount + out.align(Alignment.FOUR); + out.writeInt(this.array.length); + } + + @Override + public void marshalEntity(PacketOutput out) throws IOException { + // Structure alignment: 4 + out.align(Alignment.FOUR); + // Offset + // Alignment: 4 - Already aligned + out.writeInt(0); + // Alignment: 4 - Already aligned + out.writeInt(this.array.length); + } + + @Override + public void marshalDeferrals(PacketOutput out) throws IOException { + // Alignment: 1 - Already aligned + // Entries + out.write(this.array); + } +} diff --git a/src/main/java/com/rapid7/client/dcerpc/messages/RequestResponse.java b/src/main/java/com/rapid7/client/dcerpc/messages/RequestResponse.java index d0bacfb4..a69a9a1f 100644 --- a/src/main/java/com/rapid7/client/dcerpc/messages/RequestResponse.java +++ b/src/main/java/com/rapid7/client/dcerpc/messages/RequestResponse.java @@ -18,12 +18,15 @@ */ package com.rapid7.client.dcerpc.messages; +import java.io.EOFException; import java.io.IOException; +import java.rmi.UnmarshalException; import com.rapid7.client.dcerpc.io.Hexify; import com.rapid7.client.dcerpc.io.HexifyImpl; import com.rapid7.client.dcerpc.io.Packet; import com.rapid7.client.dcerpc.io.PacketInput; import com.rapid7.client.dcerpc.io.PacketOutput; +import com.rapid7.client.dcerpc.io.ndr.Alignment; import com.rapid7.client.dcerpc.mserref.SystemErrorCode; public abstract class RequestResponse extends HexifyImpl implements Packet, Hexify { @@ -82,7 +85,16 @@ public boolean isSuccess() { @Override public void unmarshal(PacketInput packetIn) throws IOException { unmarshalResponse(packetIn); + // NTSTATUS + packetIn.align(Alignment.FOUR); this.returnValue = packetIn.readInt(); + // Ensure EOF + try { + packetIn.readByte(); + } catch (final EOFException e) { + return; + } + throw new UnmarshalException("At least one byte remained after reading the return code. Is this response aligned properly?"); } public abstract void unmarshalResponse(PacketInput packetIn) throws IOException; diff --git a/src/main/java/com/rapid7/client/dcerpc/messages/Response.java b/src/main/java/com/rapid7/client/dcerpc/messages/Response.java index 7b65633d..145fddce 100644 --- a/src/main/java/com/rapid7/client/dcerpc/messages/Response.java +++ b/src/main/java/com/rapid7/client/dcerpc/messages/Response.java @@ -23,6 +23,7 @@ import com.rapid7.client.dcerpc.PDUType; import com.rapid7.client.dcerpc.io.PacketInput; import com.rapid7.client.dcerpc.io.PacketOutput; +import com.rapid7.client.dcerpc.io.ndr.Alignment; /** * The IDL declaration of the response PDU is as follows:
@@ -88,7 +89,7 @@ public void marshal(final PacketOutput packetOut) throws IOException { packetOut.writeInt(0); packetOut.writeShort(0); packetOut.writeByte(0); - packetOut.align(); + packetOut.align(Alignment.FOUR); packetOut.write(getStub()); packetOut.write(new byte[getAuthLength()]); } diff --git a/src/main/java/com/rapid7/client/dcerpc/mserref/SystemErrorCode.java b/src/main/java/com/rapid7/client/dcerpc/mserref/SystemErrorCode.java index 06f603ff..62f311dc 100644 --- a/src/main/java/com/rapid7/client/dcerpc/mserref/SystemErrorCode.java +++ b/src/main/java/com/rapid7/client/dcerpc/mserref/SystemErrorCode.java @@ -997,6 +997,7 @@ public enum SystemErrorCode { STATUS_ACCESS_DENIED(0xC0000022), STATUS_OBJECT_NAME_NOT_FOUND(0xC0000034), STATUS_NO_SUCH_PRIVILEGE(0xC0000060), + STATUS_NO_SUCH_ALIAS(0xC0000151), STATUS_NO_SUCH_GROUP(0xC0000066), STATUS_NONE_MAPPED(0xC0000073); diff --git a/src/main/java/com/rapid7/client/dcerpc/mslsad/LocalSecurityAuthorityService.java b/src/main/java/com/rapid7/client/dcerpc/mslsad/LocalSecurityAuthorityService.java index 9979683f..68de9da6 100644 --- a/src/main/java/com/rapid7/client/dcerpc/mslsad/LocalSecurityAuthorityService.java +++ b/src/main/java/com/rapid7/client/dcerpc/mslsad/LocalSecurityAuthorityService.java @@ -44,6 +44,7 @@ import com.rapid7.client.dcerpc.mslsad.objects.LSAPRTrustInformation; import com.rapid7.client.dcerpc.objects.RPCSID; import com.rapid7.client.dcerpc.objects.RPCUnicodeString; +import com.rapid7.client.dcerpc.objects.WChar; import com.rapid7.client.dcerpc.service.Service; import com.rapid7.client.dcerpc.transport.RPCTransport; @@ -73,7 +74,7 @@ public LocalSecurityAuthorityService(final RPCTransport transport) { * returns an unsuccessful response. */ public PolicyHandle openPolicyHandle() throws IOException { - final LsarOpenPolicy2Request request = new LsarOpenPolicy2Request("", MAXIMUM_ALLOWED); + final LsarOpenPolicy2Request request = new LsarOpenPolicy2Request(WChar.NullTerminated.of(""), MAXIMUM_ALLOWED); return parsePolicyHandle(callExpectSuccess(request, "LsarOpenPolicy2").getHandle()); } @@ -89,11 +90,10 @@ public PolicyHandle openPolicyHandle() throws IOException { public boolean closePolicyHandle(final PolicyHandle handle) throws IOException { final LsarCloseRequest request = new LsarCloseRequest(parseHandle(handle)); final HandleResponse response = call(request); - if (SystemErrorCode.ERROR_SUCCESS.is(response.getReturnValue())) { + if (SystemErrorCode.ERROR_SUCCESS.is(response.getReturnValue())) return true; - } else if (SystemErrorCode.STATUS_INVALID_HANDLE.is(response.getReturnValue())) { + else if (SystemErrorCode.STATUS_INVALID_HANDLE.is(response.getReturnValue())) return false; - } throw new RPCException("LsarClose", response.getReturnValue()); } @@ -111,8 +111,9 @@ public PolicyAuditEventsInfo getPolicyAuditEventsInfo(final PolicyHandle policyH new LsarQueryInformationPolicyRequest.PolicyAuditEventsInformation(parseHandle(policyHandle)); final LSAPRPolicyAuditEventsInfo policyInformation = callExpectSuccess(request, "LsarQueryInformationPolicy[2]").getPolicyInformation(); - return new PolicyAuditEventsInfo( - (policyInformation.getAuditingMode() != 0), + if (policyInformation == null) + return null; + return new PolicyAuditEventsInfo((policyInformation.getAuditingMode() != 0), policyInformation.getEventAuditingOptions()); } @@ -131,8 +132,9 @@ public PolicyDomainInfo getPolicyPrimaryDomainInformation(final PolicyHandle pol new LsarQueryInformationPolicyRequest.PolicyPrimaryDomainInformation(parseHandle(policyHandle)); final LSAPRPolicyPrimaryDomInfo policyInformation = callExpectSuccess(request, "LsarQueryInformationPolicy[3]").getPolicyInformation(); - return new PolicyDomainInfo( - policyInformation.getName().getValue(), + if (policyInformation == null) + return null; + return new PolicyDomainInfo(parseRPCUnicodeString(policyInformation.getName()), parseRPCSID(policyInformation.getSid())); } @@ -151,7 +153,9 @@ public PolicyDomainInfo getPolicyAccountDomainInformation(final PolicyHandle pol new LsarQueryInformationPolicyRequest.PolicyAccountDomainInformation(parseHandle(policyHandle)); final LSAPRPolicyAccountDomInfo policyInformation = callExpectSuccess(request, "LsarQueryInformationPolicy[5]").getPolicyInformation(); - return new PolicyDomainInfo(policyInformation.getDomainName().getValue(), + if (policyInformation == null) + return null; + return new PolicyDomainInfo(parseRPCUnicodeString(policyInformation.getDomainName()), parseRPCSID(policyInformation.getDomainSid())); } @@ -167,7 +171,9 @@ public PolicyDomainInfo getPolicyAccountDomainInformation(final PolicyHandle pol public String[] getAccountRights(final PolicyHandle policyHandle, final SID sid) throws IOException { final LsarEnumerateAccountRightsRequest request = new LsarEnumerateAccountRightsRequest(parseHandle(policyHandle), parseSID(sid)); - return callExpectSuccess(request, "LsarEnumerateAccountRights").getPrivNames(); + final RPCUnicodeString.NonNullTerminated[] privNames = + callExpectSuccess(request, "LsarEnumerateAccountRights").getPrivNames(); + return parseRPCUnicodeStrings(privNames); } /** @@ -197,8 +203,8 @@ public SID[] getAccountsWithUserRight(final PolicyHandle policyHandle, final Str * @throws IOException Thrown if either a communication failure is encountered, or the call * returns an unsuccessful response. */ - public SID[] lookupNames(final PolicyHandle policyHandle, String... names) throws IOException { - return lookupNames(policyHandle, LSAPLookupLevel.LSAP_LOOKUP_WKSTA, names); + public SID[] lookupSIDsForNames(final PolicyHandle policyHandle, String... names) throws IOException { + return lookupSIDsForNames(policyHandle, LSAPLookupLevel.LSAP_LOOKUP_WKSTA, names); } /** @@ -210,15 +216,19 @@ public SID[] lookupNames(final PolicyHandle policyHandle, String... names) throw * @throws IOException Thrown if either a communication failure is encountered, or the call * returns an unsuccessful response. */ - public SID[] lookupNames(final PolicyHandle policyHandle, final LSAPLookupLevel lookupLevel, final String... names) + public SID[] lookupSIDsForNames(final PolicyHandle policyHandle, final LSAPLookupLevel lookupLevel, final String... names) throws IOException { final LsarLookupNamesRequest request = new LsarLookupNamesRequest( parseHandle(policyHandle), parseNonNullTerminatedStrings(names), lookupLevel.getValue()); final LsarLookupNamesResponse response = callExpect(request, "LsarLookupNames", SystemErrorCode.ERROR_SUCCESS, SystemErrorCode.STATUS_SOME_NOT_MAPPED); - final LSAPRTranslatedSID[] translatedSIDs = response.getTranslatedSIDs().getSIDs(); - final LSAPRTrustInformation[] domainArray = response.getReferencedDomains().getDomains(); + LSAPRTranslatedSID[] translatedSIDs = response.getTranslatedSIDs().getSIDs(); + if (translatedSIDs == null) + translatedSIDs = new LSAPRTranslatedSID[0]; + LSAPRTrustInformation[] domainArray = response.getReferencedDomains().getDomains(); + if (domainArray == null) + domainArray = new LSAPRTrustInformation[0]; // Create DTO SIDs final SID[] sids = new SID[translatedSIDs.length]; for (int i = 0; i < translatedSIDs.length; i++) { @@ -234,7 +244,7 @@ public SID[] lookupNames(final PolicyHandle policyHandle, final LSAPLookupLevel //can be null because it's a pointer if (sid == null) continue; - final SID dtoSID = parseRPCSID(sid); + final SID dtoSID = parseRPCSID(sid, false); //add RID to SID sids[i] = dtoSID.resolveRelativeID(translatedSID.getRelativeId()); } @@ -250,8 +260,8 @@ public SID[] lookupNames(final PolicyHandle policyHandle, final LSAPLookupLevel * @throws IOException Thrown if either a communication failure is encountered, or the call * returns an unsuccessful response. */ - public String[] lookupSIDs(final PolicyHandle policyHandle, SID... sids) throws IOException { - return lookupSIDs(policyHandle, LSAPLookupLevel.LSAP_LOOKUP_WKSTA, sids); + public String[] lookupNamesForSIDs(final PolicyHandle policyHandle, SID ... sids) throws IOException { + return lookupNamesForSIDs(policyHandle, LSAPLookupLevel.LSAP_LOOKUP_WKSTA, sids); } /** @@ -264,16 +274,18 @@ public String[] lookupSIDs(final PolicyHandle policyHandle, SID... sids) throws * @throws IOException Thrown if either a communication failure is encountered, or the call * returns an unsuccessful response. */ - public String[] lookupSIDs(final PolicyHandle policyHandle, final LSAPLookupLevel lookupLevel, SID... sids) + public String[] lookupNamesForSIDs(final PolicyHandle policyHandle, final LSAPLookupLevel lookupLevel, SID ... sids) throws IOException { final LsarLookupSIDsRequest request = new LsarLookupSIDsRequest(parseHandle(policyHandle), parseSIDs(sids), lookupLevel.getValue()); final LsarLookupSIDsResponse lsarLookupSIDsResponse = callExpect(request, "LsarLookupSIDs", SystemErrorCode.ERROR_SUCCESS, SystemErrorCode.STATUS_SOME_NOT_MAPPED); - final LSAPRTranslatedName[] nameArray = lsarLookupSIDsResponse.getTranslatedNames().getNames(); + LSAPRTranslatedName[] nameArray = lsarLookupSIDsResponse.getTranslatedNames().getNames(); + if (nameArray == null) + nameArray = new LSAPRTranslatedName[0]; final String[] mappedNames = new String[nameArray.length]; for (int i = 0; i < nameArray.length; i++) { - mappedNames[i] = nameArray[i].getName().getValue(); + mappedNames[i] = parseRPCUnicodeString(nameArray[i].getName()); } return mappedNames; } diff --git a/src/main/java/com/rapid7/client/dcerpc/mslsad/messages/LsarEnumerateAccountRightsResponse.java b/src/main/java/com/rapid7/client/dcerpc/mslsad/messages/LsarEnumerateAccountRightsResponse.java index 35add50f..4b20a702 100755 --- a/src/main/java/com/rapid7/client/dcerpc/mslsad/messages/LsarEnumerateAccountRightsResponse.java +++ b/src/main/java/com/rapid7/client/dcerpc/mslsad/messages/LsarEnumerateAccountRightsResponse.java @@ -1,4 +1,4 @@ -/** +/* * Copyright 2017, Rapid7, Inc. * * License: BSD-3-clause @@ -21,55 +21,39 @@ import java.io.IOException; import com.rapid7.client.dcerpc.io.PacketInput; import com.rapid7.client.dcerpc.messages.RequestResponse; +import com.rapid7.client.dcerpc.objects.RPCUnicodeString; public class LsarEnumerateAccountRightsResponse extends RequestResponse { - // [out] PLSAPR_USER_RIGHT_SET UserRights - private String[] privNames; + // [out] PLSAPR_USER_RIGHT_SET UserRights + private RPCUnicodeString.NonNullTerminated[] privNames; - public String[] getPrivNames() { + public RPCUnicodeString.NonNullTerminated[] getPrivNames() { return privNames; } @Override public void unmarshalResponse(final PacketInput packetIn) throws IOException { - /* - * Rpc Info - * - * MajorVer: 05 - * MinorVer: 00 - * PacketType: 02 (Response) - * Flags: 03R - * PackType: 10000000 - * FragLen: EC00 - * AuthLen: 0000 - * CallId: 03000000 - * AllocHint: D4000000 - * ContextId: 0000 - * CancelCount: 00 - * Rsvd: 00 - * - * Count: 11000000 - * Ptr: 80DC1600 - * Count: 11000000 - * UniHdr1: 2600 2800985A1700 - * UniHdr2: 2200 2400 68F41600 ... - * UniStr1: 14000000 00000000 13000000 53006500530065.... - * SeSecurityPrivilege ... - * Status: 00000000 - */ - final int privCnt = packetIn.readInt(); - int ptr = packetIn.readInt();// 0 if status == 0xc0000034 - if (privCnt >= 1) { - // MaxCnt(4 bytes) + UnitHdr(8 bytes)* privCnt - packetIn.fullySkipBytes(4 + 8 * privCnt); - - privNames = new String[privCnt]; - for (int i = 0; i < privCnt; i++) { - privNames[i] = packetIn.readString(true); + // [out] PLSAPR_USER_RIGHT_SET UserRights + // Alignment: 4 - Already aligned + if (packetIn.readReferentID() != 0) { + this.privNames = new RPCUnicodeString.NonNullTerminated[privCnt]; + // Maximum Count: [out] PLSAPR_USER_RIGHT_SET UserRights + // Alignment: 4 - Already aligned + packetIn.fullySkipBytes(4); + // Entries: [out] PLSAPR_USER_RIGHT_SET UserRights + for (int i = 0; i < this.privNames.length; i++) { + this.privNames[i] = new RPCUnicodeString.NonNullTerminated(); + this.privNames[i].unmarshalPreamble(packetIn); + } + for (final RPCUnicodeString.NonNullTerminated privName : this.privNames) { + privName.unmarshalEntity(packetIn); } + for (final RPCUnicodeString.NonNullTerminated privName : this.privNames) { + privName.unmarshalDeferrals(packetIn); + } + } else { + this.privNames = null; } } } - - diff --git a/src/main/java/com/rapid7/client/dcerpc/mslsad/messages/LsarEnumerateAccountsWithUserRightRequest.java b/src/main/java/com/rapid7/client/dcerpc/mslsad/messages/LsarEnumerateAccountsWithUserRightRequest.java index 8f1da48c..ee708654 100755 --- a/src/main/java/com/rapid7/client/dcerpc/mslsad/messages/LsarEnumerateAccountsWithUserRightRequest.java +++ b/src/main/java/com/rapid7/client/dcerpc/mslsad/messages/LsarEnumerateAccountsWithUserRightRequest.java @@ -53,12 +53,8 @@ public LsarEnumerateAccountsWithUserRightRequest(final byte[] policyHandle, public void marshal(PacketOutput packetOut) throws IOException { // [in] LSAPR_HANDLE PolicyHandle packetOut.write(this.policyHandle); - if (this.userRight == null) { - // Alignment: 4 - Already aligned, wrote 20 bytes above - packetOut.writeNull(); - } else { - // Alignment: 4 - Already aligned, wrote 20 bytes above - packetOut.writeReferentID(); + // Alignment: 4 - Already aligned, wrote 20 bytes above + if (packetOut.writeReferentID(this.userRight)) { packetOut.writeMarshallable(this.userRight); } } diff --git a/src/main/java/com/rapid7/client/dcerpc/mslsad/messages/LsarLookupNamesRequest.java b/src/main/java/com/rapid7/client/dcerpc/mslsad/messages/LsarLookupNamesRequest.java index a449e443..9be053f2 100644 --- a/src/main/java/com/rapid7/client/dcerpc/mslsad/messages/LsarLookupNamesRequest.java +++ b/src/main/java/com/rapid7/client/dcerpc/mslsad/messages/LsarLookupNamesRequest.java @@ -99,6 +99,7 @@ public class LsarLookupNamesRequest extends RequestCall { private final static short OP_NUM = 14; + // [in] LSAPR_HANDLE PolicyHandle, private final byte[] policyHandle; private final RPCUnicodeString.NonNullTerminated[] names; private final short lookupLevel; diff --git a/src/main/java/com/rapid7/client/dcerpc/mslsad/messages/LsarOpenPolicy2Request.java b/src/main/java/com/rapid7/client/dcerpc/mslsad/messages/LsarOpenPolicy2Request.java index 7e188ff8..dbbfe7af 100644 --- a/src/main/java/com/rapid7/client/dcerpc/mslsad/messages/LsarOpenPolicy2Request.java +++ b/src/main/java/com/rapid7/client/dcerpc/mslsad/messages/LsarOpenPolicy2Request.java @@ -20,8 +20,10 @@ import java.io.IOException; import com.rapid7.client.dcerpc.io.PacketOutput; +import com.rapid7.client.dcerpc.io.ndr.Alignment; import com.rapid7.client.dcerpc.messages.HandleResponse; import com.rapid7.client.dcerpc.messages.RequestCall; +import com.rapid7.client.dcerpc.objects.WChar; /** * LsarOpenPolicy2 @@ -39,11 +41,11 @@ public class LsarOpenPolicy2Request extends RequestCall { private final static short OP_NUM = 44; // [in, unique, string] wchar_t* SystemName - private final String systemName; + private final WChar.NullTerminated systemName; // [in] ACCESS_MASK DesiredAccess private final int desiredAccess; - public LsarOpenPolicy2Request(final String systemName, final int desiredAccess) { + public LsarOpenPolicy2Request(final WChar.NullTerminated systemName, final int desiredAccess) { super(OP_NUM); this.systemName = systemName; this.desiredAccess = desiredAccess; @@ -56,7 +58,11 @@ public HandleResponse getResponseObject() { @Override public void marshal(final PacketOutput packetOut) throws IOException { - packetOut.writeStringRef(systemName, true); + if (packetOut.writeReferentID(this.systemName)) { + packetOut.writeMarshallable(this.systemName); + // Align for LSAPR_OBJECT_ATTRIBUTES + packetOut.align(Alignment.FOUR); + } // LSAPR_OBJECT_ATTRIBUTES packetOut.writeInt(24); diff --git a/src/main/java/com/rapid7/client/dcerpc/mslsad/objects/LSAPRSIDEnumBuffer.java b/src/main/java/com/rapid7/client/dcerpc/mslsad/objects/LSAPRSIDEnumBuffer.java index caf37e14..9c997f3e 100644 --- a/src/main/java/com/rapid7/client/dcerpc/mslsad/objects/LSAPRSIDEnumBuffer.java +++ b/src/main/java/com/rapid7/client/dcerpc/mslsad/objects/LSAPRSIDEnumBuffer.java @@ -50,37 +50,33 @@ * field in this structure is not 0, this field MUST be non-NULL. If Entries * is 0, this field MUST be ignored.

*/ - public class LSAPRSIDEnumBuffer implements Marshallable { private final int entries; private final LSAPRSIDInformationArray lsaprSIDInformationArray; public LSAPRSIDEnumBuffer(RPCSID ... rpcSIDs) { - lsaprSIDInformationArray = new LSAPRSIDInformationArray(); + this.lsaprSIDInformationArray = new LSAPRSIDInformationArray(); for (RPCSID rpcsid : rpcSIDs) { - LSAPRSIDInformation lsaprSIDInformation = new LSAPRSIDInformation(rpcsid); - lsaprSIDInformationArray.addLSAPRSIDInformation(lsaprSIDInformation); + final LSAPRSIDInformation lsaprSIDInformation; + if (rpcsid != null) + lsaprSIDInformation = new LSAPRSIDInformation(rpcsid); + else + lsaprSIDInformation = null; + this.lsaprSIDInformationArray.addLSAPRSIDInformation(lsaprSIDInformation); } - entries = rpcSIDs.length; + this.entries = rpcSIDs.length; } - @Override public void marshalPreamble(PacketOutput out) - throws IOException - { + @Override public void marshalPreamble(PacketOutput out) { } - @Override public void marshalEntity(PacketOutput out) - throws IOException - { + @Override public void marshalEntity(PacketOutput out) throws IOException { out.writeInt(entries); - if (lsaprSIDInformationArray != null) out.writeReferentID(); - else out.writeNull(); + out.writeReferentID(this.lsaprSIDInformationArray); } - @Override public void marshalDeferrals(PacketOutput out) - throws IOException - { + @Override public void marshalDeferrals(PacketOutput out) throws IOException { out.writeMarshallable(lsaprSIDInformationArray); } } diff --git a/src/main/java/com/rapid7/client/dcerpc/mslsad/objects/LSAPRSIDInformation.java b/src/main/java/com/rapid7/client/dcerpc/mslsad/objects/LSAPRSIDInformation.java index 600c1c39..ddf31a8d 100644 --- a/src/main/java/com/rapid7/client/dcerpc/mslsad/objects/LSAPRSIDInformation.java +++ b/src/main/java/com/rapid7/client/dcerpc/mslsad/objects/LSAPRSIDInformation.java @@ -52,28 +52,23 @@ public class LSAPRSIDInformation implements Marshallable { - private RPCSID SID; + private RPCSID sid; - public LSAPRSIDInformation(RPCSID SID){ - this.SID = SID; + public LSAPRSIDInformation(RPCSID sid) { + if (sid == null) + throw new IllegalArgumentException("sid must not be null"); + this.sid = sid; } - @Override public void marshalPreamble(PacketOutput out) - throws IOException - { + @Override public void marshalPreamble(PacketOutput out) throws IOException { } - @Override public void marshalEntity(PacketOutput out) - throws IOException - { - out.align(Alignment.FOUR); - out.writeMarshallable(SID); + @Override public void marshalEntity(PacketOutput out) throws IOException { + out.writeMarshallable(sid); } - @Override public void marshalDeferrals(PacketOutput out) - throws IOException - { - + @Override public void marshalDeferrals(PacketOutput out) throws IOException { + // No deferrals } } diff --git a/src/main/java/com/rapid7/client/dcerpc/mslsad/objects/LSAPRSIDInformationArray.java b/src/main/java/com/rapid7/client/dcerpc/mslsad/objects/LSAPRSIDInformationArray.java index 476fbe90..3cb0e066 100644 --- a/src/main/java/com/rapid7/client/dcerpc/mslsad/objects/LSAPRSIDInformationArray.java +++ b/src/main/java/com/rapid7/client/dcerpc/mslsad/objects/LSAPRSIDInformationArray.java @@ -31,39 +31,34 @@ NDR Conformant Array */ -public class LSAPRSIDInformationArray implements Marshallable -{ - +public class LSAPRSIDInformationArray implements Marshallable { private List lsaprsidInformations; public LSAPRSIDInformationArray(){ lsaprsidInformations = new ArrayList<>(); } - public void addLSAPRSIDInformation(LSAPRSIDInformation SIDInfo){ - lsaprsidInformations.add(SIDInfo); + public void addLSAPRSIDInformation(LSAPRSIDInformation sidInfo){ + lsaprsidInformations.add(sidInfo); } - @Override public void marshalPreamble(PacketOutput out) - throws IOException - { + @Override + public void marshalPreamble(PacketOutput out) throws IOException { out.writeInt(lsaprsidInformations.size()); } - @Override public void marshalEntity(PacketOutput out) - throws IOException - { - for (LSAPRSIDInformation lsaprsidInformation: lsaprsidInformations) { - if (lsaprsidInformation != null) out.writeReferentID(); - else out.writeNull(); + @Override + public void marshalEntity(PacketOutput out) throws IOException { + for (final LSAPRSIDInformation lsaprsidInformation: lsaprsidInformations) { + out.writeReferentID(lsaprsidInformation); } } - @Override public void marshalDeferrals(PacketOutput out) - throws IOException - { - for (LSAPRSIDInformation lsaprsidInformation: lsaprsidInformations) { - out.writeMarshallable(lsaprsidInformation); + @Override + public void marshalDeferrals(PacketOutput out) throws IOException { + for (final LSAPRSIDInformation lsaprsidInformation: lsaprsidInformations) { + if (lsaprsidInformation != null) + out.writeMarshallable(lsaprsidInformation); } } } diff --git a/src/main/java/com/rapid7/client/dcerpc/mslsad/objects/LSAPRTranslatedName.java b/src/main/java/com/rapid7/client/dcerpc/mslsad/objects/LSAPRTranslatedName.java index 3611aad3..d98f3caf 100644 --- a/src/main/java/com/rapid7/client/dcerpc/mslsad/objects/LSAPRTranslatedName.java +++ b/src/main/java/com/rapid7/client/dcerpc/mslsad/objects/LSAPRTranslatedName.java @@ -67,8 +67,7 @@ * values MUST NOT be used.

* */ -public class LSAPRTranslatedName implements Unmarshallable -{ +public class LSAPRTranslatedName implements Unmarshallable { // SID_NAME_USE Use; private short use; // RPC_UNICODE_STRING Name; @@ -108,7 +107,8 @@ public int getUse() { return use; } - public RPCUnicodeString getName() { return name; + public RPCUnicodeString getName() { + return name; } public int getDomainIndex() { diff --git a/src/main/java/com/rapid7/client/dcerpc/msrrp/RegistryService.java b/src/main/java/com/rapid7/client/dcerpc/msrrp/RegistryService.java index 9236d1fb..e82a005b 100644 --- a/src/main/java/com/rapid7/client/dcerpc/msrrp/RegistryService.java +++ b/src/main/java/com/rapid7/client/dcerpc/msrrp/RegistryService.java @@ -18,22 +18,24 @@ */ package com.rapid7.client.dcerpc.msrrp; -import static com.rapid7.client.dcerpc.mserref.SystemErrorCode.ERROR_NO_MORE_ITEMS; -import static com.rapid7.client.dcerpc.mserref.SystemErrorCode.ERROR_SUCCESS; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; -import java.util.EnumSet; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Objects; import com.google.common.base.Strings; -import com.hierynomus.msdtyp.AccessMask; -import com.hierynomus.protocol.commons.EnumWithValue.EnumUtils; import com.rapid7.client.dcerpc.RPCException; +import com.rapid7.client.dcerpc.io.ndr.arrays.RPCConformantVaryingByteArray; import com.rapid7.client.dcerpc.messages.HandleResponse; +import com.rapid7.client.dcerpc.mserref.SystemErrorCode; +import com.rapid7.client.dcerpc.msrrp.dto.RegistryHive; +import com.rapid7.client.dcerpc.msrrp.dto.RegistryKey; +import com.rapid7.client.dcerpc.msrrp.dto.RegistryKeyInfo; +import com.rapid7.client.dcerpc.msrrp.dto.RegistryValue; +import com.rapid7.client.dcerpc.msrrp.dto.RegistryValueType; import com.rapid7.client.dcerpc.msrrp.messages.BaseRegEnumKeyRequest; import com.rapid7.client.dcerpc.msrrp.messages.BaseRegEnumKeyResponse; import com.rapid7.client.dcerpc.msrrp.messages.BaseRegEnumValueRequest; @@ -46,10 +48,14 @@ import com.rapid7.client.dcerpc.msrrp.messages.BaseRegQueryValueRequest; import com.rapid7.client.dcerpc.msrrp.messages.BaseRegQueryValueResponse; import com.rapid7.client.dcerpc.msrrp.messages.HandleRequest; -import com.rapid7.client.dcerpc.objects.FileTime; +import com.rapid7.client.dcerpc.msrrp.dto.FileTime; +import com.rapid7.client.dcerpc.objects.RPCUnicodeString; import com.rapid7.client.dcerpc.service.Service; import com.rapid7.client.dcerpc.transport.RPCTransport; +import static com.rapid7.client.dcerpc.mserref.SystemErrorCode.ERROR_NO_MORE_ITEMS; +import static com.rapid7.client.dcerpc.mserref.SystemErrorCode.ERROR_SUCCESS; + /** * This class implements a partial registry service in accordance with [MS-RRP]: Windows Remote Registry Protocol which * specifies the Windows Remote Registry Protocol, a remote procedure call (RPC)-based client/server protocol that is @@ -62,7 +68,8 @@ public class RegistryService extends Service { private final static int MAX_REGISTRY_KEY_CLASS_SIZE = 32767; private final static int MAX_REGISTRY_VALUE_NAME_SIZE = 32767; private final static int MAX_REGISTRY_VALUE_DATA_SIZE = 1048576; - private final static EnumSet ACCESS_MASK = EnumSet.of(AccessMask.MAXIMUM_ALLOWED); + private final static int MAXIMUM_ALLOWED = 33554432; + private final static int ACCESS_SYSTEM_SECURITY = 16777216; private final Map hiveCache = new HashMap<>(); private final Map keyPathCache = new HashMap<>(); @@ -74,14 +81,9 @@ public boolean doesKeyExist(final String hiveName, final String keyPath) throws try { openKey(hiveName, keyPath); } catch (final RPCException exception) { - if (exception.hasErrorCode()) { - switch (exception.getErrorCode()) { - case ERROR_FILE_NOT_FOUND: - return false; - default: - throw exception; - } - } + if (isFileNotFound(exception)) + return false; + throw exception; } return true; } @@ -91,14 +93,9 @@ public boolean doesValueExist(final String hiveName, final String keyPath, final try { getValue(hiveName, keyPath, valueName); } catch (final RPCException exception) { - if (exception.hasErrorCode()) { - switch (exception.getErrorCode()) { - case ERROR_FILE_NOT_FOUND: - return false; - default: - throw exception; - } - } + if (isFileNotFound(exception)) + return false; + throw exception; } return true; } @@ -107,7 +104,9 @@ public RegistryKeyInfo getKeyInfo(final String hiveName, final String keyPath) t final byte[] handle = openKey(hiveName, keyPath); final BaseRegQueryInfoKeyRequest request = new BaseRegQueryInfoKeyRequest(handle); final BaseRegQueryInfoKeyResponse response = callExpectSuccess(request, "BaseRegQueryInfoKey"); - return new RegistryKeyInfo(response.getSubKeys(), response.getMaxSubKeyLen(), response.getMaxClassLen(), response.getValues(), response.getMaxValueNameLen(), response.getMaxValueLen(), response.getSecurityDescriptor(), response.getLastWriteTime()); + return new RegistryKeyInfo(response.getSubKeys(), response.getMaxSubKeyLen(), response.getMaxClassLen(), + response.getValues(), response.getMaxValueNameLen(), response.getMaxValueLen(), + response.getSecurityDescriptor(), response.getLastWriteTime()); } public List getSubKeys(final String hiveName, final String keyPath) throws IOException { @@ -119,7 +118,9 @@ public List getSubKeys(final String hiveName, final String keyPath) final int returnCode = response.getReturnValue(); if (ERROR_SUCCESS.is(returnCode)) { - keyNames.add(new RegistryKey(response.getName(), new FileTime(response.getLastWriteTime()))); + keyNames.add(new RegistryKey( + parseRPCUnicodeString(response.getLpNameOut()), + new FileTime(response.getLastWriteTime()))); } else if (ERROR_NO_MORE_ITEMS.is(returnCode)) { return Collections.unmodifiableList(new ArrayList<>(keyNames)); } else { @@ -135,9 +136,11 @@ public List getValues(final String hiveName, final String keyPath final BaseRegEnumValueRequest request = new BaseRegEnumValueRequest(handle, index, MAX_REGISTRY_VALUE_NAME_SIZE, MAX_REGISTRY_VALUE_DATA_SIZE); final BaseRegEnumValueResponse response = call(request); final int returnCode = response.getReturnValue(); - if (ERROR_SUCCESS.is(returnCode)) { - values.add(new RegistryValue(response.getName(), response.getType(), response.getData())); + values.add(new RegistryValue( + parseRPCUnicodeString(response.getName()), + RegistryValueType.getRegistryValueType(response.getType()), + response.getData().getArray())); } else if (ERROR_NO_MORE_ITEMS.is(returnCode)) { return Collections.unmodifiableList(new ArrayList<>(values)); } else { @@ -150,20 +153,22 @@ public RegistryValue getValue(final String hiveName, final String keyPath, final throws IOException { final String canonicalizedValueName = Strings.nullToEmpty(valueName); final byte[] handle = openKey(hiveName, keyPath); - final BaseRegQueryValueRequest request = new BaseRegQueryValueRequest(handle, canonicalizedValueName, MAX_REGISTRY_VALUE_DATA_SIZE); + final BaseRegQueryValueRequest request = new BaseRegQueryValueRequest(handle, RPCUnicodeString.NullTerminated.of(canonicalizedValueName), MAX_REGISTRY_VALUE_DATA_SIZE); final BaseRegQueryValueResponse response = callExpectSuccess(request, "BaseRegQueryValue"); - return new RegistryValue(canonicalizedValueName, response.getType(), response.getData()); + final RPCConformantVaryingByteArray data = response.getData(); + return new RegistryValue(canonicalizedValueName, + RegistryValueType.getRegistryValueType(response.getType()), + (data == null ? null : data.getArray())); } public byte[] getKeySecurity(final String hiveName, final String keyPath, final int securityDescriptorType) throws IOException { - final byte[] handle = openKey(hiveName, keyPath, - (int) EnumUtils.toLong(EnumSet.of(AccessMask.MAXIMUM_ALLOWED, AccessMask.ACCESS_SYSTEM_SECURITY))); + final byte[] handle = openKey(hiveName, keyPath, MAXIMUM_ALLOWED | ACCESS_SYSTEM_SECURITY); final int size = getKeyInfo(hiveName, keyPath).getSecurityDescriptor(); - final BaseRegGetKeySecurityRequest request = new BaseRegGetKeySecurityRequest(handle, securityDescriptorType, - size); + final BaseRegGetKeySecurityRequest request = + new BaseRegGetKeySecurityRequest(handle, securityDescriptorType, size); final BaseRegGetKeySecurityResponse response = callExpectSuccess(request, "BaseRegGetKeySecurity"); - return response.getRawSecurityDescriptor(); + return response.getpRpcSecurityDescriptorOut().getLpSecurityDescriptor(); } protected String canonicalize(String keyPath) { @@ -179,19 +184,17 @@ protected String canonicalize(String keyPath) { } protected byte[] openHive(final String hiveName) throws IOException { - if (hiveName == null) { - throw new IllegalArgumentException("Invalid hive: " + hiveName); - } + if (hiveName == null) + throw new IllegalArgumentException("Invalid hive: null"); final RegistryHive hive = RegistryHive.getRegistryHiveByName(hiveName); - if (hive == null) { + if (hive == null) throw new IllegalArgumentException("Unknown hive: " + hiveName); - } synchronized (hiveCache) { if (hiveCache.containsKey(hive)) { return hiveCache.get(hive); } else { final short opNum = hive.getOpNum(); - final HandleRequest request = new HandleRequest(opNum, ACCESS_MASK); + final HandleRequest request = new HandleRequest(opNum, MAXIMUM_ALLOWED); final HandleResponse response = callExpectSuccess(request, hive.getOpName()); final byte[] handle = response.getHandle(); hiveCache.put(hive, handle); @@ -201,11 +204,10 @@ protected byte[] openHive(final String hiveName) throws IOException { } protected byte[] openKey(final String hiveName, final String keyPath) throws IOException { - return openKey(hiveName, keyPath, (int) AccessMask.MAXIMUM_ALLOWED.getValue()); + return openKey(hiveName, keyPath, MAXIMUM_ALLOWED); } - protected byte[] openKey(final String hiveName, final String keyPath, int desiredAccess) - throws IOException { + private byte[] openKey(final String hiveName, final String keyPath, int desiredAccess) throws IOException { final String canonicalizedKeyPath = canonicalize(keyPath); if (canonicalizedKeyPath.isEmpty()) { return openHive(hiveName); @@ -216,7 +218,7 @@ protected byte[] openKey(final String hiveName, final String keyPath, int desire return keyPathCache.get(cachingKey); } final byte[] hiveHandle = openHive(hiveName); - final BaseRegOpenKey request = new BaseRegOpenKey(hiveHandle, canonicalizedKeyPath, 0, desiredAccess); + final BaseRegOpenKey request = new BaseRegOpenKey(hiveHandle, RPCUnicodeString.NullTerminated.of(canonicalizedKeyPath), 0, desiredAccess); final HandleResponse response = callExpectSuccess(request, "BaseRegOpenKey"); final byte[] keyHandle = response.getHandle(); keyPathCache.put(cachingKey, keyHandle); @@ -224,6 +226,10 @@ protected byte[] openKey(final String hiveName, final String keyPath, int desire } } + private boolean isFileNotFound(final RPCException exception) { + return exception != null && exception.getErrorCode() == SystemErrorCode.ERROR_FILE_NOT_FOUND; + } + private static class RegistryHandleKey { private final String path; private final int access; diff --git a/src/main/java/com/rapid7/client/dcerpc/objects/FileTime.java b/src/main/java/com/rapid7/client/dcerpc/msrrp/dto/FileTime.java similarity index 87% rename from src/main/java/com/rapid7/client/dcerpc/objects/FileTime.java rename to src/main/java/com/rapid7/client/dcerpc/msrrp/dto/FileTime.java index f3f038b9..fb0887b2 100644 --- a/src/main/java/com/rapid7/client/dcerpc/objects/FileTime.java +++ b/src/main/java/com/rapid7/client/dcerpc/msrrp/dto/FileTime.java @@ -1,22 +1,24 @@ -/** +/* * Copyright 2017, Rapid7, Inc. * * License: BSD-3-clause * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright notice, + * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - * * Redistributions in binary form must reproduce the above copyright + * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * * Neither the name of the copyright holder nor the names of its contributors + * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. + * + * */ -package com.rapid7.client.dcerpc.objects; +package com.rapid7.client.dcerpc.msrrp.dto; import java.text.SimpleDateFormat; import java.util.Date; diff --git a/src/main/java/com/rapid7/client/dcerpc/msrrp/RegistryHive.java b/src/main/java/com/rapid7/client/dcerpc/msrrp/dto/RegistryHive.java similarity index 95% rename from src/main/java/com/rapid7/client/dcerpc/msrrp/RegistryHive.java rename to src/main/java/com/rapid7/client/dcerpc/msrrp/dto/RegistryHive.java index 62522cb0..377b878e 100644 --- a/src/main/java/com/rapid7/client/dcerpc/msrrp/RegistryHive.java +++ b/src/main/java/com/rapid7/client/dcerpc/msrrp/dto/RegistryHive.java @@ -1,27 +1,27 @@ -/** +/* * Copyright 2017, Rapid7, Inc. * * License: BSD-3-clause * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright notice, + * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - * * Redistributions in binary form must reproduce the above copyright + * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * * Neither the name of the copyright holder nor the names of its contributors + * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. + * + * */ -package com.rapid7.client.dcerpc.msrrp; +package com.rapid7.client.dcerpc.msrrp.dto; -import java.util.EnumSet; import java.util.HashMap; import java.util.Map; -import com.hierynomus.msdtyp.AccessMask; import com.rapid7.client.dcerpc.msrrp.messages.*; /** @@ -131,7 +131,7 @@ public short getOpNum() { return opNum; } - public HandleRequest getRequest(final EnumSet accessMask) { + public HandleRequest getRequest(int accessMask) { return new HandleRequest(opNum, accessMask); } diff --git a/src/main/java/com/rapid7/client/dcerpc/msrrp/RegistryKey.java b/src/main/java/com/rapid7/client/dcerpc/msrrp/dto/RegistryKey.java similarity index 84% rename from src/main/java/com/rapid7/client/dcerpc/msrrp/RegistryKey.java rename to src/main/java/com/rapid7/client/dcerpc/msrrp/dto/RegistryKey.java index 3b0f2d14..8bb12c16 100644 --- a/src/main/java/com/rapid7/client/dcerpc/msrrp/RegistryKey.java +++ b/src/main/java/com/rapid7/client/dcerpc/msrrp/dto/RegistryKey.java @@ -1,25 +1,26 @@ -/** +/* * Copyright 2017, Rapid7, Inc. * * License: BSD-3-clause * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright notice, + * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - * * Redistributions in binary form must reproduce the above copyright + * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * * Neither the name of the copyright holder nor the names of its contributors + * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. + * + * */ -package com.rapid7.client.dcerpc.msrrp; +package com.rapid7.client.dcerpc.msrrp.dto; import java.util.Objects; -import com.rapid7.client.dcerpc.objects.FileTime; public class RegistryKey { private final String name; diff --git a/src/main/java/com/rapid7/client/dcerpc/msrrp/RegistryKeyInfo.java b/src/main/java/com/rapid7/client/dcerpc/msrrp/dto/RegistryKeyInfo.java similarity index 60% rename from src/main/java/com/rapid7/client/dcerpc/msrrp/RegistryKeyInfo.java rename to src/main/java/com/rapid7/client/dcerpc/msrrp/dto/RegistryKeyInfo.java index f1147de4..22c3fc98 100644 --- a/src/main/java/com/rapid7/client/dcerpc/msrrp/RegistryKeyInfo.java +++ b/src/main/java/com/rapid7/client/dcerpc/msrrp/dto/RegistryKeyInfo.java @@ -1,22 +1,26 @@ -/** +/* * Copyright 2017, Rapid7, Inc. * * License: BSD-3-clause * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright notice, + * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - * * Redistributions in binary form must reproduce the above copyright + * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * * Neither the name of the copyright holder nor the names of its contributors + * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. + * + * */ -package com.rapid7.client.dcerpc.msrrp; +package com.rapid7.client.dcerpc.msrrp.dto; + +import java.util.Objects; public class RegistryKeyInfo { private final int subKeys; @@ -94,4 +98,36 @@ public int getSecurityDescriptor() { public long getLastWriteTime() { return lastWriteTime; } + + @Override + public int hashCode() { + return Objects.hash(getSubKeys(), getMaxSubKeyLen(), getMaxClassLen(), getValues(), + getMaxValueNameLen(), getMaxValueLen(), getSecurityDescriptor(), getLastWriteTime()); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } else if (! (obj instanceof RegistryKeyInfo)) { + return false; + } + final RegistryKeyInfo other = (RegistryKeyInfo) obj; + return getSubKeys() == other.getSubKeys() + && getMaxSubKeyLen() == other.getMaxSubKeyLen() + && getMaxClassLen() == other.getMaxClassLen() + && getValues() == other.getValues() + && getMaxValueNameLen() == other.getMaxValueNameLen() + && getMaxValueLen() == other.getMaxValueLen() + && getSecurityDescriptor() == other.getSecurityDescriptor() + && getLastWriteTime() == other.getLastWriteTime(); + } + + @Override + public String toString() { + return String.format("RegistryKeyInfo{subKeys: %d, maxSubKeyLen: %d, maxClassLen: %d, " + + "values: %d, maxValueNameLen: %d, maxValueLen: %d, securityDescriptor: %d," + + "lastWriteTime: %d}", getSubKeys(), getMaxSubKeyLen(), getMaxClassLen(), + getValues(), getMaxValueNameLen(), getMaxValueLen(), getSecurityDescriptor(), getLastWriteTime()); + } } diff --git a/src/main/java/com/rapid7/client/dcerpc/msrrp/RegistryValue.java b/src/main/java/com/rapid7/client/dcerpc/msrrp/dto/RegistryValue.java similarity index 97% rename from src/main/java/com/rapid7/client/dcerpc/msrrp/RegistryValue.java rename to src/main/java/com/rapid7/client/dcerpc/msrrp/dto/RegistryValue.java index a07349db..0175408b 100644 --- a/src/main/java/com/rapid7/client/dcerpc/msrrp/RegistryValue.java +++ b/src/main/java/com/rapid7/client/dcerpc/msrrp/dto/RegistryValue.java @@ -1,22 +1,24 @@ -/** +/* * Copyright 2017, Rapid7, Inc. * * License: BSD-3-clause * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright notice, + * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - * * Redistributions in binary form must reproduce the above copyright + * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * * Neither the name of the copyright holder nor the names of its contributors + * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. + * + * */ -package com.rapid7.client.dcerpc.msrrp; +package com.rapid7.client.dcerpc.msrrp.dto; import javax.activation.UnsupportedDataTypeException; import java.io.IOException; diff --git a/src/main/java/com/rapid7/client/dcerpc/msrrp/RegistryValueType.java b/src/main/java/com/rapid7/client/dcerpc/msrrp/dto/RegistryValueType.java similarity index 85% rename from src/main/java/com/rapid7/client/dcerpc/msrrp/RegistryValueType.java rename to src/main/java/com/rapid7/client/dcerpc/msrrp/dto/RegistryValueType.java index 45ad364b..5fea51f0 100644 --- a/src/main/java/com/rapid7/client/dcerpc/msrrp/RegistryValueType.java +++ b/src/main/java/com/rapid7/client/dcerpc/msrrp/dto/RegistryValueType.java @@ -1,22 +1,24 @@ -/** +/* * Copyright 2017, Rapid7, Inc. * * License: BSD-3-clause * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright notice, + * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - * * Redistributions in binary form must reproduce the above copyright + * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * * Neither the name of the copyright holder nor the names of its contributors + * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. + * + * */ -package com.rapid7.client.dcerpc.msrrp; +package com.rapid7.client.dcerpc.msrrp.dto; import java.util.HashMap; import java.util.Map; diff --git a/src/main/java/com/rapid7/client/dcerpc/msrrp/messages/BaseRegEnumKeyRequest.java b/src/main/java/com/rapid7/client/dcerpc/msrrp/messages/BaseRegEnumKeyRequest.java index 06c3ee14..de4f2a5c 100644 --- a/src/main/java/com/rapid7/client/dcerpc/msrrp/messages/BaseRegEnumKeyRequest.java +++ b/src/main/java/com/rapid7/client/dcerpc/msrrp/messages/BaseRegEnumKeyRequest.java @@ -20,7 +20,9 @@ import java.io.IOException; import com.rapid7.client.dcerpc.io.PacketOutput; +import com.rapid7.client.dcerpc.io.ndr.Alignment; import com.rapid7.client.dcerpc.messages.RequestCall; +import com.rapid7.client.dcerpc.objects.RPCUnicodeString; /** * 3.1.5.10 BaseRegEnumKey (Opnum 9)
@@ -250,10 +252,23 @@ public void marshal(final PacketOutput packetOut) throws IOException { // Pointer to Last Changed Time (NTTIME) // Referent ID: 0x0002000c // Last Changed Time: No time specified (0) - packetOut.write(hKey); - packetOut.writeInt(index); - packetOut.writeStringBuffer(nameLen); - packetOut.writeStringBufferRef(classLen); - packetOut.writeLongRef(Long.valueOf(0)); + // [in] RPC_HKEY hKey + packetOut.write(this.hKey); + // [in] DWORD dwIndex + // Alignment: 4 - Already aligned, wrote 20 bytes above + packetOut.writeInt(this.index); + // [in] PRRP_UNICODE_STRING lpNameIn + // Alignment: 4 - Already aligned + packetOut.writeEmptyRPCUnicodeString(this.nameLen); + // [in, unique] PRRP_UNICODE_STRING lpClassIn, + // Alignment: 4 - Already aligned + packetOut.writeReferentID(); + // Alignment: 4 - Already aligned + packetOut.writeEmptyRPCUnicodeString(this.classLen); + // [in, out, unique] PFILETIME lpftLastWriteTime + // Alignment: 4 - Already aligned + packetOut.writeReferentID(); + // Alignment: 4 - Already aligned - This is a struct of 2x 4bytes. Wrote 72 bytes so far + packetOut.writeLong(0L); } } diff --git a/src/main/java/com/rapid7/client/dcerpc/msrrp/messages/BaseRegEnumKeyResponse.java b/src/main/java/com/rapid7/client/dcerpc/msrrp/messages/BaseRegEnumKeyResponse.java index e63eead0..5609771b 100644 --- a/src/main/java/com/rapid7/client/dcerpc/msrrp/messages/BaseRegEnumKeyResponse.java +++ b/src/main/java/com/rapid7/client/dcerpc/msrrp/messages/BaseRegEnumKeyResponse.java @@ -20,10 +20,9 @@ import java.io.IOException; import com.rapid7.client.dcerpc.io.PacketInput; +import com.rapid7.client.dcerpc.io.ndr.Alignment; import com.rapid7.client.dcerpc.messages.RequestResponse; -import com.rapid7.client.dcerpc.objects.FileTime; - -import static com.rapid7.client.dcerpc.mserref.SystemErrorCode.ERROR_SUCCESS; +import com.rapid7.client.dcerpc.objects.RPCUnicodeString; /** * Example: @@ -71,14 +70,24 @@ * */ public class BaseRegEnumKeyResponse extends RequestResponse { - private String name; + // [out] PRRP_UNICODE_STRING lpNameOut + private RPCUnicodeString.NullTerminated lpNameOut; + // [out] PRPC_UNICODE_STRING* lplpClassOut + private RPCUnicodeString.NullTerminated lpClassOut; private long lastWriteTime; /** * @return The name of the retrieved key. */ - public String getName() { - return name; + public RPCUnicodeString.NullTerminated getLpNameOut() { + return lpNameOut; + } + + /** + * @return The class of the retrieved key. This parameter can be NULL. + */ + public RPCUnicodeString.NullTerminated getLpClassOut() { + return lpClassOut; } /** @@ -129,8 +138,25 @@ public void unmarshalResponse(final PacketInput packetIn) throws IOException { // Referent ID: 0x0002000c // Last Changed Time: Jun 15, 2017 15:29:36.566813400 EDT // Windows Error: WERR_OK (0x00000000) - this.name = packetIn.readStringBuf(true); - packetIn.readStringBufRef(true); - this.lastWriteTime = packetIn.readLongRef(); + // [out] PRRP_UNICODE_STRING lpNameOut + this.lpNameOut = new RPCUnicodeString.NullTerminated(); + packetIn.readUnmarshallable(this.lpNameOut); + // [out] PRPC_UNICODE_STRING* lplpClassOut + packetIn.align(Alignment.FOUR); + if (packetIn.readReferentID() != 0) { + this.lpClassOut = new RPCUnicodeString.NullTerminated(); + packetIn.readUnmarshallable(this.lpClassOut); + // Alignment for lpftLastWriteTime + packetIn.align(Alignment.FOUR); + } else { + this.lpClassOut = null; + // Alignment for lpftLastWriteTime not necessary + } + if (packetIn.readReferentID() != 0) { + // Alignment: 4 - Already aligned - This is a struct of 2x 4bytes + this.lastWriteTime = packetIn.readLong(); + } else { + this.lastWriteTime = 0L; + } } } diff --git a/src/main/java/com/rapid7/client/dcerpc/msrrp/messages/BaseRegEnumValueRequest.java b/src/main/java/com/rapid7/client/dcerpc/msrrp/messages/BaseRegEnumValueRequest.java index 25bafb4e..33220198 100644 --- a/src/main/java/com/rapid7/client/dcerpc/msrrp/messages/BaseRegEnumValueRequest.java +++ b/src/main/java/com/rapid7/client/dcerpc/msrrp/messages/BaseRegEnumValueRequest.java @@ -245,12 +245,33 @@ public void marshal(final PacketOutput packetOut) throws IOException { // .... .... 0... .... .... .... .... .... = Access SACL: Not set // Standard rights: 0x00000000 // WINREG specific rights: 0x00000000 - packetOut.write(hKey); - packetOut.writeInt(index); - packetOut.writeStringBuffer(valueNameLen); - packetOut.writeIntRef(0); - packetOut.writeEmptyArrayRef(dataLen); - packetOut.writeIntRef(dataLen); - packetOut.writeIntRef(0); + // [in] RPC_HKEY hKey + packetOut.write(this.hKey); + // [in] DWORD dwIndex + // Alignment: 4 - Already aligned + packetOut.writeInt(this.index); + // [in] PRRP_UNICODE_STRING lpValueNameIn + // Alignment: 4 - Already aligned + packetOut.writeEmptyRPCUnicodeString(this.valueNameLen); + // [in, out, unique] LPDWORD lpType + // Alignment: 4 - Already aligned + packetOut.writeReferentID(); + // Alignment: 4 - Already aligned + packetOut.writeInt(0); + // [in, out, unique, size_is(lpcbData?*lpcbData:0), length_is(lpcbLen?*lpcbLen:0), range(0, 0x4000000)] LPBYTE lpData, + // Alignment: 4 - Already aligned + packetOut.writeReferentID(); + // Alignment: 4 - Already aligned + packetOut.writeEmptyCVArray(this.dataLen); + // [in, out, unique] LPDWORD lpcbData + // Alignment: 4 - Already aligned + packetOut.writeReferentID(); + // Alignment: 4 - Already aligned + packetOut.writeInt(this.dataLen); + // [in, out, unique] LPDWORD lpcbLen + // Alignment: 4 - Already aligned + packetOut.writeReferentID(); + // Alignment: 4 - Already aligned + packetOut.writeInt(0); } } diff --git a/src/main/java/com/rapid7/client/dcerpc/msrrp/messages/BaseRegEnumValueResponse.java b/src/main/java/com/rapid7/client/dcerpc/msrrp/messages/BaseRegEnumValueResponse.java index 845d35b1..9c53c1c2 100644 --- a/src/main/java/com/rapid7/client/dcerpc/msrrp/messages/BaseRegEnumValueResponse.java +++ b/src/main/java/com/rapid7/client/dcerpc/msrrp/messages/BaseRegEnumValueResponse.java @@ -20,10 +20,10 @@ import java.io.IOException; import com.rapid7.client.dcerpc.io.PacketInput; +import com.rapid7.client.dcerpc.io.ndr.Alignment; +import com.rapid7.client.dcerpc.io.ndr.arrays.RPCConformantVaryingByteArray; import com.rapid7.client.dcerpc.messages.RequestResponse; -import com.rapid7.client.dcerpc.msrrp.RegistryValueType; - -import static com.rapid7.client.dcerpc.mserref.SystemErrorCode.ERROR_SUCCESS; +import com.rapid7.client.dcerpc.objects.RPCUnicodeString; /** * Example: @@ -74,28 +74,28 @@ * */ public class BaseRegEnumValueResponse extends RequestResponse { - private String name; - private RegistryValueType type; - private byte[] data; + private RPCUnicodeString.NullTerminated name; + private Integer type; + private RPCConformantVaryingByteArray data; /** * @return The retrieved value name. */ - public String getName() { + public RPCUnicodeString.NullTerminated getName() { return name; } /** - * @return The {@link RegistryValueType} of the value. + * @return The type of the value. */ - public RegistryValueType getType() { + public Integer getType() { return type; } /** * @return The data of the value entry. */ - public byte[] getData() { + public RPCConformantVaryingByteArray getData() { return data; } @@ -161,11 +161,26 @@ public void unmarshalResponse(final PacketInput packetIn) throws IOException { // Referent ID: 0x00020010 // Length: 22 // Windows Error: WERR_OK (0x00000000) - this.name = packetIn.readStringBuf(true); - this.type = RegistryValueType.getRegistryValueType(packetIn.readIntRef()); - this.data = packetIn.readByteArrayRef(); - - packetIn.readIntRef(); - packetIn.readIntRef(); + // [out] PRPC_UNICODE_STRING lpValueNameOut + this.name = new RPCUnicodeString.NullTerminated(); + packetIn.readUnmarshallable(this.name); + // [in, out, unique] LPDWORD lpType + packetIn.align(Alignment.FOUR); + // Alignment: 4 - Already aligned + if (packetIn.readReferentID() != 0) + this.type = packetIn.readInt(); + else + this.type = null; + // [in, out, unique, size_is(lpcbData?*lpcbData:0), length_is(lpcbLen?*lpcbLen:0), range(0, 0x4000000)] LPBYTE lpData, + // Alignment: 4 - Already aligned + packetIn.readReferentID(); + this.data = new RPCConformantVaryingByteArray(); + packetIn.readUnmarshallable(this.data); + // [in, out, unique] LPDWORD lpcbData + packetIn.align(Alignment.FOUR); + packetIn.fullySkipBytes(8); + // [in, out, unique] LPDWORD lpcbLen + // Alignment: 4 - Already aligned + packetIn.fullySkipBytes(8); } } diff --git a/src/main/java/com/rapid7/client/dcerpc/msrrp/messages/BaseRegGetKeySecurityRequest.java b/src/main/java/com/rapid7/client/dcerpc/msrrp/messages/BaseRegGetKeySecurityRequest.java index 02f69461..f1de8e74 100644 --- a/src/main/java/com/rapid7/client/dcerpc/msrrp/messages/BaseRegGetKeySecurityRequest.java +++ b/src/main/java/com/rapid7/client/dcerpc/msrrp/messages/BaseRegGetKeySecurityRequest.java @@ -20,6 +20,7 @@ import java.io.IOException; import com.rapid7.client.dcerpc.io.PacketOutput; +import com.rapid7.client.dcerpc.io.ndr.arrays.RPCConformantVaryingByteArray; import com.rapid7.client.dcerpc.messages.RequestCall; import com.rapid7.client.dcerpc.msrrp.objects.RPCSecurityDescriptor; @@ -79,10 +80,15 @@ public BaseRegGetKeySecurityRequest(final byte[] hKey, final int securityDescrip @Override public void marshal(final PacketOutput out) throws IOException { - out.write(hKey); - out.writeInt(securityDescriptorInfo); + // [in] RPC_HKEY hKey + out.write(this.hKey); + // [in] SECURITY_INFORMATION SecurityInformation + // Alignment: 4 - Already aligned, wrote 20 bytes above + out.writeInt(this.securityDescriptorInfo); + // [in] PRPC_SECURITY_DESCRIPTOR pRpcSecurityDescriptorIn final RPCSecurityDescriptor sd = new RPCSecurityDescriptor(); - sd.setCbInSecurityDescriptor(securityDescriptorSize); + sd.setCbInSecurityDescriptor(this.securityDescriptorSize); + sd.setLpSecurityDescriptor(new byte[0]); out.writeMarshallable(sd); } diff --git a/src/main/java/com/rapid7/client/dcerpc/msrrp/messages/BaseRegGetKeySecurityResponse.java b/src/main/java/com/rapid7/client/dcerpc/msrrp/messages/BaseRegGetKeySecurityResponse.java index 413d27e0..d4d1581b 100644 --- a/src/main/java/com/rapid7/client/dcerpc/msrrp/messages/BaseRegGetKeySecurityResponse.java +++ b/src/main/java/com/rapid7/client/dcerpc/msrrp/messages/BaseRegGetKeySecurityResponse.java @@ -20,19 +20,21 @@ import java.io.IOException; import com.rapid7.client.dcerpc.io.PacketInput; +import com.rapid7.client.dcerpc.io.ndr.arrays.RPCConformantVaryingByteArray; import com.rapid7.client.dcerpc.messages.RequestResponse; import com.rapid7.client.dcerpc.msrrp.objects.RPCSecurityDescriptor; public class BaseRegGetKeySecurityResponse extends RequestResponse { - private RPCSecurityDescriptor securityDescriptorOut; + private RPCSecurityDescriptor pRpcSecurityDescriptorOut; - public byte[] getRawSecurityDescriptor() { - return securityDescriptorOut.getRawSecurityDescriptor(); + public RPCSecurityDescriptor getpRpcSecurityDescriptorOut() { + return this.pRpcSecurityDescriptorOut; } @Override public void unmarshalResponse(PacketInput packetIn) throws IOException { - securityDescriptorOut = new RPCSecurityDescriptor(); - packetIn.readUnmarshallable(securityDescriptorOut); + // [out] PRPC_SECURITY_DESCRIPTOR pRpcSecurityDescriptorOut + this.pRpcSecurityDescriptorOut = new RPCSecurityDescriptor(); + packetIn.readUnmarshallable(this.pRpcSecurityDescriptorOut); } } diff --git a/src/main/java/com/rapid7/client/dcerpc/msrrp/messages/BaseRegOpenKey.java b/src/main/java/com/rapid7/client/dcerpc/msrrp/messages/BaseRegOpenKey.java index 3f55e23f..5f495ce7 100644 --- a/src/main/java/com/rapid7/client/dcerpc/msrrp/messages/BaseRegOpenKey.java +++ b/src/main/java/com/rapid7/client/dcerpc/msrrp/messages/BaseRegOpenKey.java @@ -20,8 +20,10 @@ import java.io.IOException; import com.rapid7.client.dcerpc.io.PacketOutput; +import com.rapid7.client.dcerpc.io.ndr.Alignment; import com.rapid7.client.dcerpc.messages.HandleResponse; import com.rapid7.client.dcerpc.messages.RequestCall; +import com.rapid7.client.dcerpc.objects.RPCUnicodeString; /** * 3.1.5.15 BaseRegOpenKey (Opnum 15)
@@ -177,7 +179,7 @@ public class BaseRegOpenKey extends RequestCall { /** * The name of a key to open. */ - private final String subKey; + private final RPCUnicodeString.NullTerminated subKey; /** * Registry key options. The user rights are represented as a bit field. In addition to the standard user rights, as * specified in [MS-DTYP] section 2.4.3, the Windows Remote Registry Protocol SHOULD support the following user @@ -324,7 +326,7 @@ public class BaseRegOpenKey extends RequestCall { * @see 2.4.3 ACCESS_MASK * @see 3.1.1.2 Key Types */ - public BaseRegOpenKey(final byte[] hKey, final String subKey, final int options, final int accessMask) { + public BaseRegOpenKey(final byte[] hKey, final RPCUnicodeString.NullTerminated subKey, final int options, final int accessMask) { super((short) 15); this.hKey = hKey; this.subKey = subKey; @@ -363,9 +365,15 @@ public void marshal(final PacketOutput packetOut) throws IOException { // .... .... 0... .... .... .... .... .... = Access SACL: Not set // Standard rights: 0x00000000 // WINREG specific rights: 0x00000000 + // [in] RPC_HKEY hKey packetOut.write(hKey); - packetOut.writeStringBuffer(subKey, true); + // [in] PRRP_UNICODE_STRING lpSubKey + packetOut.writeMarshallable(this.subKey); + // [in] DWORD dwOptions + packetOut.align(Alignment.FOUR); packetOut.writeInt(options); + // [in] REGSAM samDesired + // Alignment: 4 - Already aligned packetOut.writeInt(accessMask); } } diff --git a/src/main/java/com/rapid7/client/dcerpc/msrrp/messages/BaseRegQueryInfoKeyRequest.java b/src/main/java/com/rapid7/client/dcerpc/msrrp/messages/BaseRegQueryInfoKeyRequest.java index 9a7520e1..17df0fc4 100644 --- a/src/main/java/com/rapid7/client/dcerpc/msrrp/messages/BaseRegQueryInfoKeyRequest.java +++ b/src/main/java/com/rapid7/client/dcerpc/msrrp/messages/BaseRegQueryInfoKeyRequest.java @@ -226,7 +226,10 @@ public void marshal(final PacketOutput packetOut) throws IOException { // Max Count: 0 // Offset: 0 // Actual Count: 0 + // [in] RPC_HKEY hKey packetOut.write(hKey); - packetOut.writeStringBuffer(0); + // [in] PRRP_UNICODE_STRING lpClassIn + // Alignment: 4 - Already aligned, wrote 20 bytes above + packetOut.writeEmptyRPCUnicodeString(0); } } diff --git a/src/main/java/com/rapid7/client/dcerpc/msrrp/messages/BaseRegQueryInfoKeyResponse.java b/src/main/java/com/rapid7/client/dcerpc/msrrp/messages/BaseRegQueryInfoKeyResponse.java index c1a0e036..f90e0d41 100644 --- a/src/main/java/com/rapid7/client/dcerpc/msrrp/messages/BaseRegQueryInfoKeyResponse.java +++ b/src/main/java/com/rapid7/client/dcerpc/msrrp/messages/BaseRegQueryInfoKeyResponse.java @@ -20,7 +20,9 @@ import java.io.IOException; import com.rapid7.client.dcerpc.io.PacketInput; +import com.rapid7.client.dcerpc.io.ndr.Alignment; import com.rapid7.client.dcerpc.messages.RequestResponse; +import com.rapid7.client.dcerpc.objects.RPCUnicodeString; /** * Example: @@ -146,15 +148,31 @@ public void unmarshalResponse(final PacketInput packetIn) throws IOException { // Pointer to Last Changed Time (NTTIME) // Last Changed Time: Jun 21, 2017 12:50:30.686403000 EDT // Windows Error: WERR_OK (0x00000000) - packetIn.readStringBuf(true); - - subKeys = packetIn.readInt(); - maxSubKeyLen = packetIn.readInt(); - maxClassLen = packetIn.readInt(); - values = packetIn.readInt(); - maxValueNameLen = packetIn.readInt(); - maxValueLen = packetIn.readInt(); - securityDescriptor = packetIn.readInt(); - lastWriteTime = packetIn.readLong(); + // + packetIn.readUnmarshallable(new RPCUnicodeString.NullTerminated()); + // + packetIn.align(Alignment.FOUR); + this.subKeys = packetIn.readInt(); + // + // Alignment: 4 - Already aligned + this.maxSubKeyLen = packetIn.readInt(); + // + // Alignment: 4 - Already aligned + this.maxClassLen = packetIn.readInt(); + // + // Alignment: 4 - Already aligned + this.values = packetIn.readInt(); + // + // Alignment: 4 - Already aligned + this.maxValueNameLen = packetIn.readInt(); + // + // Alignment: 4 - Already aligned + this.maxValueLen = packetIn.readInt(); + // + // Alignment: 4 - Already aligned + this.securityDescriptor = packetIn.readInt(); + // + // Alignment: 4 (2x unsigned long) - Already aligned + this.lastWriteTime = packetIn.readLong(); } } diff --git a/src/main/java/com/rapid7/client/dcerpc/msrrp/messages/BaseRegQueryValueRequest.java b/src/main/java/com/rapid7/client/dcerpc/msrrp/messages/BaseRegQueryValueRequest.java index 15668565..18005458 100644 --- a/src/main/java/com/rapid7/client/dcerpc/msrrp/messages/BaseRegQueryValueRequest.java +++ b/src/main/java/com/rapid7/client/dcerpc/msrrp/messages/BaseRegQueryValueRequest.java @@ -20,7 +20,10 @@ import java.io.IOException; import com.rapid7.client.dcerpc.io.PacketOutput; +import com.rapid7.client.dcerpc.io.ndr.Alignment; +import com.rapid7.client.dcerpc.io.ndr.arrays.RPCConformantVaryingBuffer; import com.rapid7.client.dcerpc.messages.RequestCall; +import com.rapid7.client.dcerpc.objects.RPCUnicodeString; /** * 3.1.5.17 BaseRegQueryValue (Opnum 17)
@@ -194,7 +197,7 @@ public class BaseRegQueryValueRequest extends RequestCallExample: @@ -58,20 +56,20 @@ * */ public class BaseRegQueryValueResponse extends RequestResponse { - private RegistryValueType type; - private byte[] data; + private Integer type; + private RPCConformantVaryingByteArray data; /** - * @return The {@link RegistryValueType} of the value. + * @return The type of the value. */ - public RegistryValueType getType() { + public Integer getType() { return type; } /** * @return The data of the value entry. */ - public byte[] getData() { + public RPCConformantVaryingByteArray getData() { return data; } @@ -103,9 +101,27 @@ public void unmarshalResponse(final PacketInput packetIn) throws IOException { // Referent ID: 0x0002000c // Data Length: 8 // Windows Error: WERR_OK (0x00000000) - this.type = RegistryValueType.getRegistryValueType(packetIn.readIntRef()); - this.data = packetIn.readByteArrayRef(); - packetIn.readIntRef(); - packetIn.readIntRef(); + // + + if (packetIn.readReferentID() != 0) + this.type = packetIn.readInt(); + else + this.type = null; + // + // Alignment: 4 - Already aligned + if (packetIn.readReferentID() != 0) { + this.data = new RPCConformantVaryingByteArray(); + packetIn.readUnmarshallable(this.data); + } else { + this.data = null; + } + // { /** * A bit field that describes the requested security access for the key. */ - private final EnumSet accessMask; + private final int accessMask; /** * One of the following method(s) {@link OpenClassesRoot}, {@link OpenCurrentUser}, {@link OpenLocalMachine}, @@ -83,7 +82,7 @@ public class HandleRequest extends RequestCall { * {@link OpenPerformanceNlsText}. * @param accessMask A bit field that describes the requested security access for the key. */ - public HandleRequest(final short op, final EnumSet accessMask) { + public HandleRequest(final short op, int accessMask) { super(op); this.accessMask = accessMask; } @@ -91,7 +90,7 @@ public HandleRequest(final short op, final EnumSet accessMask) { /** * @return A bit field that describes the requested security access for the key. */ - public EnumSet getAccessMask() { + public int getAccessMask() { return accessMask; } @@ -112,7 +111,10 @@ public void marshal(final PacketOutput packetOut) throws IOException { // .... .... 0... .... .... .... .... .... = Access SACL: Not set // Standard rights: 0x00000000 // WINREG specific rights: 0x00000000 + // packetOut.writeNull(); - packetOut.writeInt((int) EnumUtils.toLong(accessMask)); + // + // Alignment: 4 - Already aligned + packetOut.writeInt(this.accessMask); } } diff --git a/src/main/java/com/rapid7/client/dcerpc/msrrp/objects/RPCSecurityDescriptor.java b/src/main/java/com/rapid7/client/dcerpc/msrrp/objects/RPCSecurityDescriptor.java index be035586..9e50a8ce 100644 --- a/src/main/java/com/rapid7/client/dcerpc/msrrp/objects/RPCSecurityDescriptor.java +++ b/src/main/java/com/rapid7/client/dcerpc/msrrp/objects/RPCSecurityDescriptor.java @@ -19,90 +19,127 @@ package com.rapid7.client.dcerpc.msrrp.objects; import java.io.IOException; +import java.rmi.UnmarshalException; import com.rapid7.client.dcerpc.io.PacketInput; import com.rapid7.client.dcerpc.io.PacketOutput; import com.rapid7.client.dcerpc.io.ndr.Alignment; import com.rapid7.client.dcerpc.io.ndr.Marshallable; import com.rapid7.client.dcerpc.io.ndr.Unmarshallable; +import com.rapid7.client.dcerpc.io.ndr.arrays.RPCConformantVaryingByteArray; /** -

The RPC_SECURITY_DESCRIPTOR structure represents the RPC security descriptors.

-
 typedef struct _RPC_SECURITY_DESCRIPTOR {
-   [size_is(cbInSecurityDescriptor), length_is(cbOutSecurityDescriptor)]
-     PBYTE lpSecurityDescriptor;
-   DWORD cbInSecurityDescriptor;
-   DWORD cbOutSecurityDescriptor;
- } RPC_SECURITY_DESCRIPTOR,
- *  *PRPC_SECURITY_DESCRIPTOR;
-
-

lpSecurityDescriptor: A buffer that -contains a SECURITY_DESCRIPTOR, -as specified in [MS-DTYP] -section 2.4.6.

-

cbInSecurityDescriptor: The size in -bytes of the security descriptor.

-

cbOutSecurityDescriptor: The size -in bytes of the security descriptor.

-@see https://msdn.microsoft.com/en-us/library/cc244924.aspx + * Alignment: 4 + *
The RPC_SECURITY_DESCRIPTOR structure represents the RPC security descriptors.
+ *
+ *      typedef struct _RPC_SECURITY_DESCRIPTOR {
+ *          [size_is(cbInSecurityDescriptor), length_is(cbOutSecurityDescriptor)] PBYTE lpSecurityDescriptor;
+ *          DWORD cbInSecurityDescriptor;
+ *          DWORD cbOutSecurityDescriptor;
+ *      } RPC_SECURITY_DESCRIPTOR,
+ *      *PRPC_SECURITY_DESCRIPTOR;
+ *
+ *  lpSecurityDescriptor: A buffer that contains a SECURITY_DESCRIPTOR, as specified in [MS-DTYP] section 2.4.6.
+ *  cbInSecurityDescriptor: The size in bytes of the security descriptor.
+ *  cbOutSecurityDescriptor: The size in bytes of the security descriptor.
+ */ public class RPCSecurityDescriptor implements Unmarshallable, Marshallable { private int cbInSecurityDescriptor; - private int cbOutSecurityDescriptor; - private byte[] rawSecurityDescriptor = new byte[0]; + private byte[] lpSecurityDescriptor; + + public byte[] getLpSecurityDescriptor() { + return this.lpSecurityDescriptor; + } + + public void setLpSecurityDescriptor(final byte[] lpSecurityDescriptor) { + this.lpSecurityDescriptor = lpSecurityDescriptor; + } public void setCbInSecurityDescriptor(final int cbInSecurityDescriptor) { this.cbInSecurityDescriptor = cbInSecurityDescriptor; } @Override - public void unmarshalPreamble(final PacketInput in) throws IOException { + public void unmarshalPreamble(final PacketInput in) { + // No preamble } @Override public void unmarshalEntity(final PacketInput in) throws IOException { + // Strucutre Alignment: 4 in.align(Alignment.FOUR); - final int refID = in.readReferentID(); - if (refID != 0) { - cbInSecurityDescriptor = in.readInt(); - cbOutSecurityDescriptor = in.readInt(); - rawSecurityDescriptor = new byte[cbOutSecurityDescriptor]; - } + // [size_is(cbInSecurityDescriptor), length_is(cbOutSecurityDescriptor)] PBYTE lpSecurityDescriptor; + // Alignment: 4 - Already aligned + final boolean lpSecurityDescriptorPresent = in.readReferentID() != 0; + // DWORD cbInSecurityDescriptor; + // Alignment: 4 - Already aligned + in.fullySkipBytes(4); + // DWORD cbOutSecurityDescriptor; + // Alignment: 4 - Already aligned + final int cbOutSecurityDescriptor = in.readIndex("cbOutSecurityDescriptor"); + if (lpSecurityDescriptorPresent) + this.lpSecurityDescriptor = new byte[cbOutSecurityDescriptor]; + else + this.lpSecurityDescriptor = null; } @Override public void unmarshalDeferrals(final PacketInput in) throws IOException { - if (rawSecurityDescriptor == null) - return; - in.align(Alignment.FOUR); - in.readInt(); - in.readInt(); // offset - final int actualSize = in.readInt(); - if (cbOutSecurityDescriptor != actualSize) - throw new java.rmi.UnmarshalException("The actual size of the array does not match the expected."); - // TODO: Return parsed object. - in.readRawBytes(rawSecurityDescriptor); + if (this.lpSecurityDescriptor != null) { + // MaximumCount + in.align(Alignment.FOUR); + in.fullySkipBytes(4); + // Offset + // Alignment: 4 - Already aligned + final int offset = in.readIndex("Offset"); + in.fullySkipBytes(offset); + final int actualCount = in.readIndex("ActualCount"); + if (actualCount != this.lpSecurityDescriptor.length) { + throw new UnmarshalException(String.format( + "AcutalCount of the conformant varying array does not match cbOutSecurityDescriptor: %d != %d", + actualCount, this.lpSecurityDescriptor.length)); + } + // Entries + // Alignment: 1 - Already aligned + in.readRawBytes(this.lpSecurityDescriptor); + } } @Override - public void marshalPreamble(final PacketOutput out) throws IOException { + public void marshalPreamble(final PacketOutput out) { + // No preamble } @Override public void marshalEntity(final PacketOutput out) throws IOException { - out.writeReferentID(); + // Structure alignment: 4 + out.align(Alignment.FOUR); + // [size_is(cbInSecurityDescriptor), length_is(cbOutSecurityDescriptor)] PBYTE lpSecurityDescriptor; + // Alignment: 4 - Already aligned + out.writeReferentID(this.lpSecurityDescriptor); + // DWORD cbInSecurityDescriptor; + // Alignment: 4 - Already aligned out.writeInt(cbInSecurityDescriptor); - out.writeInt(cbOutSecurityDescriptor); + // DWORD cbOutSecurityDescriptor; + // Alignment: 4 - Already aligned + out.writeInt(0); } @Override public void marshalDeferrals(final PacketOutput out) throws IOException { - out.writeInt(cbInSecurityDescriptor); - out.writeInt(0); - out.writeInt(cbOutSecurityDescriptor); - out.write(rawSecurityDescriptor); - } - - public byte[] getRawSecurityDescriptor() { - return rawSecurityDescriptor; + if (this.lpSecurityDescriptor != null) { + // MaximumCount + out.align(Alignment.FOUR); + out.writeInt(this.cbInSecurityDescriptor); + // Offset + // Alignment: 4 - Already aligned + out.writeInt(0); + // ActualCount + // Alignment: 4 - Already aligned + out.writeInt(this.lpSecurityDescriptor.length); + // Entries + // Alignment: 1 - Already aligned + out.write(this.lpSecurityDescriptor); + } } } diff --git a/src/main/java/com/rapid7/client/dcerpc/mssamr/SecurityAccountManagerService.java b/src/main/java/com/rapid7/client/dcerpc/mssamr/SecurityAccountManagerService.java index 537f05f0..f51fedfa 100644 --- a/src/main/java/com/rapid7/client/dcerpc/mssamr/SecurityAccountManagerService.java +++ b/src/main/java/com/rapid7/client/dcerpc/mssamr/SecurityAccountManagerService.java @@ -22,7 +22,6 @@ import java.rmi.UnmarshalException; import java.util.ArrayList; import java.util.List; -import com.google.common.base.Strings; import com.rapid7.client.dcerpc.RPCException; import com.rapid7.client.dcerpc.dto.ContextHandle; import com.rapid7.client.dcerpc.dto.SID; @@ -32,10 +31,13 @@ import com.rapid7.client.dcerpc.mssamr.dto.AliasHandle; import com.rapid7.client.dcerpc.mssamr.dto.DomainDisplayGroup; import com.rapid7.client.dcerpc.mssamr.dto.DomainHandle; -import com.rapid7.client.dcerpc.mssamr.dto.DomainPasswordInformation; +import com.rapid7.client.dcerpc.mssamr.dto.DomainLockoutInfo; +import com.rapid7.client.dcerpc.mssamr.dto.DomainLogoffInfo; +import com.rapid7.client.dcerpc.mssamr.dto.DomainPasswordInfo; import com.rapid7.client.dcerpc.mssamr.dto.GroupGeneralInformation; import com.rapid7.client.dcerpc.mssamr.dto.GroupHandle; import com.rapid7.client.dcerpc.mssamr.dto.LogonHours; +import com.rapid7.client.dcerpc.mssamr.dto.Membership; import com.rapid7.client.dcerpc.mssamr.dto.MembershipWithAttributes; import com.rapid7.client.dcerpc.mssamr.dto.MembershipWithName; import com.rapid7.client.dcerpc.mssamr.dto.MembershipWithNameAndUse; @@ -83,10 +85,13 @@ import com.rapid7.client.dcerpc.mssamr.objects.SAMPRDomainDisplayGroup; import com.rapid7.client.dcerpc.mssamr.objects.SAMPRDomainDisplayGroupBuffer; import com.rapid7.client.dcerpc.mssamr.objects.SAMPRDomainLockoutInfo; -import com.rapid7.client.dcerpc.mssamr.objects.SAMPRDomainLogOffInfo; +import com.rapid7.client.dcerpc.mssamr.objects.SAMPRDomainLogoffInfo; import com.rapid7.client.dcerpc.mssamr.objects.SAMPRDomainPasswordInfo; import com.rapid7.client.dcerpc.mssamr.objects.SAMPRGroupGeneralInformation; +import com.rapid7.client.dcerpc.mssamr.objects.SAMPRLogonHours; +import com.rapid7.client.dcerpc.mssamr.objects.SAMPRPSIDArray; import com.rapid7.client.dcerpc.mssamr.objects.SAMPRRIDEnumeration; +import com.rapid7.client.dcerpc.mssamr.objects.SAMPRSRSecurityDescriptor; import com.rapid7.client.dcerpc.mssamr.objects.SAMPRUserAllInformation; import com.rapid7.client.dcerpc.mssamr.objects.UserInfo; import com.rapid7.client.dcerpc.objects.RPCSID; @@ -129,7 +134,7 @@ public ServerHandle openServer() throws IOException { */ public ServerHandle openServer(String serverName) throws IOException { final SamrConnect2Request request = - new SamrConnect2Request(Strings.nullToEmpty(serverName), MAXIMUM_ALLOWED); + new SamrConnect2Request(parseWCharNT(serverName), MAXIMUM_ALLOWED); return parseServerHandle(callExpectSuccess(request, "SamrConnect2")); } @@ -210,11 +215,10 @@ public boolean closeHandle(final ContextHandle handle) throws IOException { final SamrCloseHandleRequest request = new SamrCloseHandleRequest(parseHandle(handle)); final HandleResponse response = call(request); - if (SystemErrorCode.ERROR_SUCCESS.is(response.getReturnValue())) { + if (SystemErrorCode.ERROR_SUCCESS.is(response.getReturnValue())) return true; - } else if (SystemErrorCode.STATUS_INVALID_HANDLE.is(response.getReturnValue())) { + else if (SystemErrorCode.STATUS_INVALID_HANDLE.is(response.getReturnValue())) return false; - } throw new RPCException("SamrCloseHandle", response.getReturnValue()); } @@ -351,13 +355,14 @@ public SamrEnumerateResponse request(int enumContext) throws IOException { /** * Gets the user RID and name pairs for the provided domain. * Max buffer size will be used. - * All users will be returned. + * All users will be returned (UserAccountControl=0) * * @param domainHandle A valid domain handle obtained from {@link #openDomain(ServerHandle, SID)}. * @return The enumerated users. * @throws IOException On issue with communication or marshalling. */ - public MembershipWithName[] getUsersForDomain(final DomainHandle domainHandle) throws IOException { + public MembershipWithName[] getUsersForDomain(final DomainHandle domainHandle) + throws IOException { return getUsersForDomain(domainHandle, 0); } @@ -419,6 +424,8 @@ public UserAllInformation getUserAllInformation(final UserHandle userHandle) thr new SamrQueryInformationUserRequest.UserAllInformation(parseHandle(userHandle)); final SAMPRUserAllInformation userInformation = callExpectSuccess(request, "SamrQueryInformationUser[21]").getUserInformation(); + if (userInformation == null) + return null; try { return new UserAllInformation( userInformation.getLastLogon(), @@ -427,25 +434,25 @@ public UserAllInformation getUserAllInformation(final UserHandle userHandle) thr userInformation.getAccountExpires(), userInformation.getPasswordCanChange(), userInformation.getPasswordMustChange(), - userInformation.getUserName().getValue(), - userInformation.getFullName().getValue(), - userInformation.getHomeDirectory().getValue(), - userInformation.getHomeDirectoryDrive().getValue(), - userInformation.getScriptPath().getValue(), - userInformation.getProfilePath().getValue(), - userInformation.getAdminComment().getValue(), - userInformation.getWorkStations().getValue(), - userInformation.getUserComment().getValue(), - userInformation.getParameters().getValue(), + parseRPCUnicodeString(userInformation.getUserName()), + parseRPCUnicodeString(userInformation.getFullName()), + parseRPCUnicodeString(userInformation.getHomeDirectory()), + parseRPCUnicodeString(userInformation.getHomeDirectoryDrive()), + parseRPCUnicodeString(userInformation.getScriptPath()), + parseRPCUnicodeString(userInformation.getProfilePath()), + parseRPCUnicodeString(userInformation.getAdminComment()), + parseRPCUnicodeString(userInformation.getWorkStations()), + parseRPCUnicodeString(userInformation.getUserComment()), + parseRPCUnicodeString(userInformation.getParameters()), userInformation.getLmOwfPassword().getBuffer(), userInformation.getNtOwfPassword().getBuffer(), userInformation.getPrivateData().getValue(), - userInformation.getSecurityDescriptor().getSecurityDescriptor(), + parseSAMPRSRSecurityDescriptor(userInformation.getSecurityDescriptor()), userInformation.getUserId(), userInformation.getPrimaryGroupId(), userInformation.getUserAccountControl(), userInformation.getWhichFields(), - new LogonHours(userInformation.getLogonHours().getLogonHours()), + parseSAMPRLogonHours(userInformation.getLogonHours()), userInformation.getBadPasswordCount(), userInformation.getLogonCount(), userInformation.getCountryCode(), @@ -472,11 +479,13 @@ public GroupGeneralInformation getGroupGeneralInformation(final GroupHandle grou new SamrQueryInformationGroupRequest.GroupGeneralInformation(parseHandle(groupHandle)); final SAMPRGroupGeneralInformation groupGeneralInformation = callExpectSuccess(request, "SamrQueryInformationGroup[1]").getGroupInformation(); + if (groupGeneralInformation == null) + return null; return new GroupGeneralInformation( - groupGeneralInformation.getName().getValue(), + parseRPCUnicodeString(groupGeneralInformation.getName()), groupGeneralInformation.getAttributes(), groupGeneralInformation.getMemberCount(), - groupGeneralInformation.getAdminComment().getValue()); + parseRPCUnicodeString(groupGeneralInformation.getAdminComment())); } /** @@ -491,10 +500,12 @@ public AliasGeneralInformation getAliasGeneralInformation(final AliasHandle alia new SamrQueryInformationAliasRequest.AliasGeneralInformation(parseHandle(aliasHandle)); final SAMPRAliasGeneralInformation aliasGeneralInformation = callExpectSuccess(request, "SamrQueryInformationAlias[1]").getAliasInformation(); + if (aliasGeneralInformation == null) + return null; return new AliasGeneralInformation( - aliasGeneralInformation.getName().getValue(), + parseRPCUnicodeString(aliasGeneralInformation.getName()), aliasGeneralInformation.getMemberCount(), - aliasGeneralInformation.getAdminComment().getValue()); + parseRPCUnicodeString(aliasGeneralInformation.getAdminComment())); } /** @@ -517,12 +528,14 @@ public SID[] getMembersInAlias(final AliasHandle aliasHandle) throws IOException * @throws IOException Thrown if either a communication failure is encountered, or the call * returns an unsuccessful response. */ - public DomainPasswordInformation getDomainPasswordInfo(final DomainHandle domainHandle) throws IOException { + public DomainPasswordInfo getDomainPasswordInfo(final DomainHandle domainHandle) throws IOException { final SamrQueryInformationDomainRequest.DomainPasswordInformation request = new SamrQueryInformationDomainRequest.DomainPasswordInformation(parseHandle(domainHandle)); final SAMPRDomainPasswordInfo passwordInfo = callExpectSuccess(request, "SamrQueryInformationDomain[1]").getDomainInformation(); - return new DomainPasswordInformation( + if (passwordInfo == null) + return null; + return new DomainPasswordInfo( passwordInfo.getMinPasswordLength(), passwordInfo.getPasswordHistoryLength(), passwordInfo.getPasswordProperties(), @@ -537,10 +550,14 @@ public DomainPasswordInformation getDomainPasswordInfo(final DomainHandle domain * @throws IOException Thrown if either a communication failure is encountered, or the call * returns an unsuccessful response. */ - public SAMPRDomainLogOffInfo getDomainLogOffInfo(final DomainHandle domainHandle) throws IOException { + public DomainLogoffInfo getDomainLogOffInfo(final DomainHandle domainHandle) throws IOException { final SamrQueryInformationDomainRequest.DomainLogOffInformation request = new SamrQueryInformationDomainRequest.DomainLogOffInformation(parseHandle(domainHandle)); - return callExpectSuccess(request, "SamrQueryInformationDomain[3]").getDomainInformation(); + final SAMPRDomainLogoffInfo samprDomainLogoffInfo = + callExpectSuccess(request, "SamrQueryInformationDomain[3]").getDomainInformation(); + if (samprDomainLogoffInfo == null) + return null; + return new DomainLogoffInfo(samprDomainLogoffInfo.getForceLogoff()); } /** @@ -550,10 +567,15 @@ public SAMPRDomainLogOffInfo getDomainLogOffInfo(final DomainHandle domainHandle * @throws IOException Thrown if either a communication failure is encountered, or the call * returns an unsuccessful response. */ - public SAMPRDomainLockoutInfo getDomainLockoutInfo(final DomainHandle domainHandle) throws IOException { + public DomainLockoutInfo getDomainLockoutInfo(final DomainHandle domainHandle) throws IOException { final SamrQueryInformationDomain2Request.DomainLockoutInformation request = new SamrQueryInformationDomain2Request.DomainLockoutInformation(parseHandle(domainHandle)); - return callExpectSuccess(request, "SamrQueryInformationDomain2[12]").getDomainInformation(); + final SAMPRDomainLockoutInfo samprDomainLockoutInfo = + callExpectSuccess(request, "SamrQueryInformationDomain2[12]").getDomainInformation(); + if (samprDomainLockoutInfo == null) + return null; + return new DomainLockoutInfo(samprDomainLockoutInfo.getLockoutDuration(), + samprDomainLockoutInfo.getLockoutObservationWindow(), samprDomainLockoutInfo.getLockoutThreshold()); } /** @@ -615,8 +637,10 @@ public DomainDisplayGroup[] getDomainGroupInformationForDomain(final DomainHandl final DomainDisplayGroup[] ret = new DomainDisplayGroup[displayGroups.size()]; int i = 0; for (SAMPRDomainDisplayGroup displayGroup : displayGroups) { - ret[i++] = new DomainDisplayGroup(displayGroup.getRid(), displayGroup.getAccountName(), - displayGroup.getDescription(), displayGroup.getAttributes()); + ret[i++] = new DomainDisplayGroup(displayGroup.getRid(), + parseRPCUnicodeString(displayGroup.getAccountName()), + parseRPCUnicodeString(displayGroup.getDescription()), + displayGroup.getAttributes()); } return ret; } @@ -663,7 +687,7 @@ public byte[] getSecurityObject(final ContextHandle objectHandle, securityInformation |= 0x08; final SamrQuerySecurityObjectRequest request = new SamrQuerySecurityObjectRequest(parseHandle(objectHandle), securityInformation); - return callExpectSuccess(request, "SamrQuerySecurityObject").getSecurityDescriptor().getSecurityDescriptor(); + return parseSAMPRSRSecurityDescriptor(callExpectSuccess(request, "SamrQuerySecurityObject").getSecurityDescriptor()); } /** @@ -722,6 +746,38 @@ public MembershipWithUse[] lookupNamesInDomain(final DomainHandle domainHandle, return memberships; } + /** + * Gets an array of {@link MembershipWithNameAndUse} information for users/groups matching the given relative + * IDs in the provided domain. + * + * @param domainHandle A valid domain handle obtained from {@link #openDomain(ServerHandle, SID)} + * @param rids A list of relative ids. + * @return An array of RID, name, and their use; each entry corresponds 1-1 with the given RID list. + * If an entry is null, no result was found for that RID. + * @throws IOException Thrown if either a communication failure is encountered, or the call + * returns an unsuccessful response. + */ + public MembershipWithNameAndUse[] lookupRIDsInDomain(final DomainHandle domainHandle, long ... rids) throws IOException { + final SamrLookupIdsInDomainRequest request = new SamrLookupIdsInDomainRequest(parseHandle(domainHandle), rids); + final SamrLookupIdsInDomainResponse response = callExpect(request, "SamrLookupIdsInDomain", + SystemErrorCode.ERROR_SUCCESS, SystemErrorCode.STATUS_SOME_NOT_MAPPED, SystemErrorCode.STATUS_NONE_MAPPED); + + final List names = response.getNames(); + long[] uses = response.getUses().getArray(); + if (uses == null) + uses = new long[0]; + final MembershipWithNameAndUse[] members = new MembershipWithNameAndUse[names.size()]; + for (int i = 0; i < names.size(); i++) { + final String name = parseRPCUnicodeString(names.get(i)); + if (name == null) + members[i] = null; + else + members[i] = new MembershipWithNameAndUse(rids[i], name, (int) uses[i]); + } + return members; + } + + /** * Gets a list of {@link MembershipWithAttributes} information for groups containing the provided user handle. * @@ -759,36 +815,27 @@ public MembershipWithAttributes[] getMembersForGroup(GroupHandle groupHandle) th * @throws IOException Thrown if either a communication failure is encountered, or the call * returns an unsuccessful response. */ - public Integer[] getAliasMembership(final DomainHandle domainHandle, SID... sids) throws IOException { + public Membership[] getAliasMembership(final DomainHandle domainHandle, SID... sids) throws IOException { + final RPCSID[] rpcSids = parseSIDs(sids); + final SAMPRPSIDArray sidArray = new SAMPRPSIDArray(rpcSids); final SamrGetAliasMembershipRequest request = - new SamrGetAliasMembershipRequest(parseHandle(domainHandle), parseSIDs(sids)); + new SamrGetAliasMembershipRequest(parseHandle(domainHandle), sidArray); final SamrGetAliasMembershipResponse response = callExpectSuccess(request, "GetAliasMembership"); - return response.getList(); - } - - public MembershipWithNameAndUse[] lookUpIDsForDomain(final DomainHandle domainHandle, int... rids) throws IOException { - final SamrLookupIdsInDomainRequest request = new SamrLookupIdsInDomainRequest(parseHandle(domainHandle), rids); - final SamrLookupIdsInDomainResponse response = callExpect(request, "SamrLookupIdsInDomain", - SystemErrorCode.ERROR_SUCCESS, SystemErrorCode.STATUS_SOME_NOT_MAPPED, SystemErrorCode.STATUS_NONE_MAPPED); - - List names = response.getNames(); - long[] array = response.getUses().getArray(); - MembershipWithNameAndUse[] members = new MembershipWithNameAndUse[names.size()]; - for (int i = 0; i < names.size(); i++) { - if (names.get(i).getValue() == null) - members[i] = null; - else - members[i] = new MembershipWithNameAndUse(rids[i], names.get(i).getValue(), array[i]); + long[] rids = response.getMembership().getArray(); + if (rids == null) + rids = new long[0]; + final Membership[] ret = new Membership[rids.length]; + for (int i = 0; i < ret.length; i++) { + ret[i] = new Membership(rids[i]); } - return members; + return ret; } /** * Helper method for calling enumeration requests and enumerating through the buffers for * {@link SamrEnumerateResponse}. */ - private void enumerate(final List list, final EnumerationCallback callback) - throws IOException { + private void enumerate(final List list, final EnumerationCallback callback) throws IOException { for (int enumContext = 0;;) { final SamrEnumerateResponse response = callback.request(enumContext); final int returnCode = response.getReturnValue(); @@ -835,6 +882,16 @@ private AliasHandle parseAliasHandle(final HandleResponse response) { return new AliasHandle(response.getHandle()); } + private LogonHours parseSAMPRLogonHours(final SAMPRLogonHours logonHours) { + return new LogonHours(logonHours.getLogonHours()); + } + + private byte[] parseSAMPRSRSecurityDescriptor(final SAMPRSRSecurityDescriptor sd) { + if (sd == null) + return null; + return sd.getSecurityDescriptor(); + } + private MembershipWithName[] parseSAMPRRIDEnumerations(final List list) { final MembershipWithName[] memberships = new MembershipWithName[list.size()]; int i = 0; diff --git a/src/main/java/com/rapid7/client/dcerpc/mssamr/dto/DomainLockoutInfo.java b/src/main/java/com/rapid7/client/dcerpc/mssamr/dto/DomainLockoutInfo.java new file mode 100644 index 00000000..b26ec60b --- /dev/null +++ b/src/main/java/com/rapid7/client/dcerpc/mssamr/dto/DomainLockoutInfo.java @@ -0,0 +1,73 @@ +/* + * Copyright 2017, Rapid7, Inc. + * + * License: BSD-3-clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + */ + +package com.rapid7.client.dcerpc.mssamr.dto; + +import java.util.Objects; + +public class DomainLockoutInfo { + private final long lockoutDuration; + private final long lockoutObservationWindow; + private final int lockoutThreshold; + + public DomainLockoutInfo(final long lockoutDuration, final long lockoutObservationWindow, + final int lockoutThreshold) { + this.lockoutDuration = lockoutDuration; + this.lockoutObservationWindow = lockoutObservationWindow; + this.lockoutThreshold = lockoutThreshold; + } + + public long getLockoutDuration() { + return lockoutDuration; + } + + public long getLockoutObservationWindow() { + return lockoutObservationWindow; + } + + public int getLockoutThreshold() { + return lockoutThreshold; + } + + @Override + public int hashCode() { + return Objects.hash(getLockoutDuration(), getLockoutObservationWindow(), getLockoutThreshold()); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } else if (! (obj instanceof DomainLockoutInfo)) { + return false; + } + final DomainLockoutInfo other = (DomainLockoutInfo) obj; + return getLockoutDuration() == other.getLockoutDuration() + && getLockoutObservationWindow() == other.getLockoutObservationWindow() + && getLockoutThreshold() == other.getLockoutThreshold(); + } + + @Override + public String toString() { + return String.format("DomainLockoutInfo{lockoutDuration: %d, lockoutObservationWindow: %d, " + + "lockoutThreshold: %d}", getLockoutDuration(), getLockoutObservationWindow(), getLockoutThreshold()); + } +} diff --git a/src/main/java/com/rapid7/client/dcerpc/mssamr/dto/DomainLogoffInfo.java b/src/main/java/com/rapid7/client/dcerpc/mssamr/dto/DomainLogoffInfo.java new file mode 100644 index 00000000..b38b46e3 --- /dev/null +++ b/src/main/java/com/rapid7/client/dcerpc/mssamr/dto/DomainLogoffInfo.java @@ -0,0 +1,54 @@ +/* + * Copyright 2017, Rapid7, Inc. + * + * License: BSD-3-clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + */ + +package com.rapid7.client.dcerpc.mssamr.dto; + +public class DomainLogoffInfo { + private long forceLogoff; + + public DomainLogoffInfo(final long forceLogoff) { + this.forceLogoff = forceLogoff; + } + + public long getForceLogoff() { + return this.forceLogoff; + } + + @Override + public int hashCode() { + return (int) this.forceLogoff; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } else if (! (obj instanceof DomainLogoffInfo)) { + return false; + } + return getForceLogoff() == ((DomainLogoffInfo) obj).getForceLogoff(); + } + + @Override + public String toString() { + return String.format("DomainLogoffInfo{forceLogoff: %d}", getForceLogoff()); + } +} diff --git a/src/main/java/com/rapid7/client/dcerpc/mssamr/dto/DomainPasswordInfo.java b/src/main/java/com/rapid7/client/dcerpc/mssamr/dto/DomainPasswordInfo.java new file mode 100755 index 00000000..ac134a60 --- /dev/null +++ b/src/main/java/com/rapid7/client/dcerpc/mssamr/dto/DomainPasswordInfo.java @@ -0,0 +1,158 @@ +/* + * Copyright 2017, Rapid7, Inc. + * + * License: BSD-3-clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + */ + +package com.rapid7.client.dcerpc.mssamr.dto; + +import java.util.Objects; + +/** + * This class represents domain password information + */ +public class DomainPasswordInfo { + + /** + * A 32-bit bit field indicating the password properties policy setting. The defined bits are shown in the + * following table. All bits can be combined using a logical OR in any combination. Undefined bits SHOULD be + * persisted by the server (that is, stored in its database) and returned to future queries. Clients SHOULD ignore + * undefined bits. + * + * +---------------------------------+--------------------------------------------------------------------------+ + * | Name/value | Description | + * +---------------------------------+--------------------------------------------------------------------------+ + * | DOMAIN_PASSWORD_COMPLEX | The server enforces password complexity policy. | + * | 0x00000001 | | + * +---------------------------------+--------------------------------------------------------------------------+ + * | DOMAIN_PASSWORD_NO_ANON_CHANGE | Reserved. No effect on password policy. | + * | 0x00000002 | | + * +---------------------------------+--------------------------------------------------------------------------+ + * | DOMAIN_PASSWORD_NO_CLEAR_CHANGE | Change-password methods that provide the cleartext password are disabled | + * | 0x00000004 | by the server. | + * +---------------------------------+--------------------------------------------------------------------------+ + * | DOMAIN_LOCKOUT_ADMINS | Reserved. No effect on password policy. | + * | 0x00000008 | | + * +---------------------------------+--------------------------------------------------------------------------+ + * | DOMAIN_PASSWORD_STORE_CLEARTEXT | The server MUST store the cleartext password, not just the computed | + * | 0x00000010 | hashes. | + * +---------------------------------+--------------------------------------------------------------------------+ + * | DOMAIN_REFUSE_PASSWORD_CHANGE | Reserved. No effect on password policy. | + * | 0x00000020 | | + * +---------------------------------+--------------------------------------------------------------------------+ + */ + private static final int DOMAIN_PASSWORD_COMPLEX = 0x00000001; + private static final int DOMAIN_PASSWORD_NO_ANON_CHANGE = 0x00000002; + private static final int DOMAIN_PASSWORD_STORE_CLEARTEXT = 0x00000010; + + private final int minimumPasswordLength; + private final int passwordHistoryLength; + private final int passwordProperties; + private final long maximumPasswordAge; + private final long minimumPasswordAge; + + public DomainPasswordInfo(int minimumPasswordLength, int passwordHistoryLength, int passwordProperties, + long maximumPasswordAge, long minimumPasswordAge) { + this.minimumPasswordLength = minimumPasswordLength; + this.passwordHistoryLength = passwordHistoryLength; + this.passwordProperties = passwordProperties; + this.maximumPasswordAge = maximumPasswordAge; + this.minimumPasswordAge = minimumPasswordAge; + } + + public boolean isDomainPasswordComplex() { + return (this.passwordProperties & DOMAIN_PASSWORD_COMPLEX) != 0; + } + + public boolean isDomainPasswordNoAnonChange() { + return (this.passwordProperties & DOMAIN_PASSWORD_NO_ANON_CHANGE) != 0; + } + + public boolean isDomainPasswordStoredClearText() { + return (this.passwordProperties & DOMAIN_PASSWORD_STORE_CLEARTEXT) != 0; + } + + /** + * @return Minimum length of passwords. + */ + public int getMinimumPasswordLength() { + return minimumPasswordLength; + } + + /** + * @return How many passwords to remember. + */ + public int getPasswordHistoryLength() { + return passwordHistoryLength; + } + + /** + * @return A bit field representing password settings. You can use the following convenience + * methods for interpretation: {@link #isDomainPasswordComplex()}, + * {@link #isDomainPasswordNoAnonChange()}, {@link #isDomainPasswordStoredClearText()} + */ + public int getPasswordProperties() { + return passwordProperties; + } + + /** + * @return Maximum password age in nanoseconds. + */ + public long getMaximumPasswordAge() { + return maximumPasswordAge; + } + + /** + * @return Minimum password age in nanoseconds. + */ + public long getMinimumPasswordAge() { + return minimumPasswordAge; + } + + @Override + public int hashCode() { + return Objects.hash(getMinimumPasswordLength(), getPasswordHistoryLength(), getPasswordProperties(), + getMaximumPasswordAge(), getMinimumPasswordAge()); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } else if (!(obj instanceof DomainPasswordInfo)) { + return false; + } + final DomainPasswordInfo other = (DomainPasswordInfo) obj; + return Objects.equals(getMinimumPasswordLength(), other.getMinimumPasswordLength()) + && Objects.equals(getPasswordHistoryLength(), other.getPasswordHistoryLength()) + && Objects.equals(getPasswordProperties(), other.getPasswordProperties()) + && Objects.equals(getMaximumPasswordAge(), other.getMaximumPasswordAge()) + && Objects.equals(getMinimumPasswordAge(), other.getMinimumPasswordAge()); + } + + @Override + public String toString() { + return String.format( + "DomainPasswordInformation{minimumPasswordLength: %d, passwordHistoryLength: %d, passwordProperties: %d, " + + "maximumPasswordAge: %d, minimumPasswordAge: %d, isDomainPasswordComplex: %b, " + + "isDomainPasswordNoAnonChange: %b, isDomainPasswordStoredClearText: %b}", + getMinimumPasswordLength(), getPasswordHistoryLength(), getPasswordProperties(), getMaximumPasswordAge(), + getMinimumPasswordAge(), isDomainPasswordComplex(), isDomainPasswordNoAnonChange(), + isDomainPasswordStoredClearText()); + } +} diff --git a/src/main/java/com/rapid7/client/dcerpc/mssamr/dto/MembershipWithNameAndUse.java b/src/main/java/com/rapid7/client/dcerpc/mssamr/dto/MembershipWithNameAndUse.java index abdda698..16eeae56 100644 --- a/src/main/java/com/rapid7/client/dcerpc/mssamr/dto/MembershipWithNameAndUse.java +++ b/src/main/java/com/rapid7/client/dcerpc/mssamr/dto/MembershipWithNameAndUse.java @@ -18,22 +18,29 @@ */ package com.rapid7.client.dcerpc.mssamr.dto; -import java.util.Objects; +import com.rapid7.client.dcerpc.dto.SIDUse; public class MembershipWithNameAndUse extends MembershipWithName { - private final long use; - public MembershipWithNameAndUse(long relativeID, String name, long use) { + private final SIDUse use; + private final int useValue; + + public MembershipWithNameAndUse(long relativeID, String name, int useValue) { super(relativeID, name); - this.use = use; + this.use = SIDUse.fromValue((short) useValue); + this.useValue = useValue; + } + + public SIDUse getUse() { + return this.use; } - public long getUse() { - return use; + public int getUseValue() { + return this.useValue; } @Override public int hashCode() { - return (super.hashCode() * 31) + Objects.hashCode(use); + return (super.hashCode() * 31) + this.useValue; } @Override @@ -43,12 +50,15 @@ public boolean equals(Object obj) { } else if (!(obj instanceof MembershipWithNameAndUse)) { return false; } - return super.equals(obj) && Objects.equals(this.use, ((MembershipWithNameAndUse) obj).use); + final MembershipWithNameAndUse other = (MembershipWithNameAndUse) obj; + return super.equals(obj) && getUseValue() == other.getUseValue(); } @Override public String toString() { final String nameStr = (getName() != null) ? String.format("\"%s\"", getName()) : "null"; - return String.format("MembershipWithName{relativeID: %d, name: %s, use: %s}", getRelativeID(), nameStr, use); + final String useStr = (getUse() == null) ? "" : String.format(" (%s)", getUse()); + return String.format("MembershipWithNameAndUse{relativeID: %d, name: %s, use: %d%s}", + getRelativeID(), nameStr, getUseValue(), useStr); } } diff --git a/src/main/java/com/rapid7/client/dcerpc/mssamr/dto/MembershipWithUse.java b/src/main/java/com/rapid7/client/dcerpc/mssamr/dto/MembershipWithUse.java index f0451e89..408cb1aa 100644 --- a/src/main/java/com/rapid7/client/dcerpc/mssamr/dto/MembershipWithUse.java +++ b/src/main/java/com/rapid7/client/dcerpc/mssamr/dto/MembershipWithUse.java @@ -21,25 +21,33 @@ package com.rapid7.client.dcerpc.mssamr.dto; +import com.rapid7.client.dcerpc.dto.SIDUse; + /** * This class contains the relative ID and use for a member of a security issuer. */ public class MembershipWithUse extends Membership { - private final int use; + private final SIDUse use; + private final int useValue; - public MembershipWithUse(final long relativeID, final int use) { + public MembershipWithUse(final long relativeID, final int useValue) { super(relativeID); - this.use = use; + this.use = SIDUse.fromValue((short) useValue); + this.useValue = useValue; + } + + public SIDUse getUse() { + return this.use; } - public int getUse() { - return use; + public int getUseValue() { + return useValue; } @Override public int hashCode() { - return (super.hashCode() * 31) + this.use; + return (super.hashCode() * 31) + this.useValue; } @Override @@ -50,11 +58,13 @@ public boolean equals(Object obj) { return false; } return super.equals(obj) - && this.use == ((MembershipWithUse) obj).use; + && getUseValue() == ((MembershipWithUse) obj).getUseValue(); } @Override public String toString() { - return String.format("MembershipWithUse{relativeID: %d, use: %d}", getRelativeID(), this.use); + final String useStr = (getUse() == null) ? "" : String.format(" (%s)", getUse()); + return String.format("MembershipWithUse{relativeID: %d, use: %d%s}", getRelativeID(), + this.useValue, useStr); } } diff --git a/src/main/java/com/rapid7/client/dcerpc/mssamr/messages/SamrConnect2Request.java b/src/main/java/com/rapid7/client/dcerpc/mssamr/messages/SamrConnect2Request.java index ddb02357..769c96eb 100644 --- a/src/main/java/com/rapid7/client/dcerpc/mssamr/messages/SamrConnect2Request.java +++ b/src/main/java/com/rapid7/client/dcerpc/mssamr/messages/SamrConnect2Request.java @@ -20,8 +20,10 @@ import java.io.IOException; import com.rapid7.client.dcerpc.io.PacketOutput; +import com.rapid7.client.dcerpc.io.ndr.Alignment; import com.rapid7.client.dcerpc.messages.HandleResponse; import com.rapid7.client.dcerpc.messages.RequestCall; +import com.rapid7.client.dcerpc.objects.WChar; /** *
The SamrConnect2 method returns a handle to a server object.
@@ -40,11 +42,11 @@ public class SamrConnect2Request extends RequestCall {
     public final static short OP_NUM = 57;
 
     //  [in, unique, string] PSAMPR_SERVER_NAME ServerName
-    private final String serverName;
+    private final WChar.NullTerminated serverName;
     //  [in] unsigned long DesiredAccess
     private final int desiredAccess;
 
-    public SamrConnect2Request(String serverName, int desiredAccess) {
+    public SamrConnect2Request(WChar.NullTerminated serverName, int desiredAccess) {
         super(OP_NUM);
         this.serverName = serverName;
         this.desiredAccess = desiredAccess;
@@ -52,8 +54,12 @@ public SamrConnect2Request(String serverName, int desiredAccess) {
 
     @Override
     public void marshal(PacketOutput packetOut) throws IOException {
-        //  [in, unique, string] PSAMPR_SERVER_NAME ServerName
-        packetOut.writeStringRef(serverName, true);
+        //  [in, unique, string] PSAMPR_SERVER_NAME ServerName
+        if (packetOut.writeReferentID(this.serverName)) {
+            packetOut.writeMarshallable(this.serverName);
+            // Alignment for DesiredAccess
+            packetOut.align(Alignment.FOUR);
+        }
         //  [in] unsigned long DesiredAccess
         packetOut.writeInt(this.desiredAccess);
     }
diff --git a/src/main/java/com/rapid7/client/dcerpc/mssamr/messages/SamrEnumerateGroupsInDomainRequest.java b/src/main/java/com/rapid7/client/dcerpc/mssamr/messages/SamrEnumerateGroupsInDomainRequest.java
index 0095250d..e6243b3d 100644
--- a/src/main/java/com/rapid7/client/dcerpc/mssamr/messages/SamrEnumerateGroupsInDomainRequest.java
+++ b/src/main/java/com/rapid7/client/dcerpc/mssamr/messages/SamrEnumerateGroupsInDomainRequest.java
@@ -33,7 +33,6 @@
  *       https://msdn.microsoft.com/en-us/library/cc245757.aspx
  */
 public class SamrEnumerateGroupsInDomainRequest extends SamrEnumerateRequest {
-
     public static final short OP_NUM = 11;
 
     public SamrEnumerateGroupsInDomainRequest(byte[] handle, int enumContext, int maxLength) {
diff --git a/src/main/java/com/rapid7/client/dcerpc/mssamr/messages/SamrGetAliasMembershipRequest.java b/src/main/java/com/rapid7/client/dcerpc/mssamr/messages/SamrGetAliasMembershipRequest.java
index f6ab3e15..c81df105 100644
--- a/src/main/java/com/rapid7/client/dcerpc/mssamr/messages/SamrGetAliasMembershipRequest.java
+++ b/src/main/java/com/rapid7/client/dcerpc/mssamr/messages/SamrGetAliasMembershipRequest.java
@@ -21,8 +21,7 @@
 import java.io.IOException;
 import com.rapid7.client.dcerpc.io.PacketOutput;
 import com.rapid7.client.dcerpc.messages.RequestCall;
-import com.rapid7.client.dcerpc.objects.RPCSID;
-import com.rapid7.client.dcerpc.objects.RPCSIDArray;
+import com.rapid7.client.dcerpc.mssamr.objects.SAMPRPSIDArray;
 
 /**
  * The SamrGetAliasMembership method obtains the union of all aliases that a given set of SIDs is a member of.
@@ -43,9 +42,9 @@ public class SamrGetAliasMembershipRequest extends RequestCall [out] PSAMPR_ULONG_ARRAY Membership
+    private SAMPRULongArray membership;
 
-    public Integer[] getList() {
-        if (array == null)
-            return null;
-        return array.getArray();
+    public SAMPRULongArray getMembership() {
+        return this.membership;
     }
 
     @Override
     public void unmarshalResponse(PacketInput packetIn) throws IOException {
-        // unused count;
-        int count = packetIn.readInt();
-        if (packetIn.readReferentID() == 0) {
-            array = null;
-            return;
-        }
-        array = new RPCConformantIntegerArray(new Integer[count]);
-        packetIn.readUnmarshallable(array);
+        this.membership = new SAMPRULongArray();
+        packetIn.readUnmarshallable(this.membership);
     }
 }
diff --git a/src/main/java/com/rapid7/client/dcerpc/mssamr/messages/SamrLookupIdsInDomainRequest.java b/src/main/java/com/rapid7/client/dcerpc/mssamr/messages/SamrLookupIdsInDomainRequest.java
index 4f5701a6..cf80e866 100644
--- a/src/main/java/com/rapid7/client/dcerpc/mssamr/messages/SamrLookupIdsInDomainRequest.java
+++ b/src/main/java/com/rapid7/client/dcerpc/mssamr/messages/SamrLookupIdsInDomainRequest.java
@@ -67,9 +67,9 @@ public class SamrLookupIdsInDomainRequest extends RequestCall [in] DOMAIN_DISPLAY_INFORMATION DisplayInformationClass
         // Alignment: 2 - Already aligned, wrote 20 bytes above
         packetOut.writeShort(getDisplayInformationClass().getInfoLevel());
-        packetOut.pad(2);
         //  [in] unsigned long Index
-        // Alignment: 4 - Already aligned
+        packetOut.pad(2);
         packetOut.writeInt(this.index);
         //  [in] unsigned long EntryCount
         // Alignment: 4 - Already aligned
diff --git a/src/main/java/com/rapid7/client/dcerpc/mssamr/messages/SamrQueryInformationDomainRequest.java b/src/main/java/com/rapid7/client/dcerpc/mssamr/messages/SamrQueryInformationDomainRequest.java
index d9ac9f1d..515c6ba1 100755
--- a/src/main/java/com/rapid7/client/dcerpc/mssamr/messages/SamrQueryInformationDomainRequest.java
+++ b/src/main/java/com/rapid7/client/dcerpc/mssamr/messages/SamrQueryInformationDomainRequest.java
@@ -23,7 +23,7 @@
 import com.rapid7.client.dcerpc.io.ndr.Unmarshallable;
 import com.rapid7.client.dcerpc.messages.RequestCall;
 import com.rapid7.client.dcerpc.mslsad.objects.DomainInformationClass;
-import com.rapid7.client.dcerpc.mssamr.objects.SAMPRDomainLogOffInfo;
+import com.rapid7.client.dcerpc.mssamr.objects.SAMPRDomainLogoffInfo;
 import com.rapid7.client.dcerpc.mssamr.objects.SAMPRDomainPasswordInfo;
 
 /**
@@ -96,7 +96,7 @@ public SamrQueryInformationDomainResponse.DomainPasswordInformation getResponseO
         }
     }
 
-    public static class DomainLogOffInformation extends SamrQueryInformationDomainRequest {
+    public static class DomainLogOffInformation extends SamrQueryInformationDomainRequest {
         public DomainLogOffInformation(final byte[] domainHandle) {
             super(domainHandle);
         }
diff --git a/src/main/java/com/rapid7/client/dcerpc/mssamr/messages/SamrQueryInformationDomainResponse.java b/src/main/java/com/rapid7/client/dcerpc/mssamr/messages/SamrQueryInformationDomainResponse.java
index f441ad7b..6a83913b 100755
--- a/src/main/java/com/rapid7/client/dcerpc/mssamr/messages/SamrQueryInformationDomainResponse.java
+++ b/src/main/java/com/rapid7/client/dcerpc/mssamr/messages/SamrQueryInformationDomainResponse.java
@@ -24,7 +24,7 @@
 import com.rapid7.client.dcerpc.messages.RequestResponse;
 import com.rapid7.client.dcerpc.mslsad.objects.DomainInformationClass;
 import com.rapid7.client.dcerpc.mssamr.objects.SAMPRDomainLockoutInfo;
-import com.rapid7.client.dcerpc.mssamr.objects.SAMPRDomainLogOffInfo;
+import com.rapid7.client.dcerpc.mssamr.objects.SAMPRDomainLogoffInfo;
 import com.rapid7.client.dcerpc.mssamr.objects.SAMPRDomainPasswordInfo;
 
 public abstract class SamrQueryInformationDomainResponse extends RequestResponse {
@@ -66,15 +66,15 @@ SAMPRDomainPasswordInfo createDomainInformation() {
         }
     }
 
-    public static class DomainLogOffInformation extends SamrQueryInformationDomainResponse {
+    public static class DomainLogOffInformation extends SamrQueryInformationDomainResponse {
         @Override
         public DomainInformationClass getDomainInformationClass() {
             return DomainInformationClass.DOMAIN_LOGOFF_INFORMATION;
         }
 
         @Override
-        SAMPRDomainLogOffInfo createDomainInformation() {
-            return new SAMPRDomainLogOffInfo();
+        SAMPRDomainLogoffInfo createDomainInformation() {
+            return new SAMPRDomainLogoffInfo();
         }
     }
 
diff --git a/src/main/java/com/rapid7/client/dcerpc/mssamr/messages/SamrQueryInformationGroupResponse.java b/src/main/java/com/rapid7/client/dcerpc/mssamr/messages/SamrQueryInformationGroupResponse.java
index bcdb67d8..f674820a 100644
--- a/src/main/java/com/rapid7/client/dcerpc/mssamr/messages/SamrQueryInformationGroupResponse.java
+++ b/src/main/java/com/rapid7/client/dcerpc/mssamr/messages/SamrQueryInformationGroupResponse.java
@@ -28,8 +28,6 @@
 import com.rapid7.client.dcerpc.messages.RequestResponse;
 import com.rapid7.client.dcerpc.mssamr.objects.GroupInformationClass;
 import com.rapid7.client.dcerpc.mssamr.objects.SAMPRGroupGeneralInformation;
-import com.rapid7.client.dcerpc.mssamr.objects.SAMPRUserAllInformation;
-import com.rapid7.client.dcerpc.mssamr.objects.UserInformationClass;
 
 public abstract class SamrQueryInformationGroupResponse extends RequestResponse {
     private T groupInformation;
diff --git a/src/main/java/com/rapid7/client/dcerpc/mssamr/messages/SamrQuerySecurityObjectRequest.java b/src/main/java/com/rapid7/client/dcerpc/mssamr/messages/SamrQuerySecurityObjectRequest.java
index b60faa51..e6e077d8 100644
--- a/src/main/java/com/rapid7/client/dcerpc/mssamr/messages/SamrQuerySecurityObjectRequest.java
+++ b/src/main/java/com/rapid7/client/dcerpc/mssamr/messages/SamrQuerySecurityObjectRequest.java
@@ -76,7 +76,6 @@ public int getSecurityInformation() {
         return securityInformation;
     }
 
-
     @Override
     public SamrQuerySecurityObjectResponse getResponseObject() {
         return new SamrQuerySecurityObjectResponse();
diff --git a/src/main/java/com/rapid7/client/dcerpc/mssamr/objects/SAMPRDomainDisplayGroup.java b/src/main/java/com/rapid7/client/dcerpc/mssamr/objects/SAMPRDomainDisplayGroup.java
index 50f133d4..97ff96e4 100644
--- a/src/main/java/com/rapid7/client/dcerpc/mssamr/objects/SAMPRDomainDisplayGroup.java
+++ b/src/main/java/com/rapid7/client/dcerpc/mssamr/objects/SAMPRDomainDisplayGroup.java
@@ -22,7 +22,7 @@
 import com.rapid7.client.dcerpc.io.PacketInput;
 import com.rapid7.client.dcerpc.io.ndr.Unmarshallable;
 import com.rapid7.client.dcerpc.objects.RPCUnicodeString;
-import com.rapid7.client.dcerpc.objects.RPCUnicodeString.NonNullTerminated;
+import com.rapid7.client.dcerpc.objects.RPCUnicodeString;
 
 /**
  * The SAMPR_DOMAIN_DISPLAY_GROUP structure contains a subset of group information sufficient to show a summary of the account for an account management application.
@@ -50,9 +50,6 @@ public class SAMPRDomainDisplayGroup implements Unmarshallable {
     private RPCUnicodeString.NonNullTerminated accountName;
     private RPCUnicodeString.NonNullTerminated description;
 
-    public SAMPRDomainDisplayGroup() {
-    }
-
     @Override
     public void unmarshalPreamble(PacketInput in) throws IOException {
     }
@@ -69,12 +66,12 @@ public int getAttributes() {
         return attributes;
     }
 
-    public String getAccountName() {
-        return accountName.getValue();
+    public RPCUnicodeString.NonNullTerminated getAccountName() {
+        return accountName;
     }
 
-    public String getDescription() {
-        return description.getValue();
+    public RPCUnicodeString.NonNullTerminated getDescription() {
+        return description;
     }
 
     @Override
@@ -82,9 +79,9 @@ public void unmarshalEntity(PacketInput in) throws IOException {
         index = in.readInt();
         rid = in.readInt();
         attributes = in.readInt();
-        accountName = new NonNullTerminated();
+        accountName = new RPCUnicodeString.NonNullTerminated();
         accountName.unmarshalEntity(in);
-        description = new NonNullTerminated();
+        description = new RPCUnicodeString.NonNullTerminated();
         description.unmarshalEntity(in);
     }
 
diff --git a/src/main/java/com/rapid7/client/dcerpc/mssamr/objects/SAMPRDomainLogOffInfo.java b/src/main/java/com/rapid7/client/dcerpc/mssamr/objects/SAMPRDomainLogoffInfo.java
similarity index 92%
rename from src/main/java/com/rapid7/client/dcerpc/mssamr/objects/SAMPRDomainLogOffInfo.java
rename to src/main/java/com/rapid7/client/dcerpc/mssamr/objects/SAMPRDomainLogoffInfo.java
index 152108ac..6b424364 100755
--- a/src/main/java/com/rapid7/client/dcerpc/mssamr/objects/SAMPRDomainLogOffInfo.java
+++ b/src/main/java/com/rapid7/client/dcerpc/mssamr/objects/SAMPRDomainLogoffInfo.java
@@ -33,7 +33,7 @@
  * } DOMAIN_LOGOFF_INFORMATION,
  *  *PDOMAIN_LOGOFF_INFORMATION;
  */
-public class SAMPRDomainLogOffInfo implements Unmarshallable {
+public class SAMPRDomainLogoffInfo implements Unmarshallable {
 
     private long forceLogoff;
 
@@ -71,10 +71,10 @@ public int hashCode() {
     public boolean equals(Object obj) {
         if (this == obj) {
             return true;
-        } else if (!(obj instanceof SAMPRDomainLogOffInfo)) {
+        } else if (!(obj instanceof SAMPRDomainLogoffInfo)) {
             return false;
         }
-        SAMPRDomainLogOffInfo other = (SAMPRDomainLogOffInfo) obj;
+        SAMPRDomainLogoffInfo other = (SAMPRDomainLogoffInfo) obj;
         return Objects.equals(getForceLogoff(), other.getForceLogoff());
     }
 
diff --git a/src/main/java/com/rapid7/client/dcerpc/mssamr/objects/SAMPRGetMembersBuffer.java b/src/main/java/com/rapid7/client/dcerpc/mssamr/objects/SAMPRGetMembersBuffer.java
index 87db4a26..d9d5b21f 100644
--- a/src/main/java/com/rapid7/client/dcerpc/mssamr/objects/SAMPRGetMembersBuffer.java
+++ b/src/main/java/com/rapid7/client/dcerpc/mssamr/objects/SAMPRGetMembersBuffer.java
@@ -24,7 +24,7 @@
 import com.rapid7.client.dcerpc.io.PacketInput;
 import com.rapid7.client.dcerpc.io.ndr.Alignment;
 import com.rapid7.client.dcerpc.io.ndr.Unmarshallable;
-import com.rapid7.client.dcerpc.objects.RPCConformantIntegerArray;
+import com.rapid7.client.dcerpc.io.ndr.arrays.RPCConformantIntegerArray;
 
 /**
  * The SAMPR_GET_MEMBERS_BUFFER structure represents the membership of a group.
diff --git a/src/main/java/com/rapid7/client/dcerpc/mssamr/objects/SAMPRPSIDArray.java b/src/main/java/com/rapid7/client/dcerpc/mssamr/objects/SAMPRPSIDArray.java
new file mode 100644
index 00000000..3cbd1f71
--- /dev/null
+++ b/src/main/java/com/rapid7/client/dcerpc/mssamr/objects/SAMPRPSIDArray.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2017, Rapid7, Inc.
+ *
+ * License: BSD-3-clause
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *   Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ *  Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ *  Neither the name of the copyright holder nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ *
+ */
+package com.rapid7.client.dcerpc.mssamr.objects;
+
+import java.io.IOException;
+import com.rapid7.client.dcerpc.io.PacketOutput;
+import com.rapid7.client.dcerpc.io.ndr.Alignment;
+import com.rapid7.client.dcerpc.io.ndr.Marshallable;
+import com.rapid7.client.dcerpc.io.ndr.arrays.RPCConformantReferentArray;
+import com.rapid7.client.dcerpc.objects.RPCSID;
+
+/**
+ * Alignment: 4
+ * SAMPR_PSID_ARRAY
+ * 
The SAMPR_PSID_ARRAY structure holds an array of SID values.
+ *
+ *      typedef struct _SAMPR_PSID_ARRAY {
+ *          [range(0,1024)] unsigned long Count;
+ *          [size_is(Count)] PSAMPR_SID_INFORMATION Sids;
+ *      } SAMPR_PSID_ARRAY,
+ *      *PSAMPR_PSID_ARRAY;
+ *
+ * Count: The number of elements in Sids. If zero, Sids MUST be ignored. If nonzero, Sids MUST point to at least Count * sizeof(SAMPR_SID_INFORMATION) bytes of memory.
+ * Sids: An array of pointers to SID values. For more information, see section 2.2.3.5.
+ */ +public class SAMPRPSIDArray implements Marshallable { + + private RPCSIDReferentConformantArray sids; + + public SAMPRPSIDArray(RPCSID ... sids) { + this.sids = new RPCSIDReferentConformantArray(sids); + } + + public RPCSID[] getSids() { + return (this.sids == null ? null : this.sids.getArray()); + } + + @Override + public void marshalPreamble(PacketOutput out) { + // No preamble + } + + @Override + public void marshalEntity(PacketOutput out) throws IOException { + // [range(0,1024)] unsigned long Count; + out.align(Alignment.FOUR); + if (this.sids == null) { + out.writeInt(0); + out.writeNull(); + } else { + out.writeInt(this.sids.getArray().length); + out.writeReferentID(); + } + } + + @Override + public void marshalDeferrals(PacketOutput out) throws IOException { + if (this.sids != null) + out.writeMarshallable(this.sids); + } + + private static class RPCSIDReferentConformantArray extends RPCConformantReferentArray { + + private RPCSIDReferentConformantArray(RPCSID[] array) { + super(array); + } + + @Override + protected RPCSID createEntry() { + return new RPCSID(); + } + } +} diff --git a/src/main/java/com/rapid7/client/dcerpc/mssamr/objects/SAMPRULongArray.java b/src/main/java/com/rapid7/client/dcerpc/mssamr/objects/SAMPRULongArray.java index e3d872a8..806a1974 100644 --- a/src/main/java/com/rapid7/client/dcerpc/mssamr/objects/SAMPRULongArray.java +++ b/src/main/java/com/rapid7/client/dcerpc/mssamr/objects/SAMPRULongArray.java @@ -60,21 +60,21 @@ public void unmarshalEntity(PacketInput in) throws IOException { // unsigned long Count; final int count = readIndex("Count", in); if (in.readReferentID() != 0) { - array = new long[count]; + this.array = new long[count]; } else { - array = null; + this.array = null; } } @Override public void unmarshalDeferrals(PacketInput in) throws IOException { - if (array != null) { + if (this.array != null) { // MaximumCount: [size_is(Count)] unsigned long * Element; in.align(Alignment.FOUR); in.fullySkipBytes(4); // Elements: [size_is(Count)] unsigned long * Element; - for (int i = 0; i < array.length; i++) { - array[i] = in.readUnsignedInt(); + for (int i = 0; i < this.array.length; i++) { + this.array[i] = in.readUnsignedInt(); } } } diff --git a/src/main/java/com/rapid7/client/dcerpc/mssrvs/ServerService.java b/src/main/java/com/rapid7/client/dcerpc/mssrvs/ServerService.java index b9dd94a0..097408da 100644 --- a/src/main/java/com/rapid7/client/dcerpc/mssrvs/ServerService.java +++ b/src/main/java/com/rapid7/client/dcerpc/mssrvs/ServerService.java @@ -69,8 +69,13 @@ public ServerService(final RPCTransport transport) { public String getCanonicalizedName(String serverName, String pathName, String prefix, int outBufLength, int pathType, int flags) throws IOException { final NetprPathCanonicalizeRequest request = - new NetprPathCanonicalizeRequest(serverName, pathName, outBufLength, prefix, pathType, flags); - return callExpectSuccess(request, "NetprPathCanonicalize").getCanonicalizedPath(); + new NetprPathCanonicalizeRequest( + parseWCharNT(serverName), + parseWCharNT(pathName, false), + outBufLength, + parseWCharNT(prefix, false), + pathType, flags); + return callExpectSuccess(request, "NetprPathCanonicalize").getOutBuf(); } public NetShareInfo0 getShare0(String shareName) throws IOException { diff --git a/src/main/java/com/rapid7/client/dcerpc/mssrvs/NetprPathType.java b/src/main/java/com/rapid7/client/dcerpc/mssrvs/dto/NetprPathType.java similarity index 87% rename from src/main/java/com/rapid7/client/dcerpc/mssrvs/NetprPathType.java rename to src/main/java/com/rapid7/client/dcerpc/mssrvs/dto/NetprPathType.java index d7efe8dd..fc5e0fae 100644 --- a/src/main/java/com/rapid7/client/dcerpc/mssrvs/NetprPathType.java +++ b/src/main/java/com/rapid7/client/dcerpc/mssrvs/dto/NetprPathType.java @@ -1,26 +1,28 @@ -/** +/* * Copyright 2017, Rapid7, Inc. * * License: BSD-3-clause * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright notice, + * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - * * Redistributions in binary form must reproduce the above copyright + * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * * Neither the name of the copyright holder nor the names of its contributors + * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. + * + * */ /* Path types provided by Microsoft MSDN: https://msdn.microsoft.com/en-us/library/cc213230.aspx */ -package com.rapid7.client.dcerpc.mssrvs; +package com.rapid7.client.dcerpc.mssrvs.dto; import java.util.HashMap; import java.util.Map; @@ -70,7 +72,7 @@ public enum NetprPathType { this.id = id; } - public int getid() { + public int getId() { return id; } @@ -84,7 +86,7 @@ public static NetprPathType getid(final int id) { static { for (final NetprPathType id : NetprPathType.values()) { - ids.put(id.getid(), id); + ids.put(id.getId(), id); } } } diff --git a/src/main/java/com/rapid7/client/dcerpc/mssrvs/messages/NetprPathCanonicalizeRequest.java b/src/main/java/com/rapid7/client/dcerpc/mssrvs/messages/NetprPathCanonicalizeRequest.java index a21e6e27..55c898c6 100644 --- a/src/main/java/com/rapid7/client/dcerpc/mssrvs/messages/NetprPathCanonicalizeRequest.java +++ b/src/main/java/com/rapid7/client/dcerpc/mssrvs/messages/NetprPathCanonicalizeRequest.java @@ -22,7 +22,7 @@ import com.rapid7.client.dcerpc.io.PacketOutput; import com.rapid7.client.dcerpc.io.ndr.Alignment; import com.rapid7.client.dcerpc.messages.RequestCall; -import com.rapid7.client.dcerpc.mssrvs.NetrOpCode; +import com.rapid7.client.dcerpc.objects.WChar; /** *

3.1.4.30 NetprPathCanonicalize (Opnum 31)

@@ -139,16 +139,23 @@ public class NetprPathCanonicalizeRequest extends RequestCall { - final String serverName; - final String pathName; - final String prefix; - final int outBufLen; - final int pathType; - final int flags; + // [in, string, unique] SRVSVC_HANDLE ServerName + private final WChar.NullTerminated serverName; + // [in, string] WCHAR* PathName + private final WChar.NullTerminated pathName; + // [in, range(0,64000)] DWORD OutbufLen + private final int outBufLen; + // [in, string] WCHAR* Prefix + private final WChar.NullTerminated prefix; + // [in, out] DWORD* PathType + private final int pathType; + // [in] DWORD Flags + private final int flags; //private final static int MAX_BUFFER_SIZE = 64000; - public NetprPathCanonicalizeRequest(String serverName, String pathName, int outBufLen, String prefix, int pathType, int flags) { + public NetprPathCanonicalizeRequest(WChar.NullTerminated serverName, WChar.NullTerminated + pathName, int outBufLen, WChar.NullTerminated prefix, int pathType, int flags) { super(NetrOpCode.NetprPathCanonicalize.getOpCode()); this.serverName = serverName; this.pathName = pathName; @@ -158,17 +165,19 @@ public NetprPathCanonicalizeRequest(String serverName, String pathName, int outB this.flags = flags; } - public void marshal(final PacketOutput stubOut) throws IOException { - stubOut.writeStringRef(serverName, true); - stubOut.align(Alignment.FOUR); - stubOut.writeString(pathName, true); - stubOut.align(Alignment.FOUR); // align WCHAR* - stubOut.writeInt(outBufLen); - stubOut.writeString(prefix, true); - stubOut.align(Alignment.FOUR); // align WCHAR* - stubOut.writeInt(pathType); - stubOut.writeInt(flags); - + public void marshal(final PacketOutput packetOut) throws IOException { + if (packetOut.writeReferentID(this.serverName)) { + packetOut.writeMarshallable(serverName); + // Alignment for pathName + packetOut.align(Alignment.FOUR); + } + packetOut.writeMarshallable(this.pathName); + packetOut.align(Alignment.FOUR); + packetOut.writeInt(outBufLen); + packetOut.writeMarshallable(this.prefix); + packetOut.align(Alignment.FOUR); + packetOut.writeInt(pathType); + packetOut.writeInt(flags); } @Override diff --git a/src/main/java/com/rapid7/client/dcerpc/mssrvs/messages/NetprPathCanonicalizeResponse.java b/src/main/java/com/rapid7/client/dcerpc/mssrvs/messages/NetprPathCanonicalizeResponse.java index 7058f347..8d1bd1c3 100644 --- a/src/main/java/com/rapid7/client/dcerpc/mssrvs/messages/NetprPathCanonicalizeResponse.java +++ b/src/main/java/com/rapid7/client/dcerpc/mssrvs/messages/NetprPathCanonicalizeResponse.java @@ -20,8 +20,8 @@ import java.io.IOException; import com.rapid7.client.dcerpc.io.PacketInput; +import com.rapid7.client.dcerpc.io.ndr.Alignment; import com.rapid7.client.dcerpc.messages.RequestResponse; -import com.rapid7.client.dcerpc.mssrvs.NetprPathType; /** * Server Service, NetPathCanonicalize @@ -35,41 +35,41 @@ */ public class NetprPathCanonicalizeResponse extends RequestResponse { - private String canonicalizedPath; + private String outBuf; private int pathType; + @Override public void unmarshalResponse(final PacketInput packetIn) throws IOException { - canonicalizedPath = readChars(packetIn); + outBuf = readChars(packetIn); + packetIn.align(Alignment.FOUR); pathType = packetIn.readInt(); } - public String getCanonicalizedPath() { - return canonicalizedPath; + public String getOutBuf() { + return outBuf; } - public NetprPathType getPathType() { - return NetprPathType.getid(pathType); + public int getPathType() { + return this.pathType; } private String readChars(final PacketInput packetIn) throws IOException { - final StringBuffer result; - int currentOffset = 0; - int lengthInBytes = packetIn.readInt(); - int lengthOfChars = lengthInBytes / 2; - result = new StringBuffer(lengthOfChars); - - while (currentOffset++ < lengthOfChars) { + // Corresponds to [in, range(0,64000)] DWORD OutbufLen + final int byteCount = packetIn.readInt(); + // UTF-16 string + final int charCount = byteCount / 2; + final StringBuilder result = new StringBuilder(charCount); + int offset = 0; + while (offset < charCount) { + offset++; final char currentChar = (char) packetIn.readShort(); - if (currentChar == 0) { + // Null terminator indicates end of response content, but not end of buffer + if (currentChar == 0) break; - } result.append(currentChar); } - while (currentOffset++ < lengthOfChars) { - packetIn.readShort(); - } - packetIn.align(); - + // Skip the rest of the buffer + packetIn.fullySkipBytes((charCount - offset) * 2); return result.toString(); } } diff --git a/src/main/java/com/rapid7/client/dcerpc/mssrvs/NetrOpCode.java b/src/main/java/com/rapid7/client/dcerpc/mssrvs/messages/NetrOpCode.java similarity index 98% rename from src/main/java/com/rapid7/client/dcerpc/mssrvs/NetrOpCode.java rename to src/main/java/com/rapid7/client/dcerpc/mssrvs/messages/NetrOpCode.java index 4ceb1303..c511c56a 100644 --- a/src/main/java/com/rapid7/client/dcerpc/mssrvs/NetrOpCode.java +++ b/src/main/java/com/rapid7/client/dcerpc/mssrvs/messages/NetrOpCode.java @@ -20,7 +20,7 @@ /* Path types provided by Microsoft MSDN: https://msdn.microsoft.com/en-us/library/cc247234.aspx */ -package com.rapid7.client.dcerpc.mssrvs; +package com.rapid7.client.dcerpc.mssrvs.messages; import java.util.HashMap; import java.util.Map; diff --git a/src/main/java/com/rapid7/client/dcerpc/mssrvs/messages/NetrShareEnumRequest.java b/src/main/java/com/rapid7/client/dcerpc/mssrvs/messages/NetrShareEnumRequest.java index 26be6110..bd891434 100644 --- a/src/main/java/com/rapid7/client/dcerpc/mssrvs/messages/NetrShareEnumRequest.java +++ b/src/main/java/com/rapid7/client/dcerpc/mssrvs/messages/NetrShareEnumRequest.java @@ -24,7 +24,6 @@ import java.io.IOException; import com.rapid7.client.dcerpc.io.PacketOutput; import com.rapid7.client.dcerpc.messages.RequestCall; -import com.rapid7.client.dcerpc.mssrvs.NetrOpCode; import com.rapid7.client.dcerpc.mssrvs.objects.ShareEnumLevel; import com.rapid7.client.dcerpc.mssrvs.objects.ShareEnumStruct; @@ -92,13 +91,10 @@ public void marshal(PacketOutput packetOut) throws IOException { packetOut.writeInt(this.preferredMaximumLength); // [in, out, unique] DWORD* ResumeHandle // Alignment: 4 - Already aligned - if (resumeHandle != null) { - packetOut.writeReferentID(); + if (packetOut.writeReferentID(this.resumeHandle)) { // [in, out, unique] DWORD* ResumeHandle // Alignment: 4 - Already aligned packetOut.writeInt(this.resumeHandle); - } else { - packetOut.writeNull(); } } diff --git a/src/main/java/com/rapid7/client/dcerpc/mssrvs/messages/NetrShareGetInfoRequest.java b/src/main/java/com/rapid7/client/dcerpc/mssrvs/messages/NetrShareGetInfoRequest.java index 60d43676..d7a51d71 100644 --- a/src/main/java/com/rapid7/client/dcerpc/mssrvs/messages/NetrShareGetInfoRequest.java +++ b/src/main/java/com/rapid7/client/dcerpc/mssrvs/messages/NetrShareGetInfoRequest.java @@ -66,7 +66,7 @@ public abstract class NetrShareGetInfoRequest extends Reque // [in, string] WCHAR* NetName private final WChar.NullTerminated shareName; // [in] DWORD Level - // This is dervied from getShareInfoLevel() + // This is derived from getShareInfoLevel() public NetrShareGetInfoRequest(final WChar.NullTerminated shareName) { super(OP_NUM); diff --git a/src/main/java/com/rapid7/client/dcerpc/msvcctl/ServiceControlManagerService.java b/src/main/java/com/rapid7/client/dcerpc/msvcctl/ServiceControlManagerService.java index 94169f86..e76d3003 100644 --- a/src/main/java/com/rapid7/client/dcerpc/msvcctl/ServiceControlManagerService.java +++ b/src/main/java/com/rapid7/client/dcerpc/msvcctl/ServiceControlManagerService.java @@ -69,7 +69,7 @@ public boolean closeServiceManagerHandle(final ServiceManagerHandle serviceManag public ServiceHandle openServiceHandle(final ServiceManagerHandle serviceManagerHandle, final String serviceName) throws IOException { final ROpenServiceWRequest request = - new ROpenServiceWRequest(parseHandle(serviceManagerHandle), WChar.NullTerminated.of(serviceName), FULL_ACCESS); + new ROpenServiceWRequest(parseHandle(serviceManagerHandle), parseWCharNT(serviceName), FULL_ACCESS); return new ServiceHandle(callExpectSuccess(request, "ROpenServiceWRequest").getHandle()); } @@ -113,30 +113,21 @@ public IServiceStatusInfo queryService(final ServiceHandle serviceHandle) throws } public void changeServiceConfig(final ServiceHandle serviceHandle, final IServiceConfigInfo serviceConfigInfo) throws IOException { - final WChar.NullTerminated binaryPathName = (serviceConfigInfo.getBinaryPathName() == null) ? null : - WChar.NullTerminated.of(serviceConfigInfo.getBinaryPathName()); - final WChar.NullTerminated loadOrderGroup = (serviceConfigInfo.getLoadOrderGroup() == null) ? null : - WChar.NullTerminated.of(serviceConfigInfo.getLoadOrderGroup()); - final WChar.NullTerminated serviceStartName = (serviceConfigInfo.getServiceStartName() == null) ? null : - WChar.NullTerminated.of(serviceConfigInfo.getServiceStartName()); - final WChar.NullTerminated displayName = (serviceConfigInfo.getDisplayName() == null) ? null : - WChar.NullTerminated.of(serviceConfigInfo.getDisplayName()); final RChangeServiceConfigWRequest request = new RChangeServiceConfigWRequest(serviceHandle.getBytes(), serviceConfigInfo.getServiceType().getValue(), serviceConfigInfo.getStartType().getValue(), serviceConfigInfo.getErrorControl().getValue(), - binaryPathName, - loadOrderGroup, + parseWCharNT(serviceConfigInfo.getBinaryPathName()), + parseWCharNT(serviceConfigInfo.getLoadOrderGroup()), serviceConfigInfo.getTagId(), serviceConfigInfo.getDependencies(), - serviceStartName, + parseWCharNT(serviceConfigInfo.getServiceStartName()), serviceConfigInfo.getPassword(), - displayName); + parseWCharNT(serviceConfigInfo.getDisplayName())); callExpectSuccess(request, "RChangeServiceConfigW"); } - public IServiceConfigInfo queryServiceConfig(final ServiceHandle serviceHandle) - throws IOException { + public IServiceConfigInfo queryServiceConfig(final ServiceHandle serviceHandle) throws IOException { final RQueryServiceConfigWRequest request = new RQueryServiceConfigWRequest(serviceHandle.getBytes(), RQueryServiceConfigWRequest.MAX_BUFFER_SIZE); final RQueryServiceConfigWResponse response = callExpectSuccess(request, "RQueryServiceConfigW"); @@ -155,12 +146,12 @@ private ServiceConfigInfo parseLPQueryServiceConfigW(final LPQueryServiceConfigW final ServiceType serviceType = ServiceType.fromInt(response.getDwServiceType()); final ServiceStartType serviceStartType = ServiceStartType.fromInt(response.getDwStartType()); final ServiceError serviceError = ServiceError.fromInt(response.getDwErrorControl()); - final String binaryPathName = (response.getLpBinaryPathName() == null) ? null : response.getLpBinaryPathName().getValue(); - final String loadOrderGroup = (response.getLpLoadOrderGroup() == null) ? null : response.getLpLoadOrderGroup().getValue(); + final String binaryPathName = parseWChar(response.getLpBinaryPathName()); + final String loadOrderGroup = parseWChar(response.getLpLoadOrderGroup()); final int tagId = response.getDwTagId(); final String[] dependencies = response.getLpDependencies(); - final String serviceStartName = (response.getLpServiceStartName() == null) ? null : response.getLpServiceStartName().getValue(); - final String displayName = (response.getLpDisplayName() == null) ? null : response.getLpDisplayName().getValue(); + final String serviceStartName = parseWChar(response.getLpServiceStartName()); + final String displayName = parseWChar(response.getLpDisplayName()); return new ServiceConfigInfo(serviceType, serviceStartType, serviceError, binaryPathName, loadOrderGroup, tagId, dependencies, serviceStartName, displayName, null); } diff --git a/src/main/java/com/rapid7/client/dcerpc/msvcctl/messages/RChangeServiceConfigWRequest.java b/src/main/java/com/rapid7/client/dcerpc/msvcctl/messages/RChangeServiceConfigWRequest.java index 46c33393..81ee2b43 100644 --- a/src/main/java/com/rapid7/client/dcerpc/msvcctl/messages/RChangeServiceConfigWRequest.java +++ b/src/main/java/com/rapid7/client/dcerpc/msvcctl/messages/RChangeServiceConfigWRequest.java @@ -112,22 +112,16 @@ public void marshal(PacketOutput packetOut) throws IOException { packetOut.writeInt(this.dwErrorControl); // [in, string, unique, range(0, SC_MAX_PATH_LENGTH)] wchar_t* lpBinaryPathName // Alignment: 4 - Already aligned - if (this.lpBinaryPathName != null) { - packetOut.writeReferentID(); + if (packetOut.writeReferentID(this.lpBinaryPathName)) { packetOut.writeMarshallable(this.lpBinaryPathName); // Alignment for lpLoadOrderGroup packetOut.align(Alignment.FOUR); - } else { - packetOut.writeNull(); } // [in, string, unique, range(0, SC_MAX_NAME_LENGTH)] wchar_t* lpLoadOrderGroup - if (this.lpLoadOrderGroup != null) { - packetOut.writeReferentID(); + if (packetOut.writeReferentID(this.lpLoadOrderGroup)) { packetOut.writeMarshallable(this.lpLoadOrderGroup); // Alignment for lpdwTagId packetOut.align(Alignment.FOUR); - } else { - packetOut.writeNull(); } // [in, out, unique] LPDWORD lpdwTagId if (this.lpDwTagId != null && this.lpDwTagId != 0) { @@ -137,8 +131,7 @@ public void marshal(PacketOutput packetOut) throws IOException { packetOut.writeNull(); } // [in, unique, size_is(dwDependSize)] LPBYTE lpDependencies - if (this.lpDependencies != null) { - packetOut.writeReferentID(); + if (packetOut.writeReferentID(this.lpDependencies)) { // Count the number of bytes required for the array of dependencies // This is better than allocating a new byte[] to hold everything. // At the very least we have a null terminator at the end @@ -167,22 +160,17 @@ public void marshal(PacketOutput packetOut) throws IOException { packetOut.align(Alignment.FOUR); packetOut.writeInt(byteCount); } else { - packetOut.writeNull(); // [in, range(0, SC_MAX_DEPEND_SIZE)] DWORD dwDependSize packetOut.writeInt(0); } // [in, string, unique, range(0, SC_MAX_ACCOUNT_NAME_LENGTH)] wchar_t* lpServiceStartName - if (this.lpServiceStartName != null) { - packetOut.writeReferentID(); + if (packetOut.writeReferentID(this.lpServiceStartName)) { packetOut.writeMarshallable(this.lpServiceStartName); // Alignment for lpPassword packetOut.align(Alignment.FOUR); - } else { - packetOut.writeNull(); } // [in, unique, size_is(dwPwSize)] LPBYTE lpPassword - if (this.lpPassword != null) { - packetOut.writeReferentID(); + if (packetOut.writeReferentID(this.lpPassword)) { final int byteCount = (this.lpPassword.length() * 2) + 2; packetOut.writeInt(byteCount); for (int i = 0; i < this.lpPassword.length(); i++) { @@ -195,16 +183,12 @@ public void marshal(PacketOutput packetOut) throws IOException { packetOut.align(Alignment.FOUR); packetOut.writeInt(byteCount); } else { - packetOut.writeNull(); // [in, range(0, SC_MAX_PWD_SIZE)] DWORD dwPwSize packetOut.writeInt(0); } // [in, string, unique, range(0, SC_MAX_NAME_LENGTH)] wchar_t* lpDisplayName - if (this.lpDisplayName != null) { - packetOut.writeReferentID(); + if (packetOut.writeReferentID(this.lpDisplayName)) { packetOut.writeMarshallable(this.lpDisplayName); - } else { - packetOut.writeNull(); } } } diff --git a/src/main/java/com/rapid7/client/dcerpc/msvcctl/messages/ROpenSCManagerWRequest.java b/src/main/java/com/rapid7/client/dcerpc/msvcctl/messages/ROpenSCManagerWRequest.java index 40047370..36183893 100644 --- a/src/main/java/com/rapid7/client/dcerpc/msvcctl/messages/ROpenSCManagerWRequest.java +++ b/src/main/java/com/rapid7/client/dcerpc/msvcctl/messages/ROpenSCManagerWRequest.java @@ -69,22 +69,16 @@ public ROpenSCManagerWRequest(final WChar.NullTerminated lpMachineName, @Override public void marshal(PacketOutput packetOut) throws IOException { // [in, string, unique, range(0, SC_MAX_COMPUTER_NAME_LENGTH)] SVCCTL_HANDLEW lpMachineName - if (this.lpMachineName != null) { - packetOut.writeReferentID(); + if (packetOut.writeReferentID(this.lpMachineName)) { packetOut.writeMarshallable(this.lpMachineName); // Alignment for lpDatabaseName packetOut.align(Alignment.FOUR); - } else { - packetOut.writeNull(); } // [in, string, unique, range(0, SC_MAX_NAME_LENGTH)] wchar_t* lpDatabaseName - if (this.lpDatabaseName != null) { - packetOut.writeReferentID(); + if (packetOut.writeReferentID(this.lpDatabaseName)) { packetOut.writeMarshallable(this.lpDatabaseName); // Alignment for dwDesiredAccess packetOut.align(Alignment.FOUR); - } else { - packetOut.writeNull(); } packetOut.writeInt(this.dwDesiredAccess); } diff --git a/src/main/java/com/rapid7/client/dcerpc/objects/RPCConformantArray.java b/src/main/java/com/rapid7/client/dcerpc/objects/RPCConformantArray.java deleted file mode 100644 index 15a79a4c..00000000 --- a/src/main/java/com/rapid7/client/dcerpc/objects/RPCConformantArray.java +++ /dev/null @@ -1,69 +0,0 @@ -/** - * Copyright 2017, Rapid7, Inc. - * - * License: BSD-3-clause - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - */ -package com.rapid7.client.dcerpc.objects; - -import java.io.IOException; -import com.rapid7.client.dcerpc.io.PacketInput; -import com.rapid7.client.dcerpc.io.PacketOutput; -import com.rapid7.client.dcerpc.io.ndr.Alignment; -import com.rapid7.client.dcerpc.io.ndr.Marshallable; -import com.rapid7.client.dcerpc.io.ndr.Unmarshallable; - -public abstract class RPCConformantArray implements Unmarshallable, Marshallable { - - protected RPCConformantArray(T[] array) { - this.maxCount = array.length; - this.array = array; - } - - private int maxCount; - protected final T[] array; - - public int getMaxCount() { - return maxCount; - } - - public T[] getArray() { - return array; - } - - @Override - public void unmarshalPreamble(PacketInput in) throws IOException { - in.align(Alignment.FOUR); - maxCount = in.readInt(); - } - - @Override - public abstract void unmarshalEntity(PacketInput in) throws IOException; - - @Override - public abstract void unmarshalDeferrals(PacketInput in) throws IOException; - - @Override - public void marshalPreamble(PacketOutput out) throws IOException { - out.align(Alignment.FOUR); - out.writeInt(maxCount); - } - - @Override - public abstract void marshalEntity(PacketOutput out) throws IOException; - - @Override - public abstract void marshalDeferrals(PacketOutput out) throws IOException; -} diff --git a/src/main/java/com/rapid7/client/dcerpc/objects/RPCConformantIntegerArray.java b/src/main/java/com/rapid7/client/dcerpc/objects/RPCConformantIntegerArray.java deleted file mode 100644 index d95dd6e8..00000000 --- a/src/main/java/com/rapid7/client/dcerpc/objects/RPCConformantIntegerArray.java +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Copyright 2017, Rapid7, Inc. - * - * License: BSD-3-clause - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - */ -package com.rapid7.client.dcerpc.objects; - -import java.io.IOException; -import com.rapid7.client.dcerpc.io.PacketInput; -import com.rapid7.client.dcerpc.io.PacketOutput; - -public class RPCConformantIntegerArray extends RPCConformantArray { - - public RPCConformantIntegerArray(Integer[] array) { - super(array); - } - - @Override - public void unmarshalEntity(PacketInput in) throws IOException { - for (int i = 0; i < array.length; i++) { - array[i] = in.readInt(); - } - } - - @Override - public void unmarshalDeferrals(PacketInput in) throws IOException { - } - - @Override - public void marshalEntity(PacketOutput out) throws IOException { - if (array == null) - return; - - for (Integer value : array) { - out.writeInt(value); - } - } - - @Override - public void marshalDeferrals(PacketOutput out) throws IOException { - } -} diff --git a/src/main/java/com/rapid7/client/dcerpc/objects/RPCReferentConformantArray.java b/src/main/java/com/rapid7/client/dcerpc/objects/RPCReferentConformantArray.java deleted file mode 100644 index 53e463d9..00000000 --- a/src/main/java/com/rapid7/client/dcerpc/objects/RPCReferentConformantArray.java +++ /dev/null @@ -1,77 +0,0 @@ -/** - * Copyright 2017, Rapid7, Inc. - * - * License: BSD-3-clause - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - */ -package com.rapid7.client.dcerpc.objects; - -import java.io.IOException; -import com.rapid7.client.dcerpc.io.PacketInput; -import com.rapid7.client.dcerpc.io.PacketOutput; -import com.rapid7.client.dcerpc.io.ndr.Alignment; -import com.rapid7.client.dcerpc.io.ndr.Marshallable; -import com.rapid7.client.dcerpc.io.ndr.Unmarshallable; - -public abstract class RPCReferentConformantArray - extends RPCConformantArray { - - public RPCReferentConformantArray(T[] array) { - super(array); - } - - @Override - public void unmarshalEntity(PacketInput in) throws IOException { - in.align(Alignment.FOUR); - for (int i = 0; i < array.length; i++) { - int refId = in.readReferentID(); - // Not contained in the deferrals. - if (refId == 0) { - array[i] = null; - } else { - array[i] = createEntity(); - } - } - } - - @Override - public void unmarshalDeferrals(PacketInput in) throws IOException { - for (T t : array) { - if (t != null) - in.readUnmarshallable(t); - } - } - - @Override - public void marshalEntity(PacketOutput out) throws IOException { - out.align(Alignment.FOUR); - for (T t : array) { - if (t != null) - out.writeReferentID(); - else - out.writeNull(); - } - } - - @Override - public void marshalDeferrals(PacketOutput out) throws IOException { - for (T t : array) { - if (t != null) - out.writeMarshallable(t); - } - } - - protected abstract T createEntity(); -} diff --git a/src/main/java/com/rapid7/client/dcerpc/objects/RPCSIDArray.java b/src/main/java/com/rapid7/client/dcerpc/objects/RPCSIDArray.java deleted file mode 100644 index 8db09e1c..00000000 --- a/src/main/java/com/rapid7/client/dcerpc/objects/RPCSIDArray.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Copyright 2017, Rapid7, Inc. - * - * License: BSD-3-clause - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - */ -package com.rapid7.client.dcerpc.objects; - -public class RPCSIDArray extends RPCReferentConformantArray { - - public RPCSIDArray(RPCSID[] sids) { - super(sids); - } - - @Override - protected RPCSID createEntity() { - return new RPCSID(); - } -} diff --git a/src/main/java/com/rapid7/client/dcerpc/objects/RPCUnicodeString.java b/src/main/java/com/rapid7/client/dcerpc/objects/RPCUnicodeString.java index e690520a..5f8690a4 100644 --- a/src/main/java/com/rapid7/client/dcerpc/objects/RPCUnicodeString.java +++ b/src/main/java/com/rapid7/client/dcerpc/objects/RPCUnicodeString.java @@ -40,8 +40,7 @@ * typedef struct _RPC_UNICODE_STRING { * unsigned short Length; * unsigned short MaximumLength; - * [size_is(MaximumLength/2), length_is(Length/2)] - * WCHAR* Buffer; + * [size_is(MaximumLength/2), length_is(Length/2)] WCHAR* Buffer; * } RPC_UNICODE_STRING, * *PRPC_UNICODE_STRING; * Length: The length, in bytes, of the string pointed to by the Buffer member, not including the terminating null character if any. The length MUST be a multiple of 2. The length SHOULD equal the entire size of the Buffer, in which case there is no terminating null character. Any method that accesses this structure MUST use the Length specified instead of relying on the presence or absence of a null character. @@ -150,9 +149,6 @@ public void marshalEntity(PacketOutput out) throws IOException { // unsigned short MaximumLength; // Alignment 2 - Already aligned out.writeShort(0); - // [size_is(MaximumLength/2), length_is(Length/2)] WCHAR* Buffer; - // Alignment 4 - Already aligned - out.writeNull(); } else { // UTF-16 encoded string is 2 bytes per count point // Null terminator must also be considered @@ -163,10 +159,10 @@ public void marshalEntity(PacketOutput out) throws IOException { // unsigned short MaximumLength; // Alignment 2 - Already aligned out.writeShort(byteLength); - // [size_is(MaximumLength/2), length_is(Length/2)] WCHAR* Buffer; - // Alignment 4 - Already aligned - out.writeReferentID(); } + // [size_is(MaximumLength/2), length_is(Length/2)] WCHAR* Buffer; + // Alignment 4 - Already aligned + out.writeReferentID(this.wChar); } @Override diff --git a/src/main/java/com/rapid7/client/dcerpc/service/Service.java b/src/main/java/com/rapid7/client/dcerpc/service/Service.java index 1a23e228..209a85c9 100644 --- a/src/main/java/com/rapid7/client/dcerpc/service/Service.java +++ b/src/main/java/com/rapid7/client/dcerpc/service/Service.java @@ -74,6 +74,16 @@ protected RPCUnicodeString.NonNullTerminated[] parseNonNullTerminatedStrings(Str return ret; } + protected String[] parseRPCUnicodeStrings(final RPCUnicodeString ... rpcUnicodeStrings) { + if (rpcUnicodeStrings == null) + return new String[0]; + final String[] ret = new String[rpcUnicodeStrings.length]; + for (int i = 0; i < rpcUnicodeStrings.length; i++) { + ret[i] = (rpcUnicodeStrings[i] == null) ? null : rpcUnicodeStrings[i].getValue(); + } + return ret; + } + protected byte[] parseHandle(final ContextHandle handle) { return handle.getBytes(); } @@ -118,13 +128,54 @@ protected SID[] parseRPCSIDs(RPCSID[] rpcsids) { } protected SID parseRPCSID(final RPCSID rpcsid) { - if (rpcsid == null) + return parseRPCSID(rpcsid, true); + } + + protected SID parseRPCSID(final RPCSID rpcsid, boolean nullable) { + if (rpcsid == null && nullable) return null; return new SID((byte) rpcsid.getRevision(), rpcsid.getIdentifierAuthority(), rpcsid.getSubAuthority()); } + protected String parseRPCUnicodeString(final RPCUnicodeString rpcUnicodeString) { + return parseRPCUnicodeString(rpcUnicodeString, false); + } + + protected String parseRPCUnicodeString(final RPCUnicodeString rpcUnicodeString, final boolean nullable) { + if (rpcUnicodeString == null) { + if (nullable) + return null; + throw new NullPointerException("Expecting non-null rpcUnicodeString"); + } + return rpcUnicodeString.getValue(); + } + + protected WChar.NullTerminated parseWCharNT(final String str) { + return parseWCharNT(str, true); + } + + protected WChar.NullTerminated parseWCharNT(final String str, final boolean nullable) { + if (str == null && nullable) + return null; + return WChar.NullTerminated.of(str); + } + + protected WChar.NonNullTerminated parseWChar(final String str) { + return parseWChar(str, true); + } + + protected WChar.NonNullTerminated parseWChar(final String str, final boolean nullable) { + if (str == null && nullable) + return null; + return WChar.NonNullTerminated.of(str); + } + protected String parseWChar(final WChar wChar) { - if (wChar == null) + return parseWChar(wChar, true); + } + + protected String parseWChar(final WChar wChar, final boolean nullable) { + if (wChar == null && nullable) return null; return wChar.getValue(); } diff --git a/src/test/java/com/rapid7/client/dcerpc/io/Test_PacketInput.java b/src/test/java/com/rapid7/client/dcerpc/io/Test_PacketInput.java index 62a17d52..1a4f8585 100644 --- a/src/test/java/com/rapid7/client/dcerpc/io/Test_PacketInput.java +++ b/src/test/java/com/rapid7/client/dcerpc/io/Test_PacketInput.java @@ -18,123 +18,19 @@ */ package com.rapid7.client.dcerpc.io; -import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; import java.io.ByteArrayInputStream; import java.io.IOException; import org.bouncycastle.util.encoders.Hex; import org.junit.Test; public class Test_PacketInput { - @Test - public void readIntRef() throws IOException { - assertNull(getPacketInput("00000000").readIntRef()); - assertEquals(0, getPacketInput("0000000100000000").readIntRef().intValue()); - assertEquals(-1, getPacketInput("00000001FFFFFFFF").readIntRef().intValue()); - } - - @Test - public void readLongRef() throws IOException { - assertNull(getPacketInput("00000000").readLongRef()); - assertEquals(0, getPacketInput("000000010000000000000000").readLongRef().intValue()); - assertEquals(-1, getPacketInput("00000001FFFFFFFFFFFFFFFF").readLongRef().intValue()); - } - @Test public void readReferentID() throws IOException { assertEquals(0, getPacketInput("00000000").readReferentID()); assertEquals(-1, getPacketInput("FFFFFFFF").readReferentID()); } - @Test - public void readByteArray() throws IOException { - assertArrayEquals(new byte[]{0x01}, getPacketInput("00000000000000000100000001").readByteArray()); - assertArrayEquals(new byte[]{0x00, 0x01}, getPacketInput("00000000010000000100000001").readByteArray()); - } - - @Test - public void readByteArrayRef() throws IOException { - assertNull(getPacketInput("00000000").readByteArrayRef()); - assertArrayEquals(new byte[]{0x01}, getPacketInput("0000000100000000000000000100000001000000").readByteArrayRef()); - assertArrayEquals(new byte[]{0x00, 0x01}, getPacketInput("0000000100000000010000000100000001000000").readByteArrayRef()); - } - - @Test - public void readString() throws IOException { - // Empty string - assertEquals("", getPacketInput("000000000000000000000000").readString(true)); - // Empty null terminated string - assertEquals("", getPacketInput("00000000000000000100000000000000").readString(true)); - // Empty null terminated string - assertEquals("", getPacketInput("00000000000000000200000000000000").readString(true)); - // Single ? character - assertEquals("?", getPacketInput("0000000000000000010000003F000000").readString(true)); - // Single ? character and null terminated - assertEquals("?", getPacketInput("0000000000000000020000003F000000").readString(true)); - // Multiple ? characters - assertEquals("??", getPacketInput("0000000000000000020000003F003F00").readString(true)); - // Single offset ? character - assertEquals("\u0000?", getPacketInput("0000000001000000010000003F000000").readString(true)); - } - - @Test - public void readStringRef() throws IOException { - assertNull(getPacketInput("00000000").readStringRef(true)); - // Empty string - assertEquals("", getPacketInput("00000001000000000000000000000000").readStringRef(true)); - // Empty null terminated string - assertEquals("", getPacketInput("0000000100000000000000000100000000000000").readStringRef(true)); - // Empty null terminated string - assertEquals("", getPacketInput("0000000100000000000000000200000000000000").readStringRef(true)); - // Single ? character - assertEquals("?", getPacketInput("000000010000000000000000010000003F000000").readStringRef(true)); - // Single ? character and null terminated - assertEquals("?", getPacketInput("000000010000000000000000020000003F000000").readStringRef(true)); - // Multiple ? characters - assertEquals("??", getPacketInput("000000010000000000000000020000003F003F00").readStringRef(true)); - // Single offset ? character - assertEquals("\u0000?", getPacketInput("000000010000000001000000010000003F000000").readStringRef(true)); - } - - @Test - public void readStringBuf() throws IOException { - assertNull(getPacketInput("0000000000000000").readStringBuf(true)); - // Empty string - assertEquals("", getPacketInput("0000000000000001000000000000000000000000").readStringBuf(true)); - // Empty null terminated string - assertEquals("", getPacketInput("000000000000000100000000000000000100000000000000").readStringBuf(true)); - // Empty null terminated string - assertEquals("", getPacketInput("000000000000000100000000000000000200000000000000").readStringBuf(true)); - // Single ? character - assertEquals("?", getPacketInput("00000000000000010000000000000000010000003F000000").readStringBuf(true)); - // Single ? character and null terminated - assertEquals("?", getPacketInput("00000000000000010000000000000000020000003F000000").readStringBuf(true)); - // Multiple ? characters - assertEquals("??", getPacketInput("00000000000000010000000000000000020000003F003F00").readStringBuf(true)); - // Single offset ? character - assertEquals("\u0000?", getPacketInput("00000000000000010000000001000000010000003F000000").readStringBuf(true)); - } - - @Test - public void readStringBufRef() throws IOException { - assertNull(getPacketInput("00000000").readStringBufRef(true)); - // Empty string - assertEquals("", getPacketInput("000000010000000000000001000000000000000000000000").readStringBufRef(true)); - // Empty null terminated string - assertEquals("", getPacketInput("00000001000000000000000100000000000000000100000000000000").readStringBufRef(true)); - // Empty null terminated string - assertEquals("", getPacketInput("00000001000000000000000100000000000000000200000000000000").readStringBufRef(true)); - // Single ? character - assertEquals("?", getPacketInput("0000000100000000000000010000000000000000010000003F000000").readStringBufRef(true)); - // Single ? character and null terminated - assertEquals("?", getPacketInput("0000000100000000000000010000000000000000020000003F000000").readStringBufRef(true)); - // Multiple ? characters - assertEquals("??", getPacketInput("0000000100000000000000010000000000000000020000003F003F00").readStringBufRef(true)); - // Single offset ? character - assertEquals("\u0000?", getPacketInput("0000000100000000000000010000000001000000010000003F000000").readStringBufRef(true)); - } - @Test public void readLong() throws IOException { // MaximumPasswordAge diff --git a/src/test/java/com/rapid7/client/dcerpc/io/Test_PacketOutput.java b/src/test/java/com/rapid7/client/dcerpc/io/Test_PacketOutput.java index d4dc862c..3eb6686a 100644 --- a/src/test/java/com/rapid7/client/dcerpc/io/Test_PacketOutput.java +++ b/src/test/java/com/rapid7/client/dcerpc/io/Test_PacketOutput.java @@ -24,26 +24,10 @@ import org.junit.Test; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; public class Test_PacketOutput { - @Test - public void writeIntRef() throws IOException { - final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - final PacketOutput packetOut = new PacketOutput(outputStream); - packetOut.writeIntRef(null); - packetOut.writeIntRef(Integer.valueOf(50462976)); - assertEquals("000000000000020000010203", Hex.toHexString(outputStream.toByteArray()).toUpperCase()); - } - - @Test - public void writeLongRef() throws IOException { - final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - final PacketOutput packetOut = new PacketOutput(outputStream); - packetOut.writeLongRef(null); - packetOut.writeLongRef(Long.valueOf(50462976)); - assertEquals("00000000000002000001020300000000", Hex.toHexString(outputStream.toByteArray()).toUpperCase()); - } - @Test public void writeReferentID() throws IOException { final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); @@ -53,74 +37,34 @@ public void writeReferentID() throws IOException { } @Test - public void writeNull() throws IOException { - final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - final PacketOutput packetOut = new PacketOutput(outputStream); - packetOut.writeNull(); - assertEquals("00000000", Hex.toHexString(outputStream.toByteArray()).toUpperCase()); - } - - @Test - public void writeEmptyArray() throws IOException { - final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - final PacketOutput packetOut = new PacketOutput(outputStream); - packetOut.writeEmptyArray(50462976); - assertEquals("000102030000000000000000", Hex.toHexString(outputStream.toByteArray()).toUpperCase()); - } - - @Test - public void writeEmptyArrayRef() throws IOException { - final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - final PacketOutput packetOut = new PacketOutput(outputStream); - packetOut.writeEmptyArrayRef(50462976); - assertEquals("00000200000102030000000000000000", Hex.toHexString(outputStream.toByteArray()).toUpperCase()); - } - - @Test - public void writeString_null() throws IOException { - final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - final PacketOutput packetOut = new PacketOutput(outputStream); - packetOut.writeStringBuffer(null, true); - assertEquals("0000000000000000", Hex.toHexString(outputStream.toByteArray()).toUpperCase()); - } - - @Test - public void writeString() throws IOException { + public void test_writeReferentID_obj() throws IOException { final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); final PacketOutput packetOut = new PacketOutput(outputStream); - packetOut.writeStringBuffer("?", true); - assertEquals("04000400000002000200000000000000020000003F000000", Hex.toHexString(outputStream.toByteArray()).toUpperCase()); + assertTrue(packetOut.writeReferentID("Test123")); + assertEquals("00000200", Hex.toHexString(outputStream.toByteArray()).toUpperCase()); } @Test - public void writeStringRef_null() throws IOException { + public void test_writeReferentID_null() throws IOException { final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); final PacketOutput packetOut = new PacketOutput(outputStream); - packetOut.writeStringBufferRef(null, true); + assertFalse(packetOut.writeReferentID(null)); assertEquals("00000000", Hex.toHexString(outputStream.toByteArray()).toUpperCase()); } @Test - public void writeStringRef() throws IOException { - final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - final PacketOutput packetOut = new PacketOutput(outputStream); - packetOut.writeStringBufferRef("?", true); - assertEquals("0000020004000400040002000200000000000000020000003F000000", Hex.toHexString(outputStream.toByteArray()).toUpperCase()); - } - - @Test - public void writeStringBuffer() throws IOException { + public void writeNull() throws IOException { final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); final PacketOutput packetOut = new PacketOutput(outputStream); - packetOut.writeStringBuffer(256); - assertEquals("0000000200000200000100000000000000000000", Hex.toHexString(outputStream.toByteArray()).toUpperCase()); + packetOut.writeNull(); + assertEquals("00000000", Hex.toHexString(outputStream.toByteArray()).toUpperCase()); } @Test - public void writeStringBufferRef() throws IOException { + public void writeEmptyCVArray() throws IOException { final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); final PacketOutput packetOut = new PacketOutput(outputStream); - packetOut.writeStringBufferRef(256); - assertEquals("000002000000000204000200000100000000000000000000", Hex.toHexString(outputStream.toByteArray()).toUpperCase()); + packetOut.writeEmptyCVArray(50462976); + assertEquals("000102030000000000000000", Hex.toHexString(outputStream.toByteArray()).toUpperCase()); } } diff --git a/src/test/java/com/rapid7/client/dcerpc/io/Test_PrimitiveInput.java b/src/test/java/com/rapid7/client/dcerpc/io/Test_PrimitiveInput.java index c7253144..446e6151 100644 --- a/src/test/java/com/rapid7/client/dcerpc/io/Test_PrimitiveInput.java +++ b/src/test/java/com/rapid7/client/dcerpc/io/Test_PrimitiveInput.java @@ -18,6 +18,7 @@ */ package com.rapid7.client.dcerpc.io; +import com.rapid7.client.dcerpc.io.ndr.Alignment; import java.io.ByteArrayInputStream; import java.io.EOFException; import java.io.IOException; @@ -35,28 +36,38 @@ public void constructorNullByteBuffer() { new PacketInput(null); } - @Test - public void align() throws IOException { - final PacketInput packetIn = getPacketInput("0000000000000000"); - assertEquals(0, packetIn.getCount()); - - packetIn.align(); - assertEquals(0, packetIn.getCount()); - - packetIn.fullySkipBytes(1); - assertEquals(1, packetIn.getCount()); - - packetIn.align(); - assertEquals(4, packetIn.getCount()); - - packetIn.fullySkipBytes(3); - assertEquals(7, packetIn.getCount()); - - packetIn.align(); - assertEquals(8, packetIn.getCount()); + @DataProvider + public Object[][] data_align() { + return new Object[][] { + {Alignment.ONE, 0, 0}, + {Alignment.ONE, 1, 1}, + {Alignment.TWO, 0, 0}, + {Alignment.TWO, 2, 1}, + {Alignment.TWO, 2, 2}, + {Alignment.FOUR, 0, 0}, + {Alignment.FOUR, 4, 1}, + {Alignment.FOUR, 4, 2}, + {Alignment.FOUR, 4, 3}, + {Alignment.FOUR, 4, 4}, + {Alignment.EIGHT, 0, 0}, + {Alignment.EIGHT, 8, 1}, + {Alignment.EIGHT, 8, 2}, + {Alignment.EIGHT, 8, 3}, + {Alignment.EIGHT, 8, 4}, + {Alignment.EIGHT, 8, 5}, + {Alignment.EIGHT, 8, 6}, + {Alignment.EIGHT, 8, 7}, + {Alignment.EIGHT, 8, 8}, + }; + } - packetIn.align(); - assertEquals(8, packetIn.getCount()); + @Test(dataProvider = "data_align") + public void test_align(Alignment alignment, int size, int offset) throws IOException { + final ByteArrayInputStream bin = new ByteArrayInputStream(new byte[size]); + final PacketInput packetIn = new PacketInput(bin); + packetIn.fullySkipBytes(offset); + packetIn.align(alignment); + assertEquals(bin.available(), 0); } @Test diff --git a/src/test/java/com/rapid7/client/dcerpc/io/Test_PrimitiveOutput.java b/src/test/java/com/rapid7/client/dcerpc/io/Test_PrimitiveOutput.java index 4172ee0e..3e0330bc 100644 --- a/src/test/java/com/rapid7/client/dcerpc/io/Test_PrimitiveOutput.java +++ b/src/test/java/com/rapid7/client/dcerpc/io/Test_PrimitiveOutput.java @@ -18,6 +18,7 @@ */ package com.rapid7.client.dcerpc.io; +import com.rapid7.client.dcerpc.io.ndr.Alignment; import java.io.ByteArrayOutputStream; import java.io.IOException; import org.bouncycastle.util.encoders.Hex; @@ -33,29 +34,37 @@ public void constructorNullByteBuffer() { new PacketOutput(null); } - @Test - public void align() throws IOException { + @DataProvider + public Object[][] data_align() { + return new Object[][] { + {Alignment.ONE, "", ""}, + {Alignment.ONE, "FF", "FF"}, + {Alignment.TWO, "", ""}, + {Alignment.TWO, "FF", "FF00"}, + {Alignment.TWO, "FFFF", "FFFF"}, + {Alignment.FOUR, "", ""}, + {Alignment.FOUR, "FF", "FF000000"}, + {Alignment.FOUR, "FFFF", "FFFF0000"}, + {Alignment.FOUR, "FFFFFF", "FFFFFF00"}, + {Alignment.FOUR, "FFFFFFFF", "FFFFFFFF"}, + {Alignment.EIGHT, "FF", "FF00000000000000"}, + {Alignment.EIGHT, "FFFF", "FFFF000000000000"}, + {Alignment.EIGHT, "FFFFFF", "FFFFFF0000000000"}, + {Alignment.EIGHT, "FFFFFFFF", "FFFFFFFF00000000"}, + {Alignment.EIGHT, "FFFFFFFFFF", "FFFFFFFFFF000000"}, + {Alignment.EIGHT, "FFFFFFFFFFFF", "FFFFFFFFFFFF0000"}, + {Alignment.EIGHT, "FFFFFFFFFFFFFF", "FFFFFFFFFFFFFF00"}, + {Alignment.EIGHT, "FFFFFFFFFFFFFFFF", "FFFFFFFFFFFFFFFF"}, + }; + } + + @Test(dataProvider = "data_align") + public void test_align(Alignment alignment, String hex, String expectHex) throws IOException { final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); final PacketOutput packetOut = new PacketOutput(outputStream); - assertEquals(0, packetOut.getCount()); - - packetOut.align(); - assertEquals(0, packetOut.getCount()); - - packetOut.write(0); - assertEquals(1, packetOut.getCount()); - - packetOut.align(); - assertEquals(4, packetOut.getCount()); - - packetOut.write(new byte[3]); - assertEquals(7, packetOut.getCount()); - - packetOut.align(); - assertEquals(8, packetOut.getCount()); - - packetOut.align(); - assertEquals(8, packetOut.getCount()); + packetOut.write(Hex.decode(hex)); + packetOut.align(alignment); + assertEquals(Hex.toHexString(outputStream.toByteArray()).toUpperCase(), expectHex.replace(" ", "")); } @DataProvider diff --git a/src/test/java/com/rapid7/client/dcerpc/mslsad/Test_LookupNames.java b/src/test/java/com/rapid7/client/dcerpc/mslsad/Test_LookupNames.java index 0b359984..a9f8d4c3 100644 --- a/src/test/java/com/rapid7/client/dcerpc/mslsad/Test_LookupNames.java +++ b/src/test/java/com/rapid7/client/dcerpc/mslsad/Test_LookupNames.java @@ -79,7 +79,7 @@ public void encodeLookupNamesRequest2() throws IOException { //This test is to verify that the Service correctly sets invalid SIDs to null from a valid response @Test - public void testLookupNamesService() throws IOException { + public void test_lookupSIDsForNames() throws IOException { final RPCTransport transport = mock(RPCTransport.class); final PolicyHandle fakePolicyHandle = new PolicyHandle("000000008e3039708fdd".getBytes()); final LocalSecurityAuthorityService localSecurityAuthorityService = new LocalSecurityAuthorityService(transport); @@ -91,7 +91,7 @@ public void testLookupNamesService() throws IOException { when(transport.call(any(LsarLookupNamesRequest.class))).thenReturn(response); - SID[] SIDs = localSecurityAuthorityService.lookupNames(fakePolicyHandle, (String[]) null); + SID[] SIDs = localSecurityAuthorityService.lookupSIDsForNames(fakePolicyHandle, (String[]) null); SID expectedDomainSID = new SID( (byte) 1, diff --git a/src/test/java/com/rapid7/client/dcerpc/mslsad/messages/Test_LsarQueryInformationPolicyResponse.java b/src/test/java/com/rapid7/client/dcerpc/mslsad/messages/Test_LsarQueryInformationPolicyResponse.java index af91ca3e..800b6207 100644 --- a/src/test/java/com/rapid7/client/dcerpc/mslsad/messages/Test_LsarQueryInformationPolicyResponse.java +++ b/src/test/java/com/rapid7/client/dcerpc/mslsad/messages/Test_LsarQueryInformationPolicyResponse.java @@ -59,11 +59,11 @@ public void test_getters(LsarQueryInformationPolicyResponse response, PolicyInfo public Object[][] data_unmarshal() { return new Object[][] { // Reference: 1, POLICY_INFORMATION_CLASS: 2 - {new LsarQueryInformationPolicyResponse.PolicyAuditEventsInformation(), "01000000 0200 00000000"}, + {new LsarQueryInformationPolicyResponse.PolicyAuditEventsInformation(), "01000000 0200 FFFF 02000000"}, // Reference: 1, POLICY_INFORMATION_CLASS: 3 - {new LsarQueryInformationPolicyResponse.PolicyPrimaryDomainInformation(), "01000000 0300 00000000"}, + {new LsarQueryInformationPolicyResponse.PolicyPrimaryDomainInformation(), "01000000 0300 FFFF 02000000"}, // Reference: 1, POLICY_INFORMATION_CLASS: 5 - {new LsarQueryInformationPolicyResponse.PolicyAccountDomainInformation(), "01000000 0500 00000000"} + {new LsarQueryInformationPolicyResponse.PolicyAccountDomainInformation(), "01000000 0500 FFFF 02000000"} }; } @@ -74,14 +74,15 @@ public void test_unmarshal(LsarQueryInformationPolicyResponse response, String h doReturn(null).when(in).readUnmarshallable(any(Unmarshallable.class)); response.unmarshal(in); assertNotNull(response.getPolicyInformation()); + assertEquals(response.getReturnValue(), 2); } @DataProvider public Object[][] data_unmarshall_Null() { return new Object[][] { - {new LsarQueryInformationPolicyResponse.PolicyAuditEventsInformation(), "00000000 0200 00000000"}, - {new LsarQueryInformationPolicyResponse.PolicyPrimaryDomainInformation(), "00000000 0300 00000000"}, - {new LsarQueryInformationPolicyResponse.PolicyAccountDomainInformation(), "00000000 0500 00000000"} + {new LsarQueryInformationPolicyResponse.PolicyAuditEventsInformation(), "00000000 02000000"}, + {new LsarQueryInformationPolicyResponse.PolicyPrimaryDomainInformation(), "00000000 02000000"}, + {new LsarQueryInformationPolicyResponse.PolicyAccountDomainInformation(), "00000000 02000000"} }; } @@ -91,6 +92,7 @@ public void test_unmarshall_Null(LsarQueryInformationPolicyResponse response, St PacketInput in = spy(new PacketInput(bin)); response.unmarshal(in); assertNull(response.getPolicyInformation()); + assertEquals(response.getReturnValue(), 2); } @DataProvider diff --git a/src/test/java/com/rapid7/client/dcerpc/msrrp/Test_RegistryKeyInfo.java b/src/test/java/com/rapid7/client/dcerpc/msrrp/Test_RegistryKeyInfo.java deleted file mode 100644 index 44bfde52..00000000 --- a/src/test/java/com/rapid7/client/dcerpc/msrrp/Test_RegistryKeyInfo.java +++ /dev/null @@ -1,73 +0,0 @@ -/** - * Copyright 2017, Rapid7, Inc. - * - * License: BSD-3-clause - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of the copyright holder nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - */ -package com.rapid7.client.dcerpc.msrrp; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -public class Test_RegistryKeyInfo { - @Test - public void getSubKeys() { - final RegistryKeyInfo keyInfo = new RegistryKeyInfo(0xff, 0, 0, 0, 0, 0, 0, 0l); - assertEquals(0xff, keyInfo.getSubKeys()); - } - - @Test - public void getMaxSubKeyLen() { - final RegistryKeyInfo keyInfo = new RegistryKeyInfo(0, 0xff, 0, 0, 0, 0, 0, 0l); - assertEquals(0xff, keyInfo.getMaxSubKeyLen()); - } - - @Test - public void getMaxClassLen() { - final RegistryKeyInfo keyInfo = new RegistryKeyInfo(0, 0, 0xff, 0, 0, 0, 0, 0l); - assertEquals(0xff, keyInfo.getMaxClassLen()); - } - - @Test - public void getValues() { - final RegistryKeyInfo keyInfo = new RegistryKeyInfo(0, 0, 0, 0xff, 0, 0, 0, 0l); - assertEquals(0xff, keyInfo.getValues()); - } - - @Test - public void getMaxValueNameLen() { - final RegistryKeyInfo keyInfo = new RegistryKeyInfo(0, 0, 0, 0, 0xff, 0, 0, 0l); - assertEquals(0xff, keyInfo.getMaxValueNameLen()); - } - - @Test - public void getMaxValueLen() { - final RegistryKeyInfo keyInfo = new RegistryKeyInfo(0, 0, 0, 0, 0, 0xff, 0, 0l); - assertEquals(0xff, keyInfo.getMaxValueLen()); - } - - @Test - public void getSecurityDescriptor() { - final RegistryKeyInfo keyInfo = new RegistryKeyInfo(0, 0, 0, 0, 0, 0, 0xff, 0l); - assertEquals(0xff, keyInfo.getSecurityDescriptor()); - } - - @Test - public void getLastWriteTime() { - final RegistryKeyInfo keyInfo = new RegistryKeyInfo(0, 0, 0, 0, 0, 0, 0, 0xffl); - assertEquals(0xffl, keyInfo.getLastWriteTime()); - } -} diff --git a/src/test/java/com/rapid7/client/dcerpc/msrrp/Test_RegistryService.java b/src/test/java/com/rapid7/client/dcerpc/msrrp/Test_RegistryService.java index 67034d8f..d5fc47eb 100644 --- a/src/test/java/com/rapid7/client/dcerpc/msrrp/Test_RegistryService.java +++ b/src/test/java/com/rapid7/client/dcerpc/msrrp/Test_RegistryService.java @@ -1,20 +1,22 @@ -/** +/* * Copyright 2017, Rapid7, Inc. * * License: BSD-3-clause * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright notice, + * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - * * Redistributions in binary form must reproduce the above copyright + * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * * Neither the name of the copyright holder nor the names of its contributors + * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. + * + * */ package com.rapid7.client.dcerpc.msrrp; @@ -23,19 +25,35 @@ import org.bouncycastle.util.encoders.Hex; import org.testng.annotations.Test; import com.rapid7.client.dcerpc.RPCException; +import com.rapid7.client.dcerpc.io.ndr.arrays.RPCConformantVaryingByteArray; import com.rapid7.client.dcerpc.messages.HandleResponse; import com.rapid7.client.dcerpc.messages.RequestCall; +import com.rapid7.client.dcerpc.msrrp.dto.FileTime; +import com.rapid7.client.dcerpc.msrrp.dto.RegistryKey; +import com.rapid7.client.dcerpc.msrrp.dto.RegistryKeyInfo; +import com.rapid7.client.dcerpc.msrrp.dto.RegistryValue; +import com.rapid7.client.dcerpc.msrrp.dto.RegistryValueType; import com.rapid7.client.dcerpc.msrrp.messages.BaseRegEnumKeyResponse; import com.rapid7.client.dcerpc.msrrp.messages.BaseRegEnumValueResponse; import com.rapid7.client.dcerpc.msrrp.messages.BaseRegQueryInfoKeyResponse; import com.rapid7.client.dcerpc.msrrp.messages.BaseRegQueryValueResponse; -import com.rapid7.client.dcerpc.objects.FileTime; +import com.rapid7.client.dcerpc.objects.RPCUnicodeString; import com.rapid7.client.dcerpc.transport.RPCTransport; -import static com.rapid7.client.dcerpc.mserref.SystemErrorCode.*; -import static org.junit.Assert.*; +import static com.rapid7.client.dcerpc.mserref.SystemErrorCode.ERROR_FILE_NOT_FOUND; +import static com.rapid7.client.dcerpc.mserref.SystemErrorCode.ERROR_INVALID_FUNCTION; +import static com.rapid7.client.dcerpc.mserref.SystemErrorCode.ERROR_NO_MORE_ITEMS; +import static com.rapid7.client.dcerpc.mserref.SystemErrorCode.ERROR_SUCCESS; +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; public class Test_RegistryService { @@ -202,11 +220,14 @@ public void doesValueExistYes() throws IOException { final BaseRegQueryValueResponse valueResponse = mock(BaseRegQueryValueResponse.class); final RegistryService registryService = new RegistryService(transport); + final RPCConformantVaryingByteArray byteArray = mock(RPCConformantVaryingByteArray.class); + when(byteArray.getArray()).thenReturn(new byte[]{0x01, 0x23, 0x45, 0x67}); + when(transport.call(any(RequestCall.class))).thenReturn(hiveResponse).thenReturn(keyResponse).thenReturn(valueResponse); when(hiveResponse.getReturnValue()).thenReturn(ERROR_SUCCESS.getValue()); when(keyResponse.getReturnValue()).thenReturn(ERROR_SUCCESS.getValue()); - when(valueResponse.getType()).thenReturn(RegistryValueType.REG_BINARY); - when(valueResponse.getData()).thenReturn(new byte[]{0x01, 0x23, 0x45, 0x67}); + when(valueResponse.getType()).thenReturn(RegistryValueType.REG_BINARY.getTypeID()); + when(valueResponse.getData()).thenReturn(byteArray); when(valueResponse.getReturnValue()).thenReturn(ERROR_SUCCESS.getValue()); assertTrue(registryService.doesValueExist("HKLM", "key", "value")); @@ -284,11 +305,14 @@ public void doesValueExistWithEmptyKeyName() throws IOException { final BaseRegQueryValueResponse valueResponse = mock(BaseRegQueryValueResponse.class); final RegistryService registryService = new RegistryService(transport); + final RPCConformantVaryingByteArray byteArray = mock(RPCConformantVaryingByteArray.class); + when(byteArray.getArray()).thenReturn(new byte[]{0x01, 0x23, 0x45, 0x67}); + when(transport.call(any(RequestCall.class))).thenReturn(hiveResponse).thenReturn(keyResponse).thenReturn(valueResponse); when(hiveResponse.getReturnValue()).thenReturn(ERROR_SUCCESS.getValue()); when(keyResponse.getReturnValue()).thenReturn(ERROR_SUCCESS.getValue()); - when(valueResponse.getType()).thenReturn(RegistryValueType.REG_BINARY); - when(valueResponse.getData()).thenReturn(new byte[]{0x01, 0x23, 0x45, 0x67}); + when(valueResponse.getType()).thenReturn(RegistryValueType.REG_BINARY.getTypeID()); + when(valueResponse.getData()).thenReturn(byteArray); when(valueResponse.getReturnValue()).thenReturn(ERROR_SUCCESS.getValue()); assertTrue(registryService.doesValueExist("HKLM", "key", "value")); @@ -312,11 +336,14 @@ public void doesValueExistWithNullKeyName() throws IOException { final BaseRegQueryValueResponse valueResponse = mock(BaseRegQueryValueResponse.class); final RegistryService registryService = new RegistryService(transport); + final RPCConformantVaryingByteArray byteArray = mock(RPCConformantVaryingByteArray.class); + when(byteArray.getArray()).thenReturn(new byte[]{0x01, 0x23, 0x45, 0x67}); + when(transport.call(any(RequestCall.class))).thenReturn(hiveResponse).thenReturn(keyResponse).thenReturn(valueResponse); when(hiveResponse.getReturnValue()).thenReturn(ERROR_SUCCESS.getValue()); when(keyResponse.getReturnValue()).thenReturn(ERROR_SUCCESS.getValue()); - when(valueResponse.getType()).thenReturn(RegistryValueType.REG_BINARY); - when(valueResponse.getData()).thenReturn(new byte[]{0x01, 0x23, 0x45, 0x67}); + when(valueResponse.getType()).thenReturn(RegistryValueType.REG_BINARY.getTypeID()); + when(valueResponse.getData()).thenReturn(byteArray); when(valueResponse.getReturnValue()).thenReturn(ERROR_SUCCESS.getValue()); assertTrue(registryService.doesValueExist("HKLM", "key", "value")); @@ -340,11 +367,14 @@ public void doesValueExistWithEmptyName() throws IOException { final BaseRegQueryValueResponse valueResponse = mock(BaseRegQueryValueResponse.class); final RegistryService registryService = new RegistryService(transport); + final RPCConformantVaryingByteArray byteArray = mock(RPCConformantVaryingByteArray.class); + when(byteArray.getArray()).thenReturn(new byte[]{0x01, 0x23, 0x45, 0x67}); + when(transport.call(any(RequestCall.class))).thenReturn(hiveResponse).thenReturn(keyResponse).thenReturn(valueResponse); when(hiveResponse.getReturnValue()).thenReturn(ERROR_SUCCESS.getValue()); when(keyResponse.getReturnValue()).thenReturn(ERROR_SUCCESS.getValue()); - when(valueResponse.getType()).thenReturn(RegistryValueType.REG_BINARY); - when(valueResponse.getData()).thenReturn(new byte[]{0x01, 0x23, 0x45, 0x67}); + when(valueResponse.getType()).thenReturn(RegistryValueType.REG_BINARY.getTypeID()); + when(valueResponse.getData()).thenReturn(byteArray); when(valueResponse.getReturnValue()).thenReturn(ERROR_SUCCESS.getValue()); assertTrue(registryService.doesValueExist("HKLM", "key", "value")); @@ -368,11 +398,14 @@ public void doesValueExistWithNullName() throws IOException { final BaseRegQueryValueResponse valueResponse = mock(BaseRegQueryValueResponse.class); final RegistryService registryService = new RegistryService(transport); + final RPCConformantVaryingByteArray byteArray = mock(RPCConformantVaryingByteArray.class); + when(byteArray.getArray()).thenReturn(new byte[]{0x01, 0x23, 0x45, 0x67}); + when(transport.call(any(RequestCall.class))).thenReturn(hiveResponse).thenReturn(keyResponse).thenReturn(valueResponse); when(hiveResponse.getReturnValue()).thenReturn(ERROR_SUCCESS.getValue()); when(keyResponse.getReturnValue()).thenReturn(ERROR_SUCCESS.getValue()); - when(valueResponse.getType()).thenReturn(RegistryValueType.REG_BINARY); - when(valueResponse.getData()).thenReturn(new byte[]{0x01, 0x23, 0x45, 0x67}); + when(valueResponse.getType()).thenReturn(RegistryValueType.REG_BINARY.getTypeID()); + when(valueResponse.getData()).thenReturn(byteArray); when(valueResponse.getReturnValue()).thenReturn(ERROR_SUCCESS.getValue()); assertTrue(registryService.doesValueExist("HKLM", "key", "value")); @@ -500,10 +533,10 @@ public void getSubKeys() throws IOException { when(transport.call(any(RequestCall.class))).thenReturn(hiveResponse).thenReturn(keyResponse).thenReturn(enumResponse1).thenReturn(enumResponse2).thenReturn(enumResponse3); when(hiveResponse.getReturnValue()).thenReturn(ERROR_SUCCESS.getValue()); when(keyResponse.getReturnValue()).thenReturn(ERROR_SUCCESS.getValue()); - when(enumResponse1.getName()).thenReturn("subKey1"); + when(enumResponse1.getLpNameOut()).thenReturn(RPCUnicodeString.NullTerminated.of("subKey1")); when(enumResponse1.getLastWriteTime()).thenReturn(116444736000000000l); when(enumResponse1.getReturnValue()).thenReturn(ERROR_SUCCESS.getValue()); - when(enumResponse2.getName()).thenReturn("subKey2"); + when(enumResponse2.getLpNameOut()).thenReturn(RPCUnicodeString.NullTerminated.of("subKey2")); when(enumResponse2.getLastWriteTime()).thenReturn(116444736000000000l); when(enumResponse2.getReturnValue()).thenReturn(ERROR_SUCCESS.getValue()); when(enumResponse3.getReturnValue()).thenReturn(ERROR_NO_MORE_ITEMS.getValue()); @@ -521,10 +554,10 @@ public void getSubKeys() throws IOException { verify(hiveResponse, times(1)).getReturnValue(); verify(keyResponse, times(1)).getHandle(); verify(keyResponse, times(1)).getReturnValue(); - verify(enumResponse1, times(1)).getName(); + verify(enumResponse1, times(1)).getLpNameOut(); verify(enumResponse1, times(1)).getLastWriteTime(); verify(enumResponse1, times(1)).getReturnValue(); - verify(enumResponse2, times(1)).getName(); + verify(enumResponse2, times(1)).getLpNameOut(); verify(enumResponse2, times(1)).getLastWriteTime(); verify(enumResponse2, times(1)).getReturnValue(); verify(enumResponse3, times(1)).getReturnValue(); @@ -621,16 +654,19 @@ public void getValues() throws IOException { final BaseRegEnumValueResponse enumResponse3 = mock(BaseRegEnumValueResponse.class); final RegistryService registryService = new RegistryService(transport); + final RPCConformantVaryingByteArray byteArray = mock(RPCConformantVaryingByteArray.class); + when(byteArray.getArray()).thenReturn(new byte[]{0x01, 0x23, 0x45, 0x67}); + when(transport.call(any(RequestCall.class))).thenReturn(hiveResponse).thenReturn(keyResponse).thenReturn(enumResponse1).thenReturn(enumResponse2).thenReturn(enumResponse3); when(hiveResponse.getReturnValue()).thenReturn(ERROR_SUCCESS.getValue()); when(keyResponse.getReturnValue()).thenReturn(ERROR_SUCCESS.getValue()); - when(enumResponse1.getName()).thenReturn("value1"); - when(enumResponse1.getType()).thenReturn(RegistryValueType.REG_BINARY); - when(enumResponse1.getData()).thenReturn(new byte[]{0x01, 0x23, 0x45, 0x67}); + when(enumResponse1.getName()).thenReturn(RPCUnicodeString.NullTerminated.of("value1")); + when(enumResponse1.getType()).thenReturn(RegistryValueType.REG_BINARY.getTypeID()); + when(enumResponse1.getData()).thenReturn(byteArray); when(enumResponse1.getReturnValue()).thenReturn(ERROR_SUCCESS.getValue()); - when(enumResponse2.getName()).thenReturn("value2"); - when(enumResponse2.getType()).thenReturn(RegistryValueType.REG_BINARY); - when(enumResponse2.getData()).thenReturn(new byte[]{0x01, 0x23, 0x45, 0x67}); + when(enumResponse2.getName()).thenReturn(RPCUnicodeString.NullTerminated.of("value2")); + when(enumResponse2.getType()).thenReturn(RegistryValueType.REG_BINARY.getTypeID()); + when(enumResponse2.getData()).thenReturn(byteArray); when(enumResponse2.getReturnValue()).thenReturn(ERROR_SUCCESS.getValue()); when(enumResponse3.getReturnValue()).thenReturn(ERROR_NO_MORE_ITEMS.getValue()); @@ -746,11 +782,14 @@ public void getValue() throws IOException { final BaseRegQueryValueResponse valueResponse = mock(BaseRegQueryValueResponse.class); final RegistryService registryService = new RegistryService(transport); + final RPCConformantVaryingByteArray byteArray = mock(RPCConformantVaryingByteArray.class); + when(byteArray.getArray()).thenReturn(new byte[]{0x01, 0x23, 0x45, 0x67}); + when(transport.call(any(RequestCall.class))).thenReturn(hiveResponse).thenReturn(keyResponse).thenReturn(valueResponse); when(hiveResponse.getReturnValue()).thenReturn(ERROR_SUCCESS.getValue()); when(keyResponse.getReturnValue()).thenReturn(ERROR_SUCCESS.getValue()); - when(valueResponse.getType()).thenReturn(RegistryValueType.REG_BINARY); - when(valueResponse.getData()).thenReturn(new byte[]{0x01, 0x23, 0x45, 0x67}); + when(valueResponse.getType()).thenReturn(RegistryValueType.REG_BINARY.getTypeID()); + when(valueResponse.getData()).thenReturn(byteArray); when(valueResponse.getReturnValue()).thenReturn(ERROR_SUCCESS.getValue()); final RegistryValue value = registryService.getValue("HKLM", "key", "value"); @@ -778,11 +817,14 @@ public void getValueWithEmptyName() throws IOException { final BaseRegQueryValueResponse valueResponse = mock(BaseRegQueryValueResponse.class); final RegistryService registryService = new RegistryService(transport); + final RPCConformantVaryingByteArray byteArray = mock(RPCConformantVaryingByteArray.class); + when(byteArray.getArray()).thenReturn(new byte[]{0x01, 0x23, 0x45, 0x67}); + when(transport.call(any(RequestCall.class))).thenReturn(hiveResponse).thenReturn(keyResponse).thenReturn(valueResponse); when(hiveResponse.getReturnValue()).thenReturn(ERROR_SUCCESS.getValue()); when(keyResponse.getReturnValue()).thenReturn(ERROR_SUCCESS.getValue()); - when(valueResponse.getType()).thenReturn(RegistryValueType.REG_BINARY); - when(valueResponse.getData()).thenReturn(new byte[]{0x01, 0x23, 0x45, 0x67}); + when(valueResponse.getType()).thenReturn(RegistryValueType.REG_BINARY.getTypeID()); + when(valueResponse.getData()).thenReturn(byteArray); when(valueResponse.getReturnValue()).thenReturn(ERROR_SUCCESS.getValue()); final RegistryValue value = registryService.getValue("HKLM", "key", ""); @@ -810,11 +852,14 @@ public void getValueWithNullName() throws IOException { final BaseRegQueryValueResponse valueResponse = mock(BaseRegQueryValueResponse.class); final RegistryService registryService = new RegistryService(transport); + final RPCConformantVaryingByteArray byteArray = mock(RPCConformantVaryingByteArray.class); + when(byteArray.getArray()).thenReturn(new byte[]{0x01, 0x23, 0x45, 0x67}); + when(transport.call(any(RequestCall.class))).thenReturn(hiveResponse).thenReturn(keyResponse).thenReturn(valueResponse); when(hiveResponse.getReturnValue()).thenReturn(ERROR_SUCCESS.getValue()); when(keyResponse.getReturnValue()).thenReturn(ERROR_SUCCESS.getValue()); - when(valueResponse.getType()).thenReturn(RegistryValueType.REG_BINARY); - when(valueResponse.getData()).thenReturn(new byte[]{0x01, 0x23, 0x45, 0x67}); + when(valueResponse.getType()).thenReturn(RegistryValueType.REG_BINARY.getTypeID()); + when(valueResponse.getData()).thenReturn(byteArray); when(valueResponse.getReturnValue()).thenReturn(ERROR_SUCCESS.getValue()); final RegistryValue value = registryService.getValue("HKLM", "key", null); diff --git a/src/test/java/com/rapid7/net/client/dcerpc/objects/Test_FileTime.java b/src/test/java/com/rapid7/client/dcerpc/msrrp/dto/Test_FileTime.java similarity index 90% rename from src/test/java/com/rapid7/net/client/dcerpc/objects/Test_FileTime.java rename to src/test/java/com/rapid7/client/dcerpc/msrrp/dto/Test_FileTime.java index e2423d2c..19aa59bb 100644 --- a/src/test/java/com/rapid7/net/client/dcerpc/objects/Test_FileTime.java +++ b/src/test/java/com/rapid7/client/dcerpc/msrrp/dto/Test_FileTime.java @@ -1,26 +1,28 @@ -/** +/* * Copyright 2017, Rapid7, Inc. * * License: BSD-3-clause * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright notice, + * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - * * Redistributions in binary form must reproduce the above copyright + * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * * Neither the name of the copyright holder nor the names of its contributors + * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. + * + * */ -package com.rapid7.net.client.dcerpc.objects; +package com.rapid7.client.dcerpc.msrrp.dto; import java.util.Date; import org.junit.Test; -import com.rapid7.client.dcerpc.objects.FileTime; +import com.rapid7.client.dcerpc.msrrp.dto.FileTime; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; diff --git a/src/test/java/com/rapid7/client/dcerpc/msrrp/Test_RegistryHive.java b/src/test/java/com/rapid7/client/dcerpc/msrrp/dto/Test_RegistryHive.java similarity index 85% rename from src/test/java/com/rapid7/client/dcerpc/msrrp/Test_RegistryHive.java rename to src/test/java/com/rapid7/client/dcerpc/msrrp/dto/Test_RegistryHive.java index eeb20c32..f76f871a 100644 --- a/src/test/java/com/rapid7/client/dcerpc/msrrp/Test_RegistryHive.java +++ b/src/test/java/com/rapid7/client/dcerpc/msrrp/dto/Test_RegistryHive.java @@ -1,29 +1,30 @@ -/** +/* * Copyright 2017, Rapid7, Inc. * * License: BSD-3-clause * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright notice, + * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - * * Redistributions in binary form must reproduce the above copyright + * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * * Neither the name of the copyright holder nor the names of its contributors + * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. + * + * */ -package com.rapid7.client.dcerpc.msrrp; +package com.rapid7.client.dcerpc.msrrp.dto; -import java.util.EnumSet; import org.junit.Test; -import com.hierynomus.msdtyp.AccessMask; +import com.rapid7.client.dcerpc.msrrp.dto.RegistryHive; import com.rapid7.client.dcerpc.msrrp.messages.HandleRequest; -import static com.rapid7.client.dcerpc.msrrp.RegistryHive.*; +import static com.rapid7.client.dcerpc.msrrp.dto.RegistryHive.*; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; @@ -50,9 +51,9 @@ public void HKEY_CLASSES_ROOT_getOpNum() { @Test public void HKEY_CLASSES_ROOT_getRequest() { - final HandleRequest request = HKEY_CLASSES_ROOT.getRequest(EnumSet.of(AccessMask.MAXIMUM_ALLOWED)); + final HandleRequest request = HKEY_CLASSES_ROOT.getRequest(33554432); assertEquals(0, request.getOpNum()); - assertEquals(EnumSet.of(AccessMask.MAXIMUM_ALLOWED), request.getAccessMask()); + assertEquals(33554432, request.getAccessMask()); } @Test @@ -87,9 +88,9 @@ public void HKEY_CURRENT_CONFIG_getOpNum() { @Test public void HKEY_CURRENT_CONFIG_getRequest() { - final HandleRequest request = HKEY_CURRENT_CONFIG.getRequest(EnumSet.of(AccessMask.MAXIMUM_ALLOWED)); + final HandleRequest request = HKEY_CURRENT_CONFIG.getRequest(33554432); assertEquals(27, request.getOpNum()); - assertEquals(EnumSet.of(AccessMask.MAXIMUM_ALLOWED), request.getAccessMask()); + assertEquals(33554432, request.getAccessMask()); } @Test @@ -124,9 +125,9 @@ public void HKEY_CURRENT_USER_getOpNum() { @Test public void HKEY_CURRENT_USER_getRequest() { - final HandleRequest request = HKEY_CURRENT_USER.getRequest(EnumSet.of(AccessMask.MAXIMUM_ALLOWED)); + final HandleRequest request = HKEY_CURRENT_USER.getRequest(33554432); assertEquals(1, request.getOpNum()); - assertEquals(EnumSet.of(AccessMask.MAXIMUM_ALLOWED), request.getAccessMask()); + assertEquals(33554432, request.getAccessMask()); } @Test @@ -161,9 +162,9 @@ public void HKEY_LOCAL_MACHINE_getOpNum() { @Test public void HKEY_LOCAL_MACHINE_getRequest() { - final HandleRequest request = HKEY_LOCAL_MACHINE.getRequest(EnumSet.of(AccessMask.MAXIMUM_ALLOWED)); + final HandleRequest request = HKEY_LOCAL_MACHINE.getRequest(33554432); assertEquals(2, request.getOpNum()); - assertEquals(EnumSet.of(AccessMask.MAXIMUM_ALLOWED), request.getAccessMask()); + assertEquals(33554432, request.getAccessMask()); } @Test @@ -198,9 +199,9 @@ public void HKEY_PERFORMANCE_DATA_getOpNum() { @Test public void HKEY_PERFORMANCE_DATA_getRequest() { - final HandleRequest request = HKEY_PERFORMANCE_DATA.getRequest(EnumSet.of(AccessMask.MAXIMUM_ALLOWED)); + final HandleRequest request = HKEY_PERFORMANCE_DATA.getRequest(33554432); assertEquals(3, request.getOpNum()); - assertEquals(EnumSet.of(AccessMask.MAXIMUM_ALLOWED), request.getAccessMask()); + assertEquals(33554432, request.getAccessMask()); } @Test @@ -235,9 +236,9 @@ public void HKEY_PERFORMANCE_NLSTEXT_getOpNum() { @Test public void HKEY_PERFORMANCE_NLSTEXT_getRequest() { - final HandleRequest request = HKEY_PERFORMANCE_NLSTEXT.getRequest(EnumSet.of(AccessMask.MAXIMUM_ALLOWED)); + final HandleRequest request = HKEY_PERFORMANCE_NLSTEXT.getRequest(33554432); assertEquals(33, request.getOpNum()); - assertEquals(EnumSet.of(AccessMask.MAXIMUM_ALLOWED), request.getAccessMask()); + assertEquals(33554432, request.getAccessMask()); } @Test @@ -272,9 +273,9 @@ public void HKEY_PERFORMANCE_TEXT_getOpNum() { @Test public void HKEY_PERFORMANCE_TEXT_getRequest() { - final HandleRequest request = HKEY_PERFORMANCE_TEXT.getRequest(EnumSet.of(AccessMask.MAXIMUM_ALLOWED)); + final HandleRequest request = HKEY_PERFORMANCE_TEXT.getRequest(33554432); assertEquals(32, request.getOpNum()); - assertEquals(EnumSet.of(AccessMask.MAXIMUM_ALLOWED), request.getAccessMask()); + assertEquals(33554432, request.getAccessMask()); } @Test @@ -309,9 +310,9 @@ public void HKEY_USERS_getOpNum() { @Test public void HKEY_USERS_getRequest() { - final HandleRequest request = HKEY_USERS.getRequest(EnumSet.of(AccessMask.MAXIMUM_ALLOWED)); + final HandleRequest request = HKEY_USERS.getRequest(33554432); assertEquals(4, request.getOpNum()); - assertEquals(EnumSet.of(AccessMask.MAXIMUM_ALLOWED), request.getAccessMask()); + assertEquals(33554432, request.getAccessMask()); } @Test diff --git a/src/test/java/com/rapid7/client/dcerpc/msrrp/Test_RegistryKey.java b/src/test/java/com/rapid7/client/dcerpc/msrrp/dto/Test_RegistryKey.java similarity index 91% rename from src/test/java/com/rapid7/client/dcerpc/msrrp/Test_RegistryKey.java rename to src/test/java/com/rapid7/client/dcerpc/msrrp/dto/Test_RegistryKey.java index e113a5be..6eda1b3b 100644 --- a/src/test/java/com/rapid7/client/dcerpc/msrrp/Test_RegistryKey.java +++ b/src/test/java/com/rapid7/client/dcerpc/msrrp/dto/Test_RegistryKey.java @@ -1,25 +1,28 @@ -/** +/* * Copyright 2017, Rapid7, Inc. * * License: BSD-3-clause * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright notice, + * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - * * Redistributions in binary form must reproduce the above copyright + * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * * Neither the name of the copyright holder nor the names of its contributors + * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. + * + * */ -package com.rapid7.client.dcerpc.msrrp; +package com.rapid7.client.dcerpc.msrrp.dto; import org.junit.Test; -import com.rapid7.client.dcerpc.objects.FileTime; +import com.rapid7.client.dcerpc.msrrp.dto.RegistryKey; +import com.rapid7.client.dcerpc.msrrp.dto.FileTime; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; diff --git a/src/test/java/com/rapid7/client/dcerpc/msrrp/dto/Test_RegistryKeyInfo.java b/src/test/java/com/rapid7/client/dcerpc/msrrp/dto/Test_RegistryKeyInfo.java new file mode 100644 index 00000000..582cf382 --- /dev/null +++ b/src/test/java/com/rapid7/client/dcerpc/msrrp/dto/Test_RegistryKeyInfo.java @@ -0,0 +1,175 @@ +/* + * Copyright 2017, Rapid7, Inc. + * + * License: BSD-3-clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + */ +package com.rapid7.client.dcerpc.msrrp.dto; + +import org.junit.Test; + +import com.rapid7.client.dcerpc.msrrp.dto.RegistryKeyInfo; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; + +public class Test_RegistryKeyInfo { + @Test + public void getSubKeys() { + final RegistryKeyInfo keyInfo = new RegistryKeyInfo(0xff, 0, 0, 0, 0, 0, 0, 0l); + assertEquals(0xff, keyInfo.getSubKeys()); + } + + @Test + public void getMaxSubKeyLen() { + final RegistryKeyInfo keyInfo = new RegistryKeyInfo(0, 0xff, 0, 0, 0, 0, 0, 0l); + assertEquals(0xff, keyInfo.getMaxSubKeyLen()); + } + + @Test + public void getMaxClassLen() { + final RegistryKeyInfo keyInfo = new RegistryKeyInfo(0, 0, 0xff, 0, 0, 0, 0, 0l); + assertEquals(0xff, keyInfo.getMaxClassLen()); + } + + @Test + public void getValues() { + final RegistryKeyInfo keyInfo = new RegistryKeyInfo(0, 0, 0, 0xff, 0, 0, 0, 0l); + assertEquals(0xff, keyInfo.getValues()); + } + + @Test + public void getMaxValueNameLen() { + final RegistryKeyInfo keyInfo = new RegistryKeyInfo(0, 0, 0, 0, 0xff, 0, 0, 0l); + assertEquals(0xff, keyInfo.getMaxValueNameLen()); + } + + @Test + public void getMaxValueLen() { + final RegistryKeyInfo keyInfo = new RegistryKeyInfo(0, 0, 0, 0, 0, 0xff, 0, 0l); + assertEquals(0xff, keyInfo.getMaxValueLen()); + } + + @Test + public void getSecurityDescriptor() { + final RegistryKeyInfo keyInfo = new RegistryKeyInfo(0, 0, 0, 0, 0, 0, 0xff, 0l); + assertEquals(0xff, keyInfo.getSecurityDescriptor()); + } + + @Test + public void getLastWriteTime() { + final RegistryKeyInfo keyInfo = new RegistryKeyInfo(0, 0, 0, 0, 0, 0, 0, 0xffl); + assertEquals(0xffl, keyInfo.getLastWriteTime()); + } + + @Test + public void test_hashCode() { + int subKeys1 = 1; + int subKeys2 = 2; + int maxSubKeyLen1 = 3; + int maxSubKeyLen2 = 4; + int maxClassLen1 = 5; + int maxClassLen2 = 6; + int values1 = 7; + int values2 = 8; + int maxValueNameLen1 = 9; + int maxValueNameLen2 = 10; + int maxValueLen1 = 11; + int maxValueLen2 = 12; + int securityDescriptor1 = 13; + int securityDescriptor2 = 14; + int lastWriteTime1 = 15; + int lastWriteTime2 = 16; + RegistryKeyInfo keyInfo1 = new RegistryKeyInfo(subKeys1, maxSubKeyLen1, maxClassLen1, values1, maxValueNameLen1, maxValueLen1, securityDescriptor1, lastWriteTime1); + RegistryKeyInfo keyInfo2 = new RegistryKeyInfo(subKeys1, maxSubKeyLen1, maxClassLen1, values1, maxValueNameLen1, maxValueLen1, securityDescriptor1, lastWriteTime1); + RegistryKeyInfo keyInfo3 = new RegistryKeyInfo(subKeys2, maxSubKeyLen1, maxClassLen1, values1, maxValueNameLen1, maxValueLen1, securityDescriptor1, lastWriteTime1); + RegistryKeyInfo keyInfo4 = new RegistryKeyInfo(subKeys1, maxSubKeyLen2, maxClassLen1, values1, maxValueNameLen1, maxValueLen1, securityDescriptor1, lastWriteTime1); + RegistryKeyInfo keyInfo5 = new RegistryKeyInfo(subKeys1, maxSubKeyLen1, maxClassLen2, values1, maxValueNameLen1, maxValueLen1, securityDescriptor1, lastWriteTime1); + RegistryKeyInfo keyInfo6 = new RegistryKeyInfo(subKeys1, maxSubKeyLen1, maxClassLen1, values2, maxValueNameLen1, maxValueLen1, securityDescriptor1, lastWriteTime1); + RegistryKeyInfo keyInfo7 = new RegistryKeyInfo(subKeys1, maxSubKeyLen1, maxClassLen1, values1, maxValueNameLen2, maxValueLen1, securityDescriptor1, lastWriteTime1); + RegistryKeyInfo keyInfo8 = new RegistryKeyInfo(subKeys1, maxSubKeyLen1, maxClassLen1, values1, maxValueNameLen1, maxValueLen2, securityDescriptor1, lastWriteTime1); + RegistryKeyInfo keyInfo9 = new RegistryKeyInfo(subKeys1, maxSubKeyLen1, maxClassLen1, values1, maxValueNameLen1, maxValueLen1, securityDescriptor2, lastWriteTime1); + RegistryKeyInfo keyInfo10 = new RegistryKeyInfo(subKeys1, maxSubKeyLen1, maxClassLen1, values1, maxValueNameLen1, maxValueLen1, securityDescriptor1, lastWriteTime2); + assertEquals(keyInfo1.hashCode(), keyInfo2.hashCode()); + assertEquals(keyInfo1.hashCode(), keyInfo2.hashCode()); + assertNotEquals(keyInfo1.hashCode(), keyInfo3.hashCode()); + assertNotEquals(keyInfo1.hashCode(), keyInfo4.hashCode()); + assertNotEquals(keyInfo1.hashCode(), keyInfo5.hashCode()); + assertNotEquals(keyInfo1.hashCode(), keyInfo6.hashCode()); + assertNotEquals(keyInfo1.hashCode(), keyInfo7.hashCode()); + assertNotEquals(keyInfo1.hashCode(), keyInfo8.hashCode()); + assertNotEquals(keyInfo1.hashCode(), keyInfo9.hashCode()); + assertNotEquals(keyInfo1.hashCode(), keyInfo10.hashCode()); + } + + @Test + public void test_equals() { + int subKeys1 = 1; + int subKeys2 = 2; + int maxSubKeyLen1 = 3; + int maxSubKeyLen2 = 4; + int maxClassLen1 = 5; + int maxClassLen2 = 6; + int values1 = 7; + int values2 = 8; + int maxValueNameLen1 = 9; + int maxValueNameLen2 = 10; + int maxValueLen1 = 11; + int maxValueLen2 = 12; + int securityDescriptor1 = 13; + int securityDescriptor2 = 14; + int lastWriteTime1 = 15; + int lastWriteTime2 = 16; + RegistryKeyInfo keyInfo1 = new RegistryKeyInfo(subKeys1, maxSubKeyLen1, maxClassLen1, values1, maxValueNameLen1, maxValueLen1, securityDescriptor1, lastWriteTime1); + RegistryKeyInfo keyInfo2 = new RegistryKeyInfo(subKeys1, maxSubKeyLen1, maxClassLen1, values1, maxValueNameLen1, maxValueLen1, securityDescriptor1, lastWriteTime1); + RegistryKeyInfo keyInfo3 = new RegistryKeyInfo(subKeys2, maxSubKeyLen1, maxClassLen1, values1, maxValueNameLen1, maxValueLen1, securityDescriptor1, lastWriteTime1); + RegistryKeyInfo keyInfo4 = new RegistryKeyInfo(subKeys1, maxSubKeyLen2, maxClassLen1, values1, maxValueNameLen1, maxValueLen1, securityDescriptor1, lastWriteTime1); + RegistryKeyInfo keyInfo5 = new RegistryKeyInfo(subKeys1, maxSubKeyLen1, maxClassLen2, values1, maxValueNameLen1, maxValueLen1, securityDescriptor1, lastWriteTime1); + RegistryKeyInfo keyInfo6 = new RegistryKeyInfo(subKeys1, maxSubKeyLen1, maxClassLen1, values2, maxValueNameLen1, maxValueLen1, securityDescriptor1, lastWriteTime1); + RegistryKeyInfo keyInfo7 = new RegistryKeyInfo(subKeys1, maxSubKeyLen1, maxClassLen1, values1, maxValueNameLen2, maxValueLen1, securityDescriptor1, lastWriteTime1); + RegistryKeyInfo keyInfo8 = new RegistryKeyInfo(subKeys1, maxSubKeyLen1, maxClassLen1, values1, maxValueNameLen1, maxValueLen2, securityDescriptor1, lastWriteTime1); + RegistryKeyInfo keyInfo9 = new RegistryKeyInfo(subKeys1, maxSubKeyLen1, maxClassLen1, values1, maxValueNameLen1, maxValueLen1, securityDescriptor2, lastWriteTime1); + RegistryKeyInfo keyInfo10 = new RegistryKeyInfo(subKeys1, maxSubKeyLen1, maxClassLen1, values1, maxValueNameLen1, maxValueLen1, securityDescriptor1, lastWriteTime2); + assertEquals(keyInfo1, keyInfo1); + assertNotEquals(keyInfo1, null); + assertNotEquals(keyInfo1, "test"); + assertEquals(keyInfo1, keyInfo2); + assertEquals(keyInfo1, keyInfo2); + assertNotEquals(keyInfo1, keyInfo3); + assertNotEquals(keyInfo1, keyInfo4); + assertNotEquals(keyInfo1, keyInfo5); + assertNotEquals(keyInfo1, keyInfo6); + assertNotEquals(keyInfo1, keyInfo7); + assertNotEquals(keyInfo1, keyInfo8); + assertNotEquals(keyInfo1, keyInfo9); + assertNotEquals(keyInfo1, keyInfo10); + } + + @Test + public void test_toString() { + int subKeys = 1; + int maxSubKeyLen = 3; + int maxClassLen = 5; + int values = 7; + int maxValueNameLen = 9; + int maxValueLen = 11; + int securityDescriptor = 13; + int lastWriteTime = 15; + RegistryKeyInfo keyInfo = new RegistryKeyInfo(subKeys, maxSubKeyLen, maxClassLen, values, maxValueNameLen, maxValueLen, securityDescriptor, lastWriteTime); + assertEquals(keyInfo.toString(), "RegistryKeyInfo{subKeys: 1, maxSubKeyLen: 3, maxClassLen: 5, values: 7, maxValueNameLen: 9, maxValueLen: 11, securityDescriptor: 13,lastWriteTime: 15}"); + } +} diff --git a/src/test/java/com/rapid7/client/dcerpc/msrrp/Test_RegistryValue.java b/src/test/java/com/rapid7/client/dcerpc/msrrp/dto/Test_RegistryValue.java similarity index 98% rename from src/test/java/com/rapid7/client/dcerpc/msrrp/Test_RegistryValue.java rename to src/test/java/com/rapid7/client/dcerpc/msrrp/dto/Test_RegistryValue.java index d3390413..5cac2fdb 100644 --- a/src/test/java/com/rapid7/client/dcerpc/msrrp/Test_RegistryValue.java +++ b/src/test/java/com/rapid7/client/dcerpc/msrrp/dto/Test_RegistryValue.java @@ -1,26 +1,31 @@ -/** +/* * Copyright 2017, Rapid7, Inc. * * License: BSD-3-clause * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright notice, + * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - * * Redistributions in binary form must reproduce the above copyright + * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * * Neither the name of the copyright holder nor the names of its contributors + * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. + * + * */ -package com.rapid7.client.dcerpc.msrrp; +package com.rapid7.client.dcerpc.msrrp.dto; import java.io.IOException; import org.junit.Test; +import com.rapid7.client.dcerpc.msrrp.dto.RegistryValue; +import com.rapid7.client.dcerpc.msrrp.dto.RegistryValueType; + import static org.junit.Assert.*; public class Test_RegistryValue { diff --git a/src/test/java/com/rapid7/client/dcerpc/msrrp/Test_RegistryValueType.java b/src/test/java/com/rapid7/client/dcerpc/msrrp/dto/Test_RegistryValueType.java similarity index 93% rename from src/test/java/com/rapid7/client/dcerpc/msrrp/Test_RegistryValueType.java rename to src/test/java/com/rapid7/client/dcerpc/msrrp/dto/Test_RegistryValueType.java index 6d6f7d9b..ace4dc42 100644 --- a/src/test/java/com/rapid7/client/dcerpc/msrrp/Test_RegistryValueType.java +++ b/src/test/java/com/rapid7/client/dcerpc/msrrp/dto/Test_RegistryValueType.java @@ -1,26 +1,30 @@ -/** +/* * Copyright 2017, Rapid7, Inc. * * License: BSD-3-clause * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright notice, + * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - * * Redistributions in binary form must reproduce the above copyright + * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * * Neither the name of the copyright holder nor the names of its contributors + * Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. + * + * */ -package com.rapid7.client.dcerpc.msrrp; +package com.rapid7.client.dcerpc.msrrp.dto; import org.junit.Test; -import static com.rapid7.client.dcerpc.msrrp.RegistryValueType.*; +import com.rapid7.client.dcerpc.msrrp.dto.RegistryValueType; + +import static com.rapid7.client.dcerpc.msrrp.dto.RegistryValueType.*; import static org.junit.Assert.*; public class Test_RegistryValueType { diff --git a/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegEnumKeyRequest.java b/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegEnumKeyRequest.java index 799e374d..a1d88237 100644 --- a/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegEnumKeyRequest.java +++ b/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegEnumKeyRequest.java @@ -22,6 +22,8 @@ import org.bouncycastle.util.encoders.Hex; import org.junit.Test; +import com.rapid7.client.dcerpc.objects.RPCUnicodeString; + import static org.bouncycastle.util.encoders.Hex.toHexString; import static org.hamcrest.CoreMatchers.instanceOf; import static org.junit.Assert.assertEquals; diff --git a/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegEnumKeyResponse.java b/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegEnumKeyResponse.java index 88758a04..3150b29e 100644 --- a/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegEnumKeyResponse.java +++ b/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegEnumKeyResponse.java @@ -20,7 +20,7 @@ import java.io.IOException; import org.junit.Test; -import com.rapid7.client.dcerpc.objects.FileTime; +import com.rapid7.client.dcerpc.objects.RPCUnicodeString; import static org.junit.Assert.assertEquals; @@ -70,7 +70,7 @@ public void unmarshal() throws IOException { response.fromHexString("180000020000020000010000000000000c000000420043004400300030003000300030003000300030000000040002000200feff08000200ff7f00000000000001000000000000000c00020026cd57b90de6d20100000000"); - assertEquals("BCD00000000", response.getName()); + assertEquals(RPCUnicodeString.NullTerminated.of("BCD00000000"), response.getLpNameOut()); assertEquals(131420285765668134L, response.getLastWriteTime()); assertEquals(0, response.getReturnValue()); } diff --git a/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegEnumValueResponse.java b/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegEnumValueResponse.java index f8c24575..70f5b7f1 100644 --- a/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegEnumValueResponse.java +++ b/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegEnumValueResponse.java @@ -20,7 +20,7 @@ import java.io.IOException; import org.junit.Test; -import com.rapid7.client.dcerpc.msrrp.RegistryValueType; +import com.rapid7.client.dcerpc.msrrp.dto.RegistryValueType; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -92,9 +92,9 @@ public void unmarshal() throws IOException { response.fromHexString("1600feff00000200ff7f0000000000000b000000530079007300740065006d0052006f006f0074000000000004000200010000000800020016000000000000001600000043003a005c00570069006e0064006f0077007300000000000c00020016000000100002001600000000000000"); - assertEquals("SystemRoot", response.getName()); - assertEquals(RegistryValueType.REG_SZ, response.getType()); - assertArrayEquals("C:\\Windows\0".getBytes("UTF-16LE"), response.getData()); + assertEquals("SystemRoot", response.getName().getValue()); + assertEquals(RegistryValueType.REG_SZ.getTypeID(), (int) response.getType()); + assertArrayEquals("C:\\Windows\0".getBytes("UTF-16LE"), response.getData().getArray()); assertEquals(0, response.getReturnValue()); } } diff --git a/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegOpenKey.java b/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegOpenKey.java index 50cf09dd..95d7cc28 100644 --- a/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegOpenKey.java +++ b/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegOpenKey.java @@ -29,11 +29,13 @@ import com.hierynomus.msdtyp.AccessMask; import com.hierynomus.protocol.commons.EnumWithValue.EnumUtils; import com.rapid7.client.dcerpc.messages.HandleResponse; +import com.rapid7.client.dcerpc.objects.RPCUnicodeString; +import com.rapid7.client.dcerpc.objects.WChar; public class Test_BaseRegOpenKey { private final byte[] contextHandle = Hex.decode("0000000032daf234b77c86409d29efe60d326683"); private final BaseRegOpenKey request = new BaseRegOpenKey(contextHandle, - "Software\\Microsoft\\Windows NT\\CurrentVersion", 0, + RPCUnicodeString.NullTerminated.of("Software\\Microsoft\\Windows NT\\CurrentVersion"), 0, (int) EnumUtils.toLong(EnumSet.of(AccessMask.MAXIMUM_ALLOWED))); @Test diff --git a/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegQueryValueRequest.java b/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegQueryValueRequest.java index 6a1bf587..00339cab 100644 --- a/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegQueryValueRequest.java +++ b/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegQueryValueRequest.java @@ -22,6 +22,8 @@ import org.bouncycastle.util.encoders.Hex; import org.junit.Test; +import com.rapid7.client.dcerpc.objects.RPCUnicodeString; + import static org.bouncycastle.util.encoders.Hex.toHexString; import static org.hamcrest.CoreMatchers.instanceOf; import static org.junit.Assert.assertEquals; @@ -29,7 +31,7 @@ public class Test_BaseRegQueryValueRequest { private final byte[] contextHandle = Hex.decode("000000000a665393f4666e49a68cd99f269d020f"); - private final BaseRegQueryValueRequest request = new BaseRegQueryValueRequest(contextHandle, "CurrentVersion", 65536); + private final BaseRegQueryValueRequest request = new BaseRegQueryValueRequest(contextHandle, RPCUnicodeString.NullTerminated.of("CurrentVersion"), 65536); @Test public void getOpNum() { diff --git a/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegQueryValueResponse.java b/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegQueryValueResponse.java index 579e705c..ba96d3aa 100644 --- a/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegQueryValueResponse.java +++ b/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_BaseRegQueryValueResponse.java @@ -20,7 +20,7 @@ import java.io.IOException; import org.junit.Test; -import com.rapid7.client.dcerpc.msrrp.RegistryValueType; +import com.rapid7.client.dcerpc.msrrp.dto.RegistryValueType; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; @@ -58,8 +58,8 @@ public void unmarshal() throws IOException { response.fromHexString("00000200010000000400020008000000000000000800000036002e003300000008000200080000000c0002000800000000000000"); - assertArrayEquals("6.3\0".getBytes("UTF-16LE"), response.getData()); - assertEquals(RegistryValueType.REG_SZ, response.getType()); + assertArrayEquals("6.3\0".getBytes("UTF-16LE"), response.getData().getArray()); + assertEquals(RegistryValueType.REG_SZ.getTypeID(), (int) response.getType()); assertEquals(0, response.getReturnValue()); } } diff --git a/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_HandleRequest.java b/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_HandleRequest.java index 714784ca..73962333 100644 --- a/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_HandleRequest.java +++ b/src/test/java/com/rapid7/client/dcerpc/msrrp/messages/Test_HandleRequest.java @@ -19,9 +19,7 @@ package com.rapid7.client.dcerpc.msrrp.messages; import java.io.IOException; -import java.util.EnumSet; import org.junit.Test; -import com.hierynomus.msdtyp.AccessMask; import com.rapid7.client.dcerpc.messages.HandleResponse; import static org.bouncycastle.util.encoders.Hex.toHexString; @@ -30,7 +28,7 @@ import static org.junit.Assert.assertThat; public class Test_HandleRequest { - private final HandleRequest request = new HandleRequest(OpenLocalMachine.OP_NUM, EnumSet.of(AccessMask.MAXIMUM_ALLOWED)); + private final HandleRequest request = new HandleRequest(OpenLocalMachine.OP_NUM, 33554432); @Test public void getOpNum() { diff --git a/src/test/java/com/rapid7/client/dcerpc/mssamr/dto/Test_DomainLockoutInfo.java b/src/test/java/com/rapid7/client/dcerpc/mssamr/dto/Test_DomainLockoutInfo.java new file mode 100644 index 00000000..1f616737 --- /dev/null +++ b/src/test/java/com/rapid7/client/dcerpc/mssamr/dto/Test_DomainLockoutInfo.java @@ -0,0 +1,73 @@ +/* + * Copyright 2017, Rapid7, Inc. + * + * License: BSD-3-clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + */ + +package com.rapid7.client.dcerpc.mssamr.dto; + +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotEquals; + +public class Test_DomainLockoutInfo { + + @Test + public void test_getters() { + DomainLockoutInfo obj = new DomainLockoutInfo(1, 2, 3); + assertEquals(obj.getLockoutDuration(), 1); + assertEquals(obj.getLockoutObservationWindow(), 2); + assertEquals(obj.getLockoutThreshold(), 3); + } + + @Test + public void test_hashCode() { + DomainLockoutInfo obj1 = new DomainLockoutInfo(1, 2, 3); + DomainLockoutInfo obj2 = new DomainLockoutInfo(1, 2, 3); + DomainLockoutInfo obj3 = new DomainLockoutInfo(10, 2, 3); + DomainLockoutInfo obj4 = new DomainLockoutInfo(1, 20, 3); + DomainLockoutInfo obj5 = new DomainLockoutInfo(1, 2, 30); + assertEquals(obj1.hashCode(), obj2.hashCode()); + assertNotEquals(obj1.hashCode(), obj3.hashCode()); + assertNotEquals(obj1.hashCode(), obj4.hashCode()); + assertNotEquals(obj1.hashCode(), obj5.hashCode()); + } + + @Test + public void test_equals() { + DomainLockoutInfo obj1 = new DomainLockoutInfo(1, 2, 3); + DomainLockoutInfo obj2 = new DomainLockoutInfo(1, 2, 3); + DomainLockoutInfo obj3 = new DomainLockoutInfo(10, 2, 3); + DomainLockoutInfo obj4 = new DomainLockoutInfo(1, 20, 3); + DomainLockoutInfo obj5 = new DomainLockoutInfo(1, 2, 30); + assertEquals(obj1, obj1); + assertNotEquals(obj1, null); + assertNotEquals(obj1, "test"); + assertEquals(obj1, obj2); + assertNotEquals(obj1, obj3); + assertNotEquals(obj1, obj4); + assertNotEquals(obj1, obj5); + } + + @Test + public void test_toString() { + DomainLockoutInfo obj = new DomainLockoutInfo(1, 2, 3); + assertEquals(obj.toString(), "DomainLockoutInfo{lockoutDuration: 1, lockoutObservationWindow: 2, lockoutThreshold: 3}"); + } +} diff --git a/src/test/java/com/rapid7/client/dcerpc/mssamr/dto/Test_DomainLogoffInfo.java b/src/test/java/com/rapid7/client/dcerpc/mssamr/dto/Test_DomainLogoffInfo.java new file mode 100644 index 00000000..60a01f65 --- /dev/null +++ b/src/test/java/com/rapid7/client/dcerpc/mssamr/dto/Test_DomainLogoffInfo.java @@ -0,0 +1,63 @@ +/* + * Copyright 2017, Rapid7, Inc. + * + * License: BSD-3-clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + */ + +package com.rapid7.client.dcerpc.mssamr.dto; + +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotEquals; + +public class Test_DomainLogoffInfo { + + @Test + public void test_getters() { + DomainLogoffInfo obj = new DomainLogoffInfo(2L); + assertEquals(obj.getForceLogoff(), 2L); + } + + @Test + public void test_hashCode() { + DomainLogoffInfo obj1 = new DomainLogoffInfo(2L); + DomainLogoffInfo obj2 = new DomainLogoffInfo(2L); + DomainLogoffInfo obj3 = new DomainLogoffInfo(3L); + assertEquals(obj1.hashCode(), obj2.hashCode()); + assertNotEquals(obj1.hashCode(), obj3.hashCode()); + } + + @Test + public void test_equals() { + DomainLogoffInfo obj1 = new DomainLogoffInfo(2L); + DomainLogoffInfo obj2 = new DomainLogoffInfo(2L); + DomainLogoffInfo obj3 = new DomainLogoffInfo(3L); + assertEquals(obj1, obj1); + assertNotEquals(obj1, null); + assertNotEquals(obj1, "test"); + assertEquals(obj1, obj2); + assertNotEquals(obj1, obj3); + } + + @Test + public void test_toString() { + DomainLogoffInfo obj = new DomainLogoffInfo(2L); + assertEquals(obj.toString(), "DomainLogoffInfo{forceLogoff: 2}"); + } +} diff --git a/src/test/java/com/rapid7/client/dcerpc/mssamr/dto/Test_DomainPasswordInfo.java b/src/test/java/com/rapid7/client/dcerpc/mssamr/dto/Test_DomainPasswordInfo.java new file mode 100644 index 00000000..e1c7fcda --- /dev/null +++ b/src/test/java/com/rapid7/client/dcerpc/mssamr/dto/Test_DomainPasswordInfo.java @@ -0,0 +1,122 @@ +/* + * Copyright 2017, Rapid7, Inc. + * + * License: BSD-3-clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + */ + +package com.rapid7.client.dcerpc.mssamr.dto; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotEquals; + +public class Test_DomainPasswordInfo { + + @Test + public void test_getters() { + DomainPasswordInfo obj = new DomainPasswordInfo(1, 2, 3, 4L, 5L); + assertEquals(obj.getMinimumPasswordLength(), 1); + assertEquals(obj.getPasswordHistoryLength(), 2); + assertEquals(obj.getPasswordProperties(), 3); + assertEquals(obj.getMaximumPasswordAge(), 4L); + assertEquals(obj.getMinimumPasswordAge(), 5L); + } + + @DataProvider + public Object[][] data_isDomainPasswordComplex() { + return new Object[][] { + {0, false}, + {1, true}, + {3, true} + }; + } + + @Test(dataProvider = "data_isDomainPasswordComplex") + public void test_isDomainPasswordComplex(int passwordProperties, boolean expect) { + DomainPasswordInfo obj = new DomainPasswordInfo(0, 0, passwordProperties, 0L, 0L); + assertEquals(obj.isDomainPasswordComplex(), expect); + } + + @DataProvider + public Object[][] data_isDomainPasswordNoAnonChange() { + return new Object[][] { + {0, false}, + {2, true}, + {3, true} + }; + } + + @Test(dataProvider = "data_isDomainPasswordNoAnonChange") + public void test_isDomainPasswordNoAnonChange(int passwordProperties, boolean expect) { + DomainPasswordInfo obj = new DomainPasswordInfo(0, 0, passwordProperties, 0L, 0L); + assertEquals(obj.isDomainPasswordNoAnonChange(), expect); + } + + @DataProvider + public Object[][] data_isDomainPasswordStoredClearText() { + return new Object[][] { + {0, false}, + {16, true}, + {17, true} + }; + } + + @Test(dataProvider = "data_isDomainPasswordStoredClearText") + public void test_isDomainPasswordStoredClearText(int passwordProperties, boolean expect) { + DomainPasswordInfo obj = new DomainPasswordInfo(0, 0, passwordProperties, 0L, 0L); + assertEquals(obj.isDomainPasswordStoredClearText(), expect); + } + + @Test + public void test_hashCode() { + DomainPasswordInfo obj1 = new DomainPasswordInfo(1, 2, 3, 4L, 5L); + DomainPasswordInfo obj2 = new DomainPasswordInfo(1, 20, 3, 4L, 5L); + DomainPasswordInfo obj3 = new DomainPasswordInfo(1, 2, 30, 4L, 5L); + DomainPasswordInfo obj4 = new DomainPasswordInfo(1, 2, 3, 40L, 5L); + DomainPasswordInfo obj5 = new DomainPasswordInfo(1, 2, 3, 4L, 50L); + assertEquals(obj1.hashCode(), obj1.hashCode()); + assertNotEquals(obj1.hashCode(), obj2.hashCode()); + assertNotEquals(obj1.hashCode(), obj3.hashCode()); + assertNotEquals(obj1.hashCode(), obj4.hashCode()); + assertNotEquals(obj1.hashCode(), obj5.hashCode()); + } + + @Test + public void test_equals() { + DomainPasswordInfo obj1 = new DomainPasswordInfo(1, 2, 3, 4L, 5L); + DomainPasswordInfo obj2 = new DomainPasswordInfo(1, 20, 3, 4L, 5L); + DomainPasswordInfo obj3 = new DomainPasswordInfo(1, 2, 30, 4L, 5L); + DomainPasswordInfo obj4 = new DomainPasswordInfo(1, 2, 3, 40L, 5L); + DomainPasswordInfo obj5 = new DomainPasswordInfo(1, 2, 3, 4L, 50L); + assertEquals(obj1, obj1); + assertNotEquals(obj1, null); + assertNotEquals(obj1, "test"); + assertNotEquals(obj1, obj2); + assertNotEquals(obj1, obj3); + assertNotEquals(obj1, obj4); + assertNotEquals(obj1, obj5); + } + + @Test + public void test_toString() { + assertEquals(new DomainPasswordInfo(1, 2, 3, 4L, 5L).toString(), + "DomainPasswordInformation{minimumPasswordLength: 1, passwordHistoryLength: 2, passwordProperties: 3, maximumPasswordAge: 4, minimumPasswordAge: 5, isDomainPasswordComplex: true, isDomainPasswordNoAnonChange: true, isDomainPasswordStoredClearText: false}"); + } +} diff --git a/src/test/java/com/rapid7/client/dcerpc/mssamr/dto/Test_LogonHours.java b/src/test/java/com/rapid7/client/dcerpc/mssamr/dto/Test_LogonHours.java index b3490874..72ffcca2 100644 --- a/src/test/java/com/rapid7/client/dcerpc/mssamr/dto/Test_LogonHours.java +++ b/src/test/java/com/rapid7/client/dcerpc/mssamr/dto/Test_LogonHours.java @@ -24,8 +24,6 @@ import org.testng.annotations.DataProvider; import org.testng.annotations.Test; -import sun.rmi.runtime.Log; - import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotEquals; import static org.testng.Assert.assertSame; diff --git a/src/test/java/com/rapid7/client/dcerpc/mssamr/dto/Test_MembershipWithNameAndUse.java b/src/test/java/com/rapid7/client/dcerpc/mssamr/dto/Test_MembershipWithNameAndUse.java new file mode 100644 index 00000000..e48ea4cd --- /dev/null +++ b/src/test/java/com/rapid7/client/dcerpc/mssamr/dto/Test_MembershipWithNameAndUse.java @@ -0,0 +1,89 @@ +/* + * Copyright 2017, Rapid7, Inc. + * + * License: BSD-3-clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + */ + +package com.rapid7.client.dcerpc.mssamr.dto; + +import com.rapid7.client.dcerpc.dto.SIDUse; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotEquals; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertSame; + +public class Test_MembershipWithNameAndUse { + @Test + public void test_getters() { + MembershipWithNameAndUse obj = new MembershipWithNameAndUse(1L, "name1", 2); + assertEquals(obj.getRelativeID(), 1L); + assertEquals(obj.getName(), "name1"); + assertEquals(obj.getUseValue(), 2); + assertSame(obj.getUse(), SIDUse.SID_TYPE_GROUP); + } + + @Test + public void test_use_Unknown() { + MembershipWithNameAndUse obj = new MembershipWithNameAndUse(1L, "name1", 200); + assertEquals(obj.getUseValue(), 200); + assertNull(obj.getUse()); + } + + @Test + public void test_hashCode() { + MembershipWithNameAndUse obj1 = new MembershipWithNameAndUse(1L, "name1", 200); + MembershipWithNameAndUse obj2 = new MembershipWithNameAndUse(1L, "name1", 200); + MembershipWithNameAndUse obj3 = new MembershipWithNameAndUse(2L, "name1", 200); + MembershipWithNameAndUse obj4 = new MembershipWithNameAndUse(1L, "name2", 200); + MembershipWithNameAndUse obj5 = new MembershipWithNameAndUse(1L, "name1", 300); + assertEquals(obj1.hashCode(), obj2.hashCode()); + assertNotEquals(obj1.hashCode(), obj3.hashCode()); + assertNotEquals(obj1.hashCode(), obj4.hashCode()); + assertNotEquals(obj1.hashCode(), obj5.hashCode()); + } + + @Test + public void test_equals() { + MembershipWithNameAndUse obj1 = new MembershipWithNameAndUse(1L, "name1", 200); + MembershipWithNameAndUse obj2 = new MembershipWithNameAndUse(1L, "name1", 200); + MembershipWithNameAndUse obj3 = new MembershipWithNameAndUse(2L, "name1", 200); + MembershipWithNameAndUse obj4 = new MembershipWithNameAndUse(1L, "name2", 200); + MembershipWithNameAndUse obj5 = new MembershipWithNameAndUse(1L, "name1", 300); + assertEquals(obj1, obj1); + assertNotEquals(obj1, null); + assertNotEquals(obj1, "test"); + assertEquals(obj1, obj2); + assertNotEquals(obj1, obj3); + assertNotEquals(obj1, obj4); + assertNotEquals(obj1, obj5); + } + + @Test + public void test_toString() { + MembershipWithNameAndUse obj = new MembershipWithNameAndUse(1L, "name1", 2); + assertEquals(obj.toString(), "MembershipWithNameAndUse{relativeID: 1, name: \"name1\", use: 2 (SID_TYPE_GROUP)}"); + } + + @Test + public void test_toString_nulls() { + MembershipWithNameAndUse obj = new MembershipWithNameAndUse(1L, null, 200); + assertEquals(obj.toString(), "MembershipWithNameAndUse{relativeID: 1, name: null, use: 200}"); + } +} diff --git a/src/test/java/com/rapid7/client/dcerpc/mssamr/dto/Test_MembershipWithUse.java b/src/test/java/com/rapid7/client/dcerpc/mssamr/dto/Test_MembershipWithUse.java index 0b81d9b7..16e78bd3 100644 --- a/src/test/java/com/rapid7/client/dcerpc/mssamr/dto/Test_MembershipWithUse.java +++ b/src/test/java/com/rapid7/client/dcerpc/mssamr/dto/Test_MembershipWithUse.java @@ -21,18 +21,29 @@ package com.rapid7.client.dcerpc.mssamr.dto; +import com.rapid7.client.dcerpc.dto.SIDUse; import org.testng.annotations.Test; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotEquals; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertSame; public class Test_MembershipWithUse { @Test public void test_getters() { - MembershipWithUse obj = new MembershipWithUse(50L, 100); + MembershipWithUse obj = new MembershipWithUse(50L, 1); assertEquals(obj.getRelativeID(), 50L); - assertEquals(obj.getUse(), 100); + assertEquals(obj.getUseValue(), 1); + assertSame(obj.getUse(), SIDUse.SID_TYPE_USER); + } + + @Test + public void test_getUse_unknown() { + MembershipWithUse obj = new MembershipWithUse(50L, 100); + assertEquals(obj.getUseValue(), 100); + assertNull(obj.getUse()); } @Test @@ -56,7 +67,12 @@ public void test_equals() { } @Test - public void test_toString() { + public void test_toString_useUnknown() { assertEquals(new MembershipWithUse(50L, 100).toString(), "MembershipWithUse{relativeID: 50, use: 100}"); } + + @Test + public void test_toString() { + assertEquals(new MembershipWithUse(50L, 2).toString(), "MembershipWithUse{relativeID: 50, use: 2 (SID_TYPE_GROUP)}"); + } } diff --git a/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrConnect2Request.java b/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrConnect2Request.java index 8d39a11e..dd978bf3 100644 --- a/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrConnect2Request.java +++ b/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrConnect2Request.java @@ -22,6 +22,7 @@ import org.junit.Test; import com.hierynomus.msdtyp.AccessMask; import com.rapid7.client.dcerpc.messages.HandleResponse; +import com.rapid7.client.dcerpc.objects.WChar; import static org.bouncycastle.util.encoders.Hex.toHexString; import static org.hamcrest.CoreMatchers.instanceOf; @@ -29,7 +30,7 @@ import static org.junit.Assert.assertThat; public class Test_SamrConnect2Request { - private final SamrConnect2Request request = new SamrConnect2Request("", (int) AccessMask.MAXIMUM_ALLOWED.getValue()); + private final SamrConnect2Request request = new SamrConnect2Request(WChar.NullTerminated.of(""), (int) AccessMask.MAXIMUM_ALLOWED.getValue()); @Test public void getOpNum() { diff --git a/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrGetAliasMembershipRequest.java b/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrGetAliasMembershipRequest.java index a4faa78f..11e839e8 100644 --- a/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrGetAliasMembershipRequest.java +++ b/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrGetAliasMembershipRequest.java @@ -26,6 +26,7 @@ import org.bouncycastle.util.encoders.Hex; import org.junit.Test; import com.rapid7.client.dcerpc.dto.SID; +import com.rapid7.client.dcerpc.mssamr.objects.SAMPRPSIDArray; import com.rapid7.client.dcerpc.objects.RPCSID; public class Test_SamrGetAliasMembershipRequest { @@ -42,8 +43,9 @@ public void getStub() throws IOException { rpcSid2.setRevision((char) sid2.getRevision()); rpcSid2.setIdentifierAuthority(sid2.getIdentifierAuthority()); rpcSid2.setSubAuthority(sid2.getSubAuthorities()); + SAMPRPSIDArray samprpsidArray = new SAMPRPSIDArray(rpcSid1, rpcSid2); byte[] handle = Hex.decode("000000005f32a420f68b2645b4e0e8467cc2e111"); - SamrGetAliasMembershipRequest request1 = new SamrGetAliasMembershipRequest(handle, rpcSid1, rpcSid2); + SamrGetAliasMembershipRequest request1 = new SamrGetAliasMembershipRequest(handle, samprpsidArray); assertEquals( "000000005f32a420f68b2645b4e0e8467cc2e11102000000000002000200000004000200080002000100000001010000000000052000000001000000010100000000000515000000", toHexString(request1.getStub())); @@ -52,20 +54,20 @@ public void getStub() throws IOException { @Test public void getStubEmptyArray() throws IOException { byte[] handle = Hex.decode("000000005f32a420f68b2645b4e0e8467cc2e111"); - SamrGetAliasMembershipRequest request1 = new SamrGetAliasMembershipRequest(handle); + SamrGetAliasMembershipRequest request1 = new SamrGetAliasMembershipRequest(handle, new SAMPRPSIDArray()); assertEquals("000000005f32a420f68b2645b4e0e8467cc2e111000000000000020000000000", toHexString(request1.getStub())); } @Test public void getResponseObject() throws IOException { - SamrGetAliasMembershipRequest request1 = new SamrGetAliasMembershipRequest(new byte[20]); + SamrGetAliasMembershipRequest request1 = new SamrGetAliasMembershipRequest(new byte[20], null); assertThat(request1.getResponseObject(), instanceOf(SamrGetAliasMembershipResponse.class)); } @Test public void getOpNum() { - SamrGetAliasMembershipRequest request1 = new SamrGetAliasMembershipRequest(new byte[20]); + SamrGetAliasMembershipRequest request1 = new SamrGetAliasMembershipRequest(new byte[20], null); assertEquals(SamrGetAliasMembershipRequest.OP_NUM, request1.getOpNum()); } } diff --git a/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrGetAliasMembershipResponse.java b/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrGetAliasMembershipResponse.java index 8d796b22..87c1ff0a 100644 --- a/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrGetAliasMembershipResponse.java +++ b/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrGetAliasMembershipResponse.java @@ -28,7 +28,7 @@ public class Test_SamrGetAliasMembershipResponse { public void unmarshalEmptyResponse() throws IOException { SamrGetAliasMembershipResponse response = new SamrGetAliasMembershipResponse(); response.fromHexString("00000000000002000000000000000000"); - assertEquals(0, response.getList().length); + assertEquals(0, response.getMembership().getArray().length); assertEquals(0, response.getReturnValue()); } @@ -36,8 +36,8 @@ public void unmarshalEmptyResponse() throws IOException { public void unmarshalResponse() throws IOException { SamrGetAliasMembershipResponse response = new SamrGetAliasMembershipResponse(); response.fromHexString("0100000000000200010000002102000000000000"); - assertEquals(1, response.getList().length); - assertEquals(545, response.getList()[0].intValue()); + assertEquals(1, response.getMembership().getArray().length); + assertEquals(545L, response.getMembership().getArray()[0]); assertEquals(0, response.getReturnValue()); } diff --git a/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrQueryInformationAliasResponse.java b/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrQueryInformationAliasResponse.java index fdeb7394..1d2960e4 100644 --- a/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrQueryInformationAliasResponse.java +++ b/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrQueryInformationAliasResponse.java @@ -58,7 +58,7 @@ public void test_getters(SamrQueryInformationAliasResponse response, AliasInform public Object[][] data_unmarshal() { return new Object[][] { // Reference: 1, ALIAS_INFORMATION_CLASS: 1 - {new SamrQueryInformationAliasResponse.AliasGeneralInformation(), "01000000 0100 01000000"} + {new SamrQueryInformationAliasResponse.AliasGeneralInformation(), "01000000 0100 FFFF 01000000"} }; } diff --git a/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrQueryInformationDomain.java b/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrQueryInformationDomain.java index e6c78e56..15a9ee2a 100755 --- a/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrQueryInformationDomain.java +++ b/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrQueryInformationDomain.java @@ -25,7 +25,7 @@ import org.junit.Test; import com.rapid7.client.dcerpc.io.PacketInput; import com.rapid7.client.dcerpc.mssamr.objects.SAMPRDomainLockoutInfo; -import com.rapid7.client.dcerpc.mssamr.objects.SAMPRDomainLogOffInfo; +import com.rapid7.client.dcerpc.mssamr.objects.SAMPRDomainLogoffInfo; import com.rapid7.client.dcerpc.mssamr.objects.SAMPRDomainPasswordInfo; public class Test_SamrQueryInformationDomain { @@ -48,10 +48,10 @@ public void SamrQueryPasswordInformationDomain() throws IOException { @Test public void SamrQueryLogOffInformationDomain() throws IOException { String hexString = "0000020003000000000000000000008001000000"; - SamrQueryInformationDomainResponse + SamrQueryInformationDomainResponse response = new SamrQueryInformationDomainResponse.DomainLogOffInformation(); response.unmarshal(getPacketInput(hexString)); - SAMPRDomainLogOffInfo logOffInfo = response.getDomainInformation(); + SAMPRDomainLogoffInfo logOffInfo = response.getDomainInformation(); // -9223372036854775808(never expire) assertEquals(-9223372036854775808L, logOffInfo.getForceLogoff()); @@ -60,7 +60,7 @@ public void SamrQueryLogOffInformationDomain() throws IOException { @Test public void SamrQueryLockoutInformationDomain() throws IOException { - String hexString = "000002000c00000000cc1dcffbffffff00cc1dcffbffffff000001000000"; + String hexString = "000002000c00000000cc1dcffbffffff00cc1dcffbffffff0000FFFF01000000"; SamrQueryInformationDomainResponse response = new SamrQueryInformationDomainResponse.DomainLockoutInformation(); response.unmarshal(getPacketInput(hexString)); diff --git a/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrQueryInformationGroupResponse.java b/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrQueryInformationGroupResponse.java index 02aa4c05..405e01af 100644 --- a/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrQueryInformationGroupResponse.java +++ b/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrQueryInformationGroupResponse.java @@ -30,7 +30,6 @@ import com.rapid7.client.dcerpc.io.PacketInput; import com.rapid7.client.dcerpc.io.ndr.Unmarshallable; import com.rapid7.client.dcerpc.mssamr.objects.GroupInformationClass; -import com.rapid7.client.dcerpc.mssamr.objects.UserInformationClass; import static org.mockito.Matchers.any; import static org.mockito.Mockito.doReturn; @@ -59,7 +58,7 @@ public void test_getters(SamrQueryInformationGroupResponse response, GroupInform public Object[][] data_unmarshal() { return new Object[][] { // Reference: 1, GROUP_INFORMATION_CLASS: 1 - {new SamrQueryInformationGroupResponse.GroupGeneralInformation(), "01000000 0100 01000000"} + {new SamrQueryInformationGroupResponse.GroupGeneralInformation(), "01000000 0100 FFFF 01000000"} }; } diff --git a/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrQueryInformationUserResponse.java b/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrQueryInformationUserResponse.java index 95019c9b..c213b058 100644 --- a/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrQueryInformationUserResponse.java +++ b/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrQueryInformationUserResponse.java @@ -58,7 +58,7 @@ public void test_getters(SamrQueryInformationUserResponse response, UserInformat public Object[][] data_unmarshal() { return new Object[][] { // Reference: 1, USER_INFORMATION_CLASS: 21 - {new SamrQueryInformationUserResponse.UserAllInformation(), "01000000 1500 01000000"} + {new SamrQueryInformationUserResponse.UserAllInformation(), "01000000 1500 FFFF 01000000"} }; } diff --git a/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrQuerySecurityObjectResponse.java b/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrQuerySecurityObjectResponse.java index 41998cc6..180a2c46 100644 --- a/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrQuerySecurityObjectResponse.java +++ b/src/test/java/com/rapid7/client/dcerpc/mssamr/messages/Test_SamrQuerySecurityObjectResponse.java @@ -47,8 +47,10 @@ public void test_unmarshal() throws IOException { "02000000" + // SecurityDescriptor: Length: 2 Reference: 2 "02000000 00000200" + - // SecurityDescriptor: MaximumCount: 3 SecurityDescriptor: {1, 2}, ReturnValue: 1 - "02000000 01 02 01000000"; + // SecurityDescriptor: MaximumCount: 3 SecurityDescriptor: {1, 2} + "02000000 01 02" + + // Alignment, ReturnValue: 1 + "FFFF 01000000"; ByteArrayInputStream bin = new ByteArrayInputStream(Hex.decode(hex)); PacketInput in = new PacketInput(bin); diff --git a/src/test/java/com/rapid7/client/dcerpc/mssamr/objects/Test_SAMPRDisplayGroupBuffer.java b/src/test/java/com/rapid7/client/dcerpc/mssamr/objects/Test_SAMPRDisplayGroupBuffer.java index c34466d7..cfa165d6 100644 --- a/src/test/java/com/rapid7/client/dcerpc/mssamr/objects/Test_SAMPRDisplayGroupBuffer.java +++ b/src/test/java/com/rapid7/client/dcerpc/mssamr/objects/Test_SAMPRDisplayGroupBuffer.java @@ -24,6 +24,7 @@ import org.bouncycastle.util.encoders.Hex; import org.junit.Test; import com.rapid7.client.dcerpc.io.PacketInput; +import com.rapid7.client.dcerpc.objects.RPCUnicodeString; public class Test_SAMPRDisplayGroupBuffer { @@ -38,8 +39,8 @@ public void unmarshall() throws IOException { SAMPRDomainDisplayGroup groupInfo = buffer.getEntries().get(0); assertEquals(1, groupInfo.getIndex()); assertEquals(513, groupInfo.getRid()); - assertEquals("None", groupInfo.getAccountName()); - assertEquals("Ordinary users", groupInfo.getDescription()); + assertEquals(RPCUnicodeString.NonNullTerminated.of("None"), groupInfo.getAccountName()); + assertEquals(RPCUnicodeString.NonNullTerminated.of("Ordinary users"), groupInfo.getDescription()); assertEquals(0x00000007, groupInfo.getAttributes()); } diff --git a/src/test/java/com/rapid7/client/dcerpc/mssrvs/Test_LsarEnumerateAccountRights.java b/src/test/java/com/rapid7/client/dcerpc/mssrvs/Test_LsarEnumerateAccountRights.java index f4319126..9f666761 100755 --- a/src/test/java/com/rapid7/client/dcerpc/mssrvs/Test_LsarEnumerateAccountRights.java +++ b/src/test/java/com/rapid7/client/dcerpc/mssrvs/Test_LsarEnumerateAccountRights.java @@ -29,6 +29,7 @@ import com.rapid7.client.dcerpc.mslsad.messages.LsarEnumerateAccountRightsRequest; import com.rapid7.client.dcerpc.mslsad.messages.LsarEnumerateAccountRightsResponse; import com.rapid7.client.dcerpc.objects.RPCSID; +import com.rapid7.client.dcerpc.objects.RPCUnicodeString; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -41,8 +42,8 @@ public void lsar_SingleLsarEnumerateAccountRightsResponse() throws IOException { String hexString = "01000000000002000100000036003800040002001C000000000000001B00000053006500440075006D006D0079003100440075006D006D0079003200440075006D006D00790033003400350052006900670068007400000000000000"; response.unmarshal(getPacketInput(hexString)); //dummy Privilege - String[] expectedPrivs = {"SeDummy1Dummy2Dummy345Right"}; - String[] privs = response.getPrivNames(); + RPCUnicodeString.NonNullTerminated[] expectedPrivs = {RPCUnicodeString.NonNullTerminated.of("SeDummy1Dummy2Dummy345Right")}; + RPCUnicodeString.NonNullTerminated[] privs = response.getPrivNames(); assertTrue(Arrays.equals(expectedPrivs, privs)); } @@ -53,8 +54,12 @@ public void lsar_MultipleLsarEnumerateAccountRightsResponse() throws IOException String hexString = "0300000000000200030000002E0030000400020036003800080002002E0030000C00020018000000000000001700000053006500440075006D006D007900440075006D006D007900440075006D006D00790031005200690067006800740000001C000000000000001B00000053006500440075006D006D0079003100440075006D006D0079003200440075006D006D00790033003400350052006900670068007400000018000000000000001700000053006500440075006D006D007900440075006D006D0079003100440075006D006D00790052006900670068007400000000000000"; response.unmarshal(getPacketInput(hexString)); //dummy Privileges - String[] expectedPrivs = {"SeDummyDummyDummy1Right", "SeDummy1Dummy2Dummy345Right", "SeDummyDummy1DummyRight"}; - String[] privs = response.getPrivNames(); + RPCUnicodeString.NonNullTerminated[] expectedPrivs = { + RPCUnicodeString.NonNullTerminated.of("SeDummyDummyDummy1Right"), + RPCUnicodeString.NonNullTerminated.of("SeDummy1Dummy2Dummy345Right"), + RPCUnicodeString.NonNullTerminated.of("SeDummyDummy1DummyRight") + }; + RPCUnicodeString.NonNullTerminated[] privs = response.getPrivNames(); assertTrue(Arrays.equals(expectedPrivs, privs)); } diff --git a/src/test/java/com/rapid7/client/dcerpc/mssrvs/Test_NetPrPathCanonicalize.java b/src/test/java/com/rapid7/client/dcerpc/mssrvs/Test_NetPrPathCanonicalize.java index fa738471..b8e3c0fb 100644 --- a/src/test/java/com/rapid7/client/dcerpc/mssrvs/Test_NetPrPathCanonicalize.java +++ b/src/test/java/com/rapid7/client/dcerpc/mssrvs/Test_NetPrPathCanonicalize.java @@ -23,8 +23,10 @@ import org.junit.Test; import org.junit.rules.ExpectedException; import com.rapid7.client.dcerpc.mserref.SystemErrorCode; +import com.rapid7.client.dcerpc.mssrvs.dto.NetprPathType; import com.rapid7.client.dcerpc.mssrvs.messages.NetprPathCanonicalizeRequest; import com.rapid7.client.dcerpc.mssrvs.messages.NetprPathCanonicalizeResponse; +import com.rapid7.client.dcerpc.objects.WChar; import static org.junit.Assert.assertEquals; @@ -39,15 +41,20 @@ public void parseNetprPathCanonicalizeResponse() throws IOException { response.fromHexString("c800000043003a005c0053006f006d0065007400680069006e00670000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000620000000000000"); - assertEquals("C:\\Something", response.getCanonicalizedPath()); + assertEquals("C:\\Something", response.getOutBuf()); assertEquals(SystemErrorCode.ERROR_SUCCESS.getValue(), response.getReturnValue()); - assertEquals(NetprPathType.ITYPE_PATH_ABSD, response.getPathType()); + assertEquals(NetprPathType.ITYPE_PATH_ABSD.getId(), response.getPathType()); } @SuppressWarnings("unchecked") @Test public void encodeNetprPathCanonicalize() throws IOException { - final NetprPathCanonicalizeRequest request = new NetprPathCanonicalizeRequest("dummy", "C:\\Linux\\..\\Windows\\Something\\..", 25, "C:\\", 0, 0); + final NetprPathCanonicalizeRequest request = new NetprPathCanonicalizeRequest( + WChar.NullTerminated.of("dummy"), + WChar.NullTerminated.of("C:\\Linux\\..\\Windows\\Something\\.."), + 25, + WChar.NullTerminated.of("C:\\"), + 0, 0); assertEquals(request.toHexString(), "00000200060000000000000006000000640075006d006d007900000021000000000000002100000043003a005c004c0069006e00750078005c002e002e005c00570069006e0064006f00770073005c0053006f006d0065007400680069006e0067005c002e002e00000000001900000004000000000000000400000043003a005c0000000000000000000000"); } diff --git a/src/test/java/com/rapid7/client/dcerpc/objects/Test_SIDNameUse.java b/src/test/java/com/rapid7/client/dcerpc/objects/Test_SIDNameUse.java index 9a61e583..54ab90cf 100644 --- a/src/test/java/com/rapid7/client/dcerpc/objects/Test_SIDNameUse.java +++ b/src/test/java/com/rapid7/client/dcerpc/objects/Test_SIDNameUse.java @@ -21,6 +21,7 @@ package com.rapid7.client.dcerpc.objects; +import com.rapid7.client.dcerpc.dto.SIDUse; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -33,32 +34,32 @@ public class Test_SIDNameUse { @DataProvider public Object[][] data_pairs() { return new Object[][] { - {SIDNameUse.SID_TYPE_USER, (short) 1}, - {SIDNameUse.SID_TYPE_GROUP, (short) 2}, - {SIDNameUse.SID_TYPE_DOMAIN, (short) 3}, - {SIDNameUse.SID_TYPE_ALIAS, (short) 4}, - {SIDNameUse.SID_TYPE_WELL_KNOWN_GROUP, (short) 5}, - {SIDNameUse.SID_TYPE_DELETED_ACCOUNT, (short) 6}, - {SIDNameUse.SID_TYPE_INVALID, (short) 7}, - {SIDNameUse.SID_TYPE_UNKNOWN, (short) 8}, - {SIDNameUse.SID_TYPE_COMPUTER, (short) 9}, - {SIDNameUse.SID_TYPE_LABEL, (short) 10} + {SIDUse.SID_TYPE_USER, (short) 1}, + {SIDUse.SID_TYPE_GROUP, (short) 2}, + {SIDUse.SID_TYPE_DOMAIN, (short) 3}, + {SIDUse.SID_TYPE_ALIAS, (short) 4}, + {SIDUse.SID_TYPE_WELL_KNOWN_GROUP, (short) 5}, + {SIDUse.SID_TYPE_DELETED_ACCOUNT, (short) 6}, + {SIDUse.SID_TYPE_INVALID, (short) 7}, + {SIDUse.SID_TYPE_UNKNOWN, (short) 8}, + {SIDUse.SID_TYPE_COMPUTER, (short) 9}, + {SIDUse.SID_TYPE_LABEL, (short) 10} }; } @Test(dataProvider = "data_pairs") - public void test_getValue(SIDNameUse use, short expected) { + public void test_getValue(SIDUse use, short expected) { assertEquals(use.getValue(), expected); } @Test(dataProvider = "data_pairs") - public void test_fromValue(SIDNameUse expected, short value) { - assertSame(SIDNameUse.fromValue(value), expected); + public void test_fromValue(SIDUse expected, short value) { + assertSame(SIDUse.fromValue(value), expected); } @Test public void test_fromValue_unknown() { - assertNull(SIDNameUse.fromValue((short) 255)); + assertNull(SIDUse.fromValue((short) 255)); } }