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())); } }
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; }
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(); }
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; }
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; } }
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; }
void SshConnectionPrivate::handleDisconnect() { const SshDisconnect msg = m_incomingPacket.extractDisconnect(); throw SshServerException(SSH_DISCONNECT_CONNECTION_LOST, "", tr("Server closed connection: %1").arg(msg.description)); }
void SshConnectionPrivate::handleUnexpectedPacket() { throw SshServerException(SSH_DISCONNECT_PROTOCOL_ERROR, "Unexpected packet.", tr("Unexpected packet of type %1.") .arg(m_incomingPacket.type())); }
// 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; }