Esempio n. 1
0
    def send(self, message):
        hostname = get_hostname(self.endpoint)
        if self.session is None:
            self.session = self._build_session()

            # need to send an initial blank message to setup the security
            # context required for encryption
            if self.wrap_required:
                request = requests.Request('POST', self.endpoint, data=None)
                prep_request = self.session.prepare_request(request)
                self._send_request(prep_request)

                protocol = WinRMEncryption.SPNEGO
                if isinstance(self.session.auth, HttpCredSSPAuth):
                    protocol = WinRMEncryption.CREDSSP
                elif self.session.auth.contexts[
                        hostname].response_auth_header == 'kerberos':
                    # When Kerberos (not Negotiate) was used, we need to send a special protocol value and not SPNEGO.
                    protocol = WinRMEncryption.KERBEROS

                self.encryption = WinRMEncryption(
                    self.session.auth.contexts[hostname], protocol)

        log.debug("Sending message: %s" % message)
        # for testing, keep commented out
        # self._test_messages.append({"request": message.decode('utf-8'),
        #                             "response": None})

        headers = self.session.headers
        if self.wrap_required:
            content_type, payload = self.encryption.wrap_message(message)
            type_header = '%s;protocol="%s";boundary="Encrypted Boundary"' \
                          % (content_type, self.encryption.protocol)
            headers.update({
                'Content-Type': type_header,
                'Content-Length': str(len(payload)),
            })
        else:
            payload = message
            headers['Content-Type'] = "application/soap+xml;charset=UTF-8"

        request = requests.Request('POST',
                                   self.endpoint,
                                   data=payload,
                                   headers=headers)
        prep_request = self.session.prepare_request(request)
        return self._send_request(prep_request)
Esempio n. 2
0
    def send(self, message: bytes) -> bytes:
        hostname = get_hostname(self.endpoint)
        if self.session is None:
            self.session = self._build_session()

            # need to send an initial blank message to setup the security
            # context required for encryption
            if self.wrap_required:
                request = requests.Request("POST", self.endpoint, data=None)
                prep_request = self.session.prepare_request(request)
                self._send_request(prep_request)

                protocol = WinRMEncryption.SPNEGO
                if isinstance(self.session.auth, HttpCredSSPAuth):
                    protocol = WinRMEncryption.CREDSSP
                elif self.session.auth.contexts[hostname].response_auth_header == "kerberos":  # type: ignore[union-attr] # This should not happen
                    # When Kerberos (not Negotiate) was used, we need to send a special protocol value and not SPNEGO.
                    protocol = WinRMEncryption.KERBEROS

                self.encryption = WinRMEncryption(self.session.auth.contexts[hostname], protocol)  # type: ignore[union-attr] # This should not happen

        if log.isEnabledFor(logging.DEBUG):
            log.debug("Sending message: %s" % message.decode("utf-8"))
        # for testing, keep commented out
        # self._test_messages.append({"request": message.decode('utf-8'),
        #                             "response": None})

        headers = self.session.headers
        if self.wrap_required:
            content_type, payload = self.encryption.wrap_message(message)  # type: ignore[union-attr] # This should not happen
            protocol = self.encryption.protocol if self.encryption else WinRMEncryption.SPNEGO
            type_header = '%s;protocol="%s";boundary="Encrypted Boundary"' % (content_type, protocol)
            headers.update(
                {
                    "Content-Type": type_header,
                    "Content-Length": str(len(payload)),
                }
            )
        else:
            payload = message
            headers["Content-Type"] = "application/soap+xml;charset=UTF-8"

        request = requests.Request("POST", self.endpoint, data=payload, headers=headers)
        prep_request = self.session.prepare_request(request)
        return self._send_request(prep_request)
Esempio n. 3
0
    def handle_401(self, response, **kwargs):
        host = get_hostname(response.url)
        if self.send_cbt:
            cbt_app_data = HTTPNegotiateAuth._get_cbt_data(response)

        auth_hostname = self.hostname_override or host
        context, token_gen, out_token = get_auth_context(
            self.username, self.password, self.auth_provider, cbt_app_data,
            auth_hostname, self.service, self.delegate, self.wrap_required
        )
        self.contexts[host] = context

        while not context.complete or out_token is not None:
            # consume content and release the original connection to allow the
            # new request to reuse the same one.
            response.content
            response.raw.release_conn()

            # create a request with the Negotiate token present
            request = response.request.copy()
            log.debug("Sending http request with new auth token")
            self._set_auth_token(request, out_token, "Negotiate")

            # send the request with the auth token and get the response
            response = response.connection.send(request, **kwargs)

            # attempt to retrieve the auth token response
            in_token = self._get_auth_token(response, self._regex)

            # break if there was no token received from the host and return the
            # last response
            if in_token in [None, b""]:
                log.debug("Did not receive a http response with an auth "
                          "response, stopping authentication process")
                break

            out_token = token_gen.send(in_token)

        return response
Esempio n. 4
0
    def send(self, message):
        hostname = get_hostname(self.endpoint)
        if self.session is None:
            self.session = self._build_session()

            # need to send an initial blank message to setup the security
            # context required for encryption
            if self.wrap_required:
                request = requests.Request('POST', self.endpoint, data=None)
                prep_request = self.session.prepare_request(request)
                self._send_request(prep_request, hostname)

        log.debug("Sending message: %s" % message)
        # for testing, keep commented out
        # self._test_messages.append({"request": message.decode('utf-8'),
        #                             "response": None})

        headers = self.session.headers
        if self.wrap_required:
            content_type, payload = self.encryption.wrap_message(
                message, hostname)
            type_header = '%s;protocol="%s";boundary="Encrypted Boundary"' \
                          % (content_type, self.encryption.protocol)
            headers.update({
                'Content-Type': type_header,
                'Content-Length': str(len(payload)),
            })
        else:
            payload = message
            headers['Content-Type'] = "application/soap+xml;charset=UTF-8"

        request = requests.Request('POST',
                                   self.endpoint,
                                   data=payload,
                                   headers=headers)
        prep_request = self.session.prepare_request(request)
        return self._send_request(prep_request, hostname)
Esempio n. 5
0
    def handle_401(self, response, **kwargs):
        response_auth_header = kwargs.pop('_pypsrp_auth_provider')
        response_auth_header_l = response_auth_header.lower()
        auth_provider = self.auth_provider

        if response_auth_header_l != self.auth_provider:
            if self.auth_provider == 'negotiate':
                auth_provider = response_auth_header_l

            elif response_auth_header_l != 'negotiate':
                raise ValueError(
                    "Server responded with the auth protocol '%s' which is incompatible with the "
                    "specified auth_provider '%s'" %
                    (response_auth_header, auth_provider))

        host = get_hostname(response.url)
        auth_hostname = self.hostname_override or host

        cbt = None
        if self.send_cbt:
            cbt_app_data = HTTPNegotiateAuth._get_cbt_data(response)
            if cbt_app_data:
                cbt = spnego.channel_bindings.GssChannelBindings(
                    application_data=cbt_app_data)

        context_req = spnego.ContextReq.default
        if self.delegate:
            context_req |= spnego.ContextReq.delegate

        spnego_options = spnego.NegotiateOptions.wrapping_winrm if self.wrap_required else 0
        context = spnego.client(self.username,
                                self.password,
                                hostname=auth_hostname,
                                service=self.service,
                                channel_bindings=cbt,
                                context_req=context_req,
                                protocol=auth_provider,
                                options=spnego_options)
        self.contexts[host] = context

        out_token = context.step()
        while not context.complete or out_token is not None:
            # consume content and release the original connection to allow the
            # new request to reuse the same one.
            response.content
            response.raw.release_conn()

            # create a request with the Negotiate token present
            request = response.request.copy()
            log.debug("Sending http request with new auth token")
            self._set_auth_token(request, out_token, response_auth_header)

            # send the request with the auth token and get the response
            response = response.connection.send(request, **kwargs)

            # attempt to retrieve the auth token response
            in_token = self._get_auth_token(response, self._regex)

            # break if there was no token received from the host and return the
            # last response
            if in_token in [None, b""]:
                log.debug(
                    "Did not receive a http response with an auth response, stopping authentication process"
                )
                break

            out_token = context.step(in_token)

        # This is used by the message encryption to decide the MIME protocol.
        setattr(context, 'response_auth_header', response_auth_header_l)

        return response
Esempio n. 6
0
def test_get_hostname(url, expected):
    assert expected == get_hostname(url)