예제 #1
0
SftpNameResponse SftpIncomingPacket::asNameResponse() const
{
    Q_ASSERT(isComplete());
    Q_ASSERT(type() == SSH_FXP_NAME);
    try {
        SftpNameResponse response;
        quint32 offset = RequestIdOffset;
        response.requestId = SshPacketParser::asUint32(m_data, &offset);
        const quint32 count = SshPacketParser::asUint32(m_data, &offset);
        for (quint32 i = 0; i < count; ++i)
            response.files << asFile(offset);
        return response;
    } catch (SshPacketParseException &) {
        throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
            "Invalid SSH_FXP_NAME packet.");
    }
}
SshDebug SshIncomingPacket::extractDebug() const
{
    Q_ASSERT(isComplete());
    Q_ASSERT(type() == SSH_MSG_DEBUG);

    try {
        SshDebug msg;
        quint32 offset = TypeOffset + 1;
        msg.display = SshPacketParser::asBool(m_data, &offset);
        msg.message = SshPacketParser::asUserString(m_data, &offset);
        msg.language = SshPacketParser::asString(m_data, &offset);
        return msg;
    } catch (SshPacketParseException &) {
        throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
            "Invalid SSH_MSG_DEBUG.");
    }
}
예제 #3
0
SftpStatusResponse SftpIncomingPacket::asStatusResponse() const
{
    Q_ASSERT(isComplete());
    Q_ASSERT(type() == SSH_FXP_STATUS);
    try {
        SftpStatusResponse response;
        quint32 offset = RequestIdOffset;
        response.requestId = SshPacketParser::asUint32(m_data, &offset);
        response.status = static_cast<SftpStatusCode>(SshPacketParser::asUint32(m_data, &offset));
        response.errorString = SshPacketParser::asUserString(m_data, &offset);
        response.language = SshPacketParser::asString(m_data, &offset);
        return response;
    } catch (SshPacketParseException &) {
        throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
            "Invalid SSH_FXP_STATUS packet.");
    }
}
예제 #4
0
void AbstractSshChannel::handleOpenFailure(const QString &reason)
{
    switch (m_state) {
    case SessionRequested:
        break; // Ok, continue.
    case CloseRequested:
        return; // Late server reply; we requested a channel close in the meantime.
    default:
        throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
            "Unexpected SSH_MSG_CHANNEL_OPEN_FAILURE packet.");
    }

    m_timeoutTimer.stop();

   qCDebug(sshLog, "Channel open request failed for channel %u", m_localChannel);
   handleOpenFailureInternal(reason);
}
예제 #5
0
SshChannelExtendedData SshIncomingPacket::extractChannelExtendedData() const
{
    Q_ASSERT(isComplete());
    Q_ASSERT(type() == SSH_MSG_CHANNEL_EXTENDED_DATA);

    SshChannelExtendedData data;
    try {
        quint32 offset = TypeOffset + 1;
        data.localChannel = SshPacketParser::asUint32(m_data, &offset);
        data.type = SshPacketParser::asUint32(m_data, &offset);
        data.data = SshPacketParser::asString(m_data, &offset);
    } catch (SshPacketParseException &) {
        throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
            "Invalid SSH_MSG_CHANNEL_EXTENDED_DATA packet.");
    }
    return data;
}
예제 #6
0
void SshIncomingPacket::consumeData(QByteArray &newData)
{
#ifdef CREATOR_SSH_DEBUG
    qDebug("%s: current data size = %d, new data size = %d",
        Q_FUNC_INFO, m_data.size(), newData.size());
#endif

    if (isComplete() || newData.isEmpty())
        return;

    /*
     * Until we have reached the minimum packet size, we cannot decrypt the
     * length field.
     */
    const quint32 minSize = minPacketSize();
    if (currentDataSize() < minSize) {
        const int bytesToTake
            = qMin<quint32>(minSize - currentDataSize(), newData.size());
        moveFirstBytes(m_data, newData, bytesToTake);
#ifdef CREATOR_SSH_DEBUG
        qDebug("Took %d bytes from new data", bytesToTake);
#endif
        if (currentDataSize() < minSize)
            return;
    }

    if (4 + length() + macLength() < currentDataSize())
        throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR, "Server sent invalid packet.");

    const int bytesToTake
        = qMin<quint32>(length() + 4 + macLength() - currentDataSize(),
              newData.size());
    moveFirstBytes(m_data, newData, bytesToTake);
