Exemple #1
0
    def step(self, in_token=None):
        log.debug("SPNEGO step input: %s",
                  to_text(base64.b64encode(in_token or b"")))

        # Step 1. Process SPNEGO mechs.
        mech_token_in, mech_list_mic, is_spnego = self._step_spnego_input(
            in_token=in_token)

        mech_token_out = None
        if mech_token_in or self.usage == 'initiate':
            # Step 2. Process the inner context tokens.
            mech_token_out = self._step_spnego_token(in_token=mech_token_in)

        if is_spnego:
            # Step 3. Process / generate the mechListMIC.
            out_mic = self._step_spnego_mic(in_mic=mech_list_mic)

            # Step 4. Generate the output SPNEGO token.
            out_token = self._step_spnego_output(out_token=mech_token_out,
                                                 out_mic=out_mic)

        else:
            out_token = mech_token_out
            self._complete = self._context.complete

        if self.complete:
            # Remove the leftover contexts if there are still others remaining.
            self._context_list = collections.OrderedDict([
                (self._chosen_mech, (self._context, None))
            ])

        log.debug("SPNEGO step output: %s" %
                  to_text(base64.b64encode(out_token or b"")))

        return out_token
Exemple #2
0
def split_username(
        username
):  # type: (Optional[str]) -> Tuple[Optional[str], Optional[str]]
    """Splits a username and returns the domain component.

    Will split a username in the Netlogon form `DOMAIN\\username` and return the domain and user part as separate
    strings. If the user does not contain the `DOMAIN\\` prefix or is in the `UPN` form then then user stays the same
    and the domain is an empty string.

    Args:
        username: The username to split

    Returns:
        Tuple[Optional[str], Optional[str]]: The domain and username.
    """
    if username is None:
        return None, None

    if '\\' in username:
        domain, username = username.split('\\', 1)
    else:
        domain = None

    return to_text(domain, nonstring='passthru'), to_text(username,
                                                          nonstring='passthru')
Exemple #3
0
    def step(self, in_token=None):
        if not self._is_wrapped:
            log.debug("NTLM step input: %s",
                      to_text(base64.b64encode(in_token or b"")))

        out_token = getattr(self, '_step_%s' % self.usage)(in_token=in_token)

        if not self._is_wrapped:
            log.debug("NTLM step output: %s",
                      to_text(base64.b64encode(out_token or b"")))

        if self._complete:
            self._temp_msg = None  # Clear out any temp data we still have stored.

            in_usage = 'accept' if self.usage == 'initiate' else 'initiate'
            self._sign_key_out = signkey(self._context_attr, self._session_key,
                                         self.usage)
            self._sign_key_in = signkey(self._context_attr, self._session_key,
                                        in_usage)

            # Found a vague reference in MS-NLMP that states if NTLMv2 authentication was not used then only 1 key is
            # used for sealing. This seems to reference when NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY is not set and
            # not NTLMv2 messages itself.
            # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/d1c86e81-eb66-47fd-8a6f-970050121347
            if self._context_attr & NegotiateFlags.extended_session_security:
                self._handle_out = rc4init(
                    sealkey(self._context_attr, self._session_key, self.usage))
                self._handle_in = rc4init(
                    sealkey(self._context_attr, self._session_key, in_usage))
            else:
                self._handle_out = self._handle_in = rc4init(
                    sealkey(self._context_attr, self._session_key, self.usage))

        return out_token
Exemple #4
0
def ntlm_cred(tmpdir, monkeypatch):
    cleanup = None
    try:
        # Use unicode credentials to test out edge cases when dealing with non-ascii chars.
        username = u'ÜseӜ'
        password = u'Pӓ$sw0r̈d'

        if HAS_SSPI:
            domain = to_text(socket.gethostname())

            # Can only test this out with Windows due to issue with gss-ntlmssp when dealing with surrogate pairs.
            # https://github.com/gssapi/gss-ntlmssp/issues/20
            clef = to_text(b"\xF0\x9D\x84\x9E")
            username += clef
            password += clef

            buff = {
                'name': username,
                'password': password,
                'priv': win32netcon.USER_PRIV_USER,
                'comment': 'Test account for pypsnego tests',
                'flags': win32netcon.UF_NORMAL_ACCOUNT,
            }
            try:
                win32net.NetUserAdd(None, 1, buff)
            except win32net.error as err:
                if err.winerror != 2224:  # Account already exists
                    raise

            def cleanup():
                win32net.NetUserDel(None, username)
        else:
            domain = u'Dȫm̈Ąiᴞ'

            # gss-ntlmssp does a string comparison of the user/domain part using the current process locale settings.
            # To ensure it matches the credentials we specify with the non-ascii chars we need to ensure the locale is
            # something that can support UTF-8 character comparison. macOS can fail with unknown locale on getlocale(),
            # just default to env vars if this get fails.
            try:
                original_locale = locale.getlocale(locale.LC_CTYPE)
            except ValueError:
                original_locale = (None, None)

            def cleanup():
                locale.setlocale(locale.LC_CTYPE, original_locale)

            locale.setlocale(locale.LC_CTYPE, 'en_US.UTF-8')

        tmp_creds = os.path.join(to_text(tmpdir), u'pÿspᴞӛgӫ TÈ$''.creds')
        with open(tmp_creds, mode='wb') as fd:
            fd.write(to_bytes(u'%s:%s:%s' % (domain, username, password)))

        monkeypatch.setenv('NTLM_USER_FILE', to_native(tmp_creds))

        yield u"%s\\%s" % (domain, username), password

    finally:
        if cleanup:
            cleanup()
Exemple #5
0
def test_get_credential_file(tmpdir, monkeypatch):
    tmp_creds = os.path.join(to_text(tmpdir), u'pÿspᴞӛgӫ TÈ$' '.creds')
    with open(tmp_creds, mode='wb') as fd:
        fd.write(b"data")

    monkeypatch.setenv('NTLM_USER_FILE', to_native(tmp_creds))

    actual = ntlm._get_credential_file()
    assert actual == to_text(tmp_creds)
Exemple #6
0
    def __init__(self,
                 username=None,
                 password=None,
                 hostname=None,
                 service=None,
                 channel_bindings=None,
                 context_req=ContextReq.default,
                 usage='initiate',
                 protocol='negotiate',
                 options=0):

        if not HAS_SSPI:
            reraise(
                ImportError(
                    "SSPIProxy requires the SSPI Cython extension to be compiled"
                ), SSPI_IMP_ERR)

        super(SSPIProxy, self).__init__(username, password, hostname, service,
                                        channel_bindings, context_req, usage,
                                        protocol, options, False)

        self._attr_sizes = None
        self._complete = False
        self._credential = None
        self._context = SSPISecContext()
        self.__seq_num = 0

        credential_kwargs = {
            'package': to_text(protocol),
        }

        if usage == 'initiate':
            # TODO: It seems like the SPN is just an empty string for anon auth.
            credential_kwargs['principal'] = None
            credential_kwargs['credential_use'] = CredentialUse.outbound

            if self.username:
                domain, username = split_username(self.username)
                credential_kwargs['auth_data'] = WinNTAuthIdentity(
                    to_text(username, nonstring='passthru'),
                    to_text(domain, nonstring='passthru'),
                    to_text(password, nonstring='passthru'))

        else:
            credential_kwargs['principal'] = self.spn
            credential_kwargs['credential_use'] = CredentialUse.inbound

        try:
            self._credential = acquire_credentials_handle(**credential_kwargs)
        except NativeError as win_err:
            reraise(
                SpnegoError(base_error=win_err,
                            context_msg="Getting SSPI credential"))
Exemple #7
0
    def step(self, in_token=None):
        if not self._is_wrapped:
            log.debug("GSSAPI step input: %s",
                      to_text(base64.b64encode(in_token or b"")))

        out_token = self._context.step(in_token)
        self._context_attr = int(self._context.actual_flags)

        if not self._is_wrapped:
            log.debug("GSSAPI step output: %s",
                      to_text(base64.b64encode(out_token or b"")))

        return out_token
