Comments (13)
please have a look at the following complete (without dots ...) C implementation of the server side.
Can I ask where you found this C program in the OpenSSL documentation? I'm curious how it's presented to the user and made discoverable in their repository but so far I'm unable to find it there. The only place I've found this code is on this third party website.
I think much of the angst in this thread stems from comparing apples to oranges. You will always find complexity greater if you compare a simple synchronous server that accepts at most one connection with an asynchronous server that handles many (in addition to customization of server options through command line flag processing).
With that in mind I think we should have a comparable example like @djc presented in his earlier comment so that an apples to apples comparison can be easily made. I've opened #1715 to help on that front. I think it will be a helpful counterpoint to the simple client example that was already there.
I hope our continued engagement on this ticket (in spite of the negativity presented) helps show we do care about these issues.
from rustls.
When you declare our documentation to be terrible, please be very specific about both the problem you're trying to solve and which documentation you're reading, and which questions it is failing to answer.
from rustls.
@jadamcrain Thank you for a quick response.
Well, let me put it this way.
Both server and and client run locally on my Macbook.
A server runs and waits for incoming connections. Assume a client initiates a TCP connection. Upon a successful connection I want them to create a TLS session (agree upon a asymmetric key).
The server spawns a new thread for each established TLS session and they simply ping/pong some random strings encrypted with the session key.
I hope the problem is crystal clear. However, the documentation is toooooo terrible, it does not even include such a simple example or does not provide a simple reference.
from rustls.
@djc rustls
library/crate is not the only one . This thing is widespread among all crate authors. I've never seen so far a well documented crate. I've raised these two problems many times on forums, but no one gives a sh...t about it:
- Crate authors are too much obsessed with creating macros. Programming in Rust has been turning into using ugly macros. I don't know why, but people prefer ugly macros to, for example, well documented builders. Maybe they think that using mysterious macros (difficult to debug) makes them look smarter? Who knows?
- Almost all crates are poorly documented. I often hear this: "It is open source, so go and create docs yourself", "Read source code", etc.
from rustls.
- Crate authors are too much obsessed with creating macros. (..)
rustls has 0 macros in its public API, and from memory we have only one macro internal to the crate. So it sounds like this crate is doing OK here?
- Almost all crates are poorly documented.
Actionable feedback would help us improve this, and would be welcomed.
from rustls.
@fade2black rustls
is the "transport independent" low-level TLS implementation on top of which higher level libraries are written. Chances are you're looking for tokio-rustls which integrates with tokio's TcpSocket types:
https://crates.io/crates/tokio-rustls
Maintainers: I think it might be a good idea to mention and link to tokio-rustls in the Rustls README.
from rustls.
I think the example client and server in the tokio-rustls
crate do exactly that:
https://github.com/rustls/tokio-rustls/tree/main/examples
The server spawns a new task onto the Tokio runtime to handle each connection concurrently.
I think if you go through those two examples in an IDE or with the tokio-rustls docs things will make sense.
from rustls.
I think either the API design is really bad and should be reviewed completely or I miss smth.
For example, suppose I have a piece of code written in Tokio or some other async lib. Doesn’t have to be Tokio, or even TCP. It is straightforward to write in Tokio to write a simple serv/client app where a server accepts client connections, spawns a thread and waits for another request, while the worker threads “talk” to the clients on the bkgd.
Now, I want to encrypt the communication. So, I thought I could establish a tcp connection and immediately after that using your library could write a single line or couple of code lines to perform a handshake and establish a session . Instead, I have to use weird connectors/acceptors, etc.
from rustls.
The tokio-rustls README (though not the reference documentation) leads with this:
use rustls_pki_types::ServerName;
use std::sync::Arc;
use tokio::net::TcpStream;
use tokio_rustls::rustls::{ClientConfig, RootCertStore};
use tokio_rustls::TlsConnector;
// ...
let mut root_cert_store = RootCertStore::empty();
root_cert_store.extend(webpki_roots::TLS_SERVER_ROOTS.iter().cloned());
let config = ClientConfig::builder()
.with_root_certificates(root_cert_store)
.with_no_client_auth();
let connector = TlsConnector::from(Arc::new(config));
let dnsname = ServerName::try_from("www.rust-lang.org").unwrap();
let stream = TcpStream::connect(&addr).await?;
let mut stream = connector.connect(dnsname, stream).await?;
// ...
Is that roughly what you're looking for?
The rustls API is really more low-level, and focuses more on forcing you to decide on trade-offs that are application-dependent. IMO this is not "really bad" API design, but it may not be the API that works well for your application and/or level of understanding of the problem domain.
If you don't like the notion of a "Connector", what would you call something that takes a bunch of required configuration input and wraps it around a connected socket to perform the handshake?
from rustls.
@djc and maintaners. Well, to be specific, please have a look at the following complete (without dots ...) C implementation of the server side.
Please pay attention how simply the server side is implemented. My argument is that TCP logic/concern is separate from SSL (lib) logic. SSL takes a socket (or whatever) and runs handshake. It is called explicitly and you know where and when it happens.
I couldn't find something like this in your code base or docs.
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <openssl/ssl.h>
int main (int argc, char *argv[])
{
int s, cs, len, result;
struct sockaddr_in srv_addr, cli_addr;
char buf[64];
SSL_CTX *ctx;
SSL *ssl;
/* Create a TLS server context with certificates */
ctx = SSL_CTX_new(TLS_server_method());
SSL_CTX_use_certificate_file(ctx, “server.crt”, SSL_FILETYPE_PEM);
SSL_CTX_use_PrivateKey_file(ctx, “server.key”, SSL_FILETYPE_PEM);
/* Set the address and port to listen on */
srv_addr.sin_family = AF_INET;
srv_addr.sin_port = 9001;
inet_pton(AF_INET, “127.0.0.1”, &srv_addr.sin_addr);
/* Create a socket and listen */
s = socket(AF_INET, SOCK_STREAM, 0);
bind(s, (struct sockaddr *)&srv_addr, sizeof(srv_addr));
listen(s, 1);
/* Wait for a new client connection */
printf(“Waiting for a client…\n”);
len = sizeof(cli_addr);
cs = accept(s, (struct sockaddr*)&cli_addr, &len);
/* Create an SSL session for the new socket */
ssl = SSL_new(ctx);
SSL_set_fd(ssl, cs);
/* Run the OpenSSL handshake */
result = SSL_accept(ssl);
if (result == 1) {
/* Exchange some data if the connection succeeded */
sprintf(buf, “Hello from the server”);
SSL_write(ssl, buf, strlen(buf) + 1);
len = SSL_read(ssl, buf, sizeof(buf));
printf(“Received message from client: ‘%s’\n”, buf);
}
/* Done */
close(cs);
close(s);
SSL_free(ssl);
SSL_CTX_free(ctx);
return 0;
}
from rustls.
SSL_set_fd
marries TCP and SSL, SSL_accept
performs a handshake. That's all.
Later, if you want to send info, use SSL_write
, to read use SSL_read
. Isn't it simpler and more intuitive comparing to the 718-line mio example?
from rustls.
Yes, the mio example tries to do async and is probably not the most concise example even then. This should be closer to what you're proposing (should compile with rustls 0.22 and rustls_pemfile 2, otherwise untested):
use std::error::Error as StdError;
use std::fs::File;
use std::io::{BufReader, Write, Read};
use std::net::{SocketAddr, TcpListener};
use std::sync::Arc;
use rustls::ServerConnection;
fn main() -> Result<(), Box<dyn StdError>> {
let certs = rustls_pemfile::certs(&mut BufReader::new(&mut File::open("server.crt")?))
.collect::<Result<Vec<_>, _>>()?;
let private_key =
rustls_pemfile::private_key(&mut BufReader::new(&mut File::open("server.key")?))?.unwrap();
let config = rustls::ServerConfig::builder()
.with_no_client_auth()
.with_single_cert(certs, private_key)?;
let addr = SocketAddr::from(([127, 0, 0, 1], 9001));
let listener = TcpListener::bind(addr)?;
let (mut stream, _) = listener.accept()?;
let mut conn = ServerConnection::new(Arc::new(config))?;
conn.complete_io(&mut stream)?;
conn.writer().write(b"Hello from the server")?;
conn.complete_io(&mut stream)?;
let mut buf = [0; 64];
let len = conn.reader().read(&mut buf)?;
println!("Received message from client: {:?}", &buf[..len]);
Ok(())
}
I don't think the API is worse than your OpenSSL sample, though this is probably harder to discover? We could definitely do a better job at that.
from rustls.
Closing this for now. If there are more actionable suggestions we can re-open if needed.
from rustls.
Related Issues (20)
- 0.23 docs build is broken HOT 2
- optimize receiving data with TLS 1.2 and aes-128-gcm HOT 1
- optimize receiving data with TLS 1.3 and aes-256-gcm
- optimize server-side full handshakes for TLS 1.2 and 1.3 HOT 1
- Connection::dangerous_extract_secrets returns ConnectionTrafficSecrets::Aes128Gcm even when AES-256-GCM is negotiated
- Error: badRecordMac HOT 4
- Cipher suites configured through WebPkiServerVerifier::builder_with_provider is not working. Client hello contains more cipher suites then it configured. HOT 6
- rand_core::RngCore & CryptoRng support for CryptoProvider HOT 7
- expose more information in ClientHello HOT 4
- No common ciphersuit when FFDHE and ECDHE ciphersuites are available on server and client using TLS 1.2 HOT 4
- US Export control information HOT 4
- doc: AcceptedAlert::write doesn't necessarily write all bytes HOT 7
- Support using rustls without using specific ring or aws-lc-rs apis HOT 2
- Feature request: a way to set/get default ticketer dynamically HOT 6
- Feature Request: Avoid panicking when ring and aws_lc_rs are both specified HOT 19
- Option to Relax SNI Host Name Validation for IP Addresses HOT 7
- unbuffered: B: `CapacityBuffer` for `output_tls.capacity()` HOT 9
- The support for "mipsel-unknown-linux-musl" has failed. HOT 2
- Io(Custom { kind: InvalidData, error: AlertReceived(HandshakeFailure) }) HOT 6
- Linux compilation is slow and seems unable to store compilation results HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from rustls.