Пример #1
0
    def sendMsgToStorage(cmd):
        '''Forwarder of messages to storage'''
        log.debug("In sendMsgToStorage - cmd: {0}".format(cmd))
        try:
            if not util.connLock.acquire(True, 5):
                raise IKException(
                    ErrorCode.operationFailed,
                    "Failed to acquire the lock for connecting to storage.")

            log.debug("Sending...")
            connHere.send(cmd)
            log.debug("Sent. Receiving...")
            if connHere.poll(15):
                ret = connHere.recv()
                log.debug("In sendMsgToStorage - ret: {0}".format(ret))
            else:
                ret = composeResponse(
                    "0", "Socket timed out or no data to receive.")
                log.debug("Nothing to receive")

            util.connLock.release()
        except Exception as e:
            ret = composeResponse("0", str(e))
            log.error(
                "In sendMsgToStorage exception received: {0}".format(ret))

        return ret
Пример #2
0
    def chGetItem(self, cmd):
        '''Get item'''
        feeder = self._getItemFeeder(cmd)

        if self.acc == df.PL_SECURE:
            nam = feeder.__next__()
            try:
                ret = self.fs.getItem(nam).value()
                return composeResponse('1', ret)
            except IKException as e:
                if e.code == ErrorCode.objectNotExists:
                    if not self.defencread:
                        try:
                            self.read_sec_file()
                        except IKException as e1:
                            return composeResponse(
                                '0',
                                "Failed to read secure tokens: " + str(e1))

                        self.defencread = True
                    else:
                        raise

            return composeResponse('1', self.fs.getItem(nam).value())

        lres = []
        for i in feeder:
            lres.append(self.fs.getItem(i).value())

        return composeResponse('1', lres if len(lres) != 1 else lres[0])
Пример #3
0
	def handleCmd( cmd ):
		'''Switch command and intercept exceptions.'''
		try:
			bresp = CmdSwitcher.switchCmd( cmd )
		except IKException as e:
			bresp = util.composeResponse( '0', str( e ) )
		except Exception as e:
			bresp = util.composeResponse( '0', e.args[0] )
		return bresp
Пример #4
0
 def chPathExists(self, cmd):
     '''Return True if a token path exists'''
     par = cmd["params"][0]
     try:
         self.fs.getItem(par)
         return composeResponse()
     except IKException as e:
         if e.code == ErrorCode.objectNotExists:
             return composeResponse("0")
         else:
             raise
Пример #5
0
    def chRemoveSection(self, cmd):
        '''Remove section'''
        feeder = self._getItemFeeder(cmd)
        for i in feeder:
            self.fs.removeItem(i).markChanged()

        return composeResponse()
Пример #6
0
    def chRename(self, cmd):
        '''Rename item'''
        feeder = self._getItemFeeder(cmd)
        for i in feeder:
            self.fs.rename(i).markChanged()

        return composeResponse()
Пример #7
0
    def chListItems(self, cmd):
        '''List items'''
        par = cmd.get("params", None)
        swNovals = df.NOVALUES in cmd
        swTree = df.TREE in cmd
        swRecur = df.RECURS in cmd
        lres = []
        if not par:
            self.fs[''].listItems(lres=lres,
                                  bTree=swTree,
                                  nIndent=0,
                                  bNovals=swNovals,
                                  relPath=None,
                                  bRecur=swRecur)
        else:
            item = par[0]
            if item[0] != '/':
                item = "{0}/{1}".format(
                    PERSPATH if df.PERS in cmd else SESPATH, item)

            sect = self.fs.getItem(item)
            sect.listItems(lres=lres,
                           bTree=swTree,
                           nIndent=0,
                           bNovals=swNovals,
                           relPath=None,
                           bRecur=swRecur)

        return composeResponse('1', lres)
Пример #8
0
    def chReport(self, cmd):
        '''Report server variables.'''
        par = cmd["params"][0]
        retCode = '1'
        if par == df.ACCESS:
            resp = "{0}".format(self.srv.acc)
        elif par == df.REP_STORAGE:
            path = None
            if len(cmd["params"]) > 1:
                if len(cmd["params"] == 2):
                    path = cmd["params"][1]
                else:
                    raise IKException(ErrorCode.unrecognizedSyntax,
                                      " ".join(cmd["params"]))
            resp = self.fs.stat(path)
        elif par == df.REP_SERVER:
            # TODO:
            bs = getShared("bytesSent")
            br = getShared("bytesReceived")
            resp = "Bytes sent: {0}\n".format(bs)
            resp += "Bytes received: {0}\n".format(br)
        elif par == df.REP_COMMANDS:
            resp = util.printMap(self.info["cmd"], 0)
            pass
        elif par == df.DATAFILE:
            resp = self.fs.datafile
        else:
            retCode = '0'
            resp = "Unrecognized command parameter: " + par

        return composeResponse(retCode, resp)
