プログラムを使用して SSL 証明書を Internet Information Server (IIS) にインストールする方法

この資料は、アーカイブされました。これは "現状のまま" で提供され、更新されることはありません。
重要 : この資料には、メタベースの編集方法が記載されています。万一に備えて、編集の前には必ずバックアップ コピーを作成して、復元できるようにしてください。バックアップ方法の詳細については、Microsoft 管理コンソール (MMC) のヘルプで「メタベースのバックアップと復元の方法」を参照してください。
概要

この資料では、プログラムを使用して、Internet Information Server (IIS) で SSL (Secure Sockets Layer) 証明書を作成してインストールする方法について手順を追って説明します。IIS 4.0 および IIS 5.0 では、SSL サーバー証明書を作成してインストールするためのユーザー インターフェイスが提供されていますが、この作業をプログラムを使用して行うこともできます。

先頭に戻る

SSL 証明書を作成してインストールする手順

プログラムを使用して、IIS サーバーで SSL 証明書を作成してインストールするには、次の手順を実行します。
  1. 証明機関にサーバー証明書発行の要求を送信する必要があります。既に証明書がある場合は、それを IIS サーバーのファイルに保存します。要求は送信しないようにします。
  2. 証明書を適切な証明書ストアにインポートします。
  3. 手順 1. で取得した証明書が使用されるように IIS を構成します。

先頭に戻る

IIS を構成して、SSL 証明書を作成してインストールする

警告 : メタベースを誤って編集すると、深刻な問題が発生することがあります。最悪の場合、メタベースを使用するすべての製品の再インストールが必要になることがあります。マイクロソフトは、メタベースの誤った編集により発生した問題に関しては、一切責任を負わないものとします。メタベースの編集は、自己の責任において行ってください。

: メタベースを編集する前に、メタベースのバックアップを必ず作成してください。以下の手順を使用して、IIS を構成し、SSL 証明書を作成してインストールします。
  1. Microsoft Windows Crypto API を使用して、証明書の Thumbprint プロパティを取得します。
  2. IIS メタベースのプロパティ SSLCertHash を、Thumbprint の値に設定する必要があります。
  3. IIS メタベースのプロパティ SSLStoreName を、使用するストアに設定する必要があります。
証明書の拇印 (Thumbprint) を取得して、SSLCertHash プロパティを取得するサンプル コードについては、以下の箇所を参照してください。
サーバー認証証明書の拇印 (Thumbprint) を取得する C コード
メタベースに SSLCertHash プロパティを設定する C コード

先頭に戻る

特定の Web サイトで SSL を有効にする手順

「IIS を構成して、SSL 証明書を作成してインストールする」の手順を実行すると、特定のサイトまたは特定のフォルダで SSL を有効にできます。これを行うには、使用するフォルダの SSL オプションを有効にする必要があります。以下の手順は、「IIS を構成して、SSL 証明書を作成してインストールする」で概要を説明した各手順に対応しています。
  1. CEnroll::createPKCS10() メソッドを呼び出すと、証明書の要求が作成されます。その使用目的を以下の事前定義済みの値 szOID_PKIX_KP_SERVER_AUTH に設定します。
    #define szOID_PKIX_KP_SERVER_AUTH       "1.3.6.1.5.5.7.3.1"		
  2. ICertRequest::Submit () メソッドを呼び出すと、証明書の要求が証明機関に送信されます。
  3. 証明機関から証明書が取得され、適切なストアにインストールされます。IIS のサーバー証明書ウィザードでは、ローカル コンピュータの証明書ストアでサーバー認証に使用できる証明書だけが検索されます。


先頭に戻る

IIS を構成する手順

