Jeff Sanders Technical Blog

I am a Microsoft employee that has worked on all aspects of the Web Stack for a long time. I hope these blogs are useful to you! Use this information at your own risk.


<< Go Back

Understanding The New Wininet Option Internet_option_server_cert_chain_context

- 05 Jun 2009

With the release of Internet Explorer 8 comes a new option you can query for with programming with the WinInet APIs: INTERNET_OPTION_SERVER_CERT_CHAIN_CONTEXT.  The MSDN documentation tells you it allows you to get the PCCERT\_CHAIN\_CONTEXT, and not much more.  It does not show you how to properly get the Context.  I like to see things in action so here is some sample code.

This option is documented here: http://msdn.microsoft.com/en-us/library/aa385328(VS.85).aspx (note that if you are not using the latest SDK headers, the value for this option is also documented here).

To sum it up, use this option to get the Server Certificate Chain Context  to use with other Crypto API functions  To understand this option you can modify the HttpDump example in the Platforms SDK and see how this option can be used.   Since this is an option for the request you get this option using the request handle after you execute the request.  I am not a Crypto API guru so I stole some code examples from MSDN just to dump out some information about the Certificate Chain. 
 
The most important (and undocumented) part of getting this option is to pass a Pointer to a  PCCERT\_CHAIN\_CONTEXT.  Below is a code snippet that I added to the HttpDump sample in the Windows 7 SDK (RC).

First, there is a problem with that sample when compiled for unicode.  I fixed it with this replacement code:

C++ code listing for sample (Copy Code):<div id=certctxcode1 style="BACKGROUND-COLOR: #e0e0e0">

dwSize=0;
TCHAR *myBuff = NULL;

</font><font color=#008000 size=2><font color=#008000 size=2>

