def check_reply_verf(self, msg, call_cred, data): if msg.stat != MSG_ACCEPTED: return verf = msg.rbody.areply.verf if msg.rbody.areply.reply_data.stat != SUCCESS: if not self.is_NULL(verf): raise SecError("Bad reply verifier - expected NULL verifier") elif call_cred.body.gss_proc in (RPCSEC_GSS_INIT, RPCSEC_GSS_CONTINUE_INIT): # The painful case - we need to check against reply data p = GSSUnpacker(data) try: res = p.unpack_rpc_gss_init_res() p.done() except: log_gss.warn("Failure unpacking gss_init_res") raise SecError("Failure unpacking gss_init_res") if self.is_NULL(verf): if res.gss_major == GSS_S_COMPLETE: raise SecError("Expected seq_window, got NULL") else: if res.gss_major != GSS_S_COMPLETE: raise SecError("Expected NULL") # BUG - context establishment is not finished on client # - so how get context? How run verifyMIC? # - This seems to be a protocol problem. Just ignore for now else: p = Packer() p.pack_uint(call_cred.body.seq_num) qop = call_cred.context.verifyMIC(p.get_buffer(), verf.body) if qop != call_cred.body.qop: raise SecError("Mismatched qop")
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 as e: log_gss.warn("unsecure_data: gssapi call returned %s" % e.name) raise rpclib.RPCUnsuccessfulReply(GARBAGE_ARGS) return data
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 handle_gss_init(self, cred, data, first): p = GSSUnpacker(data) token = p.unpack_opaque() p.done() log_gss.debug("***ACCEPTSECCONTEXT***") if first: context = gssapi.Context() else: context = self._get_context(cred.body.handle) try: token = context.accept(token) except gssapi.Error, e: log_gss.debug("RPCSEC_GSS_INIT failed (%s, %i)!" % (e.name, e.minor)) res = rpc_gss_init_res('', e.major, e.minor, 0, '')
def init_cred(self, call, target="nfs@jupiter", source=None, oid=None): # STUB - need intelligent way to set defaults good_major = [gssapi.GSS_S_COMPLETE, gssapi.GSS_S_CONTINUE_NEEDED] p = Packer() up = GSSUnpacker('') # Set target (of form nfs@SERVER) target = gssapi.Name(target, gssapi.NT_HOSTBASED_SERVICE) # Set source (of form USERNAME) if source is not None: source = gssapi.Name(source, gssapi.NT_USER_NAME) gss_cred = gssapi.Credential(gssapi.INITIATE, source.ptr) # XXX else: # Just use default cred gss_cred = None context = gssapi.Context() token = None handle = '' proc = RPCSEC_GSS_INIT while True: # Call initSecContext. If it returns COMPLETE, we are done. # If it returns CONTINUE_NEEDED, we must send d['token'] # to the target, which will run it through acceptSecContext, # and give us back a token we need to send through initSecContext. # Repeat as necessary. token = context.init(target, token, gss_cred) if context.open: # XXX if res.major == CONTINUE there is a bug in library code # STUB - now what? Just use context? # XXX need to use res.seq_window # XXX - what if handle still '' ? self._add_context(context, handle) break # Send token to target using protocol of RFC 2203 sect 5.2.2 credinfo = CredInfo(self, context=handle, gss_proc=proc) proc = RPCSEC_GSS_CONTINUE_INIT p.reset() p.pack_opaque(token) header, reply = call(p.get_buffer(), credinfo) up.reset(reply) res = up.unpack_rpc_gss_init_res() up.done() # res now holds relevent output from target's acceptSecContext call if res.gss_major not in good_major: raise gssapi.Error(res.gss_major, res.gss_minor) handle = res.handle # Should not change between calls token = res.gss_token # This needs to be sent to initSecContext return CredInfo(self, context=handle)
def handle_gss_init(self, cred, data, first): p = GSSUnpacker(data) token = p.unpack_opaque() p.done() log_gss.debug("***ACCEPTSECCONTEXT***") if first: context = gssapi.Context() else: context = self._get_context(cred.body.handle) try: token = context.accept(token) except gssapi.Error as e: log_gss.debug("RPCSEC_GSS_INIT failed (%s, %i)!" % (e.name, e.minor)) res = rpc_gss_init_res('', e.major, e.minor, 0, '') else: log_gss.debug("RPCSEC_GSS_*INIT succeeded!") if first: handle = self._add_context(context) # XXX HACK - this ensures make_reply_verf works, but # is a subtle side-effect that could introduce bugs if code # is ever reorganized. Currently cred is forgotten once # we leave here though. cred.body.rpc_gss_cred_vers_1_t.handle = handle else: handle = cred.body.handle if context.open: major = gssapi.GSS_S_COMPLETE else: major = gssapi.GSS_S_CONTINUE_NEEDED res = rpc_gss_init_res( handle, major, 0, # XXX can't see minor WINDOWSIZE, token) # Prepare response p = GSSPacker() p.pack_rpc_gss_init_res(res) # NOTE this is an annoying case for make_reply_verf. # It is the only time that you need msg_data to feed into it. verf = self.make_reply_verf(cred, major) raise rpclib.RPCSuccessfulReply(verf, p.get_buffer())
def handle_gss_init(self, cred, data, first): p = GSSUnpacker(data) token = p.unpack_opaque() p.done() log_gss.debug("***ACCEPTSECCONTEXT***") if first: context = gssapi.Context() else: context = self._get_context(cred.body.handle) try: token = context.accept(token) except gssapi.Error as e: log_gss.debug("RPCSEC_GSS_INIT failed (%s, %i)!" % (e.name, e.minor)) res = rpc_gss_init_res('', e.major, e.minor, 0, '') else: log_gss.debug("RPCSEC_GSS_*INIT succeeded!") if first: handle = self._add_context(context) # XXX HACK - this ensures make_reply_verf works, but # is a subtle side-effect that could introduce bugs if code # is ever reorganized. Currently cred is forgotten once # we leave here though. cred.body.rpc_gss_cred_vers_1_t.handle = handle else: handle = cred.body.handle if context.open: major = gssapi.GSS_S_COMPLETE else: major = gssapi.GSS_S_CONTINUE_NEEDED res = rpc_gss_init_res(handle, major, 0, # XXX can't see minor WINDOWSIZE, token) # Prepare response p = GSSPacker() p.pack_rpc_gss_init_res(res) # NOTE this is an annoying case for make_reply_verf. # It is the only time that you need msg_data to feed into it. verf = self.make_reply_verf(cred, major) raise rpclib.RPCSuccessfulReply(verf, p.get_buffer())
def unpack_cred(cred): p = GSSUnpacker(cred) py_cred = p.unpack_rpc_gss_cred_t() p.done() return py_cred