summaryrefslogtreecommitdiff
path: root/libsoup/soup-server.c
diff options
context:
space:
mode:
Diffstat (limited to 'libsoup/soup-server.c')
-rw-r--r--libsoup/soup-server.c117
1 files changed, 116 insertions, 1 deletions
diff --git a/libsoup/soup-server.c b/libsoup/soup-server.c
index ff51e5bd..abda60ba 100644
--- a/libsoup/soup-server.c
+++ b/libsoup/soup-server.c
@@ -14,6 +14,7 @@
#include "soup-server.h"
#include "soup.h"
#include "soup-message-private.h"
+#include "soup-misc-private.h"
#include "soup-path-map.h"
/**
@@ -105,6 +106,8 @@ typedef struct {
GSList *auth_domains;
GMainContext *async_context;
+
+ char **http_aliases, **https_aliases;
} SoupServerPrivate;
#define SOUP_SERVER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_SERVER, SoupServerPrivate))
@@ -121,6 +124,8 @@ enum {
PROP_ASYNC_CONTEXT,
PROP_RAW_PATHS,
PROP_SERVER_HEADER,
+ PROP_HTTP_ALIASES,
+ PROP_HTTPS_ALIASES,
LAST_PROP
};
@@ -141,6 +146,10 @@ soup_server_init (SoupServer *server)
SoupServerPrivate *priv = SOUP_SERVER_GET_PRIVATE (server);
priv->handlers = soup_path_map_new ((GDestroyNotify)free_handler);
+
+ priv->http_aliases = g_new (char *, 2);
+ priv->http_aliases[0] = (char *)g_intern_string ("*");
+ priv->http_aliases[1] = NULL;
}
static void
@@ -191,6 +200,9 @@ soup_server_finalize (GObject *object)
g_clear_pointer (&priv->loop, g_main_loop_unref);
g_clear_pointer (&priv->async_context, g_main_context_unref);
+ g_free (priv->http_aliases);
+ g_free (priv->https_aliases);
+
G_OBJECT_CLASS (soup_server_parent_class)->finalize (object);
}
@@ -250,6 +262,29 @@ soup_server_constructor (GType type,
return server;
}
+/* priv->http_aliases and priv->https_aliases are stored as arrays of
+ * *interned* strings, so we can't just use g_strdupv() to set them.
+ */
+static void
+set_aliases (char ***variable, char **value)
+{
+ int len, i;
+
+ if (*variable)
+ g_free (*variable);
+
+ if (!value) {
+ *variable = NULL;
+ return;
+ }
+
+ len = g_strv_length (value);
+ *variable = g_new (char *, len + 1);
+ for (i = 0; i < len; i++)
+ (*variable)[i] = (char *)g_intern_string (value[i]);
+ (*variable)[i] = NULL;
+}
+
static void
soup_server_set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
@@ -304,6 +339,12 @@ soup_server_set_property (GObject *object, guint prop_id,
} else
priv->server_header = g_strdup (header);
break;
+ case PROP_HTTP_ALIASES:
+ set_aliases (&priv->http_aliases, g_value_get_boxed (value));
+ break;
+ case PROP_HTTPS_ALIASES:
+ set_aliases (&priv->https_aliases, g_value_get_boxed (value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -341,6 +382,12 @@ soup_server_get_property (GObject *object, guint prop_id,
case PROP_SERVER_HEADER:
g_value_set_string (value, priv->server_header);
break;
+ case PROP_HTTP_ALIASES:
+ g_value_set_boxed (value, priv->http_aliases);
+ break;
+ case PROP_HTTPS_ALIASES:
+ g_value_set_boxed (value, priv->https_aliases);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -628,6 +675,68 @@ soup_server_class_init (SoupServerClass *server_class)
"Server header",
NULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ /**
+ * SoupServer:http-aliases:
+ *
+ * A %NULL-terminated array of URI schemes that should be
+ * considered to be aliases for "http". Eg, if this included
+ * <literal>"dav"</literal>, than a URI of
+ * <literal>dav://example.com/path</literal> would be treated
+ * identically to <literal>http://example.com/path</literal>.
+ * In particular, this is needed in cases where a client
+ * sends requests with absolute URIs, where those URIs do
+ * not use "http:".
+ *
+ * The default value is an array containing the single element
+ * <literal>"*"</literal>, a special value which means that
+ * any scheme except "https" is considered to be an alias for
+ * "http".
+ *
+ * See also #SoupServer:https-aliases.
+ *
+ * Since: 2.44
+ */
+ /**
+ * SOUP_SERVERI_HTTP_ALIASES:
+ *
+ * Alias for the #SoupServer:http-aliases property, qv.
+ *
+ * Since: 2.44
+ */
+ g_object_class_install_property (
+ object_class, PROP_HTTP_ALIASES,
+ g_param_spec_boxed (SOUP_SERVER_HTTP_ALIASES,
+ "http aliases",
+ "URI schemes that are considered aliases for 'http'",
+ G_TYPE_STRV,
+ G_PARAM_READWRITE));
+ /**
+ * SoupServer:https-aliases:
+ *
+ * A comma-delimited list of URI schemes that should be
+ * considered to be aliases for "https". See
+ * #SoupServer:http-aliases for more information.
+ *
+ * The default value is %NULL, meaning that no URI schemes
+ * are considered aliases for "https".
+ *
+ * Since: 2.44
+ */
+ /**
+ * SOUP_SERVER_HTTPS_ALIASES:
+ *
+ * Alias for the #SoupServer:https-aliases property, qv.
+ *
+ * Since: 2.44
+ **/
+ g_object_class_install_property (
+ object_class, PROP_HTTPS_ALIASES,
+ g_param_spec_boxed (SOUP_SERVER_HTTPS_ALIASES,
+ "https aliases",
+ "URI schemes that are considered aliases for 'https'",
+ G_TYPE_STRV,
+ G_PARAM_READWRITE));
}
/**
@@ -816,10 +925,16 @@ got_headers (SoupMessage *msg, SoupClientContext *client)
gboolean rejected = FALSE;
char *auth_user;
+ uri = soup_message_get_uri (msg);
+ if ((soup_server_is_https (server) && !soup_uri_is_https (uri, priv->https_aliases)) ||
+ (!soup_server_is_https (server) && !soup_uri_is_http (uri, priv->http_aliases))) {
+ soup_message_set_status (msg, SOUP_STATUS_BAD_REQUEST);
+ return;
+ }
+
if (!priv->raw_paths) {
char *decoded_path;
- uri = soup_message_get_uri (msg);
decoded_path = soup_uri_decode (uri->path);
if (strstr (decoded_path, "/../") ||