diff --git a/api/src/main/java/com/cloud/exception/OriginDeniedException.java b/api/src/main/java/com/cloud/exception/OriginDeniedException.java new file mode 100644 index 00000000000..42a65ede717 --- /dev/null +++ b/api/src/main/java/com/cloud/exception/OriginDeniedException.java @@ -0,0 +1,62 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. +package com.cloud.exception; + +import com.cloud.user.Account; +import com.cloud.utils.SerialVersionUID; +import com.cloud.utils.exception.CloudRuntimeException; + +import java.net.InetAddress; + +public class OriginDeniedException extends CloudRuntimeException { + + private static final long serialVersionUID = SerialVersionUID.OriginDeniedException; + + public OriginDeniedException(String message) { + super(message); + } + + public OriginDeniedException(String message, Throwable cause) { + super(message, cause); + } + + protected OriginDeniedException() { + super(); + } + + InetAddress origin; + Account account; + + public OriginDeniedException(String message, Account account, InetAddress origin) { + super(message); + this.origin = origin; + this.account = account; + } + + public Account getAccount() { + return account; + } + + public InetAddress getOrigin() { + return origin; + } + + public void addDetails(Account account, InetAddress origin) { + this.account = account; + this.origin = origin; + } +} diff --git a/server/src/main/java/com/cloud/api/ApiServer.java b/server/src/main/java/com/cloud/api/ApiServer.java index cc9ec73c94e..7d096b869a8 100644 --- a/server/src/main/java/com/cloud/api/ApiServer.java +++ b/server/src/main/java/com/cloud/api/ApiServer.java @@ -29,6 +29,7 @@ import com.cloud.exception.AccountLimitException; import com.cloud.exception.CloudAuthenticationException; import com.cloud.exception.InsufficientCapacityException; import com.cloud.exception.InvalidParameterValueException; +import com.cloud.exception.OriginDeniedException; import com.cloud.exception.PermissionDeniedException; import com.cloud.exception.RequestLimitException; import com.cloud.exception.ResourceAllocationException; @@ -843,11 +844,7 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer if (userId != null) { final User user = ApiDBUtils.findUserById(userId); - if (!commandAvailable(remoteAddress, commandName, user)) { - return false; - } - - return true; + return commandAvailable(remoteAddress, commandName, user); } else { // check against every available command to see if the command exists or not if (!s_apiNameCmdClassMap.containsKey(commandName) && !commandName.equals("login") && !commandName.equals("logout")) { @@ -989,7 +986,11 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer throw new ServerApiException(ApiErrorCode.UNSUPPORTED_ACTION_ERROR, ex.getMessage()); } catch (final PermissionDeniedException ex) { final String errorMessage = "The given command '" + commandName + "' either does not exist, is not available" + - " for user, or not available from ip address '" + remoteAddress + "'."; + " for user."; + throw new ServerApiException(ApiErrorCode.UNAUTHORIZED , errorMessage); + } catch (final OriginDeniedException ex) { + // in this case we can remove the session with extreme prejudice + final String errorMessage = "The user '" + user.getUsername() + "' is not allowed to execute commands from ip address '" + remoteAddress.getHostName() + "'."; s_logger.debug(errorMessage); return false; } @@ -1163,7 +1164,7 @@ public class ApiServer extends ManagerBase implements HttpRequestHandler, ApiSer s_logger.debug("CIDRs from which account '" + account.toString() + "' is allowed to perform API calls: " + accessAllowedCidrs); if (!NetUtils.isIpInCidrList(remoteAddress, accessAllowedCidrs.split(","))) { s_logger.warn("Request by account '" + account.toString() + "' was denied since " + remoteAddress + " does not match " + accessAllowedCidrs); - throw new PermissionDeniedException("Calls for domain '" + account.getAccountName() + "' are not allowed from ip address '" + remoteAddress.getHostAddress()); + throw new OriginDeniedException("Calls from disallowed origin", account, remoteAddress); } } diff --git a/utils/src/main/java/com/cloud/utils/SerialVersionUID.java b/utils/src/main/java/com/cloud/utils/SerialVersionUID.java index 413ca1a417f..21fdbb4cf11 100644 --- a/utils/src/main/java/com/cloud/utils/SerialVersionUID.java +++ b/utils/src/main/java/com/cloud/utils/SerialVersionUID.java @@ -69,4 +69,5 @@ public interface SerialVersionUID { public static final long TaskExecutionException = Base | 0x2d; public static final long SnapshotBackupException = Base | 0x2e; public static final long UnavailableCommandException = Base | 0x2f; + public static final long OriginDeniedException = Base | 0x30; }