Пример #1
0
    def ssh_init_sec_context(self,
                             target,
                             desired_mech=None,
                             username=None,
                             recv_token=None):
        """
        Initialize a GSS-API context.

        :param str username: The name of the user who attempts to login
        :param str target: The hostname of the target to connect to
        :param str desired_mech: The negotiated GSS-API mechanism
                                 ("pseudo negotiated" mechanism, because we
                                 support just the krb5 mechanism :-))
        :param str recv_token: The GSS-API token received from the Server
        :raises:
            `.SSHException` -- Is raised if the desired mechanism of the client
            is not supported
        :return: A ``String`` if the GSS-API has returned a token or
            ``None`` if no token was returned
        """
        from pyasn1.codec.der import decoder

        self._username = username
        self._gss_host = target
        targ_name = gssapi.Name("host@" + self._gss_host,
                                gssapi.C_NT_HOSTBASED_SERVICE)
        ctx = gssapi.Context()
        ctx.flags = self._gss_flags
        if desired_mech is None:
            krb5_mech = gssapi.OID.mech_from_string(self._krb5_mech)
        else:
            mech, __ = decoder.decode(desired_mech)
            if mech.__str__() != self._krb5_mech:
                raise SSHException("Unsupported mechanism OID.")
            else:
                krb5_mech = gssapi.OID.mech_from_string(self._krb5_mech)
        token = None
        try:
            if recv_token is None:
                self._gss_ctxt = gssapi.InitContext(
                    peer_name=targ_name,
                    mech_type=krb5_mech,
                    req_flags=ctx.flags,
                )
                token = self._gss_ctxt.step(token)
            else:
                token = self._gss_ctxt.step(recv_token)
        except gssapi.GSSException:
            message = "{} Target: {}".format(sys.exc_info()[1], self._gss_host)
            raise gssapi.GSSException(message)
        self._gss_ctxt_status = self._gss_ctxt.established
        return token
Пример #2
0
 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, '')
Пример #3
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)
Пример #4
0
 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())
Пример #5
0
    def _gssapi_sspi_test(self):
        """
        Test the used methods of python-gssapi or sspi, sspicon from pywin32.
        """
        try:
            import gssapi

            if (
                hasattr(gssapi, "__title__")
                and gssapi.__title__ == "python-gssapi"
            ):
                _API = "PYTHON-GSSAPI-OLD"
            else:
                _API = "PYTHON-GSSAPI-NEW"
        except ImportError:
            import sspicon
            import sspi

            _API = "SSPI"

        c_token = None
        gss_ctxt_status = False
        mic_msg = b"G'day Mate!"

        if _API == "PYTHON-GSSAPI-OLD":
            if self.server_mode:
                gss_flags = (
                    gssapi.C_PROT_READY_FLAG,
                    gssapi.C_INTEG_FLAG,
                    gssapi.C_MUTUAL_FLAG,
                    gssapi.C_DELEG_FLAG,
                )
            else:
                gss_flags = (
                    gssapi.C_PROT_READY_FLAG,
                    gssapi.C_INTEG_FLAG,
                    gssapi.C_DELEG_FLAG,
                )
            # Initialize a GSS-API context.
            ctx = gssapi.Context()
            ctx.flags = gss_flags
            krb5_oid = gssapi.OID.mech_from_string(self.krb5_mech)
            target_name = gssapi.Name(
                "host@" + self.targ_name, gssapi.C_NT_HOSTBASED_SERVICE
            )
            gss_ctxt = gssapi.InitContext(
                peer_name=target_name, mech_type=krb5_oid, req_flags=ctx.flags
            )
            if self.server_mode:
                c_token = gss_ctxt.step(c_token)
                gss_ctxt_status = gss_ctxt.established
                self.assertEquals(False, gss_ctxt_status)
                # Accept a GSS-API context.
                gss_srv_ctxt = gssapi.AcceptContext()
                s_token = gss_srv_ctxt.step(c_token)
                gss_ctxt_status = gss_srv_ctxt.established
                self.assertNotEquals(None, s_token)
                self.assertEquals(True, gss_ctxt_status)
                # Establish the client context
                c_token = gss_ctxt.step(s_token)
                self.assertEquals(None, c_token)
            else:
                while not gss_ctxt.established:
                    c_token = gss_ctxt.step(c_token)
                self.assertNotEquals(None, c_token)
            # Build MIC
            mic_token = gss_ctxt.get_mic(mic_msg)

            if self.server_mode:
                # Check MIC
                status = gss_srv_ctxt.verify_mic(mic_msg, mic_token)
                self.assertEquals(0, status)
        elif _API == "PYTHON-GSSAPI-NEW":
            if self.server_mode:
                gss_flags = (
                    gssapi.RequirementFlag.protection_ready,
                    gssapi.RequirementFlag.integrity,
                    gssapi.RequirementFlag.mutual_authentication,
                    gssapi.RequirementFlag.delegate_to_peer,
                )
            else:
                gss_flags = (
                    gssapi.RequirementFlag.protection_ready,
                    gssapi.RequirementFlag.integrity,
                    gssapi.RequirementFlag.delegate_to_peer,
                )
            # Initialize a GSS-API context.
            krb5_oid = gssapi.MechType.kerberos
            target_name = gssapi.Name(
                "host@" + self.targ_name,
                name_type=gssapi.NameType.hostbased_service,
            )
            gss_ctxt = gssapi.SecurityContext(
                name=target_name,
                flags=gss_flags,
                mech=krb5_oid,
                usage="initiate",
            )
            if self.server_mode:
                c_token = gss_ctxt.step(c_token)
                gss_ctxt_status = gss_ctxt.complete
                self.assertEquals(False, gss_ctxt_status)
                # Accept a GSS-API context.
                gss_srv_ctxt = gssapi.SecurityContext(usage="accept")
                s_token = gss_srv_ctxt.step(c_token)
                gss_ctxt_status = gss_srv_ctxt.complete
                self.assertNotEquals(None, s_token)
                self.assertEquals(True, gss_ctxt_status)
                # Establish the client context
                c_token = gss_ctxt.step(s_token)
                self.assertEquals(None, c_token)
            else:
                while not gss_ctxt.complete:
                    c_token = gss_ctxt.step(c_token)
                self.assertNotEquals(None, c_token)
            # Build MIC
            mic_token = gss_ctxt.get_signature(mic_msg)

            if self.server_mode:
                # Check MIC
                status = gss_srv_ctxt.verify_signature(mic_msg, mic_token)
                self.assertEquals(0, status)
        else:
            gss_flags = (
                sspicon.ISC_REQ_INTEGRITY
                | sspicon.ISC_REQ_MUTUAL_AUTH
                | sspicon.ISC_REQ_DELEGATE
            )
            # Initialize a GSS-API context.
            target_name = "host/" + socket.getfqdn(self.targ_name)
            gss_ctxt = sspi.ClientAuth(
                "Kerberos", scflags=gss_flags, targetspn=target_name
            )
            if self.server_mode:
                error, token = gss_ctxt.authorize(c_token)
                c_token = token[0].Buffer
                self.assertEquals(0, error)
                # Accept a GSS-API context.
                gss_srv_ctxt = sspi.ServerAuth("Kerberos", spn=target_name)
                error, token = gss_srv_ctxt.authorize(c_token)
                s_token = token[0].Buffer
                # Establish the context.
                error, token = gss_ctxt.authorize(s_token)
                c_token = token[0].Buffer
                self.assertEquals(None, c_token)
                self.assertEquals(0, error)
                # Build MIC
                mic_token = gss_ctxt.sign(mic_msg)
                # Check MIC
                gss_srv_ctxt.verify(mic_msg, mic_token)
            else:
                error, token = gss_ctxt.authorize(c_token)
                c_token = token[0].Buffer
                self.assertNotEquals(0, error)
