Skip to content

Commit 75c81d9

Browse files
anshul-gangwarRohit Yadav
authored andcommitted
CLOUDSTACK-9705: Unauthenticated API allows Admin password reset
Now, Updating the password via UpdateUser API is not allowed via integration port (cherry picked from commit d206336) Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
1 parent 8240bc4 commit 75c81d9

3 files changed

Lines changed: 30 additions & 5 deletions

File tree

api/src/org/apache/cloudstack/api/Parameter.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,6 @@
5151
RoleType[] authorized() default {};
5252

5353
ApiArgValidator[] validations() default {};
54+
55+
boolean acceptedOnAdminPort() default true;
5456
}

api/src/org/apache/cloudstack/api/command/admin/user/UpdateUserCmd.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@
1818

1919
import javax.inject.Inject;
2020

21-
import org.apache.log4j.Logger;
22-
2321
import org.apache.cloudstack.api.APICommand;
2422
import org.apache.cloudstack.api.ApiConstants;
2523
import org.apache.cloudstack.api.ApiErrorCode;
@@ -29,6 +27,7 @@
2927
import org.apache.cloudstack.api.response.UserResponse;
3028
import org.apache.cloudstack.context.CallContext;
3129
import org.apache.cloudstack.region.RegionService;
30+
import org.apache.log4j.Logger;
3231

3332
import com.cloud.user.Account;
3433
import com.cloud.user.User;
@@ -61,10 +60,12 @@ public class UpdateUserCmd extends BaseCmd {
6160
private String lastname;
6261

6362
@Parameter(name = ApiConstants.PASSWORD,
64-
type = CommandType.STRING,
65-
description = "Clear text password (default hashed to SHA256SALT). If you wish to use any other hasing algorithm, you would need to write a custom authentication adapter")
63+
type = CommandType.STRING,
64+
description = "Clear text password (default hashed to SHA256SALT). If you wish to use any other hasing algorithm, you would need to write a custom authentication adapter. Can't be passed when command is executed via integration.api.port",
65+
acceptedOnAdminPort = false)
6666
private String password;
6767

68+
6869
@Parameter(name = ApiConstants.SECRET_KEY, type = CommandType.STRING, description = "The secret key for the user. Must be specified with userSecretKey")
6970
private String secretKey;
7071

server/src/com/cloud/api/ApiServer.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import com.cloud.utils.HttpUtils;
4545
import com.cloud.utils.NumbersUtil;
4646
import com.cloud.utils.Pair;
47+
import com.cloud.utils.ReflectUtil;
4748
import com.cloud.utils.StringUtils;
4849
import com.cloud.utils.component.ComponentContext;
4950
import com.cloud.utils.component.ManagerBase;
@@ -65,6 +66,7 @@
6566
import org.apache.cloudstack.api.BaseAsyncCreateCmd;
6667
import org.apache.cloudstack.api.BaseCmd;
6768
import org.apache.cloudstack.api.BaseListCmd;
69+
import org.apache.cloudstack.api.Parameter;
6870
import org.apache.cloudstack.api.ResponseObject;
6971
import org.apache.cloudstack.api.ResponseObject.ResponseView;
7072
import org.apache.cloudstack.api.ServerApiException;
@@ -150,6 +152,7 @@
150152
import java.io.IOException;
151153
import java.io.InterruptedIOException;
152154
import java.lang.reflect.Type;
155+
import java.lang.reflect.Field;
153156
import java.net.InetAddress;
154157
import java.net.ServerSocket;
155158
import java.net.Socket;
@@ -430,8 +433,27 @@ public void handle(final HttpRequest request, final HttpResponse response, final
430433
if (!(responseType.equals(HttpUtils.RESPONSE_TYPE_JSON) || responseType.equals(HttpUtils.RESPONSE_TYPE_XML))) {
431434
responseType = HttpUtils.RESPONSE_TYPE_XML;
432435
}
433-
434436
try {
437+
//verify that parameter is legit for passing via admin port
438+
String[] command = (String[]) parameterMap.get("command");
439+
if (command != null) {
440+
Class<?> cmdClass = getCmdClass(command[0]);
441+
if (cmdClass != null) {
442+
List<Field> fields = ReflectUtil.getAllFieldsForClass(cmdClass, BaseCmd.class);
443+
for (Field field : fields) {
444+
Parameter parameterAnnotation = field.getAnnotation(Parameter.class);
445+
if ((parameterAnnotation == null) || !parameterAnnotation.expose()) {
446+
continue;
447+
}
448+
Object paramObj = parameterMap.get(parameterAnnotation.name());
449+
if (paramObj != null) {
450+
if (!parameterAnnotation.acceptedOnAdminPort()) {
451+
throw new ServerApiException(ApiErrorCode.ACCOUNT_ERROR, "Parameter " + parameterAnnotation.name() + " can't be passed through the API integration port");
452+
}
453+
}
454+
}
455+
}
456+
}
435457
// always trust commands from API port, user context will always be UID_SYSTEM/ACCOUNT_ID_SYSTEM
436458
CallContext.register(accountMgr.getSystemUser(), accountMgr.getSystemAccount());
437459
sb.insert(0, "(userId=" + User.UID_SYSTEM + " accountId=" + Account.ACCOUNT_ID_SYSTEM + " sessionId=" + null + ") ");

0 commit comments

Comments
 (0)