Beispiel #1
0
 def __init__(self, sso, account):
     gobject.GObject.__init__(self)
     self._signals = []
     self._transport = SSLTCPClient(self.host, self.port)
     self._signals.append(
         self._transport.connect("notify::status", self.on_status_changed))
     self._signals.append(
         self._transport.connect("received", self.on_message_received))
     self._answered = False
     self._src = None
     self._msg_queue = []
     self._requests = {}
     self._relays = []
     self._account = account
     self._sso = sso
     self._tokens = {}
Beispiel #2
0
    def __init__(self, sso, account, host="relay.voice.messenger.msn.com", port=443):
        gobject.GObject.__init__(self)
        Timer.__init__(self)

        self._sso = sso
        self._account = account

        self._signals = []
        self._transport = SSLTCPClient(host, port)
        self._signals.append(self._transport.connect("notify::status",
            self.on_status_changed))
        self._signals.append(self._transport.connect("received",
            self.on_message_received))

        self._tokens = {}
        self._msg_queue = []
        self._transactions = {}  # id => (initial_request)
        self._request_id = 0
        self._requests = {} # id => (callback, errback, count, relays)
Beispiel #3
0
 def __init__(self, sso, account):
     gobject.GObject.__init__(self)
     self._signals = []
     self._transport = SSLTCPClient(self.host, self.port)
     self._signals.append(self._transport.connect("notify::status",
         self.on_status_changed))
     self._signals.append(self._transport.connect("received",
         self.on_message_received))
     self._answered = False
     self._src = None
     self._msg_queue = []
     self._requests = {}
     self._relays = []
     self._account = account
     self._sso = sso
     self._tokens = {}
