Bug 283521 - Show connection security status in statusbar and provide way to view certificate used.

ChatZilla only.
r=silver
a=asa
p=gijskruitbosch@gmail.com (Gijs "Hannibal" Kruitbosch)
This commit is contained in:
silver%warwickcompsoc.co.uk 2005-06-12 14:17:27 +00:00
parent e095c9065d
commit 9c852eb98b
8 changed files with 178 additions and 0 deletions

View File

@ -89,6 +89,8 @@ chatzilla.jar:
skin/modern/chatzilla/images/multiline-expand.png (xul/skin/images/multiline-expand.png)
skin/modern/chatzilla/images/multiline-contract.png (xul/skin/images/multiline-contract.png)
skin/modern/chatzilla/images/input-send.png (xul/skin/images/input-send.png)
skin/modern/chatzilla/images/secure.png (xul/skin/images/secure.png)
skin/modern/chatzilla/images/secure-broken.png (xul/skin/images/secure-broken.png)
locale/en-US/chatzilla/chatzillaOverlay.dtd (xul/locale/en-US/chatzillaOverlay.dtd)
locale/en-US/chatzilla/browserOverlay.dtd (xul/locale/en-US/browserOverlay.dtd)
locale/en-US/chatzilla/pref-irc.dtd (xul/locale/en-US/pref-irc.dtd)

View File

