Ejemplo n.º 1
0
def getSchemaVersion(conn, latestVersions):

      info = {'schema-category': None,
              'schema-version': None,
              'schema-created': None,
              'schema-latest-version': None}

      cur = conn.cursor()
      try:
         cur.execute("SELECT key, value FROM config WHERE key IN ('schema-category', 'schema-version', 'schema-created')")
         for row in cur.fetchall():
            info[row[0]] = json_loads(row[1]) if row[1] is not None else None
      except:
         pass

      if info.has_key('schema-category'):
         if latestVersions.has_key(info['schema-category']):
            info['schema-latest-version'] = latestVersions[info['schema-category']]

      if info['schema-version'] is not None:
         info['schema-needs-upgrade'] = info['schema-version'] < info['schema-latest-version']
      else:
         info['schema-needs-upgrade'] = False

      return info
Ejemplo n.º 2
0
   def _login(self, txn, authResponse, stayLoggedIn):

      if self.authChallenge is None:
         raise Exception(URI_ERROR + "login-without-previous-request", "Login attempt without previous login request.")

      txn.execute("SELECT value FROM config WHERE key = ?", ['admin-password'])
      res = txn.fetchone()
      if res:
         pw = str(json_loads(res[0]))
         h = hmac.new(pw, self.authChallenge, hashlib.sha256)
         v = binascii.b2a_base64(h.digest()).strip()
         if v == str(authResponse):
            self.authUser = self.authChallengeUser
            if stayLoggedIn:
               cookie = ''.join([random.choice("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_") for i in xrange(64)])
               now = utcnow()
               txn.execute("INSERT INTO cookie (created, username, value) VALUES (?, ?, ?)", [now, "admin", cookie])
               self.authCookie = cookie
               res = cookie
            else:
               res = None
            self.onLogin()
            return res
         else:
            raise Exception(URI_ERROR + "login-failed", "Login failed.")
      else:
         raise Exception(URI_ERROR + "internal-error", "Could not retrieve admin password from database.")
Ejemplo n.º 3
0
def getSchemaVersion(conn, latestVersions):

    info = {
        'schema-category': None,
        'schema-version': None,
        'schema-created': None,
        'schema-latest-version': None
    }

    cur = conn.cursor()
    try:
        cur.execute(
            "SELECT key, value FROM config WHERE key IN ('schema-category', 'schema-version', 'schema-created')"
        )
        for row in cur.fetchall():
            info[row[0]] = json_loads(row[1]) if row[1] is not None else None
    except:
        pass

    if info.has_key('schema-category'):
        if latestVersions.has_key(info['schema-category']):
            info['schema-latest-version'] = latestVersions[
                info['schema-category']]

    if info['schema-version'] is not None:
        info['schema-needs-upgrade'] = info['schema-version'] < info[
            'schema-latest-version']
    else:
        info['schema-needs-upgrade'] = False

    return info
Ejemplo n.º 4
0
   def _onQueryApiResult(self, res, remote, apiRequest):
      """
      Consume Ext.Direct API request result.
      """
      ## cut out JSON with API definition
      ## FIXME: make this more robust!
      i1 = res.find(remote.apiObject)
      if i1 < 0:
         raise Exception(URI_ERROR_REMOTING,
                         "API object could not be found in response payload",
                        {'message': "The API object %s could not be found in the response payload" % remote.apiObject,
                         'response': res,
                         'request': apiRequest})
      i2 = res.find("=", i1) + 1
      r = res[i2:len(res) - 1].strip()

      ## parse JSON API definition
      try:
         o = json_loads(r)
      except Exception, e:
         raise Exception(URI_ERROR_REMOTING,
                         "remoting API response payload could not be decoded",
                        {'message': str(e),
                         'response': res,
                         'json': r,
                         'request': apiRequest})
Ejemplo n.º 5
0
   def _onQueryApiResult(self, res, remote, apiRequest):
      """
      Consume Ext.Direct API request result.
      """
      ## cut out JSON with API definition
      ## FIXME: make this more robust!
      i1 = res.find(remote.apiObject)
      if i1 < 0:
         raise Exception(URI_ERROR_REMOTING,
                         "API object could not be found in response payload",
                        {'message': "The API object %s could not be found in the response payload" % remote.apiObject,
                         'response': res,
                         'request': apiRequest})
      i2 = res.find("=", i1) + 1
      r = res[i2:len(res) - 1].strip()

      ## parse JSON API definition
      try:
         o = json_loads(r)
      except Exception, e:
         raise Exception(URI_ERROR_REMOTING,
                         "remoting API response payload could not be decoded",
                        {'message': str(e),
                         'response': res,
                         'json': r,
                         'request': apiRequest})
Ejemplo n.º 6
0
 def _getPasswordSet(self, txn):
    txn.execute("SELECT value FROM config WHERE key = ?", ["admin-password"])
    res = txn.fetchone()
    if res:
       password = json_loads(res[0])
       return password is not None
    else:
       raise Exception(URI_ERROR + "internal-error", "admin-password key not found.")
Ejemplo n.º 7
0
def _setupSchema(app, conn, uninstallOnly = False):

   cf = os.path.join(app.webdata, "demo", "demo.json")
   try:
      cfo = json_loads(open(cf).read())
   except Exception, e:
      log.msg("Could not read Oracle demo schema spec [%s]" % e)
      raise e
Ejemplo n.º 8
0
 def _getEulaAccepted(self, txn):
    txn.execute("SELECT value FROM config WHERE key = ?", ["eula-accepted"])
    res = txn.fetchone()
    if res:
       eula_accepted = json_loads(res[0])
       return eula_accepted
    else:
       raise Exception(URI_ERROR + "internal-error", "eula-accepted key not found.")
Ejemplo n.º 9
0
 def _getAuthSecret(self, txn):
    txn.execute("SELECT value FROM config WHERE key = ?", ['admin-password'])
    res = txn.fetchone()
    if res:
       pw = str(json_loads(res[0]))
       return pw
    else:
       raise Exception(URI_ERROR + "internal-error", "Could not retrieve admin password from database.")
