Search in sources :

Example 1 with ZWaveSecurityCommandClass

use of org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveSecurityCommandClass in project openhab1-addons by openhab.

the class ZWaveNode method setSecuredClasses.

/**
     * Invoked by {@link ZWaveSecurityCommandClass} when a
     * {@link ZWaveSecurityCommandClass#SECURITY_SUPPORTED_REPORT} is received.
     *
     * @param data the class id for each class which must be encrypted in transmission
     */
public void setSecuredClasses(byte[] data) {
    logger.info("NODE {}:  Setting secured command classes for node with {}", this.getNodeId(), SerialMessage.bb2hex(data));
    boolean afterMark = false;
    // reset the existing list
    securedCommandClasses.clear();
    for (final byte aByte : data) {
        // TODO: DB support extended commandClass format by checking for 0xF1 - 0xFF
        if (ZWaveSecurityCommandClass.bytesAreEqual(aByte, ZWaveSecurityCommandClass.COMMAND_CLASS_MARK)) {
            /**
                 * Marks the end of the list of supported command classes. The remaining classes are those
                 * that can be controlled by the device. These classes are created without values.
                 * Messages received cause notification events instead.
                 */
            afterMark = true;
            continue;
        }
        // Check if this is a commandClass that is already registered with the node
        final CommandClass commandClass = CommandClass.getCommandClass((aByte & 0xFF));
        if (commandClass == null) {
            // Not supported by OpenHab
            logger.error("NODE {}:  setSecuredClasses requested secure " + "class NOT supported by OpenHab: {}   afterMark={}", this.getNodeId(), commandClass, afterMark);
        } else {
            // can't be set that way since it's the one doing the encryption work So ignore that.
            if (commandClass == CommandClass.SECURITY) {
                continue;
            } else if (afterMark) {
                // Nothing to do, we don't track devices that control other devices
                logger.info("NODE {}:  is after mark for commandClass {}", this.getNodeId(), commandClass);
                break;
            } else {
                if (!this.supportsCommandClass(commandClass)) {
                    logger.info("NODE {}:  Adding secured command class to supported that wasn't in original list {}", this.getNodeId(), commandClass.getLabel());
                    final ZWaveCommandClass classInstance = ZWaveCommandClass.getInstance((aByte & 0xFF), this, controller);
                    if (classInstance != null) {
                        addCommandClass(classInstance);
                    }
                }
                securedCommandClasses.add(commandClass);
                logger.info("NODE {}:  (Secured) {}", this.getNodeId(), commandClass.getLabel());
            }
        }
    }
    if (logger.isInfoEnabled()) {
        // show which classes are still insecure after the update
        final StringBuilder buf = new StringBuilder("NODE " + this.getNodeId() + ": After update, INSECURE command classes are: ");
        for (final ZWaveCommandClass zwCommandClass : this.getCommandClasses()) {
            if (!securedCommandClasses.contains(zwCommandClass.getCommandClass())) {
                buf.append(zwCommandClass.getCommandClass() + ", ");
            }
        }
        logger.info(buf.toString().substring(0, buf.toString().length() - 1));
    }
}
Also used : ZWaveCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveCommandClass) ZWaveMultiInstanceCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveMultiInstanceCommandClass) ZWaveAssociationCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveAssociationCommandClass) ZWaveWakeUpCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveWakeUpCommandClass) CommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveCommandClass.CommandClass) ZWaveSecurityCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveSecurityCommandClass) ZWaveVersionCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveVersionCommandClass) ZWaveNodeNamingCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveNodeNamingCommandClass) ZWaveCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveCommandClass)

Example 2 with ZWaveSecurityCommandClass

use of org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveSecurityCommandClass in project openhab1-addons by openhab.

the class ApplicationCommandMessageClass method handleRequest.

