@@ -726,6 +726,28 @@ const internalCertificate = {
726
726
} ) ;
727
727
} ,
728
728
729
+ /**
730
+ * Parse the X509 subject line as returned by the OpenSSL command when
731
+ * invoked with openssl x509 -in <certificate name> -subject -noout
732
+ *
733
+ * @param {String } line emitted from the openssl command
734
+ * @param {String } prefix expected to be removed
735
+ * @return {Object } object containing the parsed fields from the subject line
736
+ */
737
+ parseX509Output : ( line , prefix ) => {
738
+ // Remove the subject= part
739
+ const subject_value = line . slice ( prefix . length ) ;
740
+
741
+ const subject = subject_value . split ( / , (? = (?: (?: [ ^ " ] * " ) { 2 } ) * [ ^ " ] * $ ) / )
742
+ . map ( ( e ) => { return e . trim ( ) . split ( ' = ' , 2 ) ; } )
743
+ . reduce ( ( obj , [ key , value ] ) => {
744
+ obj [ key ] = value . replace ( / ^ " / , '' ) . replace ( / " $ / , '' ) ;
745
+ return obj ;
746
+ } , { } ) ;
747
+
748
+ return subject ;
749
+ } ,
750
+
729
751
/**
730
752
* Uses the openssl command to both validate and get info out of the certificate.
731
753
* It will save the file to disk first, then run commands on it, then delete the file.
@@ -739,28 +761,27 @@ const internalCertificate = {
739
761
return utils . exec ( 'openssl x509 -in ' + certificate_file + ' -subject -noout' )
740
762
. then ( ( result ) => {
741
763
// subject=CN = something.example.com
742
- const regex = / (?: s u b j e c t = ) ? [ ^ = ] + = \s + ( \S + ) / gim ;
743
- const match = regex . exec ( result ) ;
764
+ // subject=C = NoCountry, O = NoOrg, OU = NoOrgUnit, CN = Some Value With Spaces
765
+ const subjectParams = internalCertificate . parseX509Output ( result , 'subject=' ) ;
744
766
745
- if ( typeof match [ 1 ] === 'undefined' ) {
767
+ if ( typeof subjectParams . CN === 'undefined' ) {
746
768
throw new error . ValidationError ( 'Could not determine subject from certificate: ' + result ) ;
747
769
}
748
770
749
- certData [ 'cn' ] = match [ 1 ] ;
771
+ certData [ 'cn' ] = subjectParams . CN ;
750
772
} )
751
773
. then ( ( ) => {
752
774
return utils . exec ( 'openssl x509 -in ' + certificate_file + ' -issuer -noout' ) ;
753
775
} )
754
776
. then ( ( result ) => {
755
777
// issuer=C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
756
- const regex = / ^ (?: i s s u e r = ) ? ( .* ) $ / gim;
757
- const match = regex . exec ( result ) ;
778
+ const issuerParams = internalCertificate . parseX509Output ( result , 'issuer=' ) ;
758
779
759
- if ( typeof match [ 1 ] === 'undefined' ) {
780
+ if ( typeof issuerParams . CN === 'undefined' ) {
760
781
throw new error . ValidationError ( 'Could not determine issuer from certificate: ' + result ) ;
761
782
}
762
783
763
- certData [ 'issuer' ] = match [ 1 ] ;
784
+ certData [ 'issuer' ] = issuerParams . CN ;
764
785
} )
765
786
. then ( ( ) => {
766
787
return utils . exec ( 'openssl x509 -in ' + certificate_file + ' -dates -noout' ) ;
0 commit comments