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
Built Distribution
Hashes for jetblack-negotiate-stream-0.1.1.tar.gz
Algorithm | Hash digest | |
---|---|---|
SHA256 | 96a313f2d128bfc66fc95d143e0344424ac3d0b51b2aa3b2237819f4c27557ec |
|
MD5 | 0094a7c847faa1a1fa5e46fcce4e31a7 |
|
BLAKE2b-256 | 02a71b8eb338053a32841db19048c7370474c69edf19d80dee9c96b73d3153ee |
Hashes for jetblack_negotiate_stream-0.1.1-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 0bd166bb8b7577fca0e888543e257d70645540652461e722a9c029ff54275539 |
|
MD5 | 7864f0718e8b5f223e5d6bcedeb14a9b |
|
BLAKE2b-256 | 3360cacfa430891b281b77ae9751c680e19a9966f872651fc820e6d509090823 |