Skip to content

Commit 4fa7fad

Browse files
committed
Merge release branch 4.13 to master
* 4.13: break session only on illegal origin (#3715)
2 parents 482e7eb + 8844f59 commit 4fa7fad

3 files changed

Lines changed: 71 additions & 7 deletions

File tree

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Licensed to the Apache Software Foundation (ASF) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The ASF licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
package com.cloud.exception;
18+
19+
import com.cloud.user.Account;
20+
import com.cloud.utils.SerialVersionUID;
21+
import com.cloud.utils.exception.CloudRuntimeException;
22+
23+
import java.net.InetAddress;
24+
25+
public class OriginDeniedException extends CloudRuntimeException {
26+
27+
private static final long serialVersionUID = SerialVersionUID.OriginDeniedException;
28+
29+
public OriginDeniedException(String message) {
30+
super(message);
31+
}
32+
33+
public OriginDeniedException(String message, Throwable cause) {
34+
super(message, cause);
35+
}
36+
37+
protected OriginDeniedException() {
38+
super();
39+
}
40+
41+
InetAddress origin;
42+
Account account;
43+
44+
public OriginDeniedException(String message, Account account, InetAddress origin) {
45+
super(message);
46+
this.origin = origin;
47+
this.account = account;
48+
}
49+
50+
public Account getAccount() {
51+
return account;
52+
}
53+
54+
public InetAddress getOrigin() {
55+
return origin;
56+
}
57+
58+
public void addDetails(Account account, InetAddress origin) {
59+
this.account = account;
60+
this.origin = origin;
61+
}
62+
}

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

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import com.cloud.exception.CloudAuthenticationException;
3030
import com.cloud.exception.InsufficientCapacityException;
3131
import com.cloud.exception.InvalidParameterValueException;
32+
import com.cloud.exception.OriginDeniedException;
3233
import com.cloud.exception.PermissionDeniedException;
3334
import com.cloud.exception.RequestLimitException;
3435
import com.cloud.exception.ResourceAllocationException;
@@ -843,11 +844,7 @@ public boolean verifyRequest(final Map<String, Object[]> requestParameters, fina
843844
if (userId != null) {
844845
final User user = ApiDBUtils.findUserById(userId);
845846

846-
if (!commandAvailable(remoteAddress, commandName, user)) {
847-
return false;
848-
}
849-
850-
return true;
847+
return commandAvailable(remoteAddress, commandName, user);
851848
} else {
852849
// check against every available command to see if the command exists or not
853850
if (!s_apiNameCmdClassMap.containsKey(commandName) && !commandName.equals("login") && !commandName.equals("logout")) {
@@ -989,7 +986,11 @@ private boolean commandAvailable(final InetAddress remoteAddress, final String c
989986
throw new ServerApiException(ApiErrorCode.UNSUPPORTED_ACTION_ERROR, ex.getMessage());
990987
} catch (final PermissionDeniedException ex) {
991988
final String errorMessage = "The given command '" + commandName + "' either does not exist, is not available" +
992-
" for user, or not available from ip address '" + remoteAddress + "'.";
989+
" for user.";
990+
throw new ServerApiException(ApiErrorCode.UNAUTHORIZED , errorMessage);
991+
} catch (final OriginDeniedException ex) {
992+
// in this case we can remove the session with extreme prejudice
993+
final String errorMessage = "The user '" + user.getUsername() + "' is not allowed to execute commands from ip address '" + remoteAddress.getHostName() + "'.";
993994
s_logger.debug(errorMessage);
994995
return false;
995996
}
@@ -1163,7 +1164,7 @@ private void checkCommandAvailable(final User user, final String commandName, fi
11631164
s_logger.debug("CIDRs from which account '" + account.toString() + "' is allowed to perform API calls: " + accessAllowedCidrs);
11641165
if (!NetUtils.isIpInCidrList(remoteAddress, accessAllowedCidrs.split(","))) {
11651166
s_logger.warn("Request by account '" + account.toString() + "' was denied since " + remoteAddress + " does not match " + accessAllowedCidrs);
1166-
throw new PermissionDeniedException("Calls for domain '" + account.getAccountName() + "' are not allowed from ip address '" + remoteAddress.getHostAddress());
1167+
throw new OriginDeniedException("Calls from disallowed origin", account, remoteAddress);
11671168
}
11681169
}
11691170

utils/src/main/java/com/cloud/utils/SerialVersionUID.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,5 @@ public interface SerialVersionUID {
6969
public static final long TaskExecutionException = Base | 0x2d;
7070
public static final long SnapshotBackupException = Base | 0x2e;
7171
public static final long UnavailableCommandException = Base | 0x2f;
72+
public static final long OriginDeniedException = Base | 0x30;
7273
}

0 commit comments

Comments
 (0)