Cómo instalar mediante programación los certificados SSL para Internet Server (IIS)

Seleccione idioma Seleccione idioma
Id. de artículo: 313624 - Ver los productos a los que se aplica este artículo
Expandir todo | Contraer todo

En esta página

importante este artículo contiene información sobre cómo se modifica la metabase. Antes de modificar la metabase, compruebe que dispone de una copia de seguridad que pueda restaurar si surge algún problema. Para obtener información sobre cómo hacerlo, consulte el tema de la Ayuda "Hacer copia de seguridad y restaurar la configuración" de Microsoft Management Console (MMC).

Resumen


En este artículo paso a paso describe cómo crear mediante programación y, a continuación, para instalar Secure Sockets Layer (SSL) certificados para Internet Server (IIS). Mientras IIS versión 4.0 e IIS versión 5.0 cada proporcionan una interfaz de usuario (IU) para que poder crear y, a continuación, para instalar certificados de servidor SSL, también puede completar la tarea mediante programación.



Pasos para crear y luego instalar certificados SSL

Para crear mediante programación y, a continuación, para instalar certificados SSL para el servidor IIS, siga estos pasos:
  1. Debe enviar una solicitud a la entidad emisora de certificados para emitir un certificado de servidor. Si ya tiene el certificado y, a continuación, almacenar en el archivo en el servidor IIS, no envíe la solicitud.
  2. Importe el certificado en el almacén de certificados adecuado.
  3. Configurar IIS para utilizar el certificado que obtuvo en el paso 1.



Configurar IIS para crear y luego instalar SSL Certificates

Advertencia si modifica la metabase incorrectamente, puede causar serios problemas que le obligarán a instalar de nuevo todos los productos que utilizan la metabase. Microsoft no puede garantizar la solución de los problemas resultantes de una modificación incorrecta de la metabase. Modifique la metabase bajo su responsabilidad.

Nota Haga siempre una copia de seguridad de la metabase antes de modificarla. Siga estos pasos para configurar IIS para crear y, a continuación instalar SSL certificados:
  1. Utilizar API de cifrado de Microsoft Windows para obtener la huella digital de propiedad del certificado.
  2. Debe establecer la propiedad de metabase de IIS, SSLCertHash , en el valor de la huella digital .
  3. Debe establecer la propiedad de metabase de IIS, SSLStoreName , el almacén que desea utilizar.
Vea las secciones de artículo siguientes para ejemplos de código obtener una huella digital del certificado y después obtener la propiedad SSLCertHash :
C Code to Obtain the Thumbprint of a Server Authentication Certificate
C Code to Enter the SSLCertHash Property into the Metabase



Pasos para habilitar SSL en un determinado sitio Web

Después de realizar los pasos en la sección "Configurar IIS para crear y luego para instalar SSL certificados", puede habilitar SSL en un sitio determinado o en una carpeta determinada. Para ello, debe habilitar SSL opciones en la carpeta que desea utilizar. Los pasos siguientes se corresponden con cada paso que se describe en la sección "Configurar IIS para crear y luego para instalar SSL certificados":
  1. Cuando se llama al método CEnroll::createPKCS10() , se crea la solicitud de certificado. Establezca el uso en el valor predefinido siguiente: szOID_PKIX_KP_SERVER_AUTH :
    #define szOID_PKIX_KP_SERVER_AUTH       "1.3.6.1.5.5.7.3.1"		
  2. Cuando se llama al método () ICertRequest:: Submit , se envía una solicitud para el certificado a la entidad emisora de certificados.
  3. El certificado se recupera desde la entidad emisora de certificados y, a continuación, se instala en el almacén adecuado. El servidor IIS Asistente para certificados busca sólo certificados que puede utilizar para la autenticación de servidor en el almacén de certificados de equipo local.




Pasos para configurar IIS

