def tls_is_certificate_valid(self, cert): """Default certificate verification callback for TLS connections. :Parameters: - `cert`: certificate information, as returned by `ssl.SSLSocket.getpeercert` :return: computed verification result.""" try: self.__logger.debug("tls_is_certificate_valid(cert = %r)" % (cert, )) if not cert: self.__logger.warning( "No TLS certificate information received.") return False valid_hostname_found = False if 'subject' in cert: for rdns in cert['subject']: for key, value in rdns: if key == 'commonName' and JID(value) == self.peer: self.__logger.debug( " good commonName: {0}".format(value)) valid_hostname_found = True if 'subjectAltName' in cert: for key, value in cert['subjectAltName']: if key == 'DNS' and JID(value) == self.peer: self.__logger.debug( " good subjectAltName({0}): {1}".format( key, value)) valid_hostname_found = True return valid_hostname_found except: self.__logger.exception("Exception caught") raise
def handle_message(self, stanza): ''' <message from='[email protected]/desktop' to='*****@*****.**'> <x xmlns='jabber:x:conference' jid='*****@*****.**' password='******' reason='Hey Hecate, this is the place for all good witches!'/> </message> ''' try: fromjid = stanza.get_from() x = stanza.xpath_eval('c:x', {'c': CONFERENCE_NS})[0] roomjid = JID(from_utf8(x.prop('jid'))) roomname = JID(roomjid).node password = x.prop('password') password = from_utf8(password) if password else None reason = x.prop('reason') reason = from_utf8(reason) if reason else None except Exception: traceback.print_exc() return False else: if not all((roomname, fromjid)): return False self.protocol.hub.on_invite( protocol=self.protocol, buddy=fromjid, room_name=roomname, message=reason, on_yes=lambda: self.protocol.join_chat_jid( roomjid, self.protocol.self_buddy.jid.node)) return True # don't let other message handlers do it
def complete_xml_element(self, xmlnode, _unused): """Complete the XML node with `self` content. Should be overriden in classes derived from `StanzaPayloadObject`. :Parameters: - `xmlnode`: XML node with the element being built. It has already right name and namespace, but no attributes or content. - `_unused`: document to which the element belongs. :Types: - `xmlnode`: `libxml2.xmlNode` - `_unused`: `libxml2.xmlDoc`""" if self.node: xmlnode.setProp("node", to_utf8(self.node)) if self.sid: xmlnode.setProp("sid", to_utf8(self.sid)) if self.mode and self.mode != 'tcp': xmlnode.setProp("mode", to_utf8(self.mode)) for host in self.hosts: try: host.as_xml(xmlnode, _unused) except: pprint(host) raise if self.activate: xmlnode.newChild(None, "activate", JID(self.activate).as_utf8()) if self.host_used: h = xmlnode.newChild(None, "streamhost-used", None) h.setProp("jid", JID(self.host_used).as_utf8())
def check_presence_subscribe(self, p): self.failUnlessEqual(p.get_from(), JID("[email protected]/res")) self.failUnlessEqual(p.get_to(), JID("*****@*****.**")) self.failUnlessEqual(p.get_type(), "subscribe") self.failUnlessEqual(p.get_id(), None) self.failUnlessEqual(p.get_show(), None) self.failUnlessEqual(p.get_status(), None)
def service_discovery_init(self): self.disco_init = jabber.disco.DiscoNode(self.cache, JID(self.jid.domain)) self.disco_init.fetch(self.disco_finished, depth=1, timeout_duration=1) self.disco_init2 = jabber.disco.DiscoNode(self.cache, JID("google.com")) self.disco_init2.fetch(super(GoogleTalk, self).disco_finished, depth=1, timeout_duration=1)
def test_field_jid_single(self): field = Field(field_type="jid-single", value=JID(u"*****@*****.**")) self.failUnlessEqual(field.value, JID(u"*****@*****.**")) self.failUnlessEqual(field.values, [u"*****@*****.**"]) field = Field(field_type="jid-single", values=[u"*****@*****.**"]) self.failUnlessEqual(field.value, JID(u"*****@*****.**")) self.failUnlessEqual(field.values, [u"*****@*****.**"]) field.value = JID(u"example.com") self.failUnlessEqual(field.value, JID(u"example.com")) self.failUnlessEqual(field.values, [u"example.com"])
def _process_sasl_auth(self, mechanism, content): """Process incoming <sasl:auth/> element. [receiving entity only] :Parameters: - `mechanism`: mechanism choosen by the peer. - `content`: optional "initial response" included in the element. """ if self.authenticator: self.__logger.debug("Authentication already started") return False self.auth_method_used = "sasl:" + mechanism self.authenticator = sasl.server_authenticator_factory(mechanism, self) r = self.authenticator.start(base64.decodestring(content)) if isinstance(r, sasl.Success): el_name = "success" content = r.base64() elif isinstance(r, sasl.Challenge): el_name = "challenge" content = r.base64() else: el_name = "failure" content = None root = self.doc_out.getRootElement() xmlnode = root.newChild(None, el_name, None) ns = xmlnode.newNs(SASL_NS, None) xmlnode.setNs(ns) if content: xmlnode.setContent(content) if isinstance(r, sasl.Failure): xmlnode.newChild(None, r.reason, None) self._write_raw(xmlnode.serialize(encoding="UTF-8")) xmlnode.unlinkNode() xmlnode.freeNode() if isinstance(r, sasl.Success): if r.authzid: self.peer = JID(r.authzid) else: self.peer = JID(r.username, self.me.domain) self.peer_authenticated = 1 self.state_change("authenticated", self.peer) self._post_auth() if isinstance(r, sasl.Failure): raise SASLAuthenticationFailed, "SASL authentication failed" return True
def send(self, message, jabber_id, jabber_password, jabber_recpt): try: self.lock.acquire()#acquire lock subject = "Deluge Torrent completed" jid=JID(jabber_id) if not jid.resource: jid=JID(jid.node,jid.domain,"send_message") recpt=JID(jabber_recpt) send_message(jid, jabber_password, recpt, message, subject) finally: self.lock.release();#release lock
def send_msg(self, rid, msg): self.rid = JID(rid) if not self.sid.resource: self.sid = JID(self.sid.node, self.sid.domain, 'send_message') msg = Message(to_jid=self.rid, body=msg) def send(stream): stream.send(msg) self.xmpp_do(send)
def handle_message(self, stanza): ''' <message from='*****@*****.**' to='*****@*****.**'> <x xmlns='http://jabber.org/protocol/muc#user'> <invite from='[email protected]/desktop'> <reason> Hey Hecate, this is the place for all good witches! </reason> </invite> <password>cauldronburn</password> </x> </message> ''' self.stanza = stanza try: roomjid = JID(stanza.get_from()) roomname = roomjid.node except Exception: traceback.print_exc() return False else: if not roomname: return False for invite in stanza.xpath_eval('user:x/user:invite', {'user': MUC_USER_NS}): frm = invite.prop('from') if not frm: continue try: frm = JID(from_utf8(frm)) except Exception: continue else: break else: return False reason = None for rsn in xpath_eval(invite, 'user:reason/text()', {'user': MUC_USER_NS}): if rsn: reason = reason reason = reason or '' self.protocol.hub.on_invite( protocol=self.protocol, buddy=frm, room_name=roomname, message=reason, on_yes=lambda: self.protocol.join_chat_jid( roomjid, self.protocol.self_buddy.jid.node)) return True
def stream_start(self, doc): """Process <stream:stream> (stream start) tag received from peer. :Parameters: - `doc`: document created by the parser""" self.doc_in = doc log.debug("input document: %r" % (self.doc_in.serialize(), )) try: r = self.doc_in.getRootElement() if r.ns().getContent() != STREAM_NS: self._send_stream_error("invalid-namespace") raise FatalStreamError, "Invalid namespace." except libxml2.treeError: self._send_stream_error("invalid-namespace") raise FatalStreamError, "Couldn't get the namespace." self.version = r.prop("version") if self.version and self.version != "1.0": self._send_stream_error("unsupported-version") raise FatalStreamError, "Unsupported protocol version." # to_from_mismatch=0 assert self.initiator if self.initiator: self.stream_id = r.prop("id") peer = r.prop("from") if peer: peer = JID(peer) # if self.peer: # if peer and peer!=self.peer: # self.__logger.debug("peer hostname mismatch:" # " %r != %r" % (peer,self.peer)) # to_from_mismatch=1 # else: self.peer = peer else: to = r.prop("to") if to: to = self.check_to(to) if not to: self._send_stream_error("host-unknown") raise FatalStreamError, 'Bad "to"' self.me = JID(to) self._send_stream_start(self.generate_id()) self._send_stream_features() self.state_change("fully connected", self.peer) self._post_connect() if not self.version: self.state_change("fully connected", self.peer) self._post_connect()
def prefix_to_jid(self,prefix): if channel_re.match(prefix): node=channel_to_node(prefix,self.default_encoding) return JID(node,self.network.jid.domain,None) else: if "!" in prefix: nick,user=prefix.split("!",1) else: nick=prefix user="" node=nick_to_node(nick,self.default_encoding) resource=unicode(user,self.default_encoding,"replace") return JID(node,self.network.jid.domain,resource)
def _process_sasl_response(self, content): """Process incoming <sasl:response/> element. [receiving entity only] :Parameters: - `content`: the response data received (Base64-encoded). """ if not self.authenticator: self.__logger.debug("Unexpected SASL response") return 0 r = self.authenticator.response(base64.decodestring(content)) if isinstance(r, sasl.Success): el_name = "success" content = r.base64() elif isinstance(r, sasl.Challenge): el_name = "challenge" content = r.base64() else: el_name = "failure" content = None root = self.doc_out.getRootElement() xmlnode = root.newChild(None, el_name, None) ns = xmlnode.newNs(SASL_NS, None) xmlnode.setNs(ns) if content: xmlnode.setContent(content) if isinstance(r, sasl.Failure): xmlnode.newChild(None, r.reason, None) self._write_raw(xmlnode.serialize(encoding="UTF-8")) xmlnode.unlinkNode() xmlnode.freeNode() if isinstance(r, sasl.Success): authzid = r.authzid if authzid: self.peer = JID(r.authzid) else: self.peer = JID(r.username, self.me.domain) self.peer_authenticated = 1 self._restart_stream() self.state_change("authenticated", self.peer) self._post_auth() if isinstance(r, sasl.Failure): raise SASLAuthenticationFailed, "SASL authentication failed" return 1
def check_presence_full(self, p): self.failUnlessEqual(p.get_from(), JID("[email protected]/res")) self.failUnlessEqual(p.get_to(), JID("*****@*****.**")) self.failUnlessEqual(p.get_type(), None) self.failUnlessEqual(p.get_id(), "1") self.failUnlessEqual(p.get_show(), "away") self.failUnlessEqual(p.get_status(), "The Status") self.failUnlessEqual(p.get_priority(), 10) nodes = p.xpath_eval("t:payload", {"t": "http://pyxmpp.jajcus.net/xmlns/test"}) self.failUnless(nodes) self.failUnlessEqual(nodes[0].name, "payload") self.failUnless(nodes[0].children) self.failUnlessEqual(nodes[0].children.name, "abc")
def check_message_full(self, m): self.failUnlessEqual(m.get_from(), JID("[email protected]/res")) self.failUnlessEqual(m.get_to(), JID("*****@*****.**")) self.failUnlessEqual(m.get_type(), "normal") self.failUnlessEqual(m.get_id(), "1") self.failUnlessEqual(m.get_subject(), u"Subject") self.failUnlessEqual(m.get_body(), u"The body") self.failUnlessEqual(m.get_thread(), u"thread-id") nodes = m.xpath_eval("t:payload", {"t": "http://pyxmpp.jajcus.net/xmlns/test"}) self.failUnless(nodes) self.failUnlessEqual(nodes[0].name, "payload") self.failUnless(nodes[0].children) self.failUnlessEqual(nodes[0].children.name, "abc")
def __getattr__(self, name): if name != "value": raise AttributeError, "'Field' object has no attribute %r" % ( name, ) values = self.values t = self.type l = len(values) if t is not None: if t == "boolean": if l == 0: return None elif l == 1: v = values[0] if v in ("0", "false"): return False elif v in ("1", "true"): return True raise ValueError, "Bad boolean value" elif t.startswith("jid-"): values = [JID(v) for v in values] if t.endswith("-multi"): return values if l == 0: return None elif l == 1: return values[0] else: raise ValueError, "Multiple values of a single-value field"
def check_authzid(self, authzid, extra_info=None): """Check authorization id provided by the client. [server only] :Parameters: - `authzid`: authorization id provided. - `extra_info`: additional information about the user from the authentication backend. This mapping will usually contain at least 'username' item. :Types: - `authzid`: unicode - `extra_info`: mapping :return: `True` if user is authorized to use that `authzid`. :returntype: `bool`""" if not extra_info: extra_info = {} if not authzid: return 1 if not self.initiator: jid = JID(authzid) if not extra_info.has_key("username"): ret = 0 elif jid.node != extra_info["username"]: ret = 0 elif jid.domain != self.my_jid.domain: ret = 0 elif not jid.resource: ret = 0 else: ret = 1 else: ret = 0 return ret
def from_xml(self, xmlnode): """Initialize Delay object from an XML node. :Parameters: - `xmlnode`: the jabber:x:delay XML element. :Types: - `xmlnode`: `libxml2.xmlNode`""" if xmlnode.type != "element": raise ValueError, "XML node is not a jabber:x:delay element (not an element)" ns = get_node_ns_uri(xmlnode) if ns and (ns != self.xml_element_namespace or xmlnode.name != self.xml_element_name): raise ValueError, "XML node is not a " + self.xml_element_namespace + " element" stamp = xmlnode.prop("stamp") tm = _parse_ts(stamp) tm = tm[0:8] + (0, ) self.timestamp = datetime.datetime.fromtimestamp(time.mktime(tm)) delay_from = from_utf8(xmlnode.prop("from")) if delay_from: try: self.delay_from = JID(delay_from) except JIDError: raise JIDMalformedProtocolError, "Bad JID in the " + self.xml_element_namespace + " 'from' attribute" else: self.delay_from = None self.reason = from_utf8(xmlnode.getContent())
def __init__(self, node_or_datetime, delay_from=None, reason=None, utc=True): """ Initialize the Delay object. :Parameters: - `node_or_datetime`: an XML node to parse or the timestamp. - `delay_from`: JID of the entity which adds the delay mark (when `node_or_datetime` is a timestamp). - `reason`: reason of the delay (when `node_or_datetime` is a timestamp). - `utc`: if `True` then the timestamp is assumed to be UTC, otherwise it is assumed to be local time. :Types: - `node_or_datetime`: `libxml2.xmlNode` or `datetime.datetime` - `delay_from`: `pyxmpp.JID` - `reason`: `unicode` - `utc`: `bool`""" if isinstance(node_or_datetime, libxml2.xmlNode): self.from_xml(node_or_datetime) else: if utc: self.timestamp = node_or_datetime else: self.timestamp = datetime_local_to_utc(node_or_datetime) self.delay_from = JID(delay_from) self.reason = unicode(reason)
def __init__(self, node_or_jid, subscription="none", name=None, groups=(), ask=None): """ Initialize a roster item from XML node or jid and optional attributes. :Parameters: - `node_or_jid`: XML node or JID - `subscription`: subscription type ("none", "to", "from" or "both" - `name`: item visible name - `groups`: sequence of groups the item is member of - `ask`: True if there was unreplied subsription or unsubscription request sent.""" if isinstance(node_or_jid, libxml2.xmlNode): self.from_xml(node_or_jid) else: node_or_jid = JID(node_or_jid) if subscription not in ("none", "from", "to", "both", "remove"): raise ValueError, "Bad subscription type: %r" % ( subscription, ) if ask not in ("subscribe", None): raise ValueError, "Bad ask type: %r" % (ask, ) self.jid = node_or_jid self.ask = ask self.subscription = subscription self.name = name self.groups = list(groups)
def from_xml(self, node): """Initialize RosterItem from XML node.""" if node.type != "element": raise ValueError, "XML node is not a roster item (not en element)" ns = get_node_ns_uri(node) if ns and ns != ROSTER_NS or node.name != "item": raise ValueError, "XML node is not a roster item" jid = JID(node.prop("jid").decode("utf-8")) subscription = node.prop("subscription") if subscription not in ("none", "from", "to", "both", "remove"): subscription = "none" ask = node.prop("ask") if ask not in ("subscribe", None): ask = None name = from_utf8(node.prop("name")) groups = [] n = node.children while n: if n.type != "element": n = n.next continue ns = get_node_ns_uri(n) if ns and ns != ROSTER_NS or n.name != "group": n = n.next continue group = n.getContent() if group: groups.append(from_utf8(group)) n = n.next self.jid = jid self.name = name self.groups = groups self.subscription = subscription self.ask = ask
def registration_success(self, stanza): """Handle registration success. [client only] Clean up registration stuff, change state to "registered" and initialize authentication. :Parameters: - `stanza`: the stanza received. :Types: - `stanza`: `pyxmpp.iq.Iq`""" _unused = stanza self.lock.acquire() try: self.state_change("registered", self.registration_form) if ('FORM_TYPE' in self.registration_form and self.registration_form['FORM_TYPE'].value == 'jabber:iq:register'): if 'username' in self.registration_form: self.my_jid = JID(self.registration_form['username'].value, self.my_jid.domain, self.my_jid.resource) if 'password' in self.registration_form: self.password = self.registration_form['password'].value self.registration_callback = None self._post_connect() finally: self.lock.release()
def _import(self, msg_type, directory, patterns): in_pattern, out_pattern = patterns same_pattern = (in_pattern == out_pattern) if same_pattern: pattern = in_pattern.replace("@@", "") else: in_pattern = in_pattern.replace("@@", "_in") out_pattern = out_pattern.replace("@@", "_out") pattern = "(?:{0}|{1})".format(in_pattern, out_pattern) pattern = re.compile(pattern) matches, unparseable, imported = 0, 0, 0 for filename in sorted(os.listdir(directory)): path = os.path.join(directory, filename) if not os.path.isfile(path) \ or not LOG_FILENAME_RE.match(filename): self.info(" skipping {0}".format(filename)) continue try: peer = JID(filename) except ValueError: self.info(" skipping {0} (bad jid)".format(filename)) continue self.info(" {0}...".format(filename)) with codecs.open(path, "r", "utf-8", "replace") as log_file: data = log_file.read() new_m, new_up, new_i = self._import_log(msg_type, peer, pattern, data) matches += new_m unparseable += new_up imported += new_i return matches, unparseable, imported
def __init__(self, xmlnode_or_jid, host=None, port=None, zeroconf=None): """Initialize an `StreamHost` object. Wrap an existing streamhost XML element or create a new one. :Parameters: - `xmlnode_or_jid`: XML element describing the StreamHost or the JID of the StreamHost. - `host`: the hostname or IP address of the StreamHost. - `port`: the port of the StreamHost - `zeroconf`: the zeroconf identifier of the StreamHost. :Types: - `xmlnode_or_node`: `libxml2.xmlNode` or `unicode` - `host`: `unicode` - `port`: `int` - `zeroconf`: `unicode` """ if isinstance(xmlnode_or_jid, libxml2.xmlNode): self.from_xml(xmlnode_or_jid) else: self.jid = JID(xmlnode_or_jid) self.host = host self.port = port self.zeroconf = zeroconf if not (bool(self.port) ^ bool(self.zeroconf)): raise ValueError, 'StreamHost element requires one of [port, zeroconf]'
def from_xml(self, node): #need jid, host, port, zeroconf """Initialize StreamHost from XML node.""" if node.type != "element": raise ValueError, "XML node is not a streamhost (not en element)" ns = get_node_ns_uri(node) if ns and ns != self.xml_element_namespace or node.name != self.xml_element_name: raise ValueError, "XML node is not a %s descriptor" % self.xml_element_name jid = JID(node.prop("jid").decode("utf-8")) self.jid = jid host = node.prop("host").decode("utf-8") self.host = host port = node.prop("port") #py2.5: self.port = int(port.decode("utf-8")) if port else None #py2.4: # if port: # self.port = int(port.decode("utf-8")) # else: # self.port = None zeroconf = node.prop("zeroconf") #py2.5: self.zeroconf = zeroconf.decode("utf-8") if zeroconf else None
def from_xml(self, xmlnode): """Initialize Delay object from an XML node. :Parameters: - `xmlnode`: the jabber:x:delay XML element. :Types: - `xmlnode`: `libxml2.xmlNode`""" if xmlnode.type != "element": raise ValueError, "XML node is not a jabber:x:delay element (not an element)" ns = get_node_ns_uri(xmlnode) if ns and ns != DELAY_NS or xmlnode.name != "x": raise ValueError, "XML node is not a jabber:x:delay element" stamp = xmlnode.prop("stamp") if stamp.endswith("Z"): stamp = stamp[:-1] if "-" in stamp: stamp = stamp.split("-", 1)[0] try: tm = time.strptime(stamp, "%Y%m%dT%H:%M:%S") except ValueError: raise BadRequestProtocolError, "Bad timestamp" tm = tm[0:8] + (0, ) self.timestamp = datetime.datetime.fromtimestamp(time.mktime(tm)) delay_from = from_utf8(xmlnode.prop("from")) if delay_from: try: self.delay_from = JID(delay_from) except JIDError: raise JIDMalformedProtocolError, "Bad JID in the jabber:x:delay 'from' attribute" else: self.delay_from = None self.reason = from_utf8(xmlnode.getContent())
def _process_sasl_success(self, content): """Process incoming <sasl:success/> element. [initiating entity only] :Parameters: - `content`: the "additional data with success" received (Base64-encoded). """ if not self.authenticator: self.__logger.debug("Unexpected SASL response") return False r = self.authenticator.finish(base64.decodestring(content)) if isinstance(r, sasl.Success): self.__logger.debug("SASL authentication succeeded") if r.authzid: self.me = JID(r.authzid) else: self.me = self.me self.authenticated = 1 self._restart_stream() self.state_change("authenticated", self.me) self._post_auth() else: self.__logger.debug("SASL authentication failed") raise SASLAuthenticationFailed, "Additional success data procesing failed" return True
def __init__(self, config_dir, data_dir): self.doc = None self.config_dir = config_dir self.data_dir = data_dir os.chdir(data_dir) libxml2.initializeCatalog() libxml2.loadCatalog(os.path.join(data_dir, "catalog.xml")) parser = libxml2.createFileParserCtxt( os.path.join(config_dir, "jjigw.xml")) parser.validate(1) parser.parseDocument() if not parser.isValid(): raise JJIGWFatalError, "Invalid configuration" self.doc = parser.doc() self.connect = ConnectConfig(self.doc.xpathEval("jjigw/connect")[0]) self.jid = None self.networks = {} for n in self.doc.xpathEval("jjigw/network"): network = NetworkConfig(n) if not self.jid: self.jid = network.jid self.networks[network.jid.domain] = network spidentd = self.doc.xpathEval("jjigw/spidentd") if spidentd: self.spidentd = SPIdentDConfig(spidentd[0]) else: self.spidentd = None self.admins = [] for n in self.doc.xpathEval("jjigw/admin"): self.admins.append(JID(n.getContent()))
def get_jid(self): """Get the JID of the item. :return: the JID of the item. :returntype: `JID`""" jid = self.xmlnode.prop("jid") return JID(jid.decode("utf-8"))
def pass_message_to_raw_channel(self, msg): fr = JID('#', self.network.jid.domain, None) m = Message(to_jid=self.jid, from_jid=fr, body=msg, stanza_type="groupchat") self.component.send(m)