Пример #6
0
    def test_2_gssapi_sspi(self):
        """
        Test the used methods of python-gssapi or sspi, sspicon from pywin32.
        """
        _API = "MIT"
        try:
            import gssapi
        except ImportError:
            import sspicon
            import sspi
            _API = "SSPI"

        c_token = None
        gss_ctxt_status = False
        mic_msg = b"G'day Mate!"

        if _API == "MIT":
            if server_mode:
                gss_flags = (gssapi.C_PROT_READY_FLAG, gssapi.C_INTEG_FLAG,
                             gssapi.C_MUTUAL_FLAG, gssapi.C_DELEG_FLAG)
            else:
                gss_flags = (gssapi.C_PROT_READY_FLAG, gssapi.C_INTEG_FLAG,
                             gssapi.C_DELEG_FLAG)
            # Initialize a GSS-API context.
            ctx = gssapi.Context()
            ctx.flags = gss_flags
            krb5_oid = gssapi.OID.mech_from_string(krb5_mech)
            target_name = gssapi.Name("host@" + targ_name,
                                      gssapi.C_NT_HOSTBASED_SERVICE)
            gss_ctxt = gssapi.InitContext(peer_name=target_name,
                                          mech_type=krb5_oid,
                                          req_flags=ctx.flags)
            if server_mode:
                c_token = gss_ctxt.step(c_token)
                gss_ctxt_status = gss_ctxt.established
                self.assertEquals(False, gss_ctxt_status)
                # Accept a GSS-API context.
                gss_srv_ctxt = gssapi.AcceptContext()
                s_token = gss_srv_ctxt.step(c_token)
                gss_ctxt_status = gss_srv_ctxt.established
                self.assertNotEquals(None, s_token)
                self.assertEquals(True, gss_ctxt_status)
                # Establish the client context
                c_token = gss_ctxt.step(s_token)
                self.assertEquals(None, c_token)
            else:
                while not gss_ctxt.established:
                    c_token = gss_ctxt.step(c_token)
                self.assertNotEquals(None, c_token)
            # Build MIC
            mic_token = gss_ctxt.get_mic(mic_msg)

            if server_mode:
                # Check MIC
                status = gss_srv_ctxt.verify_mic(mic_msg, mic_token)
                self.assertEquals(0, status)
        else:
            gss_flags = (sspicon.ISC_REQ_INTEGRITY
                         | sspicon.ISC_REQ_MUTUAL_AUTH
                         | sspicon.ISC_REQ_DELEGATE)
            # Initialize a GSS-API context.
            target_name = "host/" + socket.getfqdn(targ_name)
            gss_ctxt = sspi.ClientAuth("Kerberos",
                                       scflags=gss_flags,
                                       targetspn=target_name)
            if server_mode:
                error, token = gss_ctxt.authorize(c_token)
                c_token = token[0].Buffer
                self.assertEquals(0, error)
                # Accept a GSS-API context.
                gss_srv_ctxt = sspi.ServerAuth("Kerberos", spn=target_name)
                error, token = gss_srv_ctxt.authorize(c_token)
                s_token = token[0].Buffer
                # Establish the context.
                error, token = gss_ctxt.authorize(s_token)
                c_token = token[0].Buffer
                self.assertEquals(None, c_token)
                self.assertEquals(0, error)
                # Build MIC
                mic_token = gss_ctxt.sign(mic_msg)
                # Check MIC
                gss_srv_ctxt.verify(mic_msg, mic_token)
            else:
                error, token = gss_ctxt.authorize(c_token)
                c_token = token[0].Buffer
                self.assertNotEquals(0, error)