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.2.0.tar.gz
Algorithm | Hash digest | |
---|---|---|
SHA256 | c82e626b2244efd8fbaf8b5208d4511766b0771264f60b518c716ee6d1a02f67 |
|
MD5 | 9c5eac9e373934b49e992613214a29f2 |
|
BLAKE2b-256 | 0e35365f5b2807731aee8c50e577f9eaa8d570d32877e462dd9d8c4d08c45c59 |
Hashes for jetblack_negotiate_stream-0.2.0-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 3206531c680c4f4a0d5224591421593997bf962f29afe79fe06930c3e432d160 |
|
MD5 | f8a0bcd761b848c7bfd2eacbd83c025e |
|
BLAKE2b-256 | 996d1d1b51a4caec3ce89335e00b892f8e06070df5eb329d82091916f16559da |