Beispiel #4
0
class TURNClient(gobject.GObject):

    host = "relay.voice.messenger.msn.com"
    port = 443

    # Signal emitted when all requests were answered or failed
    __gsignals__ = {
        'done': (gobject.SIGNAL_RUN_FIRST,
            gobject.TYPE_NONE,
            (object,))
    }

    def __init__(self, sso, account):
        gobject.GObject.__init__(self)
        self._signals = []
        self._transport = SSLTCPClient(self.host, self.port)
        self._signals.append(self._transport.connect("notify::status",
            self.on_status_changed))
        self._signals.append(self._transport.connect("received",
            self.on_message_received))
        self._answered = False
        self._src = None
        self._msg_queue = []
        self._requests = {}
        self._relays = []
        self._account = account
        self._sso = sso
        self._tokens = {}

    def send(self, message):
        self._requests[message.id] = message
        if self._transport.status != IoStatus.OPEN:
            self._msg_queue.append(message)
            self._transport.open()
            return
        self._transport.send(str(message))

    @RequireSecurityTokens(LiveService.MESSENGER_SECURE)
    def request_shared_secret(self, callback, errcb, count=4):
        self._src = gobject.timeout_add(REQUEST_TIMEOUT, self.on_timeout)
        for _ in range(count):
            token = self._tokens[LiveService.MESSENGER_SECURE]
            username = "******" % token
            attrs = [TURNAttribute(AttributeTypes.USERNAME, username)]
            msg = TURNMessage(MessageTypes.SHARED_SECRET_REQUEST, attrs)
            self.send(msg)

    @RequireSecurityTokens(LiveService.MESSENGER_SECURE)
    def request_shared_secret_with_integrity(self, callback, errcb, realm, nonce):
        token = self._tokens[LiveService.MESSENGER_SECURE]
        username = "******" % token
        attrs = [TURNAttribute(AttributeTypes.USERNAME, username),
                 TURNAttribute(AttributeTypes.REALM, realm),
                 TURNAttribute(AttributeTypes.NONCE, nonce)]
        msg = TURNMessage(MessageTypes.SHARED_SECRET_REQUEST, attrs, 24)
        hmac = self.build_message_integrity(msg, token, nonce)
        msg.attributes.append(TURNAttribute(AttributeTypes.MESSAGE_INTEGRITY, hmac))
        msg.extra_size = 0
        self.send(msg)

    def build_message_integrity(self, msg, token, nonce):
        nonce = nonce.strip("\"")
        m = hashlib.md5()
        m.update("RPS_%s\x00\x00\x00:" % token)
        m.update("%s:%s" % (nonce, self._account))
        key = m.digest() + ("\x00" * 16)

        msg = str(msg)
        padding = 64 - (len(msg) % 64)
        if padding is 64:
            padding = 0
        msg += "\x00" * padding

        h = hmac.new(key, msg, hashlib.sha1)
        return h.digest()

    def on_status_changed(self, transport, param):
        if self._transport.status == IoStatus.OPEN:
            while self._msg_queue:
                self.send(self._msg_queue.pop())
        elif self._transport.status == IoStatus.CLOSED:
            self._done()

    def on_message_received(self, transport, data, length):
        msg = TURNMessage()
        msg.parse(data)

        if self._requests.get(msg.id, None) is None:
            return
        else:
            del self._requests[msg.id]

        if msg.type == MessageTypes.SHARED_SECRET_ERROR:
            error_msg = None
            realm = None
            nonce = None
            for attr in msg.attributes:
                if attr.type == AttributeTypes.REALM:
                    realm = attr.value
                elif attr.type == AttributeTypes.NONCE:
                    nonce = attr.value
                elif attr.type == AttributeTypes.ERROR_CODE:
                    error_msg = attr.value[4:]
            if error_msg == "Unauthorized":
                if realm is not None or nonce is not None:
                    self.request_shared_secret_with_integrity(None, None, realm, nonce)
                    return

        elif msg.type == MessageTypes.SHARED_SECRET_RESPONSE:
            relay = MediaRelay()
            for attr in msg.attributes:
                if attr.type == AttributeTypes.USERNAME:
                    relay.username = base64.b64encode(attr.value)
                elif attr.type == AttributeTypes.PASSWORD:
                    relay.password = base64.b64encode(attr.value)
                elif attr.type == AttributeTypes.ALTERNATE_SERVER:
                    server = struct.unpack("!HHcccc", attr.value)
                    ip = map(lambda x: ord(x), server[2:6])
                    relay.ip = "%i.%i.%i.%i" % tuple(ip)
                    relay.port = server[1]
            self._relays.append(relay)

        if not self._requests:
            self._done()

    def on_timeout(self):
        self._done()
        return False

    def _done(self):
        if not self._answered:
            self._answered = True
            self._requests = {}
            self._msg_queue = []
            for signal_id in self._signals:
                self._transport.disconnect(signal_id)
            if self._src is not None:
                gobject.source_remove(self._src)
                self._src = None
            self.emit("done", self._relays)
        self._transport.close()
