def IBBIqHandler(self, conn, stanza): """ Handles streams state change. Used internally. """ typ = stanza.getType() log.debug('IBBIqHandler called typ->%s' % typ) if typ == 'set' and stanza.getTag('open'): self.StreamOpenHandler(conn, stanza) elif typ == 'set' and stanza.getTag('close'): self.StreamCloseHandler(conn, stanza) elif typ == 'set' and stanza.getTag('data'): sid = stanza.getTagAttr('data', 'sid') file_props = FilesProp.getFilePropByTransportSid(self.name, sid) if not file_props: conn.send(nbxmpp.Error(stanza, nbxmpp.ERR_ITEM_NOT_FOUND)) elif file_props.connected and self.IBBMessageHandler(conn, stanza): reply = stanza.buildReply('result') reply.delChild('data') conn.send(reply) elif not file_props.connected: log.debug('Received IQ for closed filetransfer, IQ dropped') elif typ == 'error': app.socks5queue.error_cb() else: conn.send(nbxmpp.Error(stanza, nbxmpp.ERR_BAD_REQUEST)) raise nbxmpp.NodeProcessed
def fail_bad_negotiation(self, reason, fields=None): """ Send 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 = nbxmpp.Error(nbxmpp.Message(), nbxmpp.ERR_FEATURE_NOT_IMPLEMENTED) err.T.error.T.text.setData(reason) if fields: feature = nbxmpp.Node(nbxmpp.NS_FEATURE + ' feature') for field in fields: fn = nbxmpp.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 __send_error(self, stanza, error, jingle_error=None, text=None, type_=None): err_stanza = nbxmpp.Error(stanza, '%s %s' % (Namespace.STANZAS, error)) err = err_stanza.getTag('error') if type_: err.setAttr('type', type_) if jingle_error: err.setTag(jingle_error, namespace=Namespace.JINGLE_ERRORS) if text: err.setTagData('text', text) self.connection.connection.send(err_stanza) self.__dispatch_error(jingle_error or error, text, type_)
def build_http_auth_answer(self, stanza, answer): if answer == 'yes': self._log.info('Auth request approved') confirm = stanza.getTag('confirm') reply = stanza.buildReply('result') if stanza.getName() == 'message': reply.addChild(node=confirm) self._con.connection.send(reply) elif answer == 'no': self._log.info('Auth request denied') err = nbxmpp.Error(stanza, nbxmpp.protocol.ERR_NOT_AUTHORIZED) self._con.connection.send(err)
def IBBMessageHandler(self, conn, stanza): """ Receive next portion of incoming datastream and store it write it to temporary file. Used internally. """ sid = stanza.getTagAttr('data', 'sid') seq = stanza.getTagAttr('data', 'seq') data = stanza.getTagData('data') log.debug('ReceiveHandler called sid->%s seq->%s' % (sid, seq)) try: seq = int(seq) data = base64.b64decode(data.encode('utf-8')).decode('utf-8') except Exception: seq = '' data = '' err = None file_props = FilesProp.getFilePropByTransportSid(self.name, sid) if file_props is None: err = nbxmpp.ERR_ITEM_NOT_FOUND else: if not data: err = nbxmpp.ERR_BAD_REQUEST elif seq != file_props.seq: err = nbxmpp.ERR_UNEXPECTED_REQUEST else: log.debug('Successfull receive sid->%s %s+%s bytes' % (sid, file_props.fp.tell(), len(data))) file_props.seq += 1 file_props.started = True file_props.fp.write(data) current_time = time.time() file_props.elapsed_time += current_time - file_props.last_time file_props.last_time = current_time file_props.received_len += len(data) gajim.socks5queue.progress_transfer_cb(self.name, file_props) if file_props.received_len >= file_props.size: file_props.completed = True if err: log.debug('Error on receive: %s' % err) conn.send( nbxmpp.Error(nbxmpp.Iq( to=stanza.getFrom(), frm=stanza.getTo(), payload=[nbxmpp.Node(nbxmpp.NS_IBB + ' close')]), err, reply=0)) else: return True
def IBBIqHandler(self, conn, stanza): """ Handles streams state change. Used internally. """ typ = stanza.getType() log.debug('IBBIqHandler called typ->%s' % typ) if typ == 'set' and stanza.getTag('open', namespace=nbxmpp.NS_IBB): self.StreamOpenHandler(conn, stanza) elif typ == 'set' and stanza.getTag('close', namespace=nbxmpp.NS_IBB): self.StreamCloseHandler(conn, stanza) elif typ == 'result': self.SendHandler() elif typ == 'error': gajim.socks5queue.error_cb() else: conn.send(nbxmpp.Error(stanza, nbxmpp.ERR_BAD_REQUEST)) raise nbxmpp.NodeProcessed
def IBBAllIqHandler(self, conn, stanza): """ Handle remote side reply about if it agree or not to receive our datastream. Used internally. Raises xmpppy event specfiying if the data transfer is agreed upon. """ syn_id = stanza.getID() log.debug('IBBAllIqHandler called syn_id->%s' % syn_id) for file_props in FilesProp.getAllFileProp(): if not file_props.direction or not file_props.connected: # It's socks5 bytestream # Or we closed the IBB stream continue if file_props.syn_id == syn_id: if stanza.getType() == 'error': if file_props.direction[0] == '<': conn.Event('IBB', 'ERROR ON RECEIVE', file_props) else: conn.Event('IBB', 'ERROR ON SEND', file_props) elif stanza.getType() == 'result': if file_props.direction[0] == '|': file_props.direction = file_props.direction[1:] self.SendHandler() else: conn.send( nbxmpp.Error(stanza, nbxmpp.ERR_UNEXPECTED_REQUEST)) break else: if stanza.getTag('data'): sid = stanza.getTagAttr('data', 'sid') file_props = FilesProp.getFilePropByTransportSid( self.name, sid) if file_props.connected and self.IBBMessageHandler( conn, stanza): reply = stanza.buildReply('result') reply.delChild('data') conn.send(reply) raise nbxmpp.NodeProcessed elif syn_id == self.last_sent_ibb_id: self.SendHandler()
def StreamCloseHandler(self, conn, stanza): """ Handle stream closure due to all data transmitted. Raise xmpppy event specifying successfull data receive. """ sid = stanza.getTagAttr('close', 'sid') log.debug('StreamCloseHandler called sid->%s' % sid) # look in sending files file_props = FilesProp.getFilePropByTransportSid(self.name, sid) if file_props: reply = stanza.buildReply('result') reply.delChild('close') conn.send(reply) # look in receiving files file_props.fp.close() file_props.completed = file_props.received_len >= file_props.size if not file_props.completed: file_props.error = -1 gajim.socks5queue.complete_transfer_cb(self.name, file_props) else: conn.send(nbxmpp.Error(stanza, nbxmpp.ERR_ITEM_NOT_FOUND))
def StreamOpenHandler(self, conn, stanza): """ Handles opening of new incoming stream. Used internally. """ err = None sid = stanza.getTagAttr('open', 'sid') blocksize = stanza.getTagAttr('open', 'block-size') log.debug('StreamOpenHandler called sid->%s blocksize->%s' % (sid, blocksize)) file_props = FilesProp.getFilePropByTransportSid(self.name, sid) try: blocksize = int(blocksize) except: err = nbxmpp.ERR_BAD_REQUEST if not sid or not blocksize: err = nbxmpp.ERR_BAD_REQUEST elif not file_props: err = nbxmpp.ERR_UNEXPECTED_REQUEST if err: rep = nbxmpp.Error(stanza, err) else: log.debug("Opening stream: id %s, block-size %s" % (sid, blocksize)) rep = nbxmpp.Protocol('iq', stanza.getFrom(), 'result', stanza.getTo(), {'id': stanza.getID()}) file_props.block_size = blocksize file_props.direction = '<' file_props.seq = 0 file_props.received_len = 0 file_props.last_time = time.time() file_props.error = 0 file_props.paused = False file_props.connected = True file_props.completed = False file_props.disconnect_cb = None file_props.continue_cb = None file_props.syn_id = stanza.getID() file_props.fp = open(file_props.file_name, 'w') conn.send(rep)
def respond_archiving(self, form): field = form.getField('logging') options = [x[1] for x in field.getOptions()] values = field.getValues() logging = self.archiving_logging_preference(options) self.negotiated['logging'] = logging response = nbxmpp.Message() feature = response.NT.feature feature.setNamespace(nbxmpp.NS_FEATURE) x = nbxmpp.DataForm(typ='submit') x.addChild(node=nbxmpp.DataField(name='FORM_TYPE', value='urn:xmpp:ssn')) x.addChild(node=nbxmpp.DataField(name='accept', value='true')) x.addChild(node=nbxmpp.DataField(name='logging', value=logging)) self.status = 'responded-archiving' feature.addChild(node=x) if not logging: response = nbxmpp.Error(response, nbxmpp.ERR_NOT_ACCEPTABLE) feature = nbxmpp.Node(nbxmpp.NS_FEATURE + ' feature') n = nbxmpp.Node('field') n['var'] = 'logging' feature.addChild(node=n) response.T.error.addChild(node=feature) self.send(response)
def badRequest(self, stanza): self.connection.connection.send( nbxmpp.Error(stanza, nbxmpp.NS_STANZAS + ' bad-request'))
def _execute_command_received(self, con, stanza): jid = helpers.get_full_jid_from_iq(stanza) cmd = stanza.getTag('command') if cmd is None: log.error('Malformed stanza (no command node) %s', stanza) raise nbxmpp.NodeProcessed node = cmd.getAttr('node') if node is None: log.error('Malformed stanza (no node attr) %s', stanza) raise nbxmpp.NodeProcessed sessionid = cmd.getAttr('sessionid') if sessionid is None: # we start a new command session # only if we are visible for the jid and command exist if node not in self._commands.keys(): self._con.connection.send( nbxmpp.Error(stanza, nbxmpp.NS_STANZAS + ' item-not-found')) log.warning('Comand %s does not exist: %s', node, jid) raise nbxmpp.NodeProcessed newcmd = self._commands[node] if not newcmd.isVisibleFor(self.is_same_jid(jid)): log.warning('Command not visible for jid: %s', jid) raise nbxmpp.NodeProcessed # generate new sessionid sessionid = self._con.connection.getAnID() # create new instance and run it obj = newcmd(conn=self, jid=jid, sessionid=sessionid) rc = obj.execute(stanza) if rc: self._sessions[(jid, sessionid, node)] = obj log.info('Comand %s executed: %s', node, jid) raise nbxmpp.NodeProcessed else: # the command is already running, check for it magictuple = (jid, sessionid, node) if magictuple not in self._sessions: # we don't have this session... ha! log.warning('Invalid session %s', magictuple) raise nbxmpp.NodeProcessed action = cmd.getAttr('action') obj = self._sessions[magictuple] try: if action == 'cancel': rc = obj.cancel(stanza) elif action == 'prev': rc = obj.prev(stanza) elif action == 'next': rc = obj.next(stanza) elif action == 'execute' or action is None: rc = obj.execute(stanza) elif action == 'complete': rc = obj.complete(stanza) else: # action is wrong. stop the session, send error raise AttributeError except AttributeError: # the command probably doesn't handle invoked action... # stop the session, return error del self._sessions[magictuple] log.warning('Wrong action %s %s', node, jid) raise nbxmpp.NodeProcessed # delete the session if rc is False if not rc: del self._sessions[magictuple] raise nbxmpp.NodeProcessed
def _CommandExecuteCB(self, con, iq_obj): jid = helpers.get_full_jid_from_iq(iq_obj) cmd = iq_obj.getTag('command') if cmd is None: return node = cmd.getAttr('node') if node is None: return sessionid = cmd.getAttr('sessionid') if sessionid is None: # we start a new command session... only if we are visible for the jid # and command exist if node not in self.__commands.keys(): self.connection.send( nbxmpp.Error(iq_obj, nbxmpp.NS_STANZAS + ' item-not-found')) raise nbxmpp.NodeProcessed newcmd = self.__commands[node] if not newcmd.isVisibleFor(self.isSameJID(jid)): return # generate new sessionid sessionid = self.connection.getAnID() # create new instance and run it obj = newcmd(conn = self, jid = jid, sessionid = sessionid) rc = obj.execute(iq_obj) if rc: self.__sessions[(jid, sessionid, node)] = obj raise nbxmpp.NodeProcessed else: # the command is already running, check for it magictuple = (jid, sessionid, node) if magictuple not in self.__sessions: # we don't have this session... ha! return action = cmd.getAttr('action') obj = self.__sessions[magictuple] try: if action == 'cancel': rc = obj.cancel(iq_obj) elif action == 'prev': rc = obj.prev(iq_obj) elif action == 'next': rc = obj.next(iq_obj) elif action == 'execute' or action is None: rc = obj.execute(iq_obj) elif action == 'complete': rc = obj.complete(iq_obj) else: # action is wrong. stop the session, send error raise AttributeError except AttributeError: # the command probably doesn't handle invoked action... # stop the session, return error del self.__sessions[magictuple] return # delete the session if rc is False if not rc: del self.__sessions[magictuple] raise nbxmpp.NodeProcessed
def respond_e2e_bob(self, form, negotiated, not_acceptable): """ 4.3 esession response (bob) """ response = nbxmpp.Message() feature = response.NT.feature feature.setNamespace(nbxmpp.NS_FEATURE) x = nbxmpp.DataForm(typ='submit') x.addChild(node=nbxmpp.DataField(name='FORM_TYPE', value='urn:xmpp:ssn')) x.addChild(node=nbxmpp.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=nbxmpp.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 modp_f = form.getField('modp') if not modp_f: return self.modp = int(modp_f.getOptions()[group_order][1]) x.addChild(node=nbxmpp.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_f = form.getField('dhhashes') if not dhhashes_f: return dhhashes = dhhashes_f.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]).decode('utf-8') x.addChild(node=nbxmpp.DataField(name=name, value=b64ed)) self.form_o = ''.join(nbxmpp.c14n.c14n(el, self._is_buggy_gajim()) for \ el in form.getChildren()) self.form_s = ''.join(nbxmpp.c14n.c14n(el, self._is_buggy_gajim()) for \ el in x.getChildren()) self.status = 'responded-e2e' feature.addChild(node=x) if not_acceptable: response = nbxmpp.Error(response, nbxmpp.ERR_NOT_ACCEPTABLE) feature = nbxmpp.Node(nbxmpp.NS_FEATURE + ' feature') for f in not_acceptable: n = nbxmpp.Node('field') n['var'] = f feature.addChild(node=n) response.T.error.addChild(node=feature) self.send(response)
def bad_request(self, stanza): self.connection.connection.send( nbxmpp.Error(stanza, Namespace.STANZAS + ' bad-request'))