1
0

quic-server-block.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. /*
  2. * Copyright 2024-2025 The OpenSSL Project Authors. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License 2.0 (the "License"). You may not use
  5. * this file except in compliance with the License. You can obtain a copy
  6. * in the file LICENSE in the source distribution or at
  7. * https://www.openssl.org/source/license.html
  8. */
  9. /*
  10. * NB: Changes to this file should also be reflected in
  11. * doc/man7/ossl-guide-quic-server-block.pod
  12. */
  13. #include <string.h>
  14. /* Include the appropriate header file for SOCK_STREAM */
  15. #ifdef _WIN32 /* Windows */
  16. # include <stdarg.h>
  17. # include <winsock2.h>
  18. #else /* Linux/Unix */
  19. # include <err.h>
  20. # include <sys/socket.h>
  21. # include <sys/select.h>
  22. # include <netinet/in.h>
  23. # include <unistd.h>
  24. #endif
  25. #include <openssl/bio.h>
  26. #include <openssl/ssl.h>
  27. #include <openssl/err.h>
  28. #include <openssl/quic.h>
  29. #ifdef _WIN32
  30. static const char *progname;
  31. static void vwarnx(const char *fmt, va_list ap)
  32. {
  33. if (progname != NULL)
  34. fprintf(stderr, "%s: ", progname);
  35. vfprintf(stderr, fmt, ap);
  36. putc('\n', stderr);
  37. }
  38. static void errx(int status, const char *fmt, ...)
  39. {
  40. va_list ap;
  41. va_start(ap, fmt);
  42. vwarnx(fmt, ap);
  43. va_end(ap);
  44. exit(status);
  45. }
  46. static void warnx(const char *fmt, ...)
  47. {
  48. va_list ap;
  49. va_start(ap, fmt);
  50. vwarnx(fmt, ap);
  51. va_end(ap);
  52. }
  53. #endif
  54. /*
  55. * ALPN strings for TLS handshake. Only 'http/1.0' and 'hq-interop'
  56. * are accepted.
  57. */
  58. static const unsigned char alpn_ossltest[] = {
  59. 8, 'h', 't', 't', 'p', '/', '1', '.', '0',
  60. 10, 'h', 'q', '-', 'i', 'n', 't', 'e', 'r', 'o', 'p',
  61. };
  62. /*
  63. * This callback validates and negotiates the desired ALPN on the server side.
  64. */
  65. static int select_alpn(SSL *ssl, const unsigned char **out,
  66. unsigned char *out_len, const unsigned char *in,
  67. unsigned int in_len, void *arg)
  68. {
  69. if (SSL_select_next_proto((unsigned char **)out, out_len, alpn_ossltest,
  70. sizeof(alpn_ossltest), in,
  71. in_len) == OPENSSL_NPN_NEGOTIATED)
  72. return SSL_TLSEXT_ERR_OK;
  73. return SSL_TLSEXT_ERR_ALERT_FATAL;
  74. }
  75. /* Create SSL_CTX. */
  76. static SSL_CTX *create_ctx(const char *cert_path, const char *key_path)
  77. {
  78. SSL_CTX *ctx;
  79. /*
  80. * An SSL_CTX holds shared configuration information for multiple
  81. * subsequent per-client connections. We specifically load a QUIC
  82. * server method here.
  83. */
  84. ctx = SSL_CTX_new(OSSL_QUIC_server_method());
  85. if (ctx == NULL)
  86. goto err;
  87. /*
  88. * Load the server's certificate *chain* file (PEM format), which includes
  89. * not only the leaf (end-entity) server certificate, but also any
  90. * intermediate issuer-CA certificates. The leaf certificate must be the
  91. * first certificate in the file.
  92. *
  93. * In advanced use-cases this can be called multiple times, once per public
  94. * key algorithm for which the server has a corresponding certificate.
  95. * However, the corresponding private key (see below) must be loaded first,
  96. * *before* moving on to the next chain file.
  97. *
  98. * The requisite files "chain.pem" and "pkey.pem" can be generated by running
  99. * "make chain" in this directory. If the server will be executed from some
  100. * other directory, move or copy the files there.
  101. */
  102. if (SSL_CTX_use_certificate_chain_file(ctx, cert_path) <= 0) {
  103. fprintf(stderr, "couldn't load certificate file: %s\n", cert_path);
  104. goto err;
  105. }
  106. /*
  107. * Load the corresponding private key, this also checks that the private
  108. * key matches the just loaded end-entity certificate. It does not check
  109. * whether the certificate chain is valid, the certificates could be
  110. * expired, or may otherwise fail to form a chain that a client can validate.
  111. */
  112. if (SSL_CTX_use_PrivateKey_file(ctx, key_path, SSL_FILETYPE_PEM) <= 0) {
  113. fprintf(stderr, "couldn't load key file: %s\n", key_path);
  114. goto err;
  115. }
  116. /*
  117. * Clients rarely employ certificate-based authentication, and so we don't
  118. * require "mutual" TLS authentication (indeed there's no way to know
  119. * whether or how the client authenticated the server, so the term "mutual"
  120. * is potentially misleading).
  121. *
  122. * Since we're not soliciting or processing client certificates, we don't
  123. * need to configure a trusted-certificate store, so no call to
  124. * SSL_CTX_set_default_verify_paths() is needed. The server's own
  125. * certificate chain is assumed valid.
  126. */
  127. SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
  128. /* Setup ALPN negotiation callback to decide which ALPN is accepted. */
  129. SSL_CTX_set_alpn_select_cb(ctx, select_alpn, NULL);
  130. return ctx;
  131. err:
  132. SSL_CTX_free(ctx);
  133. return NULL;
  134. }
  135. /* Create UDP socket on the given port. */
  136. static int create_socket(uint16_t port)
  137. {
  138. int fd;
  139. struct sockaddr_in sa = {0};
  140. /* Retrieve the file descriptor for a new UDP socket */
  141. if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
  142. fprintf(stderr, "cannot create socket");
  143. goto err;
  144. }
  145. sa.sin_family = AF_INET;
  146. sa.sin_port = htons(port);
  147. /* Bind to the new UDP socket on localhost */
  148. if (bind(fd, (const struct sockaddr *)&sa, sizeof(sa)) < 0) {
  149. fprintf(stderr, "cannot bind to %u\n", port);
  150. BIO_closesocket(fd);
  151. goto err;
  152. }
  153. return fd;
  154. err:
  155. BIO_closesocket(fd);
  156. return -1;
  157. }
  158. /*
  159. * Main loop for server to accept QUIC connections.
  160. * Echo every request back to the client.
  161. */
  162. static int run_quic_server(SSL_CTX *ctx, int fd)
  163. {
  164. int ok = 0;
  165. SSL *listener, *conn;
  166. unsigned char buf[8192];
  167. size_t nread;
  168. size_t nwritten;
  169. /*
  170. * Create a new QUIC listener. Listeners, and other QUIC objects, default
  171. * to operating in blocking mode. The configured behaviour is inherited by
  172. * child objects.
  173. */
  174. if ((listener = SSL_new_listener(ctx, 0)) == NULL)
  175. goto err;
  176. /* Provide the listener with our UDP socket. */
  177. if (!SSL_set_fd(listener, fd))
  178. goto err;
  179. /* Begin listening. */
  180. if (!SSL_listen(listener))
  181. goto err;
  182. /*
  183. * Begin an infinite loop of listening for connections. We will only
  184. * exit this loop if we encounter an error.
  185. */
  186. for (;;) {
  187. /* Pristine error stack for each new connection */
  188. ERR_clear_error();
  189. /* Block while waiting for a client connection */
  190. printf("Waiting for connection\n");
  191. conn = SSL_accept_connection(listener, 0);
  192. if (conn == NULL) {
  193. fprintf(stderr, "error while accepting connection\n");
  194. goto err;
  195. }
  196. printf("Accepted new connection\n");
  197. /* Echo client input */
  198. while (SSL_read_ex(conn, buf, sizeof(buf), &nread) > 0) {
  199. if (SSL_write_ex(conn, buf, nread, &nwritten) > 0
  200. && nwritten == nread)
  201. continue;
  202. fprintf(stderr, "Error echoing client input");
  203. break;
  204. }
  205. /* Signal the end of the stream. */
  206. if (SSL_stream_conclude(conn, 0) != 1) {
  207. fprintf(stderr, "Unable to conclude stream\n");
  208. SSL_free(conn);
  209. goto err;
  210. }
  211. /*
  212. * Shut down the connection. We may need to call this multiple times
  213. * to ensure the connection is shutdown completely.
  214. */
  215. while (SSL_shutdown(conn) != 1)
  216. continue;
  217. SSL_free(conn);
  218. }
  219. err:
  220. SSL_free(listener);
  221. return ok;
  222. }
  223. /* Minimal QUIC HTTP/1.0 server. */
  224. int main(int argc, char *argv[])
  225. {
  226. int res = EXIT_FAILURE;
  227. SSL_CTX *ctx = NULL;
  228. int fd;
  229. unsigned long port;
  230. #ifdef _WIN32
  231. static const char *progname;
  232. progname = argv[0];
  233. #endif
  234. if (argc != 4)
  235. errx(res, "usage: %s <port> <server.crt> <server.key>", argv[0]);
  236. /* Create SSL_CTX that supports QUIC. */
  237. if ((ctx = create_ctx(argv[2], argv[3])) == NULL) {
  238. ERR_print_errors_fp(stderr);
  239. errx(res, "Failed to create context");
  240. }
  241. /* Parse port number from command line arguments. */
  242. port = strtoul(argv[1], NULL, 0);
  243. if (port == 0 || port > UINT16_MAX) {
  244. SSL_CTX_free(ctx);
  245. errx(res, "Failed to parse port number");
  246. }
  247. /* Create and bind a UDP socket. */
  248. if ((fd = create_socket((uint16_t)port)) < 0) {
  249. SSL_CTX_free(ctx);
  250. ERR_print_errors_fp(stderr);
  251. errx(res, "Failed to create socket");
  252. }
  253. /* QUIC server connection acceptance loop. */
  254. if (!run_quic_server(ctx, fd)) {
  255. SSL_CTX_free(ctx);
  256. BIO_closesocket(fd);
  257. ERR_print_errors_fp(stderr);
  258. errx(res, "Error in QUIC server loop");
  259. }
  260. /* Free resources. */
  261. SSL_CTX_free(ctx);
  262. BIO_closesocket(fd);
  263. res = EXIT_SUCCESS;
  264. return res;
  265. }