Beispiel #5
0
class TURNClient(gobject.GObject, Timer):

    def __init__(self, sso, account, host="relay.voice.messenger.msn.com", port=443):
        gobject.GObject.__init__(self)
        Timer.__init__(self)

        self._sso = sso
        self._account = account

        self._signals = []
        self._transport = SSLTCPClient(host, port)
        self._signals.append(self._transport.connect("notify::status",
            self.on_status_changed))
        self._signals.append(self._transport.connect("received",
            self.on_message_received))

        self._tokens = {}
        self._msg_queue = []
        self._transactions = {}  # id => (initial_request)
        self._request_id = 0
        self._requests = {} # id => (callback, errback, count, relays)

    def send(self, message):
        self._transactions[message.id] = message
        if self._transport.status != IoStatus.OPEN:
            self._msg_queue.append(message)
            self._transport.open()
            return
        self._transport.send(str(message))

    @RequireSecurityTokens(LiveService.MESSENGER_SECURE)
    def request_shared_secret(self, callback, errback, count=1):
        logger.info("Sending shared secret requests (%i)" % count)

        self._request_id += 1
        self._requests[self._request_id] = (callback, errback, count, [])
        self.start_timeout_with_id("request", self._request_id, REQUEST_TIMEOUT)

        for _ in range(count):
            token = self._tokens[LiveService.MESSENGER_SECURE]
            username = "******" % token
            attrs = [TURNAttribute(AttributeTypes.USERNAME, username)]
            msg = TURNMessage(None, MessageTypes.SHARED_SECRET_REQUEST, attrs)
            self.send(msg)

    @RequireSecurityTokens(LiveService.MESSENGER_SECURE)
    def request_shared_secret_with_integrity(self, callback, errcb, realm, nonce):
        logger.info("Sending shared secret request with integrity")

        token = self._tokens[LiveService.MESSENGER_SECURE]
        username = "******" % token
        attrs = [TURNAttribute(AttributeTypes.USERNAME, username),
                 TURNAttribute(AttributeTypes.REALM, realm),
                 TURNAttribute(AttributeTypes.NONCE, nonce)]
        msg = TURNMessage(None, MessageTypes.SHARED_SECRET_REQUEST, attrs, 24)
        hmac = self.build_message_integrity(msg, token, nonce)
        msg.attributes.append(TURNAttribute(AttributeTypes.MESSAGE_INTEGRITY, hmac))
        msg.extra_size = 0
        self.send(msg)

    def build_message_integrity(self, msg, token, nonce):
        nonce = nonce.strip("\"")
        m = hashlib.md5()
        m.update("RPS_%s\x00\x00\x00:" % token)
        m.update("%s:%s" % (nonce, self._account))
        key = m.digest() + ("\x00" * 16)

        msg = str(msg)
        padding = 64 - (len(msg) % 64)
        if padding is 64:
            padding = 0
        msg += "\x00" * padding

        h = hmac.new(key, msg, hashlib.sha1)
        return h.digest()

    def on_status_changed(self, transport, param):
        if self._transport.status == IoStatus.OPEN:
            while self._msg_queue:
                self.send(self._msg_queue.pop())
        elif self._transport.status == IoStatus.CLOSED:
            pass #TODO something..

    def on_message_received(self, transport, data, length):
        try:
            msg = parse_message(data)

            initial_request = self._transactions.pop(msg.id, None)
            if initial_request is None:
                logger.warning("Received TURN response with invalid ID")
                return

            if msg.type == MessageTypes.SHARED_SECRET_ERROR:
                self.on_shared_secret_error(msg)
            elif msg.type == MessageTypes.SHARED_SECRET_RESPONSE:
                self.on_shared_secret_response(msg)
            else:
                logger.warning("Received unexpected message: %i" % msg.type)

        except Exception, e:
            logger.exception(e)
            logger.error("Received invalid TURN message")