Exemple #8
0
    def __init__(self, username, password, hostname, service, channel_bindings,
                 context_req, usage, protocol, options, _is_wrapped):
        # type: (Optional[text_type], Optional[text_type], Optional[text_type], Optional[text_type], Optional[GssChannelBindings], ContextReq, str, text_type, NegotiateOptions, bool) -> None  # noqa
        self.usage = usage.lower()
        if self.usage not in ['initiate', 'accept']:
            raise ValueError("Invalid usage '%s', must be initiate or accept" %
                             self.usage)

        self.protocol = protocol.lower()
        if self.protocol not in [u'ntlm', u'kerberos', u'negotiate']:
            raise ValueError(
                to_native(
                    u"Invalid protocol '%s', must be ntlm, kerberos, or negotiate"
                    % self.protocol))

        if self.protocol not in self.available_protocols(options=options):
            raise ValueError("Protocol %s is not available" % self.protocol)

        self.username = to_text(username, nonstring='passthru')
        self.password = to_text(password, nonstring='passthru')

        self.spn = None
        if service or hostname:
            self.spn = to_text(
                "%s/%s" % (service.upper() if service else "HOST", hostname
                           or "unspecified"))

        self.channel_bindings = channel_bindings
        self.options = NegotiateOptions(options)

        self.context_req = context_req  # Generic context requirements.
        self._context_req = 0  # Provider specific context requirements.
        for generic, provider in self._context_attr_map:
            if context_req & generic:
                self._context_req |= provider

        self._context_attr = 0  # Provider specific context attributes, set by self.step().

        # Whether the context is wrapped inside another context.
        self._is_wrapped = _is_wrapped  # type: bool

        if options & NegotiateOptions.negotiate_kerberos and (
                self.protocol == 'negotiate'
                and 'kerberos' not in self.available_protocols()):
            raise FeatureMissingError(NegotiateOptions.negotiate_kerberos)

        if options & NegotiateOptions.wrapping_iov and not self.iov_available(
        ):
            raise FeatureMissingError(NegotiateOptions.wrapping_iov)
Exemple #9
0
def test_win_nt_auth_identity_set_username():
    identity = sspi.WinNTAuthIdentity(u"original", None, None)

    test_user = u"user" + to_text(b"\xF0\x9D\x84\x9E")
    identity.username = test_user
    assert identity.username == test_user
    assert str(identity) == to_native(test_user)
Exemple #10
0
    def unpack(b_data):  # type: (bytes) -> TargetInfo
        """ Unpacks the structure from bytes. """
        target_info = TargetInfo()
        b_io = io.BytesIO(b_data)

        b_av_id = b_io.read(2)

        while b_av_id:
            av_id = struct.unpack("<H", b_av_id)[0]
            length = struct.unpack("<H", b_io.read(2))[0]
            b_value = b_io.read(length)

            if av_id in TargetInfo._FIELD_TYPES['text']:
                # All AV_PAIRS are UNICODE encoded.
                value = to_text(b_value, encoding='utf-16-le')

            elif av_id in TargetInfo._FIELD_TYPES['int32']:
                value = AvFlags(struct.unpack("<I", b_value)[0])

            elif av_id == AvId.timestamp:
                value = FileTime.unpack(b_value)

            elif av_id == AvId.single_host:
                value = SingleHost.unpack(b_value)

            else:
                value = b_value

            target_info[AvId(av_id)] = value
            b_av_id = b_io.read(2)

        return target_info
Exemple #11
0
def test_get_credential_file_env_var_missing_file(tmpdir, monkeypatch):
    tmp_creds = os.path.join(to_text(tmpdir), u'pÿspᴞӛgӫ TÈ$' '.creds')

    monkeypatch.setenv('NTLM_USER_FILE', to_native(tmp_creds))

    actual = ntlm._get_credential_file()
    assert actual is None
Exemple #12
0
def test_win_nt_auth_identity_set_domain():
    identity = sspi.WinNTAuthIdentity(None, u"original", None)

    test_domain = u"domain" + to_text(b"\xF0\x9D\x84\x9E")
    identity.domain = test_domain
    assert identity.domain == test_domain
    assert str(identity) == to_native(test_domain) + "\\"
