def handle_1(self, data, cred): # STUB log_cb.info("*" * 20) log_cb.info("Handling CB_COMPOUND") p = nfs4lib.FancyNFS4Packer() res = CB_COMPOUND4res(NFS4ERR_BACK_CHAN_BUSY, "STUB CB_REPLY", []) p.pack_CB_COMPOUND4res(res) return rpc.SUCCESS, p.get_buffer()
def __init__(self, rootfh, host, port, pubfh = None): rpc.RPCServer.__init__(self, prog=NFS4_PROGRAM, vers=NFS_V4, host=host, port=port) self.nfs4packer = nfs4lib.FancyNFS4Packer() self.nfs4unpacker = nfs4lib.FancyNFS4Unpacker('') self.state = nfs4state.NFSServerState(rootfh) self.fhcache = {} self.rootfh = rootfh self.pubfh = pubfh self.verfnum = 0
def check_replay(self, op, replay): """Pull appropriate info for a replay attempt""" fh, args, oldop = replay p = nfs4lib.FancyNFS4Packer() p.pack_nfs_argop4(op) newstr = p.get_buffer() p.reset() p.pack_nfs_argop4(oldop) oldstr = p.get_buffer() if oldstr == newstr: # Sadly, op == oldop won't work return (fh, args) else: return (None, (NFS4ERR_BAD_SEQID,))
def set_ssv(self, ssv=None, *args, **kwargs): protect = self.client.protect if ssv is None: ssv = nfs4lib.random_string(protect.context.ssv_len) if "credinfo" not in kwargs: kwargs["credinfo"] = self.cred seq_op = self.seq_op(kwargs.pop("slot", None)) p = nfs4lib.FancyNFS4Packer() p.pack_SEQUENCE4args(seq_op.opsequence) digest = protect.context.hmac(p.get_buffer(), SSV4_SUBKEY_MIC_I2T) ssv_op = op4.set_ssv(ssv, digest) res = self.c.compound([seq_op, ssv_op], *args, **kwargs) # STUB - do some checking protect.context.set_ssv(ssv) return res
def handle_1(self, data, cred): log_cb.info("*" * 20) log_cb.info("Handling COMPOUND") # data is an XDR packed string. Unpack it. unpacker = nfs4lib.FancyNFS4Unpacker(data) try: args = unpacker.unpack_CB_COMPOUND4args() unpacker.done() except: log_cb.warn("returning GARBAGE_ARGS") log_cb.debug("unpacking raised the following error", exc_info=True) return rpc.GARBAGE_ARGS, None log_cb.debug(repr(args)) try: # SEQUENCE needs to know size of request args.req_size = len(data) # Handle the request env = self.op_cb_compound(args, cred) log_cb.info(repr(env.results.reply.results)) # Pack the results back into an XDR string p = nfs4lib.FancyNFS4Packer() p.pack_CB_COMPOUND4res( CB_COMPOUND4res(env.results.reply.status, env.results.reply.tag, env.results.reply.results)) data = p.get_buffer() # Stuff the replay cache if env.cache is not None: p.reset() p.pack_CB_COMPOUND4res( CB_COMPOUND4res(env.results.cache.status, env.results.cache.tag, env.results.cache.results)) env.cache.data = p.get_buffer() env.cache.valid.set() except NFS4Replay as e: log_cb.info("Replay...waiting for valid data") e.cache.valid.wait() log_cb.info("Replay...sending data") data = e.cache.data return rpc.SUCCESS, data, getattr(env, "notify", None)
def handle_1(self, data, cred, callback=False): """COMPOUND procedure""" log.debug("*" * 40) if callback: log.debug("** CALLBACK **") log.debug("Handling COMPOUND") # stage 1: data in XDR as received from the client unpacker = nfs4lib.FancyNFS4Unpacker(data) if callback: args = unpacker.unpack_CB_COMPOUNDargs() else: args = unpacker.unpack_COMPOUND4args() log.debug("Client sent:") log.debug(repr(args)) unpacker.done() # stage 2: pre-processing - data in COMPOUND4args # XXX: check operation, alter stuff, delay etc. etc. args.req_size = len(data) # BUG, need to use cred.payload_size if callback: env = CBCompoundState(args, cred) else: env = CompoundState(args, cred) for arg in args.argarray: env.index += 1 opname = nfs_opnum4.get(arg.argop, 'op_illegal') log.info("*** %s (%d) ***" % (opname, arg.argop)) # look for functions implemented by the proxy # that override communication funct = getattr(self, opname.lower(), None) if funct is not None and callable(funct): try: result = funct(arg, cred, direction=0) except Exception: log.error("Function override %s failed" % opname.lower()) # handle error condition if specified error = None if self.errorhandler is not None: error = self.errorhandler.get_error(opname.lower()[3:], arg, env) if error is not None: result = encode_status_by_name(opname.lower()[3:], int(error), msg="Proxy Rewrite Error") env.results.append(result) p = nfs4lib.FancyNFS4Packer() if callback: res = CB_COMPOUND4res(env.results.reply.status, env.results.reply.tag, env.results.reply.results) p.pack_CB_COMPOUND4res(res) else: res = COMPOUND4res(env.results.reply.status, env.results.reply.tag, env.results.reply.results) p.pack_COMPOUND4res(res) log.info(repr(res)) reply = p.get_buffer() return rpc.SUCCESS, reply #stage 3: repack the data and forward to server packer = nfs4lib.FancyNFS4Packer() if callback: packer.pack_CB_COMPOUND4args(args) else: packer.pack_COMPOUND4args(args) log.debug("Proxy sent:") log.debug(repr(args)) calldata = packer.get_buffer() try: ret_data = self.forward_call(calldata, callback) except rpc.RPCTimeout: log.critical("Error: cannot connect to destination server") return rpc.GARBAGE_ARGS, None # stage 4: data in XDR as returned by the server unpacker = nfs4lib.FancyNFS4Unpacker(ret_data) if callback: res = unpacker.unpack_CB_COMPOUND4res() else: res = unpacker.unpack_COMPOUND4res() log.debug("Server returned:") log.debug(repr(res)) unpacker.done() # stage 5: post-processing - data in COMPOUND4res # XXX: check operation etc. for arg in res.resarray: opname = nfs_opnum4.get(arg.resop, 'op_illegal') log.info("*** %s (%d) ***" % (opname, arg.resop)) # look for functions implemented by the proxy # that override communication funct = getattr(self, opname.lower(), None) if funct is not None and callable(funct): try: result = funct(arg, cred, direction=1) except Exception: log.error("Function override %s failed" % opname.lower()) # state 6: repack and return XDR data to client packer = nfs4lib.FancyNFS4Packer() if callback: packer.pack_CB_COMPOUND4res(res) else: packer.pack_COMPOUND4res(res) log.debug("Proxy returned:") log.debug(repr(res)) reply = packer.get_buffer() return rpc.SUCCESS, reply
def op_readdir(self, op): # We ignore dircount hint print(" CURRENT FILEHANDLE %s" % repr(self.curr_fh)) print(" COOKIEVERF: %s, %s" % ( repr(op.opreaddir.cookieverf), repr(op.opreaddir.cookie))) print(" DIRCOUNT: %d MAXCOUNT: %d" % ( op.opreaddir.dircount, op.opreaddir.maxcount)) print(" ATTRMASK: %s" % [nfs4lib.get_attr_name(bit) for bit in nfs4lib.bitmap2list(op.opreaddir.attr_request)]) if not self.curr_fh: return simple_error(NFS4ERR_NOFILEHANDLE) if self.curr_fh.get_type() != NF4DIR: return simple_error(NFS4ERR_NOTDIR) if op.opreaddir.cookie in [1,2]: return simple_error(NFS4ERR_BAD_COOKIE) if op.opreaddir.maxcount == 0: return simple_error(NFS4ERR_TOOSMALL) zeroverf = '\x00\x00\x00\x00\x00\x00\x00\x00' if op.opreaddir.cookie == 0 and op.opreaddir.cookieverf != zeroverf: return simple_error(NFS4ERR_BAD_COOKIE) try: verifier = self.curr_fh.getdirverf() if op.opreaddir.cookie != 0: if op.opreaddir.cookieverf != verifier: return simple_error(NFS4ERR_NOT_SAME) try: dirlist = self.curr_fh.read_dir(op.opreaddir.cookie) except IndexError: return simple_error(NFS4ERR_BAD_COOKIE) attrs = nfs4lib.bitmap2list(op.opreaddir.attr_request) entries = [] bytecnt = 0 packer = nfs4lib.FancyNFS4Packer() for entry in dirlist: # Get file attributes try: attrvals = entry.fh.get_attributes(attrs) except NFS4Error: if FATTR4_RDATTR_ERROR not in attrs: raise attrvals = entry.fh.get_attributes([FATTR4_RDATTR_ERROR]) entry.attr = attrvals # Compute size of XDR encoding e4 = entry4(entry.cookie, entry.name, entry.attr, []) packer.reset() packer.pack_entry4(e4) # Make sure returned value not too big bytecnt += len(packer.get_buffer()) if bytecnt > op.opreaddir.maxcount - 16: break # Add file to returned entries entries.insert(0,entry) if (not entries) and dirlist: return simple_error(NFS4ERR_TOOSMALL) # Encode entries as linked list e4 = [] for entry in entries: e4 = [entry4(entry.cookie, entry.name, entry.attr, nextentry=e4)] if len(entries) < len(dirlist): d4 = dirlist4(e4, eof=0) else: d4 = dirlist4(e4, eof=1) except NFS4Error as e: return simple_error(e.code) rdresok = READDIR4resok(cookieverf=verifier, reply=d4) return simple_error(NFS4_OK, rdresok)