Closed
Bug 351767
Opened 19 years ago
Closed 19 years ago
pk12util cmd with -o and -W options crashes if exportfile is a directory
Categories
(NSS :: Tools, defect, P2)
Tracking
(Not tracked)
RESOLVED
FIXED
3.11.7
People
(Reporter: nelson, Assigned: neil.williams)
Details
Attachments
(1 file, 2 obsolete files)
|
2.48 KB,
patch
|
nelson
:
review+
alvolkov.bgs
:
review+
|
Details | Diff | Splinter Review |
I was trying to create a .p12 file from a DBdir containing some certs and
a private key. The pk12util program I was using was a debug build, built
with Windows' debug RTL.
I intended to create the p12 file with the name outdir/outfile.p12 but I
mistyped the output filename, omitting the "/outfile.p12", leaving just
the directory name. I typed the command like this:
pk12util -n nickname -d DBdir -o outdir -W password -K password
where nickname, DBdir, and the two passwords were the correct/expected
values, but (again) outdir should have been outdir/outfile.p12.
pk12util output a single line error message, then crashed.
The error message was:
pk12util: Initialization failed: outdir: Access Denied.
The code crashed in free().
The stack was:
free(void * 0x00a61e60) line 926 + 11 bytes
PR_Free(void * 0x00a61e60) line 536 + 10 bytes
P12U_ExportPKCS12Object() line 712 + 13 bytes
main(int 0x0000000b, char * * 0x00a61cd0) line 957 + 28 bytes
The lines of code where the crash occurred were:
if (slotPw)
PR_Free(slotPw->data);
if (p12FilePw)
PR_Free(p12FilePw->data); <- crashed here
By trial and error, I found that there are two crucial ingredients
to this crash, which are:
a) the output filename must be a name that will result in a failure
b) the -W option and its argument must be present on the command line
The -K option and its argument are not required. Without the -K option,
the user is prompted for the cert DB password before the crash.
The problem is a double-free.
In function P12U_GetP12FilePassword, the value p12FilePw->data is assigned
to a variable named p0, which is then freed. Then later, the value of
p12FilePw->data is freed again (at the line shown above) resulting in a
double-free.
One possible (untested) solution might be this change in P12U_GetP12FilePassword:
} else { /* Plaintext */
- p0 = p12FilePw->data;
+ p0 = PORT_Strdup(p12FilePw->data);
}
| Reporter | ||
Comment 1•19 years ago
|
||
More observations about this code.
In function P12U_ExportPKCS12Object, at label "loser", the function frees
the password strings
if (slotPw)
PR_Free(slotPw->data);
if (p12FilePw)
PR_Free(p12FilePw->data);
This is only done in the error path, not in the success path.
Notice that the tests are wrong. They should be
if (slowPw && slotPw->data)
and
if (p12FirePw && p12FilePw->data)
But further, since the caller allocates those strings, the caller
should free them, not this function. The caller should erase the
strings and free them regardless of whether this function returns
success or failure.
| Assignee | ||
Updated•19 years ago
|
Status: NEW → ASSIGNED
Priority: -- → P2
Target Milestone: --- → 3.11.4
| Assignee | ||
Updated•19 years ago
|
Target Milestone: 3.11.4 → 3.11.8
| Reporter | ||
Comment 2•19 years ago
|
||
please try to complete this for 3.11.7
Target Milestone: 3.11.8 → 3.11.7
| Assignee | ||
Comment 3•19 years ago
|
||
Attachment #263488 -
Flags: review?(nelson)
| Reporter | ||
Comment 4•19 years ago
|
||
Comment on attachment 263488 [details] [diff] [review]
fix to tidy up and free calls
This patch did not address the issues from comment 1 above.
Attachment #263488 -
Flags: review?(nelson) → review-
| Assignee | ||
Comment 5•19 years ago
|
||
I have not been able to get the debugger to catch the double free on Solaris--and it doesn't crash. I have verified that without this patch p12FilePw->data gets freed twice.
Attachment #263488 -
Attachment is obsolete: true
Attachment #263685 -
Flags: review?(nelson)
| Reporter | ||
Comment 6•19 years ago
|
||
Comment on attachment 263685 [details] [diff] [review]
errors in previous patched fixed
>+ if (p1 == NULL) {
>+ PR_Free(p0); /* doesn't this need to be zero'ed first? */
>+ p0 = NULL;
> break;
>+ }
>+ if (PL_strcmp(p0, p1) == 0) {
>+ PORT_Memset(p1, 0, PL_strlen(p1));
>+ PORT_Free(p1);
>+ break;
>+ }
>+ PR_Free(p0); /* see comment below */
>+ PR_Free(p1);
> }
If strings p0 and p1 don't match, odds are good that ONE of them is the password
and the other one is CLOSE to the password. So, both need to be zeroed before
freeing. PORT_ZFree is probably more concise.
There's probably a way to structure this code so that you only need
one place where p0 is conditionally zeroed and freed, and likewise only
one place where p1 is conditionally zeroed and freed.
+ if (slotPw.data != NULL)
+ PORT_Free(slotPw.data); need to be zeroed first?
+ if (p12FilePw.data != NULL)
+ PORT_Free(p12FilePw.data); need to be zeroed first?
Perhaps these should be zeroed as soon as we've used them and no longer need them?
| Assignee | ||
Comment 7•19 years ago
|
||
Attachment #263685 -
Attachment is obsolete: true
Attachment #263788 -
Flags: review?(nelson)
Attachment #263685 -
Flags: review?(nelson)
| Assignee | ||
Comment 8•19 years ago
|
||
(In reply to comment #6)
> (From update of attachment 263685 [details] [diff] [review])
...
>
> There's probably a way to structure this code so that you only need
> one place where p0 is conditionally zeroed and freed, and likewise only
> one place where p1 is conditionally zeroed and freed.
I couldn't find one. I restructured it slightly so p1 is zeroed and freed once.
| Reporter | ||
Comment 9•19 years ago
|
||
Comment on attachment 263788 [details] [diff] [review]
zero all password memory before freeing
r=nelson
Thanks.
Requesting second review from Alexei
Attachment #263788 -
Flags: review?(nelson)
Attachment #263788 -
Flags: review?(alexei.volkov.bugs)
Attachment #263788 -
Flags: review+
Comment 10•19 years ago
|
||
Comment on attachment 263788 [details] [diff] [review]
zero all password memory before freeing
r=alexei.volkov
Any idea why it is needed to have line termination data of secitem pwItem?
> pwItem = SECITEM_AllocItem(NULL, NULL, PL_strlen(p0) + 1);
^^^^^
Looks to me like the line used for password encryption will be a password
and '\n'.
Attachment #263788 -
Flags: review?(alexei.volkov.bugs) → review+
| Assignee | ||
Comment 11•19 years ago
|
||
Checking in cmd/pk12util/pk12util.c;
/cvsroot/mozilla/security/nss/cmd/pk12util/pk12util.c,v <-- pk12util.c
new revision: 1.32.2.2; previous revision: 1.32.2.1
done
Status: ASSIGNED → RESOLVED
Closed: 19 years ago
Resolution: --- → FIXED
| Assignee | ||
Comment 12•19 years ago
|
||
Checking in cmd/pk12util/pk12util.c;
/cvsroot/mozilla/security/nss/cmd/pk12util/pk12util.c,v <-- pk12util.c
new revision: 1.36; previous revision: 1.35
done
on trunk.
You need to log in
before you can comment on or make changes to this bug.
Description
•