Closed Bug 986956 Opened 10 years ago Closed 9 years ago

@mozilla.org/security/x509certdb remains readonly after using it from autoconfig

Categories

(Core :: Security: PSM, defect)

27 Branch
x86
Linux
defect
Not set
normal

Tracking

()

RESOLVED FIXED
mozilla45
Tracking Status
firefox45 --- fixed

People

(Reporter: dab1818, Assigned: keeler)

References

Details

Attachments

(1 file)

User Agent: Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.117 Safari/537.36

Steps to reproduce:

autoconfig based on examples from:
https://developer.mozilla.org/en-US/docs/MCD,_Mission_Control_Desktop_AKA_AutoConfig
https://developer.mozilla.org/en-US/Add-ons/Code_snippets/Miscellaneous#Adding_custom_certificates_to_a_XULRunner_application

1. enable MCD
pref("general.config.obscure_value", 0);
pref("general.config.filename", "bugdemo.js");

2. create config file bugdemo.js:
/* important! needed empty first line */
var certDB = Components.classes["@mozilla.org/security/x509certdb;1"].getService(Components.interfaces.nsIX509CertDB2);

3. start browser NSPR_LOG_MODULES=MCD:5 firefox -jsconsole

4. in firefox go to Edit - Preferences - Advanced - Certificates - View Certificates - Authorities,
 select any CA, click Edit Trust

5. or switch to Your Certificated and try import-export-install personal certificate.



Actual results:

Firefox27 & Seamonkey2.24 and later show error in console

JavaScript error: chrome://pippki/content/editcerts.js, line 26: NS_ERROR_NOT_AVAILABLE: Component returned failure code: 0x80040111 (NS_ERROR_NOT_AVAILABLE) [nsIX509CertDB.findCertByDBKey]

Edit Trust dialog not working, import-export-install personal certificates not working
and does nothing with certificates.



Expected results:

1 editable CA trust
2 managed personal certificates
User Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:31.0) Gecko/20100101 Firefox/31.0

Hit exactly the same with Firefox ESR 31.4.0.
I believe the issue here is that nsIX509CertDB2 was combined into nsIX509CertDB.

Can you try using nsIX509CertDB and see if that fixes it?
May I misunderstand you advice, but at least for ESR 31 the nsIX509CertDB interface has member functions different from nsIX509CertDB. For instance nsIX509CertDB doesn't have a addCertFromBase64() function.
Yes, you're correct

I was thinking of this change in Firefox 33:

https://bugzilla.mozilla.org/show_bug.cgi?id=643041
new ff33+ compatible code:

    var certDB = Components.classes["@mozilla.org/security/x509certdb;1"].getService(Components.interfaces.nsIX509CertDB);
    //https://bugzilla.mozilla.org/show_bug.cgi?id=643041
    var certDB2 = certDB;
    var appInfo = Components.classes["@mozilla.org/xre/app-info;1"].getService(Components.interfaces.nsIXULAppInfo);
    if (parseInt(appInfo.platformVersion, 10) < 33) {
        certDB2 = Components.classes["@mozilla.org/security/x509certdb;1"].getService(Components.interfaces.nsIX509CertDB2);
    }

1 Mozilla/5.0 (X11; Linux i686; rv:31.0) Gecko/20100101 Firefox/31.0

click "Edit Trust" on CA entry:
JavaScript error: chrome://pippki/content/editcerts.js, line 26: NS_ERROR_NOT_AVAILABLE: Component returned failure code: 0x80040111 (NS_ERROR_NOT_AVAILABLE) [nsIX509CertDB.findCertByDBKey]
click checkbox in "Edit CA certificate trust settings" and "OK":
JavaScript error: chrome://pippki/content/editcerts.js, line 68: NS_ERROR_NOT_AVAILABLE: Component returned failure code: 0x80040111 (NS_ERROR_NOT_AVAILABLE) [nsIX509CertDB.setCertTrust]

