@@ -115,24 +115,48 @@ static sqInt sqCopyDescToken(sqSSL *ssl, SecBufferDesc sbd, char *dstBuf, sqInt
115115}
116116
117117/* Set up the local certificate for SSL */
118+ #define MAX_NAME_SIZE 4096
118119static sqInt sqSetupCert (sqSSL * ssl , char * certName , int server ) {
119120 SCHANNEL_CRED sc_cred = { 0 };
120121 SECURITY_STATUS ret ;
121122 HCERTSTORE hStore ;
122123 PCCERT_CONTEXT pContext = NULL ;
124+ DWORD dwPropSize ;
125+ WCHAR wFriendlyName [MAX_NAME_SIZE ];
126+ char bFriendlyName [MAX_NAME_SIZE ];
123127
124128 if (certName ) {
125129 hStore = CertOpenSystemStore (0 , "MY" );
126130 if (!hStore ) {
127131 if (ssl -> loglevel ) printf ("sqSetupCert: CertOpenSystemStore failed\n" );
128132 return 0 ;
129133 }
130- pContext = CertFindCertificateInStore (hStore , X509_ASN_ENCODING | PKCS_7_ASN_ENCODING ,
131- 0 , CERT_FIND_SUBJECT_STR_A , certName , NULL );
134+ pContext = NULL ;
135+
136+ /* Enumerate the certificate store to find the cert with the given friendly name */
137+ while (pContext = CertEnumCertificatesInStore (hStore , pContext )) {
138+ if (ssl -> loglevel ) printf ("Checking certificate: " );
139+ dwPropSize = MAX_NAME_SIZE * sizeof (WCHAR );
140+ if (!CertGetCertificateContextProperty (pContext , CERT_FRIENDLY_NAME_PROP_ID , wFriendlyName , & dwPropSize )) {
141+ if (ssl -> loglevel ) printf ("<no friendly name>" );
142+ continue ;
143+ }
144+ if (!WideCharToMultiByte (CP_UTF8 , 0 , wFriendlyName , -1 , bFriendlyName , MAX_NAME_SIZE , NULL , NULL )) {
145+ if (ssl -> loglevel ) printf ("<utf-8 conversion failure>" );
146+ continue ;
147+ }
148+ if (ssl -> loglevel ) printf ("%s\n" , bFriendlyName );
149+ if (strcmp (certName , bFriendlyName ) == 0 ) break ;
150+ }
151+
152+ if (pContext == 0 ) {
153+ /* For compatibility with older versions of SqueakSSL, attempt to match against subject string */
154+ pContext = CertFindCertificateInStore (hStore , X509_ASN_ENCODING | PKCS_7_ASN_ENCODING ,
155+ 0 , CERT_FIND_SUBJECT_STR_A , certName , NULL );
156+ }
132157
133- /* XXXX: Fail? Or just not provide the cert? For now, fail. */
134158 if (!pContext ) {
135- if (ssl -> loglevel ) printf ("sqSetupCert: CertFindCertitficateInStore failed \n" );
159+ if (ssl -> loglevel ) printf ("sqSetupCert: No suitable certificate found \n" );
136160 CertCloseStore (hStore , 0 );
137161 return 0 ;
138162 }
@@ -587,6 +611,9 @@ sqInt sqAcceptSSL(sqInt handle, char* srcBuf, sqInt srcLen, char *dstBuf, sqInt
587611 if (ret != SEC_E_OK ) {
588612 /* Handle various failure conditions */
589613 switch (ret ) {
614+ case SEC_E_INCOMPLETE_MESSAGE :
615+ /* not enough data for the handshake to complete */
616+ return SQSSL_NEED_MORE_DATA ;
590617 case SEC_I_CONTINUE_NEEDED :
591618 /* Send contents back to peer and come back with more data */
592619 return sqCopyDescToken (ssl , ssl -> sbdOut , dstBuf , dstLen );
@@ -779,6 +806,48 @@ char* sqGetStringPropertySSL(sqInt handle, int propID) {
779806 return NULL ;
780807}
781808
809+ /* sqAddPfxCertToStore: Adds a PFX certificate to MY certificate store.
810+ Arguments:
811+ pfxData - the contents of the PFX certificate file
812+ pfxLen - the length of the PFX certificate file
813+ passData - the utf8 encoded password for the file
814+ passLen - the size of the password
815+ Returns: 1 on success, 0 on failure
816+ */
817+ static sqInt sqAddPfxCertToStore (char * pfxData , sqInt pfxLen , char * passData , sqInt passLen ) {
818+ PCCERT_CONTEXT pContext ;
819+ HCERTSTORE pfxStore , myStore ;
820+ CRYPT_DATA_BLOB blob ;
821+ WCHAR widePass [4096 ];
822+
823+ /* Verify that this is a PFX file */
824+ blob .cbData = pfxLen ;
825+ blob .pbData = pfxData ;
826+ if (!PFXIsPFXBlob (& blob )) return 0 ; /* Not a PFX blob */
827+
828+ /* Verify that the password is all right */
829+ widePass [0 ] = 0 ;
830+ if (passLen > 0 ) {
831+ DWORD wideLen = MultiByteToWideChar (CP_UTF8 , 0 , passData , passLen , widePass , 4095 );
832+ widePass [wideLen ] = 0 ;
833+ }
834+ if (!PFXVerifyPassword (& blob , widePass , 0 )) return 0 ; /* Invalid password */
835+
836+ /* Import the PFX blob into a temporary store */
837+ pfxStore = PFXImportCertStore (& blob , widePass , 0 );
838+ if (!pfxStore ) return 0 ;
839+
840+ /* And copy the certificates to MY store */
841+ myStore = CertOpenSystemStore (0 , "MY" );
842+ pContext = NULL ;
843+ while (pContext = CertEnumCertificatesInStore (pfxStore , pContext )) {
844+ CertAddCertificateContextToStore (myStore , pContext , CERT_STORE_ADD_REPLACE_EXISTING , NULL );
845+ }
846+ CertCloseStore (myStore , 0 );
847+ CertCloseStore (pfxStore , 0 );
848+ return 1 ;
849+ }
850+
782851/* sqSetStringPropertySSL: Set a string property in SSL.
783852 Arguments:
784853 handle - the ssl handle
@@ -802,6 +871,9 @@ sqInt sqSetStringPropertySSL(sqInt handle, int propID, char *propName, sqInt pro
802871
803872 switch (propID ) {
804873 case SQSSL_PROP_CERTNAME : ssl -> certName = property ; break ;
874+ /* Platform specific: Adds a .PFX file to MY certificate store w/o password.
875+ Useful for installing the default test certificate in SqueakSSL. */
876+ case 10001 : return sqAddPfxCertToStore (propName , propLen , NULL , 0 );
805877 default :
806878 if (ssl -> loglevel ) printf ("sqSetStringPropertySSL: Unknown property ID %d\n" , propID );
807879 return 0 ;
0 commit comments