Exemple #13
0
def test_ntowfv1_hash():
    lm_hash = os.urandom(16)
    nt_hash = os.urandom(16)
    ntlm_hash = to_text(b"%s:%s" %
                        (base64.b16encode(lm_hash), base64.b16encode(nt_hash)))

    actual = crypto.ntowfv1(ntlm_hash)

    assert actual == nt_hash
Exemple #14
0
    def step(self, in_token=None):
        log.debug("SSPI step input: %s",
                  to_text(base64.b64encode(in_token or b"")))

        sec_tokens = []
        if in_token:
            sec_tokens.append(SecBuffer(SecBufferType.token, in_token))

        if self.channel_bindings:
            sec_tokens.append(
                SecBuffer(SecBufferType.channel_bindings,
                          self._get_native_bindings()))

        in_buffer = SecBufferDesc(sec_tokens) if sec_tokens else None
        out_buffer = SecBufferDesc([SecBuffer(SecBufferType.token)])

        if self.usage == 'initiate':
            res = initialize_security_context(self._credential,
                                              self._context,
                                              self.spn,
                                              context_req=self._context_req,
                                              input_buffer=in_buffer,
                                              output_buffer=out_buffer)
        else:
            res = accept_security_context(self._credential,
                                          self._context,
                                          in_buffer,
                                          context_req=self._context_req,
                                          output_buffer=out_buffer)

        self._context_attr = int(self._context.context_attr)

        if res == SecStatus.SEC_E_OK:
            self._complete = True
            self._attr_sizes = query_context_attributes(
                self._context, SecPkgAttr.sizes)

        # TODO: Determine if this returns None or an empty byte string.
        out_token = out_buffer[0].buffer

        log.debug("SSPI step output: %s",
                  to_text(base64.b64encode(out_token or b"")))

        return out_token
Exemple #15
0
def test_get_credential_from_file_no_matches(tmpdir, monkeypatch):
    tmp_creds = os.path.join(to_text(tmpdir), u'pÿspᴞӛgӫ TÈ$' '.creds')
    monkeypatch.setenv('NTLM_USER_FILE', to_native(tmp_creds))
    with open(tmp_creds, mode='wb') as fd:
        fd.write(b'domain:username:password')

    with pytest.raises(
            SpnegoError,
            match="Failed to find any matching credential in NTLM_USER_FILE "
            "credential store."):
        ntlm._NTLMCredential("fake", "username")
Exemple #16
0
    def _step_accept_negotiate(self, token):  # type: (bytes) -> bytes
        """ Process the Negotiate message from the initiator. """
        negotiate = Negotiate.unpack(token)

        flags = negotiate.flags | NegotiateFlags.request_target | NegotiateFlags.ntlm | \
            NegotiateFlags.always_sign | NegotiateFlags.target_info | NegotiateFlags.target_type_server

        # Make sure either UNICODE or OEM is set, not both.
        if flags & NegotiateFlags.unicode:
            flags &= ~NegotiateFlags.oem
        elif flags & NegotiateFlags.oem == 0:
            raise SpnegoError(
                ErrorCode.failure,
                context_msg=
                "Neither NEGOTIATE_OEM or NEGOTIATE_UNICODE flags were "
                "set, cannot derive encoding for text fields")

        if flags & NegotiateFlags.extended_session_security:
            flags &= ~NegotiateFlags.lm_key

        server_challenge = os.urandom(8)
        target_name = to_text(socket.gethostname()).upper()

        target_info = TargetInfo()
        target_info[AvId.nb_computer_name] = target_name
        target_info[AvId.nb_domain_name] = u"WORKSTATION"
        target_info[AvId.dns_computer_name] = to_text(socket.getfqdn())
        target_info[AvId.timestamp] = FileTime.now()

        challenge = Challenge(flags,
                              server_challenge,
                              target_name=target_name,
                              target_info=target_info)

        self._temp_msg = {
            'negotiate': negotiate,
            'challenge': challenge,
        }

        return challenge.pack()
