/** * Copyright 2013-2015 Seagate Technology LLC. * * This Source Code Form is subject to the terms of the Mozilla * Public License, v. 2.0. If a copy of the MPL was not * distributed with this file, You can obtain one at * https://mozilla.org/MP:/2.0/. * * This program is distributed in the hope that it will be useful, * but is provided AS-IS, WITHOUT ANY WARRANTY; including without * the implied warranty of MERCHANTABILITY, NON-INFRINGEMENT or * FITNESS FOR A PARTICULAR PURPOSE. See the Mozilla Public * License for more details. * * See www.openkinetic.org for more project information */ package com.seagate.kinetic.simulator.lib; import java.security.Key; import java.util.logging.Level; import java.util.logging.Logger; import com.seagate.kinetic.common.lib.Hmac; import com.seagate.kinetic.common.lib.KineticMessage; import com.seagate.kinetic.proto.Kinetic.Command; import com.seagate.kinetic.proto.Kinetic.Command.MessageType; import com.seagate.kinetic.proto.Kinetic.Command.Status; import com.seagate.kinetic.proto.Kinetic.Command.Status.StatusCode; import com.seagate.kinetic.proto.Kinetic.Message.AuthType; import com.seagate.kinetic.simulator.internal.SimulatorEngine; class HeaderException extends Exception { private static final long serialVersionUID = 5201751340412081922L; Status.StatusCode status; HeaderException(Status.StatusCode status, String s) { super(s); this.status = status; } } public class HeaderOp { private final static Logger LOG = MyLogger.get(); /** * Hmac check. * * @param m * @param key * @return * @throws HeaderException */ private static boolean checkHmac(KineticMessage km, Key key) throws HeaderException { try { if (!Hmac.check(km, key)) { throw new HeaderException(StatusCode.HMAC_FAILURE, "HMAC did not compare"); } else { LOG.fine("validated hmac successfully."); } } catch (HeaderException he) { throw he; } catch (Exception e) { throw new HeaderException(StatusCode.INTERNAL_ERROR, "Internal error: " + e.getMessage()); } return true; } private HeaderOp() { } public static void checkHeader(KineticMessage km, KineticMessage kmresp, Key key, SimulatorEngine engine) throws HeaderException { LOG.fine("Header processing"); Command.Builder respCommandBuilder = (Command.Builder) kmresp.getCommand(); try { if (!km.getCommand().hasHeader()) { throw new HeaderException(StatusCode.HEADER_REQUIRED, "no header"); } if (km.getIsInvalidRequest()) { throw new HeaderException(Status.StatusCode.INVALID_REQUEST, km.getErrorMessage()); } Command.Header in = km.getCommand().getHeader(); // set ack sequence respCommandBuilder.getHeaderBuilder() .setAckSequence(in.getSequence()); if (km.getMessage().getAuthType() == AuthType.PINAUTH) { // sanity check only if (in.getMessageType() != MessageType.PINOP) { throw new HeaderException( Status.StatusCode.INVALID_REQUEST, "Invalid message type for pin operation."); } } else { // check hmac checkHmac(km, key); if (in.getClusterVersion() != engine.getClusterVersion()) { // set cluster version in response message respCommandBuilder.getHeaderBuilder().setClusterVersion( engine.getClusterVersion()); throw new HeaderException( Status.StatusCode.VERSION_FAILURE, "CLUSTER_VERSION_FAILURE: Simulator cluster version is " + engine.getClusterVersion() + "; Received request cluster version is " + in.getClusterVersion()); } } // set status code respCommandBuilder.getStatusBuilder() .setCode(Status.StatusCode.SUCCESS); LOG.fine("Header processed successfully. status code=" + respCommandBuilder.getStatus().getCode()); } catch (HeaderException he) { LOG.fine("Header Processing Failed: " + he.getMessage()); respCommandBuilder.getStatusBuilder().setCode(he.status); respCommandBuilder.getStatusBuilder() .setStatusMessage(he.getMessage()); throw he; } catch (Exception ex) { LOG.log(Level.WARNING, ex.getMessage(), ex); respCommandBuilder.getStatusBuilder() .setCode(Status.StatusCode.INTERNAL_ERROR); respCommandBuilder.getStatusBuilder() .setStatusMessage(ex.getMessage()); throw new HeaderException(StatusCode.INTERNAL_ERROR, ex.getMessage()); } finally { try { // set connection Id in the response message long cid = km.getCommand().getHeader().getConnectionID(); respCommandBuilder.getHeaderBuilder().setConnectionID(cid); // set response message type int number = km.getCommand().getHeader().getMessageType() .getNumber() - 1; respCommandBuilder.getHeaderBuilder().setMessageType( MessageType.valueOf(number)); } catch (Exception e) { LOG.warning(e.getMessage()); } } } }