Merge release branch 4.13 to master

* 4.13:
  break session only on illegal origin (#3715)
This commit is contained in:
Daan Hoogland 2019-12-24 10:24:09 +01:00
commit 4fa7fadd21
3 changed files with 71 additions and 7 deletions

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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;
}