Ejemplo n.º 10
0
    def _modifyConfig(self, txn, configDelta):
        ## determine actual set of modified stuff
        ##
        modified = {}
        for c in configDelta:
            txn.execute("SELECT value FROM config WHERE key = ?", [
                c,
            ])
            res = txn.fetchone()
            if res:
                cval = json_loads(res[0])
                if cval != configDelta[c]:
                    modified[c] = configDelta[c]
                    txn.execute("UPDATE config SET value = ? WHERE key = ?",
                                [json_dumps(configDelta[c]), c])

        ## only something to do when there was an actual change
        ##
        if len(modified) > 0:
            ## recache config
            ##
            services = self.proto.factory.services
            if services.has_key("config"):
                services["config"].recache(txn)

            ## check if WebSocket option changed .. if so, notify WS factory
            ##
            wsOptionChanged = False
            for k in modified:
                if k[:2] == 'ws':
                    wsOptionChanged = True
                    break
            if wsOptionChanged:
                if self.proto.factory.services.has_key("appws"):
                    self.proto.factory.services["appws"].setOptionsFromConfig()
                if self.proto.factory.services.has_key("echows"):
                    self.proto.factory.services["echows"].setOptionsFromConfig(
                    )

            ## check for restart required
            ##
            for k in modified:
                if k in Database.SERVICES:
                    self.proto.factory.issueRestartRequired()

            ## notify subscribers
            ##
            self.proto.dispatch(URI_EVENT + "on-config-modified", modified,
                                [self.proto])

            ## return modified set to caller
            ##
            return modified
        else:
            ## nothing changed
            ##
            return {}
Ejemplo n.º 11
0
 def _getSingleConfig(self, txn, key):
    txn.execute("SELECT value FROM config WHERE key = ?", [key,])
    res = txn.fetchone()
    if res:
       val = json_loads(res[0])
       if key in Database.NETPORTS_TLS_KEYS and val is not None:
          val = self.proto.shrink(URI_SERVICEKEY + val)
       return val
    else:
       raise Exception(URI_ERROR + "invalid-config-parameter", "No configuration parameter '%s'" % key)
Ejemplo n.º 12
0
 def _getEulaAccepted(self, txn):
     txn.execute("SELECT value FROM config WHERE key = ?",
                 ["eula-accepted"])
     res = txn.fetchone()
     if res:
         eula_accepted = json_loads(res[0])
         return eula_accepted
     else:
         raise Exception(URI_ERROR + "internal-error",
                         "eula-accepted key not found.")
Ejemplo n.º 13
0
 def _getAllConfig(self, txn):
    txn.execute("SELECT key, value FROM config ORDER BY key")
    res = {}
    for r in txn.fetchall():
       key = r[0]
       val = json_loads(r[1])
       if key in Database.NETPORTS_TLS_KEYS and val is not None:
          val = self.proto.shrink(URI_SERVICEKEY + val)
       res[key] = val
    return res
Ejemplo n.º 14
0
 def _getAllConfig(self, txn):
     txn.execute("SELECT key, value FROM config ORDER BY key")
     res = {}
     for r in txn.fetchall():
         key = r[0]
         val = json_loads(r[1])
         if key in Database.NETPORTS_TLS_KEYS and val is not None:
             val = self.proto.shrink(URI_SERVICEKEY + val)
         res[key] = val
     return res
Ejemplo n.º 15
0
 def _getPasswordSet(self, txn):
     txn.execute("SELECT value FROM config WHERE key = ?",
                 ["admin-password"])
     res = txn.fetchone()
     if res:
         password = json_loads(res[0])
         return password is not None
     else:
         raise Exception(URI_ERROR + "internal-error",
                         "admin-password key not found.")
Ejemplo n.º 16
0
 def _getAuthSecret(self, txn):
     txn.execute("SELECT value FROM config WHERE key = ?",
                 ['admin-password'])
     res = txn.fetchone()
     if res:
         pw = str(json_loads(res[0]))
         return pw
     else:
         raise Exception(
             URI_ERROR + "internal-error",
             "Could not retrieve admin password from database.")
Ejemplo n.º 17
0
   def _changePassword(self, txn, oldpassword, newpassword1, newpassword2):
      attrs = {"oldpassword": (True,
                               [str, unicode],
                               AdminWebSocketProtocol.USER_PASSWORD_MIN_LENGTH,
                               AdminWebSocketProtocol.USER_PASSWORD_MAX_LENGTH,
                               AdminWebSocketProtocol.USER_PASSWORD_PATTERN),
               "newpassword1": (True,
                                [str, unicode],
                                AdminWebSocketProtocol.USER_PASSWORD_MIN_LENGTH,
                                AdminWebSocketProtocol.USER_PASSWORD_MAX_LENGTH,
                                AdminWebSocketProtocol.USER_PASSWORD_PATTERN),
               "newpassword2": (True,
                                [str, unicode],
                                AdminWebSocketProtocol.USER_PASSWORD_MIN_LENGTH,
                                AdminWebSocketProtocol.USER_PASSWORD_MAX_LENGTH,
                                AdminWebSocketProtocol.USER_PASSWORD_PATTERN)}

      errcnt, errs = self.checkDictArg("user password",
                                       {"oldpassword": oldpassword,
                                        "newpassword1": newpassword1,
                                        "newpassword2": newpassword2},
                                       attrs)

      if newpassword1 != newpassword2:
         errcnt += 1
         if not errs.has_key('newpassword1') or errs.has_key('newpassword2'):
            p = 'newpassword1'
         else:
            p = 'newpassword2'
         if not errs.has_key(p):
            errs[p] = []
         errs[p].append((self.shrink(URI_ERROR + "invalid-attribute-value"), "New password values do not match"))

      if errcnt:
         raise Exception(URI_ERROR + "illegal-argument", "one or more illegal arguments (%d errors)" % errcnt, errs)

      txn.execute("SELECT value FROM config WHERE key = ?", ['admin-password'])
      res = txn.fetchone()
      if res:
         pw = str(json_loads(res[0]))
         if pw == oldpassword:
            if newpassword1 != oldpassword:
               txn.execute("UPDATE config SET value = ? WHERE key = ?", [json_dumps(newpassword1), "admin-password"])
            else:
               raise Exception(URI_ERROR + "illegal-argument",
                               "one or more illegal arguments (%d errors)" % 2,
                               {'newpassword1': [(self.shrink(URI_ERROR + "attribute-value-unchanged"), "Password unchanged")],
                                'newpassword2': [(self.shrink(URI_ERROR + "attribute-value-unchanged"), "Password unchanged")]})
         else:
            raise Exception(URI_ERROR + "illegal-argument",
                            "one or more illegal arguments (%d errors)" % 1,
                            {'oldpassword': [(self.shrink(URI_ERROR + "invalid-attribute-value"), "Old password is invalid")]})
      else:
         raise Exception(URI_ERROR + "internal-error", "Could not retrieve admin password from database.")
