Bug 511327

Summary: unable to setup pki-tps with lunasa
Product: [Retired] Dogtag Certificate System Reporter: Chandrasekar Kannan <ckannan>
Component: TPSAssignee: Ade Lee <alee>
Status: CLOSED NOTABUG QA Contact: Chandrasekar Kannan <ckannan>
Severity: urgent Docs Contact:
Priority: urgent    
Version: unspecifiedCC: alee, benl, dlackey, emaldona, jmagne, mrhodes, rrelyea
Target Milestone: ---   
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2009-10-12 18:43:24 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On:    
Bug Blocks: 443788, 445047, 512842    

Description Chandrasekar Kannan 2009-07-14 17:31:36 UTC
I have 4 hosts that are connected to lunasa (partition : lunasa2-ca)

1- setup ca on host1
2- setup tks on host2
3- setup kra on host3
4- setup tps on host4

Step 4 fails. here's the tps setup error log..
===========================================================================
==> error_log <==
Error opening input terminal for read
certutil: could not find certificate named "lunasa2-ca:Server-Cert cert-pki-tps": The security password entered is incorrect.
Error opening input terminal for read
certutil: could not find certificate named "lunasa2-ca:lunasa2-ca:Server-Cert cert-pki-tps": The security password entered is incorrect.
certutil: could not add certificate to token or database: Error adding certificate to database.
[Tue Jul 14 02:27:03 2009] -e: Use of uninitialized value in concatenation (.) or string at /var/lib/pki-tps/lib/perl/PKI/TPS/NamePanel.pm line 297.
POST /ca/ee/ca/profileSubmit HTTP/1.0
Content-Length: 1169
Content-Type: application/x-www-form-urlencoded

profileId=caInternalAuthSubsystemCert&cert_request_type=pkcs10&requestor_name=TPS-seraph.dsdev.sjc.redhat.com-7889&cert_request=MIICmzCCAYMCAQAwVjEeMBwGA1UEChMVRHNkZXZTamNSZWRoYXQgRG9tYWluMRAwDgYDVQQLEwdwa2ktdHBzMSIwIAYDVQQDExlUUFMgU3Vic3lzdGVtIENlcnRpZmljYXRlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAufCx5DMLyZFj6J6GoKOAVtLoZwXyE8kWtICQ7eCatPtFeyoH%2FYf3EIDiuYMzuNqLovhWSfHZ6YHc1%2BGX6fz6tppZ93ybHUFs9byXqixtOek67JEt1cAdlAv%2F2CF1GsqQHqPdT24Bjn4vqVXWQCIK%2B9eL2o8drr%2FItDneP3wQ%2FgcysN0WsTFQ8lcZ30uuSxPw3p40wtkaPgb68TGlA4OMUP9RjELtAKvisq2nWhX89BDQSMTry789u%2BP%2Bk6OTYlx7KcX3ruNWddPXQ6br79jI5gp4f2Iy2pdmNI7j4v%2FO7g4DiKzxwd5IPK8qwh6ofTe5fqkaI0BPD%2Bwc6OlEw29cCwIDAQABoAAwDQYJKoZIhvcNAQEFBQADggEBAD4tCBgRN9DBWuwnkTX5oWwpHs3iXYNoHvuBBsFGqUvykQ%2Ba3dRET6m770sgp4CfHHkOrjFcbZkwM5YfIX8RB6YMUyVP5OPV%2BUQScP1iHXqeZoDr54ijbRPOkjrYdcacrPCCVtsJRuIOdAgDe6B%2BLOn%2F1eC1RygRM%2FWr5iTkUNDHXZyCEWmHdP%2Br5yDHKrP3FuTzgGyU6H8iRzavCxlUEXoqes%2FJkG73Y8h3K5ElhdOAYBQlja%2FORQz5%2B9A5zQAtRdpLSKyi4gr9EE8sCW7NSri%2FkFFQRz39rhfHSR%2B3JvDiVh4TIvcx5ekscUitVyEvDcY%2BegOSEPz8PfHNkzCwvjc%3D&xmlOutput=true&sessionID=4587550030884575474&auth_hostname=neo.dsdev.sjc.redhat.com&auth_port=9444Can't find certificate lunasa2-ca:lunasa2-ca:Server-Cert cert-pki-tps
[Tue Jul 14 02:27:03 2009] -e: Use of uninitialized value in string eq at /var/lib/pki-tps/lib/perl/PKI/TPS/NamePanel.pm line 311.
[Tue Jul 14 02:27:03 2009] -e: Use of uninitialized value in string eq at /var/lib/pki-tps/lib/perl/PKI/TPS/NamePanel.pm line 482.

===========================================================================

tps believes the password entered is incorrect. But I don't think so.
The password entered through the wizard is infact correct as proved by

[root@seraph conf]# cat /var/lib/pki-tps/.pwfile
Secret123
[root@seraph conf]#

I believe .pwfile is used for key gen.

Comment 1 Chandrasekar Kannan 2009-07-14 17:36:11 UTC
the error message during pki-tps setup is thrown on the "Subject Names" panel where it says

"CA returned no response. Please check that the CA is available and also check the host's firewall settings. "

Comment 2 Chandrasekar Kannan 2009-07-14 17:36:29 UTC
there's no firewall enabled on any of the 4 hosts

Comment 7 Ade Lee 2009-08-06 05:42:18 UTC
After some analysis - its clear that the installation fails because the Server Cert fails to be inserted in the token. Unlike the other subsystems which install their certs through jss - the TPS and RA use certutil to install their certs. 

Specifically, the cert request is generated from a certutil command similar to the following:

certutil -R -s "CN=seraph.dsdev.sjc.redhat.com, OU=pki-tps03, O=mouse lunasa alee 0727 manualtest" -k rsa -g 2048 -d /var/lib/pki-ca/alias -h lunasa2-ca -a

This request is sent to the CA, where a cert is issued and send back to the TPS.  It is then imported into the token using the following command:

certutil -A -d /var/lib/rhpki-ca/alias -h lunasa2-ca   -n "Server-Cert seraph cert-pki-ca alee 0728 manualtest" -t "u,u,u" -a -i /root/mytest2/cert.txt

This command is the one that fails.  Specifically, it fails in devtoken.c when the C_CreateObject() command is called, with a error return code of 0x13 - CKA_INVALID_ATTRIBUTE_VALUE.

The stack trace at that point is as follows:

#0  import_object (tok=0x8c1ade0, sessionOpt=<value optimized out>,
    objectTemplate=0xbfa8eb38, otsize=9) at devtoken.c:252
#1  0x05262509 in nssToken_ImportCertificate (tok=0x8c1ade0, sessionOpt=0x0,
    certType=NSSCertificateType_PKIX, id=0x8c2e270,
    nickname=0x8a7a490 "Server-Cert seraph cert-pki-ca alee 0728 manualtest",
    encoding=0x8c2e278, issuer=0x8c2e280, subject=0x8c2e288, serial=0x8c2e290,
    email=0x0, asTokenObject=1) at devtoken.c:579
#2  0x052221f4 in PK11_ImportCert (slot=<value optimized out>,
    cert=<value optimized out>, key=<value optimized out>,
    nickname=<value optimized out>, includeTrust=Could not find the frame base for "PK11_ImportCert".
) at pk11cert.c:911
#3  0x08050f99 in AddCert (slot=0x8c28bc0, handle=0x8a9e240,
    name=0x8a7a490 "Server-Cert seraph cert-pki-ca alee 0728 manualtest",
    trusts=0xbfa8fbdb "u,u,u", inFile=0x8a7a450, ascii=1, emailcert=0,
    pwdata=0xbfa8ee78) at certutil.c:180
#4  0x08055082 in certutil_main (argc=<value optimized out>,
    argv=<value optimized out>, initialize=1) at certutil.c:2846
#5  0x08056083 in main (argc=Cannot access memory at address 0x1
) at certutil.c:2981

Note: The root cause of the failure has been isolated to changes that have occurred in nss or nss_tools between versions 3.12.2.0-4 (where it works) and 3.12.3.99-1.2 (where it doesn't)

We were able to go from a system where the certutil -A command above worked to one where it fails, simply by upgrading nss, nss-tools and nspr.

Comment 8 Ade Lee 2009-08-06 16:09:16 UTC
Ok - so on looking at the differences between the two sets of code, the problem is apparent.

Consider the following snippet from certutil.c (in the function AddCert())

This is what it used to look like:

        if (PK11_IsFIPS() || !PK11_IsInternal(slot)) {
            rv = PK11_Authenticate(slot, PR_TRUE, pwdata);
            if (rv != SECSuccess) {
                SECU_PrintError(progName, "could not authenticate to token %s.",
                                PK11_GetTokenName(slot));
                GEN_BREAK(SECFailure);
            }
        }

        rv =  PK11_ImportCert(slot, cert, CK_INVALID_HANDLE, name, PR_FALSE);
        if (rv != SECSuccess) {
            SECU_PrintError(progName, "could not add certificate to token or database");
            GEN_BREAK(SECFailure);
        }

In this case, we authenticate to the token and then attempt to import the cert.

This is how it looks now:

        rv =  PK11_ImportCert(slot, cert, CK_INVALID_HANDLE, name, PR_FALSE);
        if (rv != SECSuccess) {
            /* sigh, PK11_Import Cert and CERT_ChangeCertTrust should have
             * been coded to take a password arg. */
            if (PORT_GetError() == SEC_ERROR_TOKEN_NOT_LOGGED_IN) {
                rv = PK11_Authenticate(slot, PR_TRUE, pwdata);
                if (rv != SECSuccess) {
                    SECU_PrintError(progName,
                                "could not authenticate to token %s.",
                                PK11_GetTokenName(slot));
                    GEN_BREAK(SECFailure);
                }
                rv = PK11_ImportCert(slot, cert, CK_INVALID_HANDLE,
                                     name, PR_FALSE);
            }
            if (rv != SECSuccess) {
                SECU_PrintError(progName,
                        "could not add certificate to token or database");
                GEN_BREAK(SECFailure);
            }
        }

Here - we attempt an import and when that fails - if the return code is SEC_ERROR_NOT_LOGGED_IN, then we authenticate and retry the PK11_Import_Cert.  This obviously works for nethsm2k.

But lunasa returns a different error - ie. not SEC_ERROR_NOT_LOGGED_IN - so we do not authenticate to the token and retry the import.  We need to check if lunasa is not complying to the spec by not returning this error - but in any case, certutil with lunasa is now broken.

running certutil under gdb confirms this broken flow.

Comment 9 Elio Maldonado Batiz 2009-08-13 16:13:14 UTC
So Luna does not return SEC_ERROR_NOT_LOGGED_IN as NSS expects, then the question is what is the value of the code that Luna returns?

Comment 10 Ade Lee 2009-08-13 18:22:27 UTC
FYI - I tried a modified NSS where the token is logged into just prior to the PK11_ImportCert call (ie. putting back the old code).

With this code, certutil -A is successful against the lunasa.

********************

--- ./mozilla/security/nss/cmd/certutil/certutil.c.ade  2009-08-13 03:13:13.000000000 -0700
+++ ./mozilla/security/nss/cmd/certutil/certutil.c      2009-08-13 03:14:17.000000000 -0700
@@ -177,6 +177,16 @@ AddCert(PK11SlotInfo *slot, CERTCertDBHa
            GEN_BREAK(SECFailure);
        }

+        if (PK11_IsFIPS() || !PK11_IsInternal(slot)) {
+            rv = PK11_Authenticate(slot, PR_TRUE, pwdata);
+            if (rv != SECSuccess) {
+                SECU_PrintError(progName, "could not authenticate to token %s.",
+                                PK11_GetTokenName(slot));
+                GEN_BREAK(SECFailure);
+            }
+        }
+
+
        rv =  PK11_ImportCert(slot, cert, CK_INVALID_HANDLE, name, PR_FALSE);
        if (rv != SECSuccess) {
            /* sigh, PK11_Import Cert and CERT_ChangeCertTrust should have

Comment 11 Ade Lee 2009-08-14 16:08:40 UTC
So - looking closely at the NSS code, I see the following:

We expect the call to PK11_ImportCert to return either SEC_ERROR_TOKEN_NOT_LOGGED_IN or SEC_ERROR_ADDING_CERT

because at the end of PK11_Import, we have the following code:

loser:
    CERT_MapStanError();
    SECITEM_FreeItem(keyID,PR_TRUE);
    if (PORT_GetError() != SEC_ERROR_TOKEN_NOT_LOGGED_IN) {
        PORT_SetError(SEC_ERROR_ADDING_CERT);
    }
    return SECFailure;

This means we should look at all the cases where PK11_Import can end up in loser:
There are a number of places where this can happen - but none of these result in the return code that maps to SEC_ERROR_TOKEN_NOT_LOGGED_IN

The only place this can occur is at:
 
certobj = nssToken_ImportCertificate(token, NULL,
                                         NSSCertificateType_PKIX,
                                         &c->id,
                                         nickname,
                                         &c->encoding,
                                         &c->issuer,
                                         &c->subject,
                                         &c->serial,
                                         emailAddr,
                                         PR_TRUE);

which calls  :

 ckrv = CKAPI(epv)->C_CreateObject(session->handle,
                                      objectTemplate, otsize,
                                      &handle);

followed by:

    if (ckrv == CKR_OK) {
        object = nssCryptokiObject_Create(tok, session, handle);
    } else {
        nss_SetError(ckrv);
        nss_SetError(NSS_ERROR_PKCS11);
    }

We expect the token to return CKR_USER_NOT_LOGGED_IN when it returns 
CKR_ATTRIBUTE_VALUE_INVALID instead.

We need to figure out why this is - but I'm presuming that if more than one problem is apparent - ie. not logged in and also bad data - then the behaviour expected of the vendor is undefined ..

Comment 12 Ade Lee 2009-08-14 16:10:50 UTC
One more comment: To reproduce the bug under gdb, do the following:

1. Enter gdb by typing gdb
2. Enter the following in gdb:

   file /usr/bin/certutil

   set args -A -d /var/lib/pki-ca/alias -h lunasa2-ca   -n "Server-Cert
seraph cert-pki-ca alee 0728 manualtest 9" -t "u,u,u" -a
-i /root/mytest/cert.txt

  (the above is all one line)

3. set break points .. the ones most useful to me have been :

   b certutil.c:179 (where the certutil code change is made)
   b pk11cert.c:911 (just before the attribute struct is constructed)
   b  devtoken.c:248 (where the object is created.  If you step forward 
      here, you can query the value of ckrv, which is 19 -- 0x13 --   
      invalid_attribute_value)

Comment 13 Bob Relyea 2009-08-14 16:55:13 UTC
I talked to alee on aim about this issue: here's the summary:

The template looks good. 

1) It seems that the Luna is seeing CKA_TOKEN set to PR_TRUE, but the user isn't logged in, so it's returning 'CKR_ATTRIBUTE_VALUE_INVALID' when it should really return 'CKR_USER_NOT_LOGGED_IN'. We should notify luna of this problem.

2) We can work around the problem by adding an option to certutil to force authentication on any certutil command. That allows us to handle misbehaving tokens if we need to.

Alee is working on a patch which I will review for upstream.

bob