def fail_bad_negotiation(self, reason, fields=None): '''sends an error and cancels everything. if fields is None, the remote party has given us a bad cryptographic value of some kind otherwise, list the fields we haven't implemented''' err = xmpp.Error(xmpp.Message(), xmpp.ERR_FEATURE_NOT_IMPLEMENTED) err.T.error.T.text.setData(reason) if fields: feature = xmpp.Node(xmpp.NS_FEATURE + ' feature') for field in fields: fn = xmpp.Node('field') fn['var'] = field feature.addChild(node=feature) err.addChild(node=feature) self.send(err) self.status = None self.enable_encryption = False # this prevents the MAC check on decryption from succeeding, # preventing falsified messages from going through. self.km_o = ''
def user_send_nickname(account, nick): if not gajim.connections[account].pep_supported: return item = xmpp.Node('nick', {'xmlns': xmpp.NS_NICK}) item.addData(nick) gajim.connections[account].send_pb_publish('', xmpp.NS_NICK, item, '0')
def user_send_tune(account, artist='', title='', source='', track=0, length=0, items=None): if not (gajim.config.get_per('accounts', account, 'publish_tune') and \ gajim.connections[account].pep_supported): return item = xmpp.Node('tune', {'xmlns': xmpp.NS_TUNE}) if artist != '': i = item.addChild('artist') i.addData(artist) if title != '': i = item.addChild('title') i.addData(title) if source != '': i = item.addChild('source') i.addData(source) if track != 0: i = item.addChild('track') i.addData(track) if length != 0: i = item.addChild('length') i.addData(length) if items is not None: item.addChild(payload=items) gajim.connections[account].send_pb_publish('', xmpp.NS_TUNE, item, '0')
def user_send_activity(account, activity, subactivity='', message=''): if not gajim.connections[account].pep_supported: return item = xmpp.Node('activity', {'xmlns': xmpp.NS_ACTIVITY}) if activity != '': i = item.addChild(activity) if subactivity != '': i.addChild(subactivity) if message != '': i = item.addChild('text') i.addData(message) gajim.connections[account].send_pb_publish('', xmpp.NS_ACTIVITY, item, '0')
def user_send_mood(account, mood, message=''): if not gajim.connections[account].pep_supported: return item = xmpp.Node('mood', {'xmlns': xmpp.NS_MOOD}) if mood != '': if mood in GAJIM_MOODS: ns = 'http://gajim.org/moods' else: ns = None item.addChild(mood, namespace=ns) if message != '': i = item.addChild('text') i.addData(message) gajim.connections[account].send_pb_publish('', xmpp.NS_MOOD, item, '0')
def on_send_button_clicked(self, w): '''Gather info from widgets and send it as a message.''' # constructing item to publish... that's atom:entry element item = xmpp.Node('entry', {'xmlns': 'http://www.w3.org/2005/Atom'}) author = item.addChild('author') author.addChild('name', {}, [self.from_entry.get_text()]) item.addChild('generator', {}, ['Gajim']) item.addChild('title', {}, [self.subject_entry.get_text()]) item.addChild('id', {}, ['0']) buffer = self.contents_textview.get_buffer() item.addChild( 'content', {}, [buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter())]) # publish it to node gajim.connections[self.account].send_pb_publish( self.servicejid, self.groupid, item, '0') # close the window self.window.destroy()
def decrypt_stanza(self, stanza): # delete the unencrypted explanation body, if it exists orig_body = stanza.getTag('body') if orig_body: stanza.delChild(orig_body) c = stanza.getTag( name='c', namespace='http://www.xmpp.org/extensions/xep-0200.html#ns') stanza.delChild(c) # contents of <c>, minus <mac>, minus whitespace macable = ''.join( map(str, filter(lambda x: x.getName() != 'mac', c.getChildren()))) received_mac = base64.b64decode(c.getTagData('mac')) calculated_mac = self.hmac(self.km_o, macable + \ crypto.encode_mpi_with_padding(self.c_o)) if not calculated_mac == received_mac: raise exceptions.DecryptionError, 'bad signature' m_final = base64.b64decode(c.getTagData('data')) m_compressed = self.decrypt(m_final) plaintext = self.decompress(m_compressed) try: parsed = xmpp.Node(node='<node>' + plaintext + '</node>') except Exception: raise exceptions.DecryptionError, 'decrypted <data/> not parseable as XML' for child in parsed.getChildren(): stanza.addChild(node=child) return stanza
def respond_e2e_bob(self, form, negotiated, not_acceptable): response = xmpp.Message() feature = response.NT.feature feature.setNamespace(xmpp.NS_FEATURE) x = xmpp.DataForm(typ='submit') x.addChild(node=xmpp.DataField(name='FORM_TYPE', value='urn:xmpp:ssn')) x.addChild(node=xmpp.DataField(name='accept', value='true')) for name in negotiated: # some fields are internal and should not be sent if not name in ('send_pubkey', 'recv_pubkey'): x.addChild( node=xmpp.DataField(name=name, value=negotiated[name])) self.negotiated = negotiated # the offset of the group we chose (need it to match up with the dhhash) group_order = 0 self.modp = int(form.getField('modp').getOptions()[group_order][1]) x.addChild(node=xmpp.DataField(name='modp', value=self.modp)) g = dh.generators[self.modp] p = dh.primes[self.modp] self.n_o = base64.b64decode(form['my_nonce']) dhhashes = form.getField('dhhashes').getValues() self.negotiated['He'] = base64.b64decode( dhhashes[group_order].encode('utf8')) bytes = int(self.n / 8) self.n_s = crypto.generate_nonce() # n-bit random number self.c_o = crypto.decode_mpi(crypto.random_bytes(bytes)) self.c_s = self.c_o ^ (2**(self.n - 1)) self.y = crypto.srand(2**(2 * self.n - 1), p - 1) self.d = crypto.powmod(g, self.y, p) to_add = { 'my_nonce': self.n_s, 'dhkeys': crypto.encode_mpi(self.d), 'counter': crypto.encode_mpi(self.c_o), 'nonce': self.n_o } for name in to_add: b64ed = base64.b64encode(to_add[name]) x.addChild(node=xmpp.DataField(name=name, value=b64ed)) self.form_o = ''.join( map(lambda el: xmpp.c14n.c14n(el), form.getChildren())) self.form_s = ''.join( map(lambda el: xmpp.c14n.c14n(el), x.getChildren())) self.status = 'responded-e2e' feature.addChild(node=x) if not_acceptable: response = xmpp.Error(response, xmpp.ERR_NOT_ACCEPTABLE) feature = xmpp.Node(xmpp.NS_FEATURE + ' feature') for f in not_acceptable: n = xmpp.Node('field') n['var'] = f feature.addChild(node=n) response.T.error.addChild(node=feature) self.send(response)
def verify_identity(self, form, dh_i, sigmai, i_o): m_o = base64.b64decode(form['mac']) id_o = base64.b64decode(form['identity']) m_o_calculated = self.hmac(self.km_o, crypto.encode_mpi(self.c_o) + id_o) if m_o_calculated != m_o: raise exceptions.NegotiationError, 'calculated m_%s differs from received m_%s' % ( i_o, i_o) if i_o == 'a' and self.sas_algs == 'sas28x5': # we don't need to calculate this if there's a verified retained secret # (but we do anyways) self.sas = crypto.sas_28x5(m_o, self.form_s) if self.negotiated['recv_pubkey']: plaintext = self.decrypt(id_o) parsed = xmpp.Node(node='<node>' + plaintext + '</node>') if self.negotiated['recv_pubkey'] == 'hash': fingerprint = parsed.getTagData('fingerprint') # XXX find stored pubkey or terminate session raise 'unimplemented' else: if self.negotiated['sign_algs'] == (XmlDsig + 'rsa-sha256'): keyvalue = parsed.getTag(name='RSAKeyValue', namespace=XmlDsig) n, e = map( lambda x: crypto.decode_mpi( base64.b64decode(keyvalue.getTagData(x))), ('Modulus', 'Exponent')) eir_pubkey = RSA.construct((n, long(e))) pubkey_o = xmpp.c14n.c14n(keyvalue) else: # XXX DSA, etc. raise 'unimplemented' enc_sig = parsed.getTag(name='SignatureValue', namespace=XmlDsig).getData() signature = (crypto.decode_mpi(base64.b64decode(enc_sig)), ) else: mac_o = self.decrypt(id_o) pubkey_o = '' c7l_form = self.c7lize_mac_id(form) content = self.n_s + self.n_o + crypto.encode_mpi(dh_i) + pubkey_o if sigmai: self.form_o = c7l_form content += self.form_o else: form_o2 = c7l_form content += self.form_o + form_o2 mac_o_calculated = self.hmac(self.ks_o, content) if self.negotiated['recv_pubkey']: hash = crypto.sha256(mac_o_calculated) if not eir_pubkey.verify(hash, signature): raise exceptions.NegotiationError, 'public key signature verification failed!' elif mac_o_calculated != mac_o: raise exceptions.NegotiationError, 'calculated mac_%s differs from received mac_%s' % ( i_o, i_o)