@Override
public boolean handleRequest(ZWaveController zController, SerialMessage lastSentMessage, SerialMessage incomingMessage) {
    logger.trace("Handle Message Application Command Request");
    int nodeId = incomingMessage.getMessagePayloadByte(1);
    ZWaveNode node = zController.getNode(nodeId);
    if (node == null) {
        logger.warn("NODE {}: Not initialized yet, ignoring message.", nodeId);
        return false;
    }
    logger.debug("NODE {}: Application Command Request ({}:{})", nodeId, node.getNodeState().toString(), node.getNodeInitializationStage().toString());
    // If the node is DEAD, but we've just received a message from it, then it's not dead!
    if (node.isDead()) {
        node.setNodeState(ZWaveNodeState.ALIVE);
    }
    node.resetResendCount();
    node.incrementReceiveCount();
    int commandClassCode = incomingMessage.getMessagePayloadByte(3);
    ZWaveCommandClass zwaveCommandClass = resolveZWaveCommandClass(node, commandClassCode, zController);
    if (zwaveCommandClass == null) {
        // Error message was logged in resolveZWaveCommandClass
        return false;
    }
    final int commandByte = incomingMessage.getMessagePayloadByte(4);
    if (zwaveCommandClass instanceof ZWaveSecurityCommandClass && (ZWaveSecurityCommandClass.bytesAreEqual(ZWaveSecurityCommandClass.SECURITY_MESSAGE_ENCAP, commandByte) || ZWaveSecurityCommandClass.bytesAreEqual(ZWaveSecurityCommandClass.SECURITY_MESSAGE_ENCAP_NONCE_GET, commandByte))) {
        boolean isEncapNonceGet = ZWaveSecurityCommandClass.bytesAreEqual(ZWaveSecurityCommandClass.SECURITY_MESSAGE_ENCAP_NONCE_GET, commandByte);
        // Intercept security encapsulated messages here and decrypt them.
        ZWaveSecurityCommandClass zwaveSecurityCommandClass = (ZWaveSecurityCommandClass) zwaveCommandClass;
        logger.trace("NODE {}: Preparing to decrypt security encapsulated message, messagePayload={}", nodeId, SerialMessage.bb2hex(incomingMessage.getMessagePayload()));
        int toDecryptLength = incomingMessage.getMessageBuffer().length - 9;
        byte[] toDecrypt = new byte[toDecryptLength];
        System.arraycopy(incomingMessage.getMessageBuffer(), 8, toDecrypt, 0, toDecryptLength);
        byte[] decryptedBytes = zwaveSecurityCommandClass.decryptMessage(toDecrypt, 0);
        if (decryptedBytes == null) {
            logger.error("NODE {}: Failed to decrypt message out of {} .", nodeId, incomingMessage);
        } else {
            // call handleApplicationCommandRequest with the decrypted message. Note that we do NOT set
            // incomingMessage as that needs to be processed below with the original security encapsulated message
            final SerialMessage decryptedMessage = new SerialMessage(incomingMessage.getMessageClass(), incomingMessage.getMessageType(), incomingMessage.getExpectedReply(), incomingMessage.getPriority());
            decryptedMessage.setMessagePayload(decryptedBytes);
            // Get the new command class with the decrypted contents
            zwaveCommandClass = resolveZWaveCommandClass(node, decryptedBytes[1], zController);
            // Use a flag bc we need to handle isEncapNonceGet either way
            boolean failed = false;
            if (zwaveCommandClass == null) {
                // Error message was logged in resolveZWaveCommandClass
                failed = true;
            } else {
                // Note that we do not call node.doesMessageRequireSecurityEncapsulation since it was encapsulated.
                // Messages that are not required to be are allowed to be, just not the other way around
                logger.debug("NODE {}: After decrypt, found Command Class {}, passing to handleApplicationCommandRequest", nodeId, zwaveCommandClass.getCommandClass().getLabel());
                zwaveCommandClass.handleApplicationCommandRequest(decryptedMessage, 2, 0);
            }
            if (isEncapNonceGet) {
                // the device also needs another nonce; send it regardless of the success/failure of decryption
                zwaveSecurityCommandClass.sendNonceReport();
            }
            if (failed) {
                return false;
            }
        }
    } else {
        // Message does not require decryption
        if (node.doesMessageRequireSecurityEncapsulation(incomingMessage)) {
            // Should have been security encapsulation but wasn't!
            logger.error("NODE {}: Command Class {} {} was required to be security encapsulation but it wasn't!  Dropping message.", nodeId, zwaveCommandClass.getCommandClass().getKey(), zwaveCommandClass.getCommandClass().getLabel());
        // do not call zwaveCommandClass.handleApplicationCommandRequest();
        } else {
            logger.trace("NODE {}: Found Command Class {}, passing to handleApplicationCommandRequest", nodeId, zwaveCommandClass.getCommandClass().getLabel());
            zwaveCommandClass.handleApplicationCommandRequest(incomingMessage, 4, 0);
        }
    }
    if (node.getNodeId() == lastSentMessage.getMessageNode()) {
        checkTransactionComplete(lastSentMessage, incomingMessage);
    } else {
        logger.debug("NODE {}: Transaction not completed: node address inconsistent.  lastSent={}, incoming={}", lastSentMessage.getMessageNode(), lastSentMessage.getMessageNode(), incomingMessage.getMessageNode());
    }
    return true;
}
Also used : ZWaveSecurityCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveSecurityCommandClass) ZWaveCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveCommandClass) ZWaveNode(org.openhab.binding.zwave.internal.protocol.ZWaveNode) SerialMessage(org.openhab.binding.zwave.internal.protocol.SerialMessage)

