void OtrInternal::abortSMP(const QString& account, const QString& contact) { ConnContext* context = otrl_context_find(m_userstate, contact.toUtf8().constData(), account.toUtf8().constData(), OTR_PROTOCOL_STRING, #if (OTRL_VERSION_MAJOR >= 4) OTRL_INSTAG_BEST, #endif false, NULL, NULL, NULL); if (context) { abortSMP(context); } }
void OtrInternal::handle_smp_event(OtrlSMPEvent smp_event, ConnContext* context, unsigned short progress_percent, char* question) { if (smp_event == OTRL_SMPEVENT_CHEATED || smp_event == OTRL_SMPEVENT_ERROR) { abortSMP(context); m_callback->updateSMP(QString::fromUtf8(context->accountname), QString::fromUtf8(context->username), -2); } else if (smp_event == OTRL_SMPEVENT_ASK_FOR_SECRET || smp_event == OTRL_SMPEVENT_ASK_FOR_ANSWER) { m_callback->receivedSMP(QString::fromUtf8(context->accountname), QString::fromUtf8(context->username), QString::fromUtf8(question)); } else { m_callback->updateSMP(QString::fromUtf8(context->accountname), QString::fromUtf8(context->username), progress_percent); } }
psiotr::OtrMessageType OtrInternal::decryptMessage(const QString& account, const QString& contact, const QString& cryptedMessage, QString& decrypted) { QByteArray accArray = account.toUtf8(); QByteArray userArray = contact.toUtf8(); const char* accountName = accArray.constData(); const char* userName = userArray.constData(); int ignoreMessage = 0; char* newMessage = NULL; OtrlTLV* tlvs = NULL; OtrlTLV* tlv = NULL; ignoreMessage = otrl_message_receiving(m_userstate, &m_uiOps, this, accountName, OTR_PROTOCOL_STRING, userName, cryptedMessage.toUtf8().constData(), &newMessage, &tlvs, NULL, #if (OTRL_VERSION_MAJOR >= 4) NULL, #endif NULL); tlv = otrl_tlv_find(tlvs, OTRL_TLV_DISCONNECTED); if (tlv) { m_callback->stateChange(accountName, userName, psiotr::OTR_STATECHANGE_REMOTECLOSE); } #if (OTRL_VERSION_MAJOR >= 4) // Magic hack to force it work similar to libotr < 4.0.0. // If user received unencrypted message he (she) should be notified. // See OTRL_MSGEVENT_RCVDMSG_UNENCRYPTED as well. if (ignoreMessage && !newMessage && !cryptedMessage.startsWith("?OTR")) { ignoreMessage = 0; } #else // Check for SMP data (required only with libotr < 4.0.0) ConnContext* context = otrl_context_find(m_userstate, userName, accountName, OTR_PROTOCOL_STRING, false, NULL, NULL, NULL); if (context) { NextExpectedSMP nextMsg = context->smstate->nextExpected; if (context->smstate->sm_prog_state == OTRL_SMP_PROG_CHEATED) { abortSMP(context); // Reset state context->smstate->nextExpected = OTRL_SMP_EXPECT1; context->smstate->sm_prog_state = OTRL_SMP_PROG_OK; // Report result to user m_callback->updateSMP(accountName, userName, -2); } else { tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1Q); if (tlv) { if (nextMsg != OTRL_SMP_EXPECT1) { abortSMP(context); } else { char* question = (char *)tlv->data; char* eoq = static_cast<char*>(memchr(question, '\0', tlv->len)); if (eoq) { m_callback->receivedSMP(accountName, userName, QString::fromUtf8(question)); } } } tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1); if (tlv) { if (nextMsg != OTRL_SMP_EXPECT1) { abortSMP(context); } else { m_callback->receivedSMP(accountName, userName, QString()); } } tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP2); if (tlv) { if (nextMsg != OTRL_SMP_EXPECT2) { abortSMP(context); } else { // If we received TLV2, we will send TLV3 and expect TLV4 context->smstate->nextExpected = OTRL_SMP_EXPECT4; // Report result to user m_callback->updateSMP(accountName, userName, 66); } } tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP3); if (tlv) { if (nextMsg != OTRL_SMP_EXPECT3) { abortSMP(context); } else { // SMP finished, reset context->smstate->nextExpected = OTRL_SMP_EXPECT1; // Report result to user m_callback->updateSMP(accountName, userName, 100); } } tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP4); if (tlv) { if (nextMsg != OTRL_SMP_EXPECT4) { abortSMP(context); } else { // SMP finished, reset context->smstate->nextExpected = OTRL_SMP_EXPECT1; // Report result to user m_callback->updateSMP(accountName, userName, 100); } } tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP_ABORT); if (tlv) { // SMP aborted, reset context->smstate->nextExpected = OTRL_SMP_EXPECT1; // Report result to user m_callback->updateSMP(accountName, userName, -1); } } } #endif otrl_tlv_free(tlvs); if (ignoreMessage == 1) { // Internal protocol message return psiotr::OTR_MESSAGETYPE_IGNORE; } else if ((ignoreMessage == 0) && newMessage) { // Message has been decrypted, replace it decrypted = QString::fromUtf8(newMessage); otrl_message_free(newMessage); return psiotr::OTR_MESSAGETYPE_OTR; } return psiotr::OTR_MESSAGETYPE_NONE; }
QString OtrInternal::decryptMessage(const QString& from, const QString& to, const QString& cryptedMessage, TreeModelItem &item) { QString protocol = item.m_protocol_name; int ignoreMessage = 0; char *newMessage = NULL; OtrlTLV *tlvs = NULL; OtrlTLV *tlv = NULL; ConnContext *context = 0; NextExpectedSMP nextMsg; ignoreMessage = otrl_message_receiving(m_userstate, &m_uiOps, this, to.toStdString().c_str(), protocol.toStdString().c_str(), from.toStdString().c_str(), cryptedMessage.toUtf8().data(), &newMessage, &tlvs, NULL, NULL); context = otrl_context_find( m_userstate, from.toStdString().c_str(), to.toStdString().c_str(), protocol.toStdString().c_str(), 0, NULL, NULL, NULL); // qDebug() << "[OTR] context fragment: " << QString(context->lastmessage); tlv = otrl_tlv_find(tlvs, OTRL_TLV_DISCONNECTED); if( tlv ){ sendCustomNessage(item,tr("%1 has ended the OTR session. You should do the same.").arg(item.m_item_name)); gone_insecure(context); } while (context) { OtrlSMState *state = context->smstate; if(!state) break; nextMsg = state->nextExpected; tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1Q); if (tlv) { // qDebug() << "[OTR] SMP detected. Found SMP1Q"; //a-la pidgin if (nextMsg != OTRL_SMP_EXPECT1) abortSMP(context,item); else { char *question = (char *)tlv->data; char *eoq = (char*)memchr(question, '\0', tlv->len); if (eoq) { QString ans = QInputDialog::getText(NULL,tr("Auth"),tr("Please, answer the question to be authorised by %1.<br>Question: <b>%2</b>").arg(from).arg(QString(question))); if(!ans.isEmpty()) respondSMP(context,item,ans,false); else abortSMP(context,item); } } } tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1); if (tlv) { // qDebug() << "[OTR] SMP detected. Found SMP1"; if (nextMsg != OTRL_SMP_EXPECT1 ){ abortSMP( context, item ); } else { QString s = QInputDialog::getText ( NULL, tr("Authorysing"), tr("Please, enter passphrase to authorise %1").arg(context->username), QLineEdit::Normal); if(!s.isEmpty()) respondSMP(context,item,s,false); else abortSMP(context,item); } } tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP2); if (tlv) { // qDebug() << "[OTR] SMP detected. Found SMP2"; if (nextMsg != OTRL_SMP_EXPECT2){ abortSMP( context, item ); } else { context->smstate->nextExpected = OTRL_SMP_EXPECT4; } } tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP3); if (tlv) { // qDebug() << "[OTR] SMP detected. Found SMP3"; if (nextMsg != OTRL_SMP_EXPECT3){ abortSMP( context, item ); } else { if (context->active_fingerprint->trust && context->active_fingerprint->trust[0]) { sendCustomNessage(item, tr("Your buddy has successfully authenticated you. The conversation is now secure!")); gone_secure(context); } else { // sendCustomNessage(item, tr("Authentication failed. The conversation is now insecure!")); sendCustomNessage(item,tr("Your buddy has successfully authenticated you. You may want to authenticate your buddy as well by asking your own question.")); gone_secure(context); } context->smstate->nextExpected = OTRL_SMP_EXPECT1; } } tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP4); if (tlv) { // qDebug() << "[OTR] SMP detected. Found SMP4"; if (nextMsg != OTRL_SMP_EXPECT4) { abortSMP( context, item ); } else { if (context->active_fingerprint->trust && context->active_fingerprint->trust[0]) { sendCustomNessage(item, tr("Authentication successful. The conversation is now secure!")); gone_secure(context); } else { sendCustomNessage(item, tr("Authentication failed. The conversation is now insecure!")); gone_secure(context); } context->smstate->nextExpected = OTRL_SMP_EXPECT1; } } tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP_ABORT); if (tlv) { // qDebug() << "[OTR] SMP detected. Found SMP_ABORT"; sendCustomNessage(item,tr("Authentication error!").toLocal8Bit() ); context->smstate->nextExpected = OTRL_SMP_EXPECT1; } otrl_tlv_free(tlvs); break; } if (ignoreMessage == 1) // internal protocol message { OtrlMessageType type = otrl_proto_message_type( cryptedMessage.toStdString().c_str()); QString retMessage("<Internal OTR message>\n"+tr("received %1 \nOTR state now is [%2]").arg(otrlMessageTypeToString(type)).arg(getMessageStateString(to, from, item))) ; if (getMessageState(to, from, item) == qutimotr::OTR_MESSAGESTATE_ENCRYPTED) { retMessage.append(tr("\nsessionId: ") + getSessionId(to, from, item)); } // TODO: если бы эти сообщения можна было заблокировать... // но recivelevel1/2 не дает такой возможности... почему то // хотя в вики написано обратное // sendCustomNessage(item,retMessage); return retMessage; } else if (ignoreMessage == 0) { if (newMessage != NULL) // message has been decrypted. replace it { QString retMessage = QString::fromUtf8(newMessage); otrl_message_free(newMessage); return retMessage; } else // received message was not an otr message { return cryptedMessage; } } assert(false); return QString(); }