証明書をストアに保存した後で、IIS を以下のように構成する必要があります。
  1. CertGetCertificateContextProperty() メソッドを使用して、Thumbprint プロパティと CERT_HASH_PROP_ID プロパティの値を取得します。CertGetCertificateContextProperty() 関数で CryptHashCertificate() メソッドが使用されて、CERT_HASH_PROP_ID プロパティの値が計算されます。HASH 値が存在しない場合、CertGetCertificateContextProperty() は SHA1 アルゴリズムを返します。
  2. Web サイトに対応するバイナリ メタベースのプロパティ SSLCertHash を新規作成する必要があります。SSLCertHash を、上記の手順 1. で取得した証明書の拇印 (Thumbprint) に設定します。スキーマで SSLCertHash プロパティがバイナリ データではなく誤って拡張ヌル終端文字列として指定されると、IIS Admin Objects を使用して SSLCertHash をインポートできません。この値をインポートするには、IIS Admin Base オブジェクトが必要です。SSLCertHash を IIS Admin Base オブジェクトで使用するには、10 進の値 5506 を使用する必要があります。
  3. 対応する Web サイトの新規文字列のメタベース プロパティ SSLStoreName を作成する必要があります。SSLStoreName を文字列 MY の値に設定します。SSLStoreName は、(ADSI スクリプトなどで) IIS Admin オブジェクトを使用するか、または、IIS Admin Base オブジェクトを使用して設定できます。SSLStoreName を IIS Admin Base オブジェクトで使用するには、10 進の値 5511 を使用します。


先頭に戻る

サーバー認証証明書の拇印 (Thumbprint) を取得する C コード