Beispiel #6
0
class TURNClient(gobject.GObject):

    host = "relay.voice.messenger.msn.com"
    port = 443

    # Signal emitted when all requests were answered or failed
    __gsignals__ = {
        'done': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (object, ))
    }

    def __init__(self, sso, account):
        gobject.GObject.__init__(self)
        self._signals = []
        self._transport = SSLTCPClient(self.host, self.port)
        self._signals.append(
            self._transport.connect("notify::status", self.on_status_changed))
        self._signals.append(
            self._transport.connect("received", self.on_message_received))
        self._answered = False
        self._src = None
        self._msg_queue = []
        self._requests = {}
        self._relays = []
        self._account = account
        self._sso = sso
        self._tokens = {}

    def send(self, message):
        self._requests[message.id] = message
        if self._transport.status != IoStatus.OPEN:
            self._msg_queue.append(message)
            self._transport.open()
            return
        self._transport.send(str(message))

    @RequireSecurityTokens(LiveService.MESSENGER_SECURE)
    def request_shared_secret(self, callback, errcb, count=4):
        self._src = gobject.timeout_add(REQUEST_TIMEOUT, self.on_timeout)
        for _ in range(count):
            token = self._tokens[LiveService.MESSENGER_SECURE]
            username = "******" % token
            attrs = [TURNAttribute(AttributeTypes.USERNAME, username)]
            msg = TURNMessage(MessageTypes.SHARED_SECRET_REQUEST, attrs)
            self.send(msg)

    @RequireSecurityTokens(LiveService.MESSENGER_SECURE)
    def request_shared_secret_with_integrity(self, callback, errcb, realm,
                                             nonce):
        token = self._tokens[LiveService.MESSENGER_SECURE]
        username = "******" % token
        attrs = [
            TURNAttribute(AttributeTypes.USERNAME, username),
            TURNAttribute(AttributeTypes.REALM, realm),
            TURNAttribute(AttributeTypes.NONCE, nonce)
        ]
        msg = TURNMessage(MessageTypes.SHARED_SECRET_REQUEST, attrs, 24)
        hmac = self.build_message_integrity(msg, token, nonce)
        msg.attributes.append(
            TURNAttribute(AttributeTypes.MESSAGE_INTEGRITY, hmac))
        msg.extra_size = 0
        self.send(msg)

    def build_message_integrity(self, msg, token, nonce):
        nonce = nonce.strip("\"")
        m = hashlib.md5()
        m.update("RPS_%s\x00\x00\x00:" % token)
        m.update("%s:%s" % (nonce, self._account))
        key = m.digest() + ("\x00" * 16)

        msg = str(msg)
        padding = 64 - (len(msg) % 64)
        if padding is 64:
            padding = 0
        msg += "\x00" * padding

        h = hmac.new(key, msg, hashlib.sha1)
        return h.digest()

    def on_status_changed(self, transport, param):
        if self._transport.status == IoStatus.OPEN:
            while self._msg_queue:
                self.send(self._msg_queue.pop())
        elif self._transport.status == IoStatus.CLOSED:
            self._done()

    def on_message_received(self, transport, data, length):
        msg = TURNMessage()
        msg.parse(data)

        if self._requests.get(msg.id, None) is None:
            return
        else:
            del self._requests[msg.id]

        if msg.type == MessageTypes.SHARED_SECRET_ERROR:
            error_msg = None
            realm = None
            nonce = None
            for attr in msg.attributes:
                if attr.type == AttributeTypes.REALM:
                    realm = attr.value
                elif attr.type == AttributeTypes.NONCE:
                    nonce = attr.value
                elif attr.type == AttributeTypes.ERROR_CODE:
                    error_msg = attr.value[4:]
            if error_msg == "Unauthorized":
                if realm is not None or nonce is not None:
                    self.request_shared_secret_with_integrity(
                        None, None, realm, nonce)
                    return

        elif msg.type == MessageTypes.SHARED_SECRET_RESPONSE:
            relay = MediaRelay()
            for attr in msg.attributes:
                if attr.type == AttributeTypes.USERNAME:
                    relay.username = base64.b64encode(attr.value)
                elif attr.type == AttributeTypes.PASSWORD:
                    relay.password = base64.b64encode(attr.value)
                elif attr.type == AttributeTypes.ALTERNATE_SERVER:
                    server = struct.unpack("!HHcccc", attr.value)
                    ip = map(lambda x: ord(x), server[2:6])
                    relay.ip = "%i.%i.%i.%i" % tuple(ip)
                    relay.port = server[1]
            self._relays.append(relay)

        if not self._requests:
            self._done()

    def on_timeout(self):
        self._done()
        return False

    def _done(self):
        if not self._answered:
            self._answered = True
            self._requests = {}
            self._msg_queue = []
            for signal_id in self._signals:
                self._transport.disconnect(signal_id)
            if self._src is not None:
                gobject.source_remove(self._src)
                self._src = None
            self.emit("done", self._relays)
        self._transport.close()