Giter VIP home page Giter VIP logo

Comments (13)

cpu avatar cpu commented on June 18, 2024 4

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.

djc avatar djc commented on June 18, 2024 2

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.

fade2black avatar fade2black commented on June 18, 2024 1

@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.

fade2black avatar fade2black commented on June 18, 2024 1

@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:

  1. 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?
  2. 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.

ctz avatar ctz commented on June 18, 2024 1
  1. 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?

  1. Almost all crates are poorly documented.

Actionable feedback would help us improve this, and would be welcomed.

from rustls.

jadamcrain avatar jadamcrain commented on June 18, 2024

@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.

jadamcrain avatar jadamcrain commented on June 18, 2024

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.

fade2black avatar fade2black commented on June 18, 2024

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.

djc avatar djc commented on June 18, 2024

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.

fade2black avatar fade2black commented on June 18, 2024

@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.

fade2black avatar fade2black commented on June 18, 2024

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.

djc avatar djc commented on June 18, 2024

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.

cpu avatar cpu commented on June 18, 2024

Closing this for now. If there are more actionable suggestions we can re-open if needed.

from rustls.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.