Ejemplo n.º 18
0
 def _onRemoteCallResult(self, r, remotingRequest):
    """
    Consume Ext.Direct remoting result. Note that this still can trigger a WAMP exception.
    """
    try:
       res = json_loads(r)
    except Exception, e:
       raise Exception(URI_ERROR_REMOTING,
                       "response payload could not be decoded",
                      {'message': str(e),
                       'response': r,
                       'request': remotingRequest})
Ejemplo n.º 19
0
 def _onRemoteCallResult(self, r, remotingRequest):
    """
    Consume Ext.Direct remoting result. Note that this still can trigger a WAMP exception.
    """
    try:
       res = json_loads(r)
    except Exception, e:
       raise Exception(URI_ERROR_REMOTING,
                       "response payload could not be decoded",
                      {'message': str(e),
                       'response': r,
                       'request': remotingRequest})
Ejemplo n.º 20
0
   def _modifyConfig(self, txn, configDelta):
      ## determine actual set of modified stuff
      ##
      modified = {}
      for c in configDelta:
         txn.execute("SELECT value FROM config WHERE key = ?", [c,])
         res = txn.fetchone()
         if res:
            cval = json_loads(res[0])
            if cval != configDelta[c]:
               modified[c] = configDelta[c]
               txn.execute("UPDATE config SET value = ? WHERE key = ?", [json_dumps(configDelta[c]), c])

      ## only something to do when there was an actual change
      ##
      if len(modified) > 0:
         ## recache config
         ##
         services = self.proto.factory.services
         if services.has_key("config"):
           services["config"].recache(txn)

         ## check if WebSocket option changed .. if so, notify WS factory
         ##
         wsOptionChanged = False
         for k in modified:
            if k[:2] == 'ws':
               wsOptionChanged = True
               break
         if wsOptionChanged:
            if self.proto.factory.services.has_key("appws"):
               self.proto.factory.services["appws"].setOptionsFromConfig()
            if self.proto.factory.services.has_key("echows"):
               self.proto.factory.services["echows"].setOptionsFromConfig()

         ## check for restart required
         ##
         for k in modified:
            if k in Database.SERVICES:
               self.proto.factory.issueRestartRequired()

         ## notify subscribers
         ##
         self.proto.dispatch(URI_EVENT + "on-config-modified", modified, [self.proto])

         ## return modified set to caller
         ##
         return modified
      else:
         ## nothing changed
         ##
         return {}
Ejemplo n.º 21
0
 def _getSingleConfig(self, txn, key):
     txn.execute("SELECT value FROM config WHERE key = ?", [
         key,
     ])
     res = txn.fetchone()
     if res:
         val = json_loads(res[0])
         if key in Database.NETPORTS_TLS_KEYS and val is not None:
             val = self.proto.shrink(URI_SERVICEKEY + val)
         return val
     else:
         raise Exception(URI_ERROR + "invalid-config-parameter",
                         "No configuration parameter '%s'" % key)
Ejemplo n.º 22
0
    def loop(self):
        import time
        import pyodbc

        conn = pyodbc.connect(self.connectstr)
        cur1 = conn.cursor()
        cur2 = conn.cursor()

        cur1.execute(
            "SELECT COALESCE(MAX(id), 0), COALESCE(MIN(id), 0), COUNT(*) FROM crossbar.event"
        )
        (id, minid, evtcnt) = cur1.fetchone()

        while not self.stopped:
            cur1.execute(
                "SELECT id, pushed_by, topic, payload_type, payload FROM crossbar.event WHERE id > ? ORDER BY id ASC",
                [id])
            oldid = id
            for r in cur1.fetchall():

                id = r[0]
                pushedBy = r[1]
                topic = r[2]
                payload = None

                if r[4] is not None:

                    ## JSON payload
                    if r[3] == 2:
                        try:
                            payload = json_loads(r[4])
                        except Exception, e:
                            log.msg("%s - INVALID JSON PAYLOAD - %s" %
                                    (r[4], str(e)))

                    ## plain string payload
                    elif r[3] == 1:
                        payload = r[4]

                    else:
                        log.msg("INVALID PAYLOAD TYPE %s" % r[4])

                reactor.callFromThread(self.pusher, self.hanaconnectId,
                                       pushedBy, topic, payload)

            if self.purge and id > oldid:
                cur2.execute("DELETE FROM crossbar.event WHERE id <= ?", id)
                conn.commit()

            if self.throttle > 0:
                time.sleep(self.throttle)
Ejemplo n.º 23
0
    def _setPassword(self, txn, password1, password2):
        txn.execute("SELECT value FROM config WHERE key = ?",
                    ['admin-password'])
        res = txn.fetchone()
        if res:
            pw = json_loads(res[0])
            if pw is not None:
                raise Exception((URI_ERROR + "invalid-invocation",
                                 "Initial password already set."))
        else:
            raise Exception(
                URI_ERROR + "internal-error",
                "Could not retrieve admin password from database.")

        attrs = {
            "password1":
            (True, [str,
                    unicode], AdminWebSocketProtocol.USER_PASSWORD_MIN_LENGTH,
             AdminWebSocketProtocol.USER_PASSWORD_MAX_LENGTH,
             AdminWebSocketProtocol.USER_PASSWORD_PATTERN),
            "password2":
            (True, [str,
                    unicode], AdminWebSocketProtocol.USER_PASSWORD_MIN_LENGTH,
             AdminWebSocketProtocol.USER_PASSWORD_MAX_LENGTH,
             AdminWebSocketProtocol.USER_PASSWORD_PATTERN)
        }

        errcnt, errs = self.checkDictArg("user password", {
            "password1": password1,
            "password2": password2
        }, attrs)

        if password1 != password2:
            errcnt += 1
            if not errs.has_key('password1') or errs.has_key('password2'):
                p = 'password1'
            else:
                p = 'password2'
            if not errs.has_key(p):
                errs[p] = []
            errs[p].append((self.shrink(URI_ERROR + "invalid-attribute-value"),
                            "Passwords do not match"))

        if errcnt:
            raise Exception(
                URI_ERROR + "illegal-argument",
                "one or more illegal arguments (%d errors)" % errcnt, errs)

        txn.execute("UPDATE config SET value = ? WHERE key = ?",
                    [json_dumps(password1), "admin-password"])