#ifdef CREATOR_SSH_DEBUG
    qDebug("Took %d bytes from new data", bytesToTake);
#endif
    if (isComplete()) {
#ifdef CREATOR_SSH_DEBUG
        qDebug("Message complete. Overall size: %u, payload size: %u",
            m_data.size(), m_length - paddingLength() - 1);
#endif
        decrypt();
        ++m_serverSeqNr;
    }
}
예제 #7
0
SshChannelOpenFailure SshIncomingPacket::extractChannelOpenFailure() const
{
    Q_ASSERT(isComplete());
    Q_ASSERT(type() == SSH_MSG_CHANNEL_OPEN_FAILURE);

    SshChannelOpenFailure openFailure;
    try {
        quint32 offset = TypeOffset + 1;
        openFailure.localChannel = SshPacketParser::asUint32(m_data, &offset);
        openFailure.reasonCode = SshPacketParser::asUint32(m_data, &offset);
        openFailure.reasonString = QString::fromLocal8Bit(SshPacketParser::asString(m_data, &offset));
        openFailure.language = SshPacketParser::asString(m_data, &offset);
    } catch (SshPacketParseException &) {
        throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
            "Server sent invalid SSH_MSG_CHANNEL_OPEN_FAILURE packet.");
    }
    return openFailure;
}
예제 #8
0
SshChannelOpenConfirmation SshIncomingPacket::extractChannelOpenConfirmation() const
{
    Q_ASSERT(isComplete());
    Q_ASSERT(type() == SSH_MSG_CHANNEL_OPEN_CONFIRMATION);

    SshChannelOpenConfirmation confirmation;
    try {
        quint32 offset = TypeOffset + 1;
        confirmation.localChannel = SshPacketParser::asUint32(m_data, &offset);
        confirmation.remoteChannel = SshPacketParser::asUint32(m_data, &offset);
        confirmation.remoteWindowSize = SshPacketParser::asUint32(m_data, &offset);
        confirmation.remoteMaxPacketSize = SshPacketParser::asUint32(m_data, &offset);
    } catch (SshPacketParseException &) {
        throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
            "Server sent invalid SSH_MSG_CHANNEL_OPEN_CONFIRMATION packet.");
    }
    return confirmation;
}
예제 #9
0
SshDisconnect SshIncomingPacket::extractDisconnect() const
{
    Q_ASSERT(isComplete());
    Q_ASSERT(type() == SSH_MSG_DISCONNECT);

    SshDisconnect msg;
    try {
        quint32 offset = TypeOffset + 1;
        msg.reasonCode = SshPacketParser::asUint32(m_data, &offset);
        msg.description = SshPacketParser::asUserString(m_data, &offset);
        msg.language = SshPacketParser::asString(m_data, &offset);
    } catch (SshPacketParseException &) {
        throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
            "Invalid SSH_MSG_DISCONNECT.");
    }

    return msg;
}
예제 #10
0
SshChannelExitStatus SshIncomingPacket::extractChannelExitStatus() const
{
    Q_ASSERT(isComplete());
    Q_ASSERT(type() == SSH_MSG_CHANNEL_REQUEST);

    SshChannelExitStatus exitStatus;
    try {
        quint32 offset = TypeOffset + 1;
        exitStatus.localChannel = SshPacketParser::asUint32(m_data, &offset);
        const QByteArray &type = SshPacketParser::asString(m_data, &offset);
        Q_ASSERT(type == ExitStatusType);
        Q_UNUSED(type);
        if (SshPacketParser::asBool(m_data, &offset))
            throw SshPacketParseException();
        exitStatus.exitStatus = SshPacketParser::asUint32(m_data, &offset);
    } catch (SshPacketParseException &) {
        throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
            "Invalid exit-status packet.");
    }
    return exitStatus;
}
예제 #11
0
void SftpChannelPrivate::handleServerVersion()
{
    checkChannelActive();
    if (m_sftpState != InitSent) {
        throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
            "Unexpected SSH_FXP_VERSION packet.");
    }

