HACK quic support
authorStefan Metzmacher <metze@samba.org>
Mon, 29 Apr 2024 17:04:11 +0000 (19:04 +0200)
committerStefan Metzmacher <metze@samba.org>
Tue, 7 May 2024 14:18:01 +0000 (16:18 +0200)
source3/include/proto.h
source3/lib/util_sock.c
source3/smbd/globals.h
source3/smbd/proto.h
source3/smbd/server.c
source3/smbd/smb2_process.c
source3/smbd/smb2_server.c
source3/wscript
source3/wscript_build

index 8a6b944a0d6dac7025e44c75b566b951a7e29747..1eb0658e1f7bf28de3784421da59070447c5fbc6 100644 (file)
@@ -477,6 +477,12 @@ NTSTATUS receive_smb_raw(int fd,
                        unsigned int timeout,
                        size_t maxlen,
                        size_t *p_len);
+int open_socket_in_protocol(
+       int type,
+       int protocol,
+       const struct sockaddr_storage *paddr,
+       uint16_t port,
+       bool rebind);
 int open_socket_in(
        int type,
        const struct sockaddr_storage *paddr,
index 5ff875c230dc065f3eed97e56108a52ac99c9672..3f3c2142a102cf249dfc3e495f879f49a584e921 100644 (file)
@@ -241,8 +241,9 @@ NTSTATUS receive_smb_raw(int fd, char *buffer, size_t buflen, unsigned int timeo
  * Return sock or -errno
  */
 
-int open_socket_in(
+int open_socket_in_protocol(
        int type,
+       int protocol,
        const struct sockaddr_storage *paddr,
        uint16_t port,
        bool rebind)
@@ -271,7 +272,7 @@ int open_socket_in(
                goto fail;
        }
 
-       sock = socket(addr.u.ss.ss_family, type, 0 );
+       sock = socket(addr.u.ss.ss_family, type, protocol );
        if (sock == -1) {
                ret = -errno;
                DBG_DEBUG("socket() failed: %s\n", strerror(errno));
@@ -353,6 +354,15 @@ fail:
        return ret;
  }
 
+int open_socket_in(
+       int type,
+       const struct sockaddr_storage *paddr,
+       uint16_t port,
+       bool rebind)
+{
+       return open_socket_in_protocol(type, 0, paddr, port, rebind);
+}
+
 struct open_socket_out_state {
        int fd;
        struct tevent_context *ev;
index 507d38a97a1e715e479e8f029e41ad8d15725e2f..ca04e43d72b6cd1b972b5ec13f8be3424f0f88d1 100644 (file)
 #include "smbprofile.h"
 #include "lib/util/samba_io_uring.h"
 
+#ifdef HAVE_LIBQUIC
+#include <netinet/quic.h>
+#endif
+
 #ifdef USE_DMAPI
 struct smbd_dmapi_context;
 extern struct smbd_dmapi_context *dmapi_ctx;
@@ -375,6 +379,7 @@ struct smbXsrv_connection {
                struct tevent_queue *shutdown_wait_queue;
                int sock;
                struct tevent_fd *fde;
+               bool quic;
 
                struct {
                        bool got_session;
@@ -710,6 +715,10 @@ struct smbd_smb2_send_queue {
        struct iovec *vector;
        int count;
 
+       struct {
+               char cmsg[CMSG_SPACE(sizeof(struct quic_stream_info))];
+       } quic;
+
        struct {
                bool initialized;
 #if 0
index 0200c39778d2977262cf42fb79b1fb5bd8ff2807..4c437889317d8b1748f192d8fe9133f6940df9d3 100644 (file)
@@ -910,7 +910,8 @@ void process_smb(struct smbXsrv_connection *xconn,
 void smbd_process(struct tevent_context *ev_ctx,
                  struct messaging_context *msg_ctx,
                  int sock_fd,
-                 bool interactive);
+                 bool interactive,
+                 bool quic);
 bool valid_smb1_header(const uint8_t *inbuf);
 bool init_smb1_request(struct smb_request *req,
                      struct smbd_server_connection *sconn,
index 18c79f9df35637404bca2cb0c45ca872dd5e31fa..5348a5e67c2d8f4eb27fdf11548f06db3a5b9388 100644 (file)
@@ -83,12 +83,18 @@ struct smbd_parent_context {
        struct server_id notifyd;
 
        struct tevent_timer *cleanup_te;
+
+       struct {
+               char *keyfile;
+               char *certfile;
+       } quic;
 };
 
 struct smbd_open_socket {
        struct smbd_open_socket *prev, *next;
        struct smbd_parent_context *parent;
        int fd;
+       bool quic;
        struct tevent_fd *fde;
 };
 
@@ -957,6 +963,8 @@ static void smbd_accept_connection(struct tevent_context *ev,
        struct smbd_open_socket *s = talloc_get_type_abort(private_data,
                                     struct smbd_open_socket);
        struct messaging_context *msg_ctx = s->parent->msg_ctx;
+       char *keyfile = s->parent->quic.keyfile;
+       char *certfile = s->parent->quic.certfile;
        struct sockaddr_storage addr;
        socklen_t in_addrlen = sizeof(addr);
        int fd;
@@ -975,7 +983,14 @@ static void smbd_accept_connection(struct tevent_context *ev,
 
        if (s->parent->interactive) {
                reinit_after_fork(msg_ctx, ev, true);
-               smbd_process(ev, msg_ctx, fd, true);
+               if (s->quic) {
+                       int ret;
+                       ret = quic_server_handshake(fd, keyfile, certfile);
+                       if (ret != 0) {
+                               exit_server_cleanly("quic_server_handshake");
+                       }
+               }
+               smbd_process(ev, msg_ctx, fd, true, s->quic);
                exit_server_cleanly("end of interactive mode");
                return;
        }
@@ -989,6 +1004,7 @@ static void smbd_accept_connection(struct tevent_context *ev,
        if (pid == 0) {
                char addrstr[INET6_ADDRSTRLEN];
                NTSTATUS status = NT_STATUS_OK;
+               bool quic = s->quic;
 
                /*
                 * Can't use TALLOC_FREE here. Nulling out the argument to it
@@ -1028,7 +1044,14 @@ static void smbd_accept_connection(struct tevent_context *ev,
                print_sockaddr(addrstr, sizeof(addrstr), &addr);
                process_set_title("smbd[%s]", "client [%s]", addrstr);
 
-               smbd_process(ev, msg_ctx, fd, false);
+               if (quic) {
+                       int ret;
+                       ret = quic_server_handshake(fd, keyfile, certfile);
+                       if (ret != 0) {
+                               exit_server_cleanly("quic_server_handshake");
+                       }
+               }
+               smbd_process(ev, msg_ctx, fd, false, quic);
         exit:
                exit_server_cleanly("end of child");
                return;
@@ -1078,14 +1101,16 @@ static bool smbd_open_one_socket(struct smbd_parent_context *parent,
 {
        struct smbd_open_socket *s;
 
-       s = talloc(parent, struct smbd_open_socket);
+       s = talloc_zero(parent, struct smbd_open_socket);
        if (!s) {
                return false;
        }
 
        s->parent = parent;
 
-       s->fd = open_socket_in(SOCK_STREAM, ifss, port, true);
+       //s->fd = open_socket_in(SOCK_STREAM, ifss, port, true);
+       port = 443;
+       s->fd = open_socket_in_protocol(SOCK_DGRAM, IPPROTO_QUIC, ifss, port, false);
        if (s->fd < 0) {
                int err = -(s->fd);
                DBG_ERR("open_socket_in failed: %s\n", strerror(err));
@@ -1096,9 +1121,12 @@ static bool smbd_open_one_socket(struct smbd_parent_context *parent,
                return true;
        }
 
+       setsockopt(s->fd, SOL_QUIC, QUIC_SOCKOPT_ALPN, "smb", strlen("smb"));
+       s->quic = true;
+
        /* ready to listen */
-       set_socket_options(s->fd, "SO_KEEPALIVE");
-       set_socket_options(s->fd, lp_socket_options());
+       //set_socket_options(s->fd, "SO_KEEPALIVE");
+       //set_socket_options(s->fd, lp_socket_options());
 
        /* Set server socket to
         * non-blocking for the accept. */
@@ -1220,6 +1248,7 @@ static bool open_sockets_smbd(struct smbd_parent_context *parent,
 #else
                sock_addr = "0.0.0.0";
 #endif
+               sock_addr = "0.0.0.0";
 
                for (sock_ptr=sock_addr;
                     next_token_talloc(talloc_tos(), &sock_ptr, &sock_tok, " \t,"); ) {
@@ -1897,6 +1926,15 @@ extern void build_options(bool screen);
        parent->msg_ctx = msg_ctx;
        am_parent = parent;
 
+       {
+               struct loadparm_context *lp_ctx = NULL;
+
+               lp_ctx = loadparm_init_s3(parent, loadparm_s3_helpers());
+               parent->quic.keyfile = lpcfg_tls_keyfile(parent, lp_ctx);
+               parent->quic.certfile = lpcfg_tls_certfile(parent, lp_ctx);
+               TALLOC_FREE(lp_ctx);
+       }
+
        se = tevent_add_signal(parent->ev_ctx,
                               parent,
                               SIGTERM, 0,
@@ -2094,7 +2132,7 @@ extern void build_options(bool screen);
                /* Stop zombies */
                smbd_setup_sig_chld_handler(parent);
 
-               smbd_process(ev_ctx, msg_ctx, sock, true);
+               smbd_process(ev_ctx, msg_ctx, sock, true, false);
 
                exit_server_cleanly(NULL);
                return(0);
index 52533beb78f5274c19b2f83e0bd7c9773b64945f..c94cd473b392da890fcc636bec531a16d9be8f7b 100644 (file)
@@ -1748,7 +1748,8 @@ static void smbd_tevent_trace_callback_profile(enum tevent_trace_point point,
 void smbd_process(struct tevent_context *ev_ctx,
                  struct messaging_context *msg_ctx,
                  int sock_fd,
-                 bool interactive)
+                 bool interactive,
+                 bool quic)
 {
        struct smbd_tevent_trace_state trace_state = {
                .ev = ev_ctx,
@@ -1840,12 +1841,15 @@ void smbd_process(struct tevent_context *ev_ctx,
                 * name"
                 */
                unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
+               xconn->transport.quic = quic;
                (void)smb1_srv_send(xconn, (char *)buf, false, 0, false);
                exit_server_cleanly("connection denied");
        } else if (!NT_STATUS_IS_OK(status)) {
                exit_server_cleanly(nt_errstr(status));
        }
 
+       xconn->transport.quic = quic;
+
        sconn->local_address =
                tsocket_address_copy(xconn->local_address, sconn);
        if (sconn->local_address == NULL) {
index 55d8305666005282bd9b436b3ae075a915ea9f79..c9c11d82c1aa265134b4cc7214a0a1be1245e820 100644 (file)
@@ -5141,6 +5141,25 @@ static NTSTATUS smbd_smb2_flush_with_sendmsg(struct smbXsrv_connection *xconn)
                sendmsg_flags |= MSG_DONTWAIT;
 #endif
 
+               if (xconn->transport.quic) {
+                       struct cmsghdr *cmsg = NULL;
+                       struct quic_stream_info *info = NULL;
+
+                       e->msg.msg_control = e->quic.cmsg;
+                       e->msg.msg_controllen = sizeof(e->quic.cmsg);
+
+                       cmsg = CMSG_FIRSTHDR(&e->msg);
+                       cmsg->cmsg_level = IPPROTO_QUIC;
+                       cmsg->cmsg_type = 0;
+                       cmsg->cmsg_len = CMSG_LEN(sizeof(*info));
+
+                       info = (struct quic_stream_info *)CMSG_DATA(cmsg);
+                       info->stream_id = 0;
+                       info->stream_flag = 0;
+
+                       e->msg.msg_controllen = cmsg->cmsg_len;
+               }
+
                ret = sendmsg(xconn->transport.sock, &e->msg, sendmsg_flags);
                if (ret == 0) {
                        /* propagate end of file */
index 4d7054f2defa3722119bd97041666a90890ad463..6c51f3f5b750e5b45555e7d303c2dd350a465c6e 100644 (file)
@@ -207,6 +207,14 @@ long ret = splice(0,0,1,0,400,SPLICE_F_MOVE);
         raise Errors.WafError('libarchive library required for '
                              '--enable-selftest')
 
+    conf.CHECK_FUNCS_IN('quic_server_handshake', 'quic')
+    if conf.CHECK_CFG(package='libquic', args='--cflags --libs',
+                      msg='Checking for libquic package', uselib_store="LIBQUIC"):
+        if (conf.CHECK_HEADERS('netinet/quic.h', lib='quic')
+                                      and conf.CHECK_LIB('quic', shlib=True)):
+            conf.CHECK_FUNCS_IN('quic_server_handshake', 'quic',
+                                headers='netinet/quic.h')
+            conf.DEFINE('HAVE_LIBQUIC', '1')
 
     # check for DMAPI libs
     if Options.options.with_dmapi == False:
index 2e5e74635440809707db3f74a9c756c4b3599de0..5b81b101b15fce896a873dd9a0a0a185aeb6ba88 100644 (file)
@@ -740,6 +740,7 @@ bld.SAMBA3_LIBRARY('smbd_base',
                         fd_handle
                         cli_spoolss
                         samba-io-uring
+                        quic
                    ''' +
                    bld.env['dmapi_lib'] +
                    bld.env['legacy_quota_libs'] +