次の Microsoft C コードは、サーバー認証証明書の Thumbprint プロパティの取得方法を示したものです。
#include <stdio.h>#include <windows.h>#include <wincrypt.h>#define MY_TYPE  (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)//--------------------------------------------------------------------//    Define the name of the store where the needed certificate//    can be found. #define CERT_STORE_NAME  L"MY"//--------------------------------------------------------------------//   Declare local functions.//   Local function definitions follow main.void HandleError(char *s);void main(void){//--------------------------------------------------------------------// Declare and initialize local variables. // This includes initializing a pointer to the message. // Usually, the message will exist somewhere and a pointer will// be passed to the application.//--------------------------------------------------------------------// System store handleHCERTSTORE hStoreHandle;   //--------------------------------------------------------------------// Pointer to a certificatePCCERT_CONTEXT pCert;PCCERT_CONTEXT pPrevCert; LPBYTE pEncodedBytes = NULL;LPBYTE pHash;DWORD cbData, i;//--------------------------------------------------------------------// Open a certificate store.if ( !( hStoreHandle = CertOpenStore(   CERT_STORE_PROV_SYSTEM,   0,   NULL,   CERT_SYSTEM_STORE_LOCAL_MACHINE,   CERT_STORE_NAME))){     HandleError("The MY store could not be opened.");}pPrevCert = NULL;for (; ((pCert = CertEnumCertificatesInStore(hStoreHandle, pPrevCert)) 	                                         != NULL);    pPrevCert = pCert){    CERT_ENHKEY_USAGE *pKeyUsage;    DWORD j, nLen;    BOOL bFound = FALSE;    char certName[1024];    nLen = sizeof(certName);    certName[0] = 0;    if (CertNameToStr(MY_TYPE, &(pCert->pCertInfo->Subject),        CERT_X500_NAME_STR,        certName,        sizeof(certName)))    {        printf("Checking %s certificate\n", certName);    }    cbData = 0;    if (!CertGetEnhancedKeyUsage(pCert,        0,        NULL,        &cbData) || cbData == 0)    {        if (GetLastError() == CRYPT_E_NOT_FOUND)        {            printf("%s certificate is for all key usages\n", certName);            break;        }        else            printf("CertGetEnhancedKeyUsage failed with error code : %08X\n",                GetLastError());    }    pKeyUsage = (CERT_ENHKEY_USAGE *)        HeapAlloc(GetProcessHeap(), 0, cbData);    if (pKeyUsage == NULL)    {        printf("HeapAlloc failed with error code : %08X\n",            GetLastError());        HandleError("Certificate not found.");    }    if (!CertGetEnhancedKeyUsage(pCert,        0,        pKeyUsage,        &cbData))    {        if (GetLastError() == CRYPT_E_NOT_FOUND)        {            printf("%s certificate is for all key usages\n", certName);            HeapFree(GetProcessHeap(), 0, pKeyUsage);            break;        }        else        {            printf("CertGetEnhancedKeyUsage failed with error code : %08X\n",                GetLastError());            HeapFree(GetProcessHeap(), 0, pKeyUsage);            continue;        }    }    if (pKeyUsage->cUsageIdentifier == 0)    {        printf("%s certificate is for all key usages\n", certName);        HeapFree(GetProcessHeap(), 0, pKeyUsage);        break;    }    bFound = FALSE;    for (j = 0; j < pKeyUsage->cUsageIdentifier; j++)    {        if (strcmpi(pKeyUsage->rgpszUsageIdentifier[j], 			        szOID_PKIX_KP_SERVER_AUTH) == 0)        {            printf("%s certificate is for Server Authentication\n", 				   certName);            bFound = TRUE;            break;        }    }    HeapFree(GetProcessHeap(), 0, pKeyUsage);    if (bFound)        break;}if (pCert == NULL)   HandleError("Certificate not found.");if (pPrevCert){    CertFreeCertificateContext(pPrevCert);    pPrevCert = NULL;}/// CASE 2 Get the hash from the certificatepHash = NULL;cbData = 0;CertGetCertificateContextProperty(pCert, CERT_HASH_PROP_ID, NULL, &cbData);if (cbData == 0){   HandleError("CertGetCertificateContextProperty 1 failed");}pHash = (LPBYTE)HeapAlloc(GetProcessHeap(), 0, cbData);if (pHash == NULL){   HandleError("HeapAlloc failed");}if (!CertGetCertificateContextProperty(pCert, CERT_HASH_PROP_ID, pHash, 	                                   &cbData)){   HandleError("CertGetCertificateContextProperty 2 failed");}printf("CERT_HASH_PROP_ID Length is %d\n", cbData);printf("CERT_HASH_PROP_ID BYTES [", cbData);for (i = 0; i < cbData; i++){    printf("%02X", pHash[i]);}printf("]\n");//--------------------------------------------------------------------// Clean up and free memory.if (pEncodedBytes)    HeapFree(GetProcessHeap(), 0, pEncodedBytes);if (pHash)    HeapFree(GetProcessHeap(), 0, pHash);if(pCert)     CertFreeCertificateContext(pCert);if(CertCloseStore(      hStoreHandle,       CERT_CLOSE_STORE_CHECK_FLAG)){    printf("The store closed and all certificates are freed. \n");}else{    printf("Store closed -- \n"          "not all certificates, CRLs or CTLs were freed");}} // End of main//--------------------------------------------------------------------//  This example uses the function HandleError, a simple error//  handling function, to print an error message to the standard error //  (stderr) file and exit the program. //  For most applications, replace this function with one //  that does more extensive error reporting.void HandleError(char *s){    fprintf(stderr,"An error occurred in running the program. \n");    fprintf(stderr,"%s\n",s);    fprintf(stderr, "Error number %x.\n", GetLastError());    fprintf(stderr, "Program terminating. \n");    exit(1);} // End of HandleError


先頭に戻る

メタベースに SSLCertHash プロパティを設定する C コード