#ifdef CREATOR_SSH_DEBUG
    qDebug("sftp init received");
#endif
    const quint32 serverVersion = m_incomingPacket.extractServerVersion();
    if (serverVersion != ProtocolVersion) {
        emit initializationFailed(tr("Protocol version mismatch: Expected %1, got %2")
            .arg(serverVersion).arg(ProtocolVersion));
        closeChannel();
    } else {
        m_sftpState = Initialized;
        emit initialized();
    }
}
예제 #12
0
SshKeyExchangeInit SshIncomingPacket::extractKeyExchangeInitData() const
{
    Q_ASSERT(isComplete());
    Q_ASSERT(type() == SSH_MSG_KEXINIT);

    SshKeyExchangeInit exchangeData;
    try {
        quint32 offset = TypeOffset + 1;
        std::memcpy(exchangeData.cookie, &m_data.constData()[offset],
                    sizeof exchangeData.cookie);
        offset += sizeof exchangeData.cookie;
        exchangeData.keyAlgorithms
            = SshPacketParser::asNameList(m_data, &offset);
        exchangeData.serverHostKeyAlgorithms
            = SshPacketParser::asNameList(m_data, &offset);
        exchangeData.encryptionAlgorithmsClientToServer
            = SshPacketParser::asNameList(m_data, &offset);
        exchangeData.encryptionAlgorithmsServerToClient
            = SshPacketParser::asNameList(m_data, &offset);
        exchangeData.macAlgorithmsClientToServer
            = SshPacketParser::asNameList(m_data, &offset);
        exchangeData.macAlgorithmsServerToClient
            = SshPacketParser::asNameList(m_data, &offset);
        exchangeData.compressionAlgorithmsClientToServer
            = SshPacketParser::asNameList(m_data, &offset);
        exchangeData.compressionAlgorithmsServerToClient
            = SshPacketParser::asNameList(m_data, &offset);
        exchangeData.languagesClientToServer
            = SshPacketParser::asNameList(m_data, &offset);
        exchangeData.languagesServerToClient
            = SshPacketParser::asNameList(m_data, &offset);
        exchangeData.firstKexPacketFollows
            = SshPacketParser::asBool(m_data, &offset);
    } catch (SshPacketParseException &) {
        throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
            "Key exchange failed: Server sent invalid SSH_MSG_KEXINIT packet.");
    }
    return exchangeData;
}
예제 #13
0
SshKeyExchangeReply SshIncomingPacket::extractKeyExchangeReply(const QByteArray &pubKeyAlgo) const
{
    Q_ASSERT(isComplete());
    Q_ASSERT(type() == SSH_MSG_KEXDH_REPLY);

    try {
        SshKeyExchangeReply replyData;
        quint32 offset = TypeOffset + 1;
        const quint32 k_sLength
            = SshPacketParser::asUint32(m_data, &offset);
        if (offset + k_sLength > currentDataSize())
            throw SshPacketParseException();
        replyData.k_s = m_data.mid(offset - 4, k_sLength + 4);
        if (SshPacketParser::asString(m_data, &offset) != pubKeyAlgo)
            throw SshPacketParseException();

        // DSS: p and q, RSA: e and n
        replyData.parameters << SshPacketParser::asBigInt(m_data, &offset);
        replyData.parameters << SshPacketParser::asBigInt(m_data, &offset);

        // g and y
        if (pubKeyAlgo == SshCapabilities::PubKeyDss) {
            replyData.parameters << SshPacketParser::asBigInt(m_data, &offset);
            replyData.parameters << SshPacketParser::asBigInt(m_data, &offset);
        }

        replyData.f = SshPacketParser::asBigInt(m_data, &offset);
        offset += 4;
        if (SshPacketParser::asString(m_data, &offset) != pubKeyAlgo)
            throw SshPacketParseException();
        replyData.signatureBlob = SshPacketParser::asString(m_data, &offset);
        return replyData;
    } catch (SshPacketParseException &) {
        throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_KEY_EXCHANGE_FAILED,
            "Key exchange failed: "
            "Server sent invalid SSH_MSG_KEXDH_REPLY packet.");
    }
}
void SftpIncomingPacket::consumeData(QByteArray &newData)
{
#ifdef CREATOR_SSH_DEBUG
    qDebug("%s: current data size = %d, new data size = %d", Q_FUNC_INFO,
        m_data.size(), newData.size());
#endif

    if (isComplete() || dataSize() + newData.size() < sizeof m_length)
        return;

    if (dataSize() < sizeof m_length) {
        moveFirstBytes(m_data, newData, sizeof m_length - m_data.size());
        m_length = SshPacketParser::asUint32(m_data, static_cast<quint32>(0));
        if (m_length < static_cast<quint32>(TypeOffset + 1)
            || m_length > MaxPacketSize) {
            throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
                "Invalid length field in SFTP packet.");
        }
    }

    moveFirstBytes(m_data, newData,
        qMin<quint32>(m_length - dataSize() + 4, newData.size()));
}
예제 #15
0
SshChannelExitSignal SshIncomingPacket::extractChannelExitSignal() const
{
    Q_ASSERT(isComplete());
    Q_ASSERT(type() == SSH_MSG_CHANNEL_REQUEST);

    SshChannelExitSignal exitSignal;
    try {
        quint32 offset = TypeOffset + 1;
        exitSignal.localChannel = SshPacketParser::asUint32(m_data, &offset);
        const QByteArray &type = SshPacketParser::asString(m_data, &offset);
        Q_ASSERT(type == ExitSignalType);
        Q_UNUSED(type);
        if (SshPacketParser::asBool(m_data, &offset))
            throw SshPacketParseException();
        exitSignal.signal = SshPacketParser::asString(m_data, &offset);
        exitSignal.coreDumped = SshPacketParser::asBool(m_data, &offset);
        exitSignal.error = SshPacketParser::asUserString(m_data, &offset);
        exitSignal.language = SshPacketParser::asString(m_data, &offset);
    } catch (SshPacketParseException &) {
        throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
            "Invalid exit-signal packet.");
    }
    return exitSignal;
}
예제 #16
0
SshUserAuthInfoRequestPacket SshIncomingPacket::extractUserAuthInfoRequest() const
{
    Q_ASSERT(isComplete());
    Q_ASSERT(type() == SSH_MSG_USERAUTH_INFO_REQUEST);

    try {
        SshUserAuthInfoRequestPacket msg;
        quint32 offset = TypeOffset + 1;
        msg.name = SshPacketParser::asUserString(m_data, &offset);
        msg.instruction = SshPacketParser::asUserString(m_data, &offset);
        msg.languageTag = SshPacketParser::asString(m_data, &offset);
        const quint32 promptCount = SshPacketParser::asUint32(m_data, &offset);
        msg.prompts.reserve(promptCount);
        msg.echos.reserve(promptCount);
        for (quint32 i = 0; i < promptCount; ++i) {
            msg.prompts << SshPacketParser::asUserString(m_data, &offset);
            msg.echos << SshPacketParser::asBool(m_data, &offset);
        }
        return msg;
    } catch (SshPacketParseException &) {
        throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
            "Invalid SSH_MSG_USERAUTH_INFO_REQUEST.");
    }
}
예제 #17
0
void SshChannelManager::handleChannelOpen(const SshIncomingPacket &)
{
    throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
        "Server tried to open channel on client.");
}
예제 #18
0
void AbstractSshChannel::checkChannelActive()
{
    if (channelState() == Inactive || channelState() == Closed)
        throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
            "Channel not open.");
}
예제 #19
0
void SshDirectTcpIpTunnelPrivate::handleChannelSuccess()
{
    throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
            "Unexpected SSH_MSG_CHANNEL_SUCCESS message.");
}
예제 #20
0
void SshDirectTcpIpTunnelPrivate::handleChannelFailure()
{
    throw SSH_SERVER_EXCEPTION(SSH_DISCONNECT_PROTOCOL_ERROR,
            "Unexpected SSH_MSG_CHANNEL_FAILURE message.");
}