diff --git a/.gitignore b/.gitignore index f3bba532e27..f0aee896b52 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,5 @@ dist *~ *.bak cloud-*.tar.bz2 - +*.pyc +build.number diff --git a/client/bindir/cloud-update-xenserver-licenses.in b/client/bindir/cloud-update-xenserver-licenses.in index 6249f7805fe..94b8e3e8ceb 100755 --- a/client/bindir/cloud-update-xenserver-licenses.in +++ b/client/bindir/cloud-update-xenserver-licenses.in @@ -125,7 +125,7 @@ except IndexError: e("The first argument must be the license file to use") if options.all: if len(args) != 0: e("IP addresses cannot be specified if -a is specified") - config = cloud_utils.read_properties(cfg) + config = read_properties(cfg) creds = getknownhosts(config["db.cloud.host"],config["db.cloud.username"],config["db.cloud.password"]) hosts = creds.keys() else: diff --git a/core/src/com/cloud/dc/dao/DataCenterLinkLocalIpAddressDaoImpl.java b/core/src/com/cloud/dc/dao/DataCenterLinkLocalIpAddressDaoImpl.java index 17414e28d58..484d84005b0 100644 --- a/core/src/com/cloud/dc/dao/DataCenterLinkLocalIpAddressDaoImpl.java +++ b/core/src/com/cloud/dc/dao/DataCenterLinkLocalIpAddressDaoImpl.java @@ -52,6 +52,7 @@ public class DataCenterLinkLocalIpAddressDaoImpl extends GenericDaoBase clusters = _clusterDao.listByPodId(podId); - if (clusters.size() > 1) { - throw new DiscoveryException("There are more than one cluster in the pod and we don't know which to add to."); - } else if (clusters.size() == 1) { - clusterId = clusters.get(0).getId(); - cluster = Long.toString(clusterId); - } else { - Map pools = Pool.getAllRecords(conn); - cluster = pools.values().iterator().next().uuid; - } - } } Map hosts = Host.getAllRecords(conn); @@ -300,7 +286,7 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L if ( resources.size() == 0 ) { return false; } - if (clusterId == null && !_formPoolsInPod) { + if (clusterId == null ) { if (resources.size() > 1) { s_logger.warn("There's no cluster specified but we found a pool of xenservers " + resources.size()); throw new DiscoveryException("There's no cluster specified but we found a pool of xenservers " + resources.size()); @@ -437,9 +423,6 @@ public class XcpServerDiscoverer extends DiscovererBase implements Discoverer, L value = _params.get("xen.check.hvm"); _checkHvm = value == null ? true : Boolean.parseBoolean(value); - - value = _params.get(Config.CreatePoolsInPod.key()); - _formPoolsInPod = Boolean.parseBoolean(value); _connPool = XenServerConnectionPool.getInstance(); diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java old mode 100755 new mode 100644 index ab0a44160d7..2e7e287befe --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -221,6 +221,9 @@ public class NetworkManagerImpl implements NetworkManager, VirtualMachineManager final long accountId = account.getId(); + // use a dedicated account object for locking test, so that when we get SQL exception + // we won't be misled to release an actually un-owned lock + AccountVO lockedAccount = null; Transaction txn = Transaction.currentTxn(); try { final EventVO event = new EventVO(); @@ -230,8 +233,8 @@ public class NetworkManagerImpl implements NetworkManager, VirtualMachineManager txn.start(); - account = _accountDao.acquire(accountId); - if (account == null) { + lockedAccount = _accountDao.acquire(accountId); + if (lockedAccount == null) { s_logger.warn("Unable to lock account " + accountId); return null; } @@ -339,7 +342,7 @@ public class NetworkManagerImpl implements NetworkManager, VirtualMachineManager txn.commit(); return null; } finally { - if (account != null) { + if (lockedAccount != null) { if(s_logger.isDebugEnabled()) s_logger.debug("Releasing lock account " + accountId); @@ -767,6 +770,9 @@ public class NetworkManagerImpl implements NetworkManager, VirtualMachineManager if(s_logger.isDebugEnabled()) s_logger.debug("Lock on router " + routerId + " is acquired"); + boolean started = false; + String vnet = null; + boolean vnetAllocated = false; try { final State state = router.getState(); if (state == State.Running) { @@ -813,10 +819,7 @@ public class NetworkManagerImpl implements NetworkManager, VirtualMachineManager throw new ConcurrentOperationException("Someone else is starting the router: " + router.toString()); } - String vnet = null; - boolean vnetAllocated = false; final boolean mirroredVols = router.isMirroredVols(); - boolean started = false; try { event = new EventVO(); event.setUserId(1L); @@ -829,6 +832,7 @@ public class NetworkManagerImpl implements NetworkManager, VirtualMachineManager for (final UserVmVO vm : vms) { if (vm.getVnet() != null) { vnet = vm.getVnet(); + break; } } } @@ -841,7 +845,9 @@ public class NetworkManagerImpl implements NetworkManager, VirtualMachineManager vnet = _dcDao.allocateVnet(router.getDataCenterId(), router.getAccountId()); } vnetAllocated = true; - routerMacAddress = getRouterMacForVnet(dc, vnet); + if(vnet != null){ + routerMacAddress = getRouterMacForVnet(dc, vnet); + } } else if (router.getRole() == Role.DHCP_USERDATA) { if (!Vlan.UNTAGGED.equals(router.getVlanId())) { vnet = router.getVlanId().trim(); @@ -964,28 +970,6 @@ public class NetworkManagerImpl implements NetworkManager, VirtualMachineManager return _routerDao.findById(routerId); } catch (final Throwable th) { - Transaction txn = Transaction.currentTxn(); - if (!started) { - txn.start(); - if (vnetAllocated == true && vnet != null) { - _dcDao.releaseVnet(vnet, router.getDataCenterId(), router.getAccountId()); - } - - router.setVnet(null); - String privateIpAddress = router.getPrivateIpAddress(); - - router.setPrivateIpAddress(null); - - if (privateIpAddress != null) { - _dcDao.releasePrivateIpAddress(privateIpAddress, router.getDataCenterId(), router.getId()); - } - - - if (_routerDao.updateIf(router, Event.OperationFailed, null)) { - txn.commit(); - } - } - if (th instanceof ExecutionException) { s_logger.error("Error while starting router due to " + th.getMessage()); } else if (th instanceof ConcurrentOperationException) { @@ -998,8 +982,30 @@ public class NetworkManagerImpl implements NetworkManager, VirtualMachineManager return null; } } finally { + + if (!started){ + Transaction txn = Transaction.currentTxn(); + txn.start(); + if (vnetAllocated == true && vnet != null) { + _dcDao.releaseVnet(vnet, router.getDataCenterId(), router.getAccountId()); + } + + router.setVnet(null); + String privateIpAddress = router.getPrivateIpAddress(); + + router.setPrivateIpAddress(null); + + if (privateIpAddress != null) { + _dcDao.releasePrivateIpAddress(privateIpAddress, router.getDataCenterId(), router.getId()); + } + + + if (_routerDao.updateIf(router, Event.OperationFailed, null)) { + txn.commit(); + } + } + if (router != null) { - if(s_logger.isDebugEnabled()) s_logger.debug("Releasing lock on router " + routerId); _routerDao.release(routerId); diff --git a/server/src/com/cloud/servlet/ConsoleProxyServlet.java b/server/src/com/cloud/servlet/ConsoleProxyServlet.java index 1901f43cad3..0ed772a960e 100644 --- a/server/src/com/cloud/servlet/ConsoleProxyServlet.java +++ b/server/src/com/cloud/servlet/ConsoleProxyServlet.java @@ -16,56 +16,81 @@ * */ -package com.cloud.servlet; - -import java.io.IOException; - -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +package com.cloud.servlet; + +import java.io.IOException; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; - -import org.apache.log4j.Logger; - + +import org.apache.log4j.Logger; + +import com.cloud.api.BaseCmd; import com.cloud.host.HostVO; import com.cloud.server.ManagementServer; import com.cloud.user.Account; import com.cloud.user.User; +import com.cloud.utils.Pair; import com.cloud.utils.component.ComponentLocator; +import com.cloud.utils.db.Transaction; +import com.cloud.utils.encoding.Base64; import com.cloud.vm.UserVmVO; import com.cloud.vm.VMInstanceVO; - -/** - * Thumbnail access : /console?cmd=thumbnail&vm=xxx&w=xxx&h=xxx - * Console access : /conosole?cmd=access&vm=xxx - * Authentication : /console?cmd=auth&vm=xxx&sid=xxx - */ -public class ConsoleProxyServlet extends HttpServlet { - private static final long serialVersionUID = -5515382620323808168L; - public static final Logger s_logger = Logger.getLogger(ConsoleProxyServlet.class.getName()); - private static final int DEFAULT_THUMBNAIL_WIDTH = 144; - private static final int DEFAULT_THUMBNAIL_HEIGHT = 110; - - private final ManagementServer _ms = (ManagementServer)ComponentLocator.getComponent(ManagementServer.Name); - - @Override - protected void doPost(HttpServletRequest req, HttpServletResponse resp) { - doGet(req, resp); - } - - @Override - protected void doGet(HttpServletRequest req, HttpServletResponse resp) { + +/** + * Thumbnail access : /console?cmd=thumbnail&vm=xxx&w=xxx&h=xxx + * Console access : /conosole?cmd=access&vm=xxx + * Authentication : /console?cmd=auth&vm=xxx&sid=xxx + */ +public class ConsoleProxyServlet extends HttpServlet { + private static final long serialVersionUID = -5515382620323808168L; + public static final Logger s_logger = Logger.getLogger(ConsoleProxyServlet.class.getName()); + private static final int DEFAULT_THUMBNAIL_WIDTH = 144; + private static final int DEFAULT_THUMBNAIL_HEIGHT = 110; + + private final ManagementServer _ms = (ManagementServer)ComponentLocator.getComponent(ManagementServer.Name); + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) { + doGet(req, resp); + } + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) { try { + String userId = null; + String account = null; + Account accountObj = null; + + Map params = new HashMap(); + params.putAll(req.getParameterMap()); + HttpSession session = req.getSession(false); if(session == null) { - s_logger.info("Invalid web session, reject console/thumbnail access"); - sendResponse(resp, "Access denied. You haven't logged in or your web session has timed out"); - return; + if(verifyRequest(params)) { + userId = (String)params.get(BaseCmd.Properties.USER_ID.getName())[0]; + account = (String)params.get(BaseCmd.Properties.ACCOUNT.getName())[0]; + accountObj = (Account)params.get(BaseCmd.Properties.ACCOUNT_OBJ.getName())[0]; + } else { + s_logger.info("Invalid web session or API key in request, reject console/thumbnail access"); + sendResponse(resp, "Access denied. Invalid web session or API key in request"); + return; + } + } else { + userId = (String)session.getAttribute(BaseCmd.Properties.USER_ID.getName()); + account = (String)session.getAttribute(BaseCmd.Properties.ACCOUNT.getName()); + accountObj = (Account)session.getAttribute(BaseCmd.Properties.ACCOUNT_OBJ.getName()); } - - String userId = (String)session.getAttribute("userId"); - String account = (String)session.getAttribute("account"); - Account accountObj = (Account)session.getAttribute("accountobj"); // Do a sanity check here to make sure the user hasn't already been deleted if ((userId == null) || (account == null) || (accountObj == null) || !verifyUser(Long.valueOf(userId))) { @@ -73,202 +98,199 @@ public class ConsoleProxyServlet extends HttpServlet { sendResponse(resp, "Access denied. Invalid or inconsistent account is found"); return; } - - String cmd = req.getParameter("cmd"); - if(cmd == null || !isValidCmd(cmd)) { - s_logger.info("invalid console servlet command: " + cmd); - sendResponse(resp, ""); - return; - } - - String vmIdString = req.getParameter("vm"); - long vmId = 0; - try { - vmId = Long.parseLong(vmIdString); - } catch(NumberFormatException e) { - s_logger.info("invalid console servlet command parameter: " + vmIdString); - sendResponse(resp, ""); - return; - } - - if(!checkSessionPermision(req, vmId)) { - sendResponse(resp, "Permission denied"); - return; - } - - if(cmd.equalsIgnoreCase("thumbnail")) - handleThumbnailRequest(req, resp, vmId); - else if(cmd.equalsIgnoreCase("access")) - handleAccessRequest(req, resp, vmId); - else - handleAuthRequest(req, resp, vmId); - - } catch (Throwable e) { - s_logger.error("Unexepected exception in ConsoleProxyServlet", e); - sendResponse(resp, ""); - } - } - - private void handleThumbnailRequest(HttpServletRequest req, HttpServletResponse resp, long vmId) { - VMInstanceVO vm = _ms.findVMInstanceById(vmId); - if(vm == null) { - s_logger.warn("VM " + vmId + " does not exist, sending blank response for thumbnail request"); - sendResponse(resp, ""); - return; - } - - if(vm.getHostId() == null) { - s_logger.warn("VM " + vmId + " lost host info, sending blank response for thumbnail request"); - sendResponse(resp, ""); - return; - } - - HostVO host = _ms.getHostBy(vm.getHostId()); - if(host == null) { - s_logger.warn("VM " + vmId + "'s host does not exist, sending blank response for thumbnail request"); - sendResponse(resp, ""); - return; - } - - String rootUrl = _ms.getConsoleAccessUrlRoot(vmId); - if(rootUrl == null) { - sendResponse(resp, ""); - return; - } - - int w = DEFAULT_THUMBNAIL_WIDTH; - int h = DEFAULT_THUMBNAIL_HEIGHT; - - String value = req.getParameter("w"); - try { - w = Integer.parseInt(value); - } catch(NumberFormatException e) { - } - - value = req.getParameter("h"); - try { - h = Integer.parseInt(value); - } catch(NumberFormatException e) { - } - - try { - resp.sendRedirect(composeThumbnailUrl(rootUrl, vm, host, w, h)); - } catch (IOException e) { - if(s_logger.isInfoEnabled()) - s_logger.info("Client may already close the connection"); - } - } - - private void handleAccessRequest(HttpServletRequest req, HttpServletResponse resp, long vmId) { - VMInstanceVO vm = _ms.findVMInstanceById(vmId); - if(vm == null) { - s_logger.warn("VM " + vmId + " does not exist, sending blank response for console access request"); - sendResponse(resp, ""); - return; - } - - if(vm.getHostId() == null) { - s_logger.warn("VM " + vmId + " lost host info, sending blank response for console access request"); - sendResponse(resp, ""); - return; - } - - HostVO host = _ms.getHostBy(vm.getHostId()); - if(host == null) { - s_logger.warn("VM " + vmId + "'s host does not exist, sending blank response for console access request"); - sendResponse(resp, ""); - return; - } - - String rootUrl = _ms.getConsoleAccessUrlRoot(vmId); - if(rootUrl == null) { - sendResponse(resp, "

Console access will be ready in a few minutes. Please try it again later.

"); - return; - } + + String cmd = req.getParameter("cmd"); + if(cmd == null || !isValidCmd(cmd)) { + s_logger.info("invalid console servlet command: " + cmd); + sendResponse(resp, ""); + return; + } + + String vmIdString = req.getParameter("vm"); + long vmId = 0; + try { + vmId = Long.parseLong(vmIdString); + } catch(NumberFormatException e) { + s_logger.info("invalid console servlet command parameter: " + vmIdString); + sendResponse(resp, ""); + return; + } + + if(!checkSessionPermision(req, vmId, accountObj)) { + sendResponse(resp, "Permission denied"); + return; + } + + if(cmd.equalsIgnoreCase("thumbnail")) + handleThumbnailRequest(req, resp, vmId); + else if(cmd.equalsIgnoreCase("access")) + handleAccessRequest(req, resp, vmId); + else + handleAuthRequest(req, resp, vmId); + + } catch (Throwable e) { + s_logger.error("Unexepected exception in ConsoleProxyServlet", e); + sendResponse(resp, "Server Internal Error"); + } + } + + private void handleThumbnailRequest(HttpServletRequest req, HttpServletResponse resp, long vmId) { + VMInstanceVO vm = _ms.findVMInstanceById(vmId); + if(vm == null) { + s_logger.warn("VM " + vmId + " does not exist, sending blank response for thumbnail request"); + sendResponse(resp, ""); + return; + } + + if(vm.getHostId() == null) { + s_logger.warn("VM " + vmId + " lost host info, sending blank response for thumbnail request"); + sendResponse(resp, ""); + return; + } + + HostVO host = _ms.getHostBy(vm.getHostId()); + if(host == null) { + s_logger.warn("VM " + vmId + "'s host does not exist, sending blank response for thumbnail request"); + sendResponse(resp, ""); + return; + } + + String rootUrl = _ms.getConsoleAccessUrlRoot(vmId); + if(rootUrl == null) { + sendResponse(resp, ""); + return; + } + + int w = DEFAULT_THUMBNAIL_WIDTH; + int h = DEFAULT_THUMBNAIL_HEIGHT; + + String value = req.getParameter("w"); + try { + w = Integer.parseInt(value); + } catch(NumberFormatException e) { + } + + value = req.getParameter("h"); + try { + h = Integer.parseInt(value); + } catch(NumberFormatException e) { + } + + try { + resp.sendRedirect(composeThumbnailUrl(rootUrl, vm, host, w, h)); + } catch (IOException e) { + if(s_logger.isInfoEnabled()) + s_logger.info("Client may already close the connection"); + } + } + + private void handleAccessRequest(HttpServletRequest req, HttpServletResponse resp, long vmId) { + VMInstanceVO vm = _ms.findVMInstanceById(vmId); + if(vm == null) { + s_logger.warn("VM " + vmId + " does not exist, sending blank response for console access request"); + sendResponse(resp, ""); + return; + } + + if(vm.getHostId() == null) { + s_logger.warn("VM " + vmId + " lost host info, sending blank response for console access request"); + sendResponse(resp, ""); + return; + } + + HostVO host = _ms.getHostBy(vm.getHostId()); + if(host == null) { + s_logger.warn("VM " + vmId + "'s host does not exist, sending blank response for console access request"); + sendResponse(resp, ""); + return; + } + + String rootUrl = _ms.getConsoleAccessUrlRoot(vmId); + if(rootUrl == null) { + sendResponse(resp, "

Console access will be ready in a few minutes. Please try it again later.

"); + return; + } String vmName = vm.getName(); if(vmName == null) vmName = vm.getInstanceName(); - - StringBuffer sb = new StringBuffer(); - sb.append("").append(vmName).append(""); - sendResponse(resp, sb.toString()); - } - - private void handleAuthRequest(HttpServletRequest req, HttpServletResponse resp, long vmId) { - - // TODO authentication channel between console proxy VM and management server needs to be secured, - // the data is now being sent through private network, but this is apparently not enough - VMInstanceVO vm = _ms.findVMInstanceById(vmId); - if(vm == null) { - s_logger.warn("VM " + vmId + " does not exist, sending failed response for authentication request from console proxy"); - sendResponse(resp, "failed"); - return; - } - - if(vm.getHostId() == null) { - s_logger.warn("VM " + vmId + " lost host info, failed response for authentication request from console proxy"); - sendResponse(resp, "failed"); - return; - } - - HostVO host = _ms.getHostBy(vm.getHostId()); - if(host == null) { - s_logger.warn("VM " + vmId + "'s host does not exist, sending failed response for authentication request from console proxy"); - sendResponse(resp, "failed"); - return; - } - - String sid = req.getParameter("sid"); - if(sid == null || !sid.equals(vm.getVncPassword())) { - s_logger.warn("sid " + sid + " in url does not match stored sid " + vm.getVncPassword()); - sendResponse(resp, "failed"); - return; - } - - sendResponse(resp, "success"); - } - - private String composeThumbnailUrl(String rootUrl, VMInstanceVO vm, HostVO host, int w, int h) { - StringBuffer sb = new StringBuffer(rootUrl); - sb.append("/getscreen?host=").append(host.getPrivateIpAddress()); - sb.append("&port=").append(_ms.getVncPort(vm)); - sb.append("&sid=").append(vm.getVncPassword()); - sb.append("&w=").append(w).append("&h=").append(h); - sb.append("&tag=").append(vm.getId()); - - if(s_logger.isInfoEnabled()) - s_logger.info("Compose thumbnail url: " + sb.toString()); - return sb.toString(); - } - - private String composeConsoleAccessUrl(String rootUrl, VMInstanceVO vm, HostVO host) { - StringBuffer sb = new StringBuffer(rootUrl); - sb.append("/ajax?host=").append(host.getPrivateIpAddress()); - sb.append("&port=").append(_ms.getVncPort(vm)); - sb.append("&sid=").append(vm.getVncPassword()); - sb.append("&tag=").append(vm.getId()); - - if(s_logger.isInfoEnabled()) - s_logger.info("Compose console url: " + sb.toString()); - return sb.toString(); - } - - private void sendResponse(HttpServletResponse resp, String content) { - try { - resp.getWriter().print(content); - } catch(IOException e) { - if(s_logger.isInfoEnabled()) - s_logger.info("Client may already close the connection"); - } - } - - private boolean checkSessionPermision(HttpServletRequest req, long vmId) { + + StringBuffer sb = new StringBuffer(); + sb.append("").append(vmName).append(""); + sendResponse(resp, sb.toString()); + } + + private void handleAuthRequest(HttpServletRequest req, HttpServletResponse resp, long vmId) { + + // TODO authentication channel between console proxy VM and management server needs to be secured, + // the data is now being sent through private network, but this is apparently not enough + VMInstanceVO vm = _ms.findVMInstanceById(vmId); + if(vm == null) { + s_logger.warn("VM " + vmId + " does not exist, sending failed response for authentication request from console proxy"); + sendResponse(resp, "failed"); + return; + } + + if(vm.getHostId() == null) { + s_logger.warn("VM " + vmId + " lost host info, failed response for authentication request from console proxy"); + sendResponse(resp, "failed"); + return; + } + + HostVO host = _ms.getHostBy(vm.getHostId()); + if(host == null) { + s_logger.warn("VM " + vmId + "'s host does not exist, sending failed response for authentication request from console proxy"); + sendResponse(resp, "failed"); + return; + } + + String sid = req.getParameter("sid"); + if(sid == null || !sid.equals(vm.getVncPassword())) { + s_logger.warn("sid " + sid + " in url does not match stored sid " + vm.getVncPassword()); + sendResponse(resp, "failed"); + return; + } + + sendResponse(resp, "success"); + } + + private String composeThumbnailUrl(String rootUrl, VMInstanceVO vm, HostVO host, int w, int h) { + StringBuffer sb = new StringBuffer(rootUrl); + sb.append("/getscreen?host=").append(host.getPrivateIpAddress()); + sb.append("&port=").append(_ms.getVncPort(vm)); + sb.append("&sid=").append(vm.getVncPassword()); + sb.append("&w=").append(w).append("&h=").append(h); + sb.append("&tag=").append(vm.getId()); + + if(s_logger.isInfoEnabled()) + s_logger.info("Compose thumbnail url: " + sb.toString()); + return sb.toString(); + } + + private String composeConsoleAccessUrl(String rootUrl, VMInstanceVO vm, HostVO host) { + StringBuffer sb = new StringBuffer(rootUrl); + sb.append("/ajax?host=").append(host.getPrivateIpAddress()); + sb.append("&port=").append(_ms.getVncPort(vm)); + sb.append("&sid=").append(vm.getVncPassword()); + sb.append("&tag=").append(vm.getId()); + + if(s_logger.isInfoEnabled()) + s_logger.info("Compose console url: " + sb.toString()); + return sb.toString(); + } + + private void sendResponse(HttpServletResponse resp, String content) { + try { + resp.getWriter().print(content); + } catch(IOException e) { + if(s_logger.isInfoEnabled()) + s_logger.info("Client may already close the connection"); + } + } + + private boolean checkSessionPermision(HttpServletRequest req, long vmId, Account accountObj) { - HttpSession session = req.getSession(false); - Account accountObj = (Account)session.getAttribute("accountobj"); - VMInstanceVO vm = _ms.findVMInstanceById(vmId); UserVmVO userVm; switch(vm.getType()) @@ -295,14 +317,14 @@ public class ConsoleProxyServlet extends HttpServlet { break; } - return true; - } - - private boolean isValidCmd(String cmd) { - if(cmd.equalsIgnoreCase("thumbnail") || cmd.equalsIgnoreCase("access") || cmd.equalsIgnoreCase("auth")) - return true; - - return false; + return true; + } + + private boolean isValidCmd(String cmd) { + if(cmd.equalsIgnoreCase("thumbnail") || cmd.equalsIgnoreCase("access") || cmd.equalsIgnoreCase("auth")) + return true; + + return false; } public boolean verifyUser(Long userId) { @@ -320,4 +342,106 @@ public class ConsoleProxyServlet extends HttpServlet { } return true; } -} + + // copied and modified from ApiServer.java. + // TODO need to replace the whole servlet with a API command + private boolean verifyRequest(Map requestParameters) { + try { + String apiKey = null; + String secretKey = null; + String signature = null; + String unsignedRequest = null; + + // - build a request string with sorted params, make sure it's all lowercase + // - sign the request, verify the signature is the same + List parameterNames = new ArrayList(); + + for (Object paramNameObj : requestParameters.keySet()) { + parameterNames.add((String)paramNameObj); // put the name in a list that we'll sort later + } + + Collections.sort(parameterNames); + + for (String paramName : parameterNames) { + // parameters come as name/value pairs in the form String/String[] + String paramValue = ((String[])requestParameters.get(paramName))[0]; + + if ("signature".equalsIgnoreCase(paramName)) { + signature = paramValue; + } else { + if ("apikey".equalsIgnoreCase(paramName)) { + apiKey = paramValue; + } + + if (unsignedRequest == null) { + unsignedRequest = paramName + "=" + URLEncoder.encode(paramValue, "UTF-8").replaceAll("\\+", "%20"); + } else { + unsignedRequest = unsignedRequest + "&" + paramName + "=" + URLEncoder.encode(paramValue, "UTF-8").replaceAll("\\+", "%20"); + } + } + } + + + // if api/secret key are passed to the parameters + if ((signature == null) || (apiKey == null)) { + if (s_logger.isDebugEnabled()) { + s_logger.info("expired session, missing signature, or missing apiKey -- ignoring request...sig: " + signature + ", apiKey: " + apiKey); + } + return false; // no signature, bad request + } + + Transaction txn = Transaction.open(Transaction.CLOUD_DB); + txn.close(); + User user = null; + // verify there is a user with this api key + Pair userAcctPair = _ms.findUserByApiKey(apiKey); + if (userAcctPair == null) { + s_logger.info("apiKey does not map to a valid user -- ignoring request, apiKey: " + apiKey); + return false; + } + + user = userAcctPair.first(); + Account account = userAcctPair.second(); + + if (!user.getState().equals(Account.ACCOUNT_STATE_ENABLED) || !account.getState().equals(Account.ACCOUNT_STATE_ENABLED)) { + s_logger.info("disabled or locked user accessing the api, userid = " + user.getId() + "; name = " + user.getUsername() + "; state: " + user.getState() + "; accountState: " + account.getState()); + return false; + } + + if (account.getType() == Account.ACCOUNT_TYPE_NORMAL) { + requestParameters.put(BaseCmd.Properties.USER_ID.getName(), new String[] { user.getId().toString() }); + requestParameters.put(BaseCmd.Properties.ACCOUNT.getName(), new String[] { account.getAccountName() }); + requestParameters.put(BaseCmd.Properties.DOMAIN_ID.getName(), new String[] { account.getDomainId().toString() }); + requestParameters.put(BaseCmd.Properties.ACCOUNT_OBJ.getName(), new Object[] { account }); + } else { + requestParameters.put(BaseCmd.Properties.USER_ID.getName(), new String[] { user.getId().toString() }); + requestParameters.put(BaseCmd.Properties.ACCOUNT.getName(), new String[] { account.getAccountName() }); + requestParameters.put(BaseCmd.Properties.ACCOUNT_OBJ.getName(), new Object[] { account }); + } + + // verify secret key exists + secretKey = user.getSecretKey(); + if (secretKey == null) { + s_logger.info("User does not have a secret key associated with the account -- ignoring request, username: " + user.getUsername()); + return false; + } + + unsignedRequest = unsignedRequest.toLowerCase(); + + Mac mac = Mac.getInstance("HmacSHA1"); + SecretKeySpec keySpec = new SecretKeySpec(secretKey.getBytes(), "HmacSHA1"); + mac.init(keySpec); + mac.update(unsignedRequest.getBytes()); + byte[] encryptedBytes = mac.doFinal(); + String computedSignature = Base64.encodeBytes(encryptedBytes); + boolean equalSig = signature.equals(computedSignature); + if (!equalSig) { + s_logger.info("User signature: " + signature + " is not equaled to computed signature: " + computedSignature); + } + return equalSig; + } catch (Exception ex) { + s_logger.error("unable to verifty request signature", ex); + } + return false; + } +} diff --git a/utils/src/com/cloud/utils/net/NetUtils.java b/utils/src/com/cloud/utils/net/NetUtils.java index d0e3428f094..df63bcb505b 100755 --- a/utils/src/com/cloud/utils/net/NetUtils.java +++ b/utils/src/com/cloud/utils/net/NetUtils.java @@ -668,7 +668,15 @@ public class NetUtils { return null; } /*reserve gateway*/ - return getIpRangeFromCidr(getLinkLocalGateway(), 32 - size); + String[] range = getIpRangeFromCidr(getLinkLocalGateway(), 32 - size); + + if (range[0].equalsIgnoreCase(getLinkLocalGateway())) { + /*remove the gateway*/ + long ip = ip2Long(range[0]); + ip += 1; + range[0] = long2Ip(ip); + } + return range; } public static String getLinkLocalIpEnd() {