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
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.")
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.")
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))
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))
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