Exemple #17
0
    def _rebuild_context_list(self,
                              mech_types=None
                              ):  # type: (Optional[List[str]]) -> List[str]
        """ Builds a new context list that are available to the client. """
        context_kwargs = {
            'username': self.username,
            'password': self.password,
            'hostname': self._hostname,
            'service': self._service,
            'channel_bindings': self.channel_bindings,
            'context_req': self.context_req,
            'usage': self.usage,
            'options': self.options,
            '_is_wrapped': True,
        }
        gssapi_protocols = [
            p for p in GSSAPIProxy.available_protocols(options=self.options)
            if p != 'negotiate'
        ]
        all_protocols = gssapi_protocols[:]
        if 'ntlm' not in all_protocols:
            all_protocols.append('ntlm')

        self._context_list = collections.OrderedDict()
        mech_list = []
        last_err = None
        for protocol in all_protocols:
            mech = getattr(GSSMech, protocol)
            if mech_types and mech.value not in mech_types:
                continue

            try:
                proxy_obj = GSSAPIProxy if protocol in gssapi_protocols else NTLMProxy
                context = proxy_obj(protocol=protocol, **context_kwargs)
                first_token = context.step(
                ) if self.usage == 'initiate' else None
            except Exception as e:
                last_err = e
                log.debug(
                    "Failed to create gssapi context for SPNEGO protocol %s: %s",
                    protocol, to_text(e))
                continue

            self._context_list[mech] = (context, first_token)
            mech_list.append(mech.value)

        if not mech_list:
            raise BadMechanismError(
                context_msg="Unable to negotiate common mechanism",
                base_error=last_err)

        return mech_list
Exemple #18
0
def test_ntlm_custom_time(include_time, expected, ntlm_cred, mocker,
                          monkeypatch):
    c = spnego.client(ntlm_cred[0],
                      ntlm_cred[1],
                      hostname=socket.gethostname(),
                      options=spnego.NegotiateOptions.use_ntlm,
                      protocol='ntlm')

    b_negotiate = c.step()
    negotiate = Negotiate.unpack(b_negotiate)

    flags = negotiate.flags | NegotiateFlags.request_target | NegotiateFlags.ntlm | \
        NegotiateFlags.always_sign | NegotiateFlags.target_info | NegotiateFlags.target_type_server

    server_challenge = os.urandom(8)
    target_name = to_text(socket.gethostname()).upper()

    target_info = TargetInfo()
    target_info[AvId.nb_computer_name] = target_name
    target_info[AvId.nb_domain_name] = u"WORKSTATION"
    target_info[AvId.dns_computer_name] = to_text(socket.getfqdn())

    if include_time:
        target_info[AvId.timestamp] = FileTime.now()

    challenge = Challenge(flags,
                          server_challenge,
                          target_name=target_name,
                          target_info=target_info)

    mock_now = mocker.MagicMock()
    mock_now.side_effect = FileTime.now
    monkeypatch.setattr(FileTime, 'now', mock_now)

    c.step(challenge.pack())
    assert c.complete
    assert mock_now.call_count == expected
Exemple #19
0
def test_ntlm_workstation_override(env_var, expected, ntlm_cred, monkeypatch):
    if env_var is not None:
        monkeypatch.setenv('NETBIOS_COMPUTER_NAME', env_var)

    c = spnego.client(ntlm_cred[0],
                      ntlm_cred[1],
                      hostname=socket.gethostname(),
                      options=spnego.NegotiateOptions.use_ntlm,
                      protocol='ntlm')

    b_negotiate = c.step()
    negotiate = Negotiate.unpack(b_negotiate)

    flags = negotiate.flags | NegotiateFlags.request_target | NegotiateFlags.ntlm | \
        NegotiateFlags.always_sign | NegotiateFlags.target_info | NegotiateFlags.target_type_server

    server_challenge = os.urandom(8)
    target_name = to_text(socket.gethostname()).upper()

    target_info = TargetInfo()
    target_info[AvId.nb_computer_name] = target_name
    target_info[AvId.nb_domain_name] = u"WORKSTATION"
    target_info[AvId.dns_computer_name] = to_text(socket.getfqdn())
    target_info[AvId.timestamp] = FileTime.now()

    version = Version(10, 0, 0, 1)
    challenge = Challenge(flags,
                          server_challenge,
                          target_name=target_name,
                          target_info=target_info,
                          version=version)

    b_auth = c.step(challenge.pack())
    auth = Authenticate.unpack(b_auth)

    assert auth.workstation == expected
Exemple #20
0
def _get_credential_file():  # type: () -> Optional[text_type]
    """Get the path to the NTLM credential store.

    Returns the path to the NTLM credential store specified by the environment variable `NTLM_USER_FILE`.

    Returns:
        Optional[bytes]: The path to the NTLM credential file or None if not set or found.
    """
    user_file_path = os.environ.get('NTLM_USER_FILE', None)
    if not user_file_path:
        return

    user_file_path = to_text(user_file_path, encoding='utf-8')
    if os.path.isfile(user_file_path):
        return user_file_path
Exemple #21
0
def test_get_credential_from_file(line, username, domain, lm_hash, nt_hash,
                                  explicit, tmpdir, monkeypatch):
    tmp_creds = os.path.join(to_text(tmpdir), u'pÿspᴞӛgӫ TÈ$' '.creds')
    monkeypatch.setenv('NTLM_USER_FILE', to_native(tmp_creds))
    with open(tmp_creds, mode='wb') as fd:
        fd.write(to_bytes(line))

    if explicit:
        actual = ntlm._NTLMCredential(domain, username)

    else:
        actual = ntlm._NTLMCredential()

    assert actual.username == username
    assert actual.domain == domain
    assert actual.lm_hash == base64.b16decode(lm_hash)
    assert actual.nt_hash == base64.b16decode(nt_hash)
Exemple #22
0
def _get_workstation():  # type: () -> Optional[str]
    """Get the current workstation name.

    This gets the current workstation name that respects `NETBIOS_COMPUTER_NAME`. The env var is used by the library
    that gss-ntlmssp calls and makes sure that this Python implementation is a closer in its behaviour.

    Returns:
        Optional[str]: The workstation to supply in the NTLM authentication message or None.
    """
    if 'NETBIOS_COMPUTER_NAME' in os.environ:
        workstation = os.environ['NETBIOS_COMPUTER_NAME']

    else:
        workstation = socket.gethostname().upper()

    # An empty workstation should be None so we don't set it in the message.
    return to_text(workstation) if workstation else None
Exemple #23
0
def unpack_asn1_generalized_time(value):  # type: (Union[bytes, ASN1Value]) -> datetime.datetime
    """ Unpacks an ASN.1 GeneralizedTime value. """
    data = to_text(extract_asn1_tlv(value, TagClass.universal, TypeTagNumber.generalized_time))

    # While ASN.1 can have a timezone encoded, KerberosTime is the only thing we use and it is always in UTC with the
    # Z prefix. We strip out the Z because Python 2 doesn't support the %z identifier and add the UTC tz to the object.
    # https://www.rfc-editor.org/rfc/rfc4120#section-5.2.3
    if data.endswith('Z'):
        data = data[:-1]

    err = None
    for datetime_format in ['%Y%m%d%H%M%S.%f', '%Y%m%d%H%M%S']:
        try:
            dt = datetime.datetime.strptime(data, datetime_format)
            return dt.replace(tzinfo=UTC())
        except ValueError as e:
            err = e

    else:
        raise err
Exemple #24
0
 def domain_name(self):  # type: () -> Optional[text_type]
     """ The domain or computer name hosting the user account. """
     return to_text(_unpack_payload(self._data, 28), encoding=self._encoding, nonstring='passthru')
Exemple #25
0
    FileTime,
    NegotiateFlags,
    NTClientChallengeV2,
    TargetInfo,
)

from spnego._text import (
    text_type,
    to_bytes,
    to_text,
)

# A user does not need to specify their actual plaintext password they can specify the LM and NT hash (from lmowfv1 and
# ntowfv2) in the form 'lm_hash_hex:nt_hash_hex'. This is still considered a plaintext pass as we can use it to build
# the LM and NT response but it's only usable for NTLM.
_NTLM_HASH_PATTERN = re.compile(to_text(r'^[a-fA-F0-9]{32}:[a-fA-F0-9]{32}$'))