@ -51,6 +51,14 @@ const NS_NET_STATUS_SENDING_TO = NS_ERROR_MODULE_NETWORK + 5;
const NS_NET_STATUS_RECEIVING_FROM = NS_ERROR_MODULE_NETWORK + 6;
const NS_NET_STATUS_CONNECTING_TO = NS_ERROR_MODULE_NETWORK + 7;
// Security Constants.
const STATE_IS_BROKEN = 1;
const STATE_IS_SECURE = 2;
const STATE_IS_INSECURE = 3;
const STATE_SECURE_LOW = 1;
const STATE_SECURE_HIGH = 2;
const nsIScriptableInputStream = Components.interfaces.nsIScriptableInputStream;
const nsIBinaryInputStream = Components.interfaces.nsIBinaryInputStream;
@ -447,6 +455,62 @@ function bc_senddatanow(str)
return rv;
}
/* getSecurityState returns an array containing information about the security
* of the connection. The array always has at least one item, which contains a
* value from the STATE_IS_* enumeration at the top of this file. Iff this is
* STATE_IS_SECURE, the array has a second item indicating the level of
* security - a value from the STATE_SECURE_* enumeration.
*
* STATE_IS_BROKEN is returned if any errors occur, and STATE_IS_INSECURE is
* returned for disconnected sockets.
*/
CBSConnection.prototype.getSecurityState =
function bc_getsecuritystate()
{
if (!this.isConnected || !this._transport.securityInfo)
return [STATE_IS_INSECURE];
try
{
var sslSp = Components.interfaces.nsISSLStatusProvider;
var sslStatus = Components.interfaces.nsISSLStatus;
// Get the actual SSL Status
sslSp = this._transport.securityInfo.QueryInterface(sslSp);
sslStatus = sslSp.SSLStatus.QueryInterface(sslStatus);
// Store appropriate status
if (!("keyLength" in sslStatus) || !sslStatus.keyLength)
return [STATE_IS_BROKEN];
else if (sslStatus.keyLength >= 90)
return [STATE_IS_SECURE, STATE_SECURE_HIGH];
else
return [STATE_IS_SECURE, STATE_SECURE_LOW];
}
catch (ex)
{
// Something goes wrong -> broken security icon
dd("Exception getting certificate for connection: " + ex.message);
return [STATE_IS_BROKEN];
}
}
CBSConnection.prototype.getCertificate =
function bc_getcertificate()
{
if (!this.isConnected || !this._transport.securityInfo)
return null;
var sslSp = Components.interfaces.nsISSLStatusProvider;
var sslStatus = Components.interfaces.nsISSLStatus;
// Get the actual SSL Status
sslSp = this._transport.securityInfo.QueryInterface(sslSp);
sslStatus = sslSp.SSLStatus.QueryInterface(sslStatus);
// return the certificate
return sslStatus.serverCert;
}
function _notimpl ()
{
throw "Not Implemented.";

View File

@ -1078,6 +1078,15 @@ function promptPassword(msg, initial, parent, title)
return rv.value;
}
function viewCert(cert, parent)
{
var cd = getService("@mozilla.org/nsCertificateDialogs;1",
"nsICertificateDialogs");
if (!parent)
parent = window;
cd.viewCert(parent, cert);
}
function getHostmaskParts(hostmask)
{
var rv;

View File

@ -108,6 +108,8 @@ function initHandlers()
node = document.getElementById("multiline-input");
node.addEventListener("keypress", onMultilineInputKeyPress, false);
node.active = false;
node = document.getElementById("security-button");
node.addEventListener("dblclick", onSecurityIconDblClick, false);
window.onkeypress = onWindowKeyPress;
@ -258,6 +260,12 @@ function onSortCol(sortColName)
return false;
}
function onSecurityIconDblClick(e)
{
if (e.button == 0)
displayCertificateInfo();
}
function onMultilineInputKeyPress (e)
{
if ((e.ctrlKey || e.metaKey) && e.keyCode == 13)
@ -925,6 +933,7 @@ function my_showtonet (e)
updateTitle(this);
this.updateHeader();
client.updateHeader();
updateSecurityIcon();
updateStalkExpression(this);
// Do this after the JOINs, so they are quicker.
@ -1698,6 +1707,8 @@ function my_netdisconnect (e)
dispatch("sync-header");
updateTitle();
updateProgress();
updateSecurityIcon();
if ("userClose" in client && client.userClose &&
client.getConnectionCount() == 0)
window.close();

View File

@ -136,6 +136,10 @@
<progressmeter class="progressmeter-statusbar" id="status-progress-bar"
mode="undetermined" value="0"/>
</statusbarpanel>
<statusbarpanel id="security-button">
<label id="security-button-label"/>
<image id="security-button-image"/>
</statusbarpanel>
<!--
<statusbarpanel class="statusbarpanel-iconic" id="offline-status"
hidden="true" offline="true"/>

View File

@ -2011,6 +2011,45 @@ function updateProgress()
}
}
function updateSecurityIcon()
{
var o = getObjectDetails(client.currentObject);
var securityButton = window.document.getElementById("security-button");
securityButton.firstChild.value = "";
securityButton.removeAttribute("level");
securityButton.removeAttribute("tooltiptext");
if (!o.server || !o.server.isConnected) // No server or connection?
{
securityButton.setAttribute("tooltiptext", MSG_SECURITY_INFO);
return;
}
var securityState = o.server.connection.getSecurityState()
switch (securityState[0])
{
case STATE_IS_SECURE:
securityButton.firstChild.value = o.server.hostname;
if (securityState[1] == STATE_SECURE_HIGH)
securityButton.setAttribute("level", "high");
else // Because low security is the worst we have when being secure
securityButton.setAttribute("level", "low");
// Add the tooltip:
var issuer = o.server.connection.getCertificate().issuerOrganization;
var tooltiptext = getMsg(MSG_SECURE_CONNECTION, issuer);
securityButton.setAttribute("tooltiptext", tooltiptext);
securityButton.firstChild.setAttribute("tooltiptext", tooltiptext);
securityButton.lastChild.setAttribute("tooltiptext", tooltiptext);
break;
case STATE_IS_BROKEN:
securityButton.setAttribute("level", "broken");
// No break to make sure we get the correct tooltip
case STATE_IS_INSECURE:
default:
securityButton.setAttribute("tooltiptext", MSG_SECURITY_INFO);
}
}
function updateNetwork()
{
var o = getObjectDetails (client.currentObject);
@ -2170,6 +2209,21 @@ function multilineInputMode (state)
client.input.focus();
}
function displayCertificateInfo()
{
var o = getObjectDetails(client.currentObject);
if (!o.server)
return;
if (!o.server.isSecure)
{
alert(getMsg(MSG_INSECURE_SERVER, o.server.hostname));
return;
}
viewCert(o.server.connection.getCertificate());
}
function newInlineText (data, className, tagName)
{
if (typeof tagName == "undefined")
@ -2309,6 +2363,7 @@ function setCurrentObject (obj)
updateTitle();
updateProgress();
updateSecurityIcon();
if (client.PRINT_DIRECTION == 1)
scrollDown(obj.frame, false);

View File

@ -781,6 +781,9 @@ msg.server.info = "%S: Connected for %S, last ping: %S, server roundtrip (
msg.connect.via = Connected via %S"
msg.user.mode = User mode for %S is now %S"
msg.not.connected = "%S: Not connected.
msg.insecure.server = Your connection to the server ``%S'' is not secure.
msg.secure.connection = Signed by %S"
msg.security.info = Displays security information about the current connection
msg.member = Member
msg.operator = Operator member
msg.voiced = Voiced member

View File

@ -257,3 +257,33 @@ progressmeter[mode="undetermined"] {
direction: rtl;
}
/* Hack; Stop the status-bar from distorting without a security icon */
#status-text {
min-height: 17px;
}
#security-button {
min-width: 20px;
}
#security-button:not([level="high"]):not([level="low"]):not([level="broken"]) {
display: none;
}
#security-button[level="high"] > image {
list-style-image: url("chrome://chatzilla/skin/images/secure.png");
}
#security-button[level="low"] > image {
list-style-image: url("chrome://chatzilla/skin/images/secure.png");
}
#security-button[level="broken"] > image {
list-style-image: url("chrome://chatzilla/skin/images/secure-broken.png");
}
/* prevent margins of a value-less label from shifting the image */
#security-button > label:not([value]) {
display: none;
}