def unsecure_data(self, cred, data): def pull_seqnum(blob): """Pulls initial seq_num off of blob, checks it, then returns data. """ # blob = seq_num + data p.reset(blob) try: seq_num = p.unpack_uint() except: log_gss.exception("unsecure_data - unpacking seq_num") raise rpclib.RPCUnsuccessfulReply(GARBAGE_ARGS) if seq_num != cred.seq_num: raise rpclib.RPCUnsuccessfulReply(GARBAGE_ARGS) return p.get_buffer()[p.get_position():] def check_gssapi(qop): if qop != cred.qop: # XXX Not sure what error to give here log_gss.warn("unsecure_data: mismatched qop %i != %i" % (qop, cred.qop)) raise rpclib.RPCUnsuccessfulReply(GARBAGE_ARGS) cred = cred.body if cred.service == rpc_gss_svc_none or \ cred.gss_proc in (RPCSEC_GSS_INIT, RPCSEC_GSS_CONTINUE_INIT): return data p = GSSUnpacker(data) context = self._get_context(cred.handle) try: if cred.service == rpc_gss_svc_integrity: # data = opaque[gss_seq_num+data] + opaque[checksum] try: data = p.unpack_opaque() checksum = p.unpack_opaque() p.done() except: log_gss.exception("unsecure_data - initial unpacking") raise rpclib.RPCUnsuccessfulReply(GARBAGE_ARGS) qop = context.verifyMIC(data, checksum) check_gssapi(qop) data = pull_seqnum(data) elif cred.service == rpc_gss_svc_privacy: # data = opaque[wrap([gss_seq_num+data])] try: data = p.unpack_opaque() p.done() except: log_gss.exception("unsecure_data - initial unpacking") raise rpclib.RPCUnsuccessfulReply(GARBAGE_ARGS) # data, qop, conf = context.unwrap(data) data, qop = context.unwrap(data) check_gssapi(qop) data = pull_seqnum(data) else: # Can't get here, but doesn't hurt log_gss.error("Unknown service %i for RPCSEC_GSS" % cred.service) except gssapi.Error, e: log_gss.warn("unsecure_data: gssapi call returned %s" % e.name) raise rpclib.RPCUnsuccessfulReply(GARBAGE_ARGS)
def pull_seqnum(blob): """Pulls initial seq_num off of blob, checks it, then returns data. """ # blob = seq_num + data p.reset(blob) try: seq_num = p.unpack_uint() except: log_gss.exception("unsecure_data - unpacking seq_num") raise rpclib.RPCUnsuccessfulReply(GARBAGE_ARGS) if seq_num != cred.seq_num: raise rpclib.RPCUnsuccessfulReply(GARBAGE_ARGS) return p.get_buffer()[p.get_position():]
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()
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() except Exception: log_t.warn("Unexpected exception", exc_info=True) body, data = rpclib.RPCUnsuccessfulReply(SYSTEM_ERR).body() else: try: data = sec.secure_data(msg.body.cred, result) verf = sec.make_reply_verf(msg.body.cred, status) areply = accepted_reply(verf, rpc_reply_data(status, '')) body = reply_body(MSG_ACCEPTED, areply=areply) except Exception: body, data = rpclib.RPCUnsuccessfulReply(SYSTEM_ERR).body() pipe.send_reply(msg.xid, body, data) if notify is not None: notify() def _notify_drop(self): """Debugging hook called when a request is dropped.""" log_t.warn("Dropped request")
def check_gssapi(qop): if qop != cred.qop: # XXX Not sure what error to give here log_gss.warn("unsecure_data: mismatched qop %i != %i" % (qop, cred.qop)) raise rpclib.RPCUnsuccessfulReply(GARBAGE_ARGS)