mirror of
https://github.com/netsurf-browser/netsurf
synced 2024-11-25 07:49:38 +03:00
Allow contents to indicate if they believe they may not be secure.
HTML contents reference many other objects. The browser window needs to know if any of them may not be secure, in which case it needs to report that in its page state. If other content types might refer to sub-contents, they will need to define the callback too. Signed-off-by: Daniel Silverstone <dsilvers@digital-scurf.org>
This commit is contained in:
parent
9741df214d
commit
6fc2666d07
@ -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"
|
||||
@ -563,6 +564,50 @@ bool content_exec(struct hlcache_handle *h, const char *src, size_t srclen)
|
||||
return c->handler->exec(c, src, 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)
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -589,6 +589,31 @@ html_process_script(void *ctx, dom_node *node)
|
||||
return err;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user