Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Firefox Keystore - Parsing Certutil Output

by fixed_1978 (Initiate)
on Jun 06, 2014 at 17:35 UTC ( [id://1089081]=perlquestion: print w/replies, xml ) Need Help??

fixed_1978 has asked for the wisdom of the Perl Monks concerning the following question:

Perl Monks, I am working on a project and need to parse the content's of a user's firefox keystore. My current method is to use the certutil command to generate the output and look for matching lines. e.g.

# certutil -L -d /home/$username/.mozilla/firefox/*.default/ Certificate Nickname Trust Attributes SSL,S/MIME,JAR/XPI CN=$certname,OU=site,O=org,L=city,ST=state,C=US u,u,u CN=Certificate Authority,OU=site,O=org CT,C,C

In my script I basically do something like:

my $command = "certutil -L -d $config{firefox_profile}"; open(OUTPUT , "-|", "$command"); while (my $current = <OUTPUT>){ chomp $current; if ($current =~ /^($certname)/i) { #Do something } }

This works, but I am not happy with it. For this to work, I need to know the certificate name in advance or at least the pattern to do actual work on it and I never capture the certificate name. I would like to be able to dynamically capture the CN and trust level as separate values and place them in a hash. For example:

$cert_hash{CN=$certname,OU=site,O=org,L=city,ST=state,C=US}{trust} = “ +u,u,u”; $cert_hash{CN=Certificate Authority,OU=site,O=org}{trust} = “CT,C,C”;

No clean break exists between the certficate name and the trust level in the certutil output. Additionally, the certificate name is not a fixed length, may or may not have spaces, and may have a different path structures depending. In short, my questions are:

- Is certutil the only way to get the certificate data from firefox's db files or is there a more Perl way to do it?

- If certutil is my only option, is there a clean way to extract the certificate name and the trust level?

Thanks in advance,

Replies are listed 'Best First'.
Re: Firefox Keystore - Parsing Certutil Output
by RonW (Parson) on Jun 06, 2014 at 18:17 UTC

    Not having certutil handy, I don't really understand the sample you included in your post. Off hand, I would expect to extract the name from the CN field, but there are more than 1. Can you post sanitized versions of actual certs?

    As for a more Perlish way, Firefox stores setting, preferences, etc. in a SQLite database. Look at DB::SQLite. Also, it might be easier to examine the DB if you install SQLite and use its generic client to explore the DB.

      I am not trying to parse the actual certificates, just the simple certutil overview output I provided earlier to get the CN and Trust Level.

      However, that is a great idea to use the DB::SQLite module. I will try this and see if I have any success.

      Thanks!

      I tried to generically connect via sqlite3 and was unsuccessful:

      $ sqlite3 cert8.db SQLite version 3.3.6 Enter ".help" for instructions sqlite> .tables Error: file is encrypted or is not a database

      I did some research and it appears that sqlite3 may not be able to communicate with the stored format. However, I think I did find a work around. Basically, if I use the strings command on the cert8.db file, it will dump the contents of the db file on different lines and I can find the certificate names alone on a single from there. So I updated my code to:

      my %certs; my @stored_certs; # Get stored certificates: my $command = "strings $config{firefox_profile}/cert8.db"; open(OUTPUT , "-|", "$command"); while (my $line = <OUTPUT>){ chomp $line; if ($line =~ /CN=/i) { $line =~ s/^!//g; $line =~ s/(^\s+|\s+$)//g; if (! $certs{$line}) { $certs{$line}{stored_in_firefox}++; } } } close OUTPUT; # Get each stores certificate's trust level: $command = "certutil -L -d $config{firefox_profile}"; open(OUTPUT, "-|", "$command"); while (my $line = <OUTPUT>){ chomp $line; push (@stored_certs, $line); } foreach my $cert (sort keys %certs) { foreach my $line (@stored_certs) { if ($line =~ /^$cert/) { $line =~ s/^$cert//; $line =~ s/(^\s+|\s+$)//; $lcerts{$cert}{trust_level} = $line; } } }

      I think this is good enough for now. Thanks again,

      I did some more testing and found that the cert8.db file contains old certificate information even if the certificate is not in the certutil output. Additionally, not all of the possible certs start with CN=. So, my test was missing certs and setting certs that were not really in use. So I am back to doing a pattern match to extract the certificate information.

      Now I parse through the certutil output and filter via the following:

      foreach my $line (@certuil_output) { my $cert; my $trust; if ($line =~ /(^$|SSL,S\/MIME,JAR\/XPI|Certificate Nickname)/i) { +next; } if ($line =~ /(.*)\s+(\w+,\w+,\w+)$/) { $cert = $1; $trust = $2 } elsif ($line =~ /(.*)\s+,,\s+$/) { $cert = $1; $trust = “,,”; } else { print “Unmatched line: $line\n”; } if ($cert && $trust) { print "$cert\t$trust\n"; } }

      So unless there is a better way, this is what I have.

Re: Firefox Keystore - Parsing Certutil Output
by taint (Chaplain) on Jun 07, 2014 at 03:39 UTC
    As RonW noted, it's a DB alright, and likely Sqlite3, as Mozilla has been using that for some time.

    But for the sake of [Perl] scripting. I thought it might be helpful -- see; mandatory, to actually know how to use certutil. As it would be otherwise pretty near impossible to respond with anything creative, or of much value. :)
    Mozilla, has apparently hidden the previous link they offered for it's usage. But The WayBack Machine gave me a copy to view. So I'll share it here. :)

    --Chris

    ¡λɐp ʇɑəɹ⅁ ɐ əʌɐɥ puɐ ʻꜱdləɥ ꜱᴉɥʇ ədoH

      The documentation for Firefox's certutil is alive and well at https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Tools/certutil

      I did not have any success with sqlite3, but thanks for the information.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1089081]
Front-paged by Arunbear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others admiring the Monastery: (6)
As of 2024-04-23 18:21 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found