// First time we will find out the size of the headers.
</font></font>HttpQueryInfo (hReq,HTTP\_QUERY\_RAW\_HEADERS\_CRLF, NULL, &dwSize, NULL); myBuff = <font color=#0000ff size=2><font color=#0000ff size=2>new</font></font> TCHAR [dwSize+1]; <font color=#008000 size=2><font color=#008000 size=2>// Now we call HttpQueryInfo again to get the headers.
</font></font><font color=#0000ff size=2><font color=#0000ff size=2>if</font></font> (!HttpQueryInfo (hReq,HTTP\_QUERY\_RAW\_HEADERS\_CRLF, (LPVOID) myBuff, &dwSize, NULL)) {     ErrorOut (GetLastError(), TEXT(<font color=#a31515 size=2><font color=#a31515 size=2>“HttpQueryInfo”</font></font>)); } <font color=#0000ff size=2><font color=#0000ff size=2>else
</font></font>{     *(myBuff + dwSize) = <font color=#a31515 size=2><font color=#a31515 size=2>‘\0’</font></font>;     wcout << myBuff << endl; }

<font color=#0000ff size=2><font color=#0000ff size=2>delete</font></font> myBuff;</div>

Next I added this code just before closing the request handle ( ‘<font color=#0000ff size=2><font color=#0000ff size=2>if

</font> (!InternetCloseHandle (hReq) )’ ).

</font></font>

C++ code listing for sample (Copy Code):<div id=certctxcode2 style="BACKGROUND-COLOR: #e0e0e0"></p>

PCCERT_CHAIN_CONTEXT CertCtx=NULL;
DWORD cbCertSize = </font><font color=#0000ff size=2><font color=#0000ff size=2>sizeof</font></font>(&CertCtx);

</font><font color=#008000 size=2><font color=#008000 size=2>

//GetCertificate information
</font></font><font color=#0000ff size=2><font color=#0000ff size=2>if</font></font> (InternetQueryOption(hReq,INTERNET\_OPTION\_SERVER\_CERT\_CHAIN_CONTEXT ,(LPVOID)&CertCtx,&cbCertSize)) { <font color=#008000 size=2><font color=#008000 size=2>//—————————————————————
</font></font><font color=#008000 size=2><font color=#008000 size=2>// Display some of the contents of the chain.
</font></font>PCCERT\_CHAIN\_CONTEXT pChainContext=CertCtx; printf(<font color=#a31515 size=2><font color=#a31515 size=2>“The size of the chain context </font></font><font color=#a31515 size=2><font color=#a31515 size=2>is %d. \n”</font></font>,pChainContext->cbSize); printf(<font color=#a31515 size=2><font color=#a31515 size=2>“%d simple chains found.\n”</font></font>,pChainContext->cChain); printf(<font color=#a31515 size=2><font color=#a31515 size=2>“\nError status for the chain:\n”</font></font>); <font color=#0000ff size=2><font color=#0000ff size=2>switch</font></font>(pChainContext->TrustStatus.dwErrorStatus) { <font color=#0000ff size=2><font color=#0000ff size=2>case</font></font> CERT\_TRUST\_NO_ERROR : printf(<font color=#a31515 size=2><font color=#a31515 size=2>“No error found for this certificate or chain.\n”</font></font>); <font color=#0000ff size=2><font color=#0000ff size=2>break</font></font>; <font color=#0000ff size=2><font color=#0000ff size=2>case</font></font> CERT\_TRUST\_IS\_NOT\_TIME_VALID: printf(<font color=#a31515 size=2><font color=#a31515 size=2>“This certificate or one of the certificates in the </font></font><font color=#a31515 size=2><font color=#a31515 size=2>certificate chain is not time-valid.\n”</font></font>); <font color=#0000ff size=2><font color=#0000ff size=2>break</font></font>; <font color=#0000ff size=2><font color=#0000ff size=2>case</font></font> CERT\_TRUST\_IS\_NOT\_TIME_NESTED: printf(<font color=#a31515 size=2><font color=#a31515 size=2>“Certificates in the chain are not properly </font></font><font color=#a31515 size=2><font color=#a31515 size=2>time-nested.\n”</font></font>); <font color=#0000ff size=2><font color=#0000ff size=2>break</font></font>; <font color=#0000ff size=2><font color=#0000ff size=2>case</font></font> CERT\_TRUST\_IS_REVOKED: printf(<font color=#a31515 size=2><font color=#a31515 size=2>“Trust for this certificate or one of the certificates </font></font><font color=#a31515 size=2><font color=#a31515 size=2>in the certificate chain has been revoked.\n”</font></font>); <font color=#0000ff size=2><font color=#0000ff size=2>break</font></font>; <font color=#0000ff size=2><font color=#0000ff size=2>case</font></font> CERT\_TRUST\_IS\_NOT\_SIGNATURE_VALID: printf(<font color=#a31515 size=2><font color=#a31515 size=2>“The certificate or one of the certificates in the </font></font><font color=#a31515 size=2><font color=#a31515 size=2>certificate chain does not have a valid signature.\n”</font></font>); <font color=#0000ff size=2><font color=#0000ff size=2>break</font></font>; <font color=#0000ff size=2><font color=#0000ff size=2>case</font></font> CERT\_TRUST\_IS\_NOT\_VALID\_FOR\_USAGE: printf(<font color=#a31515 size=2><font color=#a31515 size=2>“The certificate or certificate chain is not valid </font></font><font color=#a31515 size=2><font color=#a31515 size=2>in its proposed usage.\n”</font></font>); <font color=#0000ff size=2><font color=#0000ff size=2>break</font></font>; <font color=#0000ff size=2><font color=#0000ff size=2>case</font></font> CERT\_TRUST\_IS\_UNTRUSTED\_ROOT: printf(<font color=#a31515 size=2><font color=#a31515 size=2>“The certificate or certificate chain is based </font></font><font color=#a31515 size=2><font color=#a31515 size=2>on an untrusted root.\n”</font></font>); <font color=#0000ff size=2><font color=#0000ff size=2>break</font></font>; <font color=#0000ff size=2><font color=#0000ff size=2>case</font></font> CERT\_TRUST\_REVOCATION\_STATUS\_UNKNOWN: printf(<font color=#a31515 size=2><font color=#a31515 size=2>“The revocation status of the certificate or one of the </font></font><font color=#a31515 size=2><font color=#a31515 size=2>certificates in the certificate chain is unknown.\n”</font></font>); <font color=#0000ff size=2><font color=#0000ff size=2>break</font></font>; <font color=#0000ff size=2><font color=#0000ff size=2>case</font></font> CERT\_TRUST\_IS_CYCLIC : printf(<font color=#a31515 size=2><font color=#a31515 size=2>“One of the certificates in the chain was issued by a </font></font><font color=#a31515 size=2><font color=#a31515 size=2>certification authority that the original certificate </font></font><font color=#a31515 size=2><font color=#a31515 size=2>had certified.\n”</font></font>); <font color=#0000ff size=2><font color=#0000ff size=2>break</font></font>; <font color=#0000ff size=2><font color=#0000ff size=2>case</font></font> CERT\_TRUST\_IS\_PARTIAL\_CHAIN: printf(<font color=#a31515 size=2><font color=#a31515 size=2>“The certificate chain is not complete.\n”</font></font>); <font color=#0000ff size=2><font color=#0000ff size=2>break</font></font>; <font color=#0000ff size=2><font color=#0000ff size=2>case</font></font> CERT\_TRUST\_CTL\_IS\_NOT\_TIME\_VALID: printf(<font color=#a31515 size=2><font color=#a31515 size=2>“A CTL used to create this chain was not time-valid.\n”</font></font>); <font color=#0000ff size=2><font color=#0000ff size=2>break</font></font>; <font color=#0000ff size=2><font color=#0000ff size=2>case</font></font> CERT\_TRUST\_CTL\_IS\_NOT\_SIGNATURE\_VALID: printf(<font color=#a31515 size=2><font color=#a31515 size=2>“A CTL used to create this chain did not have a valid </font></font><font color=#a31515 size=2><font color=#a31515 size=2>signature.\n”</font></font>); <font color=#0000ff size=2><font color=#0000ff size=2>break</font></font>;
<font color=#0000ff size=2><font color=#0000ff size=2>case</font></font> CERT\_TRUST\_CTL\_IS\_NOT\_VALID\_FOR_USAGE: printf(<font color=#a31515 size=2><font color=#a31515 size=2>“A CTL used to create this chain is not valid for this </font></font><font color=#a31515 size=2><font color=#a31515 size=2>usage.\n”</font></font>); } <font color=#008000 size=2><font color=#008000 size=2>// End switch

</font></font>

printf(</font><font color=#a31515 size=2><font color=#a31515 size=2>“\nInfo status for the chain:\n”</font></font>); <font color=#0000ff size=2><font color=#0000ff size=2>switch</font></font>(pChainContext->TrustStatus.dwInfoStatus) { <font color=#0000ff size=2><font color=#0000ff size=2>case</font></font> 0: printf(<font color=#a31515 size=2><font color=#a31515 size=2>“No information status reported.\n”</font></font>); <font color=#0000ff size=2><font color=#0000ff size=2>break</font></font>; <font color=#0000ff size=2><font color=#0000ff size=2>case</font></font> CERT\_TRUST\_HAS\_EXACT\_MATCH_ISSUER : printf(<font color=#a31515 size=2><font color=#a31515 size=2>“An exact match issuer certificate has been found for </font></font><font color=#a31515 size=2><font color=#a31515 size=2>this certificate.\n”</font></font>); <font color=#0000ff size=2><font color=#0000ff size=2>break</font></font>; <font color=#0000ff size=2><font color=#0000ff size=2>case</font></font> CERT\_TRUST\_HAS\_KEY\_MATCH_ISSUER: printf(<font color=#a31515 size=2><font color=#a31515 size=2>“A key match issuer certificate has been found for this </font></font><font color=#a31515 size=2><font color=#a31515 size=2>certificate.\n”</font></font>); <font color=#0000ff size=2><font color=#0000ff size=2>break</font></font>; <font color=#0000ff size=2><font color=#0000ff size=2>case</font></font> CERT\_TRUST\_HAS\_NAME\_MATCH_ISSUER: printf(<font color=#a31515 size=2><font color=#a31515 size=2>“A name match issuer certificate has been found for this </font></font><font color=#a31515 size=2><font color=#a31515 size=2>certificate.\n”</font></font>); <font color=#0000ff size=2><font color=#0000ff size=2>break</font></font>; <font color=#0000ff size=2><font color=#0000ff size=2>case</font></font> CERT\_TRUST\_IS\_SELF\_SIGNED: printf(<font color=#a31515 size=2><font color=#a31515 size=2>“This certificate is self-signed.\n”</font></font>); <font color=#0000ff size=2><font color=#0000ff size=2>break</font></font>; <font color=#0000ff size=2><font color=#0000ff size=2>case</font></font> CERT\_TRUST\_IS\_COMPLEX\_CHAIN: printf(<font color=#a31515 size=2><font color=#a31515 size=2>“The certificate chain created is a complex chain.\n”</font></font>); <font color=#0000ff size=2><font color=#0000ff size=2>break</font></font>; <font color=#0000ff size=2><font color=#0000ff size=2>case</font></font> CERT\_TRUST\_HAS\_PREFERRED\_ISSUER: printf(<font color=#a31515 size=2><font color=#a31515 size=2>“The certificate chain has a preferred issuer.\n”</font></font>); <font color=#0000ff size=2><font color=#0000ff size=2>break</font></font>; <font color=#0000ff size=2><font color=#0000ff size=2>case</font></font> CERT\_TRUST\_HAS\_ISSUANCE\_CHAIN_POLICY: printf(<font color=#a31515 size=2><font color=#a31515 size=2>“The certificate chain has issuance chain policy.\n”</font></font>); <font color=#0000ff size=2><font color=#0000ff size=2>break</font></font>; <font color=#0000ff size=2><font color=#0000ff size=2>case</font></font> CERT\_TRUST\_HAS\_VALID\_NAME_CONSTRAINTS: printf(<font color=#a31515 size=2><font color=#a31515 size=2>“The certificate chain valid name contraints.\n”</font></font>); <font color=#0000ff size=2><font color=#0000ff size=2>break</font></font>; <font color=#0000ff size=2><font color=#0000ff size=2>case</font></font> CERT\_TRUST\_IS\_PEER\_TRUSTED: printf(<font color=#a31515 size=2><font color=#a31515 size=2>“The certificate chain is peer trusted.\n”</font></font>); <font color=#0000ff size=2><font color=#0000ff size=2>break</font></font>; <font color=#0000ff size=2><font color=#0000ff size=2>case</font></font> CERT\_TRUST\_HAS\_CRL\_VALIDITY_EXTENDED: printf(<font color=#a31515 size=2><font color=#a31515 size=2>“The certificate chain has CRL validity extended.\n”</font></font>); <font color=#0000ff size=2><font color=#0000ff size=2>break</font></font>; <font color=#0000ff size=2><font color=#0000ff size=2>case</font></font> CERT\_TRUST\_IS\_FROM\_EXCLUSIVE\_TRUST\_STORE: printf(<font color=#a31515 size=2><font color=#a31515 size=2>“The certificate chain was found in a store specified by hExclusiveRoot or hExclusiveTrustedPeople.\n”</font></font>); <font color=#0000ff size=2><font color=#0000ff size=2>break</font></font>; } <font color=#008000 size=2><font color=#008000 size=2>// end switch<p mce_keep="true"></font></font>CERT\_SIMPLE\_CHAIN *simpleCertificateChainWithinContext = NULL;

</font><font color=#0000ff size=2><font color=#0000ff size=2>for</font></font> (<font color=#0000ff size=2><font color=#0000ff size=2>int</font></font> i=0; icChain; i++) {     simpleCertificateChainWithinContext=pChainContext->rgpChain[i]; </font><font color=#008000 size=2><font color=#008000 size=2>    // for each certificate chain in this context…     </font></font><font color=#0000ff size=2><font color=#0000ff size=2>for</font></font> (<font color=#0000ff size=2><font color=#0000ff size=2>int</font></font> simpleCertChainIndex = 0;     simpleCertChainIndex < simpleCertificateChainWithinContext->cElement;     simpleCertChainIndex++)     { <font color=#008000 size=2><font color=#008000 size=2></p>

        // get the CertContext from the array
</font></font></font><font color=#008000 size=2><font color=#008000 size=2>        </font></font>PCCERT_CONTEXT pCertContext =         simpleCertificateChainWithinContext->rgpElement[simpleCertChainIndex]->pCertContext;

</font><font color=#008000 size=2><font color=#008000 size=2>        //——————————————————————-
        </font></font><font color=#008000 size=2><font color=#008000 size=2>// Find and print the name of the subject of the certificate
        </font></font><font color=#008000 size=2><font color=#008000 size=2>// just retrieved.
        </font></font>TCHAR pszNameString[256];          <font color=#0000ff size=2><font color=#0000ff size=2>if</font></font>(CertGetNameString(         pCertContext,         CERT\_NAME\_SIMPLE\_DISPLAY\_TYPE,         0,         NULL,         pszNameString,         128))         {             wprintf(L<font color=#a31515 size=2><font color=#a31515 size=2>“Certificate for %s has been retrieved.\n”</font></font>, pszNameString);         }         <font color=#0000ff size=2><font color=#0000ff size=2>else
        </font></font>{             wprintf(L<font color=#a31515 size=2><font color=#a31515 size=2>“CertGetName failed. \n”</font></font>);         }

<font color=#008000 size=2><font color=#008000 size=2>         // Get the issuer now…

</font>        </font><font color=#0000ff size=2><font color=#0000ff size=2>if</font></font>(CertGetNameString( pCertContext,         CERT\_NAME\_SIMPLE\_DISPLAY\_TYPE,         CERT\_NAME\_ISSUER_FLAG,         NULL,         pszNameString,         128))         {             wprintf(L<font color=#a31515 size=2><font color=#a31515 size=2>“Certificate issuer is %s.\n\n”</font></font>, pszNameString);         } <font color=#0000ff size=2><font color=#0000ff size=2>        else
</font></font>        {             wprintf(L<font color=#a31515 size=2><font color=#a31515 size=2>“CertGetName failed. \n”</font></font>);         }     } }

</font><font color=#008000 size=2><font color=#008000 size=2>//important! Free the CertCtx
</font></font>CertFreeCertificateChain(CertCtx); } <font color=#0000ff size=2><font color=#0000ff size=2>else
</font></font>{   ErrorOut (GetLastError(), TEXT(<font color=#a31515 size=2><font color=#a31515 size=2>“HttpQueryInfo”</font></font>));

}

</font></div>

The above code simply illustrates getting the CertContext.  I will leave the actual implementation and usage of this context to all of you Crypto API types!  Please drop me a message if you found this blog useful!<p mce_keep="true"> 

<< Go Back