def secure_data(self, cred, data): log_gss.debug("secure_data(%r)" % cred) 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 = Packer() context = self._get_context(cred.handle) try: if cred.service == rpc_gss_svc_integrity: # data = opaque[gss_seq_num+data] + opaque[checksum] p.pack_uint(cred.seq_num) data = p.get_buffer() + data token = context.getMIC(data) # XXX BUG set qop p.reset() p.pack_opaque(data) p.pack_opaque(token) data = p.get_buffer() elif cred.service == rpc_gss_svc_privacy: # data = opaque[wrap([gss_seq_num+data])] p.pack_uint(cred.seq_num) data = p.get_buffer() + data token = context.wrap(data) # XXX BUG set qop p.reset() p.pack_opaque(token) data = p.get_buffer() 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: # XXX What now? log_gss.warn("secure_data: gssapi call returned %s" % e.name) raise return data
def init_cred(self, call, target="nfs@jupiter", source=None, oid=None): # STUB - need intelligent way to set defaults good_major = [GSS_S_COMPLETE, GSS_S_CONTINUE_NEEDED] p = Packer() up = GSSUnpacker('') # Set target (of form nfs@SERVER) target = gssapi.Name(target, gssapi.NameType.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 # RFC2203 5.2.2. Context Creation Requests # When GSS_Init_sec_context() is called, the parameters # replay_det_req_flag and sequence_req_flag must be turned off. # Note - by default, out_of_sequence_detection flag (sequence_req_flag) is used by gssapi.init_sec_context() # and we have 'An expected per-message token was not received' error (GSS_S_GAP_TOKEN). # To prevent this, we need to use default flags without out_of_sequence_detection bit. flags = gssapi.IntEnumFlagSet( gssapi.RequirementFlag, [gssapi.RequirementFlag.mutual_authentication]) context = gssapi.SecurityContext(name=target, creds=gss_cred, flags=flags) input_token = None handle = b'' proc = RPCSEC_GSS_INIT while not context.complete: # 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. output_token = context.step(input_token) if context.complete: # 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(output_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 GSSError(res.gss_major, res.gss_minor) handle = res.handle # Should not change between calls input_token = res.gss_token # This needs to be sent to SecurityContext.step() return CredInfo(self, context=handle)
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)