2 Mozilla/5.0 (X11; Linux i686; rv:35.0) Gecko/20100101 Firefox/35.0
JavaScript error: chrome://pippki/content/editcerts.js, line 26: NS_ERROR_NOT_AVAILABLE: Component returned failure code: 0x80040111 (NS_ERROR_NOT_AVAILABLE) [nsIX509CertDB.findCertByDBKey]
JavaScript error: chrome://pippki/content/editcerts.js, line 67: NS_ERROR_NOT_AVAILABLE: Component returned failure code: 0x80040111 (NS_ERROR_NOT_AVAILABLE) [nsIX509CertDB.setCertTrust]
I could bypass the issue by switching to the createInstance method on favour to getService.
I found this behavior in Firefox27 & Seamonkey2.24
and forced to use workaround with restart browser after accessing certdb from autoconfig:
...
function addCAcertsFromFile(filename) {
    var certDB = Components.classes["@mozilla.org/security/x509certdb;1"].getService(Components.interfaces.nsIX509CertDB);
    //https://bugzilla.mozilla.org/show_bug.cgi?id=643041
    var certDB2 = certDB;
    var appInfo = Components.classes["@mozilla.org/xre/app-info;1"].getService(Components.interfaces.nsIXULAppInfo);
    if (parseInt(appInfo.platformVersion, 10) < 33) {
        certDB2 = Components.classes["@mozilla.org/security/x509certdb;1"].getService(Components.interfaces.nsIX509CertDB2);
    }
....
///adding cert to keystore
certDB2.addCertFromBase64(....);
....
}
...
    var reboot = null;
    var appInfo = Components.classes["@mozilla.org/xre/app-info;1"].getService(Components.interfaces.nsIXULAppInfo);
    if (parseInt(appInfo.platformVersion, 10) < 27) {
        addCAcertsFromFile(cafile);
    } else {
        var env = Components.classes["@mozilla.org/process/environment;1"].getService(Components.interfaces.nsIEnvironment);
        //TODO Firefox27 & Seamonkey2.24 is byggy: keystore not closed and stay readonly. need restart
        if (!env.exists("FF_CERTS_ADDED")) {
            addCAcertsFromFile(cafile);
            env.set("FF_CERTS_ADDED", "1");
            reboot = Components.classes["@mozilla.org/toolkit/app-startup;1"].getService(Components.interfaces.nsIAppStartup);
            reboot.quit(Components.interfaces.nsIAppStartup.eForceQuit | Components.interfaces.nsIAppStartup.eRestart);
        }
    }
...
NS_ERROR_NOT_AVAILABLE probably indicates that NSS has already shut down by the time that code has run. Can you post a log with 'pipnss:5' in NSPR_LOG_MODULES?
Flags: needinfo?(dab1818)
NSPR_LOG_MODULES=pipnss:5 firefox -jsconsole

-1220385024[b72229c0]: nsNSSComponent::ctor
-1220385024[b72229c0]: Beginning NSS initialization
-1220385024[b72229c0]: nsNSSComponent: adding observers
-1220385024[b72229c0]: nsNSSComponent::InitializeNSS
-1220385024[b72229c0]: NSS Initialization beginning
-1220385024[b72229c0]: NSS Initialization done
-1220385024[b72229c0]: nsNSSComponent::ShutdownNSS
-1220385024[b72229c0]: evaporating psm resources
-1220385024[b72229c0]: now evaporating NSS resources
-1220385024[b72229c0]: NSS shutdown =====>> OK <<=====
-1220385024[b72229c0]: nsNSSComponent::InitializeNSS
-1220385024[b72229c0]: NSS Initialization beginning
-1220385024[b72229c0]: NSS Initialization done
-1377830080[b7222fc0]: [ade159c0] nsSSLIOLayerSetOptions: using TLS version range (0x0301,0x0303)
-1377830080[b7222fc0]: [ade159c0] Socket set up
-1377830080[b7222fc0]: [ade159c0] connecting SSL socket
-1377830080[b7222fc0]: [ade159c0] Lower layer connect error: -5934
-1377830080[b7222fc0]: [ade159c0] poll SSL socket using lower 6
-1377830080[b7222fc0]: [ade159c0] poll SSL socket returned 6
-1377830080[b7222fc0]: [ade159c0] poll SSL socket using lower 5
-1377830080[b7222fc0]: [ade159c0] poll SSL socket returned 6
-1377830080[b7222fc0]: [ade159c0] poll SSL socket using lower 6
-1377830080[b7222fc0]: [ade159c0] poll SSL socket returned 6
-1377830080[b7222fc0]: [ade159c0] read -1 bytes
-1377830080[b7222fc0]: [ade159c0] read -1 bytes
-1377830080[b7222fc0]: [ade159c0] wrote -1 bytes
-1377830080[b7222fc0]: [ade159c0] poll SSL socket using lower 6
-1377830080[b7222fc0]: [ade159c0] poll SSL socket returned 5
-1377830080[b7222fc0]: [ade159c0] poll SSL socket using lower 6
-1377830080[b7222fc0]: [ade159c0] poll SSL socket returned 5
-1377830080[b7222fc0]: [af5fc1a0] starting AuthCertificateHook
-1708139712[9b3c4640]: [ade111a0] SSLServerCertVerificationJob::Run
-1708139712[9b3c4640]: nsNSSHttpRequestSession::trySendAndReceiveFcn to http://clients1.google.com:80/ocsp
....

