mirror of https://github.com/deavmi/cryptstream
Credmanager
- Had to make this as was required Server - Server-side TLS stream thing Client - Client-side stream thing
This commit is contained in:
parent
679530662f
commit
70053118af
|
@ -1,7 +1,7 @@
|
|||
module cryptstream.streams.client;
|
||||
|
||||
import river.core : RiverStream = Stream, StreamException, StreamError;
|
||||
import core.thread : Thread;
|
||||
import core.thread : Thread, dur;
|
||||
import botan.tls.client;
|
||||
|
||||
|
||||
|
@ -26,6 +26,12 @@ public class CryptClient : RiverStream
|
|||
*/
|
||||
private TLSClient botanClient;
|
||||
|
||||
// TODO: Setup
|
||||
private TLSSessionManager sessionManager = new TLSSessionManagerNoop();
|
||||
private TLSCredentialsManager credentialManager;
|
||||
private TLSPolicy policy = new TLSPolicy();
|
||||
private RandomNumberGenerator rng;
|
||||
|
||||
/**
|
||||
* Constructs a new TLS-enabled client stream
|
||||
* Params:
|
||||
|
@ -35,7 +41,14 @@ public class CryptClient : RiverStream
|
|||
{
|
||||
this.stream = stream;
|
||||
|
||||
this.botanClient = new TLSClient(&tlsOutputHandler);
|
||||
this.rng = RandomNumberGenerator.makeRng();
|
||||
|
||||
import cryptstream.streams.credmanager : CredManager;
|
||||
this.credentialManager = new CredManager();
|
||||
|
||||
// FIXME: Currently we are crashing with a segmentation fault here
|
||||
this.botanClient = new TLSClient(&tlsOutputHandler, &decryptedInputHandler, &tlsAlertHandler, &tlsHandshakeHandler,
|
||||
sessionManager, credentialManager, policy, rng);
|
||||
|
||||
// TODO: Insert code to init using botan OVER `stream`
|
||||
|
||||
|
@ -54,16 +67,44 @@ public class CryptClient : RiverStream
|
|||
private void streamReaderWorker()
|
||||
{
|
||||
// TODO: Make this size configurable
|
||||
byte[100] readInto;
|
||||
byte[500] readInto;
|
||||
while(true)
|
||||
{
|
||||
ulong receivedAmount = stream.read(readInto);
|
||||
|
||||
version(unittest)
|
||||
{
|
||||
import std.stdio;
|
||||
import std.conv : to;
|
||||
writeln("streamReaderWorker(client-side): Transferring "~to!(string)(receivedAmount)~" many bytes over to Botan client...");
|
||||
writeln("streamReaderWorker(client-side): The bytes are: "~to!(string)(readInto[0..receivedAmount]));
|
||||
// writeln("streamReaderWorker(): The bytes are (as string): "~cast(string[])readInto[0..receivedAmount]);
|
||||
|
||||
}
|
||||
|
||||
// TODO: Use the hint byte count returned?
|
||||
botanClient.receivedData(cast(ubyte*)readInto.ptr, receivedAmount);
|
||||
}
|
||||
}
|
||||
|
||||
private bool tlsHandshakeHandler(in TLSSession session)
|
||||
{
|
||||
// TODO: Implement me
|
||||
return true;
|
||||
}
|
||||
|
||||
private void decryptedInputHandler(in ubyte[] receivedDecryptedData)
|
||||
{
|
||||
// TODO: This is now decrypted and THIS data should be placed
|
||||
// ... into a buffer in CryptClient that can be read from
|
||||
// ... via `read/readFully`
|
||||
}
|
||||
|
||||
private void tlsAlertHandler(in TLSAlert alert, in ubyte[] data)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// NOTE This gets called when the Botan client needs to write to
|
||||
// ... the underlying output. So If we were to call `botanClient.send`
|
||||
// ... (which takes in our plaintext), it would encrypt, and then
|
||||
|
@ -89,8 +130,10 @@ public class CryptClient : RiverStream
|
|||
/* Ensure the TLS session is active */
|
||||
openCheck();
|
||||
|
||||
// TODO: Implement me
|
||||
return 0;
|
||||
// TODO: It seems we can basically have everything or nothing
|
||||
// ... so just call read as the method of TLS records does this
|
||||
// ... to us
|
||||
return read(toArray);
|
||||
}
|
||||
|
||||
public override ulong write(byte[] fromArray)
|
||||
|
@ -136,4 +179,40 @@ public class CryptClient : RiverStream
|
|||
throw new StreamException(StreamError.CLOSED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
version(unittest)
|
||||
{
|
||||
import river.core;
|
||||
import river.impls : SockStream;
|
||||
import std.socket;
|
||||
import std.stdio;
|
||||
|
||||
import cryptstream.streams.server;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
/**
|
||||
* Setup a server
|
||||
*/
|
||||
Address addr = parseAddress("::1", 7057);
|
||||
writeln("Binding server to: ", addr);
|
||||
Server server = new Server(addr);
|
||||
server.start();
|
||||
|
||||
|
||||
Socket endpoint = new Socket(AddressFamily.INET6, SocketType.STREAM, ProtocolType.TCP);
|
||||
|
||||
|
||||
endpoint.connect(addr);
|
||||
|
||||
Stream stream = new SockStream(endpoint);
|
||||
CryptClient client = new CryptClient(stream);
|
||||
|
||||
Thread.sleep(dur!("seconds")(3));
|
||||
client.writeFully(cast(byte[])"ABBA");
|
||||
|
||||
|
||||
while(true){}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
module cryptstream.streams.credmanager;
|
||||
|
||||
import botan.tls.client;
|
||||
import botan.math.bigint.bigint : BigInt;
|
||||
|
||||
public class CredManager : TLSCredentialsManager
|
||||
{
|
||||
public override Vector!CertificateStore trustedCertificateAuthorities(in string type, in string context)
|
||||
{
|
||||
return super.trustedCertificateAuthorities(type, context);
|
||||
}
|
||||
|
||||
public override void verifyCertificateChain(in string type, in string purported_hostname, const ref Vector!X509Certificate cert_chain)
|
||||
{
|
||||
return super.verifyCertificateChain(type, purported_hostname, cert_chain);
|
||||
}
|
||||
|
||||
public override Vector!X509Certificate certChain(const ref Vector!string cert_key_types, in string type, in string context)
|
||||
{
|
||||
return super.certChain(cert_key_types, type, context);
|
||||
}
|
||||
|
||||
public override Vector!X509Certificate certChainSingleType(in string cert_key_type, in string type, in string context)
|
||||
{
|
||||
return super.certChainSingleType(cert_key_type, type, context);
|
||||
}
|
||||
|
||||
public override PrivateKey privateKeyFor(in X509Certificate cert, in string type, in string context)
|
||||
{
|
||||
return super.privateKeyFor(cert, type, context);
|
||||
}
|
||||
|
||||
public override bool attemptSrp(in string type, in string context)
|
||||
{
|
||||
return super.attemptSrp(type, context);
|
||||
}
|
||||
|
||||
public override string srpIdentifier(in string type, in string context)
|
||||
{
|
||||
return super.srpIdentifier(type, context);
|
||||
}
|
||||
|
||||
public override string srpPassword(in string type, in string context, in string identifier)
|
||||
{
|
||||
return super.srpPassword(type, context, identifier);
|
||||
}
|
||||
|
||||
public override bool srpVerifier(in string type,
|
||||
in string context,
|
||||
in string identifier,
|
||||
ref string group_name,
|
||||
ref BigInt verifier,
|
||||
ref Vector!ubyte salt,
|
||||
bool generate_fake_on_unknown)
|
||||
{
|
||||
return super.srpVerifier(type, context, identifier, group_name, verifier, salt, generate_fake_on_unknown);
|
||||
}
|
||||
|
||||
public override string pskIdentityHint(in string type, in string context)
|
||||
{
|
||||
return super.pskIdentityHint(type, context);
|
||||
}
|
||||
|
||||
public override string pskIdentity(in string type, in string context, in string identity_hint)
|
||||
{
|
||||
return super.pskIdentity(type, context, identity_hint);
|
||||
}
|
||||
|
||||
public override bool hasPsk()
|
||||
{
|
||||
return super.hasPsk();
|
||||
}
|
||||
|
||||
public override PrivateKey channelPrivateKey(string hostname)
|
||||
{
|
||||
return super.channelPrivateKey(hostname);
|
||||
}
|
||||
|
||||
public override SymmetricKey psk(in string type, in string context, in string identity)
|
||||
{
|
||||
return super.psk(type, context, identity);
|
||||
}
|
||||
}
|
|
@ -1,3 +1,160 @@
|
|||
module cryptstream.streams.server;
|
||||
|
||||
import botan.tls.server;
|
||||
import botan.tls.server;
|
||||
import river.core;
|
||||
import river.impls.sock : SockStream;
|
||||
import core.thread;
|
||||
import botan.tls.credentials_manager;
|
||||
|
||||
public class CryptServerHandle
|
||||
{
|
||||
private Stream clientSocket;
|
||||
|
||||
private TLSServer server;
|
||||
|
||||
// TODO: Setup
|
||||
private TLSSessionManager sessionManager = new TLSSessionManagerNoop();
|
||||
private TLSCredentialsManager credentialManager;
|
||||
private TLSPolicy policy = new TLSPolicy();
|
||||
private RandomNumberGenerator rng;
|
||||
|
||||
/**
|
||||
* Reads, in its own thread, bytes from the client
|
||||
* and pushes them into the Botan server
|
||||
*/
|
||||
private Thread streamReader;
|
||||
|
||||
|
||||
this(Stream clientSocket)
|
||||
{
|
||||
import std.stdio;
|
||||
writeln("HOL");
|
||||
|
||||
this.rng = RandomNumberGenerator.makeRng();
|
||||
import cryptstream.streams.credmanager : CredManager;
|
||||
this.credentialManager = new CredManager();
|
||||
this.clientSocket = clientSocket;
|
||||
|
||||
version(unittest)
|
||||
{
|
||||
import std.stdio;
|
||||
writeln("CryptServer ctor(): Before TLSServer creation");
|
||||
}
|
||||
|
||||
this.server = new TLSServer(&tlsOutputHandler, &decryptedInputHandler, &tlsAlertHandler, &tlsHandshakeHandler,
|
||||
sessionManager, credentialManager, policy, rng);
|
||||
|
||||
version(unittest)
|
||||
{
|
||||
import std.stdio;
|
||||
writeln("CryptServer ctor(): AFTER TLSServer creation");
|
||||
}
|
||||
|
||||
this.streamReader = new Thread(&streamReaderWorker);
|
||||
this.streamReader.start();
|
||||
}
|
||||
|
||||
private void streamReaderWorker()
|
||||
{
|
||||
// TODO: Make this size configurable
|
||||
byte[500] readInto;
|
||||
while(true)
|
||||
{
|
||||
ulong receivedAmount = clientSocket.read(readInto);
|
||||
|
||||
version(unittest)
|
||||
{
|
||||
import std.stdio;
|
||||
import std.conv : to;
|
||||
writeln("streamReaderWorker(server-side): Transferring "~to!(string)(receivedAmount)~" many bytes over to Botan server...");
|
||||
writeln("streamReaderWorker(server-side): The bytes are: "~to!(string)(readInto[0..receivedAmount]));
|
||||
}
|
||||
|
||||
// TODO: Use the hint byte count returned?
|
||||
server.receivedData(cast(ubyte*)readInto.ptr, receivedAmount);
|
||||
}
|
||||
}
|
||||
|
||||
private bool tlsHandshakeHandler(in TLSSession session)
|
||||
{
|
||||
// TODO: Implement me
|
||||
return true;
|
||||
}
|
||||
|
||||
private void decryptedInputHandler(in ubyte[] receivedDecryptedData)
|
||||
{
|
||||
// TODO: This is now decrypted and THIS data should be placed
|
||||
// ... into a buffer in CryptServer that can be read from
|
||||
// ... via `read/readFully`
|
||||
}
|
||||
|
||||
private void tlsAlertHandler(in TLSAlert alert, in ubyte[] data)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// NOTE This gets called when the Botan server needs to write to
|
||||
// ... the underlying output. So If we were to call `server.send`
|
||||
// ... (which takes in our plaintext), it would encrypt, and then
|
||||
// ... push the encrypted payload into this method here below
|
||||
// ... (implying we should write to our underlying stream here)
|
||||
private void tlsOutputHandler(in ubyte[] dataOut)
|
||||
{
|
||||
clientSocket.writeFully(cast(byte[])dataOut);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
version(unittest)
|
||||
{
|
||||
import std.socket;
|
||||
import cryptstream.streams.client : CryptClient;
|
||||
import core.thread;
|
||||
|
||||
public class Server : Thread
|
||||
{
|
||||
private Socket serverSocket;
|
||||
this(Address bindAddr)
|
||||
{
|
||||
serverSocket = new Socket(bindAddr.addressFamily(), SocketType.STREAM, ProtocolType.TCP);
|
||||
serverSocket.bind(bindAddr);
|
||||
serverSocket.listen(0);
|
||||
super(&begin);
|
||||
}
|
||||
|
||||
|
||||
private void begin()
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
Socket clientSocket = serverSocket.accept();
|
||||
Stream clientStream = new SockStream(clientSocket);
|
||||
CryptServerHandle cryptoClientStream = new CryptServerHandle(clientStream);
|
||||
Connection clientConnection = new Connection(cryptoClientStream);
|
||||
clientConnection.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Connection : Thread
|
||||
{
|
||||
private CryptServerHandle client;
|
||||
|
||||
this(CryptServerHandle client)
|
||||
{
|
||||
this.client = client;
|
||||
super(&worker);
|
||||
}
|
||||
|
||||
private void worker()
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
// TODO: Do something here with the client
|
||||
import std.stdio;
|
||||
writeln("Hello I am connection");
|
||||
Thread.sleep(dur!("seconds")(10));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue