Cert deleted before revocation - how to reimport?



  • Hello,

    pfsense 2.0.3

    We're in a situation whereby a user cert was deleted before it was revoked.  I was able to retrieve the key and cert from a backup config.xml however I haven't been able to figure out how to reintroduce it to the system.

    JimP kindly helped the following users in a similar situation and recommended that they import the certificate back into the system then revoke it.
    https://forum.pfsense.org/index.php?topic=71016.0
    https://forum.pfsense.org/index.php?topic=65035.0

    My attempts to do the same have resulted in the cert showing up with the 'issuer' field saying 'self-signed' instead of our on-box cert authority, meaning that the CRL settings do not show the cert as being available for revocation.  The 'distinguished name' field is empty.  This happens when I add the key in the user setup or when I add the key in 'system->cert manager->certificates'.

    I'd welcome any pointers.

    Simon



  • You'll have to manually put that chunk of the XML back into the config, otherwise it won't have that association. Open your backup with the cert in a text editor and find that part from <cert>to</cert> . Open a new backup, and paste that part in, save and restore.

    Best to restore that to a test VM to make sure you got the XML correct. If it shows up fine in the test VM, then restore it to your production system.



  • Thanks Chris, I'll give it a go.  I can see that the content has supporting markup around it:

    
                    <refid>510xxxxxxxxxx</refid>
    
                    <caref>4f3xxxxxxxxxx</caref>
    
    

    If I didn't have the XML contents and only had the end user cert as published by the client export utility, would I be in trouble on the grounds that I don't have access to these values?  I would imagine that I would have to replicate the CA on another machine and create the CRL with openssl on the command line against the cert, then import it as a third party CRL.  If so, would I have to use that new machine as my CRL generator going forward?

    I ask because we were lucky this time.  We're taking on more admins this month and this is bound to happen again.  I just want to be sure what the impact will be.

    With thanks,

    Simon


  • Rebel Alliance Developer Netgate

    If you import that cert/key (System > Cert Manager, Certs tab, +, import) it should locate the proper CA and fix the caref. The certref is OK to ignore since it will get a new one and it must not have been referenced anywhere since you were able to delete it.



  • I must be doing something wrong.  My imports on that screen from a known good cert that has been deleted but not revoked result in:

    Name: testuser2134
    Issuer: self-signed
    Distinguished Name: [blank]
    In Use: [blank]

    It doesn't show up in the list of certs available for revocation, either.  I'd say I must be missing something obvious. Again, this is 2.0.3 so if this is a quirk that was resolved in a later release I'll go the route that was suggested by Chris.

    Simon

    BTW, for other people's information, if you find yourself in a position where you have to decrypt a selection of password-protected config files outside of the pfSense environment, the following one-liner works for me on a Linux box (where base64 is provided by coreutils):

    # for i in config-*.xml; do echo $i; grep -v ^---- $i > $i.nomarkup; base64 -d < $i.nomarkup > $i.enc; /usr/bin/openssl enc -d -aes-256-cbc -in $i.enc -out $i.decrypted.xml -k YourPassword; done
    

    Where YourPassword is the password used to encrypt the config when downloading from pfSense.

    S.


  • Rebel Alliance Developer Netgate

    @sgb:

    Issuer: self-signed
    […]
    It doesn't show up in the list of certs available for revocation, either.  I'd say I must be missing something obvious. Again, this is 2.0.3 so if this is a quirk that was resolved in a later release I'll go the route that was suggested by Chris.

    It doesn't show in the list because it didn't get associated with the right CA for some reason. You could manually edit the config.xml and add the right caref to the cert if nothing else.

    @sgb:

    # for i in config-*.xml; do echo $i; grep -v ^---- $i > $i.nomarkup; base64 -d < $i.nomarkup > $i.enc; /usr/bin/openssl enc -d -aes-256-cbc -in $i.enc -out $i.decrypted.xml -k YourPassword; done
    

    For one config I prefer this:

    cat config-enc.xml | sed -e '1d' -e '$d' | base64 -d | openssl enc -d -aes-256-cbc -out config-dec.xml -k 'xxxx'
    

    Use pipes and no need to write the temp files in between.



  • Thanks Jimp, much cleaner :-).

    You could probably do a job on this too.  It's a (very) basic perl script to identify user certs in a config.xml and dump them to separate files to make it easier to reintroduce a particular cert to the config.xml.  I'm putting it here in case it's useful to someone else.  It makes heavy assumptions about the config.xml structure and I don't know what quotemeta will do on a windows box so YMMV.  Written for clarity rather than efficiency.

    
    #!/usr/bin/perl
    use strict;
    use warnings;
    
    ## pfSenseUserCertDumper.pl
    ## Script to pull out user certs from a pfsense config backup.
    ## use as follows:
    ##
    ## perl pfSenseUserCertDumper.pl config.xml
    ## 
    ## Output will be of the form certref.certdescription.usercert
    ## No provision has been made for multiple arguments
    
    my $line;
    my $cachecontents;
    my $certrefid;
    my $certdesc;
    my $certdumpfile;
    my $certdumpcontents;
    my $isusercert;
    
    my $filename = $ARGV[0];
    
    open FILE,"<$filename" or die "Cannot read the file $filename: $!\n";
    
    while ($line = <file>)
    {
        if ($certdumpcontents)
        {
           # We are capturing contents, so append
           $certdumpcontents.=$line;
            if ($line =~ m/\<refid\>(.*?)\<\/refid\>\n/)
            {
                    # Capture cert ref for dump filename
                    $certrefid =  $1;
            }
            if ($line =~ m/[CDATA[(.*?)]/)
            {
                    # Capture cert desc for dump filename, quotemeta to deal with 
                    # special characters
                    $certdesc = quotemeta $1;
            }
            if ($line =~ m/\<type\>user\<\/type\>\n/)
            {
                    # Not interested in non-user certs.  Set flag if user cert.
                    $isusercert=1;
            }
        }
        if ($line =~ m/\<cert\>\n/)
        {
            # Start of a cert.  Start capturing.
            $certdumpcontents.=$line;
        }
        if ($line =~ m/\<\/cert\>\n/ && $certdumpcontents)
        {
            # End of cert data.
            if ($isusercert)
                    {
                            $certdumpfile=$certrefid.'.'.$certdesc.'.usercert';
                            open CERTDUMPFILE, ">$certdumpfile";
                            print CERTDUMPFILE "$certdumpcontents";
                            close CERTDUMPFILE;
                            # Job done, turn off isusercert flag
                            undef $isusercert;
                    }
            # Clear assigned variables ahead of next cert. 
            undef $certdumpfile;
            undef $certrefid;
            undef $certdesc;
            undef $certdumpcontents;
        }
    }</cert\></type\></refid\></file> 
    

    Thanks again,

    Simon


Log in to reply