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

文書翻訳 文書翻訳
文書番号: 313624 - 対象製品
すべて展開する | すべて折りたたむ

目次

重要 : この資料には、メタベースの編集方法が記載されています。万一に備えて、編集の前には必ずバックアップ コピーを作成して、復元できるようにしてください。バックアップ方法の詳細については、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 handle

HCERTSTORE hStoreHandle;   

//--------------------------------------------------------------------
// Pointer to a certificate

PCCERT_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 certificate
pHash = 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");
#endif

clean:
	pIMeta->CloseKey(MyHandle); 
	pIMeta->SaveData();
	pIMeta->Release();
	CoUninitialize();

	return 1;
}



関連情報

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

プロパティ

文書番号: 313624 - 最終更新日: 2006年8月3日 - リビジョン: 2.1
この資料は以下の製品について記述したものです。
  • Microsoft Internet Information Server 4.0
  • Microsoft Internet Information Services 5.0
キーワード:?
kbcrypt kbapi kbhowtomaster kbsecurity kbisapiext kbhowto KB313624
"Microsoft Knowledge Baseに含まれている情報は、いかなる保証もない現状ベースで提供されるものです。Microsoft Corporation及びその関連会社は、市場性および特定の目的への適合性を含めて、明示的にも黙示的にも、一切の保証をいたしません。さらに、Microsoft Corporation及びその関連会社は、本文書に含まれている情報の使用及び使用結果につき、正確性、真実性等、いかなる表明・保証も行ないません。Microsoft Corporation、その関連会社及びこれらの権限ある代理人による口頭または書面による一切の情報提供またはアドバイスは、保証を意味するものではなく、かつ上記免責条項の範囲を狭めるものではありません。Microsoft Corporation、その関連会社 及びこれらの者の供給者は、直接的、間接的、偶発的、結果的損害、逸失利益、懲罰的損害、または特別損害を含む全ての損害に対して、状況のいかんを問わず一切責任を負いません。(Microsoft Corporation、その関連会社 またはこれらの者の供給者がかかる損害の発生可能性を了知している場合を含みます。) 結果的損害または偶発的損害に対する責任の免除または制限を認めていない地域においては、上記制限が適用されない場合があります。なお、本文書においては、文書の体裁上の都合により製品名の表記において商標登録表示、その他の商標表示を省略している場合がありますので、予めご了解ください。"

フィードバック

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com