/**
 * 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;	
}
Example #2
0
char* pass_otr_in_msg(char* account, char* protocol, char* msg)  {
  char *new_message = NULL;
  OtrlTLV *tlvs = NULL;
  uint32_t ignore = 0;

  pthread_mutex_lock(&log_mutex);
  fprintf(logfd, "Passing incoming msg to OTR from account %s protocol %s payload %s\n", account, protocol, msg);
  fflush(logfd);
  pthread_mutex_unlock(&log_mutex);

  #if defined OTR40
  ignore = otrl_message_receiving(us, &ops, NULL,
    our_account, protocol, account, msg,
    &new_message, &tlvs, NULL, NULL, NULL);
  #endif


  #if defined OTR30 || defined OTR31 || defined OTR32
  ignore = otrl_message_receiving(us, &ops, NULL,
    our_account, protocol, account, msg,
    &new_message, &tlvs, NULL, NULL);
  #endif

  if (new_message) {
    char *ourm = malloc(strlen(new_message) + 1);
    if (ourm) {
      strcpy(ourm, new_message);
    }

    otrl_message_free(new_message);
    new_message = ourm;
    
    pthread_mutex_lock(&log_mutex);
    fprintf(logfd, "New message from OTR message_receiving %s\n", new_message);
    fflush(logfd);
    pthread_mutex_unlock(&log_mutex);
  }

  if (ignore) {
    free(new_message);
    new_message = NULL;
  }

  return new_message;
}
Example #3
0
File: tests.c Project: Ri0n/libotr
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);
}
Example #4
0
int
otrlib_decrypt_message(OtrlUserState user_state, OtrlMessageAppOps *ops, char *jid, const char *const from,
    const char *const message, char **decrypted, OtrlTLV **tlvs)
{
    return otrl_message_receiving(
        user_state,
        ops,
        NULL,
        jid,
        "xmpp",
        from,
        message,
        decrypted,
        tlvs,
        NULL,
        NULL);
}
Example #5
0
/* PROTO */
void
getmessage(void *c, const char *who, const int automessage, const char *message)
{
	const char	*msgin = message;
	char           *msg = NULL, *tempmsg = NULL;

	char           *sname;
	struct Waiting *wtemp, *wptr = NULL;
	int             offset, foundWaiting = 0;

	int otr_message = 0;
	if (conn->otr) {
		struct BuddyList	*buddy = NULL;
		buddy = find_buddy(who);

		if (buddy) {
			if (buddy->otr != -1) {
				char *newmsg;
				int ret = otrl_message_receiving(userstate, &ui_ops, NULL, conn->username,
								otr_proto, buddy->sn, msgin, &newmsg, NULL,
								&buddy->otr_context, NULL, NULL);
				if (ret) {
#ifdef DEBUG
					b_echostr_s();
					printf("[OTR] debug: internal msg %s\n", msgin);
#endif
					return;
				} else {
					if (newmsg) {
						msgin = strdup(newmsg);
						otrl_message_free(newmsg);
	                                        if (buddy->otr_context->msgstate == OTRL_MSGSTATE_ENCRYPTED)
							otr_message = 1;
					}
				}
			}
		}
	}

	tempmsg = strip_html(msgin);

	
	if (tempmsg == NULL)
		return;
	if (strlen(tempmsg) == 0) {
		free(tempmsg);
		return;
	}
	if (conn->netspeak_filter) {
		msg = undo_netspeak(tempmsg);
		free(tempmsg);
	} else {
		msg = tempmsg;
	}

	if (msg == NULL)
		return;

	if (strlen(msg) == 0) {
		free(msg);
		return;
	}
	if (conn->istyping == 0) {
		if (conn->lastsn != NULL)
			free(conn->lastsn);
		conn->lastsn = simplify_sn(who);
	}
	sname = simplify_sn(who);

	if (waiting == NULL) {
		waiting = malloc(sizeof(struct Waiting));
		wptr = waiting;
	} else {
		for (wtemp = waiting; wtemp != NULL; wtemp = wtemp->next)
			if (imcomm_compare_nicks(c, wtemp->sn, who)) {
				foundWaiting = 1;
				wptr = wtemp;
				break;
			}
		if (!foundWaiting) {
			for (wtemp = waiting; wtemp->next != NULL;
			     wtemp = wtemp->next);
			wtemp->next = malloc(sizeof(struct Waiting));
			wptr = wtemp->next;
		}
	}

	if (!foundWaiting) {
		wptr->sn = strdup(who);
		wptr->next = NULL;

		if (conn->isaway && !automessage) {
			if ((conn->respond_idle_only && conn->isidle)
			    || (!conn->respond_idle_only)) {
				imcomm_im_send_message(c, who, conn->awaymsg, 1);
				eraseline();
				b_echostr_s();

				if (conn->timestamps) {
					addts();
					putchar(' ');
				}
				printf("Sent auto-response to %s.\n", who);
				show_prompt();
			}
		}
	}
#ifdef MESSAGE_QUEUE
	if (conn->isaway)
		wptr->mqueue = addToMQueue(wptr->mqueue, msg, who);
#endif				/* MESSAGE_QUEUE */


	eraseline();

	if (conn->bell_on_incoming)
		putchar('\a');

	if (conn->timestamps) {
		addts();
		putchar(' ');
		offset = 11;
	} else {
		offset = 0;
	}

	offset += strlen(who) + 2;
	if (automessage) {
		set_color(COLOR_AUTORESPONSE);
		printf("*AUTO RESPONSE* ");
		set_color(0);
		offset += 16;
	}
	set_color(COLOR_INCOMING_IM);
	if (!otr_message)
		printf("%s", who);
	else {
		offset += 5;
		printf("(otr)%s", who);
	}
	set_color(0);
	printf(": ");
	wordwrap_print(msg, offset);
	if (automessage)
		log_event(EVENT_IM_AUTORESPONSE, sname, msg);
	else
		log_event(EVENT_IM, sname, msg);

	free(msg);
	free(sname);
	show_prompt();
}
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;
}
Example #7
0
/*
 * 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;
}
Example #8
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();
}
Example #9
0
int main(){
	OTRL_INIT;
	OtrlUserState userstate;
	char *newmessage = NULL;
	char *nlmsg=NULL;
	OtrlMessageAppOps ui_ops;
	int sockfd, clientfd, recvbytes, recv_ret;
	socklen_t sin_size;
	char buf[1024], pwdbuf[1024];
	char *dbuf;
	struct sockaddr_in remote_addr, my_addr;
	fd_set fds;
	int one = 1;
	
	/* initialize ui callbacks */
	memset(&ui_ops, 0, sizeof(OtrlMessageAppOps));
	ui_ops.inject_message= inject_msg;
	ui_ops.gone_secure=gone_secure;
	printf("\033[31mStarting driver...\033[0m\n");

	/* initialize socket connection */
	sockfd = socket(AF_INET, SOCK_STREAM, 0);
	my_addr.sin_family=AF_INET;
	my_addr.sin_port= htons(3333);
	my_addr.sin_addr.s_addr = INADDR_ANY;
	bzero(&(my_addr.sin_zero),8);

	/* Allow rebinding to address */
	setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));

	if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) {
		perror("bind");
		exit(1);
	}
	if (listen(sockfd, 1) == -1) {
		perror("listen");
		exit(1);
	}
	sin_size = sizeof(struct sockaddr_in);
	if ((clientfd = accept(sockfd, (struct sockaddr *)&remote_addr, \
					&sin_size)) == -1) {
		perror("accept");
	}
	printf("\033[31mConnected to Bob\033[0m\n");

	/* create userstate, and read the private key */
	userstate = otrl_userstate_create();
	getcwd(pwdbuf, 1024);
	strcat(pwdbuf, "/private_key");
	otrl_privkey_read(userstate, pwdbuf);


	/* Clients send messages asynchronously*/
	while(1){
		FD_ZERO(&fds);
		FD_SET(0, &fds);
		FD_SET(clientfd, &fds);
		select(clientfd+1, &fds, NULL, NULL, NULL);
		if(FD_ISSET(0, &fds)){
			/* send message */
			fgets(buf, 1023, stdin);
			buf[strlen(buf)-1]= '\0';
			printf("\033[31mTo OTR:%d:\033[0m%s\n\033[0m",strlen(buf), buf);
			dbuf = strdup(buf);
			otrl_message_sending(userstate, &ui_ops, NULL, "*****@*****.**",
					"msn", "*****@*****.**", &dbuf, NULL, &newmessage,
					OTRL_FRAGMENT_SEND_SKIP, NULL, NULL, NULL, NULL);
			free(dbuf);
			nlmsg = (char*)malloc(strlen(newmessage)+2);			
			memcpy(nlmsg, newmessage, strlen(newmessage));
			nlmsg[strlen(newmessage)]='\n';
			nlmsg[strlen(newmessage)+1]='\0';
			send(clientfd, nlmsg, strlen(nlmsg), 0);
			printf("\033[31mTo network:%d:\033[35m%s\033[0m\n\033[0m", strlen(newmessage), newmessage);
		}else{
			/*receive message */
			recvbytes=recv(clientfd, buf, MAXDATASIZE, 0);
			if(recvbytes==0) break;
			recvbytes--;
			buf[recvbytes] = '\0';
			if(buf[recvbytes-1]=='\r'){
				 recvbytes--;
				 buf[recvbytes]='\0';
			}
			printf("\033[31mFrom network:%d:\033[35m %s\033[0m\n",recvbytes, buf);
			recv_ret=otrl_message_receiving(userstate, &ui_ops, &clientfd, "*****@*****.**",
					"msn", "*****@*****.**", buf, &newmessage, NULL,
					NULL, NULL, NULL, NULL);
			if(recv_ret==0)
				printf("\033[31mFrom OTR:%d:\033[0m %s\n", newmessage ? strlen(newmessage) : 0, newmessage);
		}
	}
	return 0;
}