static void _otr_tlv_free(OtrlTLV *tlvs) { if (tlvs) { otrl_tlv_free(tlvs); } }
static void sending(const char *from, const char *to, const char *msg) { gcry_error_t err; OtrlTLV *tlvs = NULL; char *newmsg; err = otrl_message_sending(us, &ops, NULL, from, PROTO, to, msg, tlvs, &newmsg, NULL, NULL, NULL); if (!err) { inject(from, to, newmsg ? newmsg : msg); } otrl_message_free(newmsg); otrl_tlv_free(tlvs); }
void receiving(const char *from, const char *to, const char *msg) { int ignore; char *newmsg; OtrlTLV *tlvs; ignore = otrl_message_receiving(us, &ops, NULL, to, PROTO, from, msg, &newmsg, &tlvs, NULL, NULL); if (!ignore) { printf("%s> %s\n\n", from, newmsg ? newmsg : msg); } otrl_message_free(newmsg); otrl_tlv_free(tlvs); }
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; }
/* * Hand the given message to OTR. * * Returns 0 if its an OTR protocol message or else negative value. */ int otr_receive(SERVER_REC *irssi, const char *msg, const char *from, char **new_msg) { int ret = -1; char *accname = NULL, *full_msg = NULL; const char *recv_msg = NULL; OtrlTLV *tlvs; ConnContext *ctx; struct otr_peer_context *opc; assert(irssi); accname = create_account_name(irssi); if (!accname) { goto error; } IRSSI_DEBUG("Receiving message..."); ctx = otr_find_context(irssi, from, 1); if (!ctx) { goto error; } /* Add peer context to OTR context if none exists */ if (!ctx->app_data) { add_peer_context_cb(irssi, ctx); } opc = ctx->app_data; assert(opc); ret = enqueue_otr_fragment(msg, opc, &full_msg); switch (ret) { case OTR_MSG_ORIGINAL: recv_msg = msg; break; case OTR_MSG_WAIT_MORE: ret = 1; goto error; case OTR_MSG_USE_QUEUE: recv_msg = full_msg; break; case OTR_MSG_ERROR: ret = -1; goto error; } ret = otrl_message_receiving(user_state_global->otr_state, &otr_ops, irssi, accname, OTR_PROTOCOL_ID, from, recv_msg, new_msg, &tlvs, &ctx, add_peer_context_cb, irssi); if (ret) { IRSSI_DEBUG("Ignoring message of length %d from %s to %s.\n" "%s", strlen(msg), from, accname, msg); } else { if (*new_msg) { IRSSI_DEBUG("Converted received message."); } } /* Check for disconnected message */ OtrlTLV *tlv = otrl_tlv_find(tlvs, OTRL_TLV_DISCONNECTED); if (tlv) { otr_status_change(irssi, from, OTR_STATUS_PEER_FINISHED); IRSSI_NOTICE(irssi, from, "%9%s%9 has finished the OTR " "conversation. If you want to continue talking enter " "%9/otr finish%9 for plaintext or %9/otr init%9 to restart.", from); } otrl_tlv_free(tlvs); IRSSI_DEBUG("Message received."); error: if (full_msg) { free(full_msg); } free(accname); return ret; }
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(); }