示例#1
0
 def _check_rpcvers(self, msg):
     """Returns True if rpcvers is ok, otherwise sends out MSG_DENIED"""
     if msg.rpcvers not in self.rpcversions:
         log_t.warn("RPC_MISMATCH, do not support vers=%i" % msg.rpcvers)
         raise rpclib.RPCDeniedReply(RPC_MISMATCH,
                                     (min(self.rpcversions),
                                      max(self.rpcversions)))
示例#2
0
    def _check_auth(self, msg, data):
        """Returns security module to use if call processing should continue,

        otherwise returns None.
        Note that it is possible for security module to hijack call processing.
        """
        # Check that flavor is supported
        try:
            sec = self.sec_flavors[msg.cred.flavor]
        except KeyError:
            log_t.warn("AUTH_ERROR: Unsupported flavor %i" % msg.cred.flavor)
            if msg.proc == 0 and msg.cred.flavor == AUTH_NONE:
                # RFC 1831 section 11.1 says "by convention" should allow this
                log_t.warn("Allowing NULL proc through anyway")
                sec = security.klass(AUTH_NONE)()
            else:
                raise rpclib.RPCDeniedReply(AUTH_ERROR, AUTH_FAILED)
        # Call flavor specific authority checks
        return sec.check_auth(msg, data)

        # What incoming flavors do I allow?
        #    How does server learn/change these defaults

        # For AUTH_NONE:
        #   return True - note 11.1 says "by convention" should
        #   allow AUTH_NONE, at least for proc==0

        # For AUTH_SYS:
        #    check machinename, mode - again how is accept list set on server?
        
        # For GSS:
        #   illegal enum values should return AUTH_BADCRED
        #      this will be noticed by XDR unpack failing, which means
        #      type(cred.body) == str
        #   check gss_version, fail with AUTH_BADCRED
        #   check allows service - again how does server set?
        #   check context handle - what does this mean?
        #      see 5.3.3.3, we maintain list of contexts we are in session
        #      with, if not in list, return CREDPROBLEM
        #      if security credentials expire, return CTXPROBLEM
        #   check header checksum in verf, failure returns CREDPROBLEM
        #   check seq_num in cred, silently drop repeats,
        #       return CTXPROBLEM if exceeds window
        #   check seq_num in data, return GARBAGE_ARGS if mismatches cred
        #   check gss_proc==DATA, else:
        #       if proc==0, handle elsewhere
        #       else return AUTH_BADCRED
        return True
示例#3
0
    def _event_rpc_call(self, msg, msg_data, pipe):
        """Deal with an incoming RPC CALL.
        
        msg is unpacked header, with length fields added.
        msg_data is raw procedure data.
        """
        """Given an RPC record, returns appropriate reply

        This is run in its own thread.
        """
        class XXX(object):
            pass
        call_info = XXX() # Store various info we need to pass to procedure
        call_info.header_size = msg.length
        call_info.payload_size = len(msg_data)
        call_info.connection = pipe
        notify = None
        try:
            # Check for reasons to DENY the call
            try:
                self._check_rpcvers(msg)
                call_info.credinfo = self._check_auth(msg, msg_data)
            except rpclib.RPCFlowContol:
                raise
            except Exception:
                log_t.warn("Problem with incoming call, returning AUTH_FAILED",
                           exc_info=True)
                raise rpclib.RPCDeniedReply(AUTH_ERROR, AUTH_FAILED)
            # Call has been ACCEPTED, now check for reasons not to succeed
            sec = call_info.credinfo.sec
            msg_data = sec.unsecure_data(msg.body.cred, msg_data)
            if not self._check_program(msg.prog):
                log_t.warn("PROG_UNAVAIL, do not support prog=%i" % msg.prog)
                raise rpclib.RPCUnsuccessfulReply(PROG_UNAVAIL)
            low, hi = self._version_range(msg.prog)
            if not self._check_version(low, hi, msg.vers):
                log_t.warn("PROG_MISMATCH, do not support vers=%i" % msg.vers)
                raise rpclib.RPCUnsuccessfulReply(PROG_MISMATCH, (low, hi))
            method = self._find_method(msg)
            if method is None:
                log_t.warn("PROC_UNAVAIL for vers=%i, proc=%i" %
                           (msg.vers, msg.proc))
                raise rpclib.RPCUnsuccessfulReply(PROC_UNAVAIL)
            # Everything looks good at this layer, time to do the call
            tuple = method(msg_data, call_info)
            if len(tuple) == 2:
                status, result = tuple
            else:
                status, result, notify = tuple
            if result is None:
                result = ''
            if not isinstance(result, basestring):
                raise TypeError("Expected string")
            # status, result = method(msg_data, call_info)
            log_t.debug("Called method, got %r, %r" % (status, result))
        except rpclib.RPCDrop:
            # Silently drop the request
            self._notify_drop()
            return
        except rpclib.RPCFlowContol, e:
            body, data = e.body()
示例#4
0
文件: security.py 项目: wzugang/pynfs
 def auth_error(code):
     """Return (MSG_DENIED, AUTH_ERROR, code)"""
     raise rpclib.RPCDeniedReply(AUTH_ERROR, code)