Skip to content

Commit e5e91a2

Browse files
committed
validate packages of classes to load
1 parent 3bb318b commit e5e91a2

File tree

1 file changed

+58
-15
lines changed

1 file changed

+58
-15
lines changed

server/src/main/java/com/cloud/api/ApiSerializerHelper.java

Lines changed: 58 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@
1616
// under the License.
1717
package com.cloud.api;
1818

19+
import java.util.Arrays;
1920
import java.util.HashMap;
2021
import java.util.Map;
2122

23+
import com.cloud.utils.exception.CloudRuntimeException;
2224
import org.apache.log4j.Logger;
2325

2426
import com.fasterxml.jackson.core.JsonProcessingException;
@@ -30,38 +32,51 @@
3032
public class ApiSerializerHelper {
3133
public static final Logger s_logger = Logger.getLogger(ApiSerializerHelper.class.getName());
3234
private static String token = "/";
35+
private static String[] apiPackages = {"com.cloud.agent.api", "org.apache.cloudstack.api"};
3336

34-
public static String toSerializedString(Object result) {
35-
if (result != null) {
36-
Class<?> clz = result.getClass();
37+
/**
38+
* serialise an object's class to a {@link String}
39+
* @param inputObject
40+
* @return
41+
*/
42+
public static String toSerializedString(Object inputObject) {
43+
if (inputObject != null) {
44+
Class<?> clz = inputObject.getClass();
3745
Gson gson = ApiGsonHelper.getBuilder().create();
3846

39-
if (result instanceof ResponseObject) {
40-
return clz.getName() + token + ((ResponseObject)result).getObjectName() + token + gson.toJson(result);
47+
if (inputObject instanceof ResponseObject) {
48+
return clz.getName() + token + ((ResponseObject)inputObject).getObjectName() + token + gson.toJson(inputObject);
4149
} else {
42-
return clz.getName() + token + gson.toJson(result);
50+
return clz.getName() + token + gson.toJson(inputObject);
4351
}
4452
}
4553
return null;
4654
}
4755

48-
public static Object fromSerializedString(String result) {
56+
/**
57+
* deserialise an {@link Object} from a {@link String}
58+
*
59+
* @param classString the string representation of the {@link Class} instance to create
60+
* @return an {@link Object} of the requested {@link Class} type
61+
*/
62+
public static Object fromSerializedString(String classString) {
4963
try {
50-
if (result != null && !result.isEmpty()) {
51-
String[] serializedParts = result.split(token);
64+
if (classString != null && !classString.isEmpty()) {
65+
String[] serializedParts = classString.split(token);
5266

5367
if (serializedParts.length < 2) {
5468
return null;
5569
}
5670
String clzName = serializedParts[0];
71+
validateClassPath(clzName, apiPackages);
5772
String nameField = null;
5873
String content = null;
5974
if (serializedParts.length == 2) {
6075
content = serializedParts[1];
6176
} else {
6277
nameField = serializedParts[1];
63-
int index = result.indexOf(token + nameField + token);
64-
content = result.substring(index + nameField.length() + 2);
78+
int index = classString.indexOf(token + nameField + token);
79+
content = classString.substring(index + nameField.length() + 2);
6580
}
6681

6782
Class<?> clz;
@@ -80,15 +95,43 @@ public static Object fromSerializedString(String result) {
8095
}
8196
return null;
8297
} catch (RuntimeException e) {
83-
s_logger.error("Caught runtime exception when doing GSON deserialization on: " + result);
98+
s_logger.error("Caught runtime exception when doing GSON deserialization on: " + classString);
8499
throw e;
85100
}
86101
}
87102

88-
public static Map<String, Object> fromSerializedStringToMap(String result) {
103+
/**
104+
* validates that a class is allowed to be deserialised.
105+
*
106+
* TODO move to a more globally accesible util class
107+
* TODO make generic for allow lists
108+
* TODO extend to return the desired class
109+
*
110+
* @param clzName
111+
* @param basePaths
112+
*/
113+
private static void validateClassPath(String clzName, String[] basePaths) {
114+
if (clzName != null) {
115+
for (String basePath : basePaths) {
116+
if (clzName.startsWith(basePath)) {
117+
return;
118+
}
119+
}
120+
}
121+
String packages = Arrays.toString(basePaths);
122+
throw new CloudRuntimeException(String.format("illegal to load \"%s\" forName, only classes in packages \"%s\" are allowed", clzName, packages));
123+
}
124+
125+
/**
126+
* deserialise a map
127+
*
128+
* @param mapRepresentation the {@link String} representation of the {@link Map<>} type
129+
* @return the {@link Map<>} object
130+
*/
131+
public static Map<String, Object> fromSerializedStringToMap(String mapRepresentation) {
89132
Map<String,Object> objParams = null;
90133
try {
91-
Object obj = fromSerializedString(result);
134+
Object obj = fromSerializedString(mapRepresentation);
92135
if (obj != null) {
93136
Gson gson = ApiGsonHelper.getBuilder().create();
94137
String objJson = gson.toJson(obj);
@@ -101,7 +144,7 @@ public static Map<String, Object> fromSerializedStringToMap(String result) {
101144
}
102145
}
103146
} catch (RuntimeException | JsonProcessingException e) {
104-
s_logger.error("Caught runtime exception when doing GSON deserialization to map on: " + result, e);
147+
s_logger.error("Caught runtime exception when doing GSON deserialization to map on: " + mapRepresentation, e);
105148
}
106149

107150
return objParams;

0 commit comments

Comments
 (0)