2010-10-05 23:14:46 +04:00
|
|
|
/*
|
|
|
|
* Copyright 2009 Paul Blokus <paul_pl@users.sourceforge.net>
|
|
|
|
*
|
|
|
|
* This file is part of NetSurf, http://www.netsurf-browser.org/
|
|
|
|
*
|
|
|
|
* NetSurf is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; version 2 of the License.
|
|
|
|
*
|
|
|
|
* NetSurf is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/** \file
|
|
|
|
* SSL Certificate verification UI (implementation)
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "utils/config.h"
|
|
|
|
|
|
|
|
#include <assert.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include "content/content.h"
|
|
|
|
#include "content/fetch.h"
|
|
|
|
#include "content/hlcache.h"
|
|
|
|
#include "content/urldb.h"
|
|
|
|
#include "desktop/browser.h"
|
|
|
|
#include "desktop/sslcert.h"
|
|
|
|
#include "desktop/tree.h"
|
|
|
|
#include "utils/log.h"
|
|
|
|
#include "utils/messages.h"
|
|
|
|
#include "utils/utils.h"
|
|
|
|
|
|
|
|
/** Flags for each type of ssl tree node. */
|
|
|
|
enum tree_element_ssl {
|
|
|
|
TREE_ELEMENT_SSL_VERSION = 0x01,
|
|
|
|
TREE_ELEMENT_SSL_VALID_FROM = 0x02,
|
|
|
|
TREE_ELEMENT_SSL_VALID_TO = 0x03,
|
|
|
|
TREE_ELEMENT_SSL_CERT_TYPE = 0x04,
|
|
|
|
TREE_ELEMENT_SSL_SERIAL = 0x05,
|
|
|
|
TREE_ELEMENT_SSL_ISSUER = 0x06,
|
|
|
|
};
|
|
|
|
|
|
|
|
/** ssl certificate verification context. */
|
|
|
|
struct sslcert_session_data {
|
|
|
|
unsigned long num; /**< The number of ssl certificates in the chain */
|
|
|
|
char *url; /**< The url of the certificate */
|
|
|
|
struct tree *tree; /**< The root of the treeview */
|
|
|
|
llcache_query_response cb; /**< callback when cert is accepted or rejected */
|
|
|
|
void *cbpw; /**< context passed to callback */
|
|
|
|
};
|
|
|
|
|
|
|
|
/** Handle for the window icon. */
|
2011-03-12 20:26:46 +03:00
|
|
|
static hlcache_handle *sslcert_icon = NULL;
|
2010-10-05 23:14:46 +04:00
|
|
|
|
|
|
|
/** Initialise ssl certificate window. */
|
2010-12-14 03:18:24 +03:00
|
|
|
void sslcert_init(const char* icon_name)
|
2010-10-05 23:14:46 +04:00
|
|
|
{
|
2010-12-14 03:18:24 +03:00
|
|
|
sslcert_icon = tree_load_icon(icon_name);
|
2010-10-05 23:14:46 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get flags with which the sslcert tree should be created;
|
|
|
|
*
|
|
|
|
* \return the flags
|
|
|
|
*/
|
|
|
|
unsigned int sslcert_get_tree_flags(void)
|
|
|
|
{
|
|
|
|
return TREE_NO_DRAGS | TREE_NO_SELECT;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void sslcert_cleanup(void)
|
|
|
|
{
|
2011-03-12 20:26:46 +03:00
|
|
|
if (sslcert_icon != NULL)
|
|
|
|
hlcache_handle_release(sslcert_icon);
|
2010-10-05 23:14:46 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
struct sslcert_session_data *
|
|
|
|
sslcert_create_session_data(unsigned long num,
|
|
|
|
const char *url,
|
|
|
|
llcache_query_response cb,
|
|
|
|
void *cbpw)
|
|
|
|
{
|
|
|
|
struct sslcert_session_data *data;
|
|
|
|
|
|
|
|
data = malloc(sizeof(struct sslcert_session_data));
|
|
|
|
if (data == NULL) {
|
|
|
|
warn_user("NoMemory", 0);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
data->url = strdup(url);
|
|
|
|
if (data->url == NULL) {
|
|
|
|
free(data);
|
|
|
|
warn_user("NoMemory", 0);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
data->num = num;
|
|
|
|
data->cb = cb;
|
|
|
|
data->cbpw = cbpw;
|
|
|
|
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
|
|
|
static node_callback_resp sslcert_node_callback(void *user_data,
|
|
|
|
struct node_msg_data *msg_data)
|
|
|
|
{
|
|
|
|
if (msg_data->msg == NODE_DELETE_ELEMENT_IMG)
|
|
|
|
return NODE_CALLBACK_HANDLED;
|
|
|
|
return NODE_CALLBACK_NOT_HANDLED;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct node *sslcert_create_node(const struct ssl_cert_info *cert)
|
|
|
|
{
|
|
|
|
struct node *node;
|
|
|
|
struct node_element *element;
|
|
|
|
char *text;
|
|
|
|
|
|
|
|
text = messages_get_buff("SSL_Certificate_Subject", cert->subject);
|
|
|
|
if (text == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
node = tree_create_leaf_node(NULL, NULL, text, false, false, false);
|
|
|
|
if (node == NULL) {
|
|
|
|
free(text);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
tree_set_node_user_callback(node, sslcert_node_callback, NULL);
|
|
|
|
|
|
|
|
/* add issuer node */
|
|
|
|
element = tree_create_node_element(node, NODE_ELEMENT_TEXT,
|
|
|
|
TREE_ELEMENT_SSL_ISSUER, false);
|
|
|
|
if (element != NULL) {
|
|
|
|
text = messages_get_buff("SSL_Certificate_Issuer", cert->issuer);
|
|
|
|
if (text == NULL) {
|
|
|
|
tree_delete_node(NULL, node, false);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
tree_update_node_element(NULL, element, text, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* add version node */
|
|
|
|
element = tree_create_node_element(node, NODE_ELEMENT_TEXT,
|
|
|
|
TREE_ELEMENT_SSL_VERSION, false);
|
|
|
|
if (element != NULL) {
|
|
|
|
text = messages_get_buff("SSL_Certificate_Version", cert->version);
|
|
|
|
if (text == NULL) {
|
|
|
|
tree_delete_node(NULL, node, false);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
tree_update_node_element(NULL, element, text, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* add valid from node */
|
|
|
|
element = tree_create_node_element(node, NODE_ELEMENT_TEXT,
|
|
|
|
TREE_ELEMENT_SSL_VALID_FROM, false);
|
|
|
|
if (element != NULL) {
|
|
|
|
text = messages_get_buff("SSL_Certificate_ValidFrom", cert->not_before);
|
|
|
|
if (text == NULL) {
|
|
|
|
tree_delete_node(NULL, node, false);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
tree_update_node_element(NULL, element, text, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* add valid to node */
|
|
|
|
element = tree_create_node_element(node, NODE_ELEMENT_TEXT,
|
|
|
|
TREE_ELEMENT_SSL_VALID_TO, false);
|
|
|
|
if (element != NULL) {
|
|
|
|
text = messages_get_buff("SSL_Certificate_ValidTo", cert->not_after);
|
|
|
|
if (text == NULL) {
|
|
|
|
tree_delete_node(NULL, node, false);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
tree_update_node_element(NULL, element, text, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* add certificate type */
|
|
|
|
element = tree_create_node_element(node, NODE_ELEMENT_TEXT,
|
|
|
|
TREE_ELEMENT_SSL_CERT_TYPE, false);
|
|
|
|
if (element != NULL) {
|
|
|
|
text = messages_get_buff("SSL_Certificate_Type", cert->cert_type);
|
|
|
|
if (text == NULL) {
|
|
|
|
tree_delete_node(NULL, node, false);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
tree_update_node_element(NULL, element, text, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* add serial node */
|
|
|
|
element = tree_create_node_element(node, NODE_ELEMENT_TEXT,
|
|
|
|
TREE_ELEMENT_SSL_SERIAL, false);
|
|
|
|
if (element != NULL) {
|
|
|
|
text = messages_get_buff("SSL_Certificate_Serial", cert->serial);
|
|
|
|
if (text == NULL) {
|
|
|
|
tree_delete_node(NULL, node, false);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
tree_update_node_element(NULL, element, text, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* set the display icon */
|
|
|
|
tree_set_node_icon(NULL, node, sslcert_icon);
|
|
|
|
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool sslcert_load_tree(struct tree *tree,
|
|
|
|
const struct ssl_cert_info *certs,
|
|
|
|
struct sslcert_session_data *data)
|
|
|
|
{
|
|
|
|
struct node *tree_root;
|
|
|
|
struct node *node;
|
|
|
|
unsigned long cert_loop;
|
|
|
|
|
|
|
|
assert(data != NULL && certs != NULL && tree != NULL);
|
|
|
|
|
|
|
|
tree_root = tree_get_root(tree);
|
|
|
|
|
|
|
|
for (cert_loop = 0; cert_loop < data->num; cert_loop++) {
|
|
|
|
node = sslcert_create_node(&(certs[cert_loop]));
|
|
|
|
if (node != NULL) {
|
|
|
|
/* There is no problem creating the node
|
|
|
|
* add an entry for it in the root of the
|
|
|
|
* treeview .
|
|
|
|
*/
|
|
|
|
tree_link_node(tree, tree_root, node, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
data->tree = tree;
|
|
|
|
|
|
|
|
return tree;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void sslcert_cleanup_session(struct sslcert_session_data *session)
|
|
|
|
{
|
|
|
|
assert(session != NULL);
|
|
|
|
|
|
|
|
free(session->url);
|
|
|
|
free(session);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool sslcert_reject(struct sslcert_session_data *session)
|
|
|
|
{
|
|
|
|
session->cb(false, session->cbpw);
|
|
|
|
sslcert_cleanup_session(session);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handle acceptance of certificate
|
|
|
|
*/
|
|
|
|
bool sslcert_accept(struct sslcert_session_data *session)
|
|
|
|
{
|
|
|
|
assert(session != NULL);
|
|
|
|
|
|
|
|
urldb_set_cert_permissions(session->url, true);
|
|
|
|
|
|
|
|
session->cb(true, session->cbpw);
|
|
|
|
|
|
|
|
sslcert_cleanup_session(session);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|