예제 #1
0
void SftpChannelPrivate::handleCurrentPacket()
{
#ifdef CREATOR_SSH_DEBUG
    qDebug("Handling SFTP packet of type %d", m_incomingPacket.type());
#endif
    switch (m_incomingPacket.type()) {
    case SSH_FXP_VERSION:
        handleServerVersion();
        break;
    case SSH_FXP_HANDLE:
        handleHandle();
        break;
    case SSH_FXP_NAME:
        handleName();
        break;
    case SSH_FXP_STATUS:
        handleStatus();
        break;
    case SSH_FXP_DATA:
        handleReadData();
        break;
    case SSH_FXP_ATTRS:
        handleAttrs();
        break;
    default:
        throw SshServerException(SSH_DISCONNECT_PROTOCOL_ERROR,
            "Unexpected packet.",
            tr("Unexpected packet of type %1.").arg(m_incomingPacket.type()));
    }
}
예제 #2
0
SshChannelManager::ChannelIterator SshChannelManager::lookupChannelAsIterator(quint32 channelId,
    bool allowNotFound)
{
    ChannelIterator it = m_channels.find(channelId);
    if (it == m_channels.end() && !allowNotFound) {
        throw SshServerException(SSH_DISCONNECT_PROTOCOL_ERROR,
            "Invalid channel id.",
            tr("Invalid channel id %1").arg(channelId));
    }
    return it;
}
예제 #3
0
void SshConnectionPrivate::handleUnimplementedPacket()
{
    const SshUnimplemented &msg = m_incomingPacket.extractUnimplemented();
    if (msg.invalidMsgSeqNr != m_lastInvalidMsgSeqNr) {
        throw SshServerException(SSH_DISCONNECT_PROTOCOL_ERROR,
            "Unexpected packet", tr("The server sent an unexpected SSH packet "
            "of type SSH_MSG_UNIMPLEMENTED."));
    }
    m_lastInvalidMsgSeqNr = InvalidSeqNr;
    m_timeoutTimer.stop();
    m_keepAliveTimer.start();
}
예제 #4
0
void SshConnectionPrivate::handleKeyExchangeReplyPacket()
{
    if (m_keyExchangeState != DhInitSent) {
        throw SshServerException(SSH_DISCONNECT_PROTOCOL_ERROR,
            "Unexpected packet.", tr("Unexpected packet of type %1.")
            .arg(m_incomingPacket.type()));
    }

    m_keyExchange->sendNewKeysPacket(m_incomingPacket,
        ClientId.left(ClientId.size() - 2));
    m_sendFacility.recreateKeys(*m_keyExchange);
    m_keyExchangeState = NewKeysSent;
}
예제 #5
0
void SshConnectionPrivate::handleNewKeysPacket()
{
    if (m_keyExchangeState != NewKeysSent) {
        throw SshServerException(SSH_DISCONNECT_PROTOCOL_ERROR,
            "Unexpected packet.", tr("Unexpected packet of type %1.")
            .arg(m_incomingPacket.type()));
    }

    m_incomingPacket.recreateKeys(*m_keyExchange);
    m_keyExchange.reset();
    m_keyExchangeState = NoKeyExchange;

    if (m_state == SocketConnected) {
        m_sendFacility.sendUserAuthServiceRequestPacket();
        m_state = UserAuthServiceRequested;
    }
}
예제 #6
0
void SshConnectionPrivate::handleKeyExchangeInitPacket()
{
    if (m_keyExchangeState != NoKeyExchange
            && m_keyExchangeState != KexInitSent) {
        throw SshServerException(SSH_DISCONNECT_PROTOCOL_ERROR,
            "Unexpected packet.", tr("Unexpected packet of type %1.")
            .arg(m_incomingPacket.type()));
    }

    // Server-initiated re-exchange.
    if (m_keyExchangeState == NoKeyExchange) {
        m_keyExchange.reset(new SshKeyExchange(m_sendFacility));
        m_keyExchange->sendKexInitPacket(m_serverId);
    }

    // If the server sends a guessed packet, the guess must be wrong,
    // because the algorithms we support require us to initiate the
    // key exchange.
    if (m_keyExchange->sendDhInitPacket(m_incomingPacket))
        m_ignoreNextPacket = true;

    m_keyExchangeState = DhInitSent;
}
예제 #7
0
void SshConnectionPrivate::handleDisconnect()
{
    const SshDisconnect msg = m_incomingPacket.extractDisconnect();
    throw SshServerException(SSH_DISCONNECT_CONNECTION_LOST,
        "", tr("Server closed connection: %1").arg(msg.description));
}
예제 #8
0
void SshConnectionPrivate::handleUnexpectedPacket()
{
    throw SshServerException(SSH_DISCONNECT_PROTOCOL_ERROR,
                             "Unexpected packet.", tr("Unexpected packet of type %1.")
                             .arg(m_incomingPacket.type()));
}
예제 #9
0
// RFC 4253, 4.2.
void SshConnectionPrivate::handleServerId()
{
#ifdef CREATOR_SSH_DEBUG
    qDebug("%s: incoming data size = %d, incoming data = '%s'",
        Q_FUNC_INFO, m_incomingData.count(), m_incomingData.data());
#endif
    const int newLinePos = m_incomingData.indexOf('\n');
    if (newLinePos == -1)
        return; // Not enough data yet.

    // Lines not starting with "SSH-" are ignored.
    if (!m_incomingData.startsWith("SSH-")) {
        m_incomingData.remove(0, newLinePos + 1);
        m_serverHasSentDataBeforeId = true;
        return;
    }

    if (newLinePos > 255 - 1) {
        throw SshServerException(SSH_DISCONNECT_PROTOCOL_ERROR,
            "Identification string too long.",
            tr("Server identification string is %n characters long, but the maximum "
               "allowed length is 255.", 0, newLinePos + 1));
    }

    const bool hasCarriageReturn = m_incomingData.at(newLinePos - 1) == '\r';
    m_serverId = m_incomingData.left(newLinePos);
    if (hasCarriageReturn)
        m_serverId.chop(1);
    m_incomingData.remove(0, newLinePos + 1);

    if (m_serverId.contains('\0')) {
        throw SshServerException(SSH_DISCONNECT_PROTOCOL_ERROR,
            "Identification string contains illegal NUL character.",
            tr("Server identification string contains illegal NUL character."));
    }

    // "printable US-ASCII characters, with the exception of whitespace characters
    // and the minus sign"
    QString legalString = QLatin1String("[]!\"#$!&'()*+,./0-9:;<=>?@A-Z[\\\\^_`a-z{|}~]+");
    const QRegExp versionIdpattern(QString::fromLatin1("SSH-(%1)-%1(?: .+)?").arg(legalString));
    if (!versionIdpattern.exactMatch(QString::fromLatin1(m_serverId))) {
        throw SshServerException(SSH_DISCONNECT_PROTOCOL_ERROR,
            "Identification string is invalid.",
            tr("Server Identification string '%1' is invalid.")
                    .arg(QString::fromLatin1(m_serverId)));
    }
    const QString serverProtoVersion = versionIdpattern.cap(1);
    if (serverProtoVersion != QLatin1String("2.0") && serverProtoVersion != QLatin1String("1.99")) {
        throw SshServerException(SSH_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED,
            "Invalid protocol version.",
            tr("Server protocol version is '%1', but needs to be 2.0 or 1.99.")
                    .arg(serverProtoVersion));
    }

    if (m_connParams.options & SshEnableStrictConformanceChecks) {
        if (serverProtoVersion == QLatin1String("2.0") && !hasCarriageReturn) {
            throw SshServerException(SSH_DISCONNECT_PROTOCOL_ERROR,
                    "Identification string is invalid.",
                    tr("Server identification string is invalid (missing carriage return)."));
        }

        if (serverProtoVersion == QLatin1String("1.99") && m_serverHasSentDataBeforeId) {
            throw SshServerException(SSH_DISCONNECT_PROTOCOL_ERROR,
                    "No extra data preceding identification string allowed for 1.99.",
                    tr("Server reports protocol version 1.99, but sends data "
                       "before the identification string, which is not allowed."));
        }
    }

    m_keyExchange.reset(new SshKeyExchange(m_sendFacility));
    m_keyExchange->sendKexInitPacket(m_serverId);
    m_keyExchangeState = KexInitSent;
}