class RC4Handle:
    """ RC4 class to wrap the underlying crypto function. """
    def __init__(self, key):  # type: (bytes) -> None
        self._key = key
        self._handle = None
        self.reset()

    def update(self, b_data):  # type: (bytes) -> bytes
        """ Update the RC4 stream and return the encrypted/decrypted bytes. """
        return self._handle.update(b_data)

    def reset(self):  # type: () -> None
        """ Reset's the cipher stream back to the original state. """
Exemple #26
0
    if sys.version_info[0] == 2:
        assert actual == r"SecBuffer(cbBuffer=4, BufferType=1, pvBuffer='\x01\x02\x03\x04')"

    else:
        assert actual == r"SecBuffer(cbBuffer=4, BufferType=1, pvBuffer=b'\x01\x02\x03\x04')"


@pytest.mark.skipif(
    SKIP, reason='Can only test Cython code on Windows with compiled code.')
@pytest.mark.parametrize(
    'username, domain, expected',
    [(u"username", u"domain", "domain\\username"),
     (u"username@DOMAIN", u"", "username@DOMAIN"),
     (u"username@DOMAIN", None, "username@DOMAIN"),
     (None, u"domain", "domain\\"), (None, None, u""), (u"", u"", u""),
     (u"user" + to_text(b"\xF0\x9D\x84\x9E"),
      u"domain" + to_text(b"\xF0\x9D\x84\x9E"),
      to_native(u"domain{0}\\user{0}".format(to_text(b"\xF0\x9D\x84\x9E"))))])
def test_win_nt_auth_identity(username, domain, expected):
    identity = sspi.WinNTAuthIdentity(username, domain, u"password")

    assert repr(
        identity) == "<spnego._sspi_raw.sspi.WinNTAuthIdentity %s>" % expected
    assert str(identity) == expected


@pytest.mark.skipif(
    SKIP, reason='Can only test Cython code on Windows with compiled code.')
def test_win_nt_auth_identity_set_username():
    identity = sspi.WinNTAuthIdentity(u"original", None, None)
Exemple #27
0
 def user_name(self):  # type: () -> Optional[text_type]
     """ The name of the user to be authenticated. """
     return to_text(_unpack_payload(self._data, 36), encoding=self._encoding, nonstring='passthru')
Exemple #28
0
                      hostname=socket.gethostname(),
                      options=spnego.NegotiateOptions.use_ntlm,
                      protocol='ntlm')
    s = spnego.server(options=spnego.NegotiateOptions.use_ntlm,
                      protocol='ntlm')

    auth = memoryview(bytearray(c.step(s.step(c.step()))))
    auth[64:80] = b"\x01" * 16

    with pytest.raises(InvalidTokenError,
                       match="Invalid MIC in NTLM authentication message"):
        s.step(auth.tobytes())


@pytest.mark.parametrize('env_var, expected', [
    (None, to_text(socket.gethostname()).upper()),
    ('', None),
    ('custom', 'custom'),
])
def test_ntlm_workstation_override(env_var, expected, ntlm_cred, monkeypatch):
    if env_var is not None:
        monkeypatch.setenv('NETBIOS_COMPUTER_NAME', env_var)

    c = spnego.client(ntlm_cred[0],
                      ntlm_cred[1],
                      hostname=socket.gethostname(),
                      options=spnego.NegotiateOptions.use_ntlm,
                      protocol='ntlm')

    b_negotiate = c.step()
    negotiate = Negotiate.unpack(b_negotiate)
Exemple #29
0
def test_win_nt_auth_identity_set_password():
    identity = sspi.WinNTAuthIdentity(None, None, u"original")

    test_password = u"password" + to_text(b"\xF0\x9D\x84\x9E")
    identity.password = test_password
    assert identity.password == test_password
Exemple #30
0
 def workstation(self):  # type: () -> Optional[text_type]
     """ The name of the computer to which the user is logged on. """
     return to_text(_unpack_payload(self._data, 44), encoding=self._encoding, nonstring='passthru')