Пример #9
0
    def chLoadFileSec(self, cmd):
        '''Rename item'''
        file = cmd.get("params")
        if not file:
            file = None
        else:
            file = file[0]

        self.read_sec_file(file)
        return composeResponse()
Пример #10
0
	def switchCmd( cmd ):
		'''Switch command'''
		if cmd["cmd"] not in CmdSwitcher.cmdHandlers:
			cmd['res'] = 0
			return util.composeResponse( '0', "Unrecognized command: ", cmd["cmd"] )

		cmd['res'] = 1
		CmdSwitcher.info["cmds"][cmd["cmd"]] = 1 + CmdSwitcher.info["cmds"].setdefault(cmd["cmd"], 0)
		hnd = CmdSwitcher.cmdHandlers[cmd["cmd"]]
		return hnd( cmd )
Пример #11
0
	def processCmd(self, cmd):
		'''Process command. Finds the handler for the command and passes 'cmd' dictionary to it.
		If the handler is not found, sets the 'res' field of the dictionary to 0.'''

		if cmd["cmd"] not in self.cmdMap:
			cmd["res"] = 0
			return util.composeResponse( '0', "Unrecognized command: ", cmd["cmd"] )
		
		cmd["res"] = 1
		CmdSwitcher.info["cmds"][cmd["cmd"]] = 1 + CmdSwitcher.info["cmds"].setdefault(cmd["cmd"], 0)
		hnd = self.cmdMap[cmd["cmd"]]
		return hnd( cmd )
Пример #12
0
    def chGetAttr(self, cmd):
        '''Return item's attribute'''
        """Query for attributes of a storage item.
		Syntax: GETATTR <itempath> [attrname]
		Without 'attrname' returns 'st_stat' attributes like function 'getattr'.
		With 'attrname' works like 'getxattr'.
		"""
        attrNames = None
        par = cmd["params"][0]
        if df.ATTRS in cmd:
            attrNames = cmd[df.ATTRS]
        m = self.fs.getItemAttr(par, attrNames)
        return composeResponse('1', m)
Пример #13
0
 def chShowLog(self, cmd):
     '''Show server log'''
     par = cmd["params"]
     n = 20
     if par:
         try:
             n = int(par[0])
         except ValueError:
             raise IKException(
                 ErrorCode.unrecognizedParameter,
                 par[0],
                 moreInfo="Number of lines only must contain digits.")
     return composeResponse('1', util.getLog(n))
Пример #14
0
    def chCheckServer(self, cmd):
        '''Check regd server'''
        # Polling the file storage
        log.debug("Checking storage...")
        bresp = CmdSwitcher.switchCmd({"cmd": fs.FS_CHECK})
        log.debug("Storage checked.")
        lresp = util.parsePacket(bresp)
        fsresp = "Storage:\n" + str(lresp[1])

        resp = "Server:\nUp and running since {0}\nUptime:{1}.\n".format(
            str(self.timestarted).rpartition(".")[0],
            str(datetime.now() - self.timestarted).rpartition(".")[0])

        return composeResponse('1', resp + fsresp)
Пример #15
0
    def chCreateSection(self, cmd):
        '''Create section'''
        feeder = self._getItemFeeder(cmd)
        for i in feeder:
            if not self._isPathValid(path=i, cmd=cmd):
                raise IKException(ErrorCode.unsupportedParameterValue, i,
                                  "Path is not valid")
            sec = self.fs.addItem(i)
            if df.ATTRS in cmd:
                sec.setAttrs(cmd[df.ATTRS])
                sec.readFromFile(updateFromStorage=True)
            sec.markChanged()

        return composeResponse()
Пример #16
0
    def chAddToken(self, cmd):
        '''Add item'''
        dest, addMode, attrs = self._getAddOptions(cmd)
        cnt = 0
        #with self.lock_seriz:
        for tok in cmd["params"]:
            if (dest and dest.startswith( BINPATH ) ) or \
              tok.startswith( BINPATH ):
                self.handleBinToken(dest, tok, cmd)
                continue

            # Without --dest or --pers options tokens with relative path
            # are always added to session tokens
            if not dest and tok[0] != '/':
                dest = SESPATH

            binaryVal = None
            if df.BINARY in cmd:
                if not cmd[df.BINARY] or len(cmd[df.BINARY]) < cnt + 1:
                    raise IKException(ErrorCode.unknownDataFormat, tok)
                binaryVal = cmd[df.BINARY][cnt]
                if not attrs:
                    attrs = {}
                attrs[stor.SItem.persPathAttrName] = df.BINARY
                cnt += 1

            if dest:
                tok = joinPath(dest, tok)

            if binaryVal:
                tk = None
                pt = tok
            else:
                tk = tok
                pt = None

            if not self._isPathValid(tok=tk, path=pt, cmd=cmd):
                raise IKException(ErrorCode.unsupportedParameterValue,
                                  tok[:50], "Path is not valid.")

            sec = self.fs.addItem(tok=tok,
                                  addMode=addMode,
                                  binaryVal=binaryVal,
                                  attrs=attrs)

            if sec: sec.markChanged()

        return composeResponse()
