Bug 954534 - Use toolkit untrusted cert dialog for "SSL Handshake failed" errors: chat/ part, r=florian.
This commit is contained in:
Родитель
3ee5cdae24
Коммит
7c994c36f0
|
@ -103,6 +103,11 @@ interface prplIAccount: nsISupports {
|
|||
/* When a connection error occurred, this value indicates the type of error */
|
||||
readonly attribute short connectionErrorReason;
|
||||
|
||||
/* When a certificate error occurs, the host/port that caused a
|
||||
* SSL/certificate error when connecting to it. This is only valid when
|
||||
* connectionErrorReason is one of ERROR_CERT_*. */
|
||||
readonly attribute AUTF8String connectionTarget;
|
||||
|
||||
/* Possible connection error reasons:
|
||||
ERROR_NETWORK_ERROR and ERROR_ENCRYPTION_ERROR are not fatal and
|
||||
should enable the automatic reconnection feature. */
|
||||
|
|
|
@ -52,6 +52,40 @@ const GenericAccountPrototype = {
|
|||
_connectionErrorReason: Ci.prplIAccount.NO_ERROR,
|
||||
get connectionErrorReason() this._connectionErrorReason,
|
||||
|
||||
handleBadCertificate: function(aSocket, aIsSslError) {
|
||||
this._connectionTarget = aSocket.host + ":" + aSocket.port;
|
||||
|
||||
if (aIsSslError)
|
||||
return Ci.prplIAccount.ERROR_ENCRYPTION_ERROR;
|
||||
|
||||
let sslStatus = aSocket.sslStatus;
|
||||
if (!sslStatus)
|
||||
return Ci.prplIAccount.ERROR_CERT_NOT_PROVIDED;
|
||||
|
||||
if (sslStatus.isUntrusted) {
|
||||
if (sslStatus.serverCert instanceof Ci.nsIX509Cert3 &&
|
||||
sslStatus.serverCert.isSelfSigned)
|
||||
return Ci.prplIAccount.ERROR_CERT_SELF_SIGNED;
|
||||
return Ci.prplIAccount.ERROR_CERT_UNTRUSTED;
|
||||
}
|
||||
|
||||
if (sslStatus.isNotValidAtThisTime) {
|
||||
if (sslStatus.serverCert instanceof Ci.nsIX509Cert3 &&
|
||||
sslStatus.serverCert.validity.notBefore < Date.now() * 1000)
|
||||
return Ci.prplIAccount.ERROR_CERT_NOT_ACTIVATED;
|
||||
return Ci.prplIAccount.ERROR_CERT_EXPIRED;
|
||||
}
|
||||
|
||||
if (sslStatus.isDomainMismatch)
|
||||
return Ci.prplIAccount.ERROR_CERT_HOSTNAME_MISMATCH;
|
||||
|
||||
// XXX ERROR_CERT_FINGERPRINT_MISMATCH
|
||||
|
||||
return Ci.prplIAccount.ERROR_CERT_OTHER_ERROR;
|
||||
},
|
||||
_connectionTarget: "",
|
||||
get connectionTarget() this._connectionTarget,
|
||||
|
||||
reportConnected: function() {
|
||||
this.imAccount.observe(this, "account-connected", null);
|
||||
},
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
* connectTimeout (default is no timeout)
|
||||
* readWriteTimeout (default is no timeout)
|
||||
* isConnected
|
||||
* sslStatus
|
||||
*
|
||||
* Users should "subclass" this object, i.e. set their .__proto__ to be it. And
|
||||
* then implement:
|
||||
|
@ -42,7 +43,7 @@
|
|||
* onConnectionHeard()
|
||||
* onConnectionTimedOut()
|
||||
* onConnectionReset()
|
||||
* onBadCertificate(AString aNSSErrorMessage)
|
||||
* onBadCertificate(boolean aIsSslError, AString aNSSErrorMessage)
|
||||
* onConnectionClosed()
|
||||
* onDataReceived(String <data>)
|
||||
* <length handled> = onBinaryDataReceived(ArrayBuffer <data>)
|
||||
|
@ -131,6 +132,9 @@ const Socket = {
|
|||
connectTimeout: 0,
|
||||
readWriteTimeout: 0,
|
||||
|
||||
// A nsISSLStatus instance giving details about the certificate error.
|
||||
sslStatus: null,
|
||||
|
||||
/*
|
||||
*****************************************************************************
|
||||
******************************* Public methods ******************************
|
||||
|
@ -402,12 +406,16 @@ const Socket = {
|
|||
this.onConnectionReset();
|
||||
else if (aStatus == NS_ERROR_NET_TIMEOUT)
|
||||
this.onConnectionTimedOut();
|
||||
else if (aStatus) {
|
||||
else if (!Components.isSuccessCode(aStatus)) {
|
||||
let nssErrorsService =
|
||||
Cc["@mozilla.org/nss_errors_service;1"].getService(Ci.nsINSSErrorsService);
|
||||
if (aStatus <= nssErrorsService.getXPCOMFromNSSError(nssErrorsService.NSS_SEC_ERROR_BASE) &&
|
||||
aStatus >= nssErrorsService.getXPCOMFromNSSError(nssErrorsService.NSS_SEC_ERROR_LIMIT - 1)) {
|
||||
this.onBadCertificate(nssErrorsService.getErrorMessage(aStatus));
|
||||
if ((aStatus <= nssErrorsService.getXPCOMFromNSSError(nssErrorsService.NSS_SEC_ERROR_BASE) &&
|
||||
aStatus >= nssErrorsService.getXPCOMFromNSSError(nssErrorsService.NSS_SEC_ERROR_LIMIT - 1)) ||
|
||||
(aStatus <= nssErrorsService.getXPCOMFromNSSError(nssErrorsService.NSS_SSL_ERROR_BASE) &&
|
||||
aStatus >= nssErrorsService.getXPCOMFromNSSError(nssErrorsService.NSS_SSL_ERROR_LIMIT - 1))) {
|
||||
this.onBadCertificate(nssErrorsService.getErrorClass(aStatus) ==
|
||||
nssErrorsService.ERROR_CLASS_SSL_PROTOCOL,
|
||||
nssErrorsService.getErrorMessage(aStatus));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -419,12 +427,18 @@ const Socket = {
|
|||
*/
|
||||
// Called when there's an error, return true to suppress the modal alert.
|
||||
// Whatever this function returns, NSS will close the connection.
|
||||
notifyCertProblem: function(aSocketInfo, aStatus, aTargetSite) true,
|
||||
notifyCertProblem: function(aSocketInfo, aStatus, aTargetSite) {
|
||||
this.sslStatus = aStatus;
|
||||
return true;
|
||||
},
|
||||
|
||||
/*
|
||||
* nsISSLErrorListener
|
||||
*/
|
||||
notifySSLError: function(aSocketInfo, aError, aTargetSite) true,
|
||||
notifySSLError: function(aSocketInfo, aError, aTargetSite) {
|
||||
this.sslStatus = null;
|
||||
return true;
|
||||
},
|
||||
|
||||
/*
|
||||
* nsITransportEventSink methods
|
||||
|
|
|
@ -674,10 +674,11 @@ ircSocket.prototype = {
|
|||
this._account.gotDisconnected(Ci.prplIAccount.ERROR_NETWORK_ERROR,
|
||||
_("connection.error.timeOut"));
|
||||
},
|
||||
onBadCertificate: function(aNSSErrorMessage) {
|
||||
this.ERROR("bad certificate: " + aNSSErrorMessage);
|
||||
this._account.gotDisconnected(Ci.prplIAccount.ERROR_CERT_OTHER_ERROR,
|
||||
aNSSErrorMessage);
|
||||
onBadCertificate: function(aIsSslError, aNSSErrorMessage) {
|
||||
this.ERROR("Bad certificate or SSL connection for " + this._account.name +
|
||||
":\n" + aNSSErrorMessage);
|
||||
let error = this._account.handleBadCertificate(this, aIsSslError);
|
||||
this._account.gotDisconnected(error, aNSSErrorMessage);
|
||||
},
|
||||
|
||||
get DEBUG() this._account.DEBUG,
|
||||
|
|
|
@ -196,8 +196,9 @@ XMPPSession.prototype = {
|
|||
onConnectionClosed: function() {
|
||||
this._networkError(_("connection.error.serverClosedConnection"));
|
||||
},
|
||||
onBadCertificate: function(aNSSErrorMessage) {
|
||||
this.onError(Ci.prplIAccount.ERROR_CERT_OTHER_ERROR, aNSSErrorMessage);
|
||||
onBadCertificate: function(aIsSslError, aNSSErrorMessage) {
|
||||
let error = this._account.handleBadCertificate(this, aIsSslError);
|
||||
this.onError(error, aNSSErrorMessage);
|
||||
},
|
||||
onConnectionReset: function() {
|
||||
this._networkError(_("connection.error.resetByPeer"));
|
||||
|
|
Загрузка…
Ссылка в новой задаче