Commit 9add3e3d authored by JC Brand's avatar JC Brand

Add support for Socialist's Millionaire Protocol authentication

parent 6d237d3f
...@@ -281,17 +281,16 @@ ...@@ -281,17 +281,16 @@
this.ChatBox = Backbone.Model.extend({ this.ChatBox = Backbone.Model.extend({
initialize: function () { initialize: function () {
if (this.get('box_id') !== 'controlbox') { if (this.get('box_id') !== 'controlbox') {
if (_.contains([UNVERIFIED, VERIFIED], this.get('otr_status'))) {
this.initiateOTR();
}
this.messages = new converse.Messages(); this.messages = new converse.Messages();
this.messages.localStorage = new Backbone.LocalStorage( this.messages.localStorage = new Backbone.LocalStorage(
hex_sha1('converse.messages'+this.get('jid'))); hex_sha1('converse.messages'+this.get('jid')));
this.set({ this.set({
'user_id' : Strophe.getNodeFromJid(this.get('jid')), 'user_id' : Strophe.getNodeFromJid(this.get('jid')),
'box_id' : hex_sha1(this.get('jid')), 'box_id' : hex_sha1(this.get('jid')),
'fullname' : this.get('fullname'), 'otr_status': this.get('otr_status') || UNENCRYPTED
'url': this.get('url'),
'image_type': this.get('image_type'),
'image': this.get('image'),
'otr_status': UNENCRYPTED
}); });
} }
}, },
...@@ -305,7 +304,7 @@ ...@@ -305,7 +304,7 @@
if (savedKey) { if (savedKey) {
decrypted = cipher.decrypt(crypto.algo.AES, savedKey, pass); decrypted = cipher.decrypt(crypto.algo.AES, savedKey, pass);
myKey = otr.DSA.parsePrivate(decrypted.toString(crypto.enc.Latin1)); myKey = otr.DSA.parsePrivate(decrypted.toString(crypto.enc.Latin1));
if (cipher.decrypt(crypto.algo.AES, passCheck, 'pass').toString(crypto.enc.Latin1) === 'match') { if (cipher.decrypt(crypto.algo.AES, passCheck, pass).toString(crypto.enc.Latin1) === 'match') {
// Verified that the user's password is still the same // Verified that the user's password is still the same
return myKey; return myKey;
} }
...@@ -319,6 +318,42 @@ ...@@ -319,6 +318,42 @@
return myKey; return myKey;
}, },
updateOTRStatus: function (state) {
switch (state) {
case otr.OTR.CONST.STATUS_AKE_SUCCESS:
if (this.otr.msgstate === otr.OTR.CONST.MSGSTATE_ENCRYPTED) {
this.save({'otr_status': UNVERIFIED});
}
break;
case otr.OTR.CONST.STATUS_END_OTR:
if (this.otr.msgstate === otr.OTR.CONST.MSGSTATE_FINISHED) {
this.save({'otr_status': FINISHED});
} else if (this.otr.msgstate === otr.OTR.CONST.MSGSTATE_PLAINTEXT) {
this.save({'otr_status': UNENCRYPTED});
}
break;
}
},
onSMP: function (type, data) {
// Event handler for SMP (Socialist's Millionaire Protocol)
// used by OTR (off-the-record).
switch (type) {
case 'question':
this.otr.smpSecret(prompt(data));
break;
case 'trust':
if (this.otr.trust === true) {
this.save({'otr_status': VERIFIED});
} else {
this.save({'otr_status': UNVERIFIED});
}
break;
default:
throw new Error('Unknown type.');
}
},
initiateOTR: function () { initiateOTR: function () {
this.otr = new otr.OTR({ this.otr = new otr.OTR({
fragment_size: 140, fragment_size: 140,
...@@ -326,22 +361,8 @@ ...@@ -326,22 +361,8 @@
priv: this.getPrivateKey(), priv: this.getPrivateKey(),
debug: this.debug debug: this.debug
}); });
this.otr.on('status', $.proxy(function (state) { this.otr.on('status', $.proxy(this.updateOTRStatus, this));
switch (state) { this.otr.on('smp', $.proxy(this.onSMP, this));
case otr.OTR.CONST.STATUS_AKE_SUCCESS:
if (this.otr.msgstate === otr.OTR.CONST.MSGSTATE_ENCRYPTED) {
this.set('otr_status', UNVERIFIED);
}
break;
case otr.OTR.CONST.STATUS_END_OTR:
if (this.otr.msgstate === otr.OTR.CONST.MSGSTATE_FINISHED) {
this.set('otr_status', FINISHED);
} else if (this.otr.msgstate === otr.OTR.CONST.MSGSTATE_PLAINTEXT) {
this.set('otr_status', UNENCRYPTED);
}
break;
}
}, this));
this.otr.on('ui', $.proxy(function (msg) { this.otr.on('ui', $.proxy(function (msg) {
this.trigger('showReceivedOTRMessage', msg); this.trigger('showReceivedOTRMessage', msg);
...@@ -409,10 +430,16 @@ ...@@ -409,10 +430,16 @@
this.trigger('buddyStartsOTR'); this.trigger('buddyStartsOTR');
} }
} else if (text.match(/^\?OTR\:/)) { } else if (text.match(/^\?OTR\:/)) {
// This is an encrypted message, but we don't if (this.otr) {
// appear to have an encrypted session. Send to OTR // This is an encrypted message, but we don't
// anyway, they'll complain. // appear to have an encrypted session. Send to OTR
this.otr.receiveMsg(text); // anyway, they'll complain.
this.otr.receiveMsg(text);
} else {
this.showHelpMessages(
[__('We received an encrypted message, but you are not set up for encryption yet.')],
'error');
}
} else { } else {
// Normal unencrypted message. // Normal unencrypted message.
this.createMessage(message); this.createMessage(message);
...@@ -480,7 +507,8 @@ ...@@ -480,7 +507,8 @@
'<li><a class="end-otr" href="#">'+__('End encrypted conversation')+'</a></li>'+ '<li><a class="end-otr" href="#">'+__('End encrypted conversation')+'</a></li>'+
'{[ } ]}' + '{[ } ]}' +
'{[ if (otr_status === "'+UNVERIFIED+'") { ]}' + '{[ if (otr_status === "'+UNVERIFIED+'") { ]}' +
'<li><a class="auth-otr" href="#">'+__('Authenticate buddy')+'</a></li>'+ '<li><a class="auth-otr" data-scheme="fingerprint" href="#">'+__('Verify with fingerprints')+'</a></li>'+
'<li><a class="auth-otr" data-scheme="smp" href="#">'+__('Verify with SMP')+'</a></li>'+
'{[ } ]}' + '{[ } ]}' +
'<li><a href="http://www.cypherpunks.ca/otr/help/3.2.0/levels.php" target="_blank">'+__("What\'s this?")+'</a></li>'+ '<li><a href="http://www.cypherpunks.ca/otr/help/3.2.0/levels.php" target="_blank">'+__("What\'s this?")+'</a></li>'+
'</ul>'+ '</ul>'+
...@@ -788,21 +816,31 @@ ...@@ -788,21 +816,31 @@
}, },
authOTR: function (ev) { authOTR: function (ev) {
var result = confirm(__( var scheme = $(ev.target).data().scheme;
'Here are the fingerprints, please confirm them with %1$s, outside of this chat.\n\n'+ var result, question, answer;
'Fingerprint for you, %2$s: %3$s\n\n'+ if (scheme === 'fingerprint') {
'Fingerprint for %1$s: %4$s\n\n'+ result = confirm(__(
'If you have confirmed that the fingerprints match, click OK, otherwise click Cancel.', [ 'Here are the fingerprints, please confirm them with %1$s, outside of this chat.\n\n'+
this.model.get('fullname'), 'Fingerprint for you, %2$s: %3$s\n\n'+
converse.xmppstatus.get('fullname')||converse.bare_jid, 'Fingerprint for %1$s: %4$s\n\n'+
this.model.otr.priv.fingerprint(), 'If you have confirmed that the fingerprints match, click OK, otherwise click Cancel.', [
this.model.otr.their_priv_pk.fingerprint() this.model.get('fullname'),
] converse.xmppstatus.get('fullname')||converse.bare_jid,
)); this.model.otr.priv.fingerprint(),
if (result === true) { this.model.otr.their_priv_pk.fingerprint()
this.model.set('otr_status', VERIFIED); ]
));
if (result === true) {
this.model.save({'otr_status': VERIFIED});
} else {
this.model.save({'otr_status': UNVERIFIED});
}
} else if (scheme === 'smp') {
question = prompt(__('What is your security question?'));
answer = prompt(__('What is the answer to the security question?'));
this.model.otr.smpSecret(answer, question);
} else { } else {
this.model.set('otr_status', UNVERIFIED); this.showHelpMessages([__('Invalid authentication scheme provided')], 'error');
} }
}, },
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment