Skip to main content

A python client for .Net NegotiateStream

Project description

jetblack-negotiate-stream

A Python client for .Net NegotiateStream. It supports single sign on (SSO) and encryption.

This was tested using Python 3.8 on Windows 11.

Installation

Install from pypi.

pip install jetblack-negotiate-stream

Example

The following programs provide a simple echo server in C# and client in Python.

Client

This is an example of a Python client using the synchronous NegotiateStream class. Note the call to authenticate_as_client before reading and writing.

import socket

from jetblack_negotiate_stream import NegotiateStream

def main():
    hostname = socket.gethostname()
    port = 8181

    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
        sock.connect((hostname, port))

        stream = NegotiateStream(hostname, sock)

        # Do the client side negotiate handshake.
        stream.authenticate_as_client()

        for data in (b'first line', b'second line', b'third line'):
            # All reads and writes are encrypted.
            stream.write(data)
            response = stream.read()
            print("Received: ", response)

if __name__ == '__main__':
    main()

Async Client

This program uses NegotiateStreamAsync which is simply an asynchronous version of the NegotiateStream class demonstrated above.

import asyncio
import socket

from jetblack_negotiate_stream import NegotiateStreamAsync

async def main():
    hostname = socket.gethostname()
    port = 8181

    reader, writer = await asyncio.open_connection(hostname, port)

    stream = NegotiateStreamAsync(hostname, reader, writer)

    await stream.authenticate_as_client()
    for data in (b'first line', b'second line', b'third line'):
        stream.write(data)
        await stream.drain()
        response = await stream.read()
        print("Received: ", response)

    stream.close()
    await stream.wait_closed()

if __name__ == '__main__':
    asyncio.run(main())

Alternative Async Client

The following client follows the patterns demonstrated in the asyncio library using open_negotiate_stream. This follows the conventions of the asyncio open_connection function. The negotiation happens before the function returns, resulting in cleaner code.

import asyncio
import socket

from jetblack_negotiate_stream import open_negotiate_stream

async def main():
    hostname = socket.gethostname()
    port = 8181

    # Following the same pattern as asyncio.open_connection.
    reader, writer = await open_negotiate_stream(hostname, port)

    for data in (b'first line', b'second line', b'third line'):
        writer.write(data)
        await writer.drain()
        response = await reader.read()
        print("Received: ", response)

    writer.close()
    await writer.wait_closed()

if __name__ == '__main__':
    asyncio.run(main())

Server

Here is a trivial C# echo server for the clients.

using System;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Text;

namespace NegotiateStreamServer
{
    internal class Program
    {
        static void Main(string[] args)
        {
            var listener = new TcpListener(IPAddress.Any, 8181);
            listener.Start();

            while (true)
            {
                Console.WriteLine("Listening ...");
                var client = listener.AcceptTcpClient();

                try
                {
                    Console.WriteLine("... Client connected.");

                    Console.WriteLine("Authenticating...");
                    var stream = new NegotiateStream(client.GetStream(), false);
                    stream.AuthenticateAsServer();

                    Console.WriteLine(
                        "... {0} authenticated using {1}",
                        stream.RemoteIdentity.Name,
                        stream.RemoteIdentity.AuthenticationType);

                    var buf = new byte[4096];
                    for (var i = 0; i < 3; ++i)
                    {
                        var bytesRead = stream.Read(buf, 0, buf.Length);
                        var message = Encoding.UTF8.GetString(buf, 0, bytesRead);
                        Console.WriteLine(message);
                        stream.Write(buf, 0, bytesRead);
                    }
                    stream.Close();
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.ToString());
                }
            }
        }
    }
}

Acknowledgements

The library uses the pyspnego library, and takes many ideas from net.tcp-proxy.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

jetblack-negotiate-stream-0.2.2.tar.gz (7.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

jetblack_negotiate_stream-0.2.2-py3-none-any.whl (9.8 kB view details)

Uploaded Python 3

File details

Details for the file jetblack-negotiate-stream-0.2.2.tar.gz.

File metadata

  • Download URL: jetblack-negotiate-stream-0.2.2.tar.gz
  • Upload date:
  • Size: 7.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.1.12 CPython/3.10.10 Darwin/21.6.0

File hashes

Hashes for jetblack-negotiate-stream-0.2.2.tar.gz
Algorithm Hash digest
SHA256 802bc76162ebc48f7237b725af160dca68cf11469b574af7a7a2fd0d24bb9389
MD5 0313b8c189b535b6a3657c0590b9a7f2
BLAKE2b-256 81f654c1e7894be785c2f8dab0a0620285c31c5bfbf6c4939de3011fa76390e4

See more details on using hashes here.

File details

Details for the file jetblack_negotiate_stream-0.2.2-py3-none-any.whl.

File metadata

File hashes

Hashes for jetblack_negotiate_stream-0.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 b14b563929944ca503218be09be7aa1df3304a15faf0967e8e8d37dae03bd05f
MD5 2f9a84beb8127355eea51ec42bf92a07
BLAKE2b-256 08e2ebaba1c4d187160ff863d058004f35a7acfbb46fc5f158363677bb3bbd15

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page