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.
Metadata
Release files for jetblack-negotiate-stream 0.2.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| jetblack-negotiate-stream-0.2.2.tar.gz | 7.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| jetblack_negotiate_stream-0.2.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 17.6 kB
Release files / jetblack-negotiate-stream-0.2.2.tar.gz
| Download URL | jetblack-negotiate-stream-0.2.2.tar.gz |
|---|---|
| Size | 7.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
802bc76162ebc48f7237b725af160dca68cf11469b574af7a7a2fd0d24bb9389
|
|
BLAKE2b-256 checksum How to use checksums |
81f654c1e7894be785c2f8dab0a0620285c31c5bfbf6c4939de3011fa76390e4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/1.1.12 CPython/3.10.10 Darwin/21.6.0
|
Release files / jetblack_negotiate_stream-0.2.2-py3-none-any.whl
| Download URL | jetblack_negotiate_stream-0.2.2-py3-none-any.whl |
|---|---|
| Size | 9.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b14b563929944ca503218be09be7aa1df3304a15faf0967e8e8d37dae03bd05f
|
|
BLAKE2b-256 checksum How to use checksums |
08e2ebaba1c4d187160ff863d058004f35a7acfbb46fc5f158363677bb3bbd15
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/1.1.12 CPython/3.10.10 Darwin/21.6.0
|