Ejemplo n.º 24
0
 def _acceptEula(self, txn):
    txn.execute("SELECT value FROM config WHERE key = ?", ["eula-accepted"])
    res = txn.fetchone()
    if res:
       eula_accepted = json_loads(res[0])
       if eula_accepted:
          raise Exception(URI_ERROR + "illegal-invocation", "EULA already accepted.")
       else:
          now = utcnow()
          txn.execute("UPDATE config SET value = ? WHERE key = ?", [json_dumps(now), "eula-accepted"])
          self.factory.services["config"].recache(txn)
          return now
    else:
       raise Exception(URI_ERROR + "internal-error", "EULA key not found.")
Ejemplo n.º 25
0
    def loop(self):
        import time
        import pyodbc

        conn = pyodbc.connect(self.connectstr)
        cur1 = conn.cursor()
        cur2 = conn.cursor()

        cur1.execute("SELECT COALESCE(MAX(id), 0), COALESCE(MIN(id), 0), COUNT(*) FROM crossbar.event")
        (id, minid, evtcnt) = cur1.fetchone()

        while not self.stopped:
            cur1.execute(
                "SELECT id, pushed_by, topic, payload_type, payload FROM crossbar.event WHERE id > ? ORDER BY id ASC",
                [id],
            )
            oldid = id
            for r in cur1.fetchall():

                id = r[0]
                pushedBy = r[1]
                topic = r[2]
                payload = None

                if r[4] is not None:

                    ## JSON payload
                    if r[3] == 2:
                        try:
                            payload = json_loads(r[4])
                        except Exception, e:
                            log.msg("%s - INVALID JSON PAYLOAD - %s" % (r[4], str(e)))

                    ## plain string payload
                    elif r[3] == 1:
                        payload = r[4]

                    else:
                        log.msg("INVALID PAYLOAD TYPE %s" % r[4])

                reactor.callFromThread(self.pusher, self.hanaconnectId, pushedBy, topic, payload)

            if self.purge and id > oldid:
                cur2.execute("DELETE FROM crossbar.event WHERE id <= ?", id)
                conn.commit()

            if self.throttle > 0:
                time.sleep(self.throttle)
Ejemplo n.º 26
0
 def _getConfigChangeset(self, txn, attrs, delta):
     all = delta.copy()
     changed = {}
     ss = ""
     for p in attrs:
         ss += "'%s'," % p
     ss = ss[:-1]
     txn.execute("SELECT key, value FROM config WHERE key IN (" + ss + ")")
     for r in txn.fetchall():
         val = json_loads(r[1])
         if not all.has_key(r[0]):
             all[r[0]] = val
         else:
             if all[r[0]] != val:
                 changed[r[0]] = all[r[0]]
     return (all, changed)
Ejemplo n.º 27
0
 def _getConfigChangeset(self, txn, attrs, delta):
    all = delta.copy()
    changed = {}
    ss = ""
    for p in attrs:
       ss += "'%s'," % p
    ss = ss[:-1]
    txn.execute("SELECT key, value FROM config WHERE key IN (" + ss + ")")
    for r in txn.fetchall():
       val = json_loads(r[1])
       if not all.has_key(r[0]):
          all[r[0]] = val
       else:
          if all[r[0]] != val:
             changed[r[0]] = all[r[0]]
    return (all, changed)
Ejemplo n.º 28
0
   def _loadObject(self, txn, uri):
      ## check arguments
      ##
      if type(uri) not in [str, unicode]:
         raise Exception(URI_ERROR + "illegal-argument", "Expected type str/unicode for argument uri, but got %s" % str(type(uri)))

      ## resolve URI
      ##
      uri = self.proto.resolveOrPass(uri)

      txn.execute("SELECT obj FROM objstore WHERE uri = ?", [uri])
      res = txn.fetchone()
      if res is not None:
         obj = json_loads(res[0])
         return obj
      else:
         return None
Ejemplo n.º 29
0
 def _acceptEula(self, txn):
     txn.execute("SELECT value FROM config WHERE key = ?",
                 ["eula-accepted"])
     res = txn.fetchone()
     if res:
         eula_accepted = json_loads(res[0])
         if eula_accepted:
             raise Exception(URI_ERROR + "illegal-invocation",
                             "EULA already accepted.")
         else:
             now = utcnow()
             txn.execute("UPDATE config SET value = ? WHERE key = ?",
                         [json_dumps(now), "eula-accepted"])
             self.factory.services["config"].recache(txn)
             return now
     else:
         raise Exception(URI_ERROR + "internal-error",
                         "EULA key not found.")
Ejemplo n.º 30
0
    def _storeObject(self, txn, uri, obj):
        ## check arguments
        ##
        if type(uri) not in [str, unicode]:
            raise Exception(
                URI_ERROR + "illegal-argument",
                "Expected type str/unicode for argument uri, but got %s" %
                str(type(uri)))

        ## resolve URI
        ##
        uri = self.proto.resolveOrPass(uri)
        modified = True

        txn.execute("SELECT obj FROM objstore WHERE uri = ?", [uri])
        res = txn.fetchone()
        if res is not None:
            oldobj = json_loads(res[0])
            if obj is not None:
                objser = json_dumps(obj)
                if objser != res[0]:
                    txn.execute("UPDATE objstore SET obj = ? WHERE uri = ?",
                                [objser, uri])
                else:
                    modified = False
            else:
                txn.execute("DELETE FROM objstore WHERE uri = ?", [uri])
        else:
            oldobj = None
            if obj is not None:
                objser = json_dumps(obj)
                txn.execute("INSERT INTO objstore (uri, obj) VALUES (?, ?)",
                            [uri, objser])
            else:
                modified = False

        if modified:
            event = {'uri': uri, 'old': oldobj, 'new': obj}
            self.proto.dispatch(URI_EVENT + "on-store-modified", event,
                                [self.proto])
            event["uri"] = self.proto.shrink(uri)
            return event
        else:
            return None
