NSS Shared DB: Difference between revisions

1,308 bytes added ,  5 February 2008
Line 448: Line 448:
  Sample code fragment.
  Sample code fragment.


====== Mode 3 ======
====== Mode 3A ======
Mode 3 Applications are the most complicated. NSS provides some services to help applications get through and update and merge with the least interaction with the user of the application.
Mode 3A Applications are the most complicated. NSS provides some services to help applications get through and update and merge with the least interaction with the user of the application. Below is the steps a Mode 3A application should use whenever initializing NSS.


Step 0: Preparation: collect the directory and prefix names of both the source and target DBs.  Prepare two strings for the operation:
Step 0: Preparation: collect the directory and prefix names of both the source and target DBs.  Prepare two strings for the operation:
Line 457: Line 457:
source DB, from any application "instance" names (such as profile
source DB, from any application "instance" names (such as profile
names), from the absolute path name of the source DB directory and the
names), from the absolute path name of the source DB directory and the
DB prefixes, and from the last modification time of the source DBs.<br><br>
DB prefixes, and from the last modification time of the source DBs.</nowiki><br><br></nowiki>
The algorithm for deriving this string should always produce the same
The algorithm for deriving this string should always produce the same
result for the same set of source files, so that the code can detect a
result for the same set of source files, so that the code can detect a
second or subsequent attempt to merge the same source file into the
second or subsequent attempt to merge the same source file into the
destination file.</nowiki><br><br><nowiki>
destination file.</nowiki><br><br><nowiki>
Note: The purpose of this string is to prevent multiple updates from the same old Database. This merge sequence is meant to be light enough weight that applications can safely call it each time they initialize.</nowiki>
Note: The purpose of this string is to prevent multiple updates from the same old Database. This merge sequence is meant to be light enough weight that applications can safely call it each time they initialize.</nowiki><br>
# <nowiki>A string that will be the name of the removable PKCS#11 token that
# <nowiki>A string that will be the name of the removable PKCS#11 token that
will represent the source DB.  This string must follow the rules for a
will represent the source DB.  This string must follow the rules for a
Line 470: Line 470:
directory name, destination file name prefix, source directory name,
directory name, destination file name prefix, source directory name,
source file name prefix, unique source DB identifier string, and source
source file name prefix, unique source DB identifier string, and source
token name string. If this function fails, stop.
token name string.
 
* If this function fails, stop.
* Otherwise proceed to step 2.


Step 2: Determine if a merge is even necessary. If a merge is necessary,
Step 2: Determine if a merge is even necessary. If a merge is necessary,
Line 476: Line 479:
test for this.
test for this.


*If the DB slot token is removable, then an update/merge is necessary.
* If the DB slot token is not removable, then no update/merge is necessary, goto step 7.
*However, if there is no database password on either the source or the target database,then NSS has already completed the merge. You can test for this with PK11_NeedLogin(). If PK11_NeedLogin() is true then it is necessary to authenticate to the source token, at step 3 below.
* (optional) If PK11_NeedLogin() is not true then NSS has already completed the merge for you (no passwords were needed), skip to step 7.
*If the token is not removable, then no merge is necessary and you can skip to step 7.
* Otherwise it is necessary to authenticate to the source token, at step 3 below.
 


Step 3. Authenticate to the source token.  The substeps are:
Step 3. Authenticate to the source token.  The substeps are:
Line 502: Line 506:
things happen.  After this call succeeds the token name should be that
things happen.  After this call succeeds the token name should be that
of the target token (see next step).
of the target token (see next step).
*If this fails, stop.
*If this fails, stop. (If this call indicates that the token is NOT present, something fundamentally wrong in the NSS softoken engine. Applications should treat this the same as an NSS initialization failure).
*If this call indicates that the token is NOT present, something fundamentally wrong in the NSS softoken engine. Applications should treat this the same as an NSS initialization failure.
*Otherwise continue to step 6.
*If this call indicates that the token name in the DB slot is now the target token name, continue to step 6.


Step 6: Call PK11_Authenticate to authenticate to the target token.
Step 6: Call PK11_Authenticate to authenticate to the target token.
Line 515: Line 518:
Step 7.  SUCCESS!  You have successfully performed the merge. Future calls using the same unique identifier will single that the merge is not necessary, skipping to here from step 2 above. At this point NSS is fully enabled and the application can start making NSS calls as normal.
Step 7.  SUCCESS!  You have successfully performed the merge. Future calls using the same unique identifier will single that the merge is not necessary, skipping to here from step 2 above. At this point NSS is fully enabled and the application can start making NSS calls as normal.


 
======= Failures and recovery =======
Exceptions:


Exception A. Application needs to decide what happens if the legacy password
Exception A. Application needs to decide what happens if the legacy password
Line 545: Line 547:
merge as soon as it is able, to increase reliability of the merge update actually completing. Therefore API does not make it
merge as soon as it is able, to increase reliability of the merge update actually completing. Therefore API does not make it
possible to predict, accurately, which step will actually perform the
possible to predict, accurately, which step will actually perform the
merge.  The code must try it and see. Since multiple calls to PK11_Authenticate() do not hurt (PK11_Authenticate will automatically return without prompting, so applications that just need to update (without necessarily caring which step the update completes) can simply follow the steps and know the update is done by step 7.
merge.  The application must try it and see if it cares. Since multiple calls to PK11_Authenticate() do not hurt, the application can simply follow each step in order, and failing only on bad returns from PK11_Authenticate. (PK11_Authenticate will automatically return without prompting, so applications that just need to update (without necessarily caring which step the update completes)).


2. If the attempt to open the
2. If the attempt to open the
Line 552: Line 554:
string in the target DB and act as if the merger is complete. This is similiar to what happens in all previous versions of NSS during database update. See "Database Merge" below for how to recover from this.
string in the target DB and act as if the merger is complete. This is similiar to what happens in all previous versions of NSS during database update. See "Database Merge" below for how to recover from this.
<pre>
<pre>
    /*
      * Initialize keeping track of the state
      */
     /* STEP 1: Signal that update/merge may be needed  */
     /* STEP 1: Signal that update/merge may be needed  */
     rv = NSS_InitWithMerge(SECU_ConfigDirectory(NULL),
     rv = NSS_InitWithMerge(SECU_ConfigDirectory(NULL),
Line 567: Line 572:
/* need to update/Merge the database */
/* need to update/Merge the database */
/*
/*
         * Step 3: Authenticate to the token
         * Step 3.1: Do we need to authenticate to the update Token?
         */
         */
         rv = PK11_Authenticate(slot, PR_FALSE, pwArg);
         if (PORT_Strcmp(PK11_GetTokenName(slot), updateTokenName) == 0)) {
if (rv != SECSuccess) {
            rv = PK11_Authenticate(slot, PR_FALSE, pwArg);
    if (PORT_Strcmp(PK11_GetTokenName(slot), updateTokenName) == 0)) {
    if (rv != SECSuccess) {
                /* handle exception A */
handle_failure_to_get_old_DB_Password();
handle_failure_to_get_old_DB_Password();
    } else {
                 goto fail; /* or done or fall through depending on recovery scheme */
                 /* handle exception B */
handle_failure_to_get_new_DB_Password();
    }
    }
    goto fail;
}
}
          
          
Line 585: Line 586:
                 printf("update complete!\n");
                 printf("update complete!\n");
                 rv = SECSuccess;
                 rv = SECSuccess;
                 goto shutdown;
                 goto done;
             }
             }
         }
         }
Line 594: Line 595:
         }
         }


         /* skipping optional step 6 */
         /* Step 6: */
        /* Step 7: */
         rv = PK11_Authenticate(slot, PR_FALSE, pwArg);
         rv = PK11_Authenticate(slot, PR_FALSE, pwArg);
         if (rv != SECSuccess) {
         if (rv != SECSuccess) {
             /* handle exception B */
             /* handle exception B */
    handle_failure_to_get_new_DB_Password();
    handle_failure_to_get_new_DB_Password();
          
            goto fail; /* or done depending on recovery scheme */
        }
done:
    }
 
    /* Step 7: NSS is initialized and merged, start using it */
</pre>
 
<pre>
    /*
      * simple update (applications does not care about the
      * underlying state machine).
      */
    /* STEP 1: Signal that update/merge may be needed  */
    rv = NSS_InitWithMerge(SECU_ConfigDirectory(NULL),
                            certPrefix, certPrefix, "secmod.db",
                            updateDir, updCertPrefix, updCertPrefix,
                            updateID, updateTokenName,
                            readOnly ? NSS_INIT_READONLY: 0);
 
    slot = PK11_GetInternalKeySlot();
 
    /*
      * Step 2: Determine if update/merge is needed.
      */
    if (!PK11_IsPerm(slot)) {
/* need to update/Merge the database */
/*
         * Step 3: Authenticate to the token
        */
        rv = PK11_Authenticate(slot, PR_FALSE, pwArg);
if (rv != SECSuccess) {
    goto fail;
}
       
        /* just update the state machine */
        /* Step 4: */
        PK11_IsLoggedIn(slot, &pwdata);
        /* Step 5: */
        PK11_IsPresent(slot)]
 
        /* Step 6: */
        rv = PK11_Authenticate(slot, PR_FALSE, pwArg);
        if (rv != SECSuccess) {
            goto fail;       
         }
         }
     }
     }


     /* NSS is initialized and merged, start using it */
     /* Step 7: NSS is initialized and merged, start using it */
</pre>
</pre>


439

edits