summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--content/content.c45
-rw-r--r--content/content.h12
-rw-r--r--content/content_protected.h1
-rw-r--r--content/handlers/html/html.c29
-rw-r--r--content/handlers/html/html_css.c17
-rw-r--r--content/handlers/html/html_internal.h8
-rw-r--r--content/handlers/html/html_script.c25
-rw-r--r--desktop/browser_window.c9
8 files changed, 143 insertions, 3 deletions
diff --git a/content/content.c b/content/content.c
index 82a87c536..c0119eac9 100644
--- a/content/content.c
+++ b/content/content.c
@@ -28,6 +28,7 @@
#include "netsurf/inttypes.h"
#include "utils/log.h"
#include "utils/messages.h"
+#include "utils/corestrings.h"
#include "netsurf/browser_window.h"
#include "netsurf/bitmap.h"
#include "netsurf/content.h"
@@ -564,6 +565,50 @@ bool content_exec(struct hlcache_handle *h, const char *src, size_t srclen)
}
/* exported interface, documented in content/content.h */
+bool content_saw_insecure_objects(struct hlcache_handle *h)
+{
+ struct content *c = hlcache_handle_get_content(h);
+ lwc_string *scheme = nsurl_get_component(content_get_url(c), NSURL_SCHEME);
+ bool match;
+
+ /* Is this an internal scheme? If so, we trust here and stop */
+ if ((lwc_string_isequal(scheme, corestring_lwc_about,
+ &match) == lwc_error_ok &&
+ (match == true)) ||
+ (lwc_string_isequal(scheme, corestring_lwc_data,
+ &match) == lwc_error_ok &&
+ (match == true)) ||
+ (lwc_string_isequal(scheme, corestring_lwc_resource,
+ &match) == lwc_error_ok &&
+ (match == true))) {
+ /* No insecurity to find */
+ return false;
+ }
+
+ /* Okay, not internal, am *I* secure? */
+ if ((lwc_string_isequal(scheme, corestring_lwc_https,
+ &match) == lwc_error_ok)
+ && (match == false)) {
+ /* I did see something insecure -- ME! */
+ return true;
+ }
+
+ /* I am supposed to be secure, but was I overridden */
+ if (urldb_get_cert_permissions(content_get_url(c))) {
+ /* I was https:// but I was overridden, that's no good */
+ return true;
+ }
+
+ /* Otherwise try and chain through the handler */
+ if (c->handler->saw_insecure_objects != NULL) {
+ return c->handler->saw_insecure_objects(c);
+ }
+
+ /* If we can't see insecure objects, we can't see them */
+ return false;
+}
+
+/* exported interface, documented in content/content.h */
bool content_redraw(hlcache_handle *h, struct content_redraw_data *data,
const struct rect *clip, const struct redraw_context *ctx)
{
diff --git a/content/content.h b/content/content.h
index f3e578b6b..0dbd58d95 100644
--- a/content/content.h
+++ b/content/content.h
@@ -420,5 +420,17 @@ bool content_is_locked(struct hlcache_handle *h);
*/
bool content_exec(struct hlcache_handle *h, const char *src, size_t srclen);
+/**
+ * Determine if the content referred to any insecure objects.
+ *
+ * Query the content to determine if any of its referred objects were loaded
+ * in a manner not considered secure. For a content to be recursively
+ * secure it must only load over https and must not have certificate overrides
+ * in place.
+ *
+ * \param h The handle to the content
+ * \return Whether the content referred to any insecure objects
+ */
+bool content_saw_insecure_objects(struct hlcache_handle *h);
#endif
diff --git a/content/content_protected.h b/content/content_protected.h
index ec62a2183..af0ee7259 100644
--- a/content/content_protected.h
+++ b/content/content_protected.h
@@ -83,6 +83,7 @@ struct content_handler {
void (*add_user)(struct content *c);
void (*remove_user)(struct content *c);
bool (*exec)(struct content *c, const char *src, size_t srclen);
+ bool (*saw_insecure_objects)(struct content *c);
/** handler dependant content sensitive internal data interface. */
void * (*get_internal)(const struct content *c, void *context);
diff --git a/content/handlers/html/html.c b/content/handlers/html/html.c
index 25633a875..c49697b50 100644
--- a/content/handlers/html/html.c
+++ b/content/handlers/html/html.c
@@ -2667,6 +2667,34 @@ out_no_string:
return result;
}
+/* See \ref content_saw_insecure_objects */
+static bool
+html_saw_insecure_objects(struct content *c)
+{
+ html_content *htmlc = (html_content *)c;
+ struct content_html_object *obj = htmlc->object_list;
+
+ /* Check through the object list */
+ while (obj != NULL) {
+ if (obj->content != NULL) {
+ if (content_saw_insecure_objects(obj->content))
+ return true;
+ }
+ }
+
+ /* Now check the script list */
+ if (html_saw_insecure_scripts(htmlc)) {
+ return true;
+ }
+
+ /* Now check stylesheets */
+ if (html_saw_insecure_stylesheets(htmlc)) {
+ return true;
+ }
+
+ return false;
+}
+
/**
* Compute the type of a content
*
@@ -2710,6 +2738,7 @@ static const content_handler html_content_handler = {
.get_encoding = html_encoding,
.type = html_content_type,
.exec = html_exec,
+ .saw_insecure_objects = html_saw_insecure_objects,
.no_share = true,
};
diff --git a/content/handlers/html/html_css.c b/content/handlers/html/html_css.c
index 5550573ba..5d9987d5a 100644
--- a/content/handlers/html/html_css.c
+++ b/content/handlers/html/html_css.c
@@ -487,6 +487,23 @@ struct html_stylesheet *html_get_stylesheets(hlcache_handle *h, unsigned int *n)
return c->stylesheets;
}
+/* exported interface documented in html/html_internal.h */
+bool html_saw_insecure_stylesheets(html_content *html)
+{
+ struct html_stylesheet *s;
+ unsigned int i;
+
+ for (i = 0, s = html->stylesheets; i < html->stylesheet_count;
+ i++, s++) {
+ if (s->sheet != NULL) {
+ if (content_saw_insecure_objects(s->sheet)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
/* exported interface documented in html/html_internal.h */
nserror html_css_free_stylesheets(html_content *html)
diff --git a/content/handlers/html/html_internal.h b/content/handlers/html/html_internal.h
index 388c1558d..11891e681 100644
--- a/content/handlers/html/html_internal.h
+++ b/content/handlers/html/html_internal.h
@@ -328,6 +328,11 @@ nserror html_script_free(html_content *htmlc);
*/
nserror html_script_invalidate_ctx(html_content *htmlc);
+/**
+ * Check if any of the scripts loaded were insecure
+ */
+bool html_saw_insecure_scripts(html_content *htmlc);
+
/* in html/html_forms.c */
struct form *html_forms_get_forms(const char *docenc, dom_html_document *doc);
struct form_control *html_forms_get_control_for_node(struct form *forms,
@@ -347,6 +352,9 @@ nserror html_css_new_stylesheets(html_content *c);
nserror html_css_quirks_stylesheets(html_content *c);
nserror html_css_free_stylesheets(html_content *html);
+/** Return if any of the stylesheets were loaded insecurely */
+bool html_saw_insecure_stylesheets(html_content *html);
+
bool html_css_process_link(html_content *htmlc, dom_node *node);
bool html_css_process_style(html_content *htmlc, dom_node *node);
bool html_css_update_style(html_content *c, dom_node *style);
diff --git a/content/handlers/html/html_script.c b/content/handlers/html/html_script.c
index f7131e2a2..f4754fe8a 100644
--- a/content/handlers/html/html_script.c
+++ b/content/handlers/html/html_script.c
@@ -590,6 +590,31 @@ html_process_script(void *ctx, dom_node *node)
}
/* exported internal interface documented in html/html_internal.h */
+bool html_saw_insecure_scripts(html_content *htmlc)
+{
+ struct html_script *s;
+ unsigned int i;
+
+ for (i = 0, s = htmlc->scripts; i != htmlc->scripts_count; i++, s++) {
+ if (s->type == HTML_SCRIPT_INLINE) {
+ /* Inline scripts are no less secure than their
+ * containing HTML content
+ */
+ continue;
+ }
+ if (s->data.handle == NULL) {
+ /* We've not begun loading this? */
+ continue;
+ }
+ if (content_saw_insecure_objects(s->data.handle)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/* exported internal interface documented in html/html_internal.h */
nserror html_script_free(html_content *html)
{
unsigned int i;
diff --git a/desktop/browser_window.c b/desktop/browser_window.c
index a9c277846..7227023af 100644
--- a/desktop/browser_window.c
+++ b/desktop/browser_window.c
@@ -4649,7 +4649,8 @@ browser_window_page_info_state browser_window_get_page_info_state(
assert(bw != NULL);
/* Do we have any parameters? If not -- UNKNOWN */
- if (bw->current_parameters.url == NULL) {
+ if (bw->current_parameters.url == NULL ||
+ bw->current_content == NULL) {
return PAGE_STATE_UNKNOWN;
}
@@ -4688,8 +4689,10 @@ browser_window_page_info_state browser_window_get_page_info_state(
return PAGE_STATE_SECURE_OVERRIDE;
}
- /** \todo Determine if sub-elements of this fetch were insecure */
- /* If so, return PAGE_STATE_SECURE_ISSUES */
+ /* If we've seen insecure content internally then we need to say so */
+ if (content_saw_insecure_objects(bw->current_content)) {
+ return PAGE_STATE_SECURE_ISSUES;
+ }
/* All is well, return secure state */
return PAGE_STATE_SECURE;