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;
}
Beispiel #4
0
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();
}