Después de guardar el certificado al almacén, debe configurar IIS como sigue:
  1. Utilice el método CertGetCertificateContextProperty() para obtener los valores de la propiedad Thumbprint y la propiedad CERT_HASH_PROP_ID . La función de CertGetCertificateContextProperty() utiliza el método CryptHashCertificate() para calcular el valor de la propiedad CERT_HASH_PROP_ID . Si no existe el valor HASH, CertGetCertificateContextProperty() devuelve el algoritmo SHA1 .
  2. Debe crear una nueva propiedad de metabase binario, SSLCertHash , que corresponde al sitio Web. Establezca SSLCertHash en el certificado de huella digital que obtuvo en el paso 1 de esta sección. Cuando se produce este problema, el esquema especifica incorrectamente la propiedad SSLCertHash como una cadena nula expandida terminada, en lugar de como datos binarios, y a continuación, no puede usar objetos de administración de IIS para importar SSLCertHash . Puede utilizar sólo objetos de base de administración de IIS para importar este valor. Para utilizar SSLCertHash con objetos de base de administración de IIS, debe utilizar el valor decimal 5506.
  3. Debe crear una nueva cadena de la metabase propiedad, SSLStoreName , para el sitio Web correspondiente. Establezca SSLStoreName en la cadena el valor de Mi . Puede establecer SSLStoreName mediante objetos de administración de IIS (por ejemplo, en la secuencia de comandos de ADSI) o mediante objetos de base de administración de IIS. Para utilizar SSLStoreName con objetos de base de administración de IIS, utilice el valor decimal 5511.




Código c para obtener la huella digital de un certificado de autenticación de servidor

El código de Microsoft C del ejemplo siguiente describe cómo obtener la propiedad de huella digital de un certificado de autenticación de servidor:
#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




Código c para introducir la propiedad SSLCertHash en la Metabase

El código de ejemplo siguiente describe cómo utilizar objetos de base de administración de IIS para establecer el método SSLCertHash en la metabase. El código siguiente utiliza una matriz binaria arbitraria como una huella digital de certificado. Código real podría utilizar el valor huella digital que se obtiene al ejecutar el código en la sección "Obtener la huella digital de un servidor autenticación certificado". Dependiendo de cómo se define el método SetData en tiempo de compilación, puede establecer SSLCertHash o, si ya tiene configurado SSL para el sitio Web, puede obtener SSLCertHash que existe. The SSLCertHash method return the existing 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;
}



Referencias

Para obtener más información, haga clic en el número de artículo siguiente para verlo en Microsoft Knowledge Base:
315588Cómo proteger una aplicación ASP.NET mediante certificados de cliente

Propiedades

Id. de artículo: 313624 - Última revisión: martes, 11 de julio de 2006 - Versión: 2.2
La información de este artículo se refiere a:
  • Microsoft Internet Information Server 4.0
  • Servicios de Microsoft Internet Information Server 5.0
Palabras clave: 
kbmt kbcrypt kbapi kbhowtomaster kbsecurity kbisapiext kbhowto KB313624 KbMtes
Traducción automática
IMPORTANTE: Este artículo ha sido traducido por un software de traducción automática de Microsoft (http://support.microsoft.com/gp/mtdetails) en lugar de un traductor humano. Microsoft le ofrece artículos traducidos por un traductor humano y artículos traducidos automáticamente para que tenga acceso en su propio idioma a todos los artículos de nuestra base de conocimientos (Knowledge Base). Sin embargo, los artículos traducidos automáticamente pueden contener errores en el vocabulario, la sintaxis o la gramática, como los que un extranjero podría cometer al hablar el idioma. Microsoft no se hace responsable de cualquier imprecisión, error o daño ocasionado por una mala traducción del contenido o como consecuencia de su utilización por nuestros clientes. Microsoft suele actualizar el software de traducción frecuentemente.
Haga clic aquí para ver el artículo original (en inglés): 313624

Enviar comentarios

 

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