Ejemplo n.º 31
0
    def _loadObject(self, txn, uri):
        ## check arguments
        ##
        if type(uri) not in [str, unicode]:
            raise Exception(
                URI_ERROR + "illegal-argument",
                "Expected type str/unicode for argument uri, but got %s" %
                str(type(uri)))

        ## resolve URI
        ##
        uri = self.proto.resolveOrPass(uri)

        txn.execute("SELECT obj FROM objstore WHERE uri = ?", [uri])
        res = txn.fetchone()
        if res is not None:
            obj = json_loads(res[0])
            return obj
        else:
            return None
Ejemplo n.º 32
0
   def _storeObject(self, txn, uri, obj):
      ## check arguments
      ##
      if type(uri) not in [str, unicode]:
         raise Exception(URI_ERROR + "illegal-argument", "Expected type str/unicode for argument uri, but got %s" % str(type(uri)))

      ## resolve URI
      ##
      uri = self.proto.resolveOrPass(uri)
      modified = True

      txn.execute("SELECT obj FROM objstore WHERE uri = ?", [uri])
      res = txn.fetchone()
      if res is not None:
         oldobj = json_loads(res[0])
         if obj is not None:
            objser = json_dumps(obj)
            if objser != res[0]:
               txn.execute("UPDATE objstore SET obj = ? WHERE uri = ?", [objser, uri])
            else:
               modified = False
         else:
            txn.execute("DELETE FROM objstore WHERE uri = ?", [uri])
      else:
         oldobj = None
         if obj is not None:
            objser = json_dumps(obj)
            txn.execute("INSERT INTO objstore (uri, obj) VALUES (?, ?)", [uri, objser])
         else:
            modified = False

      if modified:
         event = {'uri': uri, 'old': oldobj, 'new': obj}
         self.proto.dispatch(URI_EVENT + "on-store-modified", event, [self.proto])
         event["uri"] = self.proto.shrink(uri)
         return event
      else:
         return None
Ejemplo n.º 33
0
   def _setPassword(self, txn, password1, password2):
      txn.execute("SELECT value FROM config WHERE key = ?", ['admin-password'])
      res = txn.fetchone()
      if res:
         pw = json_loads(res[0])
         if pw is not None:
            raise Exception((URI_ERROR + "invalid-invocation", "Initial password already set."))
      else:
         raise Exception(URI_ERROR + "internal-error", "Could not retrieve admin password from database.")

      attrs = {"password1": (True,
                             [str, unicode],
                             AdminWebSocketProtocol.USER_PASSWORD_MIN_LENGTH,
                             AdminWebSocketProtocol.USER_PASSWORD_MAX_LENGTH,
                             AdminWebSocketProtocol.USER_PASSWORD_PATTERN),
               "password2": (True,
                             [str, unicode],
                             AdminWebSocketProtocol.USER_PASSWORD_MIN_LENGTH,
                             AdminWebSocketProtocol.USER_PASSWORD_MAX_LENGTH,
                             AdminWebSocketProtocol.USER_PASSWORD_PATTERN)}

      errcnt, errs = self.checkDictArg("user password", {"password1": password1, "password2": password2}, attrs)

      if password1 != password2:
         errcnt += 1
         if not errs.has_key('password1') or errs.has_key('password2'):
            p = 'password1'
         else:
            p = 'password2'
         if not errs.has_key(p):
            errs[p] = []
         errs[p].append((self.shrink(URI_ERROR + "invalid-attribute-value"), "Passwords do not match"))

      if errcnt:
         raise Exception(URI_ERROR + "illegal-argument", "one or more illegal arguments (%d errors)" % errcnt, errs)

      txn.execute("UPDATE config SET value = ? WHERE key = ?", [json_dumps(password1), "admin-password"])
Ejemplo n.º 34
0
    def _login(self, txn, authResponse, stayLoggedIn):

        if self.authChallenge is None:
            raise Exception(URI_ERROR + "login-without-previous-request",
                            "Login attempt without previous login request.")

        txn.execute("SELECT value FROM config WHERE key = ?",
                    ['admin-password'])
        res = txn.fetchone()
        if res:
            pw = str(json_loads(res[0]))
            h = hmac.new(pw, self.authChallenge, hashlib.sha256)
            v = binascii.b2a_base64(h.digest()).strip()
            if v == str(authResponse):
                self.authUser = self.authChallengeUser
                if stayLoggedIn:
                    cookie = ''.join([
                        random.choice(
                            "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
                        ) for i in xrange(64)
                    ])
                    now = utcnow()
                    txn.execute(
                        "INSERT INTO cookie (created, username, value) VALUES (?, ?, ?)",
                        [now, "admin", cookie])
                    self.authCookie = cookie
                    res = cookie
                else:
                    res = None
                self.onLogin()
                return res
            else:
                raise Exception(URI_ERROR + "login-failed", "Login failed.")
        else:
            raise Exception(
                URI_ERROR + "internal-error",
                "Could not retrieve admin password from database.")
Ejemplo n.º 35
0
         offset = error.offset
         message = error.message
         context = error.context

         ## handle crossbar.io application errors
         ##
         if code == 20999:

            ## extract crossbar.io application error payload
            ##
            try:
               lines = message.splitlines()
               fl = lines[0]
               i = fl.find(':') + 2
               s = fl[i:].strip()
               o = json_loads(s)
               rest = '\n'.join(lines[1:])
            except:
               o = {}
               rest = message

            if o.has_key('uri'):
               uri = o['uri']
            else:
               uri = URI_ERROR_SQL + ("%d" % code)

            if o.has_key('desc'):
               #m = "%s\n%s" % (o['desc'], rest)
               m = o['desc']
            else:
               m = rest
Ejemplo n.º 36
0
 def getApplianceVersion(self):
    try:
       o = json_loads(open("/etc/appliance.json").read())
       return o["image"]
    except:
       return "unknown"
