diff options
Diffstat (limited to 'riscos/sslcert.c')
-rw-r--r-- | riscos/sslcert.c | 515 |
1 files changed, 206 insertions, 309 deletions
diff --git a/riscos/sslcert.c b/riscos/sslcert.c index 5c77f31d5..990c2501c 100644 --- a/riscos/sslcert.c +++ b/riscos/sslcert.c @@ -1,5 +1,6 @@ /* * Copyright 2006 John M Bell <jmb202@ecs.soton.ac.uk> + * Copyright 2010 Stephen Fryatt <stevef@netsurf-browser.org> * * This file is part of NetSurf, http://www.netsurf-browser.org/ * @@ -32,9 +33,11 @@ #include "content/fetch.h" #include "content/urldb.h" #include "desktop/browser.h" +#include "desktop/sslcert.h" #include "desktop/gui.h" #include "desktop/tree.h" #include "riscos/dialog.h" +#include "riscos/sslcert.h" #include "riscos/textarea.h" #include "riscos/treeview.h" #include "riscos/wimp.h" @@ -47,50 +50,36 @@ #define ICON_SSL_REJECT 3 #define ICON_SSL_ACCEPT 4 -#define ICON_CERT_VERSION 3 -#define ICON_CERT_VALID_FROM 5 -#define ICON_CERT_TYPE 7 -#define ICON_CERT_VALID_TO 9 -#define ICON_CERT_SERIAL 11 -#define ICON_CERT_ISSUER 13 -#define ICON_CERT_SUBJECT 15 - -static wimp_window *dialog_tree_template; -static wimp_window *dialog_cert_template; -static wimp_window *dialog_display_template; - -struct session_data { - struct session_cert *certs; - unsigned long num; - char *url; - struct tree *tree; - - nserror (*cb)(bool proceed, void *pw); - void *cbpw; -}; -struct session_cert { - char version[16], valid_from[32], valid_to[32], type[8], serial[32]; - char *issuer_t; - char *subject_t; - uintptr_t issuer; - uintptr_t subject; +static wimp_window *ro_gui_cert_dialog_template; +static wimp_window *ro_gui_cert_tree_template; + +struct ro_sslcert +{ + wimp_w window; + wimp_w pane; + ro_treeview *tv; + struct sslcert_session_data *data; }; -static bool ro_gui_cert_click(wimp_pointer *pointer); -static void ro_gui_cert_close(wimp_w w); -static bool ro_gui_cert_apply(wimp_w w); +static void ro_gui_cert_accept(wimp_pointer *pointer); +static void ro_gui_cert_reject(wimp_pointer *pointer); +static void ro_gui_cert_close_window(wimp_w w); +static void ro_gui_cert_release_window(struct ro_sslcert *s); /** - * Load the cert window template + * Load and initialise the certificate window template */ -void ro_gui_cert_init(void) +void ro_gui_cert_preinitialise(void) { - dialog_tree_template = ro_gui_dialog_load_template("tree"); - dialog_cert_template = ro_gui_dialog_load_template("sslcert"); - dialog_display_template = ro_gui_dialog_load_template("ssldisplay"); + /* Load templates for the SSL windows and adjust the tree window + * flags to suit. + */ + + ro_gui_cert_dialog_template = ro_gui_dialog_load_template("sslcert"); + ro_gui_cert_tree_template = ro_gui_dialog_load_template("tree"); - dialog_tree_template->flags &= ~(wimp_WINDOW_MOVEABLE | + ro_gui_cert_tree_template->flags &= ~(wimp_WINDOW_MOVEABLE | wimp_WINDOW_BACK_ICON | wimp_WINDOW_CLOSE_ICON | wimp_WINDOW_TITLE_ICON | @@ -99,169 +88,169 @@ void ro_gui_cert_init(void) } /** + * Load and initialise the certificate window template + */ + +void ro_gui_cert_postinitialise(void) +{ + /* Initialise the SSL module. */ + + sslcert_init(); +} + +/** * Open the certificate verification dialog + * + * \param *bw The browser window owning the certificates. + * \param *c The content data corresponding to the + * certificates. + * \param *certs The certificate details. + * \param num The number of certificates included. */ void gui_cert_verify(const char *url, const struct ssl_cert_info *certs, unsigned long num, nserror (*cb)(bool proceed, void *pw), void *cbpw) { - wimp_w w; - wimp_w ssl_w; - const struct ssl_cert_info *from; - struct session_cert *to; - struct session_data *data; - struct tree *tree; - struct node *node; - wimp_window_state state; - wimp_icon_state istate; - os_error *error; - long i; + struct ro_sslcert *sslcert_window; + wimp_window_state state; + wimp_icon_state istate; + wimp_window_info info; + os_error *error; + bool set_extent; assert(certs); - /* copy the certificate information */ - data = calloc(1, sizeof(struct session_data)); - if (!data) { - warn_user("NoMemory", 0); + sslcert_window = malloc(sizeof(struct ro_sslcert)); + if (sslcert_window == NULL) { + LOG(("Failed to allocate memory for SSL Cert Dialog")); return; } - data->url = strdup(url); - if (!data->url) { - free(data); - warn_user("NoMemory", 0); - return; - } - data->cb = cb; - data->cbpw = cbpw; - data->num = num; - data->certs = calloc(num, sizeof(struct session_cert)); - if (!data->certs) { - free(data->url); - free(data); - warn_user("NoMemory", 0); - return; - } - for (i = 0; i < (long)num; i++) { - to = &data->certs[i]; - from = &certs[i]; - to->subject_t = strdup(from->subject); - to->issuer_t = strdup(from->issuer); - if ((!to->subject_t) || (!to->issuer_t)) { - for (; i >= 0; i--) { - to = &data->certs[i]; - free(to->subject_t); - free(to->issuer_t); - } - free(data->certs); - free(data->url); - free(data); - warn_user("NoMemory", 0); - return; - } - snprintf(to->version, sizeof data->certs->version, "%ld", - from->version); - snprintf(to->valid_from, sizeof data->certs->valid_from, "%s", - from->not_before); - snprintf(to->type, sizeof data->certs->type, "%d", - from->cert_type); - snprintf(to->valid_to, sizeof data->certs->valid_to, "%s", - from->not_after); - snprintf(to->serial, sizeof data->certs->serial, "%ld", - from->serial); - } - /* create the SSL window */ - error = xwimp_create_window(dialog_cert_template, &ssl_w); + /* Create the SSL window and its pane. */ + + error = xwimp_create_window(ro_gui_cert_dialog_template, + &(sslcert_window->window)); if (error) { - free(data->certs); - free(data->url); - free(data); LOG(("xwimp_create_window: 0x%x: %s", error->errnum, error->errmess)); + free(sslcert_window); return; } - /* automated SSL window event handling */ - ro_gui_wimp_event_set_user_data(ssl_w, data); - ro_gui_wimp_event_register_cancel(ssl_w, ICON_SSL_REJECT); - ro_gui_wimp_event_register_ok(ssl_w, ICON_SSL_ACCEPT, ro_gui_cert_apply); - ro_gui_dialog_open_persistent(NULL, ssl_w, false); - - /* create a tree window (styled as a list) */ - error = xwimp_create_window(dialog_tree_template, &w); + error = xwimp_create_window(ro_gui_cert_tree_template, + &(sslcert_window->pane)); if (error) { - ro_gui_cert_close(ssl_w); LOG(("xwimp_create_window: 0x%x: %s", error->errnum, error->errmess)); + free(sslcert_window); return; } - tree = calloc(sizeof(struct tree), 1); - if (!tree) { - ro_gui_cert_close(ssl_w); - warn_user("NoMemory", 0); + + /* Create the SSL data and build a tree from it. */ + + sslcert_window->tv = ro_treeview_create(sslcert_window->pane, NULL, + sslcert_get_tree_flags()); + if (sslcert_window->tv == NULL) { + LOG(("Failed to allocate treeview")); + free(sslcert_window); return; } - tree->root = tree_create_folder_node(NULL, "Root"); - if (!tree->root) { - ro_gui_cert_close(ssl_w); - warn_user("NoMemory", 0); - free(tree); - tree = NULL; + + sslcert_window->data = sslcert_create_session_data(num, url, cb, cbpw); + sslcert_load_tree(ro_treeview_get_tree(sslcert_window->tv), + certs, sslcert_window->data); + + tree_set_redraw(ro_treeview_get_tree(sslcert_window->tv), true); + + /* Set up the certificate window event handling. + * + * (The action buttons are registered as button events, not OK and + * Cancel, as both need to carry out actions.) + */ + + ro_gui_wimp_event_set_user_data(sslcert_window->window, sslcert_window); + ro_gui_wimp_event_register_close_window(sslcert_window->window, + ro_gui_cert_close_window); + ro_gui_wimp_event_register_button(sslcert_window->window, + ICON_SSL_REJECT, ro_gui_cert_reject); + ro_gui_wimp_event_register_button(sslcert_window->window, + ICON_SSL_ACCEPT, ro_gui_cert_accept); + + ro_gui_dialog_open_persistent(NULL, sslcert_window->window, false); + + /* Nest the tree window inside the pane window. To do this, we: + * - Get the current pane extent, + * - Get the parent window position and the location of the pane- + * locating icon inside it, + * - Set the visible area of the pane to suit, + * - Check that the pane extents are OK for this visible area, and + * increase them if necessary, + * - Before finally opening the pane as a nested part of the parent. + */ + + info.w = sslcert_window->pane; + error = xwimp_get_window_info_header_only(&info); + if (error) { + ro_gui_cert_release_window(sslcert_window); + LOG(("xwimp_get_window_info: 0x%x: %s", + error->errnum, error->errmess)); return; } - tree->root->expanded = true; - tree->handle = (int)w; - tree->movable = false; - tree->no_drag = true; - tree->no_vscroll = true; - tree->no_furniture = true; - tree->single_selection = true; - data->tree = tree; - - /* put the SSL names in the tree */ - for (i = 0; i < (long)num; i++) { - node = tree_create_leaf_node(tree->root, certs[i].subject); - if (node) { - node->data.data = TREE_ELEMENT_SSL; - tree_set_node_sprite(node, "small_xxx", "small_xxx"); - } - } - - /* automated treeview event handling */ - ro_gui_wimp_event_set_user_data(w, tree); - ro_gui_wimp_event_register_keypress(w, ro_gui_tree_keypress); - ro_gui_wimp_event_register_redraw_window(w, ro_gui_tree_redraw); - ro_gui_wimp_event_register_open_window(w, ro_gui_tree_open); - ro_gui_wimp_event_register_close_window(w, ro_gui_wimp_event_finalise); - ro_gui_wimp_event_register_mouse_click(w, ro_gui_cert_click); - /* nest the tree window inside the pane window */ - state.w = ssl_w; + state.w = sslcert_window->window; error = xwimp_get_window_state(&state); if (error) { - ro_gui_cert_close(ssl_w); + ro_gui_cert_release_window(sslcert_window); LOG(("xwimp_get_window_state: 0x%x: %s", error->errnum, error->errmess)); return; } - istate.w = ssl_w; + istate.w = sslcert_window->window; istate.i = ICON_SSL_PANE; error = xwimp_get_icon_state(&istate); if (error) { - ro_gui_cert_close(ssl_w); + ro_gui_cert_release_window(sslcert_window); LOG(("xwimp_get_icon_state: 0x%x: %s", error->errnum, error->errmess)); return; } - state.w = w; + + state.w = sslcert_window->pane; state.visible.x1 = state.visible.x0 + istate.icon.extent.x1 - 20 - - ro_get_vscroll_width(w); + ro_get_vscroll_width(sslcert_window->pane); state.visible.x0 += istate.icon.extent.x0 + 20; state.visible.y0 = state.visible.y1 + istate.icon.extent.y0 + 20; state.visible.y1 += istate.icon.extent.y1 - 32; - error = xwimp_open_window_nested(PTR_WIMP_OPEN(&state), ssl_w, + + set_extent = false; + + if ((info.extent.x1 - info.extent.x0) < + (state.visible.x1 - state.visible.x0)) { + info.extent.x0 = 0; + info.extent.x1 = state.visible.x1 - state.visible.x0; + set_extent = true; + } + if ((info.extent.y1 - info.extent.y0) < + (state.visible.y1 - state.visible.y0)) { + info.extent.y1 = 0; + info.extent.x1 = state.visible.y0 - state.visible.y1; + set_extent = true; + } + + if (set_extent) { + error = xwimp_set_extent(sslcert_window->pane, &(info.extent)); + if (error) { + ro_gui_cert_release_window(sslcert_window); + LOG(("xwimp_set_extent: 0x%x: %s", + error->errnum, error->errmess)); + return; + } + } + + error = xwimp_open_window_nested(PTR_WIMP_OPEN(&state), + sslcert_window->window, wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT << wimp_CHILD_XORIGIN_SHIFT | wimp_CHILD_LINKS_PARENT_VISIBLE_TOP_OR_RIGHT @@ -271,192 +260,100 @@ void gui_cert_verify(const char *url, wimp_CHILD_LINKS_PARENT_VISIBLE_BOTTOM_OR_LEFT << wimp_CHILD_RS_EDGE_SHIFT); if (error) { - ro_gui_cert_close(ssl_w); + ro_gui_cert_release_window(sslcert_window); LOG(("xwimp_open_window_nested: 0x%x: %s", error->errnum, error->errmess)); + ro_gui_cert_release_window(sslcert_window); return; } - tree_initialise(tree); } -void ro_gui_cert_open(struct tree *tree, struct node *node) -{ - struct node *n; - struct session_data *data; - struct session_cert *session; - wimp_window_state state; - wimp_w child; - wimp_w parent; - wimp_w w; - unsigned long i; - os_error *error; - - assert(tree->root); +/** + * Handle acceptance of certificate via event callback. + * + * \param *pointer The wimp pointer block. + */ - /* firstly we need to get our node index in the list */ - for (n = tree->root->child, i = 0; n; i++, n = n->next) - if (n == node) - break; - assert(n); +void ro_gui_cert_accept(wimp_pointer *pointer) +{ + struct ro_sslcert *s; - /* now we get the handle of our list window */ - child = (wimp_w)tree->handle; - assert(child); + s = (struct ro_sslcert *) ro_gui_wimp_event_get_user_data(pointer->w); - /* now we can get the linked parent handle */ - state.w = child; - error = xwimp_get_window_state_and_nesting(&state, &parent, 0); - if (error) { - LOG(("xwimp_get_window_state: 0x%x: %s", - error->errnum, error->errmess)); - warn_user("WimpError", error->errmess); - return; - } - assert(parent); - - /* from this we can get our session data */ - data = (struct session_data *)ro_gui_wimp_event_get_user_data(parent); - assert(data); - assert(data->tree == tree); - - /* and finally the nodes session certificate data */ - session = &data->certs[i]; - assert(session); - - dialog_display_template->icons[ICON_CERT_VERSION].data.indirected_text.text = session->version; - dialog_display_template->icons[ICON_CERT_VERSION].data.indirected_text.size = strlen(session->version) + 1; - dialog_display_template->icons[ICON_CERT_VALID_FROM].data.indirected_text.text = session->valid_from; - dialog_display_template->icons[ICON_CERT_VALID_FROM].data.indirected_text.size = strlen(session->valid_from) + 1; - dialog_display_template->icons[ICON_CERT_TYPE].data.indirected_text.text = session->type; - dialog_display_template->icons[ICON_CERT_TYPE].data.indirected_text.size = strlen(session->type) + 1; - dialog_display_template->icons[ICON_CERT_VALID_TO].data.indirected_text.text = session->valid_to; - dialog_display_template->icons[ICON_CERT_VALID_TO].data.indirected_text.size = strlen(session->valid_to) + 1; - dialog_display_template->icons[ICON_CERT_SERIAL].data.indirected_text.text = session->serial; - dialog_display_template->icons[ICON_CERT_SERIAL].data.indirected_text.size = strlen(session->serial) + 1; - - error = xwimp_create_window(dialog_display_template, &w); - if (error) { - LOG(("xwimp_create_window: 0x%x: %s", - error->errnum, error->errmess)); - free(session); - warn_user("MiscError", error->errmess); - return; + if (s != NULL) { + sslcert_accept(s->data); + ro_gui_dialog_close(s->window); + ro_gui_cert_release_window(s); } - if (session->issuer) - ro_textarea_destroy(session->issuer); - session->issuer = ro_textarea_create(w, ICON_CERT_ISSUER, - TEXTAREA_MULTILINE | TEXTAREA_READONLY, - ro_gui_desktop_font_family, ro_gui_desktop_font_size, - ro_gui_desktop_font_style); - if (!session->issuer) { - xwimp_delete_window(w); - warn_user("NoMemory", 0); - return; - } - if (!ro_textarea_set_text(session->issuer, session->issuer_t)) { - ro_textarea_destroy(session->issuer); - xwimp_delete_window(w); - warn_user("NoMemory", 0); - return; - } - - if (session->subject) - ro_textarea_destroy(session->subject); - session->subject = ro_textarea_create(w, ICON_CERT_SUBJECT, - TEXTAREA_MULTILINE | TEXTAREA_READONLY, - ro_gui_desktop_font_family, ro_gui_desktop_font_size, - ro_gui_desktop_font_style); - if (!session->subject) { - ro_textarea_destroy(session->issuer); - xwimp_delete_window(w); - warn_user("NoMemory", 0); - return; - } - if (!ro_textarea_set_text(session->subject, session->subject_t)) { - ro_textarea_destroy(session->subject); - ro_textarea_destroy(session->issuer); - xwimp_delete_window(w); - warn_user("NoMemory", 0); - return; - } - ro_gui_wimp_event_register_close_window(w, ro_gui_wimp_event_finalise); - ro_gui_dialog_open_persistent(parent, w, false); } /** - * Handle closing of certificate verification dialog + * Handle rejection of certificate via event callback. + * + * \param w The wimp pointer block. */ -void ro_gui_cert_close(wimp_w w) -{ - struct session_data *data; - os_error *error; - unsigned long i; - data = (struct session_data *)ro_gui_wimp_event_get_user_data(w); - assert(data); +void ro_gui_cert_reject(wimp_pointer *pointer) +{ + struct ro_sslcert *s; - /* If we didn't accept the certificate, send failure response */ - if (data->cb != NULL) - data->cb(false, data->cbpw); + s = (struct ro_sslcert *) ro_gui_wimp_event_get_user_data(pointer->w); - for (i = 0; i < data->num; i++) { - if (data->certs[i].subject) - ro_textarea_destroy(data->certs[i].subject); - if (data->certs[i].issuer) - ro_textarea_destroy(data->certs[i].issuer); - } - free(data->certs); - free(data->url); - if (data->tree) { - tree_delete_node(data->tree, data->tree->root, false); - ro_gui_dialog_close((wimp_w)data->tree->handle); - error = xwimp_delete_window((wimp_w)data->tree->handle); - if (error) { - LOG(("xwimp_delete_window: 0x%x:%s", - error->errnum, error->errmess)); - warn_user("WimpError", error->errmess); - } - ro_gui_wimp_event_finalise((wimp_w)data->tree->handle); - free(data->tree); + if (s != NULL) { + sslcert_reject(s->data); + ro_gui_dialog_close(s->window); + ro_gui_cert_release_window(s); } - free(data); +} - ro_gui_dialog_close(w); - error = xwimp_delete_window(w); - if (error) { - LOG(("xwimp_delete_window: 0x%x:%s", - error->errnum, error->errmess)); - warn_user("WimpError", error->errmess); - } +/** + * Callback to handle the closure of the SSL dialogue by other means. + * + * \param w The window being closed. + */ +static void ro_gui_cert_close_window(wimp_w w) +{ + struct ro_sslcert *s; + + s = (struct ro_sslcert *) ro_gui_wimp_event_get_user_data(w); + + if (s != NULL) + ro_gui_cert_release_window(s); } /** - * Handle acceptance of certificate + * Handle closing of the RISC OS certificate verification dialog, deleting + * the windows and freeing up the treeview and data block. + * + * \param *s The data block associated with the dialogue. */ -bool ro_gui_cert_apply(wimp_w w) -{ - struct session_data *session; - session = (struct session_data *)ro_gui_wimp_event_get_user_data(w); - assert(session); +void ro_gui_cert_release_window(struct ro_sslcert *s) +{ + os_error *error; - urldb_set_cert_permissions(session->url, true); - session->cb(true, session->cbpw); + if (s == NULL) + return; - /* Flag that we sent response by invalidating callback details */ - session->cb = NULL; - session->cbpw = NULL; + LOG(("Releasing SSL data: 0x%x", (unsigned) s)); - return true; -} + ro_gui_wimp_event_finalise(s->window); + ro_treeview_destroy(s->tv); -bool ro_gui_cert_click(wimp_pointer *pointer) -{ - struct tree *tree; + error = xwimp_delete_window(s->window); + if (error) { + LOG(("xwimp_delete_window: 0x%x:%s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + } + error = xwimp_delete_window(s->pane); + if (error) { + LOG(("xwimp_delete_window: 0x%x:%s", + error->errnum, error->errmess)); + warn_user("WimpError", error->errmess); + } - tree = (struct tree *)ro_gui_wimp_event_get_user_data(pointer->w); - ro_gui_tree_click(pointer, tree); - return true; + free(s); } |