|
@@ -0,0 +1,111 @@
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * Copyright (C) 2011, 2012, 2013, 2014 Citrix Systems
|
|
|
|
+ *
|
|
|
|
+ * All rights reserved.
|
|
|
|
+ *
|
|
|
|
+ * Redistribution and use in source and binary forms, with or without
|
|
|
|
+ * modification, are permitted provided that the following conditions
|
|
|
|
+ * are met:
|
|
|
|
+ * 1. Redistributions of source code must retain the above copyright
|
|
|
|
+ * notice, this list of conditions and the following disclaimer.
|
|
|
|
+ * 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
+ * notice, this list of conditions and the following disclaimer in the
|
|
|
|
+ * documentation and/or other materials provided with the distribution.
|
|
|
|
+ * 3. Neither the name of the project nor the names of its contributors
|
|
|
|
+ * may be used to endorse or promote products derived from this software
|
|
|
|
+ * without specific prior written permission.
|
|
|
|
+ *
|
|
|
|
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
|
|
|
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
+ * SUCH DAMAGE.
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+#include "acme.h"
|
|
|
|
+#include "ns_ioalib_impl.h"
|
|
|
|
+
|
|
|
|
+static int is_acme_req(char *req, size_t len) {
|
|
|
|
+ static const char *A = " - 0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ _ abcdefghijklmnopqrstuvwxyz ";
|
|
|
|
+ int c, i, k;
|
|
|
|
+
|
|
|
|
+ // Check first request line. Should be like: GET path HTTP/1.x
|
|
|
|
+ if (strncmp(req, "GET /.well-known/acme-challenge/", 32))
|
|
|
|
+ return -1;
|
|
|
|
+ // Usually (for LE) the "method path" is 32 + 43 = 55 chars. But other
|
|
|
|
+ // implementations may choose longer pathes. We define PATHMAX = 127 chars
|
|
|
|
+ // to be prepared for "DoS" attacks (STUN msg size max. is ~ 64K).
|
|
|
|
+ len =- 21; // min size of trailing headers
|
|
|
|
+ if (len > 131)
|
|
|
|
+ len = 131;
|
|
|
|
+ for (i=32; i < (int) len; i++) {
|
|
|
|
+ // find the end of the path
|
|
|
|
+ if (req[i] != ' ')
|
|
|
|
+ continue;
|
|
|
|
+ // consider path < 10 chars invalid. Also we wanna see a "trailer".
|
|
|
|
+ if (i < 42 || strncmp(req + i, " HTTP/1.", 8))
|
|
|
|
+ return -2;
|
|
|
|
+ // finally check for allowed chars
|
|
|
|
+ for (k=32; k < i; k++) {
|
|
|
|
+ c = req[k];
|
|
|
|
+ if ((c > 127) || (A[c] == ' '))
|
|
|
|
+ return -3;
|
|
|
|
+ }
|
|
|
|
+ // all checks passed: sufficient for us to answer with a redirect
|
|
|
|
+ return i;
|
|
|
|
+ }
|
|
|
|
+ return -4; // end of path not found
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int try_acme_redirect(char *req, size_t len, const char *url,
|
|
|
|
+ ioa_socket_handle s)
|
|
|
|
+{
|
|
|
|
+ static const char *HTML = "<html><head><title>301 Moved Permanently</title></head><body><h1>301 Moved Permanently</h1></body></html>";
|
|
|
|
+ char http_response[1024];
|
|
|
|
+ size_t plen, rlen;
|
|
|
|
+
|
|
|
|
+ if (url == NULL || url[0] == '\0' || req == NULL || s == 0 )
|
|
|
|
+ return 1;
|
|
|
|
+ if (len < 64 || len > 512 || (plen = is_acme_req(req, len)) < 33)
|
|
|
|
+ return 2;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ snprintf(http_response, sizeof(http_response) - 1,
|
|
|
|
+ "HTTP/1.1 301 Moved Permanently\r\n"
|
|
|
|
+ "Content-Type: text/html\r\n"
|
|
|
|
+ "Content-Length: %ld\r\n"
|
|
|
|
+ "Connection: close\r\n"
|
|
|
|
+ "Location: %s%s\r\n"
|
|
|
|
+ "\r\n%s", strlen(HTML), url, req + 32, HTML);
|
|
|
|
+
|
|
|
|
+ rlen = strlen(http_response);
|
|
|
|
+
|
|
|
|
+ // Variant A: direkt write, no eventbuf stuff
|
|
|
|
+ /*
|
|
|
|
+ if (write(s->fd, http_response, rlen) == -1) {
|
|
|
|
+ perror("Sending redirect failed");
|
|
|
|
+ } else if (((turn_turnserver *)s->session->server)->verbose) {
|
|
|
|
+ TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "ACME redirect to %s%s\n",
|
|
|
|
+ url, req + 32);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ req[plen] = ' ';
|
|
|
|
+ */
|
|
|
|
+ // Variant B: via eventbuf does not send anything for whatever reason
|
|
|
|
+
|
|
|
|
+ //set_ioa_socket_app_type(s, HTTP_CLIENT_SOCKET);
|
|
|
|
+ ioa_network_buffer_handle nbh_acme = ioa_network_buffer_allocate(s->e);
|
|
|
|
+ uint8_t *data = ioa_network_buffer_data(nbh_acme);
|
|
|
|
+ bcopy(http_response, data, rlen);
|
|
|
|
+ ioa_network_buffer_set_size(nbh_acme, rlen);
|
|
|
|
+ send_data_from_ioa_socket_nbh(s, NULL, nbh_acme, TTL_IGNORE, TOS_IGNORE, NULL);
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|