Пример #17
0
    def chInfo(self, cmd):
        '''Report server information'''
        # pylint: disable=unused-variable
        accl = getShared("accLevel")
        dfile = getShared("dataFile")
        sfile = getShared("sockFile")

        resp = "{0} : {1}\n".format(app.APPNAME, df.__description__)
        resp += "License: {0}\n".format(df.__license__)
        resp += "Homepage: {0}\n\n".format(df.__homepage__)
        resp += "Server version: {0}\n".format(df.rversion)
        resp += "Server datafile: {0}\n".format(dfile)
        resp += "Server access: {0}\n".format(accl)
        resp += "Server socket file: {0}\n".format(sfile)

        return composeResponse("1", resp)
Пример #18
0
	def listenForMessages(self, func):
		while self.cont:
			if self.conn.poll(30):
				try:
					cmd = self.conn.recv()
					try:
						resp = self.processCmd( cmd )
					except IKException as e:
						resp = util.composeResponse( "0", "In listenForMessages - exception received: {0}. Continue listening...".format( e ) )
						log.error( resp  )
					self.conn.send( resp )
				except Exception as e:
					fh = io.StringIO()
					traceback.print_exc( file=fh )
					log.error( "In listenForMessages - fatal exception received: {0}. Quit listening...".format( fh.getvalue() ) )
					raise
			else:
				func()
Пример #19
0
    def chSetAttr(self, cmd):
        '''Set an item's attribute'''
        """Set attributes of a storage item.
		Syntax: SETATTR <itempath> <attrname=attrval ...>"""

        par = cmd["params"][0]
        item = self.fs.setItemAttr(par, cmd[df.ATTRS])
        item.markChanged()

        # When the backing storage path attribute is set, the storage file
        # is overwritten with the current content of the item. In order to
        # read the file contents into an item, loadFile function is used.
        if [
                x for x in cmd[df.ATTRS]
                if x.startswith(stor.SItem.persPathAttrName + "=")
        ]:
            # TODO: move the call to fs.serialize to item, where thread sync is
            #with self.lock_seriz:
            self.fs.serialize()

        return composeResponse()
Пример #20
0
    def chLoadFile(self, cmd):
        '''Load tokens from a file.'''
        dest, addMode, attrs = self._getAddOptions(cmd)
        if not dest:
            dest = SESPATH
        swFromPars = df.FROM_PARS in cmd

        if not swFromPars:
            for filename in cmd["params"]:
                if os.path.exists(filename):
                    self.fs.readFromFile(filePath=filename,
                                         dest=dest,
                                         addMode=addMode)
                else:
                    raise IKException(ErrorCode.objectNotExists, filename,
                                      "File not found")
        else:
            for file in cmd["params"]:
                fh = io.BytesIO(file.encode())
                self.fs.readFromFile(fh=fh, dest=dest, addMode=addMode)

        return composeResponse()
Пример #21
0
    def chCopyFile(self, cmd):
        '''Copy file contents to an item'''
        dest, addMode, attrs = self._getAddOptions(cmd)
        swFromPars = df.FROM_PARS in cmd
        src = cmd["params"][0]
        dst = cmd["params"][1]
        ret = None
        if dst[0] == ':':  # cp from file to token

            if not self._isPathValid(path=dst[1:], cmd=cmd):
                raise IKException(ErrorCode.unsupportedParameterValue, dst[1:],
                                  "Path is not valid")

            if swFromPars:
                val = src
            else:
                with open(src) as f:
                    val = f.read()
            tok = dst[1:] + " =" + val
            self.fs.addItem(tok=util.joinPath(dest, tok),
                            addMode=addMode,
                            attrs=attrs)
            ret = ""
        elif src[0] == ':':  # cp from token to file
            src = src[1:]
            if src[0] != '/':
                src = "{0}/{1}".format(PERSPATH if df.PERS in cmd else SESPATH,
                                       src)
            else:
                if not self._isPathValid(path=src, cmd=cmd):
                    raise IKException(ErrorCode.unsupportedParameterValue, src,
                                      "Path is not valid")

            # File is written on the client side
            ret = self.fs.getItem(src).val

        return composeResponse('1', ret)
