Skip to content

Commit 64e38bd

Browse files
authored
Giant Refactor (#120)
* Marshalling/Unmarshalling conformance * `PacketInput.readString`, `PacketOutput.writeString` and related methods have been removed. `WChar` has been used in its place. * `PacketInput.readStringBuffer`, `PacketOutput.writeStringBuffer` and related methods have been removed. `RPCUnicodeString` has been used in its place * `PacketInput.align()` and `PacketOutput.align()` have been removed. `Alignment` must always be considered by the caller by using `align(Alignment alignment)`. * A significant change to `RequestResponse` (all request responses throughout the repository) has been made which performs the necessary alignment before reading the `NTCODE` as an int. Additionally, the code then checks that all bytes have been read off the wire, otherwise an `UnmarshalException` is thrown; this is important, as otherwise can not trust that we have read the `NTCODE` properly. * All services have been refactored so that they have a clear distinction between RPC level objects, and DTOs. This includes adding DTOs where they were missing * Adds lots of missing documentation * Adds lots of missing unit test coverage * Code styling conformance
1 parent e5f693c commit 64e38bd

File tree

121 files changed

+2780
-1459
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

121 files changed

+2780
-1459
lines changed

src/main/java/com/rapid7/client/dcerpc/objects/SIDNameUse.java renamed to src/main/java/com/rapid7/client/dcerpc/dto/SIDUse.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
*
2020
*/
2121

22-
package com.rapid7.client.dcerpc.objects;
22+
package com.rapid7.client.dcerpc.dto;
2323

2424
import java.util.HashMap;
2525
import java.util.Map;
@@ -51,7 +51,7 @@
5151
* SidTypeComputer: This member is not used.
5252
* SidTypeLabel: This member is not used.</pre></blockquote>
5353
*/
54-
public enum SIDNameUse {
54+
public enum SIDUse {
5555
SID_TYPE_USER((short) 1),
5656
SID_TYPE_GROUP((short) 2),
5757
SID_TYPE_DOMAIN((short) 3),
@@ -65,22 +65,22 @@ public enum SIDNameUse {
6565

6666
private final short value;
6767

68-
SIDNameUse(final short value) {
68+
SIDUse(final short value) {
6969
this.value = value;
7070
}
7171

7272
public short getValue() {
7373
return value;
7474
}
7575

76-
private static final Map<Short, SIDNameUse> VALUE_MAP = new HashMap<>();
76+
private static final Map<Short, SIDUse> VALUE_MAP = new HashMap<>();
7777
static {
78-
for (SIDNameUse sidNameUse : SIDNameUse.values()) {
78+
for (SIDUse sidNameUse : SIDUse.values()) {
7979
VALUE_MAP.put(sidNameUse.getValue(), sidNameUse);
8080
}
8181
}
8282

83-
public static SIDNameUse fromValue(final short value) {
83+
public static SIDUse fromValue(final short value) {
8484
return VALUE_MAP.get(value);
8585
}
8686
}

src/main/java/com/rapid7/client/dcerpc/io/PacketInput.java

Lines changed: 50 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -18,128 +18,86 @@
1818
*/
1919
package com.rapid7.client.dcerpc.io;
2020

21+
import java.io.EOFException;
2122
import java.io.IOException;
2223
import java.io.InputStream;
24+
import java.rmi.UnmarshalException;
2325
import com.rapid7.client.dcerpc.io.ndr.Unmarshallable;
2426

2527
public class PacketInput extends PrimitiveInput {
2628
public PacketInput(final InputStream inputStream) {
2729
super(inputStream);
2830
}
2931

32+
/**
33+
* Read a non-null object which implements {@link Unmarshallable}.
34+
* This object *must* be considered a top level object; if it is not, consider calling
35+
* {@link Unmarshallable#unmarshalPreamble(PacketInput)}, {@link Unmarshallable#unmarshalEntity(PacketInput)},
36+
* and {@link Unmarshallable#unmarshalDeferrals(PacketInput)} separately at the appropriate locations.
37+
* @param unmarshallable A non-null {@link Unmarshallable} object.
38+
* @param <T> The class of the provided unmarshallable object.
39+
* @return The same input parameter. Useful for chaining.
40+
* @throws IOException On read failure.
41+
*/
3042
public <T extends Unmarshallable> T readUnmarshallable(T unmarshallable) throws IOException {
3143
unmarshallable.unmarshalPreamble(this);
3244
unmarshallable.unmarshalEntity(this);
3345
unmarshallable.unmarshalDeferrals(this);
3446
return unmarshallable;
3547
}
3648

37-
public Integer readIntRef() throws IOException {
38-
return 0 != readReferentID() ? readInt() : null;
39-
}
40-
41-
public Long readLongRef() throws IOException {
42-
return 0 != readReferentID() ? readLong() : null;
43-
}
44-
49+
/**
50+
* Read a referent ID unique to this instance of {@link PacketInput}.
51+
* @return A referent ID unique to this instance of {@link PacketInput}.
52+
* @throws IOException On read failure.
53+
*/
4554
public int readReferentID() throws IOException {
4655
// Currently only supports NDR20
4756
return readInt();
4857
}
4958

50-
public byte[] readByteArray() throws IOException {
51-
readInt();
52-
final int initialOffset = readInt();
53-
final int actualCount = readInt();
54-
final byte[] result = new byte[initialOffset + actualCount];
55-
56-
for (int index = initialOffset; index < result.length; index++) {
57-
result[index] = readByte();
58-
}
59-
60-
return result;
61-
}
62-
63-
public byte[] readByteArrayRef() throws IOException {
64-
final byte[] result;
65-
if (0 != readReferentID()) {
66-
result = readByteArray();
67-
align();
68-
} else {
69-
result = null;
70-
}
71-
72-
return result;
73-
}
74-
75-
public byte[] readRawBytes(int length) throws IOException {
59+
/**
60+
* Read and return length number of bytes.
61+
* @param length The number of bytes to read.
62+
* @return A byte[] populated with length bytes.
63+
* @throws EOFException If not enough bytes are available.
64+
* @throws IOException On read failure.
65+
*/
66+
public byte[] readRawBytes(final int length) throws IOException {
7667
byte[] bytes = new byte[length];
7768
readRawBytes(bytes);
7869

7970
return bytes;
8071
}
8172

82-
public void readRawBytes(byte[] buf) throws IOException {
73+
/**
74+
* Read all bytes into the given buffer.
75+
* @param buf The buffer to read into.
76+
* @throws EOFException If not enough bytes are available to fill the buffer.
77+
* @throws IOException On read failure.
78+
*/
79+
public void readRawBytes(final byte[] buf) throws IOException {
8380
readFully(buf, 0, buf.length);
8481
}
8582

86-
public String readString(final boolean nullTerminated) throws IOException {
87-
final StringBuffer result;
88-
89-
readInt();
90-
final int initialOffset = readInt();
91-
final int currentChars = readInt();
92-
93-
result = new StringBuffer(currentChars);
94-
result.setLength(initialOffset);
95-
96-
int currentOffset = 0;
97-
while (currentOffset++ < currentChars) {
98-
final char currentChar = (char) readShort();
99-
if (nullTerminated && currentChar == 0) {
100-
break;
101-
}
102-
result.append(currentChar);
103-
}
104-
105-
while (currentOffset++ < currentChars) {
106-
readShort();
107-
}
108-
109-
align();
110-
111-
return result.toString();
112-
}
113-
114-
public String readStringRef(final boolean nullTerminated) throws IOException {
115-
final String result;
116-
117-
if (0 != readReferentID()) {
118-
result = readString(nullTerminated);
119-
align();
120-
} else {
121-
result = null;
122-
}
123-
124-
return result != null ? result.toString() : null;
125-
}
126-
127-
public String readStringBuf(final boolean nullTerminated) throws IOException {
128-
readShort(); // Current byte length
129-
readShort(); // Maximum byte length
130-
131-
return readStringRef(nullTerminated);
132-
}
133-
134-
public String readStringBufRef(final boolean nullTerminated) throws IOException {
135-
final String result;
136-
if (0 != readReferentID()) {
137-
result = readStringBuf(nullTerminated);
138-
align();
139-
} else {
140-
result = null;
83+
/**
84+
* Read an unsigned integer which is to be used as an array size or offset.
85+
*
86+
* Due to the limitations of Java, we must used a signed integer, and array lengths can not
87+
* exceed the maximum value of an unsigned integer. Therefore, if the read unsigned integer
88+
* is greater than {@link Integer#MAX_VALUE}, this will throw an {@link UnmarshalException}.
89+
*
90+
* @param name The name of the entity being read. Used in the potential {@link UnmarshalException}.
91+
* @return The unsigned integer which is guaranteed to be valid as an array size or offset.
92+
* @throws UnmarshalException When the value exceeds {@link Integer#MAX_VALUE}.
93+
* @throws IOException On read failure.
94+
*/
95+
public int readIndex(final String name) throws IOException {
96+
final long ret = readUnsignedInt();
97+
// Don't allow array length or index values bigger than signed int
98+
if (ret > Integer.MAX_VALUE) {
99+
throw new UnmarshalException(String.format("%s %d > %d", name, ret, Integer.MAX_VALUE));
141100
}
142-
143-
return result;
101+
return (int) ret;
144102
}
145103
}

0 commit comments

Comments
 (0)