Changes in otr.c [0e788f5:51f937e]
Legend:
- Unmodified
- Added
- Removed
-
otr.c
r0e788f5 r51f937e 8 8 OTR support (cf. http://www.cypherpunks.ca/otr/) 9 9 10 (c) 2008-2011 Sven Moritz Hallberg <pesco@khjk.org>11 (c) 2008funded by stonedcoder.org10 (c) 2008-2011,2013 Sven Moritz Hallberg <pesco@khjk.org> 11 funded by stonedcoder.org 12 12 13 13 files used to store OTR data: 14 14 <configdir>/<nick>.otr_keys 15 15 <configdir>/<nick>.otr_fprints 16 <configdir>/<nick>.otr_instags <- don't copy this one between hosts 16 17 17 18 top-level todos: (search for TODO for more ;-)) … … 19 20 per-account policy settings 20 21 per-user policy settings 22 add a way to select recipient instance 21 23 */ 22 24 … … 60 62 const char *recipient, const char *message); 61 63 62 int op_display_otr_message(void *opdata, const char *accountname, const char *protocol,63 const char *username, const char *msg);64 65 64 void op_new_fingerprint(void *opdata, OtrlUserState us, const char *accountname, 66 65 const char *protocol, const char *username, unsigned char fingerprint[20]); … … 80 79 const char *op_account_name(void *opdata, const char *account, const char *protocol); 81 80 81 void op_create_instag(void *opdata, const char *account, const char *protocol); 82 83 void op_convert_msg(void *opdata, ConnContext *ctx, OtrlConvertType typ, 84 char **dst, const char *src); 85 void op_convert_free(void *opdata, ConnContext *ctx, char *msg); 86 87 void op_handle_smp_event(void *opdata, OtrlSMPEvent ev, ConnContext *ctx, 88 unsigned short percent, char *question); 89 90 void op_handle_msg_event(void *opdata, OtrlMessageEvent ev, ConnContext *ctx, 91 const char *message, gcry_error_t err); 92 93 const char *op_otr_error_message(void *opdata, ConnContext *ctx, 94 OtrlErrorCode err_code); 82 95 83 96 /** otr sub-command handlers: **/ … … 141 154 void yes_forget_key(void *data); 142 155 156 /* timeout handler that calls otrl_message_poll */ 157 gboolean ev_message_poll(gpointer data, gint fd, b_input_condition cond); 158 143 159 /* helper to make sure accountname and protocol match the incoming "opdata" */ 144 160 struct im_connection *check_imc(void *opdata, const char *accountname, … … 156 172 irc_user_t *peeruser(irc_t *irc, const char *handle, const char *protocol); 157 173 158 /* handle SMP TLVs from a received message */ 159 void otr_handle_smp(struct im_connection *ic, const char *handle, OtrlTLV *tlvs); 174 /* show an otr-related message to the user */ 175 void display_otr_message(void *opdata, ConnContext *ctx, const char *fmt, ...); 176 177 /* write an otr-related message to the system log */ 178 void log_otr_message(void *opdata, const char *fmt, ...); 160 179 161 180 /* combined handler for the 'otr smp' and 'otr smpq' commands */ … … 208 227 otr_ops.is_logged_in = &op_is_logged_in; 209 228 otr_ops.inject_message = &op_inject_message; 210 otr_ops.notify = NULL;211 otr_ops.display_otr_message = &op_display_otr_message;212 229 otr_ops.update_context_list = NULL; 213 otr_ops.protocol_name = NULL;214 otr_ops.protocol_name_free = NULL;215 230 otr_ops.new_fingerprint = &op_new_fingerprint; 216 231 otr_ops.write_fingerprints = &op_write_fingerprints; … … 218 233 otr_ops.gone_insecure = &op_gone_insecure; 219 234 otr_ops.still_secure = &op_still_secure; 220 otr_ops.log_message = &op_log_message;221 235 otr_ops.max_message_size = &op_max_message_size; 222 236 otr_ops.account_name = &op_account_name; 223 237 otr_ops.account_name_free = NULL; 224 238 239 /* stuff added with libotr 4.0.0 */ 240 otr_ops.received_symkey = NULL; /* we don't use the extra key */ 241 otr_ops.otr_error_message = &op_otr_error_message; 242 otr_ops.otr_error_message_free = NULL; 243 otr_ops.resent_msg_prefix = NULL; /* default: [resent] */ 244 otr_ops.resent_msg_prefix_free = NULL; 245 otr_ops.handle_smp_event = &op_handle_smp_event; 246 otr_ops.handle_msg_event = &op_handle_msg_event; 247 otr_ops.create_instag = &op_create_instag; 248 otr_ops.convert_msg = &op_convert_msg; 249 otr_ops.convert_free = &op_convert_free; 250 otr_ops.timer_control = NULL; /* we just poll */ 251 225 252 root_command_add( "otr", 1, cmd_otr, 0 ); 226 253 register_irc_plugin( &otr_plugin ); … … 246 273 s = set_add( &irc->b->set, "otr_does_html", "true", set_eval_bool, irc ); 247 274 275 /* regularly call otrl_message_poll */ 276 gint definterval = otrl_message_poll_get_default_interval(irc->otr->us); 277 irc->otr->timer = b_timeout_add(definterval, ev_message_poll, irc->otr); 278 248 279 return TRUE; 249 280 } … … 252 283 { 253 284 otr_t *otr = irc->otr; 285 b_event_remove(otr->timer); 254 286 otrl_userstate_free(otr->us); 255 287 if(otr->keygen) { … … 286 318 g_snprintf(s, 511, "%s%s.otr_fprints", global.conf->configdir, irc->user->nick); 287 319 e = otrl_privkey_read_fingerprints(irc->otr->us, s, NULL, NULL); 320 if(e && e!=enoent) { 321 irc_rootmsg(irc, "otr load: %s: %s", s, gcry_strerror(e)); 322 } 323 g_snprintf(s, 511, "%s%s.otr_instags", global.conf->configdir, irc->user->nick); 324 e = otrl_instag_read(irc->otr->us, s); 288 325 if(e && e!=enoent) { 289 326 irc_rootmsg(irc, "otr load: %s: %s", s, gcry_strerror(e)); … … 386 423 ignore_msg = otrl_message_receiving(irc->otr->us, &otr_ops, ic, 387 424 ic->acc->user, ic->acc->prpl->name, iu->bu->handle, msg, &newmsg, 388 &tlvs, NULL, NULL); 389 390 otr_handle_smp(ic, iu->bu->handle, tlvs); 391 425 &tlvs, NULL, NULL, NULL); 426 392 427 if(ignore_msg) { 393 428 /* this was an internal OTR protocol message */ … … 397 432 return msg; 398 433 } else { 399 /* OTR has processed this message */400 ConnContext *context = otrl_context_find(irc->otr->us, iu->bu->handle,401 ic->acc->user, ic->acc->prpl->name, 0, NULL, NULL, NULL);402 403 434 /* we're done with the original msg, which will be caller-freed. */ 404 /* NB: must not change the newmsg pointer, since we free it. */ 405 msg = newmsg; 406 407 if(context && context->msgstate == OTRL_MSGSTATE_ENCRYPTED) { 408 /* HTML decoding */ 409 /* perform any necessary stripping that the top level would miss */ 410 if(set_getbool(&ic->bee->set, "otr_does_html") && 411 !(ic->flags & OPT_DOES_HTML) && 412 set_getbool(&ic->bee->set, "strip_html")) { 413 strip_html(msg); 414 } 415 416 /* coloring */ 417 if(set_getbool(&ic->bee->set, "otr_color_encrypted")) { 418 int color; /* color according to f'print trust */ 419 char *pre="", *sep=""; /* optional parts */ 420 const char *trust = context->active_fingerprint->trust; 421 422 if(trust && trust[0] != '\0') 423 color=3; /* green */ 424 else 425 color=5; /* red */ 426 427 /* in a query window, keep "/me " uncolored at the beginning */ 428 if(g_strncasecmp(msg, "/me ", 4) == 0 429 && irc_user_msgdest(iu) == irc->user->nick) { 430 msg += 4; /* skip */ 431 pre = "/me "; 432 } 433 434 /* comma in first place could mess with the color code */ 435 if(msg[0] == ',') { 436 /* insert a space between color spec and message */ 437 sep = " "; 438 } 439 440 msg = g_strdup_printf("%s\x03%.2d%s%s\x0F", pre, 441 color, sep, msg); 442 } 443 } 444 445 if(msg == newmsg) { 446 msg = g_strdup(newmsg); 447 } 448 otrl_message_free(newmsg); 449 return msg; 435 return newmsg; 450 436 } 451 437 } … … 459 445 irc_t *irc = iu->irc; 460 446 struct im_connection *ic = iu->bu->ic; 447 otrl_instag_t instag = OTRL_INSTAG_RECENT; // XXX? 461 448 462 449 /* don't do OTR on certain (not classic IM) protocols, e.g. twitter */ … … 465 452 } 466 453 467 ctx = otrl_context_find(irc->otr->us,468 iu->bu->handle, ic->acc->user, ic->acc->prpl->name,469 1, NULL, NULL, NULL);470 471 /* HTML encoding */472 /* consider OTR plaintext to be HTML if otr_does_html is set */473 if(ctx && ctx->msgstate == OTRL_MSGSTATE_ENCRYPTED &&474 set_getbool(&ic->bee->set, "otr_does_html") &&475 (g_strncasecmp(msg, "<html>", 6) != 0)) {476 emsg = escape_html(msg);477 }478 479 454 st = otrl_message_sending(irc->otr->us, &otr_ops, ic, 480 ic->acc->user, ic->acc->prpl->name, iu->bu->handle, 481 emsg, NULL, &otrmsg, NULL, NULL); 455 ic->acc->user, ic->acc->prpl->name, iu->bu->handle, instag, 456 emsg, NULL, &otrmsg, OTRL_FRAGMENT_SEND_ALL, &ctx, NULL, NULL); 457 /* in libotr 4.0.0 with OTRL_FRAGMENT_SEND_ALL, otrmsg must be passed 458 * but the value it gets carries no meaning. it can be set even though 459 * the message has been injected. */ 460 482 461 if(emsg != msg) { 483 462 g_free(emsg); /* we're done with this one */ 484 463 } 485 464 if(st) { 486 return NULL; 487 } 488 489 if(otrmsg) { 490 if(!ctx) { 491 otrl_message_free(otrmsg); 492 return NULL; 493 } 494 st = otrl_message_fragment_and_send(&otr_ops, ic, ctx, 495 otrmsg, OTRL_FRAGMENT_SEND_ALL, NULL); 496 otrl_message_free(otrmsg); 497 } else { 498 /* note: otrl_message_sending handles policy, so that if REQUIRE_ENCRYPTION is set, 499 this case does not occur */ 500 return msg; 501 } 502 503 /* TODO: Error reporting should be done here now (if st!=0), probably. */ 465 /* TODO: Error reporting? */ 466 } 504 467 505 468 return NULL; … … 620 583 } 621 584 622 int op_display_otr_message(void *opdata, const char *accountname,623 const char *protocol, const char *username, const char *message)624 {625 struct im_connection *ic = check_imc(opdata, accountname, protocol);626 char *msg = g_strdup(message);627 irc_t *irc = ic->bee->ui_data;628 irc_user_t *u = peeruser(irc, username, protocol);629 630 strip_html(msg);631 if(u) {632 /* display as a notice from this particular user */633 irc_usernotice(u, "%s", msg);634 } else {635 irc_rootmsg(irc, "[otr] %s", msg);636 }637 638 g_free(msg);639 return 0;640 }641 642 585 void op_new_fingerprint(void *opdata, OtrlUserState us, 643 586 const char *accountname, const char *protocol, … … 691 634 void op_gone_insecure(void *opdata, ConnContext *context) 692 635 { 636 /* XXX on 'otr disconnect', this gets called for every instance and we 637 * get the message multiple times... */ 638 693 639 struct im_connection *ic = 694 640 check_imc(opdata, context->accountname, context->protocol); … … 730 676 } 731 677 732 void op_log_message(void *opdata, const char *message)733 {734 char *msg = g_strdup(message);735 736 strip_html(msg);737 log_message(LOGLVL_INFO, "otr: %s", msg);738 g_free(msg);739 }740 741 678 int op_max_message_size(void *opdata, ConnContext *context) 742 679 { 743 680 struct im_connection *ic = 744 681 check_imc(opdata, context->accountname, context->protocol); 745 682 746 683 return ic->acc->prpl->mms; 747 684 } … … 754 691 return peernick(irc, account, protocol); 755 692 } 693 694 void op_create_instag(void *opdata, const char *account, const char *protocol) 695 { 696 struct im_connection *ic = 697 check_imc(opdata, account, protocol); 698 irc_t *irc = ic->bee->ui_data; 699 gcry_error_t e; 700 char s[512]; 701 702 g_snprintf(s, 511, "%s%s.otr_instags", global.conf->configdir, 703 irc->user->nick); 704 e = otrl_instag_generate(irc->otr->us, s, account, protocol); 705 if(e) { 706 irc_rootmsg(irc, "otr: %s/%s: otrl_instag_generate failed: %s", 707 account, protocol, gcry_strerror(e)); 708 } 709 } 710 711 void op_convert_msg(void *opdata, ConnContext *ctx, OtrlConvertType typ, 712 char **dst, const char *src) 713 { 714 struct im_connection *ic = 715 check_imc(opdata, ctx->accountname, ctx->protocol); 716 irc_t *irc = ic->bee->ui_data; 717 irc_user_t *iu = peeruser(irc, ctx->username, ctx->protocol); 718 719 if(typ == OTRL_CONVERT_RECEIVING) { 720 char *msg = g_strdup(src); 721 722 /* HTML decoding */ 723 if(set_getbool(&ic->bee->set, "otr_does_html") && 724 !(ic->flags & OPT_DOES_HTML) && 725 set_getbool(&ic->bee->set, "strip_html")) { 726 strip_html(msg); 727 *dst = msg; 728 } 729 730 /* coloring */ 731 if(set_getbool(&ic->bee->set, "otr_color_encrypted")) { 732 int color; /* color according to f'print trust */ 733 char *pre="", *sep=""; /* optional parts */ 734 const char *trust = ctx->active_fingerprint->trust; 735 736 if(trust && trust[0] != '\0') 737 color=3; /* green */ 738 else 739 color=5; /* red */ 740 741 /* in a query window, keep "/me " uncolored at the beginning */ 742 if(g_strncasecmp(msg, "/me ", 4) == 0 743 && irc_user_msgdest(iu) == irc->user->nick) { 744 msg += 4; /* skip */ 745 pre = "/me "; 746 } 747 748 /* comma in first place could mess with the color code */ 749 if(msg[0] == ',') { 750 /* insert a space between color spec and message */ 751 sep = " "; 752 } 753 754 *dst = g_strdup_printf("%s\x03%.2d%s%s\x0F", pre, 755 color, sep, msg); 756 g_free(msg); 757 } 758 } else { 759 /* HTML encoding */ 760 /* consider OTR plaintext to be HTML if otr_does_html is set */ 761 if(ctx && ctx->msgstate == OTRL_MSGSTATE_ENCRYPTED && 762 set_getbool(&ic->bee->set, "otr_does_html") && 763 (g_strncasecmp(src, "<html>", 6) != 0)) { 764 *dst = escape_html(src); 765 } 766 } 767 } 768 769 void op_convert_free(void *opdata, ConnContext *ctx, char *msg) 770 { 771 g_free(msg); 772 } 773 774 /* Socialist Millionaires' Protocol */ 775 void op_handle_smp_event(void *opdata, OtrlSMPEvent ev, ConnContext *ctx, 776 unsigned short percent, char *question) 777 { 778 struct im_connection *ic = 779 check_imc(opdata, ctx->accountname, ctx->protocol); 780 irc_t *irc = ic->bee->ui_data; 781 OtrlUserState us = irc->otr->us; 782 irc_user_t *u = peeruser(irc, ctx->username, ctx->protocol); 783 784 if(!u) return; 785 786 switch(ev) { 787 case OTRL_SMPEVENT_ASK_FOR_SECRET: 788 irc_rootmsg(irc, "smp: initiated by %s" 789 " - respond with \x02otr smp %s <secret>\x02", 790 u->nick, u->nick); 791 break; 792 case OTRL_SMPEVENT_ASK_FOR_ANSWER: 793 irc_rootmsg(irc, "smp: initiated by %s with question: \x02\"%s\"\x02", u->nick, 794 question); 795 irc_rootmsg(irc, "smp: respond with \x02otr smp %s <answer>\x02", 796 u->nick); 797 break; 798 case OTRL_SMPEVENT_CHEATED: 799 irc_rootmsg(irc, "smp %s: opponent violated protocol, aborting", 800 u->nick); 801 otrl_message_abort_smp(us, &otr_ops, u->bu->ic, ctx); 802 otrl_sm_state_free(ctx->smstate); 803 break; 804 case OTRL_SMPEVENT_NONE: 805 break; 806 case OTRL_SMPEVENT_IN_PROGRESS: 807 break; 808 case OTRL_SMPEVENT_SUCCESS: 809 if(ctx->smstate->received_question) { 810 irc_rootmsg(irc, "smp %s: correct answer, you are trusted", 811 u->nick); 812 } else { 813 irc_rootmsg(irc, "smp %s: secrets proved equal, fingerprint trusted", 814 u->nick); 815 } 816 otrl_sm_state_free(ctx->smstate); 817 break; 818 case OTRL_SMPEVENT_FAILURE: 819 if(ctx->smstate->received_question) { 820 irc_rootmsg(irc, "smp %s: wrong answer, you are not trusted", 821 u->nick); 822 } else { 823 irc_rootmsg(irc, "smp %s: secrets did not match, fingerprint not trusted", 824 u->nick); 825 } 826 otrl_sm_state_free(ctx->smstate); 827 break; 828 case OTRL_SMPEVENT_ABORT: 829 irc_rootmsg(irc, "smp: received abort from %s", u->nick); 830 otrl_sm_state_free(ctx->smstate); 831 break; 832 case OTRL_SMPEVENT_ERROR: 833 irc_rootmsg(irc, "smp %s: protocol error, aborting", 834 u->nick); 835 otrl_message_abort_smp(us, &otr_ops, u->bu->ic, ctx); 836 otrl_sm_state_free(ctx->smstate); 837 break; 838 } 839 } 840 841 void op_handle_msg_event(void *opdata, OtrlMessageEvent ev, ConnContext *ctx, 842 const char *message, gcry_error_t err) 843 { 844 switch(ev) { 845 case OTRL_MSGEVENT_ENCRYPTION_REQUIRED: 846 display_otr_message(opdata, ctx, 847 "policy requires encryption - message not sent"); 848 break; 849 case OTRL_MSGEVENT_ENCRYPTION_ERROR: 850 display_otr_message(opdata, ctx, 851 "error during encryption - message not sent"); 852 break; 853 case OTRL_MSGEVENT_CONNECTION_ENDED: 854 display_otr_message(opdata, ctx, 855 "other end has disconnected OTR - " 856 "close connection or reconnect!"); 857 break; 858 case OTRL_MSGEVENT_SETUP_ERROR: 859 display_otr_message(opdata, ctx, 860 "OTR connection failed: %s", gcry_strerror(err)); 861 break; 862 case OTRL_MSGEVENT_MSG_REFLECTED: 863 display_otr_message(opdata, ctx, 864 "received our own OTR message (!?)"); 865 break; 866 case OTRL_MSGEVENT_MSG_RESENT: 867 display_otr_message(opdata, ctx, 868 "the previous message was resent"); 869 break; 870 case OTRL_MSGEVENT_RCVDMSG_NOT_IN_PRIVATE: 871 display_otr_message(opdata, ctx, 872 "unexpected encrypted message received"); 873 break; 874 case OTRL_MSGEVENT_RCVDMSG_UNREADABLE: 875 display_otr_message(opdata, ctx, 876 "unreadable encrypted message received"); 877 break; 878 case OTRL_MSGEVENT_RCVDMSG_MALFORMED: 879 display_otr_message(opdata, ctx, 880 "malformed OTR message received"); 881 break; 882 case OTRL_MSGEVENT_LOG_HEARTBEAT_RCVD: 883 if(global.conf->verbose) { 884 log_otr_message(opdata, "%s/%s: heartbeat received", 885 ctx->accountname, ctx->protocol); 886 } 887 break; 888 case OTRL_MSGEVENT_LOG_HEARTBEAT_SENT: 889 if(global.conf->verbose) { 890 log_otr_message(opdata, "%s/%s: heartbeat sent", 891 ctx->accountname, ctx->protocol); 892 } 893 break; 894 case OTRL_MSGEVENT_RCVDMSG_GENERAL_ERR: 895 display_otr_message(opdata, ctx, 896 "OTR error message received: %s", message); 897 break; 898 case OTRL_MSGEVENT_RCVDMSG_UNENCRYPTED: 899 display_otr_message(opdata, ctx, 900 "unencrypted message received: %s", message); 901 break; 902 case OTRL_MSGEVENT_RCVDMSG_UNRECOGNIZED: 903 display_otr_message(opdata, ctx, 904 "unrecognized OTR message received"); 905 break; 906 case OTRL_MSGEVENT_RCVDMSG_FOR_OTHER_INSTANCE: 907 display_otr_message(opdata, ctx, 908 "OTR message for a different instance received"); 909 break; 910 default: 911 /* shouldn't happen */ 912 break; 913 } 914 } 915 916 const char *op_otr_error_message(void *opdata, ConnContext *ctx, 917 OtrlErrorCode err_code) 918 { 919 switch(err_code) { 920 case OTRL_ERRCODE_ENCRYPTION_ERROR: 921 return "i failed to encrypt a message"; 922 case OTRL_ERRCODE_MSG_NOT_IN_PRIVATE: 923 return "you sent an encrypted message i didn't expect"; 924 case OTRL_ERRCODE_MSG_UNREADABLE: 925 return "could not read encrypted message"; 926 case OTRL_ERRCODE_MSG_MALFORMED: 927 return "you sent a malformed OTR message"; 928 default: 929 return "i suffered an unexpected OTR error"; 930 } 931 } 932 756 933 757 934 … … 774 951 } 775 952 776 otrl_message_disconnect(irc->otr->us, &otr_ops, 953 /* XXX we disconnect all instances; is that what we want? */ 954 otrl_message_disconnect_all_instances(irc->otr->us, &otr_ops, 777 955 u->bu->ic, u->bu->ic->acc->user, u->bu->ic->acc->prpl->name, u->bu->handle); 778 956 779 /* for some reason, libotr (3.1.0) doesn't do this itself: */ 780 if(u->flags & IRC_USER_OTR_ENCRYPTED) { 781 ConnContext *ctx; 782 ctx = otrl_context_find(irc->otr->us, u->bu->handle, u->bu->ic->acc->user, 783 u->bu->ic->acc->prpl->name, 0, NULL, NULL, NULL); 784 if(ctx) 785 op_gone_insecure(u->bu->ic, ctx); 786 else /* huh? */ 787 u->flags &= ( IRC_USER_OTR_ENCRYPTED | IRC_USER_OTR_TRUSTED ); 788 } 957 /* for some reason, libotr (4.0.0) doesn't do this itself: */ 958 if(!(u->flags & IRC_USER_OTR_ENCRYPTED)) 959 return; 960 961 ConnContext *ctx, *p; 962 ctx = otrl_context_find(irc->otr->us, u->bu->handle, u->bu->ic->acc->user, 963 u->bu->ic->acc->prpl->name, OTRL_INSTAG_MASTER, 0, NULL, NULL, NULL); 964 if(!ctx) { /* huh? */ 965 u->flags &= ( IRC_USER_OTR_ENCRYPTED | IRC_USER_OTR_TRUSTED ); 966 return; 967 } 968 969 for(p=ctx; p && p->m_context == ctx->m_context; p=p->next) 970 op_gone_insecure(u->bu->ic, p); 789 971 } 790 972 … … 803 985 } 804 986 805 bee_user_msg(irc->b, u->bu, "?OTR?v2?", 0); 987 /* passing this through the filter so it goes through libotr which 988 * will replace the simple query string with a proper one */ 989 otr_filter_msg_out(u, "?OTR?", 0); 806 990 } 807 991 … … 831 1015 832 1016 ctx = otrl_context_find(irc->otr->us, u->bu->handle, 833 u->bu->ic->acc->user, u->bu->ic->acc->prpl->name, 0, NULL, NULL, NULL);1017 u->bu->ic->acc->user, u->bu->ic->acc->prpl->name, OTRL_INSTAG_MASTER, 0, NULL, NULL, NULL); 834 1018 if(!ctx) { 835 1019 irc_rootmsg(irc, "%s: no otr context with user", args[1]); … … 895 1079 *(myhandle++) = '\0'; 896 1080 handle = arg; 897 ctx = otrl_context_find(irc->otr->us, handle, myhandle, protocol, 0, NULL, NULL, NULL);1081 ctx = otrl_context_find(irc->otr->us, handle, myhandle, protocol, OTRL_INSTAG_MASTER, 0, NULL, NULL, NULL); 898 1082 if(!ctx) { 899 1083 irc_rootmsg(irc, "no such context"); … … 909 1093 } 910 1094 ctx = otrl_context_find(irc->otr->us, u->bu->handle, u->bu->ic->acc->user, 911 u->bu->ic->acc->prpl->name, 0, NULL, NULL, NULL);1095 u->bu->ic->acc->prpl->name, OTRL_INSTAG_MASTER, 0, NULL, NULL, NULL); 912 1096 if(!ctx) { 913 1097 irc_rootmsg(irc, "no otr context with %s", args[1]); … … 982 1166 983 1167 g_free(p); 1168 1169 // XXX forget all contexts 984 1170 985 1171 if(ctx->msgstate == OTRL_MSGSTATE_ENCRYPTED) { … … 1028 1214 1029 1215 ctx = otrl_context_find(irc->otr->us, u->bu->handle, u->bu->ic->acc->user, 1030 u->bu->ic->acc->prpl->name, 0, NULL, NULL, NULL);1216 u->bu->ic->acc->prpl->name, OTRL_INSTAG_MASTER, 0, NULL, NULL, NULL); 1031 1217 if(!ctx) { 1032 1218 irc_rootmsg(irc, "no otr context with %s", args[2]); … … 1071 1257 1072 1258 ctx = otrl_context_find(irc->otr->us, u->bu->handle, u->bu->ic->acc->user, 1073 u->bu->ic->acc->prpl->name, 0, NULL, NULL, NULL);1259 u->bu->ic->acc->prpl->name, OTRL_INSTAG_MASTER, 0, NULL, NULL, NULL); 1074 1260 if(!ctx) { 1075 1261 irc_rootmsg(irc, "no otr context with %s", args[2]); … … 1119 1305 /*** local helpers / subroutines: ***/ 1120 1306 1121 /* Socialist Millionaires' Protocol */ 1122 void otr_handle_smp(struct im_connection *ic, const char *handle, OtrlTLV *tlvs) 1123 { 1307 void log_otr_message(void *opdata, const char *fmt, ...) 1308 { 1309 va_list va; 1310 1311 va_start(va, fmt); 1312 char *msg = g_strdup_vprintf(fmt, va); 1313 va_end(va); 1314 1315 log_message(LOGLVL_INFO, "otr: %s", msg); 1316 } 1317 1318 void display_otr_message(void *opdata, ConnContext *ctx, const char *fmt, ...) 1319 { 1320 struct im_connection *ic = 1321 check_imc(opdata, ctx->accountname, ctx->protocol); 1124 1322 irc_t *irc = ic->bee->ui_data; 1125 OtrlUserState us = irc->otr->us; 1126 OtrlMessageAppOps *ops = &otr_ops; 1127 OtrlTLV *tlv = NULL; 1128 ConnContext *context; 1129 NextExpectedSMP nextMsg; 1130 irc_user_t *u; 1131 bee_user_t *bu; 1132 1133 bu = bee_user_by_handle(ic->bee, ic, handle); 1134 if(!bu || !(u = bu->ui_data)) return; 1135 context = otrl_context_find(us, handle, 1136 ic->acc->user, ic->acc->prpl->name, 1, NULL, NULL, NULL); 1137 if(!context) { 1138 /* huh? out of memory or what? */ 1139 irc_rootmsg(irc, "smp: failed to get otr context for %s", u->nick); 1140 otrl_message_abort_smp(us, ops, u->bu->ic, context); 1141 otrl_sm_state_free(context->smstate); 1142 return; 1143 } 1144 nextMsg = context->smstate->nextExpected; 1145 1146 if (context->smstate->sm_prog_state == OTRL_SMP_PROG_CHEATED) { 1147 irc_rootmsg(irc, "smp %s: opponent violated protocol, aborting", 1148 u->nick); 1149 otrl_message_abort_smp(us, ops, u->bu->ic, context); 1150 otrl_sm_state_free(context->smstate); 1151 return; 1152 } 1153 1154 tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1Q); 1155 if (tlv) { 1156 if (nextMsg != OTRL_SMP_EXPECT1) { 1157 irc_rootmsg(irc, "smp %s: spurious SMP1Q received, aborting", u->nick); 1158 otrl_message_abort_smp(us, ops, u->bu->ic, context); 1159 otrl_sm_state_free(context->smstate); 1160 } else { 1161 char *question = g_strndup((char *)tlv->data, tlv->len); 1162 irc_rootmsg(irc, "smp: initiated by %s with question: \x02\"%s\"\x02", u->nick, 1163 question); 1164 irc_rootmsg(irc, "smp: respond with \x02otr smp %s <answer>\x02", 1165 u->nick); 1166 g_free(question); 1167 /* smp stays in EXPECT1 until user responds */ 1168 } 1169 } 1170 tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1); 1171 if (tlv) { 1172 if (nextMsg != OTRL_SMP_EXPECT1) { 1173 irc_rootmsg(irc, "smp %s: spurious SMP1 received, aborting", u->nick); 1174 otrl_message_abort_smp(us, ops, u->bu->ic, context); 1175 otrl_sm_state_free(context->smstate); 1176 } else { 1177 irc_rootmsg(irc, "smp: initiated by %s" 1178 " - respond with \x02otr smp %s <secret>\x02", 1179 u->nick, u->nick); 1180 /* smp stays in EXPECT1 until user responds */ 1181 } 1182 } 1183 tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP2); 1184 if (tlv) { 1185 if (nextMsg != OTRL_SMP_EXPECT2) { 1186 irc_rootmsg(irc, "smp %s: spurious SMP2 received, aborting", u->nick); 1187 otrl_message_abort_smp(us, ops, u->bu->ic, context); 1188 otrl_sm_state_free(context->smstate); 1189 } else { 1190 /* SMP2 received, otrl_message_receiving will have sent SMP3 */ 1191 context->smstate->nextExpected = OTRL_SMP_EXPECT4; 1192 } 1193 } 1194 tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP3); 1195 if (tlv) { 1196 if (nextMsg != OTRL_SMP_EXPECT3) { 1197 irc_rootmsg(irc, "smp %s: spurious SMP3 received, aborting", u->nick); 1198 otrl_message_abort_smp(us, ops, u->bu->ic, context); 1199 otrl_sm_state_free(context->smstate); 1200 } else { 1201 /* SMP3 received, otrl_message_receiving will have sent SMP4 */ 1202 if(context->smstate->sm_prog_state == OTRL_SMP_PROG_SUCCEEDED) { 1203 if(context->smstate->received_question) { 1204 irc_rootmsg(irc, "smp %s: correct answer, you are trusted", 1205 u->nick); 1206 } else { 1207 irc_rootmsg(irc, "smp %s: secrets proved equal, fingerprint trusted", 1208 u->nick); 1209 } 1210 } else { 1211 if(context->smstate->received_question) { 1212 irc_rootmsg(irc, "smp %s: wrong answer, you are not trusted", 1213 u->nick); 1214 } else { 1215 irc_rootmsg(irc, "smp %s: secrets did not match, fingerprint not trusted", 1216 u->nick); 1217 } 1218 } 1219 otrl_sm_state_free(context->smstate); 1220 /* smp is in back in EXPECT1 */ 1221 } 1222 } 1223 tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP4); 1224 if (tlv) { 1225 if (nextMsg != OTRL_SMP_EXPECT4) { 1226 irc_rootmsg(irc, "smp %s: spurious SMP4 received, aborting", u->nick); 1227 otrl_message_abort_smp(us, ops, u->bu->ic, context); 1228 otrl_sm_state_free(context->smstate); 1229 } else { 1230 /* SMP4 received, otrl_message_receiving will have set fp trust */ 1231 if(context->smstate->sm_prog_state == OTRL_SMP_PROG_SUCCEEDED) { 1232 irc_rootmsg(irc, "smp %s: secrets proved equal, fingerprint trusted", 1233 u->nick); 1234 } else { 1235 irc_rootmsg(irc, "smp %s: secrets did not match, fingerprint not trusted", 1236 u->nick); 1237 } 1238 otrl_sm_state_free(context->smstate); 1239 /* smp is in back in EXPECT1 */ 1240 } 1241 } 1242 tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP_ABORT); 1243 if (tlv) { 1244 irc_rootmsg(irc, "smp: received abort from %s", u->nick); 1245 otrl_sm_state_free(context->smstate); 1246 /* smp is in back in EXPECT1 */ 1247 } 1323 irc_user_t *u = peeruser(irc, ctx->username, ctx->protocol); 1324 va_list va; 1325 1326 va_start(va, fmt); 1327 char *msg = g_strdup_vprintf(fmt, va); 1328 va_end(va); 1329 1330 if(u) { 1331 /* display as a notice from this particular user */ 1332 irc_usernotice(u, "%s", msg); 1333 } else { 1334 irc_rootmsg(irc, "[otr] %s", msg); 1335 } 1336 1337 g_free(msg); 1248 1338 } 1249 1339 … … 1254 1344 irc_user_t *u; 1255 1345 ConnContext *ctx; 1346 otrl_instag_t instag = OTRL_INSTAG_RECENT; // XXX 1256 1347 1257 1348 u = irc_user_by_name(irc, nick); … … 1266 1357 1267 1358 ctx = otrl_context_find(irc->otr->us, u->bu->handle, 1268 u->bu->ic->acc->user, u->bu->ic->acc->prpl->name, 0, NULL, NULL, NULL);1359 u->bu->ic->acc->user, u->bu->ic->acc->prpl->name, instag, 0, NULL, NULL, NULL); 1269 1360 if(!ctx || ctx->msgstate != OTRL_MSGSTATE_ENCRYPTED) { 1270 1361 irc_rootmsg(irc, "smp: otr inactive with %s, try \x02otr connect" … … 1307 1398 } 1308 1399 1400 /* timeout handler that calls otrl_message_poll */ 1401 gboolean ev_message_poll(gpointer data, gint fd, b_input_condition cond) 1402 { 1403 otr_t *otr = data; 1404 1405 if(otr && otr->us) 1406 otrl_message_poll(otr->us, &otr_ops, NULL); 1407 1408 return TRUE; /* cycle timer */ 1409 } 1410 1309 1411 /* helper to assert that account and protocol names given to ops below always 1310 1412 match the im_connection passed through as opdata */ … … 1313 1415 { 1314 1416 struct im_connection *ic = (struct im_connection *)opdata; 1417 1418 /* libotr 4.0.0 has a bug where it doesn't set opdata, so we catch 1419 * that and try to find the desired connection in the global list. */ 1420 if(!ic) { 1421 GSList *l; 1422 for(l=get_connections(); l; l=l->next) { 1423 ic = l->data; 1424 if(strcmp(accountname, ic->acc->user) == 0 && 1425 strcmp(protocol, ic->acc->prpl->name) == 0) 1426 break; 1427 } 1428 assert(l != NULL); /* a match should always be found */ 1429 if(!l) 1430 return NULL; 1431 } 1315 1432 1316 1433 if (strcmp(accountname, ic->acc->user) != 0) { … … 1594 1711 1595 1712 /* list all contexts */ 1713 /* XXX remove this, or split off as its own command */ 1714 /* XXX show instags? */ 1596 1715 irc_rootmsg(irc, "%s", ""); 1597 1716 irc_rootmsg(irc, "\x1f" "connection contexts:\x1f (bold=currently encrypted)"); … … 1622 1741 void show_otr_context_info(irc_t *irc, ConnContext *ctx) 1623 1742 { 1743 // XXX show all instags/subcontexts 1744 1624 1745 switch(ctx->otr_offer) { 1625 1746 case OFFER_NOT:
Note: See TracChangeset
for help on using the changeset viewer.