Пример #22
0
 def chFsStop(self, cmd):
     self.cont = False
     log.info("Stopping storage... Serializing...")
     self.serialize()
     log.info("Storage exiting.")
     return composeResponse()
Пример #23
0
    def chFsCheck(self, cmd):
        resp = "Up and running since {0}\nUptime:{1}.".format(
            str(self.timestarted).rpartition(".")[0],
            str(datetime.now() - self.timestarted).rpartition(".")[0])

        return composeResponse('1', resp)
Пример #24
0
 def chClearSessionTokens(self, cmd):
     '''Clear session tokens'''
     self.clearTokensSec()
     self.clearSessionTokens()
     return composeResponse()
Пример #25
0
 def chVersion(self, cmd):
     '''Return regd version.'''
     return composeResponse('1', "Regd server version: " + df.__version__)
Пример #26
0
	def chStopServer( self, cmd ):
		'''Stop regd server'''
		log.debug("In chStopServer")
		return composeResponse( '1', "Exiting..." )
Пример #27
0
	def _handle_connection( self, connection, client_address, storage_lock ):
		'''Connection handler'''
		if not self.host:
			creds = connection.getsockopt( socket.SOL_SOCKET, socket.SO_PEERCRED,
									struct.calcsize( "3i" ) )
			pid, uid, gid = struct.unpack( "3i", creds )
			log.debug( "new connection: pid: {0}; uid: {1}; gid: {2}".format( pid, uid, gid ) )
		else:
			log.debug( "new connection: client address: %s" % ( str( client_address ) ) )

		connection.settimeout( 5 )

		data = bytearray()
		util.recvPack( connection, data )
		bytesReceived = len( data )

		log.debug( "data: %s" % ( data[:1000] ) )
		data = data[10:]  # .decode( 'utf-8' )

		bresp = bytearray()
		cmd = None
		perm = False
		# dcmd - command dictionary. Contains three fields:
		# cmd - command name, received from client
		# params - command parameters, received from client
		# res - internal command processing result, set by the command processor or
		# command handler. This result has the server semantics, rather than the
		# command semantics: if it's 0 - this means a general program error, e.g.
		# non-existing command name. It's meant to be handled by the server before
		# sending response to the client.
		
		try:
			dcmd = util.parsePacket( data )
			# 'internal' switch is only used within regd server
			if "internal" in dcmd:
				raise Exception("Unrecognized syntax.")
			cmd = dcmd["cmd"]
			log.debug( "command received: {0}".format( cmd ) )
		except Exception as e:
			bresp = composeResponse( "0", "Exception while parsing the command: " + str( e ) )
		else:
			# Check permission and persistency
			
			if self.host:
				# IP-based server
				if not self.trustedIps:
					perm = True
				else :
					try:
						clientIp = ipaddress.IPv4Address( client_address[0] )
					except ValueError:
						log.error( "Client IP address format is not recognized." )
					else:
						for i in self.trustedIps:
							if clientIp in i:
								perm = True
								log.debug( "Client IP is trusted." )
								break
						if not perm:
							log.error( "Client IP is NOT trusted : '%s : %s" %
									( client_address[0], client_address[1] ) )
			else:
				# File socket server
				if self.useruid == uid:
					perm = True
				elif uid in self.trustedUserids:
					perm = True
				elif cmd not in defs.secure_cmds:
					if self.acc == defs.PL_PUBLIC:
						perm = True
					elif self.acc == defs.PL_PUBLIC_READ:
						if cmd in defs.pubread_cmds:
							perm = True
			log.debug( "perm: {0}".format( perm ) )
			if not perm:
				bresp = composeResponse( "0", str( IKException( ErrorCode.permissionDenied, cmd ) ) )
			#elif not self.datafile and defs.PERS in cmd:
			#	bresp = composeResponse( "0", str( IKException( ErrorCode.operationFailed, None, "Persistent tokens are not enabled." ) ) )
		
		if not len( bresp ):
			util.connLock = storage_lock
			bresp = CmdSwitcher.handleCmd( dcmd )

		try:
			bytesSent = util.sendPack( connection, bresp )
		except OSError as er:
			log.error( "Socket error {0}: {1}\nClient address: {2}\n".format( 
							er.errno, er.strerror, client_address ) )
		else: 
			if type( bytesSent ) is int:
				info.setShared( "bytesReceived", bytesReceived, defs.SUM )
				info.setShared( "bytesSent", bytesSent, defs.SUM )

		if cmd == defs.STOP_SERVER and perm:
			self.sigsock_w.send("stop".encode())

		return