Ejemplo n.º 37
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))
Ejemplo n.º 38
0
 def _cacheConfig(self, res):
    self._config = {}
    for r in res:
       self._config[r[0]] = json_loads(r[1])
    log.msg("Config._cacheConfig (%d)" % len(self._config))
Ejemplo n.º 39
0
class OraPushClient(DbPushClient):
   """
   Oracle Push Client.
   """

   LOGID = "OraPushClient"

   def loop(self):

      ## use DBMS_PIPE based notification
      self.usePipe = True

      ## DBMS_PIPE.receive_message timeout in secs
      self.pipeTimeout = int(1)

      ## Iff true, recheck event table on every pipe timeout
      self.recheckOnPipeTimeout = False

      import time, json

      import os
      os.environ["NLS_LANG"] = "AMERICAN_AMERICA.UTF8"

      import cx_Oracle

      try:
         dsn = cx_Oracle.makedsn(self.connect.host,
                                 self.connect.port,
                                 self.connect.sid)
         self.conn = cx_Oracle.connect(self.connect.user,
                                       self.connect.password,
                                       dsn,
                                       threaded = False)
         self.conn.autocommit = True
         log.msg("pusher Oracle connection established")
      except Exception, e:
         #log.msg(str(e))
         raise e


      ## verify that we are the only pusher connected to this DB
      ## by allocating an X-lock.
      ## FIXME:
      ##   - the lock is not schema-wise, but instance wise
      ##   - we should cover the whole crossbar.io/Oracle integration (not only the pusher)
      cur = self.conn.cursor()
      cur.prepare("""
         DECLARE
            l_lockhandle VARCHAR2(128);
         BEGIN
           DBMS_LOCK.ALLOCATE_UNIQUE('crossbar', l_lockhandle);
           :retval := DBMS_LOCK.REQUEST(l_lockhandle, DBMS_LOCK.X_MODE, 0, FALSE);
         END;
      """)
      curVars = cur.setinputsizes(retval = cx_Oracle.NUMBER)
      cur.execute(None)
      retval = int(curVars["retval"].getvalue())
      if retval != 0:
         rmap = {0: "Success",
                 1: "Timeout",
                 2: "Deadlock",
                 3: "Parameter error",
                 4: "Don't own lock specified by id or lockhandle",
                 5: "Illegal lock handle"}
         raise Exception("There seems to be another pusher connected [lock result %d - %s]" % (retval, rmap.get(retval, "??")))
      else:
         log.msg("Ok, we are the only pusher connected to the Oracle instance")


      self.isConnected = True
      self.pusher.publishPusherStateChange(self.connect.id, True, True)

      cur = self.conn.cursor()

      cur.execute("SELECT sys_context('USERENV', 'SESSION_USER') FROM dual")
      session_user = cur.fetchone()[0].upper()

      cur.execute("""
                  BEGIN
                     DBMS_SESSION.SET_IDENTIFIER(:1);
                  END;
                  """, ['CROSSBAR_%s_PUSHER_%s' % (session_user, self.connect.id)])

      ## when using DBMS_PIPE, the name of the event pipe
      PIPENAME = 'CROSSBAR_%s_ONPUBLISH' % session_user
      print "using pipe", PIPENAME

      ## if using pipe mode, prepare for that
      ##
      if self.usePipe:
         cur.execute("""
                     BEGIN
                        SYS.DBMS_PIPE.purge(:pipename);
                     END;
                     """, pipename = PIPENAME)

         curWaitPipe = self.conn.cursor()
         curWaitPipe.prepare("""
                             BEGIN
                                :retval := SYS.DBMS_PIPE.receive_message(:pipename, :timeout);
                                IF :retval = 0 THEN
                                   SYS.DBMS_PIPE.unpack_message(:event_id);
                                   SYS.DBMS_PIPE.purge(:pipename);
                                END IF;
                             END;
                             """)
         curWaitPipeVars = curWaitPipe.setinputsizes(retval = cx_Oracle.NUMBER,
                                                     pipename = cx_Oracle.STRING,
                                                     timeout = cx_Oracle.NUMBER,
                                                     event_id = cx_Oracle.NUMBER)
         pipePipename = curWaitPipeVars["pipename"]
         pipePipename.setvalue(0, PIPENAME)

         pipeTimeout = curWaitPipeVars["timeout"]
         pipeTimeout.setvalue(0, self.pipeTimeout)

         pipeRetVal = curWaitPipeVars["retval"]
         pipeEventId = curWaitPipeVars["event_id"]


      ## setup stuff for getting unprocessed events
      ##
      curGetEvents = self.conn.cursor()
      curGetEvents.prepare("""
                           SELECT id,
                                  published_by,
                                  topic,
                                  qos,
                                  payload_type,
                                  payload_str,
                                  payload_lob,
                                  exclude_sids,
                                  eligible_sids
                            FROM
                               event WHERE id > :id AND processed_at IS NULL
                            ORDER BY id ASC
                            """)
      curGetEventsVars = curGetEvents.setinputsizes(id = cx_Oracle.NUMBER)
      getFromEventId = curGetEventsVars["id"]


      ## setup stuff for purging/marking processed events
      ##
      if self.purge:
         curDeleteEvents = self.conn.cursor()
         curDeleteEvents.prepare("""DELETE FROM event WHERE id = :id""")
         curDeleteEventsVars = curDeleteEvents.setinputsizes(id = cx_Oracle.NUMBER)
         deleteEventId = curDeleteEventsVars["id"]
      else:
         curMarkEvents = self.conn.cursor()
         curMarkEvents.prepare("""
                               UPDATE event SET processed_at = systimestamp at time zone 'utc',
                                                processed_status = :processed_status,
                                                processed_errmsg = :processed_errmsg,
                                                processed_len = :processed_len
                                 WHERE id = :id""")
         curMarkEventsVars = curMarkEvents.setinputsizes(id = cx_Oracle.NUMBER,
                                                         processed_status = cx_Oracle.NUMBER,
                                                         processed_errmsg = cx_Oracle.STRING,
                                                         processed_len = cx_Oracle.NUMBER)
         markEventId = curMarkEventsVars["id"]
         markEventProcessedStatus = curMarkEventsVars["processed_status"]
         markEventProcessedErrMsg = curMarkEventsVars["processed_errmsg"]
         markEventProcessedLen = curMarkEventsVars["processed_len"]


      ## setup stuff for tracking stats of processed events
      ##
      if self._trackDispatched:
         curTrackEvents = self.conn.cursor()
         curTrackEvents.prepare("""
                               UPDATE event SET dispatch_status = :dispatch_status,
                                                dispatch_success = :dispatch_success,
                                                dispatch_failed = :dispatch_failed
                                 WHERE id = :id""")
         curTrackEventsVars = curTrackEvents.setinputsizes(id = cx_Oracle.NUMBER,
                                                           dispatch_status = cx_Oracle.NUMBER,
                                                           dispatch_success = cx_Oracle.NUMBER,
                                                           dispatch_failed = cx_Oracle.NUMBER)
         trackEventId = curTrackEventsVars["id"]
         trackDispatchStatus = curTrackEventsVars["dispatch_status"]
         trackDispatchSuccess = curTrackEventsVars["dispatch_success"]
         trackDispatchFailed = curTrackEventsVars["dispatch_failed"]


      ## check current contents of event table
      ##
      cur.execute("SELECT NVL(MIN(id), 0), NVL(MAX(id), 0), COUNT(*) FROM event WHERE processed_at IS NULL")
      (minId, maxId, evtCnt) = cur.fetchone()

      ## event ID after we will start processing events ..
      ##
      id = None

      ## purge or mark events left over since we were offline
      ##
      if evtCnt > 0:
         if not self.processOldEvents:
            log.msg("skipping %d events accumulated since we were offline [purge = %s]" % (evtCnt, self.purge))
            if self.purge:
               cur.execute("""
                           DELETE FROM event
                              WHERE id >= :1 AND
                                    id <= :2 AND
                                    processed_at IS NULL""",
                                    [minId,
                                     maxId])
               #self.conn.commit()
            else:
               processed_status = 5
               processed_errmsg = None
               cur.execute("""
                           UPDATE event
                              SET processed_at = systimestamp at time zone 'utc',
                                  processed_status = :1,
                                  processed_errmsg = :2
                              WHERE
                                  id >= :3 AND
                                  id <= :4 AND
                                  processed_at IS NULL""",
                                  [processed_status,
                                   processed_errmsg[:4000] if processed_errmsg is not None else None,
                                   minId,
                                   maxId])
               #self.conn.commit()

            ## start processing only with new events (skipping events that accumulated while we were offline)
            id = maxId
         else:
            log.msg("%d events accumulated since we were offline - will process those now" % evtCnt)

            ## start processing at events that accumulated while we were offline
            id = minId - 1
      else:
         log.msg("no events accumulated since we were offline")

         ## start processing with new events
         id = maxId

      ## inner loop, will run until we get stop()'ed
      ##
      while not self.stopped:

         checkAgain = True
         while checkAgain:

            if self.trackDispatched:
               while self.dispatched and len(self.dispatched) > 0:
                  trackedEventId, dispatch_status, dispatch_success, dispatch_failed = self.dispatched.popleft()
                  trackEventId.setvalue(0, trackedEventId)
                  trackDispatchStatus.setvalue(0, dispatch_status)
                  trackDispatchSuccess.setvalue(0, dispatch_success)
                  trackDispatchFailed.setvalue(0, dispatch_failed)
                  curTrackEvents.execute(None)
                  #self.conn.commit()


            ## we do this rather low-level with a cursor loop, since
            ## we process CLOB columns
            ##
            gotRows = 0

            #cur.execute("""SELECT id,
            #                      published_by,
            #                      topic,
            #                      qos,
            #                      payload_type,
            #                      payload_str,
            #                      payload_lob,
            #                      exclude_sids,
            #                      eligible_sids
            #                FROM
            #                   event WHERE id > :1 AND processed_at IS NULL
            #                ORDER BY id ASC""", [id])

            getFromEventId.setvalue(0, id)
            curGetEvents.execute(None)

            doFetch = True
            while doFetch:
               #r = cur.fetchone()
               r = curGetEvents.fetchone()
               if r is not None:
                  gotRows += 1

                  ## processed_status:
                  ##
                  ##     0 - ok
                  ##     1 - invalid event topic URI
                  ##     2 - illegal event payload type
                  ##     3 - invalid event payload
                  ##     4 - illegal event qos type
                  ##     5 - unprocessed old event (got published as we were offline)
                  ##
                  processed_status = 0 # default to valid processing
                  processed_errmsg = None # filled when processed_status != 0

                  id = r[0]
                  pushedBy = r[1]
                  topic = r[2]
                  qos = r[3]
                  payload_type = r[4]

                  if r[6] is not None:
                     ## cx_Oracle.LOB object
                     payload_raw_len = r[6].size()
                     payload_raw = r[6].read()
                  else:
                     ## cx_Oracle.STRING
                     if r[5] is not None:
                        payload_raw_len = len(r[5])
                        payload_raw = r[5]
                     else:
                        payload_raw_len = 0
                        payload_raw = None

                  payload = None
                  exclude = r[7] if r[7] is not None else []
                  eligible = r[8] if r[8] is not None else None

                  ## validate/parse event
                  ##
                  if processed_status == 0:
                     uriValid, result = validateUri(topic)
                     if not uriValid:
                        processed_status = 1
                        processed_errmsg = result

                  if processed_status == 0:
                     if payload_type == 1:
                        ## plain string
                        ##
                        payload = payload_raw
                     elif payload_type == 2:
                        ## JSON
                        ##
                        try:
                           if payload_raw is not None:
                              payload = json_loads(payload_raw)
                           else:
                              payload = None
                        except Exception, e:
                           ## this should not happen, since we have serialized the
                           ## payload from a JSON typed object within Oracle!
                           ##
                           processed_status = 3 # invalid payload
                           processed_errmsg = "invalid JSON payload ('%s')" % str(e)
                     else:
                        ## this should not happen, since we have a CHECK constraint
                        ## on the underlying event table!
                        ##
                        processed_status = 2
                        processed_errmsg = "illegal event payload type %d" % payload_type

                  if processed_status == 0:
                     if qos == 1:
                        pass
                     else:
                        processed_status = 4
                        processed_errmsg = "illegal event qos type %d" % qos

                  ## let the events be dispatched on the reactor thread
                  ##
                  if processed_status == 0:
                     self.reactor.callFromThread(self.pusher.push,
                                                id,
                                                self.connect.id,
                                                pushedBy,
                                                topic,
                                                payload,
                                                exclude,
                                                eligible)

                  ## purge or mark processed event
                  ##
                  if self.purge:
                     #cur.execute("DELETE FROM event WHERE id = :1", [id])
                     deleteEventId.setvalue(0, id)
                     curDeleteEvents.execute(None)
                     #self.conn.commit()
                  else:
                     #cur.execute("UPDATE event SET processed_at = systimestamp at time zone 'utc', processed_status = :1, processed_errmsg = :2 WHERE id = :3", [processed_status, processed_errmsg[:4000] if processed_errmsg is not None else None, id])
                     markEventId.setvalue(0, id)
                     markEventProcessedStatus.setvalue(0, processed_status)
                     markEventProcessedErrMsg.setvalue(0, processed_errmsg)
                     markEventProcessedLen.setvalue(0, payload_raw_len)
                     curMarkEvents.execute(None)
                     #self.conn.commit()
               else:
                  doFetch = False

            ## immediately check again if we got rows.
            ## otherwise go to sleep / wait on pipe notification
            ##
            if gotRows > 0:
               #log.msg("got %d events, checking again .." % gotRows)
               checkAgain = True
            else:
               #log.msg("no new events")
               checkAgain = False

         ## wait for new events ..
         ##
         if not self.usePipe:
            ## when in polling mode, just sleep a little and recheck for events ..
            ##
            if self.pollThrottle > 0:
               time.sleep(self.pollThrottle)
         else:
            ## when using DBMS_PIPE, block in pipe receive for new events ..
            ##
            waitForPipe = True
            debugPipe = False

            while waitForPipe:

               ## the following will block in pipe receive ..
               ##
               curWaitPipe.execute(None)
               retval = int(pipeRetVal.getvalue())

               if retval == 1:

                  ## pipe timeout
                  ##
                  if debugPipe:
                     log.msg("DBMS_PIPE timeout")

               elif retval == 0:

                  ## the pipe got a new event ID ..
                  ##
                  notifiedId = int(pipeEventId.getvalue())
                  waitForPipe = False

                  if debugPipe:
                     log.msg("DBMS_PIPE data available [event %s]" % notifiedId)

               else:
                  ## could not receive from pipe .. something bad happened.
                  ## exit and rely on automatic pusher restart
                  ##
                  raise Exception("error while doing DBMS_PIPE.receive_message - return value %d" % retval)

               if self.recheckOnPipeTimeout:
                  waitForPipe = False
