/** * Decrypt a received message. */ const char* OtrConnection::decryptMessage(const char* from, const char* to, const char* cryptedMessage) { int ignore_message = 0; char *newMessage = NULL; ignore_message = otrl_message_receiving( userstate, &ui_ops, this, to, "prpl-jabber", from, cryptedMessage, &newMessage, NULL, NULL, NULL); if (ignore_message == 1) { // internal protocol message. show user what kind of message was received. QString msg; OtrlMessageType type = otrl_proto_message_type(cryptedMessage); if (type == OTRL_MSGTYPE_NOTOTR) msg = "no OTR Message"; else if (type == OTRL_MSGTYPE_TAGGEDPLAINTEXT) msg= "OTR TaggedPlaintexMessage"; else if (type == OTRL_MSGTYPE_QUERY) msg= "OTR QueryMessage"; else if (type == OTRL_MSGTYPE_DH_COMMIT) msg= "OTR DH-Commit Message"; else if (type == OTRL_MSGTYPE_DH_KEY) msg= "OTR DH-Key Message"; else if (type == OTRL_MSGTYPE_REVEALSIG) msg= "OTR Reveal Signature Message"; else if (type == OTRL_MSGTYPE_SIGNATURE) msg= "OTR Signature Message"; else if (type == OTRL_MSGTYPE_V1_KEYEXCH) msg= "OTR Version 1 Key Exchange Message"; else if (type == OTRL_MSGTYPE_DATA) msg ="OTR Data Message"; else if (type == OTRL_MSGTYPE_ERROR) msg ="OTR Error Message"; else if (type == OTRL_MSGTYPE_UNKNOWN) msg= "OTR Unknown Message"; else msg= "Unknown Message Type"; msg.insert(0, "Received "); QString state = "[" + getMessageStateString(to, from) + "]"; msg.append(" " + state); OtrlMessageState* stateId; stateId = getMessageState(to, from); if (stateId != NULL && *stateId == OTRL_MSGSTATE_ENCRYPTED) { msg.append("\nsessionId: " + getSessionId(to, from)); } char* retMsg = (char*) malloc( msg.length() + 1 ); strcpy(retMsg, msg.toStdString().c_str()); return retMsg; } else if (ignore_message == 0) { if (newMessage != NULL) { // replace message return newMessage; } else { // no otr message char* retMsg = (char*) malloc(strlen(cryptedMessage)+1); strcpy(retMsg, cryptedMessage); return retMsg; } } return NULL; }
void OtrProxyChannel::Adaptee::sendMessage(const Tp::MessagePartList &message, uint flags, const Tp::Service::ChannelProxyInterfaceOTRAdaptor::SendMessageContextPtr &context) { qCDebug(KTP_PROXY); if(!connected()) { context->setFinishedWithError(KTP_PROXY_ERROR_NOT_CONNECTED, QString::fromLatin1("Proxy is not connected")); return; } OTR::Message otrMessage(message); const OTR::CryptResult cres = otrSes.encrypt(otrMessage); if(cres == OTR::CryptResult::ERROR) { qCDebug(KTP_PROXY) << "Sending error"; context->setFinishedWithError(KTP_PROXY_ERROR_ENCRYPTION_ERROR, QLatin1String("Message could not be encrypted with OTR")); return; } // we are starting an AKE - do not show it to the user // policy is probably set to ALWAYS in this case if(otrl_proto_message_type(otrMessage.text().toLocal8Bit()) == OTRL_MSGTYPE_QUERY) { sendOTRmessage(otrMessage); } else { PendingSendMessageResult *pending = new PendingSendMessageResult( chan->send(otrMessage.parts(), (Tp::MessageSendingFlags) flags), chan, context, message, flags); connect(pending, SIGNAL(finished(Tp::PendingOperation*)), SLOT(onPendingSendFinished(Tp::PendingOperation*))); } }
static void test_otrl_proto_message_type(void) { OtrlMessageType ret; const char *test1 = "This is plaintext"; ret = otrl_proto_message_type(test1); ok(ret == OTRL_MSGTYPE_NOTOTR, "Proto message type is not OTR"); const char *test2 = OTRL_MESSAGE_TAG_BASE "This is plaintext"; ret = otrl_proto_message_type(test2); ok(ret == OTRL_MSGTYPE_TAGGEDPLAINTEXT, "Proto message type is tagged plaintext"); const char *test3 = "?OTR:AAIC"; ret = otrl_proto_message_type(test3); ok(ret == OTRL_MSGTYPE_DH_COMMIT, "Proto message type v2 is dh commit"); const char *test4 = "?OTR:AAMC"; ret = otrl_proto_message_type(test4); ok(ret == OTRL_MSGTYPE_DH_COMMIT, "Proto message type v3 is dh commit"); const char *test5 = "?OTR:AAIK"; ret = otrl_proto_message_type(test5); ok(ret == OTRL_MSGTYPE_DH_KEY, "Proto message type v2 is DH key"); const char *test6 = "?OTR:AAMK"; ret = otrl_proto_message_type(test6); ok(ret == OTRL_MSGTYPE_DH_KEY, "Proto message type v3 is DH key"); const char *test7 = "?OTR:AAIR"; ret = otrl_proto_message_type(test7); ok(ret == OTRL_MSGTYPE_REVEALSIG, "Proto message type v2 is revealsig"); const char *test8 = "?OTR:AAMR"; ret = otrl_proto_message_type(test8); ok(ret == OTRL_MSGTYPE_REVEALSIG, "Proto message type v3 is revealsig"); const char *test9 = "?OTR:AAIS"; ret = otrl_proto_message_type(test9); ok(ret == OTRL_MSGTYPE_SIGNATURE, "Proto message type v2 is a signature"); const char *test10 = "?OTR:AAMS"; ret = otrl_proto_message_type(test10); ok(ret == OTRL_MSGTYPE_SIGNATURE, "Proto message type v3 is a signature"); const char *test11 = "?OTR:AAID"; ret = otrl_proto_message_type(test11); ok(ret == OTRL_MSGTYPE_DATA, "Proto message type v2 is a data msg"); const char *test12 = "?OTR:AAMD"; ret = otrl_proto_message_type(test12); ok(ret == OTRL_MSGTYPE_DATA, "Proto message type v3 is a data msg"); const char *test13 = "?OTR?"; ret = otrl_proto_message_type(test13); ok(ret == OTRL_MSGTYPE_QUERY, "Proto message type is a query"); const char *test14 = "?OTR?v"; ret = otrl_proto_message_type(test14); ok(ret == OTRL_MSGTYPE_QUERY, "Proto message type is a query"); const char *test15 = "?OTR Error:"; ret = otrl_proto_message_type(test15); ok(ret == OTRL_MSGTYPE_ERROR, "Proto message type is an error"); const char *test16 = "?OTR: Please verify me"; ret = otrl_proto_message_type(test16); ok(ret == OTRL_MSGTYPE_UNKNOWN, "Proto message type is unknown"); const char *test17 = "?OTR:AAMA"; ret = otrl_proto_message_type(test17); ok(ret == OTRL_MSGTYPE_UNKNOWN, "Proto message type is unknown"); }
int main(int argc, char **argv) { unsigned char *mackey; size_t mackeylen; unsigned char macval[20]; char *otrmsg = NULL; DataMsg datamsg; size_t textlen; unsigned int offset; const unsigned char *old_text, *new_text; char *newdatamsg; size_t i; if (argc != 5) { usage(argv[0]); } argv_to_buf(&mackey, &mackeylen, argv[1]); if (!mackey) { usage(argv[0]); } if (mackeylen != 20) { fprintf(stderr, "The MAC key must be 40 hex chars long.\n"); usage(argv[0]); } textlen = strlen(argv[2]); if (textlen != strlen(argv[3])) { fprintf(stderr, "The old_text and new_text must be of the same " "length.\n"); usage(argv[0]); } old_text = (const unsigned char *)argv[2]; new_text = (const unsigned char *)argv[3]; if (sscanf(argv[4], "%u", &offset) != 1) { fprintf(stderr, "Unparseable offset given.\n"); usage(argv[0]); } otrmsg = readotr(stdin); if (otrmsg == NULL) { fprintf(stderr, "No OTR Data Message found on stdin.\n"); exit(1); } if (otrl_proto_message_type(otrmsg) != OTRL_MSGTYPE_DATA) { fprintf(stderr, "OTR Non-Data Message found on stdin.\n"); exit(1); } datamsg = parse_datamsg(otrmsg); free(otrmsg); if (datamsg == NULL) { fprintf(stderr, "Invalid OTR Data Message found on stdin.\n"); exit(1); } /* Check the MAC */ sha1hmac(macval, mackey, datamsg->macstart, datamsg->macend - datamsg->macstart); if (memcmp(macval, datamsg->mac, 20)) { fprintf(stderr, "MAC does not verify: wrong MAC key?\n"); exit(1); } /* Modify the ciphertext */ for(i=0; i<textlen && offset+i < datamsg->encmsglen; ++i) { datamsg->encmsg[offset+i] ^= (old_text[i] ^ new_text[i]); } /* Recalculate the MAC */ newdatamsg = remac_datamsg(datamsg, mackey); printf("%s\n", newdatamsg); free(newdatamsg); free_datamsg(datamsg); free(mackey); fflush(stdout); return 0; }
int totrEncryptMessage(int windowID, char* subwindow, char* event, void* data, void* userData) { edit_event_t* msg = reinterpret_cast<edit_event_t*>(data); TotrAppData* eopts = reinterpret_cast<TotrAppData*>(userData); char* message = NULL; char* newmessage = NULL; char* account_name = NULL; int res = -1; int connection_id = -1; ConnContext* conn = userstate->context_root; //CAtlRegExp<> reStart, reEnd; //CAtlREMatchContext<> mcStart, mcEnd; BOOL resStart = FALSE; BOOL resEnd = FALSE; if(!msg || !reinterpret_cast<char*>(msg->data) || stricmp(event, "edit_sendText") != 0 || !strlen(reinterpret_cast<char*>(msg->data)) || (reinterpret_cast<char*>(msg->data)[0]) == '/') return 0; /* Bail out of parsing any messages starting with / * Too bad we can't tell if this is a real command * or not without doing some interpretive lists. * Even then, such lists would not include other * plugins that impliment their own / commands. * * May need to exclude everything and include * /me. Unsure of that. */ while(conn) { if(conn->app_data != NULL) { TotrAppData *appdata = reinterpret_cast<TotrAppData*>(conn->app_data); if(appdata->window_id == msg->window_id) { connection_id = appdata->connection_id; break; } } conn = conn->next; } if(connection_id == -1) return 0; account_name = accountNameLookup(conn->protocol, connection_id); if(!account_name) return 0; /* Cleanse our text string of the <cursor/> tag Trillian puts in */ message = _strdup(reinterpret_cast<char*>(msg->data)); stripCursorTag(message,reinterpret_cast<char*>(msg->data)); #if 0 char *search = strstr((char *) msg->data, "<cursor/>"); if (search) { char *c = NULL, *s = NULL; size_t bufsize=strlen((char *)msg->data)-strlen("<cursor/>")+1; c = message = (char *)malloc(bufsize); ZeroMemory(c,bufsize); ZeroMemory(message,bufsize); strncpy(message, (char *)msg->data, search-((char *) msg->data)); c = c + (search - (char *) msg->data); s = search + strlen("<cursor/>"); strncpy(c, s, strlen(search)-strlen("<cursor/>")+1); } else message = _strdup(reinterpret_cast<char*>(msg->data)); #endif res = otrl_message_sending(userstate, &totr_ops, msg, account_name, conn->protocol, conn->username, message, NULL, &newmessage, totrNewContext, eopts); if(res && !newmessage) newmessage = ""; if(newmessage) { if(totr_config.GetSaveHistory()) if(!totr_config.appendHistory(message,conn->protocol,account_name,conn->username)) MessageBox(NULL,"Could not save history","ERROR",MB_OK); // Added by Thisita 10/22/11 message_t msg2; message_options_t mopts; edit_event_t eet; int psres = -1; trillianInitialize(msg2); trillianInitialize(eet); memset(&mopts, -1, sizeof(mopts)); mopts.struct_size = sizeof(mopts); mopts.disable_message = mopts.logging_name = mopts.echo_name = NULL; mopts.nicklist = NULL; reinterpret_cast<TotrAppData*>(conn->app_data)->last_msg = _strdup(reinterpret_cast<char*>(msg->data)); reinterpret_cast<TotrAppData*>(conn->app_data)->last_msg_len = strlen(reinterpret_cast<char*>(msg->data)) + 1; eet.window_id = msg->window_id; eet.event = "edit_setText"; if(strlen(newmessage) != 0) { msg2.connection_id = connection_id; msg2.window_id = msg->window_id; msg2.name = conn->username; msg2.medium = conn->protocol; msg2.text = ""; //msg2.text = _strdup(newmessage); msg2.text_len = static_cast<int>(strlen(newmessage) + 1); // Change proposed by Thisita 10/20/11 msg2.type = "outgoing_privateMessage"; msg2.extra_information = &mopts; msg2.extra_information_size = mopts.struct_size; eet.data = newmessage; OutputDebugString("sent "); OutputDebugString(newmessage); if(otrl_proto_message_type(newmessage) != OTRL_MSGTYPE_TAGGEDPLAINTEXT) { messageWindowEchostate(&msg2, 1); psres = plugin_send(MYGUID, "editEventSend", &eet); msg2.type="outgoing_privateMessage"; msg2.text = message; //<HTML><BODY BGCOLOR=\"#ffffff\">greets</BODY></HTML>"; plugin_send(MYGUID, "messageReceive", &msg2); } } } otrl_message_free(newmessage); free(account_name); account_name = NULL; return 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(); }