次のサンプル コードは、IIS Admin Base オブジェクトを使用して SSLCertHash メソッドをメタベースに設定する方法を示したものです。次のコードでは、任意のバイナリ配列を証明書の拇印 (Thumbprint) として使用しています。実際のコードでは、「サーバー認証証明書の拇印 (Thumbprint) を取得する C コード」のコードを実行して取得した Thumbprint 値を使用します。コンパイル時に SetData メソッドを定義した方法によって、SSLCertHash を設定することも、(既に Web サイトで SSL を構成済みの場合は) 既存の SSLCertHash を取得することもできます。SSLCertHash メソッドは、既存の CertHash を返します。
#define UNICODE // unicode must be defined for Metabase access#define INITGUID #include <windows.h>#include <httpfilt.h>#include <stdio.h> #define SETDATA#include <iadmw.h>    // COM Interface header #include <iiscnfg.h>  // MD_ & IIS_MD_ #defines extern "C" wmain (int argc, TCHAR ** argv){  	IMSAdminBase  *pIMeta;  	METADATA_HANDLE MyHandle;     HRESULT hres;   	METADATA_RECORD record = {0};    TCHAR szError [2048];	BYTE *myData=NULL;    DWORD dwSize = sizeof (record); 	DWORD i;	// this just a sample of some thumbprint	BYTE bar[]={0x24, 0xC6, 0xBA, 0xBB, 0x81, 0x76, 0x05, 0xC9, 0xC3, 		        0x97, 0x6D, 0x4D, 0xEB, 0x85, 0x8F, 0x4F, 0xBF, 0x38,				0xFD};            CoInitialize (NULL);        // get a pointer to the IIS Admin Base Object	hres = CoCreateInstance(CLSID_MSAdminBase, NULL, CLSCTX_ALL, 			IID_IMSAdminBase, (void **) &pIMeta);  	if (FAILED(hres))  	{	    wsprintf (szError, L"CoCreateInstance Failed. Error: %x\n", hres);        printf ("%S\n", szError);		CoUninitialize();        return TRUE;  	}        // for this test use only 1st server instance    hres = pIMeta->OpenKey(METADATA_MASTER_ROOT_HANDLE, L"/LM", 		METADATA_PERMISSION_READ|METADATA_PERMISSION_WRITE, 20, &MyHandle); 	if (FAILED (hres) )	{		wsprintf (szError, L"OpenKey Failed. Error: %x\n", hres);        printf ("%S\n", szError);		goto clean;	}    	// SSLCertHash = 5506	record.dwMDIdentifier =  5506;    record.dwMDAttributes =METADATA_INHERIT;    record.dwMDUserType=IIS_MD_UT_SERVER;    record.dwMDDataType= BINARY_METADATA;    record.pbMDData = (unsigned char *) myData;#ifndef SETDATA#pragma message ("Building for GetData\n")    	again:    hres = pIMeta->GetData (MyHandle,argv[1], &record, &dwSize);   	if (FAILED (hres) )	{		if (hres == MD_ERROR_DATA_NOT_FOUND)		{			printf ("%S\n", L"Data not found, no certificate is set!");			goto clean;		}		else if (HRESULT_CODE(hres)==ERROR_INSUFFICIENT_BUFFER)		{			record.dwMDDataLen=dwSize;			myData = (LPBYTE)HeapAlloc(GetProcessHeap(), 0, dwSize);			record.pbMDData  = (unsigned char *)myData;		    goto again;		}		else  		{			wsprintf (szError, L"GetData Failed. Error: %x\n", hres);			printf ("%S\n", szError);			goto clean;;		}	}	printf ("%S", L"Got thumbprint. You can compare" 		          L" it with the MMC for IIS value:\n");		for ( i=0; i<(record.dwMDDataLen/sizeof (BYTE)); i++)				printf ("%2X ", myData[i]);  	HeapFree(GetProcessHeap(), 0, myData);#else#pragma message ("Building for SetData\n")		record.pbMDData = bar;	record.dwMDDataLen = 19; // in real code it should be the size                                                    // of the thumbprint buffer	hres = pIMeta->SetData (MyHandle,argv[1], &record);	if (FAILED (hres) )	{		printf ("Set data failed: 0x%x!\n", hres);		goto clean;	}	else		printf ("New thumbprint is set\n");#endifclean:	pIMeta->CloseKey(MyHandle); 	pIMeta->SaveData();	pIMeta->Release();	CoUninitialize();	return 1;}


先頭に戻る
関連情報
関連情報を参照するには、以下の「サポート技術情報」 (Microsoft Knowledge Base) をクリックしてください。
315588 クライアント側の証明書を使用して ASP.NET アプリケーションをセキュリティで保護する方法

先頭に戻る
プロパティ

文書番号:313624 - 最終更新日: 12/07/2015 08:14:55 - リビジョン: 2.1

Microsoft Internet Information Server 4.0, Microsoft Internet Information Services 5.0

  • kbnosurvey kbarchive kbcrypt kbapi kbhowtomaster kbsecurity kbisapiext kbhowto KB313624
フィードバック