Use tls(true) to negotiate an encrypted network connection via TLS.
sha3 = "0.8.2"
blake2 = "0.8.1"
openssl = { version = "0.10.29", features = ["vendored"] }
+native-tls = "0.2.4"
Probabilistic predicates and random number generators.
* [`sockets`](src/prolog/lib/sockets.pl)
Predicates for opening and accepting TCP connections as streams.
+ TLS negotiation is performed via the option `tls(true)` in
+ `socket_client_open/3`, yielding secure encrypted connections.
* [`crypto`](src/prolog/lib/crypto.pl)
Cryptographically secure random numbers and hashes, HMAC-based
key derivation (HKDF), password-based key derivation (PBKDF2),
("$set_seed", 1) => Some(SystemClauseType::SetSeed),
("$skip_max_list", 4) => Some(SystemClauseType::SkipMaxList),
("$sleep", 1) => Some(SystemClauseType::Sleep),
- ("$socket_client_open", 7) => Some(SystemClauseType::SocketClientOpen),
+ ("$socket_client_open", 8) => Some(SystemClauseType::SocketClientOpen),
("$socket_server_open", 3) => Some(SystemClauseType::SocketServerOpen),
("$socket_server_accept", 7) => Some(SystemClauseType::SocketServerAccept),
("$socket_server_close", 1) => Some(SystemClauseType::SocketServerClose),
current_hostname/1]).
:- use_module(library(error)).
+:- use_module(library(lists)).
+parse_socket_options_(tls(TLS), tls-TLS) :-
+ must_be(boolean, TLS), !.
+parse_socket_options_(Option, OptionPair) :-
+ builtins:parse_stream_options_(Option, OptionPair).
+
+parse_socket_options(Options, OptionValues, Stub) :-
+ DefaultOptions = [alias-[], eof_action-eof_code, reposition-false, tls-false, type-text],
+ builtins:parse_options_list(Options, parse_socket_options_, DefaultOptions, OptionValues, Stub).
socket_client_open(Addr, Stream, Options) :-
( var(Addr) ->
;
throw(error(type_error(socket_address, Addr), socket_client_open/3))
),
- builtins:parse_stream_options(Options,
- [Alias, EOFAction, Reposition, Type],
- socket_client_open/3),
- '$socket_client_open'(Address, Port, Stream, Alias, EOFAction, Reposition, Type).
+ parse_socket_options(Options,
+ [Alias, EOFAction, Reposition, TLS, Type],
+ socket_client_open/3),
+ '$socket_client_open'(Address, Port, Stream, Alias, EOFAction, Reposition, Type, TLS).
socket_server_open(Addr, ServerSocket) :-
use std::ops::DerefMut;
use std::rc::Rc;
+use native_tls::TlsStream;
+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum StreamType {
Binary,
ReadlineStream(ReadlineStream),
Stdout,
TcpStream(ClauseName, TcpStream),
+ TlsStream(ClauseName, TlsStream<TcpStream>)
}
impl Drop for StreamInstance {
StreamInstance::TcpStream(_, ref mut tcp_stream) => {
discard_result!(tcp_stream.shutdown(Shutdown::Both));
}
+ StreamInstance::TlsStream(_, ref mut tls_stream) => {
+ discard_result!(tls_stream.shutdown());
+ }
_ => {
}
}
&StreamInstance::Stdout => write!(fmt, "Stdout"),
&StreamInstance::TcpStream(_, ref tcp_stream) =>
write!(fmt, "TcpStream({:?})", tcp_stream),
+ &StreamInstance::TlsStream(_, ref tls_stream) =>
+ write!(fmt, "TlsStream({:?})", tls_stream),
}
}
}
StreamInstance::InputFile(..) => {
"read"
}
- StreamInstance::TcpStream(..) => {
+ StreamInstance::TcpStream(..) |
+ StreamInstance::TlsStream(..) => {
"read_append"
}
StreamInstance::OutputFile(_, _, true) => {
Stream::from_inst(StreamInstance::TcpStream(address, tcp_stream))
}
+ #[inline]
+ pub(crate)
+ fn from_tls_stream(address: ClauseName, tls_stream: TlsStream<TcpStream>) -> Self {
+ Stream::from_inst(StreamInstance::TlsStream(address, tls_stream))
+ }
+
#[inline]
pub(crate)
fn from_file_as_output(name: ClauseName, file: File, in_append_mode: bool) -> Self {
match self.stream_inst.0.borrow().1 {
// StreamInstance::Stdin |
StreamInstance::TcpStream(..) |
+ StreamInstance::TlsStream(..) |
StreamInstance::Bytes(_) |
StreamInstance::ReadlineStream(_) |
StreamInstance::DynReadSource(_) |
match self.stream_inst.0.borrow().1 {
StreamInstance::Stdout
| StreamInstance::TcpStream(..)
+ | StreamInstance::TlsStream(..)
| StreamInstance::Bytes(_)
| StreamInstance::OutputFile(..) => {
true
StreamInstance::TcpStream(_, ref mut tcp_stream) => {
tcp_stream.read(buf)
}
+ StreamInstance::TlsStream(_, ref mut tls_stream) => {
+ tls_stream.read(buf)
+ }
StreamInstance::ReadlineStream(ref mut rl_stream) => {
rl_stream.read(buf)
}
StreamInstance::TcpStream(_, ref mut tcp_stream) => {
tcp_stream.write(buf)
}
+ StreamInstance::TlsStream(_, ref mut tls_stream) => {
+ tls_stream.write(buf)
+ }
StreamInstance::Bytes(ref mut cursor) => {
cursor.write(buf)
}
StreamInstance::TcpStream(_, ref mut tcp_stream) => {
tcp_stream.flush()
}
+ StreamInstance::TlsStream(_, ref mut tls_stream) => {
+ tls_stream.flush()
+ }
StreamInstance::Bytes(ref mut cursor) => {
cursor.flush()
}
use openssl::bn::{BigNum, BigNumContext};
use openssl::nid::Nid;
+use native_tls::TlsConnector;
+
pub fn get_key() -> KeyEvent {
let key;
enable_raw_mode().expect("failed to enable raw mode");
Ok(tcp_stream) => {
let socket_addr = clause_name!(socket_addr, indices.atom_tbl.clone());
- let mut stream = Stream::from_tcp_stream(socket_addr, tcp_stream);
+
+ let mut stream =
+ { let tls = match self.store(self.deref(self[temp_v!(8)])) {
+ Addr::Con(h) if self.heap.atom_at(h) => {
+ if let HeapCellValue::Atom(ref atom, _) = &self.heap[h] {
+ atom.as_str()
+ } else {
+ unreachable!()
+ }
+ }
+ _ => {
+ unreachable!()
+ }
+ };
+ match tls {
+ "false" => { Stream::from_tcp_stream(socket_addr, tcp_stream) }
+ "true" => { let connector = TlsConnector::new().unwrap();
+ let stream = connector.connect(socket_atom.as_str(), tcp_stream).unwrap();
+
+ Stream::from_tls_stream(socket_addr, stream)
+ }
+ _ => { unreachable!() }
+ }
+ };
stream.options = options;
if let Some(ref alias) = &stream.options.alias {