Example 3 with ZWaveSecurityCommandClass

use of org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveSecurityCommandClass in project openhab1-addons by openhab.

the class ZWaveController method enqueue.

/**
     * Enqueues a message for sending on the send queue.
     *
     * @param serialMessage the serial message to enqueue.
     */
public void enqueue(SerialMessage serialMessage) {
    // Sanity check!
    if (serialMessage == null) {
        return;
    }
    // First try and get the node
    // If we're sending to a node, then this obviously isn't to the controller, and we should
    // queue anything to a battery node (ie a node supporting the WAKEUP class)!
    ZWaveNode node = this.getNode(serialMessage.getMessageNode());
    if (node != null) {
        // Does this message need to be security encapsulated?
        if (node.doesMessageRequireSecurityEncapsulation(serialMessage)) {
            ZWaveSecurityCommandClass securityCommandClass = (ZWaveSecurityCommandClass) node.getCommandClass(CommandClass.SECURITY);
            securityCommandClass.queueMessageForEncapsulationAndTransmission(serialMessage);
            // so we discard this one without putting it on the queue
            return;
        }
        // Keep track of the number of packets sent to this device
        node.incrementSendCount();
        // If the device isn't listening, queue the message if it supports the wakeup class
        if (!node.isListening() && !node.isFrequentlyListening()) {
            ZWaveWakeUpCommandClass wakeUpCommandClass = (ZWaveWakeUpCommandClass) node.getCommandClass(CommandClass.WAKE_UP);
            // If it's a battery operated device, check if it's awake or place in wake-up queue.
            if (wakeUpCommandClass != null && !wakeUpCommandClass.processOutgoingWakeupMessage(serialMessage)) {
                return;
            }
        }
    }
    // Add the message to the queue
    this.sendQueue.add(serialMessage);
    if (logger.isTraceEnabled()) {
        logger.debug("Enqueueing message. Queue length = {}, Queue = {}", this.sendQueue.size(), this.sendQueue);
    } else {
        logger.debug("Enqueueing message. Queue length = {}", this.sendQueue.size());
    }
}
Also used : ZWaveSecurityCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveSecurityCommandClass) ZWaveWakeUpCommandClass(org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveWakeUpCommandClass)

Aggregations

ZWaveSecurityCommandClass (org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveSecurityCommandClass)3 ZWaveCommandClass (org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveCommandClass)2 ZWaveWakeUpCommandClass (org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveWakeUpCommandClass)2 SerialMessage (org.openhab.binding.zwave.internal.protocol.SerialMessage)1 ZWaveNode (org.openhab.binding.zwave.internal.protocol.ZWaveNode)1 ZWaveAssociationCommandClass (org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveAssociationCommandClass)1 CommandClass (org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveCommandClass.CommandClass)1 ZWaveMultiInstanceCommandClass (org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveMultiInstanceCommandClass)1 ZWaveNodeNamingCommandClass (org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveNodeNamingCommandClass)1 ZWaveVersionCommandClass (org.openhab.binding.zwave.internal.protocol.commandclass.ZWaveVersionCommandClass)1