Commit 2b1a6a85 authored by chiaming2000's avatar chiaming2000
Browse files

Simulator: enforce batch commands data and permission verification. If

violated, unsolicitated status message is sent, connection is close, and
the batch is aborted.
parent 1def4b97
Loading
Loading
Loading
Loading
+42 −4
Original line number Diff line number Diff line
@@ -30,8 +30,10 @@ import com.seagate.kinetic.proto.Kinetic.Command.Algorithm;
import com.seagate.kinetic.proto.Kinetic.Command.Batch;
import com.seagate.kinetic.proto.Kinetic.Command.KeyValue;
import com.seagate.kinetic.proto.Kinetic.Command.MessageType;
import com.seagate.kinetic.proto.Kinetic.Command.Security.ACL.Permission;
import com.seagate.kinetic.proto.Kinetic.Command.Status.StatusCode;
import com.seagate.kinetic.simulator.persist.BatchOperation;
import com.seagate.kinetic.simulator.persist.KVOp;
import com.seagate.kinetic.simulator.persist.KVValue;
import com.seagate.kinetic.simulator.persist.Store;

@@ -162,8 +164,8 @@ public class BatchOperationHandler {
    }

    public synchronized void handleRequest(RequestContext context)
            throws InvalidBatchException,
            NotAttemptedException, KVStoreException {
            throws InvalidBatchException, NotAttemptedException,
            KVStoreException, InvalidRequestException, KVSecurityException {

        MessageType mtype = context.getMessageType();

@@ -220,6 +222,36 @@ public class BatchOperationHandler {
            close();

            throw nae;
        } catch (InvalidRequestException ire) {

            logger.log(Level.WARNING, ire.getMessage(), ire);

            // set status code and message
            context.getCommandBuilder().getStatusBuilder()
                    .setCode(StatusCode.INVALID_REQUEST);
            context.getCommandBuilder().getStatusBuilder()
                    .setStatusMessage(ire.getMessage());

            this.saveFailedRequestContext(context);

            close();

            throw ire;
        } catch (KVSecurityException kse) {

            logger.log(Level.WARNING, kse.getMessage(), kse);

            // set status code and message
            context.getCommandBuilder().getStatusBuilder()
                    .setCode(StatusCode.NOT_AUTHORIZED);
            context.getCommandBuilder().getStatusBuilder()
                    .setStatusMessage(kse.getMessage());

            this.saveFailedRequestContext(context);

            close();

            throw kse;
        } catch (KVStoreVersionMismatch vmismatch) {

            logger.log(Level.WARNING, vmismatch.getMessage(), vmismatch);
@@ -355,7 +387,10 @@ public class BatchOperationHandler {

    }

    private void batchDelete(KineticMessage km) throws KVStoreException {
    private void batchDelete(KineticMessage km) throws KVStoreException,
            InvalidRequestException, KVSecurityException {

        KVOp.checkWrite(engine.getAclMap(), km, Permission.DELETE);

        // proto request KV
        KeyValue requestKeyValue = km.getCommand().getBody().getKeyValue();
@@ -370,7 +405,10 @@ public class BatchOperationHandler {
        batch.delete(key);
    }

    private void batchPut(KineticMessage km) throws KVStoreException {
    private void batchPut(KineticMessage km) throws KVStoreException,
            InvalidRequestException, KVSecurityException {

        KVOp.checkWrite(engine.getAclMap(), km, Permission.WRITE);

        ByteString key = km.getCommand().getBody().getKeyValue().getKey();

+48 −31
Original line number Diff line number Diff line
@@ -161,24 +161,7 @@ public class KVOp {
                        // persist option
                        persistOption = getPersistOption(requestKeyValue);

                      //check max key length
                       checkMaxKeyLenth (key.size());
                       
                       //check max version size
                       ByteString bs = requestKeyValue.getNewVersion();
                       checkMaxVersionLength (bs);

                        if (isSupportedValueSize(kmreq) == false) {
                            throw new InvalidRequestException (
                                    "value size exceeded max supported size. Supported size: "
                                            + maxValueSize + ", received size="
                                            + kmreq.getValue().length
                                            + " (in bytes)");
                        }

                        Authorizer.checkPermission(aclmap, kmreq.getMessage()
                                .getHmacAuth().getIdentity(), Permission.WRITE,
                                key);
                        checkWrite(aclmap, kmreq, Permission.WRITE);

                        ByteString valueByteString = null;
                        if (kmreq.getValue() != null) {
@@ -221,16 +204,7 @@ public class KVOp {
                        // persist option
                        persistOption = getPersistOption(requestKeyValue);

                        //check max key length
                        checkMaxKeyLenth (key.size());
                        
                        //check max version size
                        ByteString bs = requestKeyValue.getDbVersion();
                        checkMaxVersionLength (bs);
                        
                        Authorizer.checkPermission(aclmap, kmreq.getMessage()
                                .getHmacAuth().getIdentity(), Permission.DELETE,
                                key);
                        checkWrite(aclmap, kmreq, Permission.DELETE);

                        if (requestKeyValue.getForce()) {
                            store.deleteForced(key, persistOption);
@@ -374,7 +348,7 @@ public class KVOp {
     *
     * @return true if less than max allowed size. Otherwise, returned false.
     */
    public static boolean isSupportedValueSize(KineticMessage km) {
    private static boolean isSupportedValueSize(KineticMessage km) {
        boolean supported = false;

        byte[] value = km.getValue();
@@ -432,13 +406,15 @@ public class KVOp {
        return option;
    }
    
    private static void checkMaxKeyLenth (int len) throws InvalidRequestException {
    private static void checkMaxKeyLenth(int len)
            throws InvalidRequestException {
        if (len > maxKeySize) {
            throw new InvalidRequestException ("key length exceeds max size, size=" + maxKeySize + ", request size=" + len);
        }
    }
    
    private static void checkMaxVersionLength (ByteString bs) throws InvalidRequestException {
    private static void checkMaxVersionLength(ByteString bs)
            throws InvalidRequestException {
   
        int len = 0;
        if (bs != null) {
@@ -450,4 +426,45 @@ public class KVOp {
        }
    }

    /**
     * Check if request has write privilege, key length, version length.
     * 
     * @param aclmap
     *            acl map for this instance
     * @param kmreq
     *            request message
     * @param role
     *            role to access
     * @throws InvalidRequestException
     * @throws KVSecurityException
     */
    public static void checkWrite(Map<Long, ACL> aclmap, KineticMessage kmreq,
            Permission role)
            throws InvalidRequestException,
            KVSecurityException {

        KeyValue requestKeyValue = kmreq.getCommand().getBody().getKeyValue();

        ByteString key = requestKeyValue.getKey();

        // check max key length
        checkMaxKeyLenth(key.size());

        // check max version size
        ByteString bs = requestKeyValue.getNewVersion();

        checkMaxVersionLength(bs);

        if (isSupportedValueSize(kmreq) == false) {
            throw new InvalidRequestException(
                    "value size exceeded max supported size. Supported size: "
                            + maxValueSize + ", received size="
                            + kmreq.getValue().length + " (in bytes)");
        }

        // check permission
        Authorizer.checkPermission(aclmap, kmreq.getMessage().getHmacAuth()
                .getIdentity(), role, key);
    }

}