This is an automated email from the ASF dual-hosted git repository.

nvazquez pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cloudstack.git


The following commit(s) were added to refs/heads/main by this push:
     new c123c3fd2f remove request listener to prevent untimely session 
invalidation (#6393)
c123c3fd2f is described below

commit c123c3fd2fbea38d33aa708882ac8689e9699716
Author: dahn <[email protected]>
AuthorDate: Tue May 24 15:00:06 2022 +0200

    remove request listener to prevent untimely session invalidation (#6393)
    
    * login/-out constants
    
    * no request listener
    
    * store session as value, using id as key
    
    * Apply suggestions from sonarcloud.io code review
    
    three instances of unsafe parameters to logging
    
    * new sonar issues
    
    * sonar issues
---
 .../org/apache/cloudstack/api/ApiConstants.java    |   3 +
 .../apache/cloudstack/api/command/ListIdpsCmd.java |   7 +-
 server/src/main/java/com/cloud/api/ApiServlet.java | 165 +++++++++++++--------
 .../java/com/cloud/api/ApiSessionListener.java     |  46 +++---
 .../api/auth/DefaultLoginAPIAuthenticatorCmd.java  |  54 ++++---
 .../api/auth/DefaultLogoutAPIAuthenticatorCmd.java |   3 +-
 6 files changed, 163 insertions(+), 115 deletions(-)

diff --git a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java 
b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
index 49d035610a..55002f70b1 100644
--- a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
+++ b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
@@ -905,6 +905,9 @@ public class ApiConstants {
 
     public static final String ADMINS_ONLY = "adminsonly";
     public static final String ANNOTATION_FILTER = "annotationfilter";
+    public static final String LOGIN = "login";
+    public static final String LOGOUT = "logout";
+    public static final String LIST_IDPS = "listIdps";
 
     public enum BootType {
         UEFI, BIOS;
diff --git 
a/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/api/command/ListIdpsCmd.java
 
b/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/api/command/ListIdpsCmd.java
index 67a2970006..545b17eeb9 100644
--- 
a/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/api/command/ListIdpsCmd.java
+++ 
b/plugins/user-authenticators/saml2/src/main/java/org/apache/cloudstack/api/command/ListIdpsCmd.java
@@ -19,6 +19,7 @@ package org.apache.cloudstack.api.command;
 import com.cloud.api.response.ApiResponseSerializer;
 import com.cloud.user.Account;
 import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
 import org.apache.cloudstack.api.ApiErrorCode;
 import org.apache.cloudstack.api.ApiServerService;
 import org.apache.cloudstack.api.BaseCmd;
@@ -41,10 +42,10 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
-@APICommand(name = "listIdps", description = "Returns list of discovered SAML 
Identity Providers", responseObject = IdpResponse.class, entityType = {})
+@APICommand(name = ApiConstants.LIST_IDPS, description = "Returns list of 
discovered SAML Identity Providers", responseObject = IdpResponse.class, 
entityType = {})
 public class ListIdpsCmd extends BaseCmd implements APIAuthenticator {
     public static final Logger s_logger = 
Logger.getLogger(ListIdpsCmd.class.getName());
-    private static final String s_name = "listidpsresponse";
+    public static final String APINAME = ApiConstants.LIST_IDPS;
 
     @Inject
     ApiServerService _apiServer;
@@ -57,7 +58,7 @@ public class ListIdpsCmd extends BaseCmd implements 
APIAuthenticator {
 
     @Override
     public String getCommandName() {
-        return s_name;
+        return APINAME.toLowerCase() + RESPONSE_SUFFIX;
     }
 
     @Override
diff --git a/server/src/main/java/com/cloud/api/ApiServlet.java 
b/server/src/main/java/com/cloud/api/ApiServlet.java
index 09195e0fe2..4bdf31defa 100644
--- a/server/src/main/java/com/cloud/api/ApiServlet.java
+++ b/server/src/main/java/com/cloud/api/ApiServlet.java
@@ -44,6 +44,7 @@ import org.apache.cloudstack.api.auth.APIAuthenticator;
 import org.apache.cloudstack.context.CallContext;
 import org.apache.cloudstack.managed.context.ManagedContext;
 import org.apache.log4j.Logger;
+import org.jetbrains.annotations.Nullable;
 import org.springframework.stereotype.Component;
 import org.springframework.web.context.support.SpringBeanAutowiringSupport;
 
@@ -66,6 +67,8 @@ public class ApiServlet extends HttpServlet {
     private final static List<String> s_clientAddressHeaders = Collections
             .unmodifiableList(Arrays.asList("X-Forwarded-For",
                     "HTTP_CLIENT_IP", "HTTP_X_FORWARDED_FOR", "Remote_Addr"));
+    private static final String REPLACEMENT = "_";
+    private static final String LOG_REPLACEMENTS = "[\n\r\t]";
 
     @Inject
     ApiServerService apiServer;
@@ -98,6 +101,14 @@ public class ApiServlet extends HttpServlet {
         processRequest(req, resp);
     }
 
+    /**
+     * For HTTP GET requests, it seems that 
HttpServletRequest.getParameterMap() actually tries
+     * to unwrap URL encoded content from ISO-9959-1.
+     * After failed in using setCharacterEncoding() to control it, end up with 
following hacking:
+     * for all GET requests, we will override it with our-own way of UTF-8 
based URL decoding.
+     * @param req request containing parameters
+     * @param params output of "our" map of parameters/values
+     */
     void utf8Fixup(final HttpServletRequest req, final Map<String, Object[]> 
params) {
         if (req.getQueryString() == null) {
             return;
@@ -171,10 +182,6 @@ public class ApiServlet extends HttpServlet {
         checkSingleQueryParameterValue(reqParams);
         params.putAll(reqParams);
 
-        // For HTTP GET requests, it seems that 
HttpServletRequest.getParameterMap() actually tries
-        // to unwrap URL encoded content from ISO-9959-1.
-        // After failed in using setCharacterEncoding() to control it, end up 
with following hacking:
-        // for all GET requests, we will override it with our-own way of UTF-8 
based URL decoding.
         utf8Fixup(req, params);
 
         // logging the request start and end in management log for easy 
debugging
@@ -186,22 +193,30 @@ public class ApiServlet extends HttpServlet {
         }
 
         try {
-
-            if (HttpUtils.RESPONSE_TYPE_JSON.equalsIgnoreCase(responseType)) {
-                resp.setContentType(ApiServer.JSONcontentType.value());
-            } else if 
(HttpUtils.RESPONSE_TYPE_XML.equalsIgnoreCase(responseType)){
-                resp.setContentType(HttpUtils.XML_CONTENT_TYPE);
-            }
+            resp.setContentType(HttpUtils.XML_CONTENT_TYPE);
 
             HttpSession session = req.getSession(false);
+            if (s_logger.isTraceEnabled()) {
+                s_logger.trace(String.format("session found: %s", session));
+            }
             final Object[] responseTypeParam = 
params.get(ApiConstants.RESPONSE);
             if (responseTypeParam != null) {
                 responseType = (String)responseTypeParam[0];
             }
 
             final Object[] commandObj = params.get(ApiConstants.COMMAND);
-            if (commandObj != null) {
-                final String command = (String) commandObj[0];
+            final String command = commandObj == null ? null : (String) 
commandObj[0];
+            final Object[] userObj = params.get(ApiConstants.USERNAME);
+            String username = userObj == null ? null : (String)userObj[0];
+            if (s_logger.isTraceEnabled()) {
+                String logCommand = saveLogString(command);
+                String logName = saveLogString(username);
+                s_logger.trace(String.format("command %s processing for user 
\"%s\"",
+                        logCommand,
+                        logName));
+            }
+
+            if (command != null) {
 
                 APIAuthenticator apiAuthenticator = 
authManager.getAPIAuthenticator(command);
                 if (apiAuthenticator != null) {
@@ -213,10 +228,7 @@ public class ApiServlet extends HttpServlet {
 
                     if (apiAuthenticator.getAPIType() == 
APIAuthenticationType.LOGIN_API) {
                         if (session != null) {
-                            try {
-                                session.invalidate();
-                            } catch (final IllegalStateException ise) {
-                            }
+                            invalidateHttpSession(session, "invalidating 
session for login call");
                         }
                         session = req.getSession(true);
 
@@ -229,6 +241,10 @@ public class ApiServlet extends HttpServlet {
                     }
 
                     try {
+                        if (s_logger.isTraceEnabled()) {
+                            
s_logger.trace(String.format("apiAuthenticator.authenticate(%s, params[%d], %s, 
%s, %s, %s, %s,%s)",
+                                    saveLogString(command), params.size(), 
session.getId(), remoteAddress.getHostAddress(), saveLogString(responseType), 
"auditTrailSb", "req", "resp"));
+                        }
                         responseString = 
apiAuthenticator.authenticate(command, params, session, remoteAddress, 
responseType, auditTrailSb, req, resp);
                         if (session != null && 
session.getAttribute(ApiConstants.SESSIONKEY) != null) {
                             resp.addHeader("SET-COOKIE", 
String.format("%s=%s;HttpOnly", ApiConstants.SESSIONKEY, 
session.getAttribute(ApiConstants.SESSIONKEY)));
@@ -251,10 +267,7 @@ public class ApiServlet extends HttpServlet {
                             if (userId != null) {
                                 apiServer.logoutUser(userId);
                             }
-                            try {
-                                session.invalidate();
-                            } catch (final IllegalStateException ignored) {
-                            }
+                            invalidateHttpSession(session, "invalidating 
session after logout call");
                         }
                         final Cookie[] cookies = req.getCookies();
                         if (cookies != null) {
@@ -268,8 +281,9 @@ public class ApiServlet extends HttpServlet {
                     HttpUtils.writeHttpResponse(resp, responseString, 
httpResponseCode, responseType, ApiServer.JSONcontentType.value());
                     return;
                 }
+            } else {
+                s_logger.trace("no command available");
             }
-
             auditTrailSb.append(cleanQueryString);
             final boolean isNew = ((session == null) ? true : session.isNew());
 
@@ -278,52 +292,31 @@ public class ApiServlet extends HttpServlet {
             // if a API key exists
             Long userId = null;
 
+            if (isNew && s_logger.isTraceEnabled()) {
+                s_logger.trace(String.format("new session: %s", session));
+            }
             if (!isNew) {
                 userId = (Long)session.getAttribute("userid");
                 final String account = (String) 
session.getAttribute("account");
                 final Object accountObj = session.getAttribute("accountobj");
-                if (!HttpUtils.validateSessionKey(session, params, 
req.getCookies(), ApiConstants.SESSIONKEY)) {
-                    try {
-                        session.invalidate();
-                    } catch (final IllegalStateException ise) {
-                    }
-                    auditTrailSb.append(" " + 
HttpServletResponse.SC_UNAUTHORIZED + " " + "unable to verify user 
credentials");
-                    final String serializedResponse =
-                            
apiServer.getSerializedApiError(HttpServletResponse.SC_UNAUTHORIZED, "unable to 
verify user credentials", params, responseType);
-                    HttpUtils.writeHttpResponse(resp, serializedResponse, 
HttpServletResponse.SC_UNAUTHORIZED, responseType, 
ApiServer.JSONcontentType.value());
-                    return;
-                }
-
-                // Do a sanity check here to make sure the user hasn't already 
been deleted
-                if ((userId != null) && (account != null) && (accountObj != 
null) && apiServer.verifyUser(userId)) {
-                    final String[] command = 
(String[])params.get(ApiConstants.COMMAND);
-                    if (command == null) {
-                        s_logger.info("missing command, ignoring request...");
-                        auditTrailSb.append(" " + 
HttpServletResponse.SC_BAD_REQUEST + " " + "no command specified");
-                        final String serializedResponse = 
apiServer.getSerializedApiError(HttpServletResponse.SC_BAD_REQUEST, "no command 
specified", params, responseType);
-                        HttpUtils.writeHttpResponse(resp, serializedResponse, 
HttpServletResponse.SC_BAD_REQUEST, responseType, 
ApiServer.JSONcontentType.value());
-                        return;
-                    }
-                    final User user = entityMgr.findById(User.class, userId);
-                    CallContext.register(user, (Account)accountObj);
+                if (account != null) {
+                    if (invalidateHttpSesseionIfNeeded(req, resp, 
auditTrailSb, responseType, params, session, account)) return;
                 } else {
-                    // Invalidate the session to ensure we won't allow a 
request across management server
-                    // restarts if the userId was serialized to the stored 
session
-                    try {
-                        session.invalidate();
-                    } catch (final IllegalStateException ise) {
+                    if (s_logger.isDebugEnabled()) {
+                        s_logger.debug("no account, this request will be 
validated through apikey(%s)/signature");
                     }
+                }
 
-                    auditTrailSb.append(" " + 
HttpServletResponse.SC_UNAUTHORIZED + " " + "unable to verify user 
credentials");
-                    final String serializedResponse =
-                            
apiServer.getSerializedApiError(HttpServletResponse.SC_UNAUTHORIZED, "unable to 
verify user credentials", params, responseType);
-                    HttpUtils.writeHttpResponse(resp, serializedResponse, 
HttpServletResponse.SC_UNAUTHORIZED, responseType, 
ApiServer.JSONcontentType.value());
+                if (! requestChecksoutAsSane(resp, auditTrailSb, responseType, 
params, session, command, userId, account, accountObj))
                     return;
-                }
             } else {
                 CallContext.register(accountMgr.getSystemUser(), 
accountMgr.getSystemAccount());
             }
             setProjectContext(params);
+            if (s_logger.isTraceEnabled()) {
+                s_logger.trace(String.format("verifying request for user %s 
from %s with %d parameters",
+                        userId, remoteAddress.getHostAddress(), 
params.size()));
+            }
             if (apiServer.verifyRequest(params, userId, remoteAddress)) {
                 auditTrailSb.insert(0, "(userId=" + 
CallContext.current().getCallingUserId() + " accountId=" + 
CallContext.current().getCallingAccount().getId() +
                         " sessionId=" + (session != null ? session.getId() : 
null) + ")");
@@ -335,10 +328,7 @@ public class ApiServlet extends HttpServlet {
                 HttpUtils.writeHttpResponse(resp, response != null ? response 
: "", HttpServletResponse.SC_OK, responseType, 
ApiServer.JSONcontentType.value());
             } else {
                 if (session != null) {
-                    try {
-                        session.invalidate();
-                    } catch (final IllegalStateException ise) {
-                    }
+                    invalidateHttpSession(session, String.format("request 
verification failed for %s from %s", userId, remoteAddress.getHostAddress()));
                 }
 
                 auditTrailSb.append(" " + HttpServletResponse.SC_UNAUTHORIZED 
+ " " + "unable to verify user credentials and/or request signature");
@@ -366,6 +356,63 @@ public class ApiServlet extends HttpServlet {
         }
     }
 
+    @Nullable
+    private String saveLogString(String stringToLog) {
+        return stringToLog == null ? null : 
stringToLog.replace(LOG_REPLACEMENTS, REPLACEMENT);
+    }
+
+    /**
+     * Do a sanity check here to make sure the user hasn't already been deleted
+     */
+    private boolean requestChecksoutAsSane(HttpServletResponse resp, 
StringBuilder auditTrailSb, String responseType, Map<String, Object[]> params, 
HttpSession session, String command, Long userId, String account, Object 
accountObj) {
+        if ((userId != null) && (account != null) && (accountObj != null) && 
apiServer.verifyUser(userId)) {
+            if (command == null) {
+                s_logger.info("missing command, ignoring request...");
+                auditTrailSb.append(" " + HttpServletResponse.SC_BAD_REQUEST + 
" " + "no command specified");
+                final String serializedResponse = 
apiServer.getSerializedApiError(HttpServletResponse.SC_BAD_REQUEST, "no command 
specified", params, responseType);
+                HttpUtils.writeHttpResponse(resp, serializedResponse, 
HttpServletResponse.SC_BAD_REQUEST, responseType, 
ApiServer.JSONcontentType.value());
+                return true;
+            }
+            final User user = entityMgr.findById(User.class, userId);
+            CallContext.register(user, (Account) accountObj);
+        } else {
+            invalidateHttpSession(session, "Invalidate the session to ensure 
we won't allow a request across management server restarts if the userId was 
serialized to the stored session");
+
+            auditTrailSb.append(" " + HttpServletResponse.SC_UNAUTHORIZED + " 
" + "unable to verify user credentials");
+            final String serializedResponse =
+                    
apiServer.getSerializedApiError(HttpServletResponse.SC_UNAUTHORIZED, "unable to 
verify user credentials", params, responseType);
+            HttpUtils.writeHttpResponse(resp, serializedResponse, 
HttpServletResponse.SC_UNAUTHORIZED, responseType, 
ApiServer.JSONcontentType.value());
+            return false;
+        }
+        return true;
+    }
+
+    private boolean invalidateHttpSesseionIfNeeded(HttpServletRequest req, 
HttpServletResponse resp, StringBuilder auditTrailSb, String responseType, 
Map<String, Object[]> params, HttpSession session, String account) {
+        if (!HttpUtils.validateSessionKey(session, params, req.getCookies(), 
ApiConstants.SESSIONKEY)) {
+            String msg = String.format("invalidating session %s for account 
%s", session.getId(), account);
+            invalidateHttpSession(session, msg);
+            auditTrailSb.append(" " + HttpServletResponse.SC_UNAUTHORIZED + " 
" + "unable to verify user credentials");
+            final String serializedResponse =
+                    
apiServer.getSerializedApiError(HttpServletResponse.SC_UNAUTHORIZED, "unable to 
verify user credentials", params, responseType);
+            HttpUtils.writeHttpResponse(resp, serializedResponse, 
HttpServletResponse.SC_UNAUTHORIZED, responseType, 
ApiServer.JSONcontentType.value());
+            return true;
+        }
+        return false;
+    }
+
+    public static void invalidateHttpSession(HttpSession session, String msg) {
+        try {
+            if (s_logger.isTraceEnabled()) {
+                s_logger.trace(msg);
+            }
+            session.invalidate();
+        } catch (final IllegalStateException ise) {
+            if (s_logger.isTraceEnabled()) {
+                s_logger.trace(String.format("failed to invalidate session 
%s", session.getId()));
+            }
+        }
+    }
+
     private void setProjectContext(Map<String, Object[]> requestParameters) {
         final String[] command = 
(String[])requestParameters.get(ApiConstants.COMMAND);
         if (command == null) {
diff --git a/server/src/main/java/com/cloud/api/ApiSessionListener.java 
b/server/src/main/java/com/cloud/api/ApiSessionListener.java
index 7f99bf596d..56da456b8e 100644
--- a/server/src/main/java/com/cloud/api/ApiSessionListener.java
+++ b/server/src/main/java/com/cloud/api/ApiSessionListener.java
@@ -16,10 +16,7 @@
 // under the License.
 package com.cloud.api;
 
-import javax.servlet.ServletRequestEvent;
-import javax.servlet.ServletRequestListener;
 import javax.servlet.annotation.WebListener;
-import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpSession;
 import javax.servlet.http.HttpSessionEvent;
 import javax.servlet.http.HttpSessionListener;
@@ -29,10 +26,9 @@ import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
 @WebListener
-public class ApiSessionListener implements HttpSessionListener, 
ServletRequestListener {
+public class ApiSessionListener implements HttpSessionListener {
     public static final Logger LOGGER = 
Logger.getLogger(ApiSessionListener.class.getName());
-    private static final String ATTRIBUTE_NAME = "SessionCounter";
-    private static Map<HttpSession, Object> sessions = new 
ConcurrentHashMap<>();
+    private static Map<String, HttpSession> sessions = new 
ConcurrentHashMap<>();
 
     /**
      * @return the internal adminstered session count
@@ -47,37 +43,29 @@ public class ApiSessionListener implements 
HttpSessionListener, ServletRequestLi
     public static long getNumberOfSessions() {
         return sessions.size();
     }
+
     public void sessionCreated(HttpSessionEvent event) {
-        LOGGER.debug("Session created by Id : " + event.getSession().getId() + 
" , session: " + event.getSession().toString() + " , source: " + 
event.getSource().toString() + " , event: " + event.toString());
+        if (LOGGER.isDebugEnabled()) {
+            LOGGER.debug("Session created by Id : " + 
event.getSession().getId() + " , session: " + event.getSession().toString() + " 
, source: " + event.getSource().toString() + " , event: " + event.toString());
+        }
         synchronized (this) {
             HttpSession session = event.getSession();
-            sessions.put(session, event.getSource());
+            sessions.put(session.getId(), event.getSession());
+        }
+        if (LOGGER.isTraceEnabled()) {
+            LOGGER.trace("Sessions count: " + getSessionCount());
         }
-        LOGGER.debug("Sessions count: " + getSessionCount());
     }
+
     public void sessionDestroyed(HttpSessionEvent event) {
-        LOGGER.debug("Session destroyed by Id : " + event.getSession().getId() 
+ " , session: " + event.getSession().toString() + " , source: " + 
event.getSource().toString() + " , event: " + event.toString());
+        if (LOGGER.isDebugEnabled()) {
+            LOGGER.debug("Session destroyed by Id : " + 
event.getSession().getId() + " , session: " + event.getSession().toString() + " 
, source: " + event.getSource().toString() + " , event: " + event.toString());
+        }
         synchronized (this) {
-            sessions.remove(event.getSession());
+            sessions.remove(event.getSession().getId());
         }
-        LOGGER.debug("Sessions count: " + getSessionCount());
-    }
-
-    @Override
-    public void requestDestroyed(ServletRequestEvent event) {
-        LOGGER.debug("request destroyed");
-    }
-
-    @Override
-    public void requestInitialized(ServletRequestEvent event) {
-        LOGGER.debug("request initialized");
-        HttpServletRequest request = (HttpServletRequest) 
event.getServletRequest();
-        HttpSession session = request.getSession();
-        if (session.isNew()) {
-            synchronized (this) {
-                // replace the source object for the address
-                sessions.put(session, request.getRemoteAddr());
-            }
+        if (LOGGER.isTraceEnabled()) {
+            LOGGER.trace("Sessions count: " + getSessionCount());
         }
     }
 }
diff --git 
a/server/src/main/java/com/cloud/api/auth/DefaultLoginAPIAuthenticatorCmd.java 
b/server/src/main/java/com/cloud/api/auth/DefaultLoginAPIAuthenticatorCmd.java
index bb488b0bd2..7fb9d2ef17 100644
--- 
a/server/src/main/java/com/cloud/api/auth/DefaultLoginAPIAuthenticatorCmd.java
+++ 
b/server/src/main/java/com/cloud/api/auth/DefaultLoginAPIAuthenticatorCmd.java
@@ -16,6 +16,7 @@
 // under the License.
 package com.cloud.api.auth;
 
+import com.cloud.api.ApiServlet;
 import com.cloud.domain.Domain;
 import com.cloud.user.User;
 import com.cloud.user.UserAccount;
@@ -34,6 +35,7 @@ import org.apache.cloudstack.api.auth.APIAuthenticator;
 import org.apache.cloudstack.api.auth.PluggableAPIAuthenticator;
 import org.apache.cloudstack.api.response.LoginCmdResponse;
 import org.apache.log4j.Logger;
+import org.jetbrains.annotations.Nullable;
 
 import javax.inject.Inject;
 import javax.servlet.http.HttpServletRequest;
@@ -43,7 +45,7 @@ import java.util.List;
 import java.util.Map;
 import java.net.InetAddress;
 
-@APICommand(name = "login", description = "Logs a user into the CloudStack. A 
successful login attempt will generate a JSESSIONID cookie value that can be 
passed in subsequent Query command calls until the \"logout\" command has been 
issued or the session has expired.", requestHasSensitiveInfo = true, 
responseObject = LoginCmdResponse.class, entityType = {})
+@APICommand(name = ApiConstants.LOGIN, description = "Logs a user into the 
CloudStack. A successful login attempt will generate a JSESSIONID cookie value 
that can be passed in subsequent Query command calls until the \"logout\" 
command has been issued or the session has expired.", requestHasSensitiveInfo = 
true, responseObject = LoginCmdResponse.class, entityType = {})
 public class DefaultLoginAPIAuthenticatorCmd extends BaseCmd implements 
APIAuthenticator {
 
     public static final Logger s_logger = 
Logger.getLogger(DefaultLoginAPIAuthenticatorCmd.class.getName());
@@ -79,7 +81,7 @@ public class DefaultLoginAPIAuthenticatorCmd extends BaseCmd 
implements APIAuthe
         return password;
     }
 
-    public String getDomain() {
+    public String getDomainName() {
         return domain;
     }
 
@@ -141,19 +143,7 @@ public class DefaultLoginAPIAuthenticatorCmd extends 
BaseCmd implements APIAuthe
         }
 
         String domain = null;
-        if (domainName != null) {
-            domain = domainName[0];
-            auditTrailSb.append(" domain=" + domain);
-            if (domain != null) {
-                // ensure domain starts with '/' and ends with '/'
-                if (!domain.endsWith("/")) {
-                    domain += '/';
-                }
-                if (!domain.startsWith("/")) {
-                    domain = "/" + domain;
-                }
-            }
-        }
+        domain = getDomainName(auditTrailSb, domainName, domain);
 
         String serializedResponse = null;
         if (username != null) {
@@ -172,22 +162,40 @@ public class DefaultLoginAPIAuthenticatorCmd extends 
BaseCmd implements APIAuthe
                 return 
ApiResponseSerializer.toSerializedString(_apiServer.loginUser(session, 
username[0], pwd, domainId, domain, remoteAddress, params),
                         responseType);
             } catch (final CloudAuthenticationException ex) {
+                ApiServlet.invalidateHttpSession(session, "fall through to API 
key,");
                 // TODO: fall through to API key, or just fail here w/ auth 
error? (HTTP 401)
-                try {
-                    session.invalidate();
-                } catch (final IllegalStateException ise) {
+                String msg = String.format("%s", ex.getMessage() != null ?
+                        ex.getMessage() :
+                        "failed to authenticate user, check if 
username/password are correct");
+                auditTrailSb.append(" " + ApiErrorCode.ACCOUNT_ERROR + " " + 
msg);
+                serializedResponse = 
_apiServer.getSerializedApiError(ApiErrorCode.ACCOUNT_ERROR.getHttpCode(), msg, 
params, responseType);
+                if (s_logger.isTraceEnabled()) {
+                    s_logger.trace(msg);
                 }
-                auditTrailSb.append(" " + ApiErrorCode.ACCOUNT_ERROR + " " + 
ex.getMessage() != null ? ex.getMessage()
-                        : "failed to authenticate user, check if 
username/password are correct");
-                serializedResponse =
-                        
_apiServer.getSerializedApiError(ApiErrorCode.ACCOUNT_ERROR.getHttpCode(), 
ex.getMessage() != null ? ex.getMessage()
-                                : "failed to authenticate user, check if 
username/password are correct", params, responseType);
             }
         }
         // We should not reach here and if we do we throw an exception
         throw new ServerApiException(ApiErrorCode.ACCOUNT_ERROR, 
serializedResponse);
     }
 
+    @Nullable
+    private String getDomainName(StringBuilder auditTrailSb, String[] 
domainName, String domain) {
+        if (domainName != null) {
+            domain = domainName[0];
+            auditTrailSb.append(" domain=" + domain);
+            if (domain != null) {
+                // ensure domain starts with '/' and ends with '/'
+                if (!domain.endsWith("/")) {
+                    domain += '/';
+                }
+                if (!domain.startsWith("/")) {
+                    domain = "/" + domain;
+                }
+            }
+        }
+        return domain;
+    }
+
     @Override
     public APIAuthenticationType getAPIType() {
         return APIAuthenticationType.LOGIN_API;
diff --git 
a/server/src/main/java/com/cloud/api/auth/DefaultLogoutAPIAuthenticatorCmd.java 
b/server/src/main/java/com/cloud/api/auth/DefaultLogoutAPIAuthenticatorCmd.java
index b4b59ef007..71fd955f3f 100644
--- 
a/server/src/main/java/com/cloud/api/auth/DefaultLogoutAPIAuthenticatorCmd.java
+++ 
b/server/src/main/java/com/cloud/api/auth/DefaultLogoutAPIAuthenticatorCmd.java
@@ -19,6 +19,7 @@ package com.cloud.api.auth;
 import com.cloud.api.response.ApiResponseSerializer;
 import com.cloud.user.Account;
 import org.apache.cloudstack.api.APICommand;
+import org.apache.cloudstack.api.ApiConstants;
 import org.apache.cloudstack.api.ApiErrorCode;
 import org.apache.cloudstack.api.BaseCmd;
 import org.apache.cloudstack.api.ServerApiException;
@@ -35,7 +36,7 @@ import java.util.List;
 import java.util.Map;
 import java.net.InetAddress;
 
-@APICommand(name = "logout", description = "Logs out the user", responseObject 
= LogoutCmdResponse.class, entityType = {})
+@APICommand(name = ApiConstants.LOGOUT, description = "Logs out the user", 
responseObject = LogoutCmdResponse.class, entityType = {})
 public class DefaultLogoutAPIAuthenticatorCmd extends BaseCmd implements 
APIAuthenticator {
 
     public static final Logger s_logger = 
Logger.getLogger(DefaultLogoutAPIAuthenticatorCmd.class.getName());

Reply via email to