click checkbox in "Edit CA certificate trust settings" and "OK":
JavaScript error: chrome://pippki/content/editcerts.js, line 67: NS_ERROR_NOT_AVAILABLE: Component returned failure code: 0x80040111 (NS_ERROR_NOT_AVAILABLE) [nsIX509CertDB.setCertTrust]
Flags: needinfo?(dab1818)
thanks Mathias Kresin,
finally i make "cross-browser" solution to install certificates:
...
    var appInfo = Components.classes["@mozilla.org/xre/app-info;1"].getService(Components.interfaces.nsIXULAppInfo);
    if (parseInt(appInfo.platformVersion, 10) < 31) { //31? not sure
        certDB = Components.classes["@mozilla.org/security/x509certdb;1"].getService(Components.interfaces.nsIX509CertDB);
        certDB2 = Components.classes["@mozilla.org/security/x509certdb;1"].getService(Components.interfaces.nsIX509CertDB2);
        certDB3 = certDB2;
    } else if (parseInt(appInfo.platformVersion, 10) < 33) { //33? not sure
        certDB = Components.classes["@mozilla.org/security/x509certdb;1"].createInstance(Components.interfaces.nsIX509CertDB);
        certDB2 = certDB;
        certDB3 = Components.classes["@mozilla.org/security/x509certdb;1"].createInstance(Components.interfaces.nsIX509CertDB2);
    } else {
        certDB = Components.classes["@mozilla.org/security/x509certdb;1"].createInstance(Components.interfaces.nsIX509CertDB);
        certDB2 = certDB;
        certDB3 = certDB2;
    }
...
      x509 = certDB.constructX509FromBase64(...);
...
      find = certDB2.findCertByDBKey(...);
...
      certDB3.addCertFromBase64(...);
...

tested on seanokey 2.11 - 2.38, firefox 31 - 42 ... linux + windows.

close this bug?
I still want to know the why of this. createInstance isn't the right solution.
I think I know what's going on here. The autoconfig code runs before the xul runtime emits the "profile-do-change" notification. The autoconfig code instantiates a PSM certificate DB (nsIX509CertDB), which means that the PSM component and therefore NSS are also initialized. Then, when the PSM component sees the "profile-do-change" notification and determines that NSS has already been initialized, it shuts it down and restarts it. When this happens, any object holding onto NSS resources is notified that it can no longer use those resources. The PSM certificate DB is one of these objects, and since it is a service, it stays around for a long time essentially refusing to do any more work.

The way I see it, there's two ways to solve this:

1. Make PSM/NSS initialization/destruction even more complicated by having objects with NSS resources try and see if there's a new NSS instantiation or something.

or

2. Make PSM/NSS initialization/destruction simpler by never reinitializing NSS once it's been initialized.

Luckily, option 2 is already in line with preexisting work we're doing, so we'll go with that.
bug 986956 - only ever initialize NSS once per process

As a consequence, if NSS is initialized when there is no profile directory, NSS
will not persist changes. Other failures may occur (e.g. see bug 1216882).
Attachment #8690260 - Flags: review?(mgoodwin)
Attachment #8690260 - Flags: review?(cykesiopka.bmo)
Assignee: nobody → dkeeler
> As a consequence, if NSS is initialized when there is no profile directory, NSS
will not persist changes. 

Am I correct that because when AutoConfig executes, there is a profile directory, the certs should be OK?
Yes, I verified that this is the case. I imagine there are some tests for autoconfig and that we can incorporate checking that the PSM component does the right thing with NSS.
(In reply to David Keeler [:keeler] (use needinfo?) from comment #17)
> Yes, I verified that this is the case. I imagine there are some tests for
> autoconfig and that we can incorporate checking that the PSM component does
> the right thing with NSS.

Sadly there are no AutoConfig tests because QA couldn't figure out how to do a test where we lay down files in the directory like we need do. That might have changed (It's been a while). I'll check again.
Attachment #8690260 - Flags: review?(mgoodwin) → review+
Comment on attachment 8690260 [details]
MozReview Request: bug 986956 - only ever initialize NSS once per process

https://reviewboard.mozilla.org/r/25819/#review23507

Looks good; ship it!
Comment on attachment 8690260 [details]
MozReview Request: bug 986956 - only ever initialize NSS once per process

https://reviewboard.mozilla.org/r/25819/#review23611

LGTM.
Attachment #8690260 - Flags: review?(cykesiopka.bmo) → review+
Thanks for the reviews!
Here was the try run in case anyone asks: https://treeherder.mozilla.org/#/jobs?repo=try&revision=89dd207e46ca
https://hg.mozilla.org/mozilla-central/rev/97419358e589
Status: UNCONFIRMED → RESOLVED
Closed: 9 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla45
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: