439
edits
(→Mode 3) |
|||
Line 448: | Line 448: | ||
Sample code fragment. | Sample code fragment. | ||
====== Mode | ====== Mode 3A ====== | ||
Mode | 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. | 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 | * If the DB slot token is not removable, then no update/merge is necessary, goto step 7. | ||
* | * (optional) If PK11_NeedLogin() is not true then NSS has already completed the merge for you (no passwords were needed), 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). | ||
*Otherwise 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 ======= | |||
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 | 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: | * 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)) { | ||
rv = PK11_Authenticate(slot, PR_FALSE, pwArg); | |||
if (rv != SECSuccess) { | |||
handle_failure_to_get_old_DB_Password(); | handle_failure_to_get_old_DB_Password(); | ||
goto fail; /* or done or fall through depending on recovery scheme */ | |||
/* | |||
} | } | ||
} | } | ||
Line 585: | Line 586: | ||
printf("update complete!\n"); | printf("update complete!\n"); | ||
rv = SECSuccess; | rv = SECSuccess; | ||
goto | goto done; | ||
} | } | ||
} | } | ||
Line 594: | Line 595: | ||
} | } | ||
/* | /* Step 6: */ | ||
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> | ||
edits