Пример #1
0
   def render_POST(self, request):
      """
      Perform license activation. The POST must contain a 'payload' field.
      Payload must be a string consisting of 3 substrings concatenated
      by comma:

         msg, key, sig

         msg: the AES encrypted license
         key: the RSA encrypted AES key
         sig: the RSA signature over the encrypted msg and key

      For details, see cryptoutil.verify_and_decrypt.
      """
      try:
         args = request.args
         headers = request.getAllHeaders()

         if headers.get("content-type", "missing") != 'application/x-www-form-urlencoded':
            return self.deny(request, "bad or missing content type ('%s')" % headers.get("content-type", "missing"))

         if args.has_key('payload'):
            payload = request.args['payload'][0]
         else:
            return self.deny(request, "1: missing payload field")

         # remove any whitespace (also line) from payload string
         re.sub(r'\s', '', payload)

         log.msg("License activation received:")
         log.msg("Raw License: " + payload)

         try:
            license = Database.parseLicense(self.services["config"].get('instance-priv-key'), payload)
         except Exception, e:
            return self.deny(request, "2: " + str(e))

         hostid = str(self.services['platform'].getHostId())
         if hostid != license['host-id']:
            return self.deny(request, "3: license is for host-id '%s', but this host has host-id '%s'" % (license['host-id'], hostid))

         instanceid = str(self.services['config'].get("instance-id"))
         if instanceid != license['instance-id']:
            return self.deny(request, "4: license is for instance-id '%s', but this instance has instance-id '%s'" % (license['instance-id'], instanceid))

         validfrom = parseutc(license['valid-from'])
         validto = parseutc(license['valid-to'])
         now = datetime.datetime.utcnow()
         if now < validfrom:
            return self.deny(request, "5: license is not yet valid (license validity %s - %s, now is %s)" % (license['valid-from'], license['valid-to'], utcstr(now)))
         if now >= validto:
            return self.deny(request, "6: license is expired (license validity %s - %s, now is %s)" % (license['valid-from'], license['valid-to'], utcstr(now)))

         d = self.dbpool.runInteraction(self._activateLicense, license, payload)

         d.addCallback(lambda res: self._onLicenseActivateSuccess(res, request))
         d.addErrback(lambda res: self._onLicenseActivateError(res, request))

         return NOT_DONE_YET
Пример #2
0
    def _cookieLogin(self, txn, cookie):
        if type(cookie) not in [str, unicode]:
            raise Exception(
                URI_ERROR + "illegal-argument",
                "Expected type str/unicode for argument cookie, but got %s" %
                str(type(cookie)))

        txn.execute("SELECT created, username FROM cookie WHERE value = ?",
                    [cookie])
        res = txn.fetchone()
        if res is not None:
            created = parseutc(res[0])
            now = datetime.datetime.utcnow()
            lifetime = (now - created).total_seconds()
            expiration = self.factory.services["config"].get(
                "auth-cookie-lifetime", 600)
            if expiration > 0 and lifetime > expiration:
                txn.execute("DELETE FROM cookie WHERE value = ?", [cookie])
                raise Exception(URI_ERROR + "expired-cookie",
                                "Authentication cookie expired.")
            self.authUser = str(res[1])
            self.authCookie = cookie
            self.onLogin()
        else:
            raise Exception(URI_ERROR + "bad-cookie",
                            "Invalid authentication cookie.")
Пример #3
0
   def _cookieLogin(self, txn, cookie):
      if type(cookie) not in [str, unicode]:
         raise Exception(URI_ERROR + "illegal-argument", "Expected type str/unicode for argument cookie, but got %s" % str(type(cookie)))

      txn.execute("SELECT created, username FROM cookie WHERE value = ?", [cookie])
      res = txn.fetchone()
      if res is not None:
         created = parseutc(res[0])
         now = datetime.datetime.utcnow()
         lifetime = (now - created).total_seconds()
         expiration = self.factory.services["config"].get("auth-cookie-lifetime", 600)
         if expiration > 0 and lifetime > expiration:
            txn.execute("DELETE FROM cookie WHERE value = ?", [cookie])
            raise Exception(URI_ERROR + "expired-cookie", "Authentication cookie expired.")
         self.authUser = str(res[1])
         self.authCookie = cookie
         self.onLogin()
      else:
         raise Exception(URI_ERROR + "bad-cookie", "Invalid authentication cookie.")
Пример #4
0
    def render_POST(self, request):
        """
      The HTTP/POST to WebSockets hub Twisted/Web resource main method.
      """
        try:
            path = request.path
            args = request.args
            headers = request.getAllHeaders()

            if headers.get("content-type",
                           "missing") != 'application/x-www-form-urlencoded':
                return self.deny(
                    request, 400, "bad or missing content type ('%s')" %
                    headers.get("content-type", "missing"))

            ## FIXME: post-body-limit
            ##
            content_length = int(headers.get("content-length", 0))
            if content_length > self._getContentLengthLimit():
                return self.deny(
                    request, 400, "content length (%d) exceeds maximum (%d)" %
                    (content_length, self._getContentLengthLimit()))

            if not args.has_key("topic"):
                return self.deny(request, 400,
                                 "missing query parameter 'topic'")
            topic = args["topic"][0]

            appkey = args.get("appkey", [False])[0]
            signature = args.get("signature", [False])[0]
            timestamp_str = args.get("timestamp", [False])[0]
            if appkey or signature or timestamp_str:
                if not (appkey and signature and timestamp_str):
                    return self.deny(
                        request, 400,
                        "either all or none of parameters 'appkey', 'signature' and 'timestamp' must be present"
                    )

            if timestamp_str:
                # '2011-10-14T12:59:51Z'
                timestamp = parseutc(timestamp_str)
                if timestamp is None:
                    return self.deny(
                        request, 400,
                        "invalid timestamp '%s' (must be i.e. '2011-10-14T16:59:51Z'"
                        % timestamp_str)
                delta = int(
                    round(
                        abs(timestamp -
                            datetime.datetime.utcnow()).total_seconds()))
                if delta > self._getTimestampDeltaLimit():
                    return self.deny(
                        request, 400,
                        "timestamp expired (delta %d seconds)" % delta)
            else:
                timestamp = None

            if args.has_key('event'):
                json_str = args['event'][0]
            else:
                json_str = request.content.read()

            if appkey:
                sig = self.services["restpusher"].signature(
                    topic, appkey, timestamp_str, json_str)
                if sig is None:
                    return self.deny(request, 400,
                                     "unknown application key '%s'" % appkey)
                if sig != signature:
                    return self.deny(
                        request, 401,
                        "invalid request signature (expected %s, got %s)" %
                        (sig, signature))

            user_agent = headers.get("user-agent", "unknown")
            client_ip = request.getClientIP()
            is_secure = request.isSecure()

            auth = self.services["restpusher"].authorize(
                topic, client_ip, appkey)
            if auth[0]:

                try:
                    event = json_loads(json_str)
                except:
                    return self.deny(request, 400,
                                     "invalid JSON in request body")

                if args.has_key("exclude"):
                    exclude = [
                        x.strip() for x in args["exclude"][0].split(",")
                    ]
                else:
                    exclude = []

                if args.has_key("eligible"):
                    eligible = [
                        x.strip() for x in args["eligible"][0].split(",")
                    ]
                else:
                    eligible = None

                ## dispatch & log event
                d = self.services["appws"].dispatchHubEvent(
                    topic, event, exclude, eligible)
                d.addCallback(lambda res: self.log(user_agent,
                                                   client_ip,
                                                   is_secure,
                                                   topic,
                                                   content_length,
                                                   postrule_id=auth[1],
                                                   receiver_count=res[0],
                                                   requested_count=res[1]))
                self.stats['publish-allowed'] += 1
                self.statsChanged = True

                ## signal success to submitter
                request.setResponseCode(202)
                return ""
            else:
                return self.deny(
                    request, 401,
                    "not authorized (denied by post rule %s: %s)" %
                    (auth[1], auth[2]))

        except Exception, e:
            ## catch all .. should not happen (usually)
            return self.deny(request, 500,
                             "internal server error ('%s')" % str(e))