Ejemplo n.º 40
0
 def getApplianceVersion(self):
     try:
         o = json_loads(open("/etc/appliance.json").read())
         return o["image"]
     except:
         return "unknown"
Ejemplo n.º 41
0
 def _cacheConfig(self, res):
     self._config = {}
     for r in res:
         self._config[r[0]] = json_loads(r[1])
     log.msg("Config._cacheConfig (%d)" % len(self._config))
Ejemplo n.º 42
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))
Ejemplo n.º 43
0
    def _changePassword(self, txn, oldpassword, newpassword1, newpassword2):
        attrs = {
            "oldpassword":
            (True, [str,
                    unicode], AdminWebSocketProtocol.USER_PASSWORD_MIN_LENGTH,
             AdminWebSocketProtocol.USER_PASSWORD_MAX_LENGTH,
             AdminWebSocketProtocol.USER_PASSWORD_PATTERN),
            "newpassword1":
            (True, [str,
                    unicode], AdminWebSocketProtocol.USER_PASSWORD_MIN_LENGTH,
             AdminWebSocketProtocol.USER_PASSWORD_MAX_LENGTH,
             AdminWebSocketProtocol.USER_PASSWORD_PATTERN),
            "newpassword2":
            (True, [str,
                    unicode], AdminWebSocketProtocol.USER_PASSWORD_MIN_LENGTH,
             AdminWebSocketProtocol.USER_PASSWORD_MAX_LENGTH,
             AdminWebSocketProtocol.USER_PASSWORD_PATTERN)
        }

        errcnt, errs = self.checkDictArg(
            "user password", {
                "oldpassword": oldpassword,
                "newpassword1": newpassword1,
                "newpassword2": newpassword2
            }, attrs)

        if newpassword1 != newpassword2:
            errcnt += 1
            if not errs.has_key('newpassword1') or errs.has_key(
                    'newpassword2'):
                p = 'newpassword1'
            else:
                p = 'newpassword2'
            if not errs.has_key(p):
                errs[p] = []
            errs[p].append((self.shrink(URI_ERROR + "invalid-attribute-value"),
                            "New password values do not match"))

        if errcnt:
            raise Exception(
                URI_ERROR + "illegal-argument",
                "one or more illegal arguments (%d errors)" % errcnt, errs)

        txn.execute("SELECT value FROM config WHERE key = ?",
                    ['admin-password'])
        res = txn.fetchone()
        if res:
            pw = str(json_loads(res[0]))
            if pw == oldpassword:
                if newpassword1 != oldpassword:
                    txn.execute("UPDATE config SET value = ? WHERE key = ?",
                                [json_dumps(newpassword1), "admin-password"])
                else:
                    raise Exception(
                        URI_ERROR + "illegal-argument",
                        "one or more illegal arguments (%d errors)" % 2, {
                            'newpassword1':
                            [(self.shrink(URI_ERROR +
                                          "attribute-value-unchanged"),
                              "Password unchanged")],
                            'newpassword2': [
                                (self.shrink(URI_ERROR +
                                             "attribute-value-unchanged"),
                                 "Password unchanged")
                            ]
                        })
            else:
                raise Exception(
                    URI_ERROR + "illegal-argument",
                    "one or more illegal arguments (%d errors)" % 1, {
                        'oldpassword':
                        [(self.shrink(URI_ERROR + "invalid-attribute-value"),
                          "Old password is invalid")]
                    })
        else:
            raise Exception(
                URI_ERROR + "internal-error",
                "Could not retrieve admin password from database.")