Ejemplo n.º 1
0
    def __init__(self):
        super(IRServer, self).__init__()

        self.numparams = 4

        self._service = IRService()
        self._log = self._service.getLog()
        self._repoconf = self._service.getRepoConf()

        self.port = self._repoconf.getPort()
        self.proc_max = self._repoconf.getProcMax()
        self.refresh_status = self._repoconf.getRefreshStatus()
        self._authorizedUsers = self._repoconf.getAuthorizedUsers()
        self._nopasswdusers = self._repoconf.getNoPasswdUsers()

        self._ca_certs = self._repoconf.getCaCerts()
        self._certfile = self._repoconf.getCertFile()
        self._keyfile = self._repoconf.getKeyFile()
Ejemplo n.º 2
0
class IRServer(object):

    ############################################################
    # __init__
    ############################################################
    def __init__(self):
        super(IRServer, self).__init__()

        self.numparams = 4

        self._service = IRService()
        self._log = self._service.getLog()
        self._repoconf = self._service.getRepoConf()

        self.port = self._repoconf.getPort()
        self.proc_max = self._repoconf.getProcMax()
        self.refresh_status = self._repoconf.getRefreshStatus()
        self._authorizedUsers = self._repoconf.getAuthorizedUsers()
        self._nopasswdusers = self._repoconf.getNoPasswdUsers()

        self._ca_certs = self._repoconf.getCaCerts()
        self._certfile = self._repoconf.getCertFile()
        self._keyfile = self._repoconf.getKeyFile()

    def start(self):

        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.bind(("", self.port))
        sock.listen(1)  # Maximum of system unaccepted connections. Maximum value depend of the system (usually 5)
        self._log.info("Starting Server on port " + str(self.port))
        proc_list = []
        total_count = 0
        while True:
            if len(proc_list) == self.proc_max:
                full = True
                while full:
                    for i in range(len(proc_list) - 1, -1, -1):
                        # self._log.debug(str(proc_list[i]))
                        if not proc_list[i].is_alive():
                            # print "dead"
                            proc_list.pop(i)
                            # put here terminate?? just in case the process is not done but neither alive?? I have noticed that when IOError the process keep running
                            full = False
                    if full:
                        time.sleep(self.refresh_status)

            total_count += 1
            # channel, details = sock.accept()
            newsocket, fromaddr = sock.accept()
            connstream = None
            try:
                connstream = ssl.wrap_socket(
                    newsocket,
                    server_side=True,
                    ca_certs=self._ca_certs,
                    cert_reqs=ssl.CERT_REQUIRED,
                    certfile=self._certfile,
                    keyfile=self._keyfile,
                    ssl_version=ssl.PROTOCOL_TLSv1,
                )
                # print connstream
                proc_list.append(Process(target=self.repo, args=(connstream, fromaddr[0])))
                proc_list[len(proc_list) - 1].start()
            except ssl.SSLError:
                self._log.error("Unsuccessful connection attempt from: " + repr(fromaddr) + " " + str(sys.exc_info()))
            except socket.error:
                self._log.error("Error with the socket connection")
            except:
                self._log.error("Uncontrolled Error: " + str(sys.exc_info()))
                if type(connstream) is ssl.SSLSocket:
                    connstream.shutdown(socket.SHUT_RDWR)
                    connstream.close()

    # def auth(self, userCred):
    #    return FGAuth.auth(self.user, userCred)

    def checknopasswd(self, fromaddr):
        status = False
        if self.user in self._nopasswdusers:
            if fromaddr in self._nopasswdusers[self.user]:
                status = True
        return status

    def repo(self, channel, fromaddr):

        self._log = self._log.getLogger("Img Repo Server." + str(os.getpid()))

        self._service.setLog(self._log)

        self._log.info("Processing request")

        # receive the message
        data = channel.read(2048)

        self._log.debug("received data: " + data)

        params = data.split("|")

        # params[0] is user that authenticates
        # params[1] is the user password
        # params[2] is the type of password
        # params[3] is the command
        # params[4] is the user that interact with the repo. Usually is the same that params[0]
        # params[5...] are the options

        if len(params) <= self.numparams:
            msg = "ERROR: Invalid Number of Parameters"
            self.errormsg(channel, msg)
            sys.exit(1)

        self.user = params[
            0
        ].strip()  # ONLY for authentication. To specify the user that call methods you need to use params[4]
        passwd = params[1].strip()
        passwdtype = params[2].strip()
        command = params[3].strip()

        for i in range(len(params)):
            params[i] = params[i].strip()

        if not self.user in self._authorizedUsers:
            if not (self.user == params[4]):
                msg = "ERROR: You are not authorized to act in behalf of other user"
                self.errormsg(channel, msg)
                sys.exit(1)

        retry = 0
        maxretry = 3
        endloop = False
        while not endloop:
            # userCred = FGCredential(passwd, passwdtype)
            if not self.checknopasswd(fromaddr):
                status = self._service.auth(self.user, passwd, passwdtype)
                if status == True:
                    channel.write("OK")
                    endloop = True
                elif status == False:
                    # _authorizedUsers is not used currently. If we want to activate it, we need to make sure that the authizedUsers are in the Repository database
                    if self.user in self._authorizedUsers:  # because these users are services that cannot retry.
                        msg = "ERROR: authentication failed"
                        self.errormsg(channel, msg)
                        sys.exit(1)
                    else:
                        msg = "ERROR: authentication failed. Try again"
                        self._log.error(msg)
                        retry += 1
                        if retry < maxretry:
                            channel.write("TryAuthAgain")
                            passwd = channel.read(2048)
                        else:
                            msg = "ERROR: authentication failed"
                            self.errormsg(channel, msg)
                            sys.exit(1)
                else:
                    msg = status  # this is NoActive or NoUser
                    self.errormsg(channel, msg)
                    sys.exit(1)
            else:
                channel.write("OK")
                endloop = True

        needtoclose = False
        if command == "list":
            if len(params) == self.numparams + 2:
                # user, query string
                # print params[5]
                output = self._service.query(params[4], params[5])
                channel.write(str(output))
                needtoclose = True
            else:
                msg = "Invalid Number of Parameters"
                self.errormsg(channel, msg)
        elif command == "get":
            # user, img/uri, imgid
            if len(params) == self.numparams + 3:
                output = self._service.get(params[4], params[5], params[6])
                channel.write(str(output))
                if output != None:
                    status = channel.read(1024)  ##just to wait for client answer.
                    if status != "OK":
                        self._log.error("ERROR: Client did not receive the image")
                        needtoclose = False
                    else:
                        needtoclose = True
                    if self._service.getBackend() != "mysql":
                        cmdrm = " rm -f " + output
                        self._log.debug("Deleting Temporal file: " + cmdrm)
                        os.system(cmdrm)
            else:
                msg = "Invalid Number of Parameters"
                self.errormsg(channel, msg)
        elif command == "put":
            # user, img_size, extension, attributeString
            if len(params) == self.numparams + 4:
                self._log.debug("Before uploadValidator ")
                output = self._service.uploadValidator(params[4], long(params[5]))
                self._log.debug("After uploadValidator " + str(output))
                if str(output) == "True":
                    self._log.debug("Before genImgId ")
                    imgId = self._service.genImgId()
                    self._log.debug("After genImgId " + str(imgId))
                    if imgId != None:
                        self._log.debug(
                            "sending to the client: " + str(self._service.getImgStore()) + " , " + str(imgId)
                        )
                        channel.write(self._service.getImgStore() + "," + str(imgId))
                        self._log.debug("sent and waiting in the read")
                        # waiting for client to upload image
                        output = channel.read(2048)
                        if output != "Fail":
                            # user, imgId, imgFile(uri), attributeString, size, extension
                            output = self._service.put(params[4], imgId, output, params[7], long(params[5]), params[6])
                            channel.write(str(output))
                            needtoclose = True
                        else:
                            os.system("rm -f " + self._service.getImgStore() + "/" + str(imgId))
                            self._log.debug("rm -f " + self._service.getImgStore() + "/" + str(imgId))
                    else:
                        channel.write()
                        msg = "ERROR: The imgId generation failed"
                        self.errormsg(channel, msg)
                else:
                    output = str(output)
                    if output == "NoUser":
                        status = "ERROR: The User does not exist"
                    elif output == "NoActive":
                        status = "ERROR: The User is not active"
                    elif output == "False":
                        status = "ERROR: The file exceed the quota"
                    else:
                        status = "ERROR: " + output
                    msg = status
                    self.errormsg(channel, msg)
            else:
                msg = "ERROR: Invalid Number of Parameters"
                self.errormsg(channel, msg)
            # send storage directory, temporal or not
            # receive the OK, meaning that the image is already there
        elif command == "modify":
            # userid, imgid, attributestring
            if len(params) == self.numparams + 3:
                output = self._service.updateItem(params[4], params[5], params[6])
                channel.write(str(output))
            else:
                msg = "Invalid Number of Parameters"
                self.errormsg(channel, msg)
        elif command == "remove":
            # user, imgids list separated by spaces
            if len(params) == self.numparams + 2:
                output = self._service.remove(params[4], params[5])
                channel.write(str(output))
            else:
                msg = "Invalid Number of Parameters"
                self.errormsg(channel, msg)
        elif command == "setPermission":
            # user, imgid, query
            if len(params) == self.numparams + 3:
                output = self._service.updateItem(params[4], params[5], "permission=" + params[6])
                channel.write(str(output))
            else:
                msg = "Invalid Number of Parameters"
                self.errormsg(channel, msg)
        elif command == "histimg":
            # userId, imgId
            if len(params) == self.numparams + 2:
                output = self._service.histImg(params[4], params[5])
                channel.write(str(output))
                needtoclose = True
            else:
                msg = "Invalid Number of Parameters"
                self.errormsg(channel, msg)
        elif command == "histuser":
            # userId, userId
            if len(params) == self.numparams + 2:
                output = self._service.histUser(params[4], params[5])
                channel.write(str(output))
                needtoclose = True
            else:
                msg = "Invalid Number of Parameters"
                self.errormsg(channel, msg)
        # elif (command == "uploadValidator"):
        #    #user, size of the img to upload
        #    if (len(optionlist) != 2):
        #        output = self._service.uploadValidator(optionlist[0], long(optionlist[1]))
        #        channel.write(str(output))
        #    else:
        #        msg = "Invalid Number of Parameters"
        #        self.errormsg(channel, msg)
        # elif (command == "genImgId"):
        #    if (len(optionlist) != 1):
        #        output = self._service.genImgId()
        #        channel.write(str(output))
        #    else:
        #        msg = "Invalid Number of Parameters"
        #        self.errormsg(channel, msg)
        elif command == "getBackend":
            if len(params) == self.numparams + 1:
                output = self._service.getBackend()
                output1 = self._service.getImgStore()
                channel.write(str(output) + str(output1))
            else:
                msg = "Invalid Number of Parameters"
                self.errormsg(channel, msg)
        elif command == "useradd":
            # userid, useridtoadd
            if len(params) == self.numparams + 2:
                output = self._service.userAdd(params[4], params[5])
                channel.write(str(output))
            else:
                msg = "Invalid Number of Parameters"
                self.errormsg(channel, msg)
        elif command == "userdel":
            # userid, useridtodel
            if len(params) == self.numparams + 2:
                output = self._service.userDel(params[4], params[5])
                channel.write(str(output))
            else:
                msg = "Invalid Number of Parameters"
                self.errormsg(channel, msg)
        elif command == "userlist":
            # userid
            if len(params) == self.numparams + 1:
                output = self._service.userList(params[4])
                channel.write(str(output))
                needtoclose = True
            else:
                msg = "Invalid Number of Parameters"
                self.errormsg(channel, msg)
        elif command == "setUserQuota":
            # userid, useridtomodify, quota in bytes
            if len(params) == self.numparams + 3:
                output = self._service.setUserQuota(params[4], params[5], long(params[6]))
                channel.write(str(output))
            else:
                msg = "Invalid Number of Parameters"
                self.errormsg(channel, msg)
        elif command == "setUserRole":
            # userid, useridtomodify, role
            if len(params) == self.numparams + 3:
                output = self._service.setUserRole(params[4], params[5], params[6])
                channel.write(str(output))
            else:
                msg = "Invalid Number of Parameters"
                self.errormsg(channel, msg)
        elif command == "setUserStatus":
            if len(params) == self.numparams + 3:
                output = self._service.setUserStatus(params[4], params[5], params[6])
                channel.write(str(output))
            else:
                msg = "Invalid Number of Parameters"
                self.errormsg(channel, msg)
        elif command == "getUserStatus":
            # userId
            if len(params) == self.numparams + 1:
                output = self._service.getUserStatus(params[4])
                channel.write(str(output))
            else:
                msg = "Invalid Number of Parameters"
                self.errormsg(channel, msg)
        elif command == "isUserAdmin":
            # userId
            if len(params) == self.numparams + 1:
                output = self._service.isUserAdmin(params[4])
                channel.write(str(output))
            else:
                msg = "Invalid Number of Parameters"
                self.errormsg(channel, msg)
        else:
            msg = "Invalid Command: " + command
            self.errormsg(channel, msg)
            needtoclose = False

        if needtoclose:
            channel.shutdown(socket.SHUT_RDWR)
            channel.close()
            self._log.info("Image Repository Request DONE")
        else:
            self._log.info("Image Repository Request DONE")

    def errormsg(self, channel, msg):
        self._log.error(msg)
        try:
            channel.write(msg)
            channel.shutdown(socket.SHUT_RDWR)
            channel.close()
        except:
            self._log.debug("In errormsg: " + str(sys.exc_info()))
        self._log.info("Image Repository Request DONE")