Пример #5
0
    def render_POST(self, request):
        """
      The HTTP/POST to WebSockets hub Twisted/Web resource main method.
      """
        try:
            path = request.path
            args = request.args
            headers = request.getAllHeaders()

            if headers.get("content-type", "missing") != "application/x-www-form-urlencoded":
                return self.deny(
                    request, 400, "bad or missing content type ('%s')" % headers.get("content-type", "missing")
                )

            ## FIXME: post-body-limit
            ##
            content_length = int(headers.get("content-length", 0))
            if content_length > self._getContentLengthLimit():
                return self.deny(
                    request,
                    400,
                    "content length (%d) exceeds maximum (%d)" % (content_length, self._getContentLengthLimit()),
                )

            if not args.has_key("topicuri"):
                return self.deny(request, 400, "missing query parameter 'topicuri'")
            topicuri = args["topicuri"][0]

            appkey = args.get("appkey", [False])[0]
            signature = args.get("signature", [False])[0]
            timestamp_str = args.get("timestamp", [False])[0]
            if appkey or signature or timestamp_str:
                if not (appkey and signature and timestamp_str):
                    return self.deny(
                        request,
                        400,
                        "either all or none of parameters 'appkey', 'signature' and 'timestamp' must be present",
                    )

            if timestamp_str:
                # '2011-10-14T12:59:51Z'
                timestamp = parseutc(timestamp_str)
                if timestamp is None:
                    return self.deny(
                        request, 400, "invalid timestamp '%s' (must be i.e. '2011-10-14T16:59:51Z'" % timestamp_str
                    )
                delta = int(round(abs(timestamp - datetime.datetime.utcnow()).total_seconds()))
                if delta > self._getTimestampDeltaLimit():
                    return self.deny(request, 400, "timestamp expired (delta %d seconds)" % delta)
            else:
                timestamp = None

            if args.has_key("body"):
                json_str = args["body"][0]
            else:
                json_str = request.content.read()

            if appkey:
                sig = self.services["restpusher"].signature(topicuri, appkey, timestamp_str, json_str)
                if sig is None:
                    return self.deny(request, 400, "unknown application key '%s'" % appkey)
                if sig != signature:
                    return self.deny(request, 401, "invalid request signature (expected %s, got %s)" % (sig, signature))

            user_agent = headers.get("user-agent", "unknown")
            client_ip = request.getClientIP()
            is_secure = request.isSecure()

            auth = self.services["restpusher"].authorize(topicuri, client_ip, appkey)
            if auth[0]:

                try:
                    event = json_loads(json_str)
                except:
                    return self.deny(request, 400, "invalid JSON in request body")

                if args.has_key("exclude"):
                    exclude = [x.strip() for x in args["exclude"][0].split(",")]
                else:
                    exclude = []

                if args.has_key("eligible"):
                    eligible = [x.strip() for x in args["eligible"][0].split(",")]
                else:
                    eligible = None

                ## dispatch & log event
                d = self.services["appws"].dispatchHubEvent(topicuri, event, exclude, eligible)
                d.addCallback(
                    lambda res: self.log(
                        user_agent,
                        client_ip,
                        is_secure,
                        topicuri,
                        content_length,
                        postrule_id=auth[1],
                        receiver_count=res[0],
                        requested_count=res[1],
                    )
                )
                self.stats["publish-allowed"] += 1
                self.statsChanged = True

                ## signal success to submitter
                request.setResponseCode(202)
                return ""
            else:
                return self.deny(request, 401, "not authorized (denied by post rule %s: %s)" % (auth[1], auth[2]))

        except Exception, e:
            ## catch all .. should not happen (usually)
            return self.deny(request, 500, "internal server error ('%s')" % str(e))
Пример #6
0
    def render_POST(self, request):
        """
      Perform license activation. The POST must contain a 'payload' field.
      Payload must be a string consisting of 3 substrings concatenated
      by comma:

         msg, key, sig

         msg: the AES encrypted license
         key: the RSA encrypted AES key
         sig: the RSA signature over the encrypted msg and key

      For details, see cryptoutil.verify_and_decrypt.
      """
        try:
            args = request.args
            headers = request.getAllHeaders()

            if headers.get("content-type",
                           "missing") != 'application/x-www-form-urlencoded':
                return self.deny(
                    request, "bad or missing content type ('%s')" %
                    headers.get("content-type", "missing"))

            if args.has_key('payload'):
                payload = request.args['payload'][0]
            else:
                return self.deny(request, "1: missing payload field")

            # remove any whitespace (also line) from payload string
            re.sub(r'\s', '', payload)

            log.msg("License activation received:")
            log.msg("Raw License: " + payload)

            try:
                license = Database.parseLicense(
                    self.services["config"].get('instance-priv-key'), payload)
            except Exception, e:
                return self.deny(request, "2: " + str(e))

            hostid = str(self.services['platform'].getHostId())
            if hostid != license['host-id']:
                return self.deny(
                    request,
                    "3: license is for host-id '%s', but this host has host-id '%s'"
                    % (license['host-id'], hostid))

            instanceid = str(self.services['config'].get("instance-id"))
            if instanceid != license['instance-id']:
                return self.deny(
                    request,
                    "4: license is for instance-id '%s', but this instance has instance-id '%s'"
                    % (license['instance-id'], instanceid))

            validfrom = parseutc(license['valid-from'])
            validto = parseutc(license['valid-to'])
            now = datetime.datetime.utcnow()
            if now < validfrom:
                return self.deny(
                    request,
                    "5: license is not yet valid (license validity %s - %s, now is %s)"
                    %
                    (license['valid-from'], license['valid-to'], utcstr(now)))
            if now >= validto:
                return self.deny(
                    request,
                    "6: license is expired (license validity %s - %s, now is %s)"
                    %
                    (license['valid-from'], license['valid-to'], utcstr(now)))

            d = self.dbpool.runInteraction(self._activateLicense, license,
                                           payload)

            d.addCallback(
                lambda res: self._onLicenseActivateSuccess(res, request))
            d.addErrback(
                lambda res: self._onLicenseActivateError(res, request))

            ## avoid module level import of reactor
            from twisted.web.server